trace.c revision 5c3fe0697b202cc7d95e90459de0fb312b297b27
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <errno.h>
5#include <unistd.h>
6#include <sys/types.h>
7#include "ptrace.h"
8#include <asm/unistd.h>
9
10#include "ltrace.h"
11#include "options.h"
12
13/* Returns 1 if the sysnum may make a new child to be created
14 * (ie, with fork() or clone())
15 * Returns 0 otherwise.
16 */
17int
18fork_p(int sysnum) {
19	return 0
20#if defined(__NR_fork)
21		|| (sysnum == __NR_fork)
22#endif
23#if defined(__NR_clone)
24		|| (sysnum == __NR_clone)
25#endif
26#if defined(__NR_vfork)
27		|| (sysnum == __NR_vfork)
28#endif
29		;
30}
31
32/* Returns 1 if the sysnum may make the process exec other program
33 */
34int
35exec_p(int sysnum) {
36	return (sysnum == __NR_execve);
37}
38
39void
40trace_me(void) {
41	if (ptrace(PTRACE_TRACEME, 0, 1, 0)<0) {
42		perror("PTRACE_TRACEME");
43		exit(1);
44	}
45}
46
47int
48trace_pid(pid_t pid) {
49	if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
50		return -1;
51	}
52	return 0;
53}
54
55void
56untrace_pid(pid_t pid) {
57	ptrace(PTRACE_DETACH, pid, 1, 0);
58}
59
60void
61continue_after_signal(pid_t pid, int signum) {
62	/* We should always trace syscalls to be able to control fork(), clone(), execve()... */
63	ptrace(PTRACE_SYSCALL, pid, 0, signum);
64}
65
66void
67continue_process(pid_t pid) {
68	continue_after_signal(pid, 0);
69}
70
71void
72continue_enabling_breakpoint(pid_t pid, struct breakpoint * sbp) {
73	enable_breakpoint(pid, sbp);
74	continue_process(pid);
75}
76
77void
78continue_after_breakpoint(struct process *proc, struct breakpoint * sbp) {
79	if (sbp->enabled) disable_breakpoint(proc->pid, sbp);
80	set_instruction_pointer(proc, sbp->addr);
81	if (sbp->enabled == 0) {
82		continue_process(proc->pid);
83	} else {
84		proc->breakpoint_being_enabled = sbp;
85#ifdef __sparc__
86		continue_process(proc->pid);
87#else
88		ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
89#endif
90	}
91}
92
93int
94umovestr(struct process * proc, void * addr, int len, void * laddr) {
95	union { long a; char c[sizeof(long)]; } a;
96	int i;
97	int offset=0;
98
99	while(offset<len) {
100		a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr+offset, 0);
101		for(i=0; i<sizeof(long); i++) {
102			if (a.c[i] && offset+i < len) {
103				*(char *)(laddr+offset+i) = a.c[i];
104			} else {
105				*(char *)(laddr+offset+i) = '\0';
106				return 0;
107			}
108		}
109		offset += sizeof(long);
110	}
111	*(char *)(laddr+offset) = '\0';
112	return 0;
113}
114