1 /* radare - LGPL - Copyright 2009-2020 - pancake */
2 
3 #include <r_core.h>
4 #include <r_debug.h>
5 #include <sdb.h>
6 #define TN_KEY_LEN 32
7 #define TN_KEY_FMT "%"PFMT64u
8 #ifndef SIGKILL
9 #define SIGKILL 9
10 #endif
11 
12 #if __linux__ && __GNU_LIBRARY__ && __GLIBC__ && __GLIBC_MINOR__
13 #include "r_heap_glibc.h"
14 #endif
15 
16 #if HAVE_JEMALLOC
17 #include "r_heap_jemalloc.h"
18 #include "linux_heap_jemalloc.c"
19 #endif
20 
21 void cmd_anal_reg (RCore *core, const char *str);
22 
23 static const char *help_msg_d[] = {
24 	"Usage:", "d", " # Debug commands",
25 	"db", "[?]", "Breakpoints commands",
26 	"dbt", "[?]", "Display backtrace based on dbg.btdepth and dbg.btalgo",
27 	"dc", "[?]", "Continue execution",
28 	"dd", "[?]", "File descriptors (!fd in r1)",
29 	"de", "[-sc] [perm] [rm] [e]", "Debug with ESIL (see de?)",
30 	"dg", " <file>", "Generate a core-file (WIP)",
31 	"dH", " [handler]", "Transplant process to a new handler",
32 	"di", "[?]", "Show debugger backend information (See dh)",
33 	"dk", "[?]", "List, send, get, set, signal handlers of child",
34 	"dL", "[?]", "List or set debugger handler",
35 	"dm", "[?]", "Show memory maps",
36 	"do", "[?]", "Open process (reload, alias for 'oo')",
37 	"doo", "[args]", "Reopen in debug mode with args (alias for 'ood')",
38 	"doof", "[file]", "Reopen in debug mode from file (alias for 'oodf')",
39 	"doc", "", "Close debug session",
40 	"dp", "[?]", "List, attach to process or thread id",
41 	"dr", "[?]", "Cpu registers",
42 	"ds", "[?]", "Step, over, source line",
43 	"dt", "[?]", "Display instruction traces",
44 	"dw", " <pid>", "Block prompt until pid dies",
45 #if __WINDOWS__
46 	"dW", "", "List process windows",
47 	"dWi", "", "Identify window under cursor",
48 #endif
49 	"dx", "[?]", "Inject and run code on target process (See gs)",
50 	NULL
51 };
52 
53 static const char *help_msg_db[] = {
54 	"Usage: db", "", " # Breakpoints commands",
55 	"db", "", "List breakpoints",
56 	"db*", "", "List breakpoints in r commands",
57 	"db", " sym.main", "Add breakpoint into sym.main",
58 	"db", " <addr>", "Add breakpoint",
59 	"dbH", " <addr>", "Add hardware breakpoint",
60 	"db-", " <addr>", "Remove breakpoint",
61 	"db-*", "", "Remove all the breakpoints",
62 	"db.", "", "Show breakpoint info in current offset",
63 	"dbj", "", "List breakpoints in JSON format",
64 	// "dbi", " 0x848 ecx=3", "stop execution when condition matches",
65 	"dbc", " <addr> <cmd>", "Run command when breakpoint is hit",
66 	"dbC", " <addr> <cmd>", "Run command but continue until <cmd> returns zero",
67 	"dbd", " <addr>", "Disable breakpoint",
68 	"dbe", " <addr>", "Enable breakpoint",
69 	"dbs", " <addr>", "Toggle breakpoint",
70 	"dbf", "", "Put a breakpoint into every no-return function",
71 	//
72 	"dbm", " <module> <offset>", "Add a breakpoint at an offset from a module's base",
73 	"dbn", " [<name>]", "Show or set name for current breakpoint",
74 	//
75 	"dbi", "", "List breakpoint indexes",
76 	"dbi", " <addr>", "Show breakpoint index in givengiven  offset",
77 	"dbi.", "", "Show breakpoint index in current offset",
78 	"dbi-", " <idx>", "Remove breakpoint by index",
79 	"dbix", " <idx> [expr]", "Set expression for bp at given index",
80 	"dbic", " <idx> <cmd>", "Run command at breakpoint index",
81 	"dbie", " <idx>", "Enable breakpoint by index",
82 	"dbid", " <idx>", "Disable breakpoint by index",
83 	"dbis", " <idx>", "Swap Nth breakpoint",
84 	"dbite", " <idx>", "Enable breakpoint Trace by index",
85 	"dbitd", " <idx>", "Disable breakpoint Trace by index",
86 	"dbits", " <idx>", "Swap Nth breakpoint trace",
87 	//
88 	"dbh", " x86", "Set/list breakpoint plugin handlers",
89 	"dbh-", " <name>", "Remove breakpoint plugin handler",
90 	"dbt", "[?]", "Show backtrace. See dbt? for more details",
91 	"dbx", " [expr]", "Set expression for bp in current offset",
92 	"dbw", " <addr> <r/w/rw>", "Add watchpoint",
93 #if __WINDOWS__
94 	"dbW", " <WM_DEFINE> [?|handle|name]", "Set cond. breakpoint on a window message handler",
95 #endif
96 	"drx", " number addr len perm", "Modify hardware breakpoint",
97 	"drx-", "number", "Clear hardware breakpoint",
98 	NULL
99 };
100 
101 static const char *help_msg_dbt[] = {
102 	"Usage: dbt", "", " # Backtrace commands",
103 	"dbt", "", "Display backtrace based on dbg.btdepth and dbg.btalgo",
104 	"dbt*", "", "Display backtrace in flags",
105 	"dbt=", "", "Display backtrace in one line (see dbt=s and dbt=b for sp or bp)",
106 	"dbtv", "", "Display backtrace with local vars if any",
107 	"dbtj", "", "Display backtrace in JSON",
108 	"dbta", "", "Display ascii-art representation of the stack backtrace",
109 	"dbte", " <addr>", "Enable Breakpoint Trace",
110 	"dbtd", " <addr>", "Disable Breakpoint Trace",
111 	"dbts", " <addr>", "Swap Breakpoint Trace",
112 	NULL
113 };
114 
115 static const char *help_msg_dbw[] = {
116 	"Usage: dbw", "<addr> <r/w/rw>"," # Add watchpoint",
117 	NULL
118 };
119 
120 static const char *help_msg_dc[] = {
121 	"Usage: dc", "", "Execution continuation commands",
122 	"dc", "", "Continue execution of all children",
123 	"dc", " <pid>", "Continue execution of pid",
124 	"dc", "[-pid]", "Stop execution of pid",
125 	"dca", " [sym] [sym].", "Continue at every hit on any given symbol",
126 	"dcb", "", "Continue back until breakpoint",
127 	"dcc", "", "Continue until call (use step into)",
128 	"dccu", "", "Continue until unknown call (call reg)",
129 #if __WINDOWS__
130 	"dce", "", "Continue execution (pass exception to program)",
131 #endif
132 	"dcf", "", "Continue until fork (TODO)",
133 	"dck", " <signal> <pid>", "Continue sending signal to process",
134 	"dcp", "", "Continue until program code (mapped io section)",
135 	"dcr", "", "Continue until ret (uses step over)",
136 	"dcs", "[?] <num>", "Continue until syscall",
137 	"dct", " <len>", "Traptrace from curseek to len, no argument to list",
138 	"dcu", "[?] [..end|addr] ([end])", "Continue until address (or range)",
139 	/*"TODO: dcu/dcr needs dbg.untilover=true??",*/
140 	/*"TODO: same for only user/libs side, to avoid steping into libs",*/
141 	/*"TODO: support for threads?",*/
142 	NULL
143 };
144 
145 static const char *help_msg_dcs[] = {
146 	"Usage:", "dcs", " Continue until syscall",
147 	"dcs", "", "Continue until next syscall",
148 	"dcs [str]", "", "Continue until next call to the 'str' syscall",
149 	"dcs", "*", "Trace all syscalls, a la strace",
150 	NULL
151 };
152 
153 static const char *help_msg_dcu[] = {
154 	"Usage:", "dcu", " Continue until address",
155 	"dcu.", "", "Alias for dcu $$ (continue until current address",
156 	"dcu", " address", "Continue until address",
157 	"dcu", " [..tail]", "Continue until the range",
158 	"dcu", " [from] [to]", "Continue until the range",
159 	NULL
160 };
161 
162 static const char *help_msg_dd[] = {
163 	"Usage: dd", "", "Descriptors commands",
164 	"dd", "", "List file descriptors",
165 	"dd", " <file>", "Open and map that file into the UI",
166 	"dd-", "<fd>", "Close stdout fd",
167 	"dd*", "", "List file descriptors (in radare commands)",
168 	"dds", " <fd> <off>", "Seek given fd)",
169 	"ddd", " <fd1> <fd2>", "Dup2 from fd1 to fd2",
170 	"ddr", " <fd> <size>", "Read N bytes from fd",
171 	"ddw", " <fd> <hexpairs>", "Write N bytes to fd",
172 	NULL
173 };
174 
175 static const char *help_msg_de[] = {
176 	"Usage:", "de", "[-sc] [perm] [rm] [expr]",
177 	"de", "", "List esil watchpoints",
178 	"de-*", "", "Delete all esil watchpoints",
179 	"de", " [perm] [rm] [addr|reg|from..to]", "Stop on condition",
180 	"dec", "", "Continue execution until matching expression",
181 	"des", "[?] [N]", "Step-in N instructions with esildebug",
182 	"desu", " [addr]", "Esildebug until specific address",
183 	NULL
184 };
185 
186 static const char *help_msg_des[] = {
187 	"Usage:", "des", "[u] [arg]",
188 	"des", " [N]", "step-in N instructions with esildebug",
189 	"desu", " [addr]", "esildebug until specific address",
190 	NULL
191 };
192 
193 static const char *help_msg_di[] = {
194 	"Usage: di", "", "Debugger target information",
195 	"di", "", "Show debugger target information",
196 	"di*", "", "Same as above, but in r2 commands",
197 	"diq", "", "Same as above, but in one line",
198 	"dij", "", "Same as above, but in JSON format",
199 	"dif", " [$a] [$b]", "Compare two files (or $alias files)",
200 	NULL
201 };
202 
203 static const char *help_msg_dk[] = {
204 	"Usage: dk", "", "Signal commands",
205 	"dk", "", "List all signal handlers of child process",
206 	"dk", " <signal>", "Send KILL signal to child",
207 	"dk", " <signal>=1", "Set signal handler for <signal> in child",
208 	"dk?", "<signal>", "Name/signum resolver",
209 	"dko", "[?] <signal>", "Reset skip or cont options for given signal",
210 	"dko", " <signal> [|skip|cont]", "On signal SKIP handler or CONT into",
211 	"dkj", "", "List all signal handlers in JSON",
212 	NULL
213 };
214 
215 static const char *help_msg_dko[] = {
216 	"Usage:", "dko", " # Signal handling commands",
217 	"dko", "", "List existing signal handling",
218 	"dko", " [signal]", "Clear handling for a signal",
219 	"dko", " [signal] [skip|cont]", "Set handling for a signal",
220 	NULL
221 };
222 
223 static const char *help_msg_dm[] = {
224 	"Usage:", "dm", " # Memory maps commands",
225 	"dm", "", "List memory maps of target process",
226 	"dm", " address size", "Allocate <size> bytes at <address> (anywhere if address is -1) in child process",
227 	"dm=", "", "List memory maps of target process (ascii-art bars)",
228 	"dm.", "", "Show map name of current address",
229 	"dm*", "", "List memmaps in radare commands",
230 	"dm-", " address", "Deallocate memory map of <address>",
231 	"dmd", "[a] [file]", "Dump current (all) debug map region to a file (from-to.dmp) (see Sd)",
232 	"dmh", "[?]", "Show map of heap",
233 	"dmi", " [addr|libname] [symname]", "List symbols of target lib",
234 	"dmi*", " [addr|libname] [symname]", "List symbols of target lib in radare commands",
235 	"dmi.", "", "List closest symbol to the current address",
236 	"dmiv", "", "Show address of given symbol for given lib",
237 	"dmj", "", "List memmaps in JSON format",
238 	"dml", " <file>", "Load contents of file into the current map region",
239 	"dmm", "[?][j*]", "List modules (libraries, binaries loaded in memory)",
240 	"dmp", "[?] <address> <size> <perms>", "Change page at <address> with <size>, protection <perms> (perm)",
241 	"dms", "[?] <id> <mapaddr>", "Take memory snapshot",
242 	"dms-", " <id> <mapaddr>", "Restore memory snapshot",
243 	"dmS", " [addr|libname] [sectname]", "List sections of target lib",
244 	"dmS*", " [addr|libname] [sectname]", "List sections of target lib in radare commands",
245 	"dmL", " address size", "Allocate <size> bytes at <address> and promote to huge page",
246 	//"dm, " rw- esp 9K", "set 9KB of the stack as read+write (no exec)",
247 	"TODO:", "", "map files in process memory. (dmf file @ [addr])",
248 	NULL
249 };
250 
251 static const char *help_msg_dmi[] = {
252 	"Usage: dmi", "", " # List/Load Symbols",
253 	"dmi", "[j|q|*] [libname] [symname]", "List symbols of target lib",
254 	"dmia", "[j|q|*] [libname]", "List all info of target lib",
255 	"dmi*", "", "List symbols of target lib in radare commands",
256 	"dmi.", "", "List closest symbol to the current address",
257 	"dmiv", "", "Show address of given symbol for given lib",
258 	NULL
259 };
260 
261 static const char *help_msg_dmm[] = {
262 	"Usage:", "dmm", " # Module memory maps commands",
263 	"dmm", "", "List modules of target process",
264 	"dmm*", "", "List modules of target process (r2 commands)",
265 	"dmm.", "", "List memory map of current module",
266 	"dmmj", "", "List modules of target process (JSON)",
267 	NULL
268 };
269 
270 static const char *help_msg_dmp[] = {
271 	"Usage:", "dmp", " Change page permissions",
272 	"dmp", " [addr] [size] [perms]", "Change permissions",
273 	"dmp", " [perms]", "Change dbg.map permissions",
274 	NULL
275 };
276 
277 static const char *help_msg_do[] = {
278 	"Usage:", "do", " # Debug (re)open commands",
279 	"do", "", "Open process (reload, alias for 'oo')",
280 	"dor", " [rarun2]", "Comma separated list of k=v rarun2 profile options (e dbg.profile)",
281 	"doe", "", "Show rarun2 startup profile",
282 	"doe!", "", "Edit rarun2 startup profile with $EDITOR",
283 	"doo", " [args]", "Reopen in debug mode with args (alias for 'ood')",
284 	"doof", " [args]", "Reopen in debug mode from file (alias for 'oodf')",
285 	"doc", "", "Close debug session",
286 	NULL
287 };
288 
289 static const char *help_msg_dp[] = {
290 	"Usage:", "dp", " # Process commands",
291 	"dp", "", "List current pid and children",
292 	"dp", " <pid>", "List children of pid",
293 	"dpj", " <pid>", "List children of pid in JSON format",
294 	"dpl", "", "List all attachable pids",
295 	"dplj", "", "List all attachable pids in JSON format",
296 	"dp-", " <pid>", "Detach select pid",
297 	"dp=", "<pid>", "Select pid",
298 	"dpa", " <pid>", "Attach and select pid",
299 	"dpc", "", "Select forked pid (see dbg.forks)",
300 	"dpc*", "", "Display forked pid (see dbg.forks)",
301 	"dpe", "", "Show path to executable",
302 	"dpf", "", "Attach to pid like file fd // HACK",
303 	"dpk", " <pid> [<signal>]", "Send signal to process (default 0)",
304 	"dpn", "", "Create new process (fork)",
305 	"dptn", "", "Create new thread (clone)",
306 	"dpt", "", "List threads of current pid",
307 	"dptj", "", "List threads of current pid in JSON format",
308 	"dpt", " <pid>", "List threads of process",
309 	"dptj", " <pid>", "List threads of process in JSON format",
310 	"dpt=", "<thread>", "Attach to thread",
311 	NULL
312 };
313 
314 static const char *help_msg_dr[] = {
315 	"Usage: dr", "", "Registers commands",
316 	"dr", "", "Show 'gpr' registers",
317 	"dr", " <register>=<val>", "Set register value",
318 	"dr.", " >$snapshot", "Capture current register values in r2 alias file",
319 	"dr,", " [table-query]", "Enumerate registers in table format",
320 	"dr8", "[1|2|4|8] [type]", "Display hexdump of gpr arena (WIP)",
321 	"dr=", "", "Show registers in columns",
322 	"dr?", "<register>", "Show value of given register",
323 	"dr??", "", "Same as dr?`drp~=[0]+` # list all reg roles alias names and values",
324 	"dra", "[?]", "Manage register arenas. see ara?",
325 	"drb", "[1|2|4|8] [type]", "Display hexdump of gpr arena (WIP)",
326 	"drc", " [name]", "Related to conditional flag registers",
327 	"drC", " [register]", "Show register comments",
328 	"drd", "", "Show only different registers",
329 	"drf", "", "Show fpu registers (80 bit long double)",
330 	"dri", "", "Show inverse registers dump (sorted by value)",
331 	"drl", "[j]", "List all register names",
332 	"drm", "[?]", "Show multimedia packed registers",
333 	//	"drm", " xmm0 0 32 = 12", "Set the first 32 bit word of the xmm0 reg to 12", // Do not advertise - broken
334 	"dro", "", "Show previous (old) values of registers",
335 	"drp", "[?] ", "Display current register profile",
336 	"drr", "", "Show registers references (telescoping)",
337 	"drrj", "", "Show registers references (telescoping) in JSON format",
338 	// TODO: 'drs' to swap register arenas and display old register valuez
339 	"drs", "[?]", "Stack register states",
340 	"drS", "", "Show the size of the register profile",
341 	"drt", "[?]", "Show all register types",
342 	"drw"," <hexnum>", "Set contents of the register arena",
343 	"drx", "[?]", "Show debug registers",
344 	".dr", "*", "Include common register values in flags",
345 	".dr", "-", "Unflag all registers",
346 	NULL
347 };
348 
349 static const char *help_msg_drp[] = {
350 	"Usage:", "drp", " # Register profile commands",
351 	"drp", "", "Show the current register profile",
352 	"drp", " [regprofile-file]", "Set the current register profile",
353 	"drp", " [gdb] [regprofile-file]", "Parse gdb register profile and dump an r2 profile string",
354 	"drpc", "", "Show register profile comments",
355 	"drpi", "", "Show internal representation of the register profile",
356 	"drp.", "", "Show the current fake size",
357 	"drpj", "", "Show the current register profile (JSON)",
358 	"drps", " [new fake size]", "Set the fake size",
359 	NULL
360 };
361 
362 static const char *help_msg_drs[] = {
363 	"Usage:", "drs", "register states commands",
364 	"drs", "", "list register stack",
365 	"drs", "+", "push register state",
366 	"drs", "-", "pop register state",
367 	NULL
368 };
369 
370 static const char *help_msg_drt[] = {
371 	"Usage:", "drt", " [type] [size]    # debug register types",
372 	"drt", "", "List all available register types",
373 	"drt", " [size]", "Show all regs in the profile of size",
374 	"drt", " 16", "Show 16 bit registers",
375 	"drt", " [type]", "Show all regs in the profile of this type",
376 	"drt", " all", "Show all registers",
377 	"drt", " fpu", "Show fpu registers",
378 	"drt", " [type] [size]", "Same as above for type and size",
379 	"drt", " [type] [size]", "Same as above for type and size",
380 	"drt*", "", "List flags in r commands",
381 	NULL
382 };
383 
384 static const char *help_msg_drx[] = {
385 	"Usage: drx", "", "Hardware breakpoints commands",
386 	"drx", "", "List all (x86?) hardware breakpoints",
387 	"drx", " <number> <address> <length> <perms>", "Modify hardware breakpoint",
388 	"drx-", "<number>", "Clear hardware breakpoint",
389 	NULL
390 };
391 
392 
393 static const char *help_msg_drm[] = {
394 	"Usage: drm", " [reg] [idx] [wordsize] [= value]", "Show multimedia packed registers",
395 	"drm", "", "Show XMM registers",
396 	"drm", " xmm0", "Show all packings of xmm0",
397 	"drm", " xmm0 0 32 = 12", "Set the first 32 bit word of the xmm0 reg to 12",
398 	"drmb", " [reg]", "Show registers as bytes",
399 	"drmw", " [reg]", "Show registers as words",
400 	"drmd", " [reg]", "Show registers as doublewords",
401 	"drmq", " [reg]", "Show registers as quadwords",
402 	"drmq", " xmm0~[0]", "Show first quadword of xmm0",
403 	"drmf", " [reg]", "Show registers as 32-bit floating point",
404 	"drml", " [reg]", "Show registers as 64-bit floating point",
405 	"drmyb", " [reg]", "Show YMM registers as bytes",
406 	"drmyw", " [reg]", "Show YMM registers as words",
407 	"drmyd", " [reg]", "Show YMM registers as doublewords",
408 	"drmyq", " [reg]", "Show YMM registers as quadwords",
409 	"drmq", " ymm0~[3]", "Show fourth quadword of ymm0",
410 	"drmyf", " [reg]", "Show YMM registers as 32-bit floating point",
411 	"drmyl", " [reg]", "Show YMM registers as 64-bit floating point",
412 	NULL
413 };
414 
415 static const char *help_msg_ds[] = {
416 	"Usage: ds", "", "Step commands",
417 	"ds", "", "Step one instruction",
418 	"ds", " <num>", "Step <num> instructions",
419 	"dsb", "", "Step back one instruction",
420 	"dsf", "", "Step until end of frame",
421 	"dsi", " <cond>", "Continue until condition matches",
422 	"dsl", "", "Step one source line",
423 	"dsl", " <num>", "Step <num> source lines",
424 	"dso", " <num>", "Step over <num> instructions",
425 	"dsp", "", "Step into program (skip libs)",
426 	"dss", " <num>", "Skip <num> step instructions",
427 	"dsu", "[?] <address>", "Step until <address>. See 'dsu?' for other step until cmds.",
428 	NULL
429 };
430 
431 static const char *help_msg_dsu[] = {
432 	"Usage: dsu", "", "Step until commands",
433 	"dsu", " <address>", "Step until <address>",
434 	"dsui", "[r] <instr>", "Step until an instruction that matches <instr>, use dsuir for regex match",
435 	"dsuo", " <optype> [<optype> ...]", "Step until an instr matches one of the <optype>s.",
436 	"dsue", " <esil>", "Step until <esil> expression matches",
437 	"dsuf", " <flag>", "Step until pc == <flag> matching name",
438 	NULL
439 };
440 
441 static const char *help_msg_dt[] = {
442 	"Usage: dt", "", "Trace commands",
443 	"dt", "", "List all traces ",
444 	"dt", " [addr]", "Show trace info at address",
445 	"dt%", "", "TODO",
446 	"dt*", "", "List all traced opcode offsets",
447 	"dt+"," [addr] [times]", "Add trace for address N times",
448 	"dt-", "", "Reset traces (instruction/calls)",
449 	"dt=", "", "Show ascii-art color bars with the debug trace ranges",
450 	"dta", " 0x804020 ...", "Only trace given addresses",
451 	"dtc[?][addr]|([from] [to] [addr])", "", "Trace call/ret",
452 	"dtd", "[qi] [nth-start]", "List all traced disassembled (quiet, instructions)",
453 	"dte", "[?]", "Show esil trace logs",
454 	"dtg", "", "Graph call/ret trace",
455 	"dtg*", "", "Graph in agn/age commands. use .dtg*;aggi for visual",
456 	"dtgi", "", "Interactive debug trace",
457 	"dts", "[?]", "Trace sessions",
458 	"dtt", " [tag]", "Select trace tag (no arg unsets)",
459 	NULL
460 };
461 
462 static const char *help_msg_dte[] = {
463 	"Usage:", "dte", " Show esil trace logs",
464 	"dte", "", "Esil trace log for a single instruction",
465 	"dte", " [idx]", "Show commands for that index log",
466 	"dte", "-*", "Delete all esil traces",
467 	"dtei", "", "Esil trace log single instruction",
468 	"dtek", " [sdb query]", "Esil trace log single instruction from sdb",
469 	NULL
470 };
471 
472 static const char *help_msg_dts[] = {
473 	"Usage:", "dts[*]", "",
474 	"dts+", "", "Start trace session",
475 	"dts-", "", "Stop trace session",
476 	"dtst", " [dir] ", "Save trace sessions to disk",
477 	"dtsf", " [dir] ", "Read trace sessions from disk",
478 	"dtsm", "", "List current memory map and hash",
479 	NULL
480 };
481 
482 static const char *help_msg_dx[] = {
483 	"Usage: dx", "", " # Code injection commands",
484 	"dx", " <opcode>...", "Inject opcodes",
485 	"dxa", " nop", "Assemble code and inject",
486 	"dxe", " egg-expr", "Compile egg expression and inject it",
487 	"dxr", " <opcode>...", "Inject opcodes and restore state",
488 	"dxs", " write 1, 0x8048, 12", "Syscall injection (see gs)",
489 	"\nExamples:", "", "",
490 	"dx", " 9090", "Inject two x86 nop",
491 	"\"dxa mov eax,6;mov ebx,0;int 0x80\"", "", "Inject and restore state",
492 	NULL
493 };
494 
495 static const char *help_msg_dL[] = {
496 	"Usage: dL", "", " # List or set debugger handler",
497 	"dL", "", "List debugger handlers",
498 	"dLq", "", "List debugger handlers in quiet mode",
499 	"dLj", "", "List debugger handlers in json mode",
500 	"dL", " <handler>", "Set debugger handler",
501 	NULL
502 };
503 
504 struct dot_trace_ght {
505 	RGraph *graph;
506 	Sdb *graphnodes;
507 };
508 
509 struct trace_node {
510 	ut64 addr;
511 	int refs;
512 };
513 
cmd_debug_init(RCore * core,RCmdDesc * parent)514 static void cmd_debug_init(RCore *core, RCmdDesc *parent) {
515 	DEFINE_CMD_DESCRIPTOR (core, d);
516 	DEFINE_CMD_DESCRIPTOR (core, db);
517 	DEFINE_CMD_DESCRIPTOR (core, dbt);
518 	DEFINE_CMD_DESCRIPTOR (core, dc);
519 	DEFINE_CMD_DESCRIPTOR (core, dcs);
520 	DEFINE_CMD_DESCRIPTOR (core, dcu);
521 	DEFINE_CMD_DESCRIPTOR (core, dd);
522 	DEFINE_CMD_DESCRIPTOR (core, de);
523 	DEFINE_CMD_DESCRIPTOR (core, des);
524 	DEFINE_CMD_DESCRIPTOR (core, di);
525 	DEFINE_CMD_DESCRIPTOR (core, dk);
526 	DEFINE_CMD_DESCRIPTOR (core, dko);
527 	DEFINE_CMD_DESCRIPTOR (core, dm);
528 	DEFINE_CMD_DESCRIPTOR (core, dmi);
529 	DEFINE_CMD_DESCRIPTOR (core, dmm);
530 	DEFINE_CMD_DESCRIPTOR (core, dmp);
531 	DEFINE_CMD_DESCRIPTOR (core, do);
532 	DEFINE_CMD_DESCRIPTOR (core, dp);
533 	DEFINE_CMD_DESCRIPTOR (core, dr);
534 	DEFINE_CMD_DESCRIPTOR (core, drp);
535 	DEFINE_CMD_DESCRIPTOR (core, drs);
536 	DEFINE_CMD_DESCRIPTOR (core, drt);
537 	DEFINE_CMD_DESCRIPTOR (core, drx);
538 	DEFINE_CMD_DESCRIPTOR (core, ds);
539 	DEFINE_CMD_DESCRIPTOR (core, dt);
540 	DEFINE_CMD_DESCRIPTOR (core, dte);
541 	DEFINE_CMD_DESCRIPTOR (core, dts);
542 	DEFINE_CMD_DESCRIPTOR (core, dx);
543 }
544 
545 // XXX those tmp files are never removed and we shuoldnt use files for this
setRarunProfileString(RCore * core,const char * str)546 static void setRarunProfileString(RCore *core, const char *str) {
547 	char *file = r_file_temp ("rarun2");
548 	char *s = strdup (str);
549 	r_config_set (core->config, "dbg.profile", file);
550 	r_str_replace_char (s, ',', '\n');
551 	r_file_dump (file, (const ut8*)s, strlen (s), 0);
552 	r_file_dump (file, (const ut8*)"\n", 1, 1);
553 	free (file);
554 }
555 
cmd_debug_cont_syscall(RCore * core,const char * _str)556 static void cmd_debug_cont_syscall (RCore *core, const char *_str) {
557 	// TODO : handle more than one stopping syscall
558 	int i, *syscalls = NULL;
559 	int count = 0;
560 	if (_str && *_str) {
561 		char *str = strdup (_str);
562 		count = r_str_word_set0 (str);
563 		syscalls = calloc (sizeof (int), count);
564 		for (i = 0; i < count; i++) {
565 			const char *sysnumstr = r_str_word_get0 (str, i);
566 			int sig = (int)r_num_math (core->num, sysnumstr);
567 			if (sig == -1) { // trace ALL syscalls
568 				syscalls[i] = -1;
569 			} else if (sig == 0) {
570 				sig = r_syscall_get_num (core->anal->syscall, sysnumstr);
571 				if (sig == -1) {
572 					eprintf ("Unknown syscall number\n");
573 					free (str);
574 					free (syscalls);
575 					return;
576 				}
577 				syscalls[i] = sig;
578 			}
579 		}
580 		eprintf ("Running child until syscalls:");
581 		for (i = 0; i < count; i++) {
582 			eprintf ("%d ", syscalls[i]);
583 		}
584 		eprintf ("\n");
585 		free (str);
586 	} else {
587 		eprintf ("Running child until next syscall\n");
588 	}
589 	r_reg_arena_swap (core->dbg->reg, true);
590 	r_debug_continue_syscalls (core->dbg, syscalls, count);
591 	free (syscalls);
592 }
593 
showreg(RCore * core,const char * str)594 static int showreg(RCore *core, const char *str) {
595 	int size = 0;
596 	RRegItem *r = 0;
597 	const char *rname = str;
598 	// check for alias reg
599 	int role = r_reg_get_name_idx (str);
600 	if (role != -1) {
601 		rname = r_reg_get_name (core->dbg->reg, role);
602 	}
603 	r = r_reg_get (core->dbg->reg, rname , -1);
604 	if (r) {
605 		ut64 off;
606 		utX value;
607 		if (r->size > 64) {
608 			off = r_reg_get_value_big (core->dbg->reg, r, &value);
609 			switch (r->size) {
610 			case 80:
611 				r_cons_printf ("0x%04x%016"PFMT64x"\n", value.v80.High, value.v80.Low);
612 				break;
613 			case 96:
614 				r_cons_printf ("0x%08x%016"PFMT64x"\n", value.v96.High, value.v96.Low);
615 				break;
616 			case 128:
617 				r_cons_printf ("0x%016"PFMT64x"%016"PFMT64x"\n", value.v128.High, value.v128.Low);
618 				break;
619 			case 256:
620 				r_cons_printf ("0x%016"PFMT64x"%016"PFMT64x"%016"PFMT64x"%016"PFMT64x"\n",
621 					   value.v256.High.High, value.v256.High.Low, value.v256.Low.High, value.v256.Low.Low);
622 				break;
623 			default:
624 				r_cons_printf ("Error while retrieving reg '%s' of %i bits\n", str +1, r->size);
625 			}
626 		} else {
627 			off = r_reg_get_value (core->dbg->reg, r);
628 			r_cons_printf ("0x%08"PFMT64x "\n", off);
629 		}
630 		return r->size;
631 	}
632 	char *arg = strchr (str + 1, ' ');
633 	if (arg && size == 0) {
634 		size = atoi (arg + 1);
635 	} else {
636 		size = atoi (str + 1);
637 	}
638 	return size;
639 }
640 
get_graphtrace_node(RGraph * g,Sdb * nodes,struct trace_node * tn)641 static RGraphNode *get_graphtrace_node (RGraph *g, Sdb *nodes, struct trace_node *tn) {
642 	RGraphNode *gn;
643 	char tn_key[TN_KEY_LEN];
644 
645 	snprintf (tn_key, TN_KEY_LEN, TN_KEY_FMT, tn->addr);
646 	gn = (RGraphNode *)(size_t)sdb_num_get (nodes, tn_key, NULL);
647 	if (!gn) {
648 		gn = r_graph_add_node (g, tn);
649 		sdb_num_set (nodes, tn_key, (ut64)(size_t)gn, 0);
650 	}
651 	return gn;
652 }
653 
dot_trace_create_node(RTreeNode * n,RTreeVisitor * vis)654 static void dot_trace_create_node (RTreeNode *n, RTreeVisitor *vis) {
655 	struct dot_trace_ght *data = (struct dot_trace_ght *)vis->data;
656 	struct trace_node *tn = n->data;
657 	if (tn) get_graphtrace_node (data->graph, data->graphnodes, tn);
658 }
659 
dot_trace_discover_child(RTreeNode * n,RTreeVisitor * vis)660 static void dot_trace_discover_child (RTreeNode *n, RTreeVisitor *vis) {
661 	struct dot_trace_ght *data = (struct dot_trace_ght *)vis->data;
662 	RGraph *g = data->graph;
663 	Sdb *gnodes = data->graphnodes;
664 	RTreeNode *parent = n->parent;
665 	struct trace_node *tn = n->data;
666 	struct trace_node *tn_parent = parent->data;
667 
668 	if (tn && tn_parent) {
669 		RGraphNode *gn = get_graphtrace_node (g, gnodes, tn);
670 		RGraphNode *gn_parent = get_graphtrace_node (g, gnodes, tn_parent);
671 
672 		if (!r_graph_adjacent (g, gn_parent, gn))
673 			r_graph_add_edge (g, gn_parent, gn);
674 	}
675 }
676 
dot_trace_traverse(RCore * core,RTree * t,int fmt)677 static void dot_trace_traverse(RCore *core, RTree *t, int fmt) {
678 	const char *gfont = r_config_get (core->config, "graph.font");
679 	struct dot_trace_ght aux_data;
680 	RTreeVisitor vis = { 0 };
681 	const RList *nodes;
682 	RListIter *iter;
683 	RGraphNode *n;
684 
685 	if (fmt == 'i') {
686 		r_core_cmd0 (core, "ag-;.dtg*;aggi");
687 		return;
688 	}
689 	aux_data.graph = r_graph_new ();
690 	aux_data.graphnodes = sdb_new0 ();
691 
692 	/* build a callgraph from the execution trace */
693 	vis.data = &aux_data;
694 	vis.pre_visit = (RTreeNodeVisitCb)dot_trace_create_node;
695 	vis.discover_child = (RTreeNodeVisitCb)dot_trace_discover_child;
696 	r_tree_bfs (t, &vis);
697 
698 	/* traverse the callgraph to print the dot file */
699 	nodes = r_graph_get_nodes (aux_data.graph);
700 	if (fmt == 0) {
701 		r_cons_printf ("digraph code {\n"
702 				"graph [bgcolor=white];\n"
703 				"    node [color=lightgray, style=filled"
704 				" shape=box fontname=\"%s\" fontsize=\"8\"];\n", gfont);
705 	}
706 	r_list_foreach (nodes, iter, n) {
707 		struct trace_node *tn = (struct trace_node *)n->data;
708 		const RList *neighbours = r_graph_get_neighbours (aux_data.graph, n);
709 		RListIter *it_n;
710 		RGraphNode *w;
711 
712 		if (!fmt && tn) {
713 			r_cons_printf ("\"0x%08"PFMT64x"\" [URL=\"0x%08"PFMT64x
714 					"\" color=\"lightgray\" label=\"0x%08"PFMT64x
715 					" (%d)\"]\n", tn->addr, tn->addr, tn->addr, tn->refs);
716 		}
717 		r_list_foreach (neighbours, it_n, w) {
718 			struct trace_node *tv = (struct trace_node *)w->data;
719 
720 			if (tv && tn) {
721 				if (fmt) {
722 					r_cons_printf ("agn 0x%08"PFMT64x"\n", tn->addr);
723 					r_cons_printf ("agn 0x%08"PFMT64x"\n", tv->addr);
724 					r_cons_printf ("age 0x%08"PFMT64x" 0x%08"PFMT64x"\n",
725 							tn->addr, tv->addr);
726 				} else {
727 					r_cons_printf ("\"0x%08"PFMT64x"\" -> \"0x%08"PFMT64x
728 							"\" [color=\"red\"];\n", tn->addr, tv->addr);
729 				}
730 			}
731 		}
732 	}
733 	if (!fmt) {
734 		r_cons_printf ("}\n");
735 	}
736 
737 	r_graph_free (aux_data.graph);
738 	sdb_free (aux_data.graphnodes);
739 }
740 
741 /* TODO: refactor all those step_until* function into a single one
742  * TODO: handle when the process is dead
743  * TODO: handle ^C */
744 
step_until(RCore * core,ut64 addr)745 static int step_until(RCore *core, ut64 addr) {
746 	ut64 off = r_debug_reg_get (core->dbg, "PC");
747 	if (!off) {
748 		eprintf ("Cannot 'drn PC'\n");
749 		return false;
750 	}
751 	if (!addr) {
752 		eprintf ("Cannot continue until address 0\n");
753 		return false;
754 	}
755 	r_cons_break_push (NULL, NULL);
756 	do {
757 		if (r_cons_is_breaked ()) {
758 			core->break_loop = true;
759 			break;
760 		}
761 		if (r_debug_is_dead (core->dbg)) {
762 			core->break_loop = true;
763 			break;
764 		}
765 		r_debug_step (core->dbg, 1);
766 		off = r_debug_reg_get (core->dbg, "PC");
767 		// check breakpoint here
768 	} while (off != addr);
769 	r_cons_break_pop ();
770 	return true;
771 }
772 
step_until_esil(RCore * core,const char * esilstr)773 static int step_until_esil(RCore *core, const char *esilstr) {
774 	if (!core || !esilstr || !core->dbg || !core->dbg->anal \
775 			|| !core->dbg->anal->esil) {
776 		eprintf ("Not initialized %p. Run 'aei' first.\n", core->anal->esil);
777 		return false;
778 	}
779 	r_cons_break_push (NULL, NULL);
780 	for (;;) {
781 		if (r_cons_is_breaked ()) {
782 			core->break_loop = true;
783 			break;
784 		}
785 		if (r_debug_is_dead (core->dbg)) {
786 			core->break_loop = true;
787 			break;
788 		}
789 		r_debug_step (core->dbg, 1);
790 		r_debug_reg_sync (core->dbg, R_REG_TYPE_ALL, false);
791 		if (r_anal_esil_condition (core->anal->esil, esilstr)) {
792 			eprintf ("ESIL BREAK!\n");
793 			break;
794 		}
795 	}
796 	r_cons_break_pop ();
797 	return true;
798 }
799 
is_repeatable_inst(RCore * core,ut64 addr)800 static bool is_repeatable_inst(RCore *core, ut64 addr) {
801 	// we have read the bytes already
802 	RAnalOp *op = r_core_op_anal (core, addr, R_ANAL_OP_MASK_ALL);
803 	bool ret = op && ((op->prefix & R_ANAL_OP_PREFIX_REP) || (op->prefix & R_ANAL_OP_PREFIX_REPNE));
804 	r_anal_op_free (op);
805 	return ret;
806 }
807 
step_until_inst(RCore * core,const char * instr,bool regex)808 static int step_until_inst(RCore *core, const char *instr, bool regex) {
809 	RAsmOp asmop;
810 	ut8 buf[32];
811 	ut64 pc;
812 	int ret;
813 	bool is_x86 = r_str_startswith (r_config_get (core->config, "asm.arch"), "x86");
814 
815 	instr = r_str_trim_head_ro (instr);
816 	if (!core || !instr|| !core->dbg) {
817 		eprintf ("Wrong state\n");
818 		return false;
819 	}
820 	r_cons_break_push (NULL, NULL);
821 	for (;;) {
822 		if (r_cons_is_breaked ()) {
823 			break;
824 		}
825 		if (r_debug_is_dead (core->dbg)) {
826 			break;
827 		}
828 		pc = r_debug_reg_get (core->dbg, "PC");
829 		if (is_x86 && is_repeatable_inst (core, pc)) {
830 			r_debug_step_over (core->dbg, 1);
831 		} else {
832 			r_debug_step (core->dbg, 1);
833 		}
834 		pc = r_debug_reg_get (core->dbg, "PC");
835 		r_debug_reg_sync (core->dbg, R_REG_TYPE_ALL, false);
836 		/* TODO: disassemble instruction and strstr */
837 		r_asm_set_pc (core->rasm, pc);
838 		// TODO: speedup if instructions are in the same block as the previous
839 		r_io_read_at (core->io, pc, buf, sizeof (buf));
840 		ret = r_asm_disassemble (core->rasm, &asmop, buf, sizeof (buf));
841 		eprintf ("0x%08"PFMT64x" %d %s\n", pc, ret, r_asm_op_get_asm (&asmop)); // asmop.buf_asm);
842 		if (ret > 0) {
843 			const char *buf_asm = r_asm_op_get_asm (&asmop);
844 			if (regex) {
845 				if (r_regex_match (instr, "e", buf_asm)) {
846 					eprintf ("Stop.\n");
847 					break;
848 				}
849 			} else {
850 				if (strstr (buf_asm, instr)) {
851 					eprintf ("Stop.\n");
852 					break;
853 				}
854 			}
855 		}
856 	}
857 	r_cons_break_pop ();
858 	return true;
859 }
860 
step_until_optype(RCore * core,const char * _optypes)861 static int step_until_optype(RCore *core, const char *_optypes) {
862 	RAnalOp op;
863 	ut8 buf[32];
864 	ut64 pc;
865 	int res = true;
866 
867 	RList *optypes_list = NULL;
868 	RListIter *iter;
869 	char *optype, *optypes = strdup (r_str_trim_head_ro ((char *) _optypes));
870 
871 	if (!core || !core->dbg) {
872 		eprintf ("Wrong state\n");
873 		res = false;
874 		goto end;
875 	}
876 	if (!optypes || !*optypes) {
877 		eprintf ("Missing optypes. Usage example: 'dsuo ucall ujmp'\n");
878 		res = false;
879 		goto end;
880 	}
881 
882 	bool debugMode = r_config_get_i (core->config, "cfg.debug");
883 	optypes_list = r_str_split_list (optypes, " ", 0);
884 
885 	r_cons_break_push (NULL, NULL);
886 	for (;;) {
887 		if (r_cons_is_breaked ()) {
888 			core->break_loop = true;
889 			break;
890 		}
891 		if (debugMode) {
892 			if (r_debug_is_dead (core->dbg)) {
893 				core->break_loop = true;
894 				break;
895 			}
896 			r_debug_step (core->dbg, 1);
897 			pc = r_debug_reg_get (core->dbg, core->dbg->reg->name[R_REG_NAME_PC]);
898 			// 'Copy' from r_debug_step_soft
899 			if (!core->dbg->iob.read_at) {
900 				eprintf ("ERROR\n");
901 				res = false;
902 				goto cleanup_after_push;
903 			}
904 			if (!core->dbg->iob.read_at (core->dbg->iob.io, pc, buf, sizeof (buf))) {
905 				eprintf ("ERROR\n");
906 				res = false;
907 				goto cleanup_after_push;
908 			}
909 		} else {
910 			r_core_esil_step (core, UT64_MAX, NULL, NULL, false);
911 			pc = r_reg_getv (core->anal->reg, "PC");
912 		}
913 		r_io_read_at (core->io, pc, buf, sizeof (buf));
914 
915 		if (!r_anal_op (core->dbg->anal, &op, pc, buf, sizeof (buf), R_ANAL_OP_MASK_BASIC)) {
916 			eprintf ("Error: r_anal_op failed\n");
917 			res = false;
918 			goto cleanup_after_push;
919 		}
920 
921 		// This is slow because we do lots of strcmp's.
922 		// To improve this, the function r_anal_optype_string_to_int should be implemented
923 		// I also don't check if the opcode type exists.
924 		const char *optype_str = r_anal_optype_to_string (op.type);
925 		r_list_foreach (optypes_list, iter, optype) {
926 			if (!strcmp (optype_str, optype)) {
927 				goto cleanup_after_push;
928 			}
929 		}
930 	}
931 
932 cleanup_after_push:
933 	r_cons_break_pop ();
934 end:
935 	free (optypes);
936 	r_list_free (optypes_list);
937 	return res;
938 }
939 
step_until_flag(RCore * core,const char * instr)940 static int step_until_flag(RCore *core, const char *instr) {
941 	const RList *list;
942 	RListIter *iter;
943 	RFlagItem *f;
944 	ut64 pc;
945 
946 	instr = r_str_trim_head_ro (instr);
947 	if (!core || !instr || !core->dbg) {
948 		eprintf ("Wrong state\n");
949 		return false;
950 	}
951 	r_cons_break_push (NULL, NULL);
952 	for (;;) {
953 		if (r_cons_is_breaked ()) {
954 			break;
955 		}
956 		if (r_debug_is_dead (core->dbg)) {
957 			break;
958 		}
959 		r_debug_step (core->dbg, 1);
960 		r_debug_reg_sync (core->dbg, R_REG_TYPE_ALL, false);
961 		pc = r_debug_reg_get (core->dbg, "PC");
962 		list = r_flag_get_list (core->flags, pc);
963 		r_list_foreach (list, iter, f) {
964 			if (!instr|| !*instr || (f->realname && strstr(f->realname, instr))) {
965 				r_cons_printf ("[ 0x%08"PFMT64x" ] %s\n",
966 						f->offset, f->realname);
967 				goto beach;
968 			}
969 		}
970 	}
971 beach:
972 	r_cons_break_pop ();
973 	return true;
974 }
975 
976 /* until end of frame */
step_until_eof(RCore * core)977 static int step_until_eof(RCore *core) {
978 	int maxLoops = 200000;
979 	ut64 off, now = r_debug_reg_get (core->dbg, "SP");
980 	r_cons_break_push (NULL, NULL);
981 	do {
982 		// XXX (HACK!)
983 		r_debug_step_over (core->dbg, 1);
984 		off = r_debug_reg_get (core->dbg, "SP");
985 		// check breakpoint here
986 		if (--maxLoops < 0) {
987 			eprintf ("Step loop limit exceeded\n");
988 			break;
989 		}
990 	} while (off <= now);
991 	r_cons_break_pop ();
992 	return true;
993 }
994 
step_line(RCore * core,int times)995 static int step_line(RCore *core, int times) {
996 	char file[512], file2[512];
997 	int find_meta, line = -1, line2 = -1;
998 	char *tmp_ptr = NULL;
999 	ut64 off = r_debug_reg_get (core->dbg, "PC");
1000 	if (off == 0LL) {
1001 		eprintf ("Cannot 'drn PC'\n");
1002 		return false;
1003 	}
1004 	file[0] = 0;
1005 	file2[0] = 0;
1006 	if (r_bin_addr2line (core->bin, off, file, sizeof (file), &line)) {
1007 		char* ptr = r_file_slurp_line (file, line, 0);
1008 		eprintf ("--> 0x%08"PFMT64x" %s : %d\n", off, file, line);
1009 		eprintf ("--> %s\n", ptr);
1010 		find_meta = false;
1011 		free (ptr);
1012 	} else {
1013 		eprintf ("--> Stepping until dwarf line\n");
1014 		find_meta = true;
1015 	}
1016 	do {
1017 		r_debug_step (core->dbg, 1);
1018 		off = r_debug_reg_get (core->dbg, "PC");
1019 		if (!r_bin_addr2line (core->bin, off, file2, sizeof (file2), &line2)) {
1020 			if (find_meta)
1021 				continue;
1022 			eprintf ("Cannot retrieve dwarf info at 0x%08"PFMT64x"\n", off);
1023 			return false;
1024 		}
1025 	} while (!strcmp (file, file2) && line == line2);
1026 
1027 	eprintf ("--> 0x%08"PFMT64x" %s : %d\n", off, file2, line2);
1028 	tmp_ptr = r_file_slurp_line (file2, line2, 0);
1029 	eprintf ("--> %s\n", tmp_ptr);
1030 	free (tmp_ptr);
1031 
1032 	return true;
1033 }
1034 
cmd_debug_pid(RCore * core,const char * input)1035 static void cmd_debug_pid(RCore *core, const char *input) {
1036 	int pid, sig;
1037 	const char *ptr;
1038 	switch (input[1]) {
1039 	case '\0': // "dp"
1040 		eprintf ("Selected: %d %d\n", core->dbg->pid, core->dbg->tid);
1041 		r_debug_pid_list (core->dbg, core->dbg->pid, 0);
1042 		break;
1043 	case '-': // "dp-"
1044 		if (input[2]== ' ') {
1045 			r_debug_detach (core->dbg, r_num_math (core->num, input + 2));
1046 		} else {
1047 			r_debug_detach (core->dbg, core->dbg->pid);
1048 		}
1049 		break;
1050 	case 'c': // "dpc"
1051 		if (core->dbg->forked_pid != -1) {
1052 			if (input[2] == '*') {
1053 				eprintf ("dp %d\n", core->dbg->forked_pid);
1054 			} else {
1055 				r_debug_select (core->dbg, core->dbg->forked_pid, core->dbg->tid);
1056 				core->dbg->main_pid = core->dbg->forked_pid;
1057 				core->dbg->n_threads = 0;
1058 				core->dbg->forked_pid = -1;
1059 			}
1060 		} else {
1061 			eprintf ("No recently forked children\n");
1062 		}
1063 		break;
1064 	case 'k': // "dpk"
1065 		/* stop, print, pass -- just use flags*/
1066 		/* XXX: not for threads? signal is for a whole process!! */
1067 		/* XXX: but we want fine-grained access to process resources */
1068 		pid = atoi (input + 2);
1069 		if (pid > 0) {
1070 			ptr = r_str_trim_head_ro (input + 2);
1071 			ptr = strchr (ptr, ' ');
1072 			sig = ptr? atoi (ptr + 1): 0;
1073 			eprintf ("Sending signal '%d' to pid '%d'\n", sig, pid);
1074 			r_debug_kill (core->dbg, pid, false, sig);
1075 		} else eprintf ("cmd_debug_pid: Invalid arguments (%s)\n", input);
1076 		break;
1077 	case 'n': // "dpn"
1078 		eprintf ("TODO: debug_fork: %d\n", r_debug_child_fork (core->dbg));
1079 		break;
1080 	case 't': // "dpt"
1081 		switch (input[2]) {
1082 		case '\0': // "dpt"
1083 			r_debug_thread_list (core->dbg, core->dbg->pid, 0);
1084 			break;
1085 		case 'j': // "dptj"
1086 			if (input[3] != ' ') { // "dptj"
1087 				r_debug_thread_list (core->dbg, core->dbg->pid, 'j');
1088 			} else { // "dptj "
1089 				r_debug_thread_list (core->dbg, atoi (input + 3), 'j');
1090 			}
1091 			break;
1092 		case ' ': // "dpt "
1093 			r_debug_thread_list (core->dbg, atoi (input + 2), 0);
1094 			break;
1095 		case '=': // "dpt="
1096 			r_debug_select (core->dbg, core->dbg->pid,
1097 					(int) r_num_math (core->num, input + 3));
1098 			break;
1099 		case 'n': // "dptn"
1100 			eprintf ("TODO: debug_clone: %d\n", r_debug_child_clone (core->dbg));
1101 			break;
1102 		case '?': // "dpt?"
1103 		default:
1104 			r_core_cmd_help (core, help_msg_dp);
1105 			break;
1106 		}
1107 		break;
1108 	case 'a': // "dpa"
1109 		if (input[2]) {
1110 			r_debug_attach (core->dbg, (int) r_num_math (
1111 						core->num, input + 2));
1112 		} else {
1113 			if (core->io && core->io->desc) {
1114 				r_debug_attach (core->dbg,
1115 						r_io_fd_get_pid (core->io, core->io->desc->fd));
1116 			}
1117 		}
1118 		r_debug_select (core->dbg, core->dbg->pid, core->dbg->tid);
1119 		r_config_set_i (core->config, "dbg.swstep",
1120 				(core->dbg->h && !core->dbg->h->canstep));
1121 		r_core_cmdf (core, "=!pid %d", core->dbg->pid);
1122 		break;
1123 	case 'f': // "dpf"
1124 		if (core->io && core->io->desc) {
1125 			r_debug_select (core->dbg, r_io_fd_get_pid (core->io, core->io->desc->fd),
1126 					r_io_fd_get_tid (core->io, core->io->desc->fd));
1127 		}
1128 		break;
1129 	case '=': // "dp="
1130 		r_debug_select (core->dbg,
1131 				(int) r_num_math (core->num, input + 2), core->dbg->tid);
1132 		core->dbg->main_pid = r_num_math (core->num, input + 2);
1133 		break;
1134 	case 'l': // "dpl"
1135 		switch (input[2]) {
1136 		case '\0': // "dpl"
1137 			r_debug_pid_list (core->dbg, 0, 0);
1138 			break;
1139 		case 'j': // "dplj"
1140 			r_debug_pid_list (core->dbg, 0, 'j');
1141 			break;
1142 		}
1143 		break;
1144 	case 'j': // "dpj"
1145 		switch (input[2]) {
1146 		case '\0': // "dpj"
1147 			r_debug_pid_list (core->dbg, core->dbg->pid, 'j');
1148 			break;
1149 		case ' ': // "dpj "
1150 			r_debug_pid_list (core->dbg,
1151 					(int) R_MAX (0, (int)r_num_math (core->num, input + 2)), 'j');
1152 			break;
1153 		}
1154 		break;
1155 	case 'e': // "dpe"
1156 		{
1157 			int pid = (input[2] == ' ')? atoi (input + 2): core->dbg->pid;
1158 			char *exe = r_sys_pid_to_path (pid);
1159 			if (exe) {
1160 				r_cons_println (exe);
1161 				free (exe);
1162 			}
1163 		}
1164 		break;
1165 	case ' ': // "dp "
1166 		r_debug_pid_list (core->dbg,
1167 				(int) R_MAX (0, (int)r_num_math (core->num, input + 2)), 0);
1168 		break;
1169 	case '?': // "dp?"
1170 	default:
1171 		r_core_cmd_help (core, help_msg_dp);
1172 		break;
1173 	}
1174 }
1175 
cmd_debug_backtrace(RCore * core,const char * input)1176 static void cmd_debug_backtrace(RCore *core, const char *input) {
1177 	RAnalOp analop;
1178 	ut64 addr, len = r_num_math (core->num, input);
1179 	if (!len) {
1180 		r_bp_traptrace_list (core->dbg->bp);
1181 	} else {
1182 		ut64 oaddr = 0LL;
1183 		eprintf ("Trap tracing 0x%08"PFMT64x"-0x%08"PFMT64x"\n",
1184 				core->offset, core->offset+len);
1185 		r_reg_arena_swap (core->dbg->reg, true);
1186 		r_bp_traptrace_reset (core->dbg->bp, true);
1187 		r_bp_traptrace_add (core->dbg->bp, core->offset, core->offset+len);
1188 		r_bp_traptrace_enable (core->dbg->bp, true);
1189 		do {
1190 			ut8 buf[32];
1191 			r_debug_continue (core->dbg);
1192 			addr = r_debug_reg_get (core->dbg, "PC");
1193 			if (!addr) {
1194 				eprintf ("pc=0\n");
1195 				break;
1196 			}
1197 			if (addr == oaddr) {
1198 				eprintf ("pc=opc\n");
1199 				break;
1200 			}
1201 			oaddr = addr;
1202 			/* XXX Bottleneck..we need to reuse the bytes read by traptrace */
1203 			// XXX Do asm.arch should define the max size of opcode?
1204 			r_io_read_at (core->io, addr, buf, 32); // XXX longer opcodes?
1205 			r_anal_op (core->anal, &analop, addr, buf, sizeof (buf), R_ANAL_OP_MASK_BASIC);
1206 		} while (r_bp_traptrace_at (core->dbg->bp, addr, analop.size));
1207 		r_bp_traptrace_enable (core->dbg->bp, false);
1208 	}
1209 }
1210 
grab_bits(RCore * core,const char * arg,int * pcbits2)1211 static int grab_bits(RCore *core, const char *arg, int *pcbits2) {
1212 	int pcbits = atoi (arg);
1213 	if (pcbits2) {
1214 		*pcbits2 = 0;
1215 	}
1216 	if (pcbits < 1) {
1217 		if (!strcmp (r_config_get (core->config, "asm.arch"), "avr")) {
1218 			pcbits = 8;
1219 			if (pcbits2) {
1220 				*pcbits2 = 32;
1221 			}
1222 		} else {
1223 			const char *pcname = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
1224 			RRegItem *reg = r_reg_get (core->anal->reg, pcname, 0);
1225 			if (reg) {
1226 				if (core->rasm->bits != reg->size)
1227 					pcbits = reg->size;
1228 			}
1229 		}
1230 	}
1231 	return pcbits ? pcbits : core->anal->bits;
1232 }
1233 
1234 #define MAX_MAP_SIZE 1024*1024*512
dump_maps(RCore * core,int perm,const char * filename)1235 static int dump_maps(RCore *core, int perm, const char *filename) {
1236 	RDebugMap *map;
1237 	RListIter *iter;
1238 	r_debug_map_sync (core->dbg); // update process memory maps
1239 	ut64 addr = core->offset;
1240 	int do_dump = false;
1241 	int ret = !r_list_empty (core->dbg->maps);
1242 	r_list_foreach (core->dbg->maps, iter, map) {
1243 		do_dump = false;
1244 		if (perm == -1) {
1245 			if (addr >= map->addr && addr < map->addr_end) {
1246 				do_dump = true;
1247 			}
1248 		} else if (perm == 0) {
1249 			do_dump = true;
1250 		} else if (perm == (map->perm & perm)) {
1251 			do_dump = true;
1252 		}
1253 		if (do_dump) {
1254 			ut8 *buf = malloc (map->size);
1255 			//TODO: use mmap here. we need a portable implementation
1256 			if (!buf) {
1257 				eprintf ("Cannot allocate 0x%08"PFMT64x" bytes\n", map->size);
1258 				free (buf);
1259 				/// XXX: TODO: read by blocks!!1
1260 				continue;
1261 			}
1262 			if (map->size > MAX_MAP_SIZE) {
1263 				eprintf ("Do not dumping 0x%08"PFMT64x" because it's too big\n", map->addr);
1264 				free (buf);
1265 				continue;
1266 			}
1267 			r_io_read_at (core->io, map->addr, buf, map->size);
1268 			char *file = filename
1269 			? strdup (filename)
1270 			: r_str_newf ("0x%08"PFMT64x"-0x%08"PFMT64x"-%s.dmp",
1271 					map->addr, map->addr_end, r_str_rwx_i (map->perm));
1272 			if (!r_file_dump (file, buf, map->size, 0)) {
1273 				eprintf ("Cannot write '%s'\n", file);
1274 				ret = 0;
1275 			} else {
1276 				eprintf ("Dumped %d byte(s) into %s\n", (int)map->size, file);
1277 			}
1278 			free (file);
1279 			free (buf);
1280 		}
1281 	}
1282 	//eprintf ("No debug region found here\n");
1283 	return ret;
1284 }
1285 
cmd_debug_modules(RCore * core,int mode)1286 static void cmd_debug_modules(RCore *core, int mode) { // "dmm"
1287 	ut64 addr = core->offset;
1288 	RDebugMap *map;
1289 	RList *list;
1290 	RListIter *iter;
1291 
1292 	/* avoid processing the list if the user only wants help */
1293 	if (mode == '?') {
1294 show_help:
1295 		r_core_cmd_help (core, help_msg_dmm);
1296 		return;
1297 	}
1298 	PJ *pj = NULL;
1299 	if (mode == 'j') {
1300 		pj = r_core_pj_new (core);
1301 		if (!pj) {
1302 			return;
1303 		}
1304 		pj_a (pj);
1305 	}
1306 	// TODO: honor mode
1307 	list = r_debug_modules_list (core->dbg);
1308 	r_list_foreach (list, iter, map) {
1309 		switch (mode) {
1310 		case 0:
1311 			r_cons_printf ("0x%08"PFMT64x" 0x%08"PFMT64x"  %s\n", map->addr, map->addr_end, map->file);
1312 			break;
1313 		case '.':
1314 			if (addr >= map->addr && addr < map->addr_end) {
1315 				r_cons_printf ("0x%08"PFMT64x" 0x%08"PFMT64x"  %s\n", map->addr, map->addr_end, map->file);
1316 				goto beach;
1317 			}
1318 			break;
1319 		case 'j':
1320 			{
1321 				/* Escape backslashes (e.g. for Windows). */
1322 				pj_o (pj);
1323 				pj_kn (pj, "addr", map->addr);
1324 				pj_kn (pj, "addr_end", map->addr_end);
1325 				pj_ks (pj, "file", map->file);
1326 				pj_ks (pj, "name", map->name);
1327 				pj_end (pj);
1328 			}
1329 			break;
1330 		case ':':
1331 		case '*':
1332 			if (mode == '*' || (mode == ':' && \
1333 				addr>=map->addr && addr < map->addr_end)) {
1334 				/* Escape backslashes (e.g. for Windows). */
1335 				char *escaped_path = r_str_escape (map->file);
1336 				char *filtered_name = strdup (map->name);
1337 				r_name_filter (filtered_name, 0);
1338 				r_cons_printf ("f mod.%s = 0x%08"PFMT64x"\n",
1339 					filtered_name, map->addr);
1340 				r_cons_printf ("oba 0x%08"PFMT64x" %s\n", map->addr, escaped_path);
1341 				// r_cons_printf (".!rabin2 -rsB 0x%08"PFMT64x" \"%s\"\n", map->addr, escaped_path);
1342 				free (escaped_path);
1343 				free (filtered_name);
1344 			}
1345 			break;
1346 		default:
1347 			pj_free (pj);
1348 			r_list_free (list);
1349 			goto show_help;
1350 			/* not reached */
1351 		}
1352 	}
1353 beach:
1354 	if (mode == 'j') {
1355 		pj_end (pj);
1356 		r_cons_println (pj_string (pj));
1357 	}
1358 	pj_free (pj);
1359 	r_list_free (list);
1360 }
1361 
1362 #if __linux__ && __GNU_LIBRARY__ && __GLIBC__ && __GLIBC_MINOR__
1363 
1364 static int cmd_dbg_map_heap_glibc_32(RCore *core, const char *input);
1365 static int cmd_dbg_map_heap_glibc_64(RCore *core, const char *input);
1366 #endif // __linux__ && __GNU_LIBRARY__ && __GLIBC__ && __GLIBC_MINOR__
1367 #if __WINDOWS__
1368 static int cmd_debug_map_heap_win(RCore *core, const char *input);
1369 #endif // __WINDOWS__
1370 
1371 
addroflib(RCore * core,const char * libname)1372 static ut64 addroflib(RCore *core, const char *libname) {
1373 	RListIter *iter;
1374 	RDebugMap *map;
1375 	if (!core || !libname) {
1376 		return UT64_MAX;
1377 	}
1378 	r_debug_map_sync (core->dbg);
1379 	// RList *list = r_debug_native_modules_get (core->dbg);
1380 	RList *list = r_debug_modules_list (core->dbg);
1381 	r_list_foreach (list, iter, map) {
1382 		if (strstr (r_file_basename(map->name), libname)) {
1383 			return map->addr;
1384 		}
1385 	}
1386 	r_list_foreach (core->dbg->maps, iter, map) {
1387 		if (strstr (r_file_basename(map->name), libname)) {
1388 			return map->addr;
1389 		}
1390 	}
1391 	return UT64_MAX;
1392 }
1393 
get_closest_map(RCore * core,ut64 addr)1394 static RDebugMap *get_closest_map(RCore *core, ut64 addr) {
1395 	RListIter *iter;
1396 	RDebugMap *map;
1397 
1398 	r_debug_map_sync (core->dbg);
1399 	RList *list = r_debug_modules_list (core->dbg);
1400 	r_list_foreach (list, iter, map) {
1401 		if (addr != UT64_MAX && (addr >= map->addr && addr < map->addr_end)) {
1402 			return map;
1403 		}
1404 	}
1405 	r_list_foreach (core->dbg->maps, iter, map) {
1406 		if (addr != UT64_MAX && (addr >= map->addr && addr < map->addr_end)) {
1407 			return map;
1408 		}
1409 	}
1410 	return NULL;
1411 }
1412 
r_debug_heap(RCore * core,const char * input)1413 static int r_debug_heap(RCore *core, const char *input) {
1414 	const char *m = r_config_get (core->config, "dbg.malloc");
1415 	if (m && !strcmp ("glibc", m)) {
1416 #if __linux__ && __GNU_LIBRARY__ && __GLIBC__ && __GLIBC_MINOR__
1417 		if (core->rasm->bits == 64) {
1418 			cmd_dbg_map_heap_glibc_64 (core, input + 1);
1419 		} else {
1420 			cmd_dbg_map_heap_glibc_32 (core, input + 1);
1421 		}
1422 #else
1423 		eprintf ("glibc not supported for this platform\n");
1424 #endif
1425 #if HAVE_JEMALLOC
1426 	} else if (m && !strcmp ("jemalloc", m)) {
1427 		if (core->rasm->bits == 64) {
1428 			cmd_dbg_map_jemalloc_64 (core, input + 1);
1429 		} else {
1430 			cmd_dbg_map_jemalloc_32 (core, input + 1);
1431 		}
1432 #endif
1433 	} else {
1434 #if __WINDOWS__
1435 		cmd_debug_map_heap_win (core, input + 1);
1436 #else
1437 		eprintf ("MALLOC algorithm not supported\n");
1438 		return false;
1439 #endif
1440 	}
1441 	return true;
1442 }
1443 
get_bin_info(RCore * core,const char * file,ut64 baseaddr,PJ * pj,int mode,bool symbols_only,RCoreBinFilter * filter)1444 static bool get_bin_info(RCore *core, const char *file, ut64 baseaddr, PJ *pj, int mode, bool symbols_only, RCoreBinFilter *filter) {
1445 	int fd;
1446 	if ((fd = r_io_fd_open (core->io, file, R_PERM_R, 0)) == -1) {
1447 		return false;
1448 	}
1449 	RBinOptions opt = { 0 };
1450 	opt.fd = fd;
1451 	opt.sz = r_io_fd_size (core->io, fd);
1452 	opt.baseaddr = baseaddr;
1453 	RBinFile *obf = r_bin_cur (core->bin);
1454 	if (!r_bin_open_io (core->bin, &opt)) {
1455 		r_io_fd_close (core->io, fd);
1456 		return false;
1457 	}
1458 	int action = R_CORE_BIN_ACC_ALL & ~R_CORE_BIN_ACC_INFO;
1459 	if (symbols_only || filter->name) {
1460 		action = R_CORE_BIN_ACC_SYMBOLS;
1461 	} else if (mode == R_MODE_SET || mode == R_MODE_RADARE) {
1462 		action &= ~R_CORE_BIN_ACC_ENTRIES & ~R_CORE_BIN_ACC_MAIN;
1463 	}
1464 	r_core_bin_info (core, action, pj, mode, 1, filter, NULL);
1465 	RBinFile *bf = r_bin_cur (core->bin);
1466 	r_bin_file_delete (core->bin, bf->id);
1467 	r_bin_file_set_cur_binfile (core->bin, obf);
1468 	r_io_fd_close (core->io, fd);
1469 	return true;
1470 }
1471 
cmd_debug_map(RCore * core,const char * input)1472 static int cmd_debug_map(RCore *core, const char *input) {
1473 	RListIter *iter;
1474 	RDebugMap *map;
1475 	ut64 addr = core->offset;
1476 
1477 	switch (input[0]) {
1478 	case '.': // "dm."
1479 		r_debug_map_list (core->dbg, addr, input);
1480 		break;
1481 	case 'm': // "dmm"
1482 		if (!strcmp (input + 1, ".*")) {
1483 			cmd_debug_modules (core, ':');
1484 		} else cmd_debug_modules (core, input[1]);
1485 		break;
1486 	case '?': // "dm?"
1487 		r_core_cmd_help (core, help_msg_dm);
1488 		break;
1489 	case 'p': // "dmp"
1490 		if (input[1] == '?') {
1491 			r_core_cmd_help (core, help_msg_dmp);
1492 		} else if (input[1] == ' ') {
1493 			int perms;
1494 			char *p, *q;
1495 			ut64 size = 0, addr;
1496 			p = strchr (input + 2, ' ');
1497 			if (p) {
1498 				*p++ = 0;
1499 				q = strchr (p, ' ');
1500 				if (q) {
1501 					*q++ = 0;
1502 					addr = r_num_math (core->num, input + 2);
1503 					size = r_num_math (core->num, p);
1504 					perms = r_str_rwx (q);
1505 				//	eprintf ("(%s)(%s)(%s)\n", input + 2, p, q);
1506 				//	eprintf ("0x%08"PFMT64x" %d %o\n", addr, (int) size, perms);
1507 					r_debug_map_protect (core->dbg, addr, size, perms);
1508 				} else eprintf ("See dmp?\n");
1509 			} else {
1510 				r_debug_map_sync (core->dbg); // update process memory maps
1511 				addr = UT64_MAX;
1512 				r_list_foreach (core->dbg->maps, iter, map) {
1513 					if (core->offset >= map->addr  && core->offset < map->addr_end) {
1514 						addr = map->addr;
1515 						size = map->size;
1516 						break;
1517 					}
1518 				}
1519 				perms = r_str_rwx (input + 2);
1520 				if (addr != UT64_MAX && perms >= 0) {
1521 					r_debug_map_protect (core->dbg, addr, size, perms);
1522 				} else {
1523 					eprintf ("See dmp?\n");
1524 				}
1525 			}
1526 		} else {
1527 			eprintf ("See dmp?\n");
1528 		}
1529 		break;
1530 	case 'd': // "dmd"
1531 		switch (input[1]) {
1532 		case 'a': return dump_maps (core, 0, NULL);
1533 		case 'w': return dump_maps (core, R_PERM_RW, NULL);
1534 		case ' ': return dump_maps (core, -1, input + 2);
1535 		case 0: return dump_maps (core, -1, NULL);
1536 		case '?':
1537 		default:
1538 			eprintf ("Usage: dmd[aw]  - dump (all-or-writable) debug maps\n");
1539 			break;
1540 		}
1541 		break;
1542 	case 'l': // "dml"
1543 		if (input[1] != ' ') {
1544 			eprintf ("Usage: dml [file]\n");
1545 			return false;
1546 		}
1547 		r_debug_map_sync (core->dbg); // update process memory maps
1548 		r_list_foreach (core->dbg->maps, iter, map) {
1549 			if (addr >= map->addr && addr < map->addr_end) {
1550 				size_t sz;
1551 				char *buf = r_file_slurp (input + 2, &sz);
1552 				//TODO: use mmap here. we need a portable implementation
1553 				if (!buf) {
1554 					eprintf ("Cannot allocate 0x%08"PFMT64x" byte(s)\n", map->size);
1555 					return false;
1556 				}
1557 				r_io_write_at (core->io, map->addr, (const ut8*)buf, sz);
1558 				if (sz != map->size)
1559 					eprintf	("File size differs from region size (%"PFMT64u" vs %"PFMT64d")\n",
1560 								(ut64)sz, map->size);
1561 				eprintf ("Loaded %"PFMT64u" byte(s) into the map region at 0x%08"PFMT64x"\n",
1562 						 (ut64)sz, map->addr);
1563 				free (buf);
1564 				return true;
1565 			}
1566 		}
1567 		eprintf ("No debug region found here\n");
1568 		return false;
1569 	case 'i': // "dmi"
1570 		switch (input[1]) {
1571 		case '\0': // "dmi" alias of "dmm"
1572 			r_core_cmd (core, "dmm", 0);
1573 			break;
1574 		case ' ': // "dmi "
1575 		case '*': // "dmi*"
1576 		case 'v': // "dmiv"
1577 		case 'j': // "dmij"
1578 		case 'q': // "dmiq"
1579 		case 'a': // "dmia"
1580 			{
1581 				const char *libname = NULL, *symname = NULL, *a0;
1582 				int mode;
1583 				ut64 baddr = 0LL;
1584 				char *ptr;
1585 				int i = 1;
1586 				bool symbols_only = true;
1587 				if (input[1] == 'a') {
1588 					symbols_only = false;
1589 					input++;
1590 				}
1591 				PJ *pj = NULL;
1592 				switch (input[1]) {
1593 				case 's':
1594 					mode = R_MODE_SET;
1595 					break;
1596 				case '*':
1597 					mode = R_MODE_RADARE;
1598 					break;
1599 				case 'j':
1600 					mode = R_MODE_JSON;
1601 					pj = r_core_pj_new (core);
1602 					if (!pj) {
1603 						return false;
1604 					}
1605 					break;
1606 				case 'q':
1607 					mode = input[2] == 'q' ? input++, R_MODE_SIMPLEST : R_MODE_SIMPLE;
1608 					break;
1609 				default:
1610 					mode = R_MODE_PRINT;
1611 					break;
1612 				}
1613 				ptr = strdup (r_str_trim_head_ro (input + 2));
1614 				if (!ptr || !*ptr) {
1615 					r_core_cmd (core, "dmm", 0);
1616 					free (ptr);
1617 					break;
1618 				}
1619 				if (symbols_only) {
1620 					i = r_str_word_set0 (ptr);
1621 				}
1622 				switch (i) {
1623 				case 2:
1624 					symname = r_str_word_get0 (ptr, 1);
1625 					// fall through
1626 				case 1:
1627 					a0 = r_str_word_get0 (ptr, 0);
1628 					addr = r_num_get (core->num, a0);
1629 					if (!addr || addr == UT64_MAX) {
1630 						libname = r_str_word_get0 (ptr, 0);
1631 					}
1632 					break;
1633 				}
1634 				if (libname && !addr) {
1635 					addr = addroflib (core, r_file_basename (libname));
1636 					if (addr == UT64_MAX) {
1637 						eprintf ("Unknown library, or not found in dm\n");
1638 					}
1639 				}
1640 				map = get_closest_map (core, addr);
1641 				if (map) {
1642 					RCoreBinFilter filter;
1643 					filter.offset = 0LL;
1644 					filter.name = (char *)symname;
1645 					baddr = map->addr;
1646 
1647 					if (libname) {
1648 						const char *file = map->file? map->file: map->name;
1649 						char *newfile = NULL;
1650 						if (!r_file_exists (file)) {
1651 							newfile = r_file_temp ("memlib");
1652 							if (newfile) {
1653 								file = newfile;
1654 								r_core_cmdf (core, "wtf %s 0x%"PFMT64x" @ 0x%"PFMT64x" 2> %s",
1655 								             file, map->size, baddr, R_SYS_DEVNULL);
1656 							}
1657 						}
1658 						get_bin_info (core, file, baddr, pj, mode, symbols_only, &filter);
1659 						if (newfile) {
1660 							if (!r_file_rm (newfile)) {
1661 								eprintf ("Error when removing %s\n", newfile);
1662 							}
1663 							free (newfile);
1664 						}
1665 					} else {
1666 						r_bin_set_baddr (core->bin, map->addr);
1667 						r_core_bin_info (core, R_CORE_BIN_ACC_SYMBOLS, pj, input[1] == '*', true, &filter, NULL);
1668 						r_bin_set_baddr (core->bin, baddr);
1669 					}
1670 				}
1671 				if (mode == R_MODE_JSON) {
1672 					r_cons_println (pj_string (pj));
1673 					pj_free (pj);
1674 				}
1675 				free (ptr);
1676 			}
1677 			break;
1678 		case '.': // "dmi."
1679 			{
1680 				map = get_closest_map (core, addr);
1681 				if (map) {
1682 					ut64 closest_addr = UT64_MAX;
1683 					RList *symbols = r_bin_get_symbols (core->bin);
1684 					RBinSymbol *symbol, *closest_symbol = NULL;
1685 
1686 					r_list_foreach (symbols, iter, symbol) {
1687 						if (symbol->vaddr > addr) {
1688 							if (symbol->vaddr - addr < closest_addr) {
1689 								closest_addr = symbol->vaddr - addr;
1690 								closest_symbol = symbol;
1691 							}
1692 						} else {
1693 							if (addr - symbol->vaddr < closest_addr) {
1694 								closest_addr = addr - symbol->vaddr;
1695 								closest_symbol = symbol;
1696 							}
1697 						}
1698 					}
1699 					if (closest_symbol) {
1700 						RCoreBinFilter filter;
1701 						filter.offset = 0LL;
1702 						filter.name = (char *) closest_symbol->name;
1703 
1704 						r_bin_set_baddr (core->bin, map->addr);
1705 						r_core_bin_info (core, R_CORE_BIN_ACC_SYMBOLS, NULL, false, true, &filter, NULL);
1706 					}
1707 				}
1708 			}
1709 			break;
1710 		default:
1711 			r_core_cmd_help (core, help_msg_dmi);
1712 			break;
1713 		}
1714 		break;
1715 	case 'S': // "dmS"
1716 		{ // Move to a separate function
1717 			const char *libname = NULL, *sectname = NULL, *mode = "";
1718 			ut64 baddr = 0LL;
1719 			char *ptr;
1720 			int i;
1721 
1722 			if (input[1]=='*') {
1723 				ptr = strdup (r_str_trim_head_ro ((char*)input + 2));
1724 				mode = "-r ";
1725 			} else {
1726 				ptr = strdup (r_str_trim_head_ro ((char*)input + 1));
1727 			}
1728 			i = r_str_word_set0 (ptr);
1729 
1730 			addr = UT64_MAX;
1731 			switch (i) {
1732 			case 2: // get section name
1733 				sectname = r_str_word_get0 (ptr, 1);
1734 				/* fallthrou */
1735 			case 1: // get addr|libname
1736 				if (IS_DIGIT (*ptr)) {
1737 					const char *a0 = r_str_word_get0 (ptr, 0);
1738 					addr = r_num_math (core->num, a0);
1739 				} else {
1740 					addr = UT64_MAX;
1741 				}
1742 				if (!addr || addr == UT64_MAX) {
1743 					libname = r_str_word_get0 (ptr, 0);
1744 				}
1745 				break;
1746 			}
1747 			r_debug_map_sync (core->dbg); // update process memory maps
1748 			RList *list = r_debug_modules_list (core->dbg);
1749 			r_list_foreach (list, iter, map) {
1750 				if ((!libname ||
1751 					 (addr != UT64_MAX && (addr >= map->addr && addr < map->addr_end)) ||
1752 					 (libname != NULL && (strstr (map->name, libname))))) {
1753 					baddr = map->addr;
1754 					char *res;
1755 					const char *file = map->file? map->file: map->name;
1756 					char *name = r_str_escape ((char *)r_file_basename (file));
1757 					char *filesc = r_str_escape (file);
1758 					/* TODO: do not spawn. use RBin API */
1759 					if (sectname) {
1760 						char *sect = r_str_escape (sectname);
1761 						res  = r_sys_cmd_strf ("env RABIN2_PREFIX=\"%s\" rabin2 %s-B 0x%08"
1762 							PFMT64x" -S \"%s\" | grep \"%s\"", name, mode, baddr, filesc, sect);
1763 						free (sect);
1764 					} else {
1765 						res = r_sys_cmd_strf ("env RABIN2_PREFIX=\"%s\" rabin2 %s-B 0x%08"
1766 							PFMT64x" -S \"%s\"", name, mode, baddr, filesc);
1767 					}
1768 					free (filesc);
1769 					r_cons_println (res);
1770 					free(name);
1771 					free (res);
1772 					if (libname || addr != UT64_MAX) { //only single match requested
1773 						break;
1774 					}
1775 				}
1776 			}
1777 			free (ptr);
1778 		}
1779 		break;
1780 	case ' ': // "dm "
1781 		{
1782 			int size;
1783 			char *p = strchr (input + 2, ' ');
1784 			if (p) {
1785 				*p++ = 0;
1786 				addr = r_num_math (core->num, input + 1);
1787 				size = r_num_math (core->num, p);
1788 				r_debug_map_alloc (core->dbg, addr, size, false);
1789 			} else {
1790 				eprintf ("Usage: dm addr size\n");
1791 				return false;
1792 			}
1793 		}
1794 		break;
1795 	case '-': // "dm-"
1796 		if (input[1] != ' ') {
1797 			eprintf ("|ERROR| Usage: dm- [addr]\n");
1798 			break;
1799 		}
1800 		addr = r_num_math (core->num, input + 2);
1801 		r_list_foreach (core->dbg->maps, iter, map) {
1802 			if (addr >= map->addr && addr < map->addr_end) {
1803 				r_debug_map_dealloc(core->dbg, map);
1804 				r_debug_map_sync (core->dbg);
1805 				return true;
1806 			}
1807 		}
1808 		eprintf ("The address doesn't match with any map.\n");
1809 		break;
1810 	case 'L': // "dmL"
1811 		{
1812 			int size;
1813 			char *p = strchr (input + 2, ' ');
1814 			if (p) {
1815 				*p++ = 0;
1816 				addr = r_num_math (core->num, input + 1);
1817 				size = r_num_math (core->num, p);
1818 				r_debug_map_alloc (core->dbg, addr, size, true);
1819 			} else {
1820 				eprintf ("Usage: dmL addr size\n");
1821 				return false;
1822 			}
1823 		}
1824 		break;
1825 	case '\0': // "dm"
1826 	case '*': // "dm*"
1827 	case 'j': // "dmj"
1828 	case 'q': // "dmq"
1829 		r_debug_map_sync (core->dbg); // update process memory maps
1830 		r_debug_map_list (core->dbg, core->offset, input);
1831 		break;
1832 	case '=': // "dm="
1833 		r_debug_map_sync (core->dbg);
1834 		r_debug_map_list_visual (core->dbg, core->offset, input,
1835 				r_config_get_i (core->config, "scr.color"));
1836 		break;
1837 	case 'h': // "dmh"
1838 		(void)r_debug_heap (core, input);
1839 		break;
1840 	}
1841 	return true;
1842 }
1843 
1844 #if __linux__ && __GNU_LIBRARY__ && __GLIBC__ && __GLIBC_MINOR__
1845 #include "linux_heap_glibc.c"
1846 #elif __WINDOWS__
1847 #include "windows_heap.c"
1848 #endif
1849 
1850 HEAPTYPE(ut64);
1851 
regcmp(const void * a,const void * b)1852 static int regcmp(const void *a, const void *b) {
1853 	const ut64 *A = (const ut64*)a;
1854 	const ut64 *B = (const ut64*)b;
1855 	if (*A > *B) {
1856 		return 1;
1857 	}
1858 	if (*A == *B) {
1859 		return 0;
1860 	}
1861 	return -1;
1862 }
1863 
regcb(void * u,const ut64 k,const void * v)1864 static bool regcb(void *u, const ut64 k, const void *v) {
1865 	RList *sorted = (RList*) u;
1866 	ut64 *n = ut64_new (k);
1867 	r_list_add_sorted (sorted, n, regcmp);
1868 	return true;
1869 }
1870 
r_core_debug_ri(RCore * core,RReg * reg,int mode)1871 R_API void r_core_debug_ri(RCore *core, RReg *reg, int mode) {
1872 	RList *list = r_reg_get_list (reg, R_REG_TYPE_GPR);
1873 	RListIter *iter;
1874 	RRegItem *r;
1875 	HtUP *db = ht_up_new0 ();
1876 
1877 	r_list_foreach (list, iter, r) {
1878 		if (r->size != core->rasm->bits) {
1879 			continue;
1880 		}
1881 		ut64 value = r_reg_get_value (reg, r);
1882 		RList *list = ht_up_find (db, value, NULL);
1883 		if (!list) {
1884 			list = r_list_newf (NULL);
1885 			ht_up_update (db, value, list);
1886 		}
1887 		r_list_append (list, r->name);
1888 	}
1889 
1890 	RList *sorted = r_list_newf (free);
1891 	ht_up_foreach (db, regcb, sorted);
1892 	ut64 *addr;
1893 	r_list_foreach (sorted, iter, addr) {
1894 		int rwx = 0;
1895 		RDebugMap *map = r_debug_map_get (core->dbg, *addr);
1896 		if (map) {
1897 			rwx = map->perm;
1898 		}
1899 		r_cons_printf (" %s  ", r_str_rwx_i (rwx));
1900 
1901 		r_cons_printf ("0x%08"PFMT64x" ", *addr);
1902 		RList *list = ht_up_find (db, *addr, NULL);
1903 		if (list) {
1904 			RListIter *iter;
1905 			const char *r;
1906 			r_cons_strcat (Color_YELLOW);
1907 			r_list_foreach (list, iter, r) {
1908 				r_cons_printf (" %s", r);
1909 			}
1910 			r_cons_strcat (Color_RESET);
1911 			char *rrstr = r_core_anal_hasrefs (core, *addr, true);
1912 			if (rrstr && *rrstr && strchr (rrstr, 'R')) {
1913 				r_cons_printf ("    ;%s"Color_RESET, rrstr);
1914 			}
1915 			r_cons_newline ();
1916 		}
1917 	}
1918 	r_list_free (sorted);
1919 	ht_up_free (db);
1920 }
1921 
r_core_debug_rr(RCore * core,RReg * reg,int mode)1922 R_API void r_core_debug_rr(RCore *core, RReg *reg, int mode) {
1923 	char *color = "";
1924 	char *colorend = "";
1925 	int had_colors = r_config_get_i (core->config, "scr.color");
1926 	bool use_colors = had_colors != 0;
1927 	int delta = 0;
1928 	ut64 diff, value;
1929 	int bits = core->rasm->bits;
1930 	//XXX: support other RRegisterType
1931 	RList *list = r_reg_get_list (reg, R_REG_TYPE_GPR);
1932 	RListIter *iter;
1933 	RRegItem *r;
1934 	RTable *t = r_core_table (core, "regs");
1935 
1936 	if (mode == 'j') {
1937 		r_config_set_i (core->config, "scr.color", false);
1938 		use_colors = 0;
1939 	}
1940 
1941 	if (use_colors) {
1942 #undef ConsP
1943 #define ConsP(x) (core->cons && core->cons->context->pal.x) ? core->cons->context->pal.x
1944 		color = ConsP(creg): Color_BWHITE;
1945 		colorend = Color_RESET;
1946 	}
1947 
1948 	r_table_set_columnsf (t, "ssss", "role", "reg", "value", "refstr");
1949 	r_list_foreach (list, iter, r) {
1950 		if (r->size != bits) {
1951 			continue;
1952 		}
1953 
1954 		value = r_reg_get_value (core->dbg->reg, r);
1955 		delta = 0;
1956 		int regSize = r->size;
1957 		//XXX: support larger regSize
1958 		if (regSize < 80) {
1959 			r_reg_arena_swap (core->dbg->reg, false);
1960 			diff = r_reg_get_value (core->dbg->reg, r);
1961 			r_reg_arena_swap (core->dbg->reg, false);
1962 			delta = value-diff;
1963 		}
1964 
1965 		const char *role = "";
1966 		int i;
1967 		for (i = 0; i < R_REG_NAME_LAST; i++) {
1968 			const char *t = r_reg_get_name (reg, i);
1969 			if (t && !strcmp (t, r->name)) {
1970 				role = r_reg_get_role (i);
1971 			}
1972 		}
1973 
1974 		char *namestr = NULL;
1975 		char *valuestr = NULL;
1976 		if (delta && use_colors) {
1977 			namestr = r_str_newf ("%s%s%s", color, r->name, colorend);
1978 			valuestr = r_str_newf ("%s%"PFMT64x"%s", color, value, colorend);
1979 		} else {
1980 			namestr = r_str_new (r->name);
1981 			valuestr = r_str_newf ("%"PFMT64x, value);
1982 		}
1983 
1984 		char *rrstr = r_core_anal_hasrefs (core, value, true);
1985 		if (!rrstr) {
1986 			rrstr = strdup ("");
1987 		}
1988 
1989 		r_table_add_rowf (t, "ssss", role, namestr, valuestr, rrstr);
1990 		free (namestr);
1991 		free (valuestr);
1992 		free (rrstr);
1993 	}
1994 
1995 	char *s = (mode == 'j')? r_table_tojson (t): r_table_tostring (t);
1996 	r_cons_print (s);
1997 	free (s);
1998 	r_table_free (t);
1999 
2000 	if (had_colors) {
2001 		r_config_set_i (core->config, "scr.color", had_colors);
2002 	}
2003 }
2004 
show_drpi(RCore * core)2005 static void show_drpi(RCore *core) {
2006 	int i;
2007 	RListIter *iter;
2008 	RRegItem *ri;
2009 	r_cons_printf ("Aliases (Reg->name)\n");
2010 	for (i = 0; i < R_REG_NAME_LAST; i++) {
2011 		r_cons_printf ("%d %s %s\n", i, r_reg_get_role (i), core->anal->reg->name[i]);
2012 	}
2013 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
2014 		const char *nmi = r_reg_get_type (i);
2015 		r_cons_printf ("regset %d (%s)\n", i, nmi);
2016 		RRegSet *rs = &core->anal->reg->regset[i];
2017 		r_cons_printf ("* arena %s size %d\n", r_reg_get_type (i), rs->arena->size);
2018 		r_list_foreach (rs->regs, iter, ri) {
2019 			const char *tpe = r_reg_get_type (ri->type);
2020 			const char *arn = r_reg_get_type (ri->arena);
2021 			r_cons_printf ("   %s %s @ %s (offset: %d  size: %d)", ri->name, tpe, arn, ri->offset / 8, ri->size / 8);
2022 			if ((ri->offset / 8) + (ri->size / 8) > rs->arena->size) {
2023 				r_cons_printf (" *OVERFLOW*");
2024 			}
2025 			r_cons_newline ();
2026 		}
2027 	}
2028 }
2029 
cmd_reg_profile(RCore * core,char from,const char * str)2030 static void cmd_reg_profile(RCore *core, char from, const char *str) { // "arp" and "drp"
2031 	const char *ptr;
2032 	RReg *r = r_config_get_i (core->config, "cfg.debug")? core->dbg->reg: core->anal->reg;
2033 	switch (str[1]) {
2034 	case '\0': // "drp" "arp"
2035 		if (r->reg_profile_str) {
2036 			r_cons_println (r->reg_profile_str);
2037 		} else {
2038 			eprintf ("No register profile defined. Try 'dr.'\n");
2039 		}
2040 		break;
2041 	case 'c': // "drpc" "arpc"
2042 		if (core->dbg->reg->reg_profile_cmt) {
2043 			r_cons_println (r->reg_profile_cmt);
2044 		}
2045 		break;
2046 	case 'g': // "drpg" "arpg"
2047 		ptr = r_str_trim_head_ro (str + 2);
2048 		if (!R_STR_ISEMPTY (ptr)) {
2049 			char *r2profile = r_reg_parse_gdb_profile (ptr);
2050 			if (r2profile) {
2051 				r_cons_println (r2profile);
2052 				core->num->value = 0;
2053 				free (r2profile);
2054 			} else {
2055 				core->num->value = 1;
2056 				eprintf ("Warning: Cannot parse gdb profile.\n");
2057 			}
2058 		} else {
2059 			eprintf ("Usage: arpg [gdb-reg-profile]\n");
2060 		}
2061 		break;
2062 	case ' ': // "drp " "arp "
2063 		ptr = r_str_trim_head_ro (str + 2);
2064 		r_reg_set_profile (r, ptr);
2065 		r_debug_plugin_set_reg_profile (core->dbg, ptr);
2066 		break;
2067 	case '.': { // "drp."
2068 		RRegSet *rs = r_reg_regset_get (r, R_REG_TYPE_GPR);
2069 		if (rs) {
2070 			eprintf ("size = %d\n", rs->arena->size);
2071 		}
2072 		}
2073 		break;
2074 	case 'i': // "drpi" "arpi"
2075 		show_drpi (core);
2076 		break;
2077 	case 's': // "drps" "arps"
2078 		if (str[2] == ' ') {
2079 			ut64 n = r_num_math (core->num, str+2);
2080 			// TODO: move this thing into the r_reg API
2081 			RRegSet *rs = r_reg_regset_get (core->dbg->reg, R_REG_TYPE_GPR);
2082 			if (rs && n>0) {
2083 				RListIter *iter;
2084 				RRegArena *arena;
2085 				r_list_foreach (rs->pool, iter, arena) {
2086 					ut8 *newbytes = calloc (1, n);
2087 					if (newbytes) {
2088 						free (arena->bytes);
2089 						arena->bytes = newbytes;
2090 						arena->size = n;
2091 					} else {
2092 						eprintf ("Cannot allocate %d\n", (int)n);
2093 					}
2094 				}
2095 			} else {
2096 				eprintf ("Invalid arena size\n");
2097 			}
2098 		} else {
2099 			RRegSet *rs = r_reg_regset_get (core->dbg->reg, R_REG_TYPE_GPR);
2100 			if (rs) {
2101 				r_cons_printf ("%d\n", rs->arena->size);
2102 			} else eprintf ("Cannot find GPR register arena.\n");
2103 		}
2104 		break;
2105 	case 'j': // "drpj" "arpj"
2106 		{
2107 			// "drpj" .. dup from "arpj"
2108 			RListIter *iter;
2109 			RRegItem *r;
2110 			int i;
2111 			PJ *pj = r_core_pj_new (core);
2112 			if (!pj) {
2113 				return;
2114 			}
2115 			pj_o (pj);
2116 			pj_k (pj, "alias_info");
2117 			pj_a (pj);
2118 			for (i = 0; i < R_REG_NAME_LAST; i++) {
2119 				if (core->dbg->reg->name[i]) {
2120 					pj_o (pj);
2121 					pj_kn (pj, "role", i);
2122 					pj_ks (pj, "role_str", r_reg_get_role (i));
2123 					pj_ks (pj, "reg", core->dbg->reg->name[i]);
2124 					pj_end (pj);
2125 				}
2126 			}
2127 			pj_end (pj);
2128 			pj_k (pj, "reg_info");
2129 			pj_a (pj);
2130 			for (i = 0; i < R_REG_TYPE_LAST; i++) {
2131 				r_list_foreach (core->dbg->reg->regset[i].regs, iter, r) {
2132 					pj_o (pj);
2133 					pj_kn (pj, "type", r->type);
2134 					pj_ks (pj, "type_str", r_reg_get_type (r->type));
2135 					pj_ks (pj, "name", r->name);
2136 					pj_kn (pj, "size", r->size);
2137 					pj_kn (pj, "offset", r->offset);
2138 					pj_end (pj);
2139 				}
2140 			}
2141 			pj_end (pj); // "]"
2142 			pj_end (pj); // "}"
2143 			r_cons_printf ("%s", pj_string (pj));
2144 			pj_free (pj);
2145 		}
2146 		break;
2147 	case '?': // "drp?" "arp?"
2148 	default:
2149 		{
2150 			const char *from_a[] = { "arp", "arpi", "arpg", "arp.", "arpj", "arps" };
2151 			// TODO #7967 help refactor
2152 			const char **help_msg = help_msg_drp;
2153 			if (from == 'a') {
2154 				help_msg[1] = help_msg[3] = help_msg[6] = help_msg[9] = from_a[0];
2155 				help_msg[12] = from_a[1];
2156 				help_msg[15] = from_a[2];
2157 				help_msg[18] = from_a[3];
2158 				help_msg[21] = from_a[4];
2159 			}
2160 			r_core_cmd_help (core, help_msg);
2161 			break;
2162 		}
2163 	}
2164 }
2165 
2166 
2167 #if 0
2168 static int showreg(RCore *core, const char *str, bool use_color) {
2169 	ut64 off;
2170 	utX value;
2171 	int err;
2172 	int bits = atoi (str);
2173 	r_debug_reg_sync (core->dbg, R_REG_TYPE_ALL, false); //R_REG_TYPE_GPR, false);
2174 	if (bits) {
2175 		r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, bits, str[0], use_color? Color_GREEN: NULL);
2176 	} else {
2177 		off = r_debug_reg_get_err (core->dbg, str + 1, &err, &value);
2178 		core->num->value = off;
2179 		switch (err) {
2180 		case 0:
2181 			r_cons_printf ("0x%08"PFMT64x"\n", off);
2182 			break;
2183 		case 1:
2184 			r_cons_printf ("Unknown register '%s'\n", str + 1);
2185 			break;
2186 		case 80:
2187 			r_cons_printf ("0x%04x%016"PFMT64x"\n", value.v80.High, value.v80.Low);
2188 			break;
2189 		case 96:
2190 			r_cons_printf ("0x%08x%016"PFMT64x"\n", value.v96.High, value.v96.Low);
2191 			break;
2192 		case 128:
2193 			r_cons_printf ("0x%016"PFMT64x"%016"PFMT64x"\n", value.v128.High, value.v128.Low);
2194 			break;
2195 		default:
2196 			r_cons_printf ("Error %i while retrieving '%s' \n", err, str + 1);
2197 			core->num->value = 0;
2198 		}
2199 	}
2200 	return bits;
2201 }
2202 #endif
2203 
2204 // helpers for packed registers
2205 #define NUM_PACK_TYPES 6
2206 #define NUM_INT_PACK_TYPES 4
2207 int pack_sizes[NUM_PACK_TYPES] = { 8, 16, 32, 64, 32, 64 };
2208 char *pack_format[NUM_PACK_TYPES] = { "%s0x%02" PFMT64x, "%s0x%04" PFMT64x, "%s0x%08" PFMT64x,
2209 									  "%s0x%016" PFMT64x, "%s%lf" , "%s%lf" };
2210 #define pack_print(i, reg, pack_type_index) r_cons_printf (pack_format[pack_type_index], i != 0 ? " " : "", reg);
2211 
cmd_debug_reg_print_packed_reg(RCore * core,RRegItem * item,char explicit_size,char * pack_show)2212 static void cmd_debug_reg_print_packed_reg(RCore *core, RRegItem *item, char explicit_size, char* pack_show)	{
2213 	int pi, i;
2214 	for (pi = 0; pi < NUM_PACK_TYPES; pi++) {
2215 		if (!explicit_size || pack_show[pi]) {
2216 			for (i = 0; i < item->packed_size / pack_sizes[pi]; i++) {
2217 				ut64 res = r_reg_get_pack(core->dbg->reg, item, i, pack_sizes[pi]);
2218 				if( pi > NUM_INT_PACK_TYPES-1)	{ // are we printing int or double?
2219 					if (pack_sizes[pi] == 64)	{
2220 						double dres;
2221 						memcpy ((void*)&dres, (void*)&res, 8);
2222 						pack_print (i, dres, pi);
2223 					} else if (pack_sizes[pi] == 32) {
2224 						float fres;
2225 						memcpy ((void*)&fres, (void*)&res, 4);
2226 						pack_print (i, fres, pi);
2227 					}
2228 				} else {
2229 					pack_print (i, res, pi);
2230 				}
2231 			}
2232 			r_cons_newline ();
2233 		}
2234 	}
2235 }
2236 
__table_format_string(RTable * t,int fmt)2237 static char *__table_format_string(RTable *t, int fmt) {
2238 	switch (fmt) {
2239 	case 'j': return r_table_tojson (t);
2240 	case 's': return r_table_tostring (t);
2241 	}
2242 	return r_table_tofancystring (t);
2243 }
2244 
__tableRegList(RCore * core,RReg * reg,const char * str)2245 static void __tableRegList (RCore *core, RReg *reg, const char *str) {
2246 	int i;
2247 	RRegItem *e;
2248 	RTable *t = r_core_table (core, "regprofile");
2249 	RTableColumnType *typeString = r_table_type ("string");
2250 	RTableColumnType *typeNumber = r_table_type ("number");
2251 	RTableColumnType *typeBoolean = r_table_type ("boolean");
2252 	r_table_add_column (t, typeNumber, "offset", 0);
2253 	r_table_add_column (t, typeNumber, "size", 0);
2254 	r_table_add_column (t, typeNumber, "psize", 0);
2255 	r_table_add_column (t, typeNumber, "index", 0);
2256 	r_table_add_column (t, typeNumber, "arena", 0);
2257 	r_table_add_column (t, typeBoolean, "float", 0);
2258 	r_table_add_column (t, typeString, "name", 0);
2259 	r_table_add_column (t, typeString, "flags", 0);
2260 	r_table_add_column (t, typeString, "comment", 0);
2261 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
2262 		RList *list = r_reg_get_list (reg, i);
2263 		RListIter *iter;
2264 		r_list_foreach (list, iter, e) {
2265 			// sdb_fmt is not thread safe
2266 			r_table_add_row (t,
2267 					sdb_fmt ("%d", e->offset),
2268 					sdb_fmt ("%d", e->size),
2269 					sdb_fmt ("%d", e->packed_size),
2270 					sdb_fmt ("%d", e->index),
2271 					sdb_fmt ("%d", i),
2272 					r_str_bool (e->is_float),
2273 					r_str_get (e->name),
2274 					r_str_get (e->flags),
2275 					r_str_get (e->comment),
2276 					NULL
2277 					);
2278 		}
2279 	}
2280 	const char fmt = *str++;
2281 	const char *q = str;
2282 	if (r_table_query (t, q)) {
2283 		char *s = __table_format_string (t, fmt);
2284 		r_cons_printf ("%s\n", s);
2285 		free (s);
2286 	}
2287 	r_table_free (t);
2288 }
2289 
cmd_debug_reg(RCore * core,const char * str)2290 static void cmd_debug_reg(RCore *core, const char *str) {
2291 	char *arg;
2292 	struct r_reg_item_t *r;
2293 	const char *name, *use_color;
2294 	size_t i;
2295 	int size, type = R_REG_TYPE_GPR;
2296 	int bits = (core->dbg->bits & R_SYS_BITS_64)? 64: 32;
2297 	int use_colors = r_config_get_i (core->config, "scr.color");
2298 	int newbits = atoi ((str&&*str)? str + 1: "");
2299 	if (newbits > 0) {
2300 		bits = newbits;
2301 	}
2302 	if (use_colors) {
2303 #undef ConsP
2304 #define ConsP(x) (core->cons && core->cons->context->pal.x)? core->cons->context->pal.x
2305 		use_color = ConsP(creg): Color_BWHITE;
2306 	} else {
2307 		use_color = NULL;
2308 	}
2309 	if (!str) {
2310 		str = "";
2311 	}
2312 	switch (str[0]) {
2313 	case 'C': // "drC"
2314 		{
2315 			const bool json_out = str[1] == 'j';
2316 			name = r_str_trim_head_ro (json_out ? str + 3 : str + 2);
2317 			if (name) {
2318 				r = r_reg_get (core->dbg->reg, name , -1);
2319 				if (r) {
2320 					if (json_out) {
2321 						PJ *pj = r_core_pj_new (core);
2322 						if (!pj) {
2323 							return;
2324 						}
2325 						pj_o (pj);
2326 						if (r->comment) {
2327 							pj_ks (pj, r->name, r->comment);
2328 						} else {
2329 							pj_knull (pj, r->name);
2330 						}
2331 						pj_end (pj);
2332 						const char *s = pj_string (pj);
2333 						r_cons_println (s);
2334 						pj_free (pj);
2335 					} else {
2336 						if (r->comment) {
2337 							r_cons_printf ("%s\n", r->comment);
2338 						} else {
2339 							eprintf ("Register %s doesn't have any comments\n", name);
2340 						}
2341 					}
2342 				} else {
2343 					eprintf ("Register %s not found\n", name);
2344 				}
2345 			} else {
2346 				eprintf ("usage: drC [register]\n");
2347 			}
2348 		}
2349 		break;
2350 	case '-': // "dr-"
2351 		r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, bits, NULL, '-', 0);
2352 		break;
2353 	case '?': // "dr?"
2354 		if (str[1]) {
2355 			RListIter *iter;
2356 			char *all = (char *)r_str_trim_head_ro (str + 1);
2357 			if (!strcmp (all, "?")) { // "dr??"
2358 				all = r_core_cmd_str (core, "drp~=[0]");
2359 				all = r_str_replace (all, "\n", " ", 1);
2360 			} else {
2361 				all = strdup (all);
2362 			}
2363 			char *arg;
2364 			RList *args = r_str_split_list (all, " ", 0);
2365 			r_debug_reg_sync (core->dbg, R_REG_TYPE_ALL, false); //R_REG_TYPE_GPR, false);
2366 			int count = r_list_length (args);
2367 			r_list_foreach (args, iter, arg) {
2368 				ut64 off = r_debug_reg_get (core->dbg, arg);
2369 				if (count == 1) {
2370 					r_cons_printf ("0x%08"PFMT64x"\n", off);
2371 				} else {
2372 					int type = r_reg_get_name_idx (arg);
2373 					const char *r = arg;
2374 					if (type != -1) {
2375 						r = r_reg_get_name (core->dbg->reg, type);
2376 					}
2377 					r_cons_printf ("%3s %3s 0x%08"PFMT64x"\n", arg, r, off);
2378 				}
2379 				core->num->value = off;
2380 			}
2381 			free (all);
2382 			r_list_free (args);
2383 		} else {
2384 			r_core_cmd_help (core, help_msg_dr);
2385 		}
2386 		break;
2387 	case 'l': // "drl[j]"
2388 		{
2389 			const bool json_out = str[1] == 'j';
2390 			RRegSet *rs = r_reg_regset_get (core->dbg->reg, R_REG_TYPE_GPR);
2391 			if (rs) {
2392 				RRegItem *r;
2393 				RListIter *iter;
2394 				i = 0;
2395 				PJ *pj = NULL;
2396 				if (json_out) {
2397 					pj = r_core_pj_new (core);
2398 					if (!pj) {
2399 						return;
2400 					}
2401 					pj_a (pj);
2402 				}
2403 				r_list_foreach (rs->regs, iter, r) {
2404 					if (json_out) {
2405 						pj_s (pj, r->name);
2406 						i++;
2407 					} else {
2408 						r_cons_println (r->name);
2409 					}
2410 				}
2411 				if (json_out) {
2412 					pj_end (pj);
2413 					const char *s = pj_string (pj);
2414 					r_cons_println (s);
2415 					pj_free (pj);
2416 				}
2417 			}
2418 		}
2419 		break;
2420 	case '8': // "dr8"
2421 	case 'b': // "drb"
2422 		{
2423 			int len, type = R_REG_TYPE_GPR;
2424 			arg = strchr (str, ' ');
2425 			if (arg) {
2426 				char *string = r_str_trim_dup (arg + 1);
2427 				if (string) {
2428 					type = r_reg_type_by_name (string);
2429 					if (type == -1 && string[0] != 'a') {
2430 						type = R_REG_TYPE_GPR;
2431 					}
2432 					free (string);
2433 				}
2434 			}
2435 			ut8 *buf = r_reg_get_bytes (core->dbg->reg, type, &len);
2436 			if (str[0] == '8') {
2437 				r_print_bytes (core->print, buf, len, "%02x");
2438 			} else {
2439 				switch (str[1]) {
2440 				case '1':
2441 					r_print_hexdump (core->print, 0ll, buf, len, 8, 1, 1);
2442 					break;
2443 				case '2':
2444 					r_print_hexdump (core->print, 0ll, buf, len, 16, 2, 1);
2445 					break;
2446 				case '4':
2447 					r_print_hexdump (core->print, 0ll, buf, len, 32, 4, 1);
2448 					break;
2449 				case '8':
2450 					r_print_hexdump (core->print, 0ll, buf, len, 64, 8, 1);
2451 					break;
2452 				default:
2453 					if (core->rasm->bits == 64) {
2454 						r_print_hexdump (core->print, 0ll, buf, len, 64, 8, 1);
2455 					} else {
2456 						r_print_hexdump (core->print, 0ll, buf, len, 32, 4, 1);
2457 					}
2458 					break;
2459 				}
2460 			}
2461 			free (buf);
2462 		}
2463 		break;
2464 	case 'c': // "drc"
2465 		// todo: set flag values with drc zf=1
2466 		if (str[1] == '=') {
2467 			RRegFlags *rf = r_reg_cond_retrieve (core->dbg->reg, NULL);
2468 			if (rf) {
2469 				r_cons_printf ("s:%d z:%d c:%d o:%d p:%d\n",
2470 						rf->s, rf->z, rf->c, rf->o, rf->p);
2471 				free (rf);
2472 			}
2473 		} else if (strchr (str, '=')) {
2474 			char *a = strdup (r_str_trim_head_ro (str + 1));
2475 			char *eq = strchr (a, '=');
2476 			if (eq) {
2477 				*eq++ = 0;
2478 				char *k = a;
2479 				r_str_trim (a);
2480 				bool v = !strcmp (eq, "true") || atoi (eq);
2481 				int type = r_reg_cond_from_string (k);
2482 				if (type != -1) {
2483 					RRegFlags *rf = r_reg_cond_retrieve (core->dbg->reg, NULL);
2484 					if (rf) {
2485 						r_reg_cond_bits_set (core->dbg->reg, type, rf, v);
2486 						r_reg_cond_apply (core->dbg->reg, rf);
2487 						r_debug_reg_sync (core->dbg, R_REG_TYPE_ALL, true);
2488 						free (rf);
2489 					}
2490 				} else {
2491 					eprintf ("Unknown condition register\n");
2492 				}
2493 			}
2494 			free (a);
2495 		} else {
2496 			RRegItem *r;
2497 			const char *name = r_str_trim_head_ro (str + 1);
2498 			if (*name && name[1]) {
2499 				r = r_reg_cond_get (core->dbg->reg, name);
2500 				if (r) {
2501 					r_cons_println (r->name);
2502 				} else {
2503 					int id = r_reg_cond_from_string (name);
2504 					RRegFlags* rf = r_reg_cond_retrieve (core->dbg->reg, NULL);
2505 					if (rf) {
2506 						int o = r_reg_cond_bits (core->dbg->reg, id, rf);
2507 						core->num->value = o;
2508 						// orly?
2509 						r_cons_printf ("%d\n", o);
2510 						free (rf);
2511 					} else eprintf ("unknown conditional or flag register\n");
2512 				}
2513 			} else {
2514 				RRegFlags *rf = r_reg_cond_retrieve (core->dbg->reg, NULL);
2515 				if (rf) {
2516 					if (*name=='=') {
2517 						for (i=0; i<R_REG_COND_LAST; i++) {
2518 							r_cons_printf ("%s:%d ",
2519 									r_reg_cond_to_string (i),
2520 									r_reg_cond_bits (core->dbg->reg, i, rf));
2521 						}
2522 						r_cons_newline ();
2523 					} else {
2524 						for (i=0; i<R_REG_COND_LAST; i++) {
2525 							r_cons_printf ("%d %s\n",
2526 									r_reg_cond_bits (core->dbg->reg, i, rf),
2527 									r_reg_cond_to_string (i));
2528 						}
2529 					}
2530 					free (rf);
2531 				}
2532 			}
2533 		}
2534 		break;
2535 	case 'x': // "drx"
2536 		switch (str[1]) {
2537 		case '\0':
2538 			r_debug_reg_sync (core->dbg, R_REG_TYPE_DRX, false);
2539 			r_debug_drx_list (core->dbg);
2540 			break;
2541 		case '-':
2542 			r_debug_reg_sync (core->dbg, R_REG_TYPE_DRX, false);
2543 			r_debug_drx_unset (core->dbg, atoi (str + 2));
2544 			r_debug_reg_sync (core->dbg, R_REG_TYPE_DRX, true);
2545 			break;
2546 		case ' ': {
2547 				  char *s = strdup (str+2);
2548 				  char sl, n, perm;
2549 				  int len;
2550 				  ut64 off;
2551 
2552 				  sl = r_str_word_set0 (s);
2553 				  if (sl == 4) {
2554 #define arg(x) r_str_word_get0(s,x)
2555 					  n = (char)r_num_math (core->num, arg(0));
2556 					  off = r_num_math (core->num, arg(1));
2557 					  len = (int)r_num_math (core->num, arg(2));
2558 					  perm = (char)r_str_rwx (arg (3));
2559 					  if (len == -1) {
2560 						  r_debug_reg_sync (core->dbg, R_REG_TYPE_DRX, false);
2561 						  r_debug_drx_set (core->dbg, n, 0, 0, 0, 0);
2562 						  r_debug_reg_sync (core->dbg, R_REG_TYPE_DRX, true);
2563 					  } else {
2564 						  r_debug_reg_sync (core->dbg, R_REG_TYPE_DRX, false);
2565 						  r_debug_drx_set (core->dbg, n, off, len, perm, 0);
2566 						  r_debug_reg_sync (core->dbg, R_REG_TYPE_DRX, true);
2567 					  }
2568 				  } else {
2569 					eprintf ("|usage: drx n [address] [length] [perm]\n");
2570 				  }
2571 				  free (s);
2572 			  } break;
2573 		case '?':
2574 		default:
2575 			r_core_cmd_help (core, help_msg_drx);
2576 			break;
2577 		}
2578 		break;
2579 	case 's': // "drs"
2580 		switch (str[1]) {
2581 		case '\0': // "drs"
2582 			r_cons_printf ("%d\n", r_list_length (
2583 						core->dbg->reg->regset[0].pool));
2584 			break;
2585 		case '-': // "drs-"
2586 			r_reg_arena_pop (core->dbg->reg);
2587 			// restore debug registers if in debugger mode
2588 			r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, true);
2589 			break;
2590 		case '+': // "drs+"
2591 			r_reg_arena_push (core->dbg->reg);
2592 			break;
2593 		case '?': // "drs?"
2594 		default:
2595 			r_core_cmd_help (core, help_msg_drs);
2596 			break;
2597 		}
2598 		break;
2599 	case 'm': // "drm"
2600 		if (str[1]=='?') {
2601 			r_core_cmd_help (core, help_msg_drm);
2602 		} else if (str[1] == ' ' || str[1] == 'b' || str[1] == 'd' || str[1] == 'w' || str[1] == 'q' || str[1] == 'l'
2603 				   || str[1] == 'f' || (str[1] == 'y' && str[2] != '\x00')) {
2604 			char explicit_index = 0;
2605 			char explicit_size = 0;
2606 			char explicit_name = 0;
2607 			char pack_show[NUM_PACK_TYPES] = { 0, 0, 0, 0, 0, 0};
2608 			int index = 0;
2609 			int size = 0; // auto
2610 			char *q, *p, *name;
2611 			char *eq = NULL;
2612 			RRegisterType reg_type = R_REG_TYPE_XMM;
2613 			if ((str[1] == ' ' && str[2] != '\x00') || (str[1] == 'y' && str[2] == ' ' && str[3] != '\x00')) {
2614 				if (str[1] == 'y') { // support `drmy ymm0` and `drm ymm0`
2615 					str = str + 1;
2616 				}
2617 				name = strdup (str + 2);
2618 				explicit_name = 1;
2619 				eq = strchr (name, '=');
2620 				if (eq) {
2621 					*eq++ = 0;
2622 				}
2623 				p = strchr (name, ' ');
2624 				if (p) {
2625 					*p++ = 0;
2626 					q = strchr (p, ' ');
2627 					if (p[0] != '*') {
2628 						// do not show whole register
2629 						explicit_index = 1;
2630 						index = r_num_math (core->num, p);
2631 					}
2632 					if (q) {
2633 						*q++ = 0;
2634 						size = r_num_math (core->num, q);
2635 						for (i = 0; i < NUM_PACK_TYPES; i++) {
2636 							if (size == pack_sizes[i]) {
2637 								explicit_size = 1;
2638 								pack_show[i] = 1;
2639 							}
2640 						}
2641 						if (!explicit_size) {
2642 							eprintf ("Unsupported wordsize %d\n", size);
2643 							break;
2644 						}
2645 					}
2646 				}
2647 			} else {
2648 				explicit_size = 1;
2649 				if (str[1] == 'y') {
2650 					reg_type = R_REG_TYPE_YMM;
2651 					str = str + 1;
2652 				}
2653 				if (str[2] == ' ' && str[3] != '\x00') {
2654 					name = strdup (str + 3);
2655 					explicit_name = 1;
2656 				}
2657 				switch (str[1])	{
2658 				case 'b': // "drmb"
2659 					size = pack_sizes[0];
2660 					pack_show[0] = 1;
2661 					break;
2662 				case 'w': // "drmw"
2663 					size = pack_sizes[1];
2664 					pack_show[1] = 1;
2665 					break;
2666 				case 'd': // "drmd"
2667 					size = pack_sizes[2];
2668 					pack_show[2] = 1;
2669 					break;
2670 				case 'q': // "drmq"
2671 					size = pack_sizes[3];
2672 					pack_show[3] = 1;
2673 					break;
2674 				case 'f': // "drmf"
2675 					size = pack_sizes[4];
2676 					pack_show[4] = 1;
2677 					break;
2678 				case 'l': // "drml"
2679 					size = pack_sizes[5];
2680 					pack_show[5] = 1;
2681 					break;
2682 				default:
2683 					eprintf ("Unkown comamnd");
2684 					return;
2685 				}
2686 			}
2687 			if (explicit_name) {
2688 				RRegItem *item = r_reg_get (core->dbg->reg, name, -1);
2689 				if (item) {
2690 					if (eq) {
2691 						// TODO: support setting YMM registers
2692 						if (reg_type == R_REG_TYPE_YMM) {
2693 							eprintf ("Setting ymm registers not supported yet!\n");
2694 						} else {
2695 							ut64 val = r_num_math (core->num, eq);
2696 							r_reg_set_pack (core->dbg->reg, item, index, size, val);
2697 							r_debug_reg_sync (core->dbg, reg_type, true);
2698 						}
2699 					} else {
2700 						r_debug_reg_sync (core->dbg, reg_type, false);
2701 						if (!explicit_index) {
2702 							cmd_debug_reg_print_packed_reg (core, item, explicit_size, pack_show);
2703 						} else {
2704 							ut64 res = r_reg_get_pack (core->dbg->reg, item, index, size);
2705 							// print selected index / wordsize
2706 							r_cons_printf ("0x%08" PFMT64x "\n", res);
2707 						}
2708 					}
2709 				} else {
2710 					eprintf ("cannot find multimedia register '%s'\n", name);
2711 				}
2712 				free (name);
2713 			} else {
2714 				// explicit size no name
2715 				RListIter *iter;
2716 				RRegItem *item;
2717 				RList *head;
2718 				r_debug_reg_sync (core->dbg, reg_type, false);
2719 				head = r_reg_get_list (core->dbg->reg, reg_type);
2720 				if (head) {
2721 					r_list_foreach (head, iter, item) {
2722 						if (item->type != reg_type) {
2723 							continue;
2724 						}
2725 						r_cons_printf ("%-5s = ", item->name);
2726 						cmd_debug_reg_print_packed_reg (core, item, explicit_size, pack_show);
2727 					}
2728 				}
2729 			}
2730 		} else { // drm # no arg
2731 			if (str[1] == 'y') { // drmy
2732 				r_debug_reg_sync (core->dbg, R_REG_TYPE_YMM, false);
2733 				r_debug_reg_list (core->dbg, R_REG_TYPE_YMM, 256, NULL, 0, 0);
2734 			} else { // drm
2735 				r_debug_reg_sync (core->dbg, R_REG_TYPE_XMM, false);
2736 				r_debug_reg_list (core->dbg, R_REG_TYPE_XMM, 128, NULL, 0, 0);
2737 			}
2738 		}
2739 		//r_debug_drx_list (core->dbg);
2740 		break;
2741 	case 'f': // "drf"
2742 		//r_debug_drx_list (core->dbg);
2743 		if (str[1]=='?') {
2744 			eprintf ("usage: drf [fpureg] [= value]\n");
2745 		} else if (str[1]==' ') {
2746 			char *p, *name = strdup (str + 2);
2747 			char *eq = strchr (name, '=');
2748 			if (eq) {
2749 				*eq++ = 0;
2750 			}
2751 			p = strchr (name, ' ');
2752 			if (p) {
2753 				*p++ = 0;
2754 			}
2755 			RRegItem *item = r_reg_get (core->dbg->reg, name, -1);
2756 			if (item) {
2757 				if (eq) {
2758 					long double val = 0.0f;
2759 #if __windows__
2760 					double dval = 0.0f;
2761 					sscanf (eq, "%lf", (double*)&dval);
2762 					val = dval;
2763 #else
2764 					sscanf (eq, "%Lf", &val);
2765 #endif
2766 					r_reg_set_double (core->dbg->reg, item, val);
2767 					r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, true);
2768 					r_debug_reg_sync (core->dbg, R_REG_TYPE_FPU, true);
2769 				} else {
2770 					r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false);
2771 					r_debug_reg_sync (core->dbg, R_REG_TYPE_FPU, false);
2772 					long double res = r_reg_get_longdouble (core->dbg->reg, item);
2773 					r_cons_printf ("%Lf\n", res);
2774 				}
2775 			} else {
2776 				/* note, that negative type forces sync to print the regs from the backend */
2777 				eprintf ("cannot find multimedia register '%s'\n", name);
2778 			}
2779 			free (name);
2780 		} else {
2781 			//TODO: Do not use this hack to print fpu register
2782 			r_debug_reg_sync (core->dbg, -R_REG_TYPE_FPU, false);
2783 		}
2784 		break;
2785 	case 'p': // "drp"
2786 		cmd_reg_profile (core, 'd', str);
2787 		break;
2788 	case 't': { // "drt"
2789 		char rad = 0;
2790 		switch (str[1]) {
2791 		case '\0': // "drt"
2792 			for (i = 0; (name = r_reg_get_type (i)); i++) {
2793 				r_cons_println (name);
2794 			}
2795 			break;
2796 		case 'j': // "drtj"
2797 		case '*': // "drt*"
2798 			rad = str[1];
2799 			str++;
2800 			if (rad == 'j' && !str[1]) {
2801 				PJ *pj = r_core_pj_new (core);
2802 				if (!pj) {
2803 					break;
2804 				}
2805 				pj_a (pj);
2806 				for (i = 0; (name = r_reg_get_type (i)); i++) {
2807 					pj_s (pj, name);
2808 				}
2809 				pj_end (pj);
2810 				r_cons_println (pj_string (pj));
2811 				pj_free (pj);
2812 				break;
2813 			}
2814 			// fallthrough
2815 		case ' ': // "drt "
2816 		{
2817 			int role = r_reg_get_name_idx (str+2);
2818 			const char *regname = r_reg_get_name (core->dbg->reg, role);
2819 			if (!regname) {
2820 				regname = str + 2;
2821 			}
2822 			size = atoi (regname);
2823 			if (size < 1) {
2824 				char *arg = strchr (str + 2, ' ');
2825 				size = 0;
2826 				if (arg) {
2827 					*arg++ = 0;
2828 					size = atoi (arg);
2829 				}
2830 				type = r_reg_type_by_name (str + 2);
2831 				r_debug_reg_sync (core->dbg, type, false);
2832 				r_debug_reg_list (core->dbg, type, size, NULL, rad, use_color);
2833 			} else {
2834 				if (type != R_REG_TYPE_LAST) {
2835 					r_debug_reg_sync (core->dbg, type, false);
2836 					r_debug_reg_list (core->dbg, type, size, NULL, rad, use_color);
2837 				} else {
2838 					eprintf ("cmd_debug_reg: unknown type\n");
2839 				}
2840 			}
2841 			break;
2842 		}
2843 		case '?': // "drt?"
2844 		default:
2845 			r_core_cmd_help (core, help_msg_drt);
2846 			break;
2847 		}
2848 		}
2849 		break;
2850 	case 'n': // "drn"
2851 		{
2852 			char *foo = strdup (str+2);
2853 			r_str_case (foo, true);
2854 			name = r_reg_get_name (core->dbg->reg, r_reg_get_name_idx (foo));
2855 			if (name && *name) {
2856 				r_cons_println (name);
2857 			} else eprintf ("oops. try drn [pc|sp|bp|a0|a1|a2|a3|a4|r0|r1|zf|sf|nf|of]\n");
2858 			free (foo);
2859 		}
2860 		break;
2861 	case 'd': // "drd"
2862 		r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, bits, NULL, 3, use_color); // xxx detect which one is current usage
2863 		break;
2864 	case 'o': // "dro"
2865 		r_reg_arena_swap (core->dbg->reg, false);
2866 		r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, bits, NULL, 0, use_color); // xxx detect which one is current usage
2867 		r_reg_arena_swap (core->dbg->reg, false);
2868 		break;
2869 	case ',': // "dr,"
2870 		if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false)) {
2871 			__tableRegList (core, core->dbg->reg, str + 1);
2872 		} else {
2873 			eprintf ("cannot retrieve registers from pid %d\n", core->dbg->pid);
2874 		}
2875 		break;
2876 	case '=': // "dr="
2877 		{
2878 			int pcbits2, pcbits = grab_bits (core, str + 1, &pcbits2);
2879 			if (r_config_get_i (core->config, "cfg.debug")) {
2880 				if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false)) {
2881 					if (pcbits && pcbits != bits) {
2882 						r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, pcbits, NULL, '=', use_color); // xxx detect which one is current usage
2883 					}
2884 					r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, bits, NULL, '=', use_color); // xxx detect which one is current usage
2885 					if (pcbits2) {
2886 						r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, pcbits2, NULL, '=', use_color); // xxx detect which one is current usage
2887 					}
2888 				} //else eprintf ("cannot retrieve registers from pid %d\n", core->dbg->pid);
2889 			} else {
2890 				RReg *orig = core->dbg->reg;
2891 				core->dbg->reg = core->anal->reg;
2892 				if (pcbits && pcbits != bits)
2893 					r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, pcbits, NULL, '=', use_color); // xxx detect which one is current usage
2894 				r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, bits, NULL, '=', use_color); // xxx detect which one is current usage
2895 				core->dbg->reg = orig;
2896 			}
2897 		}
2898 		break;
2899 	case '.':
2900 		if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false)) {
2901 			int pcbits2, pcbits = grab_bits (core, str + 1, &pcbits2);
2902 			r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, pcbits, NULL, '.', use_color);
2903 			if (pcbits2) {
2904 				r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, pcbits2, NULL, '.', use_color);
2905 			}
2906 		}
2907 		break;
2908 	case '*': // "dr*"
2909 		if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false)) {
2910 			int pcbits2, pcbits = grab_bits (core, str + 1, &pcbits2);
2911 			r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, pcbits, NULL, '*', use_color);
2912 			if (pcbits2) {
2913 				r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, pcbits2, NULL, '*', use_color);
2914 			}
2915 			r_flag_space_pop (core->flags);
2916 		}
2917 		break;
2918 	case 'i': // "dri"
2919 		r_core_debug_ri (core, core->dbg->reg, 0);
2920 		break;
2921 	case 'r': // "drr"
2922 		switch (str[1]) {
2923 		case 'j': // "drrj"
2924 			r_core_debug_rr (core, core->dbg->reg, 'j');
2925 			break;
2926 		default:
2927 			r_core_debug_rr (core, core->dbg->reg, 0);
2928 			break;
2929 		}
2930 		break;
2931 	case 'j': // "drj"
2932 	case '\0': // "dr"
2933 		if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false)) {
2934 			int pcbits = core->anal->bits;
2935 			const char *pcname = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
2936 			RRegItem *reg = r_reg_get (core->anal->reg, pcname, 0);
2937 			if (reg) {
2938 				if (core->rasm->bits != reg->size) {
2939 					pcbits = reg->size;
2940 				}
2941 			}
2942 			if (str[0] == 'j') {
2943 				PJ *pj = r_core_pj_new (core);
2944 				if (!pj) {
2945 					return;
2946 				}
2947 				r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, pcbits, pj, 'j', use_color);
2948 			} else {
2949 				r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, pcbits, NULL, 0, use_color);
2950 			}
2951 		} else {
2952 			eprintf ("cannot retrieve registers from pid %d\n", core->dbg->pid);
2953 		}
2954 		break;
2955 	case ' ': // "dr"
2956 		arg = strchr (str + 1, '=');
2957 		if (arg) {
2958 			*arg = 0;
2959 			char *string = r_str_trim_dup (str + 1);
2960 			const char *regname = r_reg_get_name (core->dbg->reg, r_reg_get_name_idx (string));
2961 			if (!regname) {
2962 				regname = string;
2963 			}
2964 			r = r_reg_get (core->dbg->reg, regname, -1); //R_REG_TYPE_GPR);
2965 			if (r) {
2966 				if (r->flags) {
2967 					r_cons_printf ("0x%08"PFMT64x" ->",
2968 							r_reg_get_value (core->dbg->reg, r));
2969 					r_reg_set_bvalue (core->dbg->reg, r, arg+1);
2970 					r_debug_reg_sync (core->dbg, R_REG_TYPE_ALL, true);
2971 					r_cons_printf ("0x%08"PFMT64x"\n",
2972 							r_reg_get_value (core->dbg->reg, r));
2973 				} else {
2974 					r_cons_printf ("0x%08"PFMT64x" ->",
2975 							r_reg_get_value (core->dbg->reg, r));
2976 					r_reg_set_value (core->dbg->reg, r,
2977 							r_num_math (core->num, arg+1));
2978 					r_debug_reg_sync (core->dbg, R_REG_TYPE_ALL, true);
2979 					r_cons_printf ("0x%08"PFMT64x"\n",
2980 							r_reg_get_value (core->dbg->reg, r));
2981 				}
2982 			} else {
2983 				eprintf ("unknown register '%s'\n", string);
2984 			}
2985 			free (string);
2986 			// update flags here
2987 			r_core_cmdf (core, ".dr*%d", bits);
2988 			return;
2989 		}
2990 
2991 		size = atoi (str + 1);
2992 		if (size) {
2993 			r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, size, NULL, str[0], use_color);
2994 		} else {
2995 			char *comma = strchr (str + 1, ',');
2996 			if (comma) {
2997 				char *args = strdup (str + 1);
2998 				char argc = r_str_split (args, ',');
2999 				for (i = 0; i < argc; i++) {
3000 					showreg (core, r_str_word_get0 (args, i));
3001 				}
3002 				free (args);
3003 			} else {
3004 				showreg (core, str + 1);
3005 			}
3006 		}
3007 	}
3008 }
3009 
backtrace_vars(RCore * core,RList * frames)3010 static void backtrace_vars(RCore *core, RList *frames) {
3011 	RDebugFrame *f;
3012 	RListIter *iter;
3013 	// anal vs debug ?
3014 	const char *sp = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
3015 	const char *bp = r_reg_get_name (core->anal->reg, R_REG_NAME_BP);
3016 	if (!sp) {
3017 		sp = "SP";
3018 	}
3019 	if (!bp) {
3020 		bp = "BP";
3021 	}
3022 	RReg *r = core->anal->reg;
3023 	ut64 dsp = r_reg_getv (r, sp);
3024 	ut64 dbp = r_reg_getv (r, bp);
3025 	int n = 0;
3026 	r_list_foreach (frames, iter, f) {
3027 		ut64 s = f->sp ? f->sp : dsp;
3028 		ut64 b = f->bp ? f->bp : dbp;
3029 		r_reg_setv (r, bp, s);
3030 		r_reg_setv (r, sp, b);
3031 //////////
3032 		char flagdesc[1024], flagdesc2[1024];
3033 		RFlagItem *fi = r_flag_get_at (core->flags, f->addr, true);
3034 		flagdesc[0] = flagdesc2[0] = 0;
3035 		if (fi) {
3036 			if (fi->offset != f->addr) {
3037 				int delta = (int)(f->addr - fi->offset);
3038 				if (delta > 0) {
3039 					snprintf (flagdesc, sizeof (flagdesc),
3040 							"%s+%d", fi->name, delta);
3041 				} else if (delta < 0) {
3042 					snprintf (flagdesc, sizeof (flagdesc),
3043 							"%s%d", fi->name, delta);
3044 				} else {
3045 					snprintf (flagdesc, sizeof (flagdesc),
3046 							"%s", fi->name);
3047 				}
3048 			} else {
3049 				snprintf (flagdesc, sizeof (flagdesc),
3050 						"%s", fi->name);
3051 			}
3052 		}
3053 //////////
3054 		RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, f->addr, 0);
3055 		// char *str = r_str_newf ("[frame %d]", n);
3056 		r_cons_printf ("%d  0x%08"PFMT64x" sp: 0x%08"PFMT64x" %-5d"
3057 				"[%s]  %s %s\n", n, f->addr, f->sp, (int)f->size,
3058 				fcn ? fcn->name : "??", flagdesc, flagdesc2);
3059 		eprintf ("afvd @ 0x%"PFMT64x"\n", f->addr);
3060 		r_cons_push();
3061 		char *res = r_core_cmd_strf (core, "afvd@0x%"PFMT64x, f->addr);
3062 		r_cons_pop();
3063 		r_cons_printf ("%s", res);
3064 		free (res);
3065 		n++;
3066 	}
3067 	r_reg_setv (r, bp, dbp);
3068 	r_reg_setv (r, sp, dsp);
3069 }
3070 
asciiart_backtrace(RCore * core,RList * frames)3071 static void asciiart_backtrace(RCore *core, RList *frames) {
3072 	// TODO: show local variables
3073 	// TODO: show function/flags/symbols related
3074 	// TODO: show contents of stack
3075 	// TODO: honor scr.color
3076 	RDebugFrame *f;
3077 	RListIter *iter;
3078 	bool mymap = false;
3079 	// anal vs debug ?
3080 	const char *sp = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
3081 	const char *bp = r_reg_get_name (core->anal->reg, R_REG_NAME_BP);
3082 	if (!sp) {
3083 		sp = "SP";
3084 	}
3085 	if (!bp) {
3086 		bp = "BP";
3087 	}
3088 	ut64 dsp = r_reg_getv (core->anal->reg, sp);
3089 	ut64 dbp = r_reg_getv (core->anal->reg, bp);
3090 	RDebugMap *map = r_debug_map_get (core->dbg, dsp);
3091 	if (!map) {
3092 		mymap = true;
3093 		map = R_NEW0 (RDebugMap);
3094 		map->addr = UT64_MAX;
3095 		map->addr_end = UT64_MAX;
3096 	}
3097 
3098 	r_cons_printf ("0x%016"PFMT64x"  STACK END  ^^^\n", map->addr);
3099 	r_cons_printf ("0x%016"PFMT64x"  STACK POINTER: %s\n", dsp, sp);
3100 	r_cons_printf ("                    .------------------------.\n");
3101 	int n = 0;
3102 	r_list_foreach (frames, iter, f) {
3103 		ut64 s = f->sp ? f->sp : dsp;
3104 		ut64 b = f->bp ? f->bp : dbp;
3105 		char *str = r_str_newf ("[frame %d]", n);
3106 		r_cons_printf ("0x%016"PFMT64x"  |%4s    %10s      | ; size %" PFMTDPTR "\n", s, sp, str, (ptrdiff_t)(s - b));
3107 		free (str);
3108 		r_cons_printf ("                    |            ...         |\n");
3109 		r_cons_printf ("0x%016"PFMT64x"  |%4s 0x%016"PFMT64x" | %s\n", b, bp, f->addr, "; return address");
3110 		r_cons_printf ("                    )------------------------(\n");
3111 		// eprintf ("0x%08llx 0x%08llx 0x%08llx\n", f->addr, s, b);
3112 		n++;
3113 	}
3114 	r_cons_printf ("                    |           ...          |\n");
3115 	r_cons_printf ("                    `------------------------'\n");
3116 	r_cons_printf ("0x%016"PFMT64x"  STACK BOTTOM\n", map->addr_end);
3117 	if (mymap) {
3118 		r_debug_map_free (map);
3119 	}
3120 }
3121 
get_backtrace_info(RCore * core,RDebugFrame * frame,ut64 addr,char ** flagdesc,char ** flagdesc2,char ** pcstr,char ** spstr)3122 static void get_backtrace_info(RCore* core, RDebugFrame* frame, ut64 addr, char** flagdesc, char** flagdesc2, char** pcstr, char** spstr) {
3123 	RFlagItem *f = r_flag_get_at (core->flags, frame->addr, true);
3124 	*flagdesc = NULL;
3125 	*flagdesc2 = NULL;
3126 	if (f) {
3127 		if (f->offset != addr) {
3128 			int delta = (int)(frame->addr - f->offset);
3129 			if (delta > 0) {
3130 				*flagdesc = r_str_newf ("%s+%d", f->name, delta);
3131 			} else if (delta < 0) {
3132 				*flagdesc = r_str_newf ("%s%d", f->name, delta);
3133 			} else {
3134 				*flagdesc = r_str_newf ("%s", f->name);
3135 			}
3136 		} else {
3137 			*flagdesc = r_str_newf ("%s", f->name);
3138 		}
3139 	}
3140 	f = r_flag_get_at (core->flags, frame->addr, true);
3141 	if (f && !strchr (f->name, '.')) {
3142 		f = r_flag_get_at (core->flags, frame->addr - 1, true);
3143 	}
3144 	if (f) {
3145 		if (f->offset != addr) {
3146 			int delta = (int)(frame->addr - 1 - f->offset);
3147 			if (delta > 0) {
3148 				*flagdesc2 = r_str_newf ("%s+%d", f->name, delta + 1);
3149 			} else if (delta < 0) {
3150 				*flagdesc2 = r_str_newf ("%s%d", f->name, delta + 1);
3151 			} else {
3152 				*flagdesc2 = r_str_newf ("%s+1", f->name);
3153 			}
3154 		} else {
3155 			*flagdesc2 = r_str_newf ("%s", f->name);
3156 		}
3157 	}
3158 	if (!r_str_cmp (*flagdesc, *flagdesc2, -1)) {
3159 		free (*flagdesc2);
3160 		*flagdesc2 = NULL;
3161 	}
3162 	if (pcstr && spstr) {
3163 		if (core->dbg->bits & R_SYS_BITS_64) {
3164 			*pcstr = r_str_newf ("0x%-16" PFMT64x, frame->addr);
3165 			*spstr = r_str_newf ("0x%-16" PFMT64x, frame->sp);
3166 		} else if (core->dbg->bits & R_SYS_BITS_32) {
3167 			*pcstr = r_str_newf ("0x%-8" PFMT64x, frame->addr);
3168 			*spstr = r_str_newf ("0x%-8" PFMT64x, frame->sp);
3169 		} else {
3170 			*pcstr = r_str_newf ("0x%" PFMT64x, frame->addr);
3171 			*spstr = r_str_newf ("0x%" PFMT64x, frame->sp);
3172 		}
3173 	}
3174 }
3175 
static_debug_stop(void * u)3176 static void static_debug_stop(void *u) {
3177 	RDebug *dbg = (RDebug *)u;
3178 	r_debug_stop (dbg);
3179 }
3180 
core_cmd_dbi(RCore * core,const char * input,const ut64 idx)3181 static void core_cmd_dbi(RCore *core, const char *input, const ut64 idx) {
3182 	int i;
3183 	char *p;
3184 	RBreakpointItem *bpi;
3185 	switch (input[2]) {
3186 	case ' ': // "dbi."
3187 		{
3188 			const int index = r_bp_get_index_at (core->dbg->bp, idx);
3189 			if (index != -1) {
3190 				r_cons_printf ("%d\n", index);
3191 			}
3192 		}
3193 		break;
3194 	case '-': // "dbi-"
3195 		{
3196 			if (!r_bp_del_index (core->dbg->bp, idx)) {
3197 				eprintf ("Breakpoint with index %d not found\n", (int)idx);
3198 			}
3199 		}
3200 		break;
3201 	case '.': // "dbi."
3202 		{
3203 			const int index = r_bp_get_index_at (core->dbg->bp, core->offset);
3204 			if (index != -1) {
3205 				r_cons_printf ("%d\n", index);
3206 			}
3207 		}
3208 		break;
3209 	case 0: // "dbi"
3210 		for (i = 0; i < core->dbg->bp->bps_idx_count; i++) {
3211 			if ((bpi = core->dbg->bp->bps_idx[i])) {
3212 				r_cons_printf ("%d 0x%08"PFMT64x" E:%d T:%d\n",
3213 						i, bpi->addr, bpi->enabled, bpi->trace);
3214 			}
3215 		}
3216 		break;
3217 	case 'x': // "dbix"
3218 		if (input[3] == ' ') {
3219 			if ((bpi = r_bp_get_index (core->dbg->bp, idx))) {
3220 				char *expr = strchr (input + 4, ' ');
3221 				if (expr) {
3222 					free (bpi->expr);
3223 					bpi->expr = strdup (expr);
3224 				}
3225 			}
3226 			r_cons_printf ("%d\n", (int)idx);
3227 		} else {
3228 			for (i = 0; i < core->dbg->bp->bps_idx_count; i++) {
3229 				RBreakpointItem *bp = core->dbg->bp->bps_idx[i];
3230 				if (bp) {
3231 					r_cons_printf ("%d 0x%08"PFMT64x" %s\n", i, bp->addr, bp->expr);
3232 				}
3233 			}
3234 		}
3235 		break;
3236 	case 'c': // "dbic"
3237 		p = strchr (input + 3, ' ');
3238 		if (p) {
3239 			char *q = strchr (p + 1, ' ');
3240 			if (q) {
3241 				*q++ = 0;
3242 				ut64 addr = r_num_math (core->num, p);
3243 				bpi = r_bp_get_index (core->dbg->bp, addr);
3244 				if (bpi) {
3245 					bpi->data = strdup (q);
3246 				} else {
3247 					eprintf ("Cannot set command\n");
3248 				}
3249 			} else {
3250 				eprintf ("|Usage: dbic # cmd\n");
3251 			}
3252 		} else {
3253 			eprintf ("|Usage: dbic # cmd\n");
3254 		}
3255 		break;
3256 	case 'e': // "dbie"
3257 		if ((bpi = r_bp_get_index (core->dbg->bp, idx))) {
3258 			bpi->enabled = true;
3259 		} else {
3260 			eprintf ("Cannot unset tracepoint\n");
3261 		}
3262 		break;
3263 	case 'd': // "dbid"
3264 		if ((bpi = r_bp_get_index (core->dbg->bp, idx))) {
3265 			bpi->enabled = false;
3266 		} else {
3267 			eprintf ("Cannot unset tracepoint\n");
3268 		}
3269 		break;
3270 	case 's': // "dbis"
3271 		if ((bpi = r_bp_get_index (core->dbg->bp, idx))) {
3272 			bpi->enabled = !!!bpi->enabled;
3273 		} else {
3274 			eprintf ("Cannot unset tracepoint\n");
3275 		}
3276 		break;
3277 	case 't': // "dbite" "dbitd" ...
3278 		switch (input[3]) {
3279 		case 'e':
3280 			if ((bpi = r_bp_get_index (core->dbg->bp, idx))) {
3281 				bpi->trace = true;
3282 			} else {
3283 				eprintf ("Cannot unset tracepoint\n");
3284 			}
3285 			break;
3286 		case 'd':
3287 			if ((bpi = r_bp_get_index (core->dbg->bp, idx))) {
3288 				bpi->trace = false;
3289 			} else eprintf ("Cannot unset tracepoint\n");
3290 			break;
3291 		case 's':
3292 			if ((bpi = r_bp_get_index (core->dbg->bp, idx))) {
3293 				bpi->trace = !!!bpi->trace;
3294 			} else {
3295 				eprintf ("Cannot unset tracepoint\n");
3296 			}
3297 			break;
3298 		}
3299 		break;
3300 	}
3301 }
3302 
3303 #if __WINDOWS__
3304 #include "..\debug\p\native\windows\windows_message.h"
3305 #endif
3306 
3307 #define DB_ARG(x) r_str_word_get0(str, x)
add_breakpoint(RCore * core,const char * input,bool hwbp,bool watch)3308 static void add_breakpoint(RCore *core, const char *input, bool hwbp, bool watch) {
3309 	RBreakpointItem *bpi;
3310 	ut64 addr;
3311 	int i = 0;
3312 
3313 	char *str = strdup (r_str_trim_head_ro (input + 1));
3314 	int sl = r_str_word_set0 (str);
3315 	// For dbw every second argument is 'rw', so we need to skip it.
3316 	for (; i < sl; i += 1 + (watch ? 1 : 0)) {
3317 		if (*DB_ARG (i) == '-') {
3318 			r_bp_del (core->dbg->bp, r_num_math (core->num, DB_ARG (i) + 1));
3319 		} else {
3320 			int rw = 0;
3321 			if (watch) {
3322 				if (sl % 2 == 0) {
3323 					if (!strcmp (DB_ARG (i + 1), "r")) {
3324 						rw = R_BP_PROT_READ;
3325 					} else if (!strcmp (DB_ARG (i + 1), "w")) {
3326 						rw = R_BP_PROT_WRITE;
3327 					} else if (!strcmp (DB_ARG (i + 1), "rw")) {
3328 						rw = R_BP_PROT_ACCESS;
3329 					} else {
3330 						r_core_cmd_help (core, help_msg_dbw);
3331 						break;
3332 					}
3333 				} else {
3334 					r_core_cmd_help (core, help_msg_dbw);
3335 					break;
3336 				}
3337 			}
3338 			addr = r_num_math (core->num, DB_ARG (i));
3339 			bpi = r_debug_bp_add (core->dbg, addr, hwbp, watch, rw, NULL, 0);
3340 			if (bpi) {
3341 				free (bpi->name);
3342 				if (!strcmp (DB_ARG (i), "$$")) {
3343 					RFlagItem *f = r_core_flag_get_by_spaces (core->flags, addr);
3344 					if (f) {
3345 						if (addr > f->offset) {
3346 							bpi->name = r_str_newf ("%s+0x%" PFMT64x, f->name, addr - f->offset);
3347 						} else {
3348 							bpi->name = strdup (f->name);
3349 						}
3350 					} else {
3351 						bpi->name = r_str_newf ("0x%08" PFMT64x, addr);
3352 					}
3353 				} else {
3354 					bpi->name = strdup (DB_ARG (i));
3355 				}
3356 			} else {
3357 				eprintf ("Cannot set breakpoint at '%s'\n", DB_ARG (i));
3358 			}
3359 		}
3360 	}
3361 
3362 	free (str);
3363 }
3364 
r_core_cmd_bp(RCore * core,const char * input)3365 static void r_core_cmd_bp(RCore *core, const char *input) {
3366 	RBreakpointItem *bpi;
3367 	int i, hwbp = r_config_get_i (core->config, "dbg.hwbp");
3368 	RDebugFrame *frame;
3369 	RListIter *iter;
3370 	const char *p;
3371 	bool watch = false;
3372 	RList *list;
3373 	ut64 addr, idx;
3374 	p = strchr (input, ' ');
3375 	addr = p? r_num_math (core->num, p + 1): UT64_MAX;
3376 	idx = addr; // 0 is valid index
3377 	if (!addr) {
3378 		addr = UT64_MAX;
3379 	}
3380 	char *str = NULL;
3381 
3382 	switch (input[1]) {
3383 	case '.':
3384 		if (input[2]) {
3385 			ut64 addr = r_num_tail (core->num, core->offset, input + 2);
3386 			bpi = r_debug_bp_add (core->dbg, addr, hwbp, false, 0, NULL, 0);
3387 			if (!bpi) {
3388 				eprintf ("Unable to add breakpoint (%s)\n", input + 2);
3389 			}
3390 		} else {
3391 			bpi = r_bp_get_at (core->dbg->bp, core->offset);
3392 			if (bpi) {
3393 				r_cons_printf ("breakpoint %s %s %s\n",
3394 						r_str_rwx_i (bpi->perm),
3395 						bpi->enabled ?  "enabled" : "disabled",
3396 						r_str_get (bpi->name));
3397 			}
3398 		}
3399 		break;
3400 	case 'f':
3401 		{
3402 		RList *symbols = r_bin_get_symbols (core->bin);
3403 		RBinSymbol *symbol;
3404 		r_list_foreach (symbols, iter, symbol) {
3405 			if (symbol->type && !strcmp (symbol->type, R_BIN_TYPE_FUNC_STR)) {
3406 				if (r_anal_noreturn_at (core->anal, symbol->vaddr)) {
3407 					bpi = r_debug_bp_add (core->dbg, symbol->vaddr, hwbp, false, 0, NULL, 0);
3408 					if (bpi) {
3409 						bpi->name = r_str_newf ("%s.%s", "sym", symbol->name);
3410 					} else {
3411 						eprintf ("Unable to add a breakpoint"
3412 						"into a noreturn function %s at addr 0x%"PFMT64x"\n",
3413 									symbol->name, symbol->vaddr);
3414 					}
3415 				}
3416 			}
3417 		}
3418 		}
3419 		break;
3420 	case 'x': // "dbx"
3421 		if (input[2] == ' ') {
3422 			if (addr == UT64_MAX) {
3423 				addr = core->offset;
3424 			}
3425 			bpi = r_bp_get_at (core->dbg->bp, addr);
3426 			if (bpi) {
3427 				free (bpi->expr);
3428 				bpi->expr = strdup (input + 3);
3429 			}
3430 		} else {
3431 			RBreakpointItem *bp;
3432 			r_list_foreach (core->dbg->bp->bps, iter, bp) {
3433 				r_cons_printf ("0x%08"PFMT64x" %s\n", bp->addr, r_str_get (bp->expr));
3434 			}
3435 		}
3436 		break;
3437 	case 't': // "dbt"
3438 		switch (input[2]) {
3439 		case 'v': // "dbtv"
3440 			list = r_debug_frames (core->dbg, addr);
3441 			backtrace_vars (core, list);
3442 			r_list_free (list);
3443 			break;
3444 		case 'a': // "dbta"
3445 			list = r_debug_frames (core->dbg, addr);
3446 			asciiart_backtrace (core, list);
3447 			r_list_free (list);
3448 			break;
3449 		case 'e': // "dbte"
3450 			for (p = input + 3; *p == ' '; p++) {
3451 				/* nothing to do here */
3452 			}
3453 			if (*p == '*') {
3454 				r_bp_set_trace_all (core->dbg->bp,true);
3455 			} else if (!r_bp_set_trace (core->dbg->bp, addr, true)) {
3456 				eprintf ("Cannot set tracepoint\n");
3457 			}
3458 			break;
3459 		case 'd': // "dbtd"
3460 			for (p = input + 3; *p==' ';p++) {
3461 				//nothing to see here
3462 			}
3463 			if (*p == '*') {
3464 				r_bp_set_trace_all (core->dbg->bp, false);
3465 			} else if (!r_bp_set_trace (core->dbg->bp, addr, false)) {
3466 				eprintf ("Cannot unset tracepoint\n");
3467 			}
3468 			break;
3469 		case 's': // "dbts"
3470 			bpi = r_bp_get_at (core->dbg->bp, addr);
3471 			if (bpi) {
3472 				bpi->trace = !!!bpi->trace;
3473 			} else {
3474 				eprintf ("Cannot unset tracepoint\n");
3475 			}
3476 			break;
3477 		case 'j': { // "dbtj"
3478 			PJ *pj = r_core_pj_new (core);
3479 			if (!pj) {
3480 				return;
3481 			}
3482 			addr = UT64_MAX;
3483 			if (input[2] == ' ' && input[3]) {
3484 				addr = r_num_math (core->num, input + 2);
3485 			}
3486 			i = 0;
3487 			list = r_debug_frames (core->dbg, addr);
3488 			pj_a (pj);
3489 			r_list_foreach (list, iter, frame) {
3490 				char *flagdesc, *flagdesc2, *desc;
3491 				get_backtrace_info (core, frame, addr, &flagdesc, &flagdesc2, NULL, NULL);
3492 				RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, frame->addr, 0);
3493 				desc = r_str_newf ("%s%s", r_str_get (flagdesc), r_str_get (flagdesc2));
3494 				pj_o (pj);
3495 				pj_ki (pj, "idx", i);
3496 				pj_kn (pj, "pc", frame->addr);
3497 				pj_kn (pj, "sp", frame->sp);
3498 				pj_ki (pj, "frame_size", frame->size);
3499 				pj_ks (pj, "fname", fcn ? fcn->name : "");
3500 				pj_ks (pj, "desc", desc);
3501 				pj_end (pj);
3502 				i++;
3503 				free (flagdesc);
3504 				free (flagdesc2);
3505 				free (desc);
3506 			}
3507 			pj_end (pj);
3508 			r_cons_println (pj_string (pj));
3509 			pj_free (pj);
3510 			r_list_free (list);
3511 			break;
3512 		}
3513 		case '=': // dbt=
3514 			addr = UT64_MAX;
3515 			if (input[2] == ' ' && input[3]) {
3516 				addr = r_num_math (core->num, input + 2);
3517 			}
3518 			i = 0;
3519 			list = r_debug_frames (core->dbg, addr);
3520 			r_list_reverse (list);
3521 			r_list_foreach (list, iter, frame) {
3522 				switch (input[3]) {
3523 				case 0:
3524 					r_cons_printf ("%s0x%08"PFMT64x,
3525 							(i ? " " : ""), frame->addr);
3526 					break;
3527 				case 's':
3528 					r_cons_printf ("%s0x%08"PFMT64x,
3529 							(i ? " " : ""), frame->sp);
3530 					break;
3531 				case 'b':
3532 					r_cons_printf ("%s0x%08"PFMT64x,
3533 							(i ? " " : ""), frame->bp);
3534 					break;
3535 				case '?':
3536 				default:
3537 					r_core_cmd0 (core, "db?~dbt");
3538 					break;
3539 				}
3540 				i++;
3541 			}
3542 			r_cons_newline ();
3543 			r_list_free (list);
3544 			break;
3545 		case '*': // dbt*
3546 			addr = UT64_MAX;
3547 			if (input[2] == ' ' && input[3]) {
3548 				addr = r_num_math (core->num, input + 2);
3549 			}
3550 			i = 0;
3551 			list = r_debug_frames (core->dbg, addr);
3552 			r_list_reverse (list);
3553 			r_cons_printf ("f-bt.*\n");
3554 			r_list_foreach (list, iter, frame) {
3555 				r_cons_printf ("f bt.frame%d = 0x%08"PFMT64x"\n", i, frame->addr);
3556 				r_cons_printf ("f bt.frame%d.stack %d 0x%08"PFMT64x"\n", i, frame->size, frame->sp);
3557 				i++;
3558 			}
3559 			r_list_free (list);
3560 			break;
3561 		case 0: // "dbt" -- backtrace
3562 			addr = UT64_MAX;
3563 			if (input[2] == ' ' && input[3]) {
3564 				addr = r_num_math (core->num, input + 2);
3565 			}
3566 			i = 0;
3567 			list = r_debug_frames (core->dbg, addr);
3568 			r_list_foreach (list, iter, frame) {
3569 				char *flagdesc, *flagdesc2, *pcstr, *spstr;
3570 				get_backtrace_info (core, frame, addr, &flagdesc, &flagdesc2, &pcstr, &spstr);
3571 				RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, frame->addr, 0);
3572 				r_cons_printf ("%d  %s sp: %s  %-5d"
3573 						"[%s]  %s %s\n", i++,
3574 						pcstr, spstr,
3575 						(int)frame->size,
3576 						fcn ? fcn->name : "??",
3577 						r_str_get (flagdesc),
3578 						r_str_get (flagdesc2));
3579 				free (flagdesc);
3580 				free (flagdesc2);
3581 				free (pcstr);
3582 				free (spstr);
3583 			}
3584 			r_list_free (list);
3585 			break;
3586 		case '?':
3587 		default:
3588 			r_core_cmd_help (core, help_msg_dbt);
3589 			break;
3590 		}
3591 		break;
3592 	case 'b': // "dbb"
3593 		if (input[2]) {
3594 			core->dbg->bp->delta = (st64)r_num_math (core->num, input + 2);
3595 		} else {
3596 			r_cons_printf ("%"PFMT64d"\n", core->dbg->bp->delta);
3597 		}
3598 		break;
3599 	case 'm': // "dbm"
3600 		if (input[2] && input[3]) {
3601 			char *string = strdup (input + 3);
3602 			char *module = NULL;
3603 			st64 delta = 0;
3604 
3605 			module = strtok (string, " ");
3606 			delta = (ut64)r_num_math (core->num, strtok (NULL, ""));
3607 			bpi = r_debug_bp_add (core->dbg, 0, hwbp, false, 0, module, delta);
3608 			if (!bpi) {
3609 				eprintf ("Cannot set breakpoint.\n");
3610 			}
3611 			free (string);
3612 		}
3613 		break;
3614 	case 'j': r_bp_list (core->dbg->bp, 'j'); break;
3615 	case '*': r_bp_list (core->dbg->bp, 1); break;
3616 	case '\0': r_bp_list (core->dbg->bp, 0); break;
3617 	case '-': // "db-"
3618 		if (input[2] == '*') {
3619 			r_bp_del_all (core->dbg->bp);
3620 		} else {
3621 			#define DB_ARG(x) r_str_word_get0(str, x)
3622 			char *str = strdup (r_str_trim_head_ro (input +2));
3623 			int i = 0;
3624 			int sl = r_str_word_set0 (str);
3625 			for ( ; i < sl; i++) {
3626 				const ut64 addr = r_num_math (core->num, DB_ARG (i));
3627 				r_bp_del (core->dbg->bp, addr);
3628 			}
3629 			free (str);
3630 		}
3631 		break;
3632 	case 'c': // "dbc"
3633 		if (input[2] == ' ') {
3634 			char *inp = strdup (input + 3);
3635 			if (inp) {
3636 				char *arg = strchr (inp, ' ');
3637 				if (arg) {
3638 					*arg++ = 0;
3639 					addr = r_num_math (core->num, inp);
3640 					bpi = r_bp_get_at (core->dbg->bp, addr);
3641 					if (bpi) {
3642 						free (bpi->data);
3643 						bpi->data = strdup (arg);
3644 					} else {
3645 						eprintf ("No breakpoint defined at 0x%08"PFMT64x"\n", addr);
3646 					}
3647 				} else {
3648 					eprintf ("- Missing argument\n");
3649 				}
3650 				free (inp);
3651 			} else {
3652 				eprintf ("Cannot strdup. Your heap is fucked up\n");
3653 			}
3654 		} else {
3655 			eprintf ("Use: dbc [addr] [command]\n");
3656 		}
3657 		break;
3658 	case 'C': // "dbC"
3659 		if (input[2] == ' ') {
3660 			char *inp = strdup (input + 3);
3661 			if (inp) {
3662 				char *arg = strchr (inp, ' ');
3663 				if (arg) {
3664 					*arg++ = 0;
3665 					addr = r_num_math (core->num, inp);
3666 					bpi = r_bp_get_at (core->dbg->bp, addr);
3667 					if (bpi) {
3668 						free (bpi->cond);
3669 						bpi->cond = strdup (arg);
3670 					} else {
3671 						eprintf ("No breakpoint defined at 0x%08"PFMT64x"\n", addr);
3672 					}
3673 				} else {
3674 					eprintf ("1 Missing argument\n");
3675 				}
3676 				free (inp);
3677 			} else {
3678 				eprintf ("Cannot strdup. Your heap is fucked up\n");
3679 			}
3680 		} else {
3681 			eprintf ("Use: dbC [addr] [command]\n");
3682 		}
3683 		break;
3684 	case 's': // "dbs"
3685 		addr = r_num_math (core->num, input + 2);
3686 		bpi = r_bp_get_at (core->dbg->bp, addr);
3687 		if (bpi) {
3688 			//bp->enabled = !bp->enabled;
3689 			// XXX(jjd): this ^^ is what I would think toggling means...
3690 			r_bp_del (core->dbg->bp, addr);
3691 		} else {
3692 			// XXX(jjd): does t his need an address validity check??
3693 			bpi = r_debug_bp_add (core->dbg, addr, hwbp, false, 0, NULL, 0);
3694 			if (!bpi) {
3695 				eprintf ("Cannot set breakpoint (%s)\n", input + 2);
3696 			}
3697 		}
3698 		r_bp_enable (core->dbg->bp, r_num_math (core->num, input + 2), true, 0);
3699 		break;
3700 	case 'n': // "dbn"
3701 		bpi = r_bp_get_at (core->dbg->bp, core->offset);
3702 		if (input[2] == ' ') {
3703 			if (bpi) {
3704 				free (bpi->name);
3705 				bpi->name = strdup (input + 3);
3706 			} else {
3707 				eprintf ("Cannot find breakpoint at "
3708 						"0x%08"PFMT64x"\n", core->offset);
3709 			}
3710 		} else {
3711 			if (bpi && bpi->name) {
3712 				r_cons_println (bpi->name);
3713 			}
3714 		}
3715 		break;
3716 	case 'e': // "dbe"
3717 		for (p = input + 2; *p == ' '; p++);
3718 		if (*p == '*') r_bp_enable_all (core->dbg->bp,true);
3719 		else {
3720 			for (; *p && *p != ' '; p++);
3721 			r_bp_enable (core->dbg->bp, r_num_math (core->num, input + 2), true, r_num_math (core->num, p));
3722 		}
3723 		break;
3724 	case 'd': // "dbd"
3725 		for (p = input + 2; *p == ' '; p++);
3726 		if (*p == '*') r_bp_enable_all (core->dbg->bp, false);
3727 		else {
3728 			for (; *p && *p != ' '; p++);
3729 			r_bp_enable (core->dbg->bp, r_num_math (core->num, input + 2), false, r_num_math (core->num, p));
3730 		}
3731 		break;
3732 	case 'h': // "dbh"
3733 		switch (input[2]) {
3734 		case 0:
3735 			r_bp_plugin_list (core->dbg->bp);
3736 			break;
3737 		case ' ':
3738 			if (input[3]) {
3739 				if (!r_bp_use (core->dbg->bp, input + 3, core->anal->bits)) {
3740 					eprintf ("Invalid name: '%s'.\n", input + 3);
3741 				}
3742 			}
3743 			break;
3744 		case '-':
3745 			if (input[3]) {
3746 				if (!r_bp_plugin_del (core->dbg->bp, input + 3)) {
3747 					eprintf ("Invalid name: '%s'.\n", input + 3);
3748 				}
3749 			}
3750 			break;
3751 		case '?':
3752 		default:
3753 			eprintf ("Usage: dh [plugin-name]  # select a debug handler plugin\n");
3754 			break;
3755 		}
3756 		break;
3757 #if __WINDOWS__
3758 	case 'W': // "dbW"
3759 		if (input[2] == ' ') {
3760 			if (r_w32_add_winmsg_breakpoint (core->dbg, input + 3)) {
3761 				r_cons_print ("Breakpoint set.\n");
3762 			} else {
3763 				r_cons_print ("Breakpoint not set.\n");
3764 			}
3765 		}
3766 		break;
3767 #endif
3768 	case 'w': // "dbw"
3769 		add_breakpoint (core, input + 1, hwbp, true);
3770 		break;
3771 	case 'H': // "dbH"
3772 		add_breakpoint (core, input + 1, true, watch);
3773 		break;
3774 	case ' ': // "db"
3775 		add_breakpoint (core, input + 1, hwbp, watch);
3776 		break;
3777 	case 'i':
3778 		core_cmd_dbi (core, input, idx);
3779 		break;
3780 	case '?':
3781 	default:
3782 		r_core_cmd_help (core, help_msg_db);
3783 		break;
3784 	}
3785 	free (str);
3786 }
3787 
add_trace_tree_child(Sdb * db,RTree * t,RTreeNode * cur,ut64 addr)3788 static RTreeNode *add_trace_tree_child (Sdb *db, RTree *t, RTreeNode *cur, ut64 addr) {
3789 	struct trace_node *t_node;
3790 	char dbkey[TN_KEY_LEN];
3791 
3792 	snprintf (dbkey, TN_KEY_LEN, TN_KEY_FMT, addr);
3793 	t_node = (struct trace_node *)(size_t)sdb_num_get (db, dbkey, NULL);
3794 	if (!t_node) {
3795 		t_node = R_NEW0 (struct trace_node);
3796 		t_node->addr = addr;
3797 		t_node->refs = 1;
3798 		sdb_num_set (db, dbkey, (ut64)(size_t)t_node, 0);
3799 	} else {
3800 		t_node->refs++;
3801 	}
3802 	return r_tree_add_node (t, cur, t_node);
3803 }
3804 
3805 static RCore *_core = NULL;
3806 
trace_traverse_pre(RTreeNode * n,RTreeVisitor * vis)3807 static void trace_traverse_pre (RTreeNode *n, RTreeVisitor *vis) {
3808 	const char *name = "";
3809 	struct trace_node *tn = n->data;
3810 	unsigned int i;
3811 	if (!tn) return;
3812 	for (i = 0; i < n->depth - 1; i++) {
3813 		r_cons_printf ("  ");
3814 	}
3815 	if (_core) {
3816 		RFlagItem *f = r_flag_get_at (_core->flags, tn->addr, true);
3817 		if (f) {
3818 			name = f->name;
3819 		}
3820 	}
3821 	r_cons_printf (" 0x%08"PFMT64x" refs %d %s\n", tn->addr, tn->refs, name);
3822 }
3823 
trace_traverse(RTree * t)3824 static void trace_traverse (RTree *t) {
3825 	RTreeVisitor vis = { 0 };
3826 
3827 	/* clear the line on stderr, because somebody has written there */
3828 	fprintf (stderr, "\x1b[2K\r");
3829 	fflush (stderr);
3830 	vis.pre_visit = (RTreeNodeVisitCb)trace_traverse_pre;
3831 	r_tree_dfs (t, &vis);
3832 }
3833 
do_debug_trace_calls(RCore * core,ut64 from,ut64 to,ut64 final_addr)3834 static void do_debug_trace_calls(RCore *core, ut64 from, ut64 to, ut64 final_addr) {
3835 	bool trace_libs = r_config_get_i (core->config, "dbg.trace.libs");
3836 	bool shallow_trace = r_config_get_i (core->config, "dbg.trace.inrange");
3837 	Sdb *tracenodes = core->dbg->tracenodes;
3838 	RTree *tr = core->dbg->tree;
3839 	RDebug *dbg = core->dbg;
3840 	ut64 debug_to = UT64_MAX;
3841 	RTreeNode *cur;
3842 	ut64 addr = 0;
3843 	int n = 0;
3844 
3845 	if (!trace_libs) {
3846 #if NOOP
3847 		RList *bounds = r_core_get_boundaries_prot (core, -1, "dbg.program", "search");
3848 		r_list_free (bounds);
3849 #endif
3850 	}
3851 
3852 	/* set root if not already present */
3853 	r_tree_add_node (tr, NULL, NULL);
3854 	cur = tr->root;
3855 
3856 	while (true) {
3857 		ut8 buf[32];
3858 		RAnalOp aop;
3859 		int addr_in_range;
3860 
3861 		if (r_cons_is_breaked()) {
3862 			break;
3863 		}
3864 		if (r_debug_is_dead (dbg)) {
3865 			break;
3866 		}
3867 		if (debug_to != UT64_MAX && !r_debug_continue_until (dbg, debug_to)) {
3868 			break;
3869 		}
3870 		if (!r_debug_step (dbg, 1)) {
3871 			break;
3872 		}
3873 		debug_to = UT64_MAX;
3874 		if (!r_debug_reg_sync (dbg, R_REG_TYPE_GPR, false)) {
3875 			break;
3876 		}
3877 		addr = r_debug_reg_get (dbg, "PC");
3878 		if (addr == final_addr) {
3879 			//we finished the tracing so break the loop
3880 			break;
3881 		}
3882 		addr_in_range = addr >= from && addr < to;
3883 
3884 		r_io_read_at (core->io, addr, buf, sizeof (buf));
3885 		r_anal_op (core->anal, &aop, addr, buf, sizeof (buf), R_ANAL_OP_MASK_BASIC);
3886 		eprintf ("%d %"PFMT64x"\r", n++, addr);
3887 		switch (aop.type) {
3888 		case R_ANAL_OP_TYPE_UCALL:
3889 		case R_ANAL_OP_TYPE_ICALL:
3890 		case R_ANAL_OP_TYPE_RCALL:
3891 		case R_ANAL_OP_TYPE_IRCALL:
3892 			{
3893 				ut64 called_addr;
3894 				int called_in_range;
3895 				// store regs
3896 				// step into
3897 				// get pc
3898 				r_debug_step (dbg, 1);
3899 				r_debug_reg_sync (dbg, R_REG_TYPE_GPR, false);
3900 				called_addr = r_debug_reg_get (dbg, "PC");
3901 				called_in_range = called_addr >= from && called_addr < to;
3902 				if (!called_in_range && addr_in_range && !shallow_trace) {
3903 					debug_to = addr + aop.size;
3904 				}
3905 				if (addr_in_range || shallow_trace) {
3906 					cur = add_trace_tree_child (tracenodes, tr, cur, addr);
3907 					if (debug_to != UT64_MAX) {
3908 						cur = cur->parent;
3909 					}
3910 				}
3911 				// TODO: push pc+aop.length into the call path stack
3912 				break;
3913 			}
3914 		case R_ANAL_OP_TYPE_CALL:
3915 			{
3916 				int called_in_range = aop.jump >= from && aop.jump < to;
3917 				if (!called_in_range && addr_in_range && !shallow_trace) {
3918 					debug_to = aop.addr + aop.size;
3919 				}
3920 				if (addr_in_range || shallow_trace) {
3921 					cur = add_trace_tree_child (tracenodes, tr, cur, addr);
3922 					if (debug_to != UT64_MAX) {
3923 						cur = cur->parent;
3924 					}
3925 				}
3926 				break;
3927 			}
3928 		case R_ANAL_OP_TYPE_RET:
3929 #if 0
3930 			// TODO: we must store ret value for each call in the graph path to do this check
3931 			r_debug_step (dbg, 1);
3932 			r_debug_reg_sync (dbg, R_REG_TYPE_GPR, false);
3933 			addr = r_debug_reg_get (dbg, "PC");
3934 			// TODO: step into and check return address if correct
3935 			// if not correct we are hijacking the control flow (exploit!)
3936 #endif
3937 			if (cur != tr->root) {
3938 				cur = cur->parent;
3939 			}
3940 #if 0
3941 			if (addr != gn->addr) {
3942 				eprintf ("Oops. invalid return address 0x%08"PFMT64x
3943 						"\n0x%08"PFMT64x"\n", addr, gn->addr);
3944 			}
3945 #endif
3946 			break;
3947 		}
3948 	}
3949 }
3950 
debug_trace_calls(RCore * core,const char * input)3951 static void debug_trace_calls(RCore *core, const char *input) {
3952 	RBreakpointItem *bp_final = NULL;
3953 	int t = core->dbg->trace->enabled;
3954 	ut64 from = 0, to = UT64_MAX, final_addr = UT64_MAX;
3955 
3956 	if (r_debug_is_dead (core->dbg)) {
3957 		eprintf ("No process to debug.");
3958 		return;
3959 	}
3960 	if (*input == ' ') {
3961 		input = r_str_trim_head_ro (input);
3962 		ut64 first_n = r_num_math (core->num, input);
3963 		input = strchr (input, ' ');
3964 		if (input) {
3965 			input = r_str_trim_head_ro (input);
3966 			from = first_n;
3967 			to = r_num_math (core->num, input);
3968 			input = strchr (input, ' ');
3969 			if (input) {
3970 				input = r_str_trim_head_ro (input);
3971 				final_addr = r_num_math (core->num, input);
3972 			}
3973 		} else {
3974 			final_addr = first_n;
3975 		}
3976 	}
3977 	core->dbg->trace->enabled = 0;
3978 	r_cons_break_push (static_debug_stop, core->dbg);
3979 	r_reg_arena_swap (core->dbg->reg, true);
3980 	if (final_addr != UT64_MAX) {
3981 		int hwbp = r_config_get_i (core->config, "dbg.hwbp");
3982 		bp_final = r_debug_bp_add (core->dbg, final_addr, hwbp, false, 0, NULL, 0);
3983 		if (!bp_final) {
3984 			eprintf ("Cannot set breakpoint at final address (%"PFMT64x")\n", final_addr);
3985 		}
3986 	}
3987 	do_debug_trace_calls (core, from, to, final_addr);
3988 	if (bp_final) {
3989 		r_bp_del (core->dbg->bp, final_addr);
3990 	}
3991 	_core = core;
3992 	trace_traverse (core->dbg->tree);
3993 	core->dbg->trace->enabled = t;
3994 	r_cons_break_pop ();
3995 }
3996 
r_core_debug_esil(RCore * core,const char * input)3997 static void r_core_debug_esil (RCore *core, const char *input) {
3998 	switch (input[0]) {
3999 	case '\0': // "de"
4000 		// list
4001 		r_debug_esil_watch_list (core->dbg);
4002 		break;
4003 	case ' ': // "de "
4004 		{
4005 			char *line = strdup (input + 1);
4006 			char *p, *q;
4007 			int done = 0;
4008 			int perm = 0, dev = 0;
4009 			p = strchr (line, ' ');
4010 			if (p) {
4011 				*p++ = 0;
4012 				if (strchr (line, 'r')) perm |= R_PERM_R;
4013 				if (strchr (line, 'w')) perm |= R_PERM_W;
4014 				if (strchr (line, 'x')) perm |= R_PERM_X;
4015 				q = strchr (p, ' ');
4016 				if (q) {
4017 					*q++ = 0;
4018 					dev = p[0];
4019 					r_debug_esil_watch (core->dbg, perm, dev, q);
4020 					done = 1;
4021 				}
4022 			}
4023 			if (!done) {
4024 				const char *help_de_msg[] = {
4025 					"Usage:", "de", " [perm] [reg|mem] [expr]",
4026 					NULL
4027 				};
4028 				r_core_cmd_help (core, help_de_msg);
4029 			}
4030 			free (line);
4031 		}
4032 		break;
4033 	case '-': // "de-"
4034 		r_debug_esil_watch_reset (core->dbg);
4035 		break;
4036 	case 'c': // "dec"
4037 		if (r_debug_esil_watch_empty (core->dbg)) {
4038 			eprintf ("Error: no esil watchpoints defined\n");
4039 		} else {
4040 			r_core_cmd0 (core, "aei");
4041 			r_debug_esil_prestep (core->dbg, r_config_get_i (core->config, "esil.prestep"));
4042 			r_debug_esil_continue (core->dbg);
4043 		}
4044 		break;
4045 	case 's': // "des"
4046 		if (input[1] == 'u' && input[2] == ' ') { // "desu"
4047 			ut64 addr, naddr, fin = r_num_math (core->num, input + 2);
4048 			r_core_cmd0 (core, "aei");
4049 			addr = r_debug_reg_get (core->dbg, "PC");
4050 			while (addr != fin) {
4051 				r_debug_esil_prestep (core->dbg, r_config_get_i (
4052 							core->config, "esil.prestep"));
4053 				r_debug_esil_step (core->dbg, 1);
4054 				naddr = r_debug_reg_get (core->dbg, "PC");
4055 				if (naddr == addr) {
4056 					eprintf ("Detected loophole\n");
4057 					break;
4058 				}
4059 				addr = naddr;
4060 			}
4061 		} else if (input[1] == '?' || !input[1]) {
4062 			r_core_cmd_help (core, help_msg_des);
4063 		} else {
4064 			r_core_cmd0 (core, "aei");
4065 			r_debug_esil_prestep (core->dbg, r_config_get_i (core->config, "esil.prestep"));
4066 			// continue
4067 			r_debug_esil_step (core->dbg, r_num_math (core->num, input + 1));
4068 		}
4069 		break;
4070 	case '?': // "de?"
4071 	default:
4072 		{
4073 			r_core_cmd_help (core, help_msg_de);
4074 			// TODO #7967 help refactor: move to detail
4075 			r_cons_printf ("Examples:\n"
4076 					" de r r rip       # stop when reads rip\n"
4077 					" de rw m ADDR     # stop when read or write in ADDR\n"
4078 					" de w r rdx       # stop when rdx register is modified\n"
4079 					" de x m FROM..TO  # stop when rip in range\n");
4080 		}
4081 		break;
4082 	}
4083 }
4084 
r_core_debug_kill(RCore * core,const char * input)4085 static void r_core_debug_kill (RCore *core, const char *input) {
4086 	if (!input || *input=='?') {
4087 		if (input && input[1]) {
4088 			const char *signame, *arg = input + 1;
4089 			int signum = atoi (arg);
4090 			if (signum > 0) {
4091 				signame = r_signal_to_string (signum);
4092 				if (signame)
4093 					r_cons_println (signame);
4094 			} else {
4095 				signum = r_signal_from_string (arg);
4096 				if (signum > 0) {
4097 					r_cons_printf ("%d\n", signum);
4098 				}
4099 			}
4100 		} else {
4101 			r_core_cmd_help (core, help_msg_dk);
4102 		}
4103 	} else if (*input=='o') {
4104 		switch (input[1]) {
4105 			case 0: // "dko" - list signal skip/conts
4106 				r_debug_signal_list (core->dbg, 1);
4107 				break;
4108 			case ' ': // dko SIGNAL
4109 				if (input[2]) {
4110 					char *p, *name = strdup (input + 2);
4111 					int signum = atoi (name);
4112 					p = strchr (name, ' ');
4113 					if (p) *p++ = 0; /* got SIGNAL and an action */
4114 					// Actions:
4115 					//  - pass
4116 					//  - trace
4117 					//  - stop
4118 					if (signum<1) signum = r_signal_from_string (name);
4119 					if (signum>0) {
4120 						if (!p || !p[0]) { // stop (the usual)
4121 							r_debug_signal_setup (core->dbg, signum, 0);
4122 						} else if (*p == 's') { // skip
4123 							r_debug_signal_setup (core->dbg, signum, R_DBG_SIGNAL_SKIP);
4124 						} else if (*p == 'c') { // cont
4125 							r_debug_signal_setup (core->dbg, signum, R_DBG_SIGNAL_CONT);
4126 						} else {
4127 							eprintf ("Invalid option: %s\n", p);
4128 						}
4129 					} else {
4130 						eprintf ("Invalid signal: %s\n", input + 2);
4131 					}
4132 					free (name);
4133 					break;
4134 				}
4135 				/* fall through */
4136 			case '?':
4137 			default:
4138 				{
4139 					r_core_cmd_help (core, help_msg_dko);
4140 					// TODO #7967 help refactor: move to detail
4141 					r_cons_println ("NOTE: [signal] can be a number or a string that resolves with dk?\n"
4142 							"  skip means do not enter into the signal handler\n"
4143 							"  continue means enter into the signal handler");
4144 				}
4145 		}
4146 	} else if (*input == 'j') {
4147 		core->dbg->pj = r_core_pj_new (core);
4148 		r_debug_signal_list (core->dbg, 2);
4149 		pj_free (core->dbg->pj);
4150 		core->dbg->pj = NULL;
4151 	} else if (!*input) {
4152 		r_debug_signal_list (core->dbg, 0);
4153 #if 0
4154 		RListIter *iter;
4155 		RDebugSignal *ds;
4156 		eprintf ("TODO: list signal handlers of child\n");
4157 		RList *list = r_debug_kill_list (core->dbg);
4158 		r_list_foreach (list, iter, ds) {
4159 			// TODO: resolve signal name by number and show handler offset
4160 			eprintf ("--> %d\n", ds->num);
4161 		}
4162 		r_list_free (list);
4163 #endif
4164 	} else {
4165 		int sig = atoi (input);
4166 		char *p = strchr (input, '=');
4167 		if (p) {
4168 			r_debug_kill_setup (core->dbg, sig, r_num_math (core->num, p+1));
4169 		} else {
4170 			r_debug_kill (core->dbg, core->dbg->pid, core->dbg->tid, sig);
4171 		}
4172 	}
4173 }
4174 
is_x86_call(RDebug * dbg,ut64 addr)4175 static bool is_x86_call(RDebug *dbg, ut64 addr) {
4176 	ut8 buf[3];
4177 	ut8 *op = buf;
4178 	(void)dbg->iob.read_at (dbg->iob.io, addr, buf, R_ARRAY_SIZE (buf));
4179 	switch (buf[0]) {  /* Segment override prefixes */
4180 	case 0x65:
4181 	case 0x64:
4182 	case 0x26:
4183 	case 0x3e:
4184 	case 0x36:
4185 	case 0x2e:
4186 		op++;
4187 	}
4188 	if (op[0] == 0xe8) {
4189 		return true;
4190 	}
4191 	if (op[0] == 0xff  /* bits 4-5 (from right) of next byte must be 01 */
4192 	    && (op[1] & 0x30) == 0x10) {
4193 		return true;
4194 	}
4195 	/* ... */
4196 	return false;
4197 }
4198 
is_x86_ret(RDebug * dbg,ut64 addr)4199 static bool is_x86_ret(RDebug *dbg, ut64 addr) {
4200 	ut8 buf[1];
4201 	(void)dbg->iob.read_at (dbg->iob.io, addr, buf, R_ARRAY_SIZE (buf));
4202 	switch (buf[0]) {
4203 	case 0xc3:
4204 	case 0xcb:
4205 	case 0xc2:
4206 	case 0xca:
4207 		return true;
4208 	default:
4209 		return false;
4210 	}
4211 	/* Possibly incomplete with regard to instruction prefixes */
4212 }
4213 
cmd_dcu(RCore * core,const char * input)4214 static bool cmd_dcu (RCore *core, const char *input) {
4215 	const char *ptr = NULL;
4216 	ut64 from, to, pc;
4217 	bool dcu_range = false;
4218 	bool invalid = (!input[0] || !input[1] || !input[2]);
4219 	if (invalid || (input[2] != ' ' && input[2] != '.')) {
4220 		r_core_cmd_help (core, help_msg_dcu);
4221 		return false;
4222 	}
4223 	to = UT64_MAX;
4224 	if (input[2] == '.') {
4225 		ptr = strchr (input + 3, ' ');
4226 		if (ptr) { // TODO: put '\0' in *ptr to avoid
4227 			from = r_num_tail (core->num, core->offset, input + 2);
4228 			if (ptr[1]=='.') {
4229 				to = r_num_tail (core->num, core->offset, ptr+2);
4230 			} else {
4231 				to = r_num_math (core->num, ptr+1);
4232 			}
4233 			dcu_range = true;
4234 		} else {
4235 			from = r_num_tail (core->num, core->offset, input + 2);
4236 		}
4237 	} else {
4238 		ptr = strchr (input + 3, ' ');
4239 		if (ptr) { // TODO: put '\0' in *ptr to avoid
4240 			from = r_num_math (core->num, input + 3);
4241 			if (ptr[1]=='.') {
4242 				to = r_num_tail (core->num, core->offset, ptr+2);
4243 			} else {
4244 				to = r_num_math (core->num, ptr+1);
4245 			}
4246 			dcu_range = true;
4247 		} else {
4248 			from = r_num_math (core->num, input + 3);
4249 		}
4250 	}
4251 	if (core->num->nc.errors && r_cons_is_interactive ()) {
4252 		eprintf ("Cannot continue until unknown address '%s'\n", core->num->nc.calc_buf);
4253 		return false;
4254 	}
4255 	if (to == UT64_MAX) {
4256 		to = from;
4257 	}
4258 	if (dcu_range) {
4259 		r_cons_break_push (NULL, NULL);
4260 		do {
4261 			if (r_cons_is_breaked ()) {
4262 				break;
4263 			}
4264 			r_debug_step (core->dbg, 1);
4265 			r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false);
4266 			pc = r_debug_reg_get (core->dbg, "PC");
4267 			eprintf ("Continue 0x%08"PFMT64x" > 0x%08"PFMT64x" < 0x%08"PFMT64x"\n",
4268 					from, pc, to);
4269 		} while (pc < from || pc > to);
4270 		r_cons_break_pop ();
4271 	} else {
4272 		ut64 addr = from;
4273 		if (!strcmp (core->dbg->btalgo, "trace") && core->dbg->arch
4274 		    && !strcmp (core->dbg->arch, "x86") && core->dbg->bits == 4) {
4275 			unsigned long steps = 0;
4276 			long level = 0;
4277 			const char *pc_name = core->dbg->reg->name[R_REG_NAME_PC];
4278 			ut64 prev_pc = UT64_MAX;
4279 			bool prev_call = false;
4280 			bool prev_ret = false;
4281 			const char *sp_name = core->dbg->reg->name[R_REG_NAME_SP];
4282 			ut64 old_sp, cur_sp;
4283 			r_cons_break_push (NULL, NULL);
4284 			r_list_free (core->dbg->call_frames);
4285 			core->dbg->call_frames = r_list_new ();
4286 			core->dbg->call_frames->free = free;
4287 			r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false);
4288 			old_sp = r_debug_reg_get (core->dbg, sp_name);
4289 			while (true) {
4290 				r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false);
4291 				pc = r_debug_reg_get (core->dbg, pc_name);
4292 				if (prev_call) {
4293 					ut32 ret_addr;
4294 					RDebugFrame *frame = R_NEW0 (RDebugFrame);
4295 					cur_sp = r_debug_reg_get (core->dbg, sp_name);
4296 					(void)core->dbg->iob.read_at (core->dbg->iob.io, cur_sp, (ut8 *)&ret_addr,
4297 					                              sizeof (ret_addr));
4298 					frame->addr = ret_addr;
4299 					frame->size = old_sp - cur_sp;
4300 					frame->sp = cur_sp;
4301 					frame->bp = old_sp;
4302 					r_list_prepend (core->dbg->call_frames, frame);
4303 					eprintf ("%ld Call from 0x%08"PFMT64x" to 0x%08"PFMT64x" ret 0x%08"PFMT32x"\n",
4304 					         level, prev_pc, pc, ret_addr);
4305 					level++;
4306 					old_sp = cur_sp;
4307 					prev_call = false;
4308 				} else if (prev_ret) {
4309 					RDebugFrame *head = r_list_get_bottom (core->dbg->call_frames);
4310 					if (head && head->addr != pc) {
4311 						eprintf ("*");
4312 					} else {
4313 						r_list_pop_head (core->dbg->call_frames);
4314 						eprintf ("%ld", level);
4315 						level--;
4316 					}
4317 					eprintf (" Ret from 0x%08"PFMT64x" to 0x%08"PFMT64x"\n",
4318 					         prev_pc, pc);
4319 					prev_ret = false;
4320 				}
4321 				if (steps % 500 == 0 || pc == addr) {
4322 					eprintf ("At 0x%08"PFMT64x" after %lu steps\n", pc, steps);
4323 				}
4324 				if (r_cons_is_breaked () || r_debug_is_dead (core->dbg) || pc == addr) {
4325 					break;
4326 				}
4327 				if (is_x86_call (core->dbg, pc)) {
4328 					prev_pc = pc;
4329 					prev_call = true;
4330 				} else if (is_x86_ret (core->dbg, pc)) {
4331 					prev_pc = pc;
4332 					prev_ret = true;
4333 				}
4334 				r_debug_step (core->dbg, 1);
4335 				steps++;
4336 			}
4337 			r_cons_break_pop ();
4338 			return true;
4339 		}
4340 		eprintf ("Continue until 0x%08"PFMT64x" using %d bpsize\n", addr, core->dbg->bpsize);
4341 		r_reg_arena_swap (core->dbg->reg, true);
4342 		if (r_bp_add_sw (core->dbg->bp, addr, core->dbg->bpsize, R_BP_PROT_EXEC)) {
4343 			if (r_debug_is_dead (core->dbg)) {
4344 				eprintf ("Cannot continue, run ood?\n");
4345 			} else {
4346 				r_debug_continue (core->dbg);
4347 			}
4348 			r_bp_del (core->dbg->bp, addr);
4349 		} else {
4350 			eprintf ("Cannot set breakpoint of size %d at 0x%08"PFMT64x"\n",
4351 				core->dbg->bpsize, addr);
4352 		}
4353 	}
4354 	return true;
4355 }
4356 
cmd_debug_continue(RCore * core,const char * input)4357 static int cmd_debug_continue (RCore *core, const char *input) {
4358 	int pid, old_pid, signum;
4359 	char *ptr;
4360 	// TODO: we must use this for step 'ds' too maybe...
4361 	switch (input[1]) {
4362 	case 0: // "dc"
4363 		r_reg_arena_swap (core->dbg->reg, true);
4364 #if __linux__
4365 		core->dbg->continue_all_threads = true;
4366 #endif
4367 		if (r_debug_is_dead (core->dbg)) {
4368 			eprintf ("Cannot continue, run ood?\n");
4369 			break;
4370 		}
4371 		r_debug_continue (core->dbg);
4372 		break;
4373 	case 'a': // "dca"
4374 		eprintf ("TODO: dca\n");
4375 		break;
4376 	case 'b': // "dcb"
4377 		{
4378 			if (!core->dbg->session) {
4379 				eprintf ("Error: Session has not started\n");
4380 				break;
4381 			}
4382 			if (!r_debug_continue_back (core->dbg)) {
4383 				eprintf ("cannot continue back\n");
4384 			}
4385 			break;
4386 		}
4387 #if __WINDOWS__
4388 	case 'e': // "dce"
4389 		r_reg_arena_swap (core->dbg->reg, true);
4390 		r_debug_continue_pass_exception (core->dbg);
4391 		break;
4392 #endif
4393 	case 'f': // "dcf"
4394 		eprintf ("[+] Running 'dcs vfork fork clone' behind the scenes...\n");
4395 		// we should stop in fork and vfork syscalls
4396 		//TODO: multiple syscalls not handled yet
4397 		// r_core_cmd0 (core, "dcs vfork fork");
4398 		r_core_cmd0 (core, "dcs vfork fork clone");
4399 		break;
4400 	case 'c': // "dcc"
4401 		r_reg_arena_swap (core->dbg->reg, true);
4402 		if (input[2] == 'u') {
4403 			r_debug_continue_until_optype (core->dbg, R_ANAL_OP_TYPE_UCALL, 0);
4404 		} else {
4405 			r_debug_continue_until_optype (core->dbg, R_ANAL_OP_TYPE_CALL, 0);
4406 		}
4407 		break;
4408 	case 'r':
4409 		r_reg_arena_swap (core->dbg->reg, true);
4410 		r_debug_continue_until_optype (core->dbg, R_ANAL_OP_TYPE_RET, 1);
4411 		break;
4412 	case 'k':
4413 		// select pid and r_debug_continue_kill (core->dbg,
4414 		r_reg_arena_swap (core->dbg->reg, true);
4415 		signum = r_num_math (core->num, input + 2);
4416 		ptr = strchr (input + 3, ' ');
4417 		if (ptr) {
4418 			int old_pid = core->dbg->pid;
4419 			int old_tid = core->dbg->tid;
4420 			int pid = atoi (ptr+1);
4421 			int tid = pid; // XXX
4422 			*ptr = 0;
4423 			r_debug_select (core->dbg, pid, tid);
4424 			r_debug_continue_kill (core->dbg, signum);
4425 			r_debug_select (core->dbg, old_pid, old_tid);
4426 		} else {
4427 			r_debug_continue_kill (core->dbg, signum);
4428 		}
4429 		break;
4430 	case 's': // "dcs"
4431 		switch (input[2]) {
4432 		case '*':
4433 			cmd_debug_cont_syscall (core, "-1");
4434 			break;
4435 		case ' ':
4436 			cmd_debug_cont_syscall (core, input + 3);
4437 			break;
4438 		case '\0':
4439 			cmd_debug_cont_syscall (core, NULL);
4440 			break;
4441 		default:
4442 		case '?':
4443 			r_core_cmd_help (core, help_msg_dcs);
4444 			break;
4445 		}
4446 		break;
4447 	case 'p': // "dcp"
4448 		{ // XXX: this is very slow
4449 			RIOMap *s;
4450 			ut64 pc;
4451 			int n = 0;
4452 			bool t = core->dbg->trace->enabled;
4453 			core->dbg->trace->enabled = false;
4454 			r_cons_break_push (static_debug_stop, core->dbg);
4455 			do {
4456 				r_debug_step (core->dbg, 1);
4457 				r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false);
4458 				pc = r_debug_reg_get (core->dbg, "PC");
4459 				eprintf (" %d %"PFMT64x"\r", n++, pc);
4460 				s = r_io_map_get (core->io, pc);
4461 				if (r_cons_is_breaked ()) {
4462 					break;
4463 				}
4464 			} while (!s);
4465 			eprintf ("\n");
4466 			core->dbg->trace->enabled = t;
4467 			r_cons_break_pop ();
4468 			return 1;
4469 		}
4470 	case 'u': // "dcu"
4471 		if (input[2] == '?') {
4472 			r_core_cmd_help (core, help_msg_dcu);
4473 		} else if (input[2] == '.') {
4474 			cmd_dcu (core, "cu $$");
4475 		} else {
4476 			cmd_dcu (core, input);
4477 		}
4478 		break;
4479 	case ' ':
4480 		old_pid = core->dbg->pid;
4481 		pid = atoi (input + 2);
4482 		r_reg_arena_swap (core->dbg->reg, true);
4483 		r_debug_select (core->dbg, pid, core->dbg->tid);
4484 		r_debug_continue (core->dbg);
4485 		r_debug_select (core->dbg, old_pid, core->dbg->tid);
4486 		break;
4487 	case 't':
4488 		cmd_debug_backtrace (core, input + 2);
4489 		break;
4490 	case '?': // "dc?"
4491 	default:
4492 		r_core_cmd_help (core, help_msg_dc);
4493 		return 0;
4494 	}
4495 	return 1;
4496 }
4497 
get_corefile_name(const char * raw_name,int pid)4498 static char *get_corefile_name (const char *raw_name, int pid) {
4499 	return (!*raw_name)?
4500 		r_str_newf ("core.%u", pid) :
4501 		r_str_trim_dup (raw_name);
4502 }
4503 
cmd_debug_step(RCore * core,const char * input)4504 static int cmd_debug_step (RCore *core, const char *input) {
4505 	ut64 addr = core->offset;;
4506 	ut8 buf[64];
4507 	RAnalOp aop;
4508 	int i, times = 1;
4509 	char *ptr = strchr (input, ' ');
4510 	if (ptr) {
4511 		times = r_num_math (core->num, ptr + 1);
4512 	}
4513 	if (times < 1) {
4514 		times = 1;
4515 	}
4516 	switch (input[1]) {
4517 	case 0: // "ds"
4518 	case ' ':
4519 		if (r_config_get_i (core->config, "cfg.debug")) {
4520 			r_reg_arena_swap (core->dbg->reg, true);
4521 			// sync registers for BSD PT_STEP/PT_CONT
4522 			// XXX(jjd): is this necessary?
4523 			r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false);
4524 			ut64 pc = r_debug_reg_get (core->dbg, "PC");
4525 			r_debug_trace_pc (core->dbg, pc);
4526 			if (!r_debug_step (core->dbg, times)) {
4527 				eprintf ("Step failed\n");
4528 				core->break_loop = true;
4529 			}
4530 		} else {
4531 			r_core_cmdf (core, "%daes", R_MAX (1, times));
4532 		}
4533 		break;
4534 	case 'i': // "dsi"
4535 		if (input[2] == ' ') {
4536 			int n = 0;
4537 			r_cons_break_push (static_debug_stop, core->dbg);
4538 			do {
4539 				if (r_cons_is_breaked ()) {
4540 					break;
4541 				}
4542 				r_debug_step (core->dbg, 1);
4543 				if (r_debug_is_dead (core->dbg)) {
4544 					core->break_loop = true;
4545 					break;
4546 				}
4547 				r_core_cmd0 (core, ".dr*");
4548 				n++;
4549 			} while (!r_num_conditional (core->num, input + 3));
4550 			r_cons_break_pop ();
4551 			eprintf ("Stopped after %d instructions\n", n);
4552 		} else {
4553 			eprintf ("3 Missing argument\n");
4554 		}
4555 		break;
4556 	case 'f': // "dsf"
4557 		step_until_eof (core);
4558 		break;
4559 	case 'u': // "dsu"
4560 		switch (input[2]) {
4561 		case 'f': // dsuf
4562 			step_until_flag (core, input + 3);
4563 			break;
4564 		case 'i': // dsui
4565 			if (input[3] == 'r') {
4566 				step_until_inst (core, input + 4, true);
4567 			}
4568 			else {
4569 				step_until_inst (core, input + 3, false);
4570 			}
4571 			break;
4572 		case 'e': // dsue
4573 			step_until_esil (core, input + 3);
4574 			break;
4575 		case 'o': // dsuo
4576 			step_until_optype (core, input + 3);
4577 			break;
4578 		case ' ': // dsu <address>
4579 			r_reg_arena_swap (core->dbg->reg, true);
4580 			step_until (core, r_num_math (core->num, input + 2)); // XXX dupped by times
4581 			break;
4582 		default:
4583 			r_core_cmd_help (core, help_msg_dsu);
4584 			return 0;
4585 		}
4586 		break;
4587 	case 'p': // "dsp"
4588 		r_reg_arena_swap (core->dbg->reg, true);
4589 		for (i = 0; i < times; i++) {
4590 			ut8 buf[64];
4591 			ut64 addr;
4592 			RAnalOp aop;
4593 			r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false);
4594 			addr = r_debug_reg_get (core->dbg, "PC");
4595 			r_io_read_at (core->io, addr, buf, sizeof (buf));
4596 			r_anal_op (core->anal, &aop, addr, buf, sizeof (buf), R_ANAL_OP_MASK_BASIC);
4597 			if (aop.type == R_ANAL_OP_TYPE_CALL) {
4598 				RBinObject *o = r_bin_cur_object (core->bin);
4599 				RBinSection *s = r_bin_get_section_at (o, aop.jump, true);
4600 				if (!s) {
4601 					r_debug_step_over (core->dbg, times);
4602 					continue;
4603 				}
4604 			}
4605 			r_debug_step (core->dbg, 1);
4606 		}
4607 		break;
4608 	case 's': // "dss"
4609 		{
4610 			char delb[128] = R_EMPTY;
4611 			addr = r_debug_reg_get (core->dbg, "PC");
4612 			RBreakpointItem *bpi = r_bp_get_at (core->dbg->bp, addr);
4613 			sprintf(delb, "db 0x%"PFMT64x"", addr);
4614 			r_reg_arena_swap (core->dbg->reg, true);
4615 			for (i = 0; i < times; i++) {
4616 				r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false);
4617 				r_io_read_at (core->io, addr, buf, sizeof (buf));
4618 				r_anal_op (core->anal, &aop, addr, buf, sizeof (buf), R_ANAL_OP_MASK_BASIC);
4619 #if 0
4620 				if (aop.jump != UT64_MAX && aop.fail != UT64_MAX) {
4621 					eprintf ("Don't know how to skip this instruction\n");
4622 					if (bpi) r_core_cmd0 (core, delb);
4623 					break;
4624 				}
4625 #endif
4626 				addr += aop.size;
4627 			}
4628 			r_debug_reg_set (core->dbg, "PC", addr);
4629 			r_reg_setv (core->anal->reg, "PC", addr);
4630 			r_core_cmd0 (core, ".dr*");
4631 			if (bpi) {
4632 				r_core_cmd0 (core, delb);
4633 			}
4634 			break;
4635 		}
4636 	case 'o': // "dso"
4637 		if (r_config_get_i (core->config, "dbg.skipover")) {
4638 			r_core_cmdf (core, "dss%s", input + 2);
4639 		} else {
4640 			if (r_config_get_i (core->config, "cfg.debug")) {
4641 				char delb[128] = R_EMPTY;
4642 				addr = r_debug_reg_get (core->dbg, "PC");
4643 				RBreakpointItem *bpi = r_bp_get_at (core->dbg->bp, addr);
4644 				sprintf(delb, "db 0x%"PFMT64x"", addr);
4645 				r_bp_del (core->dbg->bp, addr);
4646 				r_reg_arena_swap (core->dbg->reg, true);
4647 				r_debug_step_over (core->dbg, times);
4648 				if (bpi) r_core_cmd0 (core, delb);
4649 			} else {
4650 				r_core_cmdf (core, "aeso%s", input + 2);
4651 			}
4652 		}
4653 		break;
4654 	case 'b': // "dsb"
4655 		if (r_config_get_i (core->config, "cfg.debug")) {
4656 			if (!core->dbg->session) {
4657 				eprintf ("Session has not started\n");
4658 			} else if (r_debug_step_back (core->dbg, times) < 0) {
4659 				eprintf ("Error: stepping back failed\n");
4660 			}
4661 		} else {
4662 			if (r_core_esil_step_back (core)) {
4663 				r_core_cmd0 (core, ".dr*");
4664 			} else {
4665 				eprintf ("cannot step back\n");
4666 			}
4667 		}
4668 		break;
4669 	case 'l': // "dsl"
4670 		r_reg_arena_swap (core->dbg->reg, true);
4671 		step_line (core, times);
4672 		break;
4673 	case '?': // "ds?"
4674 	default:
4675 		r_core_cmd_help (core, help_msg_ds);
4676 		return 0;
4677 	}
4678 	return 1;
4679 }
4680 
getFileData(RCore * core,const char * arg)4681 static ut8*getFileData(RCore *core, const char *arg) {
4682 	if (*arg == '$') {
4683 		return (ut8*) r_cmd_alias_get (core->rcmd, arg, 1);
4684 	}
4685 	return (ut8*)r_file_slurp (arg, NULL);
4686 }
4687 
consumeBuffer(RBuffer * buf,const char * cmd,const char * errmsg)4688 static void consumeBuffer(RBuffer *buf, const char *cmd, const char *errmsg) {
4689 	if (!buf) {
4690 		if (errmsg) {
4691 			r_cons_printf ("%s\n", errmsg);
4692 		}
4693 		return;
4694 	}
4695 	if (cmd) {
4696 		r_cons_printf ("%s", cmd);
4697 	}
4698 	int i;
4699 	r_buf_seek (buf, 0, R_BUF_SET);
4700 	for (i = 0; i < r_buf_size (buf); i++) {
4701 		r_cons_printf ("%02x", r_buf_read8 (buf));
4702 	}
4703 	r_cons_printf ("\n");
4704 }
4705 
cmd_debug(void * data,const char * input)4706 static int cmd_debug(void *data, const char *input) {
4707 	RCore *core = (RCore *)data;
4708 	RDebugTracepoint *t;
4709 	int follow = 0;
4710 	const char *ptr;
4711 	ut64 addr;
4712 	int min;
4713 	RListIter *iter;
4714 	RList *list;
4715 	RDebugPid *p;
4716 	RDebugTracepoint *trace;
4717 	RAnalOp *op;
4718 
4719 	if (r_sandbox_enable (0)) {
4720 		eprintf ("Debugger commands disabled in sandbox mode\n");
4721 		return 0;
4722 	}
4723 	if (!strncmp (input, "ate", 3)) {
4724 		char str[128];
4725 		str[0] = 0;
4726 		r_print_date_get_now (core->print, str);
4727 		r_cons_println (str);
4728 		return 0;
4729 	}
4730 
4731 	switch (input[0]) {
4732 	case 't':
4733 		// TODO: define ranges? to display only some traces, allow to scroll on this disasm? ~.. ?
4734 		switch (input[1]) {
4735 		case '\0': // "dt"
4736 			r_debug_trace_list (core->dbg, 0, core->offset);
4737 			break;
4738 		case '=': // "dt="
4739 			r_debug_trace_list (core->dbg, '=', core->offset);
4740 			break;
4741 		case 'q': // "dtq"
4742 			r_debug_trace_list (core->dbg, 'q', core->offset);
4743 			break;
4744 		case '*': // "dt*"
4745 			r_debug_trace_list (core->dbg, 1, core->offset);
4746 			break;
4747 		case ' ': // "dt [addr]"
4748 			if ((t = r_debug_trace_get (core->dbg,
4749 					r_num_math (core->num, input + 3)))) {
4750 				r_cons_printf ("offset = 0x%" PFMT64x "\n", t->addr);
4751 				r_cons_printf ("opsize = %d\n", t->size);
4752 				r_cons_printf ("times = %d\n", t->times);
4753 				r_cons_printf ("count = %d\n", t->count);
4754 				//TODO cons_printf("time = %d\n", t->tm);
4755 			}
4756 			break;
4757 		case 'a': // "dta"
4758 			r_debug_trace_at (core->dbg, input + 3);
4759 			break;
4760 		case 't': // "dtt"
4761 			r_debug_trace_tag (core->dbg, atoi (input + 3));
4762 			break;
4763 		case 'c': // "dtc"
4764 			if (input[2] == '?') {
4765 				r_cons_println ("Usage: dtc [addr] ([from] [to] [addr]) - trace calls in debugger");
4766 			} else {
4767 				debug_trace_calls (core, input + 2);
4768 			}
4769 			break;
4770 		case 'd': // "dtd"
4771 			min = r_num_math (core->num, input + 3);
4772 			if (input[2] == 'q') { // "dtdq"
4773 				int n = 0;
4774 				r_list_foreach (core->dbg->trace->traces, iter, trace) {
4775 					if (n >= min) {
4776 						r_cons_printf ("%d  ", trace->count);
4777 						r_cons_printf ("0x%08"PFMT64x"\n", trace->addr);
4778 						break;
4779 					}
4780 					n++;
4781 				}
4782 			} else if (input[2] == 'i') {
4783 				int n = 0;
4784 				r_list_foreach (core->dbg->trace->traces, iter, trace) {
4785 					op = r_core_anal_op (core, trace->addr, R_ANAL_OP_MASK_BASIC | R_ANAL_OP_MASK_DISASM);
4786 					if (n >= min) {
4787 						r_cons_printf ("%d %s\n", trace->count, op->mnemonic);
4788 					}
4789 					n++;
4790 					r_anal_op_free (op);
4791 				}
4792 			} else if (input[2] == ' ') {
4793 				int n = 0;
4794 				r_list_foreach (core->dbg->trace->traces, iter, trace) {
4795 					op = r_core_anal_op (core, trace->addr, R_ANAL_OP_MASK_BASIC | R_ANAL_OP_MASK_DISASM);
4796 					if (n >= min) {
4797 						r_cons_printf ("0x%08"PFMT64x" %s\n", trace->addr, op->mnemonic);
4798 					}
4799 					n++;
4800 					r_anal_op_free (op);
4801 				}
4802 			} else {
4803 				// TODO: reimplement using the api
4804 				//r_core_cmd0 (core, "pd 1 @@= `dtq`");
4805 				r_list_foreach (core->dbg->trace->traces, iter, trace) {
4806 					op = r_core_anal_op (core, trace->addr, R_ANAL_OP_MASK_BASIC | R_ANAL_OP_MASK_DISASM);
4807 					r_cons_printf ("0x%08"PFMT64x" %s\n", trace->addr, op->mnemonic);
4808 					r_anal_op_free (op);
4809 				}
4810 			}
4811 			break;
4812 		case 'g': // "dtg"
4813 			dot_trace_traverse (core, core->dbg->tree, input[2]);
4814 			break;
4815 		case '-': // "dt-"
4816 			r_tree_reset (core->dbg->tree);
4817 			r_debug_trace_free (core->dbg->trace);
4818 			r_debug_tracenodes_reset (core->dbg);
4819 			core->dbg->trace = r_debug_trace_new ();
4820 			break;
4821 		case '+': // "dt+"
4822 			if (input[2] == '+') { // "dt++"
4823 				char *a, *s = r_str_trim_dup (input + 3);
4824 				RList *args = r_str_split_list (s, " ", 0);
4825 				RListIter *iter;
4826 				r_list_foreach (args, iter, a) {
4827 					ut64 addr = r_num_get (NULL, a);
4828 					(void)r_debug_trace_add (core->dbg, addr, 1);
4829 				}
4830 				r_list_free (args);
4831 				free (s);
4832 			} else {
4833 				ptr = input + 2;
4834 				addr = r_num_math (core->num, ptr);
4835 				ptr = strchr (ptr, ' ');
4836 				int count = 1;
4837 				if (ptr) {
4838 					count = r_num_math (core->num, ptr + 1);
4839 				}
4840 				RAnalOp *op = r_core_op_anal (core, addr, R_ANAL_OP_MASK_HINT);
4841 				if (op) {
4842 					RDebugTracepoint *tp = r_debug_trace_add (core->dbg, addr, op->size);
4843 					if (!tp) {
4844 						r_anal_op_free (op);
4845 						break;
4846 					}
4847 					tp->count = count;
4848 					r_anal_trace_bb (core->anal, addr);
4849 					r_anal_op_free (op);
4850 				} else {
4851 					eprintf ("Cannot analyze opcode at 0x%08" PFMT64x "\n", addr);
4852 				}
4853 			}
4854 			break;
4855 		case 'e': // "dte"
4856 			if (!core->anal->esil) {
4857 				int stacksize = r_config_get_i (core->config, "esil.stack.depth");
4858 				int romem = r_config_get_i (core->config, "esil.romem");
4859 				int stats = r_config_get_i (core->config, "esil.stats");
4860 				int iotrap = r_config_get_i (core->config, "esil.iotrap");
4861 				int nonull = r_config_get_i (core->config, "esil.nonull");
4862 				unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
4863 				if (!(core->anal->esil = r_anal_esil_new (stacksize, iotrap, addrsize))) {
4864 					return 0;
4865 				}
4866 				r_anal_esil_setup (core->anal->esil, core->anal, romem, stats, nonull);
4867 			}
4868 			switch (input[2]) {
4869 			case 0: // "dte"
4870 				r_anal_esil_trace_list (core->anal->esil);
4871 				break;
4872 			case 'i': { // "dtei"
4873 				ut64 addr = r_num_math (core->num, input + 3);
4874 				if (!addr) {
4875 					addr = core->offset;
4876 				}
4877 				RAnalOp *op = r_core_anal_op (core, addr, R_ANAL_OP_MASK_ESIL);
4878 				if (op) {
4879 					r_anal_esil_trace_op (core->anal->esil, op);
4880 				}
4881 				r_anal_op_free (op);
4882 			} break;
4883 			case '-': // "dte-"
4884 				if (!strcmp (input + 3, "*")) {
4885 					if (core->anal->esil) {
4886 						sdb_free (core->anal->esil->trace->db);
4887 						core->anal->esil->trace->db = sdb_new0 ();
4888 					}
4889 				} else {
4890 					eprintf ("TODO: dte- cannot delete specific logs. Use dte-*\n");
4891 				}
4892 				break;
4893 			case ' ': { // "dte "
4894 				int idx = atoi (input + 3);
4895 				r_anal_esil_trace_show (
4896 					core->anal->esil, idx);
4897 			} break;
4898 			case 'k': // "dtek"
4899 				if (input[3] == ' ') {
4900 					char *s = sdb_querys (core->anal->esil->trace->db,
4901 							NULL, 0, input + 4);
4902 					r_cons_println (s);
4903 					free (s);
4904 				} else {
4905 					eprintf ("Usage: dtek [query]\n");
4906 				}
4907 				break;
4908 			default:
4909 				r_core_cmd_help (core, help_msg_dte);
4910 			}
4911 			break;
4912 		case 's': // "dts"
4913 			switch (input[2]) {
4914 			case '+': // "dts+"
4915 				if (r_debug_is_dead (core->dbg)) {
4916 					eprintf ("Cannot start session outside of debug mode, run ood?\n");
4917 					break;
4918 				}
4919 				if (core->dbg->session) {
4920 					eprintf ("Session already started\n");
4921 					break;
4922 				}
4923 				core->dbg->session = r_debug_session_new ();
4924 				r_debug_add_checkpoint (core->dbg);
4925 				break;
4926 			case '-': // "dts-"
4927 				if (!core->dbg->session) {
4928 					eprintf ("No session started\n");
4929 					break;
4930 				}
4931 				r_debug_session_free (core->dbg->session);
4932 				core->dbg->session = NULL;
4933 				break;
4934 			case 't': // "dtst"
4935 				if (!core->dbg->session) {
4936 					eprintf ("No session started\n");
4937 					break;
4938 				}
4939 				r_debug_session_save (core->dbg->session, input + 4);
4940 				break;
4941 			case 'f': // "dtsf"
4942 				if (core->dbg->session) {
4943 					r_debug_session_free (core->dbg->session);
4944 					core->dbg->session = NULL;
4945 				}
4946 				core->dbg->session = r_debug_session_new ();
4947 				r_debug_session_load (core->dbg, input + 4);
4948 				break;
4949 			case 'm': // "dtsm"
4950 				if (core->dbg->session) {
4951 					r_debug_session_list_memory (core->dbg);
4952 				}
4953 				break;
4954 			default:
4955 				r_core_cmd_help (core, help_msg_dts);
4956 			}
4957 			break;
4958 		case '?':
4959 		default:
4960 			{
4961 				r_core_cmd_help (core, help_msg_dt);
4962 				r_cons_printf ("Current Tag: %d\n", core->dbg->trace->tag);
4963 			}
4964 			break;
4965 		}
4966 		break;
4967 	case 'd': // "ddd"
4968 		switch (input[1]) {
4969 		case '\0': // "ddd"
4970 			r_debug_desc_list (core->dbg, 0);
4971 			break;
4972 		case '*': // "dtd*"
4973 			r_debug_desc_list (core->dbg, 1);
4974 			break;
4975 		case 's': // "dtds"
4976 			{
4977 				ut64 off = UT64_MAX;
4978 				int fd = atoi (input + 2);
4979 				char *str = strchr (input + 2, ' ');
4980 				if (str) off = r_num_math (core->num, str+1);
4981 				if (off == UT64_MAX || !r_debug_desc_seek (core->dbg, fd, off)) {
4982 					RBuffer *buf = r_core_syscallf (core, "lseek", "%d, 0x%"PFMT64x", %d", fd, off, 0);
4983 					consumeBuffer (buf, "dx ", "Cannot seek");
4984 				}
4985 			}
4986 			break;
4987 		case 't': // "ddt" <ttypath>
4988 			r_core_cmdf (core, "dd-0");
4989 			break;
4990 		case 'd': // "ddd"
4991 			{
4992 				ut64 newfd = UT64_MAX;
4993 				int fd = atoi (input + 2);
4994 				char *str = strchr (input + 3, ' ');
4995 				if (str) newfd = r_num_math (core->num, str+1);
4996 				if (newfd == UT64_MAX || !r_debug_desc_dup (core->dbg, fd, newfd)) {
4997 					RBuffer *buf = r_core_syscallf (core, "dup2", "%d, %d", fd, (int)newfd);
4998 					if (buf) {
4999 						consumeBuffer (buf, "dx ", NULL);
5000 					} else {
5001 						eprintf ("Cannot dup %d %d\n", fd, (int)newfd);
5002 					}
5003 				}
5004 			}
5005 			break;
5006 		case 'r':
5007 			{
5008 				ut64 off = UT64_MAX;
5009 				ut64 len = UT64_MAX;
5010 				int fd = atoi (input + 2);
5011 				char *str = strchr (input + 2, ' ');
5012 				if (str) off = r_num_math (core->num, str+1);
5013 				if (str) str = strchr (str+1, ' ');
5014 				if (str) len = r_num_math (core->num, str+1);
5015 				if (len == UT64_MAX || off == UT64_MAX || \
5016 						!r_debug_desc_read (core->dbg, fd, off, len)) {
5017 					consumeBuffer (r_core_syscallf (core, "read", "%d, 0x%"PFMT64x", %d",
5018 								fd, off, (int)len), "dx ", "Cannot read");
5019 				}
5020 			}
5021 			break;
5022 		case 'w':
5023 			{
5024 				ut64 off = UT64_MAX;
5025 				ut64 len = UT64_MAX;
5026 				int fd = atoi (input + 2);
5027 				char *str = strchr (input + 2, ' ');
5028 				if (str) off = r_num_math (core->num, str+1);
5029 				if (str) str = strchr (str+1, ' ');
5030 				if (str) len = r_num_math (core->num, str+1);
5031 				if (len == UT64_MAX || off == UT64_MAX || \
5032 						!r_debug_desc_write (core->dbg, fd, off, len)) {
5033 					RBuffer *buf = r_core_syscallf (core, "write", "%d, 0x%"PFMT64x", %d", fd, off, (int)len);
5034 					consumeBuffer (buf, "dx ", "Cannot write");
5035 				}
5036 			}
5037 			break;
5038 		case '-': // "dd-"
5039 			// close file
5040 			//r_core_syscallf (core, "close", "%d", atoi (input + 2));
5041 			{
5042 				int fd = atoi (input + 2);
5043 				//r_core_cmdf (core, "dxs close %d", (int)r_num_math ( core->num, input + 2));
5044 				RBuffer *buf = r_core_syscallf (core, "close", "%d", fd);
5045 				consumeBuffer (buf, "dx ", "Cannot close");
5046 			}
5047 			break;
5048 		case ' ': // "dd"
5049 			// TODO: handle read, readwrite, append
5050 			{
5051 				RBuffer *buf = r_core_syscallf (core, "open", "%s, %d, %d", input + 2, 2, 0644);
5052 				consumeBuffer (buf, "dx ", "Cannot open");
5053 			}
5054 			// open file
5055 			break;
5056 		case '?':
5057 		default:
5058 			r_core_cmd_help (core, help_msg_dd);
5059 			break;
5060 		}
5061 		break;
5062 	case 's':
5063 		if (cmd_debug_step (core, input)) {
5064 			follow = r_config_get_i (core->config, "dbg.follow");
5065 		}
5066 		break;
5067 	case 'b':
5068 		r_core_cmd_bp (core, input);
5069 		break;
5070 	case 'H':
5071 		eprintf ("TODO: transplant process\n");
5072 		break;
5073 	case 'c': // "dc"
5074 		r_cons_break_push (static_debug_stop, core->dbg);
5075 		(void)cmd_debug_continue (core, input);
5076 		follow = r_config_get_i (core->config, "dbg.follow");
5077 		r_cons_break_pop ();
5078 		break;
5079 	case 'm': // "dm"
5080 		cmd_debug_map (core, input + 1);
5081 		break;
5082 	case 'r': // "dr"
5083 		if (r_config_get_i (core->config, "cfg.debug") || input[1] == '?') {
5084 			cmd_debug_reg (core, input + 1);
5085 		} else {
5086 			cmd_anal_reg (core, input + 1);
5087 		}
5088 		//r_core_cmd (core, "|reg", 0);
5089 		break;
5090 	case 'p': // "dp"
5091 		cmd_debug_pid (core, input);
5092 		break;
5093 	case 'L': // "dL"
5094 		switch (input[1]) {
5095 		case 'q':
5096 			r_debug_plugin_list (core->dbg, input[1]);
5097 			break;
5098 		case 'j':
5099 			core->dbg->pj = r_core_pj_new (core);
5100 			r_debug_plugin_list (core->dbg, 'j');
5101 			pj_free (core->dbg->pj);
5102 			core->dbg->pj = NULL;
5103 			break;
5104 		case '?':
5105 			r_core_cmd_help (core, help_msg_dL);
5106 			break;
5107 		case ' ': {
5108 			char *str = r_str_trim_dup (input + 2);
5109 			r_config_set (core->config, "dbg.backend", str);
5110 			// implicit by config.set r_debug_use (core->dbg, str);
5111 			free (str);
5112 			}
5113 			break;
5114 		default:
5115 			r_debug_plugin_list (core->dbg, 0);
5116 			break;
5117 		}
5118 		break;
5119 	case 'i': // "di"
5120 		{
5121 			RDebugInfo *rdi = r_debug_info (core->dbg, input + 2);
5122 			RDebugReasonType stop = r_debug_stop_reason (core->dbg);
5123 			char *escaped_str;
5124 			switch (input[1]) {
5125 			case '\0': // "di"
5126 #define P r_cons_printf
5127 #define PS(X, Y) {escaped_str = r_str_escape (Y);r_cons_printf(X, escaped_str);free(escaped_str);}
5128 				if (rdi) {
5129 					const char *s = r_signal_to_string (core->dbg->reason.signum);
5130 					P ("type=%s\n", r_debug_reason_to_string (core->dbg->reason.type));
5131 					P ("signal=%s\n", r_str_get_fail (s, "none"));
5132 					P ("signum=%d\n", core->dbg->reason.signum);
5133 					P ("sigpid=%d\n", core->dbg->reason.tid);
5134 					P ("addr=0x%"PFMT64x"\n", core->dbg->reason.addr);
5135 					P ("bp_addr=0x%"PFMT64x"\n", core->dbg->reason.bp_addr);
5136 					P ("inbp=%s\n", r_str_bool (core->dbg->reason.bp_addr));
5137 					P ("baddr=0x%"PFMT64x"\n", r_debug_get_baddr (core->dbg, NULL));
5138 					P ("pid=%d\n", rdi->pid);
5139 					P ("tid=%d\n", rdi->tid);
5140 					P ("stopaddr=0x%"PFMT64x"\n", core->dbg->stopaddr);
5141 					if (rdi->uid != -1) {
5142 						P ("uid=%d\n", rdi->uid);
5143 					}
5144 					if (rdi->gid != -1) {
5145 						P ("gid=%d\n", rdi->gid);
5146 					}
5147 					if (rdi->usr) {
5148 						P ("usr=%s\n", rdi->usr);
5149 					}
5150 					if (rdi->exe && *rdi->exe) {
5151 						P ("exe=%s\n", rdi->exe);
5152 					}
5153 					if (rdi->cmdline && *rdi->cmdline) {
5154 						P ("cmdline=%s\n", rdi->cmdline);
5155 					}
5156 					if (rdi->cwd && *rdi->cwd) {
5157 						P ("cwd=%s\n", rdi->cwd);
5158 					}
5159 					if (rdi->kernel_stack && *rdi->kernel_stack) {
5160 						P ("kernel_stack=\n%s\n", rdi->kernel_stack);
5161 					}
5162 				}
5163 				if (stop != -1) {
5164 					P ("stopreason=%d\n", stop);
5165 				}
5166 				break;
5167 			case 'f': // "dif" "diff"
5168 				if (input[1] == '?') {
5169 					eprintf ("Usage: dif $a $b  # diff two alias files\n");
5170 				} else {
5171 					char *arg = strchr (input, ' ');
5172 					if (arg) {
5173 						arg = strdup (r_str_trim_head_ro (arg + 1));
5174 						char *arg2 = strchr (arg, ' ');
5175 						if (arg2) {
5176 							*arg2++ = 0;
5177 							ut8 *a = getFileData (core, arg);
5178 							ut8 *b = getFileData (core, arg2);
5179 							if (a && b) {
5180 								int al = strlen ((const char*)a);
5181 								int bl = strlen ((const char*)b);
5182 								RDiff *d = r_diff_new ();
5183 								char *uni = r_diff_buffers_to_string (d, a, al, b, bl);
5184 								r_cons_printf ("%s\n", uni);
5185 								r_diff_free (d);
5186 								free (uni);
5187 							} else {
5188 								eprintf ("Cannot open those alias files\n");
5189 							}
5190 						}
5191 						free (arg);
5192 					} else {
5193 						eprintf ("Usage: dif $a $b  # diff two alias files\n");
5194 					}
5195 				}
5196 				break;
5197 			case '*': // "di*"
5198 				if (rdi) {
5199 					r_cons_printf ("f dbg.signal = %d\n", core->dbg->reason.signum);
5200 					r_cons_printf ("f dbg.sigpid = %d\n", core->dbg->reason.tid);
5201 					r_cons_printf ("f dbg.inbp = %d\n", core->dbg->reason.bp_addr? 1: 0);
5202 					r_cons_printf ("f dbg.sigaddr = 0x%"PFMT64x"\n", core->dbg->reason.addr);
5203 					r_cons_printf ("f dbg.baddr = 0x%"PFMT64x"\n", r_debug_get_baddr (core->dbg, NULL));
5204 					r_cons_printf ("f dbg.pid = %d\n", rdi->pid);
5205 					r_cons_printf ("f dbg.tid = %d\n", rdi->tid);
5206 					r_cons_printf ("f dbg.uid = %d\n", rdi->uid);
5207 					r_cons_printf ("f dbg.gid = %d\n", rdi->gid);
5208 				}
5209 				break;
5210 			case 'j': // "dij"
5211 				P ("{");
5212 				if (rdi) {
5213 					const char *s = r_signal_to_string (core->dbg->reason.signum);
5214 					P ("\"type\":\"%s\",", r_debug_reason_to_string (core->dbg->reason.type));
5215 					P ("\"signal\":\"%s\",", r_str_get_fail (s, "none"));
5216 					P ("\"signum\":%d,", core->dbg->reason.signum);
5217 					P ("\"sigpid\":%d,", core->dbg->reason.tid);
5218 					P ("\"addr\":%"PFMT64d",", core->dbg->reason.addr);
5219 					P ("\"inbp\":%s,", r_str_bool (core->dbg->reason.bp_addr));
5220 					P ("\"baddr\":%"PFMT64d",", r_debug_get_baddr (core->dbg, NULL));
5221 					P ("\"stopaddr\":%"PFMT64d",", core->dbg->stopaddr);
5222 					P ("\"pid\":%d,", rdi->pid);
5223 					P ("\"tid\":%d,", rdi->tid);
5224 					P ("\"uid\":%d,", rdi->uid);
5225 					P ("\"gid\":%d,", rdi->gid);
5226 					if (rdi->usr) {
5227 						PS("\"usr\":\"%s\",", rdi->usr);
5228 					}
5229 					if (rdi->exe) {
5230 						PS("\"exe\":\"%s\",", rdi->exe);
5231 					}
5232 					if (rdi->cmdline) {
5233 						PS ("\"cmdline\":\"%s\",", rdi->cmdline);
5234 					}
5235 					if (rdi->cwd) {
5236 						PS ("\"cwd\":\"%s\",", rdi->cwd);
5237 					}
5238 				}
5239 				P ("\"stopreason\":%d}\n", stop);
5240 				break;
5241 #undef P
5242 #undef PS
5243 			case 'q':
5244 				{
5245 					const char *r = r_debug_reason_to_string (core->dbg->reason.type);
5246 					if (!r) {
5247 						r = "none";
5248 					}
5249 					r_cons_printf ("%s at 0x%08"PFMT64x"\n", r, core->dbg->stopaddr);
5250 				}
5251 				break;
5252 			case '?': // "di?"
5253 			default:
5254 				r_core_cmd_help (core, help_msg_di);
5255 				break;
5256 			}
5257 			r_debug_info_free (rdi);
5258 		}
5259 		break;
5260 	case 'e': // "de"
5261 		r_core_debug_esil (core, input + 1);
5262 		break;
5263 	case 'g': // "dg"
5264 		if (core->dbg->h && core->dbg->h->gcore) {
5265 			if (core->dbg->pid == -1) {
5266 				eprintf ("Not debugging, can't write core.\n");
5267 				break;
5268 			}
5269 			char *corefile = get_corefile_name (input + 1, core->dbg->pid);
5270 			eprintf ("Writing to file '%s'\n", corefile);
5271 			r_file_rm (corefile);
5272 			RBuffer *dst = r_buf_new_file (corefile, O_RDWR | O_CREAT, 0644);
5273 			if (dst) {
5274 				if (!core->dbg->h->gcore (core->dbg, dst)) {
5275 					eprintf ("dg: coredump failed\n");
5276 				}
5277 				r_buf_free (dst);
5278 			} else {
5279 				perror ("r_buf_new_file");
5280 			}
5281 			free (corefile);
5282 		}
5283 		break;
5284 	case 'k': // "dk"
5285 		r_core_debug_kill (core, input + 1);
5286 		break;
5287 	case 'o': // "do"
5288 		switch (input[1]) {
5289 		case '\0': // "do"
5290 			r_core_file_reopen (core, input[1] ? input + 2: NULL, 0, 1);
5291 			break;
5292 		case 'e': // "doe"
5293 			switch (input[2]) {
5294 			case '\0': // "doe"
5295 				if (core->io->envprofile) {
5296 					r_cons_println (core->io->envprofile);
5297 				}
5298 				break;
5299 			case '!': // "doe!"
5300 			{
5301 				char *out = r_core_editor (core, NULL, core->io->envprofile);
5302 				if (out) {
5303 					free (core->io->envprofile);
5304 					core->io->envprofile = out;
5305 					eprintf ("%s\n", core->io->envprofile);
5306 				}
5307 			} break;
5308 			default:
5309 				break;
5310 			}
5311 			break;
5312 		case 'r': // "dor" : rarun profile
5313 			if (input[2] == ' ') {
5314 				setRarunProfileString (core, input + 3);
5315 			} else {
5316 				// TODO use the api
5317 				r_sys_cmd ("rarun2 -h");
5318 			}
5319 			break;
5320 		case 'o': // "doo" : reopen in debug mode
5321 			if (input[2] == 'f') { // "doof" : reopen in debug mode from the given file
5322 				r_config_set_i (core->config, "cfg.debug", true);
5323 				r_core_cmd0 (core, sdb_fmt ("oodf %s", input + 3));
5324 			} else {
5325 				r_core_file_reopen_debug (core, input + 2);
5326 			}
5327 			break;
5328 		case 'c': // "doc" : close current debug session
5329 			if (!core || !core->io || !core->io->desc || !r_config_get_i (core->config, "cfg.debug")) {
5330 				eprintf ("No open debug session\n");
5331 				break;
5332 			}
5333 			// Stop trace session
5334 			if (core->dbg->session) {
5335 				r_debug_session_free (core->dbg->session);
5336 				core->dbg->session = NULL;
5337 			}
5338 			// Kill debugee and all child processes
5339 			if (core->dbg && core->dbg->h && core->dbg->h->pids && core->dbg->pid != -1) {
5340 				list = core->dbg->h->pids (core->dbg, core->dbg->pid);
5341 				if (list) {
5342 					r_list_foreach (list, iter, p) {
5343 						r_debug_kill (core->dbg, p->pid, p->pid, SIGKILL);
5344 						r_debug_detach (core->dbg, p->pid);
5345 					}
5346 				} else {
5347 					r_debug_kill (core->dbg, core->dbg->pid, core->dbg->pid, SIGKILL);
5348 					r_debug_detach (core->dbg, core->dbg->pid);
5349 				}
5350 			}
5351 			// Remove registers from the flag list
5352 			r_core_cmd0 (core, ".dr-*");
5353 			// Reopen and rebase the original file
5354 			r_core_cmd0 (core, "oo");
5355 			break;
5356 		case '?': // "do?"
5357 		default:
5358 			r_core_cmd_help (core, help_msg_do);
5359 			break;
5360 		}
5361 		break;
5362 #if __WINDOWS__
5363 	case 'W': // "dW"
5364 		if (input[1] == 'i') {
5365 			r_w32_identify_window ();
5366 		} else {
5367 			r_w32_print_windows (core->dbg);
5368 		}
5369 		break;
5370 #endif
5371 	case 'w': // "dw"
5372 		r_cons_break_push (static_debug_stop, core->dbg);
5373 		for (;!r_cons_is_breaked ();) {
5374 			int pid = atoi (input + 1);
5375 			//int opid = core->dbg->pid = pid;
5376 			int res = r_debug_kill (core->dbg, pid, 0, 0);
5377 			if (!res) {
5378 				break;
5379 			}
5380 			r_sys_usleep (200);
5381 		}
5382 		r_cons_break_pop ();
5383 		break;
5384 	case 'x': // "dx"
5385 		switch (input[1]) {
5386 		case ' ': { // "dx "
5387 			ut8 bytes[4096];
5388 			if (strlen (input + 2) < 4096){
5389 				int bytes_len = r_hex_str2bin (input + 2, bytes);
5390 				if (bytes_len>0) r_debug_execute (core->dbg,
5391 						bytes, bytes_len, 0);
5392 				else eprintf ("Invalid hexpairs\n");
5393 			} else eprintf ("Injection opcodes so long\n");
5394 			break;
5395 		}
5396 		case 'a': { // "dxa"
5397 			RAsmCode *acode;
5398 			r_asm_set_pc (core->rasm, core->offset);
5399 			acode = r_asm_massemble (core->rasm, input + 2);
5400 			if (acode) {
5401 				r_reg_arena_push (core->dbg->reg);
5402 				r_debug_execute (core->dbg, acode->bytes, acode->len, 0);
5403 				r_reg_arena_pop (core->dbg->reg);
5404 			}
5405 			r_asm_code_free (acode);
5406 			break;
5407 		}
5408 		case 'e': { // "dxe"
5409 			REgg *egg = core->egg;
5410 			RBuffer *b;
5411 			const char *asm_arch = r_config_get (core->config, "asm.arch");
5412 			int asm_bits = r_config_get_i (core->config, "asm.bits");
5413 			const char *asm_os = r_config_get (core->config, "asm.os");
5414 			r_egg_setup (egg, asm_arch, asm_bits, 0, asm_os);
5415 			r_egg_reset (egg);
5416 			r_egg_load (egg, input + 1, 0);
5417 			r_egg_compile (egg);
5418 			b = r_egg_get_bin (egg);
5419 			r_asm_set_pc (core->rasm, core->offset);
5420 			r_reg_arena_push (core->dbg->reg);
5421 			ut64 tmpsz;
5422 			const ut8 *tmp = r_buf_data (b, &tmpsz);
5423 			r_debug_execute (core->dbg, tmp, tmpsz, 0);
5424 			r_reg_arena_pop (core->dbg->reg);
5425 			break;
5426 		}
5427 		case 'r': // "dxr"
5428 			r_reg_arena_push (core->dbg->reg);
5429 			if (input[2] == ' ') {
5430 				ut8 bytes[4096];
5431 				if (strlen (input + 2) < 4096){
5432 					int bytes_len = r_hex_str2bin (input + 2,
5433 							bytes);
5434 					if (bytes_len > 0) {
5435 						r_debug_execute (core->dbg,
5436 								bytes, bytes_len,
5437 								0);
5438 					} else {
5439 						eprintf ("Invalid hexpairs\n");
5440 					}
5441 				} else eprintf ("Injection opcodes so long\n");
5442 			}
5443 			r_reg_arena_pop (core->dbg->reg);
5444 			break;
5445 		case 's': // "dxs"
5446 			if (input[2]) {
5447 				char *str;
5448 				r_cons_push ();
5449 				str = r_core_cmd_str (core, sdb_fmt ("gs %s", input + 2));
5450 				r_cons_pop ();
5451 				r_core_cmdf (core, "dx %s", str); //`gs %s`", input + 2);
5452 				free (str);
5453 			} else {
5454 				eprintf ("Missing parameter used in gs by dxs\n");
5455 			}
5456 			break;
5457 		case '?': // "dx?"
5458 		default:
5459 			r_core_cmd_help (core, help_msg_dx);
5460 			break;
5461 		}
5462 		break;
5463 	case '?': // "d?"
5464 	default:
5465 		r_core_cmd_help (core, help_msg_d);
5466 		break;
5467 	}
5468 	if (follow > 0) {
5469 		ut64 pc = r_debug_reg_get (core->dbg, "PC");
5470 		if ((pc < core->offset) || (pc > (core->offset + follow))) {
5471 			r_core_cmd0 (core, "sr PC");
5472 		}
5473 	}
5474 	return 0;
5475 }
5476