blob: 81a154f3a82790d9eb65412aaadeb89a8d78a37b [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 Wienand3219f322006-02-16 06:00:00 +010029 ;
Juan Cespedes5e01f651998-03-08 22:31:44 +010030}
31
Juan Cespedes81690ef1998-03-13 19:31:29 +010032/* Returns 1 if the sysnum may make the process exec other program
33 */
Ian Wienand3219f322006-02-16 06:00:00 +010034int exec_p(int sysnum)
35{
Juan Cespedes81690ef1998-03-13 19:31:29 +010036 return (sysnum == __NR_execve);
37}
38
Ian Wienand3219f322006-02-16 06:00:00 +010039void trace_me(void)
40{
41 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010042 perror("PTRACE_TRACEME");
43 exit(1);
44 }
45}
46
Ian Wienand3219f322006-02-16 06:00:00 +010047int trace_pid(pid_t pid)
48{
Juan Cespedes1fe93d51998-03-13 00:29:21 +010049 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +010050 return -1;
Juan Cespedes1fe93d51998-03-13 00:29:21 +010051 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010052 return 0;
53}
54
Ian Wienand3219f322006-02-16 06:00:00 +010055void untrace_pid(pid_t pid)
56{
Juan Cespedes273ea6d1998-03-14 23:02:40 +010057 ptrace(PTRACE_DETACH, pid, 1, 0);
Juan Cespedes1fe93d51998-03-13 00:29:21 +010058}
59
Ian Wienand3219f322006-02-16 06:00:00 +010060void continue_after_signal(pid_t pid, int signum)
61{
Juan Cespedes5e01f651998-03-08 22:31:44 +010062 /* We should always trace syscalls to be able to control fork(), clone(), execve()... */
Juan Cespedes5916fda2002-02-25 00:19:21 +010063 ptrace(PTRACE_SYSCALL, pid, 0, signum);
Juan Cespedes5e01f651998-03-08 22:31:44 +010064}
65
Ian Wienand3219f322006-02-16 06:00:00 +010066void continue_process(pid_t pid)
67{
Juan Cespedes5e01f651998-03-08 22:31:44 +010068 continue_after_signal(pid, 0);
69}
70
Ian Wienand3219f322006-02-16 06:00:00 +010071void continue_enabling_breakpoint(pid_t pid, struct breakpoint *sbp)
72{
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020073 enable_breakpoint(pid, sbp);
Juan Cespedes5e01f651998-03-08 22:31:44 +010074 continue_process(pid);
75}
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010076
Ian Wienand3219f322006-02-16 06:00:00 +010077void continue_after_breakpoint(struct process *proc, struct breakpoint *sbp)
78{
79 if (sbp->enabled)
80 disable_breakpoint(proc->pid, sbp);
Juan Cespedes5c3fe062004-06-14 18:08:37 +020081 set_instruction_pointer(proc, sbp->addr);
Juan Cespedes8f8282f2002-03-03 18:58:40 +010082 if (sbp->enabled == 0) {
83 continue_process(proc->pid);
84 } else {
85 proc->breakpoint_being_enabled = sbp;
Juan Cespedes5c3fe062004-06-14 18:08:37 +020086#ifdef __sparc__
87 continue_process(proc->pid);
88#else
Juan Cespedes8f8282f2002-03-03 18:58:40 +010089 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
Juan Cespedes5c3fe062004-06-14 18:08:37 +020090#endif
Juan Cespedes8f8282f2002-03-03 18:58:40 +010091 }
92}
93
Ian Wienand3219f322006-02-16 06:00:00 +010094int umovestr(struct process *proc, void *addr, int len, void *laddr)
95{
96 union {
97 long a;
98 char c[sizeof(long)];
99 } a;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100100 int i;
Ian Wienand3219f322006-02-16 06:00:00 +0100101 int offset = 0;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100102
Ian Wienand3219f322006-02-16 06:00:00 +0100103 while (offset < len) {
104 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0);
105 for (i = 0; i < sizeof(long); i++) {
106 if (a.c[i] && offset + i < len) {
107 *(char *)(laddr + offset + i) = a.c[i];
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100108 } else {
Ian Wienand3219f322006-02-16 06:00:00 +0100109 *(char *)(laddr + offset + i) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100110 return 0;
111 }
112 }
113 offset += sizeof(long);
114 }
Ian Wienand3219f322006-02-16 06:00:00 +0100115 *(char *)(laddr + offset) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100116 return 0;
117}