From 7709397297c098d91f4e0745713ca6a39459adf2 Mon Sep 17 00:00:00 2001 From: epetrich Date: Mon, 19 Apr 2004 05:22:04 +0000 Subject: [PATCH] * src/SDCCmain.c (linkEdit), * src/hc08/main.c (_hc08_parseOptions), * as/hc08/Makefile.in, * as/hc08/aslink.h, * as/hc08/asm.h, * as/hc08/m08pst.c, * as/hc08/lkrloc.c (relr, rele), * as/hc08/lkarea.c (lnkarea) * as/hc08/lkmain.c (afile, parse), * as/hc08/lkelf.c: support for ELF output * as/hc08/lks19.c (s19), * as/hc08/lkihx.c (ihx): ignore areas with the NOLOAD attribute git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3292 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 15 + as/hc08/Makefile.in | 2 +- as/hc08/aslink.h | 10 +- as/hc08/asm.h | 3 + as/hc08/lkarea.c | 2 + as/hc08/lkelf.c | 774 ++++++++++++++++++++++++++++++++++++++++++++ as/hc08/lkihx.c | 2 + as/hc08/lkmain.c | 24 +- as/hc08/lkrloc.c | 10 +- as/hc08/lks19.c | 2 + as/hc08/m08pst.c | 4 + src/SDCCmain.c | 21 +- src/hc08/main.c | 22 +- 13 files changed, 880 insertions(+), 11 deletions(-) create mode 100644 as/hc08/lkelf.c diff --git a/ChangeLog b/ChangeLog index 74ceaa6b..0baf823c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2004-04-19 Erik Petrich + + * src/SDCCmain.c (linkEdit), + * src/hc08/main.c (_hc08_parseOptions), + * as/hc08/Makefile.in, + * as/hc08/aslink.h, + * as/hc08/asm.h, + * as/hc08/m08pst.c, + * as/hc08/lkrloc.c (relr, rele), + * as/hc08/lkarea.c (lnkarea) + * as/hc08/lkmain.c (afile, parse), + * as/hc08/lkelf.c: support for ELF output + * as/hc08/lks19.c (s19), + * as/hc08/lkihx.c (ihx): ignore areas with the NOLOAD attribute + 2004-04-17 Jesus Calvino-Fraga * as/mcs51/lkihx.c: Fixed bug #899105. diff --git a/as/hc08/Makefile.in b/as/hc08/Makefile.in index e9d5b992..9ac6e5bb 100644 --- a/as/hc08/Makefile.in +++ b/as/hc08/Makefile.in @@ -41,7 +41,7 @@ ASSOURCES = $(patsubst %.o,%.c,$(ASOBJECTS)) LKOBJECTS = lkmain.o lkhead.o lkarea.o lkdata.o \ lkeval.o lklex.o lksym.o lkrloc.o \ - lklibr.o lklist.o lkihx.o lks19.o \ + lklibr.o lklist.o lkihx.o lks19.o lkelf.o \ lkstore.o lknoice.o lkmem.o lkaomf51.o strcmpi.o LKSOURCES = $(patsubst %.o,%.c,$(LKOBJECTS)) diff --git a/as/hc08/aslink.h b/as/hc08/aslink.h index 263467a0..a2dd2083 100644 --- a/as/hc08/aslink.h +++ b/as/hc08/aslink.h @@ -186,6 +186,9 @@ #define A_XDATA 0100 /* external data space */ #define A_BIT 0200 /* bit addressable space */ +#define A_NOLOAD 0400 /* nonloadable */ +#define A_LOAD 0000 /* loadable (default) */ + /* * File types */ @@ -245,8 +248,10 @@ struct area Addr_T a_addr; /* Beginning address of area */ Addr_T a_size; /* Total size of the area */ char a_type; /* Area subtype */ - char a_flag; /* Flag byte */ + int a_flag; /* Flag byte */ char a_id[NCPS]; /* Name */ + char *a_image; + char *a_used; }; /* @@ -773,3 +778,6 @@ extern int summary(struct area * xp); /* JCF: lkaomf51.c */ extern void SaveLinkedFilePath(char * filepath); extern void CreateAOMF51(void); + +/* EEP: lkelf.c */ +extern VOID elf(); diff --git a/as/hc08/asm.h b/as/hc08/asm.h index c145aae4..948992a4 100644 --- a/as/hc08/asm.h +++ b/as/hc08/asm.h @@ -175,6 +175,9 @@ struct area #define A_XDATA 0100 /* external data space */ #define A_BIT 0200 /* bit addressable space */ +#define A_NOLOAD 0400 /* nonloadable */ +#define A_LOAD 0000 /* loadable (default) */ + /* * The "R_" relocation constants define values used in * generating the assembler relocation output data for diff --git a/as/hc08/lkarea.c b/as/hc08/lkarea.c index d13f104e..42cdd4c1 100644 --- a/as/hc08/lkarea.c +++ b/as/hc08/lkarea.c @@ -335,6 +335,7 @@ lnkarea() } else { /* Determine memory space */ locIndex = 0; + #if 0 if (ap->a_flag & A_CODE) { locIndex = 1; } @@ -344,6 +345,7 @@ lnkarea() if (ap->a_flag & A_BIT) { locIndex = 3; } + #endif /* * Relocatable sections */ diff --git a/as/hc08/lkelf.c b/as/hc08/lkelf.c new file mode 100644 index 00000000..d024770b --- /dev/null +++ b/as/hc08/lkelf.c @@ -0,0 +1,774 @@ +/*------------------------------------------------------------------------- + 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 +#include +#include +#include +#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; ie_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; ia_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(); +} diff --git a/as/hc08/lkihx.c b/as/hc08/lkihx.c index c5890cde..28c2f500 100644 --- a/as/hc08/lkihx.c +++ b/as/hc08/lkihx.c @@ -201,6 +201,8 @@ ihx(i) { Addr_T n; if (i) { + if (ap->a_flag & A_NOLOAD) + return; if (hilo == 0) { n = rtval[0]; rtval[0] = rtval[1]; diff --git a/as/hc08/lkmain.c b/as/hc08/lkmain.c index 548a44fd..ae5aff2f 100644 --- a/as/hc08/lkmain.c +++ b/as/hc08/lkmain.c @@ -359,6 +359,12 @@ char *argv[]; } /* include NoICE command to load hex file */ if (jfp) fprintf( jfp, "LOAD %s.S19\n", linkp->f_idp ); + } else + if (oflag == 3) { + ofp = afile(linkp->f_idp, "elf", 4); + if (ofp == NULL) { + lkexit(1); + } } } else { /* @@ -770,6 +776,11 @@ parse() oflag = 2; break; + case 't': + case 'T': + oflag = 3; + break; + case 'm': case 'M': ++mflag; @@ -1154,8 +1165,18 @@ char *ft; { FILE *fp; char fb[PATH_MAX]; - char *omode = (wf ? (wf == 2 ? "a" : "w") : "r"); + char *omode; int i; + + switch (wf) { + case 0: omode = "r"; break; + case 1: omode = "w"; break; + case 2: omode = "a"; break; + case 3: omode = "rb"; break; + case 4: omode = "wb"; break; + case 5: omode = "ab"; break; + default: omode = "r"; break; + } /*Look backward the name path and get rid of the extension, if any*/ i=strlen(fn); @@ -1309,6 +1330,7 @@ char *usetxt[] = { "Output:", " -i Intel Hex as file[IHX]", " -s Motorola S19 as file[S19]", + " -t ELF executable as file[elf]", " -j Produce NoICE debug as file[NOI]", " -z Produce SDCdb debug as file[cdb]", /* "List:", */ diff --git a/as/hc08/lkrloc.c b/as/hc08/lkrloc.c index 4fb276c4..954b9c63 100644 --- a/as/hc08/lkrloc.c +++ b/as/hc08/lkrloc.c @@ -238,6 +238,7 @@ relt() * Addr_T adb_lo() lkrloc.c * Addr_T adb_hi() lkrloc.c * Addr_T adw_w() lkrloc.c + * VOID elf() lkelf.c * Addr_T evword() lkrloc.c * int eval() lkeval.c * int fprintf() c_library @@ -288,6 +289,7 @@ relr() lkerr++; return; } + ap = a[aindex]->a_bap; /* * Base values @@ -512,7 +514,6 @@ relr() lkulist(1); } - /* JLH: output only if data (beyond two byte address) */ if ((oflag == 1) && (rtcnt > 2)) { // int extendedAddress = (a[aindex]->a_addr >> 16) & 0xffff; @@ -570,6 +571,9 @@ relr() } else if ((oflag == 2) && (rtcnt > 2)) { s19(1); + } else + if ((oflag == 3) && (rtcnt > 2)) { + elf(1); } } @@ -726,6 +730,7 @@ relp() * int uflag relocation listing flag * * called functions: + * VOID elf() lkelf.c * VOID ihx() lkihx.c * VOID lkulist() lklist.c * VOID s19() lks19.c @@ -746,6 +751,9 @@ rele() } else if (oflag == 2) { s19(0); + } else + if (oflag == 3) { + elf(0); } } diff --git a/as/hc08/lks19.c b/as/hc08/lks19.c index 26d8892e..d50a41ea 100644 --- a/as/hc08/lks19.c +++ b/as/hc08/lks19.c @@ -99,6 +99,8 @@ s19(i) register Addr_T chksum; if (i) { + if (ap->a_flag & A_NOLOAD) + return; if (hilo == 0) { chksum = rtval[0]; rtval[0] = rtval[1]; diff --git a/as/hc08/m08pst.c b/as/hc08/m08pst.c index 54d725e8..10a982d5 100644 --- a/as/hc08/m08pst.c +++ b/as/hc08/m08pst.c @@ -28,6 +28,10 @@ struct mne mne[] = { { NULL, "ABS", S_ATYP, 0, A_ABS|A_OVR }, { NULL, "NOPAG", S_ATYP, 0, A_NOPAG }, { NULL, "PAG", S_ATYP, 0, A_PAG }, + { NULL, "CODE", S_ATYP, 0, A_CODE }, + { NULL, "DATA", S_ATYP, 0, A_DATA }, + { NULL, "LOAD", S_ATYP, 0, A_LOAD }, + { NULL, "NOLOAD", S_ATYP, 0, A_NOLOAD }, { NULL, ".byte", S_BYTE, 0, 1 }, { NULL, ".db", S_BYTE, 0, 1 }, diff --git a/src/SDCCmain.c b/src/SDCCmain.c index e781993f..fb8cfa76 100644 --- a/src/SDCCmain.c +++ b/src/SDCCmain.c @@ -1300,6 +1300,23 @@ linkEdit (char **envp) if(port->linker.needLinkerScript) { + char out_fmt; + + switch (options.out_fmt) + { + case 0: + out_fmt = 'i'; /* Intel hex */ + break; + case 1: + out_fmt = 's'; /* Motorola S19 */ + break; + case 2: + out_fmt = 't'; /* Elf */ + break; + default: + out_fmt = 'i'; + } + /* first we need to create the .lnk file */ SNPRINTF (scratchFileName, sizeof(scratchFileName), "%s.lnk", dstFileName); @@ -1312,11 +1329,11 @@ linkEdit (char **envp) if (TARGET_IS_Z80 || TARGET_IS_GBZ80) { fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n", - (options.out_fmt ? 's' : 'i'), dstFileName); + out_fmt, dstFileName); } else /*For all the other ports. Including pics???*/ { - fprintf (lnkfile, "-myux%c\n", (options.out_fmt ? 's' : 'i')); + fprintf (lnkfile, "-myux%c\n", out_fmt); if(options.pack_iram) fprintf (lnkfile, "-Y\n"); } diff --git a/src/hc08/main.c b/src/hc08/main.c index a513f7ac..c25636b2 100644 --- a/src/hc08/main.c +++ b/src/hc08/main.c @@ -96,9 +96,21 @@ _hc08_regparm (sym_link * l) static bool _hc08_parseOptions (int *pargc, char **argv, int *i) { + if (!strcmp (argv[*i], "--out-fmt-elf")) + { + options.out_fmt = 2; + return TRUE; + } + return FALSE; } +static OPTION _hc08_options[] = + { + { 0, "--out-fmt-elf", NULL, "Output executable in ELF format" }, + { 0, NULL } + }; + static void _hc08_finaliseOptions (void) { @@ -374,16 +386,16 @@ PORT hc08_port = { "XSEG", "STACK", - "CSEG", + "CSEG (CODE)", "DSEG", NULL, /* "ISEG" */ "XSEG", "BSEG", "RSEG", - "GSINIT", + "GSINIT (CODE)", "OSEG (OVR)", - "GSFINAL", - "HOME", + "GSFINAL (CODE)", + "HOME (CODE)", "XISEG", // initialized xdata "XINIT", // a code copy of xiseg NULL, @@ -402,7 +414,7 @@ PORT hc08_port = "_", _hc08_init, _hc08_parseOptions, - NULL, + _hc08_options, _hc08_finaliseOptions, _hc08_setDefaultOptions, hc08_assignRegisters, -- 2.30.2