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