From ab901cebfa59b5a8efc5efceb211f68ae7446173 Mon Sep 17 00:00:00 2001 From: Peter Lafreniere Date: Fri, 29 Mar 2024 17:12:40 -0400 Subject: [PATCH 1/2] ld-tigcc: slightly optimize IsZer?() macros for x86_64 platforms IsZeroI{1,2,4}() has an optimization for 32 bit x86 processors, as they have no alignment requirement. The same holds for 64 bit x86 processors. This change is expected to have negligible impact on linking speed. --- trunk/tigcc/ld-tigcc/integers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/tigcc/ld-tigcc/integers.h b/trunk/tigcc/ld-tigcc/integers.h index dd23dab0..2d2cf746 100644 --- a/trunk/tigcc/ld-tigcc/integers.h +++ b/trunk/tigcc/ld-tigcc/integers.h @@ -32,7 +32,7 @@ typedef I4 ZI4; #define IsZero(I) (!(I)) -#ifdef __i386__ +#if defined (__i386__) || defined (__x86_64__) // This only works on targets which don't care about alignment. #define IsZeroI1(I) (IsZero (*((ZI1 *) &(I)))) #define IsZeroI2(I) (IsZero (*((ZI2 *) &(I)))) From f9d6c34671982fa9c4204c10998c57aad05d4b18 Mon Sep 17 00:00:00 2001 From: Peter Lafreniere Date: Tue, 9 Jul 2024 16:39:50 -0400 Subject: [PATCH 2/2] ld-tigcc: Add support for importing ELF object files Support importing ELF object files into ld-tigcc and ar-tigcc. Support is sufficient for most uses of the tool, but gcc4ti-specific linking extentions aren't supported due to the lack of customized ELF toolchains. The linker was not built around ELF support, so some features like visibility and weak binding aren't supported beyond the default behavior. Attempts to use those features proceed with a warning. Debug info is also not handled, as I have never used that feature with COFF code and am primarily interested in getting code off my hard drive and letting others use upstream compilers if they're as crazy as me. --- trunk/tigcc/doc/System/Info/ld/formats.hss | 14 + trunk/tigcc/ld-tigcc/Makefile | 6 +- trunk/tigcc/ld-tigcc/ar/import/imp_elf.c | 184 ++++++++ trunk/tigcc/ld-tigcc/ar/import/imp_elf.h | 33 ++ trunk/tigcc/ld-tigcc/ar/import/import.c | 10 + trunk/tigcc/ld-tigcc/formats/elf.h | 292 +++++++++++++ trunk/tigcc/ld-tigcc/import/imp_elf.c | 478 +++++++++++++++++++++ trunk/tigcc/ld-tigcc/import/imp_elf.h | 33 ++ trunk/tigcc/ld-tigcc/import/import.c | 10 + 9 files changed, 1057 insertions(+), 3 deletions(-) create mode 100644 trunk/tigcc/ld-tigcc/ar/import/imp_elf.c create mode 100644 trunk/tigcc/ld-tigcc/ar/import/imp_elf.h create mode 100644 trunk/tigcc/ld-tigcc/formats/elf.h create mode 100644 trunk/tigcc/ld-tigcc/import/imp_elf.c create mode 100644 trunk/tigcc/ld-tigcc/import/imp_elf.h diff --git a/trunk/tigcc/doc/System/Info/ld/formats.hss b/trunk/tigcc/doc/System/Info/ld/formats.hss index a26254c6..e71e9bac 100644 --- a/trunk/tigcc/doc/System/Info/ld/formats.hss +++ b/trunk/tigcc/doc/System/Info/ld/formats.hss @@ -52,6 +52,20 @@ each format is described in the following table: Yes (through symbols) +ELF +Yes +Yes +Yes +Yes +Yes (through unresolved relocations) +Yes (through unresolved relocations) +Yes (through unresolved relocations) +Yes (through symbols) +Yes (but not yet supported by the linker) +Yes (through symbols) +Yes (through symbols) + + TIOS ASM No 4-byte absolute only diff --git a/trunk/tigcc/ld-tigcc/Makefile b/trunk/tigcc/ld-tigcc/Makefile index 95890dc3..1ed6e77a 100644 --- a/trunk/tigcc/ld-tigcc/Makefile +++ b/trunk/tigcc/ld-tigcc/Makefile @@ -21,7 +21,7 @@ endif CC ?= gcc CFLAGS = -s -Os -fno-exceptions WARN_CFLAGS = -W -Wall -Wwrite-strings -Wpointer-arith -DEFINES = -DCOFF_SUPPORT -DAMIGAOS_SUPPORT -DTIOS_SUPPORT -DFLASH_OS_SUPPORT -DNOSTUB_DLL_SUPPORT -DFARGO_SUPPORT -DDATA_VAR_SUPPORT -DTIOS_FILE_SUPPORT -DTIOS_UPGRADE_FILE_SUPPORT -DDEBUGGING_INFO_SUPPORT -DCOFF_TIGCC_EXTENSIONS -DAMIGAOS_TIGCC_EXTENSIONS +DEFINES = -DCOFF_SUPPORT -DAMIGAOS_SUPPORT -DELF_SUPPORT -DTIOS_SUPPORT -DFLASH_OS_SUPPORT -DNOSTUB_DLL_SUPPORT -DFARGO_SUPPORT -DDATA_VAR_SUPPORT -DTIOS_FILE_SUPPORT -DTIOS_UPGRADE_FILE_SUPPORT -DDEBUGGING_INFO_SUPPORT -DCOFF_TIGCC_EXTENSIONS -DAMIGAOS_TIGCC_EXTENSIONS EXE_DEFINES = -DPUCRUNCH_SUPPORT -DENABLE_HELP -DENABLE_STATS -DENABLE_DUMP RM = rm @@ -31,8 +31,8 @@ COMPILE_C = $(CC) -c $(CFLAGS) $(ARCHFLAGS) $(WARN_CFLAGS) $(DEFINES) HEADERS = *.h formats/*.h import/*.h export/*.h bincode/*.h insert/*.h insert/model/*.h int_def.inc AR_HEADERS = ar/*.h ar/import/*.h ar/export/*.h *.h formats/*.h -OBJECTS = main.o integers.o int_arb.o manip.o constmrg.o gcunused.o reorder.o import/import.o import/imp_coff.o import/imp_amig.o import/imp_ar.o export/export.o export/exp_def.o export/exp_os.o export/exp_tios.o export/exp_ndll.o export/exp_farg.o export/exp_data.o export/exp_dbg.o export/pucrunch.o bincode/fix_m68k.o bincode/fix_tios.o bincode/fix_emu.o bincode/cutrange.o insert/ins_def.o insert/model/list.o insert/kernel.o insert/comprrlc.o insert/other.o special.o dump.o -AR_OBJECTS = ar/main.o ar/manip.o ar/import/import.o ar/import/imp_coff.o ar/import/imp_amig.o ar/export/exp_ar.o ar/dump.o integers.o +OBJECTS = main.o integers.o int_arb.o manip.o constmrg.o gcunused.o reorder.o import/import.o import/imp_coff.o import/imp_amig.o import/imp_elf.o import/imp_ar.o export/export.o export/exp_def.o export/exp_os.o export/exp_tios.o export/exp_ndll.o export/exp_farg.o export/exp_data.o export/exp_dbg.o export/pucrunch.o bincode/fix_m68k.o bincode/fix_tios.o bincode/fix_emu.o bincode/cutrange.o insert/ins_def.o insert/model/list.o insert/kernel.o insert/comprrlc.o insert/other.o special.o dump.o +AR_OBJECTS = ar/main.o ar/manip.o ar/import/import.o ar/import/imp_coff.o ar/import/imp_amig.o ar/import/imp_elf.o ar/export/exp_ar.o ar/dump.o integers.o DLL_OBJECTS = main.do integers.do int_arb.do manip.do constmrg.do gcunused.do reorder.do import/import.do import/imp_coff.do import/imp_amig.do import/imp_ar.do export/export.do export/exp_def.do export/exp_os.do export/exp_tios.do export/exp_ndll.do export/exp_farg.do export/exp_data.do export/exp_dbg.do bincode/fix_m68k.do bincode/fix_tios.do bincode/fix_emu.do bincode/cutrange.do insert/ins_def.do insert/model/list.do insert/kernel.do insert/comprrlc.do insert/other.do special.do DLL_AR_OBJECTS = ar/main.do ar/manip.do ar/import/import.do ar/import/imp_coff.do ar/import/imp_amig.do ar/export/exp_ar.do BACKUPS = *~ format/*~ import/*~ export/*~ bincode/*~ insert/*~ insert/model/*~ ar/*~ ar/import/*~ ar/export/*~ diff --git a/trunk/tigcc/ld-tigcc/ar/import/imp_elf.c b/trunk/tigcc/ld-tigcc/ar/import/imp_elf.c new file mode 100644 index 00000000..6f2ee9bf --- /dev/null +++ b/trunk/tigcc/ld-tigcc/ar/import/imp_elf.c @@ -0,0 +1,184 @@ +/* imp_elf.c: Routines to import an ELF file + + Copyright (C) 2024 Peter Lafreniere + + 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, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef ELF_SUPPORT + +#include "imp_elf.h" + +#include "../../formats/elf.h" + +#include +#include + + +BOOLEAN ArImportELFFile (OBJECT_FILE *ObjectFile) +{ + +// Call this for a nice and clean failing exit. +#define FailMsg(msg) ({ Error (ObjectFile->FileName, msg); return FALSE; }) +#define Fail() FailMsg("Corrupt ELF object file.") +#define TestMem(Ptr) ({ if (!(Ptr)) FailMsg("Out of memory."); }) + +// Check if a given object with a given type is completely inside the file. +#define IsInFile(Ptr,Type) (((const I1 *) (Ptr)) >= ObjectFile->Data && ((const I1 *) (Ptr)) + sizeof (Type) <= ObjectFile->Data + ObjectFile->Size) +#define TestInFile(Ptr,Type) ({ if (!(IsInFile (Ptr, Type))) { Fail (); } }) + + const ELF_HEADER *ELFHeader = (ELF_HEADER *)ObjectFile->Data; + const ELF_SYMBOLS *ELFSymbols = NULL; + const ELF_SECTIONS *ELFSections; + const char *SymNames = NULL; + const char *SecNames; + SIZE SecNamesSize; + SIZE SymNamesSize; + COUNT SecCount; + COUNT SymCount; + OFFSET SecIdx; + OFFSET SymIdx; + + if (!IsValidELFObjectFile (ELFHeader)) + FailMsg ("Invalid ELF object file"); + + ELFSections = (ELF_SECTIONS *)(ObjectFile->Data + ReadTI4 (ELFHeader->SectionHeadOff)); + SecCount = ReadTI2 (ELFHeader->SectionHeadCount); + if (IsZero (SecCount)) + Fail(); + + // *** Initialize section string table data *** + { + OFFSET SectionNameIdx = ReadTI2 (ELFHeader->SectionNameIdx); + const ELF_SECTION *Section; + + if (IsZero (SectionNameIdx)) { + Fail (); + } else if (SectionNameIdx == 0xFFFF) { + Section = &(*ELFSections) [0]; + TestInFile (Section, ELF_SECTION); + SectionNameIdx = ReadTI4 (Section->Link); + } + + Section = &(*ELFSections) [SectionNameIdx]; + TestInFile (Section, ELF_SECTION); + + SecNames = (char *)(ObjectFile->Data + ReadTI4 (Section->FileOffset)); + SecNamesSize = ReadTI4 (Section->Size); + + // Bounds check the string table here rather than for each string + // And make sure that the section is null-terminated + if (SecNames + SecNamesSize > (char *)ObjectFile->Data + ObjectFile->Size || + !IsZero (SecNames [SecNamesSize - 1])) + Fail (); + } + + // *** Locate symbol table and symbol string data *** + for (SecIdx = 0; SecIdx < SecCount; SecIdx++) { + const ELF_SECTION *Section; + const char *Name; + I4 Type; + + Section = &(*ELFSections) [SecIdx]; + TestInFile (Section, ELF_SECTION); + + Type = ReadTI4 (Section->Type); + + // If this is the symbol table + if (Type == SHT_SYMTAB) { + if (ELFSymbols != NULL) + FailMsg ("Multiple ELF symbol tables found"); + + // Make sure that the symbols are the right format + if (ReadTI4 (Section->EntrySize) != sizeof (ELF_SYMBOL)) + Fail (); + + ELFSymbols = (ELF_SYMBOLS *)(ObjectFile->Data + ReadTI4 (Section->FileOffset)); + SymCount = ReadTI4 (Section->Size) / sizeof (ELF_SYMBOL); + continue; + } + + // Bounds check the name + if ((SIZE) ReadTI4 (Section->NameIdx) > SecNamesSize) + Fail (); + + Name = &SecNames [ReadTI4 (Section->NameIdx)]; + + // If this is the symbol string table + if (Type == SHT_STRTAB && !strncmp (Name, ".strtab", 7)) { + SymNames = (char *)(ObjectFile->Data + ReadTI4 (Section->FileOffset)); + SymNamesSize = ReadTI4 (Section->Size); + + // Bounds check the string table here rather than for each string + // And make sure that the section is null-terminated + if (SymNames + SymNamesSize > (char *)ObjectFile->Data + ObjectFile->Size || + !IsZero (SymNames [SymNamesSize - 1])) + Fail (); + } + } + + if (ELFSymbols == NULL || SymNames == NULL) + Fail (); + + // For each symbol + for (SymIdx = 0; SymIdx < SymCount; SymIdx++) { + const ELF_SYMBOL *ELFSymbol; + const char *Name; + OFFSET SymSecIdx; + + ELFSymbol = &(*ELFSymbols) [SymIdx]; + // We've already checked this for every symbol in the table + //TestInFile(ELFSymbol, ELF_SYMBOL); + + // Bounds check the name + if ((SIZE) ReadTI4 (ELFSymbol->NameIdx) > SymNamesSize) + Fail (); + + // If the symbol has no name, this should point to a null byte + Name = &SymNames [ReadTI4 (ELFSymbol->NameIdx)]; + + SymSecIdx = ReadTI2 (ELFSymbol->SectionIdx); + + if (!IsZero (*Name) && !IsZero (SymSecIdx) && SymSecIdx < SecCount) { + char Visibility; + char Bind; + + Visibility = ReadTI1 (ELFSymbol->Visibility); + Bind = ELF32_ST_BIND (ReadTI1 (ELFSymbol->Info)); + + // If the symbol is exported, emit it + // + // Note that all visibilities are treated as default when linking, + // which can lead to unexpected results. + // + // The same applies to weak binding. + if (Visibility != STV_HIDDEN && (Bind == STB_GLOBAL || Bind == STB_WEAK)) { + SYMBOL *ARSym = calloc (1, sizeof (SYMBOL)); + TestMem (ARSym); + + ARSym->Parent = ObjectFile; + + ARSym->NameLength = strnlen (Name, MAX_SYM_LEN); + memcpy (ARSym->Name, Name, ARSym->NameLength); + + Append (ObjectFile->Symbols, ARSym); + ObjectFile->Parent->SymbolCount++; + } + } + } + + return TRUE; +} + +#endif /* ELF_SUPPORT */ diff --git a/trunk/tigcc/ld-tigcc/ar/import/imp_elf.h b/trunk/tigcc/ld-tigcc/ar/import/imp_elf.h new file mode 100644 index 00000000..08d99315 --- /dev/null +++ b/trunk/tigcc/ld-tigcc/ar/import/imp_elf.h @@ -0,0 +1,33 @@ +/* imp_elf.h: Routines to import an ELF file + + Copyright (C) 2024 Peter Lafreniere + + 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, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef IMP_ELF_H +#define IMP_ELF_H + +#include "../../generic.h" + +#ifdef ELF_SUPPORT + +#include "../data.h" + +// Import the exported symbols of an m68k-elf file. +BOOLEAN ArImportELFFile (OBJECT_FILE *ObjectFile); + +#endif /* ELF_SUPPORT */ + +#endif /* IMP_ELF_H */ diff --git a/trunk/tigcc/ld-tigcc/ar/import/import.c b/trunk/tigcc/ld-tigcc/ar/import/import.c index 292479c9..142cc1d9 100644 --- a/trunk/tigcc/ld-tigcc/ar/import/import.c +++ b/trunk/tigcc/ld-tigcc/ar/import/import.c @@ -28,6 +28,11 @@ #include "imp_amig.h" #endif /* AMIGAOS_SUPPORT */ +#ifdef ELF_SUPPORT +#include "../../formats/elf.h" +#include "imp_elf.h" +#endif /* ELF_SUPPORT */ + // Import an object file with an arbitrary format. BOOLEAN ArImportObjectFile (OBJECT_FILE *ObjectFile) { @@ -44,6 +49,11 @@ BOOLEAN ArImportObjectFile (OBJECT_FILE *ObjectFile) return (ArImportAmigaOSFile (ObjectFile)); else #endif /* AMIGAOS_SUPPORT */ +#ifdef ELF_SUPPORT + if (IsELFFile (ObjectFile->Data, ObjectFile->Size)) + return (ArImportELFFile (ObjectFile)); + else +#endif /* ELF_SUPPORT */ { Warning (ObjectFile->FileName, "Unknown object file format."); return FALSE; diff --git a/trunk/tigcc/ld-tigcc/formats/elf.h b/trunk/tigcc/ld-tigcc/formats/elf.h new file mode 100644 index 00000000..16af9fe0 --- /dev/null +++ b/trunk/tigcc/ld-tigcc/formats/elf.h @@ -0,0 +1,292 @@ +/* elf.h: Definitions for m68k-elf object files + + Copyright (C) 2024 Peter Lafreniere + + Based on GNU C Library header which is: + Copyright (C) 1995-2024 Free Software Foundation, Inc. + + 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, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef ELF_H +#define ELF_H + +#include "../generic.h" +#include "../integers.h" + +#define EI_NIDENT 16 + +#define ELF_MACH_M68K 4 +#define ELF_OBJ_FILE_TYPE 1 + +// ELF file header +typedef struct ATTRIBUTE_PACKED { + TI1 Ident[EI_NIDENT]; + TI2 Type; + TI2 Machine; + TI4 Version; + TI4 Entry; + TI4 ProgramHeadOff; + TI4 SectionHeadOff; + TI4 Flags; + TI2 HeaderSize; + TI2 ProgramHeadSize; + TI2 ProgramHeadCount; + TI2 SectionHeadSize; + TI2 SectionHeadCount; + TI2 SectionNameIdx; +} ELF_HEADER; + +typedef struct ATTRIBUTE_PACKED { + TI4 NameIdx; + TI4 Type; + TI4 Flags; + TI4 Address; + TI4 FileOffset; + TI4 Size; + TI4 Link; + TI4 Info; + TI4 Alignment; + TI4 EntrySize; +} ELF_SECTION; + +typedef ELF_SECTION ELF_SECTIONS[]; + +typedef struct ATTRIBUTE_PACKED { + TI4 NameIdx; + TI4 Value; + TI4 Size; + TI1 Info; + TI1 Visibility; + TI2 SectionIdx; +} ELF_SYMBOL; + +typedef ELF_SYMBOL ELF_SYMBOLS[]; + +typedef struct ATTRIBUTE_PACKED { + TI4 Offset; + TI4 Info; +} ELF_RELOC; + +typedef ELF_RELOC ELF_RELOCS[]; + +typedef struct ATTRIBUTE_PACKED { + TI4 Offset; + TI4 Info; + TI4 Addend; +} ELF_RELOCA; + +typedef ELF_RELOCA ELF_RELOCAS[]; + +/* +typedef struct { + TI4 p_type; + TI4 p_offset; + TI4 p_vaddr; + TI4 p_paddr; + TI4 p_filesz; + TI4 p_memsz; + TI4 p_flags; + TI4 p_align; +} ELF_PROGRAM; +*/ + +/* Fields in the e_ident array. The EI_* macros are indices into the + array. The macros under each EI_* macro are the values the byte + may have. */ + +#define ELFMAG 0x7f454c46 + +#define EI_CLASS 4 +#define ELFCLASS32 1 + +#define EI_DATA 5 +#define ELFDATA2MSB 2 + +#define EI_VERSION 6 +#define EV_CURRENT 1 + +/* Legal values for sh_type (section type). */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indices */ +#define SHT_RELR 19 /* RELR relative relocations */ +#define SHT_NUM 20 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific. */ +#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ +#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +/* Legal values for sh_flags (section flags). */ + +#define ELF_SECTION_WRITE (1 << 0) +#define ELF_SECTION_ALLOC (1 << 1) +#define ELF_SECTION_EXECINSTR (1 << 2) +#define ELF_SECTION_MERGE (1 << 4) +#define ELF_SECTION_STRINGS (1 << 5) +#define ELF_SECTION_INFO_LINK (1 << 6) +#define ELF_SECTION_LINK_ORDER (1 << 7) +#define ELF_SECTION_OS_NONCONFORMING (1 << 8) +#define ELF_SECTION_GROUP (1 << 9) +#define ELF_SECTION_TLS (1 << 10) +#define ELF_SECTION_COMPRESSED (1 << 11) + + +/* Motorola 68k specific definitions. */ + +/* Values for Elf32_Ehdr.e_flags. */ +#define EF_CPU32 0x00810000 + +/* How to extract and insert information held in the r_info field. */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) + +/* m68k relocs. */ + +#define R_68K_NONE 0 /* No reloc */ +#define R_68K_32 1 /* Direct 32 bit */ +#define R_68K_16 2 /* Direct 16 bit */ +#define R_68K_8 3 /* Direct 8 bit */ +#define R_68K_PC32 4 /* PC relative 32 bit */ +#define R_68K_PC16 5 /* PC relative 16 bit */ +#define R_68K_PC8 6 /* PC relative 8 bit */ +#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ +#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ +#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ +#define R_68K_GOT32O 10 /* 32 bit GOT offset */ +#define R_68K_GOT16O 11 /* 16 bit GOT offset */ +#define R_68K_GOT8O 12 /* 8 bit GOT offset */ +#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ +#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ +#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ +#define R_68K_PLT32O 16 /* 32 bit PLT offset */ +#define R_68K_PLT16O 17 /* 16 bit PLT offset */ +#define R_68K_PLT8O 18 /* 8 bit PLT offset */ +#define R_68K_COPY 19 /* Copy symbol at runtime */ +#define R_68K_GLOB_DAT 20 /* Create GOT entry */ +#define R_68K_JMP_SLOT 21 /* Create PLT entry */ +#define R_68K_RELATIVE 22 /* Adjust by program base */ +#define R_68K_TLS_GD32 25 /* 32 bit GOT offset for GD */ +#define R_68K_TLS_GD16 26 /* 16 bit GOT offset for GD */ +#define R_68K_TLS_GD8 27 /* 8 bit GOT offset for GD */ +#define R_68K_TLS_LDM32 28 /* 32 bit GOT offset for LDM */ +#define R_68K_TLS_LDM16 29 /* 16 bit GOT offset for LDM */ +#define R_68K_TLS_LDM8 30 /* 8 bit GOT offset for LDM */ +#define R_68K_TLS_LDO32 31 /* 32 bit module-relative offset */ +#define R_68K_TLS_LDO16 32 /* 16 bit module-relative offset */ +#define R_68K_TLS_LDO8 33 /* 8 bit module-relative offset */ +#define R_68K_TLS_IE32 34 /* 32 bit GOT offset for IE */ +#define R_68K_TLS_IE16 35 /* 16 bit GOT offset for IE */ +#define R_68K_TLS_IE8 36 /* 8 bit GOT offset for IE */ +#define R_68K_TLS_LE32 37 /* 32 bit offset relative to + static TLS block */ +#define R_68K_TLS_LE16 38 /* 16 bit offset relative to + static TLS block */ +#define R_68K_TLS_LE8 39 /* 8 bit offset relative to + static TLS block */ +#define R_68K_TLS_DTPMOD32 40 /* 32 bit module number */ +#define R_68K_TLS_DTPREL32 41 /* 32 bit module-relative offset */ +#define R_68K_TLS_TPREL32 42 /* 32 bit TP-relative offset */ +/* Keep this the last entry. */ +#define R_68K_NUM 43 + +#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) +#define ELF32_ST_TYPE(val) ((val) & 0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Legal values for ST_BIND subfield of st_info (symbol binding). */ + +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* Weak symbol */ +#define STB_NUM 3 /* Number of defined types. */ +#define STB_LOOS 10 /* Start of OS-specific */ +#define STB_GNU_UNIQUE 10 /* Unique symbol. */ +#define STB_HIOS 12 /* End of OS-specific */ +#define STB_LOPROC 13 /* Start of processor-specific */ +#define STB_HIPROC 15 /* End of processor-specific */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol associated with a section */ +#define STT_FILE 4 /* Symbol's name is file name */ +#define STT_COMMON 5 /* Symbol is a common data object */ +#define STT_TLS 6 /* Symbol is thread-local data object*/ +#define STT_NUM 7 /* Number of defined types. */ +#define STT_LOOS 10 /* Start of OS-specific */ +#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ +#define STT_HIOS 12 /* End of OS-specific */ +#define STT_LOPROC 13 /* Start of processor-specific */ +#define STT_HIPROC 15 /* End of processor-specific */ + +/* How to extract and insert information held in the st_other field. */ + +#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) + +/* Symbol visibility specification encoded in the st_other field. */ +#define STV_DEFAULT 0 /* Default symbol visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Sym unavailable in other modules */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + +// This ensures that the file is indeed in ELF format. +// IsValidELFObjectFile () ensures that the file is in a _valid_ ELF format. +#define IsELFFile(File, FileSize) (FileSize > (SIZE)sizeof(ELF_HEADER) && ReadTI4(*(TI4 *)File) == ELFMAG) + +static inline BOOLEAN IsValidELFObjectFile (const ELF_HEADER *ELFHeader) +{ + return (ReadI1 (ELFHeader->Ident[EI_CLASS]) == ELFCLASS32 && + ReadI1 (ELFHeader->Ident[EI_DATA]) == ELFDATA2MSB && + ReadI1 (ELFHeader->Ident[EI_VERSION]) == EV_CURRENT && + ReadTI2 (ELFHeader->Type) == ELF_OBJ_FILE_TYPE && + ReadTI4 (ELFHeader->Version) == EV_CURRENT && + ReadTI2 (ELFHeader->Machine) == ELF_MACH_M68K && + ReadTI2 (ELFHeader->SectionHeadSize) == sizeof (ELF_SECTION)); +} + +#endif /* ELF_H */ diff --git a/trunk/tigcc/ld-tigcc/import/imp_elf.c b/trunk/tigcc/ld-tigcc/import/imp_elf.c new file mode 100644 index 00000000..fc101e86 --- /dev/null +++ b/trunk/tigcc/ld-tigcc/import/imp_elf.c @@ -0,0 +1,478 @@ +/* imp_elf.c: Routines to import an ELF file + + Copyright (C) 2024 Peter Lafreniere + + 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, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef ELF_SUPPORT + +#include "imp_elf.h" + +#include "../data.h" +#include "../formats/elf.h" +#include "../integers.h" +#include "../manip.h" +#include "../special.h" + +#include +#include + +typedef struct { + SECTION *Section; + const char *Name; +} SEC_INFO; + +typedef struct { + union { + SYMBOL *Symbol; + const char *Name; + }; + BOOLEAN HasSymbol; +} SYM_INFO; + +// Call this for a nice and clean failing exit. +#define FailMsg(msg) ({ if (SecInfo) free (SecInfo); if (SymInfo) free (SymInfo); Error (FileName, msg); return FALSE; }) +#define Fail() FailMsg("Corrupt ELF object file.") +#define TestMem(Ptr) ({ if (!(Ptr)) FailMsg("Out of memory."); }) + +// Check if a given object with a given type is completely inside the file. +#define IsInFile(Ptr,Type) (((const I1 *) (Ptr)) >= File && ((const I1 *) (Ptr)) + sizeof (Type) <= File + FileSize) +#define TestInFile(Ptr,Type) ({ if (!(IsInFile (Ptr, Type))) { Fail (); } }) + +// We split the relocation code into a macro to support both .rel and .rela +// structs. +#define ImportRelocSection(RelocType, SecNameLen, ADDITIONAL_STATEMENTS) do { \ + const char *TargetSecName; \ + const RelocType *Relocs; \ + SECTION *Section = NULL; \ + COUNT RelocCount; \ + OFFSET Idx; \ + \ + if (SecNameSize <= SecNameLen) \ + Fail (); \ + \ + TargetSecName = SecName + SecNameLen; \ + \ + /* Find the section with that name */ \ + for (Idx = 0; Idx < SecCount; Idx++) { \ + if (SecInfo[Idx].Name && !strcmp (TargetSecName, SecInfo[Idx].Name)) { \ + Section = SecInfo[Idx].Section; \ + break; \ + } \ + } \ + \ + /* Either that section doesn't exist or we pruned it earlier */ \ + if (!Section) \ + FailMsg ("Relocation table found for unallocated section"); \ + \ + /* Make sure that the entries are the right format */ \ + if (ReadTI4 (ELFSection->EntrySize) != sizeof (RelocType)) \ + Fail (); \ + \ + Relocs = (const RelocType *)(File + ReadTI4 (ELFSection->FileOffset)); \ + RelocCount = ReadTI4 (ELFSection->Size) / sizeof (RelocType); \ + \ + for (Idx = 0; Idx < RelocCount; Idx++) { \ + const RelocType *ELFReloc; \ + RELOC *LDReloc; \ + I4 Info; \ + \ + ELFReloc = &Relocs[Idx]; \ + TestInFile (ELFReloc, RelocType); \ + \ + LDReloc = calloc (1, sizeof (RELOC)); \ + TestMem (LDReloc); \ + \ + Info = ReadTI4 (ELFReloc->Info); \ + \ + LDReloc->Parent = Section; \ + LDReloc->Location = ReadTI4 (ELFReloc->Offset); \ + \ + /* TODO: figure out Reloc->Unoptimizable */ \ + \ + /* Dispatch based on location */ \ + switch (ELF32_R_TYPE (Info)) { \ + case R_68K_32: \ + LDReloc->Size = 4; \ + break; \ + case R_68K_16: \ + LDReloc->Size = 2; \ + break; \ + case R_68K_8: \ + LDReloc->Size = 1; \ + case R_68K_PC32: \ + LDReloc->Size = 4; \ + LDReloc->Relative = TRUE; \ + break; \ + case R_68K_PC16: \ + LDReloc->Size = 2; \ + LDReloc->Relative = TRUE; \ + break; \ + case R_68K_PC8: \ + LDReloc->Size = 1; \ + LDReloc->Relative = TRUE; \ + default: \ + Warning (FileName, "Ignoring reloc %d at 0x%x in section '%s' with unknown type '0x%X'.", \ + Idx, LDReloc->Location, TargetSecName, ELF32_R_TYPE (Info)); \ + } \ + \ + if ((COUNT) ELF32_R_SYM (Info) >= SymCount) \ + Fail (); \ + \ + if (SymInfo[ELF32_R_SYM (Info)].HasSymbol) { \ + LDReloc->Target.Symbol = SymInfo[ELF32_R_SYM (Info)].Symbol; \ + LDReloc->Target.SymbolName = LDReloc->Target.Symbol->Name; \ + } else { \ + LDReloc->Target.SymbolName = strdup (SymInfo[ELF32_R_SYM (Info)].Name); \ + } \ + \ + ADDITIONAL_STATEMENTS \ + \ + InsertReloc (Section, LDReloc); \ + } \ +} while (0) + +BOOLEAN ImportELFFile (PROGRAM *Program, const I1 *File, SIZE FileSize, const char *FileName) +{ + const ELF_HEADER *ELFHeader = (ELF_HEADER *)File; + const ELF_SYMBOLS *ELFSymbols = NULL; + const ELF_SECTIONS *ELFSections; + BOOLEAN InitializeBSS = TRUE; + const char *SymNames = NULL; + BOOLEAN AllRelocs = FALSE; + SEC_INFO *SecInfo = NULL; + SYM_INFO *SymInfo = NULL; + const char *SecNames; + SIZE SecNamesSize; + SIZE SymNamesSize; + COUNT SecCount; + COUNT SymCount; + OFFSET SecIdx; + OFFSET SymIdx; + + if (!IsValidELFObjectFile (ELFHeader)) + FailMsg ("Invalid ELF object file"); + + ELFSections = (ELF_SECTIONS *)(File + ReadTI4 (ELFHeader->SectionHeadOff)); + SecCount = ReadTI2 (ELFHeader->SectionHeadCount); + if (IsZero (SecCount)) + Fail(); + + // *** Initialize section string table data *** + { + OFFSET SectionNameIdx = ReadTI2 (ELFHeader->SectionNameIdx); + const ELF_SECTION *Section; + + if (IsZero (SectionNameIdx)) { + Fail (); + } else if (SectionNameIdx == 0xFFFF) { + Section = &(*ELFSections)[0]; + TestInFile (Section, ELF_SECTION); + SectionNameIdx = ReadTI4 (Section->Link); + } + + Section = &(*ELFSections)[SectionNameIdx]; + TestInFile (Section, ELF_SECTION); + + SecNames = (char *)(File + ReadTI4 (Section->FileOffset)); + SecNamesSize = ReadTI4 (Section->Size); + + // Bounds check the string table here rather than for each string + // And make sure that the section is null-terminated + if (SecNames + SecNamesSize > (char *)File + FileSize || + !IsZero (SecNames[SecNamesSize - 1])) + Fail (); + } + + // *** Locate symbol table and symbol string data *** + for (SecIdx = 0; SecIdx < SecCount; SecIdx++) { + const ELF_SECTION *Section; + const char *Name; + I4 Type; + + Section = &(*ELFSections)[SecIdx]; + TestInFile (Section, ELF_SECTION); + + Type = ReadTI4 (Section->Type); + + // If this is the symbol table + if (Type == SHT_SYMTAB) { + if (ELFSymbols != NULL) + FailMsg ("Multiple ELF symbol tables found"); + + // Make sure that the symbols are the right format + if (ReadTI4 (Section->EntrySize) != sizeof (ELF_SYMBOL)) + Fail (); + + ELFSymbols = (ELF_SYMBOLS *)(File + ReadTI4 (Section->FileOffset)); + SymCount = ReadTI4 (Section->Size) / sizeof (ELF_SYMBOL); + continue; + } + + // Bounds check the name + if ((SIZE) ReadTI4 (Section->NameIdx) > SecNamesSize) + Fail (); + + Name = &SecNames[ReadTI4 (Section->NameIdx)]; + + // If this is the symbol string table + if (Type == SHT_STRTAB && !strncmp (Name, ".strtab", 7)) { + SymNames = (char *)(File + ReadTI4 (Section->FileOffset)); + SymNamesSize = ReadTI4 (Section->Size); + + // Bounds check the string table here rather than for each string + // And make sure that the section is null-terminated + if (SymNames + SymNamesSize > (char *)File + FileSize || + !IsZero (SymNames[SymNamesSize - 1])) + Fail (); + } + } + + if (ELFSymbols == NULL || SymNames == NULL) + Fail (); + + // *** Handle any special symbols before we import anything else *** + + for (SymIdx = 0; SymIdx < SymCount; SymIdx++) { + const ELF_SYMBOL *Symbol; + const char *Name; + + Symbol = &(*ELFSymbols)[SymIdx]; + TestInFile(Symbol, ELF_SYMBOL); + + // Bounds check the name + if ((SIZE) ReadTI4 (Symbol->NameIdx) > SymNamesSize) + Fail (); + + // If the symbol has no name, this should point to a null byte + Name = &SymNames[ReadTI4 (Symbol->NameIdx)]; + + if (!(strcmp (Name, SYM_OMIT_BSS_INIT))) + InitializeBSS = FALSE; + else if (!(strcmp (Name, SYM_ALL_RELOCS))) + AllRelocs = TRUE; + else if (!(strcmp (Name, SYM_IGNORE_GLOBAL_IMPORTS))) + Program->IgnoreGlobalImports = TRUE; + } + + // *** Import Sections *** + SecInfo = calloc (SecCount, sizeof (SEC_INFO)); + TestMem (SecInfo); + + // For each section, again... + for (SecIdx = 0; SecIdx < SecCount; SecIdx++) { + const ELF_SECTION *ELFSection; + SECTION *LDSection; + const char *Name; + SIZE NameSize; + SIZE Size; + I4 Flags; + I4 Align; + I4 Type; + + ELFSection = &(*ELFSections)[SecIdx]; + // This test has already been done + //TestInFile(ELFSection, ELF_SECTION); + + Flags = ReadTI4 (ELFSection->Flags); + Type = ReadTI4 (ELFSection->Type); + Size = ReadTI4 (ELFSection->Size); + Align = ReadTI4 (ELFSection->Alignment); + + // We can't guarantee that load addresses will be preserved, + // which is fine as object files never set this field. + if (!IsZeroI4 (ELFSection->Address)) + Fail (); + + // Skip sections that don't appear in the final executable + if (!(Flags & ELF_SECTION_ALLOC)) + continue; + + // Bounds check the name + if ((SIZE) ReadTI4 (ELFSection->NameIdx) > SecNamesSize) + Fail (); + + Name = &SecNames[ReadTI4 (ELFSection->NameIdx)]; + + // We know that there is a null byte between Name and the end of the file + // so this is safe + NameSize = strlen(Name); + + // *** Actually import the section *** + + LDSection = calloc (1, sizeof (SECTION)); + TestMem(LDSection); + + LDSection->Parent = Program; + LDSection->Size = Size; + + if (Type == SHT_PROGBITS && !IsZero (Size)) { + // Bounds check the file data + if ((SIZE)ReadTI4 (ELFSection->FileOffset) + Size > FileSize) + Fail (); + + LDSection->Data = malloc (Size); + TestMem(LDSection->Data); + + memcpy (LDSection->Data, File + ReadTI4 (ELFSection->FileOffset), Size); + } + // else LDSection->Data is already null + + LDSection->Initialized = LDSection->Data || InitializeBSS; + LDSection->Code = !!(Flags & ELF_SECTION_EXECINSTR); + + // TODO: figure out exactly what it means to be mergeable + // Is it enough for the section to be read-only and not executable? + LDSection->Mergeable = FALSE; + LDSection->Unaligned = IsZero (Align) || Align == 1; + + // See if the section is a startup section, + // This may need to be moved before we prune non-allocated sections + LDSection->StartupNumber = GetStartupSectionNumber (Name, NameSize); + + LDSection->Constructors = NameSize == 6 && IsZero (strncmp (Name, ".ctors", 6)); + LDSection->Destructors = NameSize == 6 && IsZero (strncmp (Name, ".dtors", 6)); + + // While we set CanCutRanges the same way as COFF importing, + // there is currently no toolchain for m68k-elf that works with + // range cutting. + LDSection->CanCutRanges = AllRelocs; + LDSection->FileName = FileName; + + // TODO: Debugging info + + // Append/insert the section. + InsertSection (Program, LDSection); + + // Create a section symbol for this section. + if (!(CreateSectionSymbol (LDSection, Name))) { + if (LDSection->Data) + free (LDSection->Data); + free (LDSection); + Fail (); + } + + // Add to table for quick lookup when importing symbols + SecInfo[SecIdx].Section = LDSection; + SecInfo[SecIdx].Name = Name; + } + + // *** Import Symbols *** + SymInfo = calloc (SymCount, sizeof (SYM_INFO)); + TestMem (SymInfo); + + // For each symbol (again) + for (SymIdx = 0; SymIdx < SymCount; SymIdx++) { + const ELF_SYMBOL *ELFSymbol; + const char *Name; + OFFSET SymSecIdx; + + ELFSymbol = &(*ELFSymbols)[SymIdx]; + // We've already checked this for every symbol in the table + //TestInFile(ELFSymbol, ELF_SYMBOL); + + // Bounds check the name + if ((SIZE) ReadTI4 (ELFSymbol->NameIdx) > SymNamesSize) + Fail (); + + // If the symbol has no name, this should point to a null byte + Name = &SymNames[ReadTI4 (ELFSymbol->NameIdx)]; + SymInfo[SymIdx].Name = Name; + + // Skip linker control symbols and global imports + if (HandleSpecialSymbol (Program, Name)) + continue; + + SymSecIdx = ReadTI2 (ELFSymbol->SectionIdx); + + if (/*!IsZero (*Name) && */!IsZero (SymSecIdx) && SymSecIdx < SecCount && SecInfo[SymSecIdx].Section) { + char Visibility; + SYMBOL *LDSym; + char Info; + + Visibility = ReadTI1 (ELFSymbol->Visibility); + Info = ReadTI1 (ELFSymbol->Info); + + SymInfo[SymIdx].HasSymbol = TRUE; + + // TODO: add support for visibility in core linker + if (ELF32_ST_VISIBILITY (Visibility) != STV_DEFAULT) + Warning (FileName, "Ignoring non-default visiblity for symbol '%s'.", + Name); + + // If the symbol is a section, we already made a symbol for it + if (ELF32_ST_TYPE(Info) == STT_SECTION) { + SymInfo[SymIdx].Symbol = SecInfo[SymSecIdx].Section->SectionSymbol; + // Otherwise make a new symbol + } else { + LDSym = calloc (1, sizeof (SYMBOL)); + TestMem (LDSym); + + LDSym->Parent = SecInfo[SymSecIdx].Section; + LDSym->Location = ReadTI4 (ELFSymbol->Value); + strncpy (LDSym->Name, Name, MAX_SYM_LEN); + LDSym->Exported = ELF32_ST_BIND (Info) != STB_LOCAL; + + // TODO: add support for weak symbols in core linker + if (ELF32_ST_BIND (Info) == STB_WEAK) + Warning (FileName, "Weak symbols not supported, symbol '%s' is being bound normally.", + Name); + + InsertSymbol (SecInfo[SymSecIdx].Section, LDSym); + + SymInfo[SymIdx].Symbol = LDSym; + } + } + } + + // *** Import relocation information *** + + // Loop over sections yet again... + for (SecIdx = 0; SecIdx < SecCount; SecIdx++) { + const ELF_SECTION *ELFSection; + const char *SecName; + SIZE SecNameSize; + I4 SecType; + + ELFSection = &(*ELFSections)[SecIdx]; + // Redundant. We've already checked this for every section + //TestInFile(ELFSection, ELF_SECTION); + + SecType = ReadTI4 (ELFSection->Type); + + // Only process relocation tables + if (SecType != SHT_REL && SecType != SHT_RELA) + continue; + + // Bounds check the name + if ((SIZE) ReadTI4 (ELFSection->NameIdx) > SecNamesSize) + Fail (); + + SecName = &SecNames[ReadTI4 (ELFSection->NameIdx)]; + SecNameSize = strlen (SecName); + + // Only handle relocation tables that begin with rel or rela + if (SecType == SHT_REL && !strncmp (SecName, ".rel", 4)) + ImportRelocSection (ELF_RELOC, 4,); + else if (SecType == SHT_RELA && !strncmp (SecName, ".rela", 5)) + ImportRelocSection (ELF_RELOCA, 5, LDReloc->Target.Offset = ReadTI4 (ELFReloc->Addend);); + } + + free (SecInfo); + free (SymInfo); + return TRUE; +} + +#endif /* ELF_SUPPORT */ diff --git a/trunk/tigcc/ld-tigcc/import/imp_elf.h b/trunk/tigcc/ld-tigcc/import/imp_elf.h new file mode 100644 index 00000000..25939ca6 --- /dev/null +++ b/trunk/tigcc/ld-tigcc/import/imp_elf.h @@ -0,0 +1,33 @@ +/* imp_elf.h: Routines to import an ELF file + + Copyright (C) 2024 Peter Lafreniere + + 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, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef IMP_ELF_H +#define IMP_ELF_H + +#include "../generic.h" + +#ifdef ELF_SUPPORT + +#include "../data.h" + +// Import a m68k-elf file into the internal data structures. +BOOLEAN ImportELFFile (PROGRAM *Program, const I1 *File, SIZE FileSize, const char *FileName); + +#endif /* ELF_SUPPORT */ + +#endif /* IMP_ELF_H */ diff --git a/trunk/tigcc/ld-tigcc/import/import.c b/trunk/tigcc/ld-tigcc/import/import.c index 2c430944..211fa019 100644 --- a/trunk/tigcc/ld-tigcc/import/import.c +++ b/trunk/tigcc/ld-tigcc/import/import.c @@ -28,6 +28,11 @@ #include "imp_amig.h" #endif /* AMIGAOS_SUPPORT */ +#ifdef ELF_SUPPORT +#include "../formats/elf.h" +#include "imp_elf.h" +#endif /* ELF_SUPPORT */ + // Import an object file with an arbitrary format. BOOLEAN ImportObjectFile (PROGRAM *Program, const I1 *File, SIZE FileSize, const char *FileName) { @@ -41,6 +46,11 @@ BOOLEAN ImportObjectFile (PROGRAM *Program, const I1 *File, SIZE FileSize, const return (ImportAmigaOSFile (Program, File, FileSize, FileName)); else #endif /* AMIGAOS_SUPPORT */ +#ifdef ELF_SUPPORT + if (IsELFFile (File, FileSize)) + return (ImportELFFile (Program, File, FileSize, FileName)); + else +#endif { Error (FileName, "Unknown object file format."); return FALSE;