trace.c revision 5570a7769869a4df25ef85f302f74a7feb6c0cd3
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 fork_p(int sysnum)
18{
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#if defined(__NR_clone2)
30	    || (sysnum == __NR_clone2)
31#endif
32	    ;
33}
34
35/* Returns 1 if the sysnum may make the process exec other program
36 */
37int exec_p(int sysnum)
38{
39	return (sysnum == __NR_execve);
40}
41
42void trace_me(void)
43{
44	if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
45		perror("PTRACE_TRACEME");
46		exit(1);
47	}
48}
49
50int trace_pid(pid_t pid)
51{
52	if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
53		return -1;
54	}
55	return 0;
56}
57
58void untrace_pid(pid_t pid)
59{
60	ptrace(PTRACE_DETACH, pid, 1, 0);
61}
62
63void continue_after_signal(pid_t pid, int signum)
64{
65	/* We should always trace syscalls to be able to control fork(), clone(), execve()... */
66	ptrace(PTRACE_SYSCALL, pid, 0, signum);
67}
68
69void continue_process(pid_t pid)
70{
71	continue_after_signal(pid, 0);
72}
73
74void continue_enabling_breakpoint(pid_t pid, struct breakpoint *sbp)
75{
76	enable_breakpoint(pid, sbp);
77	continue_process(pid);
78}
79
80void continue_after_breakpoint(struct process *proc, struct breakpoint *sbp)
81{
82	if (sbp->enabled)
83		disable_breakpoint(proc->pid, sbp);
84
85	set_instruction_pointer(proc, sbp->addr);
86
87	if (sbp->enabled == 0) {
88		continue_process(proc->pid);
89	} else {
90		proc->breakpoint_being_enabled = sbp;
91#ifdef __sparc__ || defined __ia64__
92		/* we don't want to single step here */
93		continue_process(proc->pid);
94#else
95		ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
96#endif
97	}
98}
99
100int umovestr(struct process *proc, void *addr, int len, void *laddr)
101{
102	union {
103		long a;
104		char c[sizeof(long)];
105	} a;
106	int i;
107	int offset = 0;
108
109	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];
114			} else {
115				*(char *)(laddr + offset + i) = '\0';
116				return 0;
117			}
118		}
119		offset += sizeof(long);
120	}
121	*(char *)(laddr + offset) = '\0';
122	return 0;
123}
124