diff options
Diffstat (limited to 'ldso/include')
-rw-r--r-- | ldso/include/dl-defs.h | 2 | ||||
-rw-r--r-- | ldso/include/dl-elf.h | 41 | ||||
-rw-r--r-- | ldso/include/dl-string.h | 4 | ||||
-rw-r--r-- | ldso/include/dl-syscall.h | 80 | ||||
-rwxr-xr-x[-rw-r--r--] | ldso/include/ldso.h | 13 |
5 files changed, 129 insertions, 11 deletions
diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h index f27112a11..e900640bb 100644 --- a/ldso/include/dl-defs.h +++ b/ldso/include/dl-defs.h @@ -72,7 +72,7 @@ typedef struct { #endif #ifdef _LIBC -#ifndef __ARCH_HAS_NO_SHARED__ +#ifndef __ARCH_HAS_NO_LDSO__ /* arch specific defines */ #include <dl-sysdep.h> #endif diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h index 2b99958d9..832f6b1dd 100644 --- a/ldso/include/dl-elf.h +++ b/ldso/include/dl-elf.h @@ -250,5 +250,46 @@ unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info (((X) & PF_W) ? PROT_WRITE : 0) | \ (((X) & PF_X) ? PROT_EXEC : 0)) +/* FDPIC ABI don't use relative relocations */ +#if !defined(__FDPIC__) +/* Apply relocations in DT_RELR format */ +#define DL_DO_RELOCATE_RELR(load_addr, relr_start, relr_end) \ + do { \ + const ElfW(Relr) *relr = 0; \ + ElfW(Addr) *relr_reloc_addr = 0; \ + for (relr = relr_start; relr < relr_end; relr++) { \ + ElfW(Relr) relr_entry = *relr; \ + if (!(relr_entry & 1)) \ + { \ + relr_reloc_addr = (ElfW(Addr) *)DL_RELOC_ADDR(load_addr, relr_entry); \ + *relr_reloc_addr = (ElfW(Addr))DL_RELOC_ADDR(load_addr, relr_reloc_addr); \ + relr_reloc_addr++; \ + } \ + else \ + { \ + for (long int i = 0; (relr_entry >>= 1) != 0; ++i) { \ + if ((relr_entry & 1) != 0) \ + relr_reloc_addr[i] = (ElfW(Addr))DL_RELOC_ADDR(load_addr, relr_reloc_addr[i]); \ + } \ + relr_reloc_addr += CHAR_BIT * sizeof(ElfW(Relr)) - 1; \ + } \ + } \ + } while (0) + +/* The macro to prepare data for the above DL_DO_RELOCATE_RELR */ +#define DL_RELOCATE_RELR(dyn) \ + do { \ + if (dyn->dynamic_info[DT_RELRENT]) \ + _dl_assert(dyn->dynamic_info[DT_RELRENT] == sizeof(ElfW(Relr))); \ + if (dyn->dynamic_info[DT_RELR] && \ + dyn->dynamic_info[DT_RELRSZ]) { \ + ElfW(Relr) *relr_start = (ElfW(Relr) *)((ElfW(Addr))dyn->loadaddr + (ElfW(Addr))dyn->dynamic_info[DT_RELR]); \ + ElfW(Relr) *relr_end = (ElfW(Relr) *)((const char *)relr_start + dyn->dynamic_info[DT_RELRSZ]); \ + _dl_if_debug_dprint("Relocating DT_RELR in %s: start:%p, end:%p\n", \ + dyn->libname, (void *)relr_start, (void *)relr_end); \ + DL_DO_RELOCATE_RELR(dyn->loadaddr, relr_start, relr_end); \ + } \ + } while (0) +#endif /* __FDPIC__ */ #endif /* _DL_ELF_H */ diff --git a/ldso/include/dl-string.h b/ldso/include/dl-string.h index bf6997188..4a66161e0 100644 --- a/ldso/include/dl-string.h +++ b/ldso/include/dl-string.h @@ -103,7 +103,7 @@ static __always_inline char * _dl_strstr(const char *s1, const char *s2) do { if (!*p) - return (char *) s1;; + return (char *) s1; if (*p == *s) { ++p; ++s; @@ -257,7 +257,7 @@ static __always_inline char * _dl_simple_ltoahex(char *local, unsigned long i) /* On some (wierd) arches, none of this stuff works at all, so * disable the whole lot... */ /* The same applies for ARM FDPIC at least for the moment. */ -#if defined(__mips__) || (__FDPIC__) +#if defined(__mips__) || defined(__FDPIC__) # define SEND_STDERR(X) # define SEND_ADDRESS_STDERR(X, add_a_newline) diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h index 9d80c6a26..4f41034ad 100644 --- a/ldso/include/dl-syscall.h +++ b/ldso/include/dl-syscall.h @@ -11,8 +11,11 @@ * been dynamicly linked in yet. */ #include "sys/syscall.h" extern int _dl_errno; + +#ifdef UCLIBC_LDSO #undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} +#endif /* Pull in the arch specific syscall implementation */ #include <dl-syscalls.h> @@ -20,7 +23,7 @@ extern int _dl_errno; #define _SYS_MMAN_H 1 #include <bits/mman.h> -#ifdef __ARCH_HAS_DEPRECATED_SYSCALLS__ +#if defined(__ARCH_HAS_DEPRECATED_SYSCALLS__) && (!defined(__UCLIBC_USE_TIME64__) || defined(__sparc__)) /* Pull in whatever this particular arch's kernel thinks the kernel version of * struct stat should look like. It turns out that each arch has a different * opinion on the subject, and different kernel revs use different names... */ @@ -36,9 +39,40 @@ extern int _dl_errno; /* 1. common-generic ABI doesn't need kernel_stat translation * 3. S_IS?ID already provided by stat.h */ +#include <fcntl.h> #include <sys/stat.h> +#include <dl-string.h> + +#include <bits/uClibc_arch_features.h> +#if defined __UCLIBC_HAVE_STATX__ +static __always_inline void +__cp_stat_statx (struct stat *to, struct statx *from) +{ + _dl_memset (to, 0, sizeof (struct stat)); + to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8) + | ((from->stx_dev_minor & ~0xff) << 12)); + to->st_rdev = ((from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8) + | ((from->stx_rdev_minor & ~0xff) << 12)); + to->st_ino = from->stx_ino; + to->st_mode = from->stx_mode; + to->st_nlink = from->stx_nlink; + to->st_uid = from->stx_uid; + to->st_gid = from->stx_gid; + to->st_atime = from->stx_atime.tv_sec; + to->st_atim.tv_nsec = from->stx_atime.tv_nsec; + to->st_mtime = from->stx_mtime.tv_sec; + to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec; + to->st_ctime = from->stx_ctime.tv_sec; + to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec; + to->st_size = from->stx_size; + to->st_blocks = from->stx_blocks; + to->st_blksize = from->stx_blksize; +} +#endif #endif +#define AT_NO_AUTOMOUNT 0x800 +#define AT_EMPTY_PATH 0x1000 /* Here are the definitions for some syscalls that are used by the dynamic linker. The idea is that we want to be able @@ -85,7 +119,7 @@ static __always_inline _syscall3(unsigned long, _dl_read, int, fd, static __always_inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, len, int, prot) -#if defined __NR_fstatat64 && !defined __NR_stat +#if defined __NR_fstatat64 && !defined __NR_stat && (!defined(__UCLIBC_USE_TIME64__) || defined(__sparc__)) # define __NR__dl_fstatat64 __NR_fstatat64 static __always_inline _syscall4(int, _dl_fstatat64, int, fd, const char *, fn, struct stat *, stat, int, flags) @@ -95,7 +129,7 @@ static __always_inline int _dl_stat(const char *file_name, { return _dl_fstatat64(AT_FDCWD, file_name, buf, 0); } -#elif defined __NR_newfstatat && !defined __NR_stat +#elif defined __NR_newfstatat && !defined __NR_stat && (!defined(__UCLIBC_USE_TIME64__) || defined(__sparc__)) # define __NR__dl_newfstatat __NR_newfstatat static __always_inline _syscall4(int, _dl_newfstatat, int, fd, const char *, fn, struct stat *, stat, int, flags) @@ -105,18 +139,52 @@ static __always_inline int _dl_stat(const char *file_name, { return _dl_newfstatat(AT_FDCWD, file_name, buf, 0); } -#elif defined __NR_stat +#elif defined __NR_stat && (!defined(__UCLIBC_USE_TIME64__) || defined(__sparc__)) # define __NR__dl_stat __NR_stat static __always_inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf) + +#elif defined __NR_statx && defined __UCLIBC_HAVE_STATX__ +# define __NR__dl_statx __NR_statx +# include <fcntl.h> +# include <statx_cp.h> + +static __always_inline _syscall5(int, _dl_statx, int, fd, const char *, file_name, int, flags, + unsigned int, mask, struct statx *, buf); + +static __always_inline int _dl_stat(const char *file_name, + struct stat *buf) +{ + struct statx tmp; + int rc = _dl_statx(AT_FDCWD, file_name, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat_statx ((struct stat *)buf, &tmp); + return rc; +} #endif -#if defined __NR_fstat64 && !defined __NR_fstat +#if defined __NR_fstat64 && !defined __NR_fstat && (!defined(__UCLIBC_USE_TIME64__) || defined(__sparc__)) # define __NR__dl_fstat __NR_fstat64 +static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf) #elif defined __NR_fstat # define __NR__dl_fstat __NR_fstat -#endif static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf) +#elif defined __NR_statx && defined __UCLIBC_HAVE_STATX__ +# define __NR__dl_fstatx __NR_statx +static __always_inline _syscall5(int, _dl_fstatx, int, fd, const char *, file_name, int, flags, unsigned int, mask, struct statx *, buf); + +static __always_inline int _dl_fstat(int fd, + struct stat *buf) +{ + struct statx tmp; + int rc = _dl_fstatx(fd, "", AT_EMPTY_PATH, STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat_statx ((struct stat *)buf, &tmp); + return rc; +} +#else +static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf) +#endif #define __NR__dl_munmap __NR_munmap static __always_inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length) diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h index f19957d1d..a397cce61 100644..100755 --- a/ldso/include/ldso.h +++ b/ldso/include/ldso.h @@ -48,7 +48,7 @@ /* Pull in the MIN macro */ #include <sys/param.h> /* Pull in the ldso syscalls and string functions */ -#ifndef __ARCH_HAS_NO_SHARED__ +#if !defined(__ARCH_HAS_NO_SHARED__) || !defined(__ARCH_HAS_NO_LDSO__) #include <dl-syscall.h> #include <dl-string.h> /* Now the ldso specific headers */ @@ -109,6 +109,7 @@ extern char *_dl_debug_reloc; extern char *_dl_debug_detail; extern char *_dl_debug_nofixups; extern char *_dl_debug_bindings; +extern char *_dl_debug_vdso; extern int _dl_debug_file; # define __dl_debug_dprint(fmt, args...) \ _dl_dprintf(_dl_debug_file, "%s:%i: " fmt, __func__, __LINE__, ## args); @@ -148,6 +149,7 @@ extern int _dl_debug_file; #define NULL ((void *) 0) #endif + extern void *_dl_malloc(size_t size); extern void *_dl_calloc(size_t __nmemb, size_t __size); extern void *_dl_realloc(void *__ptr, size_t __size); @@ -176,7 +178,7 @@ extern void _dl_dprintf(int, const char *, ...); #endif extern void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, - ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv + char **envp, char **argv DL_GET_READY_TO_RUN_EXTRA_PARMS); #ifdef HAVE_DL_INLINES_H @@ -185,6 +187,13 @@ extern void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE loa #else /* __ARCH_HAS_NO_SHARED__ */ #include <dl-defs.h> +#include <dl-elf.h> + #endif +#define AUX_MAX_AT_ID 40 +extern ElfW(auxv_t) _dl_auxvt[AUX_MAX_AT_ID]; + +void load_vdso(void *sys_info_ehdr, char **envp ); + #endif /* _LDSO_H */ |