aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2012-03-21 05:15:44 +0100
committerPetr Machata <pmachata@redhat.com>2012-04-19 01:17:09 +0200
commit4e2073f64f9db2974d89064dcdc49b2ed7aa9006 (patch)
tree4a21c31fc15e222222a296e32e644c2b28363123 /sysdeps
parentb120fdfda45e49d082ab2aa5caadf030f50cb4ed (diff)
downloadltrace-4e2073f64f9db2974d89064dcdc49b2ed7aa9006.tar.gz
Support tracing PPC32 processes with both BSS and secure PLTs
- only entry breakpoint is realized at the beginning - when it's hit, it's deleted, and all enabled breakpoints are realized - all PLTs are LS_TOPLT_EXEC. The difference is in the way the PLT entry address is computed
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/linux-gnu/ppc/arch.h1
-rw-r--r--sysdeps/linux-gnu/ppc/plt.c31
2 files changed, 18 insertions, 14 deletions
diff --git a/sysdeps/linux-gnu/ppc/arch.h b/sysdeps/linux-gnu/ppc/arch.h
index 15673e0..609a6b9 100644
--- a/sysdeps/linux-gnu/ppc/arch.h
+++ b/sysdeps/linux-gnu/ppc/arch.h
@@ -29,5 +29,6 @@
struct arch_ltelf_data {
GElf_Addr ppcgot;
GElf_Addr plt_stub_vma;
+ int secure_plt;
};
#endif
diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
index 94a500b..a0701eb 100644
--- a/sysdeps/linux-gnu/ppc/plt.c
+++ b/sysdeps/linux-gnu/ppc/plt.c
@@ -12,7 +12,7 @@
#define PPC_PLT_STUB_SIZE 16
static inline int
-is_ppc64()
+host_powerpc64()
{
#ifdef __powerpc64__
return 1;
@@ -21,27 +21,29 @@ is_ppc64()
#endif
}
-static inline int
-is_ppc32()
-{
- return !is_ppc64();
-}
-
GElf_Addr
-arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
- if (lte->arch.plt_stub_vma != 0)
+arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
+{
+ if (lte->ehdr.e_machine == EM_PPC && lte->arch.secure_plt) {
+ assert(lte->arch.plt_stub_vma != 0);
return lte->arch.plt_stub_vma + PPC_PLT_STUB_SIZE * ndx;
- else
+
+ } else if (lte->ehdr.e_machine == EM_PPC) {
return rela->r_offset;
+
+ } else {
+ assert(lte->ehdr.e_machine == EM_PPC64);
+ fprintf(stderr, "PPC64\n");
+ abort();
+ return rela->r_offset;
+ }
}
int
arch_translate_address(struct Process *proc,
target_address_t addr, target_address_t *ret)
{
- if (is_ppc64() && proc->e_machine == EM_PPC64) {
- fprintf (stderr, "32-bit\n");
-
+ if (host_powerpc64() && proc->e_machine == EM_PPC64) {
long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
fprintf(stderr, "arch_translate_address %p->%#lx\n",
addr, l);
@@ -178,7 +180,8 @@ arch_elf_dynamic_tag(struct ltelf *lte, GElf_Dyn dyn)
int
arch_elf_init(struct ltelf *lte)
{
- if (lte->ehdr.e_machine == EM_PPC) {
+ lte->arch.secure_plt = !(lte->lte_flags & LTE_PLT_EXECUTABLE);
+ if (lte->ehdr.e_machine == EM_PPC && lte->arch.secure_plt) {
GElf_Addr glink_vma
= get_glink_vma(lte, lte->arch.ppcgot, lte->plt_data);