blob: 797fc13a790e094cc02fcd8e6a547e4c1cc7ddb6 [file] [log] [blame]
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <asm/unistd.h>
#include "ltrace.h"
#include "options.h"
/* Returns 1 if the sysnum may make a new child to be created
* (ie, with fork() or clone())
* Returns 0 otherwise.
*/
int
fork_p(int sysnum) {
return 0
#if defined(__NR_fork)
|| (sysnum == __NR_fork)
#endif
#if defined(__NR_clone)
|| (sysnum == __NR_clone)
#endif
#if defined(__NR_vfork)
|| (sysnum == __NR_vfork)
#endif
;
}
/* Returns 1 if the sysnum may make the process exec other program
*/
int
exec_p(int sysnum) {
return (sysnum == __NR_execve);
}
void
trace_me(void) {
if (ptrace(PTRACE_TRACEME, 0, 1, 0)<0) {
perror("PTRACE_TRACEME");
exit(1);
}
}
int
trace_pid(pid_t pid) {
if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
return -1;
}
return 0;
}
void
untrace_pid(pid_t pid) {
ptrace(PTRACE_DETACH, pid, 1, 0);
}
void
continue_after_signal(pid_t pid, int signum) {
/* We should always trace syscalls to be able to control fork(), clone(), execve()... */
ptrace(PTRACE_SYSCALL, pid, 0, signum);
}
void
continue_process(pid_t pid) {
continue_after_signal(pid, 0);
}
void
continue_enabling_breakpoint(pid_t pid, struct breakpoint * sbp) {
enable_breakpoint(pid, sbp);
continue_process(pid);
}
int
umovestr(struct process * proc, void * addr, int len, void * laddr) {
long a;
int i;
int offset=0;
while(offset<len) {
a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr+offset, 0);
for(i=0; i<sizeof(long); i++) {
if (((char*)&a)[i] && offset+i < len) {
*(char *)(laddr+offset+i) = ((char*)&a)[i];
} else {
*(char *)(laddr+offset+i) = '\0';
return 0;
}
}
offset += sizeof(long);
}
*(char *)(laddr+offset) = '\0';
return 0;
}