Geant4.10
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tracer.cxx
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <signal.h>
4 #include <iostream>
5 #include <sys/types.h>
6 #include <sys/syscall.h>
7 #include <sys/ptrace.h>
8 #include <sys/wait.h>
9 #include <unistd.h>
10 #include <errno.h>
11 #include <sys/user.h>
12 #include <assert.h>
13 #include <sys/select.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
16 #include <string.h>
17 #include <pthread.h>
18 
19 #include "tls.hh"
22 
23 int fildes[2];
24 int status;
25 char cmd[1024];
26 int protect = 0;
27 
28 #define MAXTHREADS 128
29 
30 pid_t filter;
31 
34 pthread_t tids[MAXTHREADS];
35 static char libname[4096][1024];
36 
37 #if defined(__MACH__)
38 struct user_regs_struct
39 {
40  long int ebx;
41  long int ecx;
42  long int edx;
43  long int esi;
44  long int edi;
45  long int ebp;
46  long int eax;
47  long int xds;
48  long int xes;
49  long int xfs;
50  long int xgs;
51  long int orig_eax;
52  long int eip;
53  long int xcs;
54  long int eflags;
55  long int esp;
56  long int xss;
57  long int rip;
58 };
59 #define __WCLONE 0x80000000
60 #endif
61 
62 G4ThreadLocal struct user_regs_struct regs;
63 G4ThreadLocal struct user_regs_struct regssinglestep;
65 
66 pthread_mutex_t segFaultHandlingLock = PTHREAD_MUTEX_INITIALIZER;
67 
69 
70 void FetchMap(pid_t pid)
71 {
72  char fname[128], line[4096];
73  sprintf(fname, "/proc/%d/maps", pid);
74  FILE *fp = fopen(fname, "r");
75 
76  char *n1, *n2, *p;
77 
78  char lastlibname[1024];
79 
80  while (fgets(line, sizeof(line), fp) != NULL) {
81  p = NULL;
82  p = strstr(line, "/");
83 
84  if (p != NULL)
85  {
86  strcpy(lastlibname, p);
87  }
88 
89  p = strstr(line, "[");
90 
91  if (p != NULL)
92  {
93  strcpy(lastlibname, p);
94  }
95 
96  strcpy(libname[numOfSegments], lastlibname);
97 
98  n1 = strtok(line, "- ");
99  n2 = strtok(NULL, "- ");
100  memorySegments[numOfSegments].start = (void*)strtoul(n1, NULL, 16);
101  memorySegments[numOfSegments].end = (void*)strtoul(n2, NULL, 16);
102 
103  numOfSegments++;
104  }
105  fclose(fp);
106 
107  int i;
108  for (i = 0 ; i < numOfSegments ; i++)
109  {
110  std::cout << "Maps: " << memorySegments[i].start << ", "
111  << memorySegments[i].end << ", " << libname[i] << std::endl;
112  }
113 }
114 
115 char *getLibName(long int address)
116 {
117  int i;
118  for (i = 0 ; i < numOfSegments ; i++)
119  {
120  if ((void*)address >= memorySegments[i].start && (void*)address <= memorySegments[i].end)
121  return libname[i];
122  }
123  return NULL;
124 }
125 
126 void processParameters(int, char *argv[])
127 {
128  strcpy(cmd, argv[1]);
129  printf("tracer: traced process executable file: %s:: %s %s\n", cmd, argv[1], argv[2]);
130 
131  char tmpnum[1024];
132  char *current;
133  current = argv[2];
134  int i = 0;
135  while (*current != ' ')
136  {
137  tmpnum[i] = *current;
138  current++; i++;
139  }
140 
141  tmpnum[i] = 0;
142  current++;
143  numberOfThreads = atoi(tmpnum);
144  printf("tracer number of threads: %d.\n", numberOfThreads);
145 
146  int j;
147  for (j = 0 ; j < numberOfThreads; j++)
148  {
149  i = 0;
150  while (*current != ' ')
151  {
152  tmpnum[i] = *current;
153  current++; i++;
154  }
155  tmpnum[i] = 0;
156  current++;
157  threads[j] = atoi(tmpnum);
158  printf("tracer threads[%d] = %d\n", j, threads[j]);
159  }
160 }
161 
162 void test(pid_t pid, int wait_val)
163 {
164  printf("tracer for %d WIFEXITED: %d\n", pid, WIFEXITED(wait_val));
165  printf("tracer for %d WEXITSTATUS: %d\n", pid, WEXITSTATUS(wait_val));
166  printf("tracer for %d WIFSIGNALED: %d\n", pid, WIFSIGNALED(wait_val));
167  printf("tracer for %d WTERMSIG: %d\n", pid, WTERMSIG(wait_val));
168  printf("tracer for %d WIFSTOPPED: %d\n", pid, WIFSTOPPED(wait_val));
169  printf("tracer for %d WSTOPSIG: %d\n", pid, WSTOPSIG(wait_val));
170  printf("tracer for %d WIFCONTINUED: %d\n", pid, WIFCONTINUED(wait_val));
171 }
172 
173 static G4ThreadLocal int isMain = 1;
174 
175 static int my_waitpid(pid_t pid, int *state, int flags)
176 {
177  int ret;
178  do
179  {
180  ret = waitpid(pid, state, flags);
181  } while (ret == -1 && errno == EINTR);
182  return ret;
183 }
184 
185 static int my_wait(pid_t pid, int *wait_val)
186 {
187  if (isMain)
188  return my_waitpid(pid, wait_val, 0);
189  else
190  return my_waitpid(pid, wait_val, __WCLONE);
191 }
192 
193 int SingleSteps(pid_t pid)
194 {
195  int wait_val; /* traced's return value */
196 
197 #if defined(__linux__)
198  if (ptrace(PT_GETREGS, pid, 0, &regssinglestep) != 0)
199  {
200  printf("tracer for %d ptrace getregs", pid);
201  exit(-1);
202  }
203 #endif
204 
205 #ifdef __x86_64__
206  write(fildes[1], &(regssinglestep.rip), sizeof(regssinglestep.rip));
207 #else
208  write(fildes[1], &(regssinglestep.eip), sizeof(regssinglestep.eip));
209 #endif
210 
211  if (ptrace(PT_STEP, pid, 0, 0) != 0)
212  {
213  printf("tracer for %d ptrace singlestep", pid);
214  exit(-1);
215  }
216  assert(pid == my_wait(pid, &wait_val));
217  if (wait_val == 1407) return 0;
218  if (WSTOPSIG(wait_val) == SIGTERM)
219  {
220  printf("tracer for %d terminated signal\n", pid);
221  exit(-1);
222  }
223  else if (wait_val == 0)
224  {
225  printf("tracer for %d finished signal\n", pid);
226  exit(-1);
227  }
228  else
229  {
230  test(pid, wait_val);
231  exit(-1);
232  }
233  return 0;
234 }
235 
236 int traceloop(pid_t pid)
237 {
238  int wait_val;
239 
240  if (ptrace(PT_ATTACH, pid, 0, 0) != 0)
241  {
242  printf("tracer for %d ptrace attach", pid);
243  exit(-1);
244  }
245  assert(pid == my_wait(pid, &wait_val));
246 
247  printf("tracer for %d after attach\n", pid);
248 
249  if (isMain)
250  {
251  if (ptrace(PT_CONTINUE, pid, 0, SIGUSR2) != 0)
252  {
253  printf("tracer for %d ptrace continue with SIGUSR2", pid);
254  exit(-1);
255  }
256 
257  assert(pid == my_wait(pid, &wait_val));
258  assert(SIGUSR2 == WSTOPSIG(wait_val));
259 
260  protect = 1;
261  printf("tracer for %d after memory protection\n", pid);
262 
263  if (ptrace(PT_CONTINUE, pid, 0, 0) != 0)
264  {
265  printf("tracer for %d ptrace continue without SIGUSR2", pid);
266  exit(-1);
267  }
268 
269  }
270  else
271  {
272  printf("tracer for %d Waiting for the memory is protected\n", pid);
273  while (!protect) usleep(10);
274 
275  if (ptrace(PT_CONTINUE, pid, 0, 0) != 0)
276  {
277  printf("tracer for %d ptrace continue without SIGUSR2", pid);
278  exit(-1);
279  }
280 
281  printf("tracer for %d after continue\n", pid);
282 
283  }
284 
285  int tmp = 0;
286 
287  do
288  {
289  // printf("tracer for %d tracerloop\n", pid);
290  // pid_t frompid = my_wait(pid, &wait_val);
291 
292  if (WSTOPSIG(wait_val) == SIGSEGV)
293  {
294  pthread_mutex_lock(&segFaultHandlingLock);
295 
296 #if defined(__linux__)
297  if (ptrace(PT_GETREGS, pid, 0, &regssinglestep) != 0)
298  {
299  printf("tracer for %d ptrace getregs", pid);
300  }
301 #endif
302 
303  if (detectionFlag && !isMain)
304  {
305 #ifdef __x86_64__
306  write(fildes[1], &(regssinglestep.rip), sizeof(regssinglestep.rip));
307  printf("tracer for %d Address: %lx in %s", pid, regssinglestep.rip, getLibName(regssinglestep.rip));
308 #else
309  write(fildes[1], &(regssinglestep.eip), sizeof(regssinglestep.eip));
310  printf("tracer for %d Address: %lx in %s", pid, regssinglestep.eip, getLibName(regssinglestep.eip));
311 #endif
312  char convertcmd[1024];
313  memset(convertcmd, 0, 1024);
314 #ifdef __x86_64__
315  sprintf(convertcmd, "addr2line -e %s 0x%lx", cmd, regssinglestep.rip);
316 #else
317  sprintf(convertcmd, "addr2line -e %s 0x%lx", cmd, regssinglestep.eip);
318 #endif
319  system(convertcmd);
320  }
321 
322  if (ptrace(PT_CONTINUE, pid, 0, SIGSEGV) != 0)
323  {
324  printf("tracer for %d ptrace continue with SIGSEGV", pid);
325  tmp = -6;
326  }
327 
328  assert(pid == my_wait(pid, &wait_val));
329  assert(SIGUSR2 == WSTOPSIG(wait_val));
330 
331 
332  if (SIGUSR2 != WSTOPSIG(wait_val))
333  {
334  test(pid, wait_val);
335  tmp = -3;
336  }
337  else
338  {
339  SingleSteps(pid);
340  // counter++;
341  // printf("Counter: %d\n", counter);
342 
343  if (ptrace(PT_CONTINUE, pid, 0, SIGUSR1) != 0)
344  {
345  printf("tracer for %d ptrace continue with SIGUSR1\n", pid);
346  tmp = -5;
347  }
348  }
349 
350  pthread_mutex_unlock(&segFaultHandlingLock);
351 
352  }
353  else
354  {
355  if ( wait_val == 0 )
356  {
357  // test(pid, wait_val);
358  tmp = -1;
359  }
360  else if (WSTOPSIG(wait_val) == SIGUSR1)
361  {
362  // test(pid, wait_val);
363  detectionFlag = 0;
364  if (ptrace(PT_DETACH, pid, 0, 0) != 0)
365  {
366  printf("tracer for %d ptrace detach\n", pid);
367  tmp = -6;
368  }
369  }
370  else if (WSTOPSIG(wait_val) == SIGUSR2)
371  {
372  detectionFlag = 1;
373  if (ptrace(PT_CONTINUE, pid, 0, 0) != 0)
374  {
375  printf("tracer for %d ptrace continue without SIGSEGV\n", pid);
376  tmp = -4;
377  }
378  }
379  else
380  {
381  if (ptrace(PT_CONTINUE, pid, 0, 0) != 0)
382  {
383  printf("tracer for %d ptrace continue without SIGSEGV\n", pid);
384  tmp = -4;
385  }
386  }
387  // break;
388  }
389 
390 
391  } while (tmp == 0);
392 
393  printf("tracer for %d Exit code: %d\n", pid, tmp);
394 
395  if (tmp != -6)
396  {
397  if (ptrace(PT_DETACH, pid, 0, 0) != 0)
398  printf("tracer for %d ptrace detach", pid);
399  }
400 
401  return 0;
402 }
403 
404 void *tracer_thread(void *pid_ptr)
405 {
406  isMain = 0;
407  pid_t pid;
408  pid = * ((pid_t *) pid_ptr);
409 
410  traceloop(pid);
411  return 0;
412 }
413 
414 void startThreadTracers(pid_t pid)
415 {
416  FetchMap(pid);
417  int j;
418  for (j = 1 ; j < numberOfThreads; j++)
419  {
420  printf("tracer for %d start threads[%d] = %d\n", pid, j, threads[j]);
421  assert(0 == pthread_create(&tids[j], NULL, tracer_thread, &threads[j]));
422  }
423 }
424 
425 void waitForAllTracers(pid_t pid)
426 {
427  int j;
428  for (j = 1 ; j < numberOfThreads; j++)
429  {
430  printf("tracer for %d join threads[%d] = %d\n", pid, j, threads[j]);
431  assert(0 == pthread_join(tids[j], NULL));
432  printf("tracer for %d after join threads[%d] = %d\n", pid, j, threads[j]);
433  }
434 }
435 
437 {
438  status = pipe(fildes);
439 
440  filter = fork();
441 
442  if (filter == 0) //child process
443  {
444  close(fildes[1]);
445  unsigned long code;
446  fd_set rfds;
447  FD_ZERO(&rfds);
448  FD_SET(fildes[0], &rfds);
449 
450  while (1)
451  {
452  int len;
453  select(fildes[0] + 1, &rfds, NULL, NULL, NULL);
454  if ((len = read(fildes[0], &code, sizeof(code))) < 0) break;
455  else
456  {
457  if (len > 0)
458  {
459  if (code > 0) insertAddress(code);
460  else
461  break;
462  }
463  }
464  len = 0;
465  }
466  close(fildes[0]);
469  printf("tracer: filter stopping...\n");
470  exit(0);
471  }
472  else
473  {
474  close(fildes[0]);
475  }
476 }
477 
479 {
480  printf("tracer stopping...\n");
481  unsigned long exitCode = 0;
482 
483  printf("tracer: notifying filter to exit\n");
484  write(fildes[1], &exitCode, sizeof(exitCode));
485 
486  waitpid(filter, NULL, 0);
487  printf("tracer: filter stopped...%d\n", filter);
488  close(fildes[1]);
489 }
490 
491 int main(int argc, char *argv[])
492 {
493  isMain = 1;
494  processParameters(argc, argv);
495  openFilter();
497  traceloop(threads[0]);
499 
500  closeFilter();
501  return 0;
502 }
G4ThreadLocal struct user_regs_struct regssinglestep
Definition: tracer.cxx:63
pid_t filter
Definition: tracer.cxx:30
void outputAddresses(char *cmd)
Definition: filter.cc:84
char cmd[1024]
Definition: tracer.cxx:25
int protect
Definition: tracer.cxx:26
void FetchMap(pid_t pid)
Definition: tracer.cxx:70
void closeFilter()
Definition: tracer.cxx:478
const char * p
Definition: xmltok.h:285
#define assert(x)
Definition: mymalloc.cc:1309
int main(int argc, char *argv[])
Definition: tracer.cxx:491
#define G4ThreadLocal
Definition: tls.hh:52
int SingleSteps(pid_t pid)
Definition: tracer.cxx:193
#define MAXTHREADS
Definition: tracer.cxx:28
void openFilter()
Definition: tracer.cxx:436
void waitForAllTracers(pid_t pid)
Definition: tracer.cxx:425
void processParameters(int, char *argv[])
Definition: tracer.cxx:126
G4ThreadLocal struct user_regs_struct regs
Definition: tracer.cxx:62
pid_t threads[MAXTHREADS]
Definition: tracer.cxx:33
pthread_t tids[MAXTHREADS]
Definition: tracer.cxx:34
G4ThreadLocal int detectionFlag
Definition: tracer.cxx:64
void test(pid_t pid, int wait_val)
Definition: tracer.cxx:162
int insertAddress(unsigned long address)
Definition: filter.cc:44
int fildes[2]
Definition: tracer.cxx:23
int status
Definition: tracer.cxx:24
int traceloop(pid_t pid)
Definition: tracer.cxx:236
void generategdbscripts()
Definition: filter.cc:97
Definition: inftrees.h:24
char * getLibName(long int address)
Definition: tracer.cxx:115
int numberOfThreads
Definition: tracer.cxx:32
const XML_Char int len
void startThreadTracers(pid_t pid)
Definition: tracer.cxx:414
void * tracer_thread(void *pid_ptr)
Definition: tracer.cxx:404
pthread_mutex_t segFaultHandlingLock
Definition: tracer.cxx:66