blob: bbf40e617aaa4f7ccc4d3c9082736d6ee53ec569 [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"
12
Juan Cespedes81690ef1998-03-13 19:31:29 +010013/* Returns 1 if the sysnum may make a new child to be created
14 * (ie, with fork() or clone())
15 * Returns 0 otherwise.
16 */
Ian Wienand3219f322006-02-16 06:00:00 +010017int fork_p(int sysnum)
18{
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020019 return 0
20#if defined(__NR_fork)
Ian Wienand3219f322006-02-16 06:00:00 +010021 || (sysnum == __NR_fork)
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020022#endif
23#if defined(__NR_clone)
Ian Wienand3219f322006-02-16 06:00:00 +010024 || (sysnum == __NR_clone)
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020025#endif
26#if defined(__NR_vfork)
Ian Wienand3219f322006-02-16 06:00:00 +010027 || (sysnum == __NR_vfork)
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020028#endif
Ian Wienand5570a772006-02-17 02:00:00 +010029#if defined(__NR_clone2)
30 || (sysnum == __NR_clone2)
31#endif
Ian Wienand3219f322006-02-16 06:00:00 +010032 ;
Juan Cespedes5e01f651998-03-08 22:31:44 +010033}
34
Juan Cespedes81690ef1998-03-13 19:31:29 +010035/* Returns 1 if the sysnum may make the process exec other program
36 */
Ian Wienand3219f322006-02-16 06:00:00 +010037int exec_p(int sysnum)
38{
Juan Cespedes81690ef1998-03-13 19:31:29 +010039 return (sysnum == __NR_execve);
40}
41
Ian Wienand3219f322006-02-16 06:00:00 +010042void trace_me(void)
43{
44 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010045 perror("PTRACE_TRACEME");
46 exit(1);
47 }
48}
49
Ian Wienand3219f322006-02-16 06:00:00 +010050int trace_pid(pid_t pid)
51{
Juan Cespedes1fe93d51998-03-13 00:29:21 +010052 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +010053 return -1;
Juan Cespedes1fe93d51998-03-13 00:29:21 +010054 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010055 return 0;
56}
57
Ian Wienand3219f322006-02-16 06:00:00 +010058void untrace_pid(pid_t pid)
59{
Juan Cespedes273ea6d1998-03-14 23:02:40 +010060 ptrace(PTRACE_DETACH, pid, 1, 0);
Juan Cespedes1fe93d51998-03-13 00:29:21 +010061}
62
Ian Wienand3219f322006-02-16 06:00:00 +010063void continue_after_signal(pid_t pid, int signum)
64{
Juan Cespedes5e01f651998-03-08 22:31:44 +010065 /* We should always trace syscalls to be able to control fork(), clone(), execve()... */
Juan Cespedes5916fda2002-02-25 00:19:21 +010066 ptrace(PTRACE_SYSCALL, pid, 0, signum);
Juan Cespedes5e01f651998-03-08 22:31:44 +010067}
68
Ian Wienand3219f322006-02-16 06:00:00 +010069void continue_process(pid_t pid)
70{
Juan Cespedes5e01f651998-03-08 22:31:44 +010071 continue_after_signal(pid, 0);
72}
73
Ian Wienand3219f322006-02-16 06:00:00 +010074void continue_enabling_breakpoint(pid_t pid, struct breakpoint *sbp)
75{
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020076 enable_breakpoint(pid, sbp);
Juan Cespedes5e01f651998-03-08 22:31:44 +010077 continue_process(pid);
78}
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010079
Ian Wienand3219f322006-02-16 06:00:00 +010080void continue_after_breakpoint(struct process *proc, struct breakpoint *sbp)
81{
82 if (sbp->enabled)
83 disable_breakpoint(proc->pid, sbp);
Ian Wienand5570a772006-02-17 02:00:00 +010084
Juan Cespedes5c3fe062004-06-14 18:08:37 +020085 set_instruction_pointer(proc, sbp->addr);
Ian Wienand5570a772006-02-17 02:00:00 +010086
Juan Cespedes8f8282f2002-03-03 18:58:40 +010087 if (sbp->enabled == 0) {
88 continue_process(proc->pid);
89 } else {
90 proc->breakpoint_being_enabled = sbp;
Ian Wienand5570a772006-02-17 02:00:00 +010091#ifdef __sparc__ || defined __ia64__
92 /* we don't want to single step here */
Juan Cespedes5c3fe062004-06-14 18:08:37 +020093 continue_process(proc->pid);
94#else
Juan Cespedes8f8282f2002-03-03 18:58:40 +010095 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
Juan Cespedes5c3fe062004-06-14 18:08:37 +020096#endif
Juan Cespedes8f8282f2002-03-03 18:58:40 +010097 }
98}
99
Ian Wienand3219f322006-02-16 06:00:00 +0100100int umovestr(struct process *proc, void *addr, int len, void *laddr)
101{
102 union {
103 long a;
104 char c[sizeof(long)];
105 } a;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100106 int i;
Ian Wienand3219f322006-02-16 06:00:00 +0100107 int offset = 0;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100108
Ian Wienand3219f322006-02-16 06:00:00 +0100109 while (offset < len) {
110 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0);
111 for (i = 0; i < sizeof(long); i++) {
112 if (a.c[i] && offset + i < len) {
113 *(char *)(laddr + offset + i) = a.c[i];
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100114 } else {
Ian Wienand3219f322006-02-16 06:00:00 +0100115 *(char *)(laddr + offset + i) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100116 return 0;
117 }
118 }
119 offset += sizeof(long);
120 }
Ian Wienand3219f322006-02-16 06:00:00 +0100121 *(char *)(laddr + offset) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100122 return 0;
123}