summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in9
-rw-r--r--extra/locale/gen_wc8bit.c25
-rwxr-xr-xextra/scripts/install_kernel_headers.sh85
-rw-r--r--libc/Makefile.in4
-rw-r--r--libc/misc/wchar/wchar.c2
-rw-r--r--libc/string/arm/_memcpy.S5
-rw-r--r--libc/sysdeps/linux/arm/aeabi_lcsts.c15
-rw-r--r--libc/sysdeps/linux/arm/setjmp.S2
-rw-r--r--libc/sysdeps/linux/sh/Makefile.arch2
-rw-r--r--libc/sysdeps/linux/sh/cacheflush.c15
-rw-r--r--librt/shm.c101
-rw-r--r--test/librt/Makefile6
-rw-r--r--test/librt/shmtest.c102
-rw-r--r--utils/.gitignore4
-rw-r--r--utils/Makefile.in7
-rw-r--r--utils/readelf.c346
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;
-}