summaryrefslogtreecommitdiff
path: root/sysdeps/powerpc/dl-machine.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/powerpc/dl-machine.h')
-rw-r--r--sysdeps/powerpc/dl-machine.h71
1 files changed, 60 insertions, 11 deletions
diff --git a/sysdeps/powerpc/dl-machine.h b/sysdeps/powerpc/dl-machine.h
index 771b711a14..70a3f20b31 100644
--- a/sysdeps/powerpc/dl-machine.h
+++ b/sysdeps/powerpc/dl-machine.h
@@ -199,6 +199,53 @@ _dl_runtime_resolve:
bctr
0:
.size _dl_runtime_resolve,0b-_dl_runtime_resolve
+
+ .align 2
+ .globl _dl_prof_resolve
+ .type _dl_prof_resolve,@function
+_dl_prof_resolve:
+ # We need to save the registers used to pass parameters, and register 0,
+ # which is used by _mcount; the registers are saved in a stack frame.
+ stwu 1,-48(1)
+ stw 0,12(1)
+ stw 3,16(1)
+ stw 4,20(1)
+ # The code that calls this has put parameters for `fixup' in r12 and r11.
+ mr 3,12
+ stw 5,24(1)
+ mr 4,11
+ stw 6,28(1)
+ mflr 5
+ # We also need to save some of the condition register fields.
+ stw 7,32(1)
+ stw 5,52(1)
+ stw 8,36(1)
+ mfcr 0
+ stw 9,40(1)
+ stw 10,44(1)
+ stw 0,8(1)
+ bl profile_fixup@local
+ # 'fixup' returns the address we want to branch to.
+ mtctr 3
+ # Put the registers back...
+ lwz 0,52(1)
+ lwz 10,44(1)
+ lwz 9,40(1)
+ mtlr 0
+ lwz 8,36(1)
+ lwz 0,8(1)
+ lwz 7,32(1)
+ lwz 6,28(1)
+ mtcrf 0xFF,0
+ lwz 5,24(1)
+ lwz 4,20(1)
+ lwz 3,16(1)
+ lwz 0,12(1)
+ # ...unwind the stack frame, and jump to the PLT entry we updated.
+ addi 1,1,48
+ bctr
+0:
+ .size _dl_prof_resolve,0b-_dl_prof_resolve
# Undo '.section text'.
.previous
");
@@ -409,8 +456,14 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
Elf32_Word num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
/ sizeof (Elf32_Rela));
Elf32_Word rel_offset_words = PLT_DATA_START_WORDS (num_plt_entries);
- extern void _dl_runtime_resolve (void);
Elf32_Word size_modified;
+ extern void _dl_runtime_resolve (void);
+ extern void _dl_prof_resolve (void);
+ Elf32_Word dlrr;
+
+ dlrr = (Elf32_Word)(char *)(profile
+ ? _dl_prof_resolve
+ : _dl_runtime_resolve);
if (lazy)
for (i = 0; i < num_plt_entries; i++)
@@ -433,8 +486,7 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
/* Multiply index of entry by 3 (in r11). */
plt[0] = OPCODE_SLWI (12, 11, 1);
plt[1] = OPCODE_ADD (11, 12, 11);
- if ((Elf32_Word) (char *) _dl_runtime_resolve <= 0x01fffffc ||
- (Elf32_Word) (char *) _dl_runtime_resolve >= 0xfe000000)
+ if (dlrr <= 0x01fffffc || dlrr >= 0xfe000000)
{
/* Load address of link map in r12. */
plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) map);
@@ -442,15 +494,13 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
+ 0x8000) >> 16));
/* Call _dl_runtime_resolve. */
- plt[4] = OPCODE_BA ((Elf32_Word) (char *) _dl_runtime_resolve);
+ plt[4] = OPCODE_BA (dlrr);
}
else
{
/* Get address of _dl_runtime_resolve in CTR. */
- plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) _dl_runtime_resolve);
- plt[3] = OPCODE_ADDIS (12, 12, ((((Elf32_Word) (char *)
- _dl_runtime_resolve)
- + 0x8000) >> 16));
+ plt[2] = OPCODE_LI (12, dlrr);
+ plt[3] = OPCODE_ADDIS (12, 12, (dlrr + 0x8000) >> 16);
plt[4] = OPCODE_MTCTR (12);
/* Load address of link map in r12. */
@@ -501,7 +551,6 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
static inline void
elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
{
- assert (ELF32_R_TYPE (reloc->r_info) == R_PPC_JMP_SLOT);
/* elf_machine_runtime_setup handles this. */
}
@@ -513,7 +562,7 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
LOADADDR is the load address of the object; INFO is an array indexed
by DT_* of the .dynamic section info. */
-static inline void
+static void
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version,
Elf32_Addr *const reloc_addr)
@@ -709,4 +758,4 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
#define ELF_MACHINE_NO_REL 1
-#endif
+#endif /* RESOLVE */