diff options
-rw-r--r-- | Makefile.in | 9 | ||||
-rw-r--r-- | extra/locale/gen_wc8bit.c | 25 | ||||
-rwxr-xr-x | extra/scripts/install_kernel_headers.sh | 85 | ||||
-rw-r--r-- | libc/Makefile.in | 4 | ||||
-rw-r--r-- | libc/misc/wchar/wchar.c | 2 | ||||
-rw-r--r-- | libc/string/arm/_memcpy.S | 5 | ||||
-rw-r--r-- | libc/sysdeps/linux/arm/aeabi_lcsts.c | 15 | ||||
-rw-r--r-- | libc/sysdeps/linux/arm/setjmp.S | 2 | ||||
-rw-r--r-- | libc/sysdeps/linux/sh/Makefile.arch | 2 | ||||
-rw-r--r-- | libc/sysdeps/linux/sh/cacheflush.c | 15 | ||||
-rw-r--r-- | librt/shm.c | 101 | ||||
-rw-r--r-- | test/librt/Makefile | 6 | ||||
-rw-r--r-- | test/librt/shmtest.c | 102 | ||||
-rw-r--r-- | utils/.gitignore | 4 | ||||
-rw-r--r-- | utils/Makefile.in | 7 | ||||
-rw-r--r-- | utils/readelf.c | 346 |
16 files changed, 276 insertions, 454 deletions
diff --git a/Makefile.in b/Makefile.in index 2a7674543..381c09999 100644 --- a/Makefile.in +++ b/Makefile.in @@ -181,10 +181,6 @@ $(LOCAL_INSTALL_PATH): $(Q)$(MAKE) PREFIX=$(shell pwd)/$(LOCAL_INSTALL_PATH) RUNTIME_PREFIX=/ \ DEVEL_PREFIX=/usr/ \ HOSTCC="$(HOSTCC)" \ - install_kernel_headers - $(Q)$(MAKE) PREFIX=$(shell pwd)/$(LOCAL_INSTALL_PATH) RUNTIME_PREFIX=/ \ - DEVEL_PREFIX=/usr/ \ - HOSTCC="$(HOSTCC)" \ install install: install_runtime install_dev @@ -195,11 +191,6 @@ RUNTIME_PREFIX_LIB_FROM_DEVEL_PREFIX_LIB=$(shell $(top_srcdir)extra/scripts/rela $(top_builddir)extra/scripts/unifdef: $(top_srcdir)extra/scripts/unifdef.c $(hcompile.u) -# Installs kernel header files (linux/*, asm/*, asm-generic/*). -install_kernel_headers: headers - top_builddir=$(top_builddir) \ - $(top_srcdir)extra/scripts/install_kernel_headers.sh include $(PREFIX)$(DEVEL_PREFIX)include - # Installs header files. install_headers: headers $(top_builddir)extra/scripts/unifdef $(INSTALL) -d $(PREFIX)$(DEVEL_PREFIX)include diff --git a/extra/locale/gen_wc8bit.c b/extra/locale/gen_wc8bit.c index 418a1ac9d..126cd1ace 100644 --- a/extra/locale/gen_wc8bit.c +++ b/extra/locale/gen_wc8bit.c @@ -98,8 +98,31 @@ int main(int argc, char **argv) int total_size = 0; if (!setlocale(LC_CTYPE, "en_US.UTF-8")) { - printf("setlocale(LC_CTYPE,\"en_US.UTF-8\") failed!\n"); + /* Silly foreigners disabling en_US locales */ + FILE *fp = popen("locale -a", "r"); + if (!fp) + goto locale_failure; + + while (!feof(fp)) { + char buf[256]; + size_t len; + + if (fgets(buf, sizeof(buf) - 10, fp) == NULL) + goto locale_failure; + + len = strlen(buf); + if (buf[len - 1] == '\n') + buf[--len] = '\0'; + strcat(buf, ".UTF8"); + if (setlocale(LC_CTYPE, buf)) + goto locale_success; + } + + locale_failure: + printf("could not find a UTF8 locale ... please enable en_US.UTF-8\n"); return EXIT_FAILURE; + locale_success: + pclose(fp); } if (!(out = fopen("c8tables.h","w"))) { diff --git a/extra/scripts/install_kernel_headers.sh b/extra/scripts/install_kernel_headers.sh deleted file mode 100755 index 539974af0..000000000 --- a/extra/scripts/install_kernel_headers.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/sh -# Parameters: -# $1 = source dir -# $2 = dst dir -# $top_builddir = well you guessed it - -die_if_not_dir() -{ - local dir - for dir in "$@"; do - test -d "$dir" && continue - echo "Error: '$dir' is not a directory" - exit 1 - done -} - - -# Ensure that created dirs/files have 755/644 perms -umask 022 - - -# Sanity tests -die_if_not_dir "$1" -mkdir -p "$2" 2>/dev/null -die_if_not_dir "$2" -die_if_not_dir "$top_builddir" - - -# Just copy (no sanitization) some kernel headers. -eval `grep ^KERNEL_HEADERS "$top_builddir/.config"` -if ! test "$KERNEL_HEADERS" \ -|| ! test -d "$KERNEL_HEADERS/asm" \ -|| ! test -d "$KERNEL_HEADERS/linux" \ -; then - echo "Error: '$KERNEL_HEADERS' is not a directory containing kernel headers." - echo "Check KERNEL_HEADERS= in your .config file." - exit 1 -fi -# Do the copying only if src and dst dirs are not the same. -# Be thorough: do not settle just for textual compare, -# and guard against "pwd" being handled as shell builtin. -# Double quoting looks weird, but it works (even bbox ash too). -if test "`(cd "$KERNEL_HEADERS"; env pwd)`" != "`(cd "$2"; env pwd)`"; then - # NB: source or target files and directories may be symlinks, - # and for all we know, good reasons. - # We must work correctly in these cases. This includes "do not replace - # target symlink with real directory" rule. So, no rm -rf here please. - mkdir -p "$2/asm" 2>/dev/null - mkdir -p "$2/linux" 2>/dev/null - # Exists, but is not a dir? That's bad, bail out - die_if_not_dir "$2/asm" "$2/linux" - # cp -HL creates regular destination files even if sources are symlinks. - # This is intended. - # (NB: you need busybox 1.11.x for this. earlier ones are slightly buggy) - cp -RHL "$KERNEL_HEADERS/asm"/* "$2/asm" || exit 1 - cp -RHL "$KERNEL_HEADERS/linux"/* "$2/linux" || exit 1 - # Linux 2.4 doesn't have it - if test -d "$KERNEL_HEADERS/asm-generic"; then - mkdir -p "$2/asm-generic" 2>/dev/null - die_if_not_dir "$2/asm-generic" - cp -RHL "$KERNEL_HEADERS/asm-generic"/* "$2/asm-generic" || exit 1 - fi - # For paranoid reasons, we use explicit list of directories - # which may be found in kernel's "sanitized headers" directory after - # "make defconfig; make headers_install" was run in kernel tree. - # List last updated for linux-2.6.27: - for dir in drm mtd rdma sound video; do - if test -d "$KERNEL_HEADERS/$dir"; then - mkdir -p "$2/$dir" 2>/dev/null - die_if_not_dir "$2/$dir" - cp -RHL "$KERNEL_HEADERS/$dir"/* "$2/$dir" || exit 1 - fi - done - if ! test -f "$2/linux/version.h"; then - echo "Warning: '$KERNEL_HEADERS/linux/version.h' is not found" - echo "in kernel headers directory specified in .config." - echo "Some programs won't like that. Consider fixing it by hand." - fi -fi - - -# Fix mode/owner bits -cd "$2" || exit 1 -chmod -R u=rwX,go=rX . >/dev/null 2>&1 -chown -R `id | sed 's/^uid=\([0-9]*\).*gid=\([0-9]*\).*$/\1:\2/'` . >/dev/null 2>&1 diff --git a/libc/Makefile.in b/libc/Makefile.in index 16768db11..7297e9284 100644 --- a/libc/Makefile.in +++ b/libc/Makefile.in @@ -54,7 +54,7 @@ lib-gdb-y += $(top_builddir)lib/libc.gdb lib-so-y += $(libc.depend) objclean-y += libc_clean -OUTPUT_FORMAT = $(CC) $(CFLAGS) -Wl,--verbose 2>&1 | $(SED) -n 's/^OUTPUT_FORMAT("\([^"]*\)",.*/OUTPUT_FORMAT ( \1 )/p' +OUTPUT_FORMAT = $(CC) $(CFLAGS) -Wl,--verbose 2>&1 | $(SED) -n '/OUTPUT_FORMAT/,/)/p' ifeq ($(DOMULTI),n) $(libc.depend): $(libc_OUT)/libc_so.a $(LIBS-libc.so) @@ -65,7 +65,7 @@ $(libc.depend): $(libc_OUT)/libc.oS $(libc-nomulti-y:.o=.oS) | $(LIBS-libc.so) endif $(Q)$(RM) $@ $(Q)cp $(top_srcdir)extra/scripts/format.lds $@ - $(Q)echo "$(shell $(OUTPUT_FORMAT))" >> $@ + $(Q)$(OUTPUT_FORMAT) >> $@ ifeq ($(COMPAT_ATEXIT),y) $(Q)echo "GROUP ( $(NONSHARED_LIBNAME) $(SHARED_MAJORNAME) $(ASNEEDED) )" >> $@ else diff --git a/libc/misc/wchar/wchar.c b/libc/misc/wchar/wchar.c index 1ca4600b4..099ac3935 100644 --- a/libc/misc/wchar/wchar.c +++ b/libc/misc/wchar/wchar.c @@ -1679,7 +1679,7 @@ int main(int argc, char **argv) goto USAGE; } if ((ic = iconv_open(opts[0],opts[1])) == ((iconv_t)(-1))) { - error_msg( "unsupported codeset in %s -> %s conversion\n", opts[0], opts[1]); + error_msg( "unsupported codeset in %s -> %s conversion\n", opts[1], opts[0]); } if (opts[3]) { /* -c */ ((_UC_iconv_t *) ic)->skip_invalid_input = 1; diff --git a/libc/string/arm/_memcpy.S b/libc/string/arm/_memcpy.S index 103580a0c..b26080d02 100644 --- a/libc/string/arm/_memcpy.S +++ b/libc/string/arm/_memcpy.S @@ -67,8 +67,9 @@ * a time where possible. * * Note: r12 (aka ip) can be trashed during the function along with - * r0-r3 although r0-r2 have defined uses i.e. src, dest, len through out. + * r0-r3 although r0-r2 have defined uses i.e. dest, src, len throughout. * Additional registers are preserved prior to use i.e. r4, r5 & lr + * The return value in r0 must be the destination address. * * Apologies for the state of the comments ;-) */ @@ -108,7 +109,7 @@ _memcpy: cmp r1, r0 bcc .Lmemcpy_backwards - IT(tt, eq) /* Quick abort for src=dst */ + IT(t, eq) /* Quick abort for src=dst */ #if defined(__USE_BX__) bxeq lr #else diff --git a/libc/sysdeps/linux/arm/aeabi_lcsts.c b/libc/sysdeps/linux/arm/aeabi_lcsts.c index 99c79851e..0c620d4fe 100644 --- a/libc/sysdeps/linux/arm/aeabi_lcsts.c +++ b/libc/sysdeps/linux/arm/aeabi_lcsts.c @@ -81,4 +81,19 @@ eabi_constant (TMP_MAX); eabi_constant (FILENAME_MAX); eabi_constant (L_tmpnam); +FILE *__aeabi_stdin attribute_hidden; +FILE *__aeabi_stdout attribute_hidden; +FILE *__aeabi_stderr attribute_hidden; + +static void __attribute__ ((used)) +setup_aeabi_stdio (void) +{ + __aeabi_stdin = stdin; + __aeabi_stdout = stdout; + __aeabi_stderr = stderr; +} + +static void (*fp) (void) __attribute__ ((used, section (".preinit_array"))) + = setup_aeabi_stdio; + eabi_constant (CLOCKS_PER_SEC); diff --git a/libc/sysdeps/linux/arm/setjmp.S b/libc/sysdeps/linux/arm/setjmp.S index 2df7d551a..76d179043 100644 --- a/libc/sysdeps/linux/arm/setjmp.S +++ b/libc/sysdeps/linux/arm/setjmp.S @@ -47,7 +47,7 @@ __sigsetjmp: mov ip, r0 #if defined(__thumb2__) stmia ip!, {v1-v6, sl, fp} - movs r2, sp + mov r2, sp stmia ip!, {r2, lr} #else /* Save registers */ diff --git a/libc/sysdeps/linux/sh/Makefile.arch b/libc/sysdeps/linux/sh/Makefile.arch index 77ad570d6..2c69f59b8 100644 --- a/libc/sysdeps/linux/sh/Makefile.arch +++ b/libc/sysdeps/linux/sh/Makefile.arch @@ -7,7 +7,7 @@ # CSRC := \ - mmap.c pipe.c __init_brk.c brk.c sbrk.c syscall.c pread_write.c + mmap.c pipe.c __init_brk.c brk.c sbrk.c syscall.c pread_write.c cacheflush.c SSRC := setjmp.S __longjmp.S vfork.S clone.S ___fpscr_values.S diff --git a/libc/sysdeps/linux/sh/cacheflush.c b/libc/sysdeps/linux/sh/cacheflush.c new file mode 100644 index 000000000..58229186d --- /dev/null +++ b/libc/sysdeps/linux/sh/cacheflush.c @@ -0,0 +1,15 @@ +/* + * cacheflush syscall for SUPERH + * + * Copyright (C) 2009 STMicroelectronics Ltd + * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#include <errno.h> +#include <unistd.h> +#include <sys/syscall.h> + +#ifdef __NR_cacheflush +_syscall3(int, cacheflush, char *, addr, int, nbytes, int, op) +#endif diff --git a/librt/shm.c b/librt/shm.c new file mode 100644 index 000000000..c7c0ee461 --- /dev/null +++ b/librt/shm.c @@ -0,0 +1,101 @@ +/* Copyright (C) 2009 Bernhard Reutner-Fischer <uclibc@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <features.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> + +#ifndef _PATH_SHM +#define _PATH_SHM "/dev/shm/" +#endif + +#ifndef NAME_MAX +#define NAME_MAX 255 +#endif + +/* Get name of dummy shm operation handle. + * Returns a malloc'ed buffer containing the OS specific path + * to the shm filename or NULL upon failure. + */ +static __attribute_noinline__ char* get_shm_name(const char*name) __nonnull((1)); +static char* get_shm_name(const char*name) +{ + char *path; + int i; + + /* Skip leading slashes */ + while (*name == '/') + ++name; +#ifdef __USE_GNU + i = asprintf(&path, _PATH_SHM "%s", name); + if (i < 0) + return NULL; +#else + path = malloc(NAME_MAX); + if (path == NULL) + return NULL; + i = snprintf(path, NAME_MAX, _PATH_SHM "%s", name); + if (i < 0) { + free(path); + return NULL; + } else if (i >= NAME_MAX) { + free(path); + __set_errno(ENAMETOOLONG); + return NULL; + } +#endif + return path; +} + +int shm_open(const char *name, int oflag, mode_t mode) +{ + int fd, old_errno; + char *shm_name = get_shm_name(name); + + /* Stripped multiple '/' from start; may have set errno properly */ + if (shm_name == NULL) + return -1; + /* The FD_CLOEXEC file descriptor flag associated with the new + * file descriptor is set. */ +#ifdef O_CLOEXEC + /* Just open it with CLOEXEC set, for brevity */ + fd = open(shm_name, oflag | O_CLOEXEC, mode); +#else + fd = open(shm_name, oflag, mode); + if (fd >= 0) { + int fdflags = fcntl(fd, F_GETFD, 0); + if (fdflags >= 0) + fdflags = fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC); + if (fdflags < 0) { + close(fd); + fd = -1; + } + } +#endif + old_errno = errno; + free(shm_name); + errno = old_errno; + return fd; +} + +int shm_unlink(const char *name) +{ + char *shm_name = get_shm_name(name); + int ret, old_errno; + + /* Stripped multiple '/' from start; may have set errno properly */ + if (shm_name == NULL) + return -1; + ret = unlink(shm_name); + old_errno = errno; + free(shm_name); + errno = old_errno; + return ret; +} diff --git a/test/librt/Makefile b/test/librt/Makefile new file mode 100644 index 000000000..362d5d5c1 --- /dev/null +++ b/test/librt/Makefile @@ -0,0 +1,6 @@ +# uClibc shm tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak + +LDFLAGS_shmtest := -lrt diff --git a/test/librt/shmtest.c b/test/librt/shmtest.c new file mode 100644 index 000000000..8f40047be --- /dev/null +++ b/test/librt/shmtest.c @@ -0,0 +1,102 @@ +/* Copyright (C) 2009 Mikael Lund Jepsen <mlj@iccc.dk> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/wait.h> + +char shared_name[] = "/sharetest"; +int test_data[11] = {0,1,2,3,4,5,6,7,8,9,10}; + +int main(void) { + int pfds[2]; + pid_t pid; + int fd; + int test_data_fails = 0; + char *ptest_data; + unsigned int i; + char buf[30]; + int rv; + + pipe(pfds); + + switch(pid = fork()) { + case -1: + perror("fork"); + exit(1); /* parent exits */ + + case 0: + /* Child */ + + /* wait for parent */ + read(pfds[0], buf, 5); + + fd = shm_open(shared_name, O_RDWR, DEFFILEMODE); + if (fd == -1) { + perror("CHILD - shm_open(existing):"); + exit(1); + } else { + ptest_data = mmap(0, sizeof(test_data), PROT_READ + PROT_WRITE, MAP_SHARED, fd, 0); + if (ptest_data != MAP_FAILED) { + for (i=0; i < sizeof(test_data); i++) { + if (ptest_data[i] != test_data[i]) { + printf("%-40s: Offset %d, local %d, shm %d", "Compare memory error", i, test_data[i], ptest_data[i]); + test_data_fails++; + } + } + if (test_data_fails == 0) + printf("%-40s: %s\n", "Compare memory", "Success"); + + munmap(ptest_data, sizeof(test_data)); + } + } + exit(0); + + default: + /* Parent */ + fd = shm_open(shared_name, O_RDWR+O_CREAT+O_EXCL, DEFFILEMODE ); + if (fd == -1) { + perror("PARENT - shm_open(create):"); + } else { + if ((ftruncate(fd, sizeof(test_data))) == -1) + { + printf("%-40s: %s", "ftruncate", strerror(errno)); + shm_unlink(shared_name); + return 0; + } + + ptest_data = mmap(0, sizeof(test_data), PROT_READ + PROT_WRITE, MAP_SHARED, fd, 0); + if (ptest_data == MAP_FAILED) + { + perror("PARENT - mmap:"); + if (shm_unlink(shared_name) == -1) { + perror("PARENT - shm_unlink:"); + } + return 0; + } + for (i=0; i <sizeof(test_data); i++) + ptest_data[i] = test_data[i]; + + /* signal child */ + write(pfds[1], "rdy", 5); + /* wait for child */ + wait(&rv); + + /* Cleanup */ + munmap(ptest_data, sizeof(test_data)); + if (shm_unlink(shared_name) == -1) { + perror("PARENT - shm_unlink:"); + } + } + } + return 0; +} diff --git a/utils/.gitignore b/utils/.gitignore new file mode 100644 index 000000000..af2888834 --- /dev/null +++ b/utils/.gitignore @@ -0,0 +1,4 @@ +ldconfig +ldconfig.host +ldd +ldd.host 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; -} |