diff options
Diffstat (limited to 'ldso')
-rw-r--r-- | ldso/ldso/xtensa/dl-inlines.h | 1 | ||||
-rw-r--r-- | ldso/ldso/xtensa/dl-startup.h | 91 | ||||
-rw-r--r-- | ldso/ldso/xtensa/dl-sysdep.h | 66 | ||||
-rw-r--r-- | ldso/ldso/xtensa/dl-tlsdesc.S | 10 | ||||
-rw-r--r-- | ldso/ldso/xtensa/elfinterp.c | 114 |
5 files changed, 253 insertions, 29 deletions
diff --git a/ldso/ldso/xtensa/dl-inlines.h b/ldso/ldso/xtensa/dl-inlines.h new file mode 100644 index 000000000..8fdf6eb48 --- /dev/null +++ b/ldso/ldso/xtensa/dl-inlines.h @@ -0,0 +1 @@ +#include "../fdpic/dl-inlines.h" diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h index c9350c0f2..2a453752a 100644 --- a/ldso/ldso/xtensa/dl-startup.h +++ b/ldso/ldso/xtensa/dl-startup.h @@ -7,6 +7,68 @@ * Parts taken from glibc/sysdeps/xtensa/dl-machine.h. */ +#if defined(__FDPIC__) +__asm__ ( + " .text\n" + " .align 4\n" + " .literal_position\n" + " .global _start\n" + " .type _start, @function\n" + " .hidden _start\n" + "_start:\n" + " .begin no-transform\n" + " _call0 1f\n" + "2:\n" + " .end no-transform\n" + " .align 4\n" + "1:\n" +#if defined(__XTENSA_CALL0_ABI__) + " movi a15, 2b\n" + " sub a15, a0, a15\n" + + /* Save FDPIC pointers in callee-saved registers */ + " mov a12, a4\n" + " mov a13, a5\n" + " mov a14, a6\n" + + /* Call __self_reloc */ + " mov a2, a5\n" + " movi a3, __ROFIXUP_LIST__\n" + " add a3, a3, a15\n" + " movi a4, __ROFIXUP_END__\n" + " add a4, a4, a15\n" + " movi a0, __self_reloc\n" + " add a0, a0, a15\n" + " callx0 a0\n" + + /* call _dl_start */ + " mov a3, a12\n" + " mov a4, a13\n" + " mov a5, a14\n" + " mov a7, sp\n" + " addi sp, sp, -16\n" + " mov a6, sp\n" + " mov a11, a2\n" + /* a13, interpreter map is no longer needed, save interpreter GOT there */ + " mov a13, a2\n" + " movi a0, _dl_start\n" + " add a0, a0, a15\n" + " callx0 a0\n" + + /* call main */ + " l32i a0, sp, 0\n" + " l32i a11, sp, 4\n" + " addi sp, sp, 16\n" + " mov a4, a12\n" + " movi a5, _dl_fini@GOTOFFFUNCDESC\n" + " add a5, a5, a13\n" + " mov a6, a14\n" + " jx a0\n" +#else +#error Unsupported Xtensa ABI +#endif + ); +#else /* __FDPIC__ */ #ifndef L_rcrt1 __asm__ ( " .text\n" @@ -83,6 +145,7 @@ __asm__ ( " bnez a6, 3b\n" " j .Lfixup_stack_ret"); #endif +#endif /* __FDPIC__ */ /* Get a pointer to the argv value. */ #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) @@ -90,7 +153,7 @@ __asm__ ( /* Function calls are not safe until the GOT relocations have been done. */ #define NO_FUNCS_BEFORE_BOOTSTRAP -#if defined(__ARCH_USE_MMU__) +#if defined(__ARCH_USE_MMU__) && !defined(__FDPIC__) #define PERFORM_BOOTSTRAP_GOT(tpnt) \ do { \ xtensa_got_location *got_loc; \ @@ -128,3 +191,29 @@ do { \ } \ } while (0) #endif + +#ifdef __FDPIC__ +#undef DL_START +#define DL_START(X) \ +static void __attribute__ ((used)) \ +_dl_start (Elf32_Addr dl_boot_got_pointer, \ + struct elf32_fdpic_loadmap *dl_boot_progmap, \ + struct elf32_fdpic_loadmap *dl_boot_ldsomap, \ + Elf32_Dyn *dl_boot_ldso_dyn_pointer, \ + struct funcdesc_value *dl_main_funcdesc, \ + X) + +/* + * Transfer control to the user's application, once the dynamic loader + * is done. We return the address of the function's entry point to + * _dl_boot, see boot1_arch.h. + */ +#define START() do { \ + struct elf_resolve *exec_mod = _dl_loaded_modules; \ + dl_main_funcdesc->entry_point = _dl_elf_main; \ + while (exec_mod->libtype != elf_executable) \ + exec_mod = exec_mod->next; \ + dl_main_funcdesc->got_value = exec_mod->loadaddr.got_value; \ + return; \ +} while (0) +#endif /* __FDPIC__ */ diff --git a/ldso/ldso/xtensa/dl-sysdep.h b/ldso/ldso/xtensa/dl-sysdep.h index 6b908989a..5aa3e177f 100644 --- a/ldso/ldso/xtensa/dl-sysdep.h +++ b/ldso/ldso/xtensa/dl-sysdep.h @@ -26,6 +26,7 @@ in l_info array. */ #define DT_XTENSA(x) (DT_XTENSA_##x - DT_LOPROC + DT_NUM + OS_NUM) +#ifndef __FDPIC__ typedef struct xtensa_got_location_struct { Elf32_Off offset; Elf32_Word length; @@ -86,6 +87,7 @@ typedef struct xtensa_got_location_struct { else if (dpnt->d_tag == DT_XTENSA_GOT_LOC_SZ) \ dynamic[DT_XTENSA (GOT_LOC_SZ)] = dpnt->d_un.d_val; \ } while (0) +#endif /* Here we define the magic numbers that this dynamic loader should accept. */ #define MAGIC1 EM_XTENSA @@ -115,10 +117,41 @@ elf_machine_dynamic (void) return (Elf32_Addr) &_DYNAMIC; } +#ifdef __FDPIC__ + +#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \ +do \ +{ \ + (piclib) = 2; \ +} \ +while (0) + +/* We must force strings used early in the bootstrap into the data + segment. */ +#undef SEND_EARLY_STDERR +#define SEND_EARLY_STDERR(S) \ + do { /* FIXME: implement */; } while (0) + +#undef INIT_GOT +#include "../fdpic/dl-sysdep.h" +#undef INIT_GOT +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + (MODULE)->loadaddr.got_value = (GOT_BASE); \ + GOT_BASE[0] = ((unsigned long *)&_dl_linux_resolve)[0]; \ + GOT_BASE[1] = ((unsigned long *)&_dl_linux_resolve)[1]; \ + GOT_BASE[2] = (unsigned long) MODULE; \ +} + +#endif /* __FDPIC__ */ + /* Return the run-time load address of the shared object. */ static __always_inline Elf32_Addr elf_machine_load_address (void) { +#ifdef __FDPIC__ + return 0; +#else Elf32_Addr addr, tmp; /* At this point, the runtime linker is being bootstrapped and the GOT @@ -135,17 +168,48 @@ elf_machine_load_address (void) : "=a" (addr), "=a" (tmp)); return addr - 3; +#endif } +#ifdef __FDPIC__ + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + switch (ELF_R_TYPE((RELP)->r_info)){ \ + case R_XTENSA_SYM32: \ + *(REL) = (SYMBOL) + (RELP)->r_addend; \ + break; \ + case R_XTENSA_RELATIVE: \ + case R_XTENSA_NONE: \ + default: \ + break; \ + } + static __always_inline void -elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, +elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr, Elf32_Word relative_count) { Elf32_Rela *rpnt = (Elf32_Rela *) rel_addr; while (relative_count--) { + Elf32_Addr *const reloc_addr = (Elf32_Addr *) DL_RELOC_ADDR(load_off, rpnt->r_offset); + *reloc_addr = DL_RELOC_ADDR(load_off, *reloc_addr); + rpnt++; + } +} +#else +static __always_inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela *rpnt = (Elf32_Rela *) rel_addr; + while (relative_count--) + { Elf32_Addr *const reloc_addr = (Elf32_Addr *) (load_off + rpnt->r_offset); *reloc_addr += load_off + rpnt->r_addend; rpnt++; } } +#endif diff --git a/ldso/ldso/xtensa/dl-tlsdesc.S b/ldso/ldso/xtensa/dl-tlsdesc.S index 426f2180b..1a8eacff2 100644 --- a/ldso/ldso/xtensa/dl-tlsdesc.S +++ b/ldso/ldso/xtensa/dl-tlsdesc.S @@ -24,6 +24,9 @@ .text HIDDEN_ENTRY (_dl_tlsdesc_return) +#ifdef __FDPIC__ + l32i a2, a2, 4 +#endif rur.threadptr a3 add a2, a2, a3 abi_ret @@ -53,7 +56,9 @@ END (_dl_tlsdesc_return) */ HIDDEN_ENTRY (_dl_tlsdesc_dynamic) - +#ifdef __FDPIC__ + l32i a2, a2, 4 +#endif /* dtv_t *dtv = (dtv_t *)THREAD_DTV(); */ rur.threadptr a3 l32i a4, a3, 0 @@ -86,7 +91,8 @@ HIDDEN_ENTRY (_dl_tlsdesc_dynamic) #elif defined(__XTENSA_CALL0_ABI__) addi a1, a1, -16 s32i a0, a1, 0 - movi a0, __tls_get_addr + movi a0, JUMPTARGET(__tls_get_addr) + FDPIC_LOAD_JUMPTARGET(a0, a11, a0) callx0 a0 l32i a0, a1, 0 addi a1, a1, 16 diff --git a/ldso/ldso/xtensa/elfinterp.c b/ldso/ldso/xtensa/elfinterp.c index e38a02666..d97f23435 100644 --- a/ldso/ldso/xtensa/elfinterp.c +++ b/ldso/ldso/xtensa/elfinterp.c @@ -36,6 +36,13 @@ #include "tlsdeschtab.h" #endif +#ifdef __FDPIC__ +unsigned long +_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) +{ + return 0; +} +#else unsigned long _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) { @@ -83,7 +90,7 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) return (unsigned long) new_addr; } - +#endif static int _dl_parse (struct elf_resolve *tpnt, struct r_scope_elem *scope, @@ -145,8 +152,8 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, int reloc_type; int symtab_index; char *symname; -#if defined USE_TLS && USE_TLS - struct elf_resolve *tls_tpnt = NULL; +#if defined USE_TLS && USE_TLS || defined (__FDPIC__) + struct elf_resolve *def_mod = NULL; #endif struct symbol_ref sym_ref; ElfW(Addr) *reloc_addr; @@ -155,7 +162,7 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, ElfW(Addr) old_val; #endif - reloc_addr = (ElfW(Addr) *) (tpnt->loadaddr + rpnt->r_offset); + reloc_addr = (ElfW(Addr) *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset); reloc_type = ELF_R_TYPE (rpnt->r_info); symtab_index = ELF_R_SYM (rpnt->r_info); sym_ref.sym = &symtab[symtab_index]; @@ -164,9 +171,17 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, symname = strtab + sym_ref.sym->st_name; if (symtab_index) { - symbol_addr = (ElfW(Addr)) - _dl_find_hash (symname, scope, tpnt, - elf_machine_type_class (reloc_type), &sym_ref); + if (ELF_ST_BIND (sym_ref.sym->st_info) == STB_LOCAL) { + symbol_addr = (ElfW(Addr)) + DL_RELOC_ADDR(tpnt->loadaddr, + symtab[symtab_index].st_value); + sym_ref.tpnt = tpnt; + } else { + symbol_addr = (ElfW(Addr)) + _dl_find_hash (symname, scope, tpnt, + elf_machine_type_class (reloc_type), + &sym_ref); + } /* * We want to allow undefined references to weak symbols - this might @@ -182,13 +197,13 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, _dl_debug_lookup (symname, tpnt, &symtab[symtab_index], &sym_ref, elf_machine_type_class(reloc_type)); } -#if defined USE_TLS && USE_TLS - tls_tpnt = sym_ref.tpnt; +#if defined USE_TLS && USE_TLS || defined (__FDPIC__) + def_mod = sym_ref.tpnt; #endif } else { symbol_addr =symtab[symtab_index].st_value; -#if defined USE_TLS && USE_TLS - tls_tpnt = tpnt; +#if defined USE_TLS && USE_TLS || defined (__FDPIC__) + def_mod = tpnt; #endif } @@ -202,6 +217,7 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, case R_XTENSA_GLOB_DAT: case R_XTENSA_JMP_SLOT: + case R_XTENSA_SYM32: *reloc_addr = symbol_addr + rpnt->r_addend; break; @@ -219,19 +235,63 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, break; case R_XTENSA_RELATIVE: - *reloc_addr += tpnt->loadaddr + rpnt->r_addend; + *reloc_addr += DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_addend); break; +#ifdef __FDPIC__ + case R_XTENSA_FUNCDESC_VALUE: + { + struct funcdesc_value *dst = (struct funcdesc_value *) reloc_addr; + + dst->entry_point = (void *) (symbol_addr + rpnt->r_addend); + dst->got_value = def_mod->loadaddr.got_value; + } + break; + case R_XTENSA_FUNCDESC: + if (symbol_addr) + *reloc_addr = (unsigned long) + _dl_funcdesc_for((void *) (symbol_addr + rpnt->r_addend), + sym_ref.tpnt->loadaddr.got_value); + else + /* Relocation against an undefined weak symbol: + set funcdesc to zero. */ + *reloc_addr = 0; + break; + case R_XTENSA_TLS_TPOFF: + CHECK_STATIC_TLS((struct link_map *) def_mod); + *reloc_addr = symbol_addr + rpnt->r_addend + def_mod->l_tls_offset; + break; + case R_XTENSA_TLSDESC: + { + struct tlsdesc *td = (struct tlsdesc *) reloc_addr; +#ifndef SHARED + CHECK_STATIC_TLS((struct link_map *) def_mod); +#else + if (!TRY_STATIC_TLS ((struct link_map *) def_mod)) + { + td->entry = _dl_tlsdesc_dynamic; + td->argument = _dl_make_tlsdesc_dynamic((struct link_map *) def_mod, + symbol_addr + rpnt->r_addend); + } + else +#endif + { + td->entry = _dl_tlsdesc_return; + td->argument = (void *) (symbol_addr + rpnt->r_addend + def_mod->l_tls_offset); + } + } + break; +#else #if defined USE_TLS && USE_TLS case R_XTENSA_TLS_TPOFF: - CHECK_STATIC_TLS((struct link_map *) tls_tpnt); - *reloc_addr = symbol_addr + tls_tpnt->l_tls_offset + rpnt->r_addend; + CHECK_STATIC_TLS((struct link_map *) def_mod); + *reloc_addr = symbol_addr + rpnt->r_addend + def_mod->l_tls_offset; break; case R_XTENSA_TLSDESC_FN: #ifndef SHARED - CHECK_STATIC_TLS((struct link_map *) tls_tpnt); + CHECK_STATIC_TLS((struct link_map *) def_mod); #else - if (!TRY_STATIC_TLS ((struct link_map *) tls_tpnt)) + if (!TRY_STATIC_TLS ((struct link_map *) def_mod)) *reloc_addr = (ElfW(Addr)) _dl_tlsdesc_dynamic; else #endif @@ -239,25 +299,25 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, break; case R_XTENSA_TLSDESC_ARG: #ifndef SHARED - CHECK_STATIC_TLS((struct link_map *) tls_tpnt); + CHECK_STATIC_TLS((struct link_map *) def_mod); #else - if (!TRY_STATIC_TLS ((struct link_map *) tls_tpnt)) + if (!TRY_STATIC_TLS ((struct link_map *) def_mod)) *reloc_addr = (ElfW(Addr)) - _dl_make_tlsdesc_dynamic((struct link_map *) tls_tpnt, + _dl_make_tlsdesc_dynamic((struct link_map *) def_mod, symbol_addr + rpnt->r_addend); else #endif *reloc_addr = symbol_addr + rpnt->r_addend + - tls_tpnt->l_tls_offset; + def_mod->l_tls_offset; break; #endif - +#endif default: return -1; /* Calls _dl_exit(1). */ } #if defined (__SUPPORT_LD_DEBUG__) if (_dl_debug_reloc && _dl_debug_detail) - _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %p\n", old_val, *reloc_addr, reloc_addr); #endif @@ -275,7 +335,7 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, ElfW(Addr) old_val; #endif - reloc_addr = (ElfW(Addr) *) (tpnt->loadaddr + rpnt->r_offset); + reloc_addr = (ElfW(Addr) *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset); reloc_type = ELF_R_TYPE (rpnt->r_info); #if defined (__SUPPORT_LD_DEBUG__) @@ -286,7 +346,7 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, case R_XTENSA_JMP_SLOT: /* Perform a RELATIVE reloc on the GOT entry that transfers to the stub function. */ - *reloc_addr += tpnt->loadaddr; + *reloc_addr = DL_RELOC_ADDR(tpnt->loadaddr, *reloc_addr); break; case R_XTENSA_NONE: break; @@ -296,7 +356,7 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, #if defined (__SUPPORT_LD_DEBUG__) if (_dl_debug_reloc && _dl_debug_detail) - _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %p\n", old_val, *reloc_addr, reloc_addr); #endif return 0; @@ -320,3 +380,7 @@ _dl_parse_relocation_information (struct dyn_elf *rpnt, return _dl_parse (rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc); } + +#ifndef IS_IN_libdl +# include "../../libc/sysdeps/linux/xtensa/crtreloc.c" +#endif |