diff options
60 files changed, 1286 insertions, 1145 deletions
@@ -5,8 +5,17 @@ TODO list for the uClibc 0.9.28 release: *) Audit header files. When options are disabled, also disable them in the include files as well by checking for the proper define from include/bits/uClibc_config.h (pulled in from features.h) - *) Test each architecture with the latest LTP testsuite, and post - LTP testsuite results for each architecture on uclibc.org. + *) Test cris, i386, mips, mipsel, sh, x86_64, arm, armeb, and powerpc + with the latest LTP testsuite. Fix any regressions and post LTP + testsuite results for each architecture on uclibc.org. + *) Fix it so valgrind 2.4.0 no longer complains about the memory mmaped + and used by ldso. Currently it whines on basically about virtually + every function call when doing default lazy binding, which makes its + output virtually useless due to the excess noise. + *) Change all references to the older "Library GPL" to the "Lesser GPL" + and update COPYING.LIB to LGPL version 2.1. + + TODO list for the uClibc 1.0.0 release: @@ -45,10 +54,6 @@ TODO list for the uClibc 1.0.0 release: from ldso (such as HZ). Other stuff it currently just makes up, which is obviously wrong. Also bits/uClibc_clk_tck.h needs to be updated at the same time to get proper HZ values. - *) It would nice if valgrind wouldn't complain about the atexit() malloc'd - memory for destructors, which happens since the dynamic linker calls - atexit(), which calls malloc() prior to valgrind starting, so valgrind - complains because it didn't see that memory allocated. *) poll emulation using select() for old 2.0.x uClinux kernels in libc/sysdeps/linux/common/poll.c fails some python self-tests. Of course, modern systems using the actuall poll() syscall work fine. @@ -86,6 +91,7 @@ Arch specific TODO: alpha: _init/_fini hangs signal-ed (assert test) output from cloned children seems funky (unistd/clone test) + ldso is not implemented m68k: need to verify libc again ldso needs to be updated since it's totally broken atm @@ -93,7 +99,8 @@ Arch specific TODO: need a sigaction.c since common one doesnt work (signal tests) ldso needs to be updated since it's totally broken atm x86_64: - ldso needs to be finished off (elfinterp/resolve) + ldso needs to have lazy bindings checked + pthread isn't working really at all (pthreads tests) diff --git a/extra/scripts/fix_includes.sh b/extra/scripts/fix_includes.sh index a57e4f253..910242fa5 100755 --- a/extra/scripts/fix_includes.sh +++ b/extra/scripts/fix_includes.sh @@ -100,13 +100,13 @@ then exit 1 fi +if [ "$MAKE_IS_SILENT" != "y" ]; then echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION}" - - echo -e "\n" echo "Using kernel headers from $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION} for architecture '$TARGET_ARCH'" echo -e "\tprovided in directory $KERNEL_SOURCE" echo -e "\n" +fi # Create a symlink to include/asm diff --git a/include/elf.h b/include/elf.h index 11f82ba50..e00969266 100644 --- a/include/elf.h +++ b/include/elf.h @@ -920,23 +920,25 @@ typedef struct typedef struct { - int a_type; /* Entry type */ + uint32_t a_type; /* Entry type */ union { - long int a_val; /* Integer value */ - void *a_ptr; /* Pointer value */ - void (*a_fcn) (void); /* Function pointer value */ + uint32_t a_val; /* Integer value */ + /* We use to have pointer elements added here. We cannot do that, + though, since it does not work when using 32-bit definitions + on 64-bit platforms and vice versa. */ } a_un; } Elf32_auxv_t; typedef struct { - long int a_type; /* Entry type */ + uint64_t a_type; /* Entry type */ union { - long int a_val; /* Integer value */ - void *a_ptr; /* Pointer value */ - void (*a_fcn) (void); /* Function pointer value */ + uint64_t a_val; /* Integer value */ + /* We use to have pointer elements added here. We cannot do that, + though, since it does not work when using 32-bit definitions + on 64-bit platforms and vice versa. */ } a_un; } Elf64_auxv_t; @@ -1907,6 +1909,9 @@ typedef Elf32_Addr Elf32_Conflict; #define LITUSE_ALPHA_TLS_GD 4 #define LITUSE_ALPHA_TLS_LDM 5 +/* Legal values for d_tag of Elf64_Dyn. */ +#define DT_ALPHA_PLTRO 0x70000000 +#define DT_ALPHA_NUM 1 /* PowerPC specific declarations */ @@ -2017,10 +2022,19 @@ typedef Elf32_Addr Elf32_Conflict; #define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ #define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ +/* GNU relocs used in PIC code sequences. */ +#define R_PPC_REL16 249 /* word32 (sym-.) */ +#define R_PPC_REL16_LO 250 /* half16 (sym-.)@l */ +#define R_PPC_REL16_HI 251 /* half16 (sym-.)@h */ +#define R_PPC_REL16_HA 252 /* half16 (sym-.)@ha */ + /* This is a phony reloc to handle any old fashioned TOC16 references that may still be in object files. */ #define R_PPC_TOC16 255 +/* PowerPC specific values for the Dyn d_tag field. */ +#define DT_PPC_GOT (DT_LOPROC + 0) +#define DT_PPC_NUM 1 /* PowerPC64 relocations defined by the ABIs */ #define R_PPC64_NONE R_PPC_NONE diff --git a/include/errno.h b/include/errno.h index 8c7f666fe..390e51521 100644 --- a/include/errno.h +++ b/include/errno.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. +/* Copyright (C) 1991,92,93,94,95,96,97,2002 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -25,8 +25,8 @@ /* The includer defined __need_Emath if he wants only the definitions of EDOM and ERANGE, and not everything else. */ #ifndef __need_Emath -#define _ERRNO_H 1 -#include <features.h> +# define _ERRNO_H 1 +# include <features.h> #endif __BEGIN_DECLS @@ -47,6 +47,13 @@ __BEGIN_DECLS extern int errno; #endif +#if 0 /*def __USE_GNU uClibc note: not supported */ + +/* The full and simple forms of the name with which the program was + invoked. These variables are set up automatically at startup based on + the value of ARGV[0] (this works only if you use GNU ld). */ +extern char *program_invocation_name, *program_invocation_short_name; +#endif /* __USE_GNU */ #endif /* _ERRNO_H */ __END_DECLS diff --git a/include/signal.h b/include/signal.h index 7793cdbe1..c22b4372c 100644 --- a/include/signal.h +++ b/include/signal.h @@ -276,7 +276,7 @@ extern int sigqueue (__pid_t __pid, int __sig, __const union sigval __val) #ifdef __UCLIBC_HAS_SYS_SIGLIST__ /* Names of the signals. This variable exists only for compatibility. Use `strsignal' instead (see <string.h>). */ -extern __const char *__const _sys_siglist[_NSIG]; +#define _sys_siglist sys_siglist extern __const char *__const sys_siglist[_NSIG]; #endif /* __UCLIBC_HAS_SYS_SIGLIST__ */ diff --git a/include/sys/cdefs.h b/include/sys/cdefs.h index f370145f1..0a6d345bc 100644 --- a/include/sys/cdefs.h +++ b/include/sys/cdefs.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2001, 2002 Free Software Foundation, Inc. +/* Copyright (C) 1992-2001, 2002, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -39,24 +39,28 @@ /* GCC can always grok prototypes. For C++ programs we add throw() to help it optimize the function calls. But this works only with - gcc 2.8.x and egcs. */ -# if defined __cplusplus && __GNUC_PREREQ (2,8) -# define __THROW throw () + gcc 2.8.x and egcs. For gcc 3.2 and up we even mark C functions + as non-throwing using a function attribute since programs can use + the -fexceptions options for C code as well. */ +# if 0 //!defined __cplusplus && __GNUC_PREREQ (3, 3) +# define __THROW __attribute__ ((__nothrow__)) +# define __NTH(fct) __attribute__ ((__nothrow__)) fct # else -# define __THROW +# if defined __cplusplus && __GNUC_PREREQ (2,8) +# define __THROW throw () +# define __NTH(fct) fct throw () +# else +# define __THROW +# define __NTH(fct) fct +# endif # endif -# define __P(args) args __THROW -/* This macro will be used for functions which might take C++ callback - functions. */ -# define __PMT(args) args #else /* Not GCC. */ # define __inline /* No inline functions. */ # define __THROW -# define __P(args) args -# define __PMT(args) args +# define __NTH(fct) fct # define __const const # define __signed signed @@ -64,6 +68,11 @@ #endif /* GCC. */ +/* These two macros are not used in glibc anymore. They are kept here + only because some other projects expect the macros to be defined. */ +#define __P(args) args +#define __PMT(args) args + /* For these things, GCC behaves the ANSI way normally, and the non-ANSI way under -traditional. */ @@ -118,6 +127,12 @@ #endif +/* Fortify support. */ +#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1) +#define __bos0(ptr) __builtin_object_size (ptr, 0) +#define __warndecl(name, msg) extern void name (void) + + /* Support for flexible arrays. */ #if __GNUC_PREREQ (2,97) /* GCC 2.97 supports C99 flexible array members. */ @@ -150,6 +165,17 @@ # define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias)) # define __ASMNAME(cname) __C_SYMBOL_PREFIX__ cname +/* +# ifdef __cplusplus +# define __REDIRECT_NTH(name, proto, alias) \ + name proto __THROW __asm__ (__ASMNAME (#alias)) +# else +# define __REDIRECT_NTH(name, proto, alias) \ + name proto __asm__ (__ASMNAME (#alias)) __THROW +# endif +# define __ASMNAME(cname) __ASMNAME2 (__USER_LABEL_PREFIX__, cname) +# define __ASMNAME2(prefix, cname) __STRING (prefix) cname +*/ /* #elif __SOME_OTHER_COMPILER__ @@ -225,6 +251,36 @@ # define __attribute_format_strfmon__(a,b) /* Ignore */ #endif +/* The nonull function attribute allows to mark pointer parameters which + must not be NULL. */ +#if __GNUC_PREREQ (3,3) +# define __nonnull(params) __attribute__ ((__nonnull__ params)) +#else +# define __nonnull(params) +#endif + +/* If fortification mode, we warn about unused results of certain + function calls which can lead to problems. */ +#if __GNUC_PREREQ (3,4) +# define __attribute_warn_unused_result__ \ + __attribute__ ((__warn_unused_result__)) +# if __USE_FORTIFY_LEVEL > 0 +# define __wur __attribute_warn_unused_result__ +# endif +#else +# define __attribute_warn_unused_result__ /* empty */ +#endif +#ifndef __wur +# define __wur /* Ignore */ +#endif + +/* Forces a function to be always inlined. */ +#if __GNUC_PREREQ (3,2) +# define __always_inline __inline __attribute__ ((__always_inline__)) +#else +# define __always_inline __inline +#endif + /* It is possible to compile containing GCC extensions even if GCC is run in pedantic mode if the uses are carefully marked using the `__extension__' keyword. But this is not generally available before diff --git a/include/sys/sysmacros.h b/include/sys/sysmacros.h index 85dc3d281..c5efca4f9 100644 --- a/include/sys/sysmacros.h +++ b/include/sys/sysmacros.h @@ -1,5 +1,5 @@ /* Definitions of macros to access `dev_t' values. - Copyright (C) 1996, 1997, 1999, 2003 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1999, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -25,6 +25,7 @@ /* If the compiler does not know long long it is out of luck. We are not going to hack weird hacks to support the dev_t representation they need. */ +#if 1 /*def __GLIBC_HAVE_LONG_LONG uClibc note: always enable */ __extension__ static __inline unsigned int gnu_dev_major (unsigned long long int __dev) __THROW; @@ -36,32 +37,33 @@ static __inline unsigned long long int gnu_dev_makedev (unsigned int __major, unsigned int __minor) __THROW; -#if defined __GNUC__ && __GNUC__ >= 2 +# if defined __GNUC__ && __GNUC__ >= 2 __extension__ static __inline unsigned int -gnu_dev_major (unsigned long long int __dev) __THROW +__NTH (gnu_dev_major (unsigned long long int __dev)) { return ((__dev >> 8) & 0xfff) | ((unsigned int) (__dev >> 32) & ~0xfff); } __extension__ static __inline unsigned int -gnu_dev_minor (unsigned long long int __dev) __THROW +__NTH (gnu_dev_minor (unsigned long long int __dev)) { return (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff); } __extension__ static __inline unsigned long long int -gnu_dev_makedev (unsigned int __major, unsigned int __minor) __THROW +__NTH (gnu_dev_makedev (unsigned int __major, unsigned int __minor)) { return ((__minor & 0xff) | ((__major & 0xfff) << 8) | (((unsigned long long int) (__minor & ~0xff)) << 12) | (((unsigned long long int) (__major & ~0xfff)) << 32)); } -#endif +# endif /* Access the functions with their traditional names. */ -#define major(dev) gnu_dev_major (dev) -#define minor(dev) gnu_dev_minor (dev) -#define makedev(maj, min) gnu_dev_makedev (maj, min) +# define major(dev) gnu_dev_major (dev) +# define minor(dev) gnu_dev_minor (dev) +# define makedev(maj, min) gnu_dev_makedev (maj, min) +#endif #endif /* sys/sysmacros.h */ diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h index de459b0a8..37588b86c 100644 --- a/ldso/include/dl-defs.h +++ b/ldso/include/dl-defs.h @@ -1,12 +1,6 @@ #ifndef _LD_DEFS_H #define _LD_DEFS_H -/* - * NPTL - This was taken from 'sysdeps/generic/ldsodefs.h'. It is - * used for backtrace capability. - */ -extern void *__libc_stack_end; - #define LIB_ANY -1 #define LIB_DLL 0 #define LIB_ELF 1 diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h index d8f3b382c..c487436fc 100644 --- a/ldso/include/dl-elf.h +++ b/ldso/include/dl-elf.h @@ -36,6 +36,28 @@ extern int _dl_fixup(struct dyn_elf *rpnt, int flag); extern void _dl_protect_relro (struct elf_resolve *l); /* + * Bitsize related settings for things ElfW() + * does not handle already + */ +#if __WORDSIZE == 64 +# define ELF_ST_BIND(val) ELF64_ST_BIND(val) +# define ELF_ST_TYPE(val) ELF64_ST_TYPE(val) +# define ELF_R_SYM(i) ELF64_R_SYM(i) +# define ELF_R_TYPE(i) ELF64_R_TYPE(i) +# ifndef ELF_CLASS +# define ELF_CLASS ELFCLASS64 +# endif +#else +# define ELF_ST_BIND(val) ELF32_ST_BIND(val) +# define ELF_ST_TYPE(val) ELF32_ST_TYPE(val) +# define ELF_R_SYM(i) ELF32_R_SYM(i) +# define ELF_R_TYPE(i) ELF32_R_TYPE(i) +# ifndef ELF_CLASS +# define ELF_CLASS ELFCLASS32 +# endif +#endif + +/* * Datatype of a relocation on this platform */ #ifdef ELF_USES_RELOCA @@ -65,10 +87,10 @@ extern void _dl_protect_relro (struct elf_resolve *l); #define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM) -extern void _dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void *debug_addr, Elf32_Addr load_off); +extern void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off); -static inline __attribute__((always_inline)) -void __dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void *debug_addr, Elf32_Addr load_off) +static __always_inline +void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off) { for (; dpnt->d_tag; dpnt++) { if (dpnt->d_tag < DT_NUM) { @@ -84,6 +106,12 @@ void __dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void dynamic_info[DT_BIND_NOW] = 1; if (dpnt->d_tag == DT_TEXTREL) dynamic_info[DT_TEXTREL] = 1; +#ifdef __LDSO_RUNPATH__ + if (dpnt->d_tag == DT_RUNPATH) + dynamic_info[DT_RPATH] = 0; + if (dpnt->d_tag == DT_RPATH && dynamic_info[DT_RUNPATH]) + dynamic_info[DT_RPATH] = 0; +#endif } else if (dpnt->d_tag < DT_LOPROC) { if (dpnt->d_tag == DT_RELOCCOUNT) dynamic_info[DT_RELCONT_IDX] = dpnt->d_un.d_val; @@ -97,21 +125,19 @@ void __dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void } #endif } -# define ADJUST_DYN_INFO(tag, load_off) \ +#define ADJUST_DYN_INFO(tag, load_off) \ do { \ if (dynamic_info[tag]) \ dynamic_info[tag] += load_off; \ } while(0) - - ADJUST_DYN_INFO (DT_HASH, load_off); - ADJUST_DYN_INFO (DT_PLTGOT, load_off); - ADJUST_DYN_INFO (DT_STRTAB, load_off); - ADJUST_DYN_INFO (DT_SYMTAB, load_off); - ADJUST_DYN_INFO (DT_RELOC_TABLE_ADDR, load_off); - ADJUST_DYN_INFO (DT_JMPREL, load_off); -# undef ADJUST_DYN_INFO - - } + ADJUST_DYN_INFO(DT_HASH, load_off); + ADJUST_DYN_INFO(DT_PLTGOT, load_off); + ADJUST_DYN_INFO(DT_STRTAB, load_off); + ADJUST_DYN_INFO(DT_SYMTAB, load_off); + ADJUST_DYN_INFO(DT_RELOC_TABLE_ADDR, load_off); + ADJUST_DYN_INFO(DT_JMPREL, load_off); +#undef ADJUST_DYN_INFO +} /* Reloc type classes as returned by elf_machine_type_class(). ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h index dcad7bcee..162c7b425 100644 --- a/ldso/include/dl-hash.h +++ b/ldso/include/dl-hash.h @@ -32,19 +32,19 @@ struct elf_resolve{ unsigned short usage_count; unsigned short int init_flag; unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */ - unsigned int nbucket; - unsigned long * elf_buckets; + Elf32_Word nbucket; + Elf32_Word *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 */ - unsigned long nchain; - unsigned long * chains; + Elf32_Word nchain; + Elf32_Word *chains; unsigned long dynamic_info[DYNAMIC_SIZE]; unsigned long n_phent; - Elf32_Phdr * ppnt; + ElfW(Phdr) * ppnt; ElfW(Addr) relro_addr; size_t relro_size; diff --git a/ldso/include/dl-string.h b/ldso/include/dl-string.h index 9636c2764..8e35e6ad2 100644 --- a/ldso/include/dl-string.h +++ b/ldso/include/dl-string.h @@ -2,6 +2,7 @@ #define _LINUX_STRING_H_ #include <dl-sysdep.h> // for do_rem +#include <features.h> static size_t _dl_strlen(const char * str); static char *_dl_strcat(char *dst, const char *src); @@ -22,7 +23,7 @@ static char *_dl_simple_ltoahex(char * local, unsigned long i); #define NULL ((void *) 0) #endif -static inline size_t __attribute__((__always_inline__)) _dl_strlen(const char * str) +static __always_inline size_t _dl_strlen(const char * str) { register const char *ptr = (char *) str-1; @@ -30,7 +31,7 @@ static inline size_t __attribute__((__always_inline__)) _dl_strlen(const char * return (ptr - str); } -static inline char * __attribute__((__always_inline__)) _dl_strcat(char *dst, const char *src) +static __always_inline char * _dl_strcat(char *dst, const char *src) { register char *ptr = dst-1; @@ -43,7 +44,7 @@ static inline char * __attribute__((__always_inline__)) _dl_strcat(char *dst, co return dst; } -static inline char * __attribute__((__always_inline__)) _dl_strcpy(char * dst,const char *src) +static __always_inline char * _dl_strcpy(char * dst,const char *src) { register char *ptr = dst; @@ -53,7 +54,7 @@ static inline char * __attribute__((__always_inline__)) _dl_strcpy(char * dst,co return ptr; } -static inline int __attribute__((__always_inline__)) _dl_strcmp(const char * s1,const char * s2) +static __always_inline int _dl_strcmp(const char * s1,const char * s2) { register unsigned char c1, c2; s1--;s2--; @@ -68,7 +69,7 @@ static inline int __attribute__((__always_inline__)) _dl_strcmp(const char * s1, return c1 - c2; } -static inline int __attribute__((__always_inline__)) _dl_strncmp(const char * s1,const char * s2,size_t len) +static __always_inline int _dl_strncmp(const char * s1,const char * s2,size_t len) { register unsigned char c1 = '\0'; register unsigned char c2 = '\0'; @@ -84,7 +85,7 @@ static inline int __attribute__((__always_inline__)) _dl_strncmp(const char * s1 return c1 - c2; } -static inline char * __attribute__((__always_inline__)) _dl_strchr(const char * str,int c) +static __always_inline char * _dl_strchr(const char * str,int c) { register char ch; str--; @@ -145,7 +146,7 @@ static inline void * _dl_memcpy(void * dst, const void * src, size_t len) return dst; } -static inline int __attribute__((__always_inline__)) _dl_memcmp(const void * s1,const void * s2,size_t len) +static __always_inline int _dl_memcmp(const void * s1,const void * s2,size_t len) { unsigned char *c1 = (unsigned char *)s1-1; unsigned char *c2 = (unsigned char *)s2-1; @@ -160,7 +161,7 @@ static inline int __attribute__((__always_inline__)) _dl_memcmp(const void * s1, #if defined(powerpc) /* Will generate smaller and faster code due to loop unrolling.*/ -static inline void * __attribute__((__always_inline__)) _dl_memset(void *to, int c, size_t n) +static __always_inline void * _dl_memset(void *to, int c, size_t n) { unsigned long chunks; unsigned long *tmp_to; @@ -185,7 +186,7 @@ static inline void * __attribute__((__always_inline__)) _dl_memset(void *to, int return to; } #else -static inline void * __attribute__((__always_inline__)) _dl_memset(void * str,int c,size_t len) +static __always_inline void * _dl_memset(void * str,int c,size_t len) { register char *a = str; @@ -196,7 +197,7 @@ static inline void * __attribute__((__always_inline__)) _dl_memset(void * str,in } #endif -static inline char * __attribute__((__always_inline__)) _dl_get_last_path_component(char *path) +static __always_inline char * _dl_get_last_path_component(char *path) { register char *ptr = path-1; @@ -217,7 +218,7 @@ static inline char * __attribute__((__always_inline__)) _dl_get_last_path_compon /* Early on, we can't call printf, so use this to print out * numbers using the SEND_STDERR() macro. Avoid using mod * or using long division */ -static inline char * __attribute__((__always_inline__)) _dl_simple_ltoa(char * local, unsigned long i) +static __always_inline char * _dl_simple_ltoa(char * local, unsigned long i) { /* 20 digits plus a null terminator should be good for * 64-bit or smaller ints (2^64 - 1)*/ @@ -232,7 +233,7 @@ static inline char * __attribute__((__always_inline__)) _dl_simple_ltoa(char * l return p; } -static inline char * __attribute__((__always_inline__)) _dl_simple_ltoahex(char * local, unsigned long i) +static __always_inline char * _dl_simple_ltoahex(char * local, unsigned long i) { /* 16 digits plus a leading "0x" plus a null terminator, * should be good for 64-bit or smaller ints */ @@ -305,9 +306,10 @@ static inline char * __attribute__((__always_inline__)) _dl_simple_ltoahex(char _dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \ } -#define SEND_NUMBER_STDERR(X, add_a_newline) \ +#define SEND_NUMBER_STDERR(NUM, add_a_newline) \ { \ char tmp[26], v, *tmp2, *tmp1 = tmp; \ + unsigned long X = (unsigned long)(NUM); \ CONSTANT_STRING_GOT_FIXUP(tmp1); \ tmp2 = tmp1 + sizeof(tmp); \ *--tmp2 = '\0'; \ @@ -323,9 +325,11 @@ static inline char * __attribute__((__always_inline__)) _dl_simple_ltoahex(char #ifdef __SUPPORT_LD_DEBUG_EARLY__ # define SEND_STDERR_DEBUG(X) SEND_STDERR(X) +# define SEND_NUMBER_STDERR_DEBUG(X, add_a_newline) SEND_NUMBER_STDERR(X, add_a_newline) # define SEND_ADDRESS_STDERR_DEBUG(X, add_a_newline) SEND_ADDRESS_STDERR(X, add_a_newline) #else # define SEND_STDERR_DEBUG(X) +# define SEND_NUMBER_STDERR_DEBUG(X, add_a_newline) # define SEND_ADDRESS_STDERR_DEBUG(X, add_a_newline) #endif diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h index fbe852d18..1bcf95fb1 100644 --- a/ldso/include/dl-syscall.h +++ b/ldso/include/dl-syscall.h @@ -47,8 +47,8 @@ #ifndef _dl_MAX_ERRNO #define _dl_MAX_ERRNO 4096 #endif -#define _dl_mmap_check_error(__res) \ - (((int)__res) < 0 && ((int)__res) >= -_dl_MAX_ERRNO) +#define _dl_mmap_check_error(__res) \ + (((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO) #endif @@ -104,7 +104,7 @@ static inline _syscall0(gid_t, _dl_getpid); static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz); #ifdef __NR_mmap -#if defined(__powerpc__) || defined(__mips__) || defined(__sh__) || defined(__sparc__) +#if defined(__powerpc__) || defined(__mips__) || defined(__sh__) || defined(__sparc__) || defined(__x86_64__) /* PowerPC, MIPS and SuperH have a different calling convention for mmap(). */ #define __NR__dl_mmap __NR_mmap static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length, diff --git a/ldso/include/dlfcn.h b/ldso/include/dlfcn.h index 484558d83..0bacc1a22 100644 --- a/ldso/include/dlfcn.h +++ b/ldso/include/dlfcn.h @@ -12,11 +12,10 @@ `dladdr'. */ typedef struct { - __const char *dli_fname; /* File name of defining object. */ - void *dli_fbase; /* Load address of that object. */ - __const char *dli_sname; /* Name of nearest symbol. */ - void *dli_saddr; /* Exact value of nearest symbol. */ + __const char *dli_fname; /* File name of defining object. */ + void *dli_fbase; /* Load address of that object. */ + __const char *dli_sname; /* Name of nearest symbol. */ + void *dli_saddr; /* Exact value of nearest symbol. */ } Dl_info; - -#endif /* dlfcn.h */ +#endif /* _DLFCN_H */ diff --git a/ldso/include/unsecvars.h b/ldso/include/unsecvars.h index 4ed2c356c..0d996a91f 100644 --- a/ldso/include/unsecvars.h +++ b/ldso/include/unsecvars.h @@ -4,17 +4,17 @@ * '\0' explicitly. */ -#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" \ +#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" /* diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index a3177fb59..15ba3b947 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -37,13 +37,6 @@ static caddr_t _dl_cache_addr = NULL; static size_t _dl_cache_size = 0; -/* - * NPTL - This was taken from 'elf/dl-load.c' in glibc. We may - * or may not need this for backtrace support. Define - * it for NPTL compilation. - */ -void *__libc_stack_end; - int _dl_map_cache(void) { int fd; @@ -129,10 +122,7 @@ _dl_protect_relro (struct elf_resolve *l) & ~(_dl_pagesize - 1)); ElfW(Addr) end = ((l->loadaddr + l->relro_addr + l->relro_size) & ~(_dl_pagesize - 1)); -#if defined (__SUPPORT_LD_DEBUG__) - if (_dl_debug) - _dl_dprintf(2, "RELRO protecting %s: start:%x, end:%x\n", l->libname, start, end); -#endif + _dl_if_debug_dprint("RELRO protecting %s: start:%x, end:%x\n", l->libname, start, end); if (start != end && _dl_mprotect ((void *) start, end - start, PROT_READ) < 0) { _dl_dprintf(2, "%s: cannot apply additional memory protection after relocation", l->libname); @@ -146,10 +136,10 @@ static struct elf_resolve * search_for_named_library(const char *name, int secure, const char *path_list, struct dyn_elf **rpnt) { - int i, count = 1; char *path, *path_n; char mylibname[2050]; - struct elf_resolve *tpnt1; + struct elf_resolve *tpnt; + int done = 0; if (path_list==NULL) return NULL; @@ -161,29 +151,32 @@ search_for_named_library(const char *name, int secure, const char *path_list, _dl_exit(0); } - /* Unlike ldd.c, don't bother to eliminate double //s */ - - /* Replace colons with zeros in path_list and count them */ - for(i=_dl_strlen(path); i > 0; i--) { - if (path[i]==':') { - path[i]=0; - count++; - } - } - + /* Replace colons with zeros in path_list */ + /* : at the beginning or end of path maps to CWD */ + /* :: anywhere maps CWD */ + /* "" maps to CWD */ path_n = path; - for (i = 0; i < count; i++) { - _dl_strcpy(mylibname, path_n); - _dl_strcat(mylibname, "/"); - _dl_strcat(mylibname, name); - if ((tpnt1 = _dl_load_elf_shared_library(secure, rpnt, mylibname)) != NULL) - { - return tpnt1; + do { + if (*path == 0) { + *path = ':'; + done = 1; } - path_n += (_dl_strlen(path_n) + 1); - } + if (*path == ':') { + *path = 0; + if (*path_n) + _dl_strcpy(mylibname, path_n); + else + _dl_strcpy(mylibname, "."); /* Assume current dir if empty path */ + _dl_strcat(mylibname, "/"); + _dl_strcat(mylibname, name); + if ((tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname)) != NULL) + return tpnt; + path_n = path+1; + } + path++; + } while (!done); return NULL; } @@ -199,10 +192,7 @@ struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libnam pnt = libname = full_libname; -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) - _dl_dprintf(_dl_debug_file, "Checking if '%s' is already loaded\n", full_libname); -#endif + _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) @@ -262,7 +252,7 @@ unsigned long _dl_internal_error_number; struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname, int __attribute__((unused)) trace_loaded_objects) { - char *pnt, *pnt1; + char *pnt; struct elf_resolve *tpnt1; char *libname; @@ -276,9 +266,9 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, /* Skip over any initial initial './' and '/' stuff to * get the short form libname with no path garbage */ - pnt1 = _dl_strrchr(libname, '/'); - if (pnt1) { - libname = pnt1 + 1; + pnt = _dl_strrchr(libname, '/'); + if (pnt) { + libname = pnt + 1; } /* Critical step! Weed out duplicates early to avoid @@ -289,17 +279,13 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, return tpnt1; } -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfind library='%s'; searching\n", libname); -#endif + _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 /usr/i486-sysv4/lib for /usr/lib in library names. */ if (libname != full_libname) { -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) _dl_dprintf(_dl_debug_file, "\ttrying file='%s'\n", full_libname); -#endif + _dl_if_debug_dprint("\ttrying file='%s'\n", full_libname); tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname); if (tpnt1) { return tpnt1; @@ -308,30 +294,22 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, } /* - * The ABI specifies that RPATH is searched before LD_*_PATH or + * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or * the default path of /usr/lib. Check in rpath directories. */ - for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { - if (tpnt->libtype == elf_executable) { - pnt = (char *) tpnt->dynamic_info[DT_RPATH]; - if (pnt) { - pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tsearching RPATH='%s'\n", pnt); -#endif - if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) - { - return tpnt1; - } - } - } +#ifdef __LDSO_RUNPATH__ + pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL); + if (pnt) { + pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; + _dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt); + if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) + return tpnt1; } +#endif /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */ if (_dl_library_path) { -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path); -#endif + _dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path); if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) { return tpnt1; @@ -339,6 +317,19 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, } /* + * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH. + */ +#ifdef __LDSO_RUNPATH__ + pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL); + if (pnt) { + pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; + _dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt); + if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) + return tpnt1; + } +#endif + + /* * Where should the cache be searched? There is no such concept in the * ABI, so we have some flexibility here. For now, search it before * the hard coded paths that follow (i.e before /lib and /usr/lib). @@ -350,9 +341,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, libentry_t *libent = (libentry_t *) & header[1]; char *strs = (char *) &libent[header->nlibs]; -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tsearching cache='%s'\n", LDSO_CACHE); -#endif + _dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE); for (i = 0; i < header->nlibs; i++) { if ((libent[i].flags == LIB_ELF || libent[i].flags == LIB_ELF_LIBC0 || @@ -367,9 +356,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, /* Look for libraries wherever the shared library loader * was installed */ -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tsearching ldso dir='%s'\n", _dl_ldsopath); -#endif + _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath); if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL) { return tpnt1; @@ -378,9 +365,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, /* Lastly, search the standard list of paths for the library. This list must exactly match the list in uClibc/ldso/util/ldd.c */ -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tsearching full lib path list\n"); -#endif + _dl_if_debug_dprint("\tsearching full lib path list\n"); if ((tpnt1 = search_for_named_library(libname, secure, UCLIBC_RUNTIME_PREFIX "lib:" UCLIBC_RUNTIME_PREFIX "usr/lib" @@ -399,9 +384,7 @@ goof: _dl_error_number = _dl_internal_error_number; else _dl_error_number = LD_ERROR_NOFILE; -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) _dl_dprintf(2, "Bummer: could not find '%s'!\n", libname); -#endif + _dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname); return NULL; } @@ -417,7 +400,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, { ElfW(Ehdr) *epnt; unsigned long dynamic_addr = 0; - Elf32_Dyn *dpnt; + ElfW(Dyn) *dpnt; struct elf_resolve *tpnt; ElfW(Phdr) *ppnt; char *status, *header; @@ -442,9 +425,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, } tpnt->usage_count++; tpnt->libtype = elf_lib; -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) _dl_dprintf(2, "file='%s'; already loaded\n", libname); -#endif + _dl_if_debug_dprint("file='%s'; already loaded\n", libname); return tpnt; } @@ -657,7 +638,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, return NULL; } - dpnt = (Elf32_Dyn *) dynamic_addr; + dpnt = (ElfW(Dyn) *) dynamic_addr; _dl_memset(dynamic_info, 0, sizeof(dynamic_info)); _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, libaddr); /* If the TEXTREL is set, this means that we need to make the pages @@ -714,43 +695,34 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, INIT_GOT(lpnt, tpnt); }; -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) { - _dl_dprintf(2, "\n\tfile='%s'; generating link map\n", libname); - _dl_dprintf(2, "\t\tdynamic: %x base: %x\n", - dynamic_addr, libaddr); - _dl_dprintf(2, "\t\t entry: %x phdr: %x phnum: %x\n\n", - epnt->e_entry + libaddr, tpnt->ppnt, tpnt->n_phent); + _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); + _dl_if_debug_dprint("\t\t entry: %x phdr: %x phnum: %x\n\n", + epnt->e_entry + libaddr, tpnt->ppnt, tpnt->n_phent); - } -#endif _dl_munmap(header, _dl_pagesize); return tpnt; } + /* now_flag must be RTLD_NOW or zero */ int _dl_fixup(struct dyn_elf *rpnt, int now_flag) { int goof = 0; struct elf_resolve *tpnt; - Elf32_Word reloc_size, reloc_addr, relative_count; + ElfW(Word) reloc_size, relative_count; + ElfW(Addr) reloc_addr; if (rpnt->next) goof += _dl_fixup(rpnt->next, now_flag); tpnt = rpnt->dyn; -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug && !(tpnt->init_flag & RELOCS_DONE)) - _dl_dprintf(_dl_debug_file,"\nrelocation processing: %s\n", tpnt->libname); -#endif + if(!(tpnt->init_flag & RELOCS_DONE)) + _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname); if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) { -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) { - _dl_dprintf(2, "%s: can't handle %s relocation records\n", - _dl_progname, UNSUPPORTED_RELOC_STR); - } -#endif + _dl_if_debug_dprint("%s: can't handle %s relocation records\n", + _dl_progname, UNSUPPORTED_RELOC_STR); goof++; return goof; } @@ -768,7 +740,7 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */ reloc_size -= relative_count * sizeof(ELF_RELOC); - elf_machine_relative (tpnt->loadaddr, reloc_addr, relative_count); + elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count); reloc_addr += relative_count * sizeof(ELF_RELOC); } goof += _dl_parse_relocation_information(rpnt, @@ -798,7 +770,7 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag) /* Minimal printf which handles only %s, %d, and %x */ void _dl_dprintf(int fd, const char *fmt, ...) { - int num; + long num; va_list args; char *start, *ptr, *string; static char *buf; @@ -846,7 +818,7 @@ void _dl_dprintf(int fd, const char *fmt, ...) case 'd': { char tmp[22]; - num = va_arg(args, int); + num = va_arg(args, long); string = _dl_simple_ltoa(tmp, num); _dl_write(fd, string, _dl_strlen(string)); @@ -856,7 +828,7 @@ void _dl_dprintf(int fd, const char *fmt, ...) case 'X': { char tmp[22]; - num = va_arg(args, int); + num = va_arg(args, long); string = _dl_simple_ltoahex(tmp, num); _dl_write(fd, string, _dl_strlen(string)); @@ -888,7 +860,7 @@ char *_dl_strdup(const char *string) return retval; } -void _dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void *debug_addr, Elf32_Addr load_off) +void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off) { __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off); } diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index 55026b4db..977934e8f 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -57,7 +57,7 @@ struct dyn_elf *_dl_handles = NULL; /* 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 unsigned long _dl_elf_hash(const char *name) +static inline Elf32_Word _dl_elf_hash(const char *name) { unsigned long hash=0; unsigned long tmp; @@ -101,7 +101,7 @@ 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) { - unsigned long *hash_addr; + Elf32_Word *hash_addr; struct elf_resolve *tpnt; int i; @@ -125,7 +125,7 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname, tpnt->libtype = loaded_file; if (dynamic_info[DT_HASH] != 0) { - hash_addr = (unsigned long *) (intptr_t)(dynamic_info[DT_HASH]); + hash_addr = (Elf32_Word*)dynamic_info[DT_HASH]; tpnt->nbucket = *hash_addr++; tpnt->nchain = *hash_addr++; tpnt->elf_buckets = hash_addr; @@ -148,13 +148,13 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve * struct elf_resolve *tpnt; int si; char *strtab; - Elf32_Sym *symtab; + ElfW(Sym) *symtab; unsigned long elf_hash_number, hn; const ElfW(Sym) *sym; char *weak_result = NULL; elf_hash_number = _dl_elf_hash(name); - + for (; rpnt; rpnt = rpnt->next) { tpnt = rpnt->dyn; @@ -178,7 +178,7 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve * /* Avoid calling .urem here. */ do_rem(hn, elf_hash_number, tpnt->nbucket); - symtab = (Elf32_Sym *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); + symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) { @@ -190,10 +190,10 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve * continue; if (sym->st_value == 0) continue; - if (ELF32_ST_TYPE(sym->st_info) > STT_FUNC) + if (ELF_ST_TYPE(sym->st_info) > STT_FUNC) continue; - switch (ELF32_ST_BIND(sym->st_info)) { + switch (ELF_ST_BIND(sym->st_info)) { case STB_WEAK: #if 0 /* Perhaps we should support old style weak symbol handling diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c index 31529cd18..3c6ce48f5 100644 --- a/ldso/ldso/dl-startup.c +++ b/ldso/ldso/dl-startup.c @@ -97,31 +97,31 @@ /* Static declarations */ 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 */ /* When we enter this piece of code, the program stack looks like this: - argc argument counter (integer) - argv[0] program name (pointer) - argv[1...N] program args (pointers) - argv[argc-1] end of args (integer) - NULL - env[0...N] environment variables (pointers) - NULL - auxvt[0...N] Auxiliary Vector Table elements (mixed types) + argc argument counter (integer) + argv[0] program name (pointer) + argv[1...N] program args (pointers) + argv[argc-1] end of args (integer) + NULL + env[0...N] environment variables (pointers) + NULL + auxvt[0...N] Auxiliary Vector Table elements (mixed types) */ static void * __attribute_used__ _dl_start(unsigned long args) { unsigned int argc; char **argv, **envp; unsigned long load_addr; - Elf32_Addr got; + ElfW(Addr) got; unsigned long *aux_dat; ElfW(Ehdr) *header; struct elf_resolve tpnt_tmp; struct elf_resolve *tpnt = &tpnt_tmp; - Elf32_auxv_t auxvt[AT_EGID + 1]; - Elf32_Dyn *dpnt; + ElfW(auxv_t) auxvt[AT_EGID + 1]; + ElfW(Dyn) *dpnt; /* WARNING! -- we cannot make _any_ funtion calls until we have * taken care of fixing up our own relocations. Making static @@ -136,18 +136,16 @@ static void * __attribute_used__ _dl_start(unsigned long args) aux_dat += argc; /* Skip over the argv pointers */ aux_dat++; /* Skip over NULL at end of argv */ envp = (char **) aux_dat; + SEND_STDERR_DEBUG("argc="); + SEND_NUMBER_STDERR_DEBUG(argc, 0); + SEND_STDERR_DEBUG(" argv="); + SEND_ADDRESS_STDERR_DEBUG(argv, 0); + SEND_STDERR_DEBUG(" envp="); + SEND_ADDRESS_STDERR_DEBUG(envp, 1); while (*aux_dat) aux_dat++; /* Skip over the envp pointers */ aux_dat++; /* Skip over NULL at end of envp */ - /* - * NPTL - This was taken from 'sysdeps/generic/libc-start.c' - * and is associated with backtrace capability. It - * It may be removed later, but right now NPTL needs - * NPTL needs this to compile. - */ - __libc_stack_end = (void *) argv; - /* Place -1 here as a checkpoint. We later check if it was changed * when we read in the auxvt */ auxvt[AT_UID].a_type = -1; @@ -156,10 +154,10 @@ static void * __attribute_used__ _dl_start(unsigned long args) * the Auxiliary Vector Table. Read out the elements of the auxvt, * sort and store them in auxvt for later use. */ while (*aux_dat) { - Elf32_auxv_t *auxv_entry = (Elf32_auxv_t *) aux_dat; + ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat; if (auxv_entry->a_type <= AT_EGID) { - _dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t)); + _dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t))); } aux_dat += 2; } @@ -169,10 +167,10 @@ static void * __attribute_used__ _dl_start(unsigned long args) if (!auxvt[AT_BASE].a_un.a_val) auxvt[AT_BASE].a_un.a_val = elf_machine_load_address(); load_addr = auxvt[AT_BASE].a_un.a_val; - header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr; + header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; /* Check the ELF header to make sure everything looks ok. */ - if (!header || header->e_ident[EI_CLASS] != ELFCLASS32 || + if (!header || header->e_ident[EI_CLASS] != ELF_CLASS || header->e_ident[EI_VERSION] != EV_CURRENT /* Do not use an inline _dl_strncmp here or some arches * will blow chunks, i.e. those that need to relocate all @@ -185,56 +183,43 @@ static void * __attribute_used__ _dl_start(unsigned long args) SEND_STDERR("Invalid ELF header\n"); _dl_exit(0); } -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("ELF header="); - SEND_ADDRESS_STDERR(load_addr, 1); -#endif - + SEND_STDERR_DEBUG("ELF header="); + SEND_ADDRESS_STDERR_DEBUG(load_addr, 1); /* Locate the global offset table. Since this code must be PIC * we can take advantage of the magic offset register, if we * happen to know what that is for this architecture. If not, * we can always read stuff out of the ELF file to find it... */ got = elf_machine_dynamic(); - dpnt = (Elf32_Dyn *) (got + load_addr); -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("First Dynamic section entry="); - SEND_ADDRESS_STDERR(dpnt, 1); -#endif + dpnt = (ElfW(Dyn) *) (got + load_addr); + SEND_STDERR_DEBUG("First Dynamic section entry="); + SEND_ADDRESS_STDERR_DEBUG(dpnt, 1); _dl_memset(tpnt, 0, sizeof(struct elf_resolve)); tpnt->loadaddr = load_addr; /* OK, that was easy. Next scan the DYNAMIC section of the image. We are only doing ourself right now - we will have to do the rest later */ -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("scanning DYNAMIC section\n"); -#endif + SEND_STDERR_DEBUG("Scanning DYNAMIC section\n"); tpnt->dynamic_addr = dpnt; -#if defined(__mips__) || defined(__cris__) +#if defined(NO_FUNCS_BEFORE_BOOTSTRAP) /* Some architectures cannot call functions here, must inline */ __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr); #else _dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr); #endif -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("done scanning DYNAMIC section\n"); -#endif + SEND_STDERR_DEBUG("Done scanning DYNAMIC section\n"); -#if defined(__mips__) +#if defined(PERFORM_BOOTSTRAP_GOT) -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("About to do specific GOT bootstrap\n"); -#endif - /* For MIPS we have to do stuff to the GOT before we do relocations. */ + SEND_STDERR_DEBUG("About to do specific GOT bootstrap\n"); + /* some arches (like MIPS) we have to tweak the GOT before relocations */ PERFORM_BOOTSTRAP_GOT(tpnt); #else /* OK, now do the relocations. We do not do a lazy binding here, so that once we are done, we have considerably more flexibility. */ -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("About to do library loader relocations\n"); -#endif + SEND_STDERR_DEBUG("About to do library loader relocations\n"); { int goof, indx; @@ -249,50 +234,49 @@ static void * __attribute_used__ _dl_start(unsigned long args) unsigned long *reloc_addr; unsigned long symbol_addr; int symtab_index; - Elf32_Sym *sym; + ElfW(Sym) *sym; ELF_RELOC *rpnt; unsigned long rel_addr, rel_size; - Elf32_Word relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; + ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; - rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : tpnt-> - dynamic_info[DT_RELOC_TABLE_ADDR]); - rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : tpnt-> - dynamic_info[DT_RELOC_TABLE_SIZE]); + rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : + tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]); + rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : + tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]); if (!rel_addr) continue; /* Now parse the relocation information */ /* Since ldso is linked with -Bsymbolic, all relocs will be RELATIVE(for those archs that have - RELATIVE relocs) which means that the for(..) loop below has noting to do and can be deleted. + RELATIVE relocs) which means that the for(..) loop below has nothing to do and can be deleted. Possibly one should add a HAVE_RELATIVE_RELOCS directive and #ifdef away some code. */ if (!indx && relative_count) { rel_size -= relative_count * sizeof(ELF_RELOC); - elf_machine_relative (load_addr, rel_addr, relative_count); + elf_machine_relative(load_addr, rel_addr, relative_count); rel_addr += relative_count * sizeof(ELF_RELOC);; } rpnt = (ELF_RELOC *) (rel_addr + load_addr); for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) { reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset); - symtab_index = ELF32_R_SYM(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); symbol_addr = 0; sym = NULL; if (symtab_index) { char *strtab; - Elf32_Sym *symtab; + ElfW(Sym) *symtab; - symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]; strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; sym = &symtab[symtab_index]; symbol_addr = load_addr + sym->st_value; -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("relocating symbol: "); - SEND_STDERR(strtab + sym->st_name); - SEND_STDERR("\n"); -#endif - } + SEND_STDERR_DEBUG("relocating symbol: "); + SEND_STDERR_DEBUG(strtab + sym->st_name); + SEND_STDERR_DEBUG("\n"); + } else + SEND_STDERR_DEBUG("relocating unknown symbol\n"); /* Use this machine-specific macro to perform the actual relocation. */ PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym); } @@ -304,24 +288,22 @@ static void * __attribute_used__ _dl_start(unsigned long args) } #endif -#ifdef __SUPPORT_LD_DEBUG_EARLY__ /* Wahoo!!! */ - SEND_STDERR("Done relocating library loader, so we can now\n" - "\tuse globals and make function calls!\n"); -#endif + SEND_STDERR_DEBUG("Done relocating ldso; we can now use globals and make function calls!\n"); /* Now we have done the mandatory linking of some things. We are now free to start using global variables, since these things have all been - fixed up by now. Still no function calls outside of this library , + fixed up by now. Still no function calls outside of this library, since the dynamic resolver is not yet ready. */ + + __rtld_stack_end = (void *)(argv - 1); + _dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv); /* Transfer control to the application. */ -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("transfering control to application\n"); -#endif - _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_fcn; + 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); START(); } - diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 54da613aa..709d58d25 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -33,6 +33,9 @@ #include "ldso.h" #include "unsecvars.h" +/* Pull in common debug code */ +#include "dl-debug.c" + #define ALLOW_ZERO_PLTGOT /* Pull in the value of _dl_progname */ @@ -97,23 +100,18 @@ static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void) void (*dl_elf_func) (void); dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]); -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) - _dl_dprintf(_dl_debug_file, - "\ncalling FINI: %s\n\n", - tpnt->libname); -#endif + _dl_if_debug_dprint("\ncalling FINI: %s\n\n", tpnt->libname); (*dl_elf_func) (); } } } void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, - Elf32_auxv_t auxvt[AT_EGID + 1], char **envp, + ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv) { ElfW(Phdr) *ppnt; - Elf32_Dyn *dpnt; + ElfW(Dyn) *dpnt; char *lpntstr; int i, goof = 0, unlazy = 0, trace_loaded_objects = 0; struct dyn_elf *rpnt; @@ -127,7 +125,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, ElfW(Addr) relro_addr = 0; size_t relro_size = 0; - /* Wahoo!!! We managed to make a function call! Get malloc * setup so we can use _dl_dprintf() to print debug noise * instead of the SEND_STDERR macros used in dl-startup.c */ @@ -142,10 +139,8 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, _dl_malloc_addr = (unsigned char *)_dl_pagesize; _dl_mmap_zero = 0; -#ifdef __SUPPORT_LD_DEBUG_EARLY__ /* Wahoo!!! */ - _dl_dprintf(2, "\nCool, ldso survived making function calls.\n"); -#endif + _dl_debug_early("Cool, ldso survived making function calls\n"); /* Now we have done the mandatory linking of some things. We are now * free to start using global variables, since these things have all @@ -156,8 +151,8 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, _dl_progname = argv[0]; } - if (_start == (void *) auxvt[AT_ENTRY].a_un.a_fcn) { - _dl_dprintf(2, "Standalone execution is not supported yet\n"); + if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) { + _dl_dprintf(_dl_debug_file, "Standalone execution is not supported yet\n"); _dl_exit(1); } @@ -213,7 +208,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, */ { int i; - ElfW(Phdr) *ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr; + ElfW(Phdr) *ppnt = (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) { @@ -221,12 +216,9 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, break; } -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - if (app_tpnt->loadaddr) { - _dl_dprintf(2, "Position Independent Executable: " + if (app_tpnt->loadaddr) + _dl_debug_early("Position Independent Executable: " "app_tpnt->loadaddr=%x\n", app_tpnt->loadaddr); - } -#endif } /* @@ -236,14 +228,14 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, debug_addr = _dl_malloc(sizeof(struct r_debug)); _dl_memset(debug_addr, 0, sizeof(struct r_debug)); - ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr; + ppnt = (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_GNU_RELRO) { relro_addr = ppnt->p_vaddr; relro_size = ppnt->p_memsz; } if (ppnt->p_type == PT_DYNAMIC) { - dpnt = (Elf32_Dyn *) (ppnt->p_vaddr + app_tpnt->loadaddr); + dpnt = (ElfW(Dyn) *) (ppnt->p_vaddr + app_tpnt->loadaddr); _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr); #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__ /* Ugly, ugly. We need to call mprotect to change the @@ -251,12 +243,10 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, * dynamic linking. We can set the protection back * again once we are done. */ -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - _dl_dprintf(2, "calling mprotect on the application program\n"); -#endif + _dl_debug_early("calling mprotect on the application program\n"); /* Now cover the application program. */ if (app_tpnt->dynamic_info[DT_TEXTREL]) { - ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr; + ppnt = (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_LOAD && !(ppnt->p_flags & PF_W)) _dl_mprotect((void *) ((ppnt->p_vaddr + app_tpnt->loadaddr) & PAGE_ALIGN), @@ -276,7 +266,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, app_tpnt = _dl_add_elf_hash_table(_dl_progname, (char *)app_tpnt->loadaddr, app_tpnt->dynamic_info, ppnt->p_vaddr + app_tpnt->loadaddr, ppnt->p_filesz); _dl_loaded_modules->libtype = elf_executable; - _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr; + _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val; _dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); _dl_memset(rpnt, 0, sizeof(struct dyn_elf)); @@ -305,10 +295,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, if (ptmp != _dl_ldsopath) *ptmp = '\0'; -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - _dl_dprintf(2, "Lib Loader:\t(%x) %s\n", - tpnt->loadaddr, tpnt->libname); -#endif + _dl_debug_early("Lib Loader: (%x) %s\n", tpnt->loadaddr, tpnt->libname); } } app_tpnt->relro_addr = relro_addr; @@ -355,7 +342,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, _dl_debug_file= _dl_open(filename, O_WRONLY|O_CREAT, 0644); if (_dl_debug_file < 0) { _dl_debug_file = 2; - _dl_dprintf (2, "can't open file: '%s'\n",filename); + _dl_dprintf(_dl_debug_file, "can't open file: '%s'\n",filename); } } } @@ -411,12 +398,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, *str2 = '\0'; if (!_dl_secure || _dl_strchr(str, '/') == NULL) { -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) - _dl_dprintf(_dl_debug_file, - "\tfile='%s'; needed by '%s'\n", - str, _dl_progname); -#endif + _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", str, _dl_progname); tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects); if (!tpnt1) { @@ -426,16 +408,13 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, else #endif { - _dl_dprintf(2, "%s: can't load " "library '%s'\n", _dl_progname, str); + _dl_dprintf(_dl_debug_file, "%s: can't load " "library '%s'\n", _dl_progname, str); _dl_exit(15); } } else { tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - _dl_dprintf(2, - "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname); -#endif + _dl_debug_early("Loading: (%x) %s\n", tpnt1->loadaddr, tpnt1->libname); #ifdef __LDSO_LDD_SUPPORT__ if (trace_loaded_objects && @@ -447,7 +426,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, */ if (_dl_strcmp(_dl_progname, str) != 0) _dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname, - (unsigned)tpnt1->loadaddr); + tpnt1->loadaddr); } #endif } @@ -472,7 +451,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, } if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) { - _dl_dprintf(2, "%s: can't open file '%s'\n", + _dl_dprintf(_dl_debug_file, "%s: can't open file '%s'\n", _dl_progname, LDSO_PRELOAD); break; } @@ -481,7 +460,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); _dl_close(fd); if (preload == (caddr_t) -1) { - _dl_dprintf(2, "%s: can't map file '%s'\n", + _dl_dprintf(_dl_debug_file, "%s: can't map file '%s'\n", _dl_progname, LDSO_PRELOAD); break; } @@ -509,12 +488,8 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, /*nada */ ; c = *cp; *cp = '\0'; -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) - _dl_dprintf(_dl_debug_file, - "\tfile='%s'; needed by '%s'\n", - cp2, _dl_progname); -#endif + + _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", cp2, _dl_progname); tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects); if (!tpnt1) { @@ -524,15 +499,13 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, else #endif { - _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, cp2); + _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, cp2); _dl_exit(15); } } else { tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - _dl_dprintf(2, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname); -#endif + _dl_debug_early("Loading: (%x) %s\n", tpnt1->loadaddr, tpnt1->libname); #ifdef __LDSO_LDD_SUPPORT__ if (trace_loaded_objects && @@ -556,23 +529,20 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, nlist = 0; for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) { - Elf32_Dyn *dpnt; + ElfW(Dyn) *dpnt; nlist++; - for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) { + for (dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) { if (dpnt->d_tag == DT_NEEDED) { char *name; struct init_fini_list *tmp; lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val); name = _dl_get_last_path_component(lpntstr); + if (_dl_strcmp(name, "ld-uClibc.so.0") == 0) + continue; -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) - _dl_dprintf(_dl_debug_file, - "\tfile='%s'; needed by '%s'\n", - lpntstr, _dl_progname); -#endif + _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", lpntstr, _dl_progname); if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects))) { #ifdef __LDSO_LDD_SUPPORT__ @@ -582,7 +552,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, } else #endif { - _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr); + _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, lpntstr); _dl_exit(16); } } @@ -594,9 +564,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - _dl_dprintf(2, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname); -#endif + _dl_debug_early("Loading: (%x) %s\n", tpnt1->loadaddr, tpnt1->libname); #ifdef __LDSO_LDD_SUPPORT__ if (trace_loaded_objects && @@ -630,10 +598,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, for (; runp; runp = runp->next) { if (runp->tpnt == tcurr) { struct elf_resolve *here = init_fini_list[k]; -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - _dl_dprintf(2, "Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j); -#endif + _dl_if_debug_dprint("Move %s from pos %d to %d in INIT/FINI list\n", here->libname, k, j); for (i = (k - j); i; --i) init_fini_list[i+j] = init_fini_list[i+j-1]; init_fini_list[j] = here; @@ -645,16 +610,16 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, } #ifdef __SUPPORT_LD_DEBUG__ if(_dl_debug) { - _dl_dprintf(2, "\nINIT/FINI order and dependencies:\n"); + _dl_dprintf(_dl_debug_file, "\nINIT/FINI order and dependencies:\n"); for (i = 0; i < nlist; i++) { struct init_fini_list *tmp; - _dl_dprintf(2, "lib: %s has deps:\n", + _dl_dprintf(_dl_debug_file, "lib: %s has deps:\n", init_fini_list[i]->libname); tmp = init_fini_list[i]->init_fini; for (; tmp; tmp = tmp->next) - _dl_dprintf(2, " %s ", tmp->tpnt->libname); - _dl_dprintf(2, "\n"); + _dl_dprintf(_dl_debug_file, " %s ", tmp->tpnt->libname); + _dl_dprintf(_dl_debug_file, "\n"); } } #endif @@ -666,7 +631,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, * again once all libs are loaded. */ if (tpnt) { - ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr; + ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; ElfW(Phdr) *myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff); int j; @@ -722,9 +687,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, } #endif -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - _dl_dprintf(2, "Beginning relocation fixups\n"); -#endif + _dl_debug_early("Beginning relocation fixups\n"); #ifdef __mips__ /* @@ -796,17 +759,12 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]); -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) - _dl_dprintf(_dl_debug_file, - "\ncalling INIT: %s\n\n", - tpnt->libname); -#endif + _dl_if_debug_dprint("calling INIT: %s\n\n", tpnt->libname); (*dl_elf_func) (); } } -#ifndef _DL_DO_FINI_IN_LIBC +#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", @@ -880,22 +838,18 @@ void *_dl_malloc(int size) void *retval; #if 0 -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - _dl_dprintf(2, "malloc: request for %d bytes\n", size); -#endif + _dl_debug_early("request for %d bytes\n", size); #endif if (_dl_malloc_function) return (*_dl_malloc_function) (size); if (_dl_malloc_addr - _dl_mmap_zero + (unsigned)size > _dl_pagesize) { -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - _dl_dprintf(2, "malloc: mmapping more memory\n"); -#endif + _dl_debug_early("mmapping more memory\n"); _dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (_dl_mmap_check_error(_dl_mmap_zero)) { - _dl_dprintf(2, "%s: mmap of a spare page failed!\n", _dl_progname); + _dl_dprintf(_dl_debug_file, "%s: mmap of a spare page failed!\n", _dl_progname); _dl_exit(20); } } diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h index f369f77f1..df2f25a14 100644 --- a/ldso/ldso/mips/dl-startup.h +++ b/ldso/ldso/mips/dl-startup.h @@ -2,40 +2,64 @@ * will work as expected and cope with whatever platform specific wierdness is * needed for this architecture. * Copyright (C) 2005 by Joakim Tjernlund + * Copyright (C) 2005 by Erik Andersen */ + asm("" " .text\n" " .globl _start\n" + " .ent _start\n" " .type _start,@function\n" "_start:\n" " .set noreorder\n" - " bltzal $0, 0f\n" - " nop\n" - "0: .cpload $31\n" - " .set reorder\n" - " la $4, _DYNAMIC\n" - " sw $4, -0x7ff0($28)\n" - " move $4, $29\n" - " la $8, coff\n" - " .set noreorder\n" - " bltzal $0, coff\n" + " move $25, $31\n" + " bal 0f\n" " nop\n" - "coff: subu $8, $31, $8\n" + "0:\n" + " .cpload $31\n" + " move $31, $25\n" " .set reorder\n" - " la $25, _dl_start\n" - " addu $25, $8\n" - " jalr $25\n" - " move $17, $2\n" - " lw $4, 0($29)\n" - " la $5, 4($29)\n" - " sll $6, $4, 2\n" - " addu $6, $6, $5\n" - " addu $6, $6, 4\n" - " move $25, $17\n" - " jr $25\n" - " .size _start,.-_start\n" - " .previous\n" + " la $4, _DYNAMIC\n" + " sw $4, -0x7ff0($28)\n" + " move $4, $29\n" + " subu $29, 16\n" + " la $8, .coff\n" + " bltzal $8, .coff\n" + ".coff:\n" + " subu $8, $31, $8\n" + " la $25, _dl_start\n" + " addu $25, $8\n" + " jalr $25\n" + " addiu $29, 16\n" + " move $16, $28\n" + " move $17, $2\n" + " lw $2, _dl_skip_args\n" + " beq $2, $0, 1f\n" + " lw $4, 0($29)\n" + " subu $4, $2\n" + " sll $2, 2\n" + " addu $29, $2\n" + " sw $4, 0($29)\n" + "1:\n" + " lw $5, 0($29)\n" + " la $6, 4 ($29)\n" + " sll $7, $5, 2\n" + " addu $7, $7, $6\n" + " addu $7, $7, 4\n" + " and $2, $29, -2 * 4\n" + " sw $29, -4($2)\n" + " subu $29, $2, 32\n" + " .cprestore 16\n" + " lw $29, 28($29)\n" + " la $2, _dl_fini\n" + " move $25, $17\n" + " jr $25\n" + ".end _start\n" + ".size _start, . -_start\n" + "\n\n" + "\n\n" + ".previous\n" ); /* @@ -46,6 +70,10 @@ asm("" #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS)+1) +/* We can't call functions earlier in the dl startup process */ +#define NO_FUNCS_BEFORE_BOOTSTRAP + + /* * Here is a macro to perform the GOT relocation. This is only * used when bootstrapping the dynamic loader. diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index 595653000..18b5799d9 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -27,82 +27,6 @@ * SUCH DAMAGE. */ -#if defined (__SUPPORT_LD_DEBUG__) -static const char *_dl_reltypes_tab[] = -{ - [0] "R_MIPS_NONE", "R_MIPS_16", "R_MIPS_32", - [3] "R_MIPS_REL32", "R_MIPS_26", "R_MIPS_HI16", - [6] "R_MIPS_LO16", "R_MIPS_GPREL16", "R_MIPS_LITERAL", - [9] "R_MIPS_GOT16", "R_MIPS_PC16", "R_MIPS_CALL16", - [12] "R_MIPS_GPREL32", - [16] "R_MIPS_SHIFT5", "R_MIPS_SHIFT6", "R_MIPS_64", - [19] "R_MIPS_GOT_DISP", "R_MIPS_GOT_PAGE", "R_MIPS_GOT_OFST", - [22] "R_MIPS_GOT_HI16", "R_MIPS_GOT_LO16", "R_MIPS_SUB", - [25] "R_MIPS_INSERT_A", "R_MIPS_INSERT_B", "R_MIPS_DELETE", - [28] "R_MIPS_HIGHER", "R_MIPS_HIGHEST", "R_MIPS_CALL_HI16", - [31] "R_MIPS_CALL_LO16", "R_MIPS_SCN_DISP", "R_MIPS_REL16", - [34] "R_MIPS_ADD_IMMEDIATE", "R_MIPS_PJUMP", "R_MIPS_RELGOT", - [37] "R_MIPS_JALR", -}; - -static const char * -_dl_reltypes(int type) -{ - static char buf[22]; - const char *str; - - if (type >= (int)(sizeof (_dl_reltypes_tab)/sizeof(_dl_reltypes_tab[0])) || - NULL == (str = _dl_reltypes_tab[type])) - { - str =_dl_simple_ltoa( buf, (unsigned long)(type)); - } - return str; -} - -static -void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index) -{ - if(_dl_debug_symbols) - { - if(symtab_index){ - _dl_dprintf(_dl_debug_file, "\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x", - strtab + symtab[symtab_index].st_name, - symtab[symtab_index].st_value, - symtab[symtab_index].st_size, - symtab[symtab_index].st_info, - symtab[symtab_index].st_other, - symtab[symtab_index].st_shndx); - } - } -} - -static void debug_reloc(Elf32_Sym *symtab,char *strtab, ELF_RELOC *rpnt) -{ - if(_dl_debug_reloc) - { - int symtab_index; - const char *sym; - symtab_index = ELF32_R_SYM(rpnt->r_info); - sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0"; - - if(_dl_debug_symbols) - _dl_dprintf(_dl_debug_file, "\n\t"); - else - _dl_dprintf(_dl_debug_file, "\n%s\n\t", sym); -#ifdef ELF_USES_RELOCA - _dl_dprintf(_dl_debug_file, "%s\toffset=%x\taddend=%x", - _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)), - rpnt->r_offset, - rpnt->r_addend); -#else - _dl_dprintf(_dl_debug_file, "%s\toffset=%x\n", - _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)), - rpnt->r_offset); -#endif - } -} -#endif - extern int _dl_runtime_resolve(void); #define OFFSET_GP_GOT 0x7ff0 @@ -195,9 +119,9 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, symtab_index = ELF32_R_SYM(rpnt->r_info); symbol_addr = 0; -#if defined (__SUPPORT_LD_DEBUG__) debug_sym(symtab,strtab,symtab_index); debug_reloc(symtab,strtab,rpnt); +#if defined (__SUPPORT_LD_DEBUG__) if (reloc_addr) old_val = *reloc_addr; #endif diff --git a/ldso/ldso/mips/resolve.S b/ldso/ldso/mips/resolve.S index 8b492947d..6dc89643e 100644 --- a/ldso/ldso/mips/resolve.S +++ b/ldso/ldso/mips/resolve.S @@ -11,6 +11,7 @@ * Copyright (C) 2002 Steven J. Hill <sjhill@realitydiluted.com> * */ + .text .align 2 .globl _dl_runtime_resolve @@ -19,27 +20,48 @@ _dl_runtime_resolve: .frame $29, 40, $31 .set noreorder - move $3, $28 # Save GP - addu $25, 8 # t9 ($25) now points at .cpload instruction - .cpload $25 # Compute GP - .set reorder + + # Save GP. + move $3, $28 + + # Save arguments and sp value on stack. subu $29, 40 + + # Modify t9 ($25) so as to point .cpload instruction. + addiu $25, 12 + + # Compute GP. + .set noreorder + .cpload $25 + .set reorder + + # Save slot call pc. + move $2, $31 .cprestore 32 + + # Store function arguments from registers to stack sw $15, 36($29) sw $4, 16($29) sw $5, 20($29) sw $6, 24($29) sw $7, 28($29) + + # Setup functions args and call __dl_runtime_resolve move $4, $24 move $5, $3 - jal __dl_runtime_resolve + jal __dl_runtime_resolve + + # Restore function arguments from stack to registers lw $31, 36($29) lw $4, 16($29) lw $5, 20($29) lw $6, 24($29) lw $7, 28($29) - addu $29, 40 + + # Do a tail call to the original function + addiu $29, 40 move $25, $2 jr $25 -.size _dl_runtime_resolve,.-_dl_runtime_resolve -.end _dl_runtime_resolve +.end _dl_runtime_resolve +.previous + diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index 0c744c210..76c8296e1 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -76,17 +76,28 @@ extern char *_dl_debug __attribute__ ((__weak__)); #ifdef __SUPPORT_LD_DEBUG__ char *_dl_debug = 0; #endif -char *_dl_library_path = 0; /* Where we look for libraries */ -char *_dl_ldsopath = 0; /* Location of the shared lib loader */ +char *_dl_library_path = 0; /* Where we look for libraries */ +char *_dl_ldsopath = 0; /* Location of the shared lib loader */ int _dl_errno = 0; /* We can't use the real errno in ldso */ size_t _dl_pagesize = PAGE_SIZE; /* Store the page size for use later */ /* This global variable is also to communicate with debuggers such as gdb. */ struct r_debug *_dl_debug_addr = NULL; #define _dl_malloc malloc +#include "../ldso/dl-debug.c" #include "dl-progname.h" #include "../ldso/dl-hash.c" #define _dl_trace_loaded_objects 0 #include "../ldso/dl-elf.c" +#endif /* __LIBDL_SHARED__ */ + +#ifdef __SUPPORT_LD_DEBUG__ +# define _dl_if_debug_print(fmt, args...) \ + do { \ + if (_dl_debug) \ + fprintf(stderr, "%s():%i: " fmt, __FUNCTION__, __LINE__, ## args); \ + } while (0) +#else +# define _dl_if_debug_print(fmt, args...) #endif static int do_dlclose(void *, int need_fini); @@ -128,7 +139,7 @@ void __attribute__ ((destructor)) dl_cleanup(void) void *dlopen(const char *libname, int flag) { - struct elf_resolve *tpnt, *tfrom, *tcurr=NULL; + struct elf_resolve *tpnt, *tfrom; struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle; struct dyn_elf *dpnt; ElfW(Addr) from; @@ -155,7 +166,7 @@ void *dlopen(const char *libname, int flag) /* * Try and locate the module we were called from - we - * need this so that we get the correct RPATH. Note that + * need this so that we get the correct RPATH/RUNPATH. Note that * this is the current behavior under Solaris, but the * ABI+ specifies that we should only use the RPATH from * the application. Thus this may go away at some time @@ -168,14 +179,16 @@ void *dlopen(const char *libname, int flag) && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) tfrom = tpnt; } - for(rpnt = _dl_symbol_tables; rpnt->next; rpnt=rpnt->next); + for(rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt=rpnt->next); relro_ptr = rpnt; + now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0; + if (getenv("LD_BIND_NOW")) + now_flag = RTLD_NOW; + /* Try to load the specified library */ -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "Trying to dlopen '%s'\n", (char*)libname); -#endif + _dl_if_debug_print("Trying to dlopen '%s', RTLD_GLOBAL:%d RTLD_NOW:%d\n", + (char*)libname, (flag & RTLD_GLOBAL ? 1:0), (now_flag & RTLD_NOW ? 1:0)); tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0); if (tpnt == NULL) { @@ -191,10 +204,7 @@ void *dlopen(const char *libname, int flag) _dl_handles = dyn_ptr = dyn_chain; if (tpnt->usage_count > 1) { -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "Lib: % already opened\n", libname); -#endif + _dl_if_debug_print("Lib: %s already opened\n", libname); /* see if there is a handle from a earlier dlopen */ for (handle = _dl_handles->next_handle; handle; handle = handle->next_handle) { if (handle->dyn == tpnt) { @@ -211,10 +221,7 @@ void *dlopen(const char *libname, int flag) tpnt->init_flag |= DL_OPENED; } -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "Looking for needed libraries\n"); -#endif + _dl_if_debug_print("Looking for needed libraries\n"); nlist = 0; runp = alloca(sizeof(*runp)); runp->tpnt = tpnt; @@ -222,24 +229,21 @@ void *dlopen(const char *libname, int flag) dep_list = runp2 = runp; for (; runp; runp = runp->next) { - Elf32_Dyn *dpnt; + ElfW(Dyn) *dpnt; char *lpntstr; nlist++; runp->tpnt->init_fini = NULL; /* clear any previous dependcies */ - for (dpnt = (Elf32_Dyn *) runp->tpnt->dynamic_addr; dpnt->d_tag; dpnt++) { + 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); -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "Trying to load '%s', needed by '%s'\n", - lpntstr, runp->tpnt->libname); -#endif - tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, 0); + _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); if (!tpnt1) goto oops; @@ -262,11 +266,8 @@ void *dlopen(const char *libname, int flag) for (tmp=dep_list; tmp; tmp = tmp->next) { if (tpnt1 == tmp->tpnt) { /* if match => cirular dependency, drop it */ -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "Circular dependency, skipping '%s',\n", + _dl_if_debug_print("Circular dependency, skipping '%s',\n", tmp->tpnt->libname); -#endif tpnt1->usage_count--; break; } @@ -308,10 +309,7 @@ void *dlopen(const char *libname, int flag) for (; runp; runp = runp->next) { if (runp->tpnt == runp2->tpnt) { struct elf_resolve *here = init_fini_list[k]; -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j); -#endif + _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) init_fini_list[i+j] = init_fini_list[i+j-1]; init_fini_list[j] = here; @@ -327,26 +325,19 @@ void *dlopen(const char *libname, int flag) for (i=0;i < nlist;i++) { fprintf(stderr, "lib: %s has deps:\n", init_fini_list[i]->libname); runp = init_fini_list[i]->init_fini; - for ( ;runp; runp = runp->next) + for (; runp; runp = runp->next) printf(" %s ", runp->tpnt->libname); printf("\n"); } } #endif -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "Beginning dlopen relocation fixups\n"); -#endif + _dl_if_debug_print("Beginning dlopen relocation fixups\n"); /* * OK, now all of the kids are tucked into bed in their proper addresses. * Now we go through and look for REL and RELA records that indicate fixups * to the GOT tables. We need to do this in reverse order so that COPY * directives work correctly */ - now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0; - if (getenv("LD_BIND_NOW")) - now_flag = RTLD_NOW; - #ifdef __mips__ /* * Relocation of the GOT entries for MIPS have to be done @@ -358,9 +349,11 @@ void *dlopen(const char *libname, int flag) if (_dl_fixup(dyn_chain, now_flag)) goto oops; - for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) { - if (rpnt->dyn->relro_size) - _dl_protect_relro(rpnt->dyn); + if (relro_ptr) { + for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) { + if (rpnt->dyn->relro_size) + _dl_protect_relro(rpnt->dyn); + } } /* TODO: Should we set the protections of all pages back to R/O now ? */ @@ -389,10 +382,8 @@ void *dlopen(const char *libname, int flag) void (*dl_elf_func) (void); dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]); if (dl_elf_func && *dl_elf_func != NULL) { -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "running ctors for library %s at '%x'\n", tpnt->libname, (unsigned)dl_elf_func); -#endif + _dl_if_debug_print("running ctors for library %s at '%p'\n", + tpnt->libname, dl_elf_func); (*dl_elf_func) (); } } @@ -492,10 +483,8 @@ static int do_dlclose(void *vhandle, int need_fini) rpnt1->next_handle = rpnt->next_handle; else _dl_handles = rpnt->next_handle; -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "dlclose: %s, usage count: %d\n", handle->dyn->libname, handle->dyn->usage_count); -#endif + _dl_if_debug_print("%s: usage count: %d\n", + handle->dyn->libname, handle->dyn->usage_count); if (handle->dyn->usage_count != 1) { handle->dyn->usage_count--; free(handle); @@ -509,17 +498,12 @@ static int do_dlclose(void *vhandle, int 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]); -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "running dtors for library %s at '%x'\n", tpnt->libname, (unsigned)dl_elf_fini); -#endif + _dl_if_debug_print("running dtors for library %s at '%p'\n", + tpnt->libname, dl_elf_fini); (*dl_elf_fini) (); } -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "dlclose unmapping: %s\n", tpnt->libname); -#endif + _dl_if_debug_print("unmapping: %s\n", tpnt->libname); end = 0; for (i = 0, ppnt = tpnt->ppnt; i < tpnt->n_phent; ppnt++, i++) { @@ -543,10 +527,7 @@ static int do_dlclose(void *vhandle, int need_fini) } else for (run_tpnt = _dl_loaded_modules; run_tpnt; run_tpnt = run_tpnt->next) if (run_tpnt->next == tpnt) { -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "dlclose removing loaded_modules: %s\n", tpnt->libname); -#endif + _dl_if_debug_print("removing loaded_modules: %s\n", tpnt->libname); run_tpnt->next = run_tpnt->next->next; if (run_tpnt->next) run_tpnt->next->prev = run_tpnt; @@ -554,24 +535,23 @@ static int do_dlclose(void *vhandle, int need_fini) } /* Next, remove tpnt from the global symbol table list */ - if (_dl_symbol_tables->dyn == tpnt) { - _dl_symbol_tables = _dl_symbol_tables->next; - if (_dl_symbol_tables) - _dl_symbol_tables->prev = 0; - } else - for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) { - if (rpnt1->next->dyn == tpnt) { -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "dlclose removing symbol_tables: %s\n", tpnt->libname); -#endif - free(rpnt1->next); - rpnt1->next = rpnt1->next->next; - if (rpnt1->next) - rpnt1->next->prev = rpnt1; - break; + if (_dl_symbol_tables) { + if (_dl_symbol_tables->dyn == tpnt) { + _dl_symbol_tables = _dl_symbol_tables->next; + if (_dl_symbol_tables) + _dl_symbol_tables->prev = 0; + } else + 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); + free(rpnt1->next); + rpnt1->next = rpnt1->next->next; + if (rpnt1->next) + rpnt1->next->prev = rpnt1; + break; + } } - } + } free(tpnt->libname); free(tpnt); } @@ -623,24 +603,21 @@ int dlinfo(void) fprintf(stderr, "List of loaded modules\n"); /* First start with a complete list of all of the loaded files. */ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { - fprintf(stderr, "\t%x %x %x %s %d %s\n", - (unsigned) tpnt->loadaddr, (unsigned) tpnt, - (unsigned) tpnt->symbol_scope, - type[tpnt->libtype], - tpnt->usage_count, tpnt->libname); + fprintf(stderr, "\t%p %p %p %s %d %s\n", + tpnt->loadaddr, tpnt, tpnt->symbol_scope, + type[tpnt->libtype], + tpnt->usage_count, tpnt->libname); } /* Next dump the module list for the application itself */ - fprintf(stderr, "\nModules for application (%x):\n", - (unsigned) _dl_symbol_tables); + fprintf(stderr, "\nModules for application (%p):\n", _dl_symbol_tables); for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) - fprintf(stderr, "\t%x %s\n", (unsigned) rpnt->dyn, rpnt->dyn->libname); + fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname); for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) { - fprintf(stderr, "Modules for handle %x\n", (unsigned) hpnt); + fprintf(stderr, "Modules for handle %p\n", hpnt); for (rpnt = hpnt; rpnt; rpnt = rpnt->next) - fprintf(stderr, "\t%x %s\n", (unsigned) rpnt->dyn, - rpnt->dyn->libname); + fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname); } return 0; } @@ -658,7 +635,7 @@ int dladdr(const void *__address, Dl_info * __info) pelf = NULL; #if 0 - fprintf(stderr, "dladdr( %x, %x )\n", __address, __info); + fprintf(stderr, "dladdr( %p, %p )\n", __address, __info); #endif for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) { @@ -666,7 +643,7 @@ int dladdr(const void *__address, Dl_info * __info) tpnt = rpnt; #if 0 - fprintf(stderr, "Module \"%s\" at %x\n", + fprintf(stderr, "Module \"%s\" at %p\n", tpnt->libname, tpnt->loadaddr); #endif if (tpnt->loadaddr < (ElfW(Addr)) __address @@ -685,14 +662,14 @@ int dladdr(const void *__address, Dl_info * __info) { char *strtab; - Elf32_Sym *symtab; + ElfW(Sym) *symtab; int hn, si; int sf; int sn = 0; ElfW(Addr) sa; sa = 0; - symtab = (Elf32_Sym *) (pelf->dynamic_info[DT_SYMTAB]); + symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]); strtab = (char *) (pelf->dynamic_info[DT_STRTAB]); sf = 0; @@ -707,7 +684,7 @@ int dladdr(const void *__address, Dl_info * __info) sf = 1; } #if 0 - fprintf(stderr, "Symbol \"%s\" at %x\n", + fprintf(stderr, "Symbol \"%s\" at %p\n", strtab + symtab[si].st_name, symbol_addr); #endif } diff --git a/libc/inet/ntop.c b/libc/inet/ntop.c index bcdc57df8..35c302950 100644 --- a/libc/inet/ntop.c +++ b/libc/inet/ntop.c @@ -58,10 +58,12 @@ inet_ntop4(const u_char *src, char *dst, size_t size) i = 0; for (octet = 0; octet <= 3; octet++) { +#if 0 /* since src is unsigned char, it will never be > 255 ... */ if (src[octet] > 255) { __set_errno (ENOSPC); return (NULL); } +#endif tmp[i++] = '0' + src[octet] / 100; if (tmp[i - 1] == '0') { tmp[i - 1] = '0' + (src[octet] / 10 % 10); diff --git a/libc/inet/socketcalls.c b/libc/inet/socketcalls.c index f93d10952..35ab1d7a8 100644 --- a/libc/inet/socketcalls.c +++ b/libc/inet/socketcalls.c @@ -164,6 +164,12 @@ ssize_t __libc_recv(int sockfd, __ptr_t buffer, size_t len, int flags) return (__socketcall(SYS_RECV, args)); } weak_alias(__libc_recv, recv); +#elif defined(__NR_recvfrom) +ssize_t __libc_recv(int sockfd, __ptr_t buffer, size_t len, int flags) +{ + return (recvfrom(sockfd, buffer, len, flags, NULL, NULL)); +} +weak_alias(__libc_recv, recv); #endif #endif @@ -227,6 +233,12 @@ ssize_t __libc_send(int sockfd, const void *buffer, size_t len, int flags) return (__socketcall(SYS_SEND, args)); } weak_alias(__libc_send, send); +#elif defined(__NR_sendto) +ssize_t __libc_send(int sockfd, const void *buffer, size_t len, int flags) +{ + return (sendto(sockfd, buffer, len, flags, NULL, 0)); +} +weak_alias(__libc_send, send); #endif #endif diff --git a/libc/misc/error/err.c b/libc/misc/error/err.c index 5c53e545f..0d0637148 100644 --- a/libc/misc/error/err.c +++ b/libc/misc/error/err.c @@ -34,7 +34,7 @@ static void vwarn_work(const char *format, va_list args, int showerr) f = fmt + 11; /* At 11. */ if (showerr) { f -= 4; /* At 7. */ - _susv3_strerror_r(errno, buf, sizeof(buf)); + __xpg_strerror_r(errno, buf, sizeof(buf)); } __STDIO_AUTO_THREADLOCK(stderr); diff --git a/libc/misc/glob/glob.c b/libc/misc/glob/glob.c index 14e2a6e22..a93cf0ab4 100644 --- a/libc/misc/glob/glob.c +++ b/libc/misc/glob/glob.c @@ -59,7 +59,7 @@ int glob_pattern_p(const char *pattern, int quote) return 1; case '\\': - if (quote) + if (quote && p[1] != '\0') ++p; break; diff --git a/libc/misc/internals/Makefile b/libc/misc/internals/Makefile index 23816b38d..933b169a6 100644 --- a/libc/misc/internals/Makefile +++ b/libc/misc/internals/Makefile @@ -31,7 +31,7 @@ OBJS=$(COBJS) OBJ_LIST=../../obj.misc.internals -all: $(OBJ_LIST) interp.o +all: $(OBJ_LIST) interp.o static.o $(OBJ_LIST): $(OBJS) echo $(patsubst %, misc/internals/%, $(OBJS)) > $(OBJ_LIST) @@ -44,11 +44,7 @@ interp.c: Makefile "(\".interp\"))) =\""$(DYNAMIC_LINKER)"\";" >> interp.c echo "#endif" >> interp.c -interp.o: interp.c - $(CC) $(CFLAGS) -c $< -o $@ - $(STRIPTOOL) -x -R .note -R .comment $*.o - -$(COBJS): %.o : %.c +$(COBJS) interp.o static.o: %.o : %.c $(CC) $(CFLAGS) -c $< -o $@ $(STRIPTOOL) -x -R .note -R .comment $*.o diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c index a33e6fe4a..21864ba4f 100644 --- a/libc/misc/internals/__uClibc_main.c +++ b/libc/misc/internals/__uClibc_main.c @@ -32,7 +32,7 @@ extern void __guard_setup(void); /* * Prototypes. */ -extern int main(int argc, char **argv, char **envp); +extern void *__libc_stack_end; extern void weak_function _stdio_init(void); extern int *weak_const_function __errno_location(void); extern int *weak_const_function __h_errno_location(void); @@ -165,14 +165,15 @@ void attribute_hidden (*__rtld_fini)(void) = NULL; * are initialized, just before we call the application's main function. */ void __attribute__ ((__noreturn__)) -__uClibc_start_main(int argc, char **argv, char **envp, - void (*app_init)(void), void (*app_fini)(void), void (*rtld_fini)(void)) +__uClibc_main(int (*main)(int, char **, char **), int argc, + char **argv, void (*app_init)(void), void (*app_fini)(void), + void (*rtld_fini)(void), void *stack_end) { #ifdef __ARCH_HAS_MMU__ unsigned long *aux_dat; Elf32_auxv_t auxvt[AT_EGID + 1]; #endif - + __libc_stack_end = stack_end; /* We need to initialize uClibc. If we are dynamically linked this * may have already been completed by the shared lib loader. We call * __uClibc_init() regardless, to be sure the right thing happens. */ @@ -180,15 +181,19 @@ __uClibc_start_main(int argc, char **argv, char **envp, __rtld_fini = rtld_fini; - /* If we are dynamically linked, then ldso already did this for us. */ - if (__environ==NULL) { - /* Statically linked. */ - __environ = envp; + /* The environment begins right after argv. */ + __environ = &argv[argc + 1]; + + /* If the first thing after argv is the arguments + * the the environment is empty. */ + if ((char *) __environ == *argv) { + /* Make __environ point to the NULL at argv[argc] */ + __environ = &argv[argc]; } /* Pull stuff from the ELF header when possible */ #ifdef __ARCH_HAS_MMU__ - aux_dat = (unsigned long*)envp; + aux_dat = (unsigned long*)__environ; while (*aux_dat) { aux_dat++; } @@ -247,23 +252,15 @@ __uClibc_start_main(int argc, char **argv, char **envp, /* * Finally, invoke application's main and then exit. */ - exit(main(argc, argv, envp)); + exit(main(argc, argv, __environ)); } - -/* __uClibc_main is the old main stub of the uClibc. This - * function is called from crt0 (uClibc 0.9.15 and older) after - * ALL shared libraries are initialized, and just before we call - * the application's main() function. - * - * Attention: This stub does not call the .init/.fini sections of - * the application. If you need this, please fix your uClibc port - * so that __uClibc_start_main is called by your crt0.S with - * _init and _fini properly set. -*/ +#ifdef _DL_FINI_CRT_COMPAT +extern int weak_function main(int argc, char **argv, char **envp); void __attribute__ ((__noreturn__)) -__uClibc_main(int argc, char **argv, char ** envp) +__uClibc_start_main(int argc, char **argv, char **envp, + void (*app_fini)(void), void (*app_init)(void)) { - __uClibc_start_main(argc, argv, envp, NULL, NULL, NULL); + __uClibc_main(main, argc, argv, app_init, app_fini, NULL, NULL); } - +#endif diff --git a/libc/misc/pthread/weaks.c b/libc/misc/pthread/weaks.c index 90b4f5494..89c26110c 100644 --- a/libc/misc/pthread/weaks.c +++ b/libc/misc/pthread/weaks.c @@ -23,7 +23,6 @@ static int __pthread_return_0 __P ((void)); static int __pthread_return_1 __P ((void)); -static void __pthread_return_void __P ((void)); /**********************************************************************/ /* Weaks for application/library use. @@ -118,8 +117,3 @@ __pthread_return_1 (void) { return 1; } - -static void -__pthread_return_void (void) -{ -} diff --git a/libc/misc/sysvipc/ipc.h b/libc/misc/sysvipc/ipc.h index e1b94ad12..a5d443543 100644 --- a/libc/misc/sysvipc/ipc.h +++ b/libc/misc/sysvipc/ipc.h @@ -2,10 +2,10 @@ #define IPC_H #include <syscall.h> -#ifdef __NR_ipc - #define __IPC_64 0x100 +#ifdef __NR_ipc + /* The actual system call: all functions are multiplexed by this. */ extern int __syscall_ipc __P((int __call, int __first, int __second, int __third, void *__ptr)); diff --git a/libc/misc/sysvipc/msgq.c b/libc/misc/sysvipc/msgq.c index 411ea3ea4..758dbaa47 100644 --- a/libc/misc/sysvipc/msgq.c +++ b/libc/misc/sysvipc/msgq.c @@ -6,14 +6,18 @@ #ifdef L_msgctl #ifdef __NR_msgctl -_syscall3(int, msgctl, int, msqid, int, cmd | __IPC_64, struct msqid_ds *, buf); -#else +#define __NR___libc_msgctl __NR_msgctl +_syscall3(int, __libc_msgctl, int, msqid, int, cmd, struct msqid_ds *, buf); +#endif /* Message queue control operation. */ -int msgctl (int msqid, int cmd, struct msqid_ds *buf) +int msgctl(int msqid, int cmd, struct msqid_ds *buf) { - return __syscall_ipc(IPCOP_msgctl ,msqid ,cmd | __IPC_64 ,0 ,buf); -} +#ifdef __NR_msgctl + return __libc_msgctl(msqid, cmd | __IPC_64, buf); +#else + return __syscall_ipc(IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf); #endif +} #endif diff --git a/libc/misc/sysvipc/shm.c b/libc/misc/sysvipc/shm.c index d21d9f54b..29f3178d6 100644 --- a/libc/misc/sysvipc/shm.c +++ b/libc/misc/sysvipc/shm.c @@ -48,13 +48,17 @@ void * shmat (int shmid, const void *shmaddr, int shmflg) #ifdef L_shmctl /* Provide operations to control over shared memory segments. */ #ifdef __NR_shmctl -_syscall3(int, shmctl, int, shmid, int, cmd | __IPC_64, struct shmid_ds *, buf); -#else -int shmctl (int shmid, int cmd, struct shmid_ds *buf) +#define __NR___libc_shmctl __NR_shmctl +_syscall3(int, __libc_shmctl, int, shmid, int, cmd, struct shmid_ds *, buf); +#endif +int shmctl(int shmid, int cmd, struct shmid_ds *buf) { - return __syscall_ipc(IPCOP_shmctl, shmid, cmd | __IPC_64 , 0, buf); -} +#ifdef __NR_shmctl + return __libc_shmctl(shmid, cmd | __IPC_64, buf); +#else + return __syscall_ipc(IPCOP_shmctl, shmid, cmd | __IPC_64, 0, buf); #endif +} #endif diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c index 7b1ae388b..f43bb8a3c 100644 --- a/libc/misc/time/time.c +++ b/libc/misc/time/time.c @@ -118,6 +118,15 @@ * Make lookup_tzname() static (as it should have been). * Have strftime() get timezone information from the passed struct * for the %z and %Z conversions when using struct tm extensions. + * + * Jul 24, 2004 + * Fix 2 bugs in strftime related to glibc struct tm extensions. + * 1) Need to negate tm_gmtoff field value when used. (bug 336). + * 2) Deal with NULL ptr case for tm_zone field, which was causing + * segfaults in both the NIST/PCTS tests and the Python 2.4.1 + * self-test suite. + * NOTE: We set uninitialized timezone names to "???", and this + * differs (intentionally) from glibc's behavior. */ #define _GNU_SOURCE @@ -1066,7 +1075,7 @@ size_t __XL(strftime)(char *__restrict s, size_t maxsize, #define RSP_TZUNLOCK ((void) 0) #define RSP_TZNAME timeptr->tm_zone -#define RSP_GMT_OFFSET timeptr->tm_gmtoff +#define RSP_GMT_OFFSET (-timeptr->tm_gmtoff) #else @@ -1084,6 +1093,20 @@ size_t __XL(strftime)(char *__restrict s, size_t maxsize, if (*p == 'Z') { o = RSP_TZNAME; +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + /* Sigh... blasted glibc extensions. Of course we can't + * count on the pointer being valid. Best we can do is + * handle NULL, which looks to be all that glibc does. + * At least that catches the memset() with 0 case. + * NOTE: We handle this case differently than glibc! + * It uses system timezone name (based on tm_isdst) in this + * case... although it always seems to use the embedded + * tm_gmtoff value. What we'll do instead is treat the + * timezone name as unknown/invalid and return "???". */ + if (!o) { + o = "???"; + } +#endif assert(o != NULL); #if 0 if (!o) { /* PARANOIA */ @@ -1939,7 +1962,9 @@ void tzset(void) daylight = !!_time_tzinfo[1].tzname[0]; timezone = _time_tzinfo[0].gmt_offset; +#if defined(__UCLIBC_HAS_TZ_FILE__) FAST_DONE: +#endif TZUNLOCK; } diff --git a/libc/stdio/_fpmaxtostr.c b/libc/stdio/_fpmaxtostr.c index 7fd67ffb4..b9aacdca8 100644 --- a/libc/stdio/_fpmaxtostr.c +++ b/libc/stdio/_fpmaxtostr.c @@ -11,8 +11,8 @@ #include <locale.h> #include <bits/uClibc_fpmax.h> -typedef void (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, - intptr_t buf); +typedef size_t (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, + intptr_t buf); /* Copyright (C) 2000, 2001, 2003 Manuel Novoa III @@ -198,14 +198,13 @@ static const __fpmax_t exp16_table[] = { #define FPO_STR_WIDTH (0x80 | ' '); #define FPO_STR_PREC 'p' -size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, - __fp_outfunc_t fp_outfunc) +ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + __fp_outfunc_t fp_outfunc) { #ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ __fpmax_t lower_bnd; __fpmax_t upper_bnd = 1e9; #endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ - uint_fast32_t digit_block; #ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ uint_fast32_t base = 10; const __fpmax_t *power_table; @@ -221,9 +220,8 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, int nblk2; /* This does not need to be initialized. */ const char *ts; /* This does not need to be initialized. */ #endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ - int i, j; int round, o_exp; - int exp, exp_neg; + int exp; int width, preci; int cnt; char *s; @@ -304,34 +302,36 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, goto EXIT_SPECIAL; } + { + int i, j; #ifdef __UCLIBC_MJN3_ONLY__ #warning TODO: Clean up defines when hexadecimal float notation is unsupported. #endif /* __UCLIBC_MJN3_ONLY__ */ #ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ - if ((mode|0x20) == 'a') { - lower_bnd = 0x1.0p31L; - upper_bnd = 0x1.0p32L; - power_table = exp16_table; - exp = HEX_DIGITS_PER_BLOCK - 1; - i = EXP16_TABLE_SIZE; - j = EXP16_TABLE_MAX; - dpb = HEX_DIGITS_PER_BLOCK; - ndb = NUM_HEX_DIGIT_BLOCKS; - nd = NUM_HEX_DIGITS; - base = 16; - } else { - lower_bnd = 1e8; -/* upper_bnd = 1e9; */ - power_table = exp10_table; - exp = DIGITS_PER_BLOCK - 1; - i = EXP10_TABLE_SIZE; - j = EXP10_TABLE_MAX; -/* dpb = DIGITS_PER_BLOCK; */ -/* ndb = NUM_DIGIT_BLOCKS; */ -/* base = 10; */ - } + if ((mode|0x20) == 'a') { + lower_bnd = 0x1.0p31L; + upper_bnd = 0x1.0p32L; + power_table = exp16_table; + exp = HEX_DIGITS_PER_BLOCK - 1; + i = EXP16_TABLE_SIZE; + j = EXP16_TABLE_MAX; + dpb = HEX_DIGITS_PER_BLOCK; + ndb = NUM_HEX_DIGIT_BLOCKS; + nd = NUM_HEX_DIGITS; + base = 16; + } else { + lower_bnd = 1e8; + /* upper_bnd = 1e9; */ + power_table = exp10_table; + exp = DIGITS_PER_BLOCK - 1; + i = EXP10_TABLE_SIZE; + j = EXP10_TABLE_MAX; + /* dpb = DIGITS_PER_BLOCK; */ + /* ndb = NUM_DIGIT_BLOCKS; */ + /* base = 10; */ + } @@ -345,32 +345,35 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, #define ndb NUM_DIGIT_BLOCKS #define nd DECIMAL_DIG - exp = DIGITS_PER_BLOCK - 1; - i = EXP10_TABLE_SIZE; - j = EXP10_TABLE_MAX; + exp = DIGITS_PER_BLOCK - 1; + i = EXP10_TABLE_SIZE; + j = EXP10_TABLE_MAX; #endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ - exp_neg = 0; - if (x < lower_bnd) { /* Do we need to scale up or down? */ - exp_neg = 1; - } - - do { - --i; - if (exp_neg) { - if (x * power_table[i] < upper_bnd) { - x *= power_table[i]; - exp -= j; - } - } else { - if (x / power_table[i] >= lower_bnd) { - x /= power_table[i]; - exp += j; + { + int exp_neg = 0; + if (x < lower_bnd) { /* Do we need to scale up or down? */ + exp_neg = 1; } + + do { + --i; + if (exp_neg) { + if (x * power_table[i] < upper_bnd) { + x *= power_table[i]; + exp -= j; + } + } else { + if (x / power_table[i] >= lower_bnd) { + x /= power_table[i]; + exp += j; + } + } + j >>= 1; + } while (i); } - j >>= 1; - } while (i); + } if (x >= upper_bnd) { /* Handle bad rounding case. */ x /= power_table[0]; ++exp; @@ -378,22 +381,25 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, assert(x < upper_bnd); GENERATE_DIGITS: - s = buf + 2; /* Leave space for '\0' and '0'. */ - i = 0; - do { - digit_block = (uint_fast32_t) x; - assert(digit_block < upper_bnd); + { + int i, j; + s = buf + 2; /* Leave space for '\0' and '0'. */ + i = 0; + do { + uint_fast32_t digit_block = (uint_fast32_t) x; + assert(digit_block < upper_bnd); #ifdef __UCLIBC_MJN3_ONLY__ #warning CONSIDER: Can rounding be a problem? #endif /* __UCLIBC_MJN3_ONLY__ */ - x = (x - digit_block) * upper_bnd; - s += dpb; - j = 0; - do { - s[- ++j] = '0' + (digit_block % base); - digit_block /= base; - } while (j < dpb); - } while (++i < ndb); + x = (x - digit_block) * upper_bnd; + s += dpb; + j = 0; + do { + s[- ++j] = '0' + (digit_block % base); + digit_block /= base; + } while (j < dpb); + } while (++i < ndb); + } /*************************************************************************/ @@ -421,18 +427,21 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, *s++ = 0; /* Terminator for rounding and 0-triming. */ *s = '0'; /* Space to round. */ - i = 0; - e = s + nd + 1; - if (round < nd) { - e = s + round + 2; - if (*e >= '0' + (base/2)) { /* NOTE: We always round away from 0! */ - i = 1; + { + int i; + i = 0; + e = s + nd + 1; + if (round < nd) { + e = s + round + 2; + if (*e >= '0' + (base/2)) { /* NOTE: We always round away from 0! */ + i = 1; + } } - } - do { /* Handle rounding and trim trailing 0s. */ - *--e += i; /* Add the carry. */ - } while ((*e == '0') || (*e > '0' - 1 + base)); + do { /* Handle rounding and trim trailing 0s. */ + *--e += i; /* Add the carry. */ + } while ((*e == '0') || (*e > '0' - 1 + base)); + } #ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ if ((mode|0x20) == 'a') { @@ -480,80 +489,81 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, sign_str[5] = 0; ppc = pc_fwi + 6; - i = e - s; /* Total digits is 'i'. */ - if (o_exp >= 0) { + { + int i = e - s; /* Total digits is 'i'. */ + if (o_exp >= 0) { #ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - const char *p; + const char *p; - if (PRINT_INFO_FLAG_VAL(info,group) - && *(p = __UCLIBC_CURLOCALE_DATA.grouping) - ) { - int nblk1; + if (PRINT_INFO_FLAG_VAL(info,group) + && *(p = __UCLIBC_CURLOCALE_DATA.grouping) + ) { + int nblk1; - nblk2 = nblk1 = *p; - if (*++p) { - nblk2 = *p; - assert(!*++p); - } + nblk2 = nblk1 = *p; + if (*++p) { + nblk2 = *p; + assert(!*++p); + } - if (o_exp >= nblk1) { - num_groups = (o_exp - nblk1) / nblk2 + 1; - initial_group = (o_exp - nblk1) % nblk2; + if (o_exp >= nblk1) { + num_groups = (o_exp - nblk1) / nblk2 + 1; + initial_group = (o_exp - nblk1) % nblk2; #ifdef __UCLIBC_HAS_WCHAR__ - if (PRINT_INFO_FLAG_VAL(info,wide)) { - /* _fp_out_wide() will fix this up. */ - ts = fmt + THOUSEP_OFFSET; - tslen = 1; - } else { + if (PRINT_INFO_FLAG_VAL(info,wide)) { + /* _fp_out_wide() will fix this up. */ + ts = fmt + THOUSEP_OFFSET; + tslen = 1; + } else { #endif /* __UCLIBC_HAS_WCHAR__ */ - ts = __UCLIBC_CURLOCALE_DATA.thousands_sep; - tslen = __UCLIBC_CURLOCALE_DATA.thousands_sep_len; + ts = __UCLIBC_CURLOCALE_DATA.thousands_sep; + tslen = __UCLIBC_CURLOCALE_DATA.thousands_sep_len; #ifdef __UCLIBC_HAS_WCHAR__ - } + } #endif /* __UCLIBC_HAS_WCHAR__ */ - width -= num_groups * tslen; + width -= num_groups * tslen; + } } - } #endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ - ppc[0] = FPO_STR_PREC; - ppc[2] = (intptr_t)(s); - if (o_exp >= i) { /* all digit(s) left of decimal */ - ppc[1] = i; - ppc += 3; - o_exp -= i; - i = 0; - if (o_exp>0) { /* have 0s left of decimal */ - ppc[0] = FPO_ZERO_PAD; + ppc[0] = FPO_STR_PREC; + ppc[2] = (intptr_t)(s); + if (o_exp >= i) { /* all digit(s) left of decimal */ + ppc[1] = i; + ppc += 3; + o_exp -= i; + i = 0; + if (o_exp>0) { /* have 0s left of decimal */ + ppc[0] = FPO_ZERO_PAD; + ppc[1] = o_exp; + ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); + ppc += 3; + } + } else if (o_exp > 0) { /* decimal between digits */ ppc[1] = o_exp; - ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); ppc += 3; + s += o_exp; + i -= o_exp; } - } else if (o_exp > 0) { /* decimal between digits */ - ppc[1] = o_exp; - ppc += 3; - s += o_exp; - i -= o_exp; + o_exp = -1; } - o_exp = -1; - } - if (PRINT_INFO_FLAG_VAL(info,alt) - || (i) - || ((o_mode != 'g') + if (PRINT_INFO_FLAG_VAL(info,alt) + || (i) + || ((o_mode != 'g') #ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ - && (o_mode != 'a') + && (o_mode != 'a') #endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ - && (preci > 0)) - ) { - ppc[0] = FPO_STR_PREC; + && (preci > 0)) + ) { + ppc[0] = FPO_STR_PREC; #ifdef __LOCALE_C_ONLY - ppc[1] = 1; - ppc[2] = (intptr_t)(fmt + DECPT_OFFSET); + ppc[1] = 1; + ppc[2] = (intptr_t)(fmt + DECPT_OFFSET); #else /* __LOCALE_C_ONLY */ #ifdef __UCLIBC_HAS_WCHAR__ if (PRINT_INFO_FLAG_VAL(info,wide)) { @@ -569,39 +579,41 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, #endif /* __UCLIBC_HAS_WCHAR__ */ #endif /* __LOCALE_C_ONLY */ ppc += 3; - } - - if (++o_exp < 0) { /* Have 0s right of decimal. */ - ppc[0] = FPO_ZERO_PAD; - ppc[1] = -o_exp; - ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); - ppc += 3; - } - if (i) { /* Have digit(s) right of decimal. */ - ppc[0] = FPO_STR_PREC; - ppc[1] = i; - ppc[2] = (intptr_t)(s); - ppc += 3; - } + } - if (((o_mode != 'g') || PRINT_INFO_FLAG_VAL(info,alt)) -#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ - && !sufficient_precision -#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ - ) { - i -= o_exp; - if (i < preci) { /* Have 0s right of digits. */ - i = preci - i; + if (++o_exp < 0) { /* Have 0s right of decimal. */ ppc[0] = FPO_ZERO_PAD; - ppc[1] = i; + ppc[1] = -o_exp; ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); ppc += 3; } + if (i) { /* Have digit(s) right of decimal. */ + ppc[0] = FPO_STR_PREC; + ppc[1] = i; + ppc[2] = (intptr_t)(s); + ppc += 3; + } + + if (((o_mode != 'g') || PRINT_INFO_FLAG_VAL(info,alt)) +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + && !sufficient_precision +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + ) { + i -= o_exp; + if (i < preci) { /* Have 0s right of digits. */ + i = preci - i; + ppc[0] = FPO_ZERO_PAD; + ppc[1] = i; + ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); + ppc += 3; + } + } } /* Build exponent string. */ if (mode != 'f') { char *p = exp_buf + sizeof(exp_buf); + int j; char exp_char = *exp_buf; char exp_sign = '+'; #ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ @@ -631,43 +643,46 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, } EXIT_SPECIAL: - ppc_last = ppc; - ppc = pc_fwi + 4; /* Need width fields starting with second. */ - do { - width -= *ppc; - ppc += 3; - } while (ppc < ppc_last); + { + int i; + ppc_last = ppc; + ppc = pc_fwi + 4; /* Need width fields starting with second. */ + do { + width -= *ppc; + ppc += 3; + } while (ppc < ppc_last); - ppc = pc_fwi; - ppc[0] = FPO_STR_WIDTH; - ppc[1] = i = ((*sign_str) != 0); - ppc[2] = (intptr_t) sign_str; + ppc = pc_fwi; + ppc[0] = FPO_STR_WIDTH; + ppc[1] = i = ((*sign_str) != 0); + ppc[2] = (intptr_t) sign_str; #ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ - if (((mode|0x20) == 'a') && (pc_fwi[3] >= 16)) { /* Hex sign handling. */ - /* Hex and not inf or nan, so prefix with 0x. */ - char *h = sign_str + i; - *h = '0'; - *++h = 'x' - 'p' + *exp_buf; - *++h = 0; - ppc[1] = (i += 2); - } + if (((mode|0x20) == 'a') && (pc_fwi[3] >= 16)) { /* Hex sign handling. */ + /* Hex and not inf or nan, so prefix with 0x. */ + char *h = sign_str + i; + *h = '0'; + *++h = 'x' - 'p' + *exp_buf; + *++h = 0; + ppc[1] = (i += 2); + } #endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ - if ((width -= i) > 0) { - if (PRINT_INFO_FLAG_VAL(info,left)) { /* Left-justified. */ - ppc_last[0] = FPO_STR_WIDTH; - ppc_last[1] = width; - ppc_last[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); - ppc_last += 3; - } else if (info->pad == '0') { /* 0 padding */ - ppc[4] += width; /* Pad second field. */ - } else { - ppc[1] += width; /* Pad first (sign) field. */ + if ((width -= i) > 0) { + if (PRINT_INFO_FLAG_VAL(info,left)) { /* Left-justified. */ + ppc_last[0] = FPO_STR_WIDTH; + ppc_last[1] = width; + ppc_last[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); + ppc_last += 3; + } else if (info->pad == '0') { /* 0 padding */ + ppc[4] += width; /* Pad second field. */ + } else { + ppc[1] += width; /* Pad first (sign) field. */ + } } - } - cnt = 0; + cnt = 0; + } do { #ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ @@ -685,7 +700,9 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, blk = nblk2; } else if (len >= blk) { /* Enough digits for a group. */ /* printf("norm: len=%d blk=%d \"%.*s\"\n", len, blk, blk, gp); */ - fp_outfunc(fp, *ppc, blk, (intptr_t) gp); + if (fp_outfunc(fp, *ppc, blk, (intptr_t) gp) != blk) { + return -1; + } assert(gp); if (*gp) { gp += blk; @@ -695,7 +712,9 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, /* printf("trans: len=%d blk=%d \"%.*s\"\n", len, blk, len, gp); */ if (len) { /* printf("len\n"); */ - fp_outfunc(fp, *ppc, len, (intptr_t) gp); + if (fp_outfunc(fp, *ppc, len, (intptr_t) gp) != len) { + return -1; + } gp += len; } @@ -718,7 +737,9 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, } --num_groups; - fp_outfunc(fp, FPO_STR_PREC, tslen, (intptr_t) ts); + if (fp_outfunc(fp, FPO_STR_PREC, tslen, (intptr_t) ts) != tslen) { + return -1; + } blk = nblk2; /* printf("num_groups=%d blk=%d\n", num_groups, blk); */ @@ -727,8 +748,11 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, } else #endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ - - fp_outfunc(fp, *ppc, ppc[1], ppc[2]); /* NOTE: Remember 'else' above! */ + { /* NOTE: Remember 'else' above! */ + if (fp_outfunc(fp, *ppc, ppc[1], ppc[2]) != ppc[1]) { + return -1; + } + } cnt += ppc[1]; ppc += 3; diff --git a/libc/stdio/old_vfprintf.c b/libc/stdio/old_vfprintf.c index 1b7af96f9..23cb10f94 100644 --- a/libc/stdio/old_vfprintf.c +++ b/libc/stdio/old_vfprintf.c @@ -448,7 +448,7 @@ int vfprintf(FILE * __restrict op, register const char * __restrict fmt, if (*fmt == 'm') { flag[FLAG_PLUS] = '\0'; flag[FLAG_0_PAD] = ' '; - p = _glibc_strerror_r(errno, tmp, sizeof(tmp)); + p = __glibc_strerror_r(errno, tmp, sizeof(tmp)); goto print; } #endif diff --git a/libc/stdio/perror.c b/libc/stdio/perror.c index 83db7689f..26a0cebd9 100644 --- a/libc/stdio/perror.c +++ b/libc/stdio/perror.c @@ -30,7 +30,7 @@ void perror(register const char *s) { char buf[64]; fprintf(stderr, "%s%s%s\n", s, sep, - _glibc_strerror_r(errno, buf, sizeof(buf))); + __glibc_strerror_r(errno, buf, sizeof(buf))); } #endif } diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c index d3214fff0..10114f061 100644 --- a/libc/stdio/vfprintf.c +++ b/libc/stdio/vfprintf.c @@ -410,11 +410,11 @@ typedef struct { only returns -1 if sets error indicator for the stream. */ #ifdef __STDIO_PRINTF_FLOAT -typedef void (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, - intptr_t buf); +typedef size_t (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, + intptr_t buf); -extern size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, - __fp_outfunc_t fp_outfunc); +extern ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + __fp_outfunc_t fp_outfunc); #endif extern int _ppfs_init(ppfs_t *ppfs, const char *fmt0); /* validates */ @@ -1185,7 +1185,7 @@ int register_printf_function(int spec, printf_function handler, * In other words, we don't currently support glibc's 'I' flag. * We do accept it, but it is currently ignored. */ -static void _charpad(FILE * __restrict stream, int padchar, size_t numpad); +static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad); #ifdef L_vfprintf @@ -1201,16 +1201,20 @@ static void _charpad(FILE * __restrict stream, int padchar, size_t numpad); #ifdef __STDIO_PRINTF_FLOAT -static void _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) +static size_t _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) { + size_t r = 0; + if (type & 0x80) { /* Some type of padding needed. */ int buflen = strlen((const char *) buf); if ((len -= buflen) > 0) { - _charpad(fp, (type & 0x7f), len); + if ((r = _charpad(fp, (type & 0x7f), len)) != len) { + return r; + } } len = buflen; } - OUTNSTR(fp, (const char *) buf, len); + return r + OUTNSTR(fp, (const char *) buf, len); } #endif /* __STDIO_PRINTF_FLOAT */ @@ -1226,12 +1230,12 @@ static void _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) #define _outnwcs(stream, wstring, len) _wstdio_fwrite(wstring, len, stream) #define FP_OUT _fp_out_wide -static void _outnstr(FILE *stream, const char *s, size_t wclen) +static size_t _outnstr(FILE *stream, const char *s, size_t wclen) { /* NOTE!!! len here is the number of wchars we want to generate!!! */ wchar_t wbuf[64]; mbstate_t mbstate; - size_t todo, r; + size_t todo, r, n; mbstate.__mask = 0; todo = wclen; @@ -1243,9 +1247,14 @@ static void _outnstr(FILE *stream, const char *s, size_t wclen) : sizeof(wbuf)/sizeof(wbuf[0])), &mbstate); assert(((ssize_t)r) > 0); - _outnwcs(stream, wbuf, r); - todo -= r; + n = _outnwcs(stream, wbuf, r); + todo -= n; + if (n != r) { + break; + } } + + return wclen - todo; } #ifdef __STDIO_PRINTF_FLOAT @@ -1259,16 +1268,19 @@ static void _outnstr(FILE *stream, const char *s, size_t wclen) #define NUM_DIGIT_BLOCKS ((DECIMAL_DIG+DIGITS_PER_BLOCK-1)/DIGITS_PER_BLOCK) #define BUF_SIZE ( 3 + NUM_DIGIT_BLOCKS * DIGITS_PER_BLOCK ) -static void _fp_out_wide(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) +static size_t _fp_out_wide(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) { wchar_t wbuf[BUF_SIZE]; const char *s = (const char *) buf; + size_t r = 0; int i; if (type & 0x80) { /* Some type of padding needed */ int buflen = strlen(s); if ((len -= buflen) > 0) { - _charpad(fp, (type & 0x7f), len); + if ((r = _charpad(fp, (type & 0x7f), len)) != len) { + return r; + } } len = buflen; } @@ -1294,8 +1306,10 @@ static void _fp_out_wide(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) } while (++i < len); - OUTNSTR(fp, wbuf, len); + r += OUTNSTR(fp, wbuf, len); } + + return r; } #endif /* __STDIO_PRINTF_FLOAT */ @@ -1385,16 +1399,19 @@ static int _ppwfs_init(register ppfs_t *ppfs, const wchar_t *fmt0) #endif /* L_vfprintf */ -static void _charpad(FILE * __restrict stream, int padchar, size_t numpad) +static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad) { + size_t todo = numpad; + /* TODO -- Use a buffer to cut down on function calls... */ FMT_TYPE pad[1]; *pad = padchar; - while (numpad) { - OUTNSTR(stream, pad, 1); - --numpad; + while (todo && (OUTNSTR(stream, pad, 1) == 1)) { + --todo; } + + return numpad - todo; } /* TODO -- Dynamically allocate work space to accomodate stack-poor archs? */ @@ -1583,13 +1600,18 @@ static int _do_one_spec(FILE * __restrict stream, numfill = ((numfill > SLEN) ? numfill - SLEN : 0); } else if (ppfs->conv_num <= CONV_A) { /* floating point */ #ifdef __STDIO_PRINTF_FLOAT - *count += - _fpmaxtostr(stream, - (__fpmax_t) - (PRINT_INFO_FLAG_VAL(&(ppfs->info),is_long_double) - ? *(long double *) *argptr - : (long double) (* (double *) *argptr)), - &ppfs->info, FP_OUT ); + ssize_t nf; + nf = _fpmaxtostr(stream, + (__fpmax_t) + (PRINT_INFO_FLAG_VAL(&(ppfs->info),is_long_double) + ? *(long double *) *argptr + : (long double) (* (double *) *argptr)), + &ppfs->info, FP_OUT ); + if (nf < 0) { + return -1; + } + *count += nf; + return 0; #else /* __STDIO_PRINTF_FLOAT */ return -1; /* TODO -- try to continue? */ @@ -1708,7 +1730,7 @@ static int _do_one_spec(FILE * __restrict stream, #ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ } else if (ppfs->conv_num == CONV_m) { - s = _glibc_strerror_r(errno, buf, sizeof(buf)); + s = __glibc_strerror_r(errno, buf, sizeof(buf)); goto SET_STRING_LEN; #endif } else { @@ -1757,18 +1779,24 @@ static int _do_one_spec(FILE * __restrict stream, /* Now handle the output itself. */ if (!PRINT_INFO_FLAG_VAL(&(ppfs->info),left)) { - _charpad(stream, ' ', numpad); + if (_charpad(stream, ' ', numpad) != numpad) { + return -1; + } numpad = 0; } OUTPUT(stream, prefix + prefix_num); - _charpad(stream, '0', numfill); + if (_charpad(stream, '0', numfill) != numfill) { + return -1; + } #ifdef L_vfprintf #ifdef __UCLIBC_HAS_WCHAR__ if (!ws) { assert(s); - _outnstr(stream, s, slen); + if (_outnstr(stream, s, slen) != slen) { + return -1; + } } else { /* wide string */ size_t t; mbstate.__mask = 0; /* Initialize the mbstate. */ @@ -1776,25 +1804,35 @@ static int _do_one_spec(FILE * __restrict stream, t = (slen <= sizeof(buf)) ? slen : sizeof(buf); t = wcsrtombs(buf, &ws, t, &mbstate); assert (t != ((size_t)(-1))); - _outnstr(stream, buf, t); + if (_outnstr(stream, buf, t) != t) { + return -1; + } slen -= t; } } #else /* __UCLIBC_HAS_WCHAR__ */ - _outnstr(stream, s, slen); + if (_outnstr(stream, s, slen) != slen) { + return -1; + } #endif /* __UCLIBC_HAS_WCHAR__ */ #else /* L_vfprintf */ if (!ws) { assert(s); - _outnstr(stream, s, SLEN); + if (_outnstr(stream, s, SLEN) != SLEN) { + return -1; + } } else { - _outnwcs(stream, ws, SLEN); + if (_outnwcs(stream, ws, SLEN) != SLEN) { + return -1; + } } #endif /* L_vfprintf */ - _charpad(stream, ' ', numpad); + if (_charpad(stream, ' ', numpad) != numpad) { + return -1; + } } return 0; @@ -1840,7 +1878,7 @@ int VFPRINTF (FILE * __restrict stream, } if (format-s) { /* output any literal text in format string */ - if ( (r = OUTNSTR(stream, s, format-s)) < 0) { + if ( (r = OUTNSTR(stream, s, format-s)) != (format-s)) { count = -1; break; } diff --git a/libc/stdlib/abort.c b/libc/stdlib/abort.c index e34c86778..77c2cdc69 100644 --- a/libc/stdlib/abort.c +++ b/libc/stdlib/abort.c @@ -30,99 +30,120 @@ Cambridge, MA 02139, USA. */ /* Our last ditch effort to commit suicide */ -#if defined(__i386__) +#if defined(__alpha__) +#define ABORT_INSTRUCTION asm ("call_pal 0") +#elif defined(__hppa__) +#define ABORT_INSTRUCTION asm ("iitlbp %r0,(%r0)") +#elif defined(__i386__) #define ABORT_INSTRUCTION asm ("hlt") #elif defined(__ia64__) #define ABORT_INSTRUCTION asm ("break 0") +#elif defined(__m68k__) +#define ABORT_INSTRUCTION asm ("illegal") #elif defined(__mc68000__) #define ABORT_INSTRUCTION asm (".long 0xffffffff") #elif defined(__mips__) #define ABORT_INSTRUCTION asm ("break 255") +#elif defined(__powerpc__) +#define ABORT_INSTRUCTION asm (".long 0") #elif defined(__s390__) #define ABORT_INSTRUCTION asm (".word 0") #elif defined(__sparc__) #define ABORT_INSTRUCTION asm ("unimp 0xf00") -#elif defined(__x86_64__) -#define ABORT_INSTRUCTION asm ("hlt") -#elif defined(__hppa__) -#define ABORT_INSTRUCTION asm ("iitlbp %r0,(%r0)") -#elif defined(__powerpc__) -#define ABORT_INSTRUCTION asm (".long 0") #elif defined(__SH5__) #define ABORT_INSTRUCTION asm ("movi 0x10, r9; shori 0xff, r9; trapa r9") #elif defined(__sh2__) #define ABORT_INSTRUCTION asm ("trapa #32") #elif defined(__sh__) #define ABORT_INSTRUCTION asm ("trapa #0xff") +#elif defined(__x86_64__) +#define ABORT_INSTRUCTION asm ("hlt") #else #define ABORT_INSTRUCTION +#warning no abort instruction define for your arch #endif +#ifdef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +extern void weak_function _stdio_term(void); +#endif extern void _exit __P((int __status)) __attribute__ ((__noreturn__)); static int been_there_done_that = 0; -/* Be prepared in case multiple threads try to abort(). */ +/* Be prepared in case multiple threads try to abort() */ #ifdef __UCLIBC_HAS_THREADS__ -#include <pthread.h> +# include <pthread.h> static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; # define LOCK __pthread_mutex_lock(&mylock) -# define UNLOCK __pthread_mutex_unlock(&mylock); +# define UNLOCK __pthread_mutex_unlock(&mylock) #else # define LOCK # define UNLOCK #endif -/* Cause an abnormal program termination with core-dump. */ +/* Cause an abnormal program termination with core-dump */ void abort(void) { - sigset_t sigset; - - /* Make sure we acquire the lock before proceeding. */ - LOCK; - - /* Unmask SIGABRT to be sure we can get it */ - if (__sigemptyset(&sigset) == 0 && __sigaddset(&sigset, SIGABRT) == 0) { - sigprocmask(SIG_UNBLOCK, &sigset, (sigset_t *) NULL); - } - - while (1) { - /* Try to suicide with a SIGABRT. */ - if (been_there_done_that == 0) { - been_there_done_that++; - UNLOCK; - raise(SIGABRT); - LOCK; - } + sigset_t sigset; - /* Still here? Try to remove any signal handlers. */ - if (been_there_done_that == 1) { - struct sigaction act; + /* Make sure we acquire the lock before proceeding */ + LOCK; - been_there_done_that++; - memset (&act, '\0', sizeof (struct sigaction)); - act.sa_handler = SIG_DFL; - __sigfillset (&act.sa_mask); - act.sa_flags = 0; - sigaction (SIGABRT, &act, NULL); + /* Unmask SIGABRT to be sure we can get it */ + if (__sigemptyset(&sigset) == 0 && __sigaddset(&sigset, SIGABRT) == 0) { + sigprocmask(SIG_UNBLOCK, &sigset, (sigset_t *) NULL); } - /* Still here? Try to suicide with an illegal instruction */ - if (been_there_done_that == 2) { - been_there_done_that++; - ABORT_INSTRUCTION; - } + while (1) { + /* Try to suicide with a SIGABRT */ + if (been_there_done_that == 0) { + been_there_done_that++; + +#ifdef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ + /* If we are using stdio, try to shut it down. At the very least, + * this will attemt to commit all buffered writes. It may also + * unboffer all writable files, or close them outright. + * Check the stdio routines for details. */ + if (_stdio_term) { + _stdio_term(); + } +#endif - /* Still here? Try to at least exit */ - if (been_there_done_that == 3) { - been_there_done_that++; - _exit (127); +abort_it: + UNLOCK; + raise(SIGABRT); + LOCK; + } + + /* Still here? Try to remove any signal handlers */ + if (been_there_done_that == 1) { + struct sigaction act; + + been_there_done_that++; + memset(&act, '\0', sizeof(struct sigaction)); + act.sa_handler = SIG_DFL; + __sigfillset(&act.sa_mask); + act.sa_flags = 0; + sigaction(SIGABRT, &act, NULL); + + goto abort_it; + } + + /* Still here? Try to suicide with an illegal instruction */ + if (been_there_done_that == 2) { + been_there_done_that++; + ABORT_INSTRUCTION; + } + + /* Still here? Try to at least exit */ + if (been_there_done_that == 3) { + been_there_done_that++; + _exit(127); + } + + /* Still here? We're screwed. Sleepy time. Good night. */ + while (1) + /* Try for ever and ever */ + ABORT_INSTRUCTION; } - - /* Still here? We're screwed. Sleepy time. Good night */ - while (1) - /* Try for ever and ever. */ - ABORT_INSTRUCTION; - } } - diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c index d5f83ee8e..280f42cb7 100644 --- a/libc/stdlib/atexit.c +++ b/libc/stdlib/atexit.c @@ -239,8 +239,7 @@ void exit(int rv) if (__app_fini != NULL) (__app_fini)(); #endif -#ifdef _DL_DO_FINI_IN_LIBC -/* arches that has moved their ldso FINI handling should #define _DL_DO_FINI_IN_LIBC */ +#ifndef _DL_FINI_CRT_COMPAT if (__rtld_fini != NULL) (__rtld_fini)(); #endif diff --git a/libc/stdlib/malloc-simple/alloc.c b/libc/stdlib/malloc-simple/alloc.c index 68cd77665..ed14c37c4 100644 --- a/libc/stdlib/malloc-simple/alloc.c +++ b/libc/stdlib/malloc-simple/alloc.c @@ -1,6 +1,6 @@ /* alloc.c * - * Written by Erik Andersen <andersee@debian.org> + * Written by Erik Andersen <andersee@codepoet.org> * LGPLv2 * * Parts of the memalign code were stolen from malloc-930716. @@ -20,31 +20,29 @@ #ifdef L_malloc void *malloc(size_t size) { - void *result; + void *result; - if (unlikely(size == 0)) { + if (unlikely(size == 0)) { #if defined(__MALLOC_GLIBC_COMPAT__) - size++; + size++; #else - /* Some programs will call malloc (0). Lets be strict and return NULL */ - return 0; + /* Some programs will call malloc (0). Lets be strict and return NULL */ + return 0; #endif - } + } #ifdef __ARCH_HAS_MMU__ - result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); - if (result == MAP_FAILED) - return 0; - * (size_t *) result = size; - return(result + sizeof(size_t)); +# define MMAP_FLAGS MAP_PRIVATE | MAP_ANONYMOUS #else - result = mmap((void *) 0, size, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANONYMOUS, 0, 0); - if (result == MAP_FAILED) - return 0; - return(result); +# define MMAP_FLAGS MAP_SHARED | MAP_ANONYMOUS #endif + + result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE, + MMAP_FLAGS, 0, 0); + if (result == MAP_FAILED) + return 0; + * (size_t *) result = size; + return(result + sizeof(size_t)); } #endif @@ -76,27 +74,21 @@ void * calloc(size_t nmemb, size_t lsize) #ifdef L_realloc void *realloc(void *ptr, size_t size) { - void *newptr = NULL; - - if (!ptr) - return malloc(size); - if (!size) { - free(ptr); - return malloc(0); - } - - newptr = malloc(size); - if (newptr) { - memcpy(newptr, ptr, -#ifdef __ARCH_HAS_MMU__ - *((size_t *) (ptr - sizeof(size_t))) -#else - size -#endif - ); - free(ptr); - } - return newptr; + void *newptr = NULL; + + if (!ptr) + return malloc(size); + if (!size) { + free(ptr); + return malloc(0); + } + + newptr = malloc(size); + if (newptr) { + memcpy(newptr, ptr, *((size_t *) (ptr - sizeof(size_t)))); + free(ptr); + } + return newptr; } #endif @@ -104,19 +96,14 @@ void *realloc(void *ptr, size_t size) extern int weak_function __libc_free_aligned(void *ptr); void free(void *ptr) { - if (ptr == NULL) - return; - if (unlikely(__libc_free_aligned!=NULL)) { - if (__libc_free_aligned(ptr)) { - return; + if (unlikely(ptr == NULL)) + return; + if (unlikely(__libc_free_aligned != NULL)) { + if (__libc_free_aligned(ptr)) + return; } - } -#ifdef __ARCH_HAS_MMU__ - ptr -= sizeof(size_t); - munmap(ptr, * (size_t *) ptr + sizeof(size_t)); -#else - munmap(ptr, 0); -#endif + ptr -= sizeof(size_t); + munmap(ptr, * (size_t *) ptr + sizeof(size_t)); } #endif @@ -134,73 +121,67 @@ pthread_mutex_t __malloc_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; /* List of blocks allocated with memalign or valloc */ struct alignlist { - struct alignlist *next; - __ptr_t aligned; /* The address that memaligned returned. */ - __ptr_t exact; /* The address that malloc returned. */ + struct alignlist *next; + __ptr_t aligned; /* The address that memaligned returned. */ + __ptr_t exact; /* The address that malloc returned. */ }; struct alignlist *_aligned_blocks; /* Return memory to the heap. */ int __libc_free_aligned(void *ptr) { - struct alignlist *l; + struct alignlist *l; - if (ptr == NULL) - return 0; + if (ptr == NULL) + return 0; - LOCK; - for (l = _aligned_blocks; l != NULL; l = l->next) { - if (l->aligned == ptr) { - /* Mark the block as free */ - l->aligned = NULL; - ptr = l->exact; -#ifdef __ARCH_HAS_MMU__ - ptr -= sizeof(size_t); - munmap(ptr, * (size_t *) ptr + sizeof(size_t)); -#else - munmap(ptr, 0); -#endif - return 1; + LOCK; + for (l = _aligned_blocks; l != NULL; l = l->next) { + if (l->aligned == ptr) { + /* Mark the block as free */ + l->aligned = NULL; + ptr = l->exact; + ptr -= sizeof(size_t); + munmap(ptr, * (size_t *) ptr + sizeof(size_t)); + return 1; + } } - } - UNLOCK; - return 0; + UNLOCK; + return 0; } void * memalign (size_t alignment, size_t size) { - void * result; - unsigned long int adj; - - result = malloc (size + alignment - 1); - if (result == NULL) - return NULL; - adj = (unsigned long int) ((unsigned long int) ((char *) result - - (char *) NULL)) % alignment; - if (adj != 0) - { - struct alignlist *l; - LOCK; - for (l = _aligned_blocks; l != NULL; l = l->next) - if (l->aligned == NULL) - /* This slot is free. Use it. */ - break; - if (l == NULL) - { - l = (struct alignlist *) malloc (sizeof (struct alignlist)); - if (l == NULL) { - free(result); - UNLOCK; + void * result; + unsigned long int adj; + + result = malloc (size + alignment - 1); + if (result == NULL) return NULL; - } - l->next = _aligned_blocks; - _aligned_blocks = l; + + adj = (unsigned long int) ((unsigned long int) ((char *) result - + (char *) NULL)) % alignment; + if (adj != 0) { + struct alignlist *l; + LOCK; + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == NULL) + /* This slot is free. Use it. */ + break; + if (l == NULL) { + l = (struct alignlist *) malloc (sizeof (struct alignlist)); + if (l == NULL) { + free(result); + UNLOCK; + return NULL; + } + l->next = _aligned_blocks; + _aligned_blocks = l; + } + l->exact = result; + result = l->aligned = (char *) result + alignment - adj; + UNLOCK; } - l->exact = result; - result = l->aligned = (char *) result + alignment - adj; - UNLOCK; - } - return result; + return result; } #endif - diff --git a/libc/stdlib/malloc-standard/malloc.c b/libc/stdlib/malloc-standard/malloc.c index 51e02a240..7025e8335 100644 --- a/libc/stdlib/malloc-standard/malloc.c +++ b/libc/stdlib/malloc-standard/malloc.c @@ -827,6 +827,10 @@ void* malloc(size_t bytes) mchunkptr bck; /* misc temp for linking */ void * sysmem; +#if !defined(__MALLOC_GLIBC_COMPAT__) + if (!bytes) return NULL; +#endif + LOCK; av = get_malloc_state(); /* diff --git a/libc/string/Makefile b/libc/string/Makefile index 4150e403e..6b516c1c5 100644 --- a/libc/string/Makefile +++ b/libc/string/Makefile @@ -39,8 +39,8 @@ MOBJ= basename.o bcopy.o bzero.o dirname.o ffs.o memccpy.o memchr.o memcmp.o \ stpncpy.o strcasecmp.o strcasestr.o strcat.o strchrnul.o strchr.o \ strcmp.o strcpy.o strcspn.o strdup.o strlen.o strncasecmp.o strncat.o \ strncmp.o strncpy.o strndup.o strnlen.o strpbrk.o strrchr.o strsep.o \ - strspn.o strstr.o strtok.o strtok_r.o strerror.o _susv3_strerror_r.o \ - _string_syserrmsgs.o _glibc_strerror_r.o \ + strspn.o strstr.o strtok.o strtok_r.o strerror.o __xpg_strerror_r.o \ + _string_syserrmsgs.o __glibc_strerror_r.o \ _string_syssigmsgs.o sys_siglist.o strsignal.o psignal.o \ __xpg_basename.o strlcat.o strlcpy.o sys_errlist.o memmem.o @@ -64,7 +64,7 @@ endif OBJS=$(MOBJ) $(MOBJx) ifeq ($(UCLIBC_HAS_WCHAR),y) -OBJS += $(MOBJW) $(MOBJWx) + OBJS += $(MOBJW) $(MOBJWx) endif OBJ_LIST=../obj.string diff --git a/libc/string/wstring.c b/libc/string/wstring.c index ed9ebb232..6f54ae615 100644 --- a/libc/string/wstring.c +++ b/libc/string/wstring.c @@ -1299,7 +1299,7 @@ char *strerror(int errnum) { static char buf[_STRERROR_BUFSIZE]; - _susv3_strerror_r(errnum, buf, sizeof(buf)); + __xpg_strerror_r(errnum, buf, sizeof(buf)); return buf; } @@ -1308,7 +1308,7 @@ char *strerror(int errnum) /**********************************************************************/ /* SUSv3 functions. */ /**********************************************************************/ -#ifdef L__susv3_strerror_r +#ifdef L___xpg_strerror_r #ifdef __UCLIBC_HAS_ERRNO_MESSAGES__ #if defined(__alpha__) || defined(__mips__) || defined(__sparc__) @@ -1450,7 +1450,7 @@ static const unsigned char estridx[] = { #endif -int _susv3_strerror_r(int errnum, char *strerrbuf, size_t buflen) +int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen) { register char *s; int i, retval; @@ -1528,7 +1528,7 @@ int _susv3_strerror_r(int errnum, char *strerrbuf, size_t buflen) #else /* __UCLIBC_HAS_ERRNO_MESSAGES__ */ -int _susv3_strerror_r(int errnum, char *strerrbuf, size_t buflen) +int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen) { register char *s; int i, retval; @@ -1569,13 +1569,13 @@ int _susv3_strerror_r(int errnum, char *strerrbuf, size_t buflen) /**********************************************************************/ /* GNU extension functions. */ /**********************************************************************/ -#ifdef L__glibc_strerror_r +#ifdef L___glibc_strerror_r -weak_alias(_glibc_strerror_r,__strerror_r); +weak_alias(__glibc_strerror_r,__strerror_r); -char *_glibc_strerror_r(int errnum, char *strerrbuf, size_t buflen) +char *__glibc_strerror_r(int errnum, char *strerrbuf, size_t buflen) { - _susv3_strerror_r(errnum, strerrbuf, buflen); + __xpg_strerror_r(errnum, strerrbuf, buflen); return strerrbuf; } diff --git a/libc/sysdeps/linux/common/Makefile b/libc/sysdeps/linux/common/Makefile index 5e17cc9fc..84b29ac53 100644 --- a/libc/sysdeps/linux/common/Makefile +++ b/libc/sysdeps/linux/common/Makefile @@ -28,6 +28,7 @@ endif ifneq ($(strip $(UCLIBC_HAS_SSP)),y) SRCS := $(filter-out ssp.c,$(SRCS)) endif +ssp.o: CFLAGS += $(SSP_DISABLE_FLAGS) OBJS = $(patsubst %.c,%.o, $(SRCS)) diff --git a/libc/sysdeps/linux/common/__syscall_fcntl.c b/libc/sysdeps/linux/common/__syscall_fcntl.c index 62568522b..0a5812976 100644 --- a/libc/sysdeps/linux/common/__syscall_fcntl.c +++ b/libc/sysdeps/linux/common/__syscall_fcntl.c @@ -11,10 +11,12 @@ #include <stdarg.h> #include <fcntl.h> -#define __NR___syscall_fcntl __NR_fcntl #ifdef __UCLIBC_HAS_LFS__ -static inline +extern int __libc_fcntl64(int fd, int cmd, long arg); #endif + +#define __NR___syscall_fcntl __NR_fcntl +static inline _syscall3(int, __syscall_fcntl, int, fd, int, cmd, long, arg); int __libc_fcntl(int fd, int cmd, ...) @@ -22,13 +24,18 @@ int __libc_fcntl(int fd, int cmd, ...) long arg; va_list list; + va_start(list, cmd); + arg = va_arg(list, long); + va_end(list); + if (cmd == F_GETLK64 || cmd == F_SETLK64 || cmd == F_SETLKW64) { +#ifdef __UCLIBC_HAS_LFS__ + return __libc_fcntl64(fd, cmd, arg); +#else __set_errno(ENOSYS); return -1; +#endif } - va_start(list, cmd); - arg = va_arg(list, long); - va_end(list); return (__syscall_fcntl(fd, cmd, arg)); } diff --git a/libc/sysdeps/linux/common/bits/errno.h b/libc/sysdeps/linux/common/bits/errno.h index d31dca8aa..cb9c2ee43 100644 --- a/libc/sysdeps/linux/common/bits/errno.h +++ b/libc/sysdeps/linux/common/bits/errno.h @@ -37,7 +37,7 @@ extern int errno; /* Function to get address of global `errno' variable. */ extern int *__errno_location (void) __THROW __attribute__ ((__const__)); -# if defined _LIBC && !defined(__set_errno) +# if defined _LIBC /* We wouldn't need a special macro anymore but it is history. */ # define __set_errno(val) ((errno) = (val)) # endif /* _LIBC */ diff --git a/libc/sysdeps/linux/common/bits/ipc.h b/libc/sysdeps/linux/common/bits/ipc.h index 7cd2fd0c5..f1a043fe5 100644 --- a/libc/sysdeps/linux/common/bits/ipc.h +++ b/libc/sysdeps/linux/common/bits/ipc.h @@ -38,19 +38,19 @@ /* Special key values. */ #define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + /* Data structure used to pass permission information to IPC operations. */ struct ipc_perm { - __key_t __key; /* Key. */ - __uid_t uid; /* Owner's user ID. */ - __gid_t gid; /* Owner's group ID. */ - __uid_t cuid; /* Creator's user ID. */ - __gid_t cgid; /* Creator's group ID. */ - unsigned short int mode; /* Read/write permission. */ + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ + unsigned short int mode; /* Read/write permission. */ unsigned short int __pad1; - unsigned short int __seq; /* Sequence number. */ + unsigned short int __seq; /* Sequence number. */ unsigned short int __pad2; unsigned long int __unused1; unsigned long int __unused2; }; - diff --git a/libc/sysdeps/linux/common/bits/sem.h b/libc/sysdeps/linux/common/bits/sem.h index f900136f0..6193501e2 100644 --- a/libc/sysdeps/linux/common/bits/sem.h +++ b/libc/sysdeps/linux/common/bits/sem.h @@ -36,15 +36,16 @@ /* Data structure describing a set of semaphores. */ -struct semid_ds { - struct ipc_perm sem_perm; /* permissions .. see ipc.h */ - __kernel_time_t sem_otime; /* last semop time */ - __kernel_time_t sem_ctime; /* last change time */ - struct sem *sem_base; /* ptr to first semaphore in array */ - struct sem_queue *sem_pending; /* pending operations to be processed */ - struct sem_queue **sem_pending_last; /* last pending operation */ - struct sem_undo *undo; /* undo requests on this array */ - unsigned short sem_nsems; /* no. of semaphores in array */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + unsigned long int __unused1; + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int __unused2; + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused3; + unsigned long int __unused4; }; /* The user should define a union like the following to use it for arguments diff --git a/libc/sysdeps/linux/common/bits/sigthread.h b/libc/sysdeps/linux/common/bits/sigthread.h index 960bde18a..0a634ac68 100644 --- a/libc/sysdeps/linux/common/bits/sigthread.h +++ b/libc/sysdeps/linux/common/bits/sigthread.h @@ -1,18 +1,18 @@ /* Signal handling function for threaded programs. - Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + Library General Public License for more details. - You should have received a copy of the GNU Lesser General Public + You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -33,6 +33,6 @@ extern int pthread_sigmask (int __how, __sigset_t *__restrict __oldmask)__THROW; /* Send signal SIGNO to the given thread. */ -extern int pthread_kill (pthread_t __threadid, int __signo) __THROW; +extern int pthread_kill (pthread_t __thread_id, int __signo) __THROW; #endif /* bits/sigthread.h */ diff --git a/libc/sysdeps/linux/common/bits/stat.h b/libc/sysdeps/linux/common/bits/stat.h index 3ecec4a47..3e8e77f65 100644 --- a/libc/sysdeps/linux/common/bits/stat.h +++ b/libc/sysdeps/linux/common/bits/stat.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1992,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. +/* Copyright (C) 1992, 1995-2001, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -63,11 +63,11 @@ struct stat __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ #endif __time_t st_atime; /* Time of last access. */ - unsigned long int __unused1; + unsigned long int st_atimensec; /* Nscecs of last access. */ __time_t st_mtime; /* Time of last modification. */ - unsigned long int __unused2; + unsigned long int st_mtimensec; /* Nsecs of last modification. */ __time_t st_ctime; /* Time of last status change. */ - unsigned long int __unused3; + unsigned long int st_ctimensec; /* Nsecs of last status change. */ #ifndef __USE_FILE_OFFSET64 unsigned long int __unused4; unsigned long int __unused5; @@ -94,11 +94,11 @@ struct stat64 __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ __time_t st_atime; /* Time of last access. */ - unsigned long int __unused1; + unsigned long int st_atimensec; /* Nscecs of last access. */ __time_t st_mtime; /* Time of last modification. */ - unsigned long int __unused2; + unsigned long int st_mtimensec; /* Nsecs of last modification. */ __time_t st_ctime; /* Time of last status change. */ - unsigned long int __unused3; + unsigned long int st_ctimensec; /* Nsecs of last status change. */ __ino64_t st_ino; /* File serial number. */ }; #endif @@ -107,6 +107,8 @@ struct stat64 /* Tell code we have these members. */ #define _STATBUF_ST_BLKSIZE #define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC /* Encoding of the file mode. */ diff --git a/libc/sysdeps/linux/common/ioperm.c b/libc/sysdeps/linux/common/ioperm.c index 8afba049e..874577a64 100644 --- a/libc/sysdeps/linux/common/ioperm.c +++ b/libc/sysdeps/linux/common/ioperm.c @@ -8,12 +8,12 @@ */ #include "syscalls.h" -# if defined __ARCH_HAS_MMU__ && defined __NR_ioperm +#if defined __ARCH_HAS_MMU__ && defined __NR_ioperm _syscall3(int, ioperm, unsigned long, from, unsigned long, num, int, turn_on); -# else +#else int ioperm(unsigned long from, unsigned long num, int turn_on) { __set_errno(ENOSYS); return -1; } -# endif +#endif diff --git a/libc/sysdeps/linux/common/pread_write.c b/libc/sysdeps/linux/common/pread_write.c index bf04be41f..05eff4bc9 100644 --- a/libc/sysdeps/linux/common/pread_write.c +++ b/libc/sysdeps/linux/common/pread_write.c @@ -186,7 +186,9 @@ weak_alias (__libc_pread64, pread64) #ifndef __NR_pwrite ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) { - return(__fake_pread_write(fd, buf, count, offset, 1)); + /* we won't actually be modifying the buffer, + *just cast it to get rid of warnings */ + return(__fake_pread_write(fd, (void*)buf, count, offset, 1)); } weak_alias (__libc_pwrite, pwrite) diff --git a/libc/sysdeps/linux/common/ssp.c b/libc/sysdeps/linux/common/ssp.c index ecfc67e5e..31833cbb9 100644 --- a/libc/sysdeps/linux/common/ssp.c +++ b/libc/sysdeps/linux/common/ssp.c @@ -20,6 +20,10 @@ # include <config.h> #endif +#ifdef __SSP__ +# error ssp.c has to be built w/ -fno-stack-protector +#endif + #include <stdio.h> #include <string.h> #include <fcntl.h> @@ -30,29 +34,38 @@ #include <sys/syslog.h> #include <sys/time.h> #ifdef __SSP_USE_ERANDOM__ -#include <sys/sysctl.h> +# include <sys/sysctl.h> #endif #ifdef __PROPOLICE_BLOCK_SEGV__ -#define SSP_SIGTYPE SIGSEGV +# define SSP_SIGTYPE SIGSEGV #elif __PROPOLICE_BLOCK_KILL__ -#define SSP_SIGTYPE SIGKILL +# define SSP_SIGTYPE SIGKILL #else -#define SSP_SIGTYPE SIGABRT +# define SSP_SIGTYPE SIGABRT #endif -/* prototypes */ -extern int __libc_open (__const char *file, int oflag, mode_t mode); -extern ssize_t __libc_read(int fd, void *buf, size_t count); -extern int __libc_close (int fd); - unsigned long __guard = 0UL; +/* Use of __* functions from the rest of glibc here avoids + * initialisation problems for executables preloaded with + * libraries that overload the associated standard library + * functions. + */ +#ifdef __UCLIBC__ +extern int __libc_open(__const char *file, int flags, ...); +extern ssize_t __libc_read(int fd, void *buf, size_t count); +extern int __libc_close(int fd); +#else +# define __libc_open(file, flags) __open(file, flags) +# define __libc_read(fd, buf, count) __read(fd, buf, count) +# define __libc_close(fd) __close(fd) +#endif + void __guard_setup(void) __attribute__ ((constructor)); void __guard_setup(void) { size_t size; - struct timeval tv; if (__guard != 0UL) return; @@ -61,18 +74,20 @@ void __guard_setup(void) __guard = 0xFF0A0D00UL; #ifndef __SSP_QUICK_CANARY__ -#ifdef __SSP_USE_ERANDOM__ - int mib[3]; - /* Random is another depth in Linux, hence an array of 3. */ - mib[0] = CTL_KERN; - mib[1] = KERN_RANDOM; - mib[2] = RANDOM_ERANDOM; - - size = sizeof(unsigned long); - if (__sysctl(mib, 3, &__guard, &size, NULL, 0) != (-1)) - if (__guard != 0UL) - return; -#endif +# ifdef __SSP_USE_ERANDOM__ + { + int mib[3]; + /* Random is another depth in Linux, hence an array of 3. */ + mib[0] = CTL_KERN; + mib[1] = KERN_RANDOM; + mib[2] = RANDOM_ERANDOM; + + size = sizeof(unsigned long); + if (__sysctl(mib, 3, &__guard, &size, NULL, 0) != (-1)) + if (__guard != 0UL) + return; + } +# endif /* ifdef __SSP_USE_ERANDOM__ */ /* * Attempt to open kernel pseudo random device if one exists before * opening urandom to avoid system entropy depletion. @@ -80,9 +95,9 @@ void __guard_setup(void) { int fd; -#ifdef __SSP_USE_ERANDOM__ +# ifdef __SSP_USE_ERANDOM__ if ((fd = __libc_open("/dev/erandom", O_RDONLY)) == (-1)) -#endif +# endif fd = __libc_open("/dev/urandom", O_RDONLY); if (fd != (-1)) { size = __libc_read(fd, (char *) &__guard, sizeof(__guard)); @@ -91,13 +106,15 @@ void __guard_setup(void) return; } } -#endif +#endif /* ifndef __SSP_QUICK_CANARY__ */ /* Everything failed? Or we are using a weakened model of the * terminator canary */ - - gettimeofday(&tv, NULL); - __guard ^= tv.tv_usec ^ tv.tv_sec; + { + struct timeval tv; + gettimeofday(&tv, NULL); + __guard ^= tv.tv_usec ^ tv.tv_sec; + } } void __stack_smash_handler(char func[], int damaged __attribute__ ((unused))); diff --git a/libc/sysdeps/linux/common/umount.c b/libc/sysdeps/linux/common/umount.c index d8e890d8b..158aefc5f 100644 --- a/libc/sysdeps/linux/common/umount.c +++ b/libc/sysdeps/linux/common/umount.c @@ -9,26 +9,33 @@ #include "syscalls.h" -#ifdef __NR_umount /* Some newer archs only have umount2 */ + +/* arch provides umount() syscall */ +#ifdef __NR_umount + #include <sys/mount.h> _syscall1(int, umount, const char *, specialfile); + +/* arch provides umount2() syscall */ #elif defined __NR_umount2 -/* No umount syscall, but umount2 is available.... Try to - * emulate umount() using umount2() */ #define __NR___syscall_umount2 __NR_umount2 -static inline _syscall2(int, umount2, const char *, special_file, int, flags); +static inline _syscall2(int, __syscall_umount2, const char *, special_file, int, flags); int umount(const char *special_file) { return (__syscall_umount2(special_file, 0)); } + +/* arch doesn't provide any umount syscall !? */ #else + int umount(const char *special_file) { __set_errno(ENOSYS); return -1; } + #endif diff --git a/libc/sysdeps/linux/common/xstatconv.c b/libc/sysdeps/linux/common/xstatconv.c index fc25c43db..df6ebaa2b 100644 --- a/libc/sysdeps/linux/common/xstatconv.c +++ b/libc/sysdeps/linux/common/xstatconv.c @@ -34,42 +34,53 @@ void __xstat_conv(struct kernel_stat *kbuf, struct stat *buf) { - /* Convert to current kernel version of `struct stat'. */ - buf->st_dev = kbuf->st_dev; - buf->st_ino = kbuf->st_ino; - buf->st_mode = kbuf->st_mode; - buf->st_nlink = kbuf->st_nlink; - buf->st_uid = kbuf->st_uid; - buf->st_gid = kbuf->st_gid; - buf->st_rdev = kbuf->st_rdev; - buf->st_size = kbuf->st_size; - buf->st_blksize = kbuf->st_blksize; - buf->st_blocks = kbuf->st_blocks; - buf->st_atime = kbuf->st_atime; - buf->st_mtime = kbuf->st_mtime; - buf->st_ctime = kbuf->st_ctime; + /* Convert to current kernel version of `struct stat'. */ + buf->st_dev = kbuf->st_dev; + buf->st_ino = kbuf->st_ino; + buf->st_mode = kbuf->st_mode; + buf->st_nlink = kbuf->st_nlink; + buf->st_uid = kbuf->st_uid; + buf->st_gid = kbuf->st_gid; + buf->st_rdev = kbuf->st_rdev; + buf->st_size = kbuf->st_size; + buf->st_blksize = kbuf->st_blksize; + buf->st_blocks = kbuf->st_blocks; + buf->st_atime = kbuf->st_atime; + buf->st_mtime = kbuf->st_mtime; + buf->st_ctime = kbuf->st_ctime; +#ifdef STAT_HAVE_NSEC + buf->st_atimensec = kbuf->st_atime_nsec; + buf->st_mtimensec = kbuf->st_mtime_nsec; + buf->st_ctimensec = kbuf->st_ctime_nsec; +#endif } -#if defined __UCLIBC_HAS_LFS__ +#if defined(__UCLIBC_HAS_LFS__) + void __xstat64_conv(struct kernel_stat64 *kbuf, struct stat64 *buf) { - /* Convert to current kernel version of `struct stat64'. */ - buf->st_dev = kbuf->st_dev; - buf->st_ino = kbuf->st_ino; + /* Convert to current kernel version of `struct stat64'. */ + buf->st_dev = kbuf->st_dev; + buf->st_ino = kbuf->st_ino; #ifdef _HAVE_STAT64___ST_INO - buf->__st_ino = kbuf->__st_ino; + buf->__st_ino = kbuf->__st_ino; #endif - buf->st_mode = kbuf->st_mode; - buf->st_nlink = kbuf->st_nlink; - buf->st_uid = kbuf->st_uid; - buf->st_gid = kbuf->st_gid; - buf->st_rdev = kbuf->st_rdev; - buf->st_size = kbuf->st_size; - buf->st_blksize = kbuf->st_blksize; - buf->st_blocks = kbuf->st_blocks; - buf->st_atime = kbuf->st_atime; - buf->st_mtime = kbuf->st_mtime; - buf->st_ctime = kbuf->st_ctime; -} + buf->st_mode = kbuf->st_mode; + buf->st_nlink = kbuf->st_nlink; + buf->st_uid = kbuf->st_uid; + buf->st_gid = kbuf->st_gid; + buf->st_rdev = kbuf->st_rdev; + buf->st_size = kbuf->st_size; + buf->st_blksize = kbuf->st_blksize; + buf->st_blocks = kbuf->st_blocks; + buf->st_atime = kbuf->st_atime; + buf->st_mtime = kbuf->st_mtime; + buf->st_ctime = kbuf->st_ctime; +#ifdef STAT_HAVE_NSEC + buf->st_atimensec = kbuf->st_atime_nsec; + buf->st_mtimensec = kbuf->st_mtime_nsec; + buf->st_ctimensec = kbuf->st_ctime_nsec; #endif +} +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/libc/sysdeps/linux/mips/__syscall_error.c b/libc/sysdeps/linux/mips/__syscall_error.c index 9ab65ed79..de65a1f39 100644 --- a/libc/sysdeps/linux/mips/__syscall_error.c +++ b/libc/sysdeps/linux/mips/__syscall_error.c @@ -1,4 +1,4 @@ -/* Wrapper around clone system call. +/* Wrapper for setting errno. Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -18,12 +18,12 @@ 02111-1307 USA. */ #include <errno.h> +#include <features.h> /* This routine is jumped to by all the syscall handlers, to stash * an error number into errno. */ -int __syscall_error (int err_no) +int attribute_hidden __syscall_error(int err_no) { - __set_errno (err_no); + __set_errno(err_no); return -1; } - diff --git a/libc/sysdeps/linux/mips/bits/msq.h b/libc/sysdeps/linux/mips/bits/msq.h index c2c1dd2e8..2b0d38ec8 100644 --- a/libc/sysdeps/linux/mips/bits/msq.h +++ b/libc/sysdeps/linux/mips/bits/msq.h @@ -21,6 +21,7 @@ #endif #include <bits/types.h> +#include <bits/wordsize.h> /* Define options for message queue functions. */ #define MSG_NOERROR 010000 /* no error if message is too big */ @@ -38,16 +39,34 @@ typedef unsigned long int msglen_t; struct msqid_ds { struct ipc_perm msg_perm; /* structure describing operation permission */ +#if (__WORDSIZE == 32) && !defined(__MIPSEL__) + unsigned long __unused1; +#endif __time_t msg_stime; /* time of last msgsnd command */ +#if (__WORDSIZE == 32) && defined(__MIPSEL__) + unsigned long __unused1; +#endif +#if (__WORDSIZE == 32) && !defined(__MIPSEL__) + unsigned long __unused2; +#endif __time_t msg_rtime; /* time of last msgrcv command */ +#if (__WORDSIZE == 32) && defined(__MIPSEL__) + unsigned long __unused2; +#endif +#if (__WORDSIZE == 32) && !defined(__MIPSEL__) + unsigned long __unused3; +#endif __time_t msg_ctime; /* time of last change */ +#if (__WORDSIZE == 32) && defined(__MIPSEL__) + unsigned long __unused3; +#endif unsigned long int __msg_cbytes; /* current number of bytes on queue */ msgqnum_t msg_qnum; /* number of messages currently on queue */ msglen_t msg_qbytes; /* max number of bytes allowed on queue */ __pid_t msg_lspid; /* pid of last msgsnd() */ __pid_t msg_lrpid; /* pid of last msgrcv() */ - unsigned long int __unused1; - unsigned long int __unused2; + unsigned long int __unused4; + unsigned long int __unused5; }; #ifdef __USE_MISC diff --git a/libc/sysdeps/linux/mips/bsd-setjmp.S b/libc/sysdeps/linux/mips/bsd-setjmp.S index 51af9c891..49a904d29 100644 --- a/libc/sysdeps/linux/mips/bsd-setjmp.S +++ b/libc/sysdeps/linux/mips/bsd-setjmp.S @@ -34,8 +34,8 @@ .type setjmp,@function setjmp: -#ifdef __PIC__ .set noreorder +#ifdef __PIC__ .cpload t9 .set reorder la t9, __sigsetjmp diff --git a/libc/sysdeps/linux/mips/clone.S b/libc/sysdeps/linux/mips/clone.S index 3b879040a..079d2bef2 100644 --- a/libc/sysdeps/linux/mips/clone.S +++ b/libc/sysdeps/linux/mips/clone.S @@ -72,6 +72,11 @@ __clone: /* Something bad happened -- no child created */ error: addiu sp,32 + + /* uClibc change -- start */ + move a0,v0 /* Pass return val to C function. */ + /* uClibc change -- stop */ + #ifdef __PIC__ la t9,__syscall_error jr t9 diff --git a/utils/Makefile b/utils/Makefile index 03a5cfc2d..dec011780 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -54,14 +54,14 @@ ldconfig: ldconfig.c $(STRIPTOOL) -x -R .note -R .comment $@ ldd: ldd.c - $(CC) $(CFLAGS) $(PIEFLAG) $(LDPIEFLAG) -Wl,-s \ + $(CC) $(CFLAGS) $(PIEFLAG) -Wl,-s \ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \ -DUCLIBC_LDSO=$(UCLIBC_LDSO) -I. -I../ldso/include \ $^ -o $@ $(STRIPTOOL) -x -R .note -R .comment $@ iconv: ../libc/misc/wchar/wchar.c - $(CC) $(CFLAGS) $(PIEFLAG) $(LDPIEFLAG) -Wl,-s \ + $(CC) $(CFLAGS) $(PIEFLAG) -Wl,-s \ -DL_iconv_main \ $^ -o $@ $(STRIPTOOL) -x -R .note -R .comment $@ |