]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
* sysdeps/mips/dl-machine.h (_RTLD_PROLOGUE): Reformat. Declare
authorAndreas Jaeger <aj@suse.de>
Mon, 18 Sep 2000 16:40:35 +0000 (16:40 +0000)
committerAndreas Jaeger <aj@suse.de>
Mon, 18 Sep 2000 16:40:35 +0000 (16:40 +0000)
        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.

sysdeps/mips/dl-machine.h

index 0d2bf9d6b611dc12325b5192c82274e96ccc2375..6d9570542b98b5b1ae0426b139d402c029c5edc5 100644 (file)
 #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))