diff -urN uClibc-0.9.28.orig/include/elf.h uClibc-0.9.28/include/elf.h --- uClibc-0.9.28.orig/include/elf.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/include/elf.h 2006-04-28 00:14:35.000000000 -0600 @@ -142,6 +142,7 @@ #define ELFOSABI_HPUX 1 /* HP-UX */ #define ELFOSABI_NETBSD 2 /* NetBSD. */ #define ELFOSABI_LINUX 3 /* Linux. */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ #define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ #define ELFOSABI_AIX 7 /* IBM AIX. */ #define ELFOSABI_IRIX 8 /* SGI Irix. */ @@ -149,6 +150,9 @@ #define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ #define ELFOSABI_MODESTO 11 /* Novell Modesto. */ #define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +#define ELFOSABI_OPENVMS 13 /* OpenVMS */ +#define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ #define ELFOSABI_ARM 97 /* ARM */ #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ @@ -177,6 +181,7 @@ #define EM_386 3 /* Intel 80386 */ #define EM_68K 4 /* Motorola m68k family */ #define EM_88K 5 /* Motorola m88k family */ +#define EM_486 6 /* Intel 80486 *//* Reserved for future use */ #define EM_860 7 /* Intel 80860 */ #define EM_MIPS 8 /* MIPS R3000 big-endian */ #define EM_S370 9 /* IBM System/370 */ @@ -193,7 +198,8 @@ #define EM_V800 36 /* NEC V800 series */ #define EM_FR20 37 /* Fujitsu FR20 */ #define EM_RH32 38 /* TRW RH-32 */ -#define EM_RCE 39 /* Motorola RCE */ +#define EM_MCORE 39 /* Motorola M*Core */ /* May also be taken by Fujitsu MMA */ +#define EM_RCE 39 /* Old name for MCore */ #define EM_ARM 40 /* ARM */ #define EM_FAKE_ALPHA 41 /* Digital Alpha */ #define EM_SH 42 /* Renesas SH */ @@ -248,18 +254,105 @@ #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_IP2K 101 /* Ubicom IP2022 micro controller */ +#define EM_CR 103 /* National Semiconductor CompactRISC */ +#define EM_MSP430 105 /* TI msp430 micro controller */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin */ +#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ +#define EM_CRX 114 /* National Semiconductor CRX */ #define EM_NUM 95 -/* If it is necessary to assign new unofficial EM_* values, please - pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the - chances of collision with official or non-GNU unofficial values. */ +/* If it is necessary to assign new unofficial EM_* values, please pick large + random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision + with official or non-GNU unofficial values. -/* Fujitsu FR-V. */ + NOTE: Do not just increment the most recent number by one. + Somebody else somewhere will do exactly the same thing, and you + will have a collision. Instead, pick a random number. + + Normally, each entity or maintainer responsible for a machine with an + unofficial e_machine number should eventually ask registry@caldera.com for + an officially blessed number to be added to the list above. */ + +/* picoJava */ +#define EM_PJ_OLD 99 + +/* Cygnus PowerPC ELF backend. Written in the absence of an ABI. */ +#define EM_CYGNUS_POWERPC 0x9025 + +/* Old version of Sparc v9, from before the ABI; this should be + removed shortly. */ +#define EM_OLD_SPARCV9 11 + +/* Old version of PowerPC, this should be removed shortly. */ +#define EM_PPC_OLD 17 + +/* (Deprecated) Temporary number for the OpenRISC processor. */ +#define EM_OR32 0x8472 + +/* Renesas M32C and M16C. */ +#define EM_M32C 0xFEB0 + +/* Cygnus M32R ELF backend. Written in the absence of an ABI. */ +#define EM_CYGNUS_M32R 0x9041 + +/* old S/390 backend magic number. Written in the absence of an ABI. */ +#define EM_S390_OLD 0xa390 + +/* D10V backend magic number. Written in the absence of an ABI. */ +#define EM_CYGNUS_D10V 0x7650 + +/* D30V backend magic number. Written in the absence of an ABI. */ +#define EM_CYGNUS_D30V 0x7676 + +/* V850 backend magic number. Written in the absense of an ABI. */ +#define EM_CYGNUS_V850 0x9080 + +/* mn10200 and mn10300 backend magic numbers. + Written in the absense of an ABI. */ +#define EM_CYGNUS_MN10200 0xdead +#define EM_CYGNUS_MN10300 0xbeef + +/* FR30 magic number - no EABI available. */ +#define EM_CYGNUS_FR30 0x3330 + +/* AVR magic number + Written in the absense of an ABI. */ +#define EM_AVR_OLD 0x1057 + +/* OpenRISC magic number + Written in the absense of an ABI. */ +#define EM_OPENRISC_OLD 0x3426 + +/* DLX magic number + Written in the absense of an ABI. */ +#define EM_DLX 0x5aa5 + +#define EM_XSTORMY16 0xad45 + +/* FRV magic number - no EABI available??. */ #define EM_CYGNUS_FRV 0x5441 +/* Ubicom IP2xxx; no ABI */ +#define EM_IP2K_OLD 0x8217 + +#define EM_MT 0x2530 /* Morpho MT; no ABI */ + +/* MSP430 magic number + Written in the absense everything. */ +#define EM_MSP430_OLD 0x1059 + +/* Vitesse IQ2000. */ +#define EM_IQ2000 0xFEBA + +/* Old, unofficial value for Xtensa. */ +#define EM_XTENSA_OLD 0xabc7 + +/* Alpha backend magic number. Written in the absence of an ABI. */ #define EM_ALPHA 0x9026 -#define EM_NIOS32 0xfebb /* Altera Nios 32 */ -#define EM_ALTERA_NIOS2 0x9ee5 /* Altera Nios II */ + +/* NIOS magic number - no EABI available. */ +#define EM_NIOS32 0xFEBB /* V850 backend magic number. Written in the absense of an ABI. */ #define EM_CYGNUS_V850 0x9080 @@ -2498,6 +2591,12 @@ #define R_390_NUM 61 +/* CRIS flags. */ +#define EF_CRIS_VARIANT_MASK 0x0000000e +#define EF_CRIS_VARIANT_ANY_V0_V10 0x00000000 +#define EF_CRIS_VARIANT_V32 0x00000002 +#define EF_CRIS_VARIANT_COMMON_V10_V32 0x00000004 + /* CRIS relocations. */ #define R_CRIS_NONE 0 #define R_CRIS_8 1 @@ -2688,6 +2787,7 @@ #define R_V850_NUM 25 +/* Renesas H8/300 Relocations */ #define R_H8_NONE 0 #define R_H8_DIR32 1 #define R_H8_DIR32_28 2 @@ -2731,8 +2831,7 @@ #define R_H8_DIR32A16 63 #define R_H8_ABS32 65 #define R_H8_ABS32A16 127 - -/* Altera NIOS specific definitions. */ +#define R_H8_NUM 128 /* NIOS relocations. */ #define R_NIOS_NONE 0 diff -urN uClibc-0.9.28.orig/include/errno.h uClibc-0.9.28/include/errno.h --- uClibc-0.9.28.orig/include/errno.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/include/errno.h 2006-04-28 00:14:35.000000000 -0600 @@ -43,9 +43,11 @@ variable. This redeclaration using the macro still works, but it will be a function declaration without a prototype and may trigger a -Wstrict-prototypes warning. */ +#ifndef __ASSEMBLER__ #ifndef errno extern int errno; #endif +#endif #if 0 /*def __USE_GNU uClibc note: not supported */ diff -urN uClibc-0.9.28.orig/ldso/Makefile uClibc-0.9.28/ldso/Makefile --- uClibc-0.9.28.orig/ldso/Makefile 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/Makefile 2006-04-28 00:14:35.000000000 -0600 @@ -37,15 +37,12 @@ LN_HEADERS := $(patsubst %, include/%, elf.h) LN_ARCH_HEADERS := $(patsubst %, include/%, dl-startup.h dl-syscalls.h dl-sysdep.h dl-debug.h) -HEADERS := $(LN_HEADERS) $(LN_ARCH_HEADERS) include/dl-progname.h +HEADERS := $(LN_HEADERS) $(LN_ARCH_HEADERS) headers: $(HEADERS) $(LN_HEADERS): $(LN) -fs $(TOPDIR)../$@ $@ $(LN_ARCH_HEADERS): $(LN) -fs ../ldso/$(TARGET_ARCH)/$(patsubst include/%,%,$@) $@ -include/dl-progname.h: - echo '#include "$(TARGET_ARCH)/elfinterp.c"' \ - > include/dl-progname.h clean: set -e ; for d in $(DIRS) ; do $(MAKE) -C $$d $@ ; done diff -urN uClibc-0.9.28.orig/ldso/include/dl-defs.h uClibc-0.9.28/ldso/include/dl-defs.h --- uClibc-0.9.28.orig/ldso/include/dl-defs.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/include/dl-defs.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,6 +1,29 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + #ifndef _LD_DEFS_H #define _LD_DEFS_H +#define FLAG_ANY -1 +#define FLAG_TYPE_MASK 0x00ff +#define FLAG_LIBC4 0x0000 +#define FLAG_ELF 0x0001 +#define FLAG_ELF_LIBC5 0x0002 +#define FLAG_ELF_LIBC6 0x0003 +#define FLAG_ELF_UCLIBC 0x0004 +#define FLAG_REQUIRED_MASK 0xff00 +#define FLAG_SPARC_LIB64 0x0100 +#define FLAG_IA64_LIB64 0x0200 +#define FLAG_X8664_LIB64 0x0300 +#define FLAG_S390_LIB64 0x0400 +#define FLAG_POWERPC_LIB64 0x0500 +#define FLAG_MIPS64_LIBN32 0x0600 +#define FLAG_MIPS64_LIBN64 0x0700 + #define LIB_ANY -1 #define LIB_DLL 0 #define LIB_ELF 1 diff -urN uClibc-0.9.28.orig/ldso/include/dl-elf.h uClibc-0.9.28/ldso/include/dl-elf.h --- uClibc-0.9.28.orig/ldso/include/dl-elf.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/include/dl-elf.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,3 +1,10 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + #ifndef LINUXELF_H #define LINUXELF_H diff -urN uClibc-0.9.28.orig/ldso/include/dl-hash.h uClibc-0.9.28/ldso/include/dl-hash.h --- uClibc-0.9.28.orig/ldso/include/dl-hash.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/include/dl-hash.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,3 +1,10 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + #ifndef _LD_HASH_H_ #define _LD_HASH_H_ @@ -32,15 +39,15 @@ unsigned short usage_count; unsigned short int init_flag; unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */ - Elf32_Word nbucket; - Elf32_Word *elf_buckets; + Elf_Symndx nbucket; + Elf_Symndx *elf_buckets; struct init_fini_list *init_fini; struct init_fini_list *rtld_local; /* keep tack of RTLD_LOCAL libs in same group */ /* * These are only used with ELF style shared libraries */ - Elf32_Word nchain; - Elf32_Word *chains; + Elf_Symndx nchain; + Elf_Symndx *chains; unsigned long dynamic_info[DYNAMIC_SIZE]; unsigned long n_phent; @@ -49,6 +56,9 @@ ElfW(Addr) relro_addr; size_t relro_size; + dev_t st_dev; /* device */ + ino_t st_ino; /* inode */ + #ifdef __powerpc__ /* this is used to store the address of relocation data words, so * we don't have to calculate it every time, which requires a divide */ @@ -66,7 +76,6 @@ extern struct elf_resolve * _dl_loaded_modules; extern struct dyn_elf * _dl_handles; -extern struct elf_resolve * _dl_check_hashed_files(const char * libname); extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, char * loadaddr, unsigned long * dynamic_info, unsigned long dynamic_addr, unsigned long dynamic_size); diff -urN uClibc-0.9.28.orig/ldso/include/dl-string.h uClibc-0.9.28/ldso/include/dl-string.h --- uClibc-0.9.28.orig/ldso/include/dl-string.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/include/dl-string.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,9 +1,24 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + #ifndef _LINUX_STRING_H_ #define _LINUX_STRING_H_ -#include // for do_rem +#include /* for do_rem */ #include +/* provide some sane defaults */ +#ifndef do_rem +# define do_rem(result, n, base) ((result) = (n) % (base)) +#endif +#ifndef do_div_10 +# define do_div_10(result, remain) ((result) /= 10) +#endif + static size_t _dl_strlen(const char * str); static char *_dl_strcat(char *dst, const char *src); static char * _dl_strcpy(char * dst,const char *src); @@ -26,8 +41,8 @@ static __always_inline size_t _dl_strlen(const char * str) { register const char *ptr = (char *) str-1; - - while (*++ptr); + while (*++ptr) + ;/* empty */ return (ptr - str); } @@ -49,7 +64,8 @@ register char *ptr = dst; dst--;src--; - while ((*++dst = *++src) != 0); + while ((*++dst = *++src) != 0) + ;/* empty */ return ptr; } @@ -63,8 +79,7 @@ c2 = (unsigned char) *++s2; if (c1 == '\0') return c1 - c2; - } - while (c1 == c2); + } while (c1 == c2); return c1 - c2; } @@ -98,43 +113,41 @@ return 0; } -static inline char * _dl_strrchr(const char *str, int c) +static __always_inline char * _dl_strrchr(const char *str, int c) { - register char *prev = 0; - register char *ptr = (char *) str-1; + register char *prev = 0; + register char *ptr = (char *) str-1; - while (*++ptr != '\0') { - if (*ptr == c) - prev = ptr; - } - if (c == '\0') - return(ptr); - return(prev); + while (*++ptr != '\0') { + if (*ptr == c) + prev = ptr; + } + if (c == '\0') + return(ptr); + return(prev); } -static inline char * _dl_strstr(const char *s1, const char *s2) +static __always_inline char * _dl_strstr(const char *s1, const char *s2) { - register const char *s = s1; - register const char *p = s2; + register const char *s = s1; + register const char *p = s2; - do { - if (!*p) { - return (char *) s1;; - } - if (*p == *s) { - ++p; - ++s; - } else { - p = s2; - if (!*s) { - return NULL; - } - s = ++s1; - } - } while (1); + do { + if (!*p) + return (char *) s1;; + if (*p == *s) { + ++p; + ++s; + } else { + p = s2; + if (!*s) + return NULL; + s = ++s1; + } + } while (1); } -static inline void * _dl_memcpy(void * dst, const void * src, size_t len) +static __always_inline void * _dl_memcpy(void * dst, const void * src, size_t len) { register char *a = dst-1; register const char *b = src-1; @@ -163,27 +176,28 @@ /* Will generate smaller and faster code due to loop unrolling.*/ static __always_inline void * _dl_memset(void *to, int c, size_t n) { - unsigned long chunks; - unsigned long *tmp_to; + unsigned long chunks; + unsigned long *tmp_to; unsigned char *tmp_char; - chunks = n / 4; - tmp_to = to + n; - c = c << 8 | c; - c = c << 16 | c; - if (!chunks) - goto lessthan4; - do { - *--tmp_to = c; - } while (--chunks); - lessthan4: - n = n % 4; - if (!n ) return to; - tmp_char = (unsigned char *)tmp_to; - do { - *--tmp_char = c; - } while (--n); - return to; + chunks = n / 4; + tmp_to = to + n; + c = c << 8 | c; + c = c << 16 | c; + if (!chunks) + goto lessthan4; + do { + *--tmp_to = c; + } while (--chunks); +lessthan4: + n = n % 4; + if (!n) + return to; + tmp_char = (unsigned char *)tmp_to; + do { + *--tmp_char = c; + } while (--n); + return to; } #else static __always_inline void * _dl_memset(void * str,int c,size_t len) @@ -225,10 +239,10 @@ char *p = &local[22]; *--p = '\0'; do { - char temp; - do_rem(temp, i, 10); - *--p = '0' + temp; - i /= 10; + char temp; + do_rem(temp, i, 10); + *--p = '0' + temp; + do_div_10(i, temp); } while (i > 0); return p; } @@ -242,9 +256,9 @@ do { char temp = i & 0xf; if (temp <= 0x09) - *--p = '0' + temp; + *--p = '0' + temp; else - *--p = 'a' - 0x0a + temp; + *--p = 'a' - 0x0a + temp; i >>= 4; } while (i > 0); *--p = 'x'; @@ -270,8 +284,8 @@ /* On some arches constant strings are referenced through the GOT. * This requires that load_addr must already be defined... */ -#if defined(mc68000) || defined(__arm__) || defined(__mips__) \ - || defined(__sh__) || defined(__powerpc__) +#if defined(mc68000) || defined(__arm__) || defined(__thumb__) || \ + defined(__mips__) || defined(__sh__) || defined(__powerpc__) # define CONSTANT_STRING_GOT_FIXUP(X) \ if ((X) < (const char *) load_addr) (X) += load_addr # define NO_EARLY_SEND_STDERR @@ -318,7 +332,7 @@ do { \ do_rem(v, (X), 10); \ *--tmp2 = '0' + v; \ - (X) /= 10; \ + do_div_10((X), v); \ } while ((X) > 0); \ _dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \ } diff -urN uClibc-0.9.28.orig/ldso/include/dl-syscall.h uClibc-0.9.28/ldso/include/dl-syscall.h --- uClibc-0.9.28.orig/ldso/include/dl-syscall.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/include/dl-syscall.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,3 +1,10 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + #ifndef _LD_SYSCALL_H_ #define _LD_SYSCALL_H_ @@ -12,9 +19,8 @@ #include #include - /* _dl_open() parameters */ -#define O_RDONLY 0x0000 +#define O_RDONLY 00 #define O_WRONLY 01 #define O_RDWR 02 #define O_CREAT 0100 @@ -39,18 +45,6 @@ #define S_IWRITE 0200 /* Write by owner. */ #define S_IEXEC 0100 /* Execute by owner. */ -/* Stuff for _dl_mmap */ -#if 0 -#define MAP_FAILED ((void *) -1) -#define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED) -#else -#ifndef _dl_MAX_ERRNO -#define _dl_MAX_ERRNO 4096 -#endif -#define _dl_mmap_check_error(__res) \ - (((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO) -#endif - /* Here are the definitions for some syscalls that are used @@ -66,54 +60,125 @@ static inline _syscall1(int, _dl_close, int, fd); #define __NR__dl_open __NR_open -static inline _syscall3(int, _dl_open, const char *, fn, int, flags, __kernel_mode_t, mode); +static inline _syscall3(int, _dl_open, const char *, fn, int, flags, + __kernel_mode_t, mode); #define __NR__dl_write __NR_write static inline _syscall3(unsigned long, _dl_write, int, fd, - const void *, buf, unsigned long, count); + const void *, buf, unsigned long, count); #define __NR__dl_read __NR_read static inline _syscall3(unsigned long, _dl_read, int, fd, - const void *, buf, unsigned long, count); + const void *, buf, unsigned long, count); #define __NR__dl_mprotect __NR_mprotect -static inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, len, int, prot); +static inline _syscall3(int, _dl_mprotect, const void *, addr, + unsigned long, len, int, prot); #define __NR__dl_stat __NR_stat -static inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf); +static inline _syscall2(int, _dl_stat, const char *, file_name, + struct stat *, buf); + +#define __NR__dl_fstat __NR_fstat +static inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf); #define __NR__dl_munmap __NR_munmap static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length); +#ifdef __NR_getxuid +# define __NR_getuid __NR_getxuid +#endif #define __NR__dl_getuid __NR_getuid static inline _syscall0(uid_t, _dl_getuid); +#ifndef __NR_geteuid +# define __NR_geteuid __NR_getuid +#endif #define __NR__dl_geteuid __NR_geteuid static inline _syscall0(uid_t, _dl_geteuid); +#ifdef __NR_getxgid +# define __NR_getgid __NR_getxgid +#endif #define __NR__dl_getgid __NR_getgid static inline _syscall0(gid_t, _dl_getgid); +#ifndef __NR_getegid +# define __NR_getegid __NR_getgid +#endif #define __NR__dl_getegid __NR_getegid static inline _syscall0(gid_t, _dl_getegid); +#ifdef __NR_getxpid +# define __NR_getpid __NR_getxpid +#endif #define __NR__dl_getpid __NR_getpid static inline _syscall0(gid_t, _dl_getpid); #define __NR__dl_readlink __NR_readlink -static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz); +static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, + size_t, bufsiz); -#ifdef __NR_mmap -#ifdef MMAP_HAS_6_ARGS -#define __NR__dl_mmap __NR_mmap -static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length, - int, prot, int, flags, int, fd, off_t, offset); +#ifdef __UCLIBC_HAS_SSP__ +# include +# define __NR__dl_gettimeofday __NR_gettimeofday +static inline _syscall2(int, _dl_gettimeofday, struct timeval *, tv, +# ifdef __USE_BSD + struct timezone *, tz); +# else + void *, tz); +# endif +#endif + + +/* handle all the fun mmap intricacies */ +#if (defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)) || !defined(__NR_mmap2) +# define _dl_MAX_ERRNO 4096 +# define _dl_mmap_check_error(__res) \ + (((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO) #else -#define __NR__dl_mmap_real __NR_mmap -static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer); +# define MAP_FAILED ((void *) -1) +# define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED) +#endif + +/* first try mmap(), syscall6() style */ +#if defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap) + +# define __NR__dl_mmap __NR_mmap +static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length, + int, prot, int, flags, int, fd, off_t, offset); + +/* then try mmap2() */ +#elif defined(__NR_mmap2) + +# define __NR___syscall_mmap2 __NR_mmap2 +static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len, + int, prot, int, flags, int, fd, off_t, offset); + +/* Some architectures always use 12 as page shift for mmap2() eventhough the + * real PAGE_SHIFT != 12. Other architectures use the same value as + * PAGE_SHIFT... + */ +#ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +#endif static inline void * _dl_mmap(void * addr, unsigned long size, int prot, - int flags, int fd, unsigned long offset) + int flags, int fd, unsigned long offset) +{ + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) + return MAP_FAILED; + return __syscall_mmap2(addr, size, prot, flags, + fd, (off_t) (offset >> MMAP2_PAGE_SHIFT)); +} + +/* finally, fall back to mmap(), syscall1() style */ +#elif defined(__NR_mmap) + +# define __NR__dl_mmap_real __NR_mmap +static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer); +static inline void * _dl_mmap(void * addr, unsigned long size, int prot, + int flags, int fd, unsigned long offset) { unsigned long buffer[6]; @@ -125,24 +190,9 @@ buffer[5] = (unsigned long) offset; return (void *) _dl_mmap_real(buffer); } -#endif -#elif defined __NR_mmap2 -#define __NR___syscall_mmap2 __NR_mmap2 -static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, - size_t, len, int, prot, int, flags, int, fd, off_t, offset); -/*always 12, even on architectures where PAGE_SHIFT != 12 */ -#define MMAP2_PAGE_SHIFT 12 -static inline void * _dl_mmap(void * addr, unsigned long size, int prot, - int flags, int fd, unsigned long offset) -{ - if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) - return MAP_FAILED; - return(__syscall_mmap2(addr, size, prot, flags, - fd, (off_t) (offset >> MMAP2_PAGE_SHIFT))); -} + #else -#error "Your architecture doesn't seem to provide mmap() !?" +# error "Your architecture doesn't seem to provide mmap() !?" #endif #endif /* _LD_SYSCALL_H_ */ - diff -urN uClibc-0.9.28.orig/ldso/include/dlfcn.h uClibc-0.9.28/ldso/include/dlfcn.h --- uClibc-0.9.28.orig/ldso/include/dlfcn.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/include/dlfcn.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,3 +1,10 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + /* User functions for run-time dynamic loading. libdl version */ #ifndef _DLFCN_H #define _DLFCN_H 1 diff -urN uClibc-0.9.28.orig/ldso/include/ldso.h uClibc-0.9.28/ldso/include/ldso.h --- uClibc-0.9.28.orig/ldso/include/ldso.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/include/ldso.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,3 +1,10 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + #ifndef _LDSO_H_ #define _LDSO_H_ @@ -20,13 +27,15 @@ /* Pull in compiler and arch stuff */ #include #include +#include /* Pull in the arch specific type information */ #include +/* Pull in the arch specific page size */ +#include +#define attribute_unused __attribute__ ((unused)) /* Pull in the ldso syscalls and string functions */ #include #include -/* Pull in the arch specific page size */ -#include /* Now the ldso specific headers */ #include #include diff -urN uClibc-0.9.28.orig/ldso/include/unsecvars.h uClibc-0.9.28/ldso/include/unsecvars.h --- uClibc-0.9.28.orig/ldso/include/unsecvars.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/include/unsecvars.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,3 +1,10 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + /* * Environment variable to be removed for SUID programs. The names are all * stuffed in a single string which means they have to be terminated with a @@ -5,22 +12,21 @@ */ #define UNSECURE_ENVVARS \ - "LD_AOUT_PRELOAD\0" \ - "LD_AOUT_LIBRARY_PATH\0" \ "LD_PRELOAD\0" \ "LD_LIBRARY_PATH\0" \ "LD_DEBUG\0" \ "LD_DEBUG_OUTPUT\0" \ "LD_TRACE_LOADED_OBJECTS\0" \ - "HOSTALIASES\0" \ - "LOCALDOMAIN\0" \ - "RES_OPTIONS\0" \ "TMPDIR\0" /* + * LD_TRACE_LOADED_OBJECTS is not in glibc-2.3.5's unsecvars.h + * though used by ldd + * * These environment variables are defined by glibc but ignored in * uClibc, but may very well have an equivalent in uClibc. * - * MALLOC_TRACE, RESOLV_HOST_CONF, TZDIR, GCONV_PATH, LD_USE_LOAD_BIAS, - * LD_PROFILE, LD_ORIGIN_PATH, LOCPATH, NLSPATH + * LD_ORIGIN_PATH, LD_PROFILE, LD_USE_LOAD_BIAS, LD_DYNAMIC_WEAK, LD_SHOW_AUXV, + * GCONV_PATH, GETCONF_DIR, HOSTALIASES, LOCALDOMAIN, LOCPATH, MALLOC_TRACE, + * NLSPATH, RESOLV_HOST_CONF, RES_OPTIONS, TZDIR */ diff -urN uClibc-0.9.28.orig/ldso/ldso/Makefile uClibc-0.9.28/ldso/ldso/Makefile --- uClibc-0.9.28.orig/ldso/ldso/Makefile 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/Makefile 2006-04-28 00:14:35.000000000 -0600 @@ -42,7 +42,9 @@ endif XXFLAGS+= -DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\" $(XARCH_CFLAGS) $(CPU_CFLAGS) $(PICFLAG) \ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \ - -fno-builtin -nostdinc -D_LIBC -I$(TOPDIR)ldso/include -I. -I$(TOPDIR)include + -fno-builtin -nostdinc -D_LIBC \ + -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" \ + -I$(TOPDIR)ldso/ldso/$(TARGET_ARCH) -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I$(TOPDIR)include # BEWARE!!! At least mips* will die if -O0 is used!!! XXFLAGS:=$(XXFLAGS:-O0=-O1) diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-startup.h uClibc-0.9.28/ldso/ldso/arm/dl-startup.h --- uClibc-0.9.28.orig/ldso/ldso/arm/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/arm/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,10 +1,15 @@ /* vi: set sw=4 ts=4: */ /* * Architecture specific code used by dl-startup.c - * Copyright (C) 2000-2004 by Erik Andersen + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ -asm( +#include + +#if !defined(__thumb__) +__asm__( " .text\n" " .globl _start\n" " .type _start,%function\n" @@ -40,7 +45,78 @@ " ldr r0, .L_FINI_PROC\n" " ldr r0, [sl, r0]\n" " @ jump to the user_s entry point\n" +#if defined(__USE_BX__) + " bx r6\n" +#else + " mov pc, r6\n" +#endif + ".L_GET_GOT:\n" + " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n" + ".L_SKIP_ARGS:\n" + " .word _dl_skip_args(GOTOFF)\n" + ".L_FINI_PROC:\n" + " .word _dl_fini(GOT)\n" + "\n\n" + " .size _start,.-_start\n" + ".previous\n" +); +#else +__asm__( + " .text\n" + " .arm\n" + " .globl _start\n" + " .type _start,%function\n" + "_start:\n" + " @ dumb: can't persuade the linker to make the start address\n" + " @ odd, so use an arm function and change to thumb (_dl_start\n" + " @ is thumb)\n" + " adr r0, __dl_thumb_start+1\n" + " bx r0\n" + "\n\n" + " .thumb\n" + " .globl __dl_thumb_start\n" + " .thumb_func\n" + " .type __dl_thumb_start,%function\n" + "__dl_thumb_start:\n" + " @ at start time, all the args are on the stack\n" + " mov r0, sp\n" + " bl _dl_start\n" + " @ returns user entry point in r0\n" + " mov r6, r0\n" + " @ we are PIC code, so get global offset table\n" + " ldr r7, .L_GET_GOT\n" + ".L_GOT_GOT:\n" + " add r7, pc\n" + " @ See if we were run as a command with the executable file\n" + " @ name as an extra leading argument.\n" + " ldr r4, .L_SKIP_ARGS\n" + " ldr r4, [r7, r4]\n" + " @ get the original arg count\n" + " ldr r1, [sp]\n" + " @ subtract _dl_skip_args from it\n" + " sub r1, r1, r4\n" + " @ adjust the stack pointer to skip them\n" + " lsl r4, r4, #2\n" + " add sp, r4\n" + " @ get the argv address\n" + " add r2, sp, #4\n" + " @ store the new argc in the new stack location\n" + " str r1, [sp]\n" + " @ compute envp\n" + " lsl r3, r1, #2\n" + " add r3, r3, r2\n" + " add r3, #4\n" + "\n\n" + " @ load the finalizer function\n" + " ldr r0, .L_FINI_PROC\n" + " ldr r0, [r7, r0]\n" + " @ jump to the user_s entry point\n" +#if defined(__USE_BX__) + " bx r6\n" +#else " mov pc, r6\n" +#endif + "\n\n" ".L_GET_GOT:\n" " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n" ".L_SKIP_ARGS:\n" @@ -51,6 +127,7 @@ " .size _start,.-_start\n" ".previous\n" ); +#endif /* Get a pointer to the argv array. On many platforms this can be just @@ -115,9 +192,3 @@ _dl_exit(1); } } - - -/* Transfer control to the user's application, once the dynamic loader is - * done. This routine has to exit the current function, then call the - * _dl_elf_main function. */ -#define START() return _dl_elf_main; diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-syscalls.h uClibc-0.9.28/ldso/ldso/arm/dl-syscalls.h --- uClibc-0.9.28.orig/ldso/ldso/arm/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/arm/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,6 +1,7 @@ /* We can't use the real errno in ldso, since it has not yet * been dynamicly linked in yet. */ +#include "sys/syscall.h" extern int _dl_errno; +#undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} -#include "sys/syscall.h" diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-sysdep.h uClibc-0.9.28/ldso/ldso/arm/dl-sysdep.h --- uClibc-0.9.28.orig/ldso/ldso/arm/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/arm/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 @@ -43,6 +43,7 @@ return m; } #define do_rem(result, n, base) ((result) = arm_modulus(n, base)) +#define do_div_10(result, remain) ((result) = (((result) - (remain)) / 2) * -(-1ul / 5ul)) /* Here we define the magic numbers that this dynamic loader should accept */ #define MAGIC1 EM_ARM @@ -85,7 +86,25 @@ extern void __dl_start asm ("_dl_start"); Elf32_Addr got_addr = (Elf32_Addr) &__dl_start; Elf32_Addr pcrel_addr; +#if !defined __thumb__ asm ("adr %0, _dl_start" : "=r" (pcrel_addr)); +#else + int tmp; + /* The above adr will not work on thumb because it + * is negative. The only safe way is to temporarily + * swap to arm. + */ + asm( ".align 2\n" + " bx pc\n" + " nop \n" + " .arm \n" + " adr %0, _dl_start\n" + " .align 2\n" + " orr %1, pc, #1\n" + " bx %1\n" + " .force_thumb\n" + : "=r" (pcrel_addr), "=&r" (tmp)); +#endif return pcrel_addr - got_addr; } diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/elfinterp.c uClibc-0.9.28/ldso/ldso/arm/elfinterp.c --- uClibc-0.9.28.orig/ldso/ldso/arm/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/arm/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 @@ -38,6 +38,8 @@ a more than adequate job of explaining everything required to get this working. */ +#include "ldso.h" + extern int _dl_linux_resolve(void); unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) @@ -63,7 +65,6 @@ strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; symname = strtab + symtab[symtab_index].st_name; - if (unlikely(reloc_type != R_ARM_JUMP_SLOT)) { _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", _dl_progname); diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-startup.h uClibc-0.9.28/ldso/ldso/cris/dl-startup.h --- uClibc-0.9.28.orig/ldso/ldso/cris/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/cris/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 @@ -4,22 +4,43 @@ /* This code fixes the stack pointer so that the dynamic linker * can find argc, argv and auxvt (Auxillary Vector Table). */ +#ifdef __arch_v32 + +asm("" \ +" .text\n" \ +" .globl _start\n" \ +" .type _start,@function\n" \ +"_start:\n" \ +" move.d $sp,$r10\n" \ +" lapc _dl_start,$r9\n" \ +" jsr $r9\n" \ +" nop\n" \ +" moveq 0,$r8\n" \ +" jump $r10\n" \ +" move $r8,$srp\n" \ +" .size _start,.-_start\n" \ +" .previous\n" \ +); + +#else + asm("" \ " .text\n" \ " .globl _start\n" \ " .type _start,@function\n" \ "_start:\n" \ -" move.d $sp,$r10\n" \ -" move.d $pc,$r9\n" \ -" add.d _dl_start - ., $r9\n" \ -" jsr $r9\n" \ -" moveq 0,$r8\n" \ -" move $r8,$srp\n" \ -" jump $r10\n" \ +" move.d $sp,$r10\n" \ +" move.d $pc,$r9\n" \ +" add.d _dl_start - ., $r9\n" \ +" jsr $r9\n" \ +" moveq 0,$r8\n" \ +" move $r8,$srp\n" \ +" jump $r10\n" \ " .size _start,.-_start\n" \ " .previous\n" \ ); +#endif /* __arch_v32 */ /* Get a pointer to the argv array. On many platforms this can be just * the address if the first argument, on other platforms we need to @@ -58,8 +79,3 @@ break; } } - -/* Transfer control to the user's application, once the dynamic loader is - * done. This routine has to exit the current function, then call the - * _dl_elf_main function. */ -#define START() return _dl_elf_main diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-syscalls.h uClibc-0.9.28/ldso/ldso/cris/dl-syscalls.h --- uClibc-0.9.28.orig/ldso/ldso/cris/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/cris/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,5 +1,6 @@ /* We can't use the real errno in ldso, since it has not yet * been dynamicly linked in yet. */ +#include "sys/syscall.h" extern int _dl_errno; +#undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} -#include "sys/syscall.h" diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-sysdep.h uClibc-0.9.28/ldso/ldso/cris/dl-sysdep.h --- uClibc-0.9.28.orig/ldso/ldso/cris/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/cris/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 @@ -18,8 +18,6 @@ struct elf_resolve; extern unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry); -#define do_rem(result, n, base) ((result) = (n) % (base)) - /* 8192 bytes alignment */ #define PAGE_ALIGN 0xffffe000 #define ADDR_ALIGN 0x1fff @@ -68,8 +66,32 @@ { Elf32_Addr gotaddr_diff; +#ifdef __arch_v32 + extern char ___CRISv32_dummy[] __asm__ ("_dl_start"); + + __asm__ ("addo.w _dl_start:GOT16,$r0,$acr\n\t" + "lapc _dl_start,%0\n\t" + "sub.d [$acr],%0" + /* For v32, we need to force GCC to have R0 loaded with + _GLOBAL_OFFSET_TABLE_ at this point, which might not + otherwise have happened in the caller. (For v10, it's + loaded for non-global variables too, so we don't need + anything special there.) We accomplish this by faking the + address of a global variable (as seen by GCC) as input to + the asm; that address calculation goes through the GOT. + Use of this function happens before we've filled in the + GOT, so the address itself will not be correctly + calculated, therefore we don't use any symbol whose + address may be re-used later on. Let's just reuse the + _dl_start symbol, faking it as a global by renaming it as + another variable through an asm. */ + : "=r" (gotaddr_diff) + : "g" (___CRISv32_dummy) + : "acr"); +#else __asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t" "add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff)); +#endif return gotaddr_diff; } diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/resolve.S uClibc-0.9.28/ldso/ldso/cris/resolve.S --- uClibc-0.9.28.orig/ldso/ldso/cris/resolve.S 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/cris/resolve.S 2006-04-28 00:14:35.000000000 -0600 @@ -17,33 +17,73 @@ .globl _dl_linux_resolve .type _dl_linux_resolve,@function +#ifdef __arch_v32 + +_dl_linux_resolve: + subq 4,$sp + move.d $r0,[$sp] + subq 4,$sp + move.d $r13,[$sp] + subq 4,$sp + move.d $r12,[$sp] + subq 4,$sp + move.d $r11,[$sp] + subq 4,$sp + addoq 5*4,$sp,$acr + move.d $r10,[$sp] + subq 4,$sp + move $mof,$r10 + move.d $r9,[$sp] + subq 4,$sp + move.d [$acr],$r11 + move $srp,[$sp] + lapc _GLOBAL_OFFSET_TABLE_,$r0 + move.d _dl_linux_resolver:PLTG,$r9 + add.d $r0,$r9 + jsr $r9 + nop + move.d $r10,$acr + move [$sp+],$srp + move.d [$sp+],$r9 + move.d [$sp+],$r10 + move.d [$sp+],$r11 + move.d [$sp+],$r12 + move.d [$sp+],$r13 + move.d [$sp+],$r0 + jump $acr + addq 4,$sp + +#else + _dl_linux_resolve: - push $r13 - push $r12 - push $r11 - push $r10 - push $r9 - push $r0 - push $srp - move.d [$sp+7*4],$r11 - move $mof,$r10 + push $r13 + push $r12 + push $r11 + push $r10 + push $r9 + push $r0 + push $srp + move.d [$sp+7*4],$r11 + move $mof,$r10 #ifdef __PIC__ - move.d $pc,$r0 - sub.d .:GOTOFF,$r0 - move.d _dl_linux_resolver:PLTG,$r9 - add.d $r0,$r9 - jsr $r9 + move.d $pc,$r0 + sub.d .:GOTOFF,$r0 + move.d _dl_linux_resolver:PLTG,$r9 + add.d $r0,$r9 + jsr $r9 #else - jsr _dl_linux_resolver + jsr _dl_linux_resolver #endif - move.d $r10,[$sp+7*4] - pop $srp - pop $r0 - pop $r9 - pop $r10 - pop $r11 - pop $r12 - pop $r13 - jump [$sp+] + move.d $r10,[$sp+7*4] + pop $srp + pop $r0 + pop $r9 + pop $r10 + pop $r11 + pop $r12 + pop $r13 + jump [$sp+] + +#endif /* __arch_v32 */ .size _dl_linux_resolve, . - _dl_linux_resolve diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-elf.c uClibc-0.9.28/ldso/ldso/dl-elf.c --- uClibc-0.9.28.orig/ldso/ldso/dl-elf.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/dl-elf.c 2006-05-02 13:50:58.000000000 -0600 @@ -3,7 +3,7 @@ * This file contains the helper routines to load an ELF shared * library into memory and add the symbol table info to the chain. * - * Copyright (C) 2000-2004 by Erik Andersen + * Copyright (C) 2000-2006 by Erik Andersen * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, * David Engel, Hongjiu Lu and Mitch D'Souza * @@ -60,8 +60,8 @@ _dl_cache_addr = (caddr_t) _dl_mmap(0, _dl_cache_size, PROT_READ, MAP_SHARED, fd, 0); _dl_close(fd); if (_dl_mmap_check_error(_dl_cache_addr)) { - _dl_dprintf(2, "%s: can't map cache '%s'\n", - _dl_progname, LDSO_CACHE); + _dl_dprintf(2, "%s:%i: can't map '%s'\n", + _dl_progname, __LINE__, LDSO_CACHE); return -1; } @@ -115,7 +115,7 @@ #endif -void +void _dl_protect_relro (struct elf_resolve *l) { ElfW(Addr) start = ((l->loadaddr + l->relro_addr) @@ -136,27 +136,41 @@ search_for_named_library(const char *name, int secure, const char *path_list, struct dyn_elf **rpnt) { - char *path, *path_n; - char mylibname[2050]; + char *path, *path_n, *mylibname; struct elf_resolve *tpnt; - int done = 0; + int done; if (path_list==NULL) return NULL; - /* We need a writable copy of this string */ - path = _dl_strdup(path_list); - if (!path) { + /* We need a writable copy of this string, but we don't + * need this allocated permanently since we don't want + * to leak memory, so use alloca to put path on the stack */ + done = _dl_strlen(path_list); + path = alloca(done + 1); + + /* another bit of local storage */ + mylibname = alloca(2050); + + /* gcc inlines alloca using a single instruction adjusting + * the stack pointer and no stack overflow check and thus + * no NULL error return. No point leaving in dead code... */ +#if 0 + if (!path || !mylibname) { _dl_dprintf(2, "Out of memory!\n"); _dl_exit(0); } +#endif + + _dl_memcpy(path, path_list, done+1); /* Unlike ldd.c, don't bother to eliminate double //s */ /* Replace colons with zeros in path_list */ /* : at the beginning or end of path maps to CWD */ /* :: anywhere maps CWD */ - /* "" maps to CWD */ + /* "" maps to CWD */ + done = 0; path_n = path; do { if (*path == 0) { @@ -180,71 +194,6 @@ return NULL; } -/* Check if the named library is already loaded... */ -struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname, - int trace_loaded_objects) -{ - const char *pnt, *pnt1; - struct elf_resolve *tpnt1; - const char *libname, *libname2; - static const char libc[] = "libc.so."; - static const char aborted_wrong_lib[] = "%s: aborted attempt to load %s!\n"; - - pnt = libname = full_libname; - - _dl_if_debug_dprint("Checking if '%s' is already loaded\n", full_libname); - /* quick hack to ensure mylibname buffer doesn't overflow. don't - allow full_libname or any directory to be longer than 1024. */ - if (_dl_strlen(full_libname) > 1024) - return NULL; - - /* Skip over any initial initial './' and '/' stuff to - * get the short form libname with no path garbage */ - pnt1 = _dl_strrchr(pnt, '/'); - if (pnt1) { - libname = pnt1 + 1; - } - - /* Make sure they are not trying to load the wrong C library! - * This sometimes happens esp with shared libraries when the - * library path is somehow wrong! */ -#define isdigit(c) (c >= '0' && c <= '9') - if ((_dl_strncmp(libname, libc, 8) == 0) && _dl_strlen(libname) >=8 && - isdigit(libname[8])) - { - /* Abort attempts to load glibc, libc5, etc */ - if ( libname[8]!='0') { - if (!trace_loaded_objects) { - _dl_dprintf(2, aborted_wrong_lib, libname, _dl_progname); - _dl_exit(1); - } - return NULL; - } - } - - /* Critical step! Weed out duplicates early to avoid - * function aliasing, which wastes memory, and causes - * really bad things to happen with weaks and globals. */ - for (tpnt1 = _dl_loaded_modules; tpnt1; tpnt1 = tpnt1->next) { - - /* Skip over any initial initial './' and '/' stuff to - * get the short form libname with no path garbage */ - libname2 = tpnt1->libname; - pnt1 = _dl_strrchr(libname2, '/'); - if (pnt1) { - libname2 = pnt1 + 1; - } - - if (_dl_strcmp(libname2, libname) == 0) { - /* Well, that was certainly easy */ - return tpnt1; - } - } - - return NULL; -} - - /* Used to return error codes back to dlopen et. al. */ unsigned long _dl_error_number; unsigned long _dl_internal_error_number; @@ -271,14 +220,6 @@ libname = pnt + 1; } - /* Critical step! Weed out duplicates early to avoid - * function aliasing, which wastes memory, and causes - * really bad things to happen with weaks and globals. */ - if ((tpnt1=_dl_check_if_named_library_is_loaded(libname, trace_loaded_objects))!=NULL) { - tpnt1->usage_count++; - return tpnt1; - } - _dl_if_debug_dprint("\tfind library='%s'; searching\n", libname); /* If the filename has any '/', try it straight and leave it at that. For IBCS2 compatibility under linux, we substitute the string @@ -290,7 +231,6 @@ if (tpnt1) { return tpnt1; } - //goto goof; } /* @@ -411,56 +351,45 @@ int i, flags, piclib, infile; ElfW(Addr) relro_addr = 0; size_t relro_size = 0; - - /* If this file is already loaded, skip this step */ - tpnt = _dl_check_hashed_files(libname); - if (tpnt) { - if (*rpnt) { - (*rpnt)->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); - _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf)); - (*rpnt)->next->prev = (*rpnt); - *rpnt = (*rpnt)->next; - (*rpnt)->dyn = tpnt; - tpnt->symbol_scope = _dl_symbol_tables; - } - tpnt->usage_count++; - tpnt->libtype = elf_lib; - _dl_if_debug_dprint("file='%s'; already loaded\n", libname); - return tpnt; - } - - /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD), - we don't load the library if it isn't setuid. */ - - if (secure) { - struct stat st; - - if (_dl_stat(libname, &st) || !(st.st_mode & S_ISUID)) - return NULL; - } + struct stat st; libaddr = 0; infile = _dl_open(libname, O_RDONLY, 0); if (infile < 0) { -#if 0 - /* - * NO! When we open shared libraries we may search several paths. - * it is inappropriate to generate an error here. - */ - _dl_dprintf(2, "%s: can't open '%s'\n", _dl_progname, libname); -#endif _dl_internal_error_number = LD_ERROR_NOFILE; return NULL; } + if (_dl_fstat(infile, &st) < 0) { + _dl_internal_error_number = LD_ERROR_NOFILE; + _dl_close(infile); + return NULL; + } + /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD), + we don't load the library if it isn't setuid. */ + if (secure) + if (!(st.st_mode & S_ISUID)) { + _dl_close(infile); + return NULL; + } + + /* Check if file is already loaded */ + for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { + if(tpnt->st_dev == st.st_dev && tpnt->st_ino == st.st_ino) { + /* Already loaded */ + tpnt->usage_count++; + _dl_close(infile); + return tpnt; + } + } header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (_dl_mmap_check_error(header)) { - _dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname); + _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname); _dl_internal_error_number = LD_ERROR_MMAP_FAILED; _dl_close(infile); return NULL; - }; + } _dl_read(infile, header, _dl_pagesize); epnt = (ElfW(Ehdr) *) (intptr_t) header; @@ -475,7 +404,7 @@ _dl_close(infile); _dl_munmap(header, _dl_pagesize); return NULL; - }; + } if ((epnt->e_type != ET_DYN) || (epnt->e_machine != MAGIC1 #ifdef MAGIC2 @@ -490,7 +419,7 @@ _dl_close(infile); _dl_munmap(header, _dl_pagesize); return NULL; - }; + } ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; @@ -502,7 +431,7 @@ _dl_dprintf(2, "%s: '%s' has more than one dynamic section\n", _dl_progname, libname); dynamic_addr = ppnt->p_vaddr; - }; + } if (ppnt->p_type == PT_LOAD) { /* See if this is a PIC library. */ @@ -518,7 +447,7 @@ } } ppnt++; - }; + } maxvma = (maxvma + ADDR_ALIGN) & ~ADDR_ALIGN; minvma = minvma & ~0xffffU; @@ -530,12 +459,12 @@ status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma), maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0); if (_dl_mmap_check_error(status)) { - _dl_dprintf(2, "%s: can't map %s\n", _dl_progname, libname); + _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname); _dl_internal_error_number = LD_ERROR_MMAP_FAILED; _dl_close(infile); _dl_munmap(header, _dl_pagesize); return NULL; - }; + } libaddr = (unsigned long) status; flags |= MAP_FIXED; @@ -567,14 +496,14 @@ ppnt->p_offset & OFFS_ALIGN); if (_dl_mmap_check_error(status)) { - _dl_dprintf(2, "%s: can't map '%s'\n", - _dl_progname, libname); + _dl_dprintf(2, "%s:%i: can't map '%s'\n", + _dl_progname, __LINE__, libname); _dl_internal_error_number = LD_ERROR_MMAP_FAILED; _dl_munmap((char *) libaddr, maxvma - minvma); _dl_close(infile); _dl_munmap(header, _dl_pagesize); return NULL; - }; + } /* Pad the last page with zeroes. */ cpnt = (char *) (status + (ppnt->p_vaddr & ADDR_ALIGN) + @@ -601,21 +530,21 @@ ppnt->p_filesz, LXFLAGS(ppnt->p_flags), flags, infile, ppnt->p_offset & OFFS_ALIGN); if (_dl_mmap_check_error(status)) { - _dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname); + _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname); _dl_internal_error_number = LD_ERROR_MMAP_FAILED; _dl_munmap((char *) libaddr, maxvma - minvma); _dl_close(infile); _dl_munmap(header, _dl_pagesize); return NULL; - }; + } /* if(libaddr == 0 && piclib) { libaddr = (unsigned long) status; flags |= MAP_FIXED; - }; */ - }; + } */ + } ppnt++; - }; + } _dl_close(infile); /* For a non-PIC library, the addresses are all absolute */ @@ -665,6 +594,8 @@ dynamic_addr, 0); tpnt->relro_addr = relro_addr; tpnt->relro_size = relro_size; + tpnt->st_dev = st.st_dev; + tpnt->st_ino = st.st_ino; tpnt->ppnt = (ElfW(Phdr) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff); tpnt->n_phent = epnt->e_phnum; @@ -693,7 +624,7 @@ if (lpnt) { lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]); INIT_GOT(lpnt, tpnt); - }; + } _dl_if_debug_dprint("\n\tfile='%s'; generating link map\n", libname); _dl_if_debug_dprint("\t\tdynamic: %x base: %x\n", dynamic_addr, libaddr); @@ -714,10 +645,12 @@ ElfW(Addr) reloc_addr; if (rpnt->next) - goof += _dl_fixup(rpnt->next, now_flag); + goof = _dl_fixup(rpnt->next, now_flag); + if (goof) + return goof; tpnt = rpnt->dyn; - if(!(tpnt->init_flag & RELOCS_DONE)) + if(!(tpnt->init_flag & RELOCS_DONE)) _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname); if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) { @@ -735,7 +668,6 @@ #endif if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] && !(tpnt->init_flag & RELOCS_DONE)) { - tpnt->init_flag |= RELOCS_DONE; reloc_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]; relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */ @@ -746,14 +678,14 @@ goof += _dl_parse_relocation_information(rpnt, reloc_addr, reloc_size); + tpnt->init_flag |= RELOCS_DONE; } if (tpnt->dynamic_info[DT_BIND_NOW]) now_flag = RTLD_NOW; if (tpnt->dynamic_info[DT_JMPREL] && (!(tpnt->init_flag & JMP_RELOCS_DONE) || (now_flag && !(tpnt->rtld_flags & now_flag)))) { - tpnt->rtld_flags |= now_flag; - tpnt->init_flag |= JMP_RELOCS_DONE; + tpnt->rtld_flags |= now_flag; if (!(tpnt->rtld_flags & RTLD_NOW)) { _dl_parse_lazy_relocation_information(rpnt, tpnt->dynamic_info[DT_JMPREL], @@ -763,6 +695,7 @@ tpnt->dynamic_info[DT_JMPREL], tpnt->dynamic_info[DT_PLTRELSZ]); } + tpnt->init_flag |= JMP_RELOCS_DONE; } return goof; } @@ -770,11 +703,18 @@ /* Minimal printf which handles only %s, %d, and %x */ void _dl_dprintf(int fd, const char *fmt, ...) { - long num; +#if __WORDSIZE > 32 + long int num; +#else + int num; +#endif va_list args; char *start, *ptr, *string; static char *buf; + if (!fmt) + return; + buf = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (_dl_mmap_check_error(buf)) { @@ -784,9 +724,6 @@ start = ptr = buf; - if (!fmt) - return; - if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) { _dl_write(fd, "overflow\n", 11); _dl_exit(20); @@ -818,8 +755,11 @@ case 'd': { char tmp[22]; - num = va_arg(args, long); - +#if __WORDSIZE > 32 + num = va_arg(args, long int); +#else + num = va_arg(args, int); +#endif string = _dl_simple_ltoa(tmp, num); _dl_write(fd, string, _dl_strlen(string)); break; @@ -828,8 +768,11 @@ case 'X': { char tmp[22]; - num = va_arg(args, long); - +#if __WORDSIZE > 32 + num = va_arg(args, long int); +#else + num = va_arg(args, int); +#endif string = _dl_simple_ltoahex(tmp, num); _dl_write(fd, string, _dl_strlen(string)); break; @@ -864,8 +807,10 @@ { __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off); } + +/* we want this in ldso.so and libdl.a but nowhere else */ #ifdef __USE_GNU -#if ! defined LIBDL || (! defined PIC && ! defined __PIC__) +#if ! defined SHARED || (! defined PIC && ! defined __PIC__) int __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, size_t size, void *data), void *data) { @@ -884,6 +829,6 @@ } return ret; } -strong_alias(__dl_iterate_phdr, dl_iterate_phdr); +strong_alias(__dl_iterate_phdr, dl_iterate_phdr) #endif #endif diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-hash.c uClibc-0.9.28/ldso/ldso/dl-hash.c --- uClibc-0.9.28.orig/ldso/ldso/dl-hash.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/dl-hash.c 2006-04-28 00:14:35.000000000 -0600 @@ -57,7 +57,7 @@ /* This is the hash function that is used by the ELF linker to generate the * hash table that each executable and library is required to have. We need * it to decode the hash table. */ -static inline Elf32_Word _dl_elf_hash(const char *name) +static inline Elf_Symndx _dl_elf_hash(const char *name) { unsigned long hash=0; unsigned long tmp; @@ -77,21 +77,6 @@ return hash; } -/* Check to see if a library has already been added to the hash chain. */ -struct elf_resolve *_dl_check_hashed_files(const char *libname) -{ - struct elf_resolve *tpnt; - int len = _dl_strlen(libname); - - for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { - if (_dl_strncmp(tpnt->libname, libname, len) == 0 && - (tpnt->libname[len] == '\0' || tpnt->libname[len] == '.')) - return tpnt; - } - - return NULL; -} - /* * We call this function when we have just read an ELF library or executable. * We add the relevant info to the symbol chain, so that we can resolve all @@ -99,9 +84,10 @@ */ struct elf_resolve *_dl_add_elf_hash_table(const char *libname, char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr, + //attribute_unused unsigned long dynamic_size) { - Elf32_Word *hash_addr; + Elf_Symndx *hash_addr; struct elf_resolve *tpnt; int i; @@ -125,7 +111,7 @@ tpnt->libtype = loaded_file; if (dynamic_info[DT_HASH] != 0) { - hash_addr = (Elf32_Word*)dynamic_info[DT_HASH]; + hash_addr = (Elf_Symndx*)dynamic_info[DT_HASH]; tpnt->nbucket = *hash_addr++; tpnt->nchain = *hash_addr++; tpnt->elf_buckets = hash_addr; diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-startup.c uClibc-0.9.28/ldso/ldso/dl-startup.c --- uClibc-0.9.28.orig/ldso/ldso/dl-startup.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/dl-startup.c 2006-04-28 00:14:35.000000000 -0600 @@ -98,7 +98,7 @@ int (*_dl_elf_main) (int, char **, char **); static void* __rtld_stack_end; /* Points to argc on stack, e.g *((long *)__rtld_stackend) == argc */ -strong_alias(__rtld_stack_end, __libc_stack_end); /* Exported version of __rtld_stack_end */ +strong_alias(__rtld_stack_end, __libc_stack_end) /* Exported version of __rtld_stack_end */ /* When we enter this piece of code, the program stack looks like this: argc argument counter (integer) @@ -307,5 +307,11 @@ SEND_STDERR_DEBUG("transfering control to application @ "); _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_val; SEND_ADDRESS_STDERR_DEBUG(_dl_elf_main, 1); + +#ifndef START + return _dl_elf_main; +#else +#warning You need to update your arch ldso code START(); +#endif } diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/dl-syscalls.h uClibc-0.9.28/ldso/ldso/frv/dl-syscalls.h --- uClibc-0.9.28.orig/ldso/ldso/frv/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/frv/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600 @@ -20,9 +20,10 @@ /* We can't use the real errno in ldso, since it has not yet * been dynamicly linked in yet. */ +#include "sys/syscall.h" extern int _dl_errno; +#undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} -#include "sys/syscall.h" #include /* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */ diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/dl-sysdep.h uClibc-0.9.28/ldso/ldso/frv/dl-sysdep.h --- uClibc-0.9.28.orig/ldso/ldso/frv/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/frv/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 @@ -65,8 +65,6 @@ extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden"))); -#define do_rem(result, n, base) ((result) = (n) % (base)) - /* 16KiB page alignment. Should perhaps be made dynamic using getpagesize(), based on AT_PAGESZ from auxvt? */ #define PAGE_ALIGN 0xffffc000 diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/elfinterp.c uClibc-0.9.28/ldso/ldso/frv/elfinterp.c --- uClibc-0.9.28.orig/ldso/ldso/frv/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/frv/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 @@ -24,7 +24,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include /* __attribute_used__ */ +#include /* Program to load an ELF binary on a linux system, and run it. References to symbols in sharable libraries can be resolved by either @@ -37,7 +37,7 @@ a more than adequate job of explaining everything required to get this working. */ -struct funcdesc_value volatile *__attribute__((__visibility__("hidden"))) +struct funcdesc_value volatile attribute_hidden * _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) { int reloc_type; diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-startup.h uClibc-0.9.28/ldso/ldso/i386/dl-startup.h --- uClibc-0.9.28.orig/ldso/ldso/i386/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/i386/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 @@ -3,7 +3,7 @@ * Architecture specific code used by dl-startup.c * Copyright (C) 2000-2004 by Erik Andersen */ -asm( +__asm__ ( " .text\n" " .align 16\n" " .globl _start\n" @@ -41,9 +41,9 @@ #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) & ARGS)+1) /* Handle relocation of the symbols in the dynamic loader. */ -static inline +static __always_inline void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, - unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) + unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab) { switch (ELF32_R_TYPE(rpnt->r_info)) { @@ -64,8 +64,3 @@ _dl_exit(1); } } - -/* Transfer control to the user's application, once the dynamic loader is - * done. This routine has to exit the current function, then call the - * _dl_elf_main function. */ -#define START() return _dl_elf_main diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-syscalls.h uClibc-0.9.28/ldso/ldso/i386/dl-syscalls.h --- uClibc-0.9.28.orig/ldso/ldso/i386/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/i386/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,5 +1,6 @@ /* We can't use the real errno in ldso, since it has not yet * been dynamicly linked in yet. */ +#include "sys/syscall.h" extern int _dl_errno; +#undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} -#include "sys/syscall.h" diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-sysdep.h uClibc-0.9.28/ldso/ldso/i386/dl-sysdep.h --- uClibc-0.9.28.orig/ldso/ldso/i386/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/i386/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 @@ -25,8 +25,6 @@ struct elf_resolve; extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); -#define do_rem(result, n, base) ((result) = (n) % (base)) - /* 4096 bytes alignment */ #define PAGE_ALIGN 0xfffff000 #define ADDR_ALIGN 0xfff @@ -44,16 +42,18 @@ /* Return the link-time address of _DYNAMIC. Conveniently, this is the first element of the GOT. This must be inlined in a function which uses global data. */ -static inline Elf32_Addr __attribute__ ((unused)) +static inline Elf32_Addr elf_machine_dynamic (void) attribute_unused; +static inline Elf32_Addr elf_machine_dynamic (void) { - register Elf32_Addr *got asm ("%ebx"); + register Elf32_Addr *got __asm__ ("%ebx"); return *got; } /* Return the run-time load address of the shared object. */ -static inline Elf32_Addr __attribute__ ((unused)) +static inline Elf32_Addr elf_machine_load_address (void) attribute_unused; +static inline Elf32_Addr elf_machine_load_address (void) { /* It doesn't matter what variable this is, the reference never makes @@ -61,7 +61,7 @@ via the GOT to make sure the compiler initialized %ebx in time. */ extern int _dl_errno; Elf32_Addr addr; - asm ("leal _dl_start@GOTOFF(%%ebx), %0\n" + __asm__ ("leal _dl_start@GOTOFF(%%ebx), %0\n" "subl _dl_start@GOT(%%ebx), %0" : "=r" (addr) : "m" (_dl_errno) : "cc"); return addr; diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/elfinterp.c uClibc-0.9.28/ldso/ldso/i386/elfinterp.c --- uClibc-0.9.28.orig/ldso/ldso/i386/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/i386/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 @@ -67,12 +67,6 @@ strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; symname = strtab + symtab[symtab_index].st_name; - if (unlikely(reloc_type != R_386_JMP_SLOT)) { - _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", - _dl_progname); - _dl_exit(1); - } - /* Address of the jump instruction to fix up. */ instr_addr = ((unsigned long)this_reloc->r_offset + (unsigned long)tpnt->loadaddr); @@ -81,7 +75,7 @@ /* Get the address of the GOT entry. */ new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); if (unlikely(!new_addr)) { - _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname); _dl_exit(1); } @@ -147,15 +141,15 @@ int reloc_type = ELF32_R_TYPE(rpnt->r_info); #if defined (__SUPPORT_LD_DEBUG__) - _dl_dprintf(2, "can't handle reloc type %s\n", - _dl_reltypes(reloc_type)); + _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", + _dl_reltypes(reloc_type), tpnt->libname); #else - _dl_dprintf(2, "can't handle reloc type %x\n", - reloc_type); + _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", + reloc_type, tpnt->libname); #endif - _dl_exit(-res); + return res; } else if (unlikely(res > 0)) { - _dl_dprintf(2, "can't resolve symbol\n"); + _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname); return res; } } @@ -191,10 +185,8 @@ * might have been intentional. We should not be linking local * symbols here, so all bases should be covered. */ - if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { - _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); - _dl_exit(1); - }; + if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) + return 1; } #if defined (__SUPPORT_LD_DEBUG__) @@ -233,7 +225,7 @@ } break; default: - return -1; /* Calls _dl_exit(1). */ + return -1; } #if defined (__SUPPORT_LD_DEBUG__) @@ -273,7 +265,7 @@ *reloc_addr += (unsigned long)tpnt->loadaddr; break; default: - return -1; /* Calls _dl_exit(1). */ + return -1; } #if defined (__SUPPORT_LD_DEBUG__) diff -urN uClibc-0.9.28.orig/ldso/ldso/ldso.c uClibc-0.9.28/ldso/ldso/ldso.c --- uClibc-0.9.28.orig/ldso/ldso/ldso.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/ldso.c 2006-05-02 13:55:54.000000000 -0600 @@ -39,7 +39,7 @@ #define ALLOW_ZERO_PLTGOT /* Pull in the value of _dl_progname */ -#include "dl-progname.h" +#include LDSO_ELFINTERP /* Global variables used within the shared library loader */ char *_dl_library_path = 0; /* Where we look for libraries */ @@ -74,7 +74,8 @@ * can set an internal breakpoint on it, so that we are notified when the * address mapping is changed in some way. */ -void _dl_debug_state(void) +void _dl_debug_state(void); +void _dl_debug_state() { } @@ -82,9 +83,78 @@ static unsigned char *_dl_mmap_zero = 0; /* Also used by _dl_malloc */ static struct elf_resolve **init_fini_list; -static int nlist; /* # items in init_fini_list */ +static unsigned int nlist; /* # items in init_fini_list */ extern void _start(void); +#ifdef __UCLIBC_HAS_SSP__ +#ifndef __UCLIBC_HAS_SSP_COMPAT__ +#define __UCLIBC_HAS_SSP_COMPAT__ 1 +#endif +# include +uintptr_t stack_chk_guard; +# ifndef THREAD_SET_STACK_GUARD +/* Only exported for architectures that don't store the stack guard canary + * in local thread area. */ +uintptr_t __stack_chk_guard attribute_relro; +# ifdef __UCLIBC_HAS_SSP_COMPAT__ +strong_alias(__stack_chk_guard,__guard) +# endif +# elif __UCLIBC_HAS_SSP_COMPAT__ +uintptr_t __guard attribute_relro; +# endif +#endif + +static void _dl_run_array_forward(unsigned long array, unsigned long size, + ElfW(Addr) loadaddr) +{ + if (array != 0) { + unsigned int j; + unsigned int jm; + ElfW(Addr) *addrs; + jm = size / sizeof (ElfW(Addr)); + addrs = (ElfW(Addr) *) (array + loadaddr); + for (j = 0; j < jm; ++j) { + void (*dl_elf_func) (void); + dl_elf_func = (void (*)(void)) (intptr_t) addrs[j]; + (*dl_elf_func) (); + } + } +} + +void _dl_run_init_array(struct elf_resolve *tpnt); +void _dl_run_init_array(struct elf_resolve *tpnt) +{ + _dl_run_array_forward(tpnt->dynamic_info[DT_INIT_ARRAY], + tpnt->dynamic_info[DT_INIT_ARRAYSZ], + tpnt->loadaddr); +} + +void _dl_app_init_array(void); +void _dl_app_init_array(void) +{ + _dl_run_init_array(_dl_loaded_modules); +} + +void _dl_run_fini_array(struct elf_resolve *tpnt); +void _dl_run_fini_array(struct elf_resolve *tpnt) +{ + if (tpnt->dynamic_info[DT_FINI_ARRAY]) { + ElfW(Addr) *array = (ElfW(Addr) *) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI_ARRAY]); + unsigned int i = (tpnt->dynamic_info[DT_FINI_ARRAYSZ] / sizeof(ElfW(Addr))); + while (i-- > 0) { + void (*dl_elf_func) (void); + dl_elf_func = (void (*)(void)) (intptr_t) array[i]; + (*dl_elf_func) (); + } + } +} + +void _dl_app_fini_array(void); +void _dl_app_fini_array(void) +{ + _dl_run_fini_array(_dl_loaded_modules); +} + static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void) { int i; @@ -95,6 +165,7 @@ if (tpnt->init_flag & FINI_FUNCS_CALLED) continue; tpnt->init_flag |= FINI_FUNCS_CALLED; + _dl_run_fini_array(tpnt); if (tpnt->dynamic_info[DT_FINI]) { void (*dl_elf_func) (void); @@ -112,7 +183,8 @@ ElfW(Phdr) *ppnt; ElfW(Dyn) *dpnt; char *lpntstr; - int i, goof = 0, unlazy = 0, trace_loaded_objects = 0; + unsigned int i; + int unlazy = 0, trace_loaded_objects = 0; struct dyn_elf *rpnt; struct elf_resolve *tcurr; struct elf_resolve *tpnt1; @@ -128,6 +200,7 @@ * setup so we can use _dl_dprintf() to print debug noise * instead of the SEND_STDERR macros used in dl-startup.c */ + _dl_memset(app_tpnt, 0x00, sizeof(*app_tpnt)); /* Store the page size for later use */ _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE; @@ -168,8 +241,8 @@ * Note that for SUID programs we ignore the settings in * LD_LIBRARY_PATH. */ - if ((auxvt[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) || - (auxvt[AT_UID].a_un.a_val != -1 && + if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) || + (auxvt[AT_UID].a_un.a_val != (size_t)-1 && auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val && auxvt[AT_GID].a_un.a_val == auxvt[AT_EGID].a_un.a_val)) { _dl_secure = 0; @@ -196,6 +269,20 @@ unlazy = RTLD_NOW; } + /* sjhill: your TLS init should go before this */ +#ifdef __UCLIBC_HAS_SSP__ + /* Set up the stack checker's canary. */ + stack_chk_guard = _dl_setup_stack_chk_guard (); +# ifdef THREAD_SET_STACK_GUARD + THREAD_SET_STACK_GUARD (stack_chk_guard); +# ifdef __UCLIBC_HAS_SSP_COMPAT__ + __guard = stack_chk_guard; +# endif +# else + __stack_chk_guard = stack_chk_guard; +# endif +#endif + /* At this point we are now free to examine the user application, * and figure out which libraries are supposed to be called. Until * we have this list, we will not be completely ready for dynamic @@ -206,12 +293,12 @@ * different from what the ELF header says for ET_DYN/PIE executables. */ { - int i; - ElfW(Phdr) *ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; + unsigned int idx; + ElfW(Phdr) *phdr = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; - for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) - if (ppnt->p_type == PT_PHDR) { - app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr); + for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++) + if (phdr->p_type == PT_PHDR) { + app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr); break; } @@ -459,8 +546,8 @@ PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); _dl_close(fd); if (preload == (caddr_t) -1) { - _dl_dprintf(_dl_debug_file, "%s: can't map file '%s'\n", - _dl_progname, LDSO_PRELOAD); + _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n", + _dl_progname, __LINE__, LDSO_PRELOAD); break; } @@ -528,15 +615,15 @@ nlist = 0; for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) { - ElfW(Dyn) *dpnt; + ElfW(Dyn) *this_dpnt; nlist++; - for (dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) { - if (dpnt->d_tag == DT_NEEDED) { + for (this_dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; this_dpnt->d_tag; this_dpnt++) { + if (this_dpnt->d_tag == DT_NEEDED) { char *name; struct init_fini_list *tmp; - lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val); + lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val); name = _dl_get_last_path_component(lpntstr); if (_dl_strcmp(name, UCLIBC_LDSO) == 0) continue; @@ -633,7 +720,7 @@ ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; ElfW(Phdr) *myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff); int j; - + tpnt = _dl_add_elf_hash_table(tpnt->libname, (char *)load_addr, tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr, @@ -703,16 +790,14 @@ * order so that COPY directives work correctly. */ if (_dl_symbol_tables) - goof += _dl_fixup(_dl_symbol_tables, unlazy); + if (_dl_fixup(_dl_symbol_tables, unlazy)) + _dl_exit(-1); for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { if (tpnt->relro_size) _dl_protect_relro (tpnt); } - - - /* OK, at this point things are pretty much ready to run. Now we need * to touch up a few items that are required, and then we can let the * user application have at it. Note that the dynamic linker itself @@ -746,6 +831,14 @@ /* Notify the debugger we have added some objects. */ _dl_debug_addr->r_state = RT_ADD; _dl_debug_state(); + + /* Run pre-initialization functions for the executable. */ + _dl_run_array_forward(_dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAY], + _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAYSZ], + _dl_loaded_modules->loadaddr); + + /* Run initialization functions for loaded objects. For the + main executable, they will be run from __uClibc_main. */ for (i = nlist; i; --i) { tpnt = init_fini_list[i-1]; tpnt->init_fini = NULL; /* Clear, since alloca was used */ @@ -762,17 +855,9 @@ (*dl_elf_func) (); } - } -#ifdef _DL_FINI_CRT_COMPAT - /* arches that have moved their ldso FINI handling should skip this part */ - { - int (*_dl_atexit) (void *) = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", - _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT); - if (_dl_atexit) - (*_dl_atexit) (_dl_fini); + _dl_run_init_array(tpnt); } -#endif /* Find the real malloc function and make ldso functions use that from now on */ _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash("malloc", diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-startup.h uClibc-0.9.28/ldso/ldso/m68k/dl-startup.h --- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/m68k/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 @@ -4,23 +4,48 @@ * Copyright (C) 2005 by Erik Andersen */ -asm( - " .text\n" - " .globl _start\n" - " .type _start,@function\n" - "_start:\n" - " .set _start,_dl_start\n" - " .size _start,.-_start\n" - " .previous\n" -); +asm ("\ + .text\n\ + .globl _start\n\ + .type _start,@function\n\ +_start:\n\ + move.l %sp, -(%sp)\n\ + jbsr _dl_start\n\ + addq.l #4, %sp\n\ + /* FALLTHRU */\n\ +\n\ + .globl _dl_start_user\n\ +.type _dl_start_user,@function\n\ +_dl_start_user:\n\ + # Save the user entry point address in %a4.\n\ + move.l %d0, %a4\n\ + # See if we were run as a command with the executable file\n\ + # name as an extra leading argument.\n\ + move.l _dl_skip_args(%pc), %d0\n\ + # Pop the original argument count\n\ + move.l (%sp)+, %d1\n\ + # Subtract _dl_skip_args from it.\n\ + sub.l %d0, %d1\n\ + # Adjust the stack pointer to skip _dl_skip_args words.\n\ + lea (%sp, %d0*4), %sp\n\ + # Push back the modified argument count.\n\ + move.l %d1, -(%sp)\n\ + # Pass our finalizer function to the user in %a1.\n\ + lea _dl_fini(%pc), %a1\n\ + # Initialize %fp with the stack pointer.\n\ + move.l %sp, %fp\n\ + # Jump to the user's entry point.\n\ + jmp (%a4)\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous"); /* Get a pointer to the argv array. On many platforms this can be just * the address if the first argument, on other platforms we need to * do something a little more subtle here. */ -#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned int *) & ARGS) +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) /* Handle relocation of the symbols in the dynamic loader. */ -static inline +static __always_inline void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) { @@ -59,12 +84,3 @@ _dl_exit (1); } } - -/* Transfer control to the user's application, once the dynamic loader is - * done. This routine has to exit the current function, then call the - * _dl_elf_main function. */ -#define START() \ - __asm__ volatile ( \ - "unlk %%a6\n\t" \ - "jmp %0@" \ - : : "a" (_dl_elf_main)); diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-syscalls.h uClibc-0.9.28/ldso/ldso/m68k/dl-syscalls.h --- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/m68k/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,5 +1,6 @@ /* We can't use the real errno in ldso, since it has not yet * been dynamicly linked in yet. */ +#include "sys/syscall.h" extern int _dl_errno; +#undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} -#include "sys/syscall.h" diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-sysdep.h uClibc-0.9.28/ldso/ldso/m68k/dl-sysdep.h --- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/m68k/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 @@ -25,10 +25,6 @@ struct elf_resolve; extern unsigned int _dl_linux_resolver (struct elf_resolve *, int); -/* Define this because we do not want to call .udiv in the library. - Not needed for m68k. */ -#define do_rem(result, n, base) ((result) = (n) % (base)) - /* 4096 bytes alignment */ #define PAGE_ALIGN 0xfffff000 #define ADDR_ALIGN 0xfff diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/elfinterp.c uClibc-0.9.28/ldso/ldso/m68k/elfinterp.c --- uClibc-0.9.28.orig/ldso/ldso/m68k/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/m68k/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 @@ -40,6 +40,8 @@ a more than adequate job of explaining everything required to get this working. */ +#include "ldso.h" + extern int _dl_linux_resolve(void); unsigned int @@ -48,20 +50,20 @@ int reloc_type; ELF_RELOC *this_reloc; char *strtab; - Elf32_Sym *symtab; + ElfW(Sym) *symtab; int symtab_index; - ELF_RELOC *rel_addr; + char *rel_addr; char *new_addr; char **got_addr; - unsigned int instr_addr; + ElfW(Addr) instr_addr; char *symname; - rel_addr = (ELF_RELOC *)tpnt->dynamic_info[DT_JMPREL]; - this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); - reloc_type = ELF32_R_TYPE(this_reloc->r_info); - symtab_index = ELF32_R_SYM(this_reloc->r_info); + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); + reloc_type = ELF_R_TYPE(this_reloc->r_info); + symtab_index = ELF_R_SYM(this_reloc->r_info); - symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; symname = strtab + symtab[symtab_index].st_name; @@ -72,7 +74,7 @@ } /* Address of the jump instruction to fix up. */ - instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr); + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); got_addr = (char **)instr_addr; /* Get the address of the GOT entry. */ @@ -88,159 +90,237 @@ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, - "\n\tpatched: %x ==> %x @ %x", + "\tpatched: %x ==> %x @ %x\n", *got_addr, new_addr, got_addr); } } - if (!_dl_debug_nofixups) { - *got_addr = new_addr; - } -#else - *got_addr = new_addr; + if (!_dl_debug_nofixups) #endif + *got_addr = new_addr; - return (unsigned int)new_addr; + return (unsigned int)new_addr; } -void -_dl_parse_lazy_relocation_information(struct dyn_elf *arg_rpnt, - unsigned long rel_addr, unsigned long rel_size) +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) { - int i; + unsigned int i; char *strtab; - int reloc_type; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; int symtab_index; - Elf32_Sym *symtab; - Elf32_Rela *rpnt; - unsigned int *reloc_addr; - struct elf_resolve *tpnt = arg_rpnt->dyn; - - /* Now parse the relocation information. */ - rpnt = (Elf32_Rela *)rel_addr; - rel_size = rel_size / sizeof (Elf32_Rela); - symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; for (i = 0; i < rel_size; i++, rpnt++) { - reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset); - reloc_type = ELF32_R_TYPE (rpnt->r_info); - symtab_index = ELF32_R_SYM (rpnt->r_info); + int res; - switch (reloc_type) - { - case R_68K_NONE: - break; - case R_68K_JMP_SLOT: - *reloc_addr += (unsigned int) tpnt->loadaddr; - break; - default: - _dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname); + symtab_index = ELF_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " #if defined (__SUPPORT_LD_DEBUG__) - _dl_dprintf (2, "%s ", _dl_reltypes_tab[reloc_type]); + "%s\n", _dl_reltypes(reloc_type)); +#else + "%x\n", reloc_type); #endif - if (symtab_index) - _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name); - _dl_dprintf (2, "\n"); - _dl_exit (1); + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; } } + + return 0; } -int -_dl_parse_relocation_information(struct dyn_elf *arg_rpnt, - unsigned long rel_addr, unsigned long rel_size) +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) { - int i; - char *strtab; int reloc_type; - int goof = 0; - Elf32_Sym *symtab; - Elf32_Rela *rpnt; - unsigned int *reloc_addr; - unsigned int symbol_addr; int symtab_index; - struct elf_resolve *tpnt = arg_rpnt->dyn; - /* Now parse the relocation information */ + char *symname; + ElfW(Sym) *sym; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif - rpnt = (Elf32_Rela *)rel_addr; - rel_size = rel_size / sizeof (Elf32_Rela); + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + sym = &symtab[symtab_index]; + symbol_addr = 0; + symname = strtab + sym->st_name; + + if (symtab_index) { + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type)); + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + }; + } - symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; - strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif - for (i = 0; i < rel_size; i++, rpnt++) { - reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset); - reloc_type = ELF32_R_TYPE (rpnt->r_info); - symtab_index = ELF32_R_SYM (rpnt->r_info); - symbol_addr = 0; - if (symtab_index) { - symbol_addr = (unsigned int) - _dl_find_hash (strtab + symtab[symtab_index].st_name, - tpnt->symbol_scope, tpnt, - elf_machine_type_class(reloc_type)); - - /* We want to allow undefined references to weak symbols - - this might have been intentional. We should not be - linking local symbols here, so all bases should be - covered. */ - if (!symbol_addr - && ELF32_ST_BIND (symtab[symtab_index].st_info) != STB_WEAK) - { - _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", - _dl_progname, strtab + symtab[symtab_index].st_name); - _dl_exit (1); - } - } - switch (reloc_type) - { - case R_68K_NONE: - break; - case R_68K_8: - *(char *) reloc_addr = symbol_addr + rpnt->r_addend; - break; - case R_68K_16: - *(short *) reloc_addr = symbol_addr + rpnt->r_addend; - break; - case R_68K_32: - *reloc_addr = symbol_addr + rpnt->r_addend; - break; - case R_68K_PC8: - *(char *) reloc_addr = (symbol_addr + rpnt->r_addend - - (unsigned int) reloc_addr); - break; - case R_68K_PC16: - *(short *) reloc_addr = (symbol_addr + rpnt->r_addend - - (unsigned int) reloc_addr); - break; - case R_68K_PC32: - *reloc_addr = (symbol_addr + rpnt->r_addend - - (unsigned int) reloc_addr); - break; - case R_68K_GLOB_DAT: - case R_68K_JMP_SLOT: - *reloc_addr = symbol_addr; - break; - case R_68K_RELATIVE: - *reloc_addr = ((unsigned int) tpnt->loadaddr - /* Compatibility kludge. */ - + (rpnt->r_addend ? : *reloc_addr)); - break; - case R_68K_COPY: + switch (reloc_type) { + case R_68K_NONE: + break; + case R_68K_8: + *(char *) reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_16: + *(short *) reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_32: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_PC8: + *(char *) reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_PC16: + *(short *) reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_PC32: + *reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_GLOB_DAT: + case R_68K_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + /* handled by elf_machine_relative() + case R_68K_RELATIVE: + *reloc_addr = ((unsigned int) tpnt->loadaddr + / * Compatibility kludge. * / + + (rpnt->r_addend ? : *reloc_addr)); + */ + break; + case R_68K_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\t%s move %d bytes from %x to %x\n", + symname, sym->st_size, + symbol_addr, reloc_addr); +#endif _dl_memcpy ((void *) reloc_addr, (void *) symbol_addr, - symtab[symtab_index].st_size); - break; - default: - _dl_dprintf (2, "%s: can't handle reloc type ", _dl_progname); -#if defined (__SUPPORT_LD_DEBUG__) - _dl_dprintf (2, "%s ", _dl_reltypes_tab[reloc_type]); -#endif - if (symtab_index) - _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name); - _dl_dprintf (2, "\n"); - _dl_exit (1); - } + sym->st_size); + } else + _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); + break; + + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +#undef LAZY_RELOC_WORKS +#ifdef LAZY_RELOC_WORKS +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + ElfW(Addr) *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + (void)scope; + symtab_index = ELF_R_SYM(rpnt->r_info); + (void)strtab; + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_68K_NONE: + break; + case R_68K_JMP_SLOT: + *reloc_addr += (unsigned int) tpnt->loadaddr; + break; + default: + _dl_exit(1); } - return goof; + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} +#endif + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ +#ifdef LAZY_RELOC_WORKS + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +#else + _dl_parse_relocation_information(rpnt, rel_addr, rel_size); +#endif +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); } diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/resolve.S uClibc-0.9.28/ldso/ldso/m68k/resolve.S --- uClibc-0.9.28.orig/ldso/ldso/m68k/resolve.S 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/m68k/resolve.S 2006-04-28 00:14:35.000000000 -0600 @@ -8,14 +8,16 @@ .globl _dl_linux_resolve .type _dl_linux_resolve,@function _dl_linux_resolve: - moveml %a0/%a1,%sp@- -#ifdef __PIC__ - bsrl _dl_linux_resolver@PLTPC -#else - jbsr _dl_linux_resolver -#endif - moveml %sp@+,%a0/%a1 - addql #8,%sp - jmp @(%d0) -.LFE2: - .size _dl_linux_resolve,.LFE2-_dl_linux_resolve + # Save %a0 (struct return address) and %a1. + move.l %a0, -(%sp) + move.l %a1, -(%sp) + # Call the real address resolver. + jbsr _dl_linux_resolver + # Restore register %a0 and %a1. + move.l (%sp)+, %a1 + move.l (%sp)+, %a0 + # Pop parameters + addq.l #8, %sp + # Call real function. + jmp (%d0) +.size _dl_linux_resolve,.-_dl_linux_resolve diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-startup.h uClibc-0.9.28/ldso/ldso/mips/dl-startup.h --- uClibc-0.9.28.orig/ldso/ldso/mips/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/mips/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 @@ -136,13 +136,3 @@ SEND_STDERR("Aiieeee!"); \ _dl_exit(1); \ } - - -/* - * Transfer control to the user's application, once the dynamic loader - * is done. This routine has to exit the current function, then - * call the _dl_elf_main function. For MIPS, we do it in assembly - * because the stack doesn't get properly restored otherwise. Got look - * at boot1_arch.h - */ -#define START() return _dl_elf_main diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-syscalls.h uClibc-0.9.28/ldso/ldso/mips/dl-syscalls.h --- uClibc-0.9.28.orig/ldso/ldso/mips/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/mips/dl-syscalls.h 2006-05-02 13:39:25.000000000 -0600 @@ -1,7 +1,8 @@ /* We can't use the real errno in ldso, since it has not yet * been dynamicly linked in yet. */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +#include "sys/syscall.h" extern int _dl_errno; +#undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} -#include "sys/syscall.h" - -#define MMAP_HAS_6_ARGS diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-sysdep.h uClibc-0.9.28/ldso/ldso/mips/dl-sysdep.h --- uClibc-0.9.28.orig/ldso/ldso/mips/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/mips/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 @@ -30,7 +30,7 @@ /* Initialization sequence for the application/library GOT. */ #define INIT_GOT(GOT_BASE,MODULE) \ do { \ - unsigned long i; \ + unsigned long idx; \ \ /* Check if this is the dynamic linker itself */ \ if (MODULE->libtype == program_interpreter) \ @@ -41,9 +41,9 @@ GOT_BASE[1] = (unsigned long) MODULE; \ \ /* Add load address displacement to all local GOT entries */ \ - i = 2; \ - while (i < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \ - GOT_BASE[i++] += (unsigned long) MODULE->loadaddr; \ + idx = 2; \ + while (idx < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \ + GOT_BASE[idx++] += (unsigned long) MODULE->loadaddr; \ \ } while (0) @@ -63,8 +63,6 @@ struct elf_resolve; void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy); -#define do_rem(result, n, base) ((result) = (n) % (base)) - /* 4096 bytes alignment */ #define PAGE_ALIGN 0xfffff000 #define ADDR_ALIGN 0xfff diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/elfinterp.c uClibc-0.9.28/ldso/ldso/mips/elfinterp.c --- uClibc-0.9.28.orig/ldso/ldso/mips/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/mips/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 @@ -27,6 +27,8 @@ * SUCH DAMAGE. */ +#include "ldso.h" + extern int _dl_runtime_resolve(void); #define OFFSET_GP_GOT 0x7ff0 @@ -146,7 +148,6 @@ break; default: { - int reloc_type = ELF32_R_TYPE(rpnt->r_info); _dl_dprintf(2, "\n%s: ",_dl_progname); if (symtab_index) diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-startup.h uClibc-0.9.28/ldso/ldso/powerpc/dl-startup.h --- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/powerpc/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 @@ -42,8 +42,10 @@ " bne 2b\n" " addi 6,6,4\n" #endif - /* Pass a termination function pointer (in this case _dl_fini) in r7. */ - " lwz 7,_dl_fini@got(31)\n" + /* Pass a termination function pointer (in this case _dl_fini) in r3. */ + /* Paulus promized he would keep r3 zero in the exec ABI. */ + " lwz 3,_dl_fini@got(31)\n" + " mr 7,3\n" /* Pass _dl_fini in r7 to maintain compat */ " bctr\n" /* Jump to entry point */ " .size _start,.-_start\n" " .previous\n" @@ -78,9 +80,3 @@ _dl_exit(100+ELF32_R_TYPE((RELP)->r_info));\ } \ } -/* - * Transfer control to the user's application, once the dynamic loader - * is done. This routine has to exit the current function, then - * call the _dl_elf_main function. - */ -#define START() return _dl_elf_main diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-syscalls.h uClibc-0.9.28/ldso/ldso/powerpc/dl-syscalls.h --- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/powerpc/dl-syscalls.h 2006-05-02 13:39:14.000000000 -0600 @@ -1,251 +1,8 @@ -/* - * This file contains the system call macros and syscall - * numbers used by the shared library loader. - */ - -#define MMAP_HAS_6_ARGS - -#define __NR_exit 1 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_getpid 20 -#define __NR_getuid 24 -#define __NR_geteuid 49 -#define __NR_getgid 47 -#define __NR_getegid 50 -#define __NR_readlink 85 -#define __NR_mmap 90 -#define __NR_munmap 91 -#define __NR_stat 106 -#define __NR_mprotect 125 - - /* We can't use the real errno in ldso, since it has not yet * been dynamicly linked in yet. */ -extern int _dl_errno; - -/* Here are the macros which define how this platform makes - * system calls. This particular variant does _not_ set - * errno (note how it is disabled in __syscall_return) since - * these will get called before the errno symbol is dynamicly - * linked. */ - -#undef __syscall_return -#define __syscall_return(type) \ - return (__sc_err & 0x10000000 ? _dl_errno = __sc_ret, __sc_ret = -1 : 0), \ - (type) __sc_ret - -#undef __syscall_clobbers -#define __syscall_clobbers \ - "r9", "r10", "r11", "r12" - //"r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" - -#undef _syscall0 -#define _syscall0(type,name) \ -type name(void) \ -{ \ - unsigned long __sc_ret, __sc_err; \ - { \ - register unsigned long __sc_0 __asm__ ("r0"); \ - register unsigned long __sc_3 __asm__ ("r3"); \ - \ - __sc_0 = __NR_##name; \ - __asm__ __volatile__ \ - ("sc \n\t" \ - "mfcr %1 " \ - : "=&r" (__sc_3), "=&r" (__sc_0) \ - : "0" (__sc_3), "1" (__sc_0) \ - : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \ - __sc_ret = __sc_3; \ - __sc_err = __sc_0; \ - } \ - __syscall_return (type); \ -} - -#undef _syscall1 -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ - unsigned long __sc_ret, __sc_err; \ - { \ - register unsigned long __sc_0 __asm__ ("r0"); \ - register unsigned long __sc_3 __asm__ ("r3"); \ - \ - __sc_3 = (unsigned long) (arg1); \ - __sc_0 = __NR_##name; \ - __asm__ __volatile__ \ - ("sc \n\t" \ - "mfcr %1 " \ - : "=&r" (__sc_3), "=&r" (__sc_0) \ - : "0" (__sc_3), "1" (__sc_0) \ - : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \ - __sc_ret = __sc_3; \ - __sc_err = __sc_0; \ - } \ - __syscall_return (type); \ -} - -#undef _syscall2 -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1, type2 arg2) \ -{ \ - unsigned long __sc_ret, __sc_err; \ - { \ - register unsigned long __sc_0 __asm__ ("r0"); \ - register unsigned long __sc_3 __asm__ ("r3"); \ - register unsigned long __sc_4 __asm__ ("r4"); \ - \ - __sc_3 = (unsigned long) (arg1); \ - __sc_4 = (unsigned long) (arg2); \ - __sc_0 = __NR_##name; \ - __asm__ __volatile__ \ - ("sc \n\t" \ - "mfcr %1 " \ - : "=&r" (__sc_3), "=&r" (__sc_0) \ - : "0" (__sc_3), "1" (__sc_0), \ - "r" (__sc_4) \ - : "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \ - __sc_ret = __sc_3; \ - __sc_err = __sc_0; \ - } \ - __syscall_return (type); \ -} - -#undef _syscall3 -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1, type2 arg2, type3 arg3) \ -{ \ - unsigned long __sc_ret, __sc_err; \ - { \ - register unsigned long __sc_0 __asm__ ("r0"); \ - register unsigned long __sc_3 __asm__ ("r3"); \ - register unsigned long __sc_4 __asm__ ("r4"); \ - register unsigned long __sc_5 __asm__ ("r5"); \ - \ - __sc_3 = (unsigned long) (arg1); \ - __sc_4 = (unsigned long) (arg2); \ - __sc_5 = (unsigned long) (arg3); \ - __sc_0 = __NR_##name; \ - __asm__ __volatile__ \ - ("sc \n\t" \ - "mfcr %1 " \ - : "=&r" (__sc_3), "=&r" (__sc_0) \ - : "0" (__sc_3), "1" (__sc_0), \ - "r" (__sc_4), \ - "r" (__sc_5) \ - : "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \ - __sc_ret = __sc_3; \ - __sc_err = __sc_0; \ - } \ - __syscall_return (type); \ -} - -#undef _syscall4 -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ - unsigned long __sc_ret, __sc_err; \ - { \ - register unsigned long __sc_0 __asm__ ("r0"); \ - register unsigned long __sc_3 __asm__ ("r3"); \ - register unsigned long __sc_4 __asm__ ("r4"); \ - register unsigned long __sc_5 __asm__ ("r5"); \ - register unsigned long __sc_6 __asm__ ("r6"); \ - \ - __sc_3 = (unsigned long) (arg1); \ - __sc_4 = (unsigned long) (arg2); \ - __sc_5 = (unsigned long) (arg3); \ - __sc_6 = (unsigned long) (arg4); \ - __sc_0 = __NR_##name; \ - __asm__ __volatile__ \ - ("sc \n\t" \ - "mfcr %1 " \ - : "=&r" (__sc_3), "=&r" (__sc_0) \ - : "0" (__sc_3), "1" (__sc_0), \ - "r" (__sc_4), \ - "r" (__sc_5), \ - "r" (__sc_6) \ - : "r7", "r8", "r9", "r10", "r11", "r12" ); \ - __sc_ret = __sc_3; \ - __sc_err = __sc_0; \ - } \ - __syscall_return (type); \ -} - -#undef _syscall5 -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ -{ \ - unsigned long __sc_ret, __sc_err; \ - { \ - register unsigned long __sc_0 __asm__ ("r0"); \ - register unsigned long __sc_3 __asm__ ("r3"); \ - register unsigned long __sc_4 __asm__ ("r4"); \ - register unsigned long __sc_5 __asm__ ("r5"); \ - register unsigned long __sc_6 __asm__ ("r6"); \ - register unsigned long __sc_7 __asm__ ("r7"); \ - \ - __sc_3 = (unsigned long) (arg1); \ - __sc_4 = (unsigned long) (arg2); \ - __sc_5 = (unsigned long) (arg3); \ - __sc_6 = (unsigned long) (arg4); \ - __sc_7 = (unsigned long) (arg5); \ - __sc_0 = __NR_##name; \ - __asm__ __volatile__ \ - ("sc \n\t" \ - "mfcr %1 " \ - : "=&r" (__sc_3), "=&r" (__sc_0) \ - : "0" (__sc_3), "1" (__sc_0), \ - "r" (__sc_4), \ - "r" (__sc_5), \ - "r" (__sc_6), \ - "r" (__sc_7) \ - : "r8", "r9", "r10", "r11", "r12" ); \ - __sc_ret = __sc_3; \ - __sc_err = __sc_0; \ - } \ - __syscall_return (type); \ -} - - -#undef _syscall6 -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ -{ \ - unsigned long __sc_ret, __sc_err; \ - { \ - register unsigned long __sc_0 __asm__ ("r0"); \ - register unsigned long __sc_3 __asm__ ("r3"); \ - register unsigned long __sc_4 __asm__ ("r4"); \ - register unsigned long __sc_5 __asm__ ("r5"); \ - register unsigned long __sc_6 __asm__ ("r6"); \ - register unsigned long __sc_7 __asm__ ("r7"); \ - register unsigned long __sc_8 __asm__ ("r8"); \ - \ - __sc_3 = (unsigned long) (arg1); \ - __sc_4 = (unsigned long) (arg2); \ - __sc_5 = (unsigned long) (arg3); \ - __sc_6 = (unsigned long) (arg4); \ - __sc_7 = (unsigned long) (arg5); \ - __sc_8 = (unsigned long) (arg6); \ - __sc_0 = __NR_##name; \ - __asm__ __volatile__ \ - ("sc \n\t" \ - "mfcr %1 " \ - : "=&r" (__sc_3), "=&r" (__sc_0) \ - : "0" (__sc_3), "1" (__sc_0), \ - "r" (__sc_4), \ - "r" (__sc_5), \ - "r" (__sc_6), \ - "r" (__sc_7), \ - "r" (__sc_8) \ - : "r9", "r10", "r11", "r12" ); \ - __sc_ret = __sc_3; \ - __sc_err = __sc_0; \ - } \ - __syscall_return (type); \ -} - +#define __UCLIBC_MMAP_HAS_6_ARGS__ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-sysdep.h uClibc-0.9.28/ldso/ldso/powerpc/dl-sysdep.h --- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/powerpc/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 @@ -67,9 +67,6 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); void _dl_init_got(unsigned long *lpnt,struct elf_resolve *tpnt); - -#define do_rem(result, n, base) ((result) = (n) % (base)) - /* 4096 bytes alignment */ #define PAGE_ALIGN 0xfffff000 #define ADDR_ALIGN 0xfff diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/elfinterp.c uClibc-0.9.28/ldso/ldso/powerpc/elfinterp.c --- uClibc-0.9.28.orig/ldso/ldso/powerpc/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/powerpc/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 @@ -29,6 +29,8 @@ * SUCH DAMAGE. */ +#include "ldso.h" + extern int _dl_linux_resolve(void); void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt) @@ -138,7 +140,7 @@ finaladdr = (Elf32_Addr) _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); if (unlikely(!finaladdr)) { - _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname); _dl_exit(1); }; finaladdr += this_reloc->r_addend; @@ -379,15 +381,15 @@ { int reloc_type = ELF32_R_TYPE(rpnt->r_info); #if defined (__SUPPORT_LD_DEBUG__) - _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); + _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", _dl_reltypes(reloc_type), tpnt->libname); #else - _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); + _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", reloc_type, tpnt->libname); #endif - _dl_exit(-res); + return res; } if (unlikely(res >0)) { - _dl_dprintf(2, "can't resolve symbol\n"); + _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname); return res; } } diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-startup.h uClibc-0.9.28/ldso/ldso/sh/dl-startup.h --- uClibc-0.9.28.orig/ldso/ldso/sh/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/sh/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 @@ -55,11 +55,3 @@ default: \ _dl_exit(1); \ } - - -/* - * Transfer control to the user's application, once the dynamic loader - * is done. This routine has to exit the current function, then - * call the _dl_elf_main function. - */ -#define START() return _dl_elf_main; diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sh/dl-syscalls.h --- uClibc-0.9.28.orig/ldso/ldso/sh/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/sh/dl-syscalls.h 2006-05-02 13:39:28.000000000 -0600 @@ -1,7 +1,8 @@ /* We can't use the real errno in ldso, since it has not yet * been dynamicly linked in yet. */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +#include "sys/syscall.h" extern int _dl_errno; +#undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} -#include "sys/syscall.h" - -#define MMAP_HAS_6_ARGS diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sh/dl-sysdep.h --- uClibc-0.9.28.orig/ldso/ldso/sh/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/sh/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 @@ -25,7 +25,7 @@ struct elf_resolve; extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); -static __inline__ unsigned int +static inline unsigned int _dl_urem(unsigned int n, unsigned int base) { int res; @@ -104,7 +104,7 @@ elf_machine_dynamic (void) { register Elf32_Addr *got; - asm ("mov r12,%0" :"=r" (got)); + __asm__ ("mov r12,%0" :"=r" (got)); return *got; } @@ -113,7 +113,7 @@ elf_machine_load_address (void) { Elf32_Addr addr; - asm ("mov.l 1f,r0\n\ + __asm__ ("mov.l 1f,r0\n\ mov.l 3f,r2\n\ add r12,r2\n\ mov.l @(r0,r12),r0\n\ diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/elfinterp.c uClibc-0.9.28/ldso/ldso/sh/elfinterp.c --- uClibc-0.9.28.orig/ldso/ldso/sh/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/sh/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 @@ -39,6 +39,8 @@ a more than adequate job of explaining everything required to get this working. */ +#include "ldso.h" + extern int _dl_linux_resolve(void); unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-startup.h uClibc-0.9.28/ldso/ldso/sh64/dl-startup.h --- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/sh64/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 @@ -115,12 +115,3 @@ default: \ _dl_exit(1); \ } - -/* - * Transfer control to the user's application, once the dynamic loader - * is done. This routine has to exit the current function, then - * call the _dl_elf_main function. - */ - -#define START() return _dl_elf_main; - diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sh64/dl-syscalls.h --- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/sh64/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,8 +1,9 @@ /* We can't use the real errno in ldso, since it has not yet * been dynamicly linked in yet. */ +#include "sys/syscall.h" extern int _dl_errno; +#undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} -#include "sys/syscall.h" #undef __syscall_return #define __syscall_return(type, res) \ diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sh64/dl-sysdep.h --- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/sh64/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 @@ -25,8 +25,6 @@ struct elf_resolve; extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); -#define do_rem(result, n, base) ((result) = (n) % (base)) - /* 4096 bytes alignment */ #define PAGE_ALIGN 0xfffff000 #define ADDR_ALIGN 0xfff diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/elfinterp.c uClibc-0.9.28/ldso/ldso/sh64/elfinterp.c --- uClibc-0.9.28.orig/ldso/ldso/sh64/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/sh64/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 @@ -41,6 +41,8 @@ a more than adequate job of explaining everything required to get this working. */ +#include "ldso.h" + extern int _dl_linux_resolve(void); unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-startup.h uClibc-0.9.28/ldso/ldso/sparc/dl-startup.h --- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/sparc/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 @@ -3,15 +3,46 @@ * needed for this architecture. See arm/boot1_arch.h for an example of what * can be done. */ -asm( - " .text\n" - " .global _start\n" - " .type _start,%function\n" - "_start:\n" - " .set _start,_dl_start\n" - " .size _start,.-_start\n" - " .previous\n" -); + +asm ("\ + .text\n\ + .global _start\n\ + .type _start,%function\n\ + .align 32\n\ +_start:\n\ + /* Allocate space for functions to drop their arguments. */\n\ + sub %sp, 6*4, %sp\n\ + /* Pass pointer to argument block to _dl_start. */\n\ + call _dl_start\n\ + add %sp, 22*4, %o0\n\ + /* FALTHRU */\n\ + .globl _dl_start_user\n\ + .type _dl_start_user, @function\n\ +_dl_start_user:\n\ + /* Load the PIC register. */\n\ +1: call 2f\n\ + sethi %hi(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\ +2: or %l7, %lo(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\ + add %l7, %o7, %l7\n\ + /* Save the user entry point address in %l0 */\n\ + mov %o0, %l0\n\ + /* See if we were run as a command with the executable file name as an\n\ + extra leading argument. If so, adjust the contents of the stack. */\n\ + sethi %hi(_dl_skip_args), %g2\n\ + or %g2, %lo(_dl_skip_args), %g2\n\ + ld [%l7+%g2], %i0\n\ + ld [%i0], %i0\n\ + tst %i0\n\ + /* Pass our finalizer function to the user in %g1. */\n\ + sethi %hi(_dl_fini), %g1\n\ + or %g1, %lo(_dl_fini), %g1\n\ + ld [%l7+%g1], %g1\n\ + /* Jump to the user's entry point and deallocate the extra stack we got. */\n\ + jmp %l0\n\ + add %sp, 6*4, %sp\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous\n\ +"); /* * Get a pointer to the argv array. On many platforms this can be just @@ -19,17 +50,15 @@ * do something a little more subtle here. We assume that argc is stored * at the word just below the argvp that we return here. */ -#define GET_ARGV(ARGVP, ARGS) __asm__("\tadd %%fp,68,%0\n" : "=r" (ARGVP)); +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) /* * Here is a macro to perform a relocation. This is only used when * bootstrapping the dynamic loader. */ #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ - switch(ELF32_R_TYPE((RELP)->r_info)) { \ +switch(ELF_R_TYPE((RELP)->r_info)) { \ case R_SPARC_32: \ - *REL = SYMBOL + (RELP)->r_addend; \ - break; \ case R_SPARC_GLOB_DAT: \ *REL = SYMBOL + (RELP)->r_addend; \ break; \ @@ -38,7 +67,6 @@ REL[2] = 0x81c06000 | (SYMBOL & 0x3ff); \ break; \ case R_SPARC_NONE: \ - break; \ case R_SPARC_WDISP30: \ break; \ case R_SPARC_RELATIVE: \ @@ -46,18 +74,4 @@ break; \ default: \ _dl_exit(1); \ - } - -/* - * Transfer control to the user's application, once the dynamic loader - * is done. The crt calls atexit with $g1 if not null, so we need to - * ensure that it contains NULL. - */ - -#define START() \ - __asm__ volatile ( \ - "add %%g0,%%g0,%%g1\n\t" \ - "jmpl %0, %%o7\n\t" \ - "restore %%g0,%%g0,%%g0\n\t" \ - : /*"=r" (status) */ : \ - "r" (_dl_elf_main): "g1", "o0", "o1") +} diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sparc/dl-syscalls.h --- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/sparc/dl-syscalls.h 2006-05-02 13:39:21.000000000 -0600 @@ -1,187 +1,8 @@ -/* - * This file contains the system call macros and syscall - * numbers used by the shared library loader. - * - * NOTE: This should be integrated/moved to - * sysdeps/linux/sparc/bits/syscalls.h at some point ... - */ - -#define MMAP_HAS_6_ARGS - -#define __NR_exit 1 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_getpid 20 -#define __NR_getuid 24 -#define __NR_getgid 47 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_readlink 58 -#define __NR_mmap 71 -#define __NR_munmap 73 -#define __NR_stat 38 -#define __NR_mprotect 74 - /* We can't use the real errno in ldso, since it has not yet * been dynamicly linked in yet. */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +#include "sys/syscall.h" extern int _dl_errno; +#undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} - -/* Here are the macros which define how this platform makes - * system calls. This particular variant does _not_ set - * errno (note how _dl_errno is used in __syscall_return) since - * these will get called before the errno symbol is dynamicly - * linked. */ - -#define __syscall_return(type, res) \ -do { \ - if (res < -255 || res >= 0) \ - return (type) res; \ - __set_errno(-res); \ - res = -1; \ - return (type) res; \ -} while (0) - -#define _syscall0(type,name) \ -type name(void) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res)\ - : "r" (__g1) \ - : "o0", "cc"); \ - __syscall_return(type, __res); \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - register long __o0 __asm__ ("o0") = (long)(arg1); \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__g1) \ - : "cc"); \ - __syscall_return(type, __res); \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - register long __o0 __asm__ ("o0") = (long)(arg1); \ - register long __o1 __asm__ ("o1") = (long)(arg2); \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__g1) \ - : "cc"); \ - __syscall_return(type, __res); \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - register long __o0 __asm__ ("o0") = (long)(arg1); \ - register long __o1 __asm__ ("o1") = (long)(arg2); \ - register long __o2 __asm__ ("o2") = (long)(arg3); \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \ - : "cc"); \ - __syscall_return(type, __res); \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - register long __o0 __asm__ ("o0") = (long)(arg1); \ - register long __o1 __asm__ ("o1") = (long)(arg2); \ - register long __o2 __asm__ ("o2") = (long)(arg3); \ - register long __o3 __asm__ ("o3") = (long)(arg4); \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \ - : "cc"); \ - __syscall_return(type, __res); \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - register long __o0 __asm__ ("o0") = (long)(arg1); \ - register long __o1 __asm__ ("o1") = (long)(arg2); \ - register long __o2 __asm__ ("o2") = (long)(arg3); \ - register long __o3 __asm__ ("o3") = (long)(arg4); \ - register long __o4 __asm__ ("o4") = (long)(arg5); \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \ - : "cc"); \ - __syscall_return(type, __res); \ -} - -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5,type6,arg6) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - register long __o0 __asm__ ("o0") = (long)(arg1); \ - register long __o1 __asm__ ("o1") = (long)(arg2); \ - register long __o2 __asm__ ("o2") = (long)(arg3); \ - register long __o3 __asm__ ("o3") = (long)(arg4); \ - register long __o4 __asm__ ("o4") = (long)(arg5); \ - register long __o5 __asm__ ("o5") = (long)(arg6); \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__o5), "r" (__g1) \ - : "cc"); \ - __syscall_return(type, __res); \ -} diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sparc/dl-sysdep.h --- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/sparc/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 @@ -1,9 +1,9 @@ - +/* vi: set sw=4 ts=4: */ /* * Various assmbly language/system dependent hacks that are required * so that we can minimize the amount of platform specific code. + * Copyright (C) 2000-2004 by Erik Andersen */ -#define LINUXBIN /* Define this if the system uses RELOCA. */ #define ELF_USES_RELOCA @@ -31,19 +31,14 @@ #undef MAGIC2 /* Used for error messages */ -#define ELF_TARGET "Sparc" +#define ELF_TARGET "sparc" -#ifndef COMPILE_ASM -extern unsigned int _dl_linux_resolver(unsigned int reloc_entry, - unsigned int * i); -#endif +struct elf_resolve; +unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); /* * Define this if you want a dynamic loader that works on Solaris. */ -#ifndef __linux__ -#define SOLARIS_COMPATIBLE -#endif #ifndef COMPILE_ASM /* Cheap modulo implementation, taken from arm/ld_sysdep.h. */ @@ -87,13 +82,6 @@ #define do_rem(result, n, base) ((result) = sparc_mod(n, base)) #endif -/* - * dbx wants the binder to have a specific name. Mustn't disappoint it. - */ -#ifdef SOLARIS_COMPATIBLE -#define _dl_linux_resolve _elf_rtbndr -#endif - /* 4096 bytes alignment */ /* ...but 8192 is required for mmap() on sparc64 kernel */ #define PAGE_ALIGN 0xffffe000 @@ -160,7 +148,7 @@ elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, Elf32_Word relative_count) { - Elf32_Rela * rpnt = (void *)rel_addr; + Elf32_Rela * rpnt = (void *)rel_addr; --rpnt; do { Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/elfinterp.c uClibc-0.9.28/ldso/ldso/sparc/elfinterp.c --- uClibc-0.9.28.orig/ldso/ldso/sparc/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/sparc/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 @@ -33,236 +33,340 @@ an ELF sharable library or a linux style of shared library. */ /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have - I ever taken any courses on internals. This program was developed using - information available through the book "UNIX SYSTEM V RELEASE 4, - Programmers guide: Ansi C and Programming Support Tools", which did - a more than adequate job of explaining everything required to get this - working. */ + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +/* Some SPARC opcodes we need to use for self-modifying code. */ +#define OPCODE_NOP 0x01000000 /* nop */ +#define OPCODE_CALL 0x40000000 /* call ?; add PC-rel word address */ +#define OPCODE_SETHI_G1 0x03000000 /* sethi ?, %g1; add value>>10 */ +#define OPCODE_JMP_G1 0x81c06000 /* jmp %g1+?; add lo 10 bits of value */ +#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */ +#define OPCODE_BA 0x30800000 /* b,a ?; add PC-rel word address */ extern int _dl_linux_resolve(void); -unsigned int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt) +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) { - int reloc_type; - Elf32_Rela * this_reloc; - char * strtab; - Elf32_Sym * symtab; - Elf32_Rela * rel_addr; - struct elf_resolve * tpnt; - int symtab_index; - char * new_addr; - char ** got_addr; - unsigned int instr_addr; - tpnt = (struct elf_resolve *) plt[2]; - - rel_addr = (Elf32_Rela *)tpnt->dynamic_info[DT_JMPREL]; - - /* - * Generate the correct relocation index into the .rela.plt section. - */ - reloc_entry = (reloc_entry >> 10) - 0xc; - - this_reloc = (Elf32_Rela *) ((char *) rel_addr + reloc_entry); - - reloc_type = ELF32_R_TYPE(this_reloc->r_info); - symtab_index = ELF32_R_SYM(this_reloc->r_info); - - symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; - strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; - -#ifdef __SUPPORT_LD_DEBUG__ - if (_dl_debug_symbols) { - _dl_dprintf(2, "tpnt = %x\n", tpnt); - _dl_dprintf(2, "reloc = %x\n", this_reloc); - _dl_dprintf(2, "symtab = %x\n", symtab); - _dl_dprintf(2, "strtab = %x\n", strtab); - } -#endif - - - if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) { - _dl_dprintf(2, "%s: incorrect relocation type in jump relocations (%d)\n", - _dl_progname, reloc_type); - _dl_exit(30); - }; - - /* Address of jump instruction to fix up */ - instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr); - got_addr = (char **) instr_addr; - -#ifdef __SUPPORT_LD_DEBUG__ - if (_dl_debug_symbols) { - _dl_dprintf(2, "symtab_index %x\n", symtab_index); - - _dl_dprintf(2, "Resolving symbol %s\n", - strtab + symtab[symtab_index].st_name); - } -#endif - - /* Get the address of the GOT entry */ - new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, - tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); - if(unlikely(!new_addr)) { - _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", - _dl_progname, strtab + symtab[symtab_index].st_name); - _dl_exit(31); - }; + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + ElfW(Addr) instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + /* + * Generate the correct relocation index into the .rela.plt section. + */ + reloc_entry = (reloc_entry >> 10) - 0xc; + + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); + reloc_type = ELF_R_TYPE(this_reloc->r_info); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); + _dl_exit(1); + } + + /* Address of the jump instruction to fix up. */ + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } #if defined (__SUPPORT_LD_DEBUG__) - if ((unsigned long) got_addr < 0x40000000) - { - if (_dl_debug_bindings) - { - _dl_dprintf(_dl_debug_file, "\nresolve function: %s", - strtab + symtab[symtab_index].st_name); - if(_dl_debug_detail) _dl_dprintf(_dl_debug_file, - "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr); + if ((unsigned long)got_addr < 0x40000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\tpatched: %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); } } - if (!_dl_debug_nofixups) { + if (!_dl_debug_nofixups) +#endif + { got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff)); got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff)); } + + return (unsigned long)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " +#if defined (__SUPPORT_LD_DEBUG__) + "%s\n", _dl_reltypes(reloc_type)); #else - got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff)); - got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff)); + "%x\n", reloc_type); #endif + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} - _dl_dprintf(2, "Address = %x\n",new_addr); - _dl_exit(32); +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + ElfW(Sym) *sym; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + sym = &symtab[symtab_index]; + symbol_addr = 0; + symname = strtab + sym->st_name; + + if (symtab_index) { + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type)); + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif - return (unsigned int) new_addr; + symbol_addr += rpnt->r_addend; /* Assume copy relocs have zero addend. */ + + switch (reloc_type) { + case R_SPARC_NONE: + break; + +#if 0 /* these dont really seem to be useful */ + case R_SPARC_8: + *(char *) reloc_addr = symbol_addr; + break; + case R_SPARC_16: + *(short *) reloc_addr = symbol_addr; + break; + case R_SPARC_DISP8: + *(char *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr; + break; + case R_SPARC_DISP16: + *(short *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr; + break; +#endif + + case R_SPARC_DISP32: + *reloc_addr = symbol_addr - (unsigned int) reloc_addr; + break; + + case R_SPARC_LO10: + if (!symbol_addr) + symbol_addr = tpnt->loadaddr + rpnt->r_addend; + else + symbol_addr += rpnt->r_addend; + *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff); + break; + + case R_SPARC_GLOB_DAT: + case R_SPARC_32: + *reloc_addr = symbol_addr; + break; + + case R_SPARC_JMP_SLOT: +/* +value = symbol_addr; +value += reloc->r_addend; +disp = value - reloc_addr; +reloc_addr[1] = OPCODE_JMP_G1 | (value & 0x3ff); +reloc_addr[0] = OPCODE_SETHI_G1 | (value >> 10); + reloc_addr[1] = OPCODE_JMP_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) & 0x3ff); + reloc_addr[0] = OPCODE_SETHI_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) >> 10); +*/ + reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff); + reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff); + break; + + case R_SPARC_RELATIVE: + *reloc_addr += tpnt->loadaddr + rpnt->r_addend; + break; + + case R_SPARC_WDISP30: + *reloc_addr = (*reloc_addr & 0xc0000000)| + ((symbol_addr - (unsigned int) reloc_addr) >> 2); + break; + + case R_SPARC_HI22: + if (!symbol_addr) + symbol_addr = tpnt->loadaddr + rpnt->r_addend; + else + symbol_addr += rpnt->r_addend; + *reloc_addr = (*reloc_addr & 0xffc00000) | (symbol_addr >> 10); + break; + + case R_SPARC_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\t%s move %d bytes from %x to %x\n", + symname, sym->st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + sym->st_size); + } else + _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); + break; + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +#undef __SPARC_LAZY_RELOC_WORKS +#ifdef __SPARC_LAZY_RELOC_WORKS +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + ElfW(Addr) *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + (void)scope; + symtab_index = ELF_R_SYM(rpnt->r_info); + (void)strtab; + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_SPARC_NONE: + break; + case R_SPARC_JMP_SLOT: + break; + default: + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; } +#endif -void _dl_parse_lazy_relocation_information(struct dyn_elf *arg_rpnt, - unsigned long rel_addr, unsigned long rel_size) -{ - int i; - char * strtab; - int reloc_type; - int symtab_index; - Elf32_Sym * symtab; - Elf32_Rela * rpnt; - unsigned int * reloc_addr; - struct elf_resolve * tpnt = arg_rpnt->dyn; - - /* Now parse the relocation information */ - rpnt = (Elf32_Rela *)rel_addr; - - symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; - strtab = ( char *)tpnt->dynamic_info[DT_STRTAB]; - - for(i=0; i< rel_size; i += sizeof(Elf32_Rela), rpnt++){ - reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset); - reloc_type = ELF32_R_TYPE(rpnt->r_info); - symtab_index = ELF32_R_SYM(rpnt->r_info); - - switch(reloc_type){ - case R_SPARC_NONE: - break; - case R_SPARC_JMP_SLOT: - break; - default: - _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", _dl_progname); -#if defined (__SUPPORT_LD_DEBUG__) - _dl_dprintf(2, "%s ", _dl_reltypes_tab[reloc_type]); -#endif - if(symtab_index) _dl_dprintf(2, "'%s'\n", - strtab + symtab[symtab_index].st_name); - _dl_exit(33); - }; - }; -} - -int _dl_parse_relocation_information(struct dyn_elf *arg_rpnt, - unsigned long rel_addr, unsigned long rel_size) -{ - int i; - char * strtab; - int reloc_type; - int goof = 0; - Elf32_Sym * symtab; - Elf32_Rela * rpnt; - unsigned int * reloc_addr; - unsigned int symbol_addr; - int symtab_index; - struct elf_resolve * tpnt = arg_rpnt->dyn; - /* Now parse the relocation information */ - - rpnt = (Elf32_Rela *)rel_addr; - - symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; - strtab = ( char *)tpnt->dynamic_info[DT_STRTAB]; - - for(i=0; i< rel_size; i+= sizeof(Elf32_Rela), rpnt++){ - reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset); - reloc_type = ELF32_R_TYPE(rpnt->r_info); - symtab_index = ELF32_R_SYM(rpnt->r_info); - symbol_addr = 0; - - if(symtab_index) { - - symbol_addr = (unsigned int) - _dl_find_hash(strtab + symtab[symtab_index].st_name, - tpnt->symbol_scope, tpnt, elf_machine_type_class(reloc_type)); - - if(!symbol_addr && - ELF32_ST_BIND(symtab [symtab_index].st_info) != STB_WEAK) { - _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", - _dl_progname, strtab + symtab[symtab_index].st_name); - _dl_exit (1); - }; - }; - switch(reloc_type){ - case R_SPARC_NONE: - break; - case R_SPARC_32: - *reloc_addr = symbol_addr + rpnt->r_addend; - break; - case R_SPARC_DISP32: - *reloc_addr = symbol_addr + rpnt->r_addend - (unsigned int) reloc_addr; - break; - case R_SPARC_GLOB_DAT: - *reloc_addr = symbol_addr + rpnt->r_addend; - break; - case R_SPARC_JMP_SLOT: - reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff); - reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff); - break; - case R_SPARC_RELATIVE: - *reloc_addr += (unsigned int) tpnt->loadaddr + rpnt->r_addend; - break; - case R_SPARC_HI22: - if (!symbol_addr) - symbol_addr = tpnt->loadaddr + rpnt->r_addend; - else - symbol_addr += rpnt->r_addend; - *reloc_addr = (*reloc_addr & 0xffc00000)|(symbol_addr >> 10); - break; - case R_SPARC_LO10: - if (!symbol_addr) - symbol_addr = tpnt->loadaddr + rpnt->r_addend; - else - symbol_addr += rpnt->r_addend; - *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff); - break; - case R_SPARC_WDISP30: - *reloc_addr = (*reloc_addr & 0xc0000000)| - ((symbol_addr - (unsigned int) reloc_addr) >> 2); - break; - case R_SPARC_COPY: - _dl_memcpy((void *) reloc_addr, (void *) symbol_addr, symtab[symtab_index].st_size); - break; - default: - _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname); -#if defined (__SUPPORT_LD_DEBUG__) - _dl_dprintf(2, "%s ", _dl_reltypes_tab[reloc_type]); -#endif - if (symtab_index) - _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name); - _dl_exit(34); - }; +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ +#ifdef __SPARC_LAZY_RELOC_WORKS + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +#else + _dl_parse_relocation_information(rpnt, rel_addr, rel_size); +#endif +} - }; - return goof; +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); } diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-debug.h uClibc-0.9.28/ldso/ldso/x86_64/dl-debug.h --- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-debug.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/x86_64/dl-debug.h 2006-04-28 00:14:35.000000000 -0600 @@ -30,7 +30,10 @@ */ static const char *_dl_reltypes_tab[] = { - [0] "R_X86_64_NONE", "R_X86_64_64", "R_X86_64_PC32", "R_X86_64_GOT32", - [4] "R_X86_64_PLT32", "R_X86_64_COPY", "R_X86_64_GLOB_DAT", "R_X86_64_JUMP_SLOT", - [8] "R_X86_64_RELATIVE", "R_X86_64_GOTPCREL", "R_X86_64_32" + [ 0] "R_X86_64_NONE", "R_X86_64_64", "R_X86_64_PC32", "R_X86_64_GOT32", + [ 4] "R_X86_64_PLT32", "R_X86_64_COPY", "R_X86_64_GLOB_DAT", "R_X86_64_JUMP_SLOT", + [ 8] "R_X86_64_RELATIVE", "R_X86_64_GOTPCREL", "R_X86_64_32", "R_X86_64_32S", + [12] "R_X86_64_16", "R_X86_64_PC16", "R_X86_64_8", "R_X86_64_PC8", + [16] "R_X86_64_DTPMOD64", "R_X86_64_DTPOFF64", "R_X86_64_TPOFF64", "R_X86_64_TLSGD", + [20] "R_X86_64_TLSLD", "R_X86_64_DTPOFF32", "R_X86_64_GOTTPOFF", "R_X86_64_TPOFF32" }; diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-startup.h uClibc-0.9.28/ldso/ldso/x86_64/dl-startup.h --- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/x86_64/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 @@ -6,7 +6,7 @@ * * Parts taken from glibc/sysdeps/x86_64/dl-machine.h */ -asm( +__asm__ ( " .text\n" " .align 16\n" " .global _start\n" @@ -42,10 +42,10 @@ /* Handle relocation of the symbols in the dynamic loader. */ static __always_inline -void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, - unsigned long symbol_addr, unsigned long load_addr, Elf64_Sym *sym) +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr, + ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Sym) *sym) { - switch (ELF64_R_TYPE(rpnt->r_info)) { + switch (ELF_R_TYPE(rpnt->r_info)) { case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: *reloc_addr = symbol_addr + rpnt->r_addend; @@ -63,8 +63,3 @@ _dl_exit(1); } } - -/* Transfer control to the user's application, once the dynamic loader is - * done. This routine has to exit the current function, then call the - * _dl_elf_main function. */ -#define START() return _dl_elf_main diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-syscalls.h uClibc-0.9.28/ldso/ldso/x86_64/dl-syscalls.h --- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/x86_64/dl-syscalls.h 2006-05-02 13:39:17.000000000 -0600 @@ -1,7 +1,8 @@ /* We can't use the real errno in ldso, since it has not yet * been dynamicly linked in yet. */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +#include "sys/syscall.h" extern int _dl_errno; +#undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} -#include "sys/syscall.h" - -#define MMAP_HAS_6_ARGS diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-sysdep.h uClibc-0.9.28/ldso/ldso/x86_64/dl-sysdep.h --- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/x86_64/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 @@ -41,8 +41,6 @@ struct elf_resolve; extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); -#define do_rem(result, n, base) ((result) = (n) % (base)) - /* 4096 bytes alignment */ #define PAGE_ALIGN 0xfffff000 #define ADDR_ALIGN 0xfff @@ -90,7 +88,7 @@ and compare it with the current value that we can get via an RIP relative addressing mode. */ - asm ("movq 1f(%%rip), %1\n" + __asm__ ("movq 1f(%%rip), %1\n" "0:\tleaq _dl_start(%%rip), %0\n\t" "subq %1, %0\n\t" ".section\t.data\n" diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/elfinterp.c uClibc-0.9.28/ldso/ldso/x86_64/elfinterp.c --- uClibc-0.9.28.orig/ldso/ldso/x86_64/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/ldso/x86_64/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 @@ -165,6 +165,7 @@ int reloc_type; int symtab_index; char *symname; + ElfW(Sym) *sym; ElfW(Addr) *reloc_addr; ElfW(Addr) symbol_addr; #if defined (__SUPPORT_LD_DEBUG__) @@ -174,8 +175,9 @@ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); reloc_type = ELF_R_TYPE(rpnt->r_info); symtab_index = ELF_R_SYM(rpnt->r_info); + sym = &symtab[symtab_index]; symbol_addr = 0; - symname = strtab + symtab[symtab_index].st_name; + symname = strtab + sym->st_name; if (symtab_index) { symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, @@ -185,7 +187,7 @@ * might have been intentional. We should not be linking local * symbols here, so all bases should be covered. */ - if (unlikely(!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { + if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); _dl_exit(1); }; @@ -209,7 +211,7 @@ case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: - *reloc_addr = symbol_addr; + *reloc_addr = symbol_addr + rpnt->r_addend; break; /* handled by elf_machine_relative() @@ -217,33 +219,33 @@ *reloc_addr = map->l_addr + rpnt->r_addend; break; */ -#if 0 case R_X86_64_DTPMOD64: + *reloc_addr = 1; break; case R_X86_64_DTPOFF64: - *reloc_addr = symbol_addr + rpnt->r_addend; + *reloc_addr = sym->st_value + rpnt->r_addend; break; case R_X86_64_TPOFF64: - *reloc_addr = symbol_addr + rpnt->r_addend; + *reloc_addr = sym->st_value + rpnt->r_addend - symbol_addr; break; case R_X86_64_32: - *reloc_addr = symbol_addr + rpnt->r_addend; + *(unsigned int *) reloc_addr = symbol_addr + rpnt->r_addend; + /* XXX: should check for overflow eh ? */ break; -#endif case R_X86_64_COPY: if (symbol_addr) { #if defined (__SUPPORT_LD_DEBUG__) if (_dl_debug_move) _dl_dprintf(_dl_debug_file, "\t%s move %d bytes from %x to %x\n", - symname, symtab[symtab_index].st_size, + symname, sym->st_size, symbol_addr, reloc_addr); #endif _dl_memcpy((char *)reloc_addr, (char *)symbol_addr, - symtab[symtab_index].st_size); + sym->st_size); } else _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); break; @@ -261,7 +263,6 @@ return 0; } -#if 0 static int _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) @@ -288,7 +289,7 @@ case R_X86_64_NONE: break; case R_X86_64_JUMP_SLOT: - *reloc_addr = tpnt->loadaddr + symtab[symtab_index].st_value; + *reloc_addr += (unsigned long)tpnt->loadaddr; break; default: _dl_exit(1); @@ -302,17 +303,13 @@ return 0; } -#endif void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) { - _dl_parse_relocation_information(rpnt, rel_addr, rel_size); -/* jump slot isnt working (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); -*/ } int diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/resolve.S uClibc-0.9.28/ldso/ldso/x86_64/resolve.S --- uClibc-0.9.28.orig/ldso/ldso/x86_64/resolve.S 1969-12-31 17:00:00.000000000 -0700 +++ uClibc-0.9.28/ldso/ldso/x86_64/resolve.S 2006-04-28 00:14:35.000000000 -0600 @@ -0,0 +1,63 @@ +/* + * This function is _not_ called directly. It is jumped to (so no return + * address is on the stack) when attempting to use a symbol that has not yet + * been resolved. The first time a jump symbol (such as a function call inside + * a shared library) is used (before it gets resolved) it will jump here to + * _dl_linux_resolve. When we get called the stack looks like this: + * reloc_entry + * tpnt + * + * This function saves all the registers, puts a copy of reloc_entry and tpnt + * on the stack (as function arguments) then make the function call + * _dl_linux_resolver(tpnt, reloc_entry). _dl_linux_resolver() figures out + * where the jump symbol is _really_ supposed to have jumped to and returns + * that to us. Once we have that, we overwrite tpnt with this fixed up + * address. We then clean up after ourselves, put all the registers back how we + * found them, then we jump to where the fixed up address, which is where the + * jump symbol that got us here really wanted to jump to in the first place. + * found them, then we jump to the fixed up address, which is where the jump + * symbol that got us here really wanted to jump to in the first place. + * -Erik Andersen + */ + +/* more info taken from glibc/sysdeps/x86_64/dl-trampoline.S */ + +.text + +.global _dl_linux_resolve +.type _dl_linux_resolve,%function +.align 16 + +_dl_linux_resolve: + subq $56,%rsp + /* Preserve registers otherwise clobbered. */ + movq %rax, (%rsp) + movq %rcx, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rsi, 24(%rsp) + movq %rdi, 32(%rsp) + movq %r8, 40(%rsp) + movq %r9, 48(%rsp) + + movq 64(%rsp), %rsi /* Copy args pushed by PLT in register. */ + movq %rsi, %r11 /* Multiply by 24 */ + addq %r11, %rsi + addq %r11, %rsi + shlq $3, %rsi + movq 56(%rsp), %rdi /* %rdi: link_map, %rsi: reloc_offset */ + call _dl_linux_resolver /* Call resolver. */ + movq %rax, %r11 /* Save return value */ + + /* Get register content back. */ + movq 48(%rsp), %r9 + movq 40(%rsp), %r8 + movq 32(%rsp), %rdi + movq 24(%rsp), %rsi + movq 16(%rsp), %rdx + movq 8(%rsp), %rcx + movq (%rsp), %rax + + addq $72, %rsp /* Adjust stack(PLT did 2 pushes) */ + jmp *%r11 /* Jump to function address. */ + +.size _dl_linux_resolve,.-_dl_linux_resolve diff -urN uClibc-0.9.28.orig/ldso/libdl/Makefile uClibc-0.9.28/ldso/libdl/Makefile --- uClibc-0.9.28.orig/ldso/libdl/Makefile 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/libdl/Makefile 2006-04-28 00:14:35.000000000 -0600 @@ -29,12 +29,14 @@ endif XXFLAGS+= $(XARCH_CFLAGS) $(CPU_CFLAGS) \ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \ - -fno-builtin -nostdinc -D_LIBC -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I. -I$(TOPDIR)include + -fno-builtin -nostdinc -D_LIBC \ + -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" \ + -I$(TOPDIR)ldso/ldso/$(TARGET_ARCH) -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I$(TOPDIR)include XXFLAGS+=-isystem $(shell $(CC) -print-file-name=include) XXFLAGS_NOPIC:=$(XXFLAGS) ifeq ($(DOPIC),y) - XXFLAGS += $(PICFLAG) -D__LIBDL_SHARED__ + XXFLAGS += $(PICFLAG) -DSHARED endif ifeq ($(strip $(SUPPORT_LD_DEBUG)),y) XXFLAGS+=-D__SUPPORT_LD_DEBUG__ diff -urN uClibc-0.9.28.orig/ldso/libdl/libdl.c uClibc-0.9.28/ldso/libdl/libdl.c --- uClibc-0.9.28.orig/ldso/libdl/libdl.c 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/ldso/libdl/libdl.c 2006-04-28 00:14:35.000000000 -0600 @@ -3,7 +3,7 @@ * Program to load an ELF binary on a linux system, and run it * after resolving ELF shared library symbols * - * Copyright (C) 2000-2004 by Erik Andersen + * Copyright (C) 2000-2006 by Erik Andersen * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, * David Engel, Hongjiu Lu and Mitch D'Souza * @@ -30,12 +30,12 @@ */ -#define _GNU_SOURCE +#define _GNU_SOURCE #include #include -#if defined (__LIBDL_SHARED__) +#ifdef SHARED /* When libdl is loaded as a shared library, we need to load in * and use a pile of symbols from ldso... */ @@ -52,6 +51,8 @@ extern struct r_debug *_dl_debug_addr; extern unsigned long _dl_error_number; extern void *(*_dl_malloc_function)(size_t); +extern void _dl_run_init_array(struct elf_resolve *); +extern void _dl_run_fini_array(struct elf_resolve *); #ifdef __LDSO_CACHE_SUPPORT__ int _dl_map_cache(void); int _dl_unmap_cache(void); @@ -64,7 +65,7 @@ #endif -#else /* __LIBDL_SHARED__ */ +#else /* SHARED */ /* When libdl is linked as a static library, we need to replace all * the symbols that otherwise would have been loaded in from ldso... */ @@ -81,11 +82,11 @@ struct r_debug *_dl_debug_addr = NULL; #define _dl_malloc malloc #include "../ldso/dl-debug.c" -#include "dl-progname.h" +#include LDSO_ELFINTERP #include "../ldso/dl-hash.c" #define _dl_trace_loaded_objects 0 #include "../ldso/dl-elf.c" -#endif /* __LIBDL_SHARED__ */ +#endif /* SHARED */ #ifdef __SUPPORT_LD_DEBUG__ # define _dl_if_debug_print(fmt, args...) \ @@ -126,7 +127,8 @@ "Unable to resolve symbol" }; -void __attribute__ ((destructor)) dl_cleanup(void) +void dl_cleanup(void) __attribute__ ((destructor)); +void dl_cleanup(void) { struct dyn_elf *d; for (d = _dl_handles; d; d = d->next_handle) { @@ -138,13 +140,12 @@ { struct elf_resolve *tpnt, *tfrom; struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle; - struct dyn_elf *dpnt; ElfW(Addr) from; struct elf_resolve *tpnt1; void (*dl_brk) (void); int now_flag; struct init_fini_list *tmp, *runp, *runp2, *dep_list; - int nlist, i; + unsigned int nlist, i; struct elf_resolve **init_fini_list; /* A bit of sanity checking... */ @@ -169,12 +170,15 @@ * the application. Thus this may go away at some time * in the future. */ - tfrom = NULL; - for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) { - tpnt = dpnt->dyn; - if (tpnt->loadaddr < from - && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) - tfrom = tpnt; + { + struct dyn_elf *dpnt; + tfrom = NULL; + for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) { + tpnt = dpnt->dyn; + if (tpnt->loadaddr < from + && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) + tfrom = tpnt; + } } for(rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt=rpnt->next); @@ -233,11 +237,8 @@ runp->tpnt->init_fini = NULL; /* clear any previous dependcies */ for (dpnt = (ElfW(Dyn) *) runp->tpnt->dynamic_addr; dpnt->d_tag; dpnt++) { if (dpnt->d_tag == DT_NEEDED) { - char *name; - lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val); - name = _dl_get_last_path_component(lpntstr); _dl_if_debug_print("Trying to load '%s', needed by '%s'\n", lpntstr, runp->tpnt->libname); tpnt1 = _dl_load_shared_library(0, &rpnt, runp->tpnt, lpntstr, 0); @@ -297,14 +298,14 @@ } /* Sort the INIT/FINI list in dependency order. */ for (runp2 = dep_list; runp2; runp2 = runp2->next) { - int j, k; + unsigned int j, k; for (j = 0; init_fini_list[j] != runp2->tpnt; ++j) /* Empty */; for (k = j + 1; k < nlist; ++k) { - struct init_fini_list *runp = init_fini_list[k]->init_fini; + struct init_fini_list *ele = init_fini_list[k]->init_fini; - for (; runp; runp = runp->next) { - if (runp->tpnt == runp2->tpnt) { + for (; ele; ele = ele->next) { + if (ele->tpnt == runp2->tpnt) { struct elf_resolve *here = init_fini_list[k]; _dl_if_debug_print("Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j); for (i = (k - j); i; --i) @@ -367,7 +368,7 @@ } } -#if defined (__LIBDL_SHARED__) +#ifdef SHARED /* Run the ctors and setup the dtors */ for (i = nlist; i; --i) { tpnt = init_fini_list[i-1]; @@ -384,8 +385,11 @@ (*dl_elf_func) (); } } + + _dl_run_init_array(tpnt); } -#endif +#endif /* SHARED */ + _dl_unmap_cache(); return (void *) dyn_chain; @@ -450,9 +454,16 @@ return ret; } +#if 0 +void *dlvsym(void *vhandle, const char *name, const char *version) +{ + return dlsym(vhandle, name); +} +#endif + static int do_dlclose(void *vhandle, int need_fini) { - struct dyn_elf *rpnt, *rpnt1; + struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp; struct init_fini_list *runp, *tmp; ElfW(Phdr) *ppnt; struct elf_resolve *tpnt, *run_tpnt; @@ -460,7 +471,7 @@ void (*dl_brk) (void); struct dyn_elf *handle; unsigned int end; - int i = 0, j; + unsigned int i, j; handle = (struct dyn_elf *) vhandle; if (handle == _dl_symbol_tables) @@ -491,13 +502,21 @@ for (j = 0; j < handle->init_fini.nlist; ++j) { tpnt = handle->init_fini.init_fini[j]; if (--tpnt->usage_count == 0) { - if (tpnt->dynamic_info[DT_FINI] && need_fini && + if ((tpnt->dynamic_info[DT_FINI] + || tpnt->dynamic_info[DT_FINI_ARRAY]) + && need_fini && !(tpnt->init_flag & FINI_FUNCS_CALLED)) { tpnt->init_flag |= FINI_FUNCS_CALLED; - dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]); - _dl_if_debug_print("running dtors for library %s at '%p'\n", - tpnt->libname, dl_elf_fini); - (*dl_elf_fini) (); +#ifdef SHARED + _dl_run_fini_array(tpnt); +#endif + + if (tpnt->dynamic_info[DT_FINI]) { + dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]); + _dl_if_debug_print("running dtors for library %s at '%p'\n", + tpnt->libname, dl_elf_fini); + (*dl_elf_fini) (); + } } _dl_if_debug_print("unmapping: %s\n", tpnt->libname); @@ -541,8 +560,9 @@ for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) { if (rpnt1->next->dyn == tpnt) { _dl_if_debug_print("removing symbol_tables: %s\n", tpnt->libname); + rpnt1_tmp = rpnt1->next->next; free(rpnt1->next); - rpnt1->next = rpnt1->next->next; + rpnt1->next = rpnt1_tmp; if (rpnt1->next) rpnt1->next->prev = rpnt1; break; @@ -588,8 +608,9 @@ } /* - * Dump information to stderrr about the current loaded modules + * Dump information to stderr about the current loaded modules */ +#if 1 static char *type[] = { "Lib", "Exe", "Int", "Mod" }; int dlinfo(void) @@ -660,16 +681,14 @@ { char *strtab; ElfW(Sym) *symtab; - int hn, si; - int sf; - int sn = 0; + unsigned int hn, si, sn, sf; ElfW(Addr) sa; sa = 0; symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]); strtab = (char *) (pelf->dynamic_info[DT_STRTAB]); - sf = 0; + sf = sn = 0; for (hn = 0; hn < pelf->nbucket; hn++) { for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) { ElfW(Addr) symbol_addr; @@ -696,3 +715,4 @@ return 1; } } +#endif diff -urN uClibc-0.9.28.orig/libc/sysdeps/linux/i386/bits/syscalls.h uClibc-0.9.28/libc/sysdeps/linux/i386/bits/syscalls.h --- uClibc-0.9.28.orig/libc/sysdeps/linux/i386/bits/syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/libc/sysdeps/linux/i386/bits/syscalls.h 2006-04-28 00:14:35.000000000 -0600 @@ -4,17 +4,15 @@ # error "Never use directly; include instead." #endif +#include + /* This includes the `__NR_' syscall numbers taken from the Linux kernel * header files. It also defines the traditional `SYS_' macros for older * programs. */ #include -#ifndef __set_errno -# define __set_errno(val) (*__errno_location ()) = (val) -#endif - /* - Some of the sneaky macros in the code were taken from + Some of the sneaky macros in the code were taken from glibc-2.2.5/sysdeps/unix/sysv/linux/i386/sysdep.h */ @@ -22,7 +20,8 @@ /* We need some help from the assembler to generate optimal code. We define some macros here which later will be used. */ -asm (".L__X'%ebx = 1\n\t" + +__asm__ (".L__X'%ebx = 1\n\t" ".L__X'%ecx = 2\n\t" ".L__X'%edx = 2\n\t" ".L__X'%eax = 3\n\t" @@ -56,7 +55,6 @@ ".endif\n\t" ".endm\n\t"); - #undef _syscall0 #define _syscall0(type,name) \ type name(void) \ @@ -90,7 +88,7 @@ type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ { \ return (type) (INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4)); \ -} +} #undef _syscall5 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ @@ -100,10 +98,18 @@ return (type) (INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5)); \ } +#undef _syscall6 +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \ +{ \ +return (type) (INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6)); \ +} + #define INLINE_SYSCALL(name, nr, args...) \ ({ \ unsigned int resultvar; \ - asm volatile ( \ + __asm__ __volatile__ ( \ LOADARGS_##nr \ "movl %1, %%eax\n\t" \ "int $0x80\n\t" \ @@ -125,6 +131,7 @@ #define LOADARGS_3 LOADARGS_1 #define LOADARGS_4 LOADARGS_1 #define LOADARGS_5 LOADARGS_1 +#define LOADARGS_6 LOADARGS_1 "push %%ebp ; movl %7, %%ebp\n\t" #define RESTOREARGS_0 #define RESTOREARGS_1 \ @@ -133,6 +140,7 @@ #define RESTOREARGS_3 RESTOREARGS_1 #define RESTOREARGS_4 RESTOREARGS_1 #define RESTOREARGS_5 RESTOREARGS_1 +#define RESTOREARGS_6 "pop %%ebp\n\t" RESTOREARGS_1 #define ASMFMT_0() #define ASMFMT_1(arg1) \ @@ -145,7 +153,8 @@ , "aD" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) - +#define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \ + , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6) #endif /* __ASSEMBLER__ */ #endif /* _BITS_SYSCALLS_H */ diff -urN uClibc-0.9.28.orig/libc/sysdeps/linux/powerpc/bits/syscalls.h uClibc-0.9.28/libc/sysdeps/linux/powerpc/bits/syscalls.h --- uClibc-0.9.28.orig/libc/sysdeps/linux/powerpc/bits/syscalls.h 2006-05-02 10:47:27.000000000 -0600 +++ uClibc-0.9.28/libc/sysdeps/linux/powerpc/bits/syscalls.h 2006-04-28 00:14:35.000000000 -0600 @@ -5,67 +5,164 @@ # error "Never use directly; include instead." #endif +#include + /* This includes the `__NR_' syscall numbers taken from the Linux kernel * header files. It also defines the traditional `SYS_' macros for older * programs. */ #include - -#define __STRINGIFY(s) __STRINGIFY2 (s) -#define __STRINGIFY2(s) #s - -#undef JUMPTARGET -#ifdef __PIC__ -#define __MAKE_SYSCALL __STRINGIFY(__uClibc_syscall@plt) +/* Define a macro which expands inline into the wrapper code for a system + call. This use is for internal calls that do not need to handle errors + normally. It will never touch errno. + On powerpc a system call basically clobbers the same registers like a + function call, with the exception of LR (which is needed for the + "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal + an error return status). */ + +# undef INLINE_SYSCALL +#if 1 +# define INLINE_SYSCALL(name, nr, args...) \ + ({ \ + INTERNAL_SYSCALL_DECL (sc_err); \ + long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \ + if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \ + sc_ret = -1L; \ + } \ + sc_ret; \ + }) #else -#define __MAKE_SYSCALL __STRINGIFY(__uClibc_syscall) +# define INLINE_SYSCALL(name, nr, args...) \ + ({ \ + INTERNAL_SYSCALL_DECL (sc_err); \ + long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \ + if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ + { \ + sc_ret = __syscall_error(INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err));\ + } \ + sc_ret; \ + }) #endif -#define unified_syscall_body(name) \ - __asm__ ( \ - ".section \".text\"\n\t" \ - ".align 2\n\t" \ - ".globl " __STRINGIFY(name) "\n\t" \ - ".type " __STRINGIFY(name) ",@function\n\t" \ - #name":\tli 0," __STRINGIFY(__NR_##name) "\n\t" \ - "b " __MAKE_SYSCALL "\n\t" \ - ".size\t" __STRINGIFY(name) ",.""-" __STRINGIFY(name) "\n" \ - ) +/* Define a macro which expands inline into the wrapper code for a system + call. This use is for internal calls that do not need to handle errors + normally. It will never touch errno. + On powerpc a system call basically clobbers the same registers like a + function call, with the exception of LR (which is needed for the + "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal + an error return status). */ + +# undef INTERNAL_SYSCALL_DECL +# define INTERNAL_SYSCALL_DECL(err) long int err + +# undef INTERNAL_SYSCALL +# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + register long int r0 __asm__ ("r0"); \ + register long int r3 __asm__ ("r3"); \ + register long int r4 __asm__ ("r4"); \ + register long int r5 __asm__ ("r5"); \ + register long int r6 __asm__ ("r6"); \ + register long int r7 __asm__ ("r7"); \ + register long int r8 __asm__ ("r8"); \ + register long int r9 __asm__ ("r9"); \ + register long int r10 __asm__ ("r10"); \ + register long int r11 __asm__ ("r11"); \ + register long int r12 __asm__ ("r12"); \ + LOADARGS_##nr(name, args); \ + __asm__ __volatile__ \ + ("sc \n\t" \ + "mfcr %0" \ + : "=&r" (r0), \ + "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \ + "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \ + : ASM_INPUT_##nr \ + : "cr0", "ctr", "memory"); \ + err = r0; \ + (int) r3; \ + }) +# define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args) + +# undef INTERNAL_SYSCALL_ERROR_P +# define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((void) (val), __builtin_expect ((err) & (1 << 28), 0)) + +# undef INTERNAL_SYSCALL_ERRNO +# define INTERNAL_SYSCALL_ERRNO(val, err) (val) + +# define LOADARGS_0(name, dummy) \ + r0 = (long int)name +# define LOADARGS_1(name, __arg1) \ + LOADARGS_0(name, 0); \ + r3 = (long int)__arg1 +# define LOADARGS_2(name, __arg1, __arg2) \ + LOADARGS_1(name, __arg1); \ + r4 = (long int)__arg2 +# define LOADARGS_3(name, __arg1, __arg2, __arg3) \ + LOADARGS_2(name, __arg1, __arg2); \ + r5 = (long int)__arg3 +# define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \ + LOADARGS_3(name, __arg1, __arg2, __arg3); \ + r6 = (long int)__arg4 +# define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \ + LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \ + r7 = (long int)__arg5 +# define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ + LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \ + r8 = (long int)__arg6 + +# define ASM_INPUT_0 "0" (r0) +# define ASM_INPUT_1 ASM_INPUT_0, "1" (r3) +# define ASM_INPUT_2 ASM_INPUT_1, "2" (r4) +# define ASM_INPUT_3 ASM_INPUT_2, "3" (r5) +# define ASM_INPUT_4 ASM_INPUT_3, "4" (r6) +# define ASM_INPUT_5 ASM_INPUT_4, "5" (r7) +# define ASM_INPUT_6 ASM_INPUT_5, "6" (r8) #undef _syscall0 -#define _syscall0(type,name) \ -type name(void); \ -unified_syscall_body(name) +#define _syscall0(type,name) \ +type name(void){ \ + return (type) INLINE_SYSCALL(name, 0); \ +} #undef _syscall1 #define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1); \ -unified_syscall_body(name) +type name(type1 arg1){ \ + return (type) INLINE_SYSCALL(name, 1, arg1); \ +} #undef _syscall2 #define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1, type2 arg2); \ -unified_syscall_body(name) +type name(type1 arg1, type2 arg2){ \ + return (type) INLINE_SYSCALL(name, 2, arg1, arg2); \ +} #undef _syscall3 #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1, type2 arg2, type3 arg3); \ -unified_syscall_body(name) +type name(type1 arg1, type2 arg2, type3 arg3){ \ + return (type) INLINE_SYSCALL(name, 3, arg1, arg2, arg3); \ +} #undef _syscall4 #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4); \ -unified_syscall_body(name) +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4){ \ + return (type) INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4); \ +} #undef _syscall5 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5); \ -unified_syscall_body(name) +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5){ \ + return (type) INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5); \ +} #undef _syscall6 #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6); \ -unified_syscall_body(name) +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6){ \ + return (type) INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6); \ +} #endif /* _BITS_SYSCALLS_H */