summaryrefslogtreecommitdiff
path: root/ldso
diff options
context:
space:
mode:
authorCarmelo Amoroso <carmelo.amoroso@st.com>2011-04-06 15:13:59 +0200
committerCarmelo Amoroso <carmelo.amoroso@st.com>2011-04-06 15:13:59 +0200
commit3b3285b1b7c02d36c74a6ae265fdb02ca991c96b (patch)
tree0f3bf060794323ff690f6f4a86dc903c4570f540 /ldso
parent289d19f45d7f8af9a4079938a3426aafdd2674ba (diff)
parent85f4b028d767fc390a7b866d2f58d58be489242d (diff)
Merge remote-tracking branch 'origin/master' into prelink
* origin/master: (137 commits) utils/ldd: Check for returned pointer from strrchr not the value it holds cris: add provide arch-specific vfork implementation lutimes.c, stubs.c: fix compiling lutimes, if __NR_utimensat is not defined bump version to 0.9.32-rc3-git release 0.9.32-rc3 memalign: include sys/param.h for MAX arm/bits/atomic.h: Include common/bit/atomic.h for thumb1 wctype.h: fix libc_hidden_proto for iswupper and add it for iswspace add libc_hidden_proto for wcs[n]casecmp_l really fix missing __libc_drand48_data Revert "missing prototype of __libc_drand48_data fixed" missing prototype of __libc_drand48_data fixed time.c, time.h: remove unused hidden strftime/strptime nanosleep.c: remove duplicated libc_hidden_proto ctype.c, ctype.h: remove commented parts that were banned for removal after 0.9.31 _wctype.c, wctype.h: remove unused isw* and wctype_l hidden functions time.c, wchar.h: remove unused hidden wcsftime str[n]casecmp.c: fix hidden usage remove unused hidden functions frv/memset.S: add missing libc_hidden_def ... Conflicts: ldso/ldso/ldso.c Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
Diffstat (limited to 'ldso')
-rw-r--r--ldso/include/dl-defs.h2
-rw-r--r--ldso/include/dl-elf.h18
-rw-r--r--ldso/include/dl-syscall.h2
-rw-r--r--ldso/ldso/Makefile.in1
-rw-r--r--ldso/ldso/bfin/dl-syscalls.h12
-rw-r--r--ldso/ldso/c6x/dl-debug.h49
-rw-r--r--ldso/ldso/c6x/dl-inlines.h91
-rw-r--r--ldso/ldso/c6x/dl-startup.h122
-rw-r--r--ldso/ldso/c6x/dl-syscalls.h25
-rw-r--r--ldso/ldso/c6x/dl-sysdep.h209
-rw-r--r--ldso/ldso/c6x/elfinterp.c296
-rw-r--r--ldso/ldso/c6x/resolve.S68
-rw-r--r--ldso/ldso/dl-elf.c50
-rw-r--r--ldso/ldso/i386/elfinterp.c2
-rw-r--r--ldso/ldso/ldso.c14
-rw-r--r--ldso/ldso/sparc/elfinterp.c2
-rw-r--r--ldso/ldso/x86_64/elfinterp.c2
-rw-r--r--ldso/libdl/Makefile.in1
-rw-r--r--ldso/libdl/libdl.c5
19 files changed, 948 insertions, 23 deletions
diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h
index cbbaa3cea..d387c0bb9 100644
--- a/ldso/include/dl-defs.h
+++ b/ldso/include/dl-defs.h
@@ -212,7 +212,7 @@ typedef struct {
_dl_find_hash for this reloc TYPE. TPNT is the module in which the
matching SYM was found. */
#ifndef DL_FIND_HASH_VALUE
-# define DL_FIND_HASH_VALUE(TPNT, TYPE, SYM) (DL_RELOC_ADDR ((SYM)->st_value, (TPNT)->loadaddr))
+# define DL_FIND_HASH_VALUE(TPNT, TYPE, SYM) (DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value))
#endif
/* Unmap all previously-mapped segments accumulated in LOADADDR.
diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h
index 40c88b9da..908cb63ce 100644
--- a/ldso/include/dl-elf.h
+++ b/ldso/include/dl-elf.h
@@ -200,8 +200,13 @@ unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info
if (dynamic_info[tag]) \
dynamic_info[tag] = (unsigned long) DL_RELOC_ADDR(load_off, dynamic_info[tag]); \
} while (0)
- /* Don't adjust .dynamic unnecessarily. */
- if (load_off != 0) {
+ /* Don't adjust .dynamic unnecessarily. For FDPIC targets,
+ we'd have to walk all the loadsegs to find out if it was
+ actually unnecessary, so skip this optimization. */
+#if !defined __FDPIC__ && !defined __DSBT__
+ if (load_off != 0)
+#endif
+ {
ADJUST_DYN_INFO(DT_HASH, load_off);
ADJUST_DYN_INFO(DT_PLTGOT, load_off);
ADJUST_DYN_INFO(DT_STRTAB, load_off);
@@ -212,6 +217,15 @@ unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info
ADJUST_DYN_INFO(DT_GNU_HASH_IDX, load_off);
#endif
}
+#ifdef __DSBT__
+ /* Get the mapped address of the DSBT base. */
+ ADJUST_DYN_INFO(DT_DSBT_BASE_IDX, load_off);
+
+ /* Initialize loadmap dsbt info. */
+ load_off.map->dsbt_table = dynamic_info[DT_DSBT_BASE_IDX];
+ load_off.map->dsbt_size = dynamic_info[DT_DSBT_SIZE_IDX];
+ load_off.map->dsbt_index = dynamic_info[DT_DSBT_INDEX_IDX];
+#endif
#undef ADJUST_DYN_INFO
return rtld_flags;
}
diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h
index 982bc9bf6..da3ac7f6f 100644
--- a/ldso/include/dl-syscall.h
+++ b/ldso/include/dl-syscall.h
@@ -95,7 +95,7 @@ static __always_inline _syscall0(gid_t, _dl_getegid)
# define __NR_getpid __NR_getxpid
#endif
#define __NR__dl_getpid __NR_getpid
-static __always_inline _syscall0(gid_t, _dl_getpid);
+static __always_inline _syscall0(gid_t, _dl_getpid)
#define __NR__dl_readlink __NR_readlink
static __always_inline _syscall3(int, _dl_readlink, const char *, path, char *, buf,
diff --git a/ldso/ldso/Makefile.in b/ldso/ldso/Makefile.in
index c9dcebd60..ad8edbb65 100644
--- a/ldso/ldso/Makefile.in
+++ b/ldso/ldso/Makefile.in
@@ -30,6 +30,7 @@ CFLAGS-ldso/ldso/$(TARGET_ARCH)/ := $(CFLAGS-ldso)
CFLAGS-ldso.c := -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" $(CFLAGS-ldso)
+LDFLAGS-$(UCLIBC_FORMAT_DSBT_ELF)-$(UCLIBC_LDSO_NAME).so := -Wl,--dsbt-index=1
ifneq ($(SUPPORT_LD_DEBUG),y)
LDFLAGS-$(UCLIBC_LDSO_NAME).so := $(LDFLAGS)
else
diff --git a/ldso/ldso/bfin/dl-syscalls.h b/ldso/ldso/bfin/dl-syscalls.h
index 916d0f84e..f74cf1ad3 100644
--- a/ldso/ldso/bfin/dl-syscalls.h
+++ b/ldso/ldso/bfin/dl-syscalls.h
@@ -31,7 +31,7 @@ extern int _dl_errno;
#if DYNAMIC_LOADER_IN_SIMULATOR
#define __NR___syscall_mmap2 __NR_mmap2
static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr,
- size_t, len, int, prot, int, flags, int, fd, off_t, offset);
+ size_t, len, int, prot, int, flags, int, fd, off_t, offset)
/* Make sure we don't get another definition of _dl_mmap from the
machine-independent code. */
@@ -155,7 +155,7 @@ _dl_mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset)
static __always_inline unsigned long _dl_read(int fd, const void *buf, unsigned long count);
static __always_inline _syscall3(__off_t, __syscall_lseek, int, fd, __off_t, offset,
- int, whence);
+ int, whence)
static __always_inline ssize_t
_dl_pread(int fd, void *buf, size_t count, off_t offset)
{
@@ -178,7 +178,7 @@ _dl_pread(int fd, void *buf, size_t count, off_t offset)
#else
#define __NR___syscall_pread __NR_pread
static __always_inline _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf,
- size_t, count, off_t, offset_hi, off_t, offset_lo);
+ size_t, count, off_t, offset_hi, off_t, offset_lo)
static __always_inline ssize_t
_dl_pread(int fd, void *buf, size_t count, off_t offset)
@@ -191,18 +191,18 @@ _dl_pread(int fd, void *buf, size_t count, off_t offset)
#ifdef __NR_sram_alloc
#define __NR__dl_sram_alloc __NR_sram_alloc
static __always_inline _syscall2(__ptr_t, _dl_sram_alloc,
- size_t, len, unsigned long, flags);
+ size_t, len, unsigned long, flags)
#endif
#ifdef __NR_sram_free
#define __NR__dl_sram_free __NR_sram_free
-static __always_inline _syscall1(int, _dl_sram_free, __ptr_t, addr);
+static __always_inline _syscall1(int, _dl_sram_free, __ptr_t, addr)
#endif
#ifdef __NR_dma_memcpy
#define __NR__dl_dma_memcpy __NR_dma_memcpy
static __always_inline _syscall3(__ptr_t, _dl_dma_memcpy,
- __ptr_t, dest, __ptr_t, src, size_t, len);
+ __ptr_t, dest, __ptr_t, src, size_t, len)
#endif
#define __UCLIBC_MMAP_HAS_6_ARGS__
diff --git a/ldso/ldso/c6x/dl-debug.h b/ldso/ldso/c6x/dl-debug.h
new file mode 100644
index 000000000..9c6edab0a
--- /dev/null
+++ b/ldso/ldso/c6x/dl-debug.h
@@ -0,0 +1,49 @@
+/* C6X DSBT ELF shared library loader suppport.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * All rights reserved.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+static const char *_dl_reltypes_tab[] =
+{
+ "R_C6000_NONE", /* 0 */
+ "R_C6000_ABS32",
+ "R_C6000_ABS16",
+ "R_C6000_ABS8",
+ "R_C6000_PCR_S21",
+ "R_C6000_PCR_S12", /* 5 */
+ "R_C6000_PCR_S10",
+ "R_C6000_PCR_S7",
+ "R_C6000_ABS_S16",
+ "R_C6000_ABS_L16",
+ "R_C6000_ABS_H16", /* 10 */
+ "R_C6000_SBR_U15_B",
+ "R_C6000_SBR_U15_H",
+ "R_C6000_SBR_U15_W",
+ "R_C6000_SBR_S16",
+ "R_C6000_SBR_L16_B", /* 15 */
+ "R_C6000_SBR_L16_H",
+ "R_C6000_SBR_L16_W",
+ "R_C6000_SBR_H16_B",
+ "R_C6000_SBR_H16_H",
+ "R_C6000_SBR_H16_W", /* 20 */
+ "R_C6000_SBR_GOT_U15_W",
+ "R_C6000_SBR_GOT_L16_W",
+ "R_C6000_SBR_GOT_H16_W",
+ "R_C6000_DSBT_INDEX",
+ "R_C6000_PREL31", /* 25 */
+ "R_C6000_COPY",
+ "R_C6000_JUMP_SLOT",
+ "R_C6000_SBR_GOT32",
+ "R_C6000_PCR_H16",
+ "R_C6000_PCR_L16", /* 30 */
+#if 0
+ "R_C6000_ALIGN", /* 253 */
+ "R_C6000_FPHEAD", /* 254 */
+ "R_C6000_NOCMP", /* 255 */
+#endif
+};
diff --git a/ldso/ldso/c6x/dl-inlines.h b/ldso/ldso/c6x/dl-inlines.h
new file mode 100644
index 000000000..d8fb42c55
--- /dev/null
+++ b/ldso/ldso/c6x/dl-inlines.h
@@ -0,0 +1,91 @@
+/* Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Borrowed heavily from frv arch:
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Figure out whether the given address is in one of the mapped
+ segments. */
+static __always_inline int
+__dl_addr_in_loadaddr (void *p, struct elf32_dsbt_loadaddr loadaddr)
+{
+ struct elf32_dsbt_loadmap *map = loadaddr.map;
+ int c;
+
+ for (c = 0; c < map->nsegs; c++)
+ if ((void*)map->segs[c].addr <= p
+ && (char*)p < (char*)map->segs[c].addr + map->segs[c].p_memsz)
+ return 1;
+
+ return 0;
+}
+
+/* Figure out how many LOAD segments there are in the given headers,
+ and allocate a block for the load map big enough for them.
+ got_value will be properly initialized later on, with INIT_GOT. */
+static __always_inline int
+__dl_init_loadaddr (struct elf32_dsbt_loadaddr *loadaddr, Elf32_Phdr *ppnt,
+ int pcnt)
+{
+ int count = 0, i;
+ size_t size;
+
+ for (i = 0; i < pcnt; i++)
+ if (ppnt[i].p_type == PT_LOAD)
+ count++;
+
+ size = sizeof (struct elf32_dsbt_loadmap)
+ + sizeof (struct elf32_dsbt_loadseg) * count;
+ loadaddr->map = _dl_malloc (size);
+ if (! loadaddr->map)
+ _dl_exit (-1);
+
+ loadaddr->map->version = 0;
+ loadaddr->map->nsegs = 0;
+
+ return count;
+}
+
+/* Incrementally initialize a load map. */
+static __always_inline void
+__dl_init_loadaddr_hdr (struct elf32_dsbt_loadaddr loadaddr, void *addr,
+ Elf32_Phdr *phdr, int maxsegs)
+{
+ struct elf32_dsbt_loadseg *segdata;
+
+ if (loadaddr.map->nsegs == maxsegs)
+ _dl_exit (-1);
+
+ segdata = &loadaddr.map->segs[loadaddr.map->nsegs++];
+ segdata->addr = (Elf32_Addr) addr;
+ segdata->p_vaddr = phdr->p_vaddr;
+ segdata->p_memsz = phdr->p_memsz;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ {
+ if (_dl_debug)
+ _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
+ loadaddr.map->nsegs-1,
+ segdata->p_vaddr, segdata->addr, segdata->p_memsz);
+ }
+#endif
+}
+
+static __always_inline void
+__dl_loadaddr_unmap (struct elf32_dsbt_loadaddr loadaddr)
+{
+ int i;
+
+ for (i = 0; i < loadaddr.map->nsegs; i++)
+ _dl_munmap ((void*)loadaddr.map->segs[i].addr,
+ loadaddr.map->segs[i].p_memsz);
+
+ /* _dl_unmap is only called for dlopen()ed libraries, for which
+ calling free() is safe, or before we've completed the initial
+ relocation, in which case calling free() is probably pointless,
+ but still safe. */
+ _dl_free (loadaddr.map);
+}
diff --git a/ldso/ldso/c6x/dl-startup.h b/ldso/ldso/c6x/dl-startup.h
new file mode 100644
index 000000000..b9ea30409
--- /dev/null
+++ b/ldso/ldso/c6x/dl-startup.h
@@ -0,0 +1,122 @@
+/* Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Borrowed heavily from frv arch:
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#undef DL_START
+#define DL_START(X) \
+int \
+_dl_start (unsigned placeholder, \
+ struct elf32_dsbt_loadmap *dl_boot_progmap, \
+ struct elf32_dsbt_loadmap *dl_boot_ldsomap, \
+ Elf32_Dyn *dl_boot_ldso_dyn_pointer, \
+ X)
+
+/*
+ * On entry, the kernel has set up the stack thusly:
+ *
+ * 0(sp) pad0
+ * 4(sp) pad1
+ * 8(sp) argc
+ * 12(sp) argv[0]
+ * ...
+ * (4*(argc+3))(sp) NULL
+ * (4*(argc+4))(sp) envp[0]
+ * ...
+ * NULL
+ *
+ * Register values are unspecified, except:
+ *
+ * B4 --> executable loadmap address
+ * A6 --> interpreter loadmap address
+ * B6 --> dynamic section address
+ * B14 --> our DP setup by kernel
+ *
+ * NB: DSBT index is always 0 for the executable
+ * and 1 for the interpreter
+ */
+
+__asm__(" .text\n"
+ ".globl _start\n"
+ "_start:\n"
+ " B .S2 _dl_start\n"
+ " STW .D2T2 B14, *+B14[1]\n"
+ " ADD .D1X B15,8,A8\n"
+ " ADDKPC .S2 ret_from_dl,B3,2\n"
+ "ret_from_dl:\n"
+ " B .S2X A4\n"
+ " || LDW .D2T2 *+B14[0],B14\n"
+ " ADDKPC .S2 __dl_fini,B0,0\n"
+ " MV .S1X B0,A4\n"
+ " NOP\n"
+ " NOP\n"
+ " NOP\n"
+ "__dl_fini:\n"
+ " LDW .D2T2 *+B14[1],B14\n"
+ " NOP 4\n"
+ " LDW .D2T1 *+B14($GOT(_dl_fini)), A0\n"
+ " NOP 4\n"
+ " BNOP .S2X A0, 5\n");
+
+__asm__(" .text\n"
+ "__c6x_cache_sync:\n"
+ " MVK .S2 330,B0\n"
+ " SWE\n"
+ " NOP\n"
+ " BNOP .S2 B3,5\n"
+ " NOP\n"
+ " NOP\n"
+ " NOP\n"
+ " NOP\n"
+ "\n"
+);
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS) + 1)
+
+struct elf32_dsbt_loadmap;
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader. RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+ switch(ELF32_R_TYPE((RELP)->r_info)){ \
+ case R_C6000_ABS_L16: \
+ { \
+ unsigned int opcode = *(REL); \
+ unsigned int v = (SYMBOL) + (RELP)->r_addend; \
+ opcode &= ~0x7fff80; \
+ opcode |= ((v & 0xffff) << 7); \
+ *(REL) = opcode; \
+ } \
+ break; \
+ case R_C6000_ABS_H16: \
+ { \
+ unsigned int opcode = *(REL); \
+ unsigned int v = (SYMBOL) + (RELP)->r_addend; \
+ opcode &= ~0x7fff80; \
+ opcode |= ((v >> 9) & 0x7fff80); \
+ *(REL) = opcode; \
+ } \
+ break; \
+ case R_C6000_ABS32: \
+ *(REL) = (SYMBOL) + (RELP)->r_addend; \
+ break; \
+ default: \
+ _dl_exit(1); \
+ }
+
+extern void __c6x_cache_sync(unsigned long start, unsigned long end)
+ attribute_hidden;
diff --git a/ldso/ldso/c6x/dl-syscalls.h b/ldso/ldso/c6x/dl-syscalls.h
new file mode 100644
index 000000000..9ff3358b0
--- /dev/null
+++ b/ldso/ldso/c6x/dl-syscalls.h
@@ -0,0 +1,25 @@
+/* Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
+#include "sys/syscall.h"
+extern int _dl_errno;
+#undef __set_errno
+#define __set_errno(X) {(_dl_errno) = (X);}
+#include <sys/mman.h>
+
+#ifdef __NR_pread64
+#define __NR___syscall_pread __NR_pread64
+static __always_inline _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf,
+ size_t, count, off_t, offset_hi, off_t, offset_lo);
+
+static __always_inline ssize_t
+_dl_pread(int fd, void *buf, size_t count, off_t offset)
+{
+ return(__syscall_pread(fd,buf,count, offset, offset >> 31));
+}
+#endif
diff --git a/ldso/ldso/c6x/dl-sysdep.h b/ldso/ldso/c6x/dl-sysdep.h
new file mode 100644
index 000000000..8f1b122d3
--- /dev/null
+++ b/ldso/ldso/c6x/dl-sysdep.h
@@ -0,0 +1,209 @@
+/* Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Borrowed heavily from frv arch:
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <bits/elf-dsbt.h>
+
+/*
+ * Define this if the system uses RELOCA.
+ */
+#define ELF_USES_RELOCA 1
+
+/* JMPREL relocs are inside the DT_RELA table. */
+/* Actually looks like a linker bug sets DT_JMPREL anyway */
+#define ELF_MACHINE_PLTREL_OVERLAP 1
+
+#undef DL_NO_COPY_RELOCS
+
+#define HAVE_DL_INLINES_H
+
+
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/* Initialization sequence for the GOT. */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+}
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_TI_C6000
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "C6000"
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+struct elf_resolve;
+
+extern int _dl_linux_resolve(void) attribute_hidden;
+
+struct funcdesc_ht;
+struct elf32_dsbt_loadaddr;
+
+/* We must force strings used early in the bootstrap into the text
+ segment (const data), such that they are referenced relative to
+ the DP register rather than through the GOT which will not have
+ been relocated when these are used. */
+#undef SEND_EARLY_STDERR
+#define SEND_EARLY_STDERR(S) \
+ do { static char __s[] = (S); SEND_STDERR (__s); } while (0)
+
+#define DL_LOADADDR_TYPE struct elf32_dsbt_loadaddr
+
+#define DL_RELOC_ADDR(LOADADDR, ADDR) \
+ ((ElfW(Addr))__reloc_pointer ((void*)(ADDR), (LOADADDR).map))
+
+#define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \
+ do { \
+ struct elf32_dsbt_loadmap *map; \
+ map = dl_boot_ldsomap ?: dl_boot_progmap; \
+ if (map->version != 0) { \
+ SEND_EARLY_STDERR ("Invalid loadmap version number\n"); \
+ _dl_exit(-1); \
+ } \
+ if (map->nsegs < 2) { \
+ SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); \
+ _dl_exit(-1); \
+ } \
+ (LOADADDR).map = map; \
+ } while(0)
+
+#define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \
+ do { \
+ if (dl_boot_progmap->version != 0) { \
+ SEND_EARLY_STDERR ("Invalid loadmap version number\n"); \
+ _dl_exit(-1); \
+ } \
+ if (dl_boot_progmap->nsegs < 2) { \
+ SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); \
+ _dl_exit(-1); \
+ } \
+ (LOADADDR).map = dl_boot_progmap; \
+ } while(0)
+
+#define DL_INIT_LOADADDR_EXTRA_DECLS \
+ int dl_init_loadaddr_load_count;
+
+#define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \
+ (dl_init_loadaddr_load_count = \
+ __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT)))
+
+#define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
+ (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \
+ dl_init_loadaddr_load_count))
+
+#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
+ (__dl_loadaddr_unmap ((LOADADDR)))
+
+#define DL_LIB_UNMAP(LIB, LEN) \
+ (__dl_loadaddr_unmap ((LIB)->loadaddr))
+
+#define DL_LOADADDR_BASE(LOADADDR) \
+ ((LOADADDR).map->dsbt_table)
+
+#define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \
+ (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr))
+
+
+/* We only support loading DSBT relocatable shared libraries.
+ It probably wouldn't be too hard to support loading statically
+ linked executables that require relocation.*/
+#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \
+do \
+{ \
+ (piclib) = 2; \
+} \
+while (0)
+
+/* We want want to apply all relocations in the interpreter during
+ bootstrap. Because of this, we have to skip the interpreter
+ relocations in _dl_parse_relocation_information(), see
+ elfinterp.c. */
+#define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0
+
+#ifdef __NR_pread64
+#define _DL_PREAD(FD, BUF, SIZE, OFFSET) \
+ (_dl_pread((FD), (BUF), (SIZE), (OFFSET)))
+#endif
+
+#define DL_GET_READY_TO_RUN_EXTRA_PARMS \
+ , struct elf32_dsbt_loadmap *dl_boot_progmap \
+ , struct elf32_dsbt_loadmap *dl_boot_ldsomap
+#define DL_GET_READY_TO_RUN_EXTRA_ARGS \
+ , dl_boot_progmap \
+ , dl_boot_ldsomap
+
+
+/*
+ * Compute the GOT address.
+ * Also setup program and interpreter DSBT table entries.
+ */
+#define DL_BOOT_COMPUTE_GOT(GOT) \
+ do { \
+ unsigned long *ldso_dsbt, *prog_dsbt; \
+ ldso_dsbt = dl_boot_ldsomap->dsbt_table; \
+ prog_dsbt = dl_boot_progmap->dsbt_table; \
+ ldso_dsbt[0] = prog_dsbt[0] = (unsigned long)prog_dsbt; \
+ ldso_dsbt[1] = prog_dsbt[1] = (unsigned long)ldso_dsbt; \
+ (GOT) = ldso_dsbt + dl_boot_ldsomap->dsbt_size; \
+ } while(0)
+
+#define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \
+ ((dpnt) = dl_boot_ldso_dyn_pointer)
+
+
+#ifdef __USE_GNU
+# include <link.h>
+#else
+# define __USE_GNU
+# include <link.h>
+# undef __USE_GNU
+#endif
+
+static __always_inline Elf32_Addr
+elf_machine_load_address (void)
+{
+ /* this is never an issue on DSBT systems */
+ return 0;
+}
+
+static __always_inline void
+elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+}
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+ PLT entries should not be allowed to define the value.
+ ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+ of the main executable's symbols, as for a COPY reloc. */
+#define elf_machine_type_class(type) \
+ ((((type) == R_C6000_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_C6000_COPY) * ELF_RTYPE_CLASS_COPY))
+
+#define ARCH_NUM 3
+#define DT_DSBT_BASE_IDX (DT_NUM + OS_NUM)
+#define DT_DSBT_SIZE_IDX (DT_NUM + OS_NUM + 1)
+#define DT_DSBT_INDEX_IDX (DT_NUM + OS_NUM + 2)
+
+#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \
+do { \
+if (dpnt->d_tag == DT_C6000_DSBT_BASE) \
+ dynamic[DT_DSBT_BASE_IDX] = dpnt->d_un.d_val; \
+else if (dpnt->d_tag == DT_C6000_DSBT_SIZE) \
+ dynamic[DT_DSBT_SIZE_IDX] = dpnt->d_un.d_val; \
+else if (dpnt->d_tag == DT_C6000_DSBT_INDEX) \
+ dynamic[DT_DSBT_INDEX_IDX] = dpnt->d_un.d_val; \
+} while (0)
diff --git a/ldso/ldso/c6x/elfinterp.c b/ldso/ldso/c6x/elfinterp.c
new file mode 100644
index 000000000..7c79171ce
--- /dev/null
+++ b/ldso/ldso/c6x/elfinterp.c
@@ -0,0 +1,296 @@
+/* TI C64X DSBT ELF shared library loader suppport
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Borrowed heavily from frv arch:
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Contributed by Alexandre Oliva <aoliva@redhat.com>
+ * Lots of code copied from ../i386/elfinterp.c, so:
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2002, Erik Andersen
+ * All rights reserved.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <features.h>
+
+/* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+extern void __c6x_cache_sync(unsigned long start, unsigned long end)
+ attribute_hidden;
+
+static void
+_dl_c6x_flush_relocs(struct elf32_dsbt_loadmap *map)
+{
+ unsigned long s, e;
+ s = map->segs[0].addr;
+ e = s + map->segs[0].p_memsz;
+ __c6x_cache_sync(s, e);
+ s = map->segs[1].addr;
+ e = s + map->segs[1].p_memsz;
+ __c6x_cache_sync(s, e);
+}
+
+
+attribute_hidden
+char *
+_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ char *symname;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+
+ this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of GOT entry fix up */
+ got_addr = (char **) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset);
+
+ /* Get the address to be used to fill in the GOT entry. */
+ new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt,
+ ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
+ _dl_exit(1);
+ }
+
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\n\tpatched %x ==> %x @ %x\n",
+ *got_addr, new_addr, got_addr);
+ }
+ if (!_dl_debug_nofixups) {
+ *got_addr = new_addr;
+ }
+#else
+ *got_addr = new_addr;
+#endif
+
+ return new_addr;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
+ ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ Elf32_Sym *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Now parse the relocation information */
+ rpnt = (ELF_RELOC *)rel_addr;
+ rel_size = rel_size / sizeof(ELF_RELOC);
+
+ symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF32_R_SYM(rpnt->r_info);
+ debug_sym(symtab,strtab,symtab_index);
+ debug_reloc(symtab,strtab,rpnt);
+
+ res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
+
+ if (res==0) continue;
+
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
+
+ if (res <0) {
+ int reloc_type = ELF32_R_TYPE(rpnt->r_info);
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
+#else
+ _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
+#endif
+ _dl_exit(-res);
+ } else if (res >0) {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+ _dl_c6x_flush_relocs(tpnt->loadaddr.map);
+ return 0;
+}
+
+static int
+_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
+ ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+ unsigned long *reloc_addr;
+ unsigned long symbol_addr, sym_val;
+ long reloc_addend;
+ unsigned long old_val, new_val;
+
+ reloc_addr = (unsigned long *)(intptr_t)
+ DL_RELOC_ADDR (tpnt->loadaddr, rpnt->r_offset);
+
+ reloc_type = ELF32_R_TYPE(rpnt->r_info);
+ reloc_addend = rpnt->r_addend;
+ symtab_index = ELF32_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+ symname = strtab + symtab[symtab_index].st_name;
+
+ if (ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) {
+ symbol_addr = (unsigned long)
+ DL_RELOC_ADDR (tpnt->loadaddr, symtab[symtab_index].st_value);
+ } else {
+ symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
+ scope, tpnt, elf_machine_type_class(reloc_type),
+ NULL);
+ /*
+ * We want to allow undefined references to weak symbols - this might
+ * have been intentional. We should not be linking local symbols
+ * here, so all bases should be covered.
+ */
+
+ if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) {
+ _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, strtab + symtab[symtab_index].st_name);
+ _dl_exit (1);
+ }
+ }
+ old_val = *reloc_addr;
+ sym_val = symbol_addr + reloc_addend;
+
+ switch (reloc_type) {
+ case R_C6000_NONE:
+ break;
+ case R_C6000_ABS32:
+ case R_C6000_JUMP_SLOT:
+ new_val = sym_val;
+ *reloc_addr = sym_val;
+ break;
+ case R_C6000_ABS_L16:
+ new_val = (old_val & ~0x007fff80) | ((sym_val & 0xffff) << 7);
+ *reloc_addr = new_val;
+ break;
+ case R_C6000_ABS_H16:
+ new_val = (old_val & ~0x007fff80) | ((sym_val >> 9) & 0x007fff80);
+ *reloc_addr = new_val;
+ break;
+ case R_C6000_PCR_S21:
+ new_val = sym_val - (((unsigned long)reloc_addr) & ~31);
+ *reloc_addr = (old_val & ~0x0fffff80) | (((new_val >> 2) & 0x1fffff) << 7);
+ break;
+ case R_C6000_COPY:
+ if (symbol_addr) {
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_move)
+ _dl_dprintf(_dl_debug_file,
+ "\n%s move %d bytes from %x to %x",
+ symname, symtab[symtab_index].st_size,
+ symbol_addr, reloc_addr);
+#endif
+
+ _dl_memcpy((char *)reloc_addr,
+ (char *)symbol_addr,
+ symtab[symtab_index].st_size);
+ }
+ break;
+ default:
+ return -1; /*call _dl_exit(1) */
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail && reloc_type != R_C6000_NONE) {
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, new_val, reloc_addr);
+ }
+#endif
+ return 0;
+}
+
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt,
+ struct dyn_elf *scope attribute_unused,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab attribute_unused,
+ char *strtab attribute_unused)
+{
+ int reloc_type;
+ unsigned long *reloc_addr;
+ unsigned long old_val;
+
+ reloc_addr = (unsigned long *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+ old_val = *reloc_addr;
+
+ switch (reloc_type) {
+ case R_C6000_NONE:
+ break;
+ case R_C6000_JUMP_SLOT:
+ *reloc_addr = DL_RELOC_ADDR(tpnt->loadaddr, old_val);
+ break;
+ default:
+ return -1;
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+void
+_dl_parse_lazy_relocation_information
+(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size)
+{
+ _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information
+(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+}
+
+/* We don't have copy relocs. */
+int
+_dl_parse_copy_information
+(struct dyn_elf *rpnt,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ return 0;
+}
+
diff --git a/ldso/ldso/c6x/resolve.S b/ldso/ldso/c6x/resolve.S
new file mode 100644
index 000000000..ce3cbe793
--- /dev/null
+++ b/ldso/ldso/c6x/resolve.S
@@ -0,0 +1,68 @@
+;;
+;; Copyright (C) 2010 Texas Instruments Incorporated
+;; Mark Salter <msalter@redhat.com>
+;;
+;; Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+;;
+
+;; The function below is tail-called by resolver stubs when a
+;; lazily-bound function is called. It must preserve all
+;; registers that could be used to pass arguments to the actual
+;; function.
+
+;; _dl_linux_resolver() figures out where the jump symbol is
+;; _really_ supposed to have jumped to and returns that to us.
+;; Once we have that, we prepare to tail-call the actual
+;; function, clean up after ourselves, restoring the original
+;; arguments, then jump to the fixed up address. */
+
+; resolver stub - called from PLT to resolve target address and update GOT
+;
+; B0 : reloc offset (bytes from DT_RELPLT)
+; B1 : module pointer, loaded from GOT[1]
+; DP : caller's DP
+; A4,B4, etc: callee's arguments
+; B3 : return address
+
+ .text
+ .align 5
+ .global _dl_linux_resolve
+_dl_linux_resolve:
+ stw .d2t2 B14, *B15--[2]
+ stdw .d2t1 A15:A14, *B15--
+ stdw .d2t2 B13:B12, *B15--
+ stdw .d2t1 A13:A12, *B15--
+ stdw .d2t2 B11:B10, *B15--
+ stdw .d2t1 A11:A10, *B15--
+ stdw .d2t2 B9:B8, *B15--
+ stdw .d2t1 A9:A8, *B15--
+ stdw .d2t2 B7:B6, *B15--
+ stdw .d2t1 A7:A6, *B15--
+ stdw .d2t2 B5:B4, *B15--
+ stdw .d2t1 A5:A4, *B15--
+ stdw .d2t2 B3:B2, *B15--
+ stdw .d2t1 A3:A2, *B15--
+
+ ; call lookup routine
+ MV .S1X B1, A4 ; arg 1: module id
+|| MV .S2 B0,B4 ; arg 2: reloc offset
+ CALLP .S2 _dl_linux_resolver, B3 ; returns &f in A4
+ MV .S2X A4,B0 ; &f
+
+ lddw .d2t1 *++B15, A3:A2
+ lddw .d2t2 *++B15, B3:B2
+ lddw .d2t1 *++B15, A5:A4
+ lddw .d2t2 *++B15, B5:B4
+ lddw .d2t1 *++B15, A7:A6
+ lddw .d2t2 *++B15, B7:B6
+ lddw .d2t1 *++B15, A9:A8
+ lddw .d2t2 *++B15, B9:B8
+ lddw .d2t1 *++B15, A11:A10
+ lddw .d2t2 *++B15, B11:B10
+ lddw .d2t1 *++B15, A13:A12
+ lddw .d2t2 *++B15, B13:B12
+ lddw .d2t1 *++B15, A15:A14
+ ldw .d2t2 *++B15[2], B14
+
+ B .S2 B0 ; tail-call f
+ NOP 5
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index 5d49e073b..a881b7df7 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -188,7 +188,7 @@ unsigned long _dl_error_number;
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)
+ struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects)
{
char *pnt;
struct elf_resolve *tpnt1;
@@ -826,6 +826,54 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
INIT_GOT(lpnt, tpnt);
}
+#ifdef __DSBT__
+ /* Handle DSBT initialization */
+ {
+ struct elf_resolve *t, *ref = NULL;
+ int idx = tpnt->loadaddr.map->dsbt_index;
+ unsigned *dsbt = tpnt->loadaddr.map->dsbt_table;
+
+ if (idx == 0) {
+ /* This DSO has not been assigned an index */
+ _dl_dprintf(2, "%s: '%s' is missing a dsbt index assignment!\n",
+ _dl_progname, libname);
+ _dl_exit(1);
+ }
+
+ /*
+ * Setup dsbt slot for this module in dsbt of all modules.
+ */
+ for (t = _dl_loaded_modules; t; t = t->next) {
+ /* find a dsbt table from another module */
+ if (ref == NULL && t != tpnt) {
+ ref = t;
+
+ /* make sure index is not already used */
+ if (t->loadaddr.map->dsbt_table[idx]) {
+ struct elf_resolve *dup;
+ char *dup_name;
+
+ for (dup = _dl_loaded_modules; dup; dup = dup->next)
+ if (dup != tpnt && dup->loadaddr.map->dsbt_index == idx)
+ break;
+ if (dup)
+ dup_name = dup->libname;
+ else if (idx == 1)
+ dup_name = "runtime linker";
+ else
+ dup_name = "unknown library";
+ _dl_dprintf(2, "%s: '%s' dsbt index %d already used by %s!\n",
+ _dl_progname, libname, idx, dup_name);
+ _dl_exit(1);
+ }
+ }
+ t->loadaddr.map->dsbt_table[idx] = (unsigned)dsbt;
+ }
+ if (ref)
+ _dl_memcpy(dsbt, ref->loadaddr.map->dsbt_table,
+ tpnt->loadaddr.map->dsbt_size * sizeof(unsigned *));
+ }
+#endif
_dl_if_debug_dprint("\n\tfile='%s'; generating link map\n", libname);
_dl_if_debug_dprint("\t\tdynamic: %x base: %x\n", dynamic_addr, DL_LOADADDR_BASE(lib_loadaddr));
_dl_if_debug_dprint("\t\t entry: %x phdr: %x phnum: %x\n\n",
diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c
index 33c14402a..39c4e1d06 100644
--- a/ldso/ldso/i386/elfinterp.c
+++ b/ldso/ldso/i386/elfinterp.c
@@ -162,7 +162,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
int reloc_type;
int symtab_index;
char *symname;
- struct elf_resolve *tls_tpnt = 0;
+ struct elf_resolve *tls_tpnt = NULL;
unsigned long *reloc_addr;
unsigned long symbol_addr;
#if defined (__SUPPORT_LD_DEBUG__)
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index 2ff441194..775acdd15 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -119,15 +119,13 @@ extern void _start(void);
#ifdef __UCLIBC_HAS_SSP__
# include <dl-osinfo.h>
-uintptr_t stack_chk_guard;
+static uintptr_t stack_chk_guard;
# ifndef THREAD_SET_STACK_GUARD
/* Only exported for architectures that don't store the stack guard canary
* in local thread area. */
uintptr_t __stack_chk_guard attribute_relro;
-# ifdef __UCLIBC_HAS_SSP_COMPAT__
-strong_alias(__stack_chk_guard,__guard)
-# endif
-# elif __UCLIBC_HAS_SSP_COMPAT__
+# endif
+# ifdef __UCLIBC_HAS_SSP_COMPAT__
uintptr_t __guard attribute_relro;
# endif
#endif
@@ -1165,12 +1163,12 @@ of this helper program; chances are you did not intend to run this program.\n\
stack_chk_guard = _dl_setup_stack_chk_guard ();
# ifdef THREAD_SET_STACK_GUARD
THREAD_SET_STACK_GUARD (stack_chk_guard);
-# ifdef __UCLIBC_HAS_SSP_COMPAT__
- __guard = stack_chk_guard;
-# endif
# else
__stack_chk_guard = stack_chk_guard;
# endif
+# ifdef __UCLIBC_HAS_SSP_COMPAT__
+ __guard = stack_chk_guard;
+# endif
#endif
#ifdef __LDSO_PRELINK_SUPPORT__
diff --git a/ldso/ldso/sparc/elfinterp.c b/ldso/ldso/sparc/elfinterp.c
index 3c928073b..60a0161be 100644
--- a/ldso/ldso/sparc/elfinterp.c
+++ b/ldso/ldso/sparc/elfinterp.c
@@ -170,7 +170,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
int reloc_type;
int symtab_index;
char *symname;
- struct elf_resolve *tls_tpnt = 0;
+ struct elf_resolve *tls_tpnt = NULL;
struct symbol_ref sym_ref;
ElfW(Addr) *reloc_addr;
ElfW(Addr) symbol_addr;
diff --git a/ldso/ldso/x86_64/elfinterp.c b/ldso/ldso/x86_64/elfinterp.c
index a36b1154c..44e2c66d8 100644
--- a/ldso/ldso/x86_64/elfinterp.c
+++ b/ldso/ldso/x86_64/elfinterp.c
@@ -157,7 +157,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
int reloc_type;
int symtab_index;
char *symname;
- struct elf_resolve *tls_tpnt = 0;
+ struct elf_resolve *tls_tpnt = NULL;
struct symbol_ref sym_ref;
ElfW(Addr) *reloc_addr;
ElfW(Addr) symbol_addr;
diff --git a/ldso/libdl/Makefile.in b/ldso/libdl/Makefile.in
index 39db7a876..152185e37 100644
--- a/ldso/libdl/Makefile.in
+++ b/ldso/libdl/Makefile.in
@@ -19,6 +19,7 @@ endif
CFLAGS-libdl.c := -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\"
+LDFLAGS-$(UCLIBC_FORMAT_DSBT_ELF)-libdl.so := -Wl,--dsbt-index=3
LDFLAGS-libdl.so := $(LDFLAGS) -Wl,-fini,dl_cleanup
LIBS-libdl.so := $(LIBS) $(ldso)
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index 5007a7e65..83dfd0898 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -651,7 +651,6 @@ void *dlsym(void *vhandle, const char *name)
ElfW(Addr) from;
struct dyn_elf *rpnt;
void *ret;
- struct elf_resolve *tls_tpnt = NULL;
struct symbol_ref sym_ref = { NULL, NULL };
/* Nastiness to support underscore prefixes. */
#ifdef __UCLIBC_UNDERSCORES__
@@ -973,6 +972,10 @@ static int do_dlclose(void *vhandle, int need_fini)
free(tpnt);
}
}
+ for (rpnt1 = handle->next; rpnt1; rpnt1 = rpnt1_tmp) {
+ rpnt1_tmp = rpnt1->next;
+ free(rpnt1);
+ }
free(handle->init_fini.init_fini);
free(handle);