diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-11-13 07:28:12 -0800 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-11-13 07:28:12 -0800 |
commit | 59749d048d9e452f049f9151735b5256756919c3 (patch) | |
tree | 9b0935c93a3b028fd1dd35a2c632510743e7826f /sysdeps | |
download | ltrace-59749d048d9e452f049f9151735b5256756919c3.tar.gz ltrace-59749d048d9e452f049f9151735b5256756919c3.tar.bz2 ltrace-59749d048d9e452f049f9151735b5256756919c3.zip |
Imported Upstream version 0.5.3upstream/0.5.3
Diffstat (limited to 'sysdeps')
103 files changed, 8426 insertions, 0 deletions
diff --git a/sysdeps/README b/sysdeps/README new file mode 100644 index 0000000..ce033ef --- /dev/null +++ b/sysdeps/README @@ -0,0 +1,32 @@ +Each operating system must have a subdir here, with a Makefile +The first target of that Makefile must build a file "sysdep.o" in this +directory. +The "clean" target of that Makefile must undo all the efects of the +first target, and must remove "sysdep.o" in this dir. + +Files "sysdep.h", "signalent.h" and "syscallent.h" must be present +inside the directory after invoking the first target of the Makefile. + +----------- +"sysdep.o" must export the following functions: + +Event * next_event(void); +void continue_after_breakpoint(Process * proc, Breakpoint * sbp, int delete_it); +void continue_after_signal(pid_t pid, int signum); +void continue_enabling_breakpoint(pid_t pid, Breakpoint * sbp); +void continue_process(pid_t pid); +void enable_breakpoint(pid_t pid, Breakpoint * sbp); +void disable_breakpoint(pid_t pid, Breakpoint * sbp); +int fork_p(int sysnum); +int exec_p(int sysnum); +int syscall_p(Process * proc, int status, int * sysnum); +void * get_instruction_pointer(pid_t pid); +void * get_stack_pointer(pid_t pid); +void * get_return_addr(pid_t pid, void * stack_pointer); +long gimme_arg(enum tof type, Process * proc, arg_type_info*); +int umovestr(Process * proc, void * addr, int len, void * laddr); +int umovelong(Process * proc, void * addr, long * result); +char * pid2name(pid_t pid); +void trace_me(void); +int trace_pid(pid_t pid); +void untrace_pid(pid_t pid); diff --git a/sysdeps/linux-gnu/Makefile b/sysdeps/linux-gnu/Makefile new file mode 100644 index 0000000..eb1ec60 --- /dev/null +++ b/sysdeps/linux-gnu/Makefile @@ -0,0 +1,60 @@ +ARCH := $(shell uname -m | sed \ + -e s/i.86/i386/ \ + -e s/sun4u/sparc64/ \ + -e s/sparc64/sparc/ \ + -e s/arm.*/arm/ \ + -e s/sa110/arm/ \ + -e s/ppc64/ppc/ \ + -e s/s390x/s390/ \ + ) + +CPPFLAGS += -I$(TOPDIR)/sysdeps/linux-gnu/$(ARCH) + +OBJ = events.o trace.o proc.o breakpoint.o + +all: sysdep.h signalent.h syscallent.h arch_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 + +arch_syscallent.h: + if [ -f $(ARCH)/arch_syscallent.h ]; then \ + cp $(ARCH)/arch_syscallent.h arch_syscallent.h; \ + else \ + > arch_syscallent.h; \ + fi + +../sysdep.o: os.o $(ARCH)/arch.o + $(CC) -nostdlib -r -o ../sysdep.o os.o $(ARCH)/arch.o + +os.o: $(OBJ) + $(CC) -nostdlib -r -o os.o $(OBJ) + +$(ARCH)/arch.o: dummy + $(MAKE) -C $(ARCH) + +clean: + $(MAKE) -C $(ARCH) clean + rm -f $(OBJ) sysdep.h signalent.h signalent1.h syscallent.h arch_syscallent.h + rm -f syscallent1.h os.o sysdep.o ../sysdep.o + +dummy: diff --git a/sysdeps/linux-gnu/README b/sysdeps/linux-gnu/README new file mode 100644 index 0000000..a8bc8ee --- /dev/null +++ b/sysdeps/linux-gnu/README @@ -0,0 +1,13 @@ +* "arch/syscallent.h" is made from <asm/unistd.h>. + It can be done automatically with "mksyscallent" for all the + architectures except "mips" (as of linux-2.2.12) + +* "arch/signalent.h" is made from <asm/signal.h>. + It can be done automatically with "mksignalent" for all the + architectures. (linux-2.2.12) + +* s390 uses mksyscallent_s390, rather than mksyscallent + +* NOTE: This does not currently work for cross-compilers; Maybe + I should guess the architecture using `gcc -print-libgcc-file-name' + instead of `uname -m' (or even better, use the value returned by autoconf) diff --git a/sysdeps/linux-gnu/alpha/Makefile b/sysdeps/linux-gnu/alpha/Makefile new file mode 100644 index 0000000..60d7531 --- /dev/null +++ b/sysdeps/linux-gnu/alpha/Makefile @@ -0,0 +1,10 @@ +OBJ = trace.o regs.o plt.o + +all: arch.o + +arch.o: $(OBJ) + $(CC) -nostdlib -r -o arch.o $(OBJ) + +clean: + $(RM) $(OBJ) arch.o + diff --git a/sysdeps/linux-gnu/alpha/arch.h b/sysdeps/linux-gnu/alpha/arch.h new file mode 100644 index 0000000..1107b5f --- /dev/null +++ b/sysdeps/linux-gnu/alpha/arch.h @@ -0,0 +1,8 @@ +#define BREAKPOINT_VALUE { 0x80, 0x00, 0x00, 0x00 } +#define BREAKPOINT_LENGTH 4 +#define DECR_PC_AFTER_BREAK 4 + +#define LT_ELFCLASS ELFCLASS64 +#define LT_ELF_MACHINE EM_ALPHA +#define LT_ELFCLASS2 ELFCLASS64 +#define LT_ELF_MACHINE2 EM_FAKE_ALPHA diff --git a/sysdeps/linux-gnu/alpha/plt.c b/sysdeps/linux-gnu/alpha/plt.c new file mode 100644 index 0000000..83337b2 --- /dev/null +++ b/sysdeps/linux-gnu/alpha/plt.c @@ -0,0 +1,12 @@ +#include <gelf.h> +#include "common.h" + +GElf_Addr +arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) { + return lte->plt_addr + ndx * 12 + 32; +} + +void * +sym2addr(Process *proc, struct library_symbol *sym) { + return sym->enter_addr; +} diff --git a/sysdeps/linux-gnu/alpha/ptrace.h b/sysdeps/linux-gnu/alpha/ptrace.h new file mode 100644 index 0000000..c3cbcb6 --- /dev/null +++ b/sysdeps/linux-gnu/alpha/ptrace.h @@ -0,0 +1 @@ +#include <sys/ptrace.h> diff --git a/sysdeps/linux-gnu/alpha/regs.c b/sysdeps/linux-gnu/alpha/regs.c new file mode 100644 index 0000000..9554e48 --- /dev/null +++ b/sysdeps/linux-gnu/alpha/regs.c @@ -0,0 +1,40 @@ +#include "config.h" + +#include <sys/types.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> + +#include "common.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +void * +get_instruction_pointer(Process *proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 64 /* REG_PC */ , 0); +} + +void +set_instruction_pointer(Process *proc, void *addr) { + ptrace(PTRACE_POKEUSER, proc->pid, 64 /* REG_PC */ , addr); +} + +void * +get_stack_pointer(Process *proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 30 /* REG_FP */ , 0); +} + +void * +get_return_addr(Process *proc, void *stack_pointer) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 26 /* RA */ , 0); +} + +void +set_return_addr(Process *proc, void *addr) { + ptrace(PTRACE_POKEUSER, proc->pid, 26 /* RA */ , addr); +} diff --git a/sysdeps/linux-gnu/alpha/signalent.h b/sysdeps/linux-gnu/alpha/signalent.h new file mode 100644 index 0000000..c2a6170 --- /dev/null +++ b/sysdeps/linux-gnu/alpha/signalent.h @@ -0,0 +1,32 @@ +"SIG_0", /* 0 */ + "SIGHUP", /* 1 */ + "SIGINT", /* 2 */ + "SIGQUIT", /* 3 */ + "SIGILL", /* 4 */ + "SIGTRAP", /* 5 */ + "SIGABRT", /* 6 */ + "SIGEMT", /* 7 */ + "SIGFPE", /* 8 */ + "SIGKILL", /* 9 */ + "SIGBUS", /* 10 */ + "SIGSEGV", /* 11 */ + "SIGSYS", /* 12 */ + "SIGPIPE", /* 13 */ + "SIGALRM", /* 14 */ + "SIGTERM", /* 15 */ + "SIGURG", /* 16 */ + "SIGSTOP", /* 17 */ + "SIGTSTP", /* 18 */ + "SIGCONT", /* 19 */ + "SIGCHLD", /* 20 */ + "SIGTTIN", /* 21 */ + "SIGTTOU", /* 22 */ + "SIGIO", /* 23 */ + "SIGXCPU", /* 24 */ + "SIGXFSZ", /* 25 */ + "SIGVTALRM", /* 26 */ + "SIGPROF", /* 27 */ + "SIGWINCH", /* 28 */ + "SIGINFO", /* 29 */ + "SIGUSR1", /* 30 */ + "SIGUSR2", /* 31 */ diff --git a/sysdeps/linux-gnu/alpha/syscallent.h b/sysdeps/linux-gnu/alpha/syscallent.h new file mode 100644 index 0000000..7cacc8c --- /dev/null +++ b/sysdeps/linux-gnu/alpha/syscallent.h @@ -0,0 +1,439 @@ +"osf_syscall", /* 0, not implemented */ + "exit", /* 1 */ + "fork", /* 2 */ + "read", /* 3 */ + "write", /* 4 */ + "osf_old_open", /* 5, not implemented */ + "close", /* 6 */ + "osf_wait4", /* 7 */ + "osf_old_creat", /* 8, not implemented */ + "link", /* 9 */ + "unlink", /* 10 */ + "osf_execve", /* 11, not implemented */ + "chdir", /* 12 */ + "fchdir", /* 13 */ + "mknod", /* 14 */ + "chmod", /* 15 */ + "chown", /* 16 */ + "brk", /* 17 */ + "osf_getfsstat", /* 18, not implemented */ + "lseek", /* 19 */ + "getxpid", /* 20 */ + "osf_mount", /* 21 */ + "umount", /* 22 */ + "setuid", /* 23 */ + "getxuid", /* 24 */ + "exec_with_loader", /* 25, not implemented */ + "ptrace", /* 26 */ + "osf_nrecmsg", /* 27, not implemented */ + "osf_nsendmsg", /* 28, not implemented */ + "osf_nrecvfrom", /* 29, not implemented */ + "osf_naccept", /* 30, not implemented */ + "osf_ngetpeername", /* 31, not implemented */ + "osf_ngetsocketname", /* 32, not implemented */ + "access", /* 33 */ + "osf_chflags", /* 34, not implemented */ + "osf_fchflags", /* 35, not implemented */ + "sync", /* 36 */ + "kill", /* 37 */ + "osf_old_stat", /* 38, not implemented */ + "setpgid", /* 39 */ + "osf_old_lstat", /* 40, not implemented */ + "dup", /* 41 */ + "pipe", /* 42 */ + "osf_set_program_attributes", /* 43 */ + "osf_profil", /* 44, not implemented */ + "open", /* 45 */ + "osf_old_sigaction", /* 46, not implemented */ + "getxgid", /* 47 */ + "osf_sigprocmask", /* 48 */ + "osf_getlogin", /* 49, not implemented */ + "osf_setlogin", /* 50, not implemented */ + "acct", /* 51 */ + "sigpending", /* 52 */ + "SYS_53", /* 53 */ + "ioctl", /* 54 */ + "osf_reboot", /* 55, not implemented */ + "osf_revoke", /* 56, not implemented */ + "symlink", /* 57 */ + "readlink", /* 58 */ + "execve", /* 59 */ + "umask", /* 60 */ + "chroot", /* 61 */ + "osf_old_fstat", /* 62, not implemented */ + "getpgrp", /* 63 */ + "getpagesize", /* 64 */ + "osf_mremap", /* 65, not implemented */ + "vfork", /* 66 */ + "stat", /* 67 */ + "lstat", /* 68 */ + "osf_sbrk", /* 69, not implemented */ + "osf_sstk", /* 70, not implemented */ + "mmap", /* 71 */ + "osf_old_vadvise", /* 72, not implemented */ + "munmap", /* 73 */ + "mprotect", /* 74 */ + "madvise", /* 75 */ + "vhangup", /* 76 */ + "osf_kmodcall", /* 77, not implemented */ + "osf_mincore", /* 78, not implemented */ + "getgroups", /* 79 */ + "setgroups", /* 80 */ + "osf_old_getpgrp", /* 81, not implemented */ + "setpgrp", /* 82 */ + "osf_setitimer", /* 83 */ + "osf_old_wait", /* 84, not implemented */ + "osf_table", /* 85, not implemented */ + "osf_getitimer", /* 86 */ + "gethostname", /* 87 */ + "sethostname", /* 88 */ + "getdtablesize", /* 89 */ + "dup2", /* 90 */ + "fstat", /* 91 */ + "fcntl", /* 92 */ + "osf_select", /* 93 */ + "poll", /* 94 */ + "fsync", /* 95 */ + "setpriority", /* 96 */ + "socket", /* 97 */ + "connect", /* 98 */ + "accept", /* 99 */ + "osf_getpriority", /* 100 */ + "send", /* 101 */ + "recv", /* 102 */ + "sigreturn", /* 103 */ + "bind", /* 104 */ + "setsockopt", /* 105 */ + "listen", /* 106 */ + "osf_plock", /* 107, not implemented */ + "osf_old_sigvec", /* 108, not implemented */ + "osf_old_sigblock", /* 109, not implemented */ + "osf_old_sigsetmask", /* 110, not implemented */ + "sigsuspend", /* 111 */ + "sigstack", /* 112 */ + "recvmsg", /* 113 */ + "sendmsg", /* 114 */ + "osf_old_vtrace", /* 115, not implemented */ + "osf_gettimeofday", /* 116 */ + "osf_getrusage", /* 117 */ + "getsockopt", /* 118 */ + "SYS_119", /* 119 */ + "readv", /* 120 */ + "writev", /* 121 */ + "osf_settimeofday", /* 122 */ + "fchown", /* 123 */ + "fchmod", /* 124 */ + "recvfrom", /* 125 */ + "setreuid", /* 126 */ + "setregid", /* 127 */ + "rename", /* 128 */ + "truncate", /* 129 */ + "ftruncate", /* 130 */ + "flock", /* 131 */ + "setgid", /* 132 */ + "sendto", /* 133 */ + "shutdown", /* 134 */ + "socketpair", /* 135 */ + "mkdir", /* 136 */ + "rmdir", /* 137 */ + "osf_utimes", /* 138 */ + "osf_old_sigreturn", /* 139 */ + "osf_adjtime", /* 140, not implemented */ + "getpeername", /* 141 */ + "osf_gethostid", /* 142, not implemented */ + "osf_sethostid", /* 143, not implemented */ + "getrlimit", /* 144 */ + "setrlimit", /* 145 */ + "osf_old_killpg", /* 146, not implemented */ + "setsid", /* 147 */ + "quotactl", /* 148 */ + "osf_oldquota", /* 149, not implemented */ + "getsockname", /* 150 */ + "SYS_151", /* 151 */ + "SYS_152", /* 152 */ + "osf_pid_block", /* 153, not implemented */ + "osf_pid_unblock", /* 154, not implemented */ + "SYS_155", /* 155 */ + "sigaction", /* 156 */ + "osf_sigwaitprim", /* 157, not implemented */ + "osf_nfssvc", /* 158, not implemented */ + "osf_getdirentries", /* 159 */ + "osf_statfs", /* 160 */ + "osf_fstatfs", /* 161 */ + "SYS_162", /* 162 */ + "osf_asynch_daemon", /* 163, not implemented */ + "osf_getfh", /* 164, not implemented */ + "osf_getdomainname", /* 165 */ + "setdomainname", /* 166 */ + "SYS_167", /* 167 */ + "SYS_168", /* 168 */ + "osf_exportfs", /* 169, not implemented */ + "SYS_170", /* 170 */ + "SYS_171", /* 171 */ + "SYS_172", /* 172 */ + "SYS_173", /* 173 */ + "SYS_174", /* 174 */ + "SYS_175", /* 175 */ + "SYS_176", /* 176 */ + "SYS_177", /* 177 */ + "SYS_178", /* 178 */ + "SYS_179", /* 179 */ + "SYS_180", /* 180 */ + "osf_alt_plock", /* 181, not implemented */ + "SYS_182", /* 182 */ + "SYS_183", /* 183 */ + "osf_getmnt", /* 184, not implemented */ + "SYS_185", /* 185 */ + "SYS_186", /* 186 */ + "osf_alt_sigpending", /* 187, not implemented */ + "osf_alt_setsid", /* 188, not implemented */ + "SYS_189", /* 189 */ + "SYS_190", /* 190 */ + "SYS_191", /* 191 */ + "SYS_192", /* 192 */ + "SYS_193", /* 193 */ + "SYS_194", /* 194 */ + "SYS_195", /* 195 */ + "SYS_196", /* 196 */ + "SYS_197", /* 197 */ + "SYS_198", /* 198 */ + "osf_swapon", /* 199 */ + "msgctl", /* 200 */ + "msgget", /* 201 */ + "msgrcv", /* 202 */ + "msgsnd", /* 203 */ + "semctl", /* 204 */ + "semget", /* 205 */ + "semop", /* 206 */ + "osf_utsname", /* 207 */ + "lchown", /* 208 */ + "osf_shmat", /* 209 */ + "shmctl", /* 210 */ + "shmdt", /* 211 */ + "shmget", /* 212 */ + "osf_mvalid", /* 213, not implemented */ + "osf_getaddressconf", /* 214, not implemented */ + "osf_msleep", /* 215, not implemented */ + "osf_mwakeup", /* 216, not implemented */ + "msync", /* 217 */ + "osf_signal", /* 218, not implemented */ + "osf_utc_gettime", /* 219, not implemented */ + "osf_utc_adjtime", /* 220, not implemented */ + "SYS_221", /* 221 */ + "osf_security", /* 222, not implemented */ + "osf_kloadcall", /* 223, not implemented */ + "SYS_224", /* 224 */ + "SYS_225", /* 225 */ + "SYS_226", /* 226 */ + "SYS_227", /* 227 */ + "SYS_228", /* 228 */ + "SYS_229", /* 229 */ + "SYS_230", /* 230 */ + "SYS_231", /* 231 */ + "SYS_232", /* 232 */ + "getpgid", /* 233 */ + "getsid", /* 234 */ + "sigaltstack", /* 235 */ + "osf_waitid", /* 236, not implemented */ + "osf_priocntlset", /* 237, not implemented */ + "osf_sigsendset", /* 238, not implemented */ + "osf_set_speculative", /* 239, not implemented */ + "osf_msfs_syscall", /* 240, not implemented */ + "osf_sysinfo", /* 241 */ + "osf_uadmin", /* 242, not implemented */ + "osf_fuser", /* 243, not implemented */ + "osf_proplist_syscall", /* 244 */ + "osf_ntp_adjtime", /* 245, not implemented */ + "osf_ntp_gettime", /* 246, not implemented */ + "osf_pathconf", /* 247, not implemented */ + "osf_fpathconf", /* 248, not implemented */ + "SYS_249", /* 249 */ + "osf_uswitch", /* 250, not implemented */ + "osf_usleep_thread", /* 251 */ + "osf_audcntl", /* 252, not implemented */ + "osf_audgen", /* 253, not implemented */ + "sysfs", /* 254 */ + "osf_subsysinfo", /* 255, not implemented */ + "osf_getsysinfo", /* 256 */ + "osf_setsysinfo", /* 257 */ + "osf_afs_syscall", /* 258, not implemented */ + "osf_swapctl", /* 259, not implemented */ + "osf_memcntl", /* 260, not implemented */ + "osf_fdatasync", /* 261, not implemented */ + "SYS_262", /* 262 */ + "SYS_263", /* 263 */ + "SYS_264", /* 264 */ + "SYS_265", /* 265 */ + "SYS_266", /* 266 */ + "SYS_267", /* 267 */ + "SYS_268", /* 268 */ + "SYS_269", /* 269 */ + "SYS_270", /* 270 */ + "SYS_271", /* 271 */ + "SYS_272", /* 272 */ + "SYS_273", /* 273 */ + "SYS_274", /* 274 */ + "SYS_275", /* 275 */ + "SYS_276", /* 276 */ + "SYS_277", /* 277 */ + "SYS_278", /* 278 */ + "SYS_279", /* 279 */ + "SYS_280", /* 280 */ + "SYS_281", /* 281 */ + "SYS_282", /* 282 */ + "SYS_283", /* 283 */ + "SYS_284", /* 284 */ + "SYS_285", /* 285 */ + "SYS_286", /* 286 */ + "SYS_287", /* 287 */ + "SYS_288", /* 288 */ + "SYS_289", /* 289 */ + "SYS_290", /* 290 */ + "SYS_291", /* 291 */ + "SYS_292", /* 292 */ + "SYS_293", /* 293 */ + "SYS_294", /* 294 */ + "SYS_295", /* 295 */ + "SYS_296", /* 296 */ + "SYS_297", /* 297 */ + "SYS_298", /* 298 */ + "SYS_299", /* 299 */ + "bdflush", /* 300 */ + "sethae", /* 301 */ + "mount", /* 302 */ + "adjtimex32", /* 303 */ + "swapoff", /* 304 */ + "getdents", /* 305 */ + "create_module", /* 306 */ + "init_module", /* 307 */ + "delete_module", /* 308 */ + "get_kernel_syms", /* 309 */ + "syslog", /* 310 */ + "reboot", /* 311 */ + "clone", /* 312 */ + "uselib", /* 313 */ + "mlock", /* 314 */ + "munlock", /* 315 */ + "mlockall", /* 316 */ + "munlockall", /* 317 */ + "sysinfo", /* 318 */ + "sysctl", /* 319 */ + "idle", /* 320 */ + "oldumount", /* 321 */ + "swapon", /* 322 */ + "times", /* 323 */ + "personality", /* 324 */ + "setfsuid", /* 325 */ + "setfsgid", /* 326 */ + "ustat", /* 327 */ + "statfs", /* 328 */ + "fstatfs", /* 329 */ + "sched_setparam", /* 330 */ + "sched_getparam", /* 331 */ + "sched_setscheduler", /* 332 */ + "sched_getscheduler", /* 333 */ + "sched_yield", /* 334 */ + "sched_get_priority_max", /* 335 */ + "sched_get_priority_min", /* 336 */ + "sched_rr_get_interval", /* 337 */ + "afs_syscall", /* 338 */ + "uname", /* 339 */ + "nanosleep", /* 340 */ + "mremap", /* 341 */ + "nfsservctl", /* 342 */ + "setresuid", /* 343 */ + "getresuid", /* 344 */ + "pciconfig_read", /* 345 */ + "pciconfig_write", /* 346 */ + "query_module", /* 347 */ + "prctl", /* 348 */ + "pread", /* 349 */ + "pwrite", /* 350 */ + "rt_sigreturn", /* 351 */ + "rt_sigaction", /* 352 */ + "rt_sigprocmask", /* 353 */ + "rt_sigpending", /* 354 */ + "rt_sigtimedwait", /* 355 */ + "rt_sigqueueinfo", /* 356 */ + "rt_sigsuspend", /* 357 */ + "select", /* 358 */ + "gettimeofday", /* 359 */ + "settimeofday", /* 360 */ + "getitimer", /* 361 */ + "setitimer", /* 362 */ + "utimes", /* 363 */ + "getrusage", /* 364 */ + "wait4", /* 365 */ + "adjtimex", /* 366 */ + "getcwd", /* 367 */ + "capget", /* 368 */ + "capset", /* 369 */ + "sendfile", /* 370 */ + "setresgid", /* 371 */ + "getresgid", /* 372 */ + "dipc", /* 373, not implemented */ + "pivot_root", /* 374 */ + "mincore", /* 375 */ + "pciconfig_iobase", /* 376 */ + "getdents64", /* 377 */ + "gettid", /* 378 */ + "readahead", /* 379 */ + "SYS_380", /* 380 */ + "tkill", /* 381 */ + "setxattr", /* 382 */ + "lsetxattr", /* 383 */ + "fsetxattr", /* 384 */ + "getxattr", /* 385 */ + "lgetxattr", /* 386 */ + "fgetxattr", /* 387 */ + "listxattr", /* 388 */ + "llistxattr", /* 389 */ + "flistxattr", /* 390 */ + "removexattr", /* 391 */ + "lremovexattr", /* 392 */ + "fremovexattr", /* 393 */ + "futex", /* 394 */ + "sched_setaffinity", /* 395 */ + "sched_getaffinity", /* 396 */ + "tuxcall", /* 397 */ + "io_setup", /* 398 */ + "io_destroy", /* 399 */ + "io_getevents", /* 400 */ + "io_submit", /* 401 */ + "io_cancel", /* 402 */ + "SYS_403", /* 403 */ + "SYS_404", /* 404 */ + "exit_group", /* 405 */ + "lookup_dcookie", /* 406 */ + "epoll_create", /* 407 */ + "epoll_ctl", /* 408 */ + "epoll_wait", /* 409 */ + "remap_file_pages", /* 410 */ + "set_tid_address", /* 411 */ + "restart_syscall", /* 412 */ + "fadvise", /* 413 */ + "timer_create", /* 414 */ + "timer_settime", /* 415 */ + "timer_gettime", /* 416 */ + "timer_getoverrun", /* 417 */ + "timer_delete", /* 418 */ + "clock_settime", /* 419 */ + "clock_gettime", /* 420 */ + "clock_getres", /* 421 */ + "clock_nanosleep", /* 422 */ + "semtimedop", /* 423 */ + "tgkill", /* 424 */ + "stat64", /* 425 */ + "lstat64", /* 426 */ + "fstat64", /* 427 */ + "vserver", /* 428 */ + "mbind", /* 429 */ + "get_mempolicy", /* 430 */ + "set_mempolicy", /* 431 */ + "mq_open", /* 432 */ + "mq_unlink", /* 433 */ + "mq_timedsend", /* 434 */ + "mq_timedreceive", /* 435 */ + "mq_notify", /* 436 */ + "mq_getsetattr", /* 437 */ + "waitid" /* 438 */ diff --git a/sysdeps/linux-gnu/alpha/trace.c b/sysdeps/linux-gnu/alpha/trace.c new file mode 100644 index 0000000..e4d4063 --- /dev/null +++ b/sysdeps/linux-gnu/alpha/trace.c @@ -0,0 +1,75 @@ +#include "config.h" + +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> + +#include "common.h" +#include "debug.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +void +get_arch_dep(Process *proc) { +} + +/* Returns 1 if syscall, 2 if sysret, 0 otherwise. + */ +int +syscall_p(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) + 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 && + proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { + return 2; + } + if (*sysnum >= 0 && *sysnum < 500) { + return 1; + } + } + return 0; +} + +long +gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) { + 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); + 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); + } else { + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + exit(1); + } + return 0; +} + +void +save_register_args(enum tof type, Process *proc) { +} diff --git a/sysdeps/linux-gnu/arch_mksyscallent b/sysdeps/linux-gnu/arch_mksyscallent new file mode 100644 index 0000000..853d62d --- /dev/null +++ b/sysdeps/linux-gnu/arch_mksyscallent @@ -0,0 +1,42 @@ +#!/usr/bin/awk -f + +# hack expression to generate arch_syscallent.h from <asm/unistd.h> +# It reads from stdin and writes to stdout +# Currently (linux-2.6.16), it works OK on arm +# It is untested in other architectures + +BEGIN { + max=0; + FS="[ \t\n()+]+"; +} + +{ +# printf("/%s/%s/%s/%s/\n", $1, $2, $3, $4); + if (($1 ~ /^#define$/) && ($2 ~ /^__[A-Z]+_NR_/)) { + sub(/^__[A-Z]+_NR_/,"",$2); + if (($3>=0) && ($3<=1000)) { + SYSCALL[$3]=$2; + if ($3 > max) { + max=$3; + } + } else if (($3 ~ /^__[A-Z]+_NR_BASE$/) && ($4>=0) && ($4<=1000)) { + SYSCALL[$4]=$2; + if ($4 > max) { + max=$4; + } + } + } +} + +END { + for(i=0; i<=max; i++) { + if (!SYSCALL[i]) { + SYSCALL[i] = i; + } + pad = 32 - length(SYSCALL[i]); + if (pad<1) { + pad=1; + } + printf("\t\"%s\",%*s/* %d */\n", SYSCALL[i], pad, "", i); + } +} diff --git a/sysdeps/linux-gnu/arm/Makefile b/sysdeps/linux-gnu/arm/Makefile new file mode 100644 index 0000000..f55ba48 --- /dev/null +++ b/sysdeps/linux-gnu/arm/Makefile @@ -0,0 +1,10 @@ +OBJ = trace.o regs.o plt.o breakpoint.o + +all: arch.o + +arch.o: $(OBJ) arch.h + $(CC) -nostdlib -r -o arch.o $(OBJ) + +clean: + $(RM) $(OBJ) arch.o + diff --git a/sysdeps/linux-gnu/arm/arch.h b/sysdeps/linux-gnu/arm/arch.h new file mode 100644 index 0000000..8f2dfb3 --- /dev/null +++ b/sysdeps/linux-gnu/arm/arch.h @@ -0,0 +1,11 @@ +#define ARCH_HAVE_ENABLE_BREAKPOINT 1 +#define ARCH_HAVE_DISABLE_BREAKPOINT 1 + +#define BREAKPOINT_VALUE { 0xf0, 0x01, 0xf0, 0xe7 } +#define BREAKPOINT_LENGTH 4 +#define THUMB_BREAKPOINT_VALUE { 0x01, 0xde } +#define THUMB_BREAKPOINT_LENGTH 2 +#define DECR_PC_AFTER_BREAK 0 + +#define LT_ELFCLASS ELFCLASS32 +#define LT_ELF_MACHINE EM_ARM diff --git a/sysdeps/linux-gnu/arm/arch_syscallent.h b/sysdeps/linux-gnu/arm/arch_syscallent.h new file mode 100644 index 0000000..ce1e844 --- /dev/null +++ b/sysdeps/linux-gnu/arm/arch_syscallent.h @@ -0,0 +1,6 @@ + "0", /* 0 */ + "breakpoint", /* 1 */ + "cacheflush", /* 2 */ + "usr26", /* 3 */ + "usr32", /* 4 */ + "set_tls", /* 5 */ diff --git a/sysdeps/linux-gnu/arm/breakpoint.c b/sysdeps/linux-gnu/arm/breakpoint.c new file mode 100644 index 0000000..4c20260 --- /dev/null +++ b/sysdeps/linux-gnu/arm/breakpoint.c @@ -0,0 +1,77 @@ +/* + * This file is part of ltrace. + * + * Copyright (C) 2007 by Instituto Nokia de Tecnologia (INdT) + * + * Author: Anderson Lizardo <anderson.lizardo@indt.org.br> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Modified from sysdeps/linux-gnu/breakpoint.c and added ARM Thumb support. + */ + +#include <sys/ptrace.h> +#include "config.h" +#include "arch.h" +#include "options.h" +#include "output.h" +#include "debug.h" + +void +arch_enable_breakpoint(pid_t pid, Breakpoint *sbp) { + unsigned int i, j; + const unsigned char break_insn[] = BREAKPOINT_VALUE; + const unsigned char thumb_break_insn[] = THUMB_BREAKPOINT_VALUE; + + debug(1, "arch_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); + unsigned char *bytes = (unsigned char *)&a; + + debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d", a, *(long *)&sbp->orig_value, sbp->thumb_mode); + for (j = 0; j < sizeof(long) && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) { + + sbp->orig_value[i * sizeof(long) + j] = bytes[j]; + if (!sbp->thumb_mode) { + bytes[j] = break_insn[i * sizeof(long) + j]; + } + else if (j < THUMB_BREAKPOINT_LENGTH) { + bytes[j] = thumb_break_insn[i * sizeof(long) + j]; + } + } + ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a); + } +} + +void +arch_disable_breakpoint(pid_t pid, const Breakpoint *sbp) { + unsigned int i, j; + const unsigned char break_insn[] = BREAKPOINT_VALUE; + const unsigned char thumb_break_insn[] = THUMB_BREAKPOINT_VALUE; + + debug(1, "arch_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); + unsigned char *bytes = (unsigned char *)&a; + + debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d", a, *(long *)&sbp->orig_value, sbp->thumb_mode); + for (j = 0; j < sizeof(long) && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) { + bytes[j] = sbp->orig_value[i * sizeof(long) + j]; + } + ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a); + } +} diff --git a/sysdeps/linux-gnu/arm/plt.c b/sysdeps/linux-gnu/arm/plt.c new file mode 100644 index 0000000..bd92a63 --- /dev/null +++ b/sysdeps/linux-gnu/arm/plt.c @@ -0,0 +1,12 @@ +#include <gelf.h> +#include "common.h" + +GElf_Addr +arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) { + return lte->plt_addr + 20 + ndx * 12; +} + +void * +sym2addr(Process *proc, struct library_symbol *sym) { + return sym->enter_addr; +} diff --git a/sysdeps/linux-gnu/arm/ptrace.h b/sysdeps/linux-gnu/arm/ptrace.h new file mode 100644 index 0000000..52215bc --- /dev/null +++ b/sysdeps/linux-gnu/arm/ptrace.h @@ -0,0 +1,9 @@ +#include <sys/ptrace.h> +#include <asm/ptrace.h> + +typedef struct { + int valid; + struct pt_regs regs; + long func_arg[5]; + long sysc_arg[5]; +} proc_archdep; diff --git a/sysdeps/linux-gnu/arm/regs.c b/sysdeps/linux-gnu/arm/regs.c new file mode 100644 index 0000000..2488b0a --- /dev/null +++ b/sysdeps/linux-gnu/arm/regs.c @@ -0,0 +1,51 @@ +#include "config.h" + +#include <sys/types.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> + +#include "common.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +#define off_pc 60 +#define off_lr 56 +#define off_sp 52 + +void * +get_instruction_pointer(Process *proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0); +} + +void +set_instruction_pointer(Process *proc, void *addr) { + ptrace(PTRACE_POKEUSER, proc->pid, off_pc, addr); +} + +void * +get_stack_pointer(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(Process *proc, void *stack_pointer) { + long addr = ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0); + + proc->thumb_mode = addr & 1; + if (proc->thumb_mode) + addr &= ~1; + return (void *)addr; +} + +void +set_return_addr(Process *proc, void *addr) { + ptrace(PTRACE_POKEUSER, proc->pid, off_lr, addr); +} diff --git a/sysdeps/linux-gnu/arm/signalent.h b/sysdeps/linux-gnu/arm/signalent.h new file mode 100644 index 0000000..0afb004 --- /dev/null +++ b/sysdeps/linux-gnu/arm/signalent.h @@ -0,0 +1,33 @@ + "SIG_0", /* 0 */ + "SIGHUP", /* 1 */ + "SIGINT", /* 2 */ + "SIGQUIT", /* 3 */ + "SIGILL", /* 4 */ + "SIGTRAP", /* 5 */ + "SIGABRT", /* 6 */ + "SIGBUS", /* 7 */ + "SIGFPE", /* 8 */ + "SIGKILL", /* 9 */ + "SIGUSR1", /* 10 */ + "SIGSEGV", /* 11 */ + "SIGUSR2", /* 12 */ + "SIGPIPE", /* 13 */ + "SIGALRM", /* 14 */ + "SIGTERM", /* 15 */ + "SIGSTKFLT", /* 16 */ + "SIGCHLD", /* 17 */ + "SIGCONT", /* 18 */ + "SIGSTOP", /* 19 */ + "SIGTSTP", /* 20 */ + "SIGTTIN", /* 21 */ + "SIGTTOU", /* 22 */ + "SIGURG", /* 23 */ + "SIGXCPU", /* 24 */ + "SIGXFSZ", /* 25 */ + "SIGVTALRM", /* 26 */ + "SIGPROF", /* 27 */ + "SIGWINCH", /* 28 */ + "SIGIO", /* 29 */ + "SIGPWR", /* 30 */ + "SIGSYS", /* 31 */ + "SIGSWI", /* 32 */ diff --git a/sysdeps/linux-gnu/arm/syscallent.h b/sysdeps/linux-gnu/arm/syscallent.h new file mode 100644 index 0000000..4113234 --- /dev/null +++ b/sysdeps/linux-gnu/arm/syscallent.h @@ -0,0 +1,322 @@ + "restart_syscall", /* 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 */ + "48", /* 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 */ + "select", /* 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 */ + "101", /* 101 */ + "socketcall", /* 102 */ + "syslog", /* 103 */ + "setitimer", /* 104 */ + "getitimer", /* 105 */ + "stat", /* 106 */ + "lstat", /* 107 */ + "fstat", /* 108 */ + "109", /* 109 */ + "110", /* 110 */ + "vhangup", /* 111 */ + "112", /* 112 */ + "syscall", /* 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 */ + "127", /* 127 */ + "init_module", /* 128 */ + "delete_module", /* 129 */ + "130", /* 130 */ + "quotactl", /* 131 */ + "getpgid", /* 132 */ + "fchdir", /* 133 */ + "bdflush", /* 134 */ + "sysfs", /* 135 */ + "personality", /* 136 */ + "137", /* 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 */ + "167", /* 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 */ + "pread64", /* 180 */ + "pwrite64", /* 181 */ + "chown", /* 182 */ + "getcwd", /* 183 */ + "capget", /* 184 */ + "capset", /* 185 */ + "sigaltstack", /* 186 */ + "sendfile", /* 187 */ + "188", /* 188 */ + "189", /* 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 */ + "getdents64", /* 217 */ + "pivot_root", /* 218 */ + "mincore", /* 219 */ + "madvise", /* 220 */ + "fcntl64", /* 221 */ + "222", /* 222 */ + "223", /* 223 */ + "gettid", /* 224 */ + "readahead", /* 225 */ + "setxattr", /* 226 */ + "lsetxattr", /* 227 */ + "fsetxattr", /* 228 */ + "getxattr", /* 229 */ + "lgetxattr", /* 230 */ + "fgetxattr", /* 231 */ + "listxattr", /* 232 */ + "llistxattr", /* 233 */ + "flistxattr", /* 234 */ + "removexattr", /* 235 */ + "lremovexattr", /* 236 */ + "fremovexattr", /* 237 */ + "tkill", /* 238 */ + "sendfile64", /* 239 */ + "futex", /* 240 */ + "sched_setaffinity", /* 241 */ + "sched_getaffinity", /* 242 */ + "io_setup", /* 243 */ + "io_destroy", /* 244 */ + "io_getevents", /* 245 */ + "io_submit", /* 246 */ + "io_cancel", /* 247 */ + "exit_group", /* 248 */ + "lookup_dcookie", /* 249 */ + "epoll_create", /* 250 */ + "epoll_ctl", /* 251 */ + "epoll_wait", /* 252 */ + "remap_file_pages", /* 253 */ + "254", /* 254 */ + "255", /* 255 */ + "set_tid_address", /* 256 */ + "timer_create", /* 257 */ + "timer_settime", /* 258 */ + "timer_gettime", /* 259 */ + "timer_getoverrun", /* 260 */ + "timer_delete", /* 261 */ + "clock_settime", /* 262 */ + "clock_gettime", /* 263 */ + "clock_getres", /* 264 */ + "clock_nanosleep", /* 265 */ + "statfs64", /* 266 */ + "fstatfs64", /* 267 */ + "tgkill", /* 268 */ + "utimes", /* 269 */ + "arm_fadvise64_64", /* 270 */ + "pciconfig_iobase", /* 271 */ + "pciconfig_read", /* 272 */ + "pciconfig_write", /* 273 */ + "mq_open", /* 274 */ + "mq_unlink", /* 275 */ + "mq_timedsend", /* 276 */ + "mq_timedreceive", /* 277 */ + "mq_notify", /* 278 */ + "mq_getsetattr", /* 279 */ + "waitid", /* 280 */ + "socket", /* 281 */ + "bind", /* 282 */ + "connect", /* 283 */ + "listen", /* 284 */ + "accept", /* 285 */ + "getsockname", /* 286 */ + "getpeername", /* 287 */ + "socketpair", /* 288 */ + "send", /* 289 */ + "sendto", /* 290 */ + "recv", /* 291 */ + "recvfrom", /* 292 */ + "shutdown", /* 293 */ + "setsockopt", /* 294 */ + "getsockopt", /* 295 */ + "sendmsg", /* 296 */ + "recvmsg", /* 297 */ + "semop", /* 298 */ + "semget", /* 299 */ + "semctl", /* 300 */ + "msgsnd", /* 301 */ + "msgrcv", /* 302 */ + "msgget", /* 303 */ + "msgctl", /* 304 */ + "shmat", /* 305 */ + "shmdt", /* 306 */ + "shmget", /* 307 */ + "shmctl", /* 308 */ + "add_key", /* 309 */ + "request_key", /* 310 */ + "keyctl", /* 311 */ + "semtimedop", /* 312 */ + "vserver", /* 313 */ + "ioprio_set", /* 314 */ + "ioprio_get", /* 315 */ + "inotify_init", /* 316 */ + "inotify_add_watch", /* 317 */ + "inotify_rm_watch", /* 318 */ + "mbind", /* 319 */ + "get_mempolicy", /* 320 */ + "set_mempolicy", /* 321 */ diff --git a/sysdeps/linux-gnu/arm/trace.c b/sysdeps/linux-gnu/arm/trace.c new file mode 100644 index 0000000..10f7cc4 --- /dev/null +++ b/sysdeps/linux-gnu/arm/trace.c @@ -0,0 +1,131 @@ +#include "config.h" + +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> + +#include "common.h" +#include "output.h" +#include "ptrace.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +#define off_r0 0 +#define off_r7 28 +#define off_ip 48 +#define off_pc 60 + +void +get_arch_dep(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, 0, &a->regs) >= 0); +} + +/* Returns 0 if not a syscall, + * 1 if syscall entry, 2 if syscall exit, + * 3 if arch-specific syscall entry, 4 if arch-specific syscall exit, + * -1 on error. + */ +int +syscall_p(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 ip = ptrace(PTRACE_PEEKUSER, proc->pid, off_ip, 0); + + if (insn == 0xef000000 || insn == 0x0f000000) { + /* EABI syscall */ + *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, off_r7, 0); + } else if ((insn & 0xfff00000) == 0xef900000) { + /* old ABI syscall */ + *sysnum = insn & 0xfffff; + } else { + /* TODO: handle swi<cond> variations */ + /* one possible reason for getting in here is that we + * are coming from a signal handler, so the current + * PC does not point to the instruction just after the + * "swi" one. */ + output_line(proc, "unexpected instruction 0x%x at %p", insn, pc - 4); + return -1; + } + if ((*sysnum & 0xf0000) == 0xf0000) { + /* arch-specific syscall */ + *sysnum &= ~0xf0000; + return ip ? 4 : 3; + } + /* ARM syscall convention: on syscall entry, ip is zero; + * on syscall exit, ip is non-zero */ + return ip ? 2 : 1; + } + return 0; +} + +long +gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) { + proc_archdep *a = (proc_archdep *) proc->arch_ptr; + + 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) { + if (a->valid && type == LT_TOF_FUNCTION) + return a->regs.uregs[arg_num]; + if (a->valid && type == LT_TOF_FUNCTIONR) + return a->func_arg[arg_num]; + 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); + } + } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) { + if (arg_num < 5) { + if (a->valid && type == LT_TOF_SYSCALL) + return a->regs.uregs[arg_num]; + if (a->valid && type == LT_TOF_SYSCALLR) + return a->sysc_arg[arg_num]; + 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); + } + } else { + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + exit(1); + } + + return 0; +} + +void +save_register_args(enum tof type, Process *proc) { + proc_archdep *a = (proc_archdep *) proc->arch_ptr; + if (a->valid) { + if (type == LT_TOF_FUNCTION) + memcpy(a->func_arg, a->regs.uregs, sizeof(a->func_arg)); + else + memcpy(a->sysc_arg, a->regs.uregs, sizeof(a->sysc_arg)); + } +} diff --git a/sysdeps/linux-gnu/breakpoint.c b/sysdeps/linux-gnu/breakpoint.c new file mode 100644 index 0000000..5ca131a --- /dev/null +++ b/sysdeps/linux-gnu/breakpoint.c @@ -0,0 +1,86 @@ +#include "config.h" + +#include <sys/ptrace.h> +#include <string.h> + +#include "common.h" +#include "arch.h" + +static unsigned char break_insn[] = BREAKPOINT_VALUE; + +#ifdef ARCH_HAVE_ENABLE_BREAKPOINT +extern void arch_enable_breakpoint(pid_t, Breakpoint *); +void +enable_breakpoint(pid_t pid, Breakpoint *sbp) { + if (sbp->libsym) { + debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name); + } else { + debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p", pid, sbp->addr); + } + arch_enable_breakpoint(pid, sbp); +} +#else +void +enable_breakpoint(pid_t pid, Breakpoint *sbp) { + unsigned int i, j; + + if (sbp->libsym) { + debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name); + } else { + debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%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; + + 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); + } +} +#endif /* ARCH_HAVE_ENABLE_BREAKPOINT */ + +#ifdef ARCH_HAVE_DISABLE_BREAKPOINT +extern void arch_disable_breakpoint(pid_t, const Breakpoint *sbp); +void +disable_breakpoint(pid_t pid, const Breakpoint *sbp) { + if (sbp->libsym) { + debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name); + } else { + debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p", pid, sbp->addr); + } + arch_disable_breakpoint(pid, sbp); +} +#else +void +disable_breakpoint(pid_t pid, const Breakpoint *sbp) { + unsigned int i, j; + + if (sbp->libsym) { + debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name); + } else { + debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%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; + + bytes[j] = sbp->orig_value[i * sizeof(long) + j]; + } + ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a); + } +} +#endif /* ARCH_HAVE_DISABLE_BREAKPOINT */ diff --git a/sysdeps/linux-gnu/events.c b/sysdeps/linux-gnu/events.c new file mode 100644 index 0000000..a1e2a14 --- /dev/null +++ b/sysdeps/linux-gnu/events.c @@ -0,0 +1,161 @@ +#include "config.h" + +#define _GNU_SOURCE 1 +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> +#include <signal.h> +#include <string.h> +#include <sys/ptrace.h> + +#include "common.h" + +static Event event; + +Event * +next_event(void) { + pid_t pid; + int status; + int tmp; + int stop_signal; + + debug(DEBUG_FUNCTION, "next_event()"); + if (!list_of_processes) { + debug(DEBUG_EVENT, "event: No more traced programs: exiting"); + exit(0); + } + pid = waitpid(-1, &status, __WALL); + if (pid == -1) { + if (errno == ECHILD) { + debug(DEBUG_EVENT, "event: No more traced programs: exiting"); + exit(0); + } else if (errno == EINTR) { + debug(DEBUG_EVENT, "event: none (wait received EINTR?)"); + event.type = EVENT_NONE; + return &event; + } + perror("wait"); + exit(1); + } + event.proc = pid2proc(pid); + if (!event.proc || event.proc->state == STATE_BEING_CREATED) { + event.type = EVENT_NEW; + event.e_un.newpid = pid; + debug(DEBUG_EVENT, "event: NEW: pid=%d", pid); + return &event; + } + get_arch_dep(event.proc); + event.proc->instruction_pointer = NULL; + debug(3, "event from pid %u", pid); + if (event.proc->breakpoints_enabled == -1) { + enable_all_breakpoints(event.proc); + event.type = EVENT_NONE; + trace_set_options(event.proc, event.proc->pid); + continue_process(event.proc->pid); + debug(DEBUG_EVENT, "event: NONE: pid=%d (enabling breakpoints)", pid); + return &event; + } + if (opt_i) { + event.proc->instruction_pointer = + get_instruction_pointer(event.proc); + } + switch (syscall_p(event.proc, status, &tmp)) { + case 1: + event.type = EVENT_SYSCALL; + event.e_un.sysnum = tmp; + debug(DEBUG_EVENT, "event: SYSCALL: pid=%d, sysnum=%d", pid, tmp); + return &event; + case 2: + event.type = EVENT_SYSRET; + event.e_un.sysnum = tmp; + debug(DEBUG_EVENT, "event: SYSRET: pid=%d, sysnum=%d", pid, tmp); + return &event; + case 3: + event.type = EVENT_ARCH_SYSCALL; + event.e_un.sysnum = tmp; + debug(DEBUG_EVENT, "event: ARCH_SYSCALL: pid=%d, sysnum=%d", pid, tmp); + return &event; + case 4: + event.type = EVENT_ARCH_SYSRET; + event.e_un.sysnum = tmp; + debug(DEBUG_EVENT, "event: ARCH_SYSRET: pid=%d, sysnum=%d", pid, tmp); + return &event; + case -1: + event.type = EVENT_NONE; + continue_process(event.proc->pid); + debug(DEBUG_EVENT, "event: NONE: pid=%d (syscall_p returned -1)", pid); + return &event; + } + if (WIFSTOPPED(status) && ((status>>16 == PTRACE_EVENT_FORK) || (status>>16 == PTRACE_EVENT_VFORK) || (status>>16 == PTRACE_EVENT_CLONE))) { + unsigned long data; + ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data); + event.type = EVENT_CLONE; + event.e_un.newpid = data; + debug(DEBUG_EVENT, "event: CLONE: pid=%d, newpid=%d", pid, (int)data); + return &event; + } + if (WIFSTOPPED(status) && (status>>16 == PTRACE_EVENT_EXEC)) { + event.type = EVENT_EXEC; + debug(DEBUG_EVENT, "event: EXEC: pid=%d", pid); + return &event; + } + if (WIFEXITED(status)) { + event.type = EVENT_EXIT; + event.e_un.ret_val = WEXITSTATUS(status); + debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val); + return &event; + } + if (WIFSIGNALED(status)) { + event.type = EVENT_EXIT_SIGNAL; + event.e_un.signum = WTERMSIG(status); + debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum); + return &event; + } + if (!WIFSTOPPED(status)) { + /* should never happen */ + event.type = EVENT_NONE; + debug(DEBUG_EVENT, "event: NONE: pid=%d (wait error?)", pid); + return &event; + } + + stop_signal = WSTOPSIG(status); + + /* On some targets, breakpoints are signalled not using + SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. Check + for these. (TODO: is this true?) */ + if (stop_signal == SIGSEGV + || stop_signal == SIGILL +#ifdef SIGEMT + || stop_signal == SIGEMT +#endif + ) { + if (!event.proc->instruction_pointer) { + event.proc->instruction_pointer = + get_instruction_pointer(event.proc); + } + + if (address2bpstruct(event.proc, event.proc->instruction_pointer)) + stop_signal = SIGTRAP; + } + + if (stop_signal != (SIGTRAP | event.proc->tracesysgood) + && stop_signal != SIGTRAP) { + event.type = EVENT_SIGNAL; + event.e_un.signum = stop_signal; + debug(DEBUG_EVENT, "event: SIGNAL: pid=%d, signum=%d", pid, stop_signal); + return &event; + } + + /* last case [by exhaustion] */ + event.type = EVENT_BREAKPOINT; + + if (!event.proc->instruction_pointer) { + event.proc->instruction_pointer = + get_instruction_pointer(event.proc); + } + event.e_un.brk_addr = + event.proc->instruction_pointer - DECR_PC_AFTER_BREAK; + debug(DEBUG_EVENT, "event: BREAKPOINT: pid=%d, addr=%p", pid, event.e_un.brk_addr); + return &event; +} diff --git a/sysdeps/linux-gnu/i386/Makefile b/sysdeps/linux-gnu/i386/Makefile new file mode 100644 index 0000000..60d7531 --- /dev/null +++ b/sysdeps/linux-gnu/i386/Makefile @@ -0,0 +1,10 @@ +OBJ = trace.o regs.o plt.o + +all: arch.o + +arch.o: $(OBJ) + $(CC) -nostdlib -r -o arch.o $(OBJ) + +clean: + $(RM) $(OBJ) arch.o + diff --git a/sysdeps/linux-gnu/i386/arch.h b/sysdeps/linux-gnu/i386/arch.h new file mode 100644 index 0000000..dc7383f --- /dev/null +++ b/sysdeps/linux-gnu/i386/arch.h @@ -0,0 +1,6 @@ +#define BREAKPOINT_VALUE {0xcc} +#define BREAKPOINT_LENGTH 1 +#define DECR_PC_AFTER_BREAK 1 + +#define LT_ELFCLASS ELFCLASS32 +#define LT_ELF_MACHINE EM_386 diff --git a/sysdeps/linux-gnu/i386/plt.c b/sysdeps/linux-gnu/i386/plt.c new file mode 100644 index 0000000..b53ff44 --- /dev/null +++ b/sysdeps/linux-gnu/i386/plt.c @@ -0,0 +1,12 @@ +#include <gelf.h> +#include "common.h" + +GElf_Addr +arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) { + return lte->plt_addr + (ndx + 1) * 16; +} + +void * +sym2addr(Process *proc, struct library_symbol *sym) { + return sym->enter_addr; +} diff --git a/sysdeps/linux-gnu/i386/ptrace.h b/sysdeps/linux-gnu/i386/ptrace.h new file mode 100644 index 0000000..c3cbcb6 --- /dev/null +++ b/sysdeps/linux-gnu/i386/ptrace.h @@ -0,0 +1 @@ +#include <sys/ptrace.h> diff --git a/sysdeps/linux-gnu/i386/regs.c b/sysdeps/linux-gnu/i386/regs.c new file mode 100644 index 0000000..6777f17 --- /dev/null +++ b/sysdeps/linux-gnu/i386/regs.c @@ -0,0 +1,40 @@ +#include "config.h" + +#include <sys/types.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> + +#include "common.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +void * +get_instruction_pointer(Process *proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EIP, 0); +} + +void +set_instruction_pointer(Process *proc, void *addr) { + ptrace(PTRACE_POKEUSER, proc->pid, 4 * EIP, (long)addr); +} + +void * +get_stack_pointer(Process *proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * UESP, 0); +} + +void * +get_return_addr(Process *proc, void *stack_pointer) { + return (void *)ptrace(PTRACE_PEEKTEXT, proc->pid, stack_pointer, 0); +} + +void +set_return_addr(Process *proc, void *addr) { + ptrace(PTRACE_POKETEXT, proc->pid, proc->stack_pointer, (long)addr); +} diff --git a/sysdeps/linux-gnu/i386/signalent.h b/sysdeps/linux-gnu/i386/signalent.h new file mode 100644 index 0000000..5395f82 --- /dev/null +++ b/sysdeps/linux-gnu/i386/signalent.h @@ -0,0 +1,32 @@ + "SIG_0", /* 0 */ + "SIGHUP", /* 1 */ + "SIGINT", /* 2 */ + "SIGQUIT", /* 3 */ + "SIGILL", /* 4 */ + "SIGTRAP", /* 5 */ + "SIGABRT", /* 6 */ + "SIGBUS", /* 7 */ + "SIGFPE", /* 8 */ + "SIGKILL", /* 9 */ + "SIGUSR1", /* 10 */ + "SIGSEGV", /* 11 */ + "SIGUSR2", /* 12 */ + "SIGPIPE", /* 13 */ + "SIGALRM", /* 14 */ + "SIGTERM", /* 15 */ + "SIGSTKFLT", /* 16 */ + "SIGCHLD", /* 17 */ + "SIGCONT", /* 18 */ + "SIGSTOP", /* 19 */ + "SIGTSTP", /* 20 */ + "SIGTTIN", /* 21 */ + "SIGTTOU", /* 22 */ + "SIGURG", /* 23 */ + "SIGXCPU", /* 24 */ + "SIGXFSZ", /* 25 */ + "SIGVTALRM", /* 26 */ + "SIGPROF", /* 27 */ + "SIGWINCH", /* 28 */ + "SIGIO", /* 29 */ + "SIGPWR", /* 30 */ + "SIGSYS", /* 31 */ diff --git a/sysdeps/linux-gnu/i386/syscallent.h b/sysdeps/linux-gnu/i386/syscallent.h new file mode 100644 index 0000000..8f4c887 --- /dev/null +++ b/sysdeps/linux-gnu/i386/syscallent.h @@ -0,0 +1,317 @@ + "restart_syscall", /* 0 */ + "exit", /* 1 */ + "fork", /* 2 */ + "read", /* 3 */ + "write", /* 4 */ + "open", /* 5 */ + "close", /* 6 */ + "waitpid", /* 7 */ + "creat", /* 8 */ + "link", /* 9 */ + "unlink", /* 10 */ + "execve", /* 11 */ + "chdir", /* 12 */ + "time", /* 13 */ + "mknod", /* 14 */ + "chmod", /* 15 */ + "lchown", /* 16 */ + "break", /* 17 */ + "oldstat", /* 18 */ + "lseek", /* 19 */ + "getpid", /* 20 */ + "mount", /* 21 */ + "umount", /* 22 */ + "setuid", /* 23 */ + "getuid", /* 24 */ + "stime", /* 25 */ + "ptrace", /* 26 */ + "alarm", /* 27 */ + "oldfstat", /* 28 */ + "pause", /* 29 */ + "utime", /* 30 */ + "stty", /* 31 */ + "gtty", /* 32 */ + "access", /* 33 */ + "nice", /* 34 */ + "ftime", /* 35 */ + "sync", /* 36 */ + "kill", /* 37 */ + "rename", /* 38 */ + "mkdir", /* 39 */ + "rmdir", /* 40 */ + "dup", /* 41 */ + "pipe", /* 42 */ + "times", /* 43 */ + "prof", /* 44 */ + "brk", /* 45 */ + "setgid", /* 46 */ + "getgid", /* 47 */ + "signal", /* 48 */ + "geteuid", /* 49 */ + "getegid", /* 50 */ + "acct", /* 51 */ + "umount2", /* 52 */ + "lock", /* 53 */ + "ioctl", /* 54 */ + "fcntl", /* 55 */ + "mpx", /* 56 */ + "setpgid", /* 57 */ + "ulimit", /* 58 */ + "oldolduname", /* 59 */ + "umask", /* 60 */ + "chroot", /* 61 */ + "ustat", /* 62 */ + "dup2", /* 63 */ + "getppid", /* 64 */ + "getpgrp", /* 65 */ + "setsid", /* 66 */ + "sigaction", /* 67 */ + "sgetmask", /* 68 */ + "ssetmask", /* 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 */ + "select", /* 82 */ + "symlink", /* 83 */ + "oldlstat", /* 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 */ + "profil", /* 98 */ + "statfs", /* 99 */ + "fstatfs", /* 100 */ + "ioperm", /* 101 */ + "socketcall", /* 102 */ + "syslog", /* 103 */ + "setitimer", /* 104 */ + "getitimer", /* 105 */ + "stat", /* 106 */ + "lstat", /* 107 */ + "fstat", /* 108 */ + "olduname", /* 109 */ + "iopl", /* 110 */ + "vhangup", /* 111 */ + "idle", /* 112 */ + "vm86old", /* 113 */ + "wait4", /* 114 */ + "swapoff", /* 115 */ + "sysinfo", /* 116 */ + "ipc", /* 117 */ + "fsync", /* 118 */ + "sigreturn", /* 119 */ + "clone", /* 120 */ + "setdomainname", /* 121 */ + "uname", /* 122 */ + "modify_ldt", /* 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 */ + "vm86", /* 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 */ + "pread64", /* 180 */ + "pwrite64", /* 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 */ + "madvise1", /* 219 */ + "getdents64", /* 220 */ + "fcntl64", /* 221 */ + "222", /* 222 */ + "223", /* 223 */ + "gettid", /* 224 */ + "readahead", /* 225 */ + "setxattr", /* 226 */ + "lsetxattr", /* 227 */ + "fsetxattr", /* 228 */ + "getxattr", /* 229 */ + "lgetxattr", /* 230 */ + "fgetxattr", /* 231 */ + "listxattr", /* 232 */ + "llistxattr", /* 233 */ + "flistxattr", /* 234 */ + "removexattr", /* 235 */ + "lremovexattr", /* 236 */ + "fremovexattr", /* 237 */ + "tkill", /* 238 */ + "sendfile64", /* 239 */ + "futex", /* 240 */ + "sched_setaffinity", /* 241 */ + "sched_getaffinity", /* 242 */ + "set_thread_area", /* 243 */ + "get_thread_area", /* 244 */ + "io_setup", /* 245 */ + "io_destroy", /* 246 */ + "io_getevents", /* 247 */ + "io_submit", /* 248 */ + "io_cancel", /* 249 */ + "fadvise64", /* 250 */ + "251", /* 251 */ + "exit_group", /* 252 */ + "lookup_dcookie", /* 253 */ + "epoll_create", /* 254 */ + "epoll_ctl", /* 255 */ + "epoll_wait", /* 256 */ + "remap_file_pages", /* 257 */ + "set_tid_address", /* 258 */ + "timer_create", /* 259 */ + "260", /* 260 */ + "261", /* 261 */ + "262", /* 262 */ + "263", /* 263 */ + "264", /* 264 */ + "265", /* 265 */ + "266", /* 266 */ + "267", /* 267 */ + "statfs64", /* 268 */ + "fstatfs64", /* 269 */ + "tgkill", /* 270 */ + "utimes", /* 271 */ + "fadvise64_64", /* 272 */ + "vserver", /* 273 */ + "mbind", /* 274 */ + "get_mempolicy", /* 275 */ + "set_mempolicy", /* 276 */ + "mq_open", /* 277 */ + "278", /* 278 */ + "279", /* 279 */ + "280", /* 280 */ + "281", /* 281 */ + "282", /* 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 */ + "migrate_pages", /* 294 */ + "openat", /* 295 */ + "mkdirat", /* 296 */ + "mknodat", /* 297 */ + "fchownat", /* 298 */ + "futimesat", /* 299 */ + "fstatat64", /* 300 */ + "unlinkat", /* 301 */ + "renameat", /* 302 */ + "linkat", /* 303 */ + "symlinkat", /* 304 */ + "readlinkat", /* 305 */ + "fchmodat", /* 306 */ + "faccessat", /* 307 */ + "pselect6", /* 308 */ + "ppoll", /* 309 */ + "unshare", /* 310 */ + "set_robust_list", /* 311 */ + "get_robust_list", /* 312 */ + "splice", /* 313 */ + "sync_file_range", /* 314 */ + "tee", /* 315 */ + "vmsplice", /* 316 */ diff --git a/sysdeps/linux-gnu/i386/trace.c b/sysdeps/linux-gnu/i386/trace.c new file mode 100644 index 0000000..76f1105 --- /dev/null +++ b/sysdeps/linux-gnu/i386/trace.c @@ -0,0 +1,85 @@ +#include "config.h" + +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> + +#include "common.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +void +get_arch_dep(Process *proc) { +} + +/* Returns 1 if syscall, 2 if sysret, 0 otherwise. + */ +int +syscall_p(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].c_un.syscall == *sysnum) { + return 2; + } + + if (*sysnum >= 0) { + return 1; + } + } + return 0; +} + +long +gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) { + 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 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); + } +#else + return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num, 0); +#endif + } else { + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + exit(1); + } + + return 0; +} + +void +save_register_args(enum tof type, Process *proc) { +} diff --git a/sysdeps/linux-gnu/ia64/Makefile b/sysdeps/linux-gnu/ia64/Makefile new file mode 100644 index 0000000..4f0ef63 --- /dev/null +++ b/sysdeps/linux-gnu/ia64/Makefile @@ -0,0 +1,10 @@ +OBJ = trace.o regs.o plt.o breakpoint.o + +all: arch.o + +arch.o: $(OBJ) + $(LD) -r -o arch.o $(OBJ) + +clean: + $(RM) $(OBJ) arch.o + diff --git a/sysdeps/linux-gnu/ia64/arch.h b/sysdeps/linux-gnu/ia64/arch.h new file mode 100644 index 0000000..673047c --- /dev/null +++ b/sysdeps/linux-gnu/ia64/arch.h @@ -0,0 +1,13 @@ +#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 + +// ia64 actually does use .opd, but we don't need to do the +// translation manually. +#undef ARCH_SUPPORTS_OPD diff --git a/sysdeps/linux-gnu/ia64/breakpoint.c b/sysdeps/linux-gnu/ia64/breakpoint.c new file mode 100644 index 0000000..4f09173 --- /dev/null +++ b/sysdeps/linux-gnu/ia64/breakpoint.c @@ -0,0 +1,212 @@ +/* IA64 breakpoint support. Much of this clagged from gdb + * -Ian Wienand <ianw@gelato.unsw.edu.au> 10/3/2005 + */ + +#include "config.h" + +#include <sys/ptrace.h> +#include <string.h> +#include "arch.h" +#include "options.h" +#include "output.h" +#include "debug.h" + +static long long +extract_bit_field(char *bundle, int from, int len) { + long long result = 0LL; + int to = from + len; + int from_byte = from / 8; + int to_byte = to / 8; + unsigned char *b = (unsigned char *)bundle; + unsigned char c; + int lshift; + int i; + + c = b[from_byte]; + if (from_byte == to_byte) + c = ((unsigned char)(c << (8 - to % 8))) >> (8 - to % 8); + result = c >> (from % 8); + lshift = 8 - (from % 8); + + for (i = from_byte + 1; i < to_byte; i++) { + result |= ((long long)b[i]) << lshift; + lshift += 8; + } + + if (from_byte < to_byte && (to % 8 != 0)) { + c = b[to_byte]; + c = ((unsigned char)(c << (8 - to % 8))) >> (8 - to % 8); + result |= ((long long)c) << lshift; + } + + return result; +} + +/* Replace the specified bits in an instruction bundle */ +static void +replace_bit_field(char *bundle, long long val, int from, int len) { + int to = from + len; + int from_byte = from / 8; + int to_byte = to / 8; + unsigned char *b = (unsigned char *)bundle; + unsigned char c; + + if (from_byte == to_byte) { + unsigned char left, right; + c = b[from_byte]; + left = (c >> (to % 8)) << (to % 8); + right = + ((unsigned char)(c << (8 - from % 8))) >> (8 - from % 8); + c = (unsigned char)(val & 0xff); + c = (unsigned char)(c << (from % 8 + 8 - to % 8)) >> (8 - + to % 8); + c |= right | left; + b[from_byte] = c; + } else { + int i; + c = b[from_byte]; + c = ((unsigned char)(c << (8 - from % 8))) >> (8 - from % 8); + c = c | (val << (from % 8)); + b[from_byte] = c; + val >>= 8 - from % 8; + + for (i = from_byte + 1; i < to_byte; i++) { + c = val & 0xff; + val >>= 8; + b[i] = c; + } + + if (to % 8 != 0) { + unsigned char cv = (unsigned char)val; + c = b[to_byte]; + c = c >> (to % 8) << (to % 8); + c |= ((unsigned char)(cv << (8 - to % 8))) >> (8 - + to % 8); + b[to_byte] = c; + } + } +} + +/* Return the contents of slot N (for N = 0, 1, or 2) in + and instruction bundle */ +static long long +slotN_contents(char *bundle, int slotnum) { + return extract_bit_field(bundle, 5 + 41 * slotnum, 41); +} + +/* Store an instruction in an instruction bundle */ + +static void +replace_slotN_contents(char *bundle, long long instr, int slotnum) { + replace_bit_field(bundle, instr, 5 + 41 * slotnum, 41); +} + +typedef enum instruction_type { + A, /* Integer ALU ; I-unit or M-unit */ + I, /* Non-ALU integer; I-unit */ + M, /* Memory ; M-unit */ + F, /* Floating-point ; F-unit */ + B, /* Branch ; B-unit */ + L, /* Extended (L+X) ; I-unit */ + X, /* Extended (L+X) ; I-unit */ + undefined /* undefined or reserved */ +} instruction_type; + +static enum instruction_type template_encoding_table[32][3] = { + {M, I, I}, /* 00 */ + {M, I, I}, /* 01 */ + {M, I, I}, /* 02 */ + {M, I, I}, /* 03 */ + {M, L, X}, /* 04 */ + {M, L, X}, /* 05 */ + {undefined, undefined, undefined}, /* 06 */ + {undefined, undefined, undefined}, /* 07 */ + {M, M, I}, /* 08 */ + {M, M, I}, /* 09 */ + {M, M, I}, /* 0A */ + {M, M, I}, /* 0B */ + {M, F, I}, /* 0C */ + {M, F, I}, /* 0D */ + {M, M, F}, /* 0E */ + {M, M, F}, /* 0F */ + {M, I, B}, /* 10 */ + {M, I, B}, /* 11 */ + {M, B, B}, /* 12 */ + {M, B, B}, /* 13 */ + {undefined, undefined, undefined}, /* 14 */ + {undefined, undefined, undefined}, /* 15 */ + {B, B, B}, /* 16 */ + {B, B, B}, /* 17 */ + {M, M, B}, /* 18 */ + {M, M, B}, /* 19 */ + {undefined, undefined, undefined}, /* 1A */ + {undefined, undefined, undefined}, /* 1B */ + {M, F, B}, /* 1C */ + {M, F, B}, /* 1D */ + {undefined, undefined, undefined}, /* 1E */ + {undefined, undefined, undefined}, /* 1F */ +}; + +union bundle_t { + char cbundle[16]; + unsigned long ubundle[2]; +}; + +void +arch_enable_breakpoint(pid_t pid, Breakpoint *sbp) { + + unsigned long addr = (unsigned long)sbp->addr; + union bundle_t bundle; + int slotnum = (int)(addr & 0x0f) & 0x3; + long long instr; + int template; + + debug(1, "Enable Breakpoint at %p)", sbp->addr); + + if (slotnum > 2) + printf + ("Can't insert breakpoint for slot numbers greater than 2."); + + addr &= ~0x0f; + bundle.ubundle[0] = ptrace(PTRACE_PEEKTEXT, pid, addr, 0); + bundle.ubundle[1] = ptrace(PTRACE_PEEKTEXT, pid, addr + 8, 0); + + /* Check for L type instruction in 2nd slot, if present then + bump up the slot number to the 3rd slot */ + template = extract_bit_field(bundle.cbundle, 0, 5); + if (slotnum == 1 && template_encoding_table[template][1] == L) { + slotnum = 2; + } + + instr = slotN_contents(bundle.cbundle, slotnum); + + memcpy(sbp->orig_value, &instr, sizeof(instr)); + + replace_slotN_contents(bundle.cbundle, 0x00002000040LL, slotnum); + + ptrace(PTRACE_POKETEXT, pid, addr, bundle.ubundle[0]); + ptrace(PTRACE_POKETEXT, pid, addr + 8, bundle.ubundle[1]); + +} + +void +arch_disable_breakpoint(pid_t pid, const Breakpoint *sbp) { + + unsigned long addr = (unsigned long)sbp->addr; + int slotnum = (int)(addr & 0x0f) & 0x3; + union bundle_t bundle; + unsigned long instr; + + debug(1, "Disable Breakpoint at %p", sbp->addr); + + addr &= ~0x0f; + + bundle.ubundle[0] = ptrace(PTRACE_PEEKTEXT, pid, addr, 0); + bundle.ubundle[1] = ptrace(PTRACE_PEEKTEXT, pid, addr + 8, 0); + + memcpy(&instr, sbp->orig_value, sizeof(instr)); + + replace_slotN_contents(bundle.cbundle, instr, slotnum); + ptrace(PTRACE_POKETEXT, pid, addr, bundle.ubundle[0]); + ptrace(PTRACE_POKETEXT, pid, addr + 8, bundle.ubundle[1]); +} diff --git a/sysdeps/linux-gnu/ia64/plt.c b/sysdeps/linux-gnu/ia64/plt.c new file mode 100644 index 0000000..7fd451b --- /dev/null +++ b/sysdeps/linux-gnu/ia64/plt.c @@ -0,0 +1,46 @@ +#include <gelf.h> +#include "common.h" + +/* A bundle is 128 bits */ +#define BUNDLE_SIZE 16 + +/* + + The PLT has + + ] 3 bundles as a header + + ] The special reserved entry + + ] Following that, each PLT entry has it's initial code that the GOT entry + points to. Each PLT entry has one bundle allocated. + + ] Following that, each PLT entry has two bundles of actual PLT code, + i.e. load up the address from the GOT and jump to it. This is the + point we want to insert the breakpoint, as this will be captured + every time we jump to the PLT entry in the code. + +*/ + +GElf_Addr +arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) { + /* Find number of entires by removing header and special + * entry, dividing total size by three, since each PLT entry + * will have 3 bundles (1 for inital entry and two for the PLT + * code). */ + int entries = (lte->plt_size - 4 * BUNDLE_SIZE) / (3 * BUNDLE_SIZE); + + /* Now the point we want to break on is the PLT entry after + * all the header stuff */ + unsigned long addr = + lte->plt_addr + (4 * BUNDLE_SIZE) + (BUNDLE_SIZE * entries) + + (2 * ndx * BUNDLE_SIZE); + debug(3, "Found PLT %d entry at %lx\n", ndx, addr); + + return addr; +} + +void * +sym2addr(Process *proc, struct library_symbol *sym) { + return sym->enter_addr; +} diff --git a/sysdeps/linux-gnu/ia64/ptrace.h b/sysdeps/linux-gnu/ia64/ptrace.h new file mode 100644 index 0000000..c3cbcb6 --- /dev/null +++ b/sysdeps/linux-gnu/ia64/ptrace.h @@ -0,0 +1 @@ +#include <sys/ptrace.h> diff --git a/sysdeps/linux-gnu/ia64/regs.c b/sysdeps/linux-gnu/ia64/regs.c new file mode 100644 index 0000000..d161d34 --- /dev/null +++ b/sysdeps/linux-gnu/ia64/regs.c @@ -0,0 +1,51 @@ +#include "config.h" + +#include <sys/types.h> +#include <sys/ptrace.h> + +#include <asm/ptrace_offsets.h> +#include <asm/rse.h> + +#include <stddef.h> +#include "debug.h" +#include "common.h" + +void * +get_instruction_pointer(Process *proc) { + unsigned long ip = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IIP, 0); + unsigned long slot = + (ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IPSR, 0) >> 41) & 3; + + return (void *)(ip | slot); +} + +void +set_instruction_pointer(Process *proc, void *addr) { + + unsigned long newip = (unsigned long)addr; + unsigned long slot = (unsigned long)addr & 0xf; + unsigned long psr = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IPSR, 0); + + psr &= ~(3UL << 41); + psr |= (slot & 0x3) << 41; + + newip &= ~0xfUL; + + ptrace(PTRACE_POKEUSER, proc->pid, PT_CR_IIP, (long)newip); + ptrace(PTRACE_POKEUSER, proc->pid, PT_CR_IPSR, psr); +} + +void * +get_stack_pointer(Process *proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0); +} + +void * +get_return_addr(Process *proc, void *stack_pointer) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, PT_B0, 0); +} + +void +set_return_addr(Process *proc, void *addr) { + ptrace(PTRACE_POKEUSER, proc->pid, PT_B0, addr); +} diff --git a/sysdeps/linux-gnu/ia64/signalent.h b/sysdeps/linux-gnu/ia64/signalent.h new file mode 100644 index 0000000..5395f82 --- /dev/null +++ b/sysdeps/linux-gnu/ia64/signalent.h @@ -0,0 +1,32 @@ + "SIG_0", /* 0 */ + "SIGHUP", /* 1 */ + "SIGINT", /* 2 */ + "SIGQUIT", /* 3 */ + "SIGILL", /* 4 */ + "SIGTRAP", /* 5 */ + "SIGABRT", /* 6 */ + "SIGBUS", /* 7 */ + "SIGFPE", /* 8 */ + "SIGKILL", /* 9 */ + "SIGUSR1", /* 10 */ + "SIGSEGV", /* 11 */ + "SIGUSR2", /* 12 */ + "SIGPIPE", /* 13 */ + "SIGALRM", /* 14 */ + "SIGTERM", /* 15 */ + "SIGSTKFLT", /* 16 */ + "SIGCHLD", /* 17 */ + "SIGCONT", /* 18 */ + "SIGSTOP", /* 19 */ + "SIGTSTP", /* 20 */ + "SIGTTIN", /* 21 */ + "SIGTTOU", /* 22 */ + "SIGURG", /* 23 */ + "SIGXCPU", /* 24 */ + "SIGXFSZ", /* 25 */ + "SIGVTALRM", /* 26 */ + "SIGPROF", /* 27 */ + "SIGWINCH", /* 28 */ + "SIGIO", /* 29 */ + "SIGPWR", /* 30 */ + "SIGSYS", /* 31 */ diff --git a/sysdeps/linux-gnu/ia64/syscallent.h b/sysdeps/linux-gnu/ia64/syscallent.h new file mode 100644 index 0000000..9bb4fb8 --- /dev/null +++ b/sysdeps/linux-gnu/ia64/syscallent.h @@ -0,0 +1,1303 @@ + "0", /* 0 */ + "1", /* 1 */ + "2", /* 2 */ + "3", /* 3 */ + "4", /* 4 */ + "5", /* 5 */ + "6", /* 6 */ + "7", /* 7 */ + "8", /* 8 */ + "9", /* 9 */ + "10", /* 10 */ + "11", /* 11 */ + "12", /* 12 */ + "13", /* 13 */ + "14", /* 14 */ + "15", /* 15 */ + "16", /* 16 */ + "17", /* 17 */ + "18", /* 18 */ + "19", /* 19 */ + "20", /* 20 */ + "21", /* 21 */ + "22", /* 22 */ + "23", /* 23 */ + "24", /* 24 */ + "25", /* 25 */ + "26", /* 26 */ + "27", /* 27 */ + "28", /* 28 */ + "29", /* 29 */ + "30", /* 30 */ + "31", /* 31 */ + "32", /* 32 */ + "33", /* 33 */ + "34", /* 34 */ + "35", /* 35 */ + "36", /* 36 */ + "37", /* 37 */ + "38", /* 38 */ + "39", /* 39 */ + "40", /* 40 */ + "41", /* 41 */ + "42", /* 42 */ + "43", /* 43 */ + "44", /* 44 */ + "45", /* 45 */ + "46", /* 46 */ + "47", /* 47 */ + "48", /* 48 */ + "49", /* 49 */ + "50", /* 50 */ + "51", /* 51 */ + "52", /* 52 */ + "53", /* 53 */ + "54", /* 54 */ + "55", /* 55 */ + "56", /* 56 */ + "57", /* 57 */ + "58", /* 58 */ + "59", /* 59 */ + "60", /* 60 */ + "61", /* 61 */ + "62", /* 62 */ + "63", /* 63 */ + "64", /* 64 */ + "65", /* 65 */ + "66", /* 66 */ + "67", /* 67 */ + "68", /* 68 */ + "69", /* 69 */ + "70", /* 70 */ + "71", /* 71 */ + "72", /* 72 */ + "73", /* 73 */ + "74", /* 74 */ + "75", /* 75 */ + "76", /* 76 */ + "77", /* 77 */ + "78", /* 78 */ + "79", /* 79 */ + "80", /* 80 */ + "81", /* 81 */ + "82", /* 82 */ + "83", /* 83 */ + "84", /* 84 */ + "85", /* 85 */ + "86", /* 86 */ + "87", /* 87 */ + "88", /* 88 */ + "89", /* 89 */ + "90", /* 90 */ + "91", /* 91 */ + "92", /* 92 */ + "93", /* 93 */ + "94", /* 94 */ + "95", /* 95 */ + "96", /* 96 */ + "97", /* 97 */ + "98", /* 98 */ + "99", /* 99 */ + "100", /* 100 */ + "101", /* 101 */ + "102", /* 102 */ + "103", /* 103 */ + "104", /* 104 */ + "105", /* 105 */ + "106", /* 106 */ + "107", /* 107 */ + "108", /* 108 */ + "109", /* 109 */ + "110", /* 110 */ + "111", /* 111 */ + "112", /* 112 */ + "113", /* 113 */ + "114", /* 114 */ + "115", /* 115 */ + "116", /* 116 */ + "117", /* 117 */ + "118", /* 118 */ + "119", /* 119 */ + "120", /* 120 */ + "121", /* 121 */ + "122", /* 122 */ + "123", /* 123 */ + "124", /* 124 */ + "125", /* 125 */ + "126", /* 126 */ + "127", /* 127 */ + "128", /* 128 */ + "129", /* 129 */ + "130", /* 130 */ + "131", /* 131 */ + "132", /* 132 */ + "133", /* 133 */ + "134", /* 134 */ + "135", /* 135 */ + "136", /* 136 */ + "137", /* 137 */ + "138", /* 138 */ + "139", /* 139 */ + "140", /* 140 */ + "141", /* 141 */ + "142", /* 142 */ + "143", /* 143 */ + "144", /* 144 */ + "145", /* 145 */ + "146", /* 146 */ + "147", /* 147 */ + "148", /* 148 */ + "149", /* 149 */ + "150", /* 150 */ + "151", /* 151 */ + "152", /* 152 */ + "153", /* 153 */ + "154", /* 154 */ + "155", /* 155 */ + "156", /* 156 */ + "157", /* 157 */ + "158", /* 158 */ + "159", /* 159 */ + "160", /* 160 */ + "161", /* 161 */ + "162", /* 162 */ + "163", /* 163 */ + "164", /* 164 */ + "165", /* 165 */ + "166", /* 166 */ + "167", /* 167 */ + "168", /* 168 */ + "169", /* 169 */ + "170", /* 170 */ + "171", /* 171 */ + "172", /* 172 */ + "173", /* 173 */ + "174", /* 174 */ + "175", /* 175 */ + "176", /* 176 */ + "177", /* 177 */ + "178", /* 178 */ + "179", /* 179 */ + "180", /* 180 */ + "181", /* 181 */ + "182", /* 182 */ + "183", /* 183 */ + "184", /* 184 */ + "185", /* 185 */ + "186", /* 186 */ + "187", /* 187 */ + "188", /* 188 */ + "189", /* 189 */ + "190", /* 190 */ + "191", /* 191 */ + "192", /* 192 */ + "193", /* 193 */ + "194", /* 194 */ + "195", /* 195 */ + "196", /* 196 */ + "197", /* 197 */ + "198", /* 198 */ + "199", /* 199 */ + "200", /* 200 */ + "201", /* 201 */ + "202", /* 202 */ + "203", /* 203 */ + "204", /* 204 */ + "205", /* 205 */ + "206", /* 206 */ + "207", /* 207 */ + "208", /* 208 */ + "209", /* 209 */ + "210", /* 210 */ + "211", /* 211 */ + "212", /* 212 */ + "213", /* 213 */ + "214", /* 214 */ + "215", /* 215 */ + "216", /* 216 */ + "217", /* 217 */ + "218", /* 218 */ + "219", /* 219 */ + "220", /* 220 */ + "221", /* 221 */ + "222", /* 222 */ + "223", /* 223 */ + "224", /* 224 */ + "225", /* 225 */ + "226", /* 226 */ + "227", /* 227 */ + "228", /* 228 */ + "229", /* 229 */ + "230", /* 230 */ + "231", /* 231 */ + "232", /* 232 */ + "233", /* 233 */ + "234", /* 234 */ + "235", /* 235 */ + "236", /* 236 */ + "237", /* 237 */ + "238", /* 238 */ + "239", /* 239 */ + "240", /* 240 */ + "241", /* 241 */ + "242", /* 242 */ + "243", /* 243 */ + "244", /* 244 */ + "245", /* 245 */ + "246", /* 246 */ + "247", /* 247 */ + "248", /* 248 */ + "249", /* 249 */ + "250", /* 250 */ + "251", /* 251 */ + "252", /* 252 */ + "253", /* 253 */ + "254", /* 254 */ + "255", /* 255 */ + "256", /* 256 */ + "257", /* 257 */ + "258", /* 258 */ + "259", /* 259 */ + "260", /* 260 */ + "261", /* 261 */ + "262", /* 262 */ + "263", /* 263 */ + "264", /* 264 */ + "265", /* 265 */ + "266", /* 266 */ + "267", /* 267 */ + "268", /* 268 */ + "269", /* 269 */ + "270", /* 270 */ + "271", /* 271 */ + "272", /* 272 */ + "273", /* 273 */ + "274", /* 274 */ + "275", /* 275 */ + "276", /* 276 */ + "277", /* 277 */ + "278", /* 278 */ + "279", /* 279 */ + "280", /* 280 */ + "281", /* 281 */ + "282", /* 282 */ + "283", /* 283 */ + "284", /* 284 */ + "285", /* 285 */ + "286", /* 286 */ + "287", /* 287 */ + "288", /* 288 */ + "289", /* 289 */ + "290", /* 290 */ + "291", /* 291 */ + "292", /* 292 */ + "293", /* 293 */ + "294", /* 294 */ + "295", /* 295 */ + "296", /* 296 */ + "297", /* 297 */ + "298", /* 298 */ + "299", /* 299 */ + "300", /* 300 */ + "301", /* 301 */ + "302", /* 302 */ + "303", /* 303 */ + "304", /* 304 */ + "305", /* 305 */ + "306", /* 306 */ + "307", /* 307 */ + "308", /* 308 */ + "309", /* 309 */ + "310", /* 310 */ + "311", /* 311 */ + "312", /* 312 */ + "313", /* 313 */ + "314", /* 314 */ + "315", /* 315 */ + "316", /* 316 */ + "317", /* 317 */ + "318", /* 318 */ + "319", /* 319 */ + "320", /* 320 */ + "321", /* 321 */ + "322", /* 322 */ + "323", /* 323 */ + "324", /* 324 */ + "325", /* 325 */ + "326", /* 326 */ + "327", /* 327 */ + "328", /* 328 */ + "329", /* 329 */ + "330", /* 330 */ + "331", /* 331 */ + "332", /* 332 */ + "333", /* 333 */ + "334", /* 334 */ + "335", /* 335 */ + "336", /* 336 */ + "337", /* 337 */ + "338", /* 338 */ + "339", /* 339 */ + "340", /* 340 */ + "341", /* 341 */ + "342", /* 342 */ + "343", /* 343 */ + "344", /* 344 */ + "345", /* 345 */ + "346", /* 346 */ + "347", /* 347 */ + "348", /* 348 */ + "349", /* 349 */ + "350", /* 350 */ + "351", /* 351 */ + "352", /* 352 */ + "353", /* 353 */ + "354", /* 354 */ + "355", /* 355 */ + "356", /* 356 */ + "357", /* 357 */ + "358", /* 358 */ + "359", /* 359 */ + "360", /* 360 */ + "361", /* 361 */ + "362", /* 362 */ + "363", /* 363 */ + "364", /* 364 */ + "365", /* 365 */ + "366", /* 366 */ + "367", /* 367 */ + "368", /* 368 */ + "369", /* 369 */ + "370", /* 370 */ + "371", /* 371 */ + "372", /* 372 */ + "373", /* 373 */ + "374", /* 374 */ + "375", /* 375 */ + "376", /* 376 */ + "377", /* 377 */ + "378", /* 378 */ + "379", /* 379 */ + "380", /* 380 */ + "381", /* 381 */ + "382", /* 382 */ + "383", /* 383 */ + "384", /* 384 */ + "385", /* 385 */ + "386", /* 386 */ + "387", /* 387 */ + "388", /* 388 */ + "389", /* 389 */ + "390", /* 390 */ + "391", /* 391 */ + "392", /* 392 */ + "393", /* 393 */ + "394", /* 394 */ + "395", /* 395 */ + "396", /* 396 */ + "397", /* 397 */ + "398", /* 398 */ + "399", /* 399 */ + "400", /* 400 */ + "401", /* 401 */ + "402", /* 402 */ + "403", /* 403 */ + "404", /* 404 */ + "405", /* 405 */ + "406", /* 406 */ + "407", /* 407 */ + "408", /* 408 */ + "409", /* 409 */ + "410", /* 410 */ + "411", /* 411 */ + "412", /* 412 */ + "413", /* 413 */ + "414", /* 414 */ + "415", /* 415 */ + "416", /* 416 */ + "417", /* 417 */ + "418", /* 418 */ + "419", /* 419 */ + "420", /* 420 */ + "421", /* 421 */ + "422", /* 422 */ + "423", /* 423 */ + "424", /* 424 */ + "425", /* 425 */ + "426", /* 426 */ + "427", /* 427 */ + "428", /* 428 */ + "429", /* 429 */ + "430", /* 430 */ + "431", /* 431 */ + "432", /* 432 */ + "433", /* 433 */ + "434", /* 434 */ + "435", /* 435 */ + "436", /* 436 */ + "437", /* 437 */ + "438", /* 438 */ + "439", /* 439 */ + "440", /* 440 */ + "441", /* 441 */ + "442", /* 442 */ + "443", /* 443 */ + "444", /* 444 */ + "445", /* 445 */ + "446", /* 446 */ + "447", /* 447 */ + "448", /* 448 */ + "449", /* 449 */ + "450", /* 450 */ + "451", /* 451 */ + "452", /* 452 */ + "453", /* 453 */ + "454", /* 454 */ + "455", /* 455 */ + "456", /* 456 */ + "457", /* 457 */ + "458", /* 458 */ + "459", /* 459 */ + "460", /* 460 */ + "461", /* 461 */ + "462", /* 462 */ + "463", /* 463 */ + "464", /* 464 */ + "465", /* 465 */ + "466", /* 466 */ + "467", /* 467 */ + "468", /* 468 */ + "469", /* 469 */ + "470", /* 470 */ + "471", /* 471 */ + "472", /* 472 */ + "473", /* 473 */ + "474", /* 474 */ + "475", /* 475 */ + "476", /* 476 */ + "477", /* 477 */ + "478", /* 478 */ + "479", /* 479 */ + "480", /* 480 */ + "481", /* 481 */ + "482", /* 482 */ + "483", /* 483 */ + "484", /* 484 */ + "485", /* 485 */ + "486", /* 486 */ + "487", /* 487 */ + "488", /* 488 */ + "489", /* 489 */ + "490", /* 490 */ + "491", /* 491 */ + "492", /* 492 */ + "493", /* 493 */ + "494", /* 494 */ + "495", /* 495 */ + "496", /* 496 */ + "497", /* 497 */ + "498", /* 498 */ + "499", /* 499 */ + "500", /* 500 */ + "501", /* 501 */ + "502", /* 502 */ + "503", /* 503 */ + "504", /* 504 */ + "505", /* 505 */ + "506", /* 506 */ + "507", /* 507 */ + "508", /* 508 */ + "509", /* 509 */ + "510", /* 510 */ + "511", /* 511 */ + "512", /* 512 */ + "513", /* 513 */ + "514", /* 514 */ + "515", /* 515 */ + "516", /* 516 */ + "517", /* 517 */ + "518", /* 518 */ + "519", /* 519 */ + "520", /* 520 */ + "521", /* 521 */ + "522", /* 522 */ + "523", /* 523 */ + "524", /* 524 */ + "525", /* 525 */ + "526", /* 526 */ + "527", /* 527 */ + "528", /* 528 */ + "529", /* 529 */ + "530", /* 530 */ + "531", /* 531 */ + "532", /* 532 */ + "533", /* 533 */ + "534", /* 534 */ + "535", /* 535 */ + "536", /* 536 */ + "537", /* 537 */ + "538", /* 538 */ + "539", /* 539 */ + "540", /* 540 */ + "541", /* 541 */ + "542", /* 542 */ + "543", /* 543 */ + "544", /* 544 */ + "545", /* 545 */ + "546", /* 546 */ + "547", /* 547 */ + "548", /* 548 */ + "549", /* 549 */ + "550", /* 550 */ + "551", /* 551 */ + "552", /* 552 */ + "553", /* 553 */ + "554", /* 554 */ + "555", /* 555 */ + "556", /* 556 */ + "557", /* 557 */ + "558", /* 558 */ + "559", /* 559 */ + "560", /* 560 */ + "561", /* 561 */ + "562", /* 562 */ + "563", /* 563 */ + "564", /* 564 */ + "565", /* 565 */ + "566", /* 566 */ + "567", /* 567 */ + "568", /* 568 */ + "569", /* 569 */ + "570", /* 570 */ + "571", /* 571 */ + "572", /* 572 */ + "573", /* 573 */ + "574", /* 574 */ + "575", /* 575 */ + "576", /* 576 */ + "577", /* 577 */ + "578", /* 578 */ + "579", /* 579 */ + "580", /* 580 */ + "581", /* 581 */ + "582", /* 582 */ + "583", /* 583 */ + "584", /* 584 */ + "585", /* 585 */ + "586", /* 586 */ + "587", /* 587 */ + "588", /* 588 */ + "589", /* 589 */ + "590", /* 590 */ + "591", /* 591 */ + "592", /* 592 */ + "593", /* 593 */ + "594", /* 594 */ + "595", /* 595 */ + "596", /* 596 */ + "597", /* 597 */ + "598", /* 598 */ + "599", /* 599 */ + "600", /* 600 */ + "601", /* 601 */ + "602", /* 602 */ + "603", /* 603 */ + "604", /* 604 */ + "605", /* 605 */ + "606", /* 606 */ + "607", /* 607 */ + "608", /* 608 */ + "609", /* 609 */ + "610", /* 610 */ + "611", /* 611 */ + "612", /* 612 */ + "613", /* 613 */ + "614", /* 614 */ + "615", /* 615 */ + "616", /* 616 */ + "617", /* 617 */ + "618", /* 618 */ + "619", /* 619 */ + "620", /* 620 */ + "621", /* 621 */ + "622", /* 622 */ + "623", /* 623 */ + "624", /* 624 */ + "625", /* 625 */ + "626", /* 626 */ + "627", /* 627 */ + "628", /* 628 */ + "629", /* 629 */ + "630", /* 630 */ + "631", /* 631 */ + "632", /* 632 */ + "633", /* 633 */ + "634", /* 634 */ + "635", /* 635 */ + "636", /* 636 */ + "637", /* 637 */ + "638", /* 638 */ + "639", /* 639 */ + "640", /* 640 */ + "641", /* 641 */ + "642", /* 642 */ + "643", /* 643 */ + "644", /* 644 */ + "645", /* 645 */ + "646", /* 646 */ + "647", /* 647 */ + "648", /* 648 */ + "649", /* 649 */ + "650", /* 650 */ + "651", /* 651 */ + "652", /* 652 */ + "653", /* 653 */ + "654", /* 654 */ + "655", /* 655 */ + "656", /* 656 */ + "657", /* 657 */ + "658", /* 658 */ + "659", /* 659 */ + "660", /* 660 */ + "661", /* 661 */ + "662", /* 662 */ + "663", /* 663 */ + "664", /* 664 */ + "665", /* 665 */ + "666", /* 666 */ + "667", /* 667 */ + "668", /* 668 */ + "669", /* 669 */ + "670", /* 670 */ + "671", /* 671 */ + "672", /* 672 */ + "673", /* 673 */ + "674", /* 674 */ + "675", /* 675 */ + "676", /* 676 */ + "677", /* 677 */ + "678", /* 678 */ + "679", /* 679 */ + "680", /* 680 */ + "681", /* 681 */ + "682", /* 682 */ + "683", /* 683 */ + "684", /* 684 */ + "685", /* 685 */ + "686", /* 686 */ + "687", /* 687 */ + "688", /* 688 */ + "689", /* 689 */ + "690", /* 690 */ + "691", /* 691 */ + "692", /* 692 */ + "693", /* 693 */ + "694", /* 694 */ + "695", /* 695 */ + "696", /* 696 */ + "697", /* 697 */ + "698", /* 698 */ + "699", /* 699 */ + "700", /* 700 */ + "701", /* 701 */ + "702", /* 702 */ + "703", /* 703 */ + "704", /* 704 */ + "705", /* 705 */ + "706", /* 706 */ + "707", /* 707 */ + "708", /* 708 */ + "709", /* 709 */ + "710", /* 710 */ + "711", /* 711 */ + "712", /* 712 */ + "713", /* 713 */ + "714", /* 714 */ + "715", /* 715 */ + "716", /* 716 */ + "717", /* 717 */ + "718", /* 718 */ + "719", /* 719 */ + "720", /* 720 */ + "721", /* 721 */ + "722", /* 722 */ + "723", /* 723 */ + "724", /* 724 */ + "725", /* 725 */ + "726", /* 726 */ + "727", /* 727 */ + "728", /* 728 */ + "729", /* 729 */ + "730", /* 730 */ + "731", /* 731 */ + "732", /* 732 */ + "733", /* 733 */ + "734", /* 734 */ + "735", /* 735 */ + "736", /* 736 */ + "737", /* 737 */ + "738", /* 738 */ + "739", /* 739 */ + "740", /* 740 */ + "741", /* 741 */ + "742", /* 742 */ + "743", /* 743 */ + "744", /* 744 */ + "745", /* 745 */ + "746", /* 746 */ + "747", /* 747 */ + "748", /* 748 */ + "749", /* 749 */ + "750", /* 750 */ + "751", /* 751 */ + "752", /* 752 */ + "753", /* 753 */ + "754", /* 754 */ + "755", /* 755 */ + "756", /* 756 */ + "757", /* 757 */ + "758", /* 758 */ + "759", /* 759 */ + "760", /* 760 */ + "761", /* 761 */ + "762", /* 762 */ + "763", /* 763 */ + "764", /* 764 */ + "765", /* 765 */ + "766", /* 766 */ + "767", /* 767 */ + "768", /* 768 */ + "769", /* 769 */ + "770", /* 770 */ + "771", /* 771 */ + "772", /* 772 */ + "773", /* 773 */ + "774", /* 774 */ + "775", /* 775 */ + "776", /* 776 */ + "777", /* 777 */ + "778", /* 778 */ + "779", /* 779 */ + "780", /* 780 */ + "781", /* 781 */ + "782", /* 782 */ + "783", /* 783 */ + "784", /* 784 */ + "785", /* 785 */ + "786", /* 786 */ + "787", /* 787 */ + "788", /* 788 */ + "789", /* 789 */ + "790", /* 790 */ + "791", /* 791 */ + "792", /* 792 */ + "793", /* 793 */ + "794", /* 794 */ + "795", /* 795 */ + "796", /* 796 */ + "797", /* 797 */ + "798", /* 798 */ + "799", /* 799 */ + "800", /* 800 */ + "801", /* 801 */ + "802", /* 802 */ + "803", /* 803 */ + "804", /* 804 */ + "805", /* 805 */ + "806", /* 806 */ + "807", /* 807 */ + "808", /* 808 */ + "809", /* 809 */ + "810", /* 810 */ + "811", /* 811 */ + "812", /* 812 */ + "813", /* 813 */ + "814", /* 814 */ + "815", /* 815 */ + "816", /* 816 */ + "817", /* 817 */ + "818", /* 818 */ + "819", /* 819 */ + "820", /* 820 */ + "821", /* 821 */ + "822", /* 822 */ + "823", /* 823 */ + "824", /* 824 */ + "825", /* 825 */ + "826", /* 826 */ + "827", /* 827 */ + "828", /* 828 */ + "829", /* 829 */ + "830", /* 830 */ + "831", /* 831 */ + "832", /* 832 */ + "833", /* 833 */ + "834", /* 834 */ + "835", /* 835 */ + "836", /* 836 */ + "837", /* 837 */ + "838", /* 838 */ + "839", /* 839 */ + "840", /* 840 */ + "841", /* 841 */ + "842", /* 842 */ + "843", /* 843 */ + "844", /* 844 */ + "845", /* 845 */ + "846", /* 846 */ + "847", /* 847 */ + "848", /* 848 */ + "849", /* 849 */ + "850", /* 850 */ + "851", /* 851 */ + "852", /* 852 */ + "853", /* 853 */ + "854", /* 854 */ + "855", /* 855 */ + "856", /* 856 */ + "857", /* 857 */ + "858", /* 858 */ + "859", /* 859 */ + "860", /* 860 */ + "861", /* 861 */ + "862", /* 862 */ + "863", /* 863 */ + "864", /* 864 */ + "865", /* 865 */ + "866", /* 866 */ + "867", /* 867 */ + "868", /* 868 */ + "869", /* 869 */ + "870", /* 870 */ + "871", /* 871 */ + "872", /* 872 */ + "873", /* 873 */ + "874", /* 874 */ + "875", /* 875 */ + "876", /* 876 */ + "877", /* 877 */ + "878", /* 878 */ + "879", /* 879 */ + "880", /* 880 */ + "881", /* 881 */ + "882", /* 882 */ + "883", /* 883 */ + "884", /* 884 */ + "885", /* 885 */ + "886", /* 886 */ + "887", /* 887 */ + "888", /* 888 */ + "889", /* 889 */ + "890", /* 890 */ + "891", /* 891 */ + "892", /* 892 */ + "893", /* 893 */ + "894", /* 894 */ + "895", /* 895 */ + "896", /* 896 */ + "897", /* 897 */ + "898", /* 898 */ + "899", /* 899 */ + "900", /* 900 */ + "901", /* 901 */ + "902", /* 902 */ + "903", /* 903 */ + "904", /* 904 */ + "905", /* 905 */ + "906", /* 906 */ + "907", /* 907 */ + "908", /* 908 */ + "909", /* 909 */ + "910", /* 910 */ + "911", /* 911 */ + "912", /* 912 */ + "913", /* 913 */ + "914", /* 914 */ + "915", /* 915 */ + "916", /* 916 */ + "917", /* 917 */ + "918", /* 918 */ + "919", /* 919 */ + "920", /* 920 */ + "921", /* 921 */ + "922", /* 922 */ + "923", /* 923 */ + "924", /* 924 */ + "925", /* 925 */ + "926", /* 926 */ + "927", /* 927 */ + "928", /* 928 */ + "929", /* 929 */ + "930", /* 930 */ + "931", /* 931 */ + "932", /* 932 */ + "933", /* 933 */ + "934", /* 934 */ + "935", /* 935 */ + "936", /* 936 */ + "937", /* 937 */ + "938", /* 938 */ + "939", /* 939 */ + "940", /* 940 */ + "941", /* 941 */ + "942", /* 942 */ + "943", /* 943 */ + "944", /* 944 */ + "945", /* 945 */ + "946", /* 946 */ + "947", /* 947 */ + "948", /* 948 */ + "949", /* 949 */ + "950", /* 950 */ + "951", /* 951 */ + "952", /* 952 */ + "953", /* 953 */ + "954", /* 954 */ + "955", /* 955 */ + "956", /* 956 */ + "957", /* 957 */ + "958", /* 958 */ + "959", /* 959 */ + "960", /* 960 */ + "961", /* 961 */ + "962", /* 962 */ + "963", /* 963 */ + "964", /* 964 */ + "965", /* 965 */ + "966", /* 966 */ + "967", /* 967 */ + "968", /* 968 */ + "969", /* 969 */ + "970", /* 970 */ + "971", /* 971 */ + "972", /* 972 */ + "973", /* 973 */ + "974", /* 974 */ + "975", /* 975 */ + "976", /* 976 */ + "977", /* 977 */ + "978", /* 978 */ + "979", /* 979 */ + "980", /* 980 */ + "981", /* 981 */ + "982", /* 982 */ + "983", /* 983 */ + "984", /* 984 */ + "985", /* 985 */ + "986", /* 986 */ + "987", /* 987 */ + "988", /* 988 */ + "989", /* 989 */ + "990", /* 990 */ + "991", /* 991 */ + "992", /* 992 */ + "993", /* 993 */ + "994", /* 994 */ + "995", /* 995 */ + "996", /* 996 */ + "997", /* 997 */ + "998", /* 998 */ + "999", /* 999 */ + "1000", /* 1000 */ + "1001", /* 1001 */ + "1002", /* 1002 */ + "1003", /* 1003 */ + "1004", /* 1004 */ + "1005", /* 1005 */ + "1006", /* 1006 */ + "1007", /* 1007 */ + "1008", /* 1008 */ + "1009", /* 1009 */ + "1010", /* 1010 */ + "1011", /* 1011 */ + "1012", /* 1012 */ + "1013", /* 1013 */ + "1014", /* 1014 */ + "1015", /* 1015 */ + "1016", /* 1016 */ + "1017", /* 1017 */ + "1018", /* 1018 */ + "1019", /* 1019 */ + "1020", /* 1020 */ + "1021", /* 1021 */ + "1022", /* 1022 */ + "1023", /* 1023 */ + "ni_syscall", /* 1024 */ + "exit", /* 1025 */ + "read", /* 1026 */ + "write", /* 1027 */ + "open", /* 1028 */ + "close", /* 1029 */ + "creat", /* 1030 */ + "link", /* 1031 */ + "unlink", /* 1032 */ + "execve", /* 1033 */ + "chdir", /* 1034 */ + "fchdir", /* 1035 */ + "utimes", /* 1036 */ + "mknod", /* 1037 */ + "chmod", /* 1038 */ + "chown", /* 1039 */ + "lseek", /* 1040 */ + "getpid", /* 1041 */ + "getppid", /* 1042 */ + "mount", /* 1043 */ + "umount", /* 1044 */ + "setuid", /* 1045 */ + "getuid", /* 1046 */ + "geteuid", /* 1047 */ + "ptrace", /* 1048 */ + "access", /* 1049 */ + "sync", /* 1050 */ + "fsync", /* 1051 */ + "fdatasync", /* 1052 */ + "kill", /* 1053 */ + "rename", /* 1054 */ + "mkdir", /* 1055 */ + "rmdir", /* 1056 */ + "dup", /* 1057 */ + "pipe", /* 1058 */ + "times", /* 1059 */ + "brk", /* 1060 */ + "setgid", /* 1061 */ + "getgid", /* 1062 */ + "getegid", /* 1063 */ + "acct", /* 1064 */ + "ioctl", /* 1065 */ + "fcntl", /* 1066 */ + "umask", /* 1067 */ + "chroot", /* 1068 */ + "ustat", /* 1069 */ + "dup2", /* 1070 */ + "setreuid", /* 1071 */ + "setregid", /* 1072 */ + "getresuid", /* 1073 */ + "setresuid", /* 1074 */ + "getresgid", /* 1075 */ + "setresgid", /* 1076 */ + "getgroups", /* 1077 */ + "setgroups", /* 1078 */ + "getpgid", /* 1079 */ + "setpgid", /* 1080 */ + "setsid", /* 1081 */ + "getsid", /* 1082 */ + "sethostname", /* 1083 */ + "setrlimit", /* 1084 */ + "getrlimit", /* 1085 */ + "getrusage", /* 1086 */ + "gettimeofday", /* 1087 */ + "settimeofday", /* 1088 */ + "select", /* 1089 */ + "poll", /* 1090 */ + "symlink", /* 1091 */ + "readlink", /* 1092 */ + "uselib", /* 1093 */ + "swapon", /* 1094 */ + "swapoff", /* 1095 */ + "reboot", /* 1096 */ + "truncate", /* 1097 */ + "ftruncate", /* 1098 */ + "fchmod", /* 1099 */ + "fchown", /* 1100 */ + "getpriority", /* 1101 */ + "setpriority", /* 1102 */ + "statfs", /* 1103 */ + "fstatfs", /* 1104 */ + "gettid", /* 1105 */ + "semget", /* 1106 */ + "semop", /* 1107 */ + "semctl", /* 1108 */ + "msgget", /* 1109 */ + "msgsnd", /* 1110 */ + "msgrcv", /* 1111 */ + "msgctl", /* 1112 */ + "shmget", /* 1113 */ + "shmat", /* 1114 */ + "shmdt", /* 1115 */ + "shmctl", /* 1116 */ + "syslog", /* 1117 */ + "setitimer", /* 1118 */ + "getitimer", /* 1119 */ + "1120", /* 1120 */ + "1121", /* 1121 */ + "1122", /* 1122 */ + "vhangup", /* 1123 */ + "lchown", /* 1124 */ + "remap_file_pages", /* 1125 */ + "wait4", /* 1126 */ + "sysinfo", /* 1127 */ + "clone", /* 1128 */ + "setdomainname", /* 1129 */ + "uname", /* 1130 */ + "adjtimex", /* 1131 */ + "1132", /* 1132 */ + "init_module", /* 1133 */ + "delete_module", /* 1134 */ + "1135", /* 1135 */ + "1136", /* 1136 */ + "quotactl", /* 1137 */ + "bdflush", /* 1138 */ + "sysfs", /* 1139 */ + "personality", /* 1140 */ + "afs_syscall", /* 1141 */ + "setfsuid", /* 1142 */ + "setfsgid", /* 1143 */ + "getdents", /* 1144 */ + "flock", /* 1145 */ + "readv", /* 1146 */ + "writev", /* 1147 */ + "pread64", /* 1148 */ + "pwrite64", /* 1149 */ + "_sysctl", /* 1150 */ + "mmap", /* 1151 */ + "munmap", /* 1152 */ + "mlock", /* 1153 */ + "mlockall", /* 1154 */ + "mprotect", /* 1155 */ + "mremap", /* 1156 */ + "msync", /* 1157 */ + "munlock", /* 1158 */ + "munlockall", /* 1159 */ + "sched_getparam", /* 1160 */ + "sched_setparam", /* 1161 */ + "sched_getscheduler", /* 1162 */ + "sched_setscheduler", /* 1163 */ + "sched_yield", /* 1164 */ + "sched_get_priority_max", /* 1165 */ + "sched_get_priority_min", /* 1166 */ + "sched_rr_get_interval", /* 1167 */ + "nanosleep", /* 1168 */ + "nfsservctl", /* 1169 */ + "prctl", /* 1170 */ + "1171", /* 1171 */ + "mmap2", /* 1172 */ + "pciconfig_read", /* 1173 */ + "pciconfig_write", /* 1174 */ + "perfmonctl", /* 1175 */ + "sigaltstack", /* 1176 */ + "rt_sigaction", /* 1177 */ + "rt_sigpending", /* 1178 */ + "rt_sigprocmask", /* 1179 */ + "rt_sigqueueinfo", /* 1180 */ + "rt_sigreturn", /* 1181 */ + "rt_sigsuspend", /* 1182 */ + "rt_sigtimedwait", /* 1183 */ + "getcwd", /* 1184 */ + "capget", /* 1185 */ + "capset", /* 1186 */ + "sendfile", /* 1187 */ + "getpmsg", /* 1188 */ + "putpmsg", /* 1189 */ + "socket", /* 1190 */ + "bind", /* 1191 */ + "connect", /* 1192 */ + "listen", /* 1193 */ + "accept", /* 1194 */ + "getsockname", /* 1195 */ + "getpeername", /* 1196 */ + "socketpair", /* 1197 */ + "send", /* 1198 */ + "sendto", /* 1199 */ + "recv", /* 1200 */ + "recvfrom", /* 1201 */ + "shutdown", /* 1202 */ + "setsockopt", /* 1203 */ + "getsockopt", /* 1204 */ + "sendmsg", /* 1205 */ + "recvmsg", /* 1206 */ + "pivot_root", /* 1207 */ + "mincore", /* 1208 */ + "madvise", /* 1209 */ + "stat", /* 1210 */ + "lstat", /* 1211 */ + "fstat", /* 1212 */ + "clone2", /* 1213 */ + "getdents64", /* 1214 */ + "getunwind", /* 1215 */ + "readahead", /* 1216 */ + "setxattr", /* 1217 */ + "lsetxattr", /* 1218 */ + "fsetxattr", /* 1219 */ + "getxattr", /* 1220 */ + "lgetxattr", /* 1221 */ + "fgetxattr", /* 1222 */ + "listxattr", /* 1223 */ + "llistxattr", /* 1224 */ + "flistxattr", /* 1225 */ + "removexattr", /* 1226 */ + "lremovexattr", /* 1227 */ + "fremovexattr", /* 1228 */ + "tkill", /* 1229 */ + "futex", /* 1230 */ + "sched_setaffinity", /* 1231 */ + "sched_getaffinity", /* 1232 */ + "set_tid_address", /* 1233 */ + "fadvise64", /* 1234 */ + "tgkill", /* 1235 */ + "exit_group", /* 1236 */ + "lookup_dcookie", /* 1237 */ + "io_setup", /* 1238 */ + "io_destroy", /* 1239 */ + "io_getevents", /* 1240 */ + "io_submit", /* 1241 */ + "io_cancel", /* 1242 */ + "epoll_create", /* 1243 */ + "epoll_ctl", /* 1244 */ + "epoll_wait", /* 1245 */ + "restart_syscall", /* 1246 */ + "semtimedop", /* 1247 */ + "timer_create", /* 1248 */ + "timer_settime", /* 1249 */ + "timer_gettime", /* 1250 */ + "timer_getoverrun", /* 1251 */ + "timer_delete", /* 1252 */ + "clock_settime", /* 1253 */ + "clock_gettime", /* 1254 */ + "clock_getres", /* 1255 */ + "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 */ + "1276", /* 1276 */ + "inotify_init", /* 1277 */ + "inotify_add_watch", /* 1278 */ + "inotify_rm_watch", /* 1279 */ + "migrate_pages", /* 1280 */ + "openat", /* 1281 */ + "mkdirat", /* 1282 */ + "mknodat", /* 1283 */ + "fchownat", /* 1284 */ + "futimesat", /* 1285 */ + "newfstatat", /* 1286 */ + "unlinkat", /* 1287 */ + "renameat", /* 1288 */ + "linkat", /* 1289 */ + "symlinkat", /* 1290 */ + "readlinkat", /* 1291 */ + "fchmodat", /* 1292 */ + "faccessat", /* 1293 */ + "1294", /* 1294 */ + "1295", /* 1295 */ + "unshare", /* 1296 */ + "splice", /* 1297 */ + "set_robust_list", /* 1298 */ + "get_robust_list", /* 1299 */ + "sync_file_range", /* 1300 */ + "tee", /* 1301 */ + "vmsplice", /* 1302 */ diff --git a/sysdeps/linux-gnu/ia64/trace.c b/sysdeps/linux-gnu/ia64/trace.c new file mode 100644 index 0000000..799e0ff --- /dev/null +++ b/sysdeps/linux-gnu/ia64/trace.c @@ -0,0 +1,268 @@ +#include "config.h" + +#include <stdlib.h> +#include <stddef.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <sys/ptrace.h> +#include <string.h> +#include <asm/ptrace_offsets.h> +#include <asm/rse.h> + +#include "common.h" + +/* What we think of as a bundle, ptrace thinks of it as two unsigned + * longs */ +union bundle_t { + /* An IA64 instruction bundle has a 5 bit header describing the + * type of bundle, then 3 41 bit instructions + */ + struct { + struct { + unsigned long template:5; + unsigned long slot0:41; + unsigned long bot_slot1:18; + } word0; + struct { + unsigned long top_slot1:23; + unsigned long slot2:41; + } word1; + } bitmap; + unsigned long code[2]; +}; + +union cfm_t { + struct { + unsigned long sof:7; + unsigned long sol:7; + unsigned long sor:4; + unsigned long rrb_gr:7; + unsigned long rrb_fr:7; + unsigned long rrb_pr:6; + } cfm; + unsigned long value; +}; + +int +syscall_p(Process *proc, int status, int *sysnum) { + 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); + + /* r15 holds the system call number */ + unsigned long r15 = + ptrace(PTRACE_PEEKUSER, proc->pid, PT_R15, 0); + unsigned long insn; + + union bundle_t bundle; + + /* On fault, the IP has moved forward to the next + * slot. If that is zero, then the actual place we + * broke was in the previous bundle, so wind back the + * IP. + */ + if (slot == 0) + ip = ip - 16; + bundle.code[0] = ptrace(PTRACE_PEEKTEXT, proc->pid, ip, 0); + bundle.code[1] = ptrace(PTRACE_PEEKTEXT, proc->pid, ip + 8, 0); + + unsigned long bot = 0UL | bundle.bitmap.word0.bot_slot1; + unsigned long top = 0UL | bundle.bitmap.word1.top_slot1; + + /* handle the rollback, slot 0 is actually slot 2 of + * the previous instruction (see above) */ + switch (slot) { + case 0: + insn = bundle.bitmap.word1.slot2; + break; + case 1: + insn = bundle.bitmap.word0.slot0; + break; + case 2: + /* make sure we're shifting about longs */ + insn = 0UL | bot | (top << 18UL); + break; + default: + printf("Ummm, can't find instruction slot?\n"); + exit(1); + } + + /* We need to support both the older break instruction + * type syscalls, and the new epc type ones. + * + * Bit 20 of the break constant is encoded in the "i" + * bit (bit 36) of the instruction, hence you should + * see 0x1000000000. + * + * An EPC call is just 0x1ffffffffff + */ + if (insn == 0x1000000000 || insn == 0x1ffffffffff) { + *sysnum = r15; + if (proc->callstack_depth > 0 && + proc->callstack[proc->callstack_depth - 1].is_syscall && + proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { + return 2; + } + return 1; + } + } + return 0; +} + +/* Stolen from David Mosberger's utrace tool, which he released under + the GPL + (http://www.gelato.unsw.edu.au/archives/linux-ia64/0104/1405.html) */ +static inline double +fpreg_to_double (struct ia64_fpreg *fp) { + double result; + + asm ("ldf.fill %0=%1" : "=f"(result) : "m"(*fp)); + return result; +} + +static long +gimme_long_arg(enum tof type, Process *proc, int arg_num) { + union cfm_t cfm; + unsigned long bsp; + + bsp = ptrace(PTRACE_PEEKUSER, proc->pid, PT_AR_BSP, 0); + cfm.value = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CFM, 0); + + if (arg_num == -1) /* return value */ + return ptrace(PTRACE_PEEKUSER, proc->pid, PT_R8, 0); + + /* First 8 arguments are passed in registers on the register + * stack, the following arguments are passed on the stack + * after a 16 byte scratch area + * + * If the function has returned, the ia64 register window has + * been reverted to the caller's configuration. So although in + * the callee, the first parameter is in R32, in the caller + * the first parameter comes in the registers after the local + * registers (really, input parameters plus locals, but the + * hardware doesn't track the distinction.) So we have to add + * in the size of the local area (sol) to find the first + * parameter passed to the callee. */ + if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) { + if (arg_num < 8) { + if (type == LT_TOF_FUNCTIONR) + arg_num += cfm.cfm.sol; + + return ptrace(PTRACE_PEEKDATA, proc->pid, + (long)ia64_rse_skip_regs((unsigned long *)bsp, + -cfm.cfm.sof + arg_num), + 0); + } else { + unsigned long sp = + ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0) + 16; + return ptrace(PTRACE_PEEKDATA, proc->pid, + sp + (8 * (arg_num - 8))); + } + } + + if (type == LT_TOF_SYSCALL || LT_TOF_SYSCALLR) + return ptrace(PTRACE_PEEKDATA, proc->pid, + (long)ia64_rse_skip_regs((unsigned long *)bsp, arg_num), + 0); + + /* error if we get here */ + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + exit(1); +} + +static long float_regs[8] = { PT_F8, PT_F9, PT_F10, PT_F11, + PT_F12, PT_F13, PT_F14, PT_F15 }; +static double +gimme_float_arg(enum tof type, Process *proc, int arg_num) { + union cfm_t cfm; + unsigned long bsp; + struct ia64_fpreg reg; + + if (arg_num == -1) { /* return value */ + reg.u.bits[0] = ptrace(PTRACE_PEEKUSER, proc->pid, + PT_F8, 0); + reg.u.bits[1] = ptrace(PTRACE_PEEKUSER, proc->pid, + PT_F8 + 0x8, 0); + return fpreg_to_double(®); + } + + bsp = ptrace(PTRACE_PEEKUSER, proc->pid, PT_AR_BSP, 0); + cfm.value = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CFM, 0); + + /* The first 8 arguments are passed in regular registers + * (counting from R32), unless they are floating point values + * (the case in question here). In that case, up to the first + * 8 regular registers are still "allocated" for each of the + * first 8 parameters, but if a parameter is floating point, + * then the register is left unset and the parameter is passed + * in the first available floating-point register, counting + * from F8. + * + * Take func(int a, float f, int b, double d), for example. + * a - passed in R32 + * f - R33 left unset, value passed in F8 + * b - passed in R34 + * d - R35 left unset, value passed in F9 + * + * ltrace handles this by counting floating point arguments + * while parsing declarations. The "arg_num" in this routine + * (which is only called for floating point values) really + * means which floating point parameter we're looking for, + * ignoring everything else. + * + * Following the first 8 arguments, the remaining arguments + * are passed on the stack after a 16 byte scratch area + */ + if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) { + if (arg_num < 8) { + reg.u.bits[0] = ptrace(PTRACE_PEEKUSER, proc->pid, + float_regs[arg_num], 0); + reg.u.bits[1] = ptrace(PTRACE_PEEKUSER, proc->pid, + float_regs[arg_num] + 0x8, 0); + return fpreg_to_double(®); + } else { + unsigned long sp = + ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0) + 16; + reg.u.bits[0] = ptrace(PTRACE_PEEKDATA, proc->pid, + sp + (8 * (arg_num - 8))); + reg.u.bits[0] = ptrace(PTRACE_PEEKDATA, proc->pid, + sp + (8 * (arg_num - 8)) + 0x8); + return fpreg_to_double(®); + } + } + + /* error if we get here */ + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + exit(1); +} + +long +gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) { + union { + long l; + float f; + double d; + } cvt; + + if (info->type == ARGTYPE_FLOAT) + cvt.f = gimme_float_arg(type, proc, info->u.float_info.float_index); + else if (info->type == ARGTYPE_DOUBLE) + cvt.d = gimme_float_arg(type, proc, info->u.double_info.float_index); + else + cvt.l = gimme_long_arg(type, proc, arg_num); + + return cvt.l; +} + +void +save_register_args(enum tof type, Process *proc) { +} + +void +get_arch_dep(Process *proc) { +} diff --git a/sysdeps/linux-gnu/m68k/Makefile b/sysdeps/linux-gnu/m68k/Makefile new file mode 100644 index 0000000..60d7531 --- /dev/null +++ b/sysdeps/linux-gnu/m68k/Makefile @@ -0,0 +1,10 @@ +OBJ = trace.o regs.o plt.o + +all: arch.o + +arch.o: $(OBJ) + $(CC) -nostdlib -r -o arch.o $(OBJ) + +clean: + $(RM) $(OBJ) arch.o + diff --git a/sysdeps/linux-gnu/m68k/arch.h b/sysdeps/linux-gnu/m68k/arch.h new file mode 100644 index 0000000..1790d09 --- /dev/null +++ b/sysdeps/linux-gnu/m68k/arch.h @@ -0,0 +1,6 @@ +#define BREAKPOINT_VALUE { 0x4e, 0x4f } +#define BREAKPOINT_LENGTH 2 +#define DECR_PC_AFTER_BREAK 2 + +#define LT_ELFCLASS ELFCLASS32 +#define LT_ELF_MACHINE EM_68K diff --git a/sysdeps/linux-gnu/m68k/plt.c b/sysdeps/linux-gnu/m68k/plt.c new file mode 100644 index 0000000..508d7fc --- /dev/null +++ b/sysdeps/linux-gnu/m68k/plt.c @@ -0,0 +1,13 @@ +#include <gelf.h> +#include "common.h" + +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); +} + +void * +sym2addr(Process *proc, struct library_symbol *sym) { + return sym->enter_addr; +} diff --git a/sysdeps/linux-gnu/m68k/ptrace.h b/sysdeps/linux-gnu/m68k/ptrace.h new file mode 100644 index 0000000..c3cbcb6 --- /dev/null +++ b/sysdeps/linux-gnu/m68k/ptrace.h @@ -0,0 +1 @@ +#include <sys/ptrace.h> diff --git a/sysdeps/linux-gnu/m68k/regs.c b/sysdeps/linux-gnu/m68k/regs.c new file mode 100644 index 0000000..959a60e --- /dev/null +++ b/sysdeps/linux-gnu/m68k/regs.c @@ -0,0 +1,40 @@ +#include "config.h" + +#include <sys/types.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> + +#include "common.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +void * +get_instruction_pointer(Process *proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_PC, 0); +} + +void +set_instruction_pointer(Process *proc, void *addr) { + ptrace(PTRACE_POKEUSER, proc->pid, 4 * PT_PC, addr); +} + +void * +get_stack_pointer(Process *proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_USP, 0); +} + +void * +get_return_addr(Process *proc, void *stack_pointer) { + return (void *)ptrace(PTRACE_PEEKTEXT, proc->pid, stack_pointer, 0); +} + +void +set_return_addr(Process *proc, void *addr) { + ptrace(PTRACE_POKETEXT, proc->pid, proc->stack_pointer, addr); +} diff --git a/sysdeps/linux-gnu/m68k/signalent.h b/sysdeps/linux-gnu/m68k/signalent.h new file mode 100644 index 0000000..5395f82 --- /dev/null +++ b/sysdeps/linux-gnu/m68k/signalent.h @@ -0,0 +1,32 @@ + "SIG_0", /* 0 */ + "SIGHUP", /* 1 */ + "SIGINT", /* 2 */ + "SIGQUIT", /* 3 */ + "SIGILL", /* 4 */ + "SIGTRAP", /* 5 */ + "SIGABRT", /* 6 */ + "SIGBUS", /* 7 */ + "SIGFPE", /* 8 */ + "SIGKILL", /* 9 */ + "SIGUSR1", /* 10 */ + "SIGSEGV", /* 11 */ + "SIGUSR2", /* 12 */ + "SIGPIPE", /* 13 */ + "SIGALRM", /* 14 */ + "SIGTERM", /* 15 */ + "SIGSTKFLT", /* 16 */ + "SIGCHLD", /* 17 */ + "SIGCONT", /* 18 */ + "SIGSTOP", /* 19 */ + "SIGTSTP", /* 20 */ + "SIGTTIN", /* 21 */ + "SIGTTOU", /* 22 */ + "SIGURG", /* 23 */ + "SIGXCPU", /* 24 */ + "SIGXFSZ", /* 25 */ + "SIGVTALRM", /* 26 */ + "SIGPROF", /* 27 */ + "SIGWINCH", /* 28 */ + "SIGIO", /* 29 */ + "SIGPWR", /* 30 */ + "SIGSYS", /* 31 */ diff --git a/sysdeps/linux-gnu/m68k/syscallent.h b/sysdeps/linux-gnu/m68k/syscallent.h new file mode 100644 index 0000000..4d65b39 --- /dev/null +++ b/sysdeps/linux-gnu/m68k/syscallent.h @@ -0,0 +1,282 @@ + "0", /* 0 */ + "exit", /* 1 */ + "fork", /* 2 */ + "read", /* 3 */ + "write", /* 4 */ + "open", /* 5 */ + "close", /* 6 */ + "waitpid", /* 7 */ + "creat", /* 8 */ + "link", /* 9 */ + "unlink", /* 10 */ + "execve", /* 11 */ + "chdir", /* 12 */ + "time", /* 13 */ + "mknod", /* 14 */ + "chmod", /* 15 */ + "chown", /* 16 */ + "break", /* 17 */ + "oldstat", /* 18 */ + "lseek", /* 19 */ + "getpid", /* 20 */ + "mount", /* 21 */ + "umount", /* 22 */ + "setuid", /* 23 */ + "getuid", /* 24 */ + "stime", /* 25 */ + "ptrace", /* 26 */ + "alarm", /* 27 */ + "oldfstat", /* 28 */ + "pause", /* 29 */ + "utime", /* 30 */ + "stty", /* 31 */ + "gtty", /* 32 */ + "access", /* 33 */ + "nice", /* 34 */ + "ftime", /* 35 */ + "sync", /* 36 */ + "kill", /* 37 */ + "rename", /* 38 */ + "mkdir", /* 39 */ + "rmdir", /* 40 */ + "dup", /* 41 */ + "pipe", /* 42 */ + "times", /* 43 */ + "prof", /* 44 */ + "brk", /* 45 */ + "setgid", /* 46 */ + "getgid", /* 47 */ + "signal", /* 48 */ + "geteuid", /* 49 */ + "getegid", /* 50 */ + "acct", /* 51 */ + "umount2", /* 52 */ + "lock", /* 53 */ + "ioctl", /* 54 */ + "fcntl", /* 55 */ + "mpx", /* 56 */ + "setpgid", /* 57 */ + "ulimit", /* 58 */ + "oldolduname", /* 59 */ + "umask", /* 60 */ + "chroot", /* 61 */ + "ustat", /* 62 */ + "dup2", /* 63 */ + "getppid", /* 64 */ + "getpgrp", /* 65 */ + "setsid", /* 66 */ + "sigaction", /* 67 */ + "sgetmask", /* 68 */ + "ssetmask", /* 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 */ + "select", /* 82 */ + "symlink", /* 83 */ + "oldlstat", /* 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 */ + "profil", /* 98 */ + "statfs", /* 99 */ + "fstatfs", /* 100 */ + "ioperm", /* 101 */ + "socketcall", /* 102 */ + "syslog", /* 103 */ + "setitimer", /* 104 */ + "getitimer", /* 105 */ + "stat", /* 106 */ + "lstat", /* 107 */ + "fstat", /* 108 */ + "olduname", /* 109 */ + "110", /* 110 */ + "vhangup", /* 111 */ + "112", /* 112 */ + "113", /* 113 */ + "wait4", /* 114 */ + "swapoff", /* 115 */ + "sysinfo", /* 116 */ + "ipc", /* 117 */ + "fsync", /* 118 */ + "sigreturn", /* 119 */ + "clone", /* 120 */ + "setdomainname", /* 121 */ + "uname", /* 122 */ + "cacheflush", /* 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 */ + "getpagesize", /* 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 */ + "pread64", /* 180 */ + "pwrite64", /* 181 */ + "lchown", /* 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 */ + "chown32", /* 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 */ + "lchown32", /* 212 */ + "setuid32", /* 213 */ + "setgid32", /* 214 */ + "setfsuid32", /* 215 */ + "setfsgid32", /* 216 */ + "pivot_root", /* 217 */ + "218", /* 218 */ + "219", /* 219 */ + "getdents64", /* 220 */ + "gettid", /* 221 */ + "tkill", /* 222 */ + "setxattr", /* 223 */ + "lsetxattr", /* 224 */ + "fsetxattr", /* 225 */ + "getxattr", /* 226 */ + "lgetxattr", /* 227 */ + "fgetxattr", /* 228 */ + "listxattr", /* 229 */ + "llistxattr", /* 230 */ + "flistxattr", /* 231 */ + "removexattr", /* 232 */ + "lremovexattr", /* 233 */ + "fremovexattr", /* 234 */ + "futex", /* 235 */ + "sendfile64", /* 236 */ + "mincore", /* 237 */ + "madvise", /* 238 */ + "fcntl64", /* 239 */ + "readahead", /* 240 */ + "io_setup", /* 241 */ + "io_destroy", /* 242 */ + "io_getevents", /* 243 */ + "io_submit", /* 244 */ + "io_cancel", /* 245 */ + "fadvise64", /* 246 */ + "exit_group", /* 247 */ + "lookup_dcookie", /* 248 */ + "epoll_create", /* 249 */ + "epoll_ctl", /* 250 */ + "epoll_wait", /* 251 */ + "remap_file_pages", /* 252 */ + "set_tid_address", /* 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 */ + "statfs64", /* 263 */ + "fstatfs64", /* 264 */ + "tgkill", /* 265 */ + "utimes", /* 266 */ + "fadvise64_64", /* 267 */ + "mbind", /* 268 */ + "get_mempolicy", /* 269 */ + "set_mempolicy", /* 270 */ + "mq_open", /* 271 */ + "mq_unlink", /* 272 */ + "mq_timedsend", /* 273 */ + "mq_timedreceive", /* 274 */ + "mq_notify", /* 275 */ + "mq_getsetattr", /* 276 */ + "waitid", /* 277 */ + "vserver", /* 278 */ + "add_key", /* 279 */ + "request_key", /* 280 */ + "keyctl", /* 281 */ diff --git a/sysdeps/linux-gnu/m68k/trace.c b/sysdeps/linux-gnu/m68k/trace.c new file mode 100644 index 0000000..2f89fdf --- /dev/null +++ b/sysdeps/linux-gnu/m68k/trace.c @@ -0,0 +1,89 @@ +#include "config.h" + +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> + +#include "common.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +void +get_arch_dep(Process *proc) { +} + +/* Returns 1 if syscall, 2 if sysret, 0 otherwise. + */ +int +syscall_p(Process *proc, int status, int *sysnum) { + int depth; + + 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) { + return 2; + } else { + return 1; + } + } + } + return 0; +} + +long +gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) { + 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 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); + } +#else + /* That hack works on m68k, too */ + return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num, 0); +#endif + } else { + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + exit(1); + } + + return 0; +} + +void +save_register_args(enum tof type, Process *proc) { +} diff --git a/sysdeps/linux-gnu/mipsel/Doxyfile b/sysdeps/linux-gnu/mipsel/Doxyfile new file mode 100644 index 0000000..b4f5eb2 --- /dev/null +++ b/sysdeps/linux-gnu/mipsel/Doxyfile @@ -0,0 +1,275 @@ +# Doxyfile 1.5.1 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = ltrace-mipsel +PROJECT_NUMBER = +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +BUILTIN_STL_SUPPORT = NO +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = YES +SORT_BY_SCOPE_NAME = YES +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = NO +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = . +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.C \ + *.CC \ + *.C++ \ + *.II \ + *.I++ \ + *.H \ + *.HH \ + *.H++ \ + *.CS \ + *.PHP \ + *.PHP3 \ + *.M \ + *.MM \ + *.PY +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = YES +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = YES +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +CALLER_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = NO +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/sysdeps/linux-gnu/mipsel/Makefile b/sysdeps/linux-gnu/mipsel/Makefile new file mode 100644 index 0000000..44f4aae --- /dev/null +++ b/sysdeps/linux-gnu/mipsel/Makefile @@ -0,0 +1,22 @@ +.PHONY: all deps clean docs + +OBJ = trace.o regs.o plt.o +SRC=$(OBJ:.o=.c) + +all: arch.o + +deps: + $(CC) $(CFLAGS) $(CPPFLAGS) -M $(SRC) > .depends + +arch.o: $(OBJ) arch.h + $(CC) -nostdlib -r -o arch.o $(OBJ) + +clean: + -rm -f $(OBJ) arch.o + -rm -rf html + +docs: + doxygen + + +-include .depends diff --git a/sysdeps/linux-gnu/mipsel/arch.h b/sysdeps/linux-gnu/mipsel/arch.h new file mode 100644 index 0000000..dd0ca35 --- /dev/null +++ b/sysdeps/linux-gnu/mipsel/arch.h @@ -0,0 +1,9 @@ +#define BREAKPOINT_VALUE { 0x0d, 0x00, 0x00, 0x00 } +#define BREAKPOINT_LENGTH 4 +#define DECR_PC_AFTER_BREAK 0 + +#define LT_ELFCLASS ELFCLASS32 +#define LT_ELF_MACHINE EM_MIPS + +#define PLTs_INIT_BY_HERE "_start" +#define E_ENTRY_NAME "_start" diff --git a/sysdeps/linux-gnu/mipsel/mipsel.h b/sysdeps/linux-gnu/mipsel/mipsel.h new file mode 100644 index 0000000..a63cafd --- /dev/null +++ b/sysdeps/linux-gnu/mipsel/mipsel.h @@ -0,0 +1,11 @@ +#ifndef MIPSEL_h +#define MIPSEL_h +// linux-2.4.30/arch/mips/kernel/ptrace.c for these offsets. +#define off_v0 2 +#define off_pc 64 +#define off_a0 4 +#define off_a3 7 +#define off_lr 31 +#define off_sp 29 + +#endif // MIPSEL_h diff --git a/sysdeps/linux-gnu/mipsel/plt.c b/sysdeps/linux-gnu/mipsel/plt.c new file mode 100644 index 0000000..003171b --- /dev/null +++ b/sysdeps/linux-gnu/mipsel/plt.c @@ -0,0 +1,72 @@ +#include <debug.h> +#include <gelf.h> +#include <sys/ptrace.h> +#include "common.h" + +/** + \addtogroup mipsel + @{ + */ + +/** + \param lte Structure containing link table entry information + \param ndx Index into .dynsym + \param rela Not used. + \return Address of GOT table entry + + MIPS ABI Supplement: + + DT_PLTGOT This member holds the address of the .got section. + + DT_MIPS_SYMTABNO This member holds the number of entries in the + .dynsym section. + + DT_MIPS_LOCAL_GOTNO This member holds the number of local global + offset table entries. + + DT_MIPS_GOTSYM This member holds the index of the first dyamic + symbol table entry that corresponds to an entry in the gobal offset + table. + + Called by read_elf when building the symbol table. + + */ +GElf_Addr +arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) { + debug(1,"plt_addr %x ndx %#x",lte->pltgot_addr, ndx); + return lte->pltgot_addr + + sizeof(void *) * (lte->mips_local_gotno + (ndx - lte->mips_gotsym)); +} +/** + \param proc The process to work on. + \param sym The library symbol. + \return What is at the got table address + + The return value should be the address to put the breakpoint at. + + On the mips the library_symbol.enter_addr is the .got addr for the + symbol and the breakpoint.addr is the actual breakpoint address. + + Other processors use a plt, the mips is "special" in that is uses + the .got for both function and data relocations. Prior to program + startup, return 0. + + \warning MIPS relocations are lazy. This means that the breakpoint + may move after the first call. Ltrace dictionary routines don't + have a delete and symbol is one to one with breakpoint, so if the + breakpoint changes I just add a new breakpoint for the new address. + */ +void * +sym2addr(Process *proc, struct library_symbol *sym) { + long ret; + if(!proc->pid){ + return 0; + } + ret=ptrace(PTRACE_PEEKTEXT, proc->pid, sym->enter_addr, 0); + if(ret==-1){ + ret =0; + } + return (void *)ret;; +} + +/**@}*/ diff --git a/sysdeps/linux-gnu/mipsel/ptrace.h b/sysdeps/linux-gnu/mipsel/ptrace.h new file mode 100644 index 0000000..c3cbcb6 --- /dev/null +++ b/sysdeps/linux-gnu/mipsel/ptrace.h @@ -0,0 +1 @@ +#include <sys/ptrace.h> diff --git a/sysdeps/linux-gnu/mipsel/regs.c b/sysdeps/linux-gnu/mipsel/regs.c new file mode 100644 index 0000000..a7a6de1 --- /dev/null +++ b/sysdeps/linux-gnu/mipsel/regs.c @@ -0,0 +1,76 @@ +#include "config.h" + +#include <stddef.h> +#include <sys/types.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> +#include <linux/user.h> + +#include "common.h" +#include "mipsel.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +/** + \addtogroup mipsel + @{ + */ + + +/** + \param proc The process to work on. + \return The current instruction pointer. + */ +void * +get_instruction_pointer(Process *proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0); +} + +/** + \param proc The process to work on. + \param addr The address to set to. + + Called by \c continue_after_breakpoint(). + + \todo Our mips kernel ptrace doesn't support PTRACE_SINGLESTEP, so + we \c continue_process() after a breakpoint. Check if this is OK. + */ +void +set_instruction_pointer(Process *proc, void *addr) { + ptrace(PTRACE_POKEUSER, proc->pid, off_pc, addr); +} + +/** + \param proc The process to work on. + \return The current stack pointer. + */ +void * +get_stack_pointer(Process *proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_sp, 0); +} + +/** + \param proc The process to work on. + \param stack_pointer The current stack pointer for proc + \return The current return address. + + Called by \c handle_breakpoint(). + + Mips uses r31 for the return address, so the stack_pointer is + unused. + */ +void * +get_return_addr(Process *proc, void *stack_pointer) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0); +} + +void +set_return_addr(Process *proc, void *addr) { + ptrace(PTRACE_POKEUSER, proc->pid, off_lr, addr); +} diff --git a/sysdeps/linux-gnu/mipsel/signalent.h b/sysdeps/linux-gnu/mipsel/signalent.h new file mode 100644 index 0000000..6bb1ff6 --- /dev/null +++ b/sysdeps/linux-gnu/mipsel/signalent.h @@ -0,0 +1,32 @@ +"SIG_0", /* 0 */ + "SIGHUP", // 1 /* Hangup (POSIX). */ + "SIGINT", // 2 /* Interrupt (ANSI). */ + "SIGQUIT", // 3 /* Quit (POSIX). */ + "SIGILL", // 4 /* Illegal instruction (ANSI). */ + "SIGTRAP", // 5 /* Trace trap (POSIX). */ + "SIGIOT", // 6 /* IOT trap (4.2 BSD). */ + "SIGEMT", // 7 + "SIGFPE", // 8 /* Floating-point exception (ANSI). */ + "SIGKILL", // 9 /* Kill, unblockable (POSIX). */ + "SIGBUS", // 10 /* BUS error (4.2 BSD). */ + "SIGSEGV", // 11 /* Segmentation violation (ANSI). */ + "SIGSYS", // 12 + "SIGPIPE", // 13 /* Broken pipe (POSIX). */ + "SIGALRM", // 14 /* Alarm clock (POSIX). */ + "SIGTERM", // 15 /* Termination (ANSI). */ + "SIGUSR1", // 16 /* User-defined signal 1 (POSIX). */ + "SIGUSR2", // 17 /* User-defined signal 2 (POSIX). */ + "SIGCHLD", // 18 /* Child status has changed (POSIX). */ + "SIGPWR", // 19 /* Power failure restart (System V). */ + "SIGWINCH", // 20 /* Window size change (4.3 BSD, Sun). */ + "SIGURG", // 21 /* Urgent condition on socket (4.2 BSD). */ + "SIGIO", // 22 /* I/O now possible (4.2 BSD). */ + "SIGSTOP", // 23 /* Stop, unblockable (POSIX). */ + "SIGTSTP", // 24 /* Keyboard stop (POSIX). */ + "SIGCONT", // 25 /* Continue (POSIX). */ + "SIGTTIN", // 26 /* Background read from tty (POSIX). */ + "SIGTTOU", // 27 /* Background write to tty (POSIX). */ + "SIGVTALRM", // 28 /* Virtual alarm clock (4.2 BSD). */ + "SIGPROF", // 29 /* Profiling alarm clock (4.2 BSD). */ + "SIGXCPU", // 30 /* CPU limit exceeded (4.2 BSD). */ + "SIGXFSZ", // 31 /* File size limit exceeded (4.2 BSD). */ diff --git a/sysdeps/linux-gnu/mipsel/syscallent.h b/sysdeps/linux-gnu/mipsel/syscallent.h new file mode 100644 index 0000000..bed43fe --- /dev/null +++ b/sysdeps/linux-gnu/mipsel/syscallent.h @@ -0,0 +1,241 @@ + "0", /*Linux + 0*/ + "exit", /*Linux + 1*/ + "fork", /*Linux + 2*/ + "read", /*Linux + 3*/ + "write", /*Linux + 4*/ + "open", /*Linux + 5*/ + "close", /*Linux + 6*/ + "waitpid", /*Linux + 7*/ + "creat", /*Linux + 8*/ + "link", /*Linux + 9*/ + "unlink", /*Linux + 10*/ + "execve", /*Linux + 11*/ + "chdir", /*Linux + 12*/ + "time", /*Linux + 13*/ + "mknod", /*Linux + 14*/ + "chmod", /*Linux + 15*/ + "lchown", /*Linux + 16*/ + "break", /*Linux + 17*/ + "unused18", /*Linux + 18*/ + "lseek", /*Linux + 19*/ + "getpid", /*Linux + 20*/ + "mount", /*Linux + 21*/ + "umount", /*Linux + 22*/ + "setuid", /*Linux + 23*/ + "getuid", /*Linux + 24*/ + "stime", /*Linux + 25*/ + "ptrace", /*Linux + 26*/ + "alarm", /*Linux + 27*/ + "unused28", /*Linux + 28*/ + "pause", /*Linux + 29*/ + "utime", /*Linux + 30*/ + "stty", /*Linux + 31*/ + "gtty", /*Linux + 32*/ + "access", /*Linux + 33*/ + "nice", /*Linux + 34*/ + "ftime", /*Linux + 35*/ + "sync", /*Linux + 36*/ + "kill", /*Linux + 37*/ + "rename", /*Linux + 38*/ + "mkdir", /*Linux + 39*/ + "rmdir", /*Linux + 40*/ + "dup", /*Linux + 41*/ + "pipe", /*Linux + 42*/ + "times", /*Linux + 43*/ + "prof", /*Linux + 44*/ + "brk", /*Linux + 45*/ + "setgid", /*Linux + 46*/ + "getgid", /*Linux + 47*/ + "signal", /*Linux + 48*/ + "geteuid", /*Linux + 49*/ + "getegid", /*Linux + 50*/ + "acct", /*Linux + 51*/ + "umount2", /*Linux + 52*/ + "lock", /*Linux + 53*/ + "ioctl", /*Linux + 54*/ + "fcntl", /*Linux + 55*/ + "mpx", /*Linux + 56*/ + "setpgid", /*Linux + 57*/ + "ulimit", /*Linux + 58*/ + "unused59", /*Linux + 59*/ + "umask", /*Linux + 60*/ + "chroot", /*Linux + 61*/ + "ustat", /*Linux + 62*/ + "dup2", /*Linux + 63*/ + "getppid", /*Linux + 64*/ + "getpgrp", /*Linux + 65*/ + "setsid", /*Linux + 66*/ + "sigaction", /*Linux + 67*/ + "sgetmask", /*Linux + 68*/ + "ssetmask", /*Linux + 69*/ + "setreuid", /*Linux + 70*/ + "setregid", /*Linux + 71*/ + "sigsuspend", /*Linux + 72*/ + "sigpending", /*Linux + 73*/ + "sethostname", /*Linux + 74*/ + "setrlimit", /*Linux + 75*/ + "getrlimit", /*Linux + 76*/ + "getrusage", /*Linux + 77*/ + "gettimeofday", /*Linux + 78*/ + "settimeofday", /*Linux + 79*/ + "getgroups", /*Linux + 80*/ + "setgroups", /*Linux + 81*/ + "reserved82", /*Linux + 82*/ + "symlink", /*Linux + 83*/ + "unused84", /*Linux + 84*/ + "readlink", /*Linux + 85*/ + "uselib", /*Linux + 86*/ + "swapon", /*Linux + 87*/ + "reboot", /*Linux + 88*/ + "readdir", /*Linux + 89*/ + "mmap", /*Linux + 90*/ + "munmap", /*Linux + 91*/ + "truncate", /*Linux + 92*/ + "ftruncate", /*Linux + 93*/ + "fchmod", /*Linux + 94*/ + "fchown", /*Linux + 95*/ + "getpriority", /*Linux + 96*/ + "setpriority", /*Linux + 97*/ + "profil", /*Linux + 98*/ + "statfs", /*Linux + 99*/ + "fstatfs", /*Linux + 100*/ + "ioperm", /*Linux + 101*/ + "socketcall", /*Linux + 102*/ + "syslog", /*Linux + 103*/ + "setitimer", /*Linux + 104*/ + "getitimer", /*Linux + 105*/ + "stat", /*Linux + 106*/ + "lstat", /*Linux + 107*/ + "fstat", /*Linux + 108*/ + "unused109", /*Linux + 109*/ + "iopl", /*Linux + 110*/ + "vhangup", /*Linux + 111*/ + "idle", /*Linux + 112*/ + "vm86", /*Linux + 113*/ + "wait4", /*Linux + 114*/ + "swapoff", /*Linux + 115*/ + "sysinfo", /*Linux + 116*/ + "ipc", /*Linux + 117*/ + "fsync", /*Linux + 118*/ + "sigreturn", /*Linux + 119*/ + "clone", /*Linux + 120*/ + "setdomainname", /*Linux + 121*/ + "uname", /*Linux + 122*/ + "modify_ldt", /*Linux + 123*/ + "adjtimex", /*Linux + 124*/ + "mprotect", /*Linux + 125*/ + "sigprocmask", /*Linux + 126*/ + "create_module", /*Linux + 127*/ + "init_module", /*Linux + 128*/ + "delete_module", /*Linux + 129*/ + "get_kernel_syms", /*Linux + 130*/ + "quotactl", /*Linux + 131*/ + "getpgid", /*Linux + 132*/ + "fchdir", /*Linux + 133*/ + "bdflush", /*Linux + 134*/ + "sysfs", /*Linux + 135*/ + "personality", /*Linux + 136*/ + "afs_syscall", /*Linux + 137*/ /* Syscall for Andrew File System */ + "setfsuid", /*Linux + 138*/ + "setfsgid", /*Linux + 139*/ + "_llseek", /*Linux + 140*/ + "getdents", /*Linux + 141*/ + "_newselect", /*Linux + 142*/ + "flock", /*Linux + 143*/ + "msync", /*Linux + 144*/ + "readv", /*Linux + 145*/ + "writev", /*Linux + 146*/ + "cacheflush", /*Linux + 147*/ + "cachectl", /*Linux + 148*/ + "sysmips", /*Linux + 149*/ + "unused150", /*Linux + 150*/ + "getsid", /*Linux + 151*/ + "fdatasync", /*Linux + 152*/ + "_sysctl", /*Linux + 153*/ + "mlock", /*Linux + 154*/ + "munlock", /*Linux + 155*/ + "mlockall", /*Linux + 156*/ + "munlockall", /*Linux + 157*/ + "sched_setparam", /*Linux + 158*/ + "sched_getparam", /*Linux + 159*/ + "sched_setscheduler", /*Linux + 160*/ + "sched_getscheduler", /*Linux + 161*/ + "sched_yield", /*Linux + 162*/ + "sched_get_priority_max", /*Linux + 163*/ + "sched_get_priority_min", /*Linux + 164*/ + "sched_rr_get_interval", /*Linux + 165*/ + "nanosleep", /*Linux + 166*/ + "mremap", /*Linux + 167*/ + "accept", /*Linux + 168*/ + "bind", /*Linux + 169*/ + "connect", /*Linux + 170*/ + "getpeername", /*Linux + 171*/ + "getsockname", /*Linux + 172*/ + "getsockopt", /*Linux + 173*/ + "listen", /*Linux + 174*/ + "recv", /*Linux + 175*/ + "recvfrom", /*Linux + 176*/ + "recvmsg", /*Linux + 177*/ + "send", /*Linux + 178*/ + "sendmsg", /*Linux + 179*/ + "sendto", /*Linux + 180*/ + "setsockopt", /*Linux + 181*/ + "shutdown", /*Linux + 182*/ + "socket", /*Linux + 183*/ + "socketpair", /*Linux + 184*/ + "setresuid", /*Linux + 185*/ + "getresuid", /*Linux + 186*/ + "query_module", /*Linux + 187*/ + "poll", /*Linux + 188*/ + "nfsservctl", /*Linux + 189*/ + "setresgid", /*Linux + 190*/ + "getresgid", /*Linux + 191*/ + "prctl", /*Linux + 192*/ + "rt_sigreturn", /*Linux + 193*/ + "rt_sigaction", /*Linux + 194*/ + "rt_sigprocmask", /*Linux + 195*/ + "rt_sigpending", /*Linux + 196*/ + "rt_sigtimedwait", /*Linux + 197*/ + "rt_sigqueueinfo", /*Linux + 198*/ + "rt_sigsuspend", /*Linux + 199*/ + "pread", /*Linux + 200*/ + "pwrite", /*Linux + 201*/ + "chown", /*Linux + 202*/ + "getcwd", /*Linux + 203*/ + "capget", /*Linux + 204*/ + "capset", /*Linux + 205*/ + "sigaltstack", /*Linux + 206*/ + "sendfile", /*Linux + 207*/ + "getpmsg", /*Linux + 208*/ + "putpmsg", /*Linux + 209*/ + "mmap2", /*Linux + 210*/ + "truncate64", /*Linux + 211*/ + "ftruncate64", /*Linux + 212*/ + "stat64", /*Linux + 213*/ + "lstat64", /*Linux + 214*/ + "fstat64", /*Linux + 215*/ + "pivot_root", /*Linux + 216*/ + "mincore", /*Linux + 217*/ + "madvise", /*Linux + 218*/ + "getdents64", /*Linux + 219*/ + "fcntl64", /*Linux + 220*/ + "security", /*Linux + 221*/ + "gettid", /*Linux + 222*/ + "readahead", /*Linux + 223*/ + "setxattr", /*Linux + 224*/ + "lsetxattr", /*Linux + 225*/ + "fsetxattr", /*Linux + 226*/ + "getxattr", /*Linux + 227*/ + "lgetxattr", /*Linux + 228*/ + "fgetxattr", /*Linux + 229*/ + "listxattr", /*Linux + 230*/ + "llistxattr", /*Linux + 231*/ + "flistxattr", /*Linux + 232*/ + "removexattr", /*Linux + 233*/ + "lremovexattr", /*Linux + 234*/ + "fremovexattr", /*Linux + 235*/ + "tkill", /*Linux + 236*/ + "sendfile64", /*Linux + 237*/ + "futex", /*Linux + 238*/ + "sched_setaffinity", /*Linux + 239*/ + "sched_getaffinity", /*Linux + 240*/ diff --git a/sysdeps/linux-gnu/mipsel/trace.c b/sysdeps/linux-gnu/mipsel/trace.c new file mode 100644 index 0000000..ff94930 --- /dev/null +++ b/sysdeps/linux-gnu/mipsel/trace.c @@ -0,0 +1,167 @@ +#include "config.h" + +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> +#include "debug.h" +#include "common.h" +#include "mipsel.h" +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + + +/** + \addtogroup mipsel Mipsel specific functions. + + These are the functions that it looks like I need to implement in + order to get ltrace to work on our target. + + @{ + */ + +/** + \param proc The process that had an event. + + Called by \c next_event() right after the return from wait. + + Most targets just return here. A couple use proc->arch_ptr for a + private data area. + */ +void +get_arch_dep(Process *proc) { +} + +/** + \param proc Process that had event. + \param status From \c wait() + \param sysnum 0-based syscall number. + \return 1 if syscall, 2 if sysret, 0 otherwise. + + Called by \c next_event() after the call to get_arch_dep() + + It seems that the ptrace call trips twice on a system call, once + just before the system call and once when it returns. Both times, + the pc points at the instruction just after the mipsel "syscall" + instruction. + + There are several possiblities for system call sets, each is offset + by a base from the others. On our system, it looks like the base + for the system calls is 4000. + */ +int +syscall_p(Process *proc, int status, int *sysnum) { + if (WIFSTOPPED(status) + && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { + /* get the user's pc (plus 8) */ + long pc = (long)get_instruction_pointer(proc); + /* fetch the SWI instruction */ + int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0); + int num = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 8, 0); + + /* + On a mipsel, syscall looks like: + 24040fa1 li v0, 0x0fa1 # 4001 --> _exit syscall + 0000000c syscall + */ + if(insn!=0x0000000c){ + return 0; + } + + *sysnum = (num & 0xFFFF) - 4000; + /* if it is a syscall, return 1 or 2 */ + if (proc->callstack_depth > 0 && + proc->callstack[proc->callstack_depth - 1].is_syscall && + proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { + return 2; + } + + if (*sysnum >= 0) { + return 1; + } + } + return 0; +} +/** + \param type Function/syscall call or return. + \param proc The process that had an event. + \param arg_num -1 for return value, + \return The argument to fetch. + + A couple of assumptions. + +- Type is LT_TOF_FUNCTIONR or LT_TOF_SYSCALLR if arg_num==-1. These + types are only used in calls for output_right(), which only uses -1 + for arg_num. +- Type is LT_TOF_FUNCTION or LT_TOF_SYSCALL for args 0...4. +- I'm only displaying the first 4 args (Registers a0..a3). Good + enough for now. + + Mipsel conventions seem to be: +- syscall parameters: r4...r9 +- syscall return: if(!a3){ return v0;} else{ errno=v0;return -1;} +- function call: r4..r7. Not sure how to get arg number 5. +- function return: v0 + +The argument registers are wiped by a call, so it is a mistake to ask +for arguments on a return. If ltrace does this, we will need to cache +arguments somewhere on the call. + +I'm not doing any floating point support here. + +*/ +long +gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) { + long ret; + debug(2,"type %d arg %d",type,arg_num); + if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL){ + if(arg_num <4){ + ret=ptrace(PTRACE_PEEKUSER,proc->pid,off_a0+arg_num,0); + debug(2,"ret = %#lx",ret); + return ret; + } else { + // If we need this, I think we can look at [sp+16] for arg_num==4. + CP; + return 0; + } + } + if(arg_num>=0){ + fprintf(stderr,"args on return?"); + } + if(type == LT_TOF_FUNCTIONR) { + return ptrace(PTRACE_PEEKUSER,proc->pid,off_v0,0); + } + if (type == LT_TOF_SYSCALLR) { + unsigned a3=ptrace(PTRACE_PEEKUSER, proc->pid,off_a3,0); + unsigned v0=ptrace(PTRACE_PEEKUSER, proc->pid,off_v0,0); + if(!a3){ + return v0; + } + return -1; + } + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + return 0; +} + +/** + \param type Type of call/return + \param proc Process to work with. + + Called by \c output_left(), which is called on a syscall or + function. + + The other architectures stub this out, but seems to be the place to + stash off the arguments on a call so we have them on the return. + +*/ +void +save_register_args(enum tof type, Process *proc) { +} + +/**@}*/ diff --git a/sysdeps/linux-gnu/mksignalent b/sysdeps/linux-gnu/mksignalent new file mode 100755 index 0000000..316d81f --- /dev/null +++ b/sysdeps/linux-gnu/mksignalent @@ -0,0 +1,33 @@ +#!/usr/bin/awk -f + +# hack expression to generate arch/signalent.h from <asm/signal.h> +# It reads from stdin and writes to stdout + +BEGIN { + max=0; +} + +{ + if (($1 ~ /^#define$/) && (!SIGNAL[$3]) && ($2 ~ /^SIG[A-Z]/) \ + && ($2 !~ /^SIGRTMIN$/) && ($2 !~ /^SIGRTMAX$/) && ($2 !~ /^SIGSTKSZ$/) \ + && ($3>=0) && ($3<=1000)) { + SIGNAL[$3]=$2; + if ($3 > max) { + max=$3; + } + } +} + +END { + for(i=0; i<=max; i++) { + if (!SIGNAL[i]) { + SIGNAL[i] = "SIG_" i; + } + pad = 16 - length(SIGNAL[i]); + if (pad<1) { + pad=1; + } + printf("\t\"%s\",%*s/* %d */\n", SIGNAL[i], pad, "", i); + } +} + diff --git a/sysdeps/linux-gnu/mksyscallent b/sysdeps/linux-gnu/mksyscallent new file mode 100755 index 0000000..e0c3ec7 --- /dev/null +++ b/sysdeps/linux-gnu/mksyscallent @@ -0,0 +1,45 @@ +#!/usr/bin/awk -f + +# hack expression to generate arch/syscallent.h from <asm/unistd.h> +# It reads from stdin and writes to stdout +# It should work OK on i386,m68k,arm,ia64 +# It does NOT work in mips, s390 +# It is untested in other architectures + +BEGIN { + max=0; + FS="[ \t\n()+]+"; +} + +{ + #debug + #printf("/%s/%s/%s/%s/\n", $1, $2, $3, $4); + if (($1 ~ /^#define$/) && ($2 ~ /^__NR_/)) { + #ia64 syscalls are > 1000 (lower for x86 compat) + if (($3>=0) && ($3<=2000)) { + SYSCALL[$3]=substr($2,6); + if ($3 > max) { + max=$3; + } + } else if (($3 ~ /^__NR_SYSCALL_BASE$/) && ($4>=0) && ($4<=1000)) { + SYSCALL[$4]=substr($2,6); + if ($4 > max) { + max=$4; + } + } + } +} + +END { + for(i=0; i<=max; i++) { + if (!SYSCALL[i]) { + SYSCALL[i] = i; + } + pad = 32 - length(SYSCALL[i]); + if (pad<1) { + pad=1; + } + printf("\t\"%s\",%*s/* %d */\n", SYSCALL[i], pad, "", i); + } +} + diff --git a/sysdeps/linux-gnu/mksyscallent_s390 b/sysdeps/linux-gnu/mksyscallent_s390 new file mode 100644 index 0000000..73416d9 --- /dev/null +++ b/sysdeps/linux-gnu/mksyscallent_s390 @@ -0,0 +1,38 @@ +#!/usr/bin/perl +# +# Generate syscall table for s390/s390x +# +# Use this on arch/s390/kernel/syscall.s after removing the first few +# nonsyscall lines. +# +# cat syscall.s | mksyscallent_s390 > syscalls31.h +# cat syscall.s | mksyscallent_s390 -x > syscalls64.h +# + +use Getopt::Std; +use integer; +getopts('x'); +$i = 0; +$s390x = 0; +$opt_x and $s390x = 1; + +while (<>) { + chomp; + + if ($s390x==1) { + s/^SYSCALL\([^,]*,//; + } else { + s/^SYSCALL\(//; + } + + s/,.*//; + s/^sys_//; + s/^s390[x]*_//; + s/_glue$//; + s/^ni_syscall.*/$i/i; + $len = 32 - length(); + $tab = $len / 8; + $space = $len % 8; + print " \"$_\"," ," " x $space , "\t" x $tab, " \/* $i \*\/\n"; + $i++; +} diff --git a/sysdeps/linux-gnu/ppc/Makefile b/sysdeps/linux-gnu/ppc/Makefile new file mode 100644 index 0000000..60d7531 --- /dev/null +++ b/sysdeps/linux-gnu/ppc/Makefile @@ -0,0 +1,10 @@ +OBJ = trace.o regs.o plt.o + +all: arch.o + +arch.o: $(OBJ) + $(CC) -nostdlib -r -o arch.o $(OBJ) + +clean: + $(RM) $(OBJ) arch.o + diff --git a/sysdeps/linux-gnu/ppc/arch.h b/sysdeps/linux-gnu/ppc/arch.h new file mode 100644 index 0000000..711b4a3 --- /dev/null +++ b/sysdeps/linux-gnu/ppc/arch.h @@ -0,0 +1,24 @@ +#define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 } +#define BREAKPOINT_LENGTH 4 +#define DECR_PC_AFTER_BREAK 0 + +#define LT_ELFCLASS ELFCLASS32 +#define LT_ELF_MACHINE EM_PPC + +#ifdef __powerpc64__ // Says 'ltrace' is 64 bits, says nothing about target. +#define LT_ELFCLASS2 ELFCLASS64 +#define LT_ELF_MACHINE2 EM_PPC64 +#define ARCH_SUPPORTS_OPD +#endif + +#define PLT_REINITALISATION_BP "_start" + +/* Start of arch-specific functions. */ +#define ARCH_HAVE_UMOVELONG + +#define PPC_NOP { 0x60, 0x00, 0x00, 0x00 } +#define PPC_NOP_LENGTH 4 + +#if (PPC_NOP_LENGTH != BREAKPOINT_LENGTH) +#error "Length of the breakpoint value not equal to the length of a nop instruction" +#endif diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c new file mode 100644 index 0000000..31830fb --- /dev/null +++ b/sysdeps/linux-gnu/ppc/plt.c @@ -0,0 +1,54 @@ +#include <gelf.h> +#include "common.h" + +GElf_Addr +arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) { + return rela->r_offset; +} + +void * +sym2addr(Process *proc, struct library_symbol *sym) { + void *addr = sym->enter_addr; + long pt_ret; + + debug(3, 0); + + if (sym->plt_type != LS_TOPLT_POINT) { + return addr; + } + + if (proc->pid == 0) { + return 0; + } + + if (options.debug >= 3) { + xinfdump(proc->pid, (void *)(((long)addr-32)&0xfffffff0), + sizeof(void*)*8); + } + + // 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. + + // On a PowerPC-32 system, there are two types of PLTs: secure (new) and + // non-secure (old). For the secure case, the PLT is simply a pointer + // and we can treat it much as we do for the PowerPC-64 case. For the + // non-secure case, the PLT is executable code and we can put the + // break-point right in the PLT. + + pt_ret = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0); + + if (proc->mask_32bit) { + // Assume big-endian. + addr = (void *)((pt_ret >> 32) & 0xffffffff); + } else { + addr = (void *)pt_ret; + } + + return addr; +} diff --git a/sysdeps/linux-gnu/ppc/ptrace.h b/sysdeps/linux-gnu/ppc/ptrace.h new file mode 100644 index 0000000..c3cbcb6 --- /dev/null +++ b/sysdeps/linux-gnu/ppc/ptrace.h @@ -0,0 +1 @@ +#include <sys/ptrace.h> diff --git a/sysdeps/linux-gnu/ppc/regs.c b/sysdeps/linux-gnu/ppc/regs.c new file mode 100644 index 0000000..eca58ff --- /dev/null +++ b/sysdeps/linux-gnu/ppc/regs.c @@ -0,0 +1,47 @@ +#include "config.h" + +#include <sys/types.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> + +#include "common.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +void * +get_instruction_pointer(Process *proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long)*PT_NIP, 0); +} + +void +set_instruction_pointer(Process *proc, void *addr) { + ptrace(PTRACE_POKEUSER, proc->pid, sizeof(long)*PT_NIP, addr); +} + +void * +get_stack_pointer(Process *proc) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long)*PT_R1, 0); +} + +void * +get_return_addr(Process *proc, void *stack_pointer) { + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long)*PT_LNK, 0); +} + +void +set_return_addr(Process *proc, void *addr) { + ptrace(PTRACE_POKEUSER, proc->pid, sizeof(long)*PT_LNK, addr); +} + +/* Grab the value of CTR registers. */ +void * +get_count_register (Process *proc) { + return (void *) ptrace (PTRACE_PEEKUSER, proc->pid, + sizeof (long) * PT_CTR, 0); +} diff --git a/sysdeps/linux-gnu/ppc/signalent.h b/sysdeps/linux-gnu/ppc/signalent.h new file mode 100644 index 0000000..d58a36c --- /dev/null +++ b/sysdeps/linux-gnu/ppc/signalent.h @@ -0,0 +1,32 @@ +"SIG_0", /* 0 */ + "SIGHUP", /* 1 */ + "SIGINT", /* 2 */ + "SIGQUIT", /* 3 */ + "SIGILL", /* 4 */ + "SIGTRAP", /* 5 */ + "SIGABRT", /* 6 */ + "SIGBUS", /* 7 */ + "SIGFPE", /* 8 */ + "SIGKILL", /* 9 */ + "SIGUSR1", /* 10 */ + "SIGSEGV", /* 11 */ + "SIGUSR2", /* 12 */ + "SIGPIPE", /* 13 */ + "SIGALRM", /* 14 */ + "SIGTERM", /* 15 */ + "SIGSTKFLT", /* 16 */ + "SIGCHLD", /* 17 */ + "SIGCONT", /* 18 */ + "SIGSTOP", /* 19 */ + "SIGTSTP", /* 20 */ + "SIGTTIN", /* 21 */ + "SIGTTOU", /* 22 */ + "SIGURG", /* 23 */ + "SIGXCPU", /* 24 */ + "SIGXFSZ", /* 25 */ + "SIGVTALRM", /* 26 */ + "SIGPROF", /* 27 */ + "SIGWINCH", /* 28 */ + "SIGIO", /* 29 */ + "SIGPWR", /* 30 */ + "SIGSYS", /* 31 */ diff --git a/sysdeps/linux-gnu/ppc/syscallent.h b/sysdeps/linux-gnu/ppc/syscallent.h new file mode 100644 index 0000000..5ce5739 --- /dev/null +++ b/sysdeps/linux-gnu/ppc/syscallent.h @@ -0,0 +1,272 @@ +"0", /* 0 */ + "exit", /* 1 */ + "fork", /* 2 */ + "read", /* 3 */ + "write", /* 4 */ + "open", /* 5 */ + "close", /* 6 */ + "waitpid", /* 7 */ + "creat", /* 8 */ + "link", /* 9 */ + "unlink", /* 10 */ + "execve", /* 11 */ + "chdir", /* 12 */ + "time", /* 13 */ + "mknod", /* 14 */ + "chmod", /* 15 */ + "lchown", /* 16 */ + "break", /* 17 */ + "oldstat", /* 18 */ + "lseek", /* 19 */ + "getpid", /* 20 */ + "mount", /* 21 */ + "umount", /* 22 */ + "setuid", /* 23 */ + "getuid", /* 24 */ + "stime", /* 25 */ + "ptrace", /* 26 */ + "alarm", /* 27 */ + "oldfstat", /* 28 */ + "pause", /* 29 */ + "utime", /* 30 */ + "stty", /* 31 */ + "gtty", /* 32 */ + "access", /* 33 */ + "nice", /* 34 */ + "ftime", /* 35 */ + "sync", /* 36 */ + "kill", /* 37 */ + "rename", /* 38 */ + "mkdir", /* 39 */ + "rmdir", /* 40 */ + "dup", /* 41 */ + "pipe", /* 42 */ + "times", /* 43 */ + "prof", /* 44 */ + "brk", /* 45 */ + "setgid", /* 46 */ + "getgid", /* 47 */ + "signal", /* 48 */ + "geteuid", /* 49 */ + "getegid", /* 50 */ + "acct", /* 51 */ + "umount2", /* 52 */ + "lock", /* 53 */ + "ioctl", /* 54 */ + "fcntl", /* 55 */ + "mpx", /* 56 */ + "setpgid", /* 57 */ + "ulimit", /* 58 */ + "oldolduname", /* 59 */ + "umask", /* 60 */ + "chroot", /* 61 */ + "ustat", /* 62 */ + "dup2", /* 63 */ + "getppid", /* 64 */ + "getpgrp", /* 65 */ + "setsid", /* 66 */ + "sigaction", /* 67 */ + "sgetmask", /* 68 */ + "ssetmask", /* 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 */ + "select", /* 82 */ + "symlink", /* 83 */ + "oldlstat", /* 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 */ + "profil", /* 98 */ + "statfs", /* 99 */ + "fstatfs", /* 100 */ + "ioperm", /* 101 */ + "socketcall", /* 102 */ + "syslog", /* 103 */ + "setitimer", /* 104 */ + "getitimer", /* 105 */ + "stat", /* 106 */ + "lstat", /* 107 */ + "fstat", /* 108 */ + "olduname", /* 109 */ + "iopl", /* 110 */ + "vhangup", /* 111 */ + "idle", /* 112 */ + "vm86", /* 113 */ + "wait4", /* 114 */ + "swapoff", /* 115 */ + "sysinfo", /* 116 */ + "ipc", /* 117 */ + "fsync", /* 118 */ + "sigreturn", /* 119 */ + "clone", /* 120 */ + "setdomainname", /* 121 */ + "uname", /* 122 */ + "modify_ldt", /* 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 */ + "query_module", /* 166 */ + "poll", /* 167 */ + "nfsservctl", /* 168 */ + "setresgid", /* 169 */ + "getresgid", /* 170 */ + "prctl", /* 171 */ + "rt_sigreturn", /* 172 */ + "rt_sigaction", /* 173 */ + "rt_sigprocmask", /* 174 */ + "rt_sigpending", /* 175 */ + "rt_sigtimedwait", /* 176 */ + "rt_sigqueueinfo", /* 177 */ + "rt_sigsuspend", /* 178 */ + "pread", /* 179 */ + "pwrite", /* 180 */ + "chown", /* 181 */ + "getcwd", /* 182 */ + "capget", /* 183 */ + "capset", /* 184 */ + "sigaltstack", /* 185 */ + "sendfile", /* 186 */ + "getpmsg", /* 187 */ + "putpmsg", /* 188 */ + "vfork", /* 189 */ + "ugetrlimit", /* 190 */ + "readahead", /* 191 */ + "mmap2", /* 192 */ + "truncate64", /* 193 */ + "ftruncate64", /* 194 */ + "stat64", /* 195 */ + "lstat64", /* 196 */ + "fstat64", /* 197 */ + "pciconfig_read", /* 198 */ + "pciconfig_write", /* 199 */ + "pciconfig_iobase", /* 200 */ + "multiplexer", /* 201 */ + "getdents64", /* 202 */ + "pivot_root", /* 203 */ + "fcntl64", /* 204 */ + "madvise", /* 205 */ + "mincore", /* 206 */ + "gettid", /* 207 */ + "tkill", /* 208 */ + "setxattr", /* 209 */ + "lsetxattr", /* 210 */ + "fsetxattr", /* 211 */ + "getxattr", /* 212 */ + "lgetxattr", /* 213 */ + "fgetxattr", /* 214 */ + "listxattr", /* 215 */ + "llistxattr", /* 216 */ + "flistxattr", /* 217 */ + "removexattr", /* 218 */ + "lremovexattr", /* 219 */ + "fremovexattr", /* 220 */ + "futex", /* 221 */ + "sched_setaffinity", /* 222 */ + "sched_getaffinity", /* 223 */ + "224", /* 224 */ + "tuxcall", /* 225 */ + "sendfile64", /* 226 */ + "io_setup", /* 227 */ + "io_destroy", /* 228 */ + "io_getevents", /* 229 */ + "io_submit", /* 230 */ + "io_cancel", /* 231 */ + "set_tid_address", /* 232 */ + "fadvise64", /* 233 */ + "exit_group", /* 234 */ + "lookup_dcookie", /* 235 */ + "epoll_create", /* 236 */ + "epoll_ctl", /* 237 */ + "epoll_wait", /* 238 */ + "remap_file_pages", /* 239 */ + "timer_create", /* 240 */ + "timer_settime", /* 241 */ + "timer_gettime", /* 242 */ + "timer_getoverrun", /* 243 */ + "timer_delete", /* 244 */ + "clock_settime", /* 245 */ + "clock_gettime", /* 246 */ + "clock_getres", /* 247 */ + "clock_nanosleep", /* 248 */ + "swapcontext", /* 249 */ + "tgkill", /* 250 */ + "utimes", /* 251 */ + "statfs64", /* 252 */ + "fstatfs64", /* 253 */ + "fadvise64_64", /* 254 */ + "rtas", /* 255 */ + "mq_open", /* 262 */ + "mq_unlink", /* 263 */ + "mq_timedsend", /* 264 */ + "mq_timedreceive", /* 265 */ + "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 new file mode 100644 index 0000000..81fb71d --- /dev/null +++ b/sysdeps/linux-gnu/ppc/trace.c @@ -0,0 +1,155 @@ +#include "config.h" + +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> +#include <elf.h> +#include <errno.h> + +#include "common.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +void +get_arch_dep(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 + +unsigned int greg = 3; +unsigned int freg = 1; +unsigned int vreg = 2; + +int +syscall_p(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 = + (int)ptrace(PTRACE_PEEKUSER, proc->pid, + sizeof(long) * PT_R0, 0); + if (proc->callstack_depth > 0 && + proc->callstack[proc->callstack_depth - 1].is_syscall && + proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { + return 2; + } + return 1; + } + } + return 0; +} + +/* Grab functions arguments based on the PPC64 ABI. */ +long +gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) { + long data; + + if (type == LT_TOF_FUNCTIONR) { + if (info->type == ARGTYPE_FLOAT || info->type == ARGTYPE_DOUBLE) + return ptrace (PTRACE_PEEKUSER, proc->pid, + sizeof (long) * (PT_FPR0 + 1), 0); + else + return ptrace (PTRACE_PEEKUSER, proc->pid, + sizeof (long) * PT_R3, 0); + } + + /* Check if we're entering a new function call to list parameters. If + so, initialize the register control variables to keep track of where + the parameters were stored. */ + if (type == LT_TOF_FUNCTION && arg_num == 0) { + /* Initialize the set of registrers for parameter passing. */ + greg = 3; + freg = 1; + vreg = 2; + } + + if (info->type == ARGTYPE_FLOAT || info->type == ARGTYPE_DOUBLE) { + if (freg <= 13 || (proc->mask_32bit && freg <= 8)) { + data = ptrace (PTRACE_PEEKUSER, proc->pid, + sizeof (long) * (PT_FPR0 + freg), 0); + + if (info->type == ARGTYPE_FLOAT) { + /* float values passed in FP registers are automatically + promoted to double. We need to convert it back to float + before printing. */ + union { long val; float fval; double dval; } cvt; + cvt.val = data; + cvt.fval = (float) cvt.dval; + data = cvt.val; + } + + freg++; + greg++; + + return data; + } + } + else if (greg <= 10) { + data = ptrace (PTRACE_PEEKUSER, proc->pid, + sizeof (long) * greg, 0); + greg++; + + return data; + } + else + return ptrace (PTRACE_PEEKDATA, proc->pid, + proc->stack_pointer + sizeof (long) * + (arg_num - 8), 0); + + return 0; +} + +void +save_register_args(enum tof type, Process *proc) { +} + +/* Read a single long from the process's memory address 'addr'. */ +int +arch_umovelong (Process *proc, void *addr, long *result, arg_type_info *info) { + long pointed_to; + + errno = 0; + + pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0); + + if (pointed_to == -1 && errno) + return -errno; + + /* Since int's are 4-bytes (long is 8-bytes) in length for ppc64, we + need to shift the long values returned by ptrace to end up with + the correct value. */ + + if (info) { + if (info->type == ARGTYPE_INT || (proc->mask_32bit && (info->type == ARGTYPE_POINTER + || info->type == ARGTYPE_STRING))) { + pointed_to = pointed_to >> 32; + + /* Make sure we have nothing in the upper word so we can + do a explicit cast from long to int later in the code. */ + pointed_to &= 0x00000000ffffffff; + } + } + + *result = pointed_to; + return 0; +} diff --git a/sysdeps/linux-gnu/proc.c b/sysdeps/linux-gnu/proc.c new file mode 100644 index 0000000..4251c1d --- /dev/null +++ b/sysdeps/linux-gnu/proc.c @@ -0,0 +1,36 @@ +#include "config.h" + +#include <sys/types.h> +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> + +/* /proc/pid doesn't exist just after the fork, and sometimes `ltrace' + * couldn't open it to find the executable. So it may be necessary to + * have a bit delay + */ + +#define MAX_DELAY 100000 /* 100000 microseconds = 0.1 seconds */ + +/* + * Returns a (malloc'd) file name corresponding to a running pid + */ +char * +pid2name(pid_t pid) { + char proc_exe[1024]; + + if (!kill(pid, 0)) { + int delay = 0; + + sprintf(proc_exe, "/proc/%d/exe", pid); + + while (delay < MAX_DELAY) { + if (!access(proc_exe, F_OK)) { + return strdup(proc_exe); + } + delay += 1000; /* 1 milisecond */ + } + } + return NULL; +} diff --git a/sysdeps/linux-gnu/s390/Makefile b/sysdeps/linux-gnu/s390/Makefile new file mode 100644 index 0000000..cea1b45 --- /dev/null +++ b/sysdeps/linux-gnu/s390/Makefile @@ -0,0 +1,13 @@ +# +# S/390 version +# Copyright (C) 2001 IBM Poughkeepsie, IBM Corporation +# +OBJ = trace.o regs.o plt.o + +all: arch.o + +arch.o: $(OBJ) + $(CC) -nostdlib -r -o arch.o $(OBJ) + +clean: + $(RM) $(OBJ) arch.o diff --git a/sysdeps/linux-gnu/s390/arch.h b/sysdeps/linux-gnu/s390/arch.h new file mode 100644 index 0000000..03690b8 --- /dev/null +++ b/sysdeps/linux-gnu/s390/arch.h @@ -0,0 +1,18 @@ +/* +** S/390 version +** (C) Copyright 2001 IBM Poughkeepsie, IBM Corporation +*/ + +#define BREAKPOINT_VALUE { 0x00, 0x01 } +#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 diff --git a/sysdeps/linux-gnu/s390/plt.c b/sysdeps/linux-gnu/s390/plt.c new file mode 100644 index 0000000..85a1dd1 --- /dev/null +++ b/sysdeps/linux-gnu/s390/plt.c @@ -0,0 +1,12 @@ +#include <gelf.h> +#include "common.h" + +GElf_Addr +arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) { + return lte->plt_addr + (ndx + 1) * 32; +} + +void * +sym2addr(Process *proc, struct library_symbol *sym) { + return sym->enter_addr; +} diff --git a/sysdeps/linux-gnu/s390/ptrace.h b/sysdeps/linux-gnu/s390/ptrace.h new file mode 100644 index 0000000..c3cbcb6 --- /dev/null +++ b/sysdeps/linux-gnu/s390/ptrace.h @@ -0,0 +1 @@ +#include <sys/ptrace.h> diff --git a/sysdeps/linux-gnu/s390/regs.c b/sysdeps/linux-gnu/s390/regs.c new file mode 100644 index 0000000..169893e --- /dev/null +++ b/sysdeps/linux-gnu/s390/regs.c @@ -0,0 +1,75 @@ +/* +** S/390 version +** Copyright (C) 2001 IBM Poughkeepsie, IBM Corporation +*/ + +#include "config.h" + +#include <sys/types.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> + +#include "common.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +#ifdef __s390x__ +#define PSW_MASK 0xffffffffffffffff +#define PSW_MASK31 0x7fffffff +#else +#define PSW_MASK 0x7fffffff +#endif + +void * +get_instruction_pointer(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(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(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(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; +} + +void +set_return_addr(Process *proc, void *addr) { +#ifdef __s390x__ + if (proc->mask_32bit) + addr = (void *)((long)addr & PSW_MASK31); +#endif + ptrace(PTRACE_POKEUSER, proc->pid, PT_GPR14, addr); +} diff --git a/sysdeps/linux-gnu/s390/signalent.h b/sysdeps/linux-gnu/s390/signalent.h new file mode 100644 index 0000000..35b74f1 --- /dev/null +++ b/sysdeps/linux-gnu/s390/signalent.h @@ -0,0 +1,33 @@ +"SIG_0", /* 0 */ + "SIGHUP", /* 1 */ + "SIGINT", /* 2 */ + "SIGQUIT", /* 3 */ + "SIGILL", /* 4 */ + "SIGTRAP", /* 5 */ + "SIGABRT", /* 6 */ + "SIGBUS", /* 7 */ + "SIGFPE", /* 8 */ + "SIGKILL", /* 9 */ + "SIGUSR1", /* 10 */ + "SIGSEGV", /* 11 */ + "SIGUSR2", /* 12 */ + "SIGPIPE", /* 13 */ + "SIGALRM", /* 14 */ + "SIGTERM", /* 15 */ + "SIGSTKFLT", /* 16 */ + "SIGCHLD", /* 17 */ + "SIGCONT", /* 18 */ + "SIGSTOP", /* 19 */ + "SIGTSTP", /* 20 */ + "SIGTTIN", /* 21 */ + "SIGTTOU", /* 22 */ + "SIGURG", /* 23 */ + "SIGXCPU", /* 24 */ + "SIGXFSZ", /* 25 */ + "SIGVTALRM", /* 26 */ + "SIGPROF", /* 27 */ + "SIGWINCH", /* 28 */ + "SIGIO", /* 29 */ + "SIGPWR", /* 30 */ + "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 new file mode 100644 index 0000000..5a35d93 --- /dev/null +++ b/sysdeps/linux-gnu/s390/syscallent.h @@ -0,0 +1,5 @@ +#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..42631eb --- /dev/null +++ b/sysdeps/linux-gnu/s390/syscalls31.h @@ -0,0 +1,310 @@ + "0", /* 0 */ + "exit", /* 1 */ + "fork", /* 2 */ + "read", /* 3 */ + "write", /* 4 */ + "open", /* 5 */ + "close", /* 6 */ + "restart_syscall", /* 7 */ + "creat", /* 8 */ + "link", /* 9 */ + "unlink", /* 10 */ + "execve", /* 11 */ + "chdir", /* 12 */ + "time", /* 13 */ + "mknod", /* 14 */ + "chmod", /* 15 */ + "lchown16", /* 16 */ + "17", /* 17 */ + "18", /* 18 */ + "lseek", /* 19 */ + "getpid", /* 20 */ + "mount", /* 21 */ + "oldumount", /* 22 */ + "setuid16", /* 23 */ + "getuid16", /* 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 */ + "setgid16", /* 46 */ + "getgid16", /* 47 */ + "signal", /* 48 */ + "geteuid16", /* 49 */ + "getegid16", /* 50 */ + "acct", /* 51 */ + "umount", /* 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 */ + "setreuid16", /* 70 */ + "setregid16", /* 71 */ + "sigsuspend", /* 72 */ + "sigpending", /* 73 */ + "sethostname", /* 74 */ + "setrlimit", /* 75 */ + "old_getrlimit", /* 76 */ + "getrusage", /* 77 */ + "gettimeofday", /* 78 */ + "settimeofday", /* 79 */ + "getgroups16", /* 80 */ + "setgroups16", /* 81 */ + "82", /* 82 */ + "symlink", /* 83 */ + "84", /* 84 */ + "readlink", /* 85 */ + "uselib", /* 86 */ + "swapon", /* 87 */ + "reboot", /* 88 */ + "89", /* 89 */ + "old_mmap", /* 90 */ + "munmap", /* 91 */ + "truncate", /* 92 */ + "ftruncate", /* 93 */ + "fchmod", /* 94 */ + "fchown16", /* 95 */ + "getpriority", /* 96 */ + "setpriority", /* 97 */ + "98", /* 98 */ + "statfs", /* 99 */ + "fstatfs", /* 100 */ + "101", /* 101 */ + "socketcall", /* 102 */ + "syslog", /* 103 */ + "setitimer", /* 104 */ + "getitimer", /* 105 */ + "newstat", /* 106 */ + "newlstat", /* 107 */ + "newfstat", /* 108 */ + "109", /* 109 */ + "lookup_dcookie", /* 110 */ + "vhangup", /* 111 */ + "112", /* 112 */ + "113", /* 113 */ + "wait4", /* 114 */ + "swapoff", /* 115 */ + "sysinfo", /* 116 */ + "ipc", /* 117 */ + "fsync", /* 118 */ + "sigreturn", /* 119 */ + "clone", /* 120 */ + "setdomainname", /* 121 */ + "newuname", /* 122 */ + "123", /* 123 */ + "adjtimex", /* 124 */ + "mprotect", /* 125 */ + "sigprocmask", /* 126 */ + "127", /* 127 */ + "init_module", /* 128 */ + "delete_module", /* 129 */ + "130", /* 130 */ + "quotactl", /* 131 */ + "getpgid", /* 132 */ + "fchdir", /* 133 */ + "bdflush", /* 134 */ + "sysfs", /* 135 */ + "personality", /* 136 */ + "137", /* 137 */ + "setfsuid16", /* 138 */ + "setfsgid16", /* 139 */ + "llseek", /* 140 */ + "getdents", /* 141 */ + "select", /* 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 */ + "setresuid16", /* 164 */ + "getresuid16", /* 165 */ + "166", /* 166 */ + "167", /* 167 */ + "poll", /* 168 */ + "nfsservctl", /* 169 */ + "setresgid16", /* 170 */ + "getresgid16", /* 171 */ + "prctl", /* 172 */ + "rt_sigreturn", /* 173 */ + "rt_sigaction", /* 174 */ + "rt_sigprocmask", /* 175 */ + "rt_sigpending", /* 176 */ + "rt_sigtimedwait", /* 177 */ + "rt_sigqueueinfo", /* 178 */ + "rt_sigsuspend", /* 179 */ + "pread64", /* 180 */ + "pwrite64", /* 181 */ + "chown16", /* 182 */ + "getcwd", /* 183 */ + "capget", /* 184 */ + "capset", /* 185 */ + "sigaltstack", /* 186 */ + "sendfile", /* 187 */ + "188", /* 188 */ + "189", /* 189 */ + "vfork", /* 190 */ + "getrlimit", /* 191 */ + "mmap2", /* 192 */ + "truncate64", /* 193 */ + "ftruncate64", /* 194 */ + "stat64", /* 195 */ + "lstat64", /* 196 */ + "fstat64", /* 197 */ + "lchown", /* 198 */ + "getuid", /* 199 */ + "getgid", /* 200 */ + "geteuid", /* 201 */ + "getegid", /* 202 */ + "setreuid", /* 203 */ + "setregid", /* 204 */ + "getgroups", /* 205 */ + "setgroups", /* 206 */ + "fchown", /* 207 */ + "setresuid", /* 208 */ + "getresuid", /* 209 */ + "setresgid", /* 210 */ + "getresgid", /* 211 */ + "chown", /* 212 */ + "setuid", /* 213 */ + "setgid", /* 214 */ + "setfsuid", /* 215 */ + "setfsgid", /* 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 */ + "tgkill", /* 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 */ + "remap_file_pages", /* 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 */ + "kexec_load", /* 277 */ + "add_key", /* 278 */ + "request_key", /* 279 */ + "keyctl", /* 280 */ + "waitid", /* 281 */ + "ioprio_set", /* 282 */ + "ioprio_get", /* 283 */ + "inotify_init", /* 284 */ + "inotify_add_watch", /* 285 */ + "inotify_rm_watch", /* 286 */ + "287", /* 287 */ + "openat", /* 288 */ + "mkdirat", /* 289 */ + "mknodat", /* 290 */ + "fchownat", /* 291 */ + "futimesat", /* 292 */ + "fstatat64", /* 293 */ + "unlinkat", /* 294 */ + "renameat", /* 295 */ + "linkat", /* 296 */ + "symlinkat", /* 297 */ + "readlinkat", /* 298 */ + "fchmodat", /* 299 */ + "faccessat", /* 300 */ + "pselect6", /* 301 */ + "ppoll", /* 302 */ + "unshare", /* 303 */ + "set_robust_list", /* 304 */ + "get_robust_list", /* 305 */ + "splice", /* 306 */ + "sync_file_range", /* 307 */ + "tee", /* 308 */ + "vmsplice", /* 309 */ diff --git a/sysdeps/linux-gnu/s390/syscalls64.h b/sysdeps/linux-gnu/s390/syscalls64.h new file mode 100644 index 0000000..97be52c --- /dev/null +++ b/sysdeps/linux-gnu/s390/syscalls64.h @@ -0,0 +1,310 @@ + "0", /* 0 */ + "exit", /* 1 */ + "fork", /* 2 */ + "read", /* 3 */ + "write", /* 4 */ + "open", /* 5 */ + "close", /* 6 */ + "restart_syscall", /* 7 */ + "creat", /* 8 */ + "link", /* 9 */ + "unlink", /* 10 */ + "execve", /* 11 */ + "chdir", /* 12 */ + "13", /* 13 */ + "mknod", /* 14 */ + "chmod", /* 15 */ + "16", /* 16 */ + "17", /* 17 */ + "18", /* 18 */ + "lseek", /* 19 */ + "getpid", /* 20 */ + "mount", /* 21 */ + "oldumount", /* 22 */ + "23", /* 23 */ + "24", /* 24 */ + "25", /* 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 */ + "46", /* 46 */ + "47", /* 47 */ + "signal", /* 48 */ + "49", /* 49 */ + "50", /* 50 */ + "acct", /* 51 */ + "umount", /* 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 */ + "70", /* 70 */ + "71", /* 71 */ + "sigsuspend", /* 72 */ + "sigpending", /* 73 */ + "sethostname", /* 74 */ + "setrlimit", /* 75 */ + "getrlimit", /* 76 */ + "getrusage", /* 77 */ + "gettimeofday", /* 78 */ + "settimeofday", /* 79 */ + "80", /* 80 */ + "81", /* 81 */ + "82", /* 82 */ + "symlink", /* 83 */ + "84", /* 84 */ + "readlink", /* 85 */ + "uselib", /* 86 */ + "swapon", /* 87 */ + "reboot", /* 88 */ + "89", /* 89 */ + "old_mmap", /* 90 */ + "munmap", /* 91 */ + "truncate", /* 92 */ + "ftruncate", /* 93 */ + "fchmod", /* 94 */ + "95", /* 95 */ + "getpriority", /* 96 */ + "setpriority", /* 97 */ + "98", /* 98 */ + "statfs", /* 99 */ + "fstatfs", /* 100 */ + "101", /* 101 */ + "socketcall", /* 102 */ + "syslog", /* 103 */ + "setitimer", /* 104 */ + "getitimer", /* 105 */ + "newstat", /* 106 */ + "newlstat", /* 107 */ + "newfstat", /* 108 */ + "109", /* 109 */ + "lookup_dcookie", /* 110 */ + "vhangup", /* 111 */ + "112", /* 112 */ + "113", /* 113 */ + "wait4", /* 114 */ + "swapoff", /* 115 */ + "sysinfo", /* 116 */ + "ipc", /* 117 */ + "fsync", /* 118 */ + "sigreturn", /* 119 */ + "clone", /* 120 */ + "setdomainname", /* 121 */ + "newuname", /* 122 */ + "123", /* 123 */ + "adjtimex", /* 124 */ + "mprotect", /* 125 */ + "sigprocmask", /* 126 */ + "127", /* 127 */ + "init_module", /* 128 */ + "delete_module", /* 129 */ + "130", /* 130 */ + "quotactl", /* 131 */ + "getpgid", /* 132 */ + "fchdir", /* 133 */ + "bdflush", /* 134 */ + "sysfs", /* 135 */ + "personality", /* 136 */ + "137", /* 137 */ + "138", /* 138 */ + "139", /* 139 */ + "llseek", /* 140 */ + "getdents", /* 141 */ + "select", /* 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 */ + "164", /* 164 */ + "165", /* 165 */ + "166", /* 166 */ + "167", /* 167 */ + "poll", /* 168 */ + "nfsservctl", /* 169 */ + "170", /* 170 */ + "171", /* 171 */ + "prctl", /* 172 */ + "rt_sigreturn", /* 173 */ + "rt_sigaction", /* 174 */ + "rt_sigprocmask", /* 175 */ + "rt_sigpending", /* 176 */ + "rt_sigtimedwait", /* 177 */ + "rt_sigqueueinfo", /* 178 */ + "rt_sigsuspend", /* 179 */ + "pread64", /* 180 */ + "pwrite64", /* 181 */ + "182", /* 182 */ + "getcwd", /* 183 */ + "capget", /* 184 */ + "capset", /* 185 */ + "sigaltstack", /* 186 */ + "sendfile64", /* 187 */ + "188", /* 188 */ + "189", /* 189 */ + "vfork", /* 190 */ + "getrlimit", /* 191 */ + "mmap2", /* 192 */ + "193", /* 193 */ + "194", /* 194 */ + "195", /* 195 */ + "196", /* 196 */ + "197", /* 197 */ + "lchown", /* 198 */ + "getuid", /* 199 */ + "getgid", /* 200 */ + "geteuid", /* 201 */ + "getegid", /* 202 */ + "setreuid", /* 203 */ + "setregid", /* 204 */ + "getgroups", /* 205 */ + "setgroups", /* 206 */ + "fchown", /* 207 */ + "setresuid", /* 208 */ + "getresuid", /* 209 */ + "setresgid", /* 210 */ + "getresgid", /* 211 */ + "chown", /* 212 */ + "setuid", /* 213 */ + "setgid", /* 214 */ + "setfsuid", /* 215 */ + "setfsgid", /* 216 */ + "pivot_root", /* 217 */ + "mincore", /* 218 */ + "madvise", /* 219 */ + "getdents64", /* 220 */ + "221", /* 221 */ + "readahead", /* 222 */ + "223", /* 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 */ + "tgkill", /* 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_64", /* 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 */ + "264", /* 264 */ + "statfs64", /* 265 */ + "fstatfs64", /* 266 */ + "remap_file_pages", /* 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 */ + "kexec_load", /* 277 */ + "add_key", /* 278 */ + "request_key", /* 279 */ + "keyctl", /* 280 */ + "waitid", /* 281 */ + "ioprio_set", /* 282 */ + "ioprio_get", /* 283 */ + "inotify_init", /* 284 */ + "inotify_add_watch", /* 285 */ + "inotify_rm_watch", /* 286 */ + "287", /* 287 */ + "openat", /* 288 */ + "mkdirat", /* 289 */ + "mknodat", /* 290 */ + "fchownat", /* 291 */ + "futimesat", /* 292 */ + "newfstatat", /* 293 */ + "unlinkat", /* 294 */ + "renameat", /* 295 */ + "linkat", /* 296 */ + "symlinkat", /* 297 */ + "readlinkat", /* 298 */ + "fchmodat", /* 299 */ + "faccessat", /* 300 */ + "pselect6", /* 301 */ + "ppoll", /* 302 */ + "unshare", /* 303 */ + "set_robust_list", /* 304 */ + "get_robust_list", /* 305 */ + "splice", /* 306 */ + "sync_file_range", /* 307 */ + "tee", /* 308 */ + "vmsplice", /* 309 */ diff --git a/sysdeps/linux-gnu/s390/trace.c b/sysdeps/linux-gnu/s390/trace.c new file mode 100644 index 0000000..9df2437 --- /dev/null +++ b/sysdeps/linux-gnu/s390/trace.c @@ -0,0 +1,198 @@ +/* +** S390 specific part of trace.c +** +** Other routines are in ../trace.c and need to be combined +** at link time with this code. +** +** Copyright (C) 2001,2005 IBM Corp. +*/ + +#include "config.h" + +#include <errno.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <sys/ptrace.h> +#include <asm/ptrace.h> + +#include "common.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +void +get_arch_dep(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(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 | proc->tracesysgood)) { + + /* + * 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 = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR2, 0); + + if (proc->tracesysgood) { + /* System call was encountered... */ + if (proc->callstack_depth > 0 && + proc->callstack[proc->callstack_depth - + 1].is_syscall) { + /* syscall exit */ + *sysnum = + proc->callstack[proc->callstack_depth - + 1].c_un.syscall; + return 2; + } else { + /* syscall enter */ + if (*sysnum != -ENOSYS) + return 1; + } + } + + /* + * 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, Process *proc, int arg_num, arg_type_info *info) { + 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, Process *proc) { +} diff --git a/sysdeps/linux-gnu/sparc/Makefile b/sysdeps/linux-gnu/sparc/Makefile new file mode 100644 index 0000000..b3914e5 --- /dev/null +++ b/sysdeps/linux-gnu/sparc/Makefile @@ -0,0 +1,9 @@ +OBJ = regs.o trace.o plt.o + +all: arch.o + +arch.o: $(OBJ) + $(CC) -nostdlib -r -o arch.o $(OBJ) + +clean: + $(RM) $(OBJ) arch.o diff --git a/sysdeps/linux-gnu/sparc/arch.h b/sysdeps/linux-gnu/sparc/arch.h new file mode 100644 index 0000000..75251b8 --- /dev/null +++ b/sysdeps/linux-gnu/sparc/arch.h @@ -0,0 +1,8 @@ +#define BREAKPOINT_VALUE {0x91, 0xd0, 0x20, 0x01} +#define BREAKPOINT_LENGTH 4 +#define DECR_PC_AFTER_BREAK 0 + +#define LT_ELFCLASS ELFCLASS32 +#define LT_ELF_MACHINE EM_SPARC +#define LT_ELFCLASS2 ELFCLASS32 +#define LT_ELF_MACHINE2 EM_SPARC32PLUS diff --git a/sysdeps/linux-gnu/sparc/plt.c b/sysdeps/linux-gnu/sparc/plt.c new file mode 100644 index 0000000..f9e6d80 --- /dev/null +++ b/sysdeps/linux-gnu/sparc/plt.c @@ -0,0 +1,12 @@ +#include <gelf.h> +#include "common.h" + +GElf_Addr +arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) { + return rela->r_offset + 4; +} + +void * +sym2addr(Process *proc, struct library_symbol *sym) { + return sym->enter_addr; +} diff --git a/sysdeps/linux-gnu/sparc/ptrace.h b/sysdeps/linux-gnu/sparc/ptrace.h new file mode 100644 index 0000000..bbaf01a --- /dev/null +++ b/sysdeps/linux-gnu/sparc/ptrace.h @@ -0,0 +1,21 @@ +#undef PTRACE_GETREGS +#undef PTRACE_SETREGS +#undef PTRACE_GETFPREGS +#undef PTRACE_SETFPREGS +#include <sys/ptrace.h> +#ifndef PTRACE_SUNDETACH +#define PTRACE_SUNDETACH 11 +#endif +#undef PT_DETACH +#undef PTRACE_DETACH +#define PT_DETACH PTRACE_SUNDETACH +#define PTRACE_DETACH PTRACE_SUNDETACH + +#include <asm/ptrace.h> + +typedef struct { + int valid; + struct pt_regs regs; + unsigned int func_arg[6]; + unsigned int sysc_arg[6]; +} proc_archdep; diff --git a/sysdeps/linux-gnu/sparc/regs.c b/sysdeps/linux-gnu/sparc/regs.c new file mode 100644 index 0000000..49d2729 --- /dev/null +++ b/sysdeps/linux-gnu/sparc/regs.c @@ -0,0 +1,49 @@ +#include "config.h" + +#include <sys/types.h> +#include "ptrace.h" +#include "common.h" + +void * +get_instruction_pointer(Process *proc) { + proc_archdep *a = (proc_archdep *) (proc->arch_ptr); + if (a->valid) + return (void *)a->regs.pc; + return (void *)-1; +} + +void +set_instruction_pointer(Process *proc, void *addr) { + proc_archdep *a = (proc_archdep *) (proc->arch_ptr); + if (a->valid) + a->regs.pc = (long)addr; +} + +void * +get_stack_pointer(Process *proc) { + proc_archdep *a = (proc_archdep *) (proc->arch_ptr); + if (a->valid) + return (void *)a->regs.u_regs[UREG_I5]; + return (void *)-1; +} + +void * +get_return_addr(Process *proc, void *stack_pointer) { + proc_archdep *a = (proc_archdep *) (proc->arch_ptr); + unsigned int t; + if (!a->valid) + return (void *)-1; + /* Work around structure returns */ + t = ptrace(PTRACE_PEEKTEXT, proc->pid, a->regs.u_regs[UREG_I6] + 8, 0); + if (t < 0x400000) + return (void *)a->regs.u_regs[UREG_I6] + 12; + return (void *)a->regs.u_regs[UREG_I6] + 8; +} + +void +set_return_addr(Process *proc, void *addr) { + proc_archdep *a = (proc_archdep *) (proc->arch_ptr); + if (!a->valid) + return; + ptrace(PTRACE_POKETEXT, proc->pid, a->regs.u_regs[UREG_I6] + 8, addr); +} diff --git a/sysdeps/linux-gnu/sparc/signalent.h b/sysdeps/linux-gnu/sparc/signalent.h new file mode 100644 index 0000000..d30f69e --- /dev/null +++ b/sysdeps/linux-gnu/sparc/signalent.h @@ -0,0 +1,32 @@ +"SIG_0", /* 0 */ + "SIGHUP", /* 1 */ + "SIGINT", /* 2 */ + "SIGQUIT", /* 3 */ + "SIGILL", /* 4 */ + "SIGTRAP", /* 5 */ + "SIGABRT", /* 6 */ + "SIGEMT", /* 7 */ + "SIGFPE", /* 8 */ + "SIGKILL", /* 9 */ + "SIGBUS", /* 10 */ + "SIGSEGV", /* 11 */ + "SIGSYS", /* 12 */ + "SIGPIPE", /* 13 */ + "SIGALRM", /* 14 */ + "SIGTERM", /* 15 */ + "SIGURG", /* 16 */ + "SIGSTOP", /* 17 */ + "SIGTSTP", /* 18 */ + "SIGCONT", /* 19 */ + "SIGCHLD", /* 20 */ + "SIGTTIN", /* 21 */ + "SIGTTOU", /* 22 */ + "SIGIO", /* 23 */ + "SIGXCPU", /* 24 */ + "SIGXFSZ", /* 25 */ + "SIGVTALRM", /* 26 */ + "SIGPROF", /* 27 */ + "SIGWINCH", /* 28 */ + "SIGLOST", /* 29 */ + "SIGUSR1", /* 30 */ + "SIGUSR2", /* 31 */ diff --git a/sysdeps/linux-gnu/sparc/syscallent.h b/sysdeps/linux-gnu/sparc/syscallent.h new file mode 100644 index 0000000..96eeec9 --- /dev/null +++ b/sysdeps/linux-gnu/sparc/syscallent.h @@ -0,0 +1,284 @@ +"0", /* 0 */ + "exit", /* 1 */ + "fork", /* 2 */ + "read", /* 3 */ + "write", /* 4 */ + "open", /* 5 */ + "close", /* 6 */ + "wait4", /* 7 */ + "creat", /* 8 */ + "link", /* 9 */ + "unlink", /* 10 */ + "execv", /* 11 */ + "chdir", /* 12 */ + "chown", /* 13 */ + "mknod", /* 14 */ + "chmod", /* 15 */ + "lchown", /* 16 */ + "brk", /* 17 */ + "perfctr", /* 18 */ + "lseek", /* 19 */ + "getpid", /* 20 */ + "capget", /* 21 */ + "capset", /* 22 */ + "setuid", /* 23 */ + "getuid", /* 24 */ + "25", /* 25 */ + "ptrace", /* 26 */ + "alarm", /* 27 */ + "sigaltstack", /* 28 */ + "pause", /* 29 */ + "utime", /* 30 */ + "lchown32", /* 31 */ + "fchown32", /* 32 */ + "access", /* 33 */ + "nice", /* 34 */ + "chown32", /* 35 */ + "sync", /* 36 */ + "kill", /* 37 */ + "stat", /* 38 */ + "sendfile", /* 39 */ + "lstat", /* 40 */ + "dup", /* 41 */ + "pipe", /* 42 */ + "times", /* 43 */ + "getuid32", /* 44 */ + "umount2", /* 45 */ + "setgid", /* 46 */ + "getgid", /* 47 */ + "signal", /* 48 */ + "geteuid", /* 49 */ + "getegid", /* 50 */ + "acct", /* 51 */ + "memory_ordering", /* 52 */ + "getgid32", /* 53 */ + "ioctl", /* 54 */ + "reboot", /* 55 */ + "mmap2", /* 56 */ + "symlink", /* 57 */ + "readlink", /* 58 */ + "execve", /* 59 */ + "umask", /* 60 */ + "chroot", /* 61 */ + "fstat", /* 62 */ + "fstat64", /* 63 */ + "getpagesize", /* 64 */ + "msync", /* 65 */ + "vfork", /* 66 */ + "pread64", /* 67 */ + "pwrite64", /* 68 */ + "geteuid32", /* 69 */ + "getegid32", /* 70 */ + "mmap", /* 71 */ + "setreuid32", /* 72 */ + "munmap", /* 73 */ + "mprotect", /* 74 */ + "madvise", /* 75 */ + "vhangup", /* 76 */ + "truncate64", /* 77 */ + "mincore", /* 78 */ + "getgroups", /* 79 */ + "setgroups", /* 80 */ + "getpgrp", /* 81 */ + "setgroups32", /* 82 */ + "setitimer", /* 83 */ + "ftruncate64", /* 84 */ + "swapon", /* 85 */ + "getitimer", /* 86 */ + "setuid32", /* 87 */ + "sethostname", /* 88 */ + "setgid32", /* 89 */ + "dup2", /* 90 */ + "setfsuid32", /* 91 */ + "fcntl", /* 92 */ + "select", /* 93 */ + "setfsgid32", /* 94 */ + "fsync", /* 95 */ + "setpriority", /* 96 */ + "socket", /* 97 */ + "connect", /* 98 */ + "accept", /* 99 */ + "getpriority", /* 100 */ + "rt_sigreturn", /* 101 */ + "rt_sigaction", /* 102 */ + "rt_sigprocmask", /* 103 */ + "rt_sigpending", /* 104 */ + "rt_sigtimedwait", /* 105 */ + "rt_sigqueueinfo", /* 106 */ + "rt_sigsuspend", /* 107 */ + "setresuid32", /* 108 */ + "getresuid32", /* 109 */ + "setresgid32", /* 110 */ + "getresgid32", /* 111 */ + "setregid32", /* 112 */ + "recvmsg", /* 113 */ + "sendmsg", /* 114 */ + "getgroups32", /* 115 */ + "gettimeofday", /* 116 */ + "getrusage", /* 117 */ + "getsockopt", /* 118 */ + "getcwd", /* 119 */ + "readv", /* 120 */ + "writev", /* 121 */ + "settimeofday", /* 122 */ + "fchown", /* 123 */ + "fchmod", /* 124 */ + "recvfrom", /* 125 */ + "setreuid", /* 126 */ + "setregid", /* 127 */ + "rename", /* 128 */ + "truncate", /* 129 */ + "ftruncate", /* 130 */ + "flock", /* 131 */ + "lstat64", /* 132 */ + "sendto", /* 133 */ + "shutdown", /* 134 */ + "socketpair", /* 135 */ + "mkdir", /* 136 */ + "rmdir", /* 137 */ + "utimes", /* 138 */ + "stat64", /* 139 */ + "sendfile64", /* 140 */ + "getpeername", /* 141 */ + "futex", /* 142 */ + "gettid", /* 143 */ + "getrlimit", /* 144 */ + "setrlimit", /* 145 */ + "pivot_root", /* 146 */ + "prctl", /* 147 */ + "pciconfig_read", /* 148 */ + "pciconfig_write", /* 149 */ + "getsockname", /* 150 */ + "inotify_init", /* 151 */ + "inotify_add_watch", /* 152 */ + "poll", /* 153 */ + "getdents64", /* 154 */ + "fcntl64", /* 155 */ + "inotify_rm_watch", /* 156 */ + "statfs", /* 157 */ + "fstatfs", /* 158 */ + "umount", /* 159 */ + "sched_set_affinity", /* 160 */ + "sched_get_affinity", /* 161 */ + "getdomainname", /* 162 */ + "setdomainname", /* 163 */ + "utrap_install", /* 164 */ + "quotactl", /* 165 */ + "set_tid_address", /* 166 */ + "mount", /* 167 */ + "ustat", /* 168 */ + "setxattr", /* 169 */ + "lsetxattr", /* 170 */ + "fsetxattr", /* 171 */ + "getxattr", /* 172 */ + "lgetxattr", /* 173 */ + "getdents", /* 174 */ + "setsid", /* 175 */ + "fchdir", /* 176 */ + "fgetxattr", /* 177 */ + "listxattr", /* 178 */ + "llistxattr", /* 179 */ + "flistxattr", /* 180 */ + "removexattr", /* 181 */ + "lremovexattr", /* 182 */ + "sigpending", /* 183 */ + "query_module", /* 184 */ + "setpgid", /* 185 */ + "fremovexattr", /* 186 */ + "tkill", /* 187 */ + "exit_group", /* 188 */ + "uname", /* 189 */ + "init_module", /* 190 */ + "personality", /* 191 */ + "remap_file_pages", /* 192 */ + "epoll_create", /* 193 */ + "epoll_ctl", /* 194 */ + "epoll_wait", /* 195 */ + "ioprio_set", /* 196 */ + "getppid", /* 197 */ + "sigaction", /* 198 */ + "sgetmask", /* 199 */ + "ssetmask", /* 200 */ + "sigsuspend", /* 201 */ + "oldlstat", /* 202 */ + "uselib", /* 203 */ + "readdir", /* 204 */ + "readahead", /* 205 */ + "socketcall", /* 206 */ + "syslog", /* 207 */ + "lookup_dcookie", /* 208 */ + "fadvise64", /* 209 */ + "fadvise64_64", /* 210 */ + "tgkill", /* 211 */ + "waitpid", /* 212 */ + "swapoff", /* 213 */ + "sysinfo", /* 214 */ + "ipc", /* 215 */ + "sigreturn", /* 216 */ + "clone", /* 217 */ + "ioprio_get", /* 218 */ + "adjtimex", /* 219 */ + "sigprocmask", /* 220 */ + "create_module", /* 221 */ + "delete_module", /* 222 */ + "get_kernel_syms", /* 223 */ + "getpgid", /* 224 */ + "bdflush", /* 225 */ + "sysfs", /* 226 */ + "afs_syscall", /* 227 */ + "setfsuid", /* 228 */ + "setfsgid", /* 229 */ + "_newselect", /* 230 */ + "time", /* 231 */ + "232", /* 232 */ + "stime", /* 233 */ + "statfs64", /* 234 */ + "fstatfs64", /* 235 */ + "_llseek", /* 236 */ + "mlock", /* 237 */ + "munlock", /* 238 */ + "mlockall", /* 239 */ + "munlockall", /* 240 */ + "sched_setparam", /* 241 */ + "sched_getparam", /* 242 */ + "sched_setscheduler", /* 243 */ + "sched_getscheduler", /* 244 */ + "sched_yield", /* 245 */ + "sched_get_priority_max", /* 246 */ + "sched_get_priority_min", /* 247 */ + "sched_rr_get_interval", /* 248 */ + "nanosleep", /* 249 */ + "mremap", /* 250 */ + "_sysctl", /* 251 */ + "getsid", /* 252 */ + "fdatasync", /* 253 */ + "nfsservctl", /* 254 */ + "aplib", /* 255 */ + "clock_settime", /* 256 */ + "clock_gettime", /* 257 */ + "clock_getres", /* 258 */ + "clock_nanosleep", /* 259 */ + "sched_getaffinity", /* 260 */ + "sched_setaffinity", /* 261 */ + "timer_settime", /* 262 */ + "timer_gettime", /* 263 */ + "timer_getoverrun", /* 264 */ + "timer_delete", /* 265 */ + "timer_create", /* 266 */ + "vserver", /* 267 */ + "io_setup", /* 268 */ + "io_destroy", /* 269 */ + "io_submit", /* 270 */ + "io_cancel", /* 271 */ + "io_getevents", /* 272 */ + "mq_open", /* 273 */ + "mq_unlink", /* 274 */ + "mq_timedsend", /* 275 */ + "mq_timedreceive", /* 276 */ + "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 new file mode 100644 index 0000000..7f05b55 --- /dev/null +++ b/sysdeps/linux-gnu/sparc/trace.c @@ -0,0 +1,81 @@ +#include "config.h" + +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <string.h> +#include "ptrace.h" +#include "common.h" + +void +get_arch_dep(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); +} + +/* Returns syscall number if `pid' stopped because of a syscall. + * Returns -1 otherwise + */ +int +syscall_p(Process *proc, int status, int *sysnum) { + if (WIFSTOPPED(status) + && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { + void *ip = get_instruction_pointer(proc); + unsigned int insn; + 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.u_regs[UREG_G0]; + if (proc->callstack_depth > 0 && + proc->callstack[proc->callstack_depth - 1].is_syscall && + proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { + return 2; + } else if (*sysnum >= 0) { + return 1; + } + } + } + return 0; +} + +long +gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) { + 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 */ + return a->regs.u_regs[UREG_G7]; + + if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL || arg_num >= 6) { + if (arg_num < 6) + return ((int *)&a->regs.u_regs[UREG_G7])[arg_num]; + 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) + return a->sysc_arg[arg_num]; + else { + fprintf(stderr, "gimme_arg called with wrong arguments\n"); + exit(1); + } + return 0; +} + +void +save_register_args(enum tof type, Process *proc) { + proc_archdep *a = (proc_archdep *) proc->arch_ptr; + if (a->valid) { + if (type == LT_TOF_FUNCTION) + memcpy(a->func_arg, &a->regs.u_regs[UREG_G7], sizeof(a->func_arg)); + else + memcpy(a->sysc_arg, &a->regs.u_regs[UREG_G7], sizeof(a->sysc_arg)); + } +} diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c new file mode 100644 index 0000000..df5b090 --- /dev/null +++ b/sysdeps/linux-gnu/trace.c @@ -0,0 +1,193 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include "ptrace.h" +#include <asm/unistd.h> + +#include "common.h" + +/* If the system headers did not provide the constants, hard-code the normal + values. */ +#ifndef PTRACE_EVENT_FORK + +#define PTRACE_OLDSETOPTIONS 21 +#define PTRACE_SETOPTIONS 0x4200 +#define PTRACE_GETEVENTMSG 0x4201 + +/* options set using PTRACE_SETOPTIONS */ +#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_O_TRACEFORK 0x00000002 +#define PTRACE_O_TRACEVFORK 0x00000004 +#define PTRACE_O_TRACECLONE 0x00000008 +#define PTRACE_O_TRACEEXEC 0x00000010 +#define PTRACE_O_TRACEVFORKDONE 0x00000020 +#define PTRACE_O_TRACEEXIT 0x00000040 + +/* Wait extended result codes for the above trace options. */ +#define PTRACE_EVENT_FORK 1 +#define PTRACE_EVENT_VFORK 2 +#define PTRACE_EVENT_CLONE 3 +#define PTRACE_EVENT_EXEC 4 +#define PTRACE_EVENT_VFORK_DONE 5 +#define PTRACE_EVENT_EXIT 6 + +#endif /* PTRACE_EVENT_FORK */ + +#ifdef ARCH_HAVE_UMOVELONG +extern int arch_umovelong (Process *, void *, long *, arg_type_info *); +int +umovelong (Process *proc, void *addr, long *result, arg_type_info *info) { + return arch_umovelong (proc, addr, result, info); +} +#else +/* Read a single long from the process's memory address 'addr' */ +int +umovelong (Process *proc, void *addr, long *result, arg_type_info *info) { + long pointed_to; + + errno = 0; + pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0); + if (pointed_to == -1 && errno) + return -errno; + + *result = pointed_to; + return 0; +} +#endif + +void +trace_me(void) { + debug(DEBUG_PROCESS, "trace_me: pid=%d\n", getpid()); + if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) { + perror("PTRACE_TRACEME"); + exit(1); + } +} + +int +trace_pid(pid_t pid) { + debug(DEBUG_PROCESS, "trace_pid: pid=%d\n", pid); + if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) { + return -1; + } + + /* man ptrace: PTRACE_ATTACH attaches to the process specified + in pid. The child is sent a SIGSTOP, but will not + necessarily have stopped by the completion of this call; + use wait() to wait for the child to stop. */ + if (waitpid (pid, NULL, 0) != pid) { + perror ("trace_pid: waitpid"); + exit (1); + } + + return 0; +} + +void +trace_set_options(Process *proc, pid_t pid) { + if (proc->tracesysgood & 0x80) + return; + + debug(DEBUG_PROCESS, "trace_set_options: pid=%d\n", pid); + + long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK | + PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE | + PTRACE_O_TRACEEXEC; + if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 && + ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) { + perror("PTRACE_SETOPTIONS"); + return; + } + proc->tracesysgood |= 0x80; +} + +void +untrace_pid(pid_t pid) { + debug(DEBUG_PROCESS, "untrace_pid: pid=%d\n", pid); + ptrace(PTRACE_DETACH, pid, 1, 0); +} + +void +continue_after_signal(pid_t pid, int signum) { + Process *proc; + + debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d", pid, signum); + + proc = pid2proc(pid); + if (proc && proc->breakpoint_being_enabled) { +#if defined __sparc__ || defined __ia64___ + ptrace(PTRACE_SYSCALL, pid, 0, signum); +#else + ptrace(PTRACE_SINGLESTEP, pid, 0, signum); +#endif + } else { + ptrace(PTRACE_SYSCALL, pid, 0, signum); + } +} + +void +continue_process(pid_t pid) { + /* We always trace syscalls to control fork(), clone(), execve()... */ + + debug(DEBUG_PROCESS, "continue_process: pid=%d", pid); + + ptrace(PTRACE_SYSCALL, pid, 0, 0); +} + +void +continue_enabling_breakpoint(pid_t pid, Breakpoint *sbp) { + enable_breakpoint(pid, sbp); + continue_process(pid); +} + +void +continue_after_breakpoint(Process *proc, 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 { + debug(DEBUG_PROCESS, "continue_after_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr); + proc->breakpoint_being_enabled = sbp; +#if defined __sparc__ || defined __ia64___ + /* we don't want to singlestep here */ + continue_process(proc->pid); +#else + ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0); +#endif + } +} + +/* Read a series of bytes starting at the process's memory address + 'addr' and continuing until a NUL ('\0') is seen or 'len' bytes + have been read. +*/ +int +umovestr(Process *proc, void *addr, int len, void *laddr) { + union { + long a; + char c[sizeof(long)]; + } a; + int i; + 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 + (signed)i < len) { + *(char *)(laddr + offset + i) = a.c[i]; + } else { + *(char *)(laddr + offset + i) = '\0'; + return 0; + } + } + offset += sizeof(long); + } + *(char *)(laddr + offset) = '\0'; + return 0; +} diff --git a/sysdeps/linux-gnu/x86_64/Makefile b/sysdeps/linux-gnu/x86_64/Makefile new file mode 100644 index 0000000..0a19c97 --- /dev/null +++ b/sysdeps/linux-gnu/x86_64/Makefile @@ -0,0 +1,9 @@ +OBJ = trace.o regs.o plt.o + +all: arch.o + +arch.o: $(OBJ) + $(CC) -nostdlib -r -o arch.o $(OBJ) + +clean: + $(RM) $(OBJ) arch.o diff --git a/sysdeps/linux-gnu/x86_64/arch.h b/sysdeps/linux-gnu/x86_64/arch.h new file mode 100644 index 0000000..255395c --- /dev/null +++ b/sysdeps/linux-gnu/x86_64/arch.h @@ -0,0 +1,12 @@ +#define BREAKPOINT_VALUE {0xcc} +#define BREAKPOINT_LENGTH 1 +#define DECR_PC_AFTER_BREAK 1 + +#define LT_ELFCLASS ELFCLASS64 +#define LT_ELF_MACHINE EM_X86_64 +#define LT_ELFCLASS2 ELFCLASS32 +#define LT_ELF_MACHINE2 EM_386 + +/* __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/ffcheck.c b/sysdeps/linux-gnu/x86_64/ffcheck.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sysdeps/linux-gnu/x86_64/ffcheck.c diff --git a/sysdeps/linux-gnu/x86_64/plt.c b/sysdeps/linux-gnu/x86_64/plt.c new file mode 100644 index 0000000..b53ff44 --- /dev/null +++ b/sysdeps/linux-gnu/x86_64/plt.c @@ -0,0 +1,12 @@ +#include <gelf.h> +#include "common.h" + +GElf_Addr +arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) { + return lte->plt_addr + (ndx + 1) * 16; +} + +void * +sym2addr(Process *proc, struct library_symbol *sym) { + return sym->enter_addr; +} diff --git a/sysdeps/linux-gnu/x86_64/ptrace.h b/sysdeps/linux-gnu/x86_64/ptrace.h new file mode 100644 index 0000000..c3cbcb6 --- /dev/null +++ b/sysdeps/linux-gnu/x86_64/ptrace.h @@ -0,0 +1 @@ +#include <sys/ptrace.h> diff --git a/sysdeps/linux-gnu/x86_64/regs.c b/sysdeps/linux-gnu/x86_64/regs.c new file mode 100644 index 0000000..ed1f118 --- /dev/null +++ b/sysdeps/linux-gnu/x86_64/regs.c @@ -0,0 +1,54 @@ +#include "config.h" + +#include <sys/types.h> +#include <sys/ptrace.h> +#include <sys/reg.h> + +#include "common.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +void * +get_instruction_pointer(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(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(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(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; +} + +void +set_return_addr(Process *proc, void *addr) { + if (proc->mask_32bit) + addr = (void *)((long int)addr & 0xffffffff); + ptrace(PTRACE_POKETEXT, proc->pid, proc->stack_pointer, addr); +} diff --git a/sysdeps/linux-gnu/x86_64/signalent.h b/sysdeps/linux-gnu/x86_64/signalent.h new file mode 100644 index 0000000..d58a36c --- /dev/null +++ b/sysdeps/linux-gnu/x86_64/signalent.h @@ -0,0 +1,32 @@ +"SIG_0", /* 0 */ + "SIGHUP", /* 1 */ + "SIGINT", /* 2 */ + "SIGQUIT", /* 3 */ + "SIGILL", /* 4 */ + "SIGTRAP", /* 5 */ + "SIGABRT", /* 6 */ + "SIGBUS", /* 7 */ + "SIGFPE", /* 8 */ + "SIGKILL", /* 9 */ + "SIGUSR1", /* 10 */ + "SIGSEGV", /* 11 */ + "SIGUSR2", /* 12 */ + "SIGPIPE", /* 13 */ + "SIGALRM", /* 14 */ + "SIGTERM", /* 15 */ + "SIGSTKFLT", /* 16 */ + "SIGCHLD", /* 17 */ + "SIGCONT", /* 18 */ + "SIGSTOP", /* 19 */ + "SIGTSTP", /* 20 */ + "SIGTTIN", /* 21 */ + "SIGTTOU", /* 22 */ + "SIGURG", /* 23 */ + "SIGXCPU", /* 24 */ + "SIGXFSZ", /* 25 */ + "SIGVTALRM", /* 26 */ + "SIGPROF", /* 27 */ + "SIGWINCH", /* 28 */ + "SIGIO", /* 29 */ + "SIGPWR", /* 30 */ + "SIGSYS", /* 31 */ 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 new file mode 100644 index 0000000..5e5f88a --- /dev/null +++ b/sysdeps/linux-gnu/x86_64/syscallent.h @@ -0,0 +1,256 @@ +"read", /* 0 */ + "write", /* 1 */ + "open", /* 2 */ + "close", /* 3 */ + "stat", /* 4 */ + "fstat", /* 5 */ + "lstat", /* 6 */ + "poll", /* 7 */ + "lseek", /* 8 */ + "mmap", /* 9 */ + "mprotect", /* 10 */ + "munmap", /* 11 */ + "brk", /* 12 */ + "rt_sigaction", /* 13 */ + "rt_sigprocmask", /* 14 */ + "rt_sigreturn", /* 15 */ + "ioctl", /* 16 */ + "pread", /* 17 */ + "pwrite", /* 18 */ + "readv", /* 19 */ + "writev", /* 20 */ + "access", /* 21 */ + "pipe", /* 22 */ + "select", /* 23 */ + "sched_yield", /* 24 */ + "mremap", /* 25 */ + "msync", /* 26 */ + "mincore", /* 27 */ + "madvise", /* 28 */ + "shmget", /* 29 */ + "shmat", /* 30 */ + "shmctl", /* 31 */ + "dup", /* 32 */ + "dup2", /* 33 */ + "pause", /* 34 */ + "nanosleep", /* 35 */ + "getitimer", /* 36 */ + "alarm", /* 37 */ + "setitimer", /* 38 */ + "getpid", /* 39 */ + "sendfile", /* 40 */ + "socket", /* 41 */ + "connect", /* 42 */ + "accept", /* 43 */ + "sendto", /* 44 */ + "recvfrom", /* 45 */ + "sendmsg", /* 46 */ + "recvmsg", /* 47 */ + "shutdown", /* 48 */ + "bind", /* 49 */ + "listen", /* 50 */ + "getsockname", /* 51 */ + "getpeername", /* 52 */ + "socketpair", /* 53 */ + "setsockopt", /* 54 */ + "getsockopt", /* 55 */ + "clone", /* 56 */ + "fork", /* 57 */ + "vfork", /* 58 */ + "execve", /* 59 */ + "exit", /* 60 */ + "wait4", /* 61 */ + "kill", /* 62 */ + "uname", /* 63 */ + "semget", /* 64 */ + "semop", /* 65 */ + "semctl", /* 66 */ + "shmdt", /* 67 */ + "msgget", /* 68 */ + "msgsnd", /* 69 */ + "msgrcv", /* 70 */ + "msgctl", /* 71 */ + "fcntl", /* 72 */ + "flock", /* 73 */ + "fsync", /* 74 */ + "fdatasync", /* 75 */ + "truncate", /* 76 */ + "ftruncate", /* 77 */ + "getdents", /* 78 */ + "getcwd", /* 79 */ + "chdir", /* 80 */ + "fchdir", /* 81 */ + "rename", /* 82 */ + "mkdir", /* 83 */ + "rmdir", /* 84 */ + "creat", /* 85 */ + "link", /* 86 */ + "unlink", /* 87 */ + "symlink", /* 88 */ + "readlink", /* 89 */ + "chmod", /* 90 */ + "fchmod", /* 91 */ + "chown", /* 92 */ + "fchown", /* 93 */ + "lchown", /* 94 */ + "umask", /* 95 */ + "gettimeofday", /* 96 */ + "getrlimit", /* 97 */ + "getrusage", /* 98 */ + "sysinfo", /* 99 */ + "times", /* 100 */ + "ptrace", /* 101 */ + "getuid", /* 102 */ + "syslog", /* 103 */ + "getgid", /* 104 */ + "setuid", /* 105 */ + "setgid", /* 106 */ + "geteuid", /* 107 */ + "getegid", /* 108 */ + "setpgid", /* 109 */ + "getppid", /* 110 */ + "getpgrp", /* 111 */ + "setsid", /* 112 */ + "setreuid", /* 113 */ + "setregid", /* 114 */ + "getgroups", /* 115 */ + "setgroups", /* 116 */ + "setresuid", /* 117 */ + "getresuid", /* 118 */ + "setresgid", /* 119 */ + "getresgid", /* 120 */ + "getpgid", /* 121 */ + "setfsuid", /* 122 */ + "setfsgid", /* 123 */ + "getsid", /* 124 */ + "capget", /* 125 */ + "capset", /* 126 */ + "rt_sigpending", /* 127 */ + "rt_sigtimedwait", /* 128 */ + "rt_sigqueueinfo", /* 129 */ + "rt_sigsuspend", /* 130 */ + "sigaltstack", /* 131 */ + "utime", /* 132 */ + "mknod", /* 133 */ + "uselib", /* 134 */ + "personality", /* 135 */ + "ustat", /* 136 */ + "statfs", /* 137 */ + "fstatfs", /* 138 */ + "sysfs", /* 139 */ + "getpriority", /* 140 */ + "setpriority", /* 141 */ + "sched_setparam", /* 142 */ + "sched_getparam", /* 143 */ + "sched_setscheduler", /* 144 */ + "sched_getscheduler", /* 145 */ + "sched_get_priority_max", /* 146 */ + "sched_get_priority_min", /* 147 */ + "sched_rr_get_interval", /* 148 */ + "mlock", /* 149 */ + "munlock", /* 150 */ + "mlockall", /* 151 */ + "munlockall", /* 152 */ + "vhangup", /* 153 */ + "modify_ldt", /* 154 */ + "pivot_root", /* 155 */ + "_sysctl", /* 156 */ + "prctl", /* 157 */ + "arch_prctl", /* 158 */ + "adjtimex", /* 159 */ + "setrlimit", /* 160 */ + "chroot", /* 161 */ + "sync", /* 162 */ + "acct", /* 163 */ + "settimeofday", /* 164 */ + "mount", /* 165 */ + "umount2", /* 166 */ + "swapon", /* 167 */ + "swapoff", /* 168 */ + "reboot", /* 169 */ + "sethostname", /* 170 */ + "setdomainname", /* 171 */ + "iopl", /* 172 */ + "ioperm", /* 173 */ + "create_module", /* 174 */ + "init_module", /* 175 */ + "delete_module", /* 176 */ + "get_kernel_syms", /* 177 */ + "query_module", /* 178 */ + "quotactl", /* 179 */ + "nfsservctl", /* 180 */ + "getpmsg", /* 181 */ + "putpmsg", /* 182 */ + "afs_syscall", /* 183 */ + "tuxcall", /* 184 */ + "security", /* 185 */ + "gettid", /* 186 */ + "readahead", /* 187 */ + "setxattr", /* 188 */ + "lsetxattr", /* 189 */ + "fsetxattr", /* 190 */ + "getxattr", /* 191 */ + "lgetxattr", /* 192 */ + "fgetxattr", /* 193 */ + "listxattr", /* 194 */ + "llistxattr", /* 195 */ + "flistxattr", /* 196 */ + "removexattr", /* 197 */ + "lremovexattr", /* 198 */ + "fremovexattr", /* 199 */ + "tkill", /* 200 */ + "time", /* 201 */ + "futex", /* 202 */ + "sched_setaffinity", /* 203 */ + "sched_getaffinity", /* 204 */ + "set_thread_area", /* 205 */ + "io_setup", /* 206 */ + "io_destroy", /* 207 */ + "io_getevents", /* 208 */ + "io_submit", /* 209 */ + "io_cancel", /* 210 */ + "get_thread_area", /* 211 */ + "lookup_dcookie", /* 212 */ + "epoll_create", /* 213 */ + "epoll_ctl", /* 214 */ + "epoll_wait", /* 215 */ + "remap_file_pages", /* 216 */ + "getdents64", /* 217 */ + "set_tid_address", /* 218 */ + "restart_syscall", /* 219 */ + "semtimedop", /* 220 */ + "fadvise64", /* 221 */ + "timer_create", /* 222 */ + "timer_settime", /* 223 */ + "timer_gettime", /* 224 */ + "timer_getoverrun", /* 225 */ + "timer_delete", /* 226 */ + "clock_settime", /* 227 */ + "clock_gettime", /* 228 */ + "clock_getres", /* 229 */ + "clock_nanosleep", /* 230 */ + "exit_group", /* 231 */ + "epoll_wait", /* 232 */ + "epoll_ctl", /* 233 */ + "tgkill", /* 234 */ + "utimes", /* 235 */ + "vserver", /* 236 */ + "mbind", /* 237 */ + "set_mempolicy", /* 238 */ + "get_mempolicy", /* 239 */ + "mq_open", /* 240 */ + "mq_unlink", /* 241 */ + "mq_timedsend", /* 242 */ + "mq_timedreceive", /* 243 */ + "mq_notify", /* 244 */ + "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 new file mode 100644 index 0000000..189734d --- /dev/null +++ b/sysdeps/linux-gnu/x86_64/trace.c @@ -0,0 +1,144 @@ +#include "config.h" + +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <stdlib.h> +#include <sys/ptrace.h> +#include <sys/reg.h> + +#include "common.h" + +#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) +# define PTRACE_PEEKUSER PTRACE_PEEKUSR +#endif + +#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) +# define PTRACE_POKEUSER PTRACE_POKEUSR +#endif + +void +get_arch_dep(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(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].c_un.syscall == *sysnum) { + return 2; + } + + if (*sysnum >= 0) { + return 1; + } + } + return 0; +} + +static unsigned int +gimme_arg32(enum tof type, 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, Process *proc, int arg_num, arg_type_info *info) { + 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); + } + } 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"); + exit(1); + } + + return 0; +} + +void +save_register_args(enum tof type, Process *proc) { +} |