summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ldso/ldso/mips/dl-sysdep.h18
-rw-r--r--ldso/ldso/mips/elfinterp.c155
-rw-r--r--ldso/ldso/mips/resolve.S51
-rw-r--r--libc/misc/time/time.c43
-rw-r--r--libc/string/generic/memchr.c4
-rw-r--r--libc/string/generic/mempcpy.c3
-rw-r--r--libc/string/sparc/sparc64/memchr.S2
-rw-r--r--libc/string/stpcpy.c2
-rw-r--r--test/regex/tst-regex2.c21
9 files changed, 200 insertions, 99 deletions
diff --git a/ldso/ldso/mips/dl-sysdep.h b/ldso/ldso/mips/dl-sysdep.h
index 728779250..8f303fba1 100644
--- a/ldso/ldso/mips/dl-sysdep.h
+++ b/ldso/ldso/mips/dl-sysdep.h
@@ -93,10 +93,11 @@ typedef struct
#include <link.h>
-#define ARCH_NUM 3
+#define ARCH_NUM 4
#define DT_MIPS_GOTSYM_IDX (DT_NUM + OS_NUM)
#define DT_MIPS_LOCAL_GOTNO_IDX (DT_NUM + OS_NUM +1)
#define DT_MIPS_SYMTABNO_IDX (DT_NUM + OS_NUM +2)
+#define DT_MIPS_PLTGOT_IDX (DT_NUM + OS_NUM +3)
#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \
do { \
@@ -106,6 +107,8 @@ else if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO) \
dynamic[DT_MIPS_LOCAL_GOTNO_IDX] = dpnt->d_un.d_val; \
else if (dpnt->d_tag == DT_MIPS_SYMTABNO) \
dynamic[DT_MIPS_SYMTABNO_IDX] = dpnt->d_un.d_val; \
+else if (dpnt->d_tag == DT_MIPS_PLTGOT) \
+ dynamic[DT_MIPS_PLTGOT_IDX] = dpnt->d_un.d_val; \
else if (dpnt->d_tag == DT_MIPS_RLD_MAP) \
*(ElfW(Addr) *)(dpnt->d_un.d_ptr) = (ElfW(Addr)) debug_addr; \
} while (0)
@@ -114,6 +117,7 @@ else if (dpnt->d_tag == DT_MIPS_RLD_MAP) \
#define INIT_GOT(GOT_BASE,MODULE) \
do { \
unsigned long idx; \
+ unsigned long *pltgot; \
\
/* Check if this is the dynamic linker itself */ \
if (MODULE->libtype == program_interpreter) \
@@ -123,6 +127,12 @@ do { \
GOT_BASE[0] = (unsigned long) _dl_runtime_resolve; \
GOT_BASE[1] = (unsigned long) MODULE; \
\
+ pltgot = MODULE->dynamic_info[DT_MIPS_PLTGOT_IDX]; \
+ if (pltgot) { \
+ pltgot[0] = (unsigned long) _dl_runtime_pltresolve; \
+ pltgot[1] = (unsigned long) MODULE; \
+ } \
+ \
/* Add load address displacement to all local GOT entries */ \
idx = 2; \
while (idx < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
@@ -151,9 +161,9 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy)
#define OFFS_ALIGN (0x10000000000UL-0x1000)
#endif /* O32 || N32 */
-#define elf_machine_type_class(type) ELF_RTYPE_CLASS_PLT
-/* MIPS does not have COPY relocs */
-#define DL_NO_COPY_RELOCS
+#define elf_machine_type_class(type) \
+ ((((type) == R_MIPS_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY))
#define OFFSET_GP_GOT 0x7ff0
diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c
index 893c94c25..0ed2757b5 100644
--- a/ldso/ldso/mips/elfinterp.c
+++ b/ldso/ldso/mips/elfinterp.c
@@ -30,6 +30,7 @@
#include "ldso.h"
extern int _dl_runtime_resolve(void);
+extern int _dl_runtime_pltresolve(void);
#define OFFSET_GP_GOT 0x7ff0
@@ -55,7 +56,7 @@ unsigned long __dl_runtime_resolve(unsigned long sym_index,
symname = strtab + sym->st_name;
new_addr = (unsigned long) _dl_find_hash(symname,
- tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
if (unlikely(!new_addr)) {
_dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
_dl_progname, symname);
@@ -83,6 +84,61 @@ unsigned long __dl_runtime_resolve(unsigned long sym_index,
return new_addr;
}
+unsigned long
+__dl_runtime_pltresolve(struct elf_resolve *tpnt, int reloc_entry)
+{
+ int reloc_type;
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ Elf32_Sym *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ unsigned long instr_addr;
+ char *symname;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+ this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+ reloc_type = ELF32_R_TYPE(this_reloc->r_info);
+ symtab_index = ELF32_R_SYM(this_reloc->r_info);
+
+ symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of the jump instruction to fix up. */
+ instr_addr = ((unsigned long)this_reloc->r_offset +
+ (unsigned long)tpnt->loadaddr);
+ got_addr = (char **)instr_addr;
+
+ /* Get the address of the GOT entry. */
+ new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if ((unsigned long)got_addr < 0x40000000) {
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\n\tpatched: %x ==> %x @ %x",
+ *got_addr, new_addr, got_addr);
+ }
+ }
+ if (!_dl_debug_nofixups) {
+ *got_addr = new_addr;
+ }
+#else
+ *got_addr = new_addr;
+#endif
+
+ return (unsigned long)new_addr;
+}
+
void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
unsigned long rel_addr, unsigned long rel_size)
{
@@ -115,6 +171,7 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
got = (unsigned long *) tpnt->dynamic_info[DT_PLTGOT];
for (i = 0; i < rel_size; i++, rpnt++) {
+ char *symname = NULL;
reloc_addr = (unsigned long *) (tpnt->loadaddr +
(unsigned long) rpnt->r_offset);
reloc_type = ELF_R_TYPE(rpnt->r_info);
@@ -128,62 +185,22 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
old_val = *reloc_addr;
#endif
- switch (reloc_type) {
-#if USE_TLS
-# if _MIPS_SIM == _ABI64
- case R_MIPS_TLS_DTPMOD64:
- case R_MIPS_TLS_DTPREL64:
- case R_MIPS_TLS_TPREL64:
-# else
- case R_MIPS_TLS_DTPMOD32:
- case R_MIPS_TLS_DTPREL32:
- case R_MIPS_TLS_TPREL32:
-# endif
- {
- ElfW(Sym) *sym_tls = &symtab[symtab_index];
- struct elf_resolve *tpnt_tls = tpnt;
-
- if (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_LOCAL) {
- _dl_find_hash((strtab + symtab[symtab_index].st_name),
- _dl_symbol_tables, tpnt_tls, 1, &sym_tls);
- }
-
- switch (reloc_type)
- {
- case R_MIPS_TLS_DTPMOD64:
- case R_MIPS_TLS_DTPMOD32:
- if (tpnt_tls)
- *(ElfW(Word) *)reloc_addr = tpnt_tls->l_tls_modid;
-#if defined (__SUPPORT_LD_DEBUG__)
-_dl_dprintf(2, "TLS_DTPMOD : %s, %d, %d\n", (strtab + symtab[symtab_index].st_name), old_val, *((unsigned int *)reloc_addr));
-#endif
- break;
-
- case R_MIPS_TLS_DTPREL64:
- case R_MIPS_TLS_DTPREL32:
- *(ElfW(Word) *)reloc_addr +=
- TLS_DTPREL_VALUE (sym_tls);
-#if defined (__SUPPORT_LD_DEBUG__)
-_dl_dprintf(2, "TLS_DTPREL : %s, %x, %x\n", (strtab + symtab[symtab_index].st_name), old_val, *((unsigned int *)reloc_addr));
-#endif
- break;
-
- case R_MIPS_TLS_TPREL32:
- case R_MIPS_TLS_TPREL64:
- CHECK_STATIC_TLS((struct link_map *)tpnt_tls);
- *(ElfW(Word) *)reloc_addr +=
- TLS_TPREL_VALUE (tpnt_tls, sym_tls);
-#if defined (__SUPPORT_LD_DEBUG__)
-_dl_dprintf(2, "TLS_TPREL : %s, %x, %x\n", (strtab + symtab[symtab_index].st_name), old_val, *((unsigned int *)reloc_addr));
-#endif
- break;
- }
-
- break;
- }
-#endif
+ if (reloc_type == R_MIPS_JUMP_SLOT || reloc_type == R_MIPS_COPY) {
+ symname = strtab + symtab[symtab_index].st_name;
+ symbol_addr = (unsigned long)_dl_find_hash(symname,
+ tpnt->symbol_scope,
+ tpnt,
+ elf_machine_type_class(reloc_type));
+ if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
+ return 1;
+ }
+ switch (reloc_type) {
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+ case (R_MIPS_64 << 8) | R_MIPS_REL32:
+#else /* O32 || N32 */
case R_MIPS_REL32:
+#endif /* O32 || N32 */
if (symtab_index) {
if (symtab_index < tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX])
*reloc_addr +=
@@ -198,6 +215,24 @@ _dl_dprintf(2, "TLS_TPREL : %s, %x, %x\n", (strtab + symtab[symtab_index].st_na
*reloc_addr += (unsigned long) tpnt->loadaddr;
}
break;
+ case R_MIPS_JUMP_SLOT:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_MIPS_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;
case R_MIPS_NONE:
break;
default:
@@ -208,9 +243,9 @@ _dl_dprintf(2, "TLS_TPREL : %s, %x, %x\n", (strtab + symtab[symtab_index].st_na
_dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
#if defined (__SUPPORT_LD_DEBUG__)
- _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", _dl_reltypes(reloc_type), tpnt->libname);
+ _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
#else
- _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", reloc_type, tpnt->libname);
+ _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
#endif
_dl_exit(1);
}
@@ -259,12 +294,12 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy)
}
else {
*got_entry = (unsigned long) _dl_find_hash(strtab +
- sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
}
}
else if (sym->st_shndx == SHN_COMMON) {
*got_entry = (unsigned long) _dl_find_hash(strtab +
- sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
}
else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
*got_entry != sym->st_value && tmp_lazy) {
@@ -276,7 +311,7 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy)
}
else {
*got_entry = (unsigned long) _dl_find_hash(strtab +
- sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
}
got_entry++;
diff --git a/ldso/ldso/mips/resolve.S b/ldso/ldso/mips/resolve.S
index f5d988a80..d7951a1b4 100644
--- a/ldso/ldso/mips/resolve.S
+++ b/ldso/ldso/mips/resolve.S
@@ -112,3 +112,54 @@ _dl_runtime_resolve:
.end _dl_runtime_resolve
.previous
+/* Assembler veneer called from the PLT header code when using the
+ non-PIC ABI.
+
+ Code in each PLT entry puts the caller's return address into t7 ($15),
+ the PLT entry index into t8 ($24), the address of _dl_runtime_pltresolve
+ into t9 ($25) and the address of .got.plt into gp ($28). __dl_runtime_pltresolve
+ needs a0 ($4) to hold the link map and a1 ($5) to hold the index into
+ .rel.plt (== PLT entry index * 4). */
+
+ .text
+ .align 2
+ .globl _dl_runtime_pltresolve
+ .type _dl_runtime_pltresolve,@function
+ .ent _dl_runtime_pltresolve
+_dl_runtime_pltresolve:
+ .frame $29, 40, $31
+ .set noreorder
+ # Save arguments and sp value in stack.
+ subu $29, 40
+ lw $10, 4($28)
+ # Modify t9 ($25) so as to point .cpload instruction.
+ addiu $25, 12
+ # Compute GP.
+ .cpload $25
+ .set reorder
+
+ /* 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_pltresolve. */
+ move $4, $10
+ sll $5, $24, 3
+ jal __dl_runtime_pltresolve
+
+ /* 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)
+
+ /* Do a tail call to the original function */
+ addiu $29, 40
+ move $25, $2
+ jr $25
+ .end _dl_runtime_pltresolve
+ .previous
diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c
index ae800e1ca..45ec131b7 100644
--- a/libc/misc/time/time.c
+++ b/libc/misc/time/time.c
@@ -618,43 +618,48 @@ libc_hidden_def(localtime_r)
#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
-/* Experimentally off - libc_hidden_proto(strnlen) */
-
struct ll_tzname_item;
typedef struct ll_tzname_item {
struct ll_tzname_item *next;
- char tzname[TZNAME_MAX+1];
+ char tzname[1];
} ll_tzname_item_t;
-static ll_tzname_item_t ll_tzname[] = {
- { ll_tzname + 1, "UTC" }, /* Always 1st. */
- { NULL, "???" } /* Always 2nd. (invalid or out-of-memory) */
-};
+/* Structures form a list "UTC" -> "???" -> "tzname1" -> "tzname2"... */
+struct {
+ struct ll_tzname_item *next;
+ char tzname[4];
+} ll_tzname_UNKNOWN = { NULL, "???" };
+const struct {
+ struct ll_tzname_item *next;
+ char tzname[4];
+} ll_tzname_UTC = { (void*)&ll_tzname_UNKNOWN, "UTC" };
static const char *lookup_tzname(const char *key)
{
- ll_tzname_item_t *p;
+ int len;
+ ll_tzname_item_t *p = (void*) &ll_tzname_UTC;
- for (p=ll_tzname ; p ; p=p->next) {
- if (!strcmp(p->tzname, key)) {
+ do {
+ if (strcmp(p->tzname, key) == 0)
return p->tzname;
- }
- }
+ p = p->next;
+ } while (p != NULL);
/* Hmm... a new name. */
- if (strnlen(key, TZNAME_MAX+1) < TZNAME_MAX+1) { /* Verify legal length */
- if ((p = malloc(sizeof(ll_tzname_item_t))) != NULL) {
+ len = strnlen(key, TZNAME_MAX+1);
+ if (len < TZNAME_MAX+1) { /* Verify legal length */
+ p = malloc(sizeof(ll_tzname_item_t) + len);
+ if (p != NULL) {
/* Insert as 3rd item in the list. */
- p->next = ll_tzname[1].next;
- ll_tzname[1].next = p;
- strcpy(p->tzname, key);
- return p->tzname;
+ p->next = ll_tzname_UNKNOWN.next;
+ ll_tzname_UNKNOWN.next = p;
+ return strcpy(p->tzname, key);
}
}
/* Either invalid or couldn't alloc. */
- return ll_tzname[1].tzname;
+ return ll_tzname_UNKNOWN.tzname;
}
#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */
diff --git a/libc/string/generic/memchr.c b/libc/string/generic/memchr.c
index 8ea3f539a..d5cd0005e 100644
--- a/libc/string/generic/memchr.c
+++ b/libc/string/generic/memchr.c
@@ -25,14 +25,12 @@
#include <stdlib.h>
#include <limits.h>
-/* Experimentally off - libc_hidden_proto(memchr) */
-/* libc_hidden_proto(abort) */
-
#include "memcopy.h"
#define LONG_MAX_32_BITS 2147483647
/* Search no more than N bytes of S for C. */
+#undef memchr
void *memchr (const void * s, int c_in, size_t n)
{
const unsigned char *char_ptr;
diff --git a/libc/string/generic/mempcpy.c b/libc/string/generic/mempcpy.c
index 0fcdb665c..d7fa79ef5 100644
--- a/libc/string/generic/mempcpy.c
+++ b/libc/string/generic/mempcpy.c
@@ -9,12 +9,11 @@
#ifdef __USE_GNU
-#undef mempcpy
+# undef mempcpy
void *mempcpy (void *dstpp, const void *srcpp, size_t len)
{
memcpy(dstpp, srcpp, len);
return (void *)(((char *)dstpp) + len);
}
libc_hidden_weak(mempcpy)
-
#endif
diff --git a/libc/string/sparc/sparc64/memchr.S b/libc/string/sparc/sparc64/memchr.S
index 6096cc218..f44850b08 100644
--- a/libc/string/sparc/sparc64/memchr.S
+++ b/libc/string/sparc/sparc64/memchr.S
@@ -256,6 +256,4 @@ ENTRY(memchr)
END(memchr)
libc_hidden_def(memchr)
-#if !__BOUNDED_POINTERS__
weak_alias(memchr,__ubp_memchr)
-#endif
diff --git a/libc/string/stpcpy.c b/libc/string/stpcpy.c
index 8a487584e..58ace8fc7 100644
--- a/libc/string/stpcpy.c
+++ b/libc/string/stpcpy.c
@@ -10,7 +10,7 @@
#ifdef WANT_WIDE
# define Wstpcpy wcpcpy
#else
-/* Experimentally off - libc_hidden_proto(stpcpy) */
+# undef stpcpy
# define Wstpcpy stpcpy
#endif
diff --git a/test/regex/tst-regex2.c b/test/regex/tst-regex2.c
index 94be59d85..1cf3e1d09 100644
--- a/test/regex/tst-regex2.c
+++ b/test/regex/tst-regex2.c
@@ -1,3 +1,5 @@
+#define _GNU_SOURCE 1
+
#include <fcntl.h>
#include <locale.h>
#include <regex.h>
@@ -42,8 +44,8 @@ do_test (void)
return 1;
}
- struct stat64 st;
- if (fstat64 (fd, &st) < 0)
+ struct stat st;
+ if (fstat (fd, &st) < 0)
{
printf ("Couldn't fstat ChangeLog.14: %s\n", strerror(errno));
return 1;
@@ -71,9 +73,10 @@ do_test (void)
char *string = buf;
size_t len = st.st_size;
+ int testno, i;
- for (int testno = 0; testno < 4; ++testno)
- for (int i = 0; i < sizeof (pat) / sizeof (pat[0]); ++i)
+ for (testno = 0; testno < 4; ++testno)
+ for (i = 0; i < sizeof (pat) / sizeof (pat[0]); ++i)
{
printf ("test %d pattern %d", testno, i);
@@ -142,9 +145,10 @@ do_test (void)
return 1;
}
+ int j, k, l;
if (i > 0)
- for (int j = 0, l = 1; j < 7; ++j)
- for (int k = 0; k < (i == 1 ? 1 : 10); ++k, ++l)
+ for (j = 0, l = 1; j < 7; ++j)
+ for (k = 0; k < (i == 1 ? 1 : 10); ++k, ++l)
if (pmatch[l].rm_so != pmatch[0].rm_so + j
|| pmatch[l].rm_eo != pmatch[l].rm_so + 1)
{
@@ -199,9 +203,10 @@ do_test (void)
return 1;
}
+ int j, k, l;
if (i > 0)
- for (int j = 0, l = 1; j < 7; ++j)
- for (int k = 0; k < (i == 1 ? 1 : 10); ++k, ++l)
+ for (j = 0, l = 1; j < 7; ++j)
+ for (k = 0; k < (i == 1 ? 1 : 10); ++k, ++l)
if (regs.start[l] != match + j
|| regs.end[l] != regs.start[l] + 1)
{