* configure, configure.in, config.dsp, config_vc.awk,
[fw/sdcc] / as / link / hc08 / lkelf.c
1 /*-------------------------------------------------------------------------
2   lkelf.c - Create an executable ELF/DWARF file
3
4    Written By -  Erik Petrich, epetrich@users.sourceforge.net (2004)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
20
21 #include <ctype.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include "aslink.h"
26
27 static int execStartMSB;
28 static int execStartLSB;
29 static char execStartMSBfound;
30 static char execStartLSBfound;
31
32 typedef TYPE_UDWORD Elf32_Addr;
33 typedef TYPE_WORD Elf32_Half;
34 typedef TYPE_UDWORD Elf32_Off;
35 typedef TYPE_DWORD Elf32_Sword;
36 typedef TYPE_UDWORD Elf32_Word;
37
38 enum
39 {
40   EI_MAG0 = 0,
41   EI_MAG1,
42   EI_MAG2,
43   EI_MAG3,
44   EI_CLASS,
45   EI_DATA,
46   EI_VERSION,
47   EI_PAD,
48   EI_NIDENT = 16
49 };
50
51 enum
52 {
53   ELFMAG0 = 0x7f,
54   ELFMAG1 = 'E',
55   ELFMAG2 = 'L',
56   ELFMAG3 = 'F'
57 };
58
59 enum
60 {
61   ET_NONE = 0,
62   ET_REL,
63   ET_EXEC,
64   ET_DYN,
65   ET_CORE
66 };
67
68 /* These e_machine values are from "Motorola 8- and 16-bit Embedded */
69 /* Application Binary Interface (M8/16EABI)" version 2.0 */
70 enum
71 {
72   EM_NONE = 0,
73   EM_68HC05 = 72,
74   EM_68HC08 = 71,
75   EM_68HC11 = 70,
76   EM_68HC12 = 53,
77   EM_68HC16 = 69
78 };
79
80 enum
81 {
82   EV_NONE = 0,
83   EV_CURRENT
84 };
85
86 enum
87 {
88   ELFCLASSNONE = 0,
89   ELFCLASS32,
90   ELFCLASS64
91 };
92
93 enum
94 {
95   ELFDATANONE = 0,
96   ELFDATA2LSB,
97   ELFDATA2MSB
98 };
99
100 enum
101 {
102   SHT_NULL = 0,
103   SHT_PROGBITS,
104   SHT_SYMTAB,
105   SHT_STRTAB,
106   SHT_RELA,
107   SHT_HASH,
108   SHT_DYNAMIC,
109   SHT_NOTE,
110   SHT_NOBITS,
111   SHT_REL,
112   SHT_SHLIB,
113   SHT_DYNSYM
114 };
115
116 enum
117 {
118   SHF_WRITE = (1 << 0),
119   SHF_ALLOC = (1 << 1),
120   SHF_EXECINSTR = (1 << 2),
121 };
122
123 enum
124 {
125   PT_NULL = 0,
126   PT_LOAD
127 };
128
129 enum
130 {
131   PF_X = (1 << 0),
132   PF_W = (1 << 1),
133   PF_R = (1 << 2)
134 };
135
136 typedef struct
137 {
138   unsigned char e_ident[EI_NIDENT];
139   Elf32_Half e_type;
140   Elf32_Half e_machine;
141   Elf32_Word e_version;
142   Elf32_Addr e_entry;
143   Elf32_Off e_phoff;
144   Elf32_Off e_shoff;
145   Elf32_Word e_flags;
146   Elf32_Half e_ehsize;
147   Elf32_Half e_phentsize;
148   Elf32_Half e_phnum;
149   Elf32_Half e_shentsize;
150   Elf32_Half e_shnum;
151   Elf32_Half e_shstrndx;
152 } Elf32_Ehdr;
153
154 typedef struct
155 {
156   Elf32_Word sh_name;
157   Elf32_Word sh_type;
158   Elf32_Word sh_flags;
159   Elf32_Addr sh_addr;
160   Elf32_Off sh_offset;
161   Elf32_Word sh_size;
162   Elf32_Word sh_link;
163   Elf32_Word sh_info;
164   Elf32_Word sh_addralign;
165   Elf32_Word sh_entsize;
166 } Elf32_Shdr;
167
168 typedef struct
169 {
170   Elf32_Word p_type;
171   Elf32_Off p_offset;
172   Elf32_Addr p_vaddr;
173   Elf32_Addr p_paddr;
174   Elf32_Word p_filesz;
175   Elf32_Word p_memsz;
176   Elf32_Word p_flags;
177   Elf32_Word p_align;
178 } Elf32_Phdr;
179
180 typedef struct strtabString
181 {
182   char * string;
183   struct strtabString * prev;
184   struct strtabString * next;
185   Elf32_Word index;
186 } strtabString;
187
188 typedef struct
189 {
190   strtabString * first;
191   strtabString * last;
192 } strtabList;
193
194 static strtabList shstrtab;
195
196
197 typedef struct listEntry
198 {
199   void * item;
200   struct listEntry * prev;
201   struct listEntry * next;
202 } listEntry;
203
204 typedef struct
205 {
206   listEntry * first;
207   listEntry * last;
208   int count;
209 } listHeader;
210
211
212
213 static void
214 listAdd (listHeader * lhp, void * item)
215 {
216   listEntry * lep;
217
218   lep = new (sizeof (*lep));
219   lep->item = item;
220   lep->prev = lhp->last;
221   if (lep->prev)
222     lep->prev->next = lep;
223
224   lhp->last = lep;
225   if (!lhp->first)
226     lhp->first = lep;
227
228   lhp->count++;
229 }
230
231 static listHeader *
232 listNew (void)
233 {
234   listHeader * lhp;
235
236   lhp = new (sizeof (*lhp));
237
238   return lhp;
239 }
240
241
242 #if 0
243 static Elf32_Word
244 strtabFind (strtabList * strtab, char * str)
245 {
246   strtabString * sp;
247   sp = strtab->first;
248
249   while (sp)
250     {
251       if (!strcmp (str, sp->string))
252         return sp->index;
253       sp = sp->next;
254     }
255
256   return 0;
257 }
258 #endif
259
260 /*-------------------------------------------------------------------*/
261 /* strtabFindOrAdd - Finds a string in a string table or adds the    */
262 /*   string if it does not already exist. Returns the offset of the  */
263 /*   string in the table.                                            */
264 /*-------------------------------------------------------------------*/
265 static Elf32_Word
266 strtabFindOrAdd (strtabList * strtab, char * str)
267 {
268   strtabString * sp;
269   sp = strtab->first;
270
271   while (sp)
272     {
273       if (!strcmp (str, sp->string))
274         return sp->index;
275       sp = sp->next;
276     }
277
278   sp = new (sizeof(*sp));
279   if (strtab->last)
280     sp->index = strtab->last->index + 1 + strlen (strtab->last->string);
281   else
282     sp->index = 1;
283   sp->string = new (1+strlen (str));
284   strcpy (sp->string, str);
285
286   sp->prev = strtab->last;
287   if (sp->prev)
288     sp->prev->next = sp;
289   strtab->last = sp;
290   if (!strtab->first)
291     strtab->first = sp;
292
293   return sp->index;
294 }
295
296 /*-------------------------------------------------------------------*/
297 /* fputElfStrtab - writes a string table to a file                   */
298 /*-------------------------------------------------------------------*/
299 static void
300 fputElfStrtab (strtabList *strtab, FILE *fp)
301 {
302   strtabString * sp;
303
304   fputc (0, fp);        /* index 0 must be the null character */
305
306   sp = strtab->first;
307   while (sp)
308     {
309       fputs (sp->string, fp);
310       fputc (0, fp);
311       sp = sp->next;
312     }
313 }
314
315 /*-------------------------------------------------------------------*/
316 /* fputElf32_Word - writes an Elf32_Word value to a file             */
317 /*-------------------------------------------------------------------*/
318 static void
319 fputElf32_Word (Elf32_Word x, FILE *fp)
320 {
321   if (hilo == 0)
322     {
323       fputc (x & 0xff, fp);
324       fputc ((x >> 8) & 0xff, fp);
325       fputc ((x >> 16) & 0xff, fp);
326       fputc ((x >> 24) & 0xff, fp);
327     }
328   else
329     {
330       fputc ((x >> 24) & 0xff, fp);
331       fputc ((x >> 16) & 0xff, fp);
332       fputc ((x >> 8) & 0xff, fp);
333       fputc (x & 0xff, fp);
334     }
335 }
336
337 /*-------------------------------------------------------------------*/
338 /* fputElf32_Off - writes an Elf32_Off value to a file               */
339 /*-------------------------------------------------------------------*/
340 static void
341 fputElf32_Off (Elf32_Off x, FILE *fp)
342 {
343   if (hilo == 0)
344     {
345       fputc (x & 0xff, fp);
346       fputc ((x >> 8) & 0xff, fp);
347       fputc ((x >> 16) & 0xff, fp);
348       fputc ((x >> 24) & 0xff, fp);
349     }
350   else
351     {
352       fputc ((x >> 24) & 0xff, fp);
353       fputc ((x >> 16) & 0xff, fp);
354       fputc ((x >> 8) & 0xff, fp);
355       fputc (x & 0xff, fp);
356     }
357 }
358
359 /*-------------------------------------------------------------------*/
360 /* fputElf32_Addr - writes an Elf32_Addr value to a file             */
361 /*-------------------------------------------------------------------*/
362 static void
363 fputElf32_Addr (Elf32_Addr x, FILE *fp)
364 {
365   if (hilo == 0)
366     {
367       fputc (x & 0xff, fp);
368       fputc ((x >> 8) & 0xff, fp);
369       fputc ((x >> 16) & 0xff, fp);
370       fputc ((x >> 24) & 0xff, fp);
371     }
372   else
373     {
374       fputc ((x >> 24) & 0xff, fp);
375       fputc ((x >> 16) & 0xff, fp);
376       fputc ((x >> 8) & 0xff, fp);
377       fputc (x & 0xff, fp);
378     }
379 }
380
381 /*-------------------------------------------------------------------*/
382 /* fputElf32_Half - writes an Elf32_Half value to a file             */
383 /*-------------------------------------------------------------------*/
384 static void
385 fputElf32_Half (Elf32_Half x, FILE *fp)
386 {
387   if (hilo == 0)
388     {
389       fputc (x & 0xff, fp);
390       fputc ((x >> 8) & 0xff, fp);
391     }
392   else
393     {
394       fputc ((x >> 8) & 0xff, fp);
395       fputc (x & 0xff, fp);
396     }
397 }
398
399 /*------------------------------------------------------------------------*/
400 /* fputElf32_Ehdr - writes an Elf32_Ehdr struct (ELF header) to a file    */
401 /*------------------------------------------------------------------------*/
402 static void
403 fputElf32_Ehdr (Elf32_Ehdr * ehdr, FILE * fp)
404 {
405   int i;
406
407   for (i=0; i<EI_NIDENT; i++)
408     fputc (ehdr->e_ident[i], fp);
409
410   fputElf32_Half (ehdr->e_type, fp);
411   fputElf32_Half (ehdr->e_machine, fp);
412   fputElf32_Word (ehdr->e_version, fp);
413   fputElf32_Addr (ehdr->e_entry, fp);
414   fputElf32_Off (ehdr->e_phoff, fp);
415   fputElf32_Off (ehdr->e_shoff, fp);
416   fputElf32_Word (ehdr->e_flags, fp);
417   fputElf32_Half (ehdr->e_ehsize, fp);
418   fputElf32_Half (ehdr->e_phentsize, fp);
419   fputElf32_Half (ehdr->e_phnum, fp);
420   fputElf32_Half (ehdr->e_shentsize, fp);
421   fputElf32_Half (ehdr->e_shnum, fp);
422   fputElf32_Half (ehdr->e_shstrndx, fp);
423 }
424
425 /*-------------------------------------------------------------------------*/
426 /* fputElf32_Ehdr - writes an Elf32_Shdr struct (section header) to a file */
427 /*-------------------------------------------------------------------------*/
428 static void
429 fputElf32_Shdr (Elf32_Shdr * shdr, FILE * fp)
430 {
431   fputElf32_Word (shdr->sh_name, fp);
432   fputElf32_Word (shdr->sh_type, fp);
433   fputElf32_Word (shdr->sh_flags, fp);
434   fputElf32_Addr (shdr->sh_addr, fp);
435   fputElf32_Off (shdr->sh_offset, fp);
436   fputElf32_Word (shdr->sh_size, fp);
437   fputElf32_Word (shdr->sh_link, fp);
438   fputElf32_Word (shdr->sh_info, fp);
439   fputElf32_Word (shdr->sh_addralign, fp);
440   fputElf32_Word (shdr->sh_entsize, fp);
441 }
442
443 /*-------------------------------------------------------------------------*/
444 /* fputElf32_Ehdr - writes an Elf32_Phdr struct (segment header) to a file */
445 /*-------------------------------------------------------------------------*/
446 static void
447 fputElf32_Phdr (Elf32_Phdr * phdr, FILE * fp)
448 {
449   fputElf32_Word (phdr->p_type, fp);
450   fputElf32_Off (phdr->p_offset, fp);
451   fputElf32_Addr (phdr->p_vaddr, fp);
452   fputElf32_Addr (phdr->p_paddr, fp);
453   fputElf32_Word (phdr->p_filesz, fp);
454   fputElf32_Word (phdr->p_memsz, fp);
455   fputElf32_Word (phdr->p_flags, fp);
456   fputElf32_Word (phdr->p_align, fp);
457 }
458
459
460 /*--------------------------------------------------------------------------*/
461 /* elfGenerateAbs - generates segments and sections for an absolute area.   */
462 /*   This is a little more complicated than a relative area since it may    */
463 /*   contain noncontiguous regions.                                         */
464 /*--------------------------------------------------------------------------*/
465 static void
466 elfGenerateAbs (struct area *ap, listHeader * segments, listHeader * sections)
467 {
468   Elf32_Addr ofs;
469   Elf32_Addr addr;
470   Elf32_Word size;
471   Elf32_Phdr * phdrp;
472   Elf32_Shdr * shdrp;
473
474   if (!ap->a_image)
475     {
476       return;
477     }
478
479   ofs = 0;
480   for (;;)
481     {
482       /* Find the start of a contiguously */
483       /* used region within this area */
484       while (ofs < ap->a_size && !ap->a_used[ofs])
485         ofs++;
486       if (ofs >= ap->a_size)
487         return;
488
489       /* Find the end of the region */
490       addr = ap->a_addr + ofs;
491       while (ofs < ap->a_size && ap->a_used[ofs])
492         ofs++;
493       size = ap->a_addr + ofs - addr;
494
495       /* create a segment header for this region if loadable */
496       if (!(ap->a_flag & A_NOLOAD))
497         {
498           phdrp = new (sizeof (*phdrp));
499           phdrp->p_type = PT_LOAD;
500           phdrp->p_offset = ftell (ofp);
501           phdrp->p_vaddr = addr;
502           phdrp->p_paddr = addr;
503           phdrp->p_filesz = size;
504           phdrp->p_memsz = size;
505           phdrp->p_flags = PF_R;
506           if (ap->a_flag & A_CODE)
507             phdrp->p_flags |= PF_X;
508           phdrp->p_align = 1;
509           listAdd (segments, phdrp);
510         }
511
512       /* create a section header for this region */
513       shdrp = new (sizeof (*shdrp));
514       shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id);
515       shdrp->sh_type = SHT_PROGBITS;
516       shdrp->sh_flags = 0;
517       if (!(ap->a_flag & A_NOLOAD))
518         shdrp->sh_flags |= SHF_ALLOC;
519       if (ap->a_flag & A_CODE)
520         shdrp->sh_flags |= SHF_EXECINSTR;
521       shdrp->sh_addr = addr;
522       shdrp->sh_offset = ftell (ofp);
523       shdrp->sh_size = size;
524       shdrp->sh_link = 0;
525       shdrp->sh_info = 0;
526       shdrp->sh_addralign = 0;
527       shdrp->sh_entsize = 0;
528       listAdd (sections, shdrp);
529
530       fwrite (&ap->a_image[addr-ap->a_addr], 1, size, ofp);
531     }
532 }
533
534 /*--------------------------------------------------------------------------*/
535 /* elfGenerateRel - generates a segment and section for a relative area.    */
536 /*--------------------------------------------------------------------------*/
537 static void
538 elfGenerateRel (struct area *ap, listHeader * segments, listHeader * sections)
539 {
540   Elf32_Phdr * phdrp;
541   Elf32_Shdr * shdrp;
542
543   if (!ap->a_image)
544     {
545       return;
546     }
547
548   /* create a segment header for this area if loadable */
549   if (!(ap->a_flag & A_NOLOAD))
550     {
551       phdrp = new (sizeof (*phdrp));
552       phdrp->p_type = PT_LOAD;
553       phdrp->p_offset = ftell (ofp);
554       phdrp->p_vaddr = ap->a_addr;
555       phdrp->p_paddr = ap->a_addr;
556       phdrp->p_filesz = ap->a_size;
557       phdrp->p_memsz = ap->a_size;
558       phdrp->p_flags = PF_R;
559       if (ap->a_flag & A_CODE)
560         phdrp->p_flags |= PF_X;
561       phdrp->p_align = 1;
562       listAdd (segments, phdrp);
563     }
564
565   /* create a section header for this area */
566   shdrp = new (sizeof (*shdrp));
567   shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id);
568   shdrp->sh_type = SHT_PROGBITS;
569   shdrp->sh_flags = 0;
570   if (!(ap->a_flag & A_NOLOAD))
571     shdrp->sh_flags |= SHF_ALLOC;
572   if (ap->a_flag & A_CODE)
573     shdrp->sh_flags |= SHF_EXECINSTR;
574   shdrp->sh_addr = ap->a_addr;
575   shdrp->sh_offset = ftell (ofp);
576   shdrp->sh_size = ap->a_size;
577   shdrp->sh_link = 0;
578   shdrp->sh_info = 0;
579   shdrp->sh_addralign = 0;
580   shdrp->sh_entsize = 0;
581   listAdd (sections, shdrp);
582
583   fwrite (ap->a_image, 1, ap->a_size, ofp);
584 }
585
586 /*--------------------------------------------------------------------------*/
587 /* elfGenerate - generates the complete ELF file                            */
588 /*--------------------------------------------------------------------------*/
589 static void
590 elfGenerate (void)
591 {
592   listHeader * sections = listNew();
593   listHeader * segments = listNew();
594   struct area *ap;
595   Elf32_Ehdr ehdr;
596   Elf32_Shdr * shdrp;
597   Elf32_Phdr * phdrp;
598   listEntry * lep;
599   int i;
600   Elf32_Word shstrtabName;
601
602   /* create the null section header for index 0 */
603   shdrp = new (sizeof (*shdrp));
604   shdrp->sh_name = 0;
605   shdrp->sh_type = SHT_NULL;
606   shdrp->sh_flags = 0;
607   shdrp->sh_addr = 0;
608   shdrp->sh_offset = 0;
609   shdrp->sh_size = 0;
610   shdrp->sh_link = 0;
611   shdrp->sh_info = 0;
612   shdrp->sh_addralign = 0;
613   shdrp->sh_entsize = 0;
614   listAdd (sections, shdrp);
615
616   /* Initialize the ELF header */
617   for (i=0; i<EI_NIDENT; i++)
618     ehdr.e_ident[i] = 0;
619   ehdr.e_ident[EI_MAG0] = ELFMAG0;
620   ehdr.e_ident[EI_MAG1] = ELFMAG1;
621   ehdr.e_ident[EI_MAG2] = ELFMAG2;
622   ehdr.e_ident[EI_MAG3] = ELFMAG3;
623   ehdr.e_ident[EI_CLASS] = ELFCLASS32;
624   if (hilo == 0)
625     ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
626   else
627     ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
628   ehdr.e_ident[EI_VERSION] = 1;
629   ehdr.e_type = ET_EXEC;
630   ehdr.e_machine = EM_68HC08; /* FIXME: get rid of hardcoded value - EEP */
631   ehdr.e_phentsize = sizeof (*phdrp);
632   ehdr.e_shentsize = sizeof (*shdrp);
633   ehdr.e_ehsize = sizeof (ehdr);
634   ehdr.e_phnum = 0;
635   ehdr.e_shnum = 0;
636   ehdr.e_shstrndx = 0;
637   ehdr.e_version = 1;
638   ehdr.e_entry = 0;
639   if (execStartMSBfound && execStartLSBfound)
640     ehdr.e_entry = (execStartMSB << 8) + execStartLSB;
641
642   /* Write out the ELF header as a placeholder; we will update */
643   /* it with the final values when everything is complete */
644   fputElf32_Ehdr (&ehdr, ofp);
645
646   /* Iterate over the linker areas to generate */
647   /* the ELF sections and segments */
648   ap = areap;
649   while (ap)
650     {
651       if (ap->a_size)
652         {
653           if (ap->a_flag & A_ABS)
654             elfGenerateAbs (ap, segments, sections);
655           else
656             elfGenerateRel (ap, segments, sections);
657         }
658       ap = ap->a_ap;
659     }
660
661   /* Create the string table section after the other sections */
662   shdrp = new (sizeof (*shdrp));
663   shdrp->sh_name = strtabFindOrAdd (&shstrtab, ".shstrtab");
664   shdrp->sh_type = SHT_STRTAB;
665   shdrp->sh_flags = 0;
666   shdrp->sh_addr = 0;
667   shdrp->sh_offset = ftell (ofp);
668   shdrp->sh_size = shstrtab.last->index + strlen (shstrtab.last->string) + 1;
669   shdrp->sh_link = 0;
670   shdrp->sh_info = 0;
671   shdrp->sh_addralign = 0;
672   shdrp->sh_entsize = 0;
673   listAdd (sections, shdrp);
674   fputElfStrtab (&shstrtab, ofp);
675
676   /* Find the index of the section string table */
677   /* header and save it in the ELF header */
678   ehdr.e_shstrndx = 0;
679   shstrtabName = shdrp->sh_name;
680   lep = sections->first;
681   while (lep)
682     {
683       shdrp = lep->item;
684       if (shdrp->sh_name == shstrtabName)
685         break;
686       ehdr.e_shstrndx++;
687       lep = lep->next;
688     }
689
690   /* Write out the segment headers */
691   ehdr.e_phnum = segments->count;
692   ehdr.e_phoff = ftell (ofp);
693   lep = segments->first;
694   while (lep)
695     {
696       phdrp = lep->item;
697       fputElf32_Phdr (phdrp, ofp);
698       lep = lep->next;
699     }
700
701   /* Write out the section headers */
702   ehdr.e_shnum = sections->count;
703   ehdr.e_shoff = ftell (ofp);
704   lep = sections->first;
705   while (lep)
706     {
707       shdrp = lep->item;
708       fputElf32_Shdr (shdrp, ofp);
709       lep = lep->next;
710     }
711
712   /* All the values in the ELF header have now been computed; write */
713   /* over the placeholder header with the final values */
714   fseek (ofp, 0, SEEK_SET);
715   fputElf32_Ehdr (&ehdr, ofp);
716   fseek (ofp, 0, SEEK_END);
717 }
718
719 /*--------------------------------------------------------------------------*/
720 /* elf - incrementally called by the linker core to generate ELF file data. */
721 /*    The parameter is nonzero when there is data available and zero when   */
722 /*    the linker is finished.                                               */
723 /*--------------------------------------------------------------------------*/
724 void
725 elf (int i)
726 {
727   Addr_T address;
728
729   /* Buffer the data until we have it all */
730   if (i)
731     {
732       if (hilo == 0)
733         address = rtval[0] + (rtval[1] << 8); /* little endian order */
734       else
735         address = rtval[1] + (rtval[0] << 8); /* big endian order */
736
737       /* If this area doesn't have an image buffer, create one */
738       if (!ap->a_image)
739         {
740           ap->a_image = new (ap->a_size);
741           if (ap->a_flag & A_ABS)
742             ap->a_used = new (ap->a_size);
743         }
744
745       /* Copy the data into the image buffer */
746       for (i = 2; i < rtcnt ; i++)
747         {
748           if (rtflg[i])
749             {
750               ap->a_image[address-ap->a_addr] = rtval[i];
751               if (ap->a_used)
752                 ap->a_used[address-ap->a_addr] = 1;
753
754               /* Make note of the reset vector */
755               if (!(ap->a_flag & A_NOLOAD))
756                 {
757                   if (address == 0xfffe)
758                     {
759                       execStartMSB = rtval[i];
760                       execStartMSBfound = 1;
761                     }
762                   if (address == 0xffff)
763                     {
764                       execStartLSB = rtval[i];
765                       execStartLSBfound = 1;
766                     }
767                 }
768               address++;
769             }
770         }
771     }
772   else
773     elfGenerate();
774 }