aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sysdeps/mips/dl-machine.h60
1 files changed, 35 insertions, 25 deletions
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index 2a19126208..c0ece38719 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -136,7 +136,11 @@ 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
+#define ELF_MIPS_GNU_GOT1_MASK 0x80000000
+
+/* GNU Binutils upto 2.10 produce a wrong relocations. Bit 30 of
+ got[1] marks good objects. */
+#define ELF_MIPS_GNU_GOT1_OK 0x00000001
/* We can't rely on elf_machine_got_rel because _dl_object_relocation_scope
fiddles with global data. */
@@ -149,6 +153,9 @@ do { \
\
got = (ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]); \
\
+ if ((got[1] & ELF_MIPS_GNU_GOT1_MASK) != 0) \
+ got[1] = (ElfW(Addr)) ELF_MIPS_GNU_GOT1_MASK \
+ | (got[1] & ELF_MIPS_GNU_GOT1_OK); \
\
if (__builtin_expect (map->l_addr == 0, 1)) \
goto done; \
@@ -212,8 +219,8 @@ elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc)
if ((g1 & ELF_MIPS_GNU_GOT1_MASK) != 0)
{
- struct link_map *l =
- (struct link_map *) (g1 & ~ELF_MIPS_GNU_GOT1_MASK);
+ struct link_map *l = (struct link_map *)
+ (g1 & ~(ELF_MIPS_GNU_GOT1_MASK|ELF_MIPS_GNU_GOT1_OK));
ElfW(Addr) base, limit;
const ElfW(Phdr) *p = l->l_phdr;
ElfW(Half) this, nent = l->l_phnum;
@@ -352,11 +359,12 @@ asm ("\n \
.type _dl_runtime_resolve,@function\n \
.ent _dl_runtime_resolve\n \
_dl_runtime_resolve:\n \
+ .frame $29, 40, $31\n \
.set noreorder\n \
- # Save GP.\n \
+ # Save GP.\n \
move $3, $28\n \
# Modify t9 ($25) so as to point .cpload instruction.\n \
- addu $25,8\n \
+ addu $25, 8\n \
# Compute GP.\n \
.cpload $25\n \
.set reorder\n \
@@ -366,24 +374,20 @@ _dl_runtime_resolve:\n \
subu $29, 40\n \
.cprestore 32\n \
sw $15, 36($29)\n \
- sw $4, 12($29)\n \
- sw $5, 16($29)\n \
- sw $6, 20($29)\n \
- sw $7, 24($29)\n \
- sw $16, 28($29)\n \
- move $16, $29\n \
+ sw $4, 16($29)\n \
+ sw $5, 20($29)\n \
+ sw $6, 24($29)\n \
+ sw $7, 28($29)\n \
move $4, $24\n \
move $5, $15\n \
move $6, $3\n \
move $7, $2\n \
jal __dl_runtime_resolve\n \
- move $29, $16\n \
lw $31, 36($29)\n \
- lw $4, 12($29)\n \
- lw $5, 16($29)\n \
- lw $6, 20($29)\n \
- lw $7, 24($29)\n \
- lw $16, 28($29)\n \
+ lw $4, 16($29)\n \
+ lw $5, 20($29)\n \
+ lw $6, 24($29)\n \
+ lw $7, 28($29)\n \
addu $29, 40\n \
move $25, $2\n \
jr $25\n \
@@ -580,15 +584,20 @@ elf_machine_got_rel (struct link_map *map, int lazy)
got = (ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]);
- /* 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 if needed. */
- if (__builtin_expect (map->l_addr != 0, 0))
+ /* The dynamic linker's local got entries have already been relocated. */
+ if (map != &_dl_rtld_map)
{
- while (i < n)
- got[i++] += map->l_addr;
+ /* 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;
+
+ /* Add the run-time display to all local got entries if needed. */
+ if (__builtin_expect (map->l_addr != 0, 0))
+ {
+ while (i < n)
+ got[i++] += map->l_addr;
+ }
}
/* Handle global got entries. */
@@ -661,7 +670,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
of got[1] of a gnu object is set to identify gnu objects.
Where we can store l for non gnu objects? XXX */
if ((got[1] & ELF_MIPS_GNU_GOT1_MASK) != 0)
- got[1] = (ElfW(Addr)) ((unsigned) l | ELF_MIPS_GNU_GOT1_MASK);
+ got[1] = (ElfW(Addr)) ((unsigned) l | ELF_MIPS_GNU_GOT1_MASK
+ | (got[1] & ELF_MIPS_GNU_GOT1_OK));
else
_dl_mips_gnu_objects = 0;
}