diff options
-rw-r--r-- | ldso/ldso/mips/dl-sysdep.h | 18 | ||||
-rw-r--r-- | ldso/ldso/mips/elfinterp.c | 155 | ||||
-rw-r--r-- | ldso/ldso/mips/resolve.S | 51 | ||||
-rw-r--r-- | libc/misc/time/time.c | 43 | ||||
-rw-r--r-- | libc/string/generic/memchr.c | 4 | ||||
-rw-r--r-- | libc/string/generic/mempcpy.c | 3 | ||||
-rw-r--r-- | libc/string/sparc/sparc64/memchr.S | 2 | ||||
-rw-r--r-- | libc/string/stpcpy.c | 2 | ||||
-rw-r--r-- | test/regex/tst-regex2.c | 21 |
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) { |