diff options
Diffstat (limited to 'sysdeps/linux-gnu/ppc')
-rw-r--r-- | sysdeps/linux-gnu/ppc/arch.h | 12 | ||||
-rw-r--r-- | sysdeps/linux-gnu/ppc/plt.c | 38 | ||||
-rw-r--r-- | sysdeps/linux-gnu/ppc/regs.c | 24 | ||||
-rw-r--r-- | sysdeps/linux-gnu/ppc/syscallent.h | 9 | ||||
-rw-r--r-- | sysdeps/linux-gnu/ppc/trace.c | 44 |
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) { } |