* 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:
Andreas Jaeger 2000-09-18 16:40:35 +00:00
parent 56eb5d1432
commit 921bb2c300

View File

@ -37,13 +37,17 @@
#define OFFSET_GP_GOT 0x7ff0 #define OFFSET_GP_GOT 0x7ff0
#ifndef _RTLD_PROLOGUE #ifndef _RTLD_PROLOGUE
# define _RTLD_PROLOGUE(entry) "\n\t.globl " __STRING(entry) \ # define _RTLD_PROLOGUE(entry) \
"\n\t.ent " __STRING(entry) \ ".globl\t" __STRING(entry) "\n\t" \
"\n\t" __STRING(entry) ":\n\t" ".ent\t" __STRING(entry) "\n\t" \
".type\t" __STRING(entry) ", @function\n" \
__STRING(entry) ":\n\t"
#endif #endif
#ifndef _RTLD_EPILOGUE #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 #endif
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. /* 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. */ /* The MSB of got[1] of a gnu object is set to identify gnu objects. */
#define ELF_MIPS_GNU_GOT1_MASK 0x80000000 #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. */ /* Get link map for callers object containing STUB_PC. */
static inline struct link_map * static inline struct link_map *
elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc) 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 2) That under Linux the entry is named __start
and not just plain _start. */ and not just plain _start. */
#define RTLD_START asm ("\ #define RTLD_START asm (\
.text\n"\ ".text\n"\
_RTLD_PROLOGUE(ENTRY_POINT)\ _RTLD_PROLOGUE(ENTRY_POINT)\
" .globl _dl_start_user\n\ ".set noreorder\n\
.set noreorder\n\ .set noreorder\n\
bltzal $0, 0f\n\ bltzal $0, 0f\n\
nop\n\ nop\n\
@ -371,10 +429,19 @@ _RTLD_PROLOGUE(ENTRY_POINT)\
sw $4, -0x7ff0($28)\n\ sw $4, -0x7ff0($28)\n\
move $4, $29\n\ move $4, $29\n\
subu $29, 16\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\ addiu $29, 16\n\
# Get the value of label '_dl_start_user' in t9 ($25).\n\ # Get the value of label '_dl_start_user' in t9 ($25).\n\
la $25, _dl_start_user\n\ la $25, _dl_start_user\n\
.globl _dl_start_user\n\
_dl_start_user:\n\ _dl_start_user:\n\
.set noreorder\n\ .set noreorder\n\
.cpload $25\n\ .cpload $25\n\
@ -410,9 +477,9 @@ _dl_start_user:\n\
la $2, _dl_fini\n\ la $2, _dl_fini\n\
# Jump to the user entry point.\n\ # Jump to the user entry point.\n\
move $25, $17\n\ move $25, $17\n\
jr $25\n"\ jr $25\n\t"\
_RTLD_EPILOGUE(ENTRY_POINT)\ _RTLD_EPILOGUE(ENTRY_POINT)\
"\n.previous"\ ".previous"\
); );
/* The MIPS never uses Elfxx_Rela relocations. */ /* 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 /* got[0] is reserved. got[1] is also reserved for the dynamic object
generated by gnu ld. Skip these reserved entries from relocation. */ 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; n = map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;
/* Add the run-time display to all local got entries if needed. */ /* Add the run-time display to all local got entries if needed. */
if (__builtin_expect (map->l_addr != 0, 0)) if (__builtin_expect (map->l_addr != 0, 0))