From a3da7efae55c6e2d3ff66fdc476b35f5bbec09e5 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 27 Dec 2019 12:51:09 -0800 Subject: Implement readelf(1). Basic readelf(1) implementation, with output close enough to the binutils version to be usable with scripts that expect the binutils version. This started as an implementation of nm(1) until I realized that I almost always want readelf instead, and that you actually have to do much of the work needed for readelf just to implement nm. Arguably nm (being part of POSIX) belongs in toybox while readelf doesn't. An argument could also be made that neither really belongs in toybox, belonging in a separate set of development tools (such as binutils or the LLVM binutils). Doesn't support most of the architecture-specific stuff, most notably relocations, but is aware of things like ARM exidx sections and the common register state notes in core dumps for the "big four" architectures: arm, arm64, x86, and x86-64. Doesn't support symbol versions (but probably should). Doesn't support section groups or the -t "section details" (which is a long form of -S "section headers" that I've never seen used in practice and which isn't part of -a). Doesn't support dumping unwind info or the hash table bucket histograms. Reuses the table of ELF architectures from file(1). Not fuzzed, but successfully parses all the ELF files in my Ubuntu 18.04 system's lib directories. Attempts to exit with an error when presented with an invalid ELF file rather than struggle on as binutils seems to. --- lib/lib.c | 26 ++++++++++++++++++++++++++ lib/lib.h | 1 + 2 files changed, 27 insertions(+) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index b14e2e9f..4eef1355 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -1409,3 +1409,29 @@ int is_tar_header(void *pkt) return i && tar_cksum(pkt) == i; } + +char *elf_arch_name(int type) +{ + int i; + // Values from include/linux/elf-em.h (plus arch/*/include/asm/elf.h) + // Names are linux/arch/ directory (sometimes before 32/64 bit merges) + struct {int val; char *name;} types[] = {{0x9026, "alpha"}, {93, "arc"}, + {195, "arcv2"}, {40, "arm"}, {183, "arm64"}, {0x18ad, "avr32"}, + {247, "bpf"}, {106, "blackfin"}, {140, "c6x"}, {23, "cell"}, {76, "cris"}, + {252, "csky"}, {0x5441, "frv"}, {46, "h8300"}, {164, "hexagon"}, + {50, "ia64"}, {88, "m32r"}, {0x9041, "m32r"}, {4, "m68k"}, {174, "metag"}, + {189, "microblaze"}, {0xbaab, "microblaze-old"}, {8, "mips"}, + {10, "mips-old"}, {89, "mn10300"}, {0xbeef, "mn10300-old"}, {113, "nios2"}, + {92, "openrisc"}, {0x8472, "openrisc-old"}, {15, "parisc"}, {20, "ppc"}, + {21, "ppc64"}, {243, "riscv"}, {22, "s390"}, {0xa390, "s390-old"}, + {135, "score"}, {42, "sh"}, {2, "sparc"}, {18, "sparc8+"}, {43, "sparc9"}, + {188, "tile"}, {191, "tilegx"}, {3, "386"}, {6, "486"}, {62, "x86-64"}, + {94, "xtensa"}, {0xabc7, "xtensa-old"} + }; + + for (i = 0; i