Rizin
unix-like reverse engineering framework and cli tools
debug_qnx.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2016 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2009-2016 defragger <rlaemmert@gmail.com>
3 // SPDX-FileCopyrightText: 2009-2016 madprogrammer
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #include <rz_debug.h>
7 #include <libqnxr.h>
8 
9 /* HACK_FOR_PLUGIN_LINKAGE */
10 RZ_API RzDebugPid *__r_debug_pid_new(const char *path, int pid, char status, ut64 pc) {
12  if (!p) {
13  return NULL;
14  }
15  p->path = strdup(path);
16  p->pid = pid;
17  p->status = status;
18  p->runnable = true;
19  p->pc = pc;
20  return p;
21 }
23  free(pid->path);
24  free(pid);
25  return NULL;
26 }
27 /* ------------------- */
28 
29 typedef struct {
31 } RzIOQnx;
32 
33 static libqnxr_t *desc = NULL;
34 static ut8 *reg_buf = NULL;
35 static int buf_size = 0;
36 
37 static void pidlist_cb(void *ctx, pid_t pid, char *name) {
38  RzList *list = ctx;
40 }
41 
42 static int rz_debug_qnx_select(RzDebug *dbg, int pid, int tid) {
43  return qnxr_select(desc, pid, tid);
44 }
45 
47  eprintf("%s: TODO: Threads\n", __func__);
48  return NULL;
49 }
50 
52  RzList *list = rz_list_new();
53  if (!list) {
54  return NULL;
55  }
57 
58  /* TODO */
59  if (pid) {
60  rz_list_append(list, __r_debug_pid_new("(current)", pid, 's', 0));
61  } else {
63  }
64 
65  return list;
66 }
67 
68 static int rz_debug_qnx_reg_read(RzDebug *dbg, int type, ut8 *buf, int size) {
69  int copy_size;
70  int buflen = 0;
71  if (!desc) {
72  return -1;
73  }
75  if (len <= 0) {
76  return -1;
77  }
78  // read the len of the current area
80  if (size < len) {
81  eprintf("rz_debug_qnx_reg_read: small buffer %d vs %d\n",
82  (int)size, (int)len);
83  }
84  copy_size = RZ_MIN(len, size);
85  buflen = RZ_MAX(len, buflen);
86  if (reg_buf) {
87  if (buf_size < copy_size) {
88  ut8 *new_buf = realloc(reg_buf, copy_size);
89  if (!new_buf) {
90  return -1;
91  }
92  reg_buf = new_buf;
93  buflen = copy_size;
94  buf_size = len;
95  }
96  } else {
97  reg_buf = calloc(buflen, 1);
98  if (!reg_buf) {
99  return -1;
100  }
101  buf_size = buflen;
102  }
103  memset((void *)(volatile void *)buf, 0, size);
104  memcpy((void *)(volatile void *)buf, desc->recv.data, copy_size);
105  memset((void *)(volatile void *)reg_buf, 0, buflen);
106  memcpy((void *)(volatile void *)reg_buf, desc->recv.data, copy_size);
107 
108  return len;
109 }
110 
112  return NULL;
113 }
114 
115 static int rz_debug_qnx_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size) {
116  int buflen = 0;
117  int bits = dbg->analysis->bits;
118  const char *pcname = rz_reg_get_name(dbg->analysis->reg, RZ_REG_NAME_PC);
119  RzRegItem *reg = rz_reg_get(dbg->analysis->reg, pcname, 0);
120  if (!reg_buf) {
121  // we cannot write registers before we once read them
122  return -1;
123  }
124  if (reg) {
125  if (dbg->analysis->bits != reg->size) {
126  bits = reg->size;
127  }
128  }
130  // some implementations of the gdb protocol are acting weird.
131  // so winedbg is not able to write registers through the <G> packet
132  // and also it does not return the whole gdb register profile after
133  // calling <g>
134  // so this workaround resizes the small register profile buffer
135  // to the whole set and fills the rest with 0
136  if (buf_size < buflen) {
137  ut8 *new_buf = realloc(reg_buf, buflen * sizeof(ut8));
138  if (!new_buf) {
139  return -1;
140  }
141  reg_buf = new_buf;
142  memset(new_buf + buf_size, 0, buflen - buf_size);
143  }
144 
145  RzRegItem *current = NULL;
146  for (;;) {
147  current = rz_reg_next_diff(dbg->reg, type, reg_buf, buflen, current, bits);
148  if (!current) {
149  break;
150  }
151  ut64 val = rz_reg_get_value(dbg->reg, current);
152  int bytes = bits / 8;
153  qnxr_write_reg(desc, current->name, (char *)&val, bytes);
154  }
155  return true;
156 }
157 
158 static int rz_debug_qnx_continue(RzDebug *dbg, int pid, int tid, int sig) {
159  qnxr_continue(desc, -1);
160  return true;
161 }
162 
164  qnxr_step(desc, -1);
165  return true;
166 }
167 
169  ptid_t ptid = qnxr_wait(desc, pid);
170  if (!ptid_equal(ptid, null_ptid)) {
172  return desc->notify_type;
173  }
174  return RZ_DEBUG_REASON_NONE;
175 }
176 
178  qnxr_stop(desc);
179  return true;
180 }
181 
182 static int rz_debug_qnx_attach(RzDebug *dbg, int pid) {
183  RzIODesc *d = dbg->iob.io->desc;
184  dbg->swstep = false;
185 
186  if (d && d->plugin && d->plugin->name && d->data) {
187  if (!strcmp("qnx", d->plugin->name)) {
188  RzIOQnx *g = d->data;
189  int arch = rz_sys_arch_id(dbg->arch);
190  int bits = dbg->analysis->bits;
191  if ((desc = &g->desc)) {
192  switch (arch) {
193  case RZ_SYS_ARCH_X86:
194  if (bits == 16 || bits == 32) {
195  qnxr_set_architecture(&g->desc, X86_32);
196  } else {
197  eprintf("Not supported register %s %d profile\n", dbg->arch, bits);
198  return false;
199  }
200  break;
201  case RZ_SYS_ARCH_ARM:
202  if (bits == 16 || bits == 32) {
203  qnxr_set_architecture(&g->desc, ARM_32);
204  } else {
205  eprintf("Not supported register %s %d profile\n", dbg->arch, bits);
206  return false;
207  }
208  break;
209  }
210  }
211  if (pid) {
212  qnxr_attach(desc, pid);
213  }
214  } else {
215  eprintf("%s: error: underlying IO descriptor isn't a QNX one\n", __func__);
216  return false;
217  }
218  }
219 
220  dbg->pid = 0;
221  return true;
222 }
223 
224 static int rz_debug_qnx_detach(RzDebug *dbg, int pid) {
226  free(reg_buf);
227  return true;
228 }
229 
230 static const char *rz_debug_qnx_reg_profile(RzDebug *dbg) {
231  int arch = rz_sys_arch_id(dbg->arch);
232  int bits = dbg->analysis->bits;
233  switch (arch) {
234  case RZ_SYS_ARCH_X86:
235  return strdup(
236  "=PC eip\n"
237  "=SP esp\n"
238  "=BP ebp\n"
239  "=A0 eax\n"
240  "=A1 ebx\n"
241  "=A2 ecx\n"
242  "=A3 edi\n"
243  "gpr eax .32 0 0\n"
244  "gpr ecx .32 4 0\n"
245  "gpr edx .32 8 0\n"
246  "gpr ebx .32 12 0\n"
247  "gpr esp .32 16 0\n"
248  "gpr ebp .32 20 0\n"
249  "gpr esi .32 24 0\n"
250  "gpr edi .32 28 0\n"
251  "gpr eip .32 32 0\n"
252  "gpr eflags .32 36 0\n"
253  "seg cs .32 40 0\n"
254  "seg ss .32 44 0\n"
255 #if 0
256  "seg ds .32 48 0\n"
257  "seg es .32 52 0\n"
258  "seg fs .32 56 0\n"
259  "seg gs .32 60 0\n"
260 #endif
261  );
262  case RZ_SYS_ARCH_ARM:
263  if (bits == 32) {
264  return strdup(
265  "=PC r15\n"
266  "=SP r14\n" // XXX
267  "=A0 r0\n"
268  "=A1 r1\n"
269  "=A2 r2\n"
270  "=A3 r3\n"
271  "gpr r0 .32 0 0\n"
272  "gpr r1 .32 4 0\n"
273  "gpr r2 .32 8 0\n"
274  "gpr r3 .32 12 0\n"
275  "gpr r4 .32 16 0\n"
276  "gpr r5 .32 20 0\n"
277  "gpr r6 .32 24 0\n"
278  "gpr r7 .32 28 0\n"
279  "gpr r8 .32 32 0\n"
280  "gpr r9 .32 36 0\n"
281  "gpr r10 .32 40 0\n"
282  "gpr r11 .32 44 0\n"
283  "gpr r12 .32 48 0\n"
284  "gpr sp .32 52 0\n" // r13
285  "gpr lr .32 56 0\n" // r14
286  "gpr pc .32 60 0\n" // r15
287  "gpr r13 .32 52 0\n"
288  "gpr r14 .32 56 0\n"
289  "gpr r15 .32 60 0\n"
290  "gpr cpsr .96 64 0\n"
291  "mmx d0 .64 68 0\n" // neon
292  "mmx d1 .64 76 0\n" // neon
293  "mmx d2 .64 84 0\n" // neon
294  "mmx d3 .64 92 0\n" // neon
295  "mmx d4 .64 100 0\n" // neon
296  "mmx d5 .64 108 0\n" // neon
297  "mmx d6 .64 116 0\n" // neon
298  "mmx d7 .64 124 0\n" // neon
299  "mmx d8 .64 132 0\n" // neon
300  "mmx d9 .64 140 0\n" // neon
301  "mmx d10 .64 148 0\n" // neon
302  "mmx d11 .64 156 0\n" // neon
303  "mmx d12 .64 164 0\n" // neon
304  "mmx d13 .64 172 0\n" // neon
305  "mmx d14 .64 180 0\n" // neon
306  "mmx d15 .64 188 0\n" // neon
307  "mmx d16 .64 196 0\n" // neon
308  "mmx d17 .64 204 0\n" // neon
309  "mmx d18 .64 212 0\n" // neon
310  "mmx d19 .64 220 0\n" // neon
311  "mmx d20 .64 228 0\n" // neon
312  "mmx d21 .64 236 0\n" // neon
313  "mmx d22 .64 244 0\n" // neon
314  "mmx d23 .64 252 0\n" // neon
315  "mmx d24 .64 260 0\n" // neon
316  "mmx d25 .64 268 0\n" // neon
317  "mmx d26 .64 276 0\n" // neon
318  "mmx d27 .64 284 0\n" // neon
319  "mmx d28 .64 292 0\n" // neon
320  "mmx d29 .64 300 0\n" // neon
321  "mmx d30 .64 308 0\n" // neon
322  "mmx d31 .64 316 0\n" // neon
323  "mmx fpscr .32 324 0\n" // neon
324  );
325  }
326  }
327  return NULL;
328 }
329 
331  if (!b) {
332  return false;
333  }
334  int ret = set
335  ? b->hw
336  ? qnxr_set_hwbp(desc, b->addr, "")
337  : qnxr_set_bp(desc, b->addr, "")
338  : b->hw
339  ? qnxr_remove_hwbp(desc, b->addr)
340  : qnxr_remove_bp(desc, b->addr);
341  return !ret;
342 }
343 
345  .name = "qnx",
346  .license = "LGPL3",
347  .arch = "x86,arm",
348  .bits = RZ_SYS_BITS_32,
349  .step = rz_debug_qnx_step,
350  .cont = rz_debug_qnx_continue,
351  .attach = &rz_debug_qnx_attach,
352  .detach = &rz_debug_qnx_detach,
353  .pids = &rz_debug_qnx_pids,
354  .tids = &rz_debug_qnx_tids,
355  .select = &rz_debug_qnx_select,
356  .stop = &rz_debug_qnx_stop,
357  .canstep = 1,
358  .wait = &rz_debug_qnx_wait,
359  .map_get = rz_debug_qnx_map_get,
360  .breakpoint = rz_debug_qnx_breakpoint,
361  .reg_read = &rz_debug_qnx_reg_read,
362  .reg_write = &rz_debug_qnx_reg_write,
363  .reg_profile = (void *)rz_debug_qnx_reg_profile,
364 };
365 
366 #ifndef RZ_PLUGIN_INCORE
369  .data = &rz_debug_plugin_qnx,
371 };
372 #endif
size_t len
Definition: 6502dis.c:15
RZ_API ut8 * rz_reg_get_bytes(RzReg *reg, int type, int *size)
Definition: arena.c:8
ut16 val
Definition: armass64_const.h:6
static ut8 bytes[32]
Definition: asm_arc.c:23
int bits(struct state *s, int need)
Definition: blast.c:72
#define RZ_API
#define NULL
Definition: cris-opc.c:27
cs_arch arch
Definition: cstool.c:13
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
static int rz_debug_qnx_attach(RzDebug *dbg, int pid)
Definition: debug_qnx.c:182
static libqnxr_t * desc
Definition: debug_qnx.c:33
static int rz_debug_qnx_detach(RzDebug *dbg, int pid)
Definition: debug_qnx.c:224
RZ_API void * __r_debug_pid_free(RzDebugPid *pid)
Definition: debug_qnx.c:22
static int rz_debug_qnx_continue(RzDebug *dbg, int pid, int tid, int sig)
Definition: debug_qnx.c:158
static RzList * rz_debug_qnx_pids(RzDebug *dbg, int pid)
Definition: debug_qnx.c:51
static RzList * rz_debug_qnx_tids(RzDebug *dbg, int pid)
Definition: debug_qnx.c:46
static int rz_debug_qnx_step(RzDebug *dbg)
Definition: debug_qnx.c:163
static RzDebugReasonType rz_debug_qnx_wait(RzDebug *dbg, int pid)
Definition: debug_qnx.c:168
static const char * rz_debug_qnx_reg_profile(RzDebug *dbg)
Definition: debug_qnx.c:230
static int buf_size
Definition: debug_qnx.c:35
RzDebugPlugin rz_debug_plugin_qnx
Definition: debug_qnx.c:344
static int rz_debug_qnx_reg_read(RzDebug *dbg, int type, ut8 *buf, int size)
Definition: debug_qnx.c:68
RZ_API RzLibStruct rizin_plugin
Definition: debug_qnx.c:367
static ut8 * reg_buf
Definition: debug_qnx.c:34
RZ_API RzDebugPid * __r_debug_pid_new(const char *path, int pid, char status, ut64 pc)
Definition: debug_qnx.c:10
static int rz_debug_qnx_select(RzDebug *dbg, int pid, int tid)
Definition: debug_qnx.c:42
static int rz_debug_qnx_stop(RzDebug *dbg)
Definition: debug_qnx.c:177
static RzList * rz_debug_qnx_map_get(RzDebug *dbg)
Definition: debug_qnx.c:111
static int rz_debug_qnx_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size)
Definition: debug_qnx.c:115
static void pidlist_cb(void *ctx, pid_t pid, char *name)
Definition: debug_qnx.c:37
static int rz_debug_qnx_breakpoint(RzBreakpoint *bp, RzBreakpointItem *b, bool set)
Definition: debug_qnx.c:330
RzDebug * dbg
Definition: desil.c:30
struct @667 g
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
int qnxr_remove_hwbp(libqnxr_t *g, ut64 address)
Definition: core.c:611
int qnxr_set_bp(libqnxr_t *g, ut64 address, const char *conditions)
Definition: core.c:599
int ptid_equal(ptid_t ptid1, ptid_t ptid2)
Definition: utils.c:309
int qnxr_read_registers(libqnxr_t *g)
Definition: core.c:323
int qnxr_select(libqnxr_t *g, pid_t pid, int tid)
Definition: core.c:445
#define X86_32
Definition: libqnxr.h:25
int qnxr_remove_bp(libqnxr_t *g, ut64 address)
Definition: core.c:607
int qnxr_set_hwbp(libqnxr_t *g, ut64 address, const char *conditions)
Definition: core.c:603
int qnxr_continue(libqnxr_t *g, int thread_id)
Definition: core.c:470
int qnxr_disconnect(libqnxr_t *g)
Definition: core.c:206
ptid_t qnxr_attach(libqnxr_t *g, pid_t pid)
Definition: core.c:223
void qnxr_pidlist(libqnxr_t *g, void *ctx, pidlist_cb_t *cb)
Definition: core.c:417
ptid_t qnxr_wait(libqnxr_t *g, pid_t pid)
Definition: core.c:542
int qnxr_set_architecture(libqnxr_t *g, ut8 architecture)
Definition: core.c:121
#define ARM_32
Definition: libqnxr.h:26
int qnxr_stop(libqnxr_t *g)
Definition: core.c:528
int qnxr_write_reg(libqnxr_t *g, const char *name, char *value, int len)
Definition: core.c:496
ptid_t null_ptid
Definition: core.c:18
int qnxr_step(libqnxr_t *g, int thread_id)
Definition: core.c:466
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
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
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
int type
Definition: mipsasm.c:17
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
RZ_API const char * rz_reg_get_name(RzReg *reg, int role)
Definition: reg.c:147
RZ_API RzRegItem * rz_reg_next_diff(RzReg *reg, int type, const ut8 *buf, int buflen, RzRegItem *prev_ri, int regsize)
Definition: reg.c:430
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_API ut64 rz_reg_get_value(RzReg *reg, RzRegItem *item)
Definition: rvalue.c:114
RzDebugReasonType
Definition: rz_debug.h:89
@ RZ_DEBUG_REASON_NONE
Definition: rz_debug.h:91
@ RZ_LIB_TYPE_DBG
Definition: rz_lib.h:70
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
@ RZ_REG_NAME_PC
Definition: rz_reg.h:43
@ RZ_SYS_BITS_32
Definition: rz_sys.h:20
RZ_API int rz_sys_arch_id(const char *arch)
Definition: sys.c:788
#define RZ_NEW0(x)
Definition: rz_types.h:284
@ RZ_SYS_ARCH_X86
Definition: rz_types.h:532
@ RZ_SYS_ARCH_ARM
Definition: rz_types.h:533
#define RZ_MIN(x, y)
#define RZ_MAX(x, y)
#define RZ_VERSION
Definition: rz_version.h:8
int pid_t
Definition: sftypes.h:38
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
libqnxr_t desc
Definition: debug_qnx.c:30
ut8 data[DS_DATA_MAX_SIZE]
Definition: libqnxr.h:51
ut8 notify_type
Definition: libqnxr.h:62
union libqnxr_t::@603 recv
int signal
Definition: libqnxr.h:64
Definition: z80asm.h:102
Definition: libqnxr.h:30
Definition: rz_bp.h:78
const char * version
Definition: rz_debug.h:362
const char * name
Definition: rz_debug.h:359
int swstep
Definition: rz_debug.h:261
RzDebugReason reason
Definition: rz_debug.h:276
RzAnalysis * analysis
Definition: rz_debug.h:305
char * arch
Definition: rz_debug.h:242
RzReg * reg
Definition: rz_debug.h:286
RzIOBind iob
Definition: rz_debug.h:293
RzIO * io
Definition: rz_io.h:232
struct rz_io_desc_t * desc
Definition: rz_io.h:60
char * name
Definition: rz_reg.h:118
ut64 buflen
Definition: core.c:76
ut64(WINAPI *w32_GetEnabledXStateFeatures)()