diff options
Diffstat (limited to 'sysdeps')
52 files changed, 1418 insertions, 755 deletions
diff --git a/sysdeps/linux-gnu/Makefile b/sysdeps/linux-gnu/Makefile index 7163709..6cbff83 100644 --- a/sysdeps/linux-gnu/Makefile +++ b/sysdeps/linux-gnu/Makefile @@ -1,20 +1,34 @@ -ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) +ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ + -e s/arm.*/arm/ -e s/sa110/arm/ -e s/ppc64/ppc/ -e s/s390x/s390/) CPPFLAGS += -I$(TOPDIR)/sysdeps/linux-gnu/$(ARCH) OBJ = trace.o proc.o breakpoint.o -all: sysdep.h signalent.h syscallent.h ../sysdep.o +all: sysdep.h signalent.h syscallent.h signalent1.h syscallent1.h ../sysdep.o sysdep.h: $(ARCH)/arch.h cat $(ARCH)/arch.h > sysdep.h signalent.h: cp $(ARCH)/signalent.h signalent.h +signalent1.h: + if [ -f $(ARCH)/signalent1.h ]; then \ + cp $(ARCH)/signalent1.h signalent1.h; \ + else \ + > signalent1.h; \ + fi syscallent.h: cp $(ARCH)/syscallent.h syscallent.h +syscallent1.h: + if [ -f $(ARCH)/syscallent1.h ]; then \ + cp $(ARCH)/syscallent1.h syscallent1.h; \ + else \ + > syscallent1.h; \ + fi + ../sysdep.o: os.o $(ARCH)/arch.o $(CC) -nostdlib -r -o ../sysdep.o os.o $(ARCH)/arch.o @@ -26,6 +40,7 @@ $(ARCH)/arch.o: dummy clean: $(MAKE) -C $(ARCH) clean - rm -f $(OBJ) sysdep.h signalent.h syscallent.h os.o sysdep.o ../sysdep.o + rm -f $(OBJ) sysdep.h signalent.h signalent1.h syscallent.h + rm -f syscallent1.h os.o sysdep.o ../sysdep.o dummy: diff --git a/sysdeps/linux-gnu/alpha/arch.h b/sysdeps/linux-gnu/alpha/arch.h index cdeeb52..930b6f1 100644 --- a/sysdeps/linux-gnu/alpha/arch.h +++ b/sysdeps/linux-gnu/alpha/arch.h @@ -4,4 +4,8 @@ #define LT_ELFCLASS ELFCLASS64 #define LT_ELF_MACHINE EM_ALPHA +#define LT_ELFCLASS2 ELFCLASS64 #define LT_ELF_MACHINE2 EM_FAKE_ALPHA + +#define PLTs_INIT_BY_HERE NULL +#define E_ENTRY_NAME "_start" diff --git a/sysdeps/linux-gnu/alpha/plt.c b/sysdeps/linux-gnu/alpha/plt.c index 32dfafb..16ec3d0 100644 --- a/sysdeps/linux-gnu/alpha/plt.c +++ b/sysdeps/linux-gnu/alpha/plt.c @@ -2,7 +2,13 @@ #include "ltrace.h" #include "elf.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 lte->plt_addr + ndx * 12 + 32; + return lte->plt_addr + ndx * 12 + 32; +} + +void * plt2addr(struct process *proc, void ** plt) +{ + return (void *) plt; } diff --git a/sysdeps/linux-gnu/alpha/regs.c b/sysdeps/linux-gnu/alpha/regs.c index fcba535..c59eee9 100644 --- a/sysdeps/linux-gnu/alpha/regs.c +++ b/sysdeps/linux-gnu/alpha/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, 64 /* REG_PC */ , 0); +void * +get_instruction_pointer(struct process * proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 64 /* REG_PC */, 0); } -void set_instruction_pointer(struct process *proc, void *addr) -{ - ptrace(PTRACE_POKEUSER, proc->pid, 64 /* REG_PC */ , addr); +void +set_instruction_pointer(struct process * proc, void * addr) { + ptrace(PTRACE_POKEUSER, proc->pid, 64 /* REG_PC */, addr); } -void *get_stack_pointer(struct process *proc) -{ - return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 30 /* REG_FP */ , 0); +void * +get_stack_pointer(struct process * proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 30 /* REG_FP */, 0); } -void *get_return_addr(struct process *proc, void *stack_pointer) -{ - return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 26 /* RA */ , 0); +void * +get_return_addr(struct process * proc, void * stack_pointer) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 26 /* RA */, 0); } diff --git a/sysdeps/linux-gnu/alpha/trace.c b/sysdeps/linux-gnu/alpha/trace.c index 3d35cf2..3d6237c 100644 --- a/sysdeps/linux-gnu/alpha/trace.c +++ b/sysdeps/linux-gnu/alpha/trace.c @@ -25,51 +25,45 @@ void get_arch_dep(struct process *proc) /* Returns 1 if syscall, 2 if sysret, 0 otherwise. */ -int syscall_p(struct process *proc, int status, int *sysnum) -{ - if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { - char *ip = get_instruction_pointer(proc) - 4; +int +syscall_p(struct process * proc, int status, int * sysnum) { + if (WIFSTOPPED(status) && WSTOPSIG(status)==(SIGTRAP | proc->tracesysgood)) { + char *ip=get_instruction_pointer(proc) - 4; long x = ptrace(PTRACE_PEEKTEXT, proc->pid, ip, 0); debug(2, "instr: %016lx", x); - if ((x & 0xffffffff) != 0x00000083) + if((x & 0xffffffff) != 0x00000083) return 0; - *sysnum = - ptrace(PTRACE_PEEKUSER, proc->pid, 0 /* REG_R0 */ , 0); - if (proc->callstack_depth > 0 - && proc->callstack[proc->callstack_depth - 1].is_syscall) { + *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, 0 /* REG_R0 */, 0); + if (proc->callstack_depth > 0 && proc->callstack[proc->callstack_depth-1].is_syscall) { return 2; } - if (*sysnum >= 0 && *sysnum < 500) { + if (*sysnum>=0 && *sysnum<500) { return 1; } } 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, 0 /* REG_R0 */ , 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, 0 /* REG_R0 */, 0); } - if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) { - if (arg_num <= 5) - return ptrace(PTRACE_PEEKUSER, proc->pid, - arg_num + 16 /* REG_A0 */ , 0); + if (type==LT_TOF_FUNCTION || type==LT_TOF_FUNCTIONR) { + if(arg_num <= 5) + return ptrace(PTRACE_PEEKUSER, proc->pid, arg_num + 16 /* REG_A0 */, 0); else - return ptrace(PTRACE_PEEKTEXT, proc->pid, - proc->stack_pointer + 8 * (arg_num - 6), - 0); - } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) { - return ptrace(PTRACE_PEEKUSER, proc->pid, - arg_num + 16 /* REG_A0 */ , 0); + return ptrace(PTRACE_PEEKTEXT, proc->pid, proc->stack_pointer+8*(arg_num-6), 0); + } else if (type==LT_TOF_SYSCALL || type==LT_TOF_SYSCALLR) { + return ptrace(PTRACE_PEEKUSER, proc->pid, arg_num + 16 /* REG_A0 */, 0); } else { fprintf(stderr, "gimme_arg called with wrong arguments\n"); exit(1); } return 0; } - -void save_register_args(enum tof type, struct process *proc) + +void save_register_args(enum tof type, struct process * proc) { } diff --git a/sysdeps/linux-gnu/arm/arch.h b/sysdeps/linux-gnu/arm/arch.h index e8a8b66..315238d 100644 --- a/sysdeps/linux-gnu/arm/arch.h +++ b/sysdeps/linux-gnu/arm/arch.h @@ -4,3 +4,6 @@ #define LT_ELFCLASS ELFCLASS32 #define LT_ELF_MACHINE EM_ARM + +#define PLTs_INIT_BY_HERE NULL +#define E_ENTRY_NAME "_start" diff --git a/sysdeps/linux-gnu/arm/plt.c b/sysdeps/linux-gnu/arm/plt.c index 1dae91f..51463c5 100644 --- a/sysdeps/linux-gnu/arm/plt.c +++ b/sysdeps/linux-gnu/arm/plt.c @@ -2,7 +2,13 @@ #include "ltrace.h" #include "elf.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 lte->plt_addr + 20 + ndx * 12; + return lte->plt_addr + 20 + ndx * 12; +} + +void * plt2addr(struct process *proc, void ** plt) +{ + return (void *) plt; } diff --git a/sysdeps/linux-gnu/arm/regs.c b/sysdeps/linux-gnu/arm/regs.c index 819754f..70ead10 100644 --- a/sysdeps/linux-gnu/arm/regs.c +++ b/sysdeps/linux-gnu/arm/regs.c @@ -20,24 +20,24 @@ #define off_lr 56 #define off_sp 52 -void *get_instruction_pointer(struct process *proc) -{ +void * +get_instruction_pointer(struct process * proc) { return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0); } -void set_instruction_pointer(struct process *proc, void *addr) -{ +void +set_instruction_pointer(struct process * proc, void * addr) { ptrace(PTRACE_POKEUSER, proc->pid, off_pc, addr); } -void *get_stack_pointer(struct process *proc) -{ +void * +get_stack_pointer(struct process * proc) { return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_sp, 0); } /* really, this is given the *stack_pointer expecting * a CISC architecture; in our case, we don't need that */ -void *get_return_addr(struct process *proc, void *stack_pointer) -{ +void * +get_return_addr(struct process * proc, void * stack_pointer) { return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0); } diff --git a/sysdeps/linux-gnu/arm/trace.c b/sysdeps/linux-gnu/arm/trace.c index 0d68ae0..485f0ad 100644 --- a/sysdeps/linux-gnu/arm/trace.c +++ b/sysdeps/linux-gnu/arm/trace.c @@ -26,54 +26,47 @@ #define off_ip 48 #define off_pc 60 -void get_arch_dep(struct process *proc) -{ +void +get_arch_dep(struct process * proc) { } /* Returns 1 if syscall, 2 if sysret, 0 otherwise. */ -int syscall_p(struct process *proc, int status, int *sysnum) -{ - if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { +int +syscall_p(struct process * proc, int status, int * sysnum) { + if (WIFSTOPPED(status) && WSTOPSIG(status)==(SIGTRAP | proc->tracesysgood)) { /* get the user's pc (plus 8) */ int pc = ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0); /* fetch the SWI instruction */ - int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0); - + int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc-4, 0) ; + *sysnum = insn & 0xFFFF; /* if it is a syscall, return 1 or 2 */ if ((insn & 0xFFFF0000) == 0xef900000) { - return ptrace(PTRACE_PEEKUSER, proc->pid, off_ip, - 0) ? 2 : 1; + return ptrace(PTRACE_PEEKUSER, proc->pid, off_ip, 0) ? 2 : 1; } } return 0; } - -long gimme_arg(enum tof type, struct process *proc, int arg_num) -{ - if (arg_num == -1) { /* return value */ + +long +gimme_arg(enum tof type, struct process * proc, int arg_num) { + if (arg_num==-1) { /* return value */ return ptrace(PTRACE_PEEKUSER, proc->pid, off_r0, 0); } /* deal with the ARM calling conventions */ - if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) { - if (arg_num < 4) { - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num, - 0); + if (type==LT_TOF_FUNCTION || type==LT_TOF_FUNCTIONR) { + if (arg_num<4) { + return ptrace(PTRACE_PEEKUSER, proc->pid, 4*arg_num, 0); } else { - return ptrace(PTRACE_PEEKDATA, proc->pid, - proc->stack_pointer + 4 * (arg_num - 4), - 0); + return ptrace(PTRACE_PEEKDATA, proc->pid, proc->stack_pointer+4*(arg_num-4), 0); } - } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) { - if (arg_num < 5) { - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num, - 0); + } else if (type==LT_TOF_SYSCALL || type==LT_TOF_SYSCALLR) { + if (arg_num<5) { + return ptrace(PTRACE_PEEKUSER, proc->pid, 4*arg_num, 0); } else { - return ptrace(PTRACE_PEEKDATA, proc->pid, - proc->stack_pointer + 4 * (arg_num - 5), - 0); + return ptrace(PTRACE_PEEKDATA, proc->pid, proc->stack_pointer+4*(arg_num-5), 0); } } else { fprintf(stderr, "gimme_arg called with wrong arguments\n"); @@ -83,6 +76,6 @@ long gimme_arg(enum tof type, struct process *proc, int arg_num) return 0; } -void save_register_args(enum tof type, struct process *proc) -{ +void +save_register_args(enum tof type, struct process * proc) { } diff --git a/sysdeps/linux-gnu/breakpoint.c b/sysdeps/linux-gnu/breakpoint.c index fe6ac69..712f1a5 100644 --- a/sysdeps/linux-gnu/breakpoint.c +++ b/sysdeps/linux-gnu/breakpoint.c @@ -7,6 +7,7 @@ #include "arch.h" #include "options.h" #include "output.h" +#include "debug.h" static unsigned char break_insn[] = BREAKPOINT_VALUE; @@ -14,30 +15,24 @@ static unsigned char break_insn[] = BREAKPOINT_VALUE; extern void arch_enable_breakpoint(pid_t, struct breakpoint*); void enable_breakpoint(pid_t pid, struct breakpoint *sbp) { - arch_enable_breakpoint(pid, sbp); + arch_enable_breakpoint(pid, sbp); } #else -void enable_breakpoint(pid_t pid, struct breakpoint *sbp) -{ - int i, j; +void +enable_breakpoint(pid_t pid, struct breakpoint * sbp) { + int i,j; - if (opt_d > 1) { - output_line(0, "enable_breakpoint(%d,%p)", pid, sbp->addr); - } + debug(1, "enable_breakpoint(%d,%p)", pid, sbp->addr); - for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) { - long a = - ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long), - 0); - for (j = 0; - j < sizeof(long) - && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) { - unsigned char *bytes = (unsigned char *)&a; + for(i=0; i < 1+((BREAKPOINT_LENGTH-1)/sizeof(long)); i++) { + long a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i*sizeof(long), 0); + for(j=0; j<sizeof(long) && i*sizeof(long)+j < BREAKPOINT_LENGTH; j++) { + unsigned char * bytes = (unsigned char *)&a; - sbp->orig_value[i * sizeof(long) + j] = bytes[+j]; - bytes[j] = break_insn[i * sizeof(long) + j]; + sbp->orig_value[i*sizeof(long)+j] = bytes[+j]; + bytes[j] = break_insn[i*sizeof(long)+j]; } - ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a); + ptrace(PTRACE_POKETEXT, pid, sbp->addr + i*sizeof(long), a); } } #endif /* ARCH_HAVE_ENABLE_BREAKPOINT */ @@ -49,26 +44,22 @@ disable_breakpoint(pid_t pid, const struct breakpoint * sbp) { arch_disable_breakpoint(pid, sbp); } #else -void disable_breakpoint(pid_t pid, const struct breakpoint *sbp) -{ - int i, j; +void +disable_breakpoint(pid_t pid, const struct breakpoint * sbp) { + int i,j; - if (opt_d > 1) { + if (opt_d>1) { output_line(0, "disable_breakpoint(%d,%p)", pid, sbp->addr); } - for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) { - long a = - ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long), - 0); - for (j = 0; - j < sizeof(long) - && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) { - unsigned char *bytes = (unsigned char *)&a; + for(i=0; i < 1+((BREAKPOINT_LENGTH-1)/sizeof(long)); i++) { + long a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i*sizeof(long), 0); + for(j=0; j<sizeof(long) && i*sizeof(long)+j < BREAKPOINT_LENGTH; j++) { + unsigned char * bytes = (unsigned char *)&a; - bytes[j] = sbp->orig_value[i * sizeof(long) + j]; + bytes[j] = sbp->orig_value[i*sizeof(long)+j]; } - ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a); + ptrace(PTRACE_POKETEXT, pid, sbp->addr + i*sizeof(long), a); } } #endif /* ARCH_HAVE_DISABLE_BREAKPOINT */ diff --git a/sysdeps/linux-gnu/i386/arch.h b/sysdeps/linux-gnu/i386/arch.h index dc7383f..c624a8a 100644 --- a/sysdeps/linux-gnu/i386/arch.h +++ b/sysdeps/linux-gnu/i386/arch.h @@ -4,3 +4,6 @@ #define LT_ELFCLASS ELFCLASS32 #define LT_ELF_MACHINE EM_386 + +#define PLTs_INIT_BY_HERE NULL +#define E_ENTRY_NAME "_start" diff --git a/sysdeps/linux-gnu/i386/plt.c b/sysdeps/linux-gnu/i386/plt.c index 939bc4e..36d0ecd 100644 --- a/sysdeps/linux-gnu/i386/plt.c +++ b/sysdeps/linux-gnu/i386/plt.c @@ -2,7 +2,13 @@ #include "ltrace.h" #include "elf.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 lte->plt_addr + (ndx + 1) * 16; + return lte->plt_addr + (ndx + 1) * 16; +} + +void * plt2addr(struct process *proc, void ** plt) +{ + return (void *) plt; } diff --git a/sysdeps/linux-gnu/i386/regs.c b/sysdeps/linux-gnu/i386/regs.c index 158fa24..75268e9 100644 --- a/sysdeps/linux-gnu/i386/regs.c +++ b/sysdeps/linux-gnu/i386/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 * EIP, 0); +void * +get_instruction_pointer(struct process * proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4*EIP, 0); } -void set_instruction_pointer(struct process *proc, void *addr) -{ - ptrace(PTRACE_POKEUSER, proc->pid, 4 * EIP, (long)addr); +void +set_instruction_pointer(struct process * proc, void * addr) { + ptrace(PTRACE_POKEUSER, proc->pid, 4*EIP, (long)addr); } -void *get_stack_pointer(struct process *proc) -{ - return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * UESP, 0); +void * +get_stack_pointer(struct process * proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4*UESP, 0); } -void *get_return_addr(struct process *proc, void *stack_pointer) -{ +void * +get_return_addr(struct process * proc, void * stack_pointer) { return (void *)ptrace(PTRACE_PEEKTEXT, proc->pid, stack_pointer, 0); } diff --git a/sysdeps/linux-gnu/i386/syscallent.h b/sysdeps/linux-gnu/i386/syscallent.h index b6eb2a8..c4bdae5 100644 --- a/sysdeps/linux-gnu/i386/syscallent.h +++ b/sysdeps/linux-gnu/i386/syscallent.h @@ -283,3 +283,12 @@ "mq_getsetattr", /* 282 */ "kexec_load", /* 283 */ "waitid", /* 284 */ + "285", /* 285 */ + "add_key", /* 286 */ + "request_key", /* 287 */ + "keyctl", /* 288 */ + "ioprio_set", /* 289 */ + "ioprio_get", /* 290 */ + "inotify_init", /* 291 */ + "inotify_add_watch", /* 292 */ + "inotify_rm_watch", /* 293 */ diff --git a/sysdeps/linux-gnu/i386/trace.c b/sysdeps/linux-gnu/i386/trace.c index fe9d8a4..b8eff3d 100644 --- a/sysdeps/linux-gnu/i386/trace.c +++ b/sysdeps/linux-gnu/i386/trace.c @@ -19,58 +19,51 @@ # define PTRACE_POKEUSER PTRACE_POKEUSR #endif -void get_arch_dep(struct process *proc) -{ +void +get_arch_dep(struct process * proc) { } /* Returns 1 if syscall, 2 if sysret, 0 otherwise. */ -int syscall_p(struct process *proc, int status, int *sysnum) -{ - if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { - *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, 4 * ORIG_EAX, 0); +int +syscall_p(struct process * proc, int status, int * sysnum) { + if (WIFSTOPPED(status) && WSTOPSIG(status)==(SIGTRAP | proc->tracesysgood)) { + *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, 4*ORIG_EAX, 0); if (proc->callstack_depth > 0 && - proc->callstack[proc->callstack_depth - 1].is_syscall) { + proc->callstack[proc->callstack_depth-1].is_syscall) { return 2; } - if (*sysnum >= 0) { + if (*sysnum>=0) { return 1; } } 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 * EAX, 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*EAX, 0); } - if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) { - return ptrace(PTRACE_PEEKTEXT, proc->pid, - proc->stack_pointer + 4 * (arg_num + 1), 0); - } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) { + if (type==LT_TOF_FUNCTION || type==LT_TOF_FUNCTIONR) { + return ptrace(PTRACE_PEEKTEXT, proc->pid, proc->stack_pointer+4*(arg_num+1), 0); + } else if (type==LT_TOF_SYSCALL || type==LT_TOF_SYSCALLR) { #if 0 - switch (arg_num) { - case 0: - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EBX, 0); - case 1: - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * ECX, 0); - case 2: - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EDX, 0); - case 3: - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * ESI, 0); - case 4: - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EDI, 0); - default: - fprintf(stderr, - "gimme_arg called with wrong arguments\n"); - exit(2); + switch(arg_num) { + case 0: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*EBX, 0); + case 1: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*ECX, 0); + case 2: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*EDX, 0); + case 3: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*ESI, 0); + case 4: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*EDI, 0); + default: + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + exit(2); } #else - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num, 0); + return ptrace(PTRACE_PEEKUSER, proc->pid, 4*arg_num, 0); #endif } else { fprintf(stderr, "gimme_arg called with wrong arguments\n"); @@ -80,6 +73,6 @@ long gimme_arg(enum tof type, struct process *proc, int arg_num) return 0; } -void save_register_args(enum tof type, struct process *proc) -{ +void +save_register_args(enum tof type, struct process * proc) { } diff --git a/sysdeps/linux-gnu/ia64/arch.h b/sysdeps/linux-gnu/ia64/arch.h index b5f141f..6efef3d 100644 --- a/sysdeps/linux-gnu/ia64/arch.h +++ b/sysdeps/linux-gnu/ia64/arch.h @@ -1,10 +1,12 @@ #define ARCH_HAVE_DISABLE_BREAKPOINT 1 #define ARCH_HAVE_ENABLE_BREAKPOINT 1 - #define BREAKPOINT_LENGTH 16 #define BREAKPOINT_VALUE {0} #define DECR_PC_AFTER_BREAK 0 #define LT_ELFCLASS ELFCLASS64 #define LT_ELF_MACHINE EM_IA_64 + +#define PLTs_INIT_BY_HERE NULL +#define E_ENTRY_NAME "_start" diff --git a/sysdeps/linux-gnu/ia64/plt.c b/sysdeps/linux-gnu/ia64/plt.c index 05a1a24..b4ee017 100644 --- a/sysdeps/linux-gnu/ia64/plt.c +++ b/sysdeps/linux-gnu/ia64/plt.c @@ -40,3 +40,8 @@ arch_plt_sym_val (struct ltelf *lte, size_t ndx, GElf_Rela *rela) return addr; } + +void * plt2addr(struct process *proc, void ** plt) +{ + return (void *) plt; +} diff --git a/sysdeps/linux-gnu/ia64/syscallent.h b/sysdeps/linux-gnu/ia64/syscallent.h index 1a5b505..88545d4 100644 --- a/sysdeps/linux-gnu/ia64/syscallent.h +++ b/sysdeps/linux-gnu/ia64/syscallent.h @@ -1257,3 +1257,24 @@ "clock_nanosleep", /* 1256 */ "fstatfs64", /* 1257 */ "statfs64", /* 1258 */ + "mbind", /* 1259 */ + "get_mempolicy", /* 1260 */ + "set_mempolicy", /* 1261 */ + "mq_open", /* 1262 */ + "mq_unlink", /* 1263 */ + "mq_timedsend", /* 1264 */ + "mq_timedreceive", /* 1265 */ + "mq_notify", /* 1266 */ + "mq_getsetattr", /* 1267 */ + "kexec_load", /* 1268 */ + "vserver", /* 1269 */ + "waitid", /* 1270 */ + "add_key", /* 1271 */ + "request_key", /* 1272 */ + "keyctl", /* 1273 */ + "ioprio_set", /* 1274 */ + "ioprio_get", /* 1275 */ + "set_zone_reclaim", /* 1276 */ + "inotify_init", /* 1277 */ + "inotify_add_watch", /* 1278 */ + "inotify_rm_watch", /* 1279 */ diff --git a/sysdeps/linux-gnu/ia64/trace.c b/sysdeps/linux-gnu/ia64/trace.c index 46e8771..7fa6c1e 100644 --- a/sysdeps/linux-gnu/ia64/trace.c +++ b/sysdeps/linux-gnu/ia64/trace.c @@ -37,8 +37,7 @@ union bundle_t { int syscall_p(struct process * proc, int status, int * sysnum) { - if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) - { + if (WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { unsigned long slot = (ptrace (PTRACE_PEEKUSER, proc->pid, PT_CR_IPSR, 0) >> 41) & 0x3; unsigned long ip = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IIP, 0); diff --git a/sysdeps/linux-gnu/m68k/arch.h b/sysdeps/linux-gnu/m68k/arch.h index 1790d09..438545f 100644 --- a/sysdeps/linux-gnu/m68k/arch.h +++ b/sysdeps/linux-gnu/m68k/arch.h @@ -4,3 +4,6 @@ #define LT_ELFCLASS ELFCLASS32 #define LT_ELF_MACHINE EM_68K + +#define PLTs_INIT_BY_HERE NULL +#define E_ENTRY_NAME "_start" diff --git a/sysdeps/linux-gnu/m68k/plt.c b/sysdeps/linux-gnu/m68k/plt.c index 09168e9..54cc920 100644 --- a/sysdeps/linux-gnu/m68k/plt.c +++ b/sysdeps/linux-gnu/m68k/plt.c @@ -2,8 +2,14 @@ #include "ltrace.h" #include "elf.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 lte->plt_addr + (ndx + 1) - * ((lte->ehdr.e_flags & EF_CPU32) ? 24 : 12); + return lte->plt_addr + (ndx + 1) + * ((lte->ehdr.e_flags & EF_CPU32) ? 24 : 12); +} + +void * plt2addr(struct process *proc, void ** plt) +{ + return (void *) plt; } diff --git a/sysdeps/linux-gnu/m68k/regs.c b/sysdeps/linux-gnu/m68k/regs.c index d953d28..187cef5 100644 --- a/sysdeps/linux-gnu/m68k/regs.c +++ b/sysdeps/linux-gnu/m68k/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_PC, 0); +void * +get_instruction_pointer(struct process * proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4*PT_PC, 0); } -void set_instruction_pointer(struct process *proc, void *addr) -{ - ptrace(PTRACE_POKEUSER, proc->pid, 4 * PT_PC, addr); +void +set_instruction_pointer(struct process * proc, void * addr) { + ptrace(PTRACE_POKEUSER, proc->pid, 4*PT_PC, addr); } -void *get_stack_pointer(struct process *proc) -{ - return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_USP, 0); +void * +get_stack_pointer(struct process * proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4*PT_USP, 0); } -void *get_return_addr(struct process *proc, void *stack_pointer) -{ +void * +get_return_addr(struct process * proc, void * stack_pointer) { return (void *)ptrace(PTRACE_PEEKTEXT, proc->pid, stack_pointer, 0); } diff --git a/sysdeps/linux-gnu/m68k/trace.c b/sysdeps/linux-gnu/m68k/trace.c index b4e1b88..fac5fbe 100644 --- a/sysdeps/linux-gnu/m68k/trace.c +++ b/sysdeps/linux-gnu/m68k/trace.c @@ -18,26 +18,24 @@ # define PTRACE_POKEUSER PTRACE_POKEUSR #endif -void get_arch_dep(struct process *proc) -{ +void +get_arch_dep(struct process * proc) { } /* Returns 1 if syscall, 2 if sysret, 0 otherwise. */ -int syscall_p(struct process *proc, int status, int *sysnum) -{ +int +syscall_p(struct process * proc, int status, int * sysnum) { int depth; - if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { - *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_ORIG_D0, 0); - if (*sysnum == -1) - return 0; - if (*sysnum >= 0) { + if (WIFSTOPPED(status) && WSTOPSIG(status)==(SIGTRAP | proc->tracesysgood)) { + *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, 4*PT_ORIG_D0, 0); + if (*sysnum == -1) return 0; + if (*sysnum>=0) { depth = proc->callstack_depth; - if (depth > 0 && - proc->callstack[depth - 1].is_syscall && - proc->callstack[depth - 1].c_un.syscall == - *sysnum) { + if (depth>0 && + proc->callstack[depth-1].is_syscall && + proc->callstack[depth-1].c_un.syscall==*sysnum) { return 2; } else { return 1; @@ -47,36 +45,29 @@ 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_D0, 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_D0, 0); } - if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) { - return ptrace(PTRACE_PEEKTEXT, proc->pid, - proc->stack_pointer + 4 * (arg_num + 1), 0); - } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) { + if (type==LT_TOF_FUNCTION || type==LT_TOF_FUNCTIONR) { + return ptrace(PTRACE_PEEKTEXT, proc->pid, proc->stack_pointer+4*(arg_num+1), 0); + } else if (type==LT_TOF_SYSCALL || type==LT_TOF_SYSCALLR) { #if 0 - switch (arg_num) { - case 0: - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D1, 0); - case 1: - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D2, 0); - case 2: - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D3, 0); - case 3: - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D4, 0); - case 4: - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D5, 0); - default: - fprintf(stderr, - "gimme_arg called with wrong arguments\n"); - exit(2); + switch(arg_num) { + case 0: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*PT_D1, 0); + case 1: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*PT_D2, 0); + case 2: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*PT_D3, 0); + case 3: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*PT_D4, 0); + case 4: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*PT_D5, 0); + default: + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + exit(2); } #else /* That hack works on m68k, too */ - return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num, 0); + return ptrace(PTRACE_PEEKUSER, proc->pid, 4*arg_num, 0); #endif } else { fprintf(stderr, "gimme_arg called with wrong arguments\n"); @@ -86,6 +77,6 @@ long gimme_arg(enum tof type, struct process *proc, int arg_num) return 0; } -void save_register_args(enum tof type, struct process *proc) -{ +void +save_register_args(enum tof type, struct process * proc) { } 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) { } diff --git a/sysdeps/linux-gnu/proc.c b/sysdeps/linux-gnu/proc.c index 201fb6d..a5c18f6 100644 --- a/sysdeps/linux-gnu/proc.c +++ b/sysdeps/linux-gnu/proc.c @@ -13,21 +13,21 @@ * have a bit delay */ -#define MAX_DELAY 100000 /* 100000 microseconds = 0.1 seconds */ +#define MAX_DELAY 100000 /* 100000 microseconds = 0.1 seconds */ /* * Returns a file name corresponding to a running pid */ -char *pid2name(pid_t pid) -{ +char * +pid2name(pid_t pid) { char proc_exe[1024]; if (!kill(pid, 0)) { - int delay = 0; + int delay=0; sprintf(proc_exe, "/proc/%d/exe", pid); - while (delay < MAX_DELAY) { + while(delay<MAX_DELAY) { if (!access(proc_exe, F_OK)) { return strdup(proc_exe); } diff --git a/sysdeps/linux-gnu/s390/arch.h b/sysdeps/linux-gnu/s390/arch.h index bb61ca7..18a1c89 100644 --- a/sysdeps/linux-gnu/s390/arch.h +++ b/sysdeps/linux-gnu/s390/arch.h @@ -7,5 +7,15 @@ #define BREAKPOINT_LENGTH 2 #define DECR_PC_AFTER_BREAK 2 +#ifdef __s390x__ +#define LT_ELFCLASS ELFCLASS64 +#define LT_ELF_MACHINE EM_S390 +#define LT_ELFCLASS2 ELFCLASS32 +#define LT_ELF_MACHINE2 EM_S390 +#else #define LT_ELFCLASS ELFCLASS32 #define LT_ELF_MACHINE EM_S390 +#endif + +#define PLTs_INIT_BY_HERE NULL +#define E_ENTRY_NAME "_start" diff --git a/sysdeps/linux-gnu/s390/plt.c b/sysdeps/linux-gnu/s390/plt.c index deb612e..99c524d 100644 --- a/sysdeps/linux-gnu/s390/plt.c +++ b/sysdeps/linux-gnu/s390/plt.c @@ -2,7 +2,14 @@ #include "ltrace.h" #include "elf.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 lte->plt_addr + (ndx + 1) * 32; + return lte->plt_addr + (ndx + 1) * 32; +} + + +void * plt2addr(struct process *proc, void ** plt) +{ + return (void *) plt; } diff --git a/sysdeps/linux-gnu/s390/regs.c b/sysdeps/linux-gnu/s390/regs.c index efba7f8..3f14115 100644 --- a/sysdeps/linux-gnu/s390/regs.c +++ b/sysdeps/linux-gnu/s390/regs.c @@ -21,24 +21,48 @@ # define PTRACE_POKEUSER PTRACE_POKEUSR #endif -void *get_instruction_pointer(struct process *proc) -{ - return (void *)(ptrace(PTRACE_PEEKUSER, proc->pid, PT_PSWADDR, 0) & - 0x7fffffff); +#ifdef __s390x__ +#define PSW_MASK 0xffffffffffffffff +#define PSW_MASK31 0x7fffffff +#else +#define PSW_MASK 0x7fffffff +#endif + +void * +get_instruction_pointer(struct process * proc) { + long ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_PSWADDR, 0) & PSW_MASK; +#ifdef __s390x__ + if (proc->mask_32bit) + ret &= PSW_MASK31; +#endif + return (void *) ret; } -void set_instruction_pointer(struct process *proc, void *addr) -{ +void +set_instruction_pointer(struct process * proc, void * addr) { +#ifdef __s390x__ + if (proc->mask_32bit) + addr = (void *) ((long) addr & PSW_MASK31); +#endif ptrace(PTRACE_POKEUSER, proc->pid, PT_PSWADDR, addr); } -void *get_stack_pointer(struct process *proc) -{ - return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR15, 0); +void * +get_stack_pointer(struct process * proc) { + long ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR15, 0) & PSW_MASK; +#ifdef __s390x__ + if (proc->mask_32bit) + ret &= PSW_MASK31; +#endif + return (void *) ret; } -void *get_return_addr(struct process *proc, void *stack_pointer) -{ - return (void *)(ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR14, 0) & - 0x7fffffff); +void * +get_return_addr(struct process * proc, void * stack_pointer) { + long ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR14, 0) & PSW_MASK; +#ifdef __s390x__ + if (proc->mask_32bit) + ret &= PSW_MASK31; +#endif + return (void *) ret; } diff --git a/sysdeps/linux-gnu/s390/signalent.h b/sysdeps/linux-gnu/s390/signalent.h index 5395f82..714d56d 100644 --- a/sysdeps/linux-gnu/s390/signalent.h +++ b/sysdeps/linux-gnu/s390/signalent.h @@ -29,4 +29,5 @@ "SIGWINCH", /* 28 */ "SIGIO", /* 29 */ "SIGPWR", /* 30 */ - "SIGSYS", /* 31 */ + "SIGUNUSED", /* 31 */ + "SIGRTMIN", /* 32 */ diff --git a/sysdeps/linux-gnu/s390/signalent1.h b/sysdeps/linux-gnu/s390/signalent1.h new file mode 100644 index 0000000..b5b6ca8 --- /dev/null +++ b/sysdeps/linux-gnu/s390/signalent1.h @@ -0,0 +1 @@ +#include "s390/signalent.h" diff --git a/sysdeps/linux-gnu/s390/syscallent.h b/sysdeps/linux-gnu/s390/syscallent.h index 13bd3c2..5a35d93 100644 --- a/sysdeps/linux-gnu/s390/syscallent.h +++ b/sysdeps/linux-gnu/s390/syscallent.h @@ -1,277 +1,5 @@ - "0", /* 0 */ - "exit", /* 1 */ - "fork", /* 2 */ - "read", /* 3 */ - "write", /* 4 */ - "open", /* 5 */ - "close", /* 6 */ - "7", /* 7 */ - "creat", /* 8 */ - "link", /* 9 */ - "unlink", /* 10 */ - "execve", /* 11 */ - "chdir", /* 12 */ - "time", /* 13 */ - "mknod", /* 14 */ - "chmod", /* 15 */ - "lchown", /* 16 */ - "17", /* 17 */ - "18", /* 18 */ - "lseek", /* 19 */ - "getpid", /* 20 */ - "mount", /* 21 */ - "umount", /* 22 */ - "setuid", /* 23 */ - "getuid", /* 24 */ - "stime", /* 25 */ - "ptrace", /* 26 */ - "alarm", /* 27 */ - "28", /* 28 */ - "pause", /* 29 */ - "utime", /* 30 */ - "31", /* 31 */ - "32", /* 32 */ - "access", /* 33 */ - "nice", /* 34 */ - "35", /* 35 */ - "sync", /* 36 */ - "kill", /* 37 */ - "rename", /* 38 */ - "mkdir", /* 39 */ - "rmdir", /* 40 */ - "dup", /* 41 */ - "pipe", /* 42 */ - "times", /* 43 */ - "44", /* 44 */ - "brk", /* 45 */ - "setgid", /* 46 */ - "getgid", /* 47 */ - "signal", /* 48 */ - "geteuid", /* 49 */ - "getegid", /* 50 */ - "acct", /* 51 */ - "umount2", /* 52 */ - "53", /* 53 */ - "ioctl", /* 54 */ - "fcntl", /* 55 */ - "56", /* 56 */ - "setpgid", /* 57 */ - "58", /* 58 */ - "59", /* 59 */ - "umask", /* 60 */ - "chroot", /* 61 */ - "ustat", /* 62 */ - "dup2", /* 63 */ - "getppid", /* 64 */ - "getpgrp", /* 65 */ - "setsid", /* 66 */ - "sigaction", /* 67 */ - "68", /* 68 */ - "69", /* 69 */ - "setreuid", /* 70 */ - "setregid", /* 71 */ - "sigsuspend", /* 72 */ - "sigpending", /* 73 */ - "sethostname", /* 74 */ - "setrlimit", /* 75 */ - "getrlimit", /* 76 */ - "getrusage", /* 77 */ - "gettimeofday", /* 78 */ - "settimeofday", /* 79 */ - "getgroups", /* 80 */ - "setgroups", /* 81 */ - "82", /* 82 */ - "symlink", /* 83 */ - "84", /* 84 */ - "readlink", /* 85 */ - "uselib", /* 86 */ - "swapon", /* 87 */ - "reboot", /* 88 */ - "readdir", /* 89 */ - "mmap", /* 90 */ - "munmap", /* 91 */ - "truncate", /* 92 */ - "ftruncate", /* 93 */ - "fchmod", /* 94 */ - "fchown", /* 95 */ - "getpriority", /* 96 */ - "setpriority", /* 97 */ - "98", /* 98 */ - "statfs", /* 99 */ - "fstatfs", /* 100 */ - "ioperm", /* 101 */ - "socketcall", /* 102 */ - "syslog", /* 103 */ - "setitimer", /* 104 */ - "getitimer", /* 105 */ - "stat", /* 106 */ - "lstat", /* 107 */ - "fstat", /* 108 */ - "109", /* 109 */ - "110", /* 110 */ - "vhangup", /* 111 */ - "idle", /* 112 */ - "113", /* 113 */ - "wait4", /* 114 */ - "swapoff", /* 115 */ - "sysinfo", /* 116 */ - "ipc", /* 117 */ - "fsync", /* 118 */ - "sigreturn", /* 119 */ - "clone", /* 120 */ - "setdomainname", /* 121 */ - "uname", /* 122 */ - "123", /* 123 */ - "adjtimex", /* 124 */ - "mprotect", /* 125 */ - "sigprocmask", /* 126 */ - "create_module", /* 127 */ - "init_module", /* 128 */ - "delete_module", /* 129 */ - "get_kernel_syms", /* 130 */ - "quotactl", /* 131 */ - "getpgid", /* 132 */ - "fchdir", /* 133 */ - "bdflush", /* 134 */ - "sysfs", /* 135 */ - "personality", /* 136 */ - "afs_syscall", /* 137 */ - "setfsuid", /* 138 */ - "setfsgid", /* 139 */ - "_llseek", /* 140 */ - "getdents", /* 141 */ - "_newselect", /* 142 */ - "flock", /* 143 */ - "msync", /* 144 */ - "readv", /* 145 */ - "writev", /* 146 */ - "getsid", /* 147 */ - "fdatasync", /* 148 */ - "_sysctl", /* 149 */ - "mlock", /* 150 */ - "munlock", /* 151 */ - "mlockall", /* 152 */ - "munlockall", /* 153 */ - "sched_setparam", /* 154 */ - "sched_getparam", /* 155 */ - "sched_setscheduler", /* 156 */ - "sched_getscheduler", /* 157 */ - "sched_yield", /* 158 */ - "sched_get_priority_max", /* 159 */ - "sched_get_priority_min", /* 160 */ - "sched_rr_get_interval", /* 161 */ - "nanosleep", /* 162 */ - "mremap", /* 163 */ - "setresuid", /* 164 */ - "getresuid", /* 165 */ - "166", /* 166 */ - "query_module", /* 167 */ - "poll", /* 168 */ - "nfsservctl", /* 169 */ - "setresgid", /* 170 */ - "getresgid", /* 171 */ - "prctl", /* 172 */ - "rt_sigreturn", /* 173 */ - "rt_sigaction", /* 174 */ - "rt_sigprocmask", /* 175 */ - "rt_sigpending", /* 176 */ - "rt_sigtimedwait", /* 177 */ - "rt_sigqueueinfo", /* 178 */ - "rt_sigsuspend", /* 179 */ - "pread", /* 180 */ - "pwrite", /* 181 */ - "chown", /* 182 */ - "getcwd", /* 183 */ - "capget", /* 184 */ - "capset", /* 185 */ - "sigaltstack", /* 186 */ - "sendfile", /* 187 */ - "getpmsg", /* 188 */ - "putpmsg", /* 189 */ - "vfork", /* 190 */ - "ugetrlimit", /* 191 */ - "mmap2", /* 192 */ - "truncate64", /* 193 */ - "ftruncate64", /* 194 */ - "stat64", /* 195 */ - "lstat64", /* 196 */ - "fstat64", /* 197 */ - "lchown32", /* 198 */ - "getuid32", /* 199 */ - "getgid32", /* 200 */ - "geteuid32", /* 201 */ - "getegid32", /* 202 */ - "setreuid32", /* 203 */ - "setregid32", /* 204 */ - "getgroups32", /* 205 */ - "setgroups32", /* 206 */ - "fchown32", /* 207 */ - "setresuid32", /* 208 */ - "getresuid32", /* 209 */ - "setresgid32", /* 210 */ - "getresgid32", /* 211 */ - "chown32", /* 212 */ - "setuid32", /* 213 */ - "setgid32", /* 214 */ - "setfsuid32", /* 215 */ - "setfsgid32", /* 216 */ - "pivot_root", /* 217 */ - "mincore", /* 218 */ - "madvise", /* 219 */ - "getdents64", /* 220 */ - "fcntl64", /* 221 */ - "readahead", /* 222 */ - "sendfile64", /* 223 */ - "setxattr", /* 224 */ - "lsetxattr", /* 225 */ - "fsetxattr", /* 226 */ - "getxattr", /* 227 */ - "lgetxattr", /* 228 */ - "fgetxattr", /* 229 */ - "listxattr", /* 230 */ - "llistxattr", /* 231 */ - "flistxattr", /* 232 */ - "removexattr", /* 233 */ - "lremovexattr", /* 234 */ - "fremovexattr", /* 235 */ - "gettid", /* 236 */ - "tkill", /* 237 */ - "futex", /* 238 */ - "sched_setaffinity", /* 239 */ - "sched_getaffinity", /* 240 */ - "241", /* 241 */ - "242", /* 242 */ - "io_setup", /* 243 */ - "io_destroy", /* 244 */ - "io_getevents", /* 245 */ - "io_submit", /* 246 */ - "io_cancel", /* 247 */ - "exit_group", /* 248 */ - "epoll_create", /* 249 */ - "epoll_ctl", /* 250 */ - "epoll_wait", /* 251 */ - "set_tid_address", /* 252 */ - "fadvise64", /* 253 */ - "timer_create", /* 254 */ - "timer_settime", /* 255 */ - "timer_gettime", /* 256 */ - "timer_getoverrun", /* 257 */ - "timer_delete", /* 258 */ - "clock_settime", /* 259 */ - "clock_gettime", /* 260 */ - "clock_getres", /* 261 */ - "clock_nanosleep", /* 262 */ - "263", /* 263 */ - "fadvise64_64", /* 264 */ - "statfs64", /* 265 */ - "fstatfs64", /* 266 */ - "267", /* 267 */ - "268", /* 268 */ - "269", /* 269 */ - "270", /* 270 */ - "mq_open", /* 271 */ - "mq_unlink", /* 272 */ - "mq_timedsend", /* 273 */ - "mq_timedreceive", /* 274 */ - "mq_notify", /* 275 */ - "mq_getsetattr", /* 276 */ +#ifdef __s390x__ +#include "s390/syscalls64.h" +#else +#include "s390/syscalls31.h" +#endif diff --git a/sysdeps/linux-gnu/s390/syscallent1.h b/sysdeps/linux-gnu/s390/syscallent1.h new file mode 100644 index 0000000..c9fdc81 --- /dev/null +++ b/sysdeps/linux-gnu/s390/syscallent1.h @@ -0,0 +1 @@ +#include "s390/syscalls31.h" diff --git a/sysdeps/linux-gnu/s390/syscalls31.h b/sysdeps/linux-gnu/s390/syscalls31.h new file mode 100644 index 0000000..6f5876b --- /dev/null +++ b/sysdeps/linux-gnu/s390/syscalls31.h @@ -0,0 +1,287 @@ +"0", +"exit", +"fork", +"read", +"write", +"open", +"close", +"7", +"creat", +"link", +"unlink", +"execve", +"chdir", +"time", +"mknod", +"chmod", +"lchown16", +"17", +"18", +"lseek", +"getpid", +"mount", +"oldumount", +"setuid16", +"getuid16", +"stime", +"ptrace", +"alarm", +"28", +"pause", +"utime", +"31", +"32", +"access", +"nice", +"35", +"sync", +"kill", +"rename", +"mkdir", +"rmdir", +"dup", +"pipe", +"times", +"44", +"brk", +"setgid16", +"getgid16", +"signal", +"geteuid16", +"getegid16", +"acct", +"umount", +"53", +"ioctl", +"fcntl", +"56", +"setpgid", +"58", +"59", +"umask", +"chroot", +"ustat", +"dup2", +"getppid", +"getpgrp", +"setsid", +"sigaction", +"68", +"69", +"setreuid16", +"setregid16", +"sigsuspend", +"sigpending", +"sethostname", +"setrlimit", +"old_getrlimit", +"getrusage", +"gettimeofday", +"settimeofday", +"getgroups16", +"setgroups16", +"82", +"symlink", +"84", +"readlink", +"uselib", +"swapon", +"reboot", +"89", +"old_mmap", +"munmap", +"truncate", +"ftruncate", +"fchmod", +"fchown16", +"getpriority", +"setpriority", +"98", +"statfs", +"fstatfs", +"101", +"socketcall", +"syslog", +"setitimer", +"getitimer", +"newstat", +"newlstat", +"newfstat", +"109", +"lookup_dcookie", +"vhangup", +"112", +"113", +"wait4", +"swapoff", +"sysinfo", +"ipc", +"fsync", +"sigreturn", +"clone", +"setdomainname", +"newuname", +"123", +"adjtimex", +"mprotect", +"sigprocmask", +"127", +"init_module", +"delete_module", +"130", +"quotactl", +"getpgid", +"fchdir", +"bdflush", +"sysfs", +"personality", +"137", +"setfsuid16", +"setfsgid16", +"llseek", +"getdents", +"select", +"flock", +"msync", +"readv", +"writev", +"getsid", +"fdatasync", +"sysctl", +"mlock", +"munlock", +"mlockall", +"munlockall", +"sched_setparam", +"sched_getparam", +"sched_setscheduler", +"sched_getscheduler", +"sched_yield", +"sched_get_priority_max", +"sched_get_priority_min", +"sched_rr_get_interval", +"nanosleep", +"mremap", +"setresuid16", +"getresuid16", +"166", +"167", +"poll", +"nfsservctl", +"setresgid16", +"getresgid16", +"prctl", +"rt_sigreturn", +"rt_sigaction", +"rt_sigprocmask", +"rt_sigpending", +"rt_sigtimedwait", +"rt_sigqueueinfo", +"rt_sigsuspend", +"pread64", +"pwrite64", +"chown16", +"getcwd", +"capget", +"capset", +"sigaltstack", +"sendfile", +"188", +"189", +"vfork", +"getrlimit", +"mmap2", +"truncate64", +"ftruncate64", +"stat64", +"lstat64", +"fstat64", +"lchown", +"getuid", +"getgid", +"geteuid", +"getegid", +"setreuid", +"setregid", +"getgroups", +"setgroups", +"fchown", +"setresuid", +"getresuid", +"setresgid", +"getresgid", +"chown", +"setuid", +"setgid", +"setfsuid", +"setfsgid", +"pivot_root", +"mincore", +"madvise", +"getdents64", +"fcntl64", +"readahead", +"sendfile64", +"setxattr", +"lsetxattr", +"fsetxattr", +"getxattr", +"lgetxattr", +"fgetxattr", +"listxattr", +"llistxattr", +"flistxattr", +"removexattr", +"lremovexattr", +"fremovexattr", +"gettid", +"tkill", +"futex", +"sched_setaffinity", +"sched_getaffinity", +"tgkill", +"242", +"io_setup", +"io_destroy", +"io_getevents", +"io_submit", +"io_cancel", +"exit_group", +"epoll_create", +"epoll_ctl", +"epoll_wait", +"set_tid_address", +"fadvise64", +"timer_create", +"timer_settime", +"timer_gettime", +"timer_getoverrun", +"timer_delete", +"clock_settime", +"clock_gettime", +"clock_getres", +"clock_nanosleep", +"263", +"fadvise64_64", +"statfs64", +"fstatfs64", +"remap_file_pages", +"268", +"269", +"270", +"mq_open", +"mq_unlink", +"mq_timedsend", +"mq_timedreceive", +"mq_notify", +"mq_getsetattr", +"kexec_load", +"add_key", +"request_key", +"keyctl", +"waitid", +"ioprio_set", +"ioprio_get", +"inotify_init", +"inotify_add_watch", +"inotify_rm_watch", diff --git a/sysdeps/linux-gnu/s390/syscalls64.h b/sysdeps/linux-gnu/s390/syscalls64.h new file mode 100644 index 0000000..8d48c71 --- /dev/null +++ b/sysdeps/linux-gnu/s390/syscalls64.h @@ -0,0 +1,287 @@ +"0", +"exit", +"fork", +"read", +"write", +"open", +"close", +"7", +"creat", +"link", +"unlink", +"execve", +"chdir", +"13", +"mknod", +"chmod", +"16", +"17", +"18", +"lseek", +"getpid", +"mount", +"oldumount", +"23", +"24", +"25", +"ptrace", +"alarm", +"28", +"pause", +"utime", +"31", +"32", +"access", +"nice", +"35", +"sync", +"kill", +"rename", +"mkdir", +"rmdir", +"dup", +"pipe", +"times", +"44", +"brk", +"46", +"47", +"signal", +"49", +"50", +"acct", +"umount", +"53", +"ioctl", +"fcntl", +"56", +"setpgid", +"58", +"59", +"umask", +"chroot", +"ustat", +"dup2", +"getppid", +"getpgrp", +"setsid", +"sigaction", +"68", +"69", +"70", +"71", +"sigsuspend", +"sigpending", +"sethostname", +"setrlimit", +"getrlimit", +"getrusage", +"gettimeofday", +"settimeofday", +"80", +"81", +"82", +"symlink", +"84", +"readlink", +"uselib", +"swapon", +"reboot", +"89", +"old_mmap", +"munmap", +"truncate", +"ftruncate", +"fchmod", +"95", +"getpriority", +"setpriority", +"98", +"statfs", +"fstatfs", +"101", +"socketcall", +"syslog", +"setitimer", +"getitimer", +"newstat", +"newlstat", +"newfstat", +"109", +"lookup_dcookie", +"vhangup", +"112", +"113", +"wait4", +"swapoff", +"sysinfo", +"ipc", +"fsync", +"sigreturn", +"clone", +"setdomainname", +"newuname", +"123", +"adjtimex", +"mprotect", +"sigprocmask", +"127", +"init_module", +"delete_module", +"130", +"quotactl", +"getpgid", +"fchdir", +"bdflush", +"sysfs", +"personality", +"137", +"138", +"139", +"llseek", +"getdents", +"select", +"flock", +"msync", +"readv", +"writev", +"getsid", +"fdatasync", +"sysctl", +"mlock", +"munlock", +"mlockall", +"munlockall", +"sched_setparam", +"sched_getparam", +"sched_setscheduler", +"sched_getscheduler", +"sched_yield", +"sched_get_priority_max", +"sched_get_priority_min", +"sched_rr_get_interval", +"nanosleep", +"mremap", +"164", +"165", +"166", +"167", +"poll", +"nfsservctl", +"170", +"171", +"prctl", +"rt_sigreturn", +"rt_sigaction", +"rt_sigprocmask", +"rt_sigpending", +"rt_sigtimedwait", +"rt_sigqueueinfo", +"rt_sigsuspend", +"pread64", +"pwrite64", +"182", +"getcwd", +"capget", +"capset", +"sigaltstack", +"sendfile64", +"188", +"189", +"vfork", +"getrlimit", +"mmap2", +"193", +"194", +"195", +"196", +"197", +"lchown", +"getuid", +"getgid", +"geteuid", +"getegid", +"setreuid", +"setregid", +"getgroups", +"setgroups", +"fchown", +"setresuid", +"getresuid", +"setresgid", +"getresgid", +"chown", +"setuid", +"setgid", +"setfsuid", +"setfsgid", +"pivot_root", +"mincore", +"madvise", +"getdents64", +"221", +"readahead", +"223", +"setxattr", +"lsetxattr", +"fsetxattr", +"getxattr", +"lgetxattr", +"fgetxattr", +"listxattr", +"llistxattr", +"flistxattr", +"removexattr", +"lremovexattr", +"fremovexattr", +"gettid", +"tkill", +"futex", +"sched_setaffinity", +"sched_getaffinity", +"tgkill", +"242", +"io_setup", +"io_destroy", +"io_getevents", +"io_submit", +"io_cancel", +"exit_group", +"epoll_create", +"epoll_ctl", +"epoll_wait", +"set_tid_address", +"fadvise64_64", +"timer_create", +"timer_settime", +"timer_gettime", +"timer_getoverrun", +"timer_delete", +"clock_settime", +"clock_gettime", +"clock_getres", +"clock_nanosleep", +"263", +"264", +"statfs64", +"fstatfs64", +"remap_file_pages", +"268", +"269", +"270", +"mq_open", +"mq_unlink", +"mq_timedsend", +"mq_timedreceive", +"mq_notify", +"mq_getsetattr", +"kexec_load", +"add_key", +"request_key", +"keyctl", +"waitid", +"ioprio_set", +"ioprio_get", +"inotify_init", +"inotify_add_watch", +"inotify_rm_watch", diff --git a/sysdeps/linux-gnu/s390/trace.c b/sysdeps/linux-gnu/s390/trace.c index 2208555..e0e55a4 100644 --- a/sysdeps/linux-gnu/s390/trace.c +++ b/sysdeps/linux-gnu/s390/trace.c @@ -4,14 +4,15 @@ ** Other routines are in ../trace.c and need to be combined ** at link time with this code. ** -** S/390 version -** Copyright (C) 2001 IBM Poughkeepsie, IBM Corporation +** Copyright (C) 2001,2005 IBM Corp. */ #if HAVE_CONFIG_H #include "config.h" #endif +#include <errno.h> +#include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> @@ -28,75 +29,165 @@ # define PTRACE_POKEUSER PTRACE_POKEUSR #endif -void get_arch_dep(struct process *proc) -{ +void +get_arch_dep(struct process * proc) { +#ifdef __s390x__ + unsigned long psw; + + if (proc->arch_ptr) + return; + + psw = ptrace(PTRACE_PEEKUSER, proc->pid, PT_PSWMASK, 0); + + if ((psw & 0x000000180000000) == 0x000000080000000) { + proc->mask_32bit = 1; + proc->personality = 1; + } + + proc->arch_ptr = (void *) 1; +#endif } /* Returns 1 if syscall, 2 if sysret, 0 otherwise. */ -int syscall_p(struct process *proc, int status, int *sysnum) -{ - long pswa; - long svcinst; - long svcno; - long svcop; +int +syscall_p(struct process * proc, int status, int * sysnum) { + long pc, opcode, offset_reg, scno, tmp; + void *svc_addr; + int gpr_offset[16] = {PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3, + PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7, + PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11, + PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15}; - if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { + if (WIFSTOPPED(status) && WSTOPSIG(status)==(SIGTRAP | proc->tracesysgood)) { - pswa = ptrace(PTRACE_PEEKUSER, proc->pid, PT_PSWADDR, 0); - svcinst = - ptrace(PTRACE_PEEKTEXT, proc->pid, (char *)(pswa - 4), 0); - svcop = (svcinst >> 8) & 0xFF; - svcno = svcinst & 0xFF; + /* + * If we have PTRACE_O_TRACESYSGOOD and we have the new style + * of passing the system call number to user space via PT_GPR2 + * then the task is quite easy. + */ - *sysnum = svcno; + *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR2, 0); - if (*sysnum == -1) { - return 0; - } - if (svcop == 0 && svcno == 1) { - /* Breakpoint was hit... */ - return 0; - } - if (svcop == 10 && *sysnum >= 0) { + if (proc->tracesysgood) { /* System call was encountered... */ if (proc->callstack_depth > 0 && - proc->callstack[proc->callstack_depth - - 1].is_syscall) { + proc->callstack[proc->callstack_depth-1].is_syscall) { + /* syscall exit */ + *sysnum = proc->callstack[proc->callstack_depth-1].c_un.syscall; return 2; } else { - return 1; + /* syscall enter */ + if (*sysnum != -ENOSYS) + return 1; } - } else { - /* Unknown trap was encountered... */ + } + + /* + * At least one of the two requirements mentioned above is not + * met. Therefore the fun part starts here: + * We try to do some instruction decoding without even knowing + * the instruction code length of the last instruction executed. + * Needs to be done to get the system call number or to decide + * if we reached a breakpoint or even checking for a completely + * unrelated instruction. + * Just a heuristic that most of the time appears to work... + */ + + pc = ptrace(PTRACE_PEEKUSER, proc->pid, PT_PSWADDR, 0); + opcode = ptrace(PTRACE_PEEKTEXT, proc->pid, + (char *)(pc-sizeof(long)),0); + + if ((opcode & 0xffff) == 0x0001) { + /* Breakpoint */ return 0; } + else if ((opcode & 0xff00) == 0x0a00) { + /* SVC opcode */ + scno = opcode & 0xff; + } + else if ((opcode & 0xff000000) == 0x44000000) { + /* Instruction decoding of EXECUTE... */ + svc_addr = (void *) (opcode & 0xfff); + + offset_reg = (opcode & 0x000f0000) >> 16; + if (offset_reg) + svc_addr += ptrace(PTRACE_PEEKUSER, proc->pid, + gpr_offset[offset_reg], 0); + + offset_reg = (opcode & 0x0000f000) >> 12; + if (offset_reg) + svc_addr += ptrace(PTRACE_PEEKUSER, proc->pid, + gpr_offset[offset_reg], 0); + + scno = ptrace(PTRACE_PEEKTEXT, proc->pid, svc_addr, 0); +#ifdef __s390x__ + scno >>= 48; +#else + scno >>= 16; +#endif + if ((scno & 0xff00) != 0x0a000) + return 0; + + tmp = 0; + offset_reg = (opcode & 0x00f00000) >> 20; + if (offset_reg) + tmp = ptrace(PTRACE_PEEKUSER, proc->pid, + gpr_offset[offset_reg], 0); + + scno = (scno | tmp) & 0xff; + } + else { + /* No opcode related to syscall handling */ + return 0; + } + + if (scno == 0) + scno = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR1, 0); + + *sysnum = scno; + + /* System call was encountered... */ + if (proc->callstack_depth > 0 && + proc->callstack[proc->callstack_depth-1].is_syscall) { + return 2; + } else { + return 1; + } } /* Unknown status... */ return 0; } -long gimme_arg(enum tof type, struct process *proc, int arg_num) -{ - switch (arg_num) { - case -1: /* return value */ - return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR2, 0); - case 0: - return ptrace(PTRACE_PEEKUSER, proc->pid, PT_ORIGGPR2, 0); - case 1: - return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR3, 0); - case 2: - return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR4, 0); - case 3: - return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR5, 0); - case 4: - return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR6, 0); - default: - fprintf(stderr, "gimme_arg called with wrong arguments\n"); - exit(2); +long +gimme_arg(enum tof type, struct process * proc, int arg_num) { + long ret; + + switch(arg_num) { + case -1: /* return value */ + ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR2, 0); + break; + case 0: ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_ORIGGPR2, 0); + break; + case 1: ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR3, 0); + break; + case 2: ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR4, 0); + break; + case 3: ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR5, 0); + break; + case 4: ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR6, 0); + break; + default: + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + exit(2); } +#ifdef __s390x__ + if (proc->mask_32bit) + ret &= 0xffffffff; +#endif + return ret; } -void save_register_args(enum tof type, struct process *proc) -{ +void +save_register_args(enum tof type, struct process * proc) { } diff --git a/sysdeps/linux-gnu/sparc/arch.h b/sysdeps/linux-gnu/sparc/arch.h index d2f85d2..b3d3006 100644 --- a/sysdeps/linux-gnu/sparc/arch.h +++ b/sysdeps/linux-gnu/sparc/arch.h @@ -4,4 +4,8 @@ #define LT_ELFCLASS ELFCLASS32 #define LT_ELF_MACHINE EM_SPARC +#define LT_ELFCLASS2 ELFCLASS32 #define LT_ELF_MACHINE2 EM_SPARC32PLUS + +#define PLTs_INIT_BY_HERE NULL +#define E_ENTRY_NAME "_start" diff --git a/sysdeps/linux-gnu/sparc/plt.c b/sysdeps/linux-gnu/sparc/plt.c index 5a2edac..e39bb58 100644 --- a/sysdeps/linux-gnu/sparc/plt.c +++ b/sysdeps/linux-gnu/sparc/plt.c @@ -2,7 +2,13 @@ #include "ltrace.h" #include "elf.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 + 4; + return rela->r_offset + 4; +} + +void * plt2addr(struct process *proc, void ** plt) +{ + return (void *) plt; } diff --git a/sysdeps/linux-gnu/sparc/regs.c b/sysdeps/linux-gnu/sparc/regs.c index 1f2861a..78efec3 100644 --- a/sysdeps/linux-gnu/sparc/regs.c +++ b/sysdeps/linux-gnu/sparc/regs.c @@ -6,32 +6,32 @@ #include "ptrace.h" #include "ltrace.h" -void *get_instruction_pointer(struct process *proc) -{ - proc_archdep *a = (proc_archdep *) (proc->arch_ptr); +void * +get_instruction_pointer(struct process * proc) { + proc_archdep *a = (proc_archdep *)(proc->arch_ptr); if (a->valid) return (void *)a->regs.r_pc; return (void *)-1; } -void set_instruction_pointer(struct process *proc, void *addr) -{ - proc_archdep *a = (proc_archdep *) (proc->arch_ptr); +void +set_instruction_pointer(struct process * proc, void * addr) { + proc_archdep *a = (proc_archdep *)(proc->arch_ptr); if (a->valid) a->regs.r_pc = (long)addr; } -void *get_stack_pointer(struct process *proc) -{ - proc_archdep *a = (proc_archdep *) (proc->arch_ptr); +void * +get_stack_pointer(struct process * proc) { + proc_archdep *a = (proc_archdep *)(proc->arch_ptr); if (a->valid) return (void *)a->regs.r_o6; return (void *)-1; } -void *get_return_addr(struct process *proc, void *stack_pointer) -{ - proc_archdep *a = (proc_archdep *) (proc->arch_ptr); +void * +get_return_addr(struct process * proc, void * stack_pointer) { + proc_archdep *a = (proc_archdep *)(proc->arch_ptr); unsigned int t; if (!a->valid) return (void *)-1; diff --git a/sysdeps/linux-gnu/sparc/syscallent.h b/sysdeps/linux-gnu/sparc/syscallent.h index c7ddc4f..3b6f7fe 100644 --- a/sysdeps/linux-gnu/sparc/syscallent.h +++ b/sysdeps/linux-gnu/sparc/syscallent.h @@ -149,12 +149,12 @@ "pciconfig_read", /* 148 */ "pciconfig_write", /* 149 */ "getsockname", /* 150 */ - "151", /* 151 */ - "152", /* 152 */ + "inotify_init", /* 151 */ + "inotify_add_watch", /* 152 */ "poll", /* 153 */ "getdents64", /* 154 */ "fcntl64", /* 155 */ - "156", /* 156 */ + "inotify_rm_watch", /* 156 */ "statfs", /* 157 */ "fstatfs", /* 158 */ "umount", /* 159 */ @@ -194,7 +194,7 @@ "epoll_create", /* 193 */ "epoll_ctl", /* 194 */ "epoll_wait", /* 195 */ - "196", /* 196 */ + "ioprio_set", /* 196 */ "getppid", /* 197 */ "sigaction", /* 198 */ "sgetmask", /* 199 */ @@ -216,7 +216,7 @@ "ipc", /* 215 */ "sigreturn", /* 216 */ "clone", /* 217 */ - "218", /* 218 */ + "ioprio_get", /* 218 */ "adjtimex", /* 219 */ "sigprocmask", /* 220 */ "create_module", /* 221 */ @@ -278,3 +278,7 @@ "mq_notify", /* 277 */ "mq_getsetattr", /* 278 */ "waitid", /* 279 */ + "setaltroot", /* 280 */ + "add_key", /* 281 */ + "request_key", /* 282 */ + "keyctl", /* 283 */ diff --git a/sysdeps/linux-gnu/sparc/trace.c b/sysdeps/linux-gnu/sparc/trace.c index 1f407e5..c39de44 100644 --- a/sysdeps/linux-gnu/sparc/trace.c +++ b/sysdeps/linux-gnu/sparc/trace.c @@ -18,8 +18,8 @@ void get_arch_dep(struct process *proc) proc_archdep *a; if (!proc->arch_ptr) proc->arch_ptr = (void *)malloc(sizeof(proc_archdep)); - a = (proc_archdep *) (proc->arch_ptr); - a->valid = (ptrace(PTRACE_GETREGS, proc->pid, &a->regs, 0) >= 0); + a = (proc_archdep *)(proc->arch_ptr); + a->valid = (ptrace (PTRACE_GETREGS, proc->pid, &a->regs, 0) >= 0); } /* Returns syscall number if `pid' stopped because of a syscall. @@ -27,19 +27,16 @@ void get_arch_dep(struct process *proc) */ int syscall_p(struct process *proc, int status, int *sysnum) { - if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { + if (WIFSTOPPED(status) && WSTOPSIG(status)==(SIGTRAP | proc->tracesysgood)) { void *ip = get_instruction_pointer(proc); unsigned int insn; - if (ip == (void *)-1) - return 0; + if (ip == (void *)-1) return 0; insn = ptrace(PTRACE_PEEKTEXT, proc->pid, ip, 0); if ((insn & 0xc1f8007f) == 0x81d00010) { - *sysnum = ((proc_archdep *) proc->arch_ptr)->regs.r_g1; - if ((proc->callstack_depth > 0) - && proc->callstack[proc->callstack_depth - - 1].is_syscall) { + *sysnum = ((proc_archdep *)proc->arch_ptr)->regs.r_g1; + if ((proc->callstack_depth > 0) && proc->callstack[proc->callstack_depth-1].is_syscall) { return 2; - } else if (*sysnum >= 0) { + } else if(*sysnum>=0) { return 1; } } @@ -47,24 +44,23 @@ int syscall_p(struct process *proc, int status, int *sysnum) return 0; } -long gimme_arg(enum tof type, struct process *proc, int arg_num) +long gimme_arg(enum tof type, struct process * proc, int arg_num) { - proc_archdep *a = (proc_archdep *) proc->arch_ptr; + proc_archdep * a = (proc_archdep *)proc->arch_ptr; if (!a->valid) { fprintf(stderr, "Could not get child registers\n"); exit(1); } - if (arg_num == -1) /* return value */ + if (arg_num==-1) /* return value */ return a->regs.r_o0; - if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL || arg_num >= 6) { + if (type==LT_TOF_FUNCTION || type==LT_TOF_SYSCALL || arg_num >= 6) { if (arg_num < 6) return ((int *)&a->regs.r_o0)[arg_num]; - return ptrace(PTRACE_PEEKTEXT, proc->pid, - proc->stack_pointer + 64 * (arg_num + 1)); - } else if (type == LT_TOF_FUNCTIONR) + return ptrace(PTRACE_PEEKTEXT, proc->pid, proc->stack_pointer+64*(arg_num + 1)); + } else if (type==LT_TOF_FUNCTIONR) return a->func_arg[arg_num]; - else if (type == LT_TOF_SYSCALLR) + else if (type==LT_TOF_SYSCALLR) return a->sysc_arg[arg_num]; else { fprintf(stderr, "gimme_arg called with wrong arguments\n"); @@ -73,9 +69,9 @@ long gimme_arg(enum tof type, struct process *proc, int arg_num) return 0; } -void save_register_args(enum tof type, struct process *proc) +void save_register_args(enum tof type, struct process * proc) { - proc_archdep *a = (proc_archdep *) proc->arch_ptr; + proc_archdep * a = (proc_archdep *)proc->arch_ptr; if (a->valid) { if (type == LT_TOF_FUNCTION) memcpy(a->func_arg, &a->regs.r_o0, sizeof(a->func_arg)); diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c index bbf40e6..cbcce4d 100644 --- a/sysdeps/linux-gnu/trace.c +++ b/sysdeps/linux-gnu/trace.c @@ -9,87 +9,140 @@ #include "ltrace.h" #include "options.h" +#include "sysdep.h" -/* Returns 1 if the sysnum may make a new child to be created - * (ie, with fork() or clone()) - * Returns 0 otherwise. - */ -int fork_p(int sysnum) +static int fork_exec_syscalls[][5] = { { - return 0 -#if defined(__NR_fork) - || (sysnum == __NR_fork) +#ifdef __NR_fork + __NR_fork, +#else + -1, #endif -#if defined(__NR_clone) - || (sysnum == __NR_clone) +#ifdef __NR_clone + __NR_clone, +#else + -1, #endif -#if defined(__NR_vfork) - || (sysnum == __NR_vfork) +#ifdef __NR_clone2 + __NR_clone2, +#else + -1, #endif -#if defined(__NR_clone2) - || (sysnum == __NR_clone2) +#ifdef __NR_vfork + __NR_vfork, +#else + -1, +#endif +#ifdef __NR_execve + __NR_execve, +#else + -1, #endif - ; +} +#ifdef FORK_EXEC_SYSCALLS +FORK_EXEC_SYSCALLS +#endif +}; + +/* Returns 1 if the sysnum may make a new child to be created + * (ie, with fork() or clone()) + * Returns 0 otherwise. + */ +int +fork_p(struct process * proc, int sysnum) { + int i; + if (proc->personality + >= sizeof fork_exec_syscalls / sizeof (fork_exec_syscalls [0])) + return 0; + for (i = 0; i < sizeof (fork_exec_syscalls[0]) / sizeof (int) - 1; ++i) + if (sysnum == fork_exec_syscalls[proc->personality][i]) + return 1; + return 0; } /* Returns 1 if the sysnum may make the process exec other program */ -int exec_p(int sysnum) -{ - return (sysnum == __NR_execve); +int +exec_p(struct process * proc, int sysnum) { + int i; + if (proc->personality + >= sizeof fork_exec_syscalls / sizeof (fork_exec_syscalls [0])) + return 0; + i = sizeof (fork_exec_syscalls[0]) / sizeof (int) - 1; + if (sysnum == fork_exec_syscalls[proc->personality][i]) + return 1; + return 0; } -void trace_me(void) -{ - if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) { +void +trace_me(void) { + if (ptrace(PTRACE_TRACEME, 0, 1, 0)<0) { perror("PTRACE_TRACEME"); exit(1); } } -int trace_pid(pid_t pid) -{ +int +trace_pid(pid_t pid) { if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) { return -1; } return 0; } -void untrace_pid(pid_t pid) -{ +void +trace_set_options(struct process * proc, pid_t pid) { +#ifndef PTRACE_SETOPTIONS + #define PTRACE_SETOPTIONS 0x4200 +#endif +#ifndef PTRACE_OLDSETOPTIONS + #define PTRACE_OLDSETOPTIONS 21 +#endif +#ifndef PTRACE_O_TRACESYSGOOD + #define PTRACE_O_TRACESYSGOOD 0x00000001 +#endif + if (proc->tracesysgood & 0x80) + return; + if (ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0 && + ptrace(PTRACE_OLDSETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0) { + perror("PTRACE_SETOPTIONS"); + return; + } + proc->tracesysgood |= 0x80; +} + +void +untrace_pid(pid_t pid) { ptrace(PTRACE_DETACH, pid, 1, 0); } -void continue_after_signal(pid_t pid, int signum) -{ +void +continue_after_signal(pid_t pid, int signum) { /* We should always trace syscalls to be able to control fork(), clone(), execve()... */ ptrace(PTRACE_SYSCALL, pid, 0, signum); } -void continue_process(pid_t pid) -{ +void +continue_process(pid_t pid) { continue_after_signal(pid, 0); } -void continue_enabling_breakpoint(pid_t pid, struct breakpoint *sbp) -{ +void +continue_enabling_breakpoint(pid_t pid, struct breakpoint * sbp) { enable_breakpoint(pid, sbp); continue_process(pid); } -void continue_after_breakpoint(struct process *proc, struct breakpoint *sbp) -{ - if (sbp->enabled) - disable_breakpoint(proc->pid, sbp); - +void +continue_after_breakpoint(struct process *proc, struct breakpoint * sbp) { + if (sbp->enabled) disable_breakpoint(proc->pid, sbp); set_instruction_pointer(proc, sbp->addr); - if (sbp->enabled == 0) { continue_process(proc->pid); } else { proc->breakpoint_being_enabled = sbp; -#ifdef __sparc__ || defined __ia64__ - /* we don't want to single step here */ +#if defined __sparc__ || defined __ia64___ + /* we don't want to singlestep here */ continue_process(proc->pid); #else ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0); @@ -97,27 +150,24 @@ void continue_after_breakpoint(struct process *proc, struct breakpoint *sbp) } } -int umovestr(struct process *proc, void *addr, int len, void *laddr) -{ - union { - long a; - char c[sizeof(long)]; - } a; +int +umovestr(struct process * proc, void * addr, int len, void * laddr) { + union { long a; char c[sizeof(long)]; } a; int i; - int offset = 0; + int offset=0; - while (offset < len) { - a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0); - for (i = 0; i < sizeof(long); i++) { - if (a.c[i] && offset + i < len) { - *(char *)(laddr + offset + i) = a.c[i]; + while(offset<len) { + a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr+offset, 0); + for(i=0; i<sizeof(long); i++) { + if (a.c[i] && offset+i < len) { + *(char *)(laddr+offset+i) = a.c[i]; } else { - *(char *)(laddr + offset + i) = '\0'; + *(char *)(laddr+offset+i) = '\0'; return 0; } } offset += sizeof(long); } - *(char *)(laddr + offset) = '\0'; + *(char *)(laddr+offset) = '\0'; return 0; } diff --git a/sysdeps/linux-gnu/x86_64/arch.h b/sysdeps/linux-gnu/x86_64/arch.h index a7c8816..e819d2c 100644 --- a/sysdeps/linux-gnu/x86_64/arch.h +++ b/sysdeps/linux-gnu/x86_64/arch.h @@ -4,3 +4,12 @@ #define LT_ELFCLASS ELFCLASS64 #define LT_ELF_MACHINE EM_X86_64 +#define LT_ELFCLASS2 ELFCLASS32 +#define LT_ELF_MACHINE2 EM_386 + +#define PLTs_INIT_BY_HERE NULL +#define E_ENTRY_NAME "_start" + +/* __NR_fork, __NR_clone, __NR_clone2, __NR_vfork and __NR_execve + from asm-i386/unistd.h. */ +#define FORK_EXEC_SYSCALLS , { 2, 120, -1, 190, 11 } diff --git a/sysdeps/linux-gnu/x86_64/plt.c b/sysdeps/linux-gnu/x86_64/plt.c index 939bc4e..36d0ecd 100644 --- a/sysdeps/linux-gnu/x86_64/plt.c +++ b/sysdeps/linux-gnu/x86_64/plt.c @@ -2,7 +2,13 @@ #include "ltrace.h" #include "elf.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 lte->plt_addr + (ndx + 1) * 16; + return lte->plt_addr + (ndx + 1) * 16; +} + +void * plt2addr(struct process *proc, void ** plt) +{ + return (void *) plt; } diff --git a/sysdeps/linux-gnu/x86_64/regs.c b/sysdeps/linux-gnu/x86_64/regs.c index a2a27a9..29160b3 100644 --- a/sysdeps/linux-gnu/x86_64/regs.c +++ b/sysdeps/linux-gnu/x86_64/regs.c @@ -16,22 +16,34 @@ # define PTRACE_POKEUSER PTRACE_POKEUSR #endif -void *get_instruction_pointer(struct process *proc) -{ - return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RIP, 0); +void * +get_instruction_pointer(struct process * proc) { + long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, 8*RIP, 0); + if (proc->mask_32bit) + ret &= 0xffffffff; + return (void *)ret; } -void set_instruction_pointer(struct process *proc, void *addr) -{ - ptrace(PTRACE_POKEUSER, proc->pid, 8 * RIP, addr); +void +set_instruction_pointer(struct process * proc, void * addr) { + if (proc->mask_32bit) + addr = (void *)((long int) addr & 0xffffffff); + ptrace(PTRACE_POKEUSER, proc->pid, 8*RIP, addr); } -void *get_stack_pointer(struct process *proc) -{ - return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RSP, 0); +void * +get_stack_pointer(struct process * proc) { + long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, 8*RSP, 0); + if (proc->mask_32bit) + ret &= 0xffffffff; + return (void *)ret; } -void *get_return_addr(struct process *proc, void *stack_pointer) -{ - return (void *)ptrace(PTRACE_PEEKTEXT, proc->pid, stack_pointer, 0); +void * +get_return_addr(struct process * proc, void * stack_pointer) { + unsigned long int ret; + ret = ptrace(PTRACE_PEEKTEXT, proc->pid, stack_pointer, 0); + if (proc->mask_32bit) + ret &= 0xffffffff; + return (void *)ret; } diff --git a/sysdeps/linux-gnu/x86_64/signalent1.h b/sysdeps/linux-gnu/x86_64/signalent1.h new file mode 100644 index 0000000..5ead946 --- /dev/null +++ b/sysdeps/linux-gnu/x86_64/signalent1.h @@ -0,0 +1 @@ +#include "i386/signalent.h" diff --git a/sysdeps/linux-gnu/x86_64/syscallent.h b/sysdeps/linux-gnu/x86_64/syscallent.h index 31aa74a..e98f98c 100644 --- a/sysdeps/linux-gnu/x86_64/syscallent.h +++ b/sysdeps/linux-gnu/x86_64/syscallent.h @@ -246,3 +246,11 @@ "mq_getsetattr", /* 245 */ "kexec_load", /* 246 */ "waitid", /* 247 */ + "add_key", /* 248 */ + "request_key", /* 249 */ + "keyctl", /* 250 */ + "ioprio_set", /* 251 */ + "ioprio_get", /* 252 */ + "inotify_init", /* 253 */ + "inotify_add_watch", /* 254 */ + "inotify_rm_watch", /* 255 */ diff --git a/sysdeps/linux-gnu/x86_64/syscallent1.h b/sysdeps/linux-gnu/x86_64/syscallent1.h new file mode 100644 index 0000000..d8dd9f7 --- /dev/null +++ b/sysdeps/linux-gnu/x86_64/syscallent1.h @@ -0,0 +1 @@ +#include "i386/syscallent.h" diff --git a/sysdeps/linux-gnu/x86_64/trace.c b/sysdeps/linux-gnu/x86_64/trace.c index 3232afd..f08583d 100644 --- a/sysdeps/linux-gnu/x86_64/trace.c +++ b/sysdeps/linux-gnu/x86_64/trace.c @@ -21,73 +21,93 @@ void get_arch_dep(struct process *proc) { + unsigned long cs; + if (proc->arch_ptr) + return; + cs = ptrace(PTRACE_PEEKUSER, proc->pid, 8*CS, 0); + if (cs == 0x23) { + proc->mask_32bit = 1; + proc->personality = 1; + } + proc->arch_ptr = (void *) 1; } /* Returns 1 if syscall, 2 if sysret, 0 otherwise. */ -int syscall_p(struct process *proc, int status, int *sysnum) -{ - if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { - *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, 8 * ORIG_RAX, 0); +int +syscall_p(struct process * proc, int status, int * sysnum) { + if (WIFSTOPPED(status) && WSTOPSIG(status)==(SIGTRAP | proc->tracesysgood)) { + *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, 8*ORIG_RAX, 0); if (proc->callstack_depth > 0 && - proc->callstack[proc->callstack_depth - 1].is_syscall) { + proc->callstack[proc->callstack_depth-1].is_syscall) { return 2; } - if (*sysnum >= 0) { + if (*sysnum>=0) { return 1; } } 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, 8 * RAX, 0); +static unsigned int +gimme_arg32(enum tof type, struct process * proc, int arg_num) { + if (arg_num==-1) { /* return value */ + return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RAX, 0); + } + + if (type==LT_TOF_FUNCTION || type==LT_TOF_FUNCTIONR) { + return ptrace(PTRACE_PEEKTEXT, proc->pid, proc->stack_pointer+4*(arg_num+1), 0); + } else if (type==LT_TOF_SYSCALL || type==LT_TOF_SYSCALLR) { + switch(arg_num) { + case 0: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RBX, 0); + case 1: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RCX, 0); + case 2: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RDX, 0); + case 3: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RSI, 0); + case 4: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RDI, 0); + case 5: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RBP, 0); + default: + fprintf(stderr, "gimme_arg32 called with wrong arguments\n"); + exit(2); + } + } + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + exit(1); +} + +long +gimme_arg(enum tof type, struct process * proc, int arg_num) { + if (proc->mask_32bit) + return (unsigned int)gimme_arg32(type, proc, arg_num); + + if (arg_num==-1) { /* return value */ + return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RAX, 0); } - if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) { - switch (arg_num) { - case 0: - return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDI, 0); - case 1: - return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RSI, 0); - case 2: - return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDX, 0); - case 3: - return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RCX, 0); - case 4: - return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R8, 0); - case 5: - return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R9, 0); - default: - return ptrace(PTRACE_PEEKTEXT, proc->pid, - proc->stack_pointer + 8 * (arg_num - 6 + - 1), 0); - fprintf(stderr, - "gimme_arg called with wrong arguments\n"); - exit(2); + if (type==LT_TOF_FUNCTION || type==LT_TOF_FUNCTIONR) { + switch(arg_num) { + case 0: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RDI, 0); + case 1: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RSI, 0); + case 2: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RDX, 0); + case 3: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RCX, 0); + case 4: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*R8, 0); + case 5: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*R9, 0); + default: + return ptrace(PTRACE_PEEKTEXT, proc->pid, + proc->stack_pointer + 8 * (arg_num - 6 + 1), 0); } - } else if (type == LT_TOF_SYSCALL || LT_TOF_SYSCALLR) { - switch (arg_num) { - case 0: - return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDI, 0); - case 1: - return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RSI, 0); - case 2: - return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDX, 0); - case 3: - return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R10, 0); - case 4: - return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R8, 0); - case 5: - return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R9, 0); - default: - fprintf(stderr, - "gimme_arg called with wrong arguments\n"); - exit(2); + } else if (type==LT_TOF_SYSCALL || LT_TOF_SYSCALLR) { + switch(arg_num) { + case 0: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RDI, 0); + case 1: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RSI, 0); + case 2: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*RDX, 0); + case 3: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*R10, 0); + case 4: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*R8, 0); + case 5: return ptrace(PTRACE_PEEKUSER, proc->pid, 8*R9, 0); + default: + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + exit(2); } } else { fprintf(stderr, "gimme_arg called with wrong arguments\n"); @@ -97,6 +117,6 @@ long gimme_arg(enum tof type, struct process *proc, int arg_num) return 0; } -void save_register_args(enum tof type, struct process *proc) +void save_register_args(enum tof type, struct process * proc) { } |