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