blob: ce3e5ada96d97cae9d3092cd1cf01bfd736651fe [file] [log] [blame]
Juan Cespedesd44c6b81998-09-25 14:48:42 +02001#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
Juan Cespedes5e01f651998-03-08 22:31:44 +01005#include <sys/types.h>
6#include <sys/wait.h>
7#include <signal.h>
8#include <sys/ptrace.h>
Juan Cespedes64c6dfb1998-07-14 13:49:47 +02009#include <asm/ptrace.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010010
11#include "ltrace.h"
12
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020013#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
14# define PTRACE_PEEKUSER PTRACE_PEEKUSR
15#endif
16
17#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
18# define PTRACE_POKEUSER PTRACE_POKEUSR
19#endif
20
Juan Cespedes35d70631998-03-15 14:05:40 +010021/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
Juan Cespedes5e01f651998-03-08 22:31:44 +010022 */
Juan Cespedes35d70631998-03-15 14:05:40 +010023int syscall_p(struct process * proc, int status, int * sysnum)
Juan Cespedes5e01f651998-03-08 22:31:44 +010024{
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020025 int depth;
26
Juan Cespedes5e01f651998-03-08 22:31:44 +010027 if (WIFSTOPPED(status) && WSTOPSIG(status)==SIGTRAP) {
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020028 *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, 4*ORIG_EAX, 0);
Juan Cespedes35d70631998-03-15 14:05:40 +010029 if (*sysnum>=0) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020030 depth = proc->callstack_depth;
31 if (depth>0 &&
32 proc->callstack[depth-1].is_syscall &&
33 proc->callstack[depth-1].c_un.syscall==*sysnum) {
Juan Cespedes35d70631998-03-15 14:05:40 +010034 return 2;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020035 } else {
36 return 1;
Juan Cespedes35d70631998-03-15 14:05:40 +010037 }
Juan Cespedesf0fdae91998-03-11 00:03:00 +010038 }
39 }
Juan Cespedes35d70631998-03-15 14:05:40 +010040 return 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +010041}
42
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020043void continue_after_breakpoint(struct process *proc, struct breakpoint * sbp)
Juan Cespedes5e01f651998-03-08 22:31:44 +010044{
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020045 if (sbp->enabled) disable_breakpoint(proc->pid, sbp);
Juan Cespedes5e01f651998-03-08 22:31:44 +010046 ptrace(PTRACE_POKEUSER, proc->pid, 4*EIP, sbp->addr);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020047 if (sbp->enabled == 0) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010048 continue_process(proc->pid);
49 } else {
50 proc->breakpoint_being_enabled = sbp;
51 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
52 }
53}
54
55long gimme_arg(enum tof type, struct process * proc, int arg_num)
56{
57 if (arg_num==-1) { /* return value */
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020058 return ptrace(PTRACE_PEEKUSER, proc->pid, 4*EAX, 0);
Juan Cespedes5e01f651998-03-08 22:31:44 +010059 }
60
61 if (type==LT_TOF_FUNCTION) {
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020062 return ptrace(PTRACE_PEEKTEXT, proc->pid, proc->stack_pointer+4*(arg_num+1), 0);
Juan Cespedes5e01f651998-03-08 22:31:44 +010063 } else if (type==LT_TOF_SYSCALL) {
64#if 0
65 switch(arg_num) {
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020066 case 0: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*EBX, 0);
67 case 1: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*ECX, 0);
68 case 2: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*EDX, 0);
69 case 3: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*ESI, 0);
70 case 4: return ptrace(PTRACE_PEEKUSER, proc->pid, 4*EDI, 0);
Juan Cespedes5e01f651998-03-08 22:31:44 +010071 default:
72 fprintf(stderr, "gimme_arg called with wrong arguments\n");
73 exit(2);
74 }
75#else
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020076 return ptrace(PTRACE_PEEKUSER, proc->pid, 4*arg_num, 0);
Juan Cespedes5e01f651998-03-08 22:31:44 +010077#endif
78 } else {
79 fprintf(stderr, "gimme_arg called with wrong arguments\n");
80 exit(1);
81 }
82
83 return 0;
84}
85
86int umovestr(struct process * proc, void * addr, int len, void * laddr)
87{
88 long a;
89 int i;
90 int offset=0;
91
92 while(offset<len) {
93 a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr+offset, 0);
94 for(i=0; i<sizeof(long); i++) {
95 if (((char*)&a)[i] && offset+i < len) {
96 *(char *)(laddr+offset+i) = ((char*)&a)[i];
97 } else {
98 *(char *)(laddr+offset+i) = '\0';
99 return 0;
100 }
101 }
102 offset += sizeof(long);
103 }
104 *(char *)(laddr+offset) = '\0';
105 return 0;
106}