diff options
author | Mike Frysinger <vapier@gentoo.org> | 2009-06-28 13:00:02 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-06-28 13:00:02 -0400 |
commit | 0d1ced74e44060d09ff794e28cde0924054c3756 (patch) | |
tree | d75a26eded8ad5dec5df1ff2727a0635b4a14380 /utils | |
parent | 0e605ccee71b9072671b7dfe93a4b82400277e60 (diff) |
utils: punt readelf
This miniature version of readelf has never been terribly useful and has
caused significantly more headaches in its maintenance, so punt it.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'utils')
-rw-r--r-- | utils/Makefile.in | 7 | ||||
-rw-r--r-- | utils/readelf.c | 346 |
2 files changed, 1 insertions, 352 deletions
diff --git a/utils/Makefile.in b/utils/Makefile.in index 163b5a665..446973ea3 100644 --- a/utils/Makefile.in +++ b/utils/Makefile.in @@ -32,8 +32,6 @@ endif CFLAGS-ldd := $(CFLAGS-utils-shared) -CFLAGS-readelf := $(CFLAGS-utils-shared) - # Need CFLAGS-utils explicitly, because the source file is not located in utils CFLAGS-iconv := $(CFLAGS-utils) \ $(CFLAGS-utils-shared) \ @@ -56,7 +54,6 @@ BUILD_CFLAGS-utils := \ $(LDSO_CACHE_SUPPORT) BUILD_CFLAGS-ldconfig.host := $(BUILD_CFLAGS-utils) BUILD_CFLAGS-ldd.host := $(BUILD_CFLAGS-utils) -BUILD_CFLAGS-readelf.host := $(BUILD_CFLAGS-utils) # Rules @@ -67,7 +64,6 @@ utils_OUT := $(top_builddir)utils DEPS-ldconfig := $(utils_DIR)/chroot_realpath.c DEPS-ldconfig.host := $(DEPS-ldconfig) -utils_OBJ := readelf ifeq ($(HAVE_SHARED),y) utils_OBJ += ldconfig ldd endif @@ -107,7 +103,6 @@ install-y += utils_install # This installs both utils and hostutils, so doesn't depend on either. utils_install: $(addsuffix $(DOTHOST), $(utils_OBJ) $(utils_ICONV_OBJ) $(utils_LOCALE_OBJ)) - $(Q)$(INSTALL) -D -m 755 $(utils_OUT)/readelf$(DOTHOST) $(PREFIX)$(DEVEL_PREFIX)bin/readelf ifeq ($(HAVE_SHARED),y) $(Q)$(INSTALL) -D -m 755 $(utils_OUT)/ldd$(DOTHOST) $(PREFIX)$(DEVEL_PREFIX)bin/ldd $(Q)$(INSTALL) -D -m 755 $(utils_OUT)/ldconfig$(DOTHOST) $(PREFIX)$(RUNTIME_PREFIX)sbin/ldconfig @@ -121,6 +116,6 @@ endif objclean-y += utils_clean utils_clean: - $(do_rm) $(addprefix $(utils_OUT)/, ldconfig ldd readelf iconv locale *.host) + $(do_rm) $(addprefix $(utils_OUT)/, ldconfig ldd iconv locale *.host) # This is a hack.. $(Q)$(RM) $(utils_OUT)/.*.dep diff --git a/utils/readelf.c b/utils/readelf.c deleted file mode 100644 index 191242b2f..000000000 --- a/utils/readelf.c +++ /dev/null @@ -1,346 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * A small little readelf implementation for uClibc - * - * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> - * - * Several functions in this file (specifically, elf_find_section_type(), - * elf_find_phdr_type(), and elf_find_dynamic(), were stolen from elflib.c from - * elfvector (http://www.BitWagon.com/elfvector.html) by John F. Reiser - * <jreiser@BitWagon.com>, which is copyright 2000 BitWagon Software LLC - * (GPL2). - * - * Licensed under GPLv2 or later - */ - -#include "porting.h" - -static int byteswap; -static __inline__ uint32_t byteswap32_to_host(uint32_t value) -{ - if (byteswap==1) { - return(bswap_32(value)); - } else { - return(value); - } -} -static __inline__ uint64_t byteswap64_to_host(uint64_t value) -{ - if (byteswap==1) { - return(bswap_64(value)); - } else { - return(value); - } -} -#if __WORDSIZE == 64 -# define byteswap_to_host(x) byteswap64_to_host(x) -#else -# define byteswap_to_host(x) byteswap32_to_host(x) -#endif - -static ElfW(Shdr) * elf_find_section_type( uint32_t key, ElfW(Ehdr) *ehdr) -{ - int j; - ElfW(Shdr) *shdr = (ElfW(Shdr) *)(ehdr->e_shoff + (char *)ehdr); - for (j = ehdr->e_shnum; --j>=0; ++shdr) { - if (key==byteswap32_to_host(shdr->sh_type)) { - return shdr; - } - } - return NULL; -} - -static ElfW(Phdr) * elf_find_phdr_type( uint32_t type, ElfW(Ehdr) *ehdr) -{ - int j; - ElfW(Phdr) *phdr = (ElfW(Phdr) *)(ehdr->e_phoff + (char *)ehdr); - for (j = ehdr->e_phnum; --j>=0; ++phdr) { - if (type==byteswap32_to_host(phdr->p_type)) { - return phdr; - } - } - return NULL; -} - -/* Returns value if return_val==1, ptr otherwise */ -static void * elf_find_dynamic( int64_t const key, ElfW(Dyn) *dynp, - ElfW(Ehdr) *ehdr, int return_val) -{ - ElfW(Phdr) *pt_text = elf_find_phdr_type(PT_LOAD, ehdr); - ElfW(Addr) tx_reloc = byteswap_to_host(pt_text->p_vaddr) - byteswap_to_host(pt_text->p_offset); - for (; DT_NULL!=byteswap_to_host(dynp->d_tag); ++dynp) { - if (key == byteswap_to_host(dynp->d_tag)) { - if (return_val == 1) - return (void *)byteswap_to_host(dynp->d_un.d_val); - else - return (void *)(byteswap_to_host(dynp->d_un.d_val) - tx_reloc + (char *)ehdr ); - } - } - return NULL; -} - -static int check_elf_header(ElfW(Ehdr) *const ehdr) -{ - if (!ehdr || *(uint32_t*)ehdr != ELFMAG_U32 - || (ehdr->e_ident[EI_CLASS] != ELFCLASS32 - && ehdr->e_ident[EI_CLASS] != ELFCLASS64) - || ehdr->e_ident[EI_VERSION] != EV_CURRENT - ) { - return 1; - } - - /* Check if the target endianness matches the host's endianness */ - byteswap = 0; - if (UCLIBC_ENDIAN_HOST == UCLIBC_ENDIAN_LITTLE) { - if (ehdr->e_ident[5] == ELFDATA2MSB) - byteswap = 1; - } else if (UCLIBC_ENDIAN_HOST == UCLIBC_ENDIAN_BIG) { - if (ehdr->e_ident[5] == ELFDATA2LSB) - byteswap = 1; - } - /* Be very lazy, and only byteswap the stuff we use */ - if (byteswap) { - ehdr->e_type = bswap_16(ehdr->e_type); - ehdr->e_machine = bswap_16(ehdr->e_machine); - ehdr->e_phoff = byteswap_to_host(ehdr->e_phoff); - ehdr->e_shoff = byteswap_to_host(ehdr->e_shoff); - ehdr->e_phnum = bswap_16(ehdr->e_phnum); - ehdr->e_shnum = bswap_16(ehdr->e_shnum); - } - return 0; -} - - -static void describe_elf_hdr(ElfW(Ehdr)* ehdr) -{ - char *tmp, *tmp1; - - switch (ehdr->e_type) { - case ET_NONE: tmp = "None"; tmp1 = "NONE"; break; - case ET_REL: tmp = "Relocatable File"; tmp1 = "REL"; break; - case ET_EXEC: tmp = "Executable file"; tmp1 = "EXEC"; break; - case ET_DYN: tmp = "Shared object file"; tmp1 = "DYN"; break; - case ET_CORE: tmp = "Core file"; tmp1 = "CORE"; break; - default: - tmp = tmp1 = "Unknown"; - } - printf( "Type:\t\t%s (%s)\n", tmp1, tmp); - - switch (ehdr->e_machine) { - case EM_NONE: tmp="No machine"; break; - case EM_M32: tmp="AT&T WE 32100"; break; - case EM_SPARC: tmp="SUN SPARC"; break; - case EM_386: tmp="Intel 80386"; break; - case EM_68K: tmp="Motorola m68k family"; break; - case EM_88K: tmp="Motorola m88k family"; break; - case EM_486: tmp="Intel 80486"; break; - case EM_860: tmp="Intel 80860"; break; - case EM_MIPS: tmp="MIPS R3000 big-endian"; break; - case EM_S370: tmp="IBM System/370"; break; - case EM_MIPS_RS3_LE: tmp="MIPS R3000 little-endian"; break; - case EM_OLD_SPARCV9: tmp="Sparc v9 (old)"; break; - case EM_PARISC: tmp="HPPA"; break; - /*case EM_PPC_OLD: tmp="Power PC (old)"; break; conflicts with EM_VPP500 */ - case EM_SPARC32PLUS: tmp="Sun's v8plus"; break; - case EM_960: tmp="Intel 80960"; break; - case EM_PPC: tmp="PowerPC"; break; - case EM_PPC64: tmp="PowerPC 64-bit"; break; - case EM_V800: tmp="NEC V800 series"; break; - case EM_FR20: tmp="Fujitsu FR20"; break; - case EM_RH32: tmp="TRW RH-32"; break; - case EM_MCORE: tmp="MCORE"; break; - case EM_ARM: tmp="ARM"; break; - case EM_FAKE_ALPHA: tmp="Digital Alpha"; break; - case EM_SH: tmp="Renesas SH"; break; - case EM_SPARCV9: tmp="SPARC v9 64-bit"; break; - case EM_TRICORE: tmp="Siemens Tricore"; break; - case EM_ARC: tmp="Argonaut RISC Core"; break; - case EM_H8_300: tmp="Renesas H8/300"; break; - case EM_H8_300H: tmp="Renesas H8/300H"; break; - case EM_H8S: tmp="Renesas H8S"; break; - case EM_H8_500: tmp="Renesas H8/500"; break; - case EM_IA_64: tmp="Intel Merced"; break; - case EM_MIPS_X: tmp="Stanford MIPS-X"; break; - case EM_COLDFIRE: tmp="Motorola Coldfire"; break; - case EM_68HC12: tmp="Motorola M68HC12"; break; - case EM_ALPHA: tmp="Alpha"; break; - case EM_CYGNUS_D10V: - case EM_D10V: tmp="Mitsubishi D10V"; break; - case EM_CYGNUS_D30V: - case EM_D30V: tmp="Mitsubishi D30V"; break; - case EM_CYGNUS_M32R: - case EM_M32R: tmp="Renesas M32R (formerly Mitsubishi M32r)"; break; - case EM_CYGNUS_V850: - case EM_V850: tmp="NEC v850"; break; - case EM_CYGNUS_MN10300: - case EM_MN10300: tmp="Matsushita MN10300"; break; - case EM_CYGNUS_MN10200: - case EM_MN10200: tmp="Matsushita MN10200"; break; - case EM_CYGNUS_FR30: - case EM_FR30: tmp="Fujitsu FR30"; break; - case EM_CYGNUS_FRV: - case EM_PJ_OLD: - case EM_PJ: tmp="picoJava"; break; - case EM_MMA: tmp="Fujitsu MMA Multimedia Accelerator"; break; - case EM_PCP: tmp="Siemens PCP"; break; - case EM_NCPU: tmp="Sony nCPU embeeded RISC"; break; - case EM_NDR1: tmp="Denso NDR1 microprocessor"; break; - case EM_STARCORE: tmp="Motorola Start*Core processor"; break; - case EM_ME16: tmp="Toyota ME16 processor"; break; - case EM_ST100: tmp="STMicroelectronic ST100 processor"; break; - case EM_TINYJ: tmp="Advanced Logic Corp. Tinyj emb.fam"; break; - case EM_FX66: tmp="Siemens FX66 microcontroller"; break; - case EM_ST9PLUS: tmp="STMicroelectronics ST9+ 8/16 mc"; break; - case EM_ST7: tmp="STmicroelectronics ST7 8 bit mc"; break; - case EM_68HC16: tmp="Motorola MC68HC16 microcontroller"; break; - case EM_68HC11: tmp="Motorola MC68HC11 microcontroller"; break; - case EM_68HC08: tmp="Motorola MC68HC08 microcontroller"; break; - case EM_68HC05: tmp="Motorola MC68HC05 microcontroller"; break; - case EM_SVX: tmp="Silicon Graphics SVx"; break; - case EM_ST19: tmp="STMicroelectronics ST19 8 bit mc"; break; - case EM_VAX: tmp="Digital VAX"; break; - case EM_AVR_OLD: - case EM_AVR: tmp="Atmel AVR 8-bit microcontroller"; break; - case EM_CRIS: tmp="Axis Communications 32-bit embedded processor"; break; - case EM_JAVELIN: tmp="Infineon Technologies 32-bit embedded processor"; break; - case EM_FIREPATH: tmp="Element 14 64-bit DSP Processor"; break; - case EM_ZSP: tmp="LSI Logic 16-bit DSP Processor"; break; - case EM_MMIX: tmp="Donald Knuth's educational 64-bit processor"; break; - case EM_HUANY: tmp="Harvard University machine-independent object files"; break; - case EM_PRISM: tmp="SiTera Prism"; break; - case EM_X86_64: tmp="AMD x86-64 architecture"; break; - case EM_S390_OLD: - case EM_S390: tmp="IBM S390"; break; - case EM_XSTORMY16: tmp="Sanyo Xstormy16 CPU core"; break; - case EM_OPENRISC: - case EM_OR32: tmp="OpenRISC"; break; - case EM_CRX: tmp="National Semiconductor CRX microprocessor"; break; - case EM_DLX: tmp="OpenDLX"; break; - case EM_IP2K_OLD: - case EM_IP2K: tmp="Ubicom IP2xxx 8-bit microcontrollers"; break; - case EM_IQ2000: tmp="Vitesse IQ2000"; break; - case EM_XTENSA_OLD: - case EM_XTENSA: tmp="Tensilica Xtensa Processor"; break; - case EM_M32C: tmp="Renesas M32c"; break; - case EM_MT: tmp="Morpho Techologies MT processor"; break; - case EM_BLACKFIN: tmp="Analog Devices Blackfin"; break; - case EM_NIOS32: tmp="Altera Nios 32"; break; - case EM_ALTERA_NIOS2: tmp="Altera Nios II"; break; - case EM_VPP500: tmp="Fujitsu VPP500"; break; - case EM_PDSP: tmp="Sony DSP Processor"; break; - default: tmp="unknown"; - } - printf( "Machine:\t%s\n", tmp); - - switch (ehdr->e_ident[EI_CLASS]) { - case ELFCLASSNONE: tmp = "Invalid class"; break; - case ELFCLASS32: tmp = "ELF32"; break; - case ELFCLASS64: tmp = "ELF64"; break; - default: tmp = "Unknown"; - } - printf( "Class:\t\t%s\n", tmp); - - switch (ehdr->e_ident[EI_DATA]) { - case ELFDATANONE: tmp = "Invalid data encoding"; break; - case ELFDATA2LSB: tmp = "2's complement, little endian"; break; - case ELFDATA2MSB: tmp = "2's complement, big endian"; break; - default: tmp = "Unknown"; - } - printf( "Data:\t\t%s\n", tmp); - - printf( "Version:\t%d %s\n", ehdr->e_ident[EI_VERSION], - (ehdr->e_ident[EI_VERSION]==EV_CURRENT)? - "(current)" : "(unknown: %lx)"); - - switch (ehdr->e_ident[EI_OSABI]) { - case ELFOSABI_SYSV: tmp ="UNIX - System V"; break; - case ELFOSABI_HPUX: tmp ="UNIX - HP-UX"; break; - case ELFOSABI_NETBSD: tmp ="UNIX - NetBSD"; break; - case ELFOSABI_LINUX: tmp ="UNIX - Linux"; break; - case ELFOSABI_HURD: tmp ="GNU/Hurd"; break; - case ELFOSABI_SOLARIS: tmp ="UNIX - Solaris"; break; - case ELFOSABI_AIX: tmp ="UNIX - AIX"; break; - case ELFOSABI_IRIX: tmp ="UNIX - IRIX"; break; - case ELFOSABI_FREEBSD: tmp ="UNIX - FreeBSD"; break; - case ELFOSABI_TRU64: tmp ="UNIX - TRU64"; break; - case ELFOSABI_MODESTO: tmp ="Novell - Modesto"; break; - case ELFOSABI_OPENBSD: tmp ="UNIX - OpenBSD"; break; - case ELFOSABI_STANDALONE: tmp ="Standalone App"; break; - case ELFOSABI_ARM: tmp ="ARM"; break; - default: tmp = "Unknown"; - } - printf( "OS/ABI:\t\t%s\n", tmp); - - printf( "ABI Version:\t%d\n", ehdr->e_ident[EI_ABIVERSION]); -} - -static void list_needed_libraries(ElfW(Dyn)* dynamic, char *strtab) -{ - ElfW(Dyn) *dyns; - - printf("Dependancies:\n"); - for (dyns=dynamic; byteswap_to_host(dyns->d_tag)!=DT_NULL; ++dyns) { - if (dyns->d_tag == DT_NEEDED) { - printf("\t%s\n", (char*)strtab + byteswap_to_host(dyns->d_un.d_val)); - } - } -} - -static void describe_elf_interpreter(ElfW(Ehdr)* ehdr) -{ - ElfW(Phdr) *phdr; - phdr = elf_find_phdr_type(PT_INTERP, ehdr); - if (phdr) { - printf("Interpreter:\t%s\n", (char*)ehdr + byteswap_to_host(phdr->p_offset)); - } -} - -int main( int argc, char** argv) -{ - /* map the .so, and locate interesting pieces */ - char *dynstr; - char *thefilename = argv[1]; - FILE *thefile; - struct stat statbuf; - ElfW(Ehdr) *ehdr = 0; - ElfW(Shdr) *dynsec; - ElfW(Dyn) *dynamic; - - if (argc < 2 || !thefilename) { - fprintf(stderr, "No filename specified.\n"); - exit(EXIT_FAILURE); - } - if (!(thefile = fopen(thefilename, "r"))) { - perror(thefilename); - exit(EXIT_FAILURE); - } - if (fstat(fileno(thefile), &statbuf) < 0) { - perror(thefilename); - exit(EXIT_FAILURE); - } - - if ((size_t)statbuf.st_size < sizeof(ElfW(Ehdr))) - goto foo; - - /* mmap the file to make reading stuff from it effortless */ - ehdr = (ElfW(Ehdr) *)mmap(0, statbuf.st_size, - PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(thefile), 0); - -foo: - /* Check if this looks legit */ - if (check_elf_header(ehdr)) { - fprintf(stderr, "This does not appear to be an ELF file.\n"); - exit(EXIT_FAILURE); - } - describe_elf_hdr(ehdr); - describe_elf_interpreter(ehdr); - - dynsec = elf_find_section_type(SHT_DYNAMIC, ehdr); - if (dynsec) { - dynamic = (ElfW(Dyn)*)(byteswap_to_host(dynsec->sh_offset) + (char *)ehdr); - dynstr = (char *)elf_find_dynamic(DT_STRTAB, dynamic, ehdr, 0); - list_needed_libraries(dynamic, dynstr); - } - - return 0; -} |