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