--- /dev/null
+/*-------------------------------------------------------------------------
+ lkelf.c - Create an executable ELF/DWARF file
+
+ Written By - Erik Petrich, epetrich@users.sourceforge.net (2004)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-------------------------------------------------------------------------*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "aslink.h"
+#include "sdccconf.h"
+
+static int execStartMSB;
+static int execStartLSB;
+static char execStartMSBfound;
+static char execStartLSBfound;
+
+typedef TYPE_UDWORD Elf32_Addr;
+typedef TYPE_WORD Elf32_Half;
+typedef TYPE_UDWORD Elf32_Off;
+typedef TYPE_DWORD Elf32_Sword;
+typedef TYPE_UDWORD Elf32_Word;
+
+enum
+{
+ EI_MAG0 = 0,
+ EI_MAG1,
+ EI_MAG2,
+ EI_MAG3,
+ EI_CLASS,
+ EI_DATA,
+ EI_VERSION,
+ EI_PAD,
+ EI_NIDENT = 16
+};
+
+enum
+{
+ ELFMAG0 = 0x7f,
+ ELFMAG1 = 'E',
+ ELFMAG2 = 'L',
+ ELFMAG3 = 'F'
+};
+
+enum
+{
+ ET_NONE = 0,
+ ET_REL,
+ ET_EXEC,
+ ET_DYN,
+ ET_CORE
+};
+
+/* These e_machine values are from "Motorola 8- and 16-bit Embedded */
+/* Application Binary Interface (M8/16EABI)" version 2.0 */
+enum
+{
+ EM_NONE = 0,
+ EM_68HC05 = 72,
+ EM_68HC08 = 71,
+ EM_68HC11 = 70,
+ EM_68HC12 = 53,
+ EM_68HC16 = 69
+};
+
+enum
+{
+ EV_NONE = 0,
+ EV_CURRENT
+};
+
+enum
+{
+ ELFCLASSNONE = 0,
+ ELFCLASS32,
+ ELFCLASS64
+};
+
+enum
+{
+ ELFDATANONE = 0,
+ ELFDATA2LSB,
+ ELFDATA2MSB
+};
+
+enum
+{
+ SHT_NULL = 0,
+ SHT_PROGBITS,
+ SHT_SYMTAB,
+ SHT_STRTAB,
+ SHT_RELA,
+ SHT_HASH,
+ SHT_DYNAMIC,
+ SHT_NOTE,
+ SHT_NOBITS,
+ SHT_REL,
+ SHT_SHLIB,
+ SHT_DYNSYM
+};
+
+enum
+{
+ SHF_WRITE = (1 << 0),
+ SHF_ALLOC = (1 << 1),
+ SHF_EXECINSTR = (1 << 2),
+};
+
+enum
+{
+ PT_NULL = 0,
+ PT_LOAD
+};
+
+enum
+{
+ PF_X = (1 << 0),
+ PF_W = (1 << 1),
+ PF_R = (1 << 2)
+};
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT];
+ Elf32_Half e_type;
+ Elf32_Half e_machine;
+ Elf32_Word e_version;
+ Elf32_Addr e_entry;
+ Elf32_Off e_phoff;
+ Elf32_Off e_shoff;
+ Elf32_Word e_flags;
+ Elf32_Half e_ehsize;
+ Elf32_Half e_phentsize;
+ Elf32_Half e_phnum;
+ Elf32_Half e_shentsize;
+ Elf32_Half e_shnum;
+ Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+typedef struct
+{
+ Elf32_Word sh_name;
+ Elf32_Word sh_type;
+ Elf32_Word sh_flags;
+ Elf32_Addr sh_addr;
+ Elf32_Off sh_offset;
+ Elf32_Word sh_size;
+ Elf32_Word sh_link;
+ Elf32_Word sh_info;
+ Elf32_Word sh_addralign;
+ Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+typedef struct
+{
+ Elf32_Word p_type;
+ Elf32_Off p_offset;
+ Elf32_Addr p_vaddr;
+ Elf32_Addr p_paddr;
+ Elf32_Word p_filesz;
+ Elf32_Word p_memsz;
+ Elf32_Word p_flags;
+ Elf32_Word p_align;
+} Elf32_Phdr;
+
+typedef struct strtabString
+{
+ char * string;
+ struct strtabString * prev;
+ struct strtabString * next;
+ Elf32_Word index;
+} strtabString;
+
+typedef struct
+{
+ strtabString * first;
+ strtabString * last;
+} strtabList;
+
+static strtabList shstrtab;
+
+
+typedef struct listEntry
+{
+ void * item;
+ struct listEntry * prev;
+ struct listEntry * next;
+} listEntry;
+
+typedef struct
+{
+ listEntry * first;
+ listEntry * last;
+ int count;
+} listHeader;
+
+
+
+static void
+listAdd (listHeader * lhp, void * item)
+{
+ listEntry * lep;
+
+ lep = new (sizeof (*lep));
+ lep->item = item;
+ lep->prev = lhp->last;
+ if (lep->prev)
+ lep->prev->next = lep;
+
+ lhp->last = lep;
+ if (!lhp->first)
+ lhp->first = lep;
+
+ lhp->count++;
+}
+
+static listHeader *
+listNew (void)
+{
+ listHeader * lhp;
+
+ lhp = new (sizeof (*lhp));
+
+ return lhp;
+}
+
+
+#if 0
+static Elf32_Word
+strtabFind (strtabList * strtab, char * str)
+{
+ strtabString * sp;
+ sp = strtab->first;
+
+ while (sp)
+ {
+ if (!strcmp (str, sp->string))
+ return sp->index;
+ sp = sp->next;
+ }
+
+ return 0;
+}
+#endif
+
+/*-------------------------------------------------------------------*/
+/* strtabFindOrAdd - Finds a string in a string table or adds the */
+/* string if it does not already exist. Returns the offset of the */
+/* string in the table. */
+/*-------------------------------------------------------------------*/
+static Elf32_Word
+strtabFindOrAdd (strtabList * strtab, char * str)
+{
+ strtabString * sp;
+ sp = strtab->first;
+
+ while (sp)
+ {
+ if (!strcmp (str, sp->string))
+ return sp->index;
+ sp = sp->next;
+ }
+
+ sp = new (sizeof(*sp));
+ if (strtab->last)
+ sp->index = strtab->last->index + 1 + strlen (strtab->last->string);
+ else
+ sp->index = 1;
+ sp->string = new (1+strlen (str));
+ strcpy (sp->string, str);
+
+ sp->prev = strtab->last;
+ if (sp->prev)
+ sp->prev->next = sp;
+ strtab->last = sp;
+ if (!strtab->first)
+ strtab->first = sp;
+
+ return sp->index;
+}
+
+/*-------------------------------------------------------------------*/
+/* fputElfStrtab - writes a string table to a file */
+/*-------------------------------------------------------------------*/
+static void
+fputElfStrtab (strtabList *strtab, FILE *fp)
+{
+ strtabString * sp;
+
+ fputc (0, fp); /* index 0 must be the null character */
+
+ sp = strtab->first;
+ while (sp)
+ {
+ fputs (sp->string, fp);
+ fputc (0, fp);
+ sp = sp->next;
+ }
+}
+
+/*-------------------------------------------------------------------*/
+/* fputElf32_Word - writes an Elf32_Word value to a file */
+/*-------------------------------------------------------------------*/
+static void
+fputElf32_Word (Elf32_Word x, FILE *fp)
+{
+ if (hilo == 0)
+ {
+ fputc (x & 0xff, fp);
+ fputc ((x >> 8) & 0xff, fp);
+ fputc ((x >> 16) & 0xff, fp);
+ fputc ((x >> 24) & 0xff, fp);
+ }
+ else
+ {
+ fputc ((x >> 24) & 0xff, fp);
+ fputc ((x >> 16) & 0xff, fp);
+ fputc ((x >> 8) & 0xff, fp);
+ fputc (x & 0xff, fp);
+ }
+}
+
+/*-------------------------------------------------------------------*/
+/* fputElf32_Off - writes an Elf32_Off value to a file */
+/*-------------------------------------------------------------------*/
+static void
+fputElf32_Off (Elf32_Off x, FILE *fp)
+{
+ if (hilo == 0)
+ {
+ fputc (x & 0xff, fp);
+ fputc ((x >> 8) & 0xff, fp);
+ fputc ((x >> 16) & 0xff, fp);
+ fputc ((x >> 24) & 0xff, fp);
+ }
+ else
+ {
+ fputc ((x >> 24) & 0xff, fp);
+ fputc ((x >> 16) & 0xff, fp);
+ fputc ((x >> 8) & 0xff, fp);
+ fputc (x & 0xff, fp);
+ }
+}
+
+/*-------------------------------------------------------------------*/
+/* fputElf32_Addr - writes an Elf32_Addr value to a file */
+/*-------------------------------------------------------------------*/
+static void
+fputElf32_Addr (Elf32_Addr x, FILE *fp)
+{
+ if (hilo == 0)
+ {
+ fputc (x & 0xff, fp);
+ fputc ((x >> 8) & 0xff, fp);
+ fputc ((x >> 16) & 0xff, fp);
+ fputc ((x >> 24) & 0xff, fp);
+ }
+ else
+ {
+ fputc ((x >> 24) & 0xff, fp);
+ fputc ((x >> 16) & 0xff, fp);
+ fputc ((x >> 8) & 0xff, fp);
+ fputc (x & 0xff, fp);
+ }
+}
+
+/*-------------------------------------------------------------------*/
+/* fputElf32_Half - writes an Elf32_Half value to a file */
+/*-------------------------------------------------------------------*/
+static void
+fputElf32_Half (Elf32_Half x, FILE *fp)
+{
+ if (hilo == 0)
+ {
+ fputc (x & 0xff, fp);
+ fputc ((x >> 8) & 0xff, fp);
+ }
+ else
+ {
+ fputc ((x >> 8) & 0xff, fp);
+ fputc (x & 0xff, fp);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+/* fputElf32_Ehdr - writes an Elf32_Ehdr struct (ELF header) to a file */
+/*------------------------------------------------------------------------*/
+static void
+fputElf32_Ehdr (Elf32_Ehdr * ehdr, FILE * fp)
+{
+ int i;
+
+ for (i=0; i<EI_NIDENT; i++)
+ fputc (ehdr->e_ident[i], fp);
+
+ fputElf32_Half (ehdr->e_type, fp);
+ fputElf32_Half (ehdr->e_machine, fp);
+ fputElf32_Word (ehdr->e_version, fp);
+ fputElf32_Addr (ehdr->e_entry, fp);
+ fputElf32_Off (ehdr->e_phoff, fp);
+ fputElf32_Off (ehdr->e_shoff, fp);
+ fputElf32_Word (ehdr->e_flags, fp);
+ fputElf32_Half (ehdr->e_ehsize, fp);
+ fputElf32_Half (ehdr->e_phentsize, fp);
+ fputElf32_Half (ehdr->e_phnum, fp);
+ fputElf32_Half (ehdr->e_shentsize, fp);
+ fputElf32_Half (ehdr->e_shnum, fp);
+ fputElf32_Half (ehdr->e_shstrndx, fp);
+}
+
+/*-------------------------------------------------------------------------*/
+/* fputElf32_Ehdr - writes an Elf32_Shdr struct (section header) to a file */
+/*-------------------------------------------------------------------------*/
+static void
+fputElf32_Shdr (Elf32_Shdr * shdr, FILE * fp)
+{
+ fputElf32_Word (shdr->sh_name, fp);
+ fputElf32_Word (shdr->sh_type, fp);
+ fputElf32_Word (shdr->sh_flags, fp);
+ fputElf32_Addr (shdr->sh_addr, fp);
+ fputElf32_Off (shdr->sh_offset, fp);
+ fputElf32_Word (shdr->sh_size, fp);
+ fputElf32_Word (shdr->sh_link, fp);
+ fputElf32_Word (shdr->sh_info, fp);
+ fputElf32_Word (shdr->sh_addralign, fp);
+ fputElf32_Word (shdr->sh_entsize, fp);
+}
+
+/*-------------------------------------------------------------------------*/
+/* fputElf32_Ehdr - writes an Elf32_Phdr struct (segment header) to a file */
+/*-------------------------------------------------------------------------*/
+static void
+fputElf32_Phdr (Elf32_Phdr * phdr, FILE * fp)
+{
+ fputElf32_Word (phdr->p_type, fp);
+ fputElf32_Off (phdr->p_offset, fp);
+ fputElf32_Addr (phdr->p_vaddr, fp);
+ fputElf32_Addr (phdr->p_paddr, fp);
+ fputElf32_Word (phdr->p_filesz, fp);
+ fputElf32_Word (phdr->p_memsz, fp);
+ fputElf32_Word (phdr->p_flags, fp);
+ fputElf32_Word (phdr->p_align, fp);
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* elfGenerateAbs - generates segments and sections for an absolute area. */
+/* This is a little more complicated than a relative area since it may */
+/* contain noncontiguous regions. */
+/*--------------------------------------------------------------------------*/
+static void
+elfGenerateAbs (struct area *ap, listHeader * segments, listHeader * sections)
+{
+ Elf32_Addr ofs;
+ Elf32_Addr addr;
+ Elf32_Word size;
+ Elf32_Phdr * phdrp;
+ Elf32_Shdr * shdrp;
+
+ if (!ap->a_image)
+ {
+ return;
+ }
+
+ ofs = 0;
+ for (;;)
+ {
+ /* Find the start of a contiguously */
+ /* used region within this area */
+ while (ofs < ap->a_size && !ap->a_used[ofs])
+ ofs++;
+ if (ofs >= ap->a_size)
+ return;
+
+ /* Find the end of the region */
+ addr = ap->a_addr + ofs;
+ while (ofs < ap->a_size && ap->a_used[ofs])
+ ofs++;
+ size = ap->a_addr + ofs - addr;
+
+ /* create a segment header for this region if loadable */
+ if (!(ap->a_flag & A_NOLOAD))
+ {
+ phdrp = new (sizeof (*phdrp));
+ phdrp->p_type = PT_LOAD;
+ phdrp->p_offset = ftell (ofp);
+ phdrp->p_vaddr = addr;
+ phdrp->p_paddr = addr;
+ phdrp->p_filesz = size;
+ phdrp->p_memsz = size;
+ phdrp->p_flags = PF_R;
+ if (ap->a_flag & A_CODE)
+ phdrp->p_flags |= PF_X;
+ phdrp->p_align = 1;
+ listAdd (segments, phdrp);
+ }
+
+ /* create a section header for this region */
+ shdrp = new (sizeof (*shdrp));
+ shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id);
+ shdrp->sh_type = SHT_PROGBITS;
+ shdrp->sh_flags = 0;
+ if (!(ap->a_flag & A_NOLOAD))
+ shdrp->sh_flags |= SHF_ALLOC;
+ if (ap->a_flag & A_CODE)
+ shdrp->sh_flags |= SHF_EXECINSTR;
+ shdrp->sh_addr = addr;
+ shdrp->sh_offset = ftell (ofp);
+ shdrp->sh_size = size;
+ shdrp->sh_link = 0;
+ shdrp->sh_info = 0;
+ shdrp->sh_addralign = 0;
+ shdrp->sh_entsize = 0;
+ listAdd (sections, shdrp);
+
+ fwrite (&ap->a_image[addr-ap->a_addr], 1, size, ofp);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+/* elfGenerateRel - generates a segment and section for a relative area. */
+/*--------------------------------------------------------------------------*/
+static void
+elfGenerateRel (struct area *ap, listHeader * segments, listHeader * sections)
+{
+ Elf32_Phdr * phdrp;
+ Elf32_Shdr * shdrp;
+
+ if (!ap->a_image)
+ {
+ return;
+ }
+
+ /* create a segment header for this area if loadable */
+ if (!(ap->a_flag & A_NOLOAD))
+ {
+ phdrp = new (sizeof (*phdrp));
+ phdrp->p_type = PT_LOAD;
+ phdrp->p_offset = ftell (ofp);
+ phdrp->p_vaddr = ap->a_addr;
+ phdrp->p_paddr = ap->a_addr;
+ phdrp->p_filesz = ap->a_size;
+ phdrp->p_memsz = ap->a_size;
+ phdrp->p_flags = PF_R;
+ if (ap->a_flag & A_CODE)
+ phdrp->p_flags |= PF_X;
+ phdrp->p_align = 1;
+ listAdd (segments, phdrp);
+ }
+
+ /* create a section header for this area */
+ shdrp = new (sizeof (*shdrp));
+ shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id);
+ shdrp->sh_type = SHT_PROGBITS;
+ shdrp->sh_flags = 0;
+ if (!(ap->a_flag & A_NOLOAD))
+ shdrp->sh_flags |= SHF_ALLOC;
+ if (ap->a_flag & A_CODE)
+ shdrp->sh_flags |= SHF_EXECINSTR;
+ shdrp->sh_addr = ap->a_addr;
+ shdrp->sh_offset = ftell (ofp);
+ shdrp->sh_size = ap->a_size;
+ shdrp->sh_link = 0;
+ shdrp->sh_info = 0;
+ shdrp->sh_addralign = 0;
+ shdrp->sh_entsize = 0;
+ listAdd (sections, shdrp);
+
+ fwrite (ap->a_image, 1, ap->a_size, ofp);
+}
+
+/*--------------------------------------------------------------------------*/
+/* elfGenerate - generates the complete ELF file */
+/*--------------------------------------------------------------------------*/
+static void
+elfGenerate (void)
+{
+ listHeader * sections = listNew();
+ listHeader * segments = listNew();
+ struct area *ap;
+ Elf32_Ehdr ehdr;
+ Elf32_Shdr * shdrp;
+ Elf32_Phdr * phdrp;
+ listEntry * lep;
+ int i;
+ Elf32_Word shstrtabName;
+
+ /* create the null section header for index 0 */
+ shdrp = new (sizeof (*shdrp));
+ shdrp->sh_name = 0;
+ shdrp->sh_type = SHT_NULL;
+ shdrp->sh_flags = 0;
+ shdrp->sh_addr = 0;
+ shdrp->sh_offset = 0;
+ shdrp->sh_size = 0;
+ shdrp->sh_link = 0;
+ shdrp->sh_info = 0;
+ shdrp->sh_addralign = 0;
+ shdrp->sh_entsize = 0;
+ listAdd (sections, shdrp);
+
+ /* Initialize the ELF header */
+ for (i=0; i<EI_NIDENT; i++)
+ ehdr.e_ident[i] = 0;
+ ehdr.e_ident[EI_MAG0] = ELFMAG0;
+ ehdr.e_ident[EI_MAG1] = ELFMAG1;
+ ehdr.e_ident[EI_MAG2] = ELFMAG2;
+ ehdr.e_ident[EI_MAG3] = ELFMAG3;
+ ehdr.e_ident[EI_CLASS] = ELFCLASS32;
+ if (hilo == 0)
+ ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+ else
+ ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
+ ehdr.e_ident[EI_VERSION] = 1;
+ ehdr.e_type = ET_EXEC;
+ ehdr.e_machine = EM_68HC08; /* FIXME: get rid of hardcoded value - EEP */
+ ehdr.e_phentsize = sizeof (*phdrp);
+ ehdr.e_shentsize = sizeof (*shdrp);
+ ehdr.e_ehsize = sizeof (ehdr);
+ ehdr.e_phnum = 0;
+ ehdr.e_shnum = 0;
+ ehdr.e_shstrndx = 0;
+ ehdr.e_version = 1;
+ ehdr.e_entry = 0;
+ if (execStartMSBfound && execStartLSBfound)
+ ehdr.e_entry = (execStartMSB << 8) + execStartLSB;
+
+ /* Write out the ELF header as a placeholder; we will update */
+ /* it with the final values when everything is complete */
+ fputElf32_Ehdr (&ehdr, ofp);
+
+ /* Iterate over the linker areas to generate */
+ /* the ELF sections and segments */
+ ap = areap;
+ while (ap)
+ {
+ if (ap->a_size)
+ {
+ if (ap->a_flag & A_ABS)
+ elfGenerateAbs (ap, segments, sections);
+ else
+ elfGenerateRel (ap, segments, sections);
+ }
+ ap = ap->a_ap;
+ }
+
+ /* Create the string table section after the other sections */
+ shdrp = new (sizeof (*shdrp));
+ shdrp->sh_name = strtabFindOrAdd (&shstrtab, ".shstrtab");
+ shdrp->sh_type = SHT_STRTAB;
+ shdrp->sh_flags = 0;
+ shdrp->sh_addr = 0;
+ shdrp->sh_offset = ftell (ofp);
+ shdrp->sh_size = shstrtab.last->index + strlen (shstrtab.last->string) + 1;
+ shdrp->sh_link = 0;
+ shdrp->sh_info = 0;
+ shdrp->sh_addralign = 0;
+ shdrp->sh_entsize = 0;
+ listAdd (sections, shdrp);
+ fputElfStrtab (&shstrtab, ofp);
+
+ /* Find the index of the section string table */
+ /* header and save it in the ELF header */
+ ehdr.e_shstrndx = 0;
+ shstrtabName = shdrp->sh_name;
+ lep = sections->first;
+ while (lep)
+ {
+ shdrp = lep->item;
+ if (shdrp->sh_name == shstrtabName)
+ break;
+ ehdr.e_shstrndx++;
+ lep = lep->next;
+ }
+
+ /* Write out the segment headers */
+ ehdr.e_phnum = segments->count;
+ ehdr.e_phoff = ftell (ofp);
+ lep = segments->first;
+ while (lep)
+ {
+ phdrp = lep->item;
+ fputElf32_Phdr (phdrp, ofp);
+ lep = lep->next;
+ }
+
+ /* Write out the section headers */
+ ehdr.e_shnum = sections->count;
+ ehdr.e_shoff = ftell (ofp);
+ lep = sections->first;
+ while (lep)
+ {
+ shdrp = lep->item;
+ fputElf32_Shdr (shdrp, ofp);
+ lep = lep->next;
+ }
+
+ /* All the values in the ELF header have now been computed; write */
+ /* over the placeholder header with the final values */
+ fseek (ofp, 0, SEEK_SET);
+ fputElf32_Ehdr (&ehdr, ofp);
+ fseek (ofp, 0, SEEK_END);
+}
+
+/*--------------------------------------------------------------------------*/
+/* elf - incrementally called by the linker core to generate ELF file data. */
+/* The parameter is nonzero when there is data available and zero when */
+/* the linker is finished. */
+/*--------------------------------------------------------------------------*/
+void
+elf (int i)
+{
+ Addr_T address;
+
+ /* Buffer the data until we have it all */
+ if (i)
+ {
+ if (hilo == 0)
+ address = rtval[0] + (rtval[1] << 8); /* little endian order */
+ else
+ address = rtval[1] + (rtval[0] << 8); /* big endian order */
+
+ /* If this area doesn't have an image buffer, create one */
+ if (!ap->a_image)
+ {
+ ap->a_image = new (ap->a_size);
+ if (ap->a_flag & A_ABS)
+ ap->a_used = new (ap->a_size);
+ }
+
+ /* Copy the data into the image buffer */
+ for (i = 2; i < rtcnt ; i++, address++)
+ {
+ if (rtflg[i])
+ {
+ ap->a_image[address-ap->a_addr] = rtval[i];
+ if (ap->a_used)
+ ap->a_used[address-ap->a_addr] = 1;
+
+ /* Make note of the reset vector */
+ if (!(ap->a_flag & A_NOLOAD))
+ {
+ if (address == 0xfffe)
+ {
+ execStartMSB = rtval[i];
+ execStartMSBfound = 1;
+ }
+ if (address == 0xffff)
+ {
+ execStartLSB = rtval[i];
+ execStartLSBfound = 1;
+ }
+ }
+ }
+ }
+ }
+ else
+ elfGenerate();
+}