diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | sysdeps/mips/dl-machine.h | 93 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/kernel-features.h | 2 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/mips/Dist | 1 |
4 files changed, 99 insertions, 14 deletions
@@ -1,3 +1,20 @@ +2000-09-16 Ralf Baechle <ralf@gnu.org> + + * 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. + +2000-09-18 Andreas Jaeger <aj@suse.de> + + * sysdeps/unix/sysv/linux/kernel-features.h: Always define + __ASSUME_32BITUIDS for MIPS. + * sysdeps/unix/sysv/linux/mips/ipc_priv.h: New file. + * sysdeps/unix/sysv/linux/mips/Dist: Add ipc_priv.h. + 2000-09-17 H.J. Lu <hjl@gnu.org> * catgets/Makefile ($(objpfx)de/libc.cat): Use diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h index 0d2bf9d6b6..6d9570542b 100644 --- a/sysdeps/mips/dl-machine.h +++ b/sysdeps/mips/dl-machine.h @@ -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)) diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h index 48dc192568..9639be3fa1 100644 --- a/sysdeps/unix/sysv/linux/kernel-features.h +++ b/sysdeps/unix/sysv/linux/kernel-features.h @@ -112,7 +112,7 @@ /* Linux 2.3.39 introduced 32bit UID/GIDs. Some platforms had 32 bit type all along. */ -#if __LINUX_KERNEL_VERSION >= 131879 || defined __powerpc__ +#if __LINUX_KERNEL_VERSION >= 131879 || defined __powerpc__ || defined __mips__ # define __ASSUME_32BITUIDS 1 # ifdef __sparc__ # define __ASSUME_SETRESUID_SYSCALL 1 diff --git a/sysdeps/unix/sysv/linux/mips/Dist b/sysdeps/unix/sysv/linux/mips/Dist index d8943b6a10..a983244372 100644 --- a/sysdeps/unix/sysv/linux/mips/Dist +++ b/sysdeps/unix/sysv/linux/mips/Dist @@ -1,6 +1,7 @@ _test_and_set.c clone.S entry.h +ipc_priv.h kernel_sigaction.h kernel_stat.h kernel_termios.h |