scc

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

commit f2f60fcbe4ac4096f4e0681f498c21167ac30166
parent dbe2170b3140a6719b908f380c6a36594f6f4731
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 24 Jan 2025 10:03:45 +0100

objdump: Add support for elf

Diffstat:
Minclude/bits/scc/mach.h | 1-
Msrc/cmd/scc-objdump/Makefile | 1+
Msrc/cmd/scc-objdump/coff32.c | 14++++++++++++++
Asrc/cmd/scc-objdump/elf64.c | 734+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/cmd/scc-objdump/main.c | 26+++++++++++++++++++++++++-
Msrc/cmd/scc-objdump/objdump.h | 7+++++++
Msrc/libmach/coff32/coff32getsec.c | 1-
Msrc/libmach/elf64/elf64getsec.c | 15++++++++-------
8 files changed, 789 insertions(+), 10 deletions(-)

diff --git a/include/bits/scc/mach.h b/include/bits/scc/mach.h @@ -98,7 +98,6 @@ struct section { unsigned long long size; unsigned long long offset; - unsigned long nreloc; unsigned flags; int index; int align; diff --git a/src/cmd/scc-objdump/Makefile b/src/cmd/scc-objdump/Makefile @@ -6,6 +6,7 @@ include $(PROJECTDIR)/scripts/rules.mk OBJS =\ main.o\ coff32.o\ + elf64.o\ TARGET = scc-objdump MORE_LDLIBS = -lmach -lscc diff --git a/src/cmd/scc-objdump/coff32.c b/src/cmd/scc-objdump/coff32.c @@ -6,6 +6,15 @@ #include "objdump.h" +int +coff32hasrelloc(Obj *obj, Section *sec) +{ + struct coff32 *coff = obj->data; + SCNHDR *scn = &coff->scns[sec->index]; + + return scn->s_nrelloc != 0; +} + void coff32syms(Obj *obj) { @@ -13,6 +22,11 @@ coff32syms(Obj *obj) struct coff32 *coff = obj->data; FILHDR *hdr = &coff->hdr; + if (hdr->f_nsyms == 0) { + puts("no symbols"); + return; + } + for (i = 0; i < hdr->f_nsyms; i++) { SYMENT *ent; AUXENT *aux; diff --git a/src/cmd/scc-objdump/elf64.c b/src/cmd/scc-objdump/elf64.c @@ -0,0 +1,734 @@ +#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 @@ -90,6 +90,9 @@ dumpfhdr(Obj *obj, char *fmt) case COFF32: coff32fhdr(obj, &start, &f); break; + case ELF64: + elf64fhdr(obj, &start, &f); + break; default: error("unknown fhdr binary format"); return; @@ -128,6 +131,21 @@ selected(char *secname) return 0; } +static int +hasrelloc(Obj *obj, Section *sec) +{ + switch (FORMAT(obj->type)) { + case COFF32: + coff32hasrelloc(obj, sec); + break; + case ELF64: + elf64hasrelloc(obj, sec); + break; + default: + return 0; + } +} + static void dumpscns(Obj *obj) { @@ -168,7 +186,7 @@ dumpscns(Obj *obj) debug = sec.type == 'N'; setflag(&f, flags & SALLOC, SEC_ALLOC); setflag(&f, flags & SLOAD, SEC_LOAD); - setflag(&f, (flags & SRELOC) && sec.nreloc > 0, SEC_RELOC); + setflag(&f, hasrelloc(obj, &sec), SEC_RELOC); setflag(&f, (flags & SWRITE) == 0 && !debug, SEC_READONLY); setflag(&f, flags & SEXEC, SEC_CODE); setflag(&f, (flags & (SEXEC|SLOAD)) == SLOAD, SEC_DATA); @@ -185,6 +203,9 @@ dumpscns(Obj *obj) case COFF32: coff32scns(obj); break; + case ELF64: + elf64scns(obj); + break; default: error("unknown fhdr binary format"); } @@ -253,6 +274,9 @@ dumpsyms(Obj *obj) case COFF32: coff32syms(obj); break; + case ELF64: + elf64syms(obj); + break; default: error("unknown symbol binary format"); } diff --git a/src/cmd/scc-objdump/objdump.h b/src/cmd/scc-objdump/objdump.h @@ -33,6 +33,13 @@ struct flags { extern void coff32syms(Obj *); extern void coff32scns(Obj *); 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 *); /* main.c */ extern void error(char *, ...); diff --git a/src/libmach/coff32/coff32getsec.c b/src/libmach/coff32/coff32getsec.c @@ -85,7 +85,6 @@ coff32getsec(Obj *obj, int *idx, Section *sec) sec->base = scn->s_vaddr; sec->load = scn->s_paddr; sec->offset = scn->s_scnptr; - sec->nreloc = scn->s_nrelloc; sec->type = type; sec->flags = sflags; sec->align = 4; diff --git a/src/libmach/elf64/elf64getsec.c b/src/libmach/elf64/elf64getsec.c @@ -15,8 +15,15 @@ elf64getsec(Obj *obj, int *idx, Section *sec) Elf_Ehdr *hdr = &elf->hdr; Elf_Shdr *shdr; - if (n >= elf->nsec) + 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; @@ -49,11 +56,6 @@ elf64getsec(Obj *obj, int *idx, Section *sec) * We cannot differentiate between load and base address * in a section, while we can use the physical address * for that when dealing with segments. - * Also, we don't have an easy way to know the number of - * relocations affecting one section. To know that, we - * have to run over the relocation sections and find one - * with the sh_link pointing to this section. Maybe, - * we should just remove the nrelloc field. */ if (n == SHN_UNDEF) sec->name = "*UND*"; @@ -65,7 +67,6 @@ elf64getsec(Obj *obj, int *idx, Section *sec) sec->base = shdr->sh_addr; sec->load = shdr->sh_addr; sec->offset = shdr->sh_offset; - sec->nreloc = 0; sec->type = stype; sec->flags = sflags; sec->align = shdr->sh_addralign;