Rizin
unix-like reverse engineering framework and cli tools
winkd.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2014-2017 LemonBoy <thatlemon@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 #include <stdio.h>
4 #include <stdarg.h>
5 #include <stdint.h>
6 #include <stdbool.h>
7 #include <string.h>
8 #include <rz_util.h>
9 #include <rz_cons.h>
10 #include <rz_list.h>
11 #include <rz_debug.h>
12 #include "transport.h"
13 #include "winkd.h"
14 #include "kd.h"
15 
16 #define O_FLAG_XPVAD 1
17 #define O_(n) ctx->profile->f[n]
18 #include "profiles.h"
19 
20 #define KOBJECT_PROCESS 3
21 #define KOBJECT_THREAD 6
22 
25  while (!rz_th_lock_tryenter(ctx->dontmix)) {
26  if (rz_cons_is_breaked()) {
28  return false;
29  }
30  }
31  return true;
32 }
33 
36  rz_th_lock_leave(ctx->dontmix);
37  return true;
38 }
39 
41  ut64 ptr = 0;
42  // Grab the CmNtCSDVersion field to extract the Service Pack number
43  if (!ctx->read_at_kernel_virtual(ctx->user, ctx->KdDebuggerDataBlock + K_CmNtCSDVersion, (ut8 *)&ptr, 8)) {
44  RZ_LOG_DEBUG("Failed to read at %" PFMT64x "\n", ctx->KdDebuggerDataBlock + K_CmNtCSDVersion);
45  return 0;
46  }
47  ut64 res;
48  if (!ctx->read_at_kernel_virtual(ctx->user, ptr, (ut8 *)&res, 8)) {
49  RZ_LOG_DEBUG("Failed to read at %" PFMT64x "\n", ptr);
50  return 0;
51  }
52  if (res == UT64_MAX) {
53  return 0;
54  }
55  return (res >> 8) & 0xff;
56 }
57 
59  int i;
60  for (i = 0; p_table[i]; i++) {
61  if (p_table[i]->build != build) {
62  continue;
63  }
64  if (p_table[i]->sp != sp) {
65  continue;
66  }
67  if (p_table[i]->bits != bits) {
68  continue;
69  }
71  if (!p) {
72  return NULL;
73  }
74  *p = *p_table[i];
75  return p;
76  }
77  return NULL;
78 }
79 
81  return ctx->is_64bit ? RZ_SYS_BITS_64 : RZ_SYS_BITS_32;
82 }
83 
85  if (!ctx) {
86  return -1;
87  }
88  return ctx->cpu_count;
89 }
90 
92  if (!ctx || cpu > ctx->cpu_count) {
93  return false;
94  }
95  ctx->cpu = cpu;
96  return true;
97 }
98 
100  if (!ctx) {
101  return -1;
102  }
103  return ctx->cpu;
104 }
105 
107  WindProc *p;
108  WindThread *t;
109  RzList *l;
110  RzListIter *it;
111  const bool is_cur_process = ctx->target.eprocess && (ctx->target.uniqueid == pid);
112  bool found = false;
113  if (!is_cur_process) {
114  l = winkd_list_process(ctx);
115  rz_list_foreach (l, it, p) {
116  if (p->uniqueid == pid) {
117  found = true;
118  ctx->target = *p;
119  break;
120  }
121  }
122  rz_list_free(l);
123  if (!found) {
124  ctx->target.eprocess = 0;
125  ctx->target.uniqueid = 0;
126  return false;
127  }
128  }
129  const bool is_cur_thread = ctx->target_thread.ethread && (ctx->target_thread.uniqueid == tid);
130  found = false;
131  if (!is_cur_thread || !is_cur_process) {
132  l = winkd_list_threads(ctx);
133  if (is_cur_process) {
134  rz_list_foreach (l, it, t) {
135  if (t->uniqueid == tid) {
136  ctx->target_thread = *t;
137  found = true;
138  break;
139  }
140  }
141  } else {
142  t = rz_list_first(l);
143  if (t) {
144  ctx->target_thread = *t;
145  found = true;
146  }
147  }
148  rz_list_free(l);
149  if (!found) {
150  ctx->target_thread.ethread = 0;
151  ctx->target_thread.uniqueid = 0;
152  return false;
153  }
154  }
155  return true;
156 }
157 
159  return ctx->target.uniqueid;
160 }
161 
163  return ctx->target_thread.uniqueid;
164 }
165 
167  ut64 base = 0;
168 
169  if (!winkd_read_at_uva(ctx, ctx->target.peb + O_(P_ImageBaseAddress),
170  (ut8 *)&base, 4 << ctx->is_64bit)) {
171  return 0;
172  }
173 
174  return base;
175 }
176 
178  KdCtx *ctx = RZ_NEW0(KdCtx);
179  if (!ctx) {
180  return NULL;
181  }
182  ctx->dontmix = rz_th_lock_new(true);
183  ctx->desc = desc;
184  return ctx;
185 }
186 
188  if (!ctx || !*ctx) {
189  return;
190  }
191  rz_list_free((*ctx)->plist_cache);
192  rz_list_free((*ctx)->tlist_cache);
193  io_desc_t *desc = (*ctx)->desc;
194  desc->iob->close(desc->fp);
195  RZ_FREE(desc);
196  rz_th_lock_free((*ctx)->dontmix);
197  winkd_ctx_fini(&(*ctx)->windctx);
198  free((*ctx)->kernel_module.name);
199  RZ_FREE(*ctx);
200 }
201 
202 #define PKT_REQ(p) ((kd_req_t *)(((kd_packet_t *)p)->data))
203 #define PKT_STC(p) ((kd_stc_64 *)(((kd_packet_t *)p)->data))
204 #define PKT_IO(p) ((kd_ioc_t *)(((kd_packet_t *)p)->data))
205 
206 #if 0
207 static void dump_stc(kd_packet_t *p) {
208  kd_stc_64 *stc = PKT_STC (p);
209 
210  eprintf ("New state: %08x\n", stc->state);
211  eprintf ("EIP: 0x%016"PFMT64x " Kthread: 0x%016"PFMT64x "\n",
212  (ut64) stc->pc, (ut64) stc->kthread);
213  eprintf ("On cpu %i/%i\n", stc->cpu + 1, stc->cpu_count);
214 
215  if (stc->state == DbgKdExceptionStateChange) {
216  eprintf ("Exception\n");
217  eprintf (" Code : %08x\n", stc->exception.code);
218  eprintf (" Flags : %08x\n", stc->exception.flags);
219  eprintf (" Record : %016"PFMT64x "\n", (ut64) stc->exception.ex_record);
220  eprintf (" Addr : %016"PFMT64x "\n", (ut64) stc->exception.ex_addr);
221  }
222 }
223 #endif
224 
225 static int do_io_reply(RZ_BORROW RZ_NONNULL KdCtx *ctx, kd_packet_t *pkt) {
226  kd_ioc_t ioc = {
227  0
228  };
229  int ret;
230  ioc.req = PKT_IO(pkt)->req;
231  ioc.ret = KD_RET_ENOENT;
232  while (!winkd_lock_enter(ctx)) {
233  };
235  ctx->seq_id, (ut8 *)&ioc, sizeof(kd_ioc_t), NULL, 0);
236  if (ret != KD_E_OK) {
237  goto error;
238  }
239  RZ_LOG_DEBUG("Waiting for io_reply ack...\n");
241  if (ret != KD_E_OK) {
242  goto error;
243  }
245  RZ_LOG_DEBUG("Ack received, restore flow\n");
246  return true;
247 error:
249  return 0;
250 }
251 
252 static inline bool load_symbol_path_is_valid(kd_packet_t *pkt) {
253  kd_stc_64 *stc = PKT_STC(pkt);
254  return stc->load_symbols.pathsize &&
255  (stc->load_symbols.pathsize < pkt->length - (rz_offsetof(kd_stc_64, load_symbols.unload) + sizeof(stc->load_symbols.unload)));
256 }
257 
259  kd_packet_t *pkt = NULL;
260  int ret;
261  if (p) {
262  *p = NULL;
263  }
264 
265  bool is_repeated_packet;
266  do {
267  free(pkt);
268  // Try to read a whole packet
269  ret = kd_read_packet(ctx->desc, &pkt);
270  if (ret != KD_E_OK) {
271  return ret;
272  }
273  RZ_LOG_DEBUG("=== Received Packet ===\n");
274  RZ_LOG_DEBUG("PACKET ID : 0x%x\n", pkt->id);
275  is_repeated_packet = ctx->last_received_id == pkt->id;
276  if (is_repeated_packet) {
277  RZ_LOG_DEBUG("Repeated packet, skipping\n");
278  } else if (pkt->leader == KD_PACKET_DATA) {
279  ctx->last_received_id = pkt->id;
280  }
281  if (pkt->type == KD_PACKET_TYPE_UNUSED) {
282  is_repeated_packet = true;
283  continue;
284  }
285  } while (is_repeated_packet);
286 
287  if (pkt->type != type) {
288  RZ_LOG_DEBUG("We were not waiting for this: %02x Expected: %02x\n", pkt->type, type);
289  }
290  if (pkt->leader == KD_PACKET_DATA && pkt->type == KD_PACKET_TYPE_STATE_CHANGE64) {
291  RZ_LOG_VERBOSE("Got STATE_CHANGE64 packet\n");
292  kd_stc_64 *stc = PKT_STC(pkt);
293  if (stc->state == DbgKdExceptionStateChange) {
294  RZ_LOG_VERBOSE(" Exception\n");
295  RZ_LOG_VERBOSE(" Code : %08" PFMT32x "\n", stc->exception.code);
296  RZ_LOG_VERBOSE(" Flags : %08" PFMT32x "\n", stc->exception.flags);
297  RZ_LOG_VERBOSE(" Record : %016" PFMT64x "\n", stc->exception.ex_record);
298  RZ_LOG_VERBOSE(" Addr : %016" PFMT64x "\n", stc->exception.ex_addr);
299  if (ctx->breaked) {
300  RZ_LOG_VERBOSE(" BREAKED\n");
301  }
302  } else if (stc->state == DbgKdLoadSymbolsStateChange) {
303  RZ_LOG_VERBOSE(stc->load_symbols.unload ? " Unload Symbols\n" : " Load Symbols\n");
304  RZ_LOG_VERBOSE(" Path Size : %016" PFMT64x "\n", stc->load_symbols.pathsize);
305  RZ_LOG_VERBOSE(" Base : %016" PFMT64x "\n", stc->load_symbols.base);
306  RZ_LOG_VERBOSE(" Checksum : %08" PFMT32x "\n", stc->load_symbols.checksum);
307  RZ_LOG_VERBOSE(" ImageSize : %08" PFMT32x "\n", stc->load_symbols.size);
308  if (load_symbol_path_is_valid(pkt)) {
309  char *path = (char *)pkt->data + pkt->length - stc->load_symbols.pathsize;
310  path[stc->load_symbols.pathsize - 1] = 0;
311  RZ_LOG_VERBOSE(" Image : %s\n", path);
312  if (rz_str_endswith(path, "\\ntoskrnl.exe")) {
313  ctx->kernel_module.addr = stc->load_symbols.base;
314  ctx->kernel_module.size = stc->load_symbols.size;
315  ctx->kernel_module.name = strdup(path);
316  }
317  }
318  } else if (stc->state == DbgKdCommandStringStateChange) {
319  RZ_LOG_VERBOSE("CommandString\n");
320  } else {
321  RZ_LOG_WARN("Unknown state change packet type: 0x%" PFMT32x "\n", (ut32)pkt->type);
322  }
323  } else if (pkt->leader == KD_PACKET_DATA && pkt->type == KD_PACKET_TYPE_FILE_IO) {
324  RZ_LOG_DEBUG("File IO\n");
325  RZ_LOG_DEBUG(" req: %08" PFMT32x "\n", PKT_IO(pkt)->req);
326  RZ_LOG_DEBUG(" ret: %08" PFMT32x "\n", PKT_IO(pkt)->ret);
327  RZ_LOG_DEBUG("Replying IO\n");
328  do_io_reply(ctx, pkt);
329  } else if (pkt->leader == KD_PACKET_DATA && pkt->type == KD_PACKET_TYPE_STATE_MANIPULATE) {
330  RZ_LOG_DEBUG("State_manipulate\n");
331  RZ_LOG_DEBUG(" req: %08" PFMT32x "\n", PKT_REQ(pkt)->req);
332  RZ_LOG_DEBUG(" cpu_level: %08x\n", PKT_REQ(pkt)->cpu_level);
333  RZ_LOG_DEBUG(" cpu: %i\n", PKT_REQ(pkt)->cpu);
334  RZ_LOG_DEBUG(" ret: %08" PFMT32x "\n", PKT_REQ(pkt)->ret);
335  }
336 
337  if (pkt->leader == KD_PACKET_CTRL) {
338  switch (pkt->type) {
340  RZ_LOG_DEBUG("ACK received\n");
341  if (pkt->id == ctx->seq_id) {
342  ctx->seq_id ^= 1;
343  }
345  free(pkt);
346  return KD_E_OK;
347  }
348  break;
350  RZ_LOG_DEBUG("Reset received\n");
351  ctx->seq_id = KD_INITIAL_PACKET_ID;
352  ctx->last_received_id = KD_INITIAL_PACKET_ID;
353  free(pkt);
354  if (type == KD_PACKET_TYPE_RESET) {
355  return KD_E_OK;
356  }
357  return KD_E_MALFORMED;
359  // The host didn't like our request
361  RZ_LOG_DEBUG("Waoh. You probably sent a malformed packet!\n");
362  free(pkt);
363  return KD_E_MALFORMED;
364  }
365  }
366  if (pkt->type != type) {
367  free(pkt);
368  if (ctx->breaked) {
369  ctx->breaked = false;
370  return KD_E_BREAK;
371  } else {
372  return KD_E_MALFORMED;
373  }
374  }
375  ctx->breaked = false;
376  if (ret != KD_E_OK) {
377  free(pkt);
378  return ret;
379  }
380 
381  if (p) {
382  *p = pkt;
383  } else {
384  free(pkt);
385  }
386 
387  return KD_E_OK;
388 }
389 
391  ut8 buf[4];
392  const ut8 ptr_size = ctx->is_64bit ? 8 : 4;
393  const ut64 self = address;
394  const ut64 tag_addr = self - ptr_size - 4;
395 
396  if (ctx->read_at_kernel_virtual(ctx->user, tag_addr, buf, 4) != 4) {
397  RZ_LOG_DEBUG("Failed to read vadtree\n");
398  return;
399  }
400 
401  if (memcmp(buf, "Vad", 3)) {
402  RZ_LOG_DEBUG("Failed to read VAD: Tag is not 'Vad'\n");
403  return;
404  }
405 
406  const bool is_vad_short = buf[3] == 'S';
407 
408  ut64 left = winkd_read_ptr_at(ctx, ctx->read_at_kernel_virtual, address);
409  address += ptr_size;
410  ut64 right = winkd_read_ptr_at(ctx, ctx->read_at_kernel_virtual, address);
411  address += ptr_size;
412  ut64 parent_value = winkd_read_ptr_at(ctx, ctx->read_at_kernel_virtual, address);
413  address += ptr_size;
414 
415  if (parent != UT64_MAX && (parent_value & ~3) != (parent & ~3)) {
416  RZ_LOG_DEBUG("Wrong parent!\n");
417  return;
418  }
419 
420  if (ctx->read_at_kernel_virtual(ctx->user, address, buf, 4) != 4) {
421  RZ_LOG_DEBUG("Failed to read vadtree\n");
422  return;
423  }
424  address += 4;
425  const ut64 start_vpn = rz_read_le32(buf);
426 
427  if (ctx->read_at_kernel_virtual(ctx->user, address, buf, 4) != 4) {
428  RZ_LOG_DEBUG("Failed to read vadtree\n");
429  return;
430  }
431  address += 4;
432  const ut64 end_vpn = rz_read_le32(buf);
433  ut8 start_vpn_high = 0;
434  ut8 end_vpn_high = 0;
435  if (ctx->is_64bit) {
436  if (ctx->read_at_kernel_virtual(ctx->user, address, &start_vpn_high, 1) != 1) {
437  RZ_LOG_DEBUG("Failed to read vadtree\n");
438  return;
439  }
440  address++;
441  if (ctx->read_at_kernel_virtual(ctx->user, address, &end_vpn_high, 1) != 1) {
442  RZ_LOG_DEBUG("Failed to read vadtree\n");
443  return;
444  }
445  address++;
446  }
447 
448  const ut64 start = (start_vpn | (ut64)start_vpn_high << 32) << 12;
449  const ut64 end = (((end_vpn | (ut64)end_vpn_high << 32) + 1) << 12) - 1;
450 
451  if (!is_vad_short) {
452  // TODO: get file info that vad is based from
453  // either in nt!_MMVAD->FileObject or in nt!_MMVAD->Subsection->ControlArea->FilePointer
454  }
455 
457  if (!map) {
458  return;
459  }
460  map->start = start;
461  map->end = end;
462  // TODO: get permission from nt!_MMVAD_FLAGS bitfield,
463  // Protection is an index into nt!MmProtectToValue
464  // that contains the PAGE_* memory protection constants
465  map->perm = RZ_PERM_RWX;
467 
468  if (left) {
469  winkd_walk_vadtree(ctx, left, self, out);
470  }
471  if (right) {
472  winkd_walk_vadtree(ctx, right, self, out);
473  }
474 }
475 
477  if (!ctx->target.vadroot) {
478  return NULL;
479  }
481  if (!maps) {
482  return NULL;
483  }
484  winkd_walk_vadtree(ctx, ctx->target.vadroot, UT64_MAX, maps);
485  return maps;
486 }
487 
489  ut8 type;
490  if (!ctx->read_at_kernel_virtual(ctx->user, address, &type, 1)) {
491  RZ_LOG_WARN("Failed to read DISPACHER_HEAD.Type at: 0x%" PFMT64x "\n", address);
492  return NULL;
493  }
494  if ((type & 0x7f) != KOBJECT_PROCESS) {
495  RZ_LOG_WARN("KOBJECT at 0x%" PFMT64x " is not a process.\n", address);
496  return NULL;
497  }
499  if (!proc) {
500  return NULL;
501  }
502  // Read the short name
503  ctx->read_at_kernel_virtual(ctx->user, address + O_(E_ImageFileName), (ut8 *)proc->name, sizeof(proc->name));
504  proc->name[sizeof(proc->name) - 1] = '\0';
505  proc->eprocess = address;
506  proc->vadroot = winkd_read_ptr_at(ctx, ctx->read_at_kernel_virtual, address + O_(E_VadRoot));
507  proc->uniqueid = winkd_read_ptr_at(ctx, ctx->read_at_kernel_virtual, address + O_(E_UniqueProcessId));
508  proc->peb = winkd_read_ptr_at(ctx, ctx->read_at_kernel_virtual, address + O_(E_Peb));
509  proc->dir_base_table = winkd_read_ptr_at(ctx, ctx->read_at_kernel_virtual, address + O_(K_DirectoryTableBase));
510  return proc;
511 }
512 
514  RzList *ret = NULL;
515  bool current_process_found = false;
516  // Grab the PsActiveProcessHead from _KDDEBUGGER_DATA64
517  ctx->PsActiveProcessHead = winkd_read_ptr_at(ctx, ctx->read_at_kernel_virtual, ctx->KdDebuggerDataBlock + K_PsActiveProcessHead);
518 
519  // Walk the LIST_ENTRY
520  ut64 ptr = winkd_read_ptr_at(ctx, ctx->read_at_kernel_virtual, ctx->PsActiveProcessHead);
521 
522  // Check for empty list
523  if (ptr == 0 || ptr == UT64_MAX) {
524  RZ_LOG_ERROR("NULL value at PsActiveProcessHead\n");
525  if (ctx->target.eprocess) {
526  ret = rz_list_newf(free);
527  goto get_cur_process;
528  }
529  return NULL;
530  }
531  ret = rz_list_newf(free);
532 
533  do {
534  ut64 next;
535 
536  // Read the ActiveProcessLinks entry
537  next = winkd_read_ptr_at(ctx, ctx->read_at_kernel_virtual, ptr);
538 
539  if (!next || next == UT64_MAX) {
540  RZ_LOG_WARN("Corrupted ActiveProcessLinks entry found at: 0x%" PFMT64x "\n", ptr);
541  break;
542  }
543 
544  // This points to the 'ActiveProcessLinks' list, adjust the ptr so that it point to the
545  // EPROCESS base
546  ptr -= O_(E_ActiveProcessLinks);
547 
549  if (proc) {
550  if (proc->eprocess == ctx->target.eprocess) {
551  current_process_found = true;
552  }
553  rz_list_append(ret, proc);
554  }
555  ptr = next;
556  } while (ptr != ctx->PsActiveProcessHead);
557 get_cur_process:
558  if (!current_process_found && ctx->target.eprocess) {
559  WindProc *proc = winkd_get_process_at(ctx, ctx->target.eprocess);
560  if (proc) {
561  rz_list_append(ret, proc);
562  }
563  }
564  return ret;
565 }
566 
568  ut32 total = 0;
569  ut32 offset = 0;
570  const ut64 end = address + count;
571  while (address < end) {
572  ut64 pa;
573  const ut32 restOfPage = 0x1000 - (address & 0xfff);
574  if (!winkd_va_to_pa(ctx, ctx->target.dir_base_table, address, &pa)) {
575  RZ_LOG_VERBOSE("0x%" PFMT64x " not mapped\n", address);
576  if (UT64_ADD_OVFCHK(address, restOfPage)) {
577  break;
578  }
579  address += restOfPage;
580  offset += restOfPage;
581  continue;
582  }
583  int result;
584  if (write) {
585  result = ctx->write_at_physical(ctx->user, pa, buf + offset, RZ_MIN(count - offset, restOfPage));
586  } else {
587  result = ctx->read_at_physical(ctx->user, pa, buf + offset, RZ_MIN(count - offset, restOfPage));
588  }
589  address += result;
590  offset += result;
591  total += result;
592  }
593  return total;
594 }
595 
597  return winkd_op_at_uva(ctx, address, buf, count, false);
598 }
599 
601  return winkd_op_at_uva(ctx, address, (ut8 *)buf, count, true);
602 }
603 
604 int map_comparator(const void *m1, const void *m2) {
605  const RzDebugMap *map1 = m1;
606  const RzDebugMap *map2 = m2;
607  return map1->addr > map2->addr ? 1 : map1->addr < map2->addr ? -1
608  : 0;
609 }
610 
611 void winkd_windmodule_free(void *ptr) {
612  WindModule *mod = ptr;
613  free(mod->name);
614  free(mod);
615 }
616 
618  const bool is_target_kernel = ctx->target.uniqueid <= 4;
619  if (is_target_kernel) {
620  return ctx->read_at_kernel_virtual(ctx->user, address, buf, count);
621  }
622  return winkd_read_at_uva(ctx, address, buf, count);
623 }
624 
627  if (!ret) {
628  return NULL;
629  }
630  ut64 ptr, base;
631  int list_entry_off = 0;
632  const bool is_target_kernel = ctx->target.uniqueid <= 4;
633  if (is_target_kernel) {
634  if (!ctx->PsLoadedModuleList) {
635  RZ_LOG_ERROR("No PsLoadedModuleList\n");
636  return ret;
637  }
638  ptr = ctx->PsLoadedModuleList;
639  base = ptr;
640  if (!ctx->read_at_kernel_virtual(ctx->user, ptr, (ut8 *)&ptr, 4 << ctx->is_64bit)) {
641  RZ_LOG_ERROR("PsLoadedModuleList not present in mappings\n");
642  }
643  if (ptr == base) {
644  return ret;
645  }
646  } else {
647  // Get kernel modules
648  const ut32 saved_target = ctx->target.uniqueid;
649  ctx->target.uniqueid = 0;
650  RzList *kernel_modules = winkd_list_modules(ctx);
651  ctx->target.uniqueid = saved_target;
652 
653  if (kernel_modules) {
654  rz_list_join(ret, kernel_modules);
655  rz_list_free(kernel_modules);
656  }
657 
658  if (!ctx->target.peb) {
659  RZ_LOG_ERROR("No PEB for target\n");
660  return ret;
661  }
662 
663  // Grab the _PEB_LDR_DATA from PEB
664  ut64 ldroff = ctx->is_64bit ? 0x18 : 0xC;
665  if (!winkd_read_at_uva(ctx, ctx->target.peb + ldroff, (ut8 *)&ptr, 4 << ctx->is_64bit)) {
666  RZ_LOG_ERROR("PEB not present in target mappings\n");
667  return ret;
668  }
669 
670  RZ_LOG_DEBUG("_PEB_LDR_DATA : 0x%016" PFMT64x "\n", ptr);
671 
672  // LIST_ENTRY InMemoryOrderModuleList
673  ut64 mlistoff = ctx->is_64bit ? 0x20 : 0x14;
674 
675  base = ptr + mlistoff;
676 
677  winkd_read_at_uva(ctx, base, (ut8 *)&ptr, 4 << ctx->is_64bit);
678 
679  // Offset of InMemoryOrderLinks inside _LDR_DATA_TABLE_ENTRY
680  list_entry_off = (4 << ctx->is_64bit) * 2;
681  }
682 
683  RZ_LOG_DEBUG("InMemoryOrderModuleList : 0x%016" PFMT64x "\n", ptr);
684 
685  const ut64 baseoff = ctx->is_64bit ? 0x30 : 0x18;
686  const ut64 sizeoff = ctx->is_64bit ? 0x40 : 0x20;
687  const ut64 nameoff = ctx->is_64bit ? 0x48 : 0x24;
688  const ut64 timestampoff = is_target_kernel
689  ? ctx->is_64bit ? 0x9c : 0x58
690  : ctx->is_64bit ? 0x80
691  : 0x44;
692  do {
693 
694  ut64 next = 0;
695  read_at_uva_or_kernel(ctx, ptr, (ut8 *)&next, 4 << ctx->is_64bit);
696 
697  RZ_LOG_DEBUG("_%sLDR_DATA_TABLE_ENTRY : 0x%016" PFMT64x "\n", is_target_kernel ? "K" : "", next);
698  if (!next || next == UT64_MAX) {
699  RZ_LOG_WARN("Corrupted InMemoryOrderModuleList found at: 0x%" PFMT64x "\n", ptr);
700  break;
701  }
702 
703  ptr -= list_entry_off;
704 
706  if (!mod) {
707  break;
708  }
709  read_at_uva_or_kernel(ctx, ptr + baseoff, (ut8 *)&mod->addr, 4 << ctx->is_64bit);
710  read_at_uva_or_kernel(ctx, ptr + sizeoff, (ut8 *)&mod->size, 4);
711  read_at_uva_or_kernel(ctx, ptr + timestampoff, (ut8 *)&mod->timestamp, 4);
712 
713  ut16 length;
714  read_at_uva_or_kernel(ctx, ptr + nameoff, (ut8 *)&length, sizeof(ut16));
715 
716  ut64 bufferaddr = 0;
717  int align = ctx->is_64bit ? sizeof(ut64) : sizeof(ut32);
718  read_at_uva_or_kernel(ctx, ptr + nameoff + align, (ut8 *)&bufferaddr, 4 << ctx->is_64bit);
719 
720  ut8 *unname = calloc((ut64)length + 2, 1);
721  if (!unname) {
722  break;
723  }
724  read_at_uva_or_kernel(ctx, bufferaddr, unname, length);
725 
726  mod->name = calloc((ut64)length + 1, 1);
727  if (!mod->name) {
728  break;
729  }
730  rz_str_utf16_to_utf8((ut8 *)mod->name, length + 1, unname, length + 2, true);
731  free(unname);
733 
734  ptr = next;
735  } while (ptr != base);
736  return ret;
737 }
738 
740  int running_offset;
741  if (ctx->profile->build < 9200) {
742  running_offset = ctx->is_64bit ? 0x49 : 0x39;
743  } else {
744  running_offset = ctx->is_64bit ? 0x71 : 0x55;
745  }
746  ut8 type = 0;
747  if (!ctx->read_at_kernel_virtual(ctx->user, address, &type, 1)) {
748  RZ_LOG_WARN("Failed to read DISPACHER_HEAD.Type at: 0x%" PFMT64x "\n", address);
749  return NULL;
750  }
751  if ((type & 0x7f) != KOBJECT_THREAD) {
752  RZ_LOG_WARN("KOBJECT at 0x%" PFMT64x " is not a thread.\n", address);
753  return NULL;
754  }
755  ut64 entrypoint = 0;
756  if (!ctx->read_at_kernel_virtual(ctx->user, address + O_(ET_Win32StartAddress), (ut8 *)&entrypoint, 4 << ctx->is_64bit)) {
757  RZ_LOG_WARN("Failed to read Win32StartAddress at: 0x%" PFMT64x "\n", address + O_(ET_Win32StartAddress));
758  return NULL;
759  }
760  ut64 uniqueid = 0;
761  if (!ctx->read_at_kernel_virtual(ctx->user, address + O_(ET_Cid) + O_(C_UniqueThread), (ut8 *)&uniqueid, 4 << ctx->is_64bit)) {
762  RZ_LOG_WARN("Failed to read UniqueThread at: 0x%" PFMT64x "\n", address + O_(ET_Cid) + O_(C_UniqueThread));
763  return NULL;
764  }
765  bool running = false;
766  if (!ctx->read_at_kernel_virtual(ctx->user, address + running_offset, (ut8 *)&running, 1)) {
767  RZ_LOG_WARN("Failed to read KTHREAD.Running at: 0x%" PFMT64x "\n", address + running_offset);
768  return NULL;
769  }
770  WindThread *thread = calloc(1, sizeof(WindThread));
771  if (!thread) {
772  return NULL;
773  }
774  thread->uniqueid = uniqueid;
775  thread->status = running ? 'r' : 's';
776  thread->runnable = true;
777  thread->ethread = address;
778  thread->entrypoint = entrypoint;
779  return thread;
780 }
781 
783  RzList *ret;
784  ut64 ptr, base;
785  bool current_thread_found = false;
786  ptr = ctx->target.eprocess;
787  if (!ptr) {
788  RZ_LOG_ERROR("No _EPROCESS for target\n");
789  if (ctx->target_thread.ethread) {
790  ret = rz_list_newf(free);
791  goto get_cur_thread;
792  }
793  return NULL;
794  }
795 
796  // Grab the ThreadListHead from _EPROCESS
797  ctx->read_at_kernel_virtual(ctx->user, ptr + O_(E_ThreadListHead), (ut8 *)&ptr, 4 << ctx->is_64bit);
798  if (!ptr) {
799  RZ_LOG_ERROR("No ThreadListHead for target\n");
800  if (ctx->target_thread.ethread) {
801  ret = rz_list_newf(free);
802  goto get_cur_thread;
803  }
804  return NULL;
805  }
806 
807  base = ptr;
808 
809  ret = rz_list_newf(free);
810 
811  do {
812  ut64 next = 0;
813 
814  ctx->read_at_kernel_virtual(ctx->user, ptr, (ut8 *)&next, 4 << ctx->is_64bit);
815  if (!next || next == UT64_MAX) {
816  RZ_LOG_WARN("Corrupted ThreadListEntry found at: 0x%" PFMT64x "\n", ptr);
817  break;
818  }
819  if (next == base) {
820  break;
821  }
822 
823  // Adjust the ptr so that it points to the ETHREAD base
824  ptr -= O_(ET_ThreadListEntry);
825 
826  WindThread *thread = winkd_get_thread_at(ctx, ptr);
827  if (thread) {
828  if (thread->ethread == ctx->target_thread.ethread) {
829  current_thread_found = true;
830  }
831  rz_list_append(ret, thread);
832  }
833  ptr = next;
834  } while (true);
835 get_cur_thread:
836  if (!current_thread_found && ctx->target_thread.ethread) {
837  WindThread *thread = winkd_get_thread_at(ctx, ctx->target_thread.ethread);
838  if (thread) {
839  rz_list_append(ret, thread);
840  }
841  }
842  return ret;
843 }
844 
845 #define PTE_VALID 0x0001
846 #define PTE_LARGEPAGE 0x0080
847 #define PTE_PROTOTYPE 0x0400
848 #define ARM_DESCRIPTOR 0x0002
849 
850 static inline bool is_page_large(RZ_BORROW RZ_NONNULL WindCtx *ctx, ut64 page_descriptor) {
851  if (ctx->is_arm) {
852  return !(page_descriptor & ARM_DESCRIPTOR);
853  }
854  return page_descriptor & PTE_LARGEPAGE;
855 }
856 
857 // http://blogs.msdn.com/b/ntdebugging/archive/2010/02/05/understanding-pte-part-1-let-s-get-physical.aspx
858 // http://blogs.msdn.com/b/ntdebugging/archive/2010/04/14/understanding-pte-part2-flags-and-large-pages.aspx
859 // http://blogs.msdn.com/b/ntdebugging/archive/2010/06/22/part-3-understanding-pte-non-pae-and-x64.aspx
861  ut64 pml4i, pdpi, pdi, pti;
862  ut64 tmp, mask;
863 
864  if (ctx->is_64bit) {
865  pti = (va >> 12) & 0x1ff;
866  pdi = (va >> 21) & 0x1ff;
867  pdpi = (va >> 30) & 0x1ff;
868  pml4i = (va >> 39) & 0x1ff;
869  // Grab the PageFrameNumber field off the _HARDWARE_PTE entry
870  mask = 0x000000fffffff000;
871  } else {
872  if (ctx->is_pae) {
873  pti = (va >> 12) & 0x1ff;
874  pdi = (va >> 21) & 0x1ff;
875  pdpi = (va >> 30) & 0x3;
876  pml4i = 0;
877  } else {
878  pti = (va >> 12) & 0x3ff;
879  pdi = (va >> 22) & 0x3ff;
880  pdpi = 0;
881  pml4i = 0;
882  }
883  // Grab the PageFrameNumber field off the _HARDWARE_PTE entry
884  mask = 0xfffff000;
885  }
886 
887  tmp = directory_table;
888  tmp &= ~0x1f;
889 
890  if (ctx->is_64bit) {
891  // PML4 lookup
892  if (!ctx->read_at_physical(ctx->user, tmp + pml4i * 8, (ut8 *)&tmp, 8)) {
893  return false;
894  }
895  tmp &= mask;
896  }
897 
898  if (ctx->is_pae) {
899  // PDPT lookup
900  if (!ctx->read_at_physical(ctx->user, tmp + pdpi * 8, (ut8 *)&tmp, 8)) {
901  return false;
902  }
903  tmp &= mask;
904  }
905 
906  const int read_size = ctx->is_pae ? 8 : 4;
907 
908  // PDT lookup
909  if (!ctx->read_at_physical(ctx->user, tmp + pdi * read_size, (ut8 *)&tmp, read_size)) {
910  return false;
911  }
912 
913  // Large page entry
914  // The page size differs between pae and non-pae systems, the former points to 2MB pages while
915  // the latter points to 4MB pages
916  if (is_page_large(ctx, tmp)) {
917  tmp = (tmp << 16) >> 16;
918  *pa = ctx->is_pae ? (tmp & (~0x1fffff)) | (va & 0x1fffff) : (tmp & (~0x3fffff)) | (va & 0x3fffff);
919  return true;
920  }
921 
922  // PT lookup
923  if (!ctx->read_at_physical(ctx->user, (tmp & mask) + pti * read_size, (ut8 *)&tmp, read_size)) {
924  return false;
925  }
926 
927  if (tmp & PTE_VALID) {
928  *pa = (tmp & mask) | (va & 0xfff);
929  return true;
930  }
931 
932  if (tmp & PTE_PROTOTYPE) {
933  // TODO : prototype PTE support
934  RZ_LOG_ERROR("Prototype PTE lookup is currently missing!\n");
935  }
936 
937  return false;
938 }
939 
941  if (pkt) {
942  *pkt = NULL;
943  }
944  int ret;
945  if (!winkd_lock_enter(ctx)) {
946  return false;
947  }
948  const ut32 cur_seq_id = ctx->seq_id;
949  do {
951  ctx->seq_id, (ut8 *)req, sizeof(kd_req_t), buf, buf_len);
952  if (ret != KD_E_OK) {
953  break;
954  }
955 
957  if (ret == KD_E_OK) {
959  if (ret == KD_E_OK) {
960  kd_req_t *rr = PKT_REQ(*pkt);
961  if (rr->req != req->req) {
962  RZ_LOG_DEBUG("Got wrong packet %x for request %x\n", rr->req, req->req);
963  ret = KD_E_MALFORMED;
964  } else if ((*pkt)->length < sizeof(kd_req_t)) {
965  RZ_LOG_DEBUG("Got too small of a packet: %u bytes\n", (*pkt)->length);
966  ret = KD_E_MALFORMED;
967  }
968  }
969  }
970  if (rz_cons_is_breaked()) {
971  break;
972  }
973  } while (ret == KD_E_MALFORMED);
974 
975  if (ret == KD_E_OK && cur_seq_id == ctx->seq_id) {
976  RZ_LOG_DEBUG("We didn't get and ACK but got the packet\n");
977  ctx->seq_id ^= 1;
978  }
979 
981 
982  if (ret != KD_E_OK) {
983  return false;
984  }
985 
986  kd_req_t *rr = PKT_REQ(*pkt);
987 
988  if (rr->ret) {
989  RZ_LOG_DEBUG("%s : req returned %08x\n", __FUNCTION__, rr->ret);
990  RZ_FREE(*pkt);
991  return false;
992  }
993 
994  return true;
995 }
996 
998  kd_req_t req = { 0 };
999  kd_packet_t *pkt;
1000 
1001  if (!ctx || !ctx->desc || !ctx->syncd) {
1002  return false;
1003  }
1004 
1005  req.req = 0x3146;
1006  req.cpu = ctx->cpu;
1007 
1008  if (!winkd_send_state_manipulate_req(ctx, &req, NULL, 0, &pkt)) {
1009  return false;
1010  }
1011 
1012  kd_req_t *rr = PKT_REQ(pkt);
1013 
1014  RZ_LOG_DEBUG("Major : %i Minor %i\n", rr->rz_ver.major, rr->rz_ver.minor);
1015  RZ_LOG_DEBUG("Protocol version : %i.%i\n", rr->rz_ver.proto_major, rr->rz_ver.proto_minor);
1016  RZ_LOG_DEBUG("Flags : %08x\n", rr->rz_ver.flags);
1017  RZ_LOG_DEBUG("Machine : %08x\n", rr->rz_ver.machine);
1018  RZ_LOG_DEBUG("Kernel Base : %016" PFMT64x "\n", rr->rz_ver.kernel_base);
1019  RZ_LOG_DEBUG("Module list : %016" PFMT64x "\n", rr->rz_ver.mod_addr);
1020  RZ_LOG_DEBUG("Debug block : %016" PFMT64x "\n", rr->rz_ver.dbg_addr);
1021 
1022  if (rr->rz_ver.machine != KD_MACH_I386 && rr->rz_ver.machine != KD_MACH_AMD64) {
1023  RZ_LOG_ERROR("Unsupported target host\n");
1024  free(pkt);
1025  return false;
1026  }
1027 
1028  if (!(rr->rz_ver.flags & DBGKD_VERS_FLAG_DATA)) {
1029  RZ_LOG_ERROR("No _KDDEBUGGER_DATA64 pointer has been supplied by the debugee!\n");
1030  free(pkt);
1031  return false;
1032  }
1033 
1034  ctx->kernel_module.addr = rr->rz_ver.kernel_base;
1035  ctx->windctx.is_64bit = rr->rz_ver.flags & DBGKD_VERS_FLAG_PTR64;
1036 
1037  ut64 ptr = 0;
1038  if (!winkd_read_at(ctx, rr->rz_ver.dbg_addr, (ut8 *)&ptr, 4 << ctx->windctx.is_64bit)) {
1039  free(pkt);
1040  return false;
1041  }
1042 
1043  ctx->windctx.PsLoadedModuleList = rr->rz_ver.mod_addr;
1044  ctx->windctx.KdDebuggerDataBlock = ptr;
1045 
1046  RZ_LOG_DEBUG("PsLoadedModuleList at 0x%016" PFMT64x "\n", ctx->windctx.PsLoadedModuleList);
1047  RZ_LOG_DEBUG("_KDDEBUGGER_DATA64 at 0x%016" PFMT64x "\n", ctx->windctx.KdDebuggerDataBlock);
1048 
1049  // Thanks to this we don't have to find a way to read the cr4
1050  ut16 pae_enabled;
1051  if (!winkd_read_at(ctx, ctx->windctx.KdDebuggerDataBlock + K_PaeEnabled, (ut8 *)&pae_enabled, sizeof(ut16))) {
1052  free(pkt);
1053  return false;
1054  }
1055 
1056  ctx->windctx.is_pae = pae_enabled & 1;
1057  ctx->windctx.profile = winkd_get_profile(32 << ctx->windctx.is_64bit, rr->rz_ver.minor, winkd_get_sp(&ctx->windctx));
1058  if (!ctx->windctx.profile) {
1059  RZ_LOG_WARN("Could not find a suitable profile for the target OS\n");
1060  }
1061  free(pkt);
1062  return true;
1063 }
1064 
1066  int ret = -1;
1067  kd_packet_t *s;
1068 
1069  if (!ctx || !ctx->desc) {
1070  return -1;
1071  }
1072 
1073  if (ctx->syncd) {
1074  return 0;
1075  }
1076 
1077  while (!winkd_lock_enter(ctx)) {
1078  };
1079 
1080  if (ctx->desc->iob->type == KD_IO_NET) {
1081  // Read a KD packet to initialize KDNet interface
1082  // The first packet will always be type of KD_PACKET_TYPE_UNUSED
1083  ret = kd_read_packet(ctx->desc, &s);
1084  if (ret != KD_E_OK) {
1085  goto end;
1086  }
1087  }
1088 
1089  // Send the breakin packet
1090  if (iob_write(ctx->desc, (const ut8 *)"b", 1) != 1) {
1091  ret = KD_E_IOERR;
1092  goto end;
1093  }
1094 
1095  if (ctx->desc->iob->type == KD_IO_PIPE) {
1096  // Reset the host
1097  ret = kd_send_ctrl_packet(ctx->desc, KD_PACKET_TYPE_RESET, 0);
1098  if (ret != KD_E_OK) {
1099  goto end;
1100  }
1101 
1102  // Wait for the response
1104  if (ret != KD_E_OK) {
1105  goto end;
1106  }
1107  }
1108  ctx->last_received_id = KD_INITIAL_PACKET_ID;
1109 
1110  // Syncronize with the first KD_PACKET_TYPE_STATE_CHANGE64 packet
1112  if (ret != KD_E_OK) {
1113  goto end;
1114  }
1115 
1116  // Reset the sequence id
1117  ctx->seq_id = KD_INITIAL_PACKET_ID;
1118 
1119  kd_stc_64 *stc64 = PKT_STC(s);
1120  ctx->cpu = stc64->cpu;
1121  ctx->cpu_count = stc64->cpu_count;
1122  ctx->windctx.target.eprocess = 0;
1123  rz_list_free(ctx->plist_cache);
1124  ctx->plist_cache = NULL;
1125  rz_list_free(ctx->tlist_cache);
1126  ctx->tlist_cache = NULL;
1127  ctx->windctx.is_pae = 0;
1128  ctx->windctx.target_thread.ethread = stc64->kthread;
1129  // We're ready to go
1130  ctx->syncd = 1;
1131 
1132  free(s);
1133  RZ_LOG_INFO("Sync done! (%i cpus found)\n", ctx->cpu_count);
1134  ret = 1;
1135 
1136 end:
1138  return ret;
1139 }
1140 
1142  kd_req_t req = { 0 };
1143 
1144  if (!ctx || !ctx->desc || !ctx->syncd) {
1145  return 0;
1146  }
1147  req.req = DbgKdContinueApi;
1148  req.cpu = ctx->cpu;
1149  req.rz_cont.reason = handled ? 0x10001 : 0x80010001;
1150  // The meaning of 0x400 is unknown, but Windows doesn't
1151  // behave like suggested by ReactOS source
1152  req.rz_cont.tf = 0x400;
1153 
1154  if (!winkd_lock_enter(ctx)) {
1155  return KD_E_TIMEOUT;
1156  }
1157  int ret;
1158  do {
1160  ctx->seq_id, (ut8 *)&req, sizeof(kd_req_t), NULL, 0);
1161  if (ret != KD_E_OK) {
1162  break;
1163  }
1165  if (ret == KD_E_OK) {
1166  break;
1167  }
1168  } while (ret == KD_E_MALFORMED);
1169 
1170  rz_list_free(ctx->plist_cache);
1171  ctx->plist_cache = NULL;
1172  rz_list_free(ctx->tlist_cache);
1173  ctx->tlist_cache = NULL;
1174  ctx->context_cache_valid = false;
1176  return ret == KD_E_OK;
1177 }
1178 
1180  kd_packet_t *pkt = NULL;
1181  kd_req_t req = { 0 };
1182 
1183  if (!ctx || !ctx->desc || !ctx->syncd) {
1184  return false;
1185  }
1186  const ut64 max_ctx_size = KD_MAX_PAYLOAD - sizeof(kd_req_t);
1187  RZ_LOG_DEBUG("Regwrite() size: %x\n", size);
1188  if (size > max_ctx_size) {
1189  ut32 offset = 0;
1190  ut32 left = size;
1191  req.req = DbgKdSetContextEx;
1192  req.cpu = ctx->cpu;
1193  req.rz_ctx_ex.copied = size;
1194  do {
1195  const ut64 rest = RZ_MIN(left, max_ctx_size);
1196  req.rz_ctx_ex.count = rest;
1197  req.rz_ctx_ex.offset = offset;
1198  RZ_FREE(pkt);
1199  if (!winkd_send_state_manipulate_req(ctx, &req, buf + offset, rest, &pkt)) {
1200  break;
1201  }
1202  if (PKT_REQ(pkt)->rz_ctx_ex.count > left) {
1203  offset = size;
1204  break;
1205  }
1206  left -= PKT_REQ(pkt)->rz_ctx_ex.count;
1207  offset += PKT_REQ(pkt)->rz_ctx_ex.count;
1208  } while (left);
1209  size = offset;
1210  } else {
1211  req.req = DbgKdSetContextApi;
1212  req.cpu = ctx->cpu;
1213  req.rz_ctx.flags = flags;
1214  if (!winkd_send_state_manipulate_req(ctx, &req, buf, size, &pkt)) {
1215  return false;
1216  }
1217  }
1218 
1219  if (size > ctx->context_cache_size) {
1220  free(ctx->context_cache);
1221  ctx->context_cache = malloc(size);
1222  ctx->context_cache_size = size;
1223  }
1224 
1225  memcpy(ctx->context_cache, buf, size);
1226 
1227  free(pkt);
1228  return size;
1229 }
1230 
1232  kd_req_t req = { 0 };
1233  kd_packet_t *pkt = NULL;
1234 
1235  if (!ctx || !ctx->desc || !ctx->syncd) {
1236  return 0;
1237  }
1238 
1239  if (ctx->context_cache_size >= size && ctx->context_cache_valid) {
1240  memcpy(buf, ctx->context_cache, size);
1241  return size;
1242  }
1243 
1244  req.req = DbgKdGetContextApi;
1245  req.cpu = ctx->cpu;
1246 
1247  req.rz_ctx.flags = 0x1003F;
1248 
1249  if (!winkd_send_state_manipulate_req(ctx, &req, NULL, 0, &pkt)) {
1250  return 0;
1251  }
1252 
1253  kd_req_t *rr = PKT_REQ(pkt);
1254  const size_t context_rq_sz = pkt->length - sizeof(kd_req_t);
1255  memcpy(buf, rr->data, RZ_MIN(size, context_rq_sz));
1256  free(pkt);
1257 
1258  if (context_rq_sz > ctx->context_cache_size || !ctx->context_cache) {
1259  void *tmp = realloc(ctx->context_cache, context_rq_sz);
1260  if (!tmp) {
1261  free(ctx->context_cache);
1262  ctx->context_cache = NULL;
1263  ctx->context_cache_size = 0;
1264  ctx->context_cache_valid = false;
1265  return 0;
1266  }
1267  ctx->context_cache = tmp;
1268  ctx->context_cache_size = context_rq_sz;
1269  }
1270  memcpy(ctx->context_cache, rr->data, context_rq_sz);
1271  ctx->context_cache_valid = true;
1272  ctx->context_cache_valid = context_rq_sz;
1273  return context_rq_sz;
1274 }
1275 
1276 int winkd_query_mem(RZ_BORROW RZ_NONNULL KdCtx *ctx, const ut64 addr, int *address_space, int *flags) {
1277  kd_req_t req = { 0 };
1278  kd_packet_t *pkt;
1279 
1280  if (!ctx || !ctx->desc || !ctx->syncd) {
1281  return 0;
1282  }
1283 
1284  req.req = DbgKdQueryMemoryApi;
1285  req.cpu = ctx->cpu;
1286 
1287  req.rz_query_mem.addr = addr;
1288  req.rz_query_mem.address_space = 0; // Tells the kernel that 'addr' is a virtual address
1289 
1290  if (!winkd_send_state_manipulate_req(ctx, &req, NULL, 0, &pkt)) {
1291  return 0;
1292  }
1293 
1294  kd_req_t *rr = PKT_REQ(pkt);
1295 
1296  if (rr->ret) {
1297  free(pkt);
1298  return 0;
1299  }
1300 
1301  if (address_space) {
1302  *address_space = rr->rz_query_mem.address_space;
1303  }
1304  if (flags) {
1305  *flags = rr->rz_query_mem.flags;
1306  }
1307 
1308  free(pkt);
1309  return 1;
1310 }
1311 
1312 int winkd_bkpt(RZ_BORROW RZ_NONNULL KdCtx *ctx, const ut64 addr, const int set, const int hw, RZ_BORROW RZ_NONNULL int *handle) {
1313  kd_req_t req = { 0 };
1314  kd_packet_t *pkt;
1315 
1316  if (!ctx || !ctx->desc || !ctx->syncd) {
1317  return 0;
1318  }
1319 
1321  req.cpu = ctx->cpu;
1322 
1323  if (set) {
1324  req.rz_set_bp.addr = addr;
1325  } else {
1326  req.rz_del_bp.handle = *handle;
1327  }
1328 
1329  if (!winkd_send_state_manipulate_req(ctx, &req, NULL, 0, &pkt)) {
1330  return 0;
1331  }
1332 
1333  kd_req_t *rr = PKT_REQ(pkt);
1334 
1335  if (rr->ret) {
1336  free(pkt);
1337  return 0;
1338  }
1339  *handle = rr->rz_set_bp.handle;
1340  free(pkt);
1341  return 1;
1342 }
1343 
1345  kd_req_t req = {
1346  .req = type,
1347  .cpu = ctx->cpu
1348  };
1349  int ret = 0;
1350  int left = count;
1351  do {
1352  req.rz_mem.addr = offset + ret;
1353  req.rz_mem.length = RZ_MIN(left, KD_MAX_PAYLOAD - sizeof(kd_req_t));
1354  kd_packet_t *pkt;
1355  if (!winkd_send_state_manipulate_req(ctx, &req, NULL, 0, &pkt)) {
1356  return ret;
1357  }
1358 
1359  kd_req_t *rr = PKT_REQ(pkt);
1360  const int returned_bytes = RZ_MIN(rr->rz_mem.read, pkt->length - sizeof(kd_req_t));
1361  const int read_len = RZ_MIN(returned_bytes, RZ_MIN(rr->rz_mem.read, left));
1362  memcpy(buf + ret, rr->data, read_len);
1363  ret += read_len;
1364  left -= read_len;
1365  free(pkt);
1366  } while (left);
1367  return ret;
1368 }
1369 
1371  if (!ctx || !ctx->desc || !ctx->syncd) {
1372  return 0;
1373  }
1375 }
1376 
1378  if (!ctx || !ctx->desc || !ctx->syncd || count < 0) {
1379  return 0;
1380  }
1382 }
1383 
1385  kd_packet_t *pkt = NULL;
1386  kd_req_t req = { 0 };
1387 
1388  if (!ctx || !ctx->desc || !ctx->syncd) {
1389  return 0;
1390  }
1391 
1392  int payload = RZ_MIN(count, KD_MAX_PAYLOAD - sizeof(kd_req_t));
1394  req.cpu = ctx->cpu;
1395  req.rz_mem.addr = offset;
1396  req.rz_mem.length = payload;
1397 
1398  if (!winkd_send_state_manipulate_req(ctx, &req, buf, payload, &pkt)) {
1399  return 0;
1400  }
1401 
1402  kd_req_t *rr = PKT_REQ(pkt);
1403  int ret = rr->rz_mem.read;
1404  free(pkt);
1405  return ret;
1406 }
1407 
1409  kd_packet_t *pkt;
1410  kd_req_t req = { 0 };
1411 
1412  if (!ctx || !ctx->desc || !ctx->syncd) {
1413  return 0;
1414  }
1415 
1416  int payload = RZ_MIN(count, KD_MAX_PAYLOAD - sizeof(kd_req_t));
1417 
1418  memset(&req, 0, sizeof(kd_req_t));
1419 
1421  req.cpu = ctx->cpu;
1422 
1423  req.rz_mem.addr = offset;
1424  req.rz_mem.length = payload;
1425  req.rz_mem.read = 0; // Default caching option
1426 
1427  if (!winkd_send_state_manipulate_req(ctx, &req, buf, payload, &pkt)) {
1428  return 0;
1429  }
1430 
1431  kd_req_t *rr = PKT_REQ(pkt);
1432 
1433  if (rr->ret) {
1434  free(pkt);
1435  return 0;
1436  }
1437  int ret = rr->rz_mem.read;
1438  free(pkt);
1439  return ret;
1440 }
1441 
1442 void winkd_break(void *arg) {
1443  // This command shouldn't be wrapped by locks since it can always be sent and we don't
1444  // want break queued up after another background task
1445  KdCtx *ctx = (KdCtx *)arg;
1446  ctx->breaked = true;
1447  (void)iob_write(ctx->desc, (const ut8 *)"b", 1);
1448 }
#define mask()
static ut32 cpu[32]
Definition: analysis_or1k.c:21
#define PFMT32x
lzma_index ** i
Definition: index.h:629
static int buf_len
Definition: asm_arc.c:22
static mcore_handle handle
Definition: asm_mcore.c:8
static RzList * maps(RzBinFile *bf)
Definition: bin_bf.c:116
const char * desc
Definition: bin_vsf.c:19
int bits(struct state *s, int need)
Definition: blast.c:72
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
RZ_API void rz_cons_break_pop(void)
Definition: cons.c:361
RZ_API void rz_cons_break_push(RzConsBreak cb, void *user)
Definition: cons.c:357
RZ_API bool rz_cons_is_breaked(void)
Definition: cons.c:373
#define NULL
Definition: cris-opc.c:27
int mod(int a, int b)
Definition: crypto_rot.c:8
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 static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec req
Definition: sflib.h:128
static static fork write
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
static bool is_target_kernel(DbgEngContext *idbg)
Definition: debug_windbg.c:47
uint16_t ut16
uint32_t ut32
static RzBuffer * build(RzEgg *egg)
Definition: egg_bind.c:144
size_t map(int syms, int left, int len)
Definition: enough.c:237
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
int kd_send_ctrl_packet(io_desc_t *desc, const ut32 type, const ut32 id)
Definition: kd.c:25
int kd_send_data_packet(io_desc_t *desc, const ut32 type, const ut32 id, const ut8 *req, const int req_len, const ut8 *buf, const ut32 buf_len)
Definition: kd.c:41
int kd_read_packet(io_desc_t *desc, kd_packet_t **p)
Definition: kd.c:80
#define KD_RET_ENOENT
Definition: kd.h:108
#define KD_MACH_I386
Definition: kd.h:110
#define KD_MACH_AMD64
Definition: kd.h:112
@ KD_E_BREAK
Definition: kd.h:15
@ KD_E_IOERR
Definition: kd.h:14
@ KD_E_OK
Definition: kd.h:10
@ KD_E_MALFORMED
Definition: kd.h:13
@ KD_E_TIMEOUT
Definition: kd.h:12
#define KD_MAX_PAYLOAD
Definition: kd.h:102
KD_PACKET_MANIPULATE_TYPE
Definition: kd.h:41
@ DbgKdContinueApi
Definition: kd.h:49
@ DbgKdWritePhysicalMemoryApi
Definition: kd.h:57
@ DbgKdWriteVirtualMemoryApi
Definition: kd.h:44
@ DbgKdSetContextEx
Definition: kd.h:85
@ DbgKdReadPhysicalMemoryApi
Definition: kd.h:56
@ DbgKdGetContextApi
Definition: kd.h:45
@ DbgKdReadVirtualMemoryApi
Definition: kd.h:43
@ DbgKdWriteBreakPointApi
Definition: kd.h:47
@ DbgKdQueryMemoryApi
Definition: kd.h:81
@ DbgKdSetContextApi
Definition: kd.h:46
@ DbgKdRestoreBreakPointApi
Definition: kd.h:48
#define KD_PACKET_DATA
Definition: kd.h:97
@ DbgKdCommandStringStateChange
Definition: kd.h:37
@ DbgKdLoadSymbolsStateChange
Definition: kd.h:36
@ DbgKdExceptionStateChange
Definition: kd.h:35
@ KD_PACKET_TYPE_STATE_MANIPULATE
Definition: kd.h:21
@ KD_PACKET_TYPE_STATE_CHANGE64
Definition: kd.h:26
@ KD_PACKET_TYPE_RESEND
Definition: kd.h:24
@ KD_PACKET_TYPE_UNUSED
Definition: kd.h:19
@ KD_PACKET_TYPE_ACKNOWLEDGE
Definition: kd.h:23
@ KD_PACKET_TYPE_FILE_IO
Definition: kd.h:30
@ KD_PACKET_TYPE_RESET
Definition: kd.h:25
#define KD_INITIAL_PACKET_ID
Definition: kd.h:100
#define DBGKD_VERS_FLAG_PTR64
Definition: kd.h:117
#define KD_PACKET_CTRL
Definition: kd.h:98
#define DBGKD_VERS_FLAG_DATA
Definition: kd.h:116
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))
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API bool rz_list_join(RZ_NONNULL RzList *list1, RZ_NONNULL RzList *list2)
Joins 2 list into one (list2 pointer needs to be freed by the user)
Definition: list.c:209
RZ_API RZ_BORROW void * rz_list_first(RZ_NONNULL const RzList *list)
Returns the first element of the list.
Definition: list.c:77
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
RZ_API RZ_BORROW RzListIter * rz_list_add_sorted(RZ_NONNULL RzList *list, void *data, RZ_NONNULL RzListComparator cmp)
Adds an element to a sorted list via the RzListComparator.
Definition: list.c:518
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
void * malloc(size_t size)
Definition: malloc.c:123
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")
int type
Definition: mipsasm.c:17
static Profile * p_table[]
Definition: profiles.h:201
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
static ut32 rz_read_le32(const void *src)
Definition: rz_endian.h:239
#define RZ_LOG_VERBOSE(fmtstr,...)
Definition: rz_log.h:52
#define RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_DEBUG(fmtstr,...)
Definition: rz_log.h:49
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API int rz_str_utf16_to_utf8(ut8 *dst, int len_dst, const ut8 *src, int len_src, bool little_endian)
Definition: str.c:2884
RZ_API bool rz_str_endswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string ends with a specifc sequence of characters (case sensitive)
Definition: str.c:3329
RZ_API char RZ_API void rz_sys_backtrace(void)
Print the backtrace at the point this function is called from.
Definition: sys.c:265
@ RZ_SYS_BITS_32
Definition: rz_sys.h:20
@ RZ_SYS_BITS_64
Definition: rz_sys.h:21
#define RZ_IN
Definition: rz_types.h:50
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_OUT
Definition: rz_types.h:51
#define RZ_NONNULL
Definition: rz_types.h:64
#define RZ_PERM_RWX
Definition: rz_types.h:98
#define rz_offsetof(type, member)
Definition: rz_types.h:360
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define RZ_BORROW
Definition: rz_types.h:63
#define RZ_MIN(x, y)
#define UT64_MAX
Definition: rz_types_base.h:86
#define UT64_ADD_OVFCHK(x, y)
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
const char * name
Definition: spp.h:129
Definition: winkd.h:68
Definition: winkd.h:35
Definition: winkd.h:11
ut64 entrypoint
Definition: winkd.h:25
ut64 ethread
Definition: winkd.h:24
bool runnable
Definition: winkd.h:22
char status
Definition: winkd.h:23
ut32 uniqueid
Definition: winkd.h:21
Definition: winkd.h:95
Definition: winkd.h:79
Definition: kd.h:227
ut32 ret
Definition: kd.h:229
ut32 req
Definition: kd.h:228
struct Proc * proc
RZ_API void rz_th_lock_leave(RZ_NONNULL RzThreadLock *thl)
Releases a RzThreadLock structure.
Definition: thread_lock.c:75
RZ_API void rz_th_lock_free(RZ_NULLABLE RzThreadLock *thl)
Frees a RzThreadLock structure.
Definition: thread_lock.c:89
RZ_API RZ_OWN RzThreadLock * rz_th_lock_new(bool recursive)
Allocates and initialize a RzThreadLock structure.
Definition: thread_lock.c:14
RZ_API bool rz_th_lock_tryenter(RZ_NONNULL RzThreadLock *thl)
Tries to acquire a RzThreadLock structure.
Definition: thread_lock.c:61
int iob_write(io_desc_t *desc, const uint8_t *buf, const uint32_t buf_len)
Definition: transport.c:16
#define KD_IO_PIPE
Definition: transport.h:17
#define KD_IO_NET
Definition: transport.h:18
void error(const char *msg)
Definition: untgz.c:593
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
int map_comparator(const void *m1, const void *m2)
Definition: winkd.c:604
bool winkd_va_to_pa(RZ_BORROW RZ_NONNULL WindCtx *ctx, ut64 directory_table, ut64 va, RZ_BORROW RZ_NONNULL RZ_OUT ut64 *pa)
Definition: winkd.c:860
int winkd_write_at_uva(RZ_BORROW RZ_NONNULL WindCtx *ctx, ut64 address, RZ_BORROW RZ_NONNULL RZ_IN const ut8 *buf, int count)
Definition: winkd.c:600
static int do_io_reply(RZ_BORROW RZ_NONNULL KdCtx *ctx, kd_packet_t *pkt)
Definition: winkd.c:225
ut64 winkd_get_target_base(RZ_BORROW RZ_NONNULL WindCtx *ctx)
Definition: winkd.c:166
int winkd_write_at(RZ_BORROW RZ_NONNULL KdCtx *ctx, const ut64 offset, RZ_BORROW RZ_NONNULL RZ_IN const ut8 *buf, const int count)
Definition: winkd.c:1384
bool winkd_read_ver(RZ_BORROW RZ_NONNULL KdCtx *ctx)
Definition: winkd.c:997
ut32 winkd_get_target(RZ_BORROW RZ_NONNULL WindCtx *ctx)
Definition: winkd.c:158
WindThread * winkd_get_thread_at(RZ_BORROW RZ_NONNULL WindCtx *ctx, ut64 address)
Definition: winkd.c:739
bool winkd_lock_leave(RZ_BORROW RZ_NONNULL KdCtx *ctx)
Definition: winkd.c:34
#define PKT_REQ(p)
Definition: winkd.c:202
int winkd_write_at_phys(RZ_BORROW RZ_NONNULL KdCtx *ctx, const ut64 offset, RZ_BORROW RZ_NONNULL RZ_IN const ut8 *buf, const int count)
Definition: winkd.c:1408
#define KOBJECT_PROCESS
Definition: winkd.c:20
static bool load_symbol_path_is_valid(kd_packet_t *pkt)
Definition: winkd.c:252
int winkd_read_at(RZ_BORROW RZ_NONNULL KdCtx *ctx, const ut64 offset, RZ_BORROW RZ_NONNULL RZ_OUT ut8 *buf, const int count)
Definition: winkd.c:1377
Profile * winkd_get_profile(int bits, int build, int sp)
Definition: winkd.c:58
#define O_(n)
Definition: winkd.c:17
static bool winkd_send_state_manipulate_req(RZ_BORROW RZ_NONNULL KdCtx *ctx, kd_req_t *req, RZ_BORROW RZ_NULLABLE RZ_IN const ut8 *buf, const ut32 buf_len, RZ_BORROW RZ_NULLABLE RZ_OUT kd_packet_t **pkt)
Definition: winkd.c:940
#define PTE_LARGEPAGE
Definition: winkd.c:846
#define PKT_STC(p)
Definition: winkd.c:203
#define KOBJECT_THREAD
Definition: winkd.c:21
RzList * winkd_list_threads(RZ_BORROW RZ_NONNULL WindCtx *ctx)
Definition: winkd.c:782
void winkd_break(void *arg)
Definition: winkd.c:1442
int winkd_wait_packet(RZ_BORROW RZ_NONNULL KdCtx *ctx, const ut32 type, RZ_NULLABLE RZ_OUT kd_packet_t **p)
Definition: winkd.c:258
int winkd_get_cpus(RZ_BORROW RZ_NONNULL KdCtx *ctx)
Definition: winkd.c:84
#define PTE_PROTOTYPE
Definition: winkd.c:847
void winkd_kdctx_free(RZ_OWN KdCtx **ctx)
Definition: winkd.c:187
int winkd_get_cpu(RZ_BORROW RZ_NONNULL KdCtx *ctx)
Definition: winkd.c:99
int winkd_read_reg(RZ_BORROW RZ_NONNULL KdCtx *ctx, RZ_BORROW RZ_NONNULL RZ_OUT ut8 *buf, int size)
Definition: winkd.c:1231
RzList * winkd_list_maps(RZ_BORROW RZ_NONNULL WindCtx *ctx)
Definition: winkd.c:476
int winkd_get_sp(RZ_BORROW RZ_NONNULL WindCtx *ctx)
Definition: winkd.c:40
bool winkd_write_reg(RZ_BORROW RZ_NONNULL KdCtx *ctx, ut32 flags, RZ_BORROW RZ_NONNULL RZ_IN const ut8 *buf, int size)
Definition: winkd.c:1179
int winkd_read_at_uva(RZ_BORROW RZ_NONNULL WindCtx *ctx, ut64 address, RZ_BORROW RZ_NONNULL RZ_OUT ut8 *buf, int count)
Definition: winkd.c:596
void winkd_windmodule_free(void *ptr)
Definition: winkd.c:611
ut32 winkd_get_target_thread(RZ_BORROW RZ_NONNULL WindCtx *ctx)
Definition: winkd.c:162
RzList * winkd_list_modules(RZ_BORROW RZ_NONNULL WindCtx *ctx)
Definition: winkd.c:625
static int read_at_uva_or_kernel(RZ_BORROW RZ_NONNULL WindCtx *ctx, ut64 address, ut8 *buf, int count)
Definition: winkd.c:617
bool winkd_set_cpu(RZ_BORROW RZ_NONNULL KdCtx *ctx, int cpu)
Definition: winkd.c:91
int winkd_read_at_phys(RZ_BORROW RZ_NONNULL KdCtx *ctx, const ut64 offset, RZ_BORROW RZ_NONNULL RZ_OUT ut8 *buf, const int count)
Definition: winkd.c:1370
#define ARM_DESCRIPTOR
Definition: winkd.c:848
int winkd_op_at_uva(RZ_BORROW RZ_NONNULL WindCtx *ctx, ut64 address, ut8 *buf, int count, bool write)
Definition: winkd.c:567
int winkd_continue(RZ_BORROW RZ_NONNULL KdCtx *ctx, bool handled)
Definition: winkd.c:1141
static int read_at(RZ_BORROW RZ_NONNULL KdCtx *ctx, enum KD_PACKET_MANIPULATE_TYPE type, ut8 *buf, const ut64 offset, const int count)
Definition: winkd.c:1344
bool winkd_set_target(RZ_BORROW RZ_NONNULL WindCtx *ctx, ut32 pid, ut32 tid)
Definition: winkd.c:106
#define PKT_IO(p)
Definition: winkd.c:204
void winkd_walk_vadtree(RZ_BORROW RZ_NONNULL WindCtx *ctx, ut64 address, ut64 parent, RzList *out)
Definition: winkd.c:390
#define PTE_VALID
Definition: winkd.c:845
KdCtx * winkd_kdctx_new(RZ_BORROW RZ_NONNULL io_desc_t *desc)
Definition: winkd.c:177
bool winkd_lock_enter(RZ_BORROW RZ_NONNULL KdCtx *ctx)
Definition: winkd.c:23
int winkd_sync(RZ_BORROW RZ_NONNULL KdCtx *ctx)
Definition: winkd.c:1065
int winkd_query_mem(RZ_BORROW RZ_NONNULL KdCtx *ctx, const ut64 addr, int *address_space, int *flags)
Definition: winkd.c:1276
static bool is_page_large(RZ_BORROW RZ_NONNULL WindCtx *ctx, ut64 page_descriptor)
Definition: winkd.c:850
WindProc * winkd_get_process_at(RZ_BORROW RZ_NONNULL WindCtx *ctx, ut64 address)
Definition: winkd.c:488
int winkd_bkpt(RZ_BORROW RZ_NONNULL KdCtx *ctx, const ut64 addr, const int set, const int hw, RZ_BORROW RZ_NONNULL int *handle)
Definition: winkd.c:1312
RzList * winkd_list_process(RZ_BORROW RZ_NONNULL WindCtx *ctx)
Definition: winkd.c:513
int winkd_get_bits(RZ_BORROW RZ_NONNULL WindCtx *ctx)
Definition: winkd.c:80
@ K_CmNtCSDVersion
Definition: winkd.h:45
@ K_PsActiveProcessHead
Definition: winkd.h:44
@ K_PaeEnabled
Definition: winkd.h:43
@ C_UniqueThread
Definition: winkd.h:64
@ E_Peb
Definition: winkd.h:52
@ E_UniqueProcessId
Definition: winkd.h:51
@ ET_Win32StartAddress
Definition: winkd.h:62
@ E_ActiveProcessLinks
Definition: winkd.h:50
@ K_DirectoryTableBase
Definition: winkd.h:56
@ ET_Cid
Definition: winkd.h:63
@ E_VadRoot
Definition: winkd.h:54
@ E_ImageFileName
Definition: winkd.h:53
@ ET_ThreadListEntry
Definition: winkd.h:61
@ E_ThreadListHead
Definition: winkd.h:55
@ P_ImageBaseAddress
Definition: winkd.h:57
static void winkd_ctx_fini(RZ_BORROW RZ_NONNULL WindCtx *ctx)
Definition: winkd.h:141
static ut64 winkd_read_ptr_at(RZ_BORROW RZ_NONNULL WindCtx *ctx, RZ_BORROW RZ_NONNULL WindReadAt *read_at_func, ut64 at)
Definition: winkd.h:133
static int sp
Definition: z80asm.c:91
static int addr
Definition: z80asm.c:58