* sysdeps/mips/dl-machine.h (_RTLD_PROLOGUE): Reformat. Declare
as function. (_RTLD_EPILOGUE): Reformat. Declare size of entry function. (ELF_MACHINE_BEFORE_RTLD_RELOC): Relocate the dynamic linker itself so it will even work when not loaded to the standard address. (RTLD_START): Reformat. Call _dl_start in a way that is safe even before the dynamic linker itself is relocated.
This commit is contained in:
parent
56eb5d1432
commit
921bb2c300
|
@ -37,13 +37,17 @@
|
|||
#define OFFSET_GP_GOT 0x7ff0
|
||||
|
||||
#ifndef _RTLD_PROLOGUE
|
||||
# define _RTLD_PROLOGUE(entry) "\n\t.globl " __STRING(entry) \
|
||||
"\n\t.ent " __STRING(entry) \
|
||||
"\n\t" __STRING(entry) ":\n\t"
|
||||
# define _RTLD_PROLOGUE(entry) \
|
||||
".globl\t" __STRING(entry) "\n\t" \
|
||||
".ent\t" __STRING(entry) "\n\t" \
|
||||
".type\t" __STRING(entry) ", @function\n" \
|
||||
__STRING(entry) ":\n\t"
|
||||
#endif
|
||||
|
||||
#ifndef _RTLD_EPILOGUE
|
||||
# define _RTLD_EPILOGUE(entry) "\t.end " __STRING(entry) "\n"
|
||||
# define _RTLD_EPILOGUE(entry) \
|
||||
".end\t" __STRING(entry) "\n\t" \
|
||||
".size\t" __STRING(entry) ", . - " __STRING(entry) "\n\t"
|
||||
#endif
|
||||
|
||||
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.
|
||||
|
@ -134,6 +138,60 @@ elf_machine_load_address (void)
|
|||
/* The MSB of got[1] of a gnu object is set to identify gnu objects. */
|
||||
#define ELF_MIPS_GNU_GOT1_MASK 0x80000000
|
||||
|
||||
/* We can't rely on elf_machine_got_rel because _dl_object_relocation_scope
|
||||
fiddles with global data. */
|
||||
#define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) \
|
||||
do { \
|
||||
struct link_map *map = &bootstrap_map; \
|
||||
ElfW(Sym) *sym; \
|
||||
ElfW(Addr) *got; \
|
||||
int i, n; \
|
||||
\
|
||||
got = (ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]); \
|
||||
\
|
||||
\
|
||||
if (__builtin_expect (map->l_addr == 0, 1)) \
|
||||
goto done; \
|
||||
\
|
||||
/* got[0] is reserved. got[1] is also reserved for the dynamic object \
|
||||
generated by gnu ld. Skip these reserved entries from \
|
||||
relocation. */ \
|
||||
i = (got[1] & ELF_MIPS_GNU_GOT1_MASK)? 2 : 1; \
|
||||
n = map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val; \
|
||||
\
|
||||
/* Add the run-time display to all local got entries. */ \
|
||||
while (i < n) \
|
||||
got[i++] += map->l_addr; \
|
||||
\
|
||||
/* Handle global got entries. */ \
|
||||
got += n; \
|
||||
sym = (ElfW(Sym) *) D_PTR(map, l_info[DT_SYMTAB]) \
|
||||
+ map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val; \
|
||||
i = (map->l_info[DT_MIPS (SYMTABNO)]->d_un.d_val \
|
||||
- map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val); \
|
||||
\
|
||||
while (i--) \
|
||||
{ \
|
||||
if (sym->st_shndx == SHN_UNDEF || sym->st_shndx == SHN_COMMON) \
|
||||
*got = map->l_addr + sym->st_value; \
|
||||
else if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC \
|
||||
&& *got != sym->st_value) \
|
||||
*got += map->l_addr; \
|
||||
else if (ELFW(ST_TYPE) (sym->st_info) == STT_SECTION) \
|
||||
{ \
|
||||
if (sym->st_other == 0) \
|
||||
*got += map->l_addr; \
|
||||
} \
|
||||
else \
|
||||
*got = map->l_addr + sym->st_value; \
|
||||
\
|
||||
got++; \
|
||||
sym++; \
|
||||
} \
|
||||
done: \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* Get link map for callers object containing STUB_PC. */
|
||||
static inline struct link_map *
|
||||
elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc)
|
||||
|
@ -354,10 +412,10 @@ _dl_runtime_resolve:\n \
|
|||
2) That under Linux the entry is named __start
|
||||
and not just plain _start. */
|
||||
|
||||
#define RTLD_START asm ("\
|
||||
.text\n"\
|
||||
_RTLD_PROLOGUE(ENTRY_POINT)\
|
||||
" .globl _dl_start_user\n\
|
||||
#define RTLD_START asm (\
|
||||
".text\n"\
|
||||
_RTLD_PROLOGUE(ENTRY_POINT)\
|
||||
".set noreorder\n\
|
||||
.set noreorder\n\
|
||||
bltzal $0, 0f\n\
|
||||
nop\n\
|
||||
|
@ -371,10 +429,19 @@ _RTLD_PROLOGUE(ENTRY_POINT)\
|
|||
sw $4, -0x7ff0($28)\n\
|
||||
move $4, $29\n\
|
||||
subu $29, 16\n\
|
||||
jal _dl_start\n\
|
||||
\n\
|
||||
la $8, coff\n\
|
||||
bltzal $8, coff\n\
|
||||
coff: subu $8, $31, $8\n\
|
||||
\n\
|
||||
la $25, _dl_start\n\
|
||||
addu $25, $8\n\
|
||||
jalr $25\n\
|
||||
\n\
|
||||
addiu $29, 16\n\
|
||||
# Get the value of label '_dl_start_user' in t9 ($25).\n\
|
||||
la $25, _dl_start_user\n\
|
||||
.globl _dl_start_user\n\
|
||||
_dl_start_user:\n\
|
||||
.set noreorder\n\
|
||||
.cpload $25\n\
|
||||
|
@ -410,9 +477,9 @@ _dl_start_user:\n\
|
|||
la $2, _dl_fini\n\
|
||||
# Jump to the user entry point.\n\
|
||||
move $25, $17\n\
|
||||
jr $25\n"\
|
||||
_RTLD_EPILOGUE(ENTRY_POINT)\
|
||||
"\n.previous"\
|
||||
jr $25\n\t"\
|
||||
_RTLD_EPILOGUE(ENTRY_POINT)\
|
||||
".previous"\
|
||||
);
|
||||
|
||||
/* The MIPS never uses Elfxx_Rela relocations. */
|
||||
|
@ -513,7 +580,7 @@ elf_machine_got_rel (struct link_map *map, int lazy)
|
|||
|
||||
/* got[0] is reserved. got[1] is also reserved for the dynamic object
|
||||
generated by gnu ld. Skip these reserved entries from relocation. */
|
||||
i = (got[1] & ELF_MIPS_GNU_GOT1_MASK)? 2: 1;
|
||||
i = (got[1] & ELF_MIPS_GNU_GOT1_MASK)? 2 : 1;
|
||||
n = map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;
|
||||
/* Add the run-time display to all local got entries if needed. */
|
||||
if (__builtin_expect (map->l_addr != 0, 0))
|
||||
|
|
Loading…
Reference in New Issue