aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2019-12-27 12:51:09 -0800
committerRob Landley <rob@landley.net>2020-01-08 17:51:57 -0600
commita3da7efae55c6e2d3ff66fdc476b35f5bbec09e5 (patch)
tree8804f3e15453da20617837421d0ee374361f2616 /lib
parent8f1a7f921aec469ea85247c12f204d0891d7853b (diff)
downloadtoybox-a3da7efae55c6e2d3ff66fdc476b35f5bbec09e5.tar.gz
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/lib.c26
-rw-r--r--lib/lib.h1
2 files changed, 27 insertions, 0 deletions
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<ARRAY_LEN(types); i++) {
+ if (type==types[i].val) return types[i].name;
+ }
+ sprintf(libbuf, "unknown arch %d", type);
+ return libbuf;
+} \ No newline at end of file
diff --git a/lib/lib.h b/lib/lib.h
index 9e933401..e2914a09 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -271,6 +271,7 @@ void reset_env(struct passwd *p, int clear);
void loggit(int priority, char *format, ...);
unsigned tar_cksum(void *data);
int is_tar_header(void *pkt);
+char *elf_arch_name(int type);
#define HR_SPACE 1 // Space between number and units
#define HR_B 2 // Use "B" for single byte units