* src/SDCCmain.c (linkEdit),
authorepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Mon, 19 Apr 2004 05:22:04 +0000 (05:22 +0000)
committerepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Mon, 19 Apr 2004 05:22:04 +0000 (05:22 +0000)
* 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

13 files changed:
ChangeLog
as/hc08/Makefile.in
as/hc08/aslink.h
as/hc08/asm.h
as/hc08/lkarea.c
as/hc08/lkelf.c [new file with mode: 0644]
as/hc08/lkihx.c
as/hc08/lkmain.c
as/hc08/lkrloc.c
as/hc08/lks19.c
as/hc08/m08pst.c
src/SDCCmain.c
src/hc08/main.c

index 74ceaa6bf54aa22c3b2b8e26d5f5d1e58189373e..0baf823c417e4c69b545caa2d679fd2804256226 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2004-04-19 Erik Petrich <epetrich AT ivorytower.norman.ok.us>
+
+       * 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 <jesusc AT ece.ubc.ca>
 
        * as/mcs51/lkihx.c: Fixed bug #899105.
index e9d5b9928b081f1b86f0481fe076804668b1fa2e..9ac6e5bb154a371a36167a9cbedb60c46fc7362b 100644 (file)
@@ -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))
 
index 263467a07e5d0c3df7609e366ae13a53c4bf05e9..a2dd2083d8c61fb12a7b7455d7bab2dccdf21f94 100644 (file)
 #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();
index c145aae46c3f44834002cf7dbb758aa2848464ea..948992a4dd61f654cdbdf29591703dc98c4d087c 100644 (file)
@@ -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
index d13f104ea186fc9d682e3fa584567ff62fc5b735..42cdd4c1efc6a3accd5da074f8b1034e1bd11185 100644 (file)
@@ -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 (file)
index 0000000..d024770
--- /dev/null
@@ -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 <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();
+}
index c5890cde1adbad071a8a9aa03b30a132da7e7475..28c2f500312bc803ce39172e5c31d486ab93efd3 100644 (file)
@@ -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];
index 548a44fdf53ba6e222c337bba8c1681192fff450..ae5aff2fa9000276cf832be2c3b93ce566ae4834 100644 (file)
@@ -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:", */
index 4fb276c46f16ad375ff01d7ce6e42c906d0ac03e..954b9c639ce9596d6e9e64848016c54235296a4f 100644 (file)
@@ -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);
        }
 }
 
index 26d8892e850de128e3d1d929b5c66fab5db3c7de..d50a41ea3472e6d5ff506b813d0908b691e4b7b3 100644 (file)
@@ -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];
index 54d725e87f480895700439dfb493307c4b913cd3..10a982d51eb0e4b64dd69218e6cecee6cabde020 100644 (file)
@@ -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       },
index e781993fb638dc81e1918f9ef39e13762fc17e16..fb8cfa76d50d2e03952464f695d02c46a31d757a 100644 (file)
@@ -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 <filename>.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");
         }
index a513f7ac12023503ba87651721d8d4c505b0f248..c25636b2f71957b7f4d6b5775371c829bbf47232 100644 (file)
@@ -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,