aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/linux-gnu/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/linux-gnu/ppc')
-rw-r--r--sysdeps/linux-gnu/ppc/arch.h12
-rw-r--r--sysdeps/linux-gnu/ppc/plt.c38
-rw-r--r--sysdeps/linux-gnu/ppc/regs.c24
-rw-r--r--sysdeps/linux-gnu/ppc/syscallent.h9
-rw-r--r--sysdeps/linux-gnu/ppc/trace.c44
5 files changed, 93 insertions, 34 deletions
diff --git a/sysdeps/linux-gnu/ppc/arch.h b/sysdeps/linux-gnu/ppc/arch.h
index e04e885..37634bf 100644
--- a/sysdeps/linux-gnu/ppc/arch.h
+++ b/sysdeps/linux-gnu/ppc/arch.h
@@ -1,6 +1,18 @@
#define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
#define BREAKPOINT_LENGTH 4
#define DECR_PC_AFTER_BREAK 0
+#define E_ENTRY_NAME "_start"
#define LT_ELFCLASS ELFCLASS32
#define LT_ELF_MACHINE EM_PPC
+#ifdef __powerpc64__
+#define LT_ELFCLASS2 ELFCLASS64
+#define LT_ELF_MACHINE2 EM_PPC64
+
+#define PLTs_INIT_BY_HERE E_ENTRY_NAME
+
+#else
+
+#define PLTs_INIT_BY_HERE NULL
+
+#endif
diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
index 19991b5..c85ea92 100644
--- a/sysdeps/linux-gnu/ppc/plt.c
+++ b/sysdeps/linux-gnu/ppc/plt.c
@@ -1,8 +1,42 @@
#include <gelf.h>
#include "ltrace.h"
#include "elf.h"
+#include "debug.h"
+#include "ptrace.h"
+#include "options.h"
-GElf_Addr arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela)
+GElf_Addr
+arch_plt_sym_val (struct ltelf *lte, size_t ndx, GElf_Rela *rela)
{
- return rela->r_offset;
+ return rela->r_offset;
}
+
+void * plt2addr(struct process *proc, void ** plt)
+{
+ long addr;
+
+ debug(3, 0);
+
+ if (proc->e_machine == EM_PPC || plt == 0)
+ return (void *)plt;
+
+ if (proc->pid == 0)
+ return (void *)0;
+
+ // On a PowerPC-64 system, a plt is three 64-bit words: the first is the
+ // 64-bit address of the routine. Before the PLT has been initialized, this
+ // will be 0x0. In fact, the symbol table won't have the plt's address even.
+ // Ater the PLT has been initialized, but before it has been resolved, the
+ // first word will be the address of the function in the dynamic linker that
+ // will reslove the PLT. After the PLT is resolved, this will will be the
+ // address of the routine whose symbol is in the symbol table.
+
+ addr = ptrace(PTRACE_PEEKTEXT, proc->pid, plt);
+
+ if (opt_d >= 3) {
+ xinfdump(proc->pid, plt, sizeof(void*)*3);
+ }
+
+ return (void *)addr;
+}
+
diff --git a/sysdeps/linux-gnu/ppc/regs.c b/sysdeps/linux-gnu/ppc/regs.c
index d0d51e3..a14e8d6 100644
--- a/sysdeps/linux-gnu/ppc/regs.c
+++ b/sysdeps/linux-gnu/ppc/regs.c
@@ -16,22 +16,22 @@
# define PTRACE_POKEUSER PTRACE_POKEUSR
#endif
-void *get_instruction_pointer(struct process *proc)
-{
- return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_NIP, 0);
+void *
+get_instruction_pointer(struct process * proc) {
+ return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long)*PT_NIP, 0);
}
-void set_instruction_pointer(struct process *proc, void *addr)
-{
- ptrace(PTRACE_POKEUSER, proc->pid, 4 * PT_NIP, addr);
+void
+set_instruction_pointer(struct process * proc, void * addr) {
+ ptrace(PTRACE_POKEUSER, proc->pid, sizeof(long)*PT_NIP, addr);
}
-void *get_stack_pointer(struct process *proc)
-{
- return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_R1, 0);
+void *
+get_stack_pointer(struct process * proc) {
+ return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long)*PT_R1, 0);
}
-void *get_return_addr(struct process *proc, void *stack_pointer)
-{
- return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_LNK, 0);
+void *
+get_return_addr(struct process * proc, void * stack_pointer) {
+ return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long)*PT_LNK, 0);
}
diff --git a/sysdeps/linux-gnu/ppc/syscallent.h b/sysdeps/linux-gnu/ppc/syscallent.h
index 2bbba38..205fc4a 100644
--- a/sysdeps/linux-gnu/ppc/syscallent.h
+++ b/sysdeps/linux-gnu/ppc/syscallent.h
@@ -261,3 +261,12 @@
"mq_notify", /* 266 */
"mq_getsetattr", /* 267 */
"kexec_load", /* 268 */
+ "add_key", /* 269 */
+ "request_key", /* 270 */
+ "keyctl", /* 271 */
+ "waitid", /* 272 */
+ "ioprio_set", /* 273 */
+ "ioprio_get", /* 274 */
+ "inotify_init", /* 275 */
+ "inotify_add_watch", /* 276 */
+ "inotify_rm_watch", /* 277 */
diff --git a/sysdeps/linux-gnu/ppc/trace.c b/sysdeps/linux-gnu/ppc/trace.c
index 6670be1..f31fb35 100644
--- a/sysdeps/linux-gnu/ppc/trace.c
+++ b/sysdeps/linux-gnu/ppc/trace.c
@@ -7,6 +7,7 @@
#include <signal.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>
+#include <elf.h>
#include "ltrace.h"
@@ -20,23 +21,28 @@
void get_arch_dep(struct process *proc)
{
+#ifdef __powerpc64__
+ if (proc->arch_ptr)
+ return;
+ proc->mask_32bit = (proc->e_machine == EM_PPC);
+ proc->arch_ptr = (void *) 1;
+#endif
}
+
/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
*/
#define SYSCALL_INSN 0x44000002
-int syscall_p(struct process *proc, int status, int *sysnum)
-{
- if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
- int pc = ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_NIP, 0);
- int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0);
+int
+syscall_p(struct process * proc, int status, int * sysnum) {
+ if (WIFSTOPPED(status) && WSTOPSIG(status)==(SIGTRAP | proc->tracesysgood)) {
+ long pc = (long)get_instruction_pointer(proc);
+ int insn = (int)ptrace(PTRACE_PEEKTEXT, proc->pid, pc-sizeof(long), 0);
if (insn == SYSCALL_INSN) {
- *sysnum =
- ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_R0, 0);
- if (proc->callstack_depth > 0
- && proc->callstack[proc->callstack_depth -
- 1].is_syscall) {
+ *sysnum = (int)ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long)*PT_R0, 0);
+ if (proc->callstack_depth > 0 &&
+ proc->callstack[proc->callstack_depth-1].is_syscall) {
return 2;
}
return 1;
@@ -45,20 +51,18 @@ int syscall_p(struct process *proc, int status, int *sysnum)
return 0;
}
-long gimme_arg(enum tof type, struct process *proc, int arg_num)
-{
- if (arg_num == -1) { /* return value */
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_R3, 0);
+long
+gimme_arg(enum tof type, struct process * proc, int arg_num) {
+ if (arg_num==-1) { /* return value */
+ return ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long)*PT_R3, 0);
} else if (arg_num < 8) {
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * (arg_num + PT_R3),
- 0);
+ return ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long)*(arg_num+PT_R3), 0);
} else {
- return ptrace(PTRACE_PEEKDATA, proc->pid,
- proc->stack_pointer + 8 * (arg_num - 8), 0);
+ return ptrace(PTRACE_PEEKDATA, proc->pid, proc->stack_pointer+8*(arg_num-8), 0);
}
return 0;
}
-void save_register_args(enum tof type, struct process *proc)
-{
+void
+save_register_args(enum tof type, struct process * proc) {
}