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