blob: cc7b1b905712b3738cdee06237237fc8d0286055 [file] [log] [blame]
Juan Cespedes5e01f651998-03-08 22:31:44 +01001#include <stdio.h>
Juan Cespedes504a3852003-02-04 23:24:38 +01002#include <stdlib.h>
Juan Cespedes1fe93d51998-03-13 00:29:21 +01003#include <string.h>
4#include <errno.h>
Juan Cespedes8f8282f2002-03-03 18:58:40 +01005#include <unistd.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +01006#include <sys/types.h>
Juan Cespedes5c3fe062004-06-14 18:08:37 +02007#include "ptrace.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +01008#include <asm/unistd.h>
9
10#include "ltrace.h"
11#include "options.h"
Ian Wienand9a2ad352006-02-20 22:44:45 +010012#include "sysdep.h"
13
14static int fork_exec_syscalls[][5] = {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010015 {
Ian Wienand9a2ad352006-02-20 22:44:45 +010016#ifdef __NR_fork
Ian Wienand2d45b1a2006-02-20 22:48:07 +010017 __NR_fork,
Ian Wienand9a2ad352006-02-20 22:44:45 +010018#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +010019 -1,
Ian Wienand9a2ad352006-02-20 22:44:45 +010020#endif
21#ifdef __NR_clone
Ian Wienand2d45b1a2006-02-20 22:48:07 +010022 __NR_clone,
Ian Wienand9a2ad352006-02-20 22:44:45 +010023#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +010024 -1,
Ian Wienand9a2ad352006-02-20 22:44:45 +010025#endif
26#ifdef __NR_clone2
Ian Wienand2d45b1a2006-02-20 22:48:07 +010027 __NR_clone2,
Ian Wienand9a2ad352006-02-20 22:44:45 +010028#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +010029 -1,
Ian Wienand9a2ad352006-02-20 22:44:45 +010030#endif
31#ifdef __NR_vfork
Ian Wienand2d45b1a2006-02-20 22:48:07 +010032 __NR_vfork,
Ian Wienand9a2ad352006-02-20 22:44:45 +010033#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +010034 -1,
Ian Wienand9a2ad352006-02-20 22:44:45 +010035#endif
36#ifdef __NR_execve
Ian Wienand2d45b1a2006-02-20 22:48:07 +010037 __NR_execve,
Ian Wienand9a2ad352006-02-20 22:44:45 +010038#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +010039 -1,
Ian Wienand9a2ad352006-02-20 22:44:45 +010040#endif
Ian Wienand2d45b1a2006-02-20 22:48:07 +010041 }
Ian Wienand9a2ad352006-02-20 22:44:45 +010042#ifdef FORK_EXEC_SYSCALLS
Ian Wienand2d45b1a2006-02-20 22:48:07 +010043 FORK_EXEC_SYSCALLS
Ian Wienand9a2ad352006-02-20 22:44:45 +010044#endif
45};
Juan Cespedes5e01f651998-03-08 22:31:44 +010046
Juan Cespedes81690ef1998-03-13 19:31:29 +010047/* Returns 1 if the sysnum may make a new child to be created
48 * (ie, with fork() or clone())
49 * Returns 0 otherwise.
50 */
Ian Wienand2d45b1a2006-02-20 22:48:07 +010051int fork_p(struct process *proc, int sysnum)
52{
Ian Wienand9a2ad352006-02-20 22:44:45 +010053 int i;
54 if (proc->personality
Ian Wienand2d45b1a2006-02-20 22:48:07 +010055 >= sizeof fork_exec_syscalls / sizeof(fork_exec_syscalls[0]))
56 return 0;
57 for (i = 0; i < sizeof(fork_exec_syscalls[0]) / sizeof(int) - 1; ++i)
Ian Wienand9a2ad352006-02-20 22:44:45 +010058 if (sysnum == fork_exec_syscalls[proc->personality][i])
59 return 1;
60 return 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +010061}
62
Juan Cespedes81690ef1998-03-13 19:31:29 +010063/* Returns 1 if the sysnum may make the process exec other program
64 */
Ian Wienand2d45b1a2006-02-20 22:48:07 +010065int exec_p(struct process *proc, int sysnum)
66{
Ian Wienand9a2ad352006-02-20 22:44:45 +010067 int i;
68 if (proc->personality
Ian Wienand2d45b1a2006-02-20 22:48:07 +010069 >= sizeof fork_exec_syscalls / sizeof(fork_exec_syscalls[0]))
70 return 0;
71 i = sizeof(fork_exec_syscalls[0]) / sizeof(int) - 1;
Ian Wienand9a2ad352006-02-20 22:44:45 +010072 if (sysnum == fork_exec_syscalls[proc->personality][i])
73 return 1;
74 return 0;
Juan Cespedes81690ef1998-03-13 19:31:29 +010075}
76
Ian Wienand2d45b1a2006-02-20 22:48:07 +010077void trace_me(void)
78{
79 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010080 perror("PTRACE_TRACEME");
81 exit(1);
82 }
83}
84
Ian Wienand2d45b1a2006-02-20 22:48:07 +010085int trace_pid(pid_t pid)
86{
Juan Cespedes1fe93d51998-03-13 00:29:21 +010087 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +010088 return -1;
Juan Cespedes1fe93d51998-03-13 00:29:21 +010089 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010090 return 0;
91}
92
Ian Wienand2d45b1a2006-02-20 22:48:07 +010093void trace_set_options(struct process *proc, pid_t pid)
94{
Ian Wienand9a2ad352006-02-20 22:44:45 +010095#ifndef PTRACE_SETOPTIONS
Ian Wienand2d45b1a2006-02-20 22:48:07 +010096#define PTRACE_SETOPTIONS 0x4200
Ian Wienand9a2ad352006-02-20 22:44:45 +010097#endif
98#ifndef PTRACE_OLDSETOPTIONS
Ian Wienand2d45b1a2006-02-20 22:48:07 +010099#define PTRACE_OLDSETOPTIONS 21
Ian Wienand9a2ad352006-02-20 22:44:45 +0100100#endif
101#ifndef PTRACE_O_TRACESYSGOOD
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100102#define PTRACE_O_TRACESYSGOOD 0x00000001
Ian Wienand9a2ad352006-02-20 22:44:45 +0100103#endif
104 if (proc->tracesysgood & 0x80)
105 return;
106 if (ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0 &&
107 ptrace(PTRACE_OLDSETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0) {
108 perror("PTRACE_SETOPTIONS");
109 return;
110 }
111 proc->tracesysgood |= 0x80;
112}
113
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100114void untrace_pid(pid_t pid)
115{
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100116 ptrace(PTRACE_DETACH, pid, 1, 0);
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100117}
118
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100119void continue_after_signal(pid_t pid, int signum)
120{
Juan Cespedes5e01f651998-03-08 22:31:44 +0100121 /* We should always trace syscalls to be able to control fork(), clone(), execve()... */
Juan Cespedes5916fda2002-02-25 00:19:21 +0100122 ptrace(PTRACE_SYSCALL, pid, 0, signum);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100123}
124
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100125void continue_process(pid_t pid)
126{
Juan Cespedes5e01f651998-03-08 22:31:44 +0100127 continue_after_signal(pid, 0);
128}
129
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100130void continue_enabling_breakpoint(pid_t pid, struct breakpoint *sbp)
131{
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200132 enable_breakpoint(pid, sbp);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100133 continue_process(pid);
134}
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100135
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100136void continue_after_breakpoint(struct process *proc, struct breakpoint *sbp)
137{
138 if (sbp->enabled)
139 disable_breakpoint(proc->pid, sbp);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200140 set_instruction_pointer(proc, sbp->addr);
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100141 if (sbp->enabled == 0) {
142 continue_process(proc->pid);
143 } else {
144 proc->breakpoint_being_enabled = sbp;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100145#if defined __sparc__ || defined __ia64___
146 /* we don't want to singlestep here */
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200147 continue_process(proc->pid);
148#else
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100149 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200150#endif
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100151 }
152}
153
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100154int umovestr(struct process *proc, void *addr, int len, void *laddr)
155{
156 union {
157 long a;
158 char c[sizeof(long)];
159 } a;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100160 int i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100161 int offset = 0;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100162
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100163 while (offset < len) {
164 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0);
165 for (i = 0; i < sizeof(long); i++) {
166 if (a.c[i] && offset + i < len) {
167 *(char *)(laddr + offset + i) = a.c[i];
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100168 } else {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100169 *(char *)(laddr + offset + i) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100170 return 0;
171 }
172 }
173 offset += sizeof(long);
174 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100175 *(char *)(laddr + offset) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100176 return 0;
177}