Rizin
unix-like reverse engineering framework and cli tools
ptrace_wrap.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2018-2021 thestr4ng3r <info@florianmaerkl.de>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <ptrace_wrap.h>
5 
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <signal.h>
10 #include <rz_util/rz_sys.h>
11 
12 static void *th_run(ptrace_wrap_instance *inst);
13 
15  int r = sem_init(&inst->request_sem, 0, 0);
16  if (r != 0) {
17  return r;
18  }
19 
20  r = sem_init(&inst->result_sem, 0, 0);
21  if (r != 0) {
22  sem_destroy(&inst->request_sem);
23  return r;
24  }
25 
26  r = pthread_create(&inst->th, NULL, (void *(*)(void *))th_run, inst);
27  if (r != 0) {
28  sem_destroy(&inst->request_sem);
29  sem_destroy(&inst->result_sem);
30  return r;
31  }
32 
33  return 0;
34 }
35 
38  sem_post(&inst->request_sem);
39  pthread_join(inst->th, NULL);
40  sem_destroy(&inst->request_sem);
41  sem_destroy(&inst->result_sem);
42 }
43 
44 static void wrap_ptrace(ptrace_wrap_instance *inst) {
45  inst->ptrace_result = ptrace(
46  inst->request.ptrace.request,
47  inst->request.ptrace.pid,
48  inst->request.ptrace.addr,
49  inst->request.ptrace.data);
50  if (inst->request.ptrace._errno) {
51  *inst->request.ptrace._errno = errno;
52  }
53 }
54 
55 static void wrap_fork(ptrace_wrap_instance *inst) {
56  pid_t r = rz_sys_fork();
57  if (r == 0) {
58  inst->request.fork.child_callback(inst->request.fork.child_callback_user);
59  } else {
60  inst->fork_result = r;
61  }
62 }
63 
64 static void wrap_func(ptrace_wrap_instance *inst) {
65  inst->func_result = inst->request.func.func(inst->request.func.user);
66 }
67 
68 static void *th_run(ptrace_wrap_instance *inst) {
69  while (1) {
70  sem_wait(&inst->request_sem);
71  switch (inst->request.type) {
73  goto stop;
75  wrap_ptrace(inst);
76  break;
78  wrap_fork(inst);
79  break;
81  wrap_func(inst);
82  break;
83  }
84  sem_post(&inst->result_sem);
85  }
86 stop:
87  return NULL;
88 }
89 
91  if (inst->th == pthread_self()) {
92  return ptrace(request, pid, addr, data);
93  }
94 
95  int _errno = 0;
97  inst->request.ptrace.request = request;
98  inst->request.ptrace.pid = pid;
99  inst->request.ptrace.addr = addr;
100  inst->request.ptrace.data = data;
101  inst->request.ptrace._errno = &_errno;
102  sem_post(&inst->request_sem);
103  sem_wait(&inst->result_sem);
104  errno = _errno;
105  return inst->ptrace_result;
106 }
107 
108 pid_t ptrace_wrap_fork(ptrace_wrap_instance *inst, void (*child_callback)(void *), void *child_callback_user) {
109  if (inst->th == pthread_self()) {
110  pid_t r = fork();
111  if (r == 0) {
112  child_callback(child_callback_user);
113  return 0;
114  } else {
115  return r;
116  }
117  }
118 
119  int _errno = 0;
121  inst->request.fork.child_callback = child_callback;
122  inst->request.fork.child_callback_user = child_callback_user;
123  inst->request.fork._errno = &_errno;
124  sem_post(&inst->request_sem);
125  sem_wait(&inst->result_sem);
126  errno = _errno;
127  return inst->fork_result;
128 }
129 
131  if (inst->th == pthread_self()) {
132  return func(user);
133  }
134 
136  inst->request.func.func = func;
137  inst->request.func.user = user;
138  sem_post(&inst->request_sem);
139  sem_wait(&inst->result_sem);
140  return inst->func_result;
141 }
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
static static sync static getppid static getegid const char static filename request
Definition: sflib.h:62
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
Definition: sflib.h:64
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid ptrace
Definition: sflib.h:57
int sem_wait(UV_PLATFORM_SEM_T *semid)
int sem_destroy(UV_PLATFORM_SEM_T *semid)
int sem_post(UV_PLATFORM_SEM_T *semid)
int sem_init(UV_PLATFORM_SEM_T *semid, int pshared, unsigned int value)
static void wrap_ptrace(ptrace_wrap_instance *inst)
Definition: ptrace_wrap.c:44
void * ptrace_wrap_func(ptrace_wrap_instance *inst, ptrace_wrap_func_func func, void *user)
Definition: ptrace_wrap.c:130
void ptrace_wrap_instance_stop(ptrace_wrap_instance *inst)
Definition: ptrace_wrap.c:36
pid_t ptrace_wrap_fork(ptrace_wrap_instance *inst, void(*child_callback)(void *), void *child_callback_user)
Definition: ptrace_wrap.c:108
long ptrace_wrap(ptrace_wrap_instance *inst, ptrace_wrap_ptrace_request request, pid_t pid, void *addr, void *data)
Definition: ptrace_wrap.c:90
int ptrace_wrap_instance_start(ptrace_wrap_instance *inst)
Definition: ptrace_wrap.c:14
static void * th_run(ptrace_wrap_instance *inst)
Definition: ptrace_wrap.c:68
static void wrap_func(ptrace_wrap_instance *inst)
Definition: ptrace_wrap.c:64
static void wrap_fork(ptrace_wrap_instance *inst)
Definition: ptrace_wrap.c:55
int ptrace_wrap_ptrace_request
Definition: ptrace_wrap.h:14
@ PTRACE_WRAP_REQUEST_TYPE_STOP
Definition: ptrace_wrap.h:18
@ PTRACE_WRAP_REQUEST_TYPE_PTRACE
Definition: ptrace_wrap.h:19
@ PTRACE_WRAP_REQUEST_TYPE_FORK
Definition: ptrace_wrap.h:20
@ PTRACE_WRAP_REQUEST_TYPE_FUNC
Definition: ptrace_wrap.h:21
void *(* ptrace_wrap_func_func)(void *)
Definition: ptrace_wrap.h:24
RZ_API int rz_sys_fork(void)
Definition: sys.c:1679
int pid_t
Definition: sftypes.h:38
ptrace_wrap_request request
Definition: ptrace_wrap.h:51
struct ptrace_wrap_request_t::@423::@425 ptrace
ptrace_wrap_func_func func
Definition: ptrace_wrap.h:42
ptrace_wrap_request_type type
Definition: ptrace_wrap.h:27
struct ptrace_wrap_request_t::@423::@426 fork
static int addr
Definition: z80asm.c:58