scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 71539b6717e562995e294b8b2d0173cd38885354
parent 5d5161359e267f3f6dc4979fa46fe4a351acc884
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 28 Jan 2025 12:46:29 +0100

libmach: Rewrite elf support

This rewrite was needed to support any elf file,
independently of the target machine, and without
worring about 32 or 64 bit elf version.

Diffstat:
Ainclude/bits/scc/elf.h | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Minclude/bits/scc/elf/elfent.h | 16++++++++++------
Minclude/bits/scc/elf/elfhdr.h | 2+-
Minclude/bits/scc/elf64.h | 2--
Minclude/bits/scc/mach.h | 4+++-
Msrc/cmd/scc-objdump/Makefile | 2+-
Asrc/cmd/scc-objdump/elf.c | 738+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/cmd/scc-objdump/elf64.c | 734-------------------------------------------------------------------------------
Msrc/cmd/scc-objdump/main.c | 10+++++-----
Msrc/cmd/scc-objdump/objdump.h | 8++++----
Msrc/libmach/Makefile | 4++--
Msrc/libmach/delobj.c | 4++--
Asrc/libmach/elf/Makefile | 25+++++++++++++++++++++++++
Asrc/libmach/elf/elfarchs.c | 19+++++++++++++++++++
Asrc/libmach/elf/elfdel.c | 23+++++++++++++++++++++++
Asrc/libmach/elf/elfgetsec.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libmach/elf/elfgetsym.c | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libmach/elf/elfnew.c | 20++++++++++++++++++++
Asrc/libmach/elf/elfprobe.c | 47+++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libmach/elf/elfread.c | 761+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libmach/elf/elftype.c | 21+++++++++++++++++++++
Asrc/libmach/elf/fun.h | 17+++++++++++++++++
Dsrc/libmach/elf64/Makefile | 35-----------------------------------
Dsrc/libmach/elf64/elf64.c | 24------------------------
Dsrc/libmach/elf64/elf64archs.c | 16----------------
Dsrc/libmach/elf64/elf64del.c | 24------------------------
Dsrc/libmach/elf64/elf64getsec.c | 76----------------------------------------------------------------------------
Dsrc/libmach/elf64/elf64getsym.c | 112-------------------------------------------------------------------------------
Dsrc/libmach/elf64/elf64new.c | 20--------------------
Dsrc/libmach/elf64/elf64probe.c | 45---------------------------------------------
Dsrc/libmach/elf64/elf64read.c | 386-------------------------------------------------------------------------------
Dsrc/libmach/elf64/elf64type.c | 21---------------------
Dsrc/libmach/elf64/fun.h | 17-----------------
Msrc/libmach/getindex.c | 2+-
Msrc/libmach/getsec.c | 4++--
Msrc/libmach/getsym.c | 4++--
Msrc/libmach/loadmap.c | 2+-
Msrc/libmach/newobj.c | 4++--
Msrc/libmach/objprobe.c | 4++--
Msrc/libmach/objtype.c | 4++--
Msrc/libmach/pc2line.c | 2+-
Msrc/libmach/readobj.c | 4++--
Msrc/libmach/setindex.c | 2+-
Msrc/libmach/setsec.c | 2+-
Msrc/libmach/setsym.c | 2+-
Msrc/libmach/strip.c | 2+-
Msrc/libmach/writeobj.c | 2+-
47 files changed, 2026 insertions(+), 1554 deletions(-)

diff --git a/include/bits/scc/elf.h b/include/bits/scc/elf.h @@ -0,0 +1,107 @@ +#define EI_NIDENT 16 + +typedef struct elf Elf; +typedef struct elfhdr Elfhdr; +typedef struct elfphdr Elfphdr; +typedef struct elfsec Elfsec; +typedef struct elfsym Elfsym; +typedef struct elfpack Elfpack; +typedef struct elfunpack Elfunpack; +typedef struct elfrel Elfrel; + +struct elfhdr { + unsigned char ident[EI_NIDENT]; + unsigned short type; + unsigned short machine; + unsigned long version; + unsigned long long entry; + unsigned long long phoff; + unsigned long long shoff; + unsigned long flags; + unsigned short ehsize; + + unsigned short phentsize; + unsigned short phnum; + + unsigned short shentsize; + unsigned short shnum; + unsigned short shstrndx; +}; + +struct elfphdr { + unsigned long type; + unsigned long flags; + unsigned long long offset; + + unsigned long long vaddr; + unsigned long long paddr; + + unsigned long long filesz; + unsigned long long memsz; + unsigned long long align; +}; + +struct elfsec { + char *name; + char *strtbl; + + unsigned long sh_name; + unsigned long type; + unsigned long long flags; + unsigned long long addr; + unsigned long long offset; + unsigned long long size; + unsigned long link; + unsigned long info; + unsigned long long addralign; + unsigned long long entsize; +}; + +struct elfrel { + Elfsym *sym; + Elfsec *sec; + + unsigned long long off; + unsigned long info; + long addend; +}; + +struct elfsym { + char *name; + Elfsec *symsec; + + unsigned long st_name; + unsigned char info; + unsigned char other; + unsigned short shndx; + unsigned long long value; + unsigned long long size; +}; + +struct elf { + Elfhdr hdr; + Elfphdr *phdr; + + Elfsec *secs; + int nsec; + int secstrtbl; + + Elfsym *syms; + int nsym; + + Elfrel *rels; + int nrel; + + Elfpack *pack; + Elfunpack *unpack; +}; + +struct arch { + char *name; + int mach; + int endian; + int type; +}; + +/* globals */ +extern struct arch elfarchs[]; diff --git a/include/bits/scc/elf/elfent.h b/include/bits/scc/elf/elfent.h @@ -4,13 +4,17 @@ #define STN_UNDEF 0 /* undefined */ /* Extract symbol info - st_info */ -#define ELF32_ST_BIND(x) ((x) >> 4) -#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf) -#define ELF32_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf)) +#define ELF_ST_BIND(x) ((x) >> 4) +#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf) +#define ELF_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf)) -#define ELF64_ST_BIND(x) ((x) >> 4) -#define ELF64_ST_TYPE(x) (((unsigned int) x) & 0xf) -#define ELF64_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf)) +#define ELF32_ST_BIND(x) ELF_ST_BIND(x) +#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) +#define ELF32_ST_INFO(b,t) ELF_ST_INFO(b, t) + +#define ELF64_ST_BIND(x) ELF_ST_BIND(x) +#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) +#define ELF64_ST_INFO(b,t) ELF_ST_INFO(b, t) /* Symbol Binding - ELF32_ST_BIND - st_info */ #define STB_LOCAL 0 /* Local symbol */ diff --git a/include/bits/scc/elf/elfhdr.h b/include/bits/scc/elf/elfhdr.h @@ -261,7 +261,7 @@ /* Magic for e_phnum: get real value from sh_info of first section header */ #define PN_XNUM 0xffff -#define ELFH32SZ 54 +#define ELFH32SZ 52 #define ELFH64SZ 64 typedef struct elfhdr32 Elf32_Ehdr; diff --git a/include/bits/scc/elf64.h b/include/bits/scc/elf64.h @@ -4,8 +4,6 @@ #include <scc/elf/elfshdr.h> #include <scc/elf/elfent.h> -#define ELF_ST_BIND ELF64_ST_BIND -#define ELF_ST_TYPE ELF64_ST_TYPE #define Elf_Ehdr Elf64_Ehdr #define Elf_Phdr Elf64_Phdr #define Elf_Shdr Elf64_Shdr diff --git a/include/bits/scc/mach.h b/include/bits/scc/mach.h @@ -21,7 +21,7 @@ typedef struct mapsec Mapsec; enum objformat { COFF32, - ELF64, + ELF, NFORMATS, }; @@ -32,6 +32,8 @@ enum objarch { ARCHZ80, ARCHARM32, ARCHARM64, + ARCHUNK32, + ARCHUNK64, }; enum order { diff --git a/src/cmd/scc-objdump/Makefile b/src/cmd/scc-objdump/Makefile @@ -6,7 +6,7 @@ include $(PROJECTDIR)/scripts/rules.mk OBJS =\ main.o\ coff32.o\ - elf64.o\ + elf.o\ TARGET = scc-objdump MORE_LDLIBS = -lmach -lscc diff --git a/src/cmd/scc-objdump/elf.c b/src/cmd/scc-objdump/elf.c @@ -0,0 +1,738 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/mach.h> +#include <scc/elf/elftypes.h> +#include <scc/elf/elfhdr.h> +#include <scc/elf/elfphdr.h> +#include <scc/elf/elfshdr.h> +#include <scc/elf/elfent.h> +#include <scc/elf.h> + +#include "objdump.h" + +enum elfsecflags { + ELF_WRITE = 0, + ELF_ALLOC = 1, + ELF_EXEC = 2, + ELF_MERGE = 3, + ELF_STRINGS = 4, + ELF_INFO_LINK = 5, + ELF_LINK_ORDER = 6, + ELF_OS_NONCONFOR = 7, + ELF_GROUP = 8, + ELF_TLS = 9, + ELF_COMPRESSED = 10, + ELF_NR_FLAGS = 11, +}; + +enum phdrflags { + FLAG_X = 0, + FLAG_W = 1, + FLAG_R = 2, + NR_RIGHTS = 3, +}; + +int +elfhasrelloc(Obj *obj, Section *sec) +{ + size_t i; + Elf *elf = obj->data; + Elfsec *shdr; + + for (i = 0; i < elf->nsec; i++) { + shdr = &elf->secs[i]; + if (shdr->type != SHT_RELA && shdr->type != SHT_REL) + continue; + if (shdr->info == sec->index) + return 1; + } + + return 0; +} + +static void +printents(Obj *obj) +{ + int n; + size_t i; + Section sec; + Elfsym *ent; + Elf *elf = obj->data; + char *sbind, *stype, *svis, *ssec; + unsigned info, bind, type, vis, nsec; + + static char *binds[] = { + [STB_LOCAL] = "Local symbol", + [STB_GLOBAL] = "Global symbol", + [STB_WEAK] = "like global - lower precedence", + [STB_NUM] = "number of symbol bindings", + [STB_LOPROC] = "reserved range for processor", + [STB_HIPROC] = " specific symbol bindings", + }; + static char *types[] = { + [STT_NOTYPE] = "not specified", + [STT_OBJECT] = "data object", + [STT_FUNC] = "function", + [STT_SECTION] = "section", + [STT_FILE] = "file", + [STT_COMMON] = "common symbol", + [STT_TLS] = "thread local storage", + [STT_LOPROC] = "reserved range for processor", + [STT_HIPROC] = " specific symbol types", + }; + static char *visibilities[] = { + [STV_DEFAULT] = "Visibility set by binding type", + [STV_INTERNAL] = "OS specific version of STV_HIDDEN", + [STV_HIDDEN] = "can only be seen inside own .so", + [STV_PROTECTED] = "HIDDEN inside, DEFAULT outside", + }; + + for (i = 0; i < elf->nsym; i++) { + ent = &elf->syms[i]; + + info = ent->info; + bind = ELF_ST_BIND(info); + type = ELF_ST_TYPE(info); + vis = ELF_ST_VISIBILITY(ent->other); + nsec = ent->shndx; + + sbind = (bind <= STB_HIPROC) ? binds[bind] : "Unknown"; + stype = (type <= STT_HIPROC) ? types[type] : "Unknown"; + svis = (vis <= STV_PROTECTED) ? visibilities[vis] : "Unknown"; + if (!sbind) + sbind = "Unknown"; + if (!stype) + stype = "Unknown"; + if (!svis) + svis = "Unknown"; + + switch (nsec) { + case SHN_ABS: + ssec = "*ABS*"; + break; + case SHN_COMMON: + ssec = "*COM*"; + break; + default: + n = nsec; + ssec = "*UNK*"; + if (getsec(obj, &n, &sec)) + ssec = sec.name; + } + + printf("Symbol %zu:\n" + "\tst_name: %lu '%s'\n" + "\tst_info: %u\n" + "\t\tst_bind: %u %s\n" + "\t\tst_type: %u %s\n" + "\tst_other: %u %s\n" + "\tst_shndx: %u %s\n" + "\tst_value: %#llx\n" + "\tst_size: %llu\n" + "\n", + i, + (long) ent->st_name, ent->name, + info, + bind, sbind, + type, stype, + vis, svis, + nsec, ssec, + (unsigned long long) ent->value, + (unsigned long long) ent->size); + } +} + +static void +printstbl(Obj *obj) +{ + int n; + size_t i; + Symbol sym; + Section sec; + Elfsym *ent; + Elfsec *shdr; + Elf *elf = obj->data; + unsigned info, bind, type; + char cbind, cweak, cctor, cwarn, cindir, cdebug, ctype; + + if (elf->nsym == 0) { + puts("no symbols"); + return; + } + + for (i = 1; i < elf->nsym; i++) { + ent = &elf->syms[i]; + shdr =&elf->secs[ent->shndx]; + n = i; + getsym(obj, &n, &sym); + n = ent->shndx; + getsec(obj, &n, &sec); + + info = ent->info; + bind = ELF64_ST_BIND(info); + type = ELF64_ST_TYPE(info); + + cbind = (bind == STB_LOCAL) ? 'l' : 'g'; + cweak = (bind == STB_WEAK) ? 'w' : ' '; + cctor = ' '; + cwarn = ' '; + cindir = ' '; + + switch (sym.type) { + case 'N': + case 'n': + cdebug = 'd'; + break; + case 'U': + cdebug = ' '; + cbind = ' '; + break; + default: + cdebug = (ent->symsec->type == SHT_DYNAMIC) ? 'D' : ' '; + } + + switch (type) { + case STT_OBJECT: + ctype = 'O'; + break; + case STT_FUNC: + ctype = 'F'; + break; + case STT_FILE: + ctype = 'f'; + cdebug = 'd'; + break; + default: + ctype = ' '; + break; + } + + printf("%016llx %c%c%c%c%c%c%c %-15s %08llu %-20s [%4zu]\n", + (long long) ent->value, + cbind, + cweak, + cctor, + cwarn, + cindir, + cdebug, + ctype, + sec.name, + (long long) ent->size, + sym.name, + i); + } +} + +void +elfsyms(Obj *obj) +{ + printstbl(obj); + + if (pflag) + printents(obj); +} + +void +elfscns(Obj *obj) +{ + size_t i; + Elf *elf = obj->data; + Elfsec *shdr; + static char *types[] = { + [SHT_NULL] = "inactive", + [SHT_PROGBITS] = "program defined information", + [SHT_SYMTAB] = "symbol table section", + [SHT_STRTAB] = "string table section", + [SHT_RELA] = "relocation section with addends", + [SHT_HASH] = "symbol hash table section", + [SHT_DYNAMIC] = "dynamic section", + [SHT_NOTE] = "note section", + [SHT_NOBITS] = "no space section", + [SHT_REL] = "relation section without addends", + [SHT_SHLIB] = "reserved - purpose unknown", + [SHT_DYNSYM] = "dynamic symbol table section", + [SHT_NUM] = "number of section types", + [SHT_INIT_ARRAY] = "pointers to init functions", + [SHT_FINI_ARRAY] = "pointers to termination functions", + [SHT_PREINIT_ARRAY] = "ptrs to funcs called before init", + [SHT_GROUP] = "defines a section group", + [SHT_SYMTAB_SHNDX] = "Section indexes (see SHN_XINDEX).", + }; + static Flags f = { + .nr = ELF_NR_FLAGS, + .text = { + [ELF_WRITE] = "WRITE", + [ELF_ALLOC] = "ALLOC", + [ELF_EXEC] = "EXEC", + [ELF_MERGE] = "MERGE", + [ELF_STRINGS] = "STRINGS", + [ELF_INFO_LINK] = "INFO_LINK", + [ELF_LINK_ORDER] = "LINK_ORDER", + [ELF_OS_NONCONFOR] = "OS_NONCONFORMING", + [ELF_GROUP] = "GROUP", + [ELF_TLS] = "TLS", + [ELF_COMPRESSED] = "COMPRESSED", + } + }; + + for (i = 0; i < elf->nsec; i++) { + long type; + char *stype; + shdr = &elf->secs[i]; + + type = shdr->type; + if (type <= SHT_SYMTAB_SHNDX) { + stype = types[type]; + } else { + switch (type) { + case SHT_SUNW_dof: + stype = "SHT_SUNW_dof"; + break; + case SHT_GNU_LIBLIST: + stype = "SHT_GNU_LIBLIST"; + break; + case SHT_SUNW_move: + stype = "SHT_SUNW_move"; + break; + case SHT_SUNW_syminfo: + stype = "SHT_SUNW_syminfo"; + break; + case SHT_GNU_VERDEF: + stype = "SHT_GNU_VERDEF"; + break; + case SHT_GNU_VERNEED: + stype = "SHT_GNU_VERNEED"; + break; + case SHT_GNU_VERSYM: + stype = "SHT_GNU_VERSYM"; + break; + default: + stype = NULL; + } + } + + if (!stype) + stype = "Unknown"; + + f.flags = shdr->flags; + + printf("Section %zu:\n" + "\tsh_name: %lu %s\n" + "\tsh_type: %lu %s\n" + "\tsh_flags: %#llx\n" + "\tsh_addr: %#llx\n" + "\tsh_offset: %#llx\n" + "\tsh_size: %#llx\n" + "\tsh_link: %lu\n" + "\tsh_info: %lu\n" + "\tsh_addralign: %llu\n" + "\tsh_entsize: %llu\n", + i, + (long) shdr->sh_name, shdr->name, + type, stype, + (long long) shdr->flags, + (long long) shdr->addr, + (long long) shdr->offset, + (long long) shdr->size, + (long) shdr->link, + (long) shdr->info, + (long long) shdr->addralign, + (long long) shdr->entsize); + + putchar('\t'); + printflags(&f); + putchar('\n'); + } +} + +static void +printfhdr(Elfhdr *hdr) +{ + unsigned long version; + unsigned class, data, abi, type, mach; + char *sclass, *sdata, *sabi, *stype, *smach, *sversion; + + static char *abis[] = { + [ELFOSABI_SYSV] = "UNIX System V ABI", + [ELFOSABI_HPUX] = "HP-UX operating system", + [ELFOSABI_NETBSD] = "NetBSD", + [ELFOSABI_LINUX] = "GNU/Linux", + [ELFOSABI_HURD] = "GNU/Hurd", + [ELFOSABI_86OPEN] = "86Open common IA32 ABI", + [ELFOSABI_SOLARIS] = "Solaris", + [ELFOSABI_MONTEREY] = "Monterey", + [ELFOSABI_IRIX] = "IRIX", + [ELFOSABI_FREEBSD] = "FreeBSD", + [ELFOSABI_TRU64] = "TRU64 UNIX", + [ELFOSABI_MODESTO] = "Novell Modesto", + [ELFOSABI_OPENBSD] = "OpenBSD", + [ELFOSABI_OPENVMS] = "Open VMS", + [ELFOSABI_NSK] = "Hewlett-Packard Non-Stop Kernel", + [ELFOSABI_AROS] = "Amiga Research OS", + [ELFOSABI_FENIXOS] = "The FenixOS multi-core OS", + [ELFOSABI_CLOUDABI] = "Nuxi CloudABI", + [ELFOSABI_OPENVOS] = "Stratus Technologies OpenVOS", + [ELFOSABI_ARM] = "ARM", + [ELFOSABI_STANDALONE] = "Standalone (embedded) application", + }; + static char *classes[] = { + [ELFCLASSNONE] = "invalid", + [ELFCLASS32] = "32-bit objs", + [ELFCLASS64] = "64-bit objs", + }; + static char *datas[] = { + [ELFDATANONE] = "invalid", + [ELFDATA2LSB] = "Little-Endian", + [ELFDATA2MSB] = "Big-Endian", + }; + static char *types[] = { + [ET_NONE] = "No file type", + [ET_REL] = "Relocatable file", + [ET_EXEC] = "Executable file", + [ET_DYN] = "Shared object file", + [ET_CORE] = "Core file", + }; + static char *machs[] = { + [EM_NONE] = "No machine", + [EM_M32] = "AT&T WE 32100", + [EM_SPARC] = "SPARC", + [EM_386] = "Intel 80386", + [EM_68K] = "Motorola 68000", + [EM_88K] = "Motorola 88000", + [EM_IAMCU] = "Intel MCU", + [EM_860] = "Intel 80860", + [EM_MIPS] = "MIPS I Architecture", + [EM_S370] = "IBM System/370 Processor", + [EM_MIPS_RS3_LE] = "MIPS RS3000 Little-endian", + [EM_PARISC] = "Hewlett-Packard PA-RISC", + [EM_VPP500] = "Fujitsu VPP500", + [EM_SPARC32PLUS] = "Enhanced instruction set SPARC", + [EM_960] = "Intel 80960", + [EM_PPC] = "PowerPC", + [EM_PPC64] = "64-bit PowerPC", + [EM_S390] = "IBM System/390", + [EM_SPU] = "IBM SPU/SPC", + [EM_V800] = "NEC V800", + [EM_FR20] = "Fujitsu FR20", + [EM_RH32] = "TRW RH-32", + [EM_RCE] = "Motorola RCE", + [EM_ARM] = "ARM AARCH32", + [EM_ALPHA] = "Digital Alpha", + [EM_SH] = "Hitachi SH", + [EM_SPARCV9] = "SPARC Version 9", + [EM_TRICORE] = "Siemens TriCore", + [EM_ARC] = "Argonaut RISC Core", + [EM_H8_300] = "Hitachi H8/300", + [EM_H8_300H] = "Hitachi H8/300H", + [EM_H8S] = "Hitachi H8S", + [EM_H8_500] = "Hitachi H8/500", + [EM_IA_64] = "Intel IA-64", + [EM_MIPS_X] = "Stanford MIPS-X", + [EM_COLDFIRE] = "Motorola ColdFire", + [EM_68HC12] = "Motorola M68HC12", + [EM_MMA] = "Fujitsu MMA", + [EM_PCP] = "Siemens PCP", + [EM_NCPU] = "Sony nCPU", + [EM_NDR1] = "Denso NDR1", + [EM_STARCORE] = "Motorola Star*Core", + [EM_ME16] = "Toyota ME16", + [EM_ST100] = "STMicroelectronics ST100", + [EM_TINYJ] = "Advanced Logic Corp. TinyJ", + [EM_X86_64] = "AMD x86-64", + [EM_PDSP] = "Sony DSP Processor", + [EM_PDP10] = "DEC PDP-10", + [EM_PDP11] = "DEC PDP-11", + [EM_FX66] = "Siemens FX66", + [EM_ST9PLUS] = "STMicroelectronics ST9+", + [EM_ST7] = "STMicroelectronics ST7", + [EM_68HC16] = "Motorola MC68HC16", + [EM_68HC11] = "Motorola MC68HC11", + [EM_68HC08] = "Motorola MC68HC08", + [EM_68HC05] = "Motorola MC68HC05", + [EM_SVX] = "Silicon Graphics SVx", + [EM_ST19] = "STMicroelectronics ST19", + [EM_VAX] = "Digital VAX", + [EM_CRIS] = "Axis Communications 32-bit", + [EM_JAVELIN] = "Infineon Technologies 32-bit", + [EM_FIREPATH] = "Element 14 64-bit DSP Processor", + [EM_ZSP] = "LSI Logic 16-bit DSP Processor", + [EM_MMIX] = "Donald Knuth's educational 64-bit", + [EM_HUANY] = "Harvard machine-independent", + [EM_PRISM] = "SiTera Prism", + [EM_AVR] = "Atmel AVR 8-bit", + [EM_FR30] = "Fujitsu FR30", + [EM_D10V] = "Mitsubishi D10V", + [EM_D30V] = "Mitsubishi D30V", + [EM_V850] = "NEC v850", + [EM_M32R] = "Mitsubishi M32R", + [EM_MN10300] = "Matsushita MN10300", + [EM_MN10200] = "Matsushita MN10200", + [EM_PJ] = "picoJava", + [EM_OPENRISC] = "OpenRISC 32-bit", + [EM_ARC_A5] = "ARC ARCompact", + [EM_ARC_COMPACT] = "ARC ARCompact", + [EM_XTENSA] = "Tensilica Xtensa", + [EM_VIDEOCORE] = "Alphamosaic VideoCore", + [EM_TMM_GPP] = "Thompson Multimedia GPP", + [EM_NS32K] = "National 32000 series", + [EM_TPC] = "Tenor Network TPC", + [EM_SNP1K] = "Trebia SNP 1000", + [EM_ST200] = "STMicroelectronics ST200", + [EM_IP2K] = "Ubicom IP2xxx", + [EM_MAX] = "MAX Processor", + [EM_CR] = "National CompactRISC", + [EM_F2MC16] = "Fujitsu F2MC16", + [EM_MSP430] = "Texas msp430", + [EM_BLACKFIN] = "Analog Devices Blackfin", + [EM_SE_C33] = "S1C33 of Seiko Epson", + [EM_SEP] = "Sharp embedded", + [EM_ARCA] = "Arca RISC", + [EM_UNICORE] = "PKU-Unity Ltd. and MPRC", + [EM_EXCESS] = "eXcess CPU", + [EM_DXP] = "Deep Execution Processor", + [EM_ALTERA_NIOS2] = "Altera Nios II", + [EM_CRX] = "National CompactRISC CRX", + [EM_XGATE] = "Motorola XGATE", + [EM_C166] = "Infineon C16x/XC16x", + [EM_M16C] = "Renesas M16C", + [EM_DSPIC30F] = "Microchip dsPIC30F", + [EM_CE] = "Freescale Communication Engine", + [EM_M32C] = "Renesas M32C", + [EM_TSK3000] = "Altium TSK3000 core", + [EM_RS08] = "Freescale RS08", + [EM_SHARC] = "Analog Devices SHARC", + [EM_ECOG2] = "Cyan Technology eCOG2", + [EM_SCORE7] = "Sunplus S+core7", + [EM_DSP24] = "NJR 24-bit DSP", + [EM_VIDEOCORE3] = "Broadcom VideoCore III", + [EM_LATTICEMICO3] = "RISC processor for Lattice FPGA", + [EM_SE_C17] = "Seiko Epson C17", + [EM_TI_C6000] = "TMS320C6000 DSP family", + [EM_TI_C2000] = "TMS320C2000 DSP family", + [EM_TI_C5500] = "TMS320C55x DSP family", + [EM_TI_ARP32] = "Texas Application Specific RISC", + [EM_TI_PRU] = "Texas Programmable Realtime Unit", + [EM_MMDSP_PLUS] = "STMicroelectronics 64bit VLIW", + [EM_CYPRESS_M8C] = "Cypress M8C microprocessor", + [EM_R32C] = "Renesas R32C series", + [EM_TRIMEDIA] = "NXP Semiconductors TriMedia", + [EM_QDSP6] = "QUALCOMM DSP6 Processor", + [EM_8051] = "Intel 8051 and variants", + [EM_STXP7X] = "STMicroelectronics STxP7x", + [EM_NDS32] = "Andes Technology embedded RISC", + [EM_ECOG1] = "Cyan Technology eCOG1X family", + [EM_ECOG1X] = "Cyan Technology eCOG1X family", + [EM_MAXQ30] = "MAXQ30 Core Micro-controllers", + [EM_XIMO16] = "NJR 16-bit DSP Processor", + [EM_MANIK] = "M2000 Reconfigurable RISC", + [EM_CRAYNV2] = "Cray Inc. NV2 vector architecture", + [EM_RX] = "Renesas RX family", + [EM_METAG] = "Imagination Technologies META", + [EM_MCST_ELBRUS] = "MCST Elbrus", + [EM_ECOG16] = "Cyan Technology eCOG16 family", + [EM_CR16] = "National CompactRISC CR16", + [EM_ETPU] = "Freescale Extended Time Unit", + [EM_SLE9X] = "Infineon Technologies SLE9X core", + [EM_L10M] = "Intel L10M", + [EM_K10M] = "Intel K10M", + [EM_AARCH64] = "ARM AARCH64", + [EM_AVR32] = "Atmel 32-bit", + [EM_STM8] = "STMicroeletronics STM8 ", + [EM_TILE64] = "Tilera TILE64", + [EM_TILEPRO] = "Tilera TILEPro", + [EM_MICROBLAZE] = "Xilinx MicroBlaze 32-bit", + [EM_CUDA] = "NVIDIA CUDA architecture", + [EM_TILEGX] = "Tilera TILE-Gx family", + [EM_CLOUDSHIELD] = "CloudShield architecture family", + [EM_COREA_1ST] = "KIPO-KAIST Core-A 1st gen family", + [EM_COREA_2ND] = "KIPO-KAIST Core-A 2nd gen family", + [EM_ARC_COMPACT2] = "Synopsys ARCompact V2", + [EM_OPEN8] = "Open8 8-bit RISC soft processor core", + [EM_RL78] = "Renesas RL78 family", + [EM_VIDEOCORE5] = "Broadcom VideoCore V processor", + [EM_78KOR] = "Renesas 78KOR family", + [EM_56800EX] = "Freescale 56800EX (DSC)", + [EM_BA1] = "Beyond BA1 CPU architecture", + [EM_BA2] = "Beyond BA2 CPU architecture", + [EM_XCORE] = "XMOS xCORE processor family", + [EM_MCHP_PIC] = "Microchip 8-bit PIC(r) family", + [EM_KM32] = "KM211 KM32 32-bit processor", + [EM_KMX32] = "KM211 KMX32 32-bit processor", + [EM_KMX16] = "KM211 KMX16 16-bit processor", + [EM_KMX8] = "KM211 KMX8 8-bit processor", + [EM_KVARC] = "KM211 KVARC processor", + [EM_CDP] = "Paneve CDP architecture family", + [EM_COGE] = "Cognitive Smart Memory Processor", + [EM_COOL] = "Bluechip Systems CoolEngine", + [EM_NORC] = "Nanoradio Optimized RISC", + [EM_CSR_KALIMBA] = "CSR Kalimba architecture family", + [EM_Z80] = "Zilog Z80", + [EM_VISIUM] = "VISIUMcore processor", + [EM_FT32] = "FTDI Chip FT32", + [EM_MOXIE] = "Moxie processor family", + [EM_AMDGPU] = "AMD GPU architecture", + [EM_RISCV] = "RISC-V", + [EM_BPF] = "Linux BPF", + [EM_CSKY] = "C-SKY", + }; + static char *versions[] = { + [EV_NONE] = "Invalid", + [EV_CURRENT] = "Current", + }; + + class = hdr->ident[EI_CLASS]; + data = hdr->ident[EI_DATA]; + abi = hdr->ident[EI_OSABI]; + type = hdr->type; + mach = hdr->machine; + version = hdr->version; + + sclass = (class <= ELFCLASS64) ? classes[class] : "Unknown"; + sdata = (data <= ELFDATA2MSB) ? datas[data] : "Unknown"; + stype = (type <= ET_CORE) ? types[type] : "Unknown"; + smach = (mach <= EM_CSKY) ? machs[mach] : "Unknown"; + if (!smach) + smach = "Unknown"; + sversion = (version <= EV_CURRENT) ? versions[version] : "Unknown"; + + switch (abi) { + case ELFOSABI_ARM: + sabi = "ARM"; + break; + case ELFOSABI_STANDALONE: + sabi = "Standalone (embedded) application"; + break; + default: + sabi = (abi <= ELFOSABI_OPENVOS) ? abis[abi] : "Unknown"; + } + + printf("elfhdr:\n" + "\tei_class: %u, %s\n" + "\tei_data: %u, %s\n" + "\tei_version: %u\n" + "\tei_osabi: %u, %s\n" + "\tei_abiversion: %u\n" + "\te_type: %u, %s\n" + "\te_machine: %u, %s\n" + "\te_version: %lu, %s\n" + "\te_entry: 0x%08llx\n" + "\te_phoff: %llu\n" + "\te_shoff: %llu\n" + "\te_flags: %#lx\n" + "\te_ehsize: %lu\n" + "\te_phentsize: %lu\n" + "\te_phnum: %lu\n" + "\te_shentsize: %lu\n" + "\te_shnum: %lu\n" + "\te_shstrndx: %lu\n" + "\n", + class, sclass, + data, sdata, + hdr->ident[EI_VERSION], + abi, sabi, + hdr->ident[EI_ABIVERSION], + type, stype, + mach, smach, + version, sversion, + (long long) hdr->entry, + (long long) hdr->phoff, + (long long) hdr->shoff, + (long) hdr->flags, + (long) hdr->ehsize, + (long) hdr->phentsize, + (long) hdr->phnum, + (long) hdr->shentsize, + (long) hdr->shnum, + (long) hdr->shstrndx); +} + +static void +printphdr(Elfphdr *phdr, unsigned long n) +{ + unsigned long i; + static char *types[] = { + [PT_NULL] = "unused", + [PT_LOAD] = "loadable segment", + [PT_DYNAMIC] = "dynamic linking section", + [PT_INTERP] = "the RTLD", + [PT_NOTE] = "auxiliary information", + [PT_SHLIB] = "reserved - purpose undefined", + [PT_PHDR] = "program header", + [PT_TLS] = "thread local storage", + }; + static Flags f ={ + .nr = NR_RIGHTS, + .text = { + [FLAG_X] = "Executable", + [FLAG_W] = "Writable", + [FLAG_R] = "Readable", + } + }; + + for (i = 0; i < n; i++) { + unsigned long type; + char *stype; + + type = phdr->type; + stype = (type <= PT_TLS) ? types[type] : "Unknown"; + f.flags = phdr->flags; + + printf("Program header %ld\n" + "\tp_type: %#lx, %s\n" + "\tp_flags: %#lx\n" + "\tp_offset: %#08llx\n" + "\tp_vaddr: %#08llx\n" + "\tp_paddr: %#08llx\n" + "\tp_filesz: %#08llx\n" + "\tp_memsz: %#08llx\n" + "\tp_align: %#08llx\n", + i, + type, stype, + (long) phdr->flags, + (long long) phdr->offset, + (long long) phdr->vaddr, + (long long) phdr->paddr, + (long long) phdr->filesz, + (long long) phdr->memsz, + (long long) phdr->align); + + putchar('\t'); + printflags(&f); + putchar('\n'); + ++phdr; + } +} + +void +elffhdr(Obj *obj, unsigned long long *start, Flags *f) +{ + size_t i; + char *name; + Elf *elf = obj->data; + Elfhdr *hdr = &elf->hdr; + Elfsec *shdr; + + *start = hdr->entry; + + for (i = 0; i < elf->nsec; i++) { + shdr = &elf->secs[i]; + name = shdr->name; + setflag(f, strncmp(name, ".debug", 6) == 0, HAS_DEBUG); + setflag(f, strncmp(name, ".line", 5) == 0, HAS_LINENO); + setflag(f, strcmp(name, ".debug_line") == 0, HAS_LINENO); + setflag(f, shdr->type == SHT_RELA, HAS_RELOC); + setflag(f, shdr->type == SHT_REL, HAS_RELOC); + } + + setflag(f, hdr->type == ET_EXEC, EXEC_P); + setflag(f, hdr->type == ET_DYN, DYNAMIC); + setflag(f, elf->nsym > 0, HAS_SYMS); + + if (!pflag) + return; + + printfhdr(hdr); + printphdr(elf->phdr, hdr->phnum); +} diff --git a/src/cmd/scc-objdump/elf64.c b/src/cmd/scc-objdump/elf64.c @@ -1,734 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <scc/mach.h> -#include <scc/elf64.h> - -#include "objdump.h" - -enum elfsecflags { - ELF_WRITE = 0, - ELF_ALLOC = 1, - ELF_EXEC = 2, - ELF_MERGE = 3, - ELF_STRINGS = 4, - ELF_INFO_LINK = 5, - ELF_LINK_ORDER = 6, - ELF_OS_NONCONFOR = 7, - ELF_GROUP = 8, - ELF_TLS = 9, - ELF_COMPRESSED = 10, - ELF_NR_FLAGS = 11, -}; - -enum phdrflags { - FLAG_X = 0, - FLAG_W = 1, - FLAG_R = 2, - NR_RIGHTS = 3, -}; - -int -elf64hasrelloc(Obj *obj, Section *sec) -{ - size_t i; - Elf64 *elf = obj->data; - Elf_Shdr *shdr; - - for (i = 0; i < elf->nsec; i++) { - shdr = &elf->shdr[i]; - if (shdr->sh_type != SHT_RELA && shdr->sh_type != SHT_REL) - continue; - if (shdr->sh_info == sec->index) - return 1; - } - - return 0; -} - -static void -printents(Obj *obj) -{ - int n; - size_t i; - Section sec; - Elf_Sym *ent; - Elf64 *elf = obj->data; - char *sbind, *stype, *svis, *ssec; - unsigned info, bind, type, vis, nsec; - - static char *binds[] = { - [STB_LOCAL] = "Local symbol", - [STB_GLOBAL] = "Global symbol", - [STB_WEAK] = "like global - lower precedence", - [STB_NUM] = "number of symbol bindings", - [STB_LOPROC] = "reserved range for processor", - [STB_HIPROC] = " specific symbol bindings", - }; - static char *types[] = { - [STT_NOTYPE] = "not specified", - [STT_OBJECT] = "data object", - [STT_FUNC] = "function", - [STT_SECTION] = "section", - [STT_FILE] = "file", - [STT_COMMON] = "common symbol", - [STT_TLS] = "thread local storage", - [STT_LOPROC] = "reserved range for processor", - [STT_HIPROC] = " specific symbol types", - }; - static char *visibilities[] = { - [STV_DEFAULT] = "Visibility set by binding type", - [STV_INTERNAL] = "OS specific version of STV_HIDDEN", - [STV_HIDDEN] = "can only be seen inside own .so", - [STV_PROTECTED] = "HIDDEN inside, DEFAULT outside", - }; - - for (i = 0; i < elf->nsym; i++) { - ent = &elf->syms[i]; - - info = ent->st_info; - bind = ELF64_ST_BIND(info); - type = ELF64_ST_TYPE(info); - vis = ELF_ST_VISIBILITY(ent->st_other); - nsec = ent->st_shndx; - - sbind = (bind <= STB_HIPROC) ? binds[bind] : "Unknown"; - stype = (type <= STT_HIPROC) ? types[type] : "Unknown"; - svis = (vis <= STV_PROTECTED) ? visibilities[vis] : "Unknown"; - if (!sbind) - sbind = "Unknown"; - if (!stype) - stype = "Unknown"; - if (!svis) - svis = "Unknown"; - - switch (nsec) { - case SHN_ABS: - ssec = "*ABS*"; - break; - case SHN_COMMON: - ssec = "*COM*"; - break; - default: - n = nsec; - ssec = "*UNK*"; - if (getsec(obj, &n, &sec)) - ssec = sec.name; - } - - printf("Symbol %zu:\n" - "\tst_name: %lu '%s'\n" - "\tst_info: %u\n" - "\t\tst_bind: %u %s\n" - "\t\tst_type: %u %s\n" - "\tst_other: %u %s\n" - "\tst_shndx: %u %s\n" - "\tst_value: %llu\n" - "\tst_size: %llu\n" - "\n", - i, - (long) ent->st_name, - elf64str(obj, SYM_STRTBL, ent->st_name), - info, - bind, sbind, - type, stype, - vis, svis, - nsec, ssec, - (unsigned long long) ent->st_value, - (unsigned long long) ent->st_size); - } -} - -static void -printstbl(Obj *obj) -{ - int n; - size_t i; - Symbol sym; - Section sec; - Elf_Sym *ent; - Elf_Shdr *shdr; - Elf64 *elf = obj->data; - unsigned info, bind, type; - char cbind, cweak, cctor, cwarn, cindir, cdebug, ctype; - - if (elf->nsym == 0) { - puts("no symbols"); - return; - } - - for (i = 1; i < elf->nsym; i++) { - ent = &elf->syms[i]; - shdr =&elf->shdr[ent->st_shndx]; - n = i; - getsym(obj, &n, &sym); - n = ent->st_shndx; - getsec(obj, &n, &sec); - - info = ent->st_info; - bind = ELF64_ST_BIND(info); - type = ELF64_ST_TYPE(info); - - cbind = (bind == STB_LOCAL) ? 'l' : 'g'; - cweak = (bind == STB_WEAK) ? 'w' : ' '; - cctor = ' '; - cwarn = ' '; - cindir = ' '; - - switch (sym.type) { - case 'N': - case 'n': - cdebug = 'd'; - break; - case 'U': - cdebug = ' '; - cbind = ' '; - break; - default: - cdebug = (elf->symtab->sh_type == SHT_DYNAMIC) ? 'D' : ' '; - } - - switch (type) { - case STT_OBJECT: - ctype = 'O'; - break; - case STT_FUNC: - ctype = 'F'; - break; - case STT_FILE: - ctype = 'f'; - cdebug = 'd'; - break; - default: - ctype = ' '; - break; - } - - printf("%016llx %c%c%c%c%c%c%c %-15s %08llu %-20s [%4zu]\n", - (long long) ent->st_value, - cbind, - cweak, - cctor, - cwarn, - cindir, - cdebug, - ctype, - sec.name, - (long long) ent->st_size, - sym.name, - i); - } -} - -void -elf64syms(Obj *obj) -{ - printstbl(obj); - - if (pflag) - printents(obj); -} - -void -elf64scns(Obj *obj) -{ - size_t i; - Elf64 *elf = obj->data; - Elf_Shdr *shdr; - static char *types[] = { - [SHT_NULL] = "inactive", - [SHT_PROGBITS] = "program defined information", - [SHT_SYMTAB] = "symbol table section", - [SHT_STRTAB] = "string table section", - [SHT_RELA] = "relocation section with addends", - [SHT_HASH] = "symbol hash table section", - [SHT_DYNAMIC] = "dynamic section", - [SHT_NOTE] = "note section", - [SHT_NOBITS] = "no space section", - [SHT_REL] = "relation section without addends", - [SHT_SHLIB] = "reserved - purpose unknown", - [SHT_DYNSYM] = "dynamic symbol table section", - [SHT_NUM] = "number of section types", - [SHT_INIT_ARRAY] = "pointers to init functions", - [SHT_FINI_ARRAY] = "pointers to termination functions", - [SHT_PREINIT_ARRAY] = "ptrs to funcs called before init", - [SHT_GROUP] = "defines a section group", - [SHT_SYMTAB_SHNDX] = "Section indexes (see SHN_XINDEX).", - }; - static Flags f = { - .nr = ELF_NR_FLAGS, - .text = { - [ELF_WRITE] = "WRITE", - [ELF_ALLOC] = "ALLOC", - [ELF_EXEC] = "EXEC", - [ELF_MERGE] = "MERGE", - [ELF_STRINGS] = "STRINGS", - [ELF_INFO_LINK] = "INFO_LINK", - [ELF_LINK_ORDER] = "LINK_ORDER", - [ELF_OS_NONCONFOR] = "OS_NONCONFORMING", - [ELF_GROUP] = "GROUP", - [ELF_TLS] = "TLS", - [ELF_COMPRESSED] = "COMPRESSED", - } - }; - - for (i = 0; i < elf->nsec; i++) { - long type; - char *stype; - shdr = &elf->shdr[i]; - - type = shdr->sh_type; - if (type <= SHT_SYMTAB_SHNDX) { - stype = types[type]; - } else { - switch (type) { - case SHT_SUNW_dof: - stype = "SHT_SUNW_dof"; - break; - case SHT_GNU_LIBLIST: - stype = "SHT_GNU_LIBLIST"; - break; - case SHT_SUNW_move: - stype = "SHT_SUNW_move"; - break; - case SHT_SUNW_syminfo: - stype = "SHT_SUNW_syminfo"; - break; - case SHT_GNU_VERDEF: - stype = "SHT_GNU_VERDEF"; - break; - case SHT_GNU_VERNEED: - stype = "SHT_GNU_VERNEED"; - break; - case SHT_GNU_VERSYM: - stype = "SHT_GNU_VERSYM"; - break; - default: - stype = NULL; - } - } - - if (!stype) - stype = "Unknown"; - - f.flags = shdr->sh_flags; - - printf("Section %zu:\n" - "\tsh_name: %lu\n" - "\tsh_type: %lu %s\n" - "\tsh_flags: %#llx\n" - "\tsh_addr: %#llx\n" - "\tsh_offset: %#llx\n" - "\tsh_size: %#llx\n" - "\tsh_link: %lu\n" - "\tsh_info: %lu\n" - "\tsh_addralign: %llu\n" - "\tsh_entsize: %llu\n", - i, - (long) shdr->sh_name, - type, stype, - (long long) shdr->sh_flags, - (long long) shdr->sh_addr, - (long long) shdr->sh_offset, - (long long) shdr->sh_size, - (long) shdr->sh_link, - (long) shdr->sh_info, - (long long) shdr->sh_addralign, - (long long) shdr->sh_entsize); - - putchar('\t'); - printflags(&f); - putchar('\n'); - } -} - -static void -printfhdr(Elf_Ehdr *hdr) -{ - unsigned long version; - unsigned class, data, abi, type, mach; - char *sclass, *sdata, *sabi, *stype, *smach, *sversion; - - static char *abis[] = { - [ELFOSABI_SYSV] = "UNIX System V ABI", - [ELFOSABI_HPUX] = "HP-UX operating system", - [ELFOSABI_NETBSD] = "NetBSD", - [ELFOSABI_LINUX] = "GNU/Linux", - [ELFOSABI_HURD] = "GNU/Hurd", - [ELFOSABI_86OPEN] = "86Open common IA32 ABI", - [ELFOSABI_SOLARIS] = "Solaris", - [ELFOSABI_MONTEREY] = "Monterey", - [ELFOSABI_IRIX] = "IRIX", - [ELFOSABI_FREEBSD] = "FreeBSD", - [ELFOSABI_TRU64] = "TRU64 UNIX", - [ELFOSABI_MODESTO] = "Novell Modesto", - [ELFOSABI_OPENBSD] = "OpenBSD", - [ELFOSABI_OPENVMS] = "Open VMS", - [ELFOSABI_NSK] = "Hewlett-Packard Non-Stop Kernel", - [ELFOSABI_AROS] = "Amiga Research OS", - [ELFOSABI_FENIXOS] = "The FenixOS multi-core OS", - [ELFOSABI_CLOUDABI] = "Nuxi CloudABI", - [ELFOSABI_OPENVOS] = "Stratus Technologies OpenVOS", - [ELFOSABI_ARM] = "ARM", - [ELFOSABI_STANDALONE] = "Standalone (embedded) application", - }; - static char *classes[] = { - [ELFCLASSNONE] = "invalid", - [ELFCLASS32] = "32-bit objs", - [ELFCLASS64] = "64-bit objs", - }; - static char *datas[] = { - [ELFDATANONE] = "invalid", - [ELFDATA2LSB] = "Little-Endian", - [ELFDATA2MSB] = "Big-Endian", - }; - static char *types[] = { - [ET_NONE] = "No file type", - [ET_REL] = "Relocatable file", - [ET_EXEC] = "Executable file", - [ET_DYN] = "Shared object file", - [ET_CORE] = "Core file", - }; - static char *machs[] = { - [EM_NONE] = "No machine", - [EM_M32] = "AT&T WE 32100", - [EM_SPARC] = "SPARC", - [EM_386] = "Intel 80386", - [EM_68K] = "Motorola 68000", - [EM_88K] = "Motorola 88000", - [EM_IAMCU] = "Intel MCU", - [EM_860] = "Intel 80860", - [EM_MIPS] = "MIPS I Architecture", - [EM_S370] = "IBM System/370 Processor", - [EM_MIPS_RS3_LE] = "MIPS RS3000 Little-endian", - [EM_PARISC] = "Hewlett-Packard PA-RISC", - [EM_VPP500] = "Fujitsu VPP500", - [EM_SPARC32PLUS] = "Enhanced instruction set SPARC", - [EM_960] = "Intel 80960", - [EM_PPC] = "PowerPC", - [EM_PPC64] = "64-bit PowerPC", - [EM_S390] = "IBM System/390", - [EM_SPU] = "IBM SPU/SPC", - [EM_V800] = "NEC V800", - [EM_FR20] = "Fujitsu FR20", - [EM_RH32] = "TRW RH-32", - [EM_RCE] = "Motorola RCE", - [EM_ARM] = "ARM AARCH32", - [EM_ALPHA] = "Digital Alpha", - [EM_SH] = "Hitachi SH", - [EM_SPARCV9] = "SPARC Version 9", - [EM_TRICORE] = "Siemens TriCore", - [EM_ARC] = "Argonaut RISC Core", - [EM_H8_300] = "Hitachi H8/300", - [EM_H8_300H] = "Hitachi H8/300H", - [EM_H8S] = "Hitachi H8S", - [EM_H8_500] = "Hitachi H8/500", - [EM_IA_64] = "Intel IA-64", - [EM_MIPS_X] = "Stanford MIPS-X", - [EM_COLDFIRE] = "Motorola ColdFire", - [EM_68HC12] = "Motorola M68HC12", - [EM_MMA] = "Fujitsu MMA", - [EM_PCP] = "Siemens PCP", - [EM_NCPU] = "Sony nCPU", - [EM_NDR1] = "Denso NDR1", - [EM_STARCORE] = "Motorola Star*Core", - [EM_ME16] = "Toyota ME16", - [EM_ST100] = "STMicroelectronics ST100", - [EM_TINYJ] = "Advanced Logic Corp. TinyJ", - [EM_X86_64] = "AMD x86-64", - [EM_PDSP] = "Sony DSP Processor", - [EM_PDP10] = "DEC PDP-10", - [EM_PDP11] = "DEC PDP-11", - [EM_FX66] = "Siemens FX66", - [EM_ST9PLUS] = "STMicroelectronics ST9+", - [EM_ST7] = "STMicroelectronics ST7", - [EM_68HC16] = "Motorola MC68HC16", - [EM_68HC11] = "Motorola MC68HC11", - [EM_68HC08] = "Motorola MC68HC08", - [EM_68HC05] = "Motorola MC68HC05", - [EM_SVX] = "Silicon Graphics SVx", - [EM_ST19] = "STMicroelectronics ST19", - [EM_VAX] = "Digital VAX", - [EM_CRIS] = "Axis Communications 32-bit", - [EM_JAVELIN] = "Infineon Technologies 32-bit", - [EM_FIREPATH] = "Element 14 64-bit DSP Processor", - [EM_ZSP] = "LSI Logic 16-bit DSP Processor", - [EM_MMIX] = "Donald Knuth's educational 64-bit", - [EM_HUANY] = "Harvard machine-independent", - [EM_PRISM] = "SiTera Prism", - [EM_AVR] = "Atmel AVR 8-bit", - [EM_FR30] = "Fujitsu FR30", - [EM_D10V] = "Mitsubishi D10V", - [EM_D30V] = "Mitsubishi D30V", - [EM_V850] = "NEC v850", - [EM_M32R] = "Mitsubishi M32R", - [EM_MN10300] = "Matsushita MN10300", - [EM_MN10200] = "Matsushita MN10200", - [EM_PJ] = "picoJava", - [EM_OPENRISC] = "OpenRISC 32-bit", - [EM_ARC_A5] = "ARC ARCompact", - [EM_ARC_COMPACT] = "ARC ARCompact", - [EM_XTENSA] = "Tensilica Xtensa", - [EM_VIDEOCORE] = "Alphamosaic VideoCore", - [EM_TMM_GPP] = "Thompson Multimedia GPP", - [EM_NS32K] = "National 32000 series", - [EM_TPC] = "Tenor Network TPC", - [EM_SNP1K] = "Trebia SNP 1000", - [EM_ST200] = "STMicroelectronics ST200", - [EM_IP2K] = "Ubicom IP2xxx", - [EM_MAX] = "MAX Processor", - [EM_CR] = "National CompactRISC", - [EM_F2MC16] = "Fujitsu F2MC16", - [EM_MSP430] = "Texas msp430", - [EM_BLACKFIN] = "Analog Devices Blackfin", - [EM_SE_C33] = "S1C33 of Seiko Epson", - [EM_SEP] = "Sharp embedded", - [EM_ARCA] = "Arca RISC", - [EM_UNICORE] = "PKU-Unity Ltd. and MPRC", - [EM_EXCESS] = "eXcess CPU", - [EM_DXP] = "Deep Execution Processor", - [EM_ALTERA_NIOS2] = "Altera Nios II", - [EM_CRX] = "National CompactRISC CRX", - [EM_XGATE] = "Motorola XGATE", - [EM_C166] = "Infineon C16x/XC16x", - [EM_M16C] = "Renesas M16C", - [EM_DSPIC30F] = "Microchip dsPIC30F", - [EM_CE] = "Freescale Communication Engine", - [EM_M32C] = "Renesas M32C", - [EM_TSK3000] = "Altium TSK3000 core", - [EM_RS08] = "Freescale RS08", - [EM_SHARC] = "Analog Devices SHARC", - [EM_ECOG2] = "Cyan Technology eCOG2", - [EM_SCORE7] = "Sunplus S+core7", - [EM_DSP24] = "NJR 24-bit DSP", - [EM_VIDEOCORE3] = "Broadcom VideoCore III", - [EM_LATTICEMICO3] = "RISC processor for Lattice FPGA", - [EM_SE_C17] = "Seiko Epson C17", - [EM_TI_C6000] = "TMS320C6000 DSP family", - [EM_TI_C2000] = "TMS320C2000 DSP family", - [EM_TI_C5500] = "TMS320C55x DSP family", - [EM_TI_ARP32] = "Texas Application Specific RISC", - [EM_TI_PRU] = "Texas Programmable Realtime Unit", - [EM_MMDSP_PLUS] = "STMicroelectronics 64bit VLIW", - [EM_CYPRESS_M8C] = "Cypress M8C microprocessor", - [EM_R32C] = "Renesas R32C series", - [EM_TRIMEDIA] = "NXP Semiconductors TriMedia", - [EM_QDSP6] = "QUALCOMM DSP6 Processor", - [EM_8051] = "Intel 8051 and variants", - [EM_STXP7X] = "STMicroelectronics STxP7x", - [EM_NDS32] = "Andes Technology embedded RISC", - [EM_ECOG1] = "Cyan Technology eCOG1X family", - [EM_ECOG1X] = "Cyan Technology eCOG1X family", - [EM_MAXQ30] = "MAXQ30 Core Micro-controllers", - [EM_XIMO16] = "NJR 16-bit DSP Processor", - [EM_MANIK] = "M2000 Reconfigurable RISC", - [EM_CRAYNV2] = "Cray Inc. NV2 vector architecture", - [EM_RX] = "Renesas RX family", - [EM_METAG] = "Imagination Technologies META", - [EM_MCST_ELBRUS] = "MCST Elbrus", - [EM_ECOG16] = "Cyan Technology eCOG16 family", - [EM_CR16] = "National CompactRISC CR16", - [EM_ETPU] = "Freescale Extended Time Unit", - [EM_SLE9X] = "Infineon Technologies SLE9X core", - [EM_L10M] = "Intel L10M", - [EM_K10M] = "Intel K10M", - [EM_AARCH64] = "ARM AARCH64", - [EM_AVR32] = "Atmel 32-bit", - [EM_STM8] = "STMicroeletronics STM8 ", - [EM_TILE64] = "Tilera TILE64", - [EM_TILEPRO] = "Tilera TILEPro", - [EM_MICROBLAZE] = "Xilinx MicroBlaze 32-bit", - [EM_CUDA] = "NVIDIA CUDA architecture", - [EM_TILEGX] = "Tilera TILE-Gx family", - [EM_CLOUDSHIELD] = "CloudShield architecture family", - [EM_COREA_1ST] = "KIPO-KAIST Core-A 1st gen family", - [EM_COREA_2ND] = "KIPO-KAIST Core-A 2nd gen family", - [EM_ARC_COMPACT2] = "Synopsys ARCompact V2", - [EM_OPEN8] = "Open8 8-bit RISC soft processor core", - [EM_RL78] = "Renesas RL78 family", - [EM_VIDEOCORE5] = "Broadcom VideoCore V processor", - [EM_78KOR] = "Renesas 78KOR family", - [EM_56800EX] = "Freescale 56800EX (DSC)", - [EM_BA1] = "Beyond BA1 CPU architecture", - [EM_BA2] = "Beyond BA2 CPU architecture", - [EM_XCORE] = "XMOS xCORE processor family", - [EM_MCHP_PIC] = "Microchip 8-bit PIC(r) family", - [EM_KM32] = "KM211 KM32 32-bit processor", - [EM_KMX32] = "KM211 KMX32 32-bit processor", - [EM_KMX16] = "KM211 KMX16 16-bit processor", - [EM_KMX8] = "KM211 KMX8 8-bit processor", - [EM_KVARC] = "KM211 KVARC processor", - [EM_CDP] = "Paneve CDP architecture family", - [EM_COGE] = "Cognitive Smart Memory Processor", - [EM_COOL] = "Bluechip Systems CoolEngine", - [EM_NORC] = "Nanoradio Optimized RISC", - [EM_CSR_KALIMBA] = "CSR Kalimba architecture family", - [EM_Z80] = "Zilog Z80", - [EM_VISIUM] = "VISIUMcore processor", - [EM_FT32] = "FTDI Chip FT32", - [EM_MOXIE] = "Moxie processor family", - [EM_AMDGPU] = "AMD GPU architecture", - [EM_RISCV] = "RISC-V", - [EM_BPF] = "Linux BPF", - [EM_CSKY] = "C-SKY", - }; - static char *versions[] = { - [EV_NONE] = "Invalid", - [EV_CURRENT] = "Current", - }; - - class = hdr->e_ident[EI_CLASS]; - data = hdr->e_ident[EI_DATA]; - abi = hdr->e_ident[EI_OSABI]; - type = hdr->e_type; - mach = hdr->e_machine; - version = hdr->e_version; - - sclass = (class <= ELFCLASS64) ? classes[class] : "Unknown"; - sdata = (data <= ELFDATA2MSB) ? datas[data] : "Unknown"; - stype = (type <= ET_CORE) ? types[type] : "Unknown"; - smach = (mach <= EM_CSKY) ? machs[mach] : "Unknown"; - if (!smach) - smach = "Unknown"; - sversion = (version <= EV_CURRENT) ? versions[version] : "Unknown"; - - switch (abi) { - case ELFOSABI_ARM: - sabi = "ARM"; - break; - case ELFOSABI_STANDALONE: - sabi = "Standalone (embedded) application"; - break; - default: - sabi = (abi <= ELFOSABI_OPENVOS) ? abis[abi] : "Unknown"; - } - - printf("elfhdr64:\n" - "\tei_class: %u, %s\n" - "\tei_data: %u, %s\n" - "\tei_version: %u\n" - "\tei_osabi: %u, %s\n" - "\tei_abiversion: %u\n" - "\te_type: %u, %s\n" - "\te_machine: %u, %s\n" - "\te_version: %lu, %s\n" - "\te_entry: 0x%08llx\n" - "\te_phoff: %llu\n" - "\te_shoff: %llu\n" - "\te_flags: %#lx\n" - "\te_ehsize: %lu\n" - "\te_phentsize: %lu\n" - "\te_phnum: %lu\n" - "\te_shentsize: %lu\n" - "\te_shnum: %lu\n" - "\te_shstrndx: %lu\n" - "\n", - class, sclass, - data, sdata, - hdr->e_ident[EI_VERSION], - abi, sabi, - hdr->e_ident[EI_ABIVERSION], - type, stype, - mach, smach, - version, sversion, - (long long) hdr->e_entry, - (long long) hdr->e_phoff, - (long long) hdr->e_shoff, - (long) hdr->e_flags, - (long) hdr->e_ehsize, - (long) hdr->e_phentsize, - (long) hdr->e_phnum, - (long) hdr->e_shentsize, - (long) hdr->e_shnum, - (long) hdr->e_shstrndx); -} - -static void -printphdr(Elf_Phdr *phdr, unsigned long n) -{ - unsigned long i; - static char *types[] = { - [PT_NULL] = "unused", - [PT_LOAD] = "loadable segment", - [PT_DYNAMIC] = "dynamic linking section", - [PT_INTERP] = "the RTLD", - [PT_NOTE] = "auxiliary information", - [PT_SHLIB] = "reserved - purpose undefined", - [PT_PHDR] = "program header", - [PT_TLS] = "thread local storage", - }; - static Flags f ={ - .nr = NR_RIGHTS, - .text = { - [FLAG_X] = "Executable", - [FLAG_W] = "Writable", - [FLAG_R] = "Readable", - } - }; - - for (i = 0; i < n; i++) { - unsigned long type; - char *stype; - - type = phdr->p_type; - stype = (type <= PT_TLS) ? types[type] : "Unknown"; - f.flags = phdr->p_flags; - - printf("Program header %ld\n" - "\tp_type: %#lx, %s\n" - "\tp_flags: %#lx\n" - "\tp_offset: %#08llx\n" - "\tp_vaddr: %#08llx\n" - "\tp_paddr: %#08llx\n" - "\tp_filesz: %#08llx\n" - "\tp_memsz: %#08llx\n" - "\tp_align: %#08llx\n", - i, - type, stype, - (long) phdr->p_flags, - (long long) phdr->p_offset, - (long long) phdr->p_vaddr, - (long long) phdr->p_paddr, - (long long) phdr->p_filesz, - (long long) phdr->p_memsz, - (long long) phdr->p_align); - - putchar('\t'); - printflags(&f); - putchar('\n'); - ++phdr; - } -} - -void -elf64fhdr(Obj *obj, unsigned long long *start, Flags *f) -{ - size_t i; - char *name; - Elf64 *elf = obj->data; - Elf_Ehdr *hdr = &elf->hdr; - Elf_Shdr *shdr; - - *start = hdr->e_entry; - - for (i = 0; i < elf->nsec; i++) { - shdr = &elf->shdr[i]; - name = elf64str(obj, SEC_STRTBL, shdr->sh_name); - setflag(f, strncmp(name, ".debug", 6) == 0, HAS_DEBUG); - setflag(f, strncmp(name, ".line", 5) == 0, HAS_LINENO); - setflag(f, strcmp(name, ".debug_line") == 0, HAS_LINENO); - setflag(f, shdr->sh_type == SHT_RELA, HAS_RELOC); - setflag(f, shdr->sh_type == SHT_REL, HAS_RELOC); - } - - setflag(f, hdr->e_type == ET_EXEC, EXEC_P); - setflag(f, hdr->e_type == ET_DYN, DYNAMIC); - setflag(f, elf->nsym > 0, HAS_SYMS); - - if (!pflag) - return; - - printfhdr(hdr); - printphdr(elf->phdr, hdr->e_phnum); -} diff --git a/src/cmd/scc-objdump/main.c b/src/cmd/scc-objdump/main.c @@ -34,11 +34,11 @@ static struct binops *op, ops[NFORMATS] = { .dumpfhdr = coff32fhdr, .hasrelloc = coff32hasrelloc, }, - [ELF64] = { - .dumpsyms = elf64syms, - .dumpsecs = elf64scns, - .dumpfhdr = elf64fhdr, - .hasrelloc = elf64hasrelloc, + [ELF] = { + .dumpsyms = elfsyms, + .dumpsecs = elfscns, + .dumpfhdr = elffhdr, + .hasrelloc = elfhasrelloc, }, }; diff --git a/src/cmd/scc-objdump/objdump.h b/src/cmd/scc-objdump/objdump.h @@ -36,10 +36,10 @@ extern void coff32fhdr(Obj *, unsigned long long *, Flags *); extern int coff32hasrelloc(Obj *, Section *); /* elf64.c */ -extern void elf64syms(Obj *); -extern void elf64scns(Obj *); -extern void elf64fhdr(Obj *, unsigned long long *, Flags *); -extern int elf64hasrelloc(Obj *, Section *); +extern void elfsyms(Obj *); +extern void elfscns(Obj *); +extern void elffhdr(Obj *, unsigned long long *, Flags *); +extern int elfhasrelloc(Obj *, Section *); /* main.c */ extern void error(char *, ...); diff --git a/src/libmach/Makefile b/src/libmach/Makefile @@ -1,7 +1,7 @@ .POSIX: DIRS =\ - elf64\ + elf\ coff32\ PROJECTDIR =../.. @@ -45,4 +45,4 @@ $(TARGET): $(OBJS) cp $@ $(LIBDIR)/scc dep: - ./mkdep elf64 coff32 + ./mkdep elf coff32 diff --git a/src/libmach/delobj.c b/src/libmach/delobj.c @@ -5,12 +5,12 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static void (*ops[NFORMATS])(Obj *) = { [COFF32] = coff32del, - [ELF64] = elf64del, + [ELF] = elfdel, }; void diff --git a/src/libmach/elf/Makefile b/src/libmach/elf/Makefile @@ -0,0 +1,25 @@ +.POSIX: + +PROJECTDIR =../../.. +include $(PROJECTDIR)/scripts/rules.mk + +OBJS =\ + elfarchs.o\ + elfdel.o\ + elfgetsec.o\ + elfgetsym.o\ + elfnew.o\ + elfprobe.o\ + elfread.o\ + elftype.o\ + +all: $(OBJS) + +dep: + @(printf 'ELFOBJS=\\';\ + echo;\ + echo $(OBJS) |\ + sed -E 's@ *([^ ]*)@\telf/\1\\\n@g') > deps.mk + +distclean: + rm -f deps.mk diff --git a/src/libmach/elf/elfarchs.c b/src/libmach/elf/elfarchs.c @@ -0,0 +1,19 @@ +#include <stdio.h> + + +#include <scc/mach.h> +#include <scc/elf/elftypes.h> +#include <scc/elf/elfhdr.h> +#include <scc/elf.h> + +#include "../libmach.h" + +struct arch elfarchs[] = { + { + .name = "elf-amd64", + .mach = EM_X86_64, + .endian = ELFDATA2LSB, + .type = OBJ(ELF, ARCHAMD64, LITTLE_ENDIAN), + }, + NULL, +}; diff --git a/src/libmach/elf/elfdel.c b/src/libmach/elf/elfdel.c @@ -0,0 +1,23 @@ +#include <stdio.h> +#include <stdlib.h> + +#include <scc/mach.h> +#include <scc/elf.h> + +#include "../libmach.h" +#include "fun.h" + +void +elfdel(Obj *obj) +{ + struct elf *elf = obj->data; + + if (elf) { + free(elf->phdr); + free(elf->secs); + free(elf->syms); + free(elf->rels); + } + free(obj->data); + obj->data = NULL; +} diff --git a/src/libmach/elf/elfgetsec.c b/src/libmach/elf/elfgetsec.c @@ -0,0 +1,77 @@ +#include <stdio.h> + +#include <scc/mach.h> +#include <scc/elf/elftypes.h> +#include <scc/elf/elfshdr.h> +#include <scc/elf.h> + +#include "../libmach.h" +#include "fun.h" + +Section * +elfgetsec(Obj *obj, int *idx, Section *sec) +{ + int stype, n = *idx; + unsigned long flags, type; + unsigned sflags; + Elf *elf = obj->data; + Elfsec *shdr; + + if (n >= elf->nsec) { + if (n == SHN_ABS) + sec->name = "*ABS"; + else if (n == SHN_COMMON) + sec->name = "*COM*"; + else + sec->name = "*UNK*"; + return NULL; + } + + shdr = &elf->secs[n]; + flags = shdr->flags; + type = shdr->type; + + if (flags & SHF_ALLOC) { + if (type == SHT_NOBITS) + stype = 'B'; + else if (flags & SHF_WRITE) + stype = 'D'; + else + stype = 'T'; + } else { + stype = 'N'; + } + + sflags = 0; + if (flags & SHF_WRITE) + sflags |= SWRITE; + if (flags & SHF_EXECINSTR) + sflags |= SEXEC; + if (flags & SHF_ALLOC) + sflags |= SLOAD|SREAD; + if (type != SHT_NOBITS) + sflags |= SALLOC; + if (stype == 'T' || stype == 'D') + sflags |= SRELOC; + + /* + * We cannot differentiate between load and base address + * in a section, while we can use the physical address + * for that when dealing with segments. + */ + if (n == SHN_UNDEF) + sec->name = "*UND*"; + else + sec->name = shdr->name; + + sec->index = n; + sec->size = shdr->size; + sec->base = shdr->addr; + sec->load = shdr->addr; + sec->offset = shdr->offset; + sec->type = stype; + sec->flags = sflags; + sec->align = shdr->addralign; + + return sec; +} diff --git a/src/libmach/elf/elfgetsym.c b/src/libmach/elf/elfgetsym.c @@ -0,0 +1,123 @@ +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/mach.h> +#include <scc/elf/elftypes.h> +#include <scc/elf/elfent.h> +#include <scc/elf/elfshdr.h> +#include <scc/elf.h> + +#include "../libmach.h" +#include "fun.h" + +static int +typeof(Elf *elf, Elfsym *ent, char *name) +{ + int c, bind, weak; + unsigned long flags, type; + Elfsec *shdr; + + weak = ELF_ST_BIND(ent->info) == STB_WEAK; + + switch (ent->shndx) { + case SHN_UNDEF: + c = 'U'; + break; + case SHN_ABS: + c = 'a'; + break; + case SHN_COMMON: + c = 'C'; + break; + case SHN_XINDEX: + abort(); + default: + shdr = &elf->secs[ent->shndx]; + flags = shdr->flags; + type = shdr->type; + + if (ELF_ST_BIND(ent->info) == STB_WEAK) { + c = (flags & SHF_EXECINSTR) ? 'W' : 'V'; + } else { + if (flags & SHF_ALLOC) { + if (type == SHT_NOBITS) + c = 'b'; + else if (flags & SHF_WRITE) + c = 'd'; + else if (flags & SHF_EXECINSTR) + c = 't'; + else + c = 'r'; + } else if (strncmp(name, ".debug", 6) == 0) { + c = 'N'; + } else if (strcmp(name, ".comment") == 0) { + c = 'N'; + } else if (strcmp(name, ".line") == 0) { + c = 'N'; + } else if (strcmp(name, ".stab") == 0) { + c = 'N'; + } else { + c = '?'; + } + if (ELF_ST_BIND(ent->info) != STB_LOCAL) + c = toupper(c); + } + } + + return c; +} + +static int +stypeof(Elfsym *ent) +{ + switch (ELF_ST_TYPE(ent->info)) { + case STT_OBJECT: + return SYMOBJECT; + case STT_FUNC: + return SYMFUNC; + case STT_SECTION: + return SYMSECTION; + case STT_FILE: + return SYMFILE; + case STT_COMMON: + return SYMCOMMON; + default: + case STT_NOTYPE: + return SYMNOTYPE; + } +} + +#include <assert.h> + +Symbol * +elfgetsym(Obj *obj, int *idx, Symbol *sym) +{ + int n = *idx; + Elfsym *ent; + Elf *elf = obj->data; + + if (n == 0) + n++; + + if (!elf->syms || n >= elf->nsym) + return NULL; + ent = &elf->syms[n]; + + if (ELF_ST_TYPE(ent->info) == STT_SECTION) { + Elfsec *shdr = &elf->secs[ent->shndx]; + sym->name = shdr->name; + } else { + sym->name = ent->name; + } + + // assert(strlen(sym->name) > 0); + sym->type = typeof(elf, ent, sym->name); + sym->stype = stypeof(ent); + sym->value = ent->value; + sym->size = ent->size; + sym->index = *idx = n; + + return sym; +} diff --git a/src/libmach/elf/elfnew.c b/src/libmach/elf/elfnew.c @@ -0,0 +1,20 @@ +#include <stdio.h> +#include <stdlib.h> + +#include <scc/mach.h> +#include <scc/elf.h> + +#include "../libmach.h" +#include "fun.h" + +int +elfnew(Obj *obj, int type) +{ + struct elf *elf; + + if ((elf = calloc(1, sizeof(*elf))) == NULL) + return -1; + obj->data = elf; + obj->index = "/"; + return 0; +} diff --git a/src/libmach/elf/elfprobe.c b/src/libmach/elf/elfprobe.c @@ -0,0 +1,47 @@ +#include <stdio.h> + +#include <scc/mach.h> +#include <scc/elf/elftypes.h> +#include <scc/elf/elfhdr.h> +#include <scc/elf.h> + +#include "../libmach.h" +#include "fun.h" + +int +elfprobe(unsigned char *buf, char **name) +{ + int arch, data, endian; + struct elfhdr32 hdr; + struct arch *ap; + + data = buf[EI_DATA]; + endian = (data == ELFDATA2LSB) ? LITTLE_ENDIAN : BIG_ENDIAN; + arch = (buf[EI_CLASS] == ELFCLASS32) ? ARCHUNK32 : ARCHUNK64; + + unpack(endian, + buf, + "'16sss", + hdr.e_ident, + &hdr.e_type, + &hdr.e_machine, + &hdr.e_version); + + if (!IS_ELF(hdr) + || buf[EI_VERSION] != EV_CURRENT + || hdr.e_version != EV_CURRENT + || buf[EI_CLASS] != ELFCLASS32 && buf[EI_CLASS] != ELFCLASS64 + || (data != ELFDATA2LSB && data != ELFDATA2MSB)) { + return -1; + } + + for (ap = elfarchs; ap->name; ap++) { + if (ap->mach == hdr.e_machine && ap->endian == data) { + if (name) + *name = ap->name; + return ap->type; + } + } + + return OBJ(ELF, arch, endian); +} diff --git a/src/libmach/elf/elfread.c b/src/libmach/elf/elfread.c @@ -0,0 +1,761 @@ +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/mach.h> +#include <scc/elf.h> + +#include <scc/elf/elftypes.h> +#include <scc/elf/elfhdr.h> +#include <scc/elf/elfphdr.h> +#include <scc/elf/elfshdr.h> +#include <scc/elf/elfent.h> +#include <scc/elf/elfrel.h> + +#include "../libmach.h" +#include "fun.h" + +struct elfunpack { + void (*hdr)(int, unsigned char *, Elfhdr *); + void (*phdr)(int, unsigned char *, Elfphdr *); + void (*sec)(int, unsigned char *, Elfsec *); + void (*sym)(int, unsigned char *, Elfsym *); + void (*rel)(int, unsigned char *, Elfrel *); + void (*rela)(int, unsigned char *, Elfrel *); + + int hdrsiz; + int phdrsiz; + int shentsiz; + int symsiz; + int relsiz; + int relasiz; +}; + +struct elfunpack unpack64; +struct elfunpack unpack32; + +static void +unpack_hdr64(int order, unsigned char *buf, Elfhdr *hdr) +{ + Elf64_Ehdr ehdr; + int n; + + n = unpack(order, + buf, + "'16sslqqqlssssss", + ehdr.e_ident, + &ehdr.e_type, + &ehdr.e_machine, + &ehdr.e_version, + &ehdr.e_entry, + &ehdr.e_phoff, + &ehdr.e_shoff, + &ehdr.e_flags, + &ehdr.e_ehsize, + &ehdr.e_phentsize, + &ehdr.e_phnum, + &ehdr.e_shentsize, + &ehdr.e_shnum, + &ehdr.e_shstrndx); + + assert(n == ELFH64SZ); + + memcpy(hdr->ident, ehdr.e_ident, EI_NIDENT); + hdr->type = ehdr.e_type; + hdr->machine = ehdr.e_machine; + hdr->version = ehdr.e_version; + hdr->entry = ehdr.e_entry; + hdr->phoff = ehdr.e_phoff; + hdr->shoff = ehdr.e_shoff; + hdr->flags = ehdr.e_flags; + hdr->ehsize = ehdr.e_ehsize; + hdr->phentsize = ehdr.e_phentsize; + hdr->phnum = ehdr.e_phnum; + hdr->shentsize = ehdr.e_shentsize; + hdr->shnum = ehdr.e_shnum; + hdr->shstrndx = ehdr.e_shstrndx; +} + +static void +unpack_hdr32(int order, unsigned char *buf, Elfhdr *hdr) +{ + Elf32_Ehdr ehdr; + int n; + + n = unpack(order, + buf, + "'16sslllllssssss", + ehdr.e_ident, + &ehdr.e_type, + &ehdr.e_machine, + &ehdr.e_version, + &ehdr.e_entry, + &ehdr.e_phoff, + &ehdr.e_shoff, + &ehdr.e_flags, + &ehdr.e_ehsize, + &ehdr.e_phentsize, + &ehdr.e_phnum, + &ehdr.e_shentsize, + &ehdr.e_shnum, + &ehdr.e_shstrndx); + + assert(n == ELFH32SZ); + + memcpy(hdr->ident, ehdr.e_ident, EI_NIDENT); + hdr->type = ehdr.e_type; + hdr->machine = ehdr.e_machine; + hdr->version = ehdr.e_version; + hdr->entry = ehdr.e_entry; + hdr->phoff = ehdr.e_phoff; + hdr->shoff = ehdr.e_shoff; + hdr->flags = ehdr.e_flags; + hdr->ehsize = ehdr.e_ehsize; + hdr->phentsize = ehdr.e_phentsize; + hdr->phnum = ehdr.e_phnum; + hdr->shentsize = ehdr.e_shentsize; + hdr->shnum = ehdr.e_shnum; + hdr->shstrndx = ehdr.e_shstrndx; +} + +static void +unpack_phdr64(int order, unsigned char *buf, Elfphdr *hdr) +{ + int n; + Elf64_Phdr phdr; + + n = unpack(order, + buf, + "llqqqqqq", + &phdr.p_type, + &phdr.p_flags, + &phdr.p_offset, + &phdr.p_vaddr, + &phdr.p_paddr, + &phdr.p_filesz, + &phdr.p_memsz, + &phdr.p_align); + + assert(n == ELFP64SZ); + + hdr->type = phdr.p_type; + hdr->flags = phdr.p_flags; + hdr->offset = phdr.p_offset; + hdr->vaddr = phdr.p_vaddr; + hdr->paddr = phdr.p_paddr; + hdr->filesz = phdr.p_filesz; + hdr->memsz = phdr.p_memsz; + hdr->align = phdr.p_align; +} + +static void +unpack_phdr32(int order, unsigned char *buf, Elfphdr *hdr) +{ + int n; + Elf32_Phdr phdr; + + n = unpack(order, + buf, + "llllllll", + &phdr.p_type, + &phdr.p_offset, + &phdr.p_vaddr, + &phdr.p_paddr, + &phdr.p_filesz, + &phdr.p_memsz, + &phdr.p_flags, + &phdr.p_align); + + assert(n == ELFP32SZ); + + hdr->type = phdr.p_type; + hdr->flags = phdr.p_flags; + hdr->offset = phdr.p_offset; + hdr->vaddr = phdr.p_vaddr; + hdr->paddr = phdr.p_paddr; + hdr->filesz = phdr.p_filesz; + hdr->memsz = phdr.p_memsz; + hdr->align = phdr.p_align; +} + +static void +unpack_shdr64(int order, unsigned char *buf, Elfsec *sec) +{ + int n; + Elf64_Shdr shdr; + + n = unpack(order, + buf, + "llqqqqllqq", + &shdr.sh_name, + &shdr.sh_type, + &shdr.sh_flags, + &shdr.sh_addr, + &shdr.sh_offset, + &shdr.sh_size, + &shdr.sh_link, + &shdr.sh_info, + &shdr.sh_addralign, + &shdr.sh_entsize); + + assert(n == ELFS64SZ); + + sec->sh_name = shdr.sh_name; + sec->type = shdr.sh_type; + sec->flags = shdr.sh_flags; + sec->addr = shdr.sh_addr; + sec->offset = shdr.sh_offset; + sec->size = shdr.sh_size; + sec->link = shdr.sh_link; + sec->info = shdr.sh_info; + sec->addralign = shdr.sh_addralign; + sec->entsize = shdr.sh_entsize; +} + +static void +unpack_shdr32(int order, unsigned char *buf, Elfsec *sec) +{ + int n; + Elf32_Shdr shdr; + + n = unpack(order, + buf, + "llllllllll", + &shdr.sh_name, + &shdr.sh_type, + &shdr.sh_flags, + &shdr.sh_addr, + &shdr.sh_offset, + &shdr.sh_size, + &shdr.sh_link, + &shdr.sh_info, + &shdr.sh_addralign, + &shdr.sh_entsize); + + assert(n == ELFS32SZ); + + sec->sh_name = shdr.sh_name; + sec->type = shdr.sh_type; + sec->flags = shdr.sh_flags; + sec->addr = shdr.sh_addr; + sec->offset = shdr.sh_offset; + sec->size = shdr.sh_size; + sec->link = shdr.sh_link; + sec->info = shdr.sh_info; + sec->addralign = shdr.sh_addralign; + sec->entsize = shdr.sh_entsize; +} + +static void +unpack_sym64(int order, unsigned char *buf, Elfsym *sym) +{ + int n; + Elf64_Sym ent; + + n = unpack(order, + buf, + "lccsqq", + &ent.st_name, + &ent.st_info, + &ent.st_other, + &ent.st_shndx, + &ent.st_value, + &ent.st_size); + + assert(n == ELFE64SZ); + + sym->st_name = ent.st_name; + sym->info = ent.st_info; + sym->other = ent.st_other; + sym->shndx = ent.st_shndx; + sym->value = ent.st_value; + sym->size = ent.st_size; +} + +static void +unpack_sym32(int order, unsigned char *buf, Elfsym *sym) +{ + int n; + Elf32_Sym ent; + + n = unpack(order, + buf, + "lllccs", + &ent.st_name, + &ent.st_value, + &ent.st_size, + &ent.st_info, + &ent.st_other, + &ent.st_shndx); + + assert(n == ELFE32SZ); + + sym->st_name = ent.st_name; + sym->info = ent.st_info; + sym->other = ent.st_other; + sym->shndx = ent.st_shndx; + sym->value = ent.st_value; + sym->size = ent.st_size; +} + +static void +unpack_rel64(int order, unsigned char *buf, Elfrel *rp) +{ + int n; + Elf64_Rel r; + + n = unpack(order, + buf, + "qq", + &r.r_offset, + &r.r_info); + + assert(n == ELFR64SZ); + + rp->off = r.r_offset; + rp->info = r.r_info; + rp->addend = 0; +} + +static void +unpack_rel32(int order, unsigned char *buf, Elfrel *rp) +{ + int n; + Elf32_Rel r; + + n = unpack(order, + buf, + "ll", + &r.r_offset, + &r.r_info); + + assert(n == ELFR32SZ); + + rp->off = r.r_offset; + rp->info = r.r_info; + rp->addend = 0; +} + +static void +unpack_rela64(int order, unsigned char *buf, Elfrel *rp) +{ + int n; + Elf64_Rela r; + + n = unpack(order, + buf, + "qqq", + &r.r_offset, + &r.r_info, + &r.r_addend); + + assert(n == ELFRA64SZ); + + rp->off = r.r_offset; + rp->info = r.r_info; + rp->addend = r.r_addend; +} + +static void +unpack_rela32(int order, unsigned char *buf, Elfrel *rp) +{ + int n; + Elf32_Rela r; + + n = unpack(order, + buf, + "lll", + &r.r_offset, + &r.r_info, + &r.r_addend); + + assert(n == ELFRA32SZ); + + rp->off = r.r_offset; + rp->info = r.r_info; + rp->addend = r.r_addend; +} + +static int +readhdr(Obj *obj, FILE *fp) +{ + Elf *elf = obj->data; + Elfhdr *hdr = &elf->hdr; + Elfunpack *u = elf->unpack; + unsigned char buf[ELFH64SZ]; + + if (fread(buf, u->hdrsiz, 1, fp) != 1) + return 0; + (*u->hdr)(ORDER(obj->type), buf, hdr); + + if (hdr->shnum > INT_MAX || hdr->phnum > INT_MAX) + return 0; + + switch (hdr->type) { + case ET_REL: + case ET_EXEC: + case ET_DYN: + return 1; + default: + return 0; + } +} + +static int +readphdr(Obj *obj, FILE *fp) +{ + int i, r; + Elfphdr *phdr; + Elf *elf = obj->data; + Elfhdr *hdr = &elf->hdr; + Elfunpack *u = elf->unpack; + unsigned char *buf; + + r = 0; + if (hdr->phnum > 0 + && (hdr->phoff == 0 || hdr->phentsize < u->phdrsiz)) { + errno = ERANGE; + goto err0; + } + if (hdr->phoff == 0 || hdr->phnum == 0) + return 1; + + if ((buf = malloc(hdr->phentsize)) == NULL) + goto err0; + if ((phdr = calloc(hdr->phnum, sizeof(*phdr))) == NULL) + goto err1; + elf->phdr = phdr; + + if (!objpos(obj, fp, hdr->phoff)) + goto err1; + + for (i = 0; i < hdr->phnum; i++) { + if (fread(buf, hdr->phentsize, 1, fp) != 1) + goto err1; + (*u->phdr)(ORDER(obj->type), buf, &phdr[i]); + } + r = 1; + +err1: + free(buf); +err0: + return r; +} + +static int +readshdr(Obj *obj, FILE *fp) +{ + int r, nsec; + Elfsec *sec; + Elf *elf = obj->data; + Elfhdr *hdr = &elf->hdr; + Elfunpack *u = elf->unpack; + unsigned char *buf; + + if (hdr->shoff == 0) + return 1; + + if (!objpos(obj, fp, hdr->shoff)) + return 0; + + if (hdr->shnum != SHN_UNDEF) { + if (hdr->shnum > INT_MAX) + return 0; + nsec = hdr->shnum; + } else { + Elfsec sec0; + fpos_t pos; + unsigned char buf0[ELFS64SZ]; + + fgetpos(fp, &pos); + fread(buf0, u->shentsiz, 1, fp); + fsetpos(fp, &pos); + + if (ferror(fp)) + return 0; + + (*u->sec)(ORDER(obj->type), buf0, &sec0); + if (sec0.size > INT_MAX) + return 0; + nsec = sec0.size; + } + + if (nsec == 0) + return 1; + + r = 0; + if ((buf = malloc(hdr->shentsize)) == NULL) + return 0; + if ((sec = calloc(nsec, sizeof(*sec))) == NULL) + goto err; + elf->secs = sec; + elf->nsec = nsec; + + for ( ; nsec-- > 0; ++sec) { + if (fread(buf, hdr->shentsize, 1, fp) != 1) + goto err; + (*u->sec)(ORDER(obj->type), buf, sec); + } + r = 1; +err: + free(buf); + return r; +} + +static int +readstrtbl(Obj *obj, FILE *fp) +{ + char *s; + int idx; + Elfsec *tbl, *sec; + Elf *elf = obj->data; + Elfhdr *hdr = &elf->hdr; + + if (hdr->shstrndx != SHN_XINDEX) { + idx = hdr->shstrndx; + } else { + if (hdr->shnum == 0) + return 0; + sec = elf->secs; + if (sec->link > INT_MAX) + return 0; + idx = sec->link; + } + if (idx > elf->nsec || elf->secs[idx].type != SHT_STRTAB) + return 0; + elf->secstrtbl = idx; + + for (sec = elf->secs; sec < &elf->secs[elf->nsec]; ++sec) { + if (sec->type != SHT_STRTAB) + continue; + + if (sec->size > SIZE_MAX) + return 0; + if ((s = malloc(sec->size)) == NULL) + return 0; + sec->strtbl = s; + + if (!objpos(obj, fp, sec->offset)) + return 0; + if (fread(s, sec->size, 1, fp) != 1) + return 0; + } + + return 1; +} + +static int +secsize(Elfsec *sec, int onent, int entsiz) +{ + unsigned long long nent; + + if (sec->entsize == 0 || sec->entsize < entsiz) + return -1; + nent = sec->size / sec->entsize; + if (nent > INT_MAX - onent) + return -1; + + return nent; +} + +static int +readsyms(Obj *obj, Elfsec *sec, FILE *fp) +{ + int r = 0, n, oldn; + Elfsym *sym; + Elfsec *tbl; + Elf *elf = obj->data; + Elfunpack *u = elf->unpack; + Elfhdr *hdr = &elf->hdr; + unsigned char *buf; + + if ((n = secsize(sec, elf->nsym, u->symsiz)) <= 0) + return n; + if ((buf = malloc(sec->entsize)) == NULL) + return 0; + + oldn = elf->nsym; + sym = realloc(elf->syms, (oldn + n) * sizeof(Elfsym)); + if (!sym) + goto err; + elf->syms = sym; + elf->nsym += n; + + if (!objpos(obj, fp, sec->offset)) + goto err; + + if (sec->link >= hdr->shnum) + goto err; + tbl = &elf->secs[sec->link]; + if (tbl->type != SHT_STRTAB) + goto err; + + for (sym = &elf->syms[oldn] ; n-- > 0 ; ++sym) { + if (fread(buf, sec->entsize, 1, fp) != 1) + goto err; + (*u->sym)(ORDER(obj->type), buf, sym); + sym->symsec = sec; + if (sym->st_name >= tbl->size) + goto err; + sym->name = &tbl->strtbl[sym->st_name]; + + switch (sym->shndx) { + case SHN_XINDEX: + /* + * Elf supports an extension mechanism to allow + * indexes bigger than 4 bytes. We don't care + * and we reject elf files using this feature. + */ + goto err; + case SHN_UNDEF: + case SHN_ABS: + case SHN_COMMON: + break; + default: + if (sym->shndx >= elf->nsec) + goto err; + break; + } + } + r = 1; + +err: + free(buf); + return r; +} + +static int +readrels(Obj *obj, Elfsec *sec, FILE *fp) +{ + int r = 0, oldn, n, min; + Elf *elf = obj->data; + Elfunpack *u = elf->unpack; + Elfrel *rp; + void (*fn)(int, unsigned char *, Elfrel *); + unsigned char *buf; + + if (sec->type == SHT_RELA) { + fn = u->rela; + min = u->relasiz; + } else { + fn = u->rel; + min = u->relsiz; + } + + if (!objpos(obj, fp, sec->offset)) + goto err; + + if ((n = secsize(sec, elf->nrel, min)) <= 0) + return n; + if ((buf = malloc(sec->entsize)) == NULL) + return 0; + + oldn = elf->nrel; + rp = realloc(elf->rels, (oldn + n) * sizeof(Elfrel)); + if (!rp) + goto err; + elf->rels = rp; + elf->nrel += n; + + for (rp = &elf->rels[oldn]; n-- > 0; ++rp) { + if (fread(buf, sec->entsize, 1, fp) != 1) + goto err; + (*fn)(ORDER(obj->type), buf, rp); + } + r = 1; + +err: + free(buf); + return r; +} + +static int +procsecs(Obj *obj, FILE *fp) +{ + Elf *elf = obj->data; + Elfsec *tbl, *sec; + + tbl = &elf->secs[elf->secstrtbl]; + for (sec = elf->secs; sec < &elf->secs[elf->nsec]; ++sec) { + if (sec->sh_name >= tbl->size) + return 0; + sec->name = &tbl->strtbl[sec->sh_name]; + + switch (sec->type) { + case SHT_DYNSYM: + case SHT_SYMTAB: + if (!readsyms(obj, sec, fp)) + return 0; + break; + case SHT_RELA: + case SHT_REL: + if (!readrels(obj, sec, fp)) + return 0; + break; + } + } + + return 1; +} + +int +elfread(Obj *obj, FILE *fp) +{ + fpos_t pos; + Elf *elf = obj->data; + unsigned char buf[EI_CLASS+1]; + + fgetpos(fp, &pos); + fread(buf, sizeof(buf), 1, fp); + fsetpos(fp, &pos); + + elf->unpack = (buf[EI_CLASS] == ELFCLASS64) ? &unpack64 : &unpack32; + + if (!readhdr(obj, fp)) + return -1; + if (!readphdr(obj, fp)) + return -1; + if (!readshdr(obj, fp)) + return -1; + if (!readstrtbl(obj, fp)) + return -1; + if (!procsecs(obj, fp)) + return -1; + + return 0; +} + +struct elfunpack unpack64 = { + .hdr = unpack_hdr64, + .phdr = unpack_phdr64, + .sec = unpack_shdr64, + .sym = unpack_sym64, + .rel = unpack_rel64, + .rela = unpack_rela64, + + .hdrsiz = ELFH64SZ, + .phdrsiz = ELFP64SZ, + .shentsiz = ELFS64SZ, + .symsiz = ELFE64SZ, + .relsiz = ELFR64SZ, + .relasiz = ELFRA64SZ, +}; + +struct elfunpack unpack32 = { + .hdr = unpack_hdr32, + .phdr = unpack_phdr32, + .sec = unpack_shdr32, + .sym = unpack_sym32, + .rel = unpack_rel32, + .rela = unpack_rela32, + + .hdrsiz = ELFH32SZ, + .phdrsiz = ELFP32SZ, + .shentsiz = ELFS32SZ, + .symsiz = ELFE32SZ, + .relsiz = ELFR32SZ, + .relasiz = ELFRA32SZ, +}; diff --git a/src/libmach/elf/elftype.c b/src/libmach/elf/elftype.c @@ -0,0 +1,21 @@ +#include <stdio.h> +#include <string.h> + +#include <scc/mach.h> +#include <scc/elf.h> + +#include "../libmach.h" +#include "fun.h" + +int +elftype(char *name) +{ + struct arch *ap; + + for (ap = elfarchs; ap ->name; ap++) { + if (strcmp(ap->name, name) == 0) + return ap->type; + } + + return -1; +} diff --git a/src/libmach/elf/fun.h b/src/libmach/elf/fun.h @@ -0,0 +1,17 @@ +extern int elfnew(Obj *, int); +extern int elfread(Obj *, FILE *); +extern int elfsetidx(long, char **, long *, FILE *); +extern int elfgetidx(long *, char ***, long **, FILE *); +extern int elfpc2line(Obj *, unsigned long long , char *, int *); +extern int elfstrip(Obj *); +extern void elfdel(Obj *); +extern int elfwrite(Obj *, Map *, FILE *); +extern int elfprobe(unsigned char *, char **); +extern int elftype(char *); + +extern int elfxsetidx(int long , char *[], long [], FILE *); +extern int elfxgetidx(int, long *, char ***, long **, FILE *); + +extern Symbol *elfgetsym(Obj *, int *, Symbol *); +extern Section *elfgetsec(Obj *, int *, Section *); +extern Map *elfloadmap(Obj *, FILE *); diff --git a/src/libmach/elf64/Makefile b/src/libmach/elf64/Makefile @@ -1,35 +0,0 @@ -.POSIX: - -PROJECTDIR =../../.. -include $(PROJECTDIR)/scripts/rules.mk - -OBJS =\ - elf64.o\ - elf64archs.o\ - elf64del.o\ - elf64getsec.o\ - elf64getsym.o\ - elf64new.o\ - elf64probe.o\ - elf64read.o\ - elf64type.o\ - -ELFHDRS =\ - $(INCDIR)/bits/scc/elf/elfent.h\ - $(INCDIR)/bits/scc/elf/elfhdr.h\ - $(INCDIR)/bits/scc/elf/elfphdr.h\ - $(INCDIR)/bits/scc/elf/elfshdr.h\ - $(INCDIR)/bits/scc/elf/elftypes.h\ - -all: $(OBJS) - -$(OBJS): $(ELFHDRS) - -dep: - @(printf 'ELF64OBJS=\\';\ - echo;\ - echo $(OBJS) |\ - sed -E 's@ *([^ ]*)@\telf64/\1\\\n@g') > deps.mk - -distclean: - rm -f deps.mk diff --git a/src/libmach/elf64/elf64.c b/src/libmach/elf64/elf64.c @@ -1,24 +0,0 @@ -#include <stdio.h> - -#include <scc/mach.h> -#include <scc/elf64.h> - -#include "../libmach.h" -#include "fun.h" - -char * -elf64str(Obj *obj, int n, long stroff) -{ - char *tbl; - size_t siz; - struct elf64 *elf; - - elf = obj->data; - - tbl = elf->strtbl[n]; - siz = elf->strsiz[n]; - - if (!tbl || siz < stroff) - return ""; - return &tbl[stroff]; -} diff --git a/src/libmach/elf64/elf64archs.c b/src/libmach/elf64/elf64archs.c @@ -1,16 +0,0 @@ -#include <stdio.h> - -#include <scc/mach.h> -#include <scc/elf64.h> - -#include "../libmach.h" - -struct arch elf64archs[] = { - { - .name = "elf-amd64", - .mach = EM_X86_64, - .endian = ELFDATA2LSB, - .type = OBJ(ELF64, ARCHAMD64, LITTLE_ENDIAN), - }, - NULL, -}; diff --git a/src/libmach/elf64/elf64del.c b/src/libmach/elf64/elf64del.c @@ -1,24 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -#include <scc/mach.h> -#include <scc/elf64.h> - -#include "../libmach.h" -#include "fun.h" - -void -elf64del(Obj *obj) -{ - struct elf64 *elf = obj->data; - - if (elf) { - free(elf->phdr); - free(elf->shdr); - free(elf->syms); - free(elf->strtbl[0]); - free(elf->strtbl[1]); - } - free(obj->data); - obj->data = NULL; -} diff --git a/src/libmach/elf64/elf64getsec.c b/src/libmach/elf64/elf64getsec.c @@ -1,76 +0,0 @@ -#include <stdio.h> - -#include <scc/mach.h> -#include <scc/elf64.h> - -#include "../libmach.h" -#include "fun.h" - -Section * -elf64getsec(Obj *obj, int *idx, Section *sec) -{ - int stype, n = *idx; - unsigned long flags, type; - unsigned sflags; - Elf64 *elf = obj->data; - Elf_Ehdr *hdr = &elf->hdr; - Elf_Shdr *shdr; - - if (n >= elf->nsec) { - if (n == SHN_ABS) - sec->name = "*ABS"; - else if (n == SHN_COMMON) - sec->name = "*COM*"; - else - sec->name = "*UNK*"; - return NULL; - } - - shdr = &elf->shdr[n]; - flags = shdr->sh_flags; - type = shdr->sh_type; - - if (flags & SHF_ALLOC) { - if (type == SHT_NOBITS) - stype = 'B'; - else if (flags & SHF_WRITE) - stype = 'D'; - else - stype = 'T'; - } else { - stype = 'N'; - } - - sflags = 0; - if (flags & SHF_WRITE) - sflags |= SWRITE; - if (flags & SHF_EXECINSTR) - sflags |= SEXEC; - if (flags & SHF_ALLOC) - sflags |= SLOAD|SREAD; - if (type != SHT_NOBITS) - sflags |= SALLOC; - if (stype == 'T' || stype == 'D') - sflags |= SRELOC; - - /* - * We cannot differentiate between load and base address - * in a section, while we can use the physical address - * for that when dealing with segments. - */ - if (n == SHN_UNDEF) - sec->name = "*UND*"; - else - sec->name = elf64str(obj, SEC_STRTBL, shdr->sh_name); - - sec->index = n; - sec->size = shdr->sh_size; - sec->base = shdr->sh_addr; - sec->load = shdr->sh_addr; - sec->offset = shdr->sh_offset; - sec->type = stype; - sec->flags = sflags; - sec->align = shdr->sh_addralign; - - return sec; -} diff --git a/src/libmach/elf64/elf64getsym.c b/src/libmach/elf64/elf64getsym.c @@ -1,112 +0,0 @@ -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <scc/mach.h> -#include <scc/elf64.h> - -#include "../libmach.h" -#include "fun.h" - -static int -typeof(Elf64 *elf, Elf_Sym *ent, char *name) -{ - int c, bind; - unsigned long flags, type; - Elf_Shdr *shdr; - - switch (ent->st_shndx) { - case SHN_UNDEF: - c = 'U'; - break; - case SHN_ABS: - c = 'a'; - break; - case SHN_COMMON: - c = 'C'; - break; - case SHN_XINDEX: - abort(); - default: - shdr = &elf->shdr[ent->st_shndx]; - flags = shdr->sh_flags; - type = shdr->sh_type; - - if (flags & SHF_ALLOC) { - if (type == SHT_NOBITS) - c = 'b'; - else if (flags & SHF_WRITE) - c = 'd'; - else if (flags & SHF_EXECINSTR) - c = 't'; - else - c = 'r'; - } else if (strncmp(name, ".debug", 6) == 0) { - c = 'N'; - } else if (strcmp(name, ".comment") == 0) { - c = 'N'; - } else if (strcmp(name, ".line") == 0) { - c = 'N'; - } else if (strcmp(name, ".stab") == 0) { - c = 'N'; - } else { - c = '?'; - } - } - - if (ELF_ST_BIND(ent->st_info) != STB_LOCAL) - c = toupper(c); - - return c; -} - -static int -stypeof(Elf_Sym *ent) -{ - switch (ELF_ST_TYPE(ent->st_info)) { - case STT_OBJECT: - return SYMOBJECT; - case STT_FUNC: - return SYMFUNC; - case STT_SECTION: - return SYMSECTION; - case STT_FILE: - return SYMFILE; - case STT_COMMON: - return SYMCOMMON; - default: - case STT_NOTYPE: - return SYMNOTYPE; - } -} - -Symbol * -elf64getsym(Obj *obj, int *idx, Symbol *sym) -{ - int n = *idx; - Elf_Sym *ent; - Elf64 *elf = obj->data; - - if (n == 0) - n++; - - if (!elf->symtab || n >= elf->nsym) - return NULL; - ent = &elf->syms[n]; - - if (ELF_ST_TYPE(ent->st_info) == STT_SECTION) { - Elf_Shdr *shdr = &elf->shdr[ent->st_shndx]; - sym->name = elf64str(obj, SEC_STRTBL, shdr->sh_name); - } else { - sym->name = elf64str(obj, SYM_STRTBL, ent->st_name); - } - - sym->type = typeof(elf, ent, sym->name); - sym->stype = stypeof(ent); - sym->value = ent->st_value; - sym->size = ent->st_size; - sym->index = *idx = n; - - return sym; -} diff --git a/src/libmach/elf64/elf64new.c b/src/libmach/elf64/elf64new.c @@ -1,20 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -#include <scc/mach.h> -#include <scc/elf64.h> - -#include "../libmach.h" -#include "fun.h" - -int -elf64new(Obj *obj, int type) -{ - struct elf64 *elf; - - if ((elf = calloc(1, sizeof(*elf))) == NULL) - return -1; - obj->data = elf; - obj->index = "/"; - return 0; -} diff --git a/src/libmach/elf64/elf64probe.c b/src/libmach/elf64/elf64probe.c @@ -1,45 +0,0 @@ -#include <stdio.h> - -#include <scc/mach.h> -#include <scc/elf64.h> - -#include "../libmach.h" -#include "fun.h" - -int -elf64probe(unsigned char *buf, char **name) -{ - int endian; - Elf_Ehdr hdr; - struct arch *ap; - - unpack(buf[EI_DATA] == ELFDATA2LSB ? LITTLE_ENDIAN : BIG_ENDIAN, - buf, - "'16sss", - hdr.e_ident, - &hdr.e_type, - &hdr.e_machine, - &hdr.e_version); - - if (!IS_ELF(hdr) - || buf[EI_CLASS] != ELFCLASS64 - || buf[EI_DATA] == ELFDATANONE - || buf[EI_VERSION] != EV_CURRENT - || (buf[EI_DATA] != ELFDATA2LSB && buf[EI_DATA] != ELFDATA2MSB)) { - return -1; - } - - if (hdr.e_version != EV_CURRENT) - return -1; - - endian = hdr.e_ident[EI_DATA]; - for (ap = elf64archs; ap->name; ap++) { - if (ap->mach == hdr.e_machine && ap->endian == endian) { - if (name) - *name = ap->name; - return ap->type; - } - } - - return -1; -} diff --git a/src/libmach/elf64/elf64read.c b/src/libmach/elf64/elf64read.c @@ -1,386 +0,0 @@ -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> - -#include <scc/mach.h> -#include <scc/elf64.h> - -#include "../libmach.h" -#include "fun.h" - -static int -unpack_hdr(int order, unsigned char *buf, Elf_Ehdr *hdr) -{ - int n; - - n = unpack(order, - buf, - "'16sslqqqlssssss", - hdr->e_ident, - &hdr->e_type, - &hdr->e_machine, - &hdr->e_version, - &hdr->e_entry, - &hdr->e_phoff, - &hdr->e_shoff, - &hdr->e_flags, - &hdr->e_ehsize, - &hdr->e_phentsize, - &hdr->e_phnum, - &hdr->e_shentsize, - &hdr->e_shnum, - &hdr->e_shstrndx); - - assert(n == ELFHSZ); - - return n; -} - -static int -unpack_phdr(int order, unsigned char *buf, Elf_Phdr *phdr) -{ - int n; - - n = unpack(order, - buf, - "llqqqqqq", - &phdr->p_type, - &phdr->p_flags, - &phdr->p_offset, - &phdr->p_vaddr, - &phdr->p_paddr, - &phdr->p_filesz, - &phdr->p_memsz, - &phdr->p_align); - - assert(n == ELFPSZ); - - return n; -} - -static int -unpack_shdr(int order, unsigned char *buf, Elf_Shdr *shdr) -{ - int n; - - n = unpack(order, - buf, - "llqqqqllqq", - &shdr->sh_name, - &shdr->sh_type, - &shdr->sh_flags, - &shdr->sh_addr, - &shdr->sh_offset, - &shdr->sh_size, - &shdr->sh_link, - &shdr->sh_info, - &shdr->sh_addralign, - &shdr->sh_entsize); - - assert(n == ELFSSZ); - - return n; -} - -static int -unpack_sym(int order, unsigned char *buf, Elf_Sym *sym) -{ - int n; - - n = unpack(order, - buf, - "lccsqq", - &sym->st_name, - &sym->st_info, - &sym->st_other, - &sym->st_shndx, - &sym->st_value, - &sym->st_size); - assert(n == ELFESZ); - - return n; -} - -static int -readhdr(Obj *obj, FILE *fp) -{ - Elf64 *elf; - Elf_Ehdr *hdr; - unsigned char buf[ELFHSZ]; - - elf = obj->data; - hdr = &elf->hdr; - - if (fread(buf, ELFHSZ, 1, fp) != 1) - return 0; - unpack_hdr(ORDER(obj->type), buf, hdr); - - switch (hdr->e_type) { - case ET_REL: - case ET_EXEC: - case ET_DYN: - return 1; - default: - return 0; - } -} - -static int -readphdr(Obj *obj, FILE *fp) -{ - long long i; - Elf_Ehdr *hdr; - Elf_Phdr *phdr; - Elf64 *elf; - unsigned char buf[ELFPSZ]; - - elf = obj->data; - hdr = &elf->hdr; - - if (hdr->e_phoff == 0 || hdr->e_phnum == 0) - return 1; - - phdr = calloc(hdr->e_phnum, sizeof(*phdr)); - if (!phdr) - return 0; - elf->phdr = phdr; - - if (!objpos(obj, fp, hdr->e_phoff)) - return 0; - for (i = 0; i < hdr->e_phnum; i++) { - if (fread(buf, ELFPSZ, 1, fp) != 1) - return 0; - unpack_phdr(ORDER(obj->type), buf, &phdr[i]); - } - - return 1; -} - -static int -readshdr(Obj *obj, FILE *fp) -{ - unsigned long long i, nsec; - Elf_Ehdr *hdr; - Elf_Shdr *shdr; - Elf64 *elf; - unsigned char buf[ELFSSZ + ELFHSZ]; - - elf = obj->data; - hdr = &elf->hdr; - elf->nsec = 0; - elf->shdr = NULL; - - if (hdr->e_shoff == 0) - return 1; - - if (!objpos(obj, fp, hdr->e_shoff)) - return 0; - - if (hdr->e_shnum != SHN_UNDEF) { - nsec = hdr->e_shnum; - } else { - Elf_Shdr sec0; - fpos_t pos; - - fgetpos(fp, &pos); - fread(buf, ELFHSZ, 1, fp); - fsetpos(fp, &pos); - - if (ferror(fp)) - return 0; - - unpack_shdr(ORDER(obj->type), buf, &sec0); - nsec = sec0.sh_size; - } - - if (nsec > SIZE_MAX) - return 0; - if (nsec == 0) - return 1; - - shdr = calloc(nsec, sizeof(*shdr)); - if (!shdr) - return 0; - elf->shdr = shdr; - elf->nsec = nsec; - - for (i = 0; i < nsec; i++) { - if (fread(buf, ELFSSZ, 1, fp) != 1) - return 0; - unpack_shdr(ORDER(obj->type), buf, &shdr[i]); - if (shdr[i].sh_type == SHT_SYMTAB) { - /* - * elf supports multiple symbol table, but we don't - * care and we only support one, and we reject elf - * files with more of one symbol table. - */ - if (elf->symtab) - return 0; - elf->symtab = &shdr[i]; - } - } - - return 1; -} - -static int -readsecstr(Obj *obj, FILE *fp) -{ - long idx; - size_t siz; - char *str; - Elf_Shdr *shdr; - Elf64 *elf; - Elf_Ehdr *hdr; - - elf = obj->data; - hdr = &elf->hdr; - idx = hdr->e_shstrndx; - if (idx == SHN_UNDEF) - return 0; - if (idx == SHN_XINDEX) { - if (hdr->e_shnum == 0) - return 0; - idx = elf->shdr[0].sh_link; - } - - if (idx >= hdr->e_shnum) - return 0; - shdr = &elf->shdr[idx]; - - if (shdr->sh_size > SIZE_MAX) - return 0; - - siz = shdr->sh_size; - if (siz == 0) - return 1; - str = malloc(siz); - if (!str) - return 0; - - elf->strtbl[SEC_STRTBL] = str; - elf->strsiz[SEC_STRTBL] = siz; - - if (!objpos(obj, fp, shdr->sh_offset)) - return 0; - if (fread(str, siz, 1, fp) != 1) - return 0; - - return 1; -} - -static int -readsymstr(Obj *obj, FILE *fp) -{ - long idx; - size_t siz; - char *str; - Elf64 *elf; - Elf_Shdr *shdr; - - elf = obj->data; - if (!elf->symtab) - return 1; - - idx = elf->symtab->sh_link; - if (idx >= elf->nsec) - return 0; - shdr = &elf->shdr[idx]; - - if (shdr->sh_size > SIZE_MAX) - return 0; - - siz = shdr->sh_size; - if (siz == 0) - return 1; - str = malloc(siz); - if (!str) - return 0; - - elf->strtbl[SYM_STRTBL] = str; - elf->strsiz[SYM_STRTBL] = siz; - - if (!objpos(obj, fp, shdr->sh_offset)) - return 0; - if (fread(str, siz, 1, fp) != 1) - return 0; - - return 1; -} - -static int -readsym(Obj *obj, FILE *fp) -{ - long nsym, i; - int sec; - Elf64 *elf; - Elf_Sym *syms; - Elf_Shdr *shdr; - unsigned char buf[ELFSSZ]; - - elf = obj->data; - if (!elf->symtab) - return 1; - shdr = elf->symtab; - - assert(shdr->sh_type == SHT_SYMTAB); - - nsym = shdr->sh_size / shdr->sh_entsize; - if (nsym >= SIZE_MAX) - return 0; - - syms = calloc(nsym, sizeof(*syms)); - if (!syms) - return 0; - elf->syms = syms; - elf->nsym = nsym; - - if (!objpos(obj, fp, shdr->sh_offset)) - return 0; - - for (i = 0; i < nsym; i++) { - if (fread(buf, ELFESZ, 1, fp) != 1) - return 0; - unpack_sym(ORDER(obj->type), buf, &syms[i]); - - sec = syms[i].st_shndx; - switch (sec) { - case SHN_XINDEX: - /* - * Elf supports an extension mechanism to allow - * indexes bigger than 4 bytes. We don't care - * and we reject elf files using this feature. - */ - return 0; - case SHN_UNDEF: - case SHN_ABS: - case SHN_COMMON: - break; - default: - if (sec >= elf->nsec) - return 0; - break; - } - } - - return 1; -} - -int -elf64read(Obj *obj, FILE *fp) -{ - if (!readhdr(obj, fp)) - return -1; - if (!readphdr(obj, fp)) - return -1; - if (!readshdr(obj, fp)) - return -1; - if (!readsym(obj, fp)) - return -1; - if (!readsecstr(obj, fp)) - return -1; - if (!readsymstr(obj, fp)) - return -1; - - return 0; -} diff --git a/src/libmach/elf64/elf64type.c b/src/libmach/elf64/elf64type.c @@ -1,21 +0,0 @@ -#include <stdio.h> -#include <string.h> - -#include <scc/mach.h> -#include <scc/elf64.h> - -#include "../libmach.h" -#include "fun.h" - -int -elf64type(char *name) -{ - struct arch *ap; - - for (ap = elf64archs; ap ->name; ap++) { - if (strcmp(ap->name, name) == 0) - return ap->type; - } - - return -1; -} diff --git a/src/libmach/elf64/fun.h b/src/libmach/elf64/fun.h @@ -1,17 +0,0 @@ -extern int elf64new(Obj *, int); -extern int elf64read(Obj *, FILE *); -extern int elf64setidx(long, char **, long *, FILE *); -extern int elf64getidx(long *, char ***, long **, FILE *); -extern int elf64pc2line(Obj *, unsigned long long , char *, int *); -extern int elf64strip(Obj *); -extern void elf64del(Obj *); -extern int elf64write(Obj *, Map *, FILE *); -extern int elf64probe(unsigned char *, char **); -extern int elf64type(char *); - -extern int elf64xsetidx(int long , char *[], long [], FILE *); -extern int elf64xgetidx(int, long *, char ***, long **, FILE *); - -extern Symbol *elf64getsym(Obj *, int *, Symbol *); -extern Section *elf64getsec(Obj *, int *, Section *); -extern Map *elf64loadmap(Obj *, FILE *); diff --git a/src/libmach/getindex.c b/src/libmach/getindex.c @@ -5,7 +5,7 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static int (*ops[NFORMATS])(long *, char ***, long **, FILE *) = { diff --git a/src/libmach/getsec.c b/src/libmach/getsec.c @@ -4,12 +4,12 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static Section *(*ops[NFORMATS])(Obj *, int *, Section *) = { [COFF32] = coff32getsec, - [ELF64] = elf64getsec, + [ELF] = elfgetsec, }; Section * diff --git a/src/libmach/getsym.c b/src/libmach/getsym.c @@ -4,12 +4,12 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static Symbol *(*ops[NFORMATS])(Obj *, int *, Symbol *) = { [COFF32] = coff32getsym, - [ELF64] = elf64getsym, + [ELF] = elfgetsym, }; Symbol * diff --git a/src/libmach/loadmap.c b/src/libmach/loadmap.c @@ -4,7 +4,7 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static Map *(*ops[NFORMATS])(Obj *, FILE *) = { diff --git a/src/libmach/newobj.c b/src/libmach/newobj.c @@ -7,12 +7,12 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static int (*ops[NFORMATS])(Obj *, int) = { [COFF32] = coff32new, - [ELF64] = elf64new, + [ELF] = elfnew, }; Obj * diff --git a/src/libmach/objprobe.c b/src/libmach/objprobe.c @@ -4,12 +4,12 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static int (*ops[NFORMATS])(unsigned char *, char **) = { [COFF32] = coff32probe, - [ELF64] = elf64probe, + [ELF] = elfprobe, }; int diff --git a/src/libmach/objtype.c b/src/libmach/objtype.c @@ -4,12 +4,12 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static int (*ops[NFORMATS])(char *) = { [COFF32] = coff32type, - [ELF64] = elf64type, + [ELF] = elftype, }; int diff --git a/src/libmach/pc2line.c b/src/libmach/pc2line.c @@ -4,7 +4,7 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static int (*ops[NFORMATS])(Obj *, unsigned long long , char *, int *) = { diff --git a/src/libmach/readobj.c b/src/libmach/readobj.c @@ -4,12 +4,12 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static int (*ops[NFORMATS])(Obj *, FILE *) = { [COFF32] = coff32read, - [ELF64] = elf64read, + [ELF] = elfread, }; int diff --git a/src/libmach/setindex.c b/src/libmach/setindex.c @@ -5,7 +5,7 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static int (*ops[NFORMATS])(long, char **, long *, FILE *) = { diff --git a/src/libmach/setsec.c b/src/libmach/setsec.c @@ -4,7 +4,7 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static Section *(*ops[NFORMATS])(Obj *, int *, Section *) = { diff --git a/src/libmach/setsym.c b/src/libmach/setsym.c @@ -4,7 +4,7 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static Symbol *(*ops[NFORMATS])(Obj *, int *, Symbol *) = { diff --git a/src/libmach/strip.c b/src/libmach/strip.c @@ -4,7 +4,7 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static int (*ops[NFORMATS])(Obj *) = { diff --git a/src/libmach/writeobj.c b/src/libmach/writeobj.c @@ -4,7 +4,7 @@ #include "libmach.h" -#include "elf64/fun.h" +#include "elf/fun.h" #include "coff32/fun.h" static int (*ops[NFORMATS])(Obj *, Map *, FILE *) = {