summaryrefslogtreecommitdiff
path: root/sysdeps/mips/dl-machine.h
diff options
context:
space:
mode:
authorAndreas Jaeger <aj@suse.de>2000-09-18 16:41:55 +0000
committerAndreas Jaeger <aj@suse.de>2000-09-18 16:41:55 +0000
commit65f1c9ef2e51197e27e4eeac08e256e969292950 (patch)
tree8d12ad63cb767d1130da84a65c03a056ea6aa8fd /sysdeps/mips/dl-machine.h
parent54419496e5313081733eef87aaa53f529ec1b225 (diff)
Update.
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.
Diffstat (limited to 'sysdeps/mips/dl-machine.h')
-rw-r--r--sysdeps/mips/dl-machine.h93
1 files changed, 80 insertions, 13 deletions
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))