2018-01-27 22:32:47 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2018 - pancake, maijin */
|
2012-02-27 01:40:27 +00:00
|
|
|
|
2015-01-27 04:47:27 +00:00
|
|
|
#include "r_util.h"
|
2016-05-03 02:52:41 +00:00
|
|
|
#include "r_core.h"
|
2016-08-21 09:50:33 +00:00
|
|
|
|
2017-07-24 15:41:50 +00:00
|
|
|
static const char *help_msg_a[] = {
|
|
|
|
"Usage:", "a", "[abdefFghoprxstc] [...]",
|
|
|
|
"aa", "[?]", "analyze all (fcns + bbs) (aa0 to avoid sub renaming)",
|
2018-04-05 07:30:47 +00:00
|
|
|
"a8", " [hexpairs]", "analyze bytes",
|
|
|
|
"ab", "[b] [addr]", "analyze block at given address",
|
2017-07-24 15:41:50 +00:00
|
|
|
"abb", " [len]", "analyze N basic blocks in [len] (section.size by default)",
|
|
|
|
"ac", " [cycles]", "analyze which op could be executed in [cycles]",
|
|
|
|
"ad", "[?]", "analyze data trampoline (wip)",
|
|
|
|
"ad", " [from] [to]", "analyze data pointers to (from-to)",
|
|
|
|
"ae", "[?] [expr]", "analyze opcode eval expression (see ao)",
|
|
|
|
"af", "[?]", "analyze Functions",
|
|
|
|
"aF", "", "same as above, but using anal.depth=1",
|
|
|
|
"ag", "[?] [options]", "output Graphviz code",
|
|
|
|
"ah", "[?]", "analysis hints (force opcode size, ...)",
|
|
|
|
"ai", " [addr]", "address information (show perms, stack, heap, ...)",
|
2017-11-30 13:21:24 +00:00
|
|
|
"an"," [name] [@addr]","show/rename/create whatever flag/function is used at addr",
|
2017-07-24 15:41:50 +00:00
|
|
|
"ao", "[?] [len]", "analyze Opcodes (or emulate it)",
|
2017-12-18 14:58:06 +00:00
|
|
|
"aO", "[?] [len]", "Analyze N instructions in M bytes",
|
2017-07-24 15:41:50 +00:00
|
|
|
"ap", "", "find prelude for current offset",
|
|
|
|
"ar", "[?]", "like 'dr' but for the esil vm. (registers)",
|
|
|
|
"as", "[?] [num]", "analyze syscall using dbg.reg",
|
|
|
|
"av", "[?] [.]", "show vtables",
|
|
|
|
"ax", "[?]", "manage refs/xrefs (see also afx?)",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_aa[] = {
|
|
|
|
"Usage:", "aa[0*?]", " # see also 'af' and 'afna'",
|
|
|
|
"aa", " ", "alias for 'af@@ sym.*;af@entry0;afva'", //;.afna @@ fcn.*'",
|
|
|
|
"aa*", "", "analyze all flags starting with sym. (af @@ sym.*)",
|
|
|
|
"aaa", "[?]", "autoname functions after aa (see afna)",
|
|
|
|
"aab", "", "aab across io.sections.text",
|
|
|
|
"aac", " [len]", "analyze function calls (af @@ `pi len~call[1]`)",
|
2017-09-08 14:44:37 +00:00
|
|
|
"aac*", " [len]", "flag function calls without performing a complete analysis",
|
2017-07-24 15:41:50 +00:00
|
|
|
"aad", " [len]", "analyze data references to code",
|
|
|
|
"aae", " [len] ([addr])", "analyze references with ESIL (optionally to address)",
|
2017-08-27 18:52:35 +00:00
|
|
|
"aaE", "", "run aef on all functions (same as aef @@f)",
|
2018-04-11 23:01:51 +00:00
|
|
|
"aaf", " ", "analyze all functions (e anal.hasnext=1;afr @@c:isq)",
|
2017-07-24 15:41:50 +00:00
|
|
|
"aai", "[j]", "show info of all analysis parameters",
|
|
|
|
"aan", "", "autoname functions that either start with fcn.* or sym.func.*",
|
|
|
|
"aap", "", "find and analyze function preludes",
|
|
|
|
"aar", "[?] [len]", "analyze len bytes of instructions for references",
|
|
|
|
"aas", " [len]", "analyze symbols (af @@= `isq~[0]`)",
|
|
|
|
"aat", " [len]", "analyze all consecutive functions in section",
|
|
|
|
"aaT", " [len]", "analyze code after trap-sleds",
|
|
|
|
"aau", " [len]", "list mem areas (larger than len bytes) not covered by functions",
|
|
|
|
"aav", " [sat]", "find values referencing a specific section or map",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_aar[] = {
|
|
|
|
"Usage:", "aar", "[j*] [sz] # search and analyze xrefs",
|
|
|
|
"aar", " [sz]", "analyze xrefs in current section or sz bytes of code",
|
|
|
|
"aar*", " [sz]", "list found xrefs in radare commands format",
|
|
|
|
"aarj", " [sz]", "list found xrefs in JSON format",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2018-04-04 23:45:12 +00:00
|
|
|
static const char *help_msg_ab[] = {
|
|
|
|
"Usage:", "ab", "",
|
|
|
|
"ab", " [addr]", "show basic block information at given address",
|
|
|
|
"abb", " [length]", "analyze N bytes and extract basic blocks",
|
|
|
|
"abj", "", "display basic block information in JSON",
|
|
|
|
"abx", " [hexpair-bytes]", "analyze N bytes",
|
2017-08-18 13:04:48 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-24 15:41:50 +00:00
|
|
|
static const char *help_msg_ad[] = {
|
|
|
|
"Usage:", "ad", "[kt] [...]",
|
|
|
|
"ad", " [N] [D]", "analyze N data words at D depth",
|
|
|
|
"ad4", " [N] [D]", "analyze N data words at D depth (asm.bits=32)",
|
|
|
|
"ad8", " [N] [D]", "analyze N data words at D depth (asm.bits=64)",
|
|
|
|
"adf", "", "analyze data in function (use like .adf @@=`afl~[0]`",
|
|
|
|
"adfg", "", "analyze data in function gaps",
|
|
|
|
"adt", "", "analyze data trampolines (wip)",
|
|
|
|
"adk", "", "analyze data kind (code, text, data, invalid, ...)",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_ae[] = {
|
|
|
|
"Usage:", "ae[idesr?] [arg]", "ESIL code emulation",
|
|
|
|
"ae", " [expr]", "evaluate ESIL expression",
|
|
|
|
"ae?", "", "show this help",
|
|
|
|
"ae??", "", "show ESIL help",
|
|
|
|
"ae[aA]", "[f] [count]", "analyse esil accesses (regs, mem..)",
|
|
|
|
"aec", "[?]", "continue until ^C",
|
|
|
|
"aecs", " [sn]", "continue until syscall number",
|
|
|
|
"aecu", " [addr]", "continue until address",
|
|
|
|
"aecue", " [esil]", "continue until esil expression match",
|
|
|
|
"aef", " [addr]", "emulate function",
|
|
|
|
"aei", "", "initialize ESIL VM state (aei- to deinitialize)",
|
|
|
|
"aeim", " [addr] [size] [name]", "initialize ESIL VM stack (aeim- remove)",
|
|
|
|
"aeip", "", "initialize ESIL program counter to curseek",
|
|
|
|
"aek", " [query]", "perform sdb query on ESIL.info",
|
|
|
|
"aek-", "", "resets the ESIL.info sdb instance",
|
|
|
|
"aep", "[?] [addr]", "manage esil pin hooks",
|
|
|
|
"aepc", " [addr]", "change esil PC to this address",
|
|
|
|
"aer", " [..]", "handle ESIL registers like 'ar' or 'dr' does",
|
2017-07-29 10:59:41 +00:00
|
|
|
"aets", "[?]", "ESIL Trace session",
|
2017-07-24 15:41:50 +00:00
|
|
|
"aes", "", "perform emulated debugger step",
|
2017-12-01 12:46:01 +00:00
|
|
|
"aesp", " [X] [N]", "evaluate N instr from offset X",
|
2017-07-29 10:59:41 +00:00
|
|
|
"aesb", "", "step back",
|
2017-07-24 15:41:50 +00:00
|
|
|
"aeso", " ", "step over",
|
|
|
|
"aesu", " [addr]", "step until given address",
|
|
|
|
"aesue", " [esil]", "step until esil expression match",
|
|
|
|
"aetr", "[esil]", "Convert an ESIL Expression to REIL",
|
|
|
|
"aex", " [hex]", "evaluate opcode expression",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-25 07:11:29 +00:00
|
|
|
static const char *help_detail_ae[] = {
|
2017-07-24 15:41:50 +00:00
|
|
|
"Examples:", "ESIL", " examples and documentation",
|
2018-05-07 18:02:22 +00:00
|
|
|
"+=", "", "A+=B => B,A,+=",
|
2017-07-24 15:41:50 +00:00
|
|
|
"+", "", "A=A+B => B,A,+,A,=",
|
|
|
|
"++", "", "increment, 2,A,++ == 3 (see rsi,--=[1], ... )",
|
|
|
|
"--", "", "decrement, 2,A,-- == 1",
|
2018-05-07 18:02:22 +00:00
|
|
|
"*=", "", "A*=B => B,A,*=",
|
|
|
|
"/=", "", "A/=B => B,A,/=",
|
|
|
|
"%=", "", "A%=B => B,A,%=",
|
|
|
|
"&=", "", "and ax, bx => bx,ax,&=",
|
2017-07-24 15:41:50 +00:00
|
|
|
"|", "", "or r0, r1, r2 => r2,r1,|,r0,=",
|
2018-05-07 18:02:22 +00:00
|
|
|
"!=", "", "negate all bits",
|
|
|
|
"^=", "", "xor ax, bx => bx,ax,^=",
|
2017-07-24 15:41:50 +00:00
|
|
|
"", "[]", "mov eax,[eax] => eax,[],eax,=",
|
|
|
|
"=", "[]", "mov [eax+3], 1 => 1,3,eax,+,=[]",
|
|
|
|
"=", "[1]", "mov byte[eax],1 => 1,eax,=[1]",
|
|
|
|
"=", "[8]", "mov [rax],1 => 1,rax,=[8]",
|
|
|
|
"[]", "", "peek from random position",
|
|
|
|
"[*]", "", "peek some from random position",
|
|
|
|
"=", "[*]", "poke some at random position",
|
|
|
|
"$", "", "int 0x80 => 0x80,$",
|
|
|
|
"$$", "", "simulate a hardware trap",
|
|
|
|
"==", "", "pops twice, compare and update esil flags",
|
|
|
|
"<", "", "compare for smaller",
|
2018-05-07 18:02:22 +00:00
|
|
|
"<=", "", "compare for smaller or equal",
|
2017-07-24 15:41:50 +00:00
|
|
|
">", "", "compare for bigger",
|
2018-05-07 18:02:22 +00:00
|
|
|
">=", "", "compare bigger for or equal",
|
|
|
|
">>=", "", "shr ax, bx => bx,ax,>>= # shift right",
|
|
|
|
"<<=", "", "shl ax, bx => bx,ax,<<= # shift left",
|
|
|
|
">>>=", "", "ror ax, bx => bx,ax,>>>= # rotate right",
|
|
|
|
"<<<=", "", "rol ax, bx => bx,ax,<<<= # rotate left",
|
2017-07-24 15:41:50 +00:00
|
|
|
"?{", "", "if popped value != 0 run the block until }",
|
|
|
|
"POP", "", "drops last element in the esil stack",
|
|
|
|
"DUP", "", "duplicate last value in stack",
|
|
|
|
"NUM", "", "evaluate last item in stack to number",
|
|
|
|
"PICK", "", "pick Nth element in stack",
|
|
|
|
"RPICK", "", "pick Nth element in reversed stack",
|
|
|
|
"SWAP", "", "swap last two values in stack",
|
|
|
|
"TRAP", "", "stop execution",
|
|
|
|
"BITS", "", "16,BITS # change bits, useful for arm/thumb",
|
|
|
|
"TODO", "", "the instruction is not yet esilized",
|
|
|
|
"STACK", "", "show contents of stack",
|
|
|
|
"CLEAR", "", "clears the esil stack",
|
|
|
|
"REPEAT", "", "repeat n times",
|
|
|
|
"BREAK", "", "terminates the string parsing",
|
|
|
|
"GOTO", "", "jump to the Nth word popped from the stack",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_aea[] = {
|
|
|
|
"Examples:", "aea", " show regs used in a range",
|
2018-02-18 02:31:59 +00:00
|
|
|
"aea", " [ops]", "Show regs used in N instructions (all,read,{no,}written,memreads,memwrites)",
|
2017-07-24 15:41:50 +00:00
|
|
|
"aea*", " [ops]", "Create mem.* flags for memory accesses",
|
|
|
|
"aeaf", "", "Show regs used in current function",
|
|
|
|
"aear", " [ops]", "Show regs read in N instructions",
|
|
|
|
"aeaw", " [ops]", "Show regs written in N instructions",
|
|
|
|
"aean", " [ops]", "Show regs not written in N instructions",
|
|
|
|
"aeaj", " [ops]", "Show aea output in JSON format",
|
|
|
|
"aeA", " [len]", "Show regs used in N bytes (subcommands are the same)",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_aec[] = {
|
|
|
|
"Examples:", "aec", " continue until ^c",
|
|
|
|
"aec", "", "Continue until exception",
|
|
|
|
"aecs", "", "Continue until syscall",
|
|
|
|
"aecu", "[addr]", "Continue until address",
|
|
|
|
"aecue", "[addr]", "Continue until esil expression",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_aep[] = {
|
|
|
|
"Usage:", "aep[-c] ", " [...]",
|
|
|
|
"aepc", " [addr]", "change program counter for esil",
|
|
|
|
"aep", "-[addr]", "remove pin",
|
|
|
|
"aep", " [name] @ [addr]", "set pin",
|
|
|
|
"aep", "", "list pins",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-29 10:59:41 +00:00
|
|
|
static const char *help_msg_aets[] = {
|
|
|
|
"Usage:", "aets ", " [...]",
|
|
|
|
"aets", "", "List all ESIL trace sessions",
|
|
|
|
"aets+", "", "Add ESIL trace session",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-24 15:41:50 +00:00
|
|
|
static const char *help_msg_af[] = {
|
|
|
|
"Usage:", "af", "",
|
|
|
|
"af", " ([name]) ([addr])", "analyze functions (start at addr or $$)",
|
|
|
|
"afr", " ([name]) ([addr])", "analyze functions recursively",
|
|
|
|
"af+", " addr name [type] [diff]", "hand craft a function (requires afb+)",
|
|
|
|
"af-", " [addr]", "clean all function analysis data (or function at addr)",
|
|
|
|
"afb+", " fcnA bbA sz [j] [f] ([t]( [d]))", "add bb to function @ fcnaddr",
|
|
|
|
"afb", "[?] [addr]", "List basic blocks of given function",
|
|
|
|
"afB", " 16", "set current function as thumb (change asm.bits)",
|
2017-11-24 13:22:29 +00:00
|
|
|
"afC[lc]", " ([addr])@[addr]", "calculate the Cycles (afC) or Cyclomatic Complexity (afCc)",
|
2017-08-14 17:09:36 +00:00
|
|
|
"afc", "[?] type @[addr]", "set calling convention for function",
|
2017-12-17 19:29:43 +00:00
|
|
|
"afd", "[addr]","show function + delta for given offset",
|
2017-07-24 15:41:50 +00:00
|
|
|
"aff", "", "re-adjust function boundaries to fit",
|
|
|
|
"afF", "[1|0|]", "fold/unfold/toggle",
|
|
|
|
"afi", " [addr|fcn.name]", "show function(s) information (verbose afl)",
|
|
|
|
"afl", "[?] [l*] [fcn name]", "list functions (addr, size, bbs, name) (see afll)",
|
|
|
|
"afm", " name", "merge two functions",
|
|
|
|
"afM", " name", "print functions map",
|
|
|
|
"afn", "[?] name [addr]", "rename name for function at address (change flag too)",
|
|
|
|
"afna", "", "suggest automatic name for current offset",
|
2018-05-03 16:55:07 +00:00
|
|
|
"afo", " [fcn.name]", "show address for the function named like this",
|
2017-07-24 15:41:50 +00:00
|
|
|
"afs", " [addr] [fcnsign]", "get/set function signature at current address",
|
|
|
|
"afS", "[stack_size]", "set stack frame size for function at current address",
|
2018-05-03 16:55:07 +00:00
|
|
|
"aft", "[?]", "type matching, type propagation",
|
2017-07-24 15:41:50 +00:00
|
|
|
"afu", " [addr]", "resize and analyze function from current address until addr",
|
|
|
|
"afv[bsra]", "?", "manipulate args, registers and variables in function",
|
2018-05-08 06:41:53 +00:00
|
|
|
"afx", "", "list function references",
|
2017-08-18 13:04:48 +00:00
|
|
|
NULL
|
|
|
|
};
|
2017-07-24 15:41:50 +00:00
|
|
|
|
|
|
|
static const char *help_msg_afb[] = {
|
|
|
|
"Usage:", "afb", " List basic blocks of given function",
|
|
|
|
".afbr-", "", "Set breakpoint on every return address of the function",
|
|
|
|
".afbr-*", "", "Remove breakpoint on every return address of the function",
|
|
|
|
"afb", " [addr]", "list basic blocks of function",
|
|
|
|
"afb.", " [addr]", "show info of current basic block",
|
|
|
|
"afb+", " fcn_at bbat bbsz [jump] [fail] ([type] ([diff]))", "add basic block by hand",
|
|
|
|
"afbr", "", "Show addresses of instructions which leave the function",
|
2017-09-11 23:54:58 +00:00
|
|
|
"afbi", "", "print current basic block information",
|
2017-07-24 15:41:50 +00:00
|
|
|
"afbj", "", "show basic blocks information in json",
|
2017-09-01 08:33:28 +00:00
|
|
|
"afbe", " bbfrom bbto", "add basic-block edge for switch-cases",
|
2017-07-24 15:41:50 +00:00
|
|
|
"afB", " [bits]", "define asm.bits for the given function",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-08-18 13:04:48 +00:00
|
|
|
static const char *help_msg_afc[] = {
|
|
|
|
"Usage:", "afc[agl?]", "",
|
|
|
|
"afc", " convention", "Manually set calling convention for current function",
|
|
|
|
"afc", "", "Show Calling convention for the Current function",
|
|
|
|
"afcr", "[j]", "Show register usage for the current function",
|
|
|
|
"afca", "", "Analyse function for finding the current calling convention",
|
2018-05-11 13:27:31 +00:00
|
|
|
"afcf", " name", "Prints return type function(arg1, arg2...)",
|
2017-08-18 13:04:48 +00:00
|
|
|
"afcl", "", "List all available calling conventions",
|
|
|
|
"afco", " path", "Open Calling Convention sdb profile from given path",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_afC[] = {
|
|
|
|
"Usage:", "afC", " [addr]",
|
|
|
|
"afC", "", "function cycles cost",
|
|
|
|
"afCc", "", "cyclomatic complexity",
|
2017-11-24 13:22:29 +00:00
|
|
|
"afCl", "", "loop count (backward jumps)",
|
2017-08-18 13:04:48 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_afi[] = {
|
|
|
|
"Usage:", "afi[jl*]", " <addr>",
|
2017-11-28 10:37:49 +00:00
|
|
|
"afi", "", "show information of the function",
|
|
|
|
"afi.", "", "show function name in current offset",
|
|
|
|
"afi*", "", "function, variables and arguments",
|
2017-08-18 13:04:48 +00:00
|
|
|
"afij", "", "function info in json format",
|
|
|
|
"afil", "", "verbose function info",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-24 15:41:50 +00:00
|
|
|
static const char *help_msg_afl[] = {
|
|
|
|
"Usage:", "afl", " List all functions",
|
|
|
|
"afl", "", "list functions",
|
2017-11-23 17:57:33 +00:00
|
|
|
"aflc", "", "count of functions",
|
2017-07-24 15:41:50 +00:00
|
|
|
"aflj", "", "list functions in json",
|
|
|
|
"afll", "", "list functions in verbose mode",
|
2018-02-05 10:54:11 +00:00
|
|
|
"afllj", "", "list functions in verbose mode (alias to aflj)",
|
2017-07-24 15:41:50 +00:00
|
|
|
"aflq", "", "list functions in quiet mode",
|
|
|
|
"aflqj", "", "list functions in json quiet mode",
|
|
|
|
"afls", "", "print sum of sizes of all functions",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_afll[] = {
|
|
|
|
"Usage:", "", " List functions in verbose mode",
|
|
|
|
"", "", "",
|
|
|
|
"Table fields:", "", "",
|
|
|
|
"", "", "",
|
|
|
|
"address", "", "start address",
|
|
|
|
"size", "", "function size (realsize)",
|
|
|
|
"nbbs", "", "number of basic blocks",
|
|
|
|
"edges", "", "number of edges between basic blocks",
|
|
|
|
"cc", "", "cyclomatic complexity ( cc = edges - blocks + 2 * exit_blocks)",
|
|
|
|
"cost", "", "cyclomatic cost",
|
|
|
|
"min bound", "", "minimal address",
|
|
|
|
"range", "", "function size",
|
|
|
|
"max bound", "", "maximal address",
|
|
|
|
"calls", "", "number of caller functions",
|
|
|
|
"locals", "", "number of local variables",
|
|
|
|
"args", "", "number of function arguments",
|
|
|
|
"xref", "", "number of cross references",
|
|
|
|
"frame", "", "function stack size",
|
|
|
|
"name", "", "function name",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_afn[] = {
|
|
|
|
"Usage:", "afn[sa]", " Analyze function names",
|
|
|
|
"afn", " [name]", "rename the function",
|
|
|
|
"afna", "", "construct a function name for the current offset",
|
|
|
|
"afns", "", "list all strings associated with the current function",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_aft[] = {
|
2018-05-03 16:55:07 +00:00
|
|
|
"Usage:", "aft[a|m]", "",
|
|
|
|
"afta", "", "setup memory and analyse do type matching analysis for all functions",
|
|
|
|
"aftm", "", "type matching analysis for current function",
|
2017-07-24 15:41:50 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-25 07:11:29 +00:00
|
|
|
static const char *help_msg_afv[] = {
|
|
|
|
"Usage:", "afv","[rbs]",
|
|
|
|
"afvr", "[?]", "manipulate register based arguments",
|
|
|
|
"afvb", "[?]", "manipulate bp based arguments/locals",
|
|
|
|
"afvs", "[?]", "manipulate sp based arguments/locals",
|
|
|
|
"afvR", " [varname]", "list addresses where vars are accessed",
|
|
|
|
"afvW", " [varname]", "list addresses where vars are accessed",
|
|
|
|
"afva", "", "analyze function arguments/locals",
|
|
|
|
"afvd", " name", "output r2 command for displaying the value of args/locals in the debugger",
|
|
|
|
"afvn", " [old_name] [new_name]", "rename argument/local",
|
|
|
|
"afvt", " [name] [new_type]", "change type for given argument/local",
|
2017-08-07 16:26:48 +00:00
|
|
|
"afv-", "([name])", "remove all or given var",
|
2017-07-24 15:41:50 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_afvb[] = {
|
2017-10-04 11:01:38 +00:00
|
|
|
"Usage:", "afvb", " [idx] [name] ([type])",
|
2017-07-24 15:41:50 +00:00
|
|
|
"afvb", "", "list base pointer based arguments, locals",
|
|
|
|
"afvb*", "", "same as afvb but in r2 commands",
|
2017-10-04 11:01:38 +00:00
|
|
|
"afvb", " [idx] [name] ([type])", "define base pointer based arguments, locals",
|
2017-07-24 15:41:50 +00:00
|
|
|
"afvbj", "", "return list of base pointer based arguments, locals in JSON format",
|
|
|
|
"afvb-", " [name]", "delete argument/locals at the given name",
|
|
|
|
"afvbg", " [idx] [addr]", "define var get reference",
|
|
|
|
"afvbs", " [idx] [addr]", "define var set reference",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_afvr[] = {
|
|
|
|
"Usage:", "afvr", " [reg] [type] [name]",
|
|
|
|
"afvr", "", "list register based arguments",
|
|
|
|
"afvr*", "", "same as afvr but in r2 commands",
|
|
|
|
"afvr", " [reg] [name] ([type])", "define register arguments",
|
|
|
|
"afvrj", "", "return list of register arguments in JSON format",
|
|
|
|
"afvr-", " [name]", "delete register arguments at the given index",
|
|
|
|
"afvrg", " [reg] [addr]", "define argument get reference",
|
|
|
|
"afvrs", " [reg] [addr]", "define argument set reference",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-25 07:11:29 +00:00
|
|
|
static const char *help_msg_afvs[] = {
|
|
|
|
"Usage:", "afvs", " [idx] [type] [name]",
|
|
|
|
"afvs", "", "list stack based arguments and locals",
|
|
|
|
"afvs*", "", "same as afvs but in r2 commands",
|
|
|
|
"afvs", " [idx] [name] [type]", "define stack based arguments,locals",
|
|
|
|
"afvsj", "", "return list of stack based arguments and locals in JSON format",
|
|
|
|
"afvs-", " [name]", "delete stack based argument or locals with the given name",
|
|
|
|
"afvsg", " [idx] [addr]", "define var get reference",
|
|
|
|
"afvss", " [idx] [addr]", "define var set reference",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-24 15:41:50 +00:00
|
|
|
static const char *help_msg_ag[] = {
|
2017-08-18 13:04:48 +00:00
|
|
|
"Usage:", "ag[?f]", " Graphviz/graph code",
|
2017-07-24 15:41:50 +00:00
|
|
|
"ag", " [addr]", "output graphviz code (bb at addr and children)",
|
|
|
|
"ag-", "", "Reset the current ASCII art graph (see agn, age, agg?)",
|
|
|
|
"aga", " [addr]", "idem, but only addresses",
|
2017-08-06 01:58:38 +00:00
|
|
|
"agr", "[j] [addr]", "output graphviz call graph of function",
|
|
|
|
"agg", "", "display current graph created with agn and age (see also ag-)",
|
2017-12-29 10:19:56 +00:00
|
|
|
"agc", "[*j] [addr]", "output graphviz call graph of function",
|
2017-07-24 15:41:50 +00:00
|
|
|
"agC", "[j]", "Same as agc -1. full program callgraph",
|
|
|
|
"agd", " [fcn name]", "output graphviz code of diffed function",
|
|
|
|
"age", "[?] title1 title2", "Add an edge to the current graph",
|
|
|
|
"agf", " [addr]", "Show ASCII art graph of given function",
|
|
|
|
"agg", "[?] [kdi*]", "Print graph in ASCII-Art, graphviz, k=v, r2 or visual",
|
|
|
|
"agj", " [addr]", "idem, but in JSON format",
|
2018-02-01 14:12:27 +00:00
|
|
|
"agJ", " [addr]", "idem, but in JSON format with formatted disassembly (like pdJ)",
|
2017-07-24 15:41:50 +00:00
|
|
|
"agk", " [addr]", "idem, but in SDB key-value format",
|
|
|
|
"agl", " [fcn name]", "output graphviz code using meta-data",
|
|
|
|
"agn", "[?] title body", "Add a node to the current graph",
|
|
|
|
"ags", " [addr]", "output simple graphviz call graph of function (only bb offset)",
|
|
|
|
"agt", " [addr]", "find paths from current offset to given address",
|
|
|
|
"agv", "", "Show function graph in web/png (see graph.web and cmd.graph) or agf for asciiart",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_age[] = {
|
|
|
|
"Usage:", "age [title1] [title2]", "",
|
|
|
|
"Examples:", "", "",
|
|
|
|
"age", " title1 title2", "Add an edge from the node with \"title1\" as title to the one with title \"title2\"",
|
|
|
|
"age", " \"title1 with spaces\" title2", "Add an edge from node \"title1 with spaces\" to node \"title2\"",
|
|
|
|
"age-", " title1 title2", "Remove an edge from the node with \"title1\" as title to the one with title \"title2\"",
|
|
|
|
"age?", "", "Show this help",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_agg[] = {
|
|
|
|
"Usage:", "agg[kid?*]", "print graph",
|
|
|
|
"agg", "", "show current graph in ascii art",
|
|
|
|
"aggk", "", "show graph in key=value form",
|
|
|
|
"aggi", "", "enter interactive mode for the current graph",
|
|
|
|
"aggd", "", "print the current graph in GRAPHVIZ dot format",
|
|
|
|
"aggv", "", "run graphviz + viewer (see 'e cmd.graph')",
|
|
|
|
"agg*", "", "in r2 commands, to save in projects, etc",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_agn[] = {
|
|
|
|
"Usage:", "agn [title] [body]", "",
|
|
|
|
"Examples:", "", "",
|
|
|
|
"agn", " title1 body1", "Add a node with title \"title1\" and body \"body1\"",
|
|
|
|
"agn", " \"title with space\" \"body with space\"", "Add a node with spaces in the title and in the body",
|
|
|
|
"agn", " title1 base64:Ym9keTE=", "Add a node with the body specified as base64",
|
|
|
|
"agn-", " title1", "Remove a node with title \"title1\"",
|
|
|
|
"agn?", "", "Show this help",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_ah[] = {
|
|
|
|
"Usage:", "ah[lba-]", "Analysis Hints",
|
|
|
|
"ah?", "", "show this help",
|
|
|
|
"ah?", " offset", "show hint of given offset",
|
|
|
|
"ah", "", "list hints in human-readable format",
|
|
|
|
"ah.", "", "list hints in human-readable format from current offset",
|
|
|
|
"ah-", "", "remove all hints",
|
|
|
|
"ah-", " offset [size]", "remove hints at given offset",
|
|
|
|
"ah*", " offset", "list hints in radare commands format",
|
|
|
|
"aha", " ppc 51", "set arch for a range of N bytes",
|
|
|
|
"ahb", " 16 @ $$", "force 16bit for current instruction",
|
|
|
|
"ahc", " 0x804804", "override call/jump address",
|
|
|
|
"ahe", " 3,eax,+=", "set vm analysis string",
|
|
|
|
"ahf", " 0x804840", "override fallback address for call",
|
2017-11-14 14:36:04 +00:00
|
|
|
"ahh", " 0x804840", "highlight this adrress offset in disasm",
|
2017-07-24 15:41:50 +00:00
|
|
|
"ahi", "[?] 10", "define numeric base for immediates (1, 8, 10, 16, s)",
|
|
|
|
"ahj", "", "list hints in JSON",
|
|
|
|
"aho", " foo a0,33", "replace opcode string",
|
|
|
|
"ahp", " addr", "set pointer hint",
|
|
|
|
"ahs", " 4", "set opcode size=4",
|
|
|
|
"ahS", " jz", "set asm.syntax=jz for this opcode",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-08-18 13:04:48 +00:00
|
|
|
static const char *help_msg_ahi[] = {
|
|
|
|
"Usage", "ahi [sbodh] [@ offset]", " Define numeric base",
|
|
|
|
"ahi", " [base]", "set numeric base (1, 2, 8, 10, 16)",
|
2017-09-01 10:49:01 +00:00
|
|
|
"ahi", " b", "set base to binary (2)",
|
2017-08-18 13:04:48 +00:00
|
|
|
"ahi", " d", "set base to decimal (10)",
|
|
|
|
"ahi", " h", "set base to hexadecimal (16)",
|
|
|
|
"ahi", " o", "set base to octal (8)",
|
2017-11-09 11:57:51 +00:00
|
|
|
"ahi", " p", "set base to htons(port) (3)",
|
2017-08-18 13:04:48 +00:00
|
|
|
"ahi", " i", "set base to IP address (32)",
|
|
|
|
"ahi", " S", "set base to syscall (80)",
|
2017-09-01 10:49:01 +00:00
|
|
|
"ahi", " s", "set base to string (1)",
|
2017-08-18 13:04:48 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-24 15:41:50 +00:00
|
|
|
static const char *help_msg_ao[] = {
|
|
|
|
"Usage:", "ao[e?] [len]", "Analyze Opcodes",
|
|
|
|
"aoj", " N", "display opcode analysis information in JSON for N opcodes",
|
|
|
|
"aoe", " N", "display esil form for N opcodes",
|
|
|
|
"aor", " N", "display reil form for N opcodes",
|
2018-04-08 12:00:21 +00:00
|
|
|
"aos", " N", "display size of N opcodes",
|
2017-07-24 15:41:50 +00:00
|
|
|
"ao", " 5", "display opcode analysis of 5 opcodes",
|
|
|
|
"ao*", "", "display opcode in r commands",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_ar[] = {
|
|
|
|
"Usage: ar", "", "# Analysis Registers",
|
|
|
|
"ar", "", "Show 'gpr' registers",
|
|
|
|
"ar0", "", "Reset register arenas to 0",
|
|
|
|
"ara", "[?]", "Manage register arenas",
|
|
|
|
"ar", " 16", "Show 16 bit registers",
|
|
|
|
"ar", " 32", "Show 32 bit registers",
|
|
|
|
"ar", " all", "Show all bit registers",
|
|
|
|
"ar", " <type>", "Show all registers of given type",
|
|
|
|
"arC", "", "Display register profile comments",
|
|
|
|
"arr", "", "Show register references (telescoping)",
|
2018-03-22 16:32:57 +00:00
|
|
|
"ar=", "([size])(:[regs])", "Show register values in columns",
|
2017-07-24 15:41:50 +00:00
|
|
|
"ar?", " <reg>", "Show register value",
|
|
|
|
"arb", " <type>", "Display hexdump of the given arena",
|
|
|
|
"arc", " <name>", "Conditional flag registers",
|
|
|
|
"ard", " <name>", "Show only different registers",
|
|
|
|
"arn", " <regalias>", "Get regname for pc,sp,bp,a0-3,zf,cf,of,sg",
|
|
|
|
"aro", "", "Show old (previous) register values",
|
|
|
|
"arp", "[?] <file>", "Load register profile from file",
|
|
|
|
"ars", "", "Stack register state",
|
|
|
|
"art", "", "List all register types",
|
|
|
|
"arw", " <hexnum>", "Set contents of the register arena",
|
|
|
|
".ar*", "", "Import register values as flags",
|
|
|
|
".ar-", "", "Unflag all registers",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_ara[] = {
|
|
|
|
"Usage:", "ara[+-s]", "Register Arena Push/Pop/Swap",
|
|
|
|
"ara", "", "show all register arenas allocated",
|
|
|
|
"ara", "+", "push a new register arena for each type",
|
|
|
|
"ara", "-", "pop last register arena",
|
|
|
|
"aras", "", "swap last two register arenas",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_arw[] = {
|
|
|
|
"Usage:", "arw ", "# Set contents of the register arena",
|
|
|
|
"arw", " <hexnum>", "Set contents of the register arena",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_as[] = {
|
|
|
|
"Usage: as[ljk?]", "", "syscall name <-> number utility",
|
|
|
|
"as", "", "show current syscall and arguments",
|
|
|
|
"as", " 4", "show syscall 4 based on asm.os and current regs/mem",
|
|
|
|
"asc[a]", " 4", "dump syscall info in .asm or .h",
|
|
|
|
"asf", " [k[=[v]]]", "list/set/unset pf function signatures (see fcnsign)",
|
|
|
|
"asj", "", "list of syscalls in JSON",
|
|
|
|
"asl", "", "list of syscalls by asm.os and asm.arch",
|
|
|
|
"asl", " close", "returns the syscall number for close",
|
|
|
|
"asl", " 4", "returns the name of the syscall number 4",
|
|
|
|
"ask", " [query]", "perform syscall/ queries",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2018-03-14 12:29:44 +00:00
|
|
|
static const char *help_msg_av[] = {
|
2018-04-11 10:15:14 +00:00
|
|
|
"Usage:", "av[?jr*]", " C++ vtables and RTTI",
|
|
|
|
"av", "", "search for vtables in data sections and show results",
|
|
|
|
"avj", "", "like av, but as json",
|
|
|
|
"av*", "", "like av, but as r2 commands",
|
|
|
|
"avr", "[j@addr]", "try to parse RTTI at vtable addr (see anal.cpp.abi)",
|
|
|
|
"avra", "[j]", "search for vtables and try to parse RTTI at each of them",
|
|
|
|
NULL
|
2018-03-14 12:29:44 +00:00
|
|
|
};
|
|
|
|
|
2017-07-24 15:41:50 +00:00
|
|
|
static const char *help_msg_ax[] = {
|
|
|
|
"Usage:", "ax[?d-l*]", " # see also 'afx?'",
|
2017-12-22 14:55:45 +00:00
|
|
|
"ax", "", "list refs",
|
2018-05-08 06:41:53 +00:00
|
|
|
"ax*", "", "output radare commands",
|
2017-07-24 15:41:50 +00:00
|
|
|
"ax", " addr [at]", "add code ref pointing to addr (from curseek)",
|
2018-02-09 21:25:30 +00:00
|
|
|
"ax-", " [at]", "clean all refs/refs from addr",
|
|
|
|
"ax-*", "", "clean all refs/refs",
|
2018-05-08 06:41:53 +00:00
|
|
|
"axc", " addr [at]", "add generic code ref",
|
2017-07-24 15:41:50 +00:00
|
|
|
"axC", " addr [at]", "add code call ref",
|
2017-12-17 08:53:28 +00:00
|
|
|
"axg", " [addr]", "show xrefs graph to reach current function",
|
2018-03-01 09:50:56 +00:00
|
|
|
"axgj", " [addr]", "show xrefs graph to reach current function in json format",
|
2017-07-24 15:41:50 +00:00
|
|
|
"axd", " addr [at]", "add data ref",
|
|
|
|
"axq", "", "list refs in quiet/human-readable format",
|
|
|
|
"axj", "", "list refs in json format",
|
|
|
|
"axF", " [flg-glob]", "find data/code references of flags",
|
|
|
|
"axt", " [addr]", "find data/code references to this address",
|
|
|
|
"axf", " [addr]", "find data/code references from this address",
|
2018-05-08 06:41:53 +00:00
|
|
|
"axs", " addr [at]", "add string ref",
|
2017-07-24 15:41:50 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-27 12:52:17 +00:00
|
|
|
static void cmd_anal_init(RCore *core) {
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, a);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, aa);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, aar);
|
2018-04-04 23:45:12 +00:00
|
|
|
DEFINE_CMD_DESCRIPTOR (core, ab);
|
2017-07-27 12:52:17 +00:00
|
|
|
DEFINE_CMD_DESCRIPTOR (core, ad);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, ae);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, aea);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, aec);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, aep);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, af);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, afb);
|
2017-08-18 13:04:48 +00:00
|
|
|
DEFINE_CMD_DESCRIPTOR (core, afc);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, afC);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, afi);
|
2017-07-27 12:52:17 +00:00
|
|
|
DEFINE_CMD_DESCRIPTOR (core, afl);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, afll);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, afn);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, aft);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, afv);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, afvb);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, afvr);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, afvs);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, ag);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, age);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, agg);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, agn);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, ah);
|
2017-08-18 13:04:48 +00:00
|
|
|
DEFINE_CMD_DESCRIPTOR (core, ahi);
|
2017-07-27 12:52:17 +00:00
|
|
|
DEFINE_CMD_DESCRIPTOR (core, ao);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, ar);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, ara);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, arw);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, as);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, ax);
|
2017-07-25 07:11:29 +00:00
|
|
|
}
|
|
|
|
|
2016-08-21 09:50:33 +00:00
|
|
|
/* better aac for windows-x86-32 */
|
|
|
|
#define JAYRO_03 0
|
|
|
|
|
|
|
|
#if JAYRO_03
|
|
|
|
|
|
|
|
static bool anal_is_bad_call(RCore *core, ut64 from, ut64 to, ut64 addr, ut8 *buf, int bufi) {
|
2017-08-22 22:21:28 +00:00
|
|
|
ut64 align = R_ABS (addr % PE_ALIGN);
|
2016-08-21 09:50:33 +00:00
|
|
|
ut32 call_bytes;
|
|
|
|
|
|
|
|
// XXX this is x86 specific
|
|
|
|
if (align == 0) {
|
|
|
|
call_bytes = (ut32)((ut8*)buf)[bufi + 3] << 24;
|
|
|
|
call_bytes |= (ut32)((ut8*)buf)[bufi + 2] << 16;
|
|
|
|
call_bytes |= (ut32)((ut8*)buf)[bufi + 1] << 8;
|
|
|
|
call_bytes |= (ut32)((ut8*)buf)[bufi];
|
|
|
|
} else {
|
|
|
|
call_bytes = (ut32)((ut8*)buf)[bufi - align + 3] << 24;
|
|
|
|
call_bytes |= (ut32)((ut8*)buf)[bufi - align + 2] << 16;
|
|
|
|
call_bytes |= (ut32)((ut8*)buf)[bufi - align + 1] << 8;
|
|
|
|
call_bytes |= (ut32)((ut8*)buf)[bufi - align];
|
|
|
|
}
|
|
|
|
if (call_bytes >= from && call_bytes <= to) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
call_bytes = (ut32)((ut8*)buf)[bufi + 4] << 24;
|
|
|
|
call_bytes |= (ut32)((ut8*)buf)[bufi + 3] << 16;
|
|
|
|
call_bytes |= (ut32)((ut8*)buf)[bufi + 2] << 8;
|
|
|
|
call_bytes |= (ut32)((ut8*)buf)[bufi + 1];
|
|
|
|
call_bytes += addr + 5;
|
|
|
|
if (call_bytes >= from && call_bytes <= to) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-08-13 10:09:14 +00:00
|
|
|
static void type_cmd(RCore *core, const char *input) {
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, -1);
|
2016-08-29 18:19:05 +00:00
|
|
|
if (!fcn && *input != '?' && *input != 'a') {
|
2016-08-13 10:09:14 +00:00
|
|
|
eprintf ("cant find function here\n");
|
2016-08-15 06:50:46 +00:00
|
|
|
return;
|
2016-08-13 10:09:14 +00:00
|
|
|
}
|
2016-08-29 18:19:05 +00:00
|
|
|
RListIter *it;
|
|
|
|
ut64 seek;
|
2017-01-18 17:20:47 +00:00
|
|
|
bool io_cache = r_config_get_i (core->config, "io.cache");
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2016-08-13 10:09:14 +00:00
|
|
|
switch (*input) {
|
2016-11-10 11:32:34 +00:00
|
|
|
case 'a': // "afta"
|
2018-01-31 15:20:23 +00:00
|
|
|
if (r_config_get_i (core->config, "cfg.debug")) {
|
|
|
|
eprintf ("TOFIX: afta can't run in debugger mode.\n");
|
2018-03-06 00:33:12 +00:00
|
|
|
break;
|
2018-01-31 15:20:23 +00:00
|
|
|
}
|
2016-08-29 18:19:05 +00:00
|
|
|
seek = core->offset;
|
|
|
|
r_core_cmd0 (core, "aei");
|
|
|
|
r_core_cmd0 (core, "aeim");
|
2018-03-12 12:10:59 +00:00
|
|
|
r_reg_arena_push (core->anal->reg);
|
2016-08-29 18:19:05 +00:00
|
|
|
r_list_foreach (core->anal->fcns, it, fcn) {
|
2017-08-22 22:21:28 +00:00
|
|
|
int ret = r_core_seek (core, fcn->addr, true);
|
|
|
|
if (!ret) {
|
|
|
|
continue;
|
|
|
|
}
|
2016-08-29 18:19:05 +00:00
|
|
|
r_anal_esil_set_pc (core->anal->esil, fcn->addr);
|
2016-11-14 00:17:58 +00:00
|
|
|
r_core_anal_type_match (core, fcn);
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
2016-08-29 18:19:05 +00:00
|
|
|
}
|
|
|
|
r_core_cmd0 (core, "aeim-");
|
|
|
|
r_core_cmd0 (core, "aei-");
|
|
|
|
r_core_seek (core, seek, true);
|
2017-12-20 16:35:11 +00:00
|
|
|
r_reg_arena_pop (core->anal->reg);
|
2016-08-29 18:19:05 +00:00
|
|
|
break;
|
2016-11-10 11:32:34 +00:00
|
|
|
case 'm': // "aftm"
|
2017-01-18 17:20:47 +00:00
|
|
|
r_config_set_i (core->config, "io.cache", true);
|
2016-10-25 18:45:19 +00:00
|
|
|
seek = core->offset;
|
2016-08-16 01:26:26 +00:00
|
|
|
r_anal_esil_set_pc (core->anal->esil, fcn? fcn->addr: core->offset);
|
2016-11-14 00:17:58 +00:00
|
|
|
r_core_anal_type_match (core, fcn);
|
2016-10-25 18:45:19 +00:00
|
|
|
r_core_seek (core, seek, true);
|
2017-01-18 17:20:47 +00:00
|
|
|
r_config_set_i (core->config, "io.cache", io_cache);
|
2016-08-13 10:09:14 +00:00
|
|
|
break;
|
|
|
|
case '?':
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_aft);
|
2016-08-13 10:09:14 +00:00
|
|
|
break;
|
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_pop ();
|
2016-08-13 10:09:14 +00:00
|
|
|
}
|
2016-08-04 20:52:33 +00:00
|
|
|
|
2016-07-27 11:50:14 +00:00
|
|
|
static int cc_print(void *p, const char *k, const char *v) {
|
|
|
|
if (!strcmp (v, "cc")) {
|
|
|
|
r_cons_println (k);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
2016-08-04 20:52:33 +00:00
|
|
|
|
2014-04-21 11:50:38 +00:00
|
|
|
static void find_refs(RCore *core, const char *glob) {
|
|
|
|
char cmd[128];
|
|
|
|
ut64 curseek = core->offset;
|
2015-12-16 13:35:56 +00:00
|
|
|
while (*glob == ' ') glob++;
|
2016-08-04 20:52:33 +00:00
|
|
|
if (!*glob) {
|
2014-04-21 11:50:38 +00:00
|
|
|
glob = "str.";
|
2016-08-04 20:52:33 +00:00
|
|
|
}
|
2014-04-21 11:50:38 +00:00
|
|
|
if (*glob == '?') {
|
|
|
|
eprintf ("Usage: arf [flag-str-filter]\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
eprintf ("Finding references of flags matching '%s'...\n", glob);
|
2015-12-16 13:35:56 +00:00
|
|
|
snprintf (cmd, sizeof (cmd) - 1, ".(findstref) @@= `f~%s[0]`", glob);
|
2014-04-21 11:50:38 +00:00
|
|
|
r_core_cmd0 (core, "(findstref,f here=$$,s entry0,/r here,f-here)");
|
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
r_core_cmd0 (core, "(-findstref)");
|
|
|
|
r_core_seek (core, curseek, 1);
|
|
|
|
}
|
|
|
|
|
2015-07-27 21:56:11 +00:00
|
|
|
/* set flags for every function */
|
|
|
|
static void flag_every_function(RCore *core) {
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalFunction *fcn;
|
|
|
|
r_flag_space_push (core->flags, "functions");
|
|
|
|
r_list_foreach (core->anal->fcns, iter, fcn) {
|
|
|
|
r_flag_set (core->flags, fcn->name,
|
2016-05-15 12:37:22 +00:00
|
|
|
fcn->addr, r_anal_fcn_size (fcn));
|
2015-07-27 21:56:11 +00:00
|
|
|
}
|
|
|
|
r_flag_space_pop (core->flags);
|
|
|
|
}
|
|
|
|
|
2014-09-02 00:48:41 +00:00
|
|
|
static void var_help(RCore *core, char ch) {
|
2016-06-05 22:33:42 +00:00
|
|
|
switch (ch) {
|
2016-07-01 14:15:29 +00:00
|
|
|
case 'b':
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_afvb);
|
2016-06-05 22:33:42 +00:00
|
|
|
break;
|
2016-07-01 14:15:29 +00:00
|
|
|
case 's':
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_afvs);
|
2016-06-05 22:33:42 +00:00
|
|
|
break;
|
2016-07-01 14:15:29 +00:00
|
|
|
case 'r':
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_afvr);
|
2016-06-05 22:33:42 +00:00
|
|
|
break;
|
2016-07-06 22:14:06 +00:00
|
|
|
case '?':
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_afv);
|
2016-07-06 22:14:06 +00:00
|
|
|
break;
|
2016-06-05 22:33:42 +00:00
|
|
|
default:
|
2016-07-06 22:14:06 +00:00
|
|
|
eprintf ("See afv?, afvb?, afvr? and afvs?\n");
|
2014-06-16 03:58:00 +00:00
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 23:06:44 +00:00
|
|
|
static void var_accesses_list(RAnal *a, RAnalFunction *fcn, int delta, const char *typestr) {
|
2018-04-10 21:52:47 +00:00
|
|
|
const char *var_local = sdb_fmt ("var.0x%"PFMT64x".%d.%d.%s",
|
2017-01-24 23:06:44 +00:00
|
|
|
fcn->addr, 1, delta, typestr);
|
|
|
|
const char *xss = sdb_const_get (a->sdb_fcns, var_local, 0);
|
|
|
|
if (xss && *xss) {
|
|
|
|
r_cons_printf ("%s\n", xss);
|
|
|
|
} else {
|
|
|
|
r_cons_newline ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void list_vars(RCore *core, RAnalFunction *fcn, int type, const char *name) {
|
|
|
|
RAnalVar *var;
|
|
|
|
RListIter *iter;
|
|
|
|
RList *list = r_anal_var_list (core->anal, fcn, 0);
|
2017-01-25 00:07:48 +00:00
|
|
|
if (type == '*') {
|
|
|
|
const char *bp = r_reg_get_name (core->anal->reg, R_REG_NAME_BP);
|
|
|
|
r_cons_printf ("f-fcnvar*\n");
|
|
|
|
r_list_foreach (list, iter, var) {
|
|
|
|
r_cons_printf ("f fcnvar.%s @ %s%s%d\n", var->name, bp,
|
|
|
|
var->delta>=0? "+":"", var->delta);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2017-01-24 23:06:44 +00:00
|
|
|
if (type != 'W' && type != 'R') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const char *typestr = type == 'R'?"reads":"writes";
|
|
|
|
r_list_foreach (list, iter, var) {
|
|
|
|
r_cons_printf ("%10s ", var->name);
|
|
|
|
var_accesses_list (core->anal, fcn, var->delta, typestr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-30 15:14:38 +00:00
|
|
|
static int cmd_an(RCore *core, bool use_json, const char *name)
|
2017-11-26 19:10:49 +00:00
|
|
|
{
|
|
|
|
ut64 off = core->offset;
|
|
|
|
RAnalOp op;
|
|
|
|
char *q = NULL;
|
|
|
|
ut64 tgt_addr = UT64_MAX;
|
2017-11-30 15:14:38 +00:00
|
|
|
|
|
|
|
if (use_json) {
|
|
|
|
r_cons_print ("[");
|
|
|
|
}
|
|
|
|
|
2017-11-26 19:10:49 +00:00
|
|
|
r_anal_op (core->anal, &op, off,
|
2018-03-15 11:31:01 +00:00
|
|
|
core->block + off - core->offset, 32, R_ANAL_OP_MASK_ALL);
|
2017-11-26 19:10:49 +00:00
|
|
|
|
|
|
|
tgt_addr = op.jump != UT64_MAX ? op.jump : op.ptr;
|
|
|
|
if (op.var) {
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off, 0);
|
|
|
|
if (fcn) {
|
|
|
|
RAnalVar *bar = r_anal_var_get_byname (core->anal, fcn, op.var->name);
|
|
|
|
if (!bar) {
|
|
|
|
bar = r_anal_var_get_byname (core->anal, fcn, op.var->name);
|
|
|
|
if (!bar) {
|
|
|
|
bar = r_anal_var_get_byname (core->anal, fcn, op.var->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bar) {
|
2017-11-30 13:21:24 +00:00
|
|
|
if (name) {
|
|
|
|
r_anal_var_rename (core->anal, fcn->addr, bar->scope,
|
|
|
|
bar->kind, bar->name, name);
|
2017-11-30 15:14:38 +00:00
|
|
|
} else if (!use_json) {
|
2017-11-30 13:21:24 +00:00
|
|
|
r_cons_println (bar->name);
|
2017-11-30 15:14:38 +00:00
|
|
|
} else {
|
|
|
|
r_cons_printf ("{\"type\":\"var\",\"name\":\"%s\"}",
|
|
|
|
bar->name);
|
2017-11-30 13:21:24 +00:00
|
|
|
}
|
2017-11-26 19:10:49 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Cannot find variable\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
eprintf ("Cannot find function\n");
|
|
|
|
}
|
|
|
|
} else if (tgt_addr != UT64_MAX) {
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, tgt_addr, R_ANAL_FCN_TYPE_NULL);
|
|
|
|
RFlagItem *f = r_flag_get_i (core->flags, tgt_addr);
|
|
|
|
if (fcn) {
|
2017-11-30 13:21:24 +00:00
|
|
|
if (name) {
|
|
|
|
q = r_str_newf ("afn %s 0x%"PFMT64x, name, tgt_addr);
|
2017-11-30 15:14:38 +00:00
|
|
|
} else if (!use_json) {
|
2017-11-30 13:21:24 +00:00
|
|
|
r_cons_println (fcn->name);
|
2017-11-30 15:14:38 +00:00
|
|
|
} else {
|
|
|
|
r_cons_printf ("{\"type\":\"function\",\"name\":\"%s\"}",
|
|
|
|
fcn->name);
|
2017-11-30 13:21:24 +00:00
|
|
|
}
|
2017-11-26 19:10:49 +00:00
|
|
|
} else if (f) {
|
2017-11-30 13:21:24 +00:00
|
|
|
if (name) {
|
|
|
|
q = r_str_newf ("fr %s %s", f->name, name);
|
2017-11-30 15:14:38 +00:00
|
|
|
} else if (!use_json) {
|
2017-11-30 13:21:24 +00:00
|
|
|
r_cons_println (f->name);
|
2017-11-30 15:14:38 +00:00
|
|
|
} else {
|
|
|
|
r_cons_printf ("{\"type\":\"flag\",\"name\":\"%s\"}",
|
|
|
|
f->name);
|
2017-11-30 13:21:24 +00:00
|
|
|
}
|
2017-11-26 19:10:49 +00:00
|
|
|
} else {
|
2017-11-30 15:14:38 +00:00
|
|
|
if (name) {
|
|
|
|
q = r_str_newf ("f %s @ 0x%"PFMT64x, name, tgt_addr);
|
|
|
|
} else if (!use_json) {
|
|
|
|
r_cons_printf ("0x%" PFMT64x "\n", tgt_addr);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("{\"type\":\"address\",\"offset\":"
|
2017-11-30 21:12:57 +00:00
|
|
|
"%" PFMT64d "}", tgt_addr);
|
2017-11-30 15:14:38 +00:00
|
|
|
}
|
2017-11-26 19:10:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-30 15:14:38 +00:00
|
|
|
if (use_json) {
|
|
|
|
r_cons_print ("]\n");
|
|
|
|
}
|
|
|
|
|
2017-11-26 19:10:49 +00:00
|
|
|
if (q) {
|
|
|
|
r_core_cmd0 (core, q);
|
|
|
|
free (q);
|
|
|
|
}
|
|
|
|
r_anal_op_fini (&op);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-01-24 23:06:44 +00:00
|
|
|
static int var_cmd(RCore *core, const char *str) {
|
2014-09-22 15:23:17 +00:00
|
|
|
char *p, *ostr;
|
2015-11-19 20:26:54 +00:00
|
|
|
int delta, type = *str, res = true;
|
2016-09-13 22:11:20 +00:00
|
|
|
RAnalVar *v1;
|
2015-12-28 00:47:16 +00:00
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, -1);
|
2016-11-24 00:56:49 +00:00
|
|
|
ostr = p = NULL;
|
2017-01-13 22:15:07 +00:00
|
|
|
if (!str[0]) {
|
2017-01-17 14:52:43 +00:00
|
|
|
// "afv"
|
2017-01-13 22:15:07 +00:00
|
|
|
if (fcn) {
|
|
|
|
r_core_cmd0 (core, "afvs");
|
|
|
|
r_core_cmd0 (core, "afvb");
|
|
|
|
r_core_cmd0 (core, "afvr");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
eprintf ("Cannot find function\n");
|
|
|
|
return false;
|
|
|
|
}
|
2017-01-17 14:52:43 +00:00
|
|
|
if (str[0] == 'j') {
|
|
|
|
// "afvj"
|
|
|
|
if (fcn) {
|
2017-08-07 16:26:48 +00:00
|
|
|
r_cons_printf ("{\"sp\":");
|
2017-01-17 14:52:43 +00:00
|
|
|
r_core_cmd0 (core, "afvsj");
|
2017-08-07 16:26:48 +00:00
|
|
|
r_cons_printf (",\"bp\":");
|
2017-01-17 14:52:43 +00:00
|
|
|
r_core_cmd0 (core, "afvbj");
|
2017-08-07 16:26:48 +00:00
|
|
|
r_cons_printf (",\"reg\":");
|
2017-01-17 14:52:43 +00:00
|
|
|
r_core_cmd0 (core, "afvrj");
|
2017-08-07 16:26:48 +00:00
|
|
|
r_cons_printf ("}\n");
|
2017-01-17 14:52:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
eprintf ("Cannot find function\n");
|
|
|
|
return false;
|
|
|
|
}
|
2016-07-01 14:15:29 +00:00
|
|
|
if (!str[0] || str[1] == '?'|| str[0] == '?') {
|
|
|
|
var_help (core, *str);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
if (!fcn) {
|
2017-08-09 21:38:42 +00:00
|
|
|
eprintf ("Cannot find function in 0x%08"PFMT64x"\n", core->offset);
|
2016-07-01 14:15:29 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-11-09 01:28:14 +00:00
|
|
|
ostr = p = strdup (str);
|
2016-07-01 14:15:29 +00:00
|
|
|
/* Variable access CFvs = set fun var */
|
2016-08-08 22:17:42 +00:00
|
|
|
switch (str[0]) {
|
2017-08-07 16:21:17 +00:00
|
|
|
case '-':
|
|
|
|
// "afv"
|
|
|
|
if (fcn) {
|
|
|
|
r_core_cmdf (core, "afvs-%s", str + 1);
|
|
|
|
r_core_cmdf (core, "afvb-%s", str + 1);
|
|
|
|
r_core_cmdf (core, "afvr-%s", str + 1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
eprintf ("Cannot find function\n");
|
|
|
|
return false;
|
2017-01-24 23:06:44 +00:00
|
|
|
case 'R': // "afvR"
|
|
|
|
case 'W': // "afvW"
|
2017-01-25 00:07:48 +00:00
|
|
|
case '*': // "afv*"
|
2017-01-24 23:06:44 +00:00
|
|
|
list_vars (core, fcn, str[0], str + 1);
|
|
|
|
break;
|
2016-09-03 12:22:31 +00:00
|
|
|
case 'a': // "afva"
|
|
|
|
r_anal_var_delete_all (core->anal, fcn->addr, R_ANAL_VAR_KIND_REG);
|
|
|
|
r_anal_var_delete_all (core->anal, fcn->addr, R_ANAL_VAR_KIND_BPV);
|
|
|
|
r_anal_var_delete_all (core->anal, fcn->addr, R_ANAL_VAR_KIND_SPV);
|
|
|
|
fcn_callconv (core, fcn);
|
2016-11-09 01:28:14 +00:00
|
|
|
free (p);
|
2016-08-08 22:17:42 +00:00
|
|
|
return true;
|
2017-08-09 20:55:44 +00:00
|
|
|
case 'n':
|
2017-08-07 16:32:20 +00:00
|
|
|
if (str[1]) { // "afvn"
|
|
|
|
char *old_name = r_str_trim_head (strchr (ostr, ' '));
|
|
|
|
if (!old_name) {
|
|
|
|
free (ostr);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
char *new_name = strchr (old_name, ' ');
|
|
|
|
if (!new_name) {
|
|
|
|
free (ostr);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
*new_name++ = 0;
|
2018-01-08 02:22:26 +00:00
|
|
|
r_str_trim (new_name);
|
2017-08-07 16:32:20 +00:00
|
|
|
v1 = r_anal_var_get_byname (core->anal, fcn, old_name);
|
|
|
|
if (v1) {
|
|
|
|
r_anal_var_rename (core->anal, fcn->addr, R_ANAL_VAR_SCOPE_LOCAL,
|
|
|
|
v1->kind, old_name, new_name);
|
|
|
|
r_anal_var_free (v1);
|
|
|
|
} else {
|
|
|
|
eprintf ("Cant find var by name\n");
|
|
|
|
}
|
2016-09-13 22:11:20 +00:00
|
|
|
free (ostr);
|
2017-08-07 16:16:23 +00:00
|
|
|
} else {
|
2017-08-07 16:32:20 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RAnalVar *v;
|
|
|
|
RList *list = r_anal_var_list (core->anal, fcn, 0);
|
|
|
|
r_list_foreach (list, iter, v) {
|
|
|
|
r_cons_printf ("%s\n", v->name);
|
|
|
|
}
|
2017-01-24 23:06:44 +00:00
|
|
|
}
|
2016-08-16 15:35:33 +00:00
|
|
|
return true;
|
2017-08-09 20:55:15 +00:00
|
|
|
case 'd': // "afvd"
|
|
|
|
if (str[1]) {
|
2018-01-08 02:22:26 +00:00
|
|
|
p = r_str_trim (strchr (ostr, ' '));
|
2017-08-09 20:55:15 +00:00
|
|
|
if (!p) {
|
|
|
|
free (ostr);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
v1 = r_anal_var_get_byname (core->anal, fcn, p);
|
|
|
|
if (!v1) {
|
|
|
|
free (ostr);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
r_anal_var_display (core->anal, v1->delta, v1->kind, v1->type);
|
|
|
|
r_anal_var_free (v1);
|
2016-09-13 22:11:20 +00:00
|
|
|
free (ostr);
|
2017-08-09 20:55:15 +00:00
|
|
|
} else {
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalVar *p;
|
|
|
|
RList *list = r_anal_var_list (core->anal, fcn, 0);
|
|
|
|
r_list_foreach (list, iter, p) {
|
|
|
|
char *a = r_core_cmd_strf (core, ".afvd %s", p->name);
|
|
|
|
if ((a && !*a) || !a) {
|
|
|
|
free (a);
|
|
|
|
a = strdup ("\n");
|
|
|
|
}
|
|
|
|
r_cons_printf ("var %s = %s", p->name, a);
|
|
|
|
free (a);
|
|
|
|
}
|
|
|
|
r_list_free (list);
|
|
|
|
// args
|
|
|
|
list = r_anal_var_list (core->anal, fcn, 1);
|
|
|
|
r_list_foreach (list, iter, p) {
|
|
|
|
char *a = r_core_cmd_strf (core, ".afvd %s", p->name);
|
|
|
|
if ((a && !*a) || !a) {
|
|
|
|
free (a);
|
|
|
|
a = strdup ("\n");
|
|
|
|
}
|
|
|
|
r_cons_printf ("arg %s = %s", p->name, a);
|
|
|
|
free (a);
|
|
|
|
}
|
|
|
|
r_list_free (list);
|
2016-09-13 22:11:20 +00:00
|
|
|
}
|
|
|
|
return true;
|
2017-08-09 20:55:15 +00:00
|
|
|
case 't':{ // "afvt"
|
2016-09-13 22:11:20 +00:00
|
|
|
p = strchr (ostr, ' ');
|
|
|
|
if (!p++) {
|
|
|
|
free (ostr);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *type = strchr (p, ' ');
|
|
|
|
if (!type) {
|
|
|
|
free (ostr);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
*type++ = 0;
|
|
|
|
v1 = r_anal_var_get_byname (core->anal, fcn, p);
|
|
|
|
if (!v1) {
|
2017-08-07 16:16:23 +00:00
|
|
|
eprintf ("Cant find get by name %s\n", p);
|
2016-09-13 22:11:20 +00:00
|
|
|
free (ostr);
|
|
|
|
return false;
|
|
|
|
}
|
2017-08-07 16:16:23 +00:00
|
|
|
r_anal_var_retype (core->anal, fcn->addr,
|
|
|
|
R_ANAL_VAR_SCOPE_LOCAL, -1, v1->kind, type, -1, p);
|
2016-09-13 22:11:20 +00:00
|
|
|
r_anal_var_free (v1);
|
|
|
|
free (ostr);
|
|
|
|
return true;
|
|
|
|
|
2016-08-16 15:35:33 +00:00
|
|
|
}
|
2016-07-06 22:14:06 +00:00
|
|
|
}
|
2016-07-01 14:15:29 +00:00
|
|
|
switch (str[1]) {
|
|
|
|
case '\0':
|
|
|
|
case '*':
|
|
|
|
case 'j':
|
|
|
|
r_anal_var_list_show (core->anal, fcn, type, str[1]);
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
2016-07-01 14:15:29 +00:00
|
|
|
case '.':
|
|
|
|
r_anal_var_list_show (core->anal, fcn, core->offset, 0);
|
|
|
|
break;
|
|
|
|
case '-': // "afv[bsr]-"
|
|
|
|
if (str[2] == '*') {
|
|
|
|
r_anal_var_delete_all (core->anal, fcn->addr, type);
|
|
|
|
} else {
|
2017-02-05 21:50:54 +00:00
|
|
|
if (IS_DIGIT (str[2])) {
|
2016-07-01 14:15:29 +00:00
|
|
|
r_anal_var_delete (core->anal, fcn->addr,
|
|
|
|
type, 1, (int)r_num_math (core->num, str + 1));
|
|
|
|
} else {
|
2018-01-08 02:22:26 +00:00
|
|
|
char *name = r_str_trim ( strdup (str + 2));
|
2016-07-01 14:15:29 +00:00
|
|
|
r_anal_var_delete_byname (core->anal, fcn, type, name);
|
|
|
|
free (name);
|
|
|
|
}
|
2015-11-22 20:45:25 +00:00
|
|
|
}
|
2016-07-01 14:15:29 +00:00
|
|
|
break;
|
2016-09-13 22:11:20 +00:00
|
|
|
case 'd':
|
|
|
|
eprintf ("This command is deprecated, use afvd instead\n");
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
eprintf ("This command is deprecated use afvt instead\n");
|
|
|
|
break;
|
2016-07-01 14:15:29 +00:00
|
|
|
case 's':
|
|
|
|
case 'g':
|
|
|
|
if (str[2] != '\0') {
|
|
|
|
int rw = 0; // 0 = read, 1 = write
|
|
|
|
RAnalVar *var = r_anal_var_get (core->anal, fcn->addr,
|
|
|
|
(char)type, atoi (str + 2), R_ANAL_VAR_SCOPE_LOCAL);
|
|
|
|
if (!var) {
|
|
|
|
eprintf ("Cannot find variable in: '%s'\n", str);
|
|
|
|
res = false;
|
2016-06-08 16:13:36 +00:00
|
|
|
break;
|
|
|
|
}
|
2016-07-01 14:15:29 +00:00
|
|
|
if (var != NULL) {
|
|
|
|
int scope = (str[1] == 'g')? 0: 1;
|
|
|
|
r_anal_var_access (core->anal, fcn->addr, (char)type,
|
|
|
|
scope, atoi (str + 2), rw, core->offset);
|
|
|
|
r_anal_var_free (var);
|
2015-12-14 00:49:53 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-01-24 23:06:44 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Missing argument\n");
|
|
|
|
}
|
2016-07-01 14:15:29 +00:00
|
|
|
break;
|
|
|
|
case ' ': {
|
|
|
|
const char *name;
|
|
|
|
char *vartype;
|
|
|
|
int size = 4;
|
|
|
|
int scope = 1;
|
2015-12-16 13:35:56 +00:00
|
|
|
for (str++; *str == ' ';) str++;
|
2016-07-01 14:15:29 +00:00
|
|
|
p = strchr (str, ' ');
|
|
|
|
if (!p) {
|
|
|
|
var_help (core, type);
|
2014-09-22 02:22:47 +00:00
|
|
|
break;
|
2015-11-19 20:26:54 +00:00
|
|
|
}
|
2016-07-01 14:15:29 +00:00
|
|
|
*p++ = 0;
|
|
|
|
if (type == 'r') { //registers
|
|
|
|
RRegItem *i = r_reg_get (core->anal->reg, str, -1);
|
|
|
|
if (!i) {
|
|
|
|
eprintf ("Register not found");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
delta = i->index;
|
|
|
|
} else {
|
|
|
|
delta = r_num_math (core->num, str);
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
2016-07-01 14:15:29 +00:00
|
|
|
name = p;
|
|
|
|
vartype = strchr (name, ' ');
|
|
|
|
if (vartype) {
|
|
|
|
*vartype++ = 0;
|
|
|
|
r_anal_var_add (core->anal, fcn->addr,
|
|
|
|
scope, delta, type,
|
|
|
|
vartype, size, name);
|
2017-01-13 22:08:37 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Missing name\n");
|
|
|
|
}
|
|
|
|
}
|
2015-11-19 20:26:54 +00:00
|
|
|
break;
|
2016-07-01 14:15:29 +00:00
|
|
|
};
|
2015-11-19 20:26:54 +00:00
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
free (ostr);
|
2015-11-19 20:26:54 +00:00
|
|
|
return res;
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
|
2014-12-05 17:56:33 +00:00
|
|
|
static void print_trampolines(RCore *core, ut64 a, ut64 b, size_t element_size) {
|
|
|
|
int i;
|
2015-12-16 13:35:56 +00:00
|
|
|
for (i = 0; i < core->blocksize; i += element_size) {
|
2014-12-05 17:56:33 +00:00
|
|
|
ut32 n;
|
2015-12-16 13:35:56 +00:00
|
|
|
memcpy (&n, core->block + i, sizeof (ut32));
|
|
|
|
if (n >= a && n <= b) {
|
2017-01-13 22:08:37 +00:00
|
|
|
if (element_size == 4) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("f trampoline.%x @ 0x%" PFMT64x "\n", n, core->offset + i);
|
2017-01-13 22:08:37 +00:00
|
|
|
} else {
|
|
|
|
r_cons_printf ("f trampoline.%" PFMT64x " @ 0x%" PFMT64x "\n", n, core->offset + i);
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("Cd %u @ 0x%" PFMT64x ":%u\n", element_size, core->offset + i, element_size);
|
2014-12-05 17:56:33 +00:00
|
|
|
// TODO: add data xrefs
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-16 13:35:56 +00:00
|
|
|
static void cmd_anal_trampoline(RCore *core, const char *input) {
|
2014-12-05 17:56:33 +00:00
|
|
|
int bits = r_config_get_i (core->config, "asm.bits");
|
2012-11-20 02:59:00 +00:00
|
|
|
char *p, *inp = strdup (input);
|
|
|
|
p = strchr (inp, ' ');
|
2016-11-24 00:56:49 +00:00
|
|
|
if (p) {
|
|
|
|
*p = 0;
|
|
|
|
}
|
2012-11-20 02:59:00 +00:00
|
|
|
ut64 a = r_num_math (core->num, inp);
|
2015-12-16 13:35:56 +00:00
|
|
|
ut64 b = p? r_num_math (core->num, p + 1): 0;
|
2012-11-20 02:59:00 +00:00
|
|
|
free (inp);
|
2014-12-05 17:56:33 +00:00
|
|
|
|
2012-11-20 02:59:00 +00:00
|
|
|
switch (bits) {
|
2013-02-21 10:31:04 +00:00
|
|
|
case 32:
|
2015-12-16 13:35:56 +00:00
|
|
|
print_trampolines (core, a, b, 4);
|
2013-02-21 10:31:04 +00:00
|
|
|
break;
|
|
|
|
case 64:
|
2015-12-16 13:35:56 +00:00
|
|
|
print_trampolines (core, a, b, 8);
|
2013-02-21 10:31:04 +00:00
|
|
|
break;
|
2012-11-20 02:59:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-29 10:54:00 +00:00
|
|
|
R_API char *cmd_syscall_dostr(RCore *core, int n) {
|
|
|
|
char *res = NULL;
|
2012-02-27 01:40:27 +00:00
|
|
|
int i;
|
|
|
|
char str[64];
|
2015-10-29 10:54:00 +00:00
|
|
|
if (n == -1) {
|
|
|
|
n = (int)r_debug_reg_get (core->dbg, "oeax");
|
2016-12-05 17:46:45 +00:00
|
|
|
if (!n || n == -1) {
|
2016-10-28 00:27:50 +00:00
|
|
|
const char *a0 = r_reg_get_name (core->anal->reg, R_REG_NAME_SN);
|
2015-10-29 10:54:00 +00:00
|
|
|
n = (int)r_debug_reg_get (core->dbg, a0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RSyscallItem *item = r_syscall_get (core->anal->syscall, n, -1);
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!item) {
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, "%d = unknown ()", n);
|
2015-10-29 10:54:00 +00:00
|
|
|
return res;
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, "%d = %s (", item->num, item->name);
|
2012-02-27 01:40:27 +00:00
|
|
|
// TODO: move this to r_syscall
|
2017-08-11 14:24:19 +00:00
|
|
|
//TODO replace the hardcoded CC with the sdb ones
|
2015-12-16 13:35:56 +00:00
|
|
|
for (i = 0; i < item->args; i++) {
|
2017-08-11 14:24:19 +00:00
|
|
|
// XXX this is a hack to make syscall args work on x86-32 and x86-64
|
|
|
|
// we need to shift sn first.. which is bad, but needs to be redesigned
|
|
|
|
int regidx = i;
|
|
|
|
if (core->assembler->bits == 32) {
|
|
|
|
regidx++;
|
|
|
|
}
|
|
|
|
ut64 arg = r_debug_arg_get (core->dbg, R_ANAL_CC_TYPE_FASTCALL, regidx);
|
2016-04-22 17:33:23 +00:00
|
|
|
//r_cons_printf ("(%d:0x%"PFMT64x")\n", i, arg);
|
2015-10-29 10:22:49 +00:00
|
|
|
if (item->sargs) {
|
2014-06-16 03:58:00 +00:00
|
|
|
switch (item->sargs[i]) {
|
|
|
|
case 'p': // pointer
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, "0x%08" PFMT64x "", arg);
|
2014-06-16 03:58:00 +00:00
|
|
|
break;
|
|
|
|
case 'i':
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, "%" PFMT64d "", arg);
|
2014-06-16 03:58:00 +00:00
|
|
|
break;
|
|
|
|
case 'z':
|
2017-08-11 14:24:19 +00:00
|
|
|
memset (str, 0, sizeof (str));
|
|
|
|
r_io_read_at (core->io, arg, (ut8 *)str, sizeof (str) - 1);
|
2014-06-16 03:58:00 +00:00
|
|
|
r_str_filter (str, strlen (str));
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, "\"%s\"", str);
|
2014-06-16 03:58:00 +00:00
|
|
|
break;
|
2015-12-16 13:35:56 +00:00
|
|
|
case 'Z': {
|
2016-07-27 11:50:14 +00:00
|
|
|
//TODO replace the hardcoded CC with the sdb ones
|
2016-04-22 17:33:23 +00:00
|
|
|
ut64 len = r_debug_arg_get (core->dbg, R_ANAL_CC_TYPE_FASTCALL, i + 2);
|
2015-12-16 13:35:56 +00:00
|
|
|
len = R_MIN (len + 1, sizeof (str) - 1);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (len == 0) {
|
|
|
|
len = 16; // override default
|
|
|
|
}
|
2016-04-22 17:33:23 +00:00
|
|
|
(void)r_io_read_at (core->io, arg, (ut8 *)str, len);
|
2015-12-16 13:35:56 +00:00
|
|
|
str[len] = 0;
|
|
|
|
r_str_filter (str, -1);
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, "\"%s\"", str);
|
2015-12-16 13:35:56 +00:00
|
|
|
} break;
|
2014-06-16 03:58:00 +00:00
|
|
|
default:
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, "0x%08" PFMT64x "", arg);
|
2014-06-16 03:58:00 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-10-29 10:22:49 +00:00
|
|
|
} else {
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, "0x%08" PFMT64x "", arg);
|
2015-10-29 10:22:49 +00:00
|
|
|
}
|
2016-11-24 00:56:49 +00:00
|
|
|
if (i + 1 < item->args) {
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, ", ");
|
2016-11-24 00:56:49 +00:00
|
|
|
}
|
2015-10-29 10:54:00 +00:00
|
|
|
}
|
2017-10-11 22:54:14 +00:00
|
|
|
r_syscall_item_free (item);
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, ")");
|
2015-10-29 10:54:00 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cmd_syscall_do(RCore *core, int n) {
|
|
|
|
char *msg = cmd_syscall_dostr (core, n);
|
|
|
|
if (msg) {
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_println (msg);
|
2015-10-29 10:54:00 +00:00
|
|
|
free (msg);
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-16 13:35:56 +00:00
|
|
|
static void core_anal_bytes(RCore *core, const ut8 *buf, int len, int nops, int fmt) {
|
2017-03-27 01:39:13 +00:00
|
|
|
int stacksize = r_config_get_i (core->config, "esil.stack.depth");
|
2016-05-31 06:33:18 +00:00
|
|
|
bool iotrap = r_config_get_i (core->config, "esil.iotrap");
|
|
|
|
bool romem = r_config_get_i (core->config, "esil.romem");
|
|
|
|
bool stats = r_config_get_i (core->config, "esil.stats");
|
2017-12-22 12:40:11 +00:00
|
|
|
bool be = core->print->big_endian;
|
2016-05-31 06:33:18 +00:00
|
|
|
bool use_color = core->print->flags & R_PRINT_FLAGS_COLOR;
|
2017-12-22 12:19:02 +00:00
|
|
|
core->parser->relsub = r_config_get_i (core->config, "asm.relsub");
|
2013-11-26 02:25:31 +00:00
|
|
|
int ret, i, j, idx, size;
|
2016-05-31 06:33:18 +00:00
|
|
|
const char *color = "";
|
|
|
|
const char *esilstr;
|
2017-03-09 17:51:58 +00:00
|
|
|
const char *opexstr;
|
2016-05-31 06:33:18 +00:00
|
|
|
RAnalHint *hint;
|
2016-12-12 16:29:50 +00:00
|
|
|
RAnalEsil *esil = NULL;
|
2013-05-04 00:35:52 +00:00
|
|
|
RAsmOp asmop;
|
2012-02-27 01:40:27 +00:00
|
|
|
RAnalOp op;
|
2013-06-17 01:26:48 +00:00
|
|
|
ut64 addr;
|
2017-12-18 14:58:06 +00:00
|
|
|
bool isFirst = true;
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
|
2018-04-08 12:00:21 +00:00
|
|
|
int totalsize = 0;
|
2016-05-31 06:33:18 +00:00
|
|
|
|
|
|
|
// Variables required for setting up ESIL to REIL conversion
|
|
|
|
if (use_color) {
|
2014-10-16 23:15:17 +00:00
|
|
|
color = core->cons->pal.label;
|
2016-05-31 06:33:18 +00:00
|
|
|
}
|
|
|
|
switch (fmt) {
|
|
|
|
case 'j':
|
2013-12-14 03:15:01 +00:00
|
|
|
r_cons_printf ("[");
|
2016-05-31 06:33:18 +00:00
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
// Setup for ESIL to REIL conversion
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
esil = r_anal_esil_new (stacksize, iotrap, addrsize);
|
2016-05-31 06:33:18 +00:00
|
|
|
if (!esil) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
r_anal_esil_to_reil_setup (esil, core->anal, romem, stats);
|
|
|
|
r_anal_esil_set_pc (esil, core->offset);
|
|
|
|
break;
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
for (i = idx = ret = 0; idx < len && (!nops || (nops && i < nops)); i++, idx += ret) {
|
|
|
|
addr = core->offset + idx;
|
2014-06-16 03:58:00 +00:00
|
|
|
// TODO: use more anal hints
|
|
|
|
hint = r_anal_hint_get (core->anal, addr);
|
2013-06-17 01:26:48 +00:00
|
|
|
r_asm_set_pc (core->assembler, addr);
|
2015-12-16 13:35:56 +00:00
|
|
|
ret = r_asm_disassemble (core->assembler, &asmop, buf + idx, len - idx);
|
2018-03-15 11:31:01 +00:00
|
|
|
ret = r_anal_op (core->anal, &op, core->offset + idx, buf + idx, len - idx, R_ANAL_OP_MASK_ALL);
|
2016-06-06 08:16:26 +00:00
|
|
|
esilstr = R_STRBUF_SAFEGET (&op.esil);
|
2017-03-09 17:51:58 +00:00
|
|
|
opexstr = R_STRBUF_SAFEGET (&op.opex);
|
2017-03-12 23:43:44 +00:00
|
|
|
char *mnem = strdup (asmop.buf_asm);
|
|
|
|
char *sp = strchr (mnem, ' ');
|
|
|
|
if (sp) {
|
|
|
|
*sp = 0;
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
if (ret < 1 && fmt != 'd') {
|
|
|
|
eprintf ("Oops at 0x%08" PFMT64x " (", core->offset + idx);
|
|
|
|
for (i = idx, j = 0; i < core->blocksize && j < 3; ++i, ++j) {
|
2015-07-14 20:58:54 +00:00
|
|
|
eprintf ("%02x ", buf[i]);
|
2015-07-13 20:57:51 +00:00
|
|
|
}
|
|
|
|
eprintf ("...)\n");
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
size = (hint && hint->size)? hint->size: op.size;
|
|
|
|
if (fmt == 'd') {
|
2015-01-27 04:47:27 +00:00
|
|
|
char *opname = strdup (asmop.buf_asm);
|
|
|
|
r_str_split (opname, ' ');
|
|
|
|
char *d = r_asm_describe (core->assembler, opname);
|
|
|
|
if (d && *d) {
|
|
|
|
r_cons_printf ("%s: %s\n", opname, d);
|
|
|
|
free (d);
|
2016-12-12 13:47:42 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Unknown opcode\n");
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
free (opname);
|
2016-05-31 06:33:18 +00:00
|
|
|
} else if (fmt == 'e') {
|
|
|
|
if (*esilstr) {
|
|
|
|
if (use_color) {
|
|
|
|
r_cons_printf ("%s0x%" PFMT64x Color_RESET " %s\n", color, core->offset + idx, esilstr);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("0x%" PFMT64x " %s\n", core->offset + idx, esilstr);
|
|
|
|
}
|
|
|
|
}
|
2018-04-08 12:00:21 +00:00
|
|
|
} else if (fmt == 's') {
|
|
|
|
totalsize += op.size;
|
2016-05-31 06:33:18 +00:00
|
|
|
} else if (fmt == 'r') {
|
|
|
|
if (*esilstr) {
|
|
|
|
if (use_color) {
|
|
|
|
r_cons_printf ("%s0x%" PFMT64x Color_RESET "\n", color, core->offset + idx);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("0x%" PFMT64x "\n", core->offset + idx);
|
|
|
|
}
|
|
|
|
r_anal_esil_parse (esil, esilstr);
|
|
|
|
r_anal_esil_dumpstack (esil);
|
|
|
|
r_anal_esil_stack_free (esil);
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
} else if (fmt == 'j') {
|
2017-12-18 14:58:06 +00:00
|
|
|
if (isFirst) {
|
|
|
|
isFirst = false;
|
|
|
|
} else {
|
|
|
|
r_cons_print (",");
|
|
|
|
}
|
2017-03-12 23:43:44 +00:00
|
|
|
r_cons_printf ("{\"opcode\":\"%s\",", asmop.buf_asm);
|
2017-12-22 12:19:02 +00:00
|
|
|
{
|
2018-02-17 07:14:34 +00:00
|
|
|
char strsub[128] = { 0 };
|
2017-12-22 12:19:02 +00:00
|
|
|
// pc+33
|
|
|
|
r_parse_varsub (core->parser, NULL,
|
|
|
|
core->offset + idx,
|
|
|
|
asmop.size, asmop.buf_asm,
|
|
|
|
strsub, sizeof (strsub));
|
2017-12-22 12:40:11 +00:00
|
|
|
{
|
|
|
|
ut64 killme = UT64_MAX;
|
|
|
|
if (r_io_read_i (core->io, op.ptr, &killme, op.refptr, be)) {
|
|
|
|
core->parser->relsub_addr = killme;
|
|
|
|
}
|
|
|
|
}
|
2017-12-22 12:19:02 +00:00
|
|
|
// 0x33->sym.xx
|
|
|
|
char *p = strdup (strsub);
|
|
|
|
r_parse_filter (core->parser, core->flags, p,
|
2017-12-22 12:40:11 +00:00
|
|
|
strsub, sizeof (strsub), be);
|
2017-12-22 12:19:02 +00:00
|
|
|
free (p);
|
|
|
|
r_cons_printf ("\"disasm\":\"%s\",", strsub);
|
|
|
|
}
|
2017-03-12 23:43:44 +00:00
|
|
|
r_cons_printf ("\"mnemonic\":\"%s\",", mnem);
|
2016-09-03 12:22:31 +00:00
|
|
|
if (hint && hint->opcode) {
|
2017-03-12 23:43:44 +00:00
|
|
|
r_cons_printf ("\"ophint\":\"%s\",", hint->opcode);
|
2016-09-03 12:22:31 +00:00
|
|
|
}
|
2017-03-12 23:43:44 +00:00
|
|
|
r_cons_printf ("\"prefix\":%" PFMT64d ",", op.prefix);
|
|
|
|
r_cons_printf ("\"id\":%d,", op.id);
|
2017-03-09 17:51:58 +00:00
|
|
|
if (opexstr && *opexstr) {
|
|
|
|
r_cons_printf ("\"opex\":%s,", opexstr);
|
|
|
|
}
|
2017-03-12 23:43:44 +00:00
|
|
|
r_cons_printf ("\"addr\":%" PFMT64d ",", core->offset + idx);
|
|
|
|
r_cons_printf ("\"bytes\":\"");
|
2016-08-01 14:18:24 +00:00
|
|
|
for (j = 0; j < size; j++) {
|
|
|
|
r_cons_printf ("%02x", buf[j + idx]);
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("\",");
|
2016-09-03 12:22:31 +00:00
|
|
|
if (op.val != UT64_MAX) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("\"val\": %" PFMT64d ",", op.val);
|
2016-09-03 12:22:31 +00:00
|
|
|
}
|
|
|
|
if (op.ptr != UT64_MAX) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("\"ptr\": %" PFMT64d ",", op.ptr);
|
2016-09-03 12:22:31 +00:00
|
|
|
}
|
2013-12-14 03:15:01 +00:00
|
|
|
r_cons_printf ("\"size\": %d,", size);
|
|
|
|
r_cons_printf ("\"type\": \"%s\",",
|
|
|
|
r_anal_optype_to_string (op.type));
|
2016-05-30 02:18:48 +00:00
|
|
|
if (op.reg) {
|
|
|
|
r_cons_printf ("\"reg\": \"%s\",", op.reg);
|
|
|
|
}
|
2016-12-12 15:24:46 +00:00
|
|
|
if (hint && hint->esil) {
|
2016-12-12 13:47:42 +00:00
|
|
|
r_cons_printf ("\"esil\": \"%s\",", hint->esil);
|
|
|
|
} else if (*esilstr) {
|
|
|
|
r_cons_printf ("\"esil\": \"%s\",", esilstr);
|
2016-05-30 02:18:48 +00:00
|
|
|
}
|
2016-12-12 12:22:03 +00:00
|
|
|
if (hint && hint->jump != UT64_MAX) {
|
2013-12-14 03:15:01 +00:00
|
|
|
op.jump = hint->jump;
|
2016-12-12 12:22:03 +00:00
|
|
|
}
|
|
|
|
if (op.jump != UT64_MAX) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("\"jump\":%" PFMT64d ",", op.jump);
|
2016-12-12 12:22:03 +00:00
|
|
|
}
|
|
|
|
if (hint && hint->fail != UT64_MAX) {
|
2013-12-14 03:15:01 +00:00
|
|
|
op.fail = hint->fail;
|
2016-12-12 12:22:03 +00:00
|
|
|
}
|
|
|
|
if (op.refptr != -1) {
|
2015-03-25 02:03:34 +00:00
|
|
|
r_cons_printf ("\"refptr\":%d,", op.refptr);
|
2016-12-12 12:22:03 +00:00
|
|
|
}
|
|
|
|
if (op.fail != UT64_MAX) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("\"fail\":%" PFMT64d ",", op.fail);
|
2016-12-12 12:22:03 +00:00
|
|
|
}
|
2014-08-08 11:50:16 +00:00
|
|
|
r_cons_printf ("\"cycles\":%d,", op.cycles);
|
2016-12-12 12:22:03 +00:00
|
|
|
if (op.failcycles) {
|
2015-06-20 19:40:14 +00:00
|
|
|
r_cons_printf ("\"failcycles\":%d,", op.failcycles);
|
2016-12-12 12:22:03 +00:00
|
|
|
}
|
2015-06-20 19:39:52 +00:00
|
|
|
r_cons_printf ("\"delay\":%d,", op.delay);
|
2016-04-02 21:45:21 +00:00
|
|
|
{
|
|
|
|
const char *p = r_anal_stackop_tostring (op.stackop);
|
|
|
|
if (p && *p && strcmp (p, "null"))
|
|
|
|
r_cons_printf ("\"stack\":\"%s\",", p);
|
|
|
|
}
|
2016-08-22 16:07:15 +00:00
|
|
|
if (op.stackptr) {
|
|
|
|
r_cons_printf ("\"stackptr\":%d,", op.stackptr);
|
|
|
|
}
|
2016-04-02 21:45:21 +00:00
|
|
|
{
|
2017-12-18 14:58:06 +00:00
|
|
|
const char *arg = (op.type & R_ANAL_OP_TYPE_COND)
|
|
|
|
? r_anal_cond_tostring (op.cond): NULL;
|
2016-04-02 21:45:21 +00:00
|
|
|
if (arg) {
|
|
|
|
r_cons_printf ("\"cond\":\"%s\",", arg);
|
|
|
|
}
|
|
|
|
}
|
2014-12-01 23:36:42 +00:00
|
|
|
r_cons_printf ("\"family\":\"%s\"}", r_anal_op_family_to_string (op.family));
|
2013-12-14 03:15:01 +00:00
|
|
|
} else {
|
2015-12-16 13:35:56 +00:00
|
|
|
#define printline(k, fmt, arg)\
|
|
|
|
{ \
|
|
|
|
if (use_color)\
|
|
|
|
r_cons_printf ("%s%s: " Color_RESET, color, k);\
|
|
|
|
else\
|
|
|
|
r_cons_printf ("%s: ", k);\
|
|
|
|
if (fmt) r_cons_printf (fmt, arg);\
|
|
|
|
}
|
|
|
|
printline ("address", "0x%" PFMT64x "\n", core->offset + idx);
|
2014-10-16 23:15:17 +00:00
|
|
|
printline ("opcode", "%s\n", asmop.buf_asm);
|
2017-03-12 23:43:44 +00:00
|
|
|
printline ("mnemonic", "%s\n", mnem);
|
2014-10-16 23:15:17 +00:00
|
|
|
if (hint) {
|
2016-08-01 14:18:24 +00:00
|
|
|
if (hint->opcode) {
|
2014-10-16 23:15:17 +00:00
|
|
|
printline ("ophint", "%s\n", hint->opcode);
|
2016-08-01 14:18:24 +00:00
|
|
|
}
|
2016-12-12 12:22:03 +00:00
|
|
|
#if 0
|
|
|
|
// addr should not override core->offset + idx.. its silly
|
|
|
|
if (hint->addr != UT64_MAX) {
|
|
|
|
printline ("addr", "0x%08" PFMT64x "\n", (hint->addr + idx));
|
|
|
|
}
|
|
|
|
#endif
|
2014-10-16 23:15:17 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
printline ("prefix", "%" PFMT64d "\n", op.prefix);
|
2016-11-01 22:44:21 +00:00
|
|
|
printline ("id", "%d\n", op.id);
|
2017-03-10 19:05:28 +00:00
|
|
|
#if 0
|
|
|
|
// no opex here to avoid lot of tests broken..and having json in here is not much useful imho
|
2017-03-09 17:51:58 +00:00
|
|
|
if (opexstr && *opexstr) {
|
|
|
|
printline ("opex", "%s\n", opexstr);
|
|
|
|
}
|
2017-03-10 19:05:28 +00:00
|
|
|
#endif
|
2014-10-16 23:15:17 +00:00
|
|
|
printline ("bytes", NULL, 0);
|
2016-08-01 14:18:24 +00:00
|
|
|
for (j = 0; j < size; j++) {
|
|
|
|
r_cons_printf ("%02x", buf[j + idx]);
|
|
|
|
}
|
2013-12-14 03:15:01 +00:00
|
|
|
r_cons_newline ();
|
|
|
|
if (op.val != UT64_MAX)
|
2015-12-16 13:35:56 +00:00
|
|
|
printline ("val", "0x%08" PFMT64x "\n", op.val);
|
2013-12-14 03:15:01 +00:00
|
|
|
if (op.ptr != UT64_MAX)
|
2015-12-16 13:35:56 +00:00
|
|
|
printline ("ptr", "0x%08" PFMT64x "\n", op.ptr);
|
2014-11-07 02:48:27 +00:00
|
|
|
if (op.refptr != -1)
|
2015-12-16 13:35:56 +00:00
|
|
|
printline ("refptr", "%d\n", op.refptr);
|
2014-10-16 23:15:17 +00:00
|
|
|
printline ("size", "%d\n", size);
|
2015-12-16 13:35:56 +00:00
|
|
|
printline ("type", "%s\n", r_anal_optype_to_string (op.type));
|
2016-03-11 08:50:36 +00:00
|
|
|
{
|
|
|
|
const char *t2 = r_anal_optype_to_string (op.type2);
|
|
|
|
if (t2 && strcmp (t2, "null")) {
|
|
|
|
printline ("type2", "%s\n", t2);
|
|
|
|
}
|
|
|
|
}
|
2016-12-12 13:47:42 +00:00
|
|
|
if (op.reg) {
|
2016-05-29 22:38:35 +00:00
|
|
|
printline ("reg", "%s\n", op.reg);
|
2016-12-12 13:47:42 +00:00
|
|
|
}
|
|
|
|
if (hint && hint->esil) {
|
|
|
|
printline ("esil", "%s\n", hint->esil);
|
|
|
|
} else if (*esilstr) {
|
2016-05-31 06:33:18 +00:00
|
|
|
printline ("esil", "%s\n", esilstr);
|
2016-12-12 13:47:42 +00:00
|
|
|
}
|
|
|
|
if (hint && hint->jump != UT64_MAX) {
|
2013-12-14 03:15:01 +00:00
|
|
|
op.jump = hint->jump;
|
2016-12-12 13:47:42 +00:00
|
|
|
}
|
|
|
|
if (op.jump != UT64_MAX) {
|
2015-12-16 13:35:56 +00:00
|
|
|
printline ("jump", "0x%08" PFMT64x "\n", op.jump);
|
2016-12-12 13:47:42 +00:00
|
|
|
}
|
2017-10-16 21:38:10 +00:00
|
|
|
if (op.direction != 0) {
|
|
|
|
const char * dir = op.direction == 1 ? "read"
|
|
|
|
: op.direction == 2 ? "write"
|
|
|
|
: op.direction == 4 ? "exec"
|
|
|
|
: op.direction == 8 ? "ref": "none";
|
|
|
|
printline ("direction", "%s\n", dir);
|
|
|
|
}
|
2016-12-12 13:47:42 +00:00
|
|
|
if (hint && hint->fail != UT64_MAX) {
|
2013-12-14 03:15:01 +00:00
|
|
|
op.fail = hint->fail;
|
2016-12-12 13:47:42 +00:00
|
|
|
}
|
|
|
|
if (op.fail != UT64_MAX) {
|
2015-12-16 13:35:56 +00:00
|
|
|
printline ("fail", "0x%08" PFMT64x "\n", op.fail);
|
2016-12-12 13:47:42 +00:00
|
|
|
}
|
|
|
|
if (op.delay) {
|
2016-05-16 19:48:52 +00:00
|
|
|
printline ("delay", "%d\n", op.delay);
|
2016-12-12 13:47:42 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
printline ("stack", "%s\n", r_anal_stackop_tostring (op.stackop));
|
2016-04-02 21:05:09 +00:00
|
|
|
{
|
|
|
|
const char *arg = (op.type & R_ANAL_OP_TYPE_COND)? r_anal_cond_tostring (op.cond): NULL;
|
|
|
|
if (arg) {
|
|
|
|
printline ("cond", "%s\n", arg);
|
|
|
|
}
|
|
|
|
}
|
2018-01-27 22:32:47 +00:00
|
|
|
printline ("family", "%s\n", r_anal_op_family_to_string (op.family));
|
2018-01-28 02:12:50 +00:00
|
|
|
printline ("stackop", "%s\n", r_anal_stackop_tostring (op.stackop));
|
2018-01-27 02:16:50 +00:00
|
|
|
if (op.stackptr) {
|
|
|
|
printline ("stackptr", "%"PFMT64d"\n", op.stackptr);
|
|
|
|
}
|
2013-12-14 03:15:01 +00:00
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
//r_cons_printf ("false: 0x%08"PFMT64x"\n", core->offset+idx);
|
2014-03-29 01:49:49 +00:00
|
|
|
//free (hint);
|
2017-03-12 23:43:44 +00:00
|
|
|
free (mnem);
|
2014-03-29 01:49:49 +00:00
|
|
|
r_anal_hint_free (hint);
|
2013-12-14 03:15:01 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
if (fmt == 'j') {
|
2013-12-14 03:15:01 +00:00
|
|
|
r_cons_printf ("]");
|
|
|
|
r_cons_newline ();
|
2018-04-08 12:00:21 +00:00
|
|
|
} else if (fmt == 's') {
|
|
|
|
r_cons_printf ("%d\n", totalsize);
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
2016-12-12 16:29:50 +00:00
|
|
|
r_anal_esil_free (esil);
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
|
2015-06-15 22:16:29 +00:00
|
|
|
static int bb_cmp(const void *a, const void *b) {
|
|
|
|
const RAnalBlock *ba = a;
|
|
|
|
const RAnalBlock *bb = b;
|
2015-01-31 03:13:59 +00:00
|
|
|
return ba->addr - bb->addr;
|
|
|
|
}
|
|
|
|
|
2017-04-26 11:35:03 +00:00
|
|
|
static int anal_fcn_list_bb(RCore *core, const char *input, bool one) {
|
2015-01-29 23:36:15 +00:00
|
|
|
RDebugTracepoint *tp = NULL;
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalBlock *b;
|
2015-01-29 12:33:33 +00:00
|
|
|
int mode = 0;
|
2016-09-14 14:42:23 +00:00
|
|
|
ut64 addr, bbaddr = UT64_MAX;
|
2017-04-26 11:35:03 +00:00
|
|
|
bool firstItem = true;
|
2015-01-29 23:36:15 +00:00
|
|
|
|
2017-04-26 11:35:03 +00:00
|
|
|
if (*input == '.') {
|
|
|
|
one = true;
|
|
|
|
input++;
|
|
|
|
}
|
2016-06-17 00:49:41 +00:00
|
|
|
if (*input) {
|
|
|
|
mode = *input;
|
2015-01-29 12:33:33 +00:00
|
|
|
input++;
|
|
|
|
}
|
2017-04-26 11:35:03 +00:00
|
|
|
if (*input == '.') {
|
|
|
|
one = true;
|
|
|
|
input++;
|
|
|
|
}
|
2016-09-14 14:42:23 +00:00
|
|
|
if (input && *input) {
|
|
|
|
addr = bbaddr = r_num_math (core->num, input);
|
2015-01-29 12:33:33 +00:00
|
|
|
} else {
|
|
|
|
addr = core->offset;
|
|
|
|
}
|
2017-04-26 11:35:03 +00:00
|
|
|
if (one) {
|
|
|
|
bbaddr = addr;
|
|
|
|
}
|
2017-07-17 10:58:48 +00:00
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, 0);
|
2016-09-14 14:42:23 +00:00
|
|
|
if (!fcn) {
|
2015-09-14 10:35:38 +00:00
|
|
|
return false;
|
2016-09-14 14:42:23 +00:00
|
|
|
}
|
2015-01-29 12:33:33 +00:00
|
|
|
switch (mode) {
|
|
|
|
case 'j':
|
|
|
|
r_cons_printf ("[");
|
|
|
|
break;
|
|
|
|
case '*':
|
|
|
|
r_cons_printf ("fs blocks\n");
|
|
|
|
break;
|
|
|
|
}
|
2015-01-31 03:13:59 +00:00
|
|
|
r_list_sort (fcn->bbs, bb_cmp);
|
2015-01-29 12:33:33 +00:00
|
|
|
r_list_foreach (fcn->bbs, iter, b) {
|
2017-04-26 11:35:03 +00:00
|
|
|
if (one) {
|
|
|
|
if (bbaddr != UT64_MAX && (bbaddr < b->addr || bbaddr >= (b->addr + b->size))) {
|
|
|
|
continue;
|
|
|
|
}
|
2016-09-14 14:42:23 +00:00
|
|
|
}
|
2015-01-29 12:33:33 +00:00
|
|
|
switch (mode) {
|
2016-06-17 00:49:41 +00:00
|
|
|
case 'r':
|
|
|
|
if (b->jump == UT64_MAX) {
|
|
|
|
ut64 retaddr = b->addr;
|
|
|
|
if (b->op_pos) {
|
|
|
|
retaddr += b->op_pos[b->ninstr - 2];
|
|
|
|
}
|
|
|
|
if (!strcmp (input, "*")) {
|
|
|
|
r_cons_printf ("db 0x%08"PFMT64x"\n", retaddr);
|
|
|
|
} else if (!strcmp (input, "-*")) {
|
|
|
|
r_cons_printf ("db-0x%08"PFMT64x"\n", retaddr);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("0x%08"PFMT64x"\n", retaddr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2015-01-29 12:33:33 +00:00
|
|
|
case '*':
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("f bb.%05" PFMT64x " = 0x%08" PFMT64x "\n",
|
2015-01-29 12:41:38 +00:00
|
|
|
b->addr & 0xFFFFF, b->addr);
|
2015-01-29 12:33:33 +00:00
|
|
|
break;
|
|
|
|
case 'q':
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("0x%08" PFMT64x "\n", b->addr);
|
2015-01-29 12:33:33 +00:00
|
|
|
break;
|
|
|
|
case 'j':
|
2016-06-25 02:17:31 +00:00
|
|
|
//r_cons_printf ("%" PFMT64d "%s", b->addr, iter->n? ",": "");
|
|
|
|
{
|
|
|
|
RListIter *iter2;
|
|
|
|
RAnalBlock *b2;
|
|
|
|
int inputs = 0;
|
|
|
|
int outputs = 0;
|
|
|
|
r_list_foreach (fcn->bbs, iter2, b2) {
|
|
|
|
if (b2->jump == b->addr) {
|
|
|
|
inputs++;
|
|
|
|
}
|
|
|
|
if (b2->fail == b->addr) {
|
|
|
|
inputs++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (b->jump != UT64_MAX) {
|
|
|
|
outputs ++;
|
|
|
|
}
|
|
|
|
if (b->fail != UT64_MAX) {
|
|
|
|
outputs ++;
|
|
|
|
}
|
2017-04-26 11:35:03 +00:00
|
|
|
r_cons_printf ("%s{", firstItem? "": ",");
|
|
|
|
firstItem = false;
|
2016-09-13 10:28:34 +00:00
|
|
|
if (b->jump != UT64_MAX) {
|
|
|
|
r_cons_printf ("\"jump\":%"PFMT64d",", b->jump);
|
|
|
|
}
|
|
|
|
if (b->fail != UT64_MAX) {
|
|
|
|
r_cons_printf ("\"fail\":%"PFMT64d",", b->fail);
|
|
|
|
}
|
2017-04-26 11:35:03 +00:00
|
|
|
r_cons_printf ("\"addr\":%" PFMT64d ",\"size\":%d,\"inputs\":%d,\"outputs\":%d,\"ninstr\":%d,\"traced\":%s}",
|
|
|
|
b->addr, b->size, inputs, outputs, b->ninstr, r_str_bool (b->traced));
|
2016-06-25 02:17:31 +00:00
|
|
|
}
|
2015-01-29 12:33:33 +00:00
|
|
|
break;
|
2017-09-11 23:54:58 +00:00
|
|
|
case 'i':
|
|
|
|
{
|
|
|
|
RListIter *iter2;
|
|
|
|
RAnalBlock *b2;
|
|
|
|
int inputs = 0;
|
|
|
|
int outputs = 0;
|
|
|
|
r_list_foreach (fcn->bbs, iter2, b2) {
|
|
|
|
if (b2->jump == b->addr) {
|
|
|
|
inputs++;
|
|
|
|
}
|
|
|
|
if (b2->fail == b->addr) {
|
|
|
|
inputs++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (b->jump != UT64_MAX) {
|
|
|
|
outputs ++;
|
|
|
|
}
|
|
|
|
if (b->fail != UT64_MAX) {
|
|
|
|
outputs ++;
|
|
|
|
}
|
|
|
|
firstItem = false;
|
|
|
|
if (b->jump != UT64_MAX) {
|
|
|
|
r_cons_printf ("jump: 0x%08"PFMT64x"\n", b->jump);
|
|
|
|
}
|
|
|
|
if (b->fail != UT64_MAX) {
|
|
|
|
r_cons_printf ("fail: 0x%08"PFMT64x"\n", b->fail);
|
|
|
|
}
|
|
|
|
r_cons_printf ("addr: 0x%08"PFMT64x"\nsize: %d\ninputs: %d\noutputs: %d\nninstr: %d\ntraced: %s\n",
|
|
|
|
b->addr, b->size, inputs, outputs, b->ninstr, r_str_bool (b->traced));
|
|
|
|
}
|
|
|
|
break;
|
2015-01-29 12:33:33 +00:00
|
|
|
default:
|
2015-01-29 23:36:15 +00:00
|
|
|
tp = r_debug_trace_get (core->dbg, b->addr);
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("0x%08" PFMT64x " 0x%08" PFMT64x " %02X:%04X %d",
|
2015-01-29 23:36:15 +00:00
|
|
|
b->addr, b->addr + b->size,
|
2015-12-16 13:35:56 +00:00
|
|
|
tp? tp->times: 0, tp? tp->count: 0,
|
2015-01-29 23:36:15 +00:00
|
|
|
b->size);
|
2015-01-29 12:33:33 +00:00
|
|
|
if (b->jump != UT64_MAX) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf (" j 0x%08" PFMT64x, b->jump);
|
2015-01-29 12:33:33 +00:00
|
|
|
}
|
|
|
|
if (b->fail != UT64_MAX) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf (" f 0x%08" PFMT64x, b->fail);
|
2015-01-29 12:33:33 +00:00
|
|
|
}
|
|
|
|
r_cons_newline ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
if (mode == 'j') {
|
2016-06-15 11:41:17 +00:00
|
|
|
r_cons_printf ("]\n");
|
2015-01-29 12:33:33 +00:00
|
|
|
}
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2015-01-29 12:33:33 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 02:34:16 +00:00
|
|
|
static bool anal_bb_edge (RCore *core, const char *input) {
|
|
|
|
// "afbe" switch-bb-addr case-bb-addr
|
2018-01-08 02:29:29 +00:00
|
|
|
char *arg = strdup (r_str_trim_ro(input));
|
2016-12-29 02:34:16 +00:00
|
|
|
char *sp = strchr (arg, ' ');
|
|
|
|
if (sp) {
|
|
|
|
*sp++ = 0;
|
|
|
|
ut64 sw_at = r_num_math (core->num, arg);
|
|
|
|
ut64 cs_at = r_num_math (core->num, sp);
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, sw_at, 0);
|
|
|
|
if (fcn) {
|
|
|
|
RAnalBlock *bb;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (fcn->bbs, iter, bb) {
|
|
|
|
if (sw_at >= bb->addr && sw_at < (bb->addr + bb->size)) {
|
|
|
|
if (!bb->switch_op) {
|
|
|
|
bb->switch_op = r_anal_switch_op_new (
|
|
|
|
sw_at, 0, 0);
|
|
|
|
}
|
|
|
|
r_anal_switch_op_add_case (bb->switch_op, cs_at, 0, cs_at);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free (arg);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free (arg);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-01-25 16:28:56 +00:00
|
|
|
static bool anal_fcn_del_bb(RCore *core, const char *input) {
|
|
|
|
ut64 addr = r_num_math (core->num, input);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (!addr) {
|
|
|
|
addr = core->offset;
|
|
|
|
}
|
2016-01-25 16:28:56 +00:00
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, -1);
|
|
|
|
if (fcn) {
|
2016-01-25 18:19:01 +00:00
|
|
|
if (!strcmp (input, "*")) {
|
|
|
|
r_list_free (fcn->bbs);
|
|
|
|
fcn->bbs = NULL;
|
|
|
|
} else {
|
|
|
|
RAnalBlock *b;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (fcn->bbs, iter, b) {
|
|
|
|
if (b->addr == addr) {
|
|
|
|
r_list_delete (fcn->bbs, iter);
|
|
|
|
return true;
|
|
|
|
}
|
2016-01-25 16:28:56 +00:00
|
|
|
}
|
2016-01-25 18:19:01 +00:00
|
|
|
eprintf ("Cannot find basic block\n");
|
2016-01-25 16:28:56 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
eprintf ("Cannot find function\n");
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-12-16 13:35:56 +00:00
|
|
|
static int anal_fcn_add_bb(RCore *core, const char *input) {
|
2014-11-13 10:17:43 +00:00
|
|
|
// fcn_addr bb_addr bb_size [jump] [fail]
|
|
|
|
char *ptr;
|
2013-05-24 00:53:15 +00:00
|
|
|
const char *ptr2 = NULL;
|
|
|
|
ut64 fcnaddr = -1LL, addr = -1LL;
|
|
|
|
ut64 size = 0LL;
|
2013-10-25 00:06:00 +00:00
|
|
|
ut64 jump = UT64_MAX;
|
|
|
|
ut64 fail = UT64_MAX;
|
2013-05-24 00:53:15 +00:00
|
|
|
int type = R_ANAL_BB_TYPE_NULL;
|
|
|
|
RAnalFunction *fcn = NULL;
|
|
|
|
RAnalDiff *diff = NULL;
|
|
|
|
|
2015-12-16 13:35:56 +00:00
|
|
|
while (*input == ' ') input++;
|
2014-11-13 10:17:43 +00:00
|
|
|
ptr = strdup (input);
|
|
|
|
|
2013-10-25 00:06:00 +00:00
|
|
|
switch (r_str_word_set0 (ptr)) {
|
2014-06-16 03:58:00 +00:00
|
|
|
case 7:
|
|
|
|
ptr2 = r_str_word_get0 (ptr, 6);
|
|
|
|
if (!(diff = r_anal_diff_new ())) {
|
|
|
|
eprintf ("error: Cannot init RAnalDiff\n");
|
|
|
|
free (ptr);
|
2015-09-14 10:35:38 +00:00
|
|
|
return false;
|
2014-06-16 03:58:00 +00:00
|
|
|
}
|
2016-09-21 10:07:44 +00:00
|
|
|
if (ptr2[0] == 'm') {
|
2014-06-16 03:58:00 +00:00
|
|
|
diff->type = R_ANAL_DIFF_TYPE_MATCH;
|
2016-09-21 10:07:44 +00:00
|
|
|
} else if (ptr2[0] == 'u') {
|
2014-06-16 03:58:00 +00:00
|
|
|
diff->type = R_ANAL_DIFF_TYPE_UNMATCH;
|
2016-09-21 10:07:44 +00:00
|
|
|
}
|
2014-06-16 03:58:00 +00:00
|
|
|
case 6:
|
|
|
|
ptr2 = r_str_word_get0 (ptr, 5);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (strchr (ptr2, 'h')) {
|
|
|
|
type |= R_ANAL_BB_TYPE_HEAD;
|
|
|
|
}
|
|
|
|
if (strchr (ptr2, 'b')) {
|
|
|
|
type |= R_ANAL_BB_TYPE_BODY;
|
|
|
|
}
|
|
|
|
if (strchr (ptr2, 'l')) {
|
|
|
|
type |= R_ANAL_BB_TYPE_LAST;
|
|
|
|
}
|
|
|
|
if (strchr (ptr2, 'f')) {
|
|
|
|
type |= R_ANAL_BB_TYPE_FOOT;
|
|
|
|
}
|
2014-06-16 03:58:00 +00:00
|
|
|
case 5: // get fail
|
|
|
|
fail = r_num_math (core->num, r_str_word_get0 (ptr, 4));
|
|
|
|
case 4: // get jump
|
|
|
|
jump = r_num_math (core->num, r_str_word_get0 (ptr, 3));
|
|
|
|
case 3: // get size
|
|
|
|
size = r_num_math (core->num, r_str_word_get0 (ptr, 2));
|
|
|
|
case 2: // get addr
|
|
|
|
addr = r_num_math (core->num, r_str_word_get0 (ptr, 1));
|
|
|
|
case 1: // get fcnaddr
|
|
|
|
fcnaddr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
2013-05-24 00:53:15 +00:00
|
|
|
}
|
2014-12-14 00:49:04 +00:00
|
|
|
fcn = r_anal_get_fcn_in (core->anal, fcnaddr, 0);
|
|
|
|
if (fcn) {
|
2016-09-21 10:07:44 +00:00
|
|
|
int ret = r_anal_fcn_add_bb (core->anal, fcn, addr, size, jump, fail, type, diff);
|
2014-12-14 00:49:04 +00:00
|
|
|
if (!ret) {
|
|
|
|
eprintf ("Cannot add basic block\n");
|
|
|
|
}
|
|
|
|
} else {
|
2015-12-16 13:35:56 +00:00
|
|
|
eprintf ("Cannot find function at 0x%" PFMT64x "\n", fcnaddr);
|
2013-05-24 00:53:15 +00:00
|
|
|
}
|
|
|
|
r_anal_diff_free (diff);
|
|
|
|
free (ptr);
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2013-05-24 00:53:15 +00:00
|
|
|
}
|
2014-11-13 10:17:43 +00:00
|
|
|
|
2016-04-15 17:39:04 +00:00
|
|
|
static void r_core_anal_nofunclist (RCore *core, const char *input) {
|
|
|
|
int minlen = (int)(input[0]==' ') ? r_num_math (core->num, input + 1): 16;
|
|
|
|
ut64 code_size = r_num_get (core->num, "$SS");
|
2016-05-31 06:33:18 +00:00
|
|
|
ut64 base_addr = r_num_get (core->num, "$S");
|
2016-04-15 17:39:04 +00:00
|
|
|
ut64 chunk_size, chunk_offset, i;
|
2016-05-31 06:33:18 +00:00
|
|
|
RListIter *iter, *iter2;
|
2016-04-15 17:39:04 +00:00
|
|
|
RAnalFunction *fcn;
|
|
|
|
RAnalBlock *b;
|
|
|
|
char* bitmap;
|
|
|
|
int counter;
|
|
|
|
|
2016-11-24 00:56:49 +00:00
|
|
|
if (minlen < 1) {
|
2017-01-24 00:41:12 +00:00
|
|
|
minlen = 1;
|
2016-11-24 00:56:49 +00:00
|
|
|
}
|
|
|
|
if (code_size < 1) {
|
|
|
|
return;
|
|
|
|
}
|
2016-04-15 17:39:04 +00:00
|
|
|
bitmap = calloc (1, code_size+64);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (!bitmap) {
|
|
|
|
return;
|
|
|
|
}
|
2016-04-15 17:39:04 +00:00
|
|
|
|
|
|
|
// for each function
|
|
|
|
r_list_foreach (core->anal->fcns, iter, fcn) {
|
|
|
|
// for each basic block in the function
|
2016-05-31 06:33:18 +00:00
|
|
|
r_list_foreach (fcn->bbs, iter2, b) {
|
2016-04-15 17:39:04 +00:00
|
|
|
// if it is not withing range, continue
|
|
|
|
if ((fcn->addr < base_addr) || (fcn->addr >= base_addr+code_size))
|
|
|
|
continue;
|
|
|
|
// otherwise mark each byte in the BB in the bitmap
|
|
|
|
for (counter = 0; counter < b->size; counter++) {
|
2016-05-31 06:33:18 +00:00
|
|
|
bitmap[b->addr+counter-base_addr] = '=';
|
2016-04-15 17:39:04 +00:00
|
|
|
}
|
|
|
|
// finally, add a special marker to show the beginning of a
|
|
|
|
// function
|
|
|
|
bitmap[fcn->addr-base_addr] = 'F';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now we print the list of memory regions that are not assigned to a function
|
|
|
|
chunk_size = 0;
|
|
|
|
chunk_offset = 0;
|
|
|
|
for (i = 0; i < code_size; i++) {
|
|
|
|
if (bitmap[i]){
|
|
|
|
// We only print a region is its size is bigger than 15 bytes
|
|
|
|
if (chunk_size >= minlen){
|
|
|
|
fcn = r_anal_get_fcn_in (core->anal, base_addr+chunk_offset, R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
2016-05-31 06:33:18 +00:00
|
|
|
if (fcn) {
|
2016-04-15 17:39:04 +00:00
|
|
|
r_cons_printf ("0x%08"PFMT64x" %6d %s\n", base_addr+chunk_offset, chunk_size, fcn->name);
|
2016-05-31 06:33:18 +00:00
|
|
|
} else {
|
2016-04-15 17:39:04 +00:00
|
|
|
r_cons_printf ("0x%08"PFMT64x" %6d\n", base_addr+chunk_offset, chunk_size);
|
2016-05-31 06:33:18 +00:00
|
|
|
}
|
2016-04-15 17:39:04 +00:00
|
|
|
}
|
|
|
|
chunk_size = 0;
|
|
|
|
chunk_offset = i+1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
chunk_size+=1;
|
|
|
|
}
|
|
|
|
if (chunk_size >= 16) {
|
|
|
|
fcn = r_anal_get_fcn_in (core->anal, base_addr+chunk_offset, R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
|
|
|
if (fcn) {
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" %6d %s\n", base_addr+chunk_offset, chunk_size, fcn->name);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" %6d\n", base_addr+chunk_offset, chunk_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(bitmap);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void r_core_anal_fmap (RCore *core, const char *input) {
|
|
|
|
int show_color = r_config_get_i (core->config, "scr.color");
|
|
|
|
int cols = r_config_get_i (core->config, "hex.cols") * 4;
|
|
|
|
ut64 code_size = r_num_get (core->num, "$SS");
|
|
|
|
ut64 base_addr = r_num_get (core->num, "$S");
|
|
|
|
RListIter *iter, *iter2;
|
|
|
|
RAnalFunction *fcn;
|
|
|
|
RAnalBlock *b;
|
|
|
|
char* bitmap;
|
|
|
|
int assigned;
|
|
|
|
ut64 i;
|
2016-05-31 06:33:18 +00:00
|
|
|
|
2016-11-24 00:56:49 +00:00
|
|
|
if (code_size < 1) {
|
|
|
|
return;
|
|
|
|
}
|
2016-04-15 17:39:04 +00:00
|
|
|
bitmap = calloc (1, code_size+64);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (!bitmap) {
|
|
|
|
return;
|
|
|
|
}
|
2016-04-15 17:39:04 +00:00
|
|
|
|
|
|
|
// for each function
|
|
|
|
r_list_foreach (core->anal->fcns, iter, fcn) {
|
|
|
|
// for each basic block in the function
|
2016-05-31 06:33:18 +00:00
|
|
|
r_list_foreach (fcn->bbs, iter2, b) {
|
2016-04-15 17:39:04 +00:00
|
|
|
// if it is not within range, continue
|
|
|
|
if ((fcn->addr < base_addr) || (fcn->addr >= base_addr+code_size))
|
|
|
|
continue;
|
|
|
|
// otherwise mark each byte in the BB in the bitmap
|
|
|
|
int counter = 1;
|
|
|
|
for (counter = 0; counter < b->size; counter++) {
|
2016-05-31 06:33:18 +00:00
|
|
|
bitmap[b->addr+counter-base_addr] = '=';
|
2016-04-15 17:39:04 +00:00
|
|
|
}
|
|
|
|
bitmap[fcn->addr-base_addr] = 'F';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// print the bitmap
|
|
|
|
assigned = 0;
|
2016-10-20 13:39:36 +00:00
|
|
|
if (cols < 1) {
|
|
|
|
cols = 1;
|
|
|
|
}
|
2016-04-15 17:39:04 +00:00
|
|
|
for (i = 0; i < code_size; i += 1) {
|
|
|
|
if (!(i % cols)) {
|
|
|
|
r_cons_printf ("\n0x%08"PFMT64x" ", base_addr+i);
|
|
|
|
}
|
2016-11-24 00:56:49 +00:00
|
|
|
if (bitmap[i]) {
|
|
|
|
assigned++;
|
|
|
|
}
|
2016-04-15 17:39:04 +00:00
|
|
|
if (show_color) {
|
2018-04-11 10:15:14 +00:00
|
|
|
if (bitmap[i]) {
|
2016-04-15 17:39:04 +00:00
|
|
|
r_cons_printf ("%s%c\x1b[0m", Color_GREEN, bitmap[i]);
|
2018-04-11 10:15:14 +00:00
|
|
|
} else {
|
2016-04-15 17:39:04 +00:00
|
|
|
r_cons_printf (".");
|
2018-04-11 10:15:14 +00:00
|
|
|
}
|
|
|
|
} else {
|
2016-04-15 17:39:04 +00:00
|
|
|
r_cons_printf ("%c", bitmap[i] ? bitmap[i] : '.' );
|
2018-04-11 10:15:14 +00:00
|
|
|
}
|
2016-04-15 17:39:04 +00:00
|
|
|
}
|
|
|
|
r_cons_printf ("\n%d / %d (%.2lf%%) bytes assigned to a function\n", assigned, code_size, 100.0*( (float) assigned) / code_size);
|
|
|
|
free(bitmap);
|
|
|
|
}
|
|
|
|
|
2015-12-16 13:35:56 +00:00
|
|
|
static bool fcnNeedsPrefix(const char *name) {
|
2016-12-29 02:34:16 +00:00
|
|
|
if (!strncmp (name, "entry", 5)) {
|
2015-10-18 16:47:04 +00:00
|
|
|
return false;
|
2016-12-29 02:34:16 +00:00
|
|
|
}
|
|
|
|
if (!strncmp (name, "main", 4)) {
|
2015-10-18 16:47:04 +00:00
|
|
|
return false;
|
2016-12-29 02:34:16 +00:00
|
|
|
}
|
2015-10-18 16:47:04 +00:00
|
|
|
return (!strchr (name, '.'));
|
|
|
|
}
|
|
|
|
|
2016-05-23 23:47:09 +00:00
|
|
|
/* TODO: move into r_anal_fcn_rename(); */
|
2017-08-29 11:27:24 +00:00
|
|
|
static bool setFunctionName(RCore *core, ut64 off, const char *_name, bool prefix) {
|
|
|
|
char *name, *oname, *nname = NULL;
|
2015-10-18 15:54:27 +00:00
|
|
|
RAnalFunction *fcn;
|
2017-08-29 11:27:24 +00:00
|
|
|
if (!core || !_name) {
|
2015-10-18 15:54:27 +00:00
|
|
|
return false;
|
2016-05-23 23:47:09 +00:00
|
|
|
}
|
2017-03-24 09:46:13 +00:00
|
|
|
const char *fcnpfx = r_config_get (core->config, "anal.fcnprefix");
|
|
|
|
if (!fcnpfx) {
|
|
|
|
fcnpfx = "fcn";
|
|
|
|
}
|
2017-08-29 11:27:24 +00:00
|
|
|
if (r_reg_get (core->anal->reg, _name, -1)) {
|
|
|
|
name = r_str_newf ("%s.%s", fcnpfx, _name);
|
|
|
|
} else {
|
|
|
|
name = strdup (_name);
|
2016-05-23 23:47:09 +00:00
|
|
|
}
|
2015-10-18 15:54:27 +00:00
|
|
|
fcn = r_anal_get_fcn_in (core->anal, off,
|
2015-12-16 13:35:56 +00:00
|
|
|
R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM | R_ANAL_FCN_TYPE_LOC);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (!fcn) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-03-22 01:05:23 +00:00
|
|
|
if (prefix && fcnNeedsPrefix (name)) {
|
2017-03-24 09:46:13 +00:00
|
|
|
nname = r_str_newf ("%s.%s", fcnpfx, name);
|
2015-10-18 15:54:27 +00:00
|
|
|
} else {
|
|
|
|
nname = strdup (name);
|
|
|
|
}
|
2015-03-16 01:52:26 +00:00
|
|
|
oname = fcn->name;
|
2016-05-23 23:47:09 +00:00
|
|
|
r_flag_rename (core->flags, r_flag_get (core->flags, fcn->name), nname);
|
2015-10-18 15:54:27 +00:00
|
|
|
fcn->name = strdup (nname);
|
2015-03-16 01:52:26 +00:00
|
|
|
if (core->anal->cb.on_fcn_rename) {
|
2015-10-18 15:54:27 +00:00
|
|
|
core->anal->cb.on_fcn_rename (core->anal,
|
2015-12-16 13:35:56 +00:00
|
|
|
core->anal->user, fcn, nname);
|
2015-03-16 01:52:26 +00:00
|
|
|
}
|
|
|
|
free (oname);
|
2015-10-18 15:54:27 +00:00
|
|
|
free (nname);
|
2017-08-29 11:27:24 +00:00
|
|
|
free (name);
|
2015-10-18 15:54:27 +00:00
|
|
|
return true;
|
2014-11-08 00:03:04 +00:00
|
|
|
}
|
2013-05-24 00:53:15 +00:00
|
|
|
|
2017-08-14 17:09:36 +00:00
|
|
|
static void afCc(RCore *core, const char *input) {
|
2017-01-10 00:30:24 +00:00
|
|
|
ut64 addr;
|
|
|
|
RAnalFunction *fcn;
|
|
|
|
if (*input == ' ') {
|
|
|
|
addr = r_num_math (core->num, input);
|
|
|
|
} else {
|
|
|
|
addr = core->offset;
|
|
|
|
}
|
|
|
|
if (addr == 0LL) {
|
|
|
|
fcn = r_anal_fcn_find_name (core->anal, input + 3);
|
|
|
|
} else {
|
|
|
|
fcn = r_anal_get_fcn_in (core->anal, addr, R_ANAL_FCN_TYPE_NULL);
|
|
|
|
}
|
|
|
|
if (fcn) {
|
2017-01-13 22:08:37 +00:00
|
|
|
ut32 totalCycles = r_anal_fcn_cost (core->anal, fcn);
|
2017-10-17 23:27:49 +00:00
|
|
|
// FIXME: This defeats the purpose of the function, but afC is used in project files.
|
|
|
|
// cf. canal.c
|
2017-10-18 01:07:39 +00:00
|
|
|
r_cons_printf ("%d\n", totalCycles);
|
2017-01-10 00:30:24 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Cannot find function\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-23 01:31:51 +00:00
|
|
|
static int cmd_anal_fcn(RCore *core, const char *input) {
|
2016-07-29 17:34:43 +00:00
|
|
|
char i;
|
2017-05-02 14:18:46 +00:00
|
|
|
|
2016-12-12 22:57:04 +00:00
|
|
|
r_cons_break_timeout (r_config_get_i (core->config, "anal.timeout"));
|
2014-01-23 01:31:51 +00:00
|
|
|
switch (input[1]) {
|
2017-09-01 08:33:28 +00:00
|
|
|
case 'f': // "aff"
|
2014-09-02 00:41:40 +00:00
|
|
|
r_anal_fcn_fit_overlaps (core->anal, NULL);
|
|
|
|
break;
|
2018-02-22 05:21:41 +00:00
|
|
|
case 'a':
|
|
|
|
if (input[2] == 'l') { // afal : list function call arguments
|
|
|
|
int show_args = r_config_get_i (core->config, "dbg.funcarg");
|
|
|
|
if (show_args) {
|
|
|
|
r_core_print_func_args (core);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2017-12-17 19:29:43 +00:00
|
|
|
case 'd': // "afd"
|
|
|
|
{
|
2018-03-12 12:10:59 +00:00
|
|
|
ut64 addr = 0;
|
2017-12-18 16:52:14 +00:00
|
|
|
if (input[2] == '?') {
|
|
|
|
eprintf ("afd [offset]\n");
|
|
|
|
} else if (input[2] == ' ') {
|
2018-03-12 12:10:59 +00:00
|
|
|
addr = r_num_math (core->num, input + 2);
|
2017-12-17 19:29:43 +00:00
|
|
|
} else {
|
2017-12-18 16:52:14 +00:00
|
|
|
addr = core->offset;
|
2018-03-12 12:10:59 +00:00
|
|
|
}
|
2017-12-17 19:29:43 +00:00
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, 0);
|
|
|
|
if (fcn) {
|
|
|
|
if (fcn->addr != addr) {
|
|
|
|
r_cons_printf ("%s + %d\n", fcn->name,
|
|
|
|
(int)(addr - fcn->addr));
|
|
|
|
} else {
|
|
|
|
r_cons_println (fcn->name);
|
2018-03-12 12:10:59 +00:00
|
|
|
}
|
2017-12-17 19:29:43 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Cannot find function\n");
|
|
|
|
}
|
|
|
|
}
|
2018-03-12 12:10:59 +00:00
|
|
|
break;
|
2015-11-13 08:22:56 +00:00
|
|
|
case '-': // "af-"
|
2015-12-16 13:35:56 +00:00
|
|
|
if (!input[2] || !strcmp (input + 2, "*")) {
|
2015-11-13 08:22:56 +00:00
|
|
|
r_anal_fcn_del_locs (core->anal, UT64_MAX);
|
|
|
|
r_anal_fcn_del (core->anal, UT64_MAX);
|
|
|
|
} else {
|
2017-01-13 22:08:37 +00:00
|
|
|
ut64 addr = input[2]
|
|
|
|
? r_num_math (core->num, input + 2)
|
|
|
|
: core->offset;
|
2014-06-16 03:58:00 +00:00
|
|
|
r_anal_fcn_del_locs (core->anal, addr);
|
|
|
|
r_anal_fcn_del (core->anal, addr);
|
2015-12-16 13:35:56 +00:00
|
|
|
}
|
2014-01-23 01:31:51 +00:00
|
|
|
break;
|
2017-09-01 08:33:28 +00:00
|
|
|
case 'u': // "afu"
|
2016-03-21 15:41:18 +00:00
|
|
|
{
|
2014-11-26 12:25:23 +00:00
|
|
|
ut64 addr = core->offset;
|
2015-12-16 13:35:56 +00:00
|
|
|
ut64 addr_end = r_num_math (core->num, input + 2);
|
2015-03-16 01:52:26 +00:00
|
|
|
if (addr_end < addr) {
|
2014-11-26 12:25:23 +00:00
|
|
|
eprintf ("Invalid address ranges\n");
|
|
|
|
} else {
|
|
|
|
int depth = 1;
|
|
|
|
ut64 a, b;
|
2014-11-26 12:34:23 +00:00
|
|
|
const char *c;
|
2014-11-26 12:25:23 +00:00
|
|
|
a = r_config_get_i (core->config, "anal.from");
|
|
|
|
b = r_config_get_i (core->config, "anal.to");
|
2014-11-26 12:34:23 +00:00
|
|
|
c = r_config_get (core->config, "anal.limits");
|
2014-11-26 12:25:23 +00:00
|
|
|
r_config_set_i (core->config, "anal.from", addr);
|
|
|
|
r_config_set_i (core->config, "anal.to", addr_end);
|
2014-11-26 12:34:23 +00:00
|
|
|
r_config_set (core->config, "anal.limits", "true");
|
2014-11-26 12:25:23 +00:00
|
|
|
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, 0);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (fcn) {
|
2018-03-17 13:09:13 +00:00
|
|
|
r_anal_fcn_resize (core->anal, fcn, addr_end - addr);
|
2016-11-24 00:56:49 +00:00
|
|
|
}
|
2014-11-26 12:25:23 +00:00
|
|
|
r_core_anal_fcn (core, addr, UT64_MAX,
|
|
|
|
R_ANAL_REF_TYPE_NULL, depth);
|
|
|
|
fcn = r_anal_get_fcn_in (core->anal, addr, 0);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (fcn) {
|
2018-03-17 13:09:13 +00:00
|
|
|
r_anal_fcn_resize (core->anal, fcn, addr_end - addr);
|
2016-11-24 00:56:49 +00:00
|
|
|
}
|
2014-11-26 12:25:23 +00:00
|
|
|
r_config_set_i (core->config, "anal.from", a);
|
|
|
|
r_config_set_i (core->config, "anal.to", b);
|
2015-12-16 13:35:56 +00:00
|
|
|
r_config_set (core->config, "anal.limits", c? c: "");
|
|
|
|
}
|
2016-03-21 15:41:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-08-18 13:05:47 +00:00
|
|
|
case '+': { // "af+"
|
|
|
|
if (input[2] != ' ') {
|
|
|
|
eprintf ("Missing arguments\n");
|
|
|
|
return false;
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
char *ptr = strdup (input + 3);
|
|
|
|
const char *ptr2;
|
|
|
|
int n = r_str_word_set0 (ptr);
|
|
|
|
const char *name = NULL;
|
2017-02-09 23:02:39 +00:00
|
|
|
ut64 addr = UT64_MAX;
|
2015-12-16 13:35:56 +00:00
|
|
|
ut64 size = 0LL;
|
|
|
|
RAnalDiff *diff = NULL;
|
|
|
|
int type = R_ANAL_FCN_TYPE_FCN;
|
2017-02-09 23:02:39 +00:00
|
|
|
if (n > 1) {
|
2015-12-16 13:35:56 +00:00
|
|
|
switch (n) {
|
|
|
|
case 5:
|
2017-02-09 23:02:39 +00:00
|
|
|
size = r_num_math (core->num, r_str_word_get0 (ptr, 4));
|
|
|
|
case 4:
|
|
|
|
ptr2 = r_str_word_get0 (ptr, 3);
|
2015-12-16 13:35:56 +00:00
|
|
|
if (!(diff = r_anal_diff_new ())) {
|
|
|
|
eprintf ("error: Cannot init RAnalDiff\n");
|
|
|
|
free (ptr);
|
|
|
|
return false;
|
2014-01-23 01:31:51 +00:00
|
|
|
}
|
2016-09-21 10:07:44 +00:00
|
|
|
if (ptr2[0] == 'm') {
|
2015-12-16 13:35:56 +00:00
|
|
|
diff->type = R_ANAL_DIFF_TYPE_MATCH;
|
2016-09-21 10:07:44 +00:00
|
|
|
} else if (ptr2[0] == 'u') {
|
2015-12-16 13:35:56 +00:00
|
|
|
diff->type = R_ANAL_DIFF_TYPE_UNMATCH;
|
2016-09-21 10:07:44 +00:00
|
|
|
}
|
2017-02-09 23:02:39 +00:00
|
|
|
case 3:
|
|
|
|
ptr2 = r_str_word_get0 (ptr, 2);
|
2016-11-01 17:36:09 +00:00
|
|
|
if (strchr (ptr2, 'l')) {
|
2015-12-16 13:35:56 +00:00
|
|
|
type = R_ANAL_FCN_TYPE_LOC;
|
2016-11-01 17:36:09 +00:00
|
|
|
} else if (strchr (ptr2, 'i')) {
|
2015-12-16 13:35:56 +00:00
|
|
|
type = R_ANAL_FCN_TYPE_IMP;
|
2016-11-01 17:36:09 +00:00
|
|
|
} else if (strchr (ptr2, 's')) {
|
2015-12-16 13:35:56 +00:00
|
|
|
type = R_ANAL_FCN_TYPE_SYM;
|
2016-11-01 17:36:09 +00:00
|
|
|
} else {
|
|
|
|
type = R_ANAL_FCN_TYPE_FCN;
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
case 2:
|
2017-02-09 23:02:39 +00:00
|
|
|
name = r_str_word_get0 (ptr, 1);
|
2015-12-16 13:35:56 +00:00
|
|
|
case 1:
|
|
|
|
addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
2014-01-23 01:31:51 +00:00
|
|
|
}
|
2017-02-09 23:02:39 +00:00
|
|
|
if (!r_anal_fcn_add (core->anal, addr, size, name, type, diff)) {
|
2015-12-16 13:35:56 +00:00
|
|
|
eprintf ("Cannot add function (duplicated)\n");
|
2017-02-09 23:02:39 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
}
|
|
|
|
r_anal_diff_free (diff);
|
|
|
|
free (ptr);
|
2016-03-21 15:41:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2014-10-29 09:41:43 +00:00
|
|
|
case 'o': // "afo"
|
2016-03-21 15:41:18 +00:00
|
|
|
{
|
2015-12-16 13:35:56 +00:00
|
|
|
RAnalFunction *fcn;
|
|
|
|
ut64 addr = core->offset;
|
|
|
|
if (input[2] == ' ')
|
|
|
|
addr = r_num_math (core->num, input + 3);
|
|
|
|
if (addr == 0LL) {
|
|
|
|
fcn = r_anal_fcn_find_name (core->anal, input + 3);
|
|
|
|
} else {
|
|
|
|
fcn = r_anal_get_fcn_in (core->anal, addr, R_ANAL_FCN_TYPE_NULL);
|
|
|
|
}
|
2016-11-24 00:56:49 +00:00
|
|
|
if (fcn) {
|
|
|
|
r_cons_printf ("0x%08" PFMT64x "\n", fcn->addr);
|
|
|
|
}
|
2016-03-21 15:41:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2014-10-20 23:07:25 +00:00
|
|
|
case 'i': // "afi"
|
|
|
|
switch (input[2]) {
|
2016-06-14 15:54:17 +00:00
|
|
|
case '?':
|
2017-08-18 13:04:48 +00:00
|
|
|
r_core_cmd_help (core, help_msg_afi);
|
2016-07-05 13:58:09 +00:00
|
|
|
break;
|
2017-11-28 10:37:49 +00:00
|
|
|
case '.': // "afi."
|
|
|
|
{
|
|
|
|
ut64 addr = core->offset;
|
|
|
|
if (input[3] == ' ') {
|
|
|
|
addr = r_num_math (core->num, input + 3);
|
|
|
|
}
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, R_ANAL_FCN_TYPE_NULL);
|
|
|
|
if (fcn) {
|
|
|
|
r_cons_printf ("%s\n", fcn->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'l': // "afil"
|
2017-05-02 14:18:46 +00:00
|
|
|
if (input[3] == '?') {
|
2017-07-24 15:41:50 +00:00
|
|
|
// TODO #7967 help refactor
|
2017-05-02 14:18:46 +00:00
|
|
|
help_msg_afll[1] = "afil";
|
|
|
|
r_core_cmd_help (core, help_msg_afll);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fallthrough */
|
|
|
|
case 'j': // "afij"
|
2016-07-05 13:58:09 +00:00
|
|
|
case '*': // "afi*"
|
2016-07-29 17:34:43 +00:00
|
|
|
r_core_anal_fcn_list (core, input + 3, input + 2);
|
2016-07-05 13:58:09 +00:00
|
|
|
break;
|
2016-06-14 15:54:17 +00:00
|
|
|
default:
|
2016-07-29 17:34:43 +00:00
|
|
|
i = 1;
|
|
|
|
r_core_anal_fcn_list (core, input + 2, &i);
|
2016-07-05 13:58:09 +00:00
|
|
|
break;
|
2014-10-20 23:07:25 +00:00
|
|
|
}
|
2014-08-08 12:40:50 +00:00
|
|
|
break;
|
2015-01-31 18:24:18 +00:00
|
|
|
case 'l': // "afl"
|
|
|
|
switch (input[2]) {
|
2017-05-02 14:18:46 +00:00
|
|
|
case '?':
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_afl);
|
2015-05-31 21:46:32 +00:00
|
|
|
break;
|
2017-09-01 08:33:28 +00:00
|
|
|
case 'l': // "afll"
|
2017-05-02 14:18:46 +00:00
|
|
|
if (input[3] == '?') {
|
2017-07-24 15:41:50 +00:00
|
|
|
// TODO #7967 help refactor
|
2017-05-02 14:18:46 +00:00
|
|
|
help_msg_afll[1] = "afll";
|
|
|
|
r_core_cmd_help (core, help_msg_afll);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fallthrough */
|
2017-09-01 08:33:28 +00:00
|
|
|
case 'j': // "aflj"
|
|
|
|
case 'q': // "aflq"
|
|
|
|
case 's': // "afls"
|
|
|
|
case '*': // "afl*"
|
2016-07-29 17:34:43 +00:00
|
|
|
r_core_anal_fcn_list (core, NULL, input + 2);
|
2015-05-31 21:46:32 +00:00
|
|
|
break;
|
2017-11-23 17:57:33 +00:00
|
|
|
case 'c': // "aflc"
|
|
|
|
r_cons_printf ("%d\n", r_list_length (core->anal->fcns));
|
|
|
|
break;
|
2017-09-01 08:33:28 +00:00
|
|
|
default: // "afl "
|
2016-10-20 13:39:36 +00:00
|
|
|
r_core_anal_fcn_list (core, NULL, "o");
|
2015-05-31 21:46:32 +00:00
|
|
|
break;
|
2015-01-31 18:24:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-09-01 08:33:28 +00:00
|
|
|
case 's': // "afs"
|
|
|
|
{
|
2015-12-16 13:35:56 +00:00
|
|
|
ut64 addr;
|
|
|
|
RAnalFunction *f;
|
|
|
|
const char *arg = input + 3;
|
|
|
|
if (input[2] && (addr = r_num_math (core->num, arg))) {
|
|
|
|
arg = strchr (arg, ' ');
|
2016-11-24 00:56:49 +00:00
|
|
|
if (arg) {
|
|
|
|
arg++;
|
|
|
|
}
|
2017-08-23 14:45:05 +00:00
|
|
|
} else {
|
|
|
|
addr = core->offset;
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
if ((f = r_anal_get_fcn_in (core->anal, addr, R_ANAL_FCN_TYPE_NULL))) {
|
|
|
|
if (arg && *arg) {
|
|
|
|
r_anal_str_to_fcn (core->anal, f, arg);
|
|
|
|
} else {
|
|
|
|
char *str = r_anal_fcn_to_string (core->anal, f);
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_println (str);
|
2015-12-16 13:35:56 +00:00
|
|
|
free (str);
|
|
|
|
}
|
2016-03-21 15:41:18 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("No function defined at 0x%08" PFMT64x "\n", addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2014-11-15 01:07:08 +00:00
|
|
|
case 'm': // "afm" - merge two functions
|
2016-03-21 15:41:18 +00:00
|
|
|
r_core_anal_fcn_merge (core, core->offset, r_num_math (core->num, input + 2));
|
2014-11-15 01:07:08 +00:00
|
|
|
break;
|
2016-04-15 17:39:04 +00:00
|
|
|
case 'M': // "afM" - print functions map
|
|
|
|
r_core_anal_fmap (core, input + 1);
|
|
|
|
break;
|
2014-10-28 16:24:01 +00:00
|
|
|
case 'v': // "afv"
|
2016-07-01 14:15:29 +00:00
|
|
|
var_cmd (core, input + 2);
|
2015-12-16 13:35:56 +00:00
|
|
|
break;
|
2016-08-13 10:09:14 +00:00
|
|
|
case 't': // "aft"
|
|
|
|
type_cmd (core, input + 2);
|
|
|
|
break;
|
2017-08-14 17:09:36 +00:00
|
|
|
case 'C': // "afC"
|
2017-01-10 00:30:24 +00:00
|
|
|
if (input[2] == 'c') {
|
|
|
|
RAnalFunction *fcn;
|
|
|
|
if ((fcn = r_anal_get_fcn_in (core->anal, core->offset, 0)) != NULL) {
|
|
|
|
r_cons_printf ("%i\n", r_anal_fcn_cc (fcn));
|
|
|
|
} else {
|
|
|
|
eprintf ("Error: Cannot find function at 0x08%" PFMT64x "\n", core->offset);
|
|
|
|
}
|
2017-11-24 13:22:29 +00:00
|
|
|
} else if (input[2] == 'l') {
|
|
|
|
RAnalFunction *fcn;
|
|
|
|
if ((fcn = r_anal_get_fcn_in (core->anal, core->offset, 0)) != NULL) {
|
|
|
|
r_cons_printf ("%d\n", r_anal_fcn_loops (fcn));
|
|
|
|
} else {
|
|
|
|
eprintf ("Error: Cannot find function at 0x08%" PFMT64x "\n", core->offset);
|
|
|
|
}
|
2017-01-10 00:30:24 +00:00
|
|
|
} else if (input[2] == '?') {
|
2017-08-18 13:04:48 +00:00
|
|
|
r_core_cmd_help (core, help_msg_afC);
|
2017-01-10 00:30:24 +00:00
|
|
|
} else {
|
2017-08-14 17:09:36 +00:00
|
|
|
afCc (core, input + 3);
|
2016-03-21 15:41:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-08-14 17:09:36 +00:00
|
|
|
case 'c':{ // "afc"
|
2016-04-21 19:19:01 +00:00
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
|
2018-05-11 13:27:31 +00:00
|
|
|
if (!fcn && !(input[2] == '?'|| input[2] == 'l' || input[2] == 'o' || input[2] == 'f')) {
|
2016-08-07 15:14:14 +00:00
|
|
|
eprintf ("Cannot find function here\n");
|
2016-04-21 19:19:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (input[2]) {
|
2017-09-01 08:33:28 +00:00
|
|
|
case '\0': // "afc"
|
|
|
|
r_cons_println (fcn->cc);
|
|
|
|
break;
|
|
|
|
case ' ': { // "afc "
|
2018-01-08 02:22:26 +00:00
|
|
|
char *cc = r_str_trim (strdup (input + 3));
|
2017-09-01 08:33:28 +00:00
|
|
|
if (!r_anal_cc_exist (core->anal, cc)) {
|
|
|
|
eprintf ("Unknown calling convention '%s'\n"
|
|
|
|
"See afcl for available types\n", cc);
|
|
|
|
} else {
|
|
|
|
fcn->cc = r_str_const (r_anal_cc_to_constant (core->anal, cc));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2018-05-11 13:27:31 +00:00
|
|
|
case 'a': // "afca"
|
2017-09-01 08:33:28 +00:00
|
|
|
eprintf ("Todo\n");
|
|
|
|
break;
|
2018-05-11 13:27:31 +00:00
|
|
|
case 'f': { // "afcf"
|
|
|
|
const char *fcn_name = r_str_trim (strdup (input + 3));
|
|
|
|
char *key = NULL;
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalFuncArg *arg;
|
|
|
|
if (fcn && !*fcn_name) {
|
|
|
|
fcn_name = fcn->name;
|
|
|
|
}
|
|
|
|
if (fcn_name) {
|
|
|
|
key = resolve_fcn_name (core->anal, fcn_name);
|
|
|
|
}
|
|
|
|
if (key) {
|
|
|
|
const char *fcn_type = r_anal_type_func_ret (core->anal, key);
|
|
|
|
int nargs = r_anal_type_func_args_count (core->anal, key);
|
|
|
|
if (fcn_type) {
|
|
|
|
char *sp = " ";
|
|
|
|
if (*fcn_type && (fcn_type[strlen (fcn_type) - 1] == '*')) {
|
|
|
|
sp = "";
|
|
|
|
}
|
|
|
|
r_cons_printf ("%s%s%s(", r_str_get (fcn_type), sp, r_str_get (key));
|
|
|
|
if (!nargs) {
|
|
|
|
r_cons_println ("void)");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
RList *list = r_core_get_func_args (core, fcn_name);
|
|
|
|
r_list_foreach (list, iter, arg) {
|
|
|
|
RListIter *nextele = r_list_iter_get_next (iter);
|
|
|
|
char *type = arg->orig_c_type;
|
|
|
|
char *sp1 = " ";
|
|
|
|
if (*type && (type[strlen (type) - 1] == '*')) {
|
|
|
|
sp1 = "";
|
|
|
|
}
|
|
|
|
r_cons_printf ("%s%s%s%s", type, sp1, arg->name, nextele?", ":")");
|
|
|
|
}
|
|
|
|
r_cons_println ("");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2017-09-01 08:33:28 +00:00
|
|
|
case 'l': // "afcl" list all function Calling conventions.
|
|
|
|
sdb_foreach (core->anal->sdb_cc, cc_print, NULL);
|
|
|
|
break;
|
|
|
|
case 'o': { // "afco"
|
2018-01-08 02:22:26 +00:00
|
|
|
char *dbpath = r_str_trim (strdup (input + 3));
|
2016-07-27 11:50:14 +00:00
|
|
|
if (r_file_exists (dbpath)) {
|
|
|
|
Sdb *db = sdb_new (0, dbpath, 0);
|
|
|
|
sdb_merge (core->anal->sdb_cc, db);
|
|
|
|
sdb_close (db);
|
|
|
|
sdb_free (db);
|
|
|
|
}
|
2016-08-01 12:46:17 +00:00
|
|
|
free (dbpath);
|
2016-07-27 11:50:14 +00:00
|
|
|
break;
|
2017-09-01 08:33:28 +00:00
|
|
|
}
|
|
|
|
case 'r': { // "afcr"
|
2017-08-14 17:09:36 +00:00
|
|
|
int i;
|
|
|
|
char *out, *cmd, *regname, *tmp;
|
|
|
|
char *subvec_str = r_str_new ("");
|
|
|
|
char *json_str = r_str_new ("");
|
2017-08-18 12:31:56 +00:00
|
|
|
// if json_str initialize to NULL, it's possible for afcrj to output a (NULL)
|
2017-08-14 17:09:36 +00:00
|
|
|
// subvec_str and json_str should be valid until exiting this code block
|
|
|
|
bool json = input[3] == 'j'? true: false;
|
|
|
|
for (i = 0; i <= 11; i++) {
|
|
|
|
if (i == 0) {
|
|
|
|
cmd = r_str_newf ("cc.%s.ret", fcn->cc);
|
|
|
|
} else {
|
|
|
|
cmd = r_str_newf ("cc.%s.arg%d", fcn->cc, i);
|
|
|
|
}
|
|
|
|
if (i < 7) {
|
|
|
|
regname = r_str_new (cmd);
|
|
|
|
} else {
|
|
|
|
regname = r_str_newf ("cc.%s.float_arg%d", fcn->cc, i - 6);
|
|
|
|
}
|
|
|
|
out = sdb_querys (core->anal->sdb_cc, NULL, 0, cmd);
|
|
|
|
free (cmd);
|
|
|
|
if (out) {
|
|
|
|
out[strlen (out) - 1] = 0;
|
|
|
|
if (json) {
|
|
|
|
tmp = subvec_str;
|
|
|
|
subvec_str = r_str_newf ("%s,\"%s\"", subvec_str, out);
|
|
|
|
free (tmp);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%s: %s\n", regname, out);
|
|
|
|
}
|
|
|
|
free (out);
|
|
|
|
}
|
|
|
|
free (regname);
|
|
|
|
if (!subvec_str[0]) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
switch (i) {
|
|
|
|
case 0: {
|
|
|
|
tmp = json_str;
|
|
|
|
json_str = r_str_newf ("%s,\"ret\":%s", json_str, subvec_str + 1);
|
|
|
|
free (tmp);
|
|
|
|
} break;
|
|
|
|
case 6: {
|
|
|
|
tmp = json_str;
|
|
|
|
json_str = r_str_newf ("%s,\"args\":[%s]", json_str, subvec_str + 1);
|
|
|
|
free (tmp);
|
|
|
|
} break;
|
|
|
|
case 11: {
|
|
|
|
tmp = json_str;
|
|
|
|
json_str = r_str_newf ("%s,\"float_args\":[%s]", json_str, subvec_str + 1);
|
|
|
|
free (tmp);
|
|
|
|
} break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
free (subvec_str);
|
|
|
|
subvec_str = r_str_new ("");
|
|
|
|
}
|
|
|
|
if (json && json_str[0]) {
|
|
|
|
r_cons_printf ("{%s}\n", json_str + 1);
|
|
|
|
}
|
|
|
|
free (subvec_str);
|
|
|
|
free (json_str);
|
|
|
|
} break;
|
2017-09-01 08:33:28 +00:00
|
|
|
case '?': // "afc?"
|
2016-04-21 19:19:01 +00:00
|
|
|
default:
|
2017-09-01 08:33:28 +00:00
|
|
|
r_core_cmd_help (core, help_msg_afc);
|
2014-10-14 15:09:42 +00:00
|
|
|
}
|
2016-04-21 19:19:01 +00:00
|
|
|
}break;
|
2015-01-29 12:41:38 +00:00
|
|
|
case 'B': // "afB" // set function bits
|
|
|
|
if (input[2] == ' ') {
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset,
|
2016-09-14 14:42:23 +00:00
|
|
|
R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
|
|
|
if (fcn) {
|
2017-01-19 20:44:48 +00:00
|
|
|
int bits = atoi (input + 3);
|
|
|
|
r_anal_hint_set_bits (core->anal, fcn->addr, bits);
|
|
|
|
r_anal_hint_set_bits (core->anal,
|
|
|
|
fcn->addr + r_anal_fcn_size (fcn),
|
|
|
|
core->anal->bits);
|
|
|
|
fcn->bits = bits;
|
2016-09-14 14:42:23 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Cannot find function to set bits\n");
|
|
|
|
}
|
2015-01-29 12:41:38 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Usage: afB [bits]\n");
|
|
|
|
}
|
|
|
|
break;
|
2014-10-28 16:24:01 +00:00
|
|
|
case 'b': // "afb"
|
2014-11-13 10:17:43 +00:00
|
|
|
switch (input[2]) {
|
2017-09-01 08:33:28 +00:00
|
|
|
case '-': // "afb-"
|
2016-12-29 02:34:16 +00:00
|
|
|
anal_fcn_del_bb (core, input + 3);
|
|
|
|
break;
|
2017-09-01 08:33:28 +00:00
|
|
|
case 'e': // "afbe"
|
2016-12-29 02:34:16 +00:00
|
|
|
anal_bb_edge (core, input + 3);
|
2016-01-25 16:28:56 +00:00
|
|
|
break;
|
2016-01-25 18:19:01 +00:00
|
|
|
case 0:
|
2017-09-01 08:33:28 +00:00
|
|
|
case ' ': // "afb "
|
|
|
|
case 'q': // "afbq"
|
|
|
|
case 'r': // "afbr"
|
|
|
|
case '*': // "afb*"
|
2017-07-17 10:58:48 +00:00
|
|
|
case 'j': // "afbj"
|
2017-04-26 11:35:03 +00:00
|
|
|
anal_fcn_list_bb (core, input + 2, false);
|
|
|
|
break;
|
2017-09-12 14:12:05 +00:00
|
|
|
case 'i': // "afbi"
|
|
|
|
anal_fcn_list_bb (core, input + 2, true);
|
|
|
|
break;
|
2017-09-01 08:33:28 +00:00
|
|
|
case '.': // "afb."
|
2017-04-26 11:35:03 +00:00
|
|
|
anal_fcn_list_bb (core, input[2]? " $$": input + 2, true);
|
2015-01-29 12:33:33 +00:00
|
|
|
break;
|
2014-11-13 10:17:43 +00:00
|
|
|
case '+': // "afb+"
|
2015-12-16 13:35:56 +00:00
|
|
|
anal_fcn_add_bb (core, input + 3);
|
2014-11-13 10:17:43 +00:00
|
|
|
break;
|
2015-01-29 12:33:33 +00:00
|
|
|
default:
|
|
|
|
case '?':
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_afb);
|
2015-01-29 12:33:33 +00:00
|
|
|
break;
|
2014-11-13 10:17:43 +00:00
|
|
|
}
|
|
|
|
break;
|
2014-10-28 16:24:01 +00:00
|
|
|
case 'n': // "afn"
|
2015-07-06 09:30:35 +00:00
|
|
|
switch (input[2]) {
|
2017-09-01 08:33:28 +00:00
|
|
|
case 's': // "afns"
|
2015-07-06 09:30:35 +00:00
|
|
|
free (r_core_anal_fcn_autoname (core, core->offset, 1));
|
|
|
|
break;
|
2017-09-01 08:33:28 +00:00
|
|
|
case 'a': // "afna"
|
2016-03-21 15:41:18 +00:00
|
|
|
{
|
2015-07-06 09:30:35 +00:00
|
|
|
char *name = r_core_anal_fcn_autoname (core, core->offset, 0);
|
2014-09-12 01:17:02 +00:00
|
|
|
if (name) {
|
2016-03-24 19:39:19 +00:00
|
|
|
r_cons_printf ("afn %s 0x%08" PFMT64x "\n", name, core->offset);
|
2014-09-12 01:17:02 +00:00
|
|
|
free (name);
|
|
|
|
}
|
2016-03-21 15:41:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-09-01 08:33:28 +00:00
|
|
|
case 0: // "afn"
|
2016-08-19 12:15:10 +00:00
|
|
|
{
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, -1);
|
|
|
|
if (fcn) {
|
|
|
|
r_cons_printf ("%s\n", fcn->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2017-09-01 08:33:28 +00:00
|
|
|
case ' ': // "afn "
|
2016-03-21 15:41:18 +00:00
|
|
|
{
|
2015-07-06 09:30:35 +00:00
|
|
|
ut64 off = core->offset;
|
2015-12-16 13:35:56 +00:00
|
|
|
char *p, *name = strdup (input + 3);
|
|
|
|
if ((p = strchr (name, ' '))) {
|
2015-07-06 09:30:35 +00:00
|
|
|
*p++ = 0;
|
|
|
|
off = r_num_math (core->num, p);
|
|
|
|
}
|
|
|
|
if (*name) {
|
2016-05-23 23:47:09 +00:00
|
|
|
if (!setFunctionName (core, off, name, false)) {
|
2015-12-16 13:35:56 +00:00
|
|
|
eprintf ("Cannot find function '%s' at 0x%08" PFMT64x "\n", name, off);
|
2016-05-23 23:47:09 +00:00
|
|
|
}
|
2015-07-06 09:30:35 +00:00
|
|
|
free (name);
|
|
|
|
} else {
|
|
|
|
eprintf ("Usage: afn newname [off] # set new name to given function\n");
|
|
|
|
free (name);
|
|
|
|
}
|
2016-03-21 15:41:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-02-20 11:15:58 +00:00
|
|
|
default:
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_afn);
|
2016-08-19 12:13:57 +00:00
|
|
|
break;
|
2015-12-16 13:35:56 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-09-01 08:33:28 +00:00
|
|
|
case 'S': // afS"
|
2016-10-14 19:54:00 +00:00
|
|
|
{
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, -1);
|
|
|
|
if (fcn) {
|
|
|
|
fcn->maxstack = r_num_math (core->num, input + 3);
|
2017-03-09 12:23:41 +00:00
|
|
|
//fcn->stack = fcn->maxstack;
|
2016-10-14 19:54:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2016-05-01 12:48:04 +00:00
|
|
|
#if 0
|
2015-12-16 13:35:56 +00:00
|
|
|
/* this is undocumented and probably have no uses. plz discuss */
|
2014-10-28 16:24:01 +00:00
|
|
|
case 'e': // "afe"
|
2016-03-21 15:41:18 +00:00
|
|
|
{
|
2015-12-16 13:35:56 +00:00
|
|
|
RAnalFunction *fcn;
|
|
|
|
ut64 off = core->offset;
|
2016-03-06 22:31:21 +00:00
|
|
|
char *p, *name = strdup ((input[2]&&input[3])? input + 3: "");
|
2015-12-16 13:35:56 +00:00
|
|
|
if ((p = strchr (name, ' '))) {
|
|
|
|
*p = 0;
|
|
|
|
off = r_num_math (core->num, p + 1);
|
|
|
|
}
|
2016-03-21 15:41:18 +00:00
|
|
|
fcn = r_anal_get_fcn_in (core->anal, off, R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
2015-12-16 13:35:56 +00:00
|
|
|
if (fcn) {
|
|
|
|
RAnalBlock *b;
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalRef *r;
|
|
|
|
r_list_foreach (fcn->refs, iter, r) {
|
|
|
|
r_cons_printf ("0x%08" PFMT64x " -%c 0x%08" PFMT64x "\n", r->at, r->type, r->addr);
|
|
|
|
}
|
|
|
|
r_list_foreach (fcn->bbs, iter, b) {
|
|
|
|
int ok = 0;
|
|
|
|
if (b->type == R_ANAL_BB_TYPE_LAST) ok = 1;
|
|
|
|
if (b->type == R_ANAL_BB_TYPE_FOOT) ok = 1;
|
|
|
|
if (b->jump == UT64_MAX && b->fail == UT64_MAX) ok = 1;
|
|
|
|
if (ok) {
|
|
|
|
r_cons_printf ("0x%08" PFMT64x " -r\n", b->addr);
|
|
|
|
// TODO: check if destination is outside the function boundaries
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else eprintf ("Cannot find function at 0x%08" PFMT64x "\n", core->offset);
|
|
|
|
free (name);
|
2016-03-21 15:41:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2014-09-22 22:40:35 +00:00
|
|
|
#endif
|
2017-09-01 08:33:28 +00:00
|
|
|
case 'x': // "afx"
|
2015-12-16 13:35:56 +00:00
|
|
|
switch (input[2]) {
|
2017-09-01 08:33:28 +00:00
|
|
|
case '\0': // "afx"
|
2018-04-02 02:16:42 +00:00
|
|
|
case 'j': // "afxj"
|
2017-09-01 08:33:28 +00:00
|
|
|
case ' ': // "afx "
|
2018-04-02 02:16:42 +00:00
|
|
|
if (input[2] == 'j') {
|
|
|
|
r_cons_printf ("[");
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
// list xrefs from current address
|
|
|
|
{
|
2018-04-02 02:16:42 +00:00
|
|
|
ut64 addr = input[2]==' '? r_num_math (core->num, input + 2): core->offset;
|
2015-12-16 13:35:56 +00:00
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, R_ANAL_FCN_TYPE_NULL);
|
|
|
|
if (fcn) {
|
|
|
|
RAnalRef *ref;
|
|
|
|
RListIter *iter;
|
2018-02-09 21:25:30 +00:00
|
|
|
RList *refs = r_anal_fcn_get_refs_sorted (core->anal, fcn);
|
2018-01-09 19:38:08 +00:00
|
|
|
r_list_foreach (refs, iter, ref) {
|
2018-04-02 02:16:42 +00:00
|
|
|
if (input[2] == 'j') {
|
|
|
|
r_cons_printf ("{\"type\":\"%c\",\"from\":%"PFMT64d",\"to\":%"PFMT64d"}%s",
|
|
|
|
ref->type, ref->at, ref->addr, iter->n? ",": "");
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%c 0x%08" PFMT64x " -> 0x%08" PFMT64x "\n",
|
|
|
|
ref->type, ref->at, ref->addr);
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
}
|
2018-01-09 19:38:08 +00:00
|
|
|
r_list_free (refs);
|
2018-04-02 02:16:42 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Cannot find function at 0x%08"PFMT64x"\n", addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (input[2] == 'j') {
|
|
|
|
r_cons_printf ("]\n");
|
2015-12-16 13:35:56 +00:00
|
|
|
}
|
2016-03-21 15:41:18 +00:00
|
|
|
break;
|
2015-12-16 13:35:56 +00:00
|
|
|
default:
|
2018-05-08 06:41:53 +00:00
|
|
|
eprintf ("Wrong command. Look at af?\n");
|
2016-03-21 15:41:18 +00:00
|
|
|
break;
|
2015-12-14 09:19:07 +00:00
|
|
|
}
|
|
|
|
break;
|
2015-12-16 13:35:56 +00:00
|
|
|
case 'F': // "afF"
|
2016-03-21 15:41:18 +00:00
|
|
|
{
|
2017-07-28 13:06:06 +00:00
|
|
|
int val = input[2] && r_num_math (core->num, input + 2);
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_NULL);
|
|
|
|
if (fcn) {
|
|
|
|
fcn->folded = input[2]? val: !fcn->folded;
|
|
|
|
}
|
2016-03-21 15:41:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-09-01 08:33:28 +00:00
|
|
|
case '?': // "af?"
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_af);
|
2016-03-21 15:41:18 +00:00
|
|
|
break;
|
2015-07-27 21:56:11 +00:00
|
|
|
case 'r': // "afr" // analyze function recursively
|
2017-09-01 08:33:28 +00:00
|
|
|
case ' ': // "af "
|
|
|
|
case '\0': // "af"
|
2016-08-24 14:45:55 +00:00
|
|
|
{
|
2015-12-16 13:35:56 +00:00
|
|
|
char *uaddr = NULL, *name = NULL;
|
|
|
|
int depth = r_config_get_i (core->config, "anal.depth");
|
2016-03-15 10:28:56 +00:00
|
|
|
bool analyze_recursively = r_config_get_i (core->config, "anal.calls");
|
2015-12-16 13:35:56 +00:00
|
|
|
RAnalFunction *fcn;
|
|
|
|
ut64 addr = core->offset;
|
|
|
|
if (input[1] == 'r') {
|
|
|
|
input++;
|
|
|
|
analyze_recursively = true;
|
|
|
|
}
|
2014-11-08 00:03:04 +00:00
|
|
|
|
2015-12-16 13:35:56 +00:00
|
|
|
// first undefine
|
|
|
|
if (input[0] && input[1] == ' ') {
|
|
|
|
name = strdup (input + 2);
|
|
|
|
uaddr = strchr (name, ' ');
|
|
|
|
if (uaddr) {
|
|
|
|
*uaddr++ = 0;
|
|
|
|
addr = r_num_math (core->num, uaddr);
|
2014-11-08 00:03:04 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
// depth = 1; // or 1?
|
|
|
|
// disable hasnext
|
|
|
|
}
|
2016-04-27 23:38:11 +00:00
|
|
|
|
2015-12-16 13:35:56 +00:00
|
|
|
//r_core_anal_undefine (core, core->offset);
|
2016-03-21 15:41:18 +00:00
|
|
|
r_core_anal_fcn (core, addr, UT64_MAX, R_ANAL_REF_TYPE_NULL, depth);
|
2016-09-03 12:57:59 +00:00
|
|
|
fcn = r_anal_get_fcn_in (core->anal, addr, 0);
|
|
|
|
if (fcn && r_config_get_i (core->config, "anal.vars")) {
|
2016-09-03 12:53:34 +00:00
|
|
|
fcn_callconv (core, fcn);
|
|
|
|
}
|
2016-09-03 12:57:59 +00:00
|
|
|
if (fcn) {
|
|
|
|
/* ensure we use a proper name */
|
|
|
|
setFunctionName (core, addr, fcn->name, false);
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
if (analyze_recursively) {
|
|
|
|
fcn = r_anal_get_fcn_in (core->anal, addr, 0); /// XXX wrong in case of nopskip
|
|
|
|
if (fcn) {
|
|
|
|
RAnalRef *ref;
|
|
|
|
RListIter *iter;
|
2018-02-09 21:25:30 +00:00
|
|
|
RList *refs = r_anal_fcn_get_refs_sorted (core->anal, fcn);
|
2018-01-09 19:38:08 +00:00
|
|
|
r_list_foreach (refs, iter, ref) {
|
2016-08-07 08:17:05 +00:00
|
|
|
if (ref->addr == UT64_MAX) {
|
2016-08-04 20:52:33 +00:00
|
|
|
//eprintf ("Warning: ignore 0x%08"PFMT64x" call 0x%08"PFMT64x"\n", ref->at, ref->addr);
|
2015-12-16 13:35:56 +00:00
|
|
|
continue;
|
2016-03-15 10:28:56 +00:00
|
|
|
}
|
2018-05-08 06:41:53 +00:00
|
|
|
if (ref->type != R_ANAL_REF_TYPE_CODE && ref->type != R_ANAL_REF_TYPE_CALL) {
|
2016-08-07 12:07:52 +00:00
|
|
|
/* only follow code/call references */
|
|
|
|
continue;
|
|
|
|
}
|
2017-12-08 02:19:08 +00:00
|
|
|
if (!r_io_is_valid_offset (core->io, ref->addr, !core->anal->opt.noncode)) {
|
2016-08-07 08:17:05 +00:00
|
|
|
continue;
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
r_core_anal_fcn (core, ref->addr, fcn->addr, R_ANAL_REF_TYPE_CALL, depth);
|
2016-08-07 12:07:52 +00:00
|
|
|
/* use recursivity here */
|
|
|
|
#if 1
|
2016-08-07 08:17:05 +00:00
|
|
|
RAnalFunction *f = r_anal_get_fcn_at (core->anal, ref->addr, 0);
|
|
|
|
if (f) {
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalRef *ref;
|
2018-02-09 21:25:30 +00:00
|
|
|
RList *refs1 = r_anal_fcn_get_refs_sorted (core->anal, f);
|
2018-01-09 19:38:08 +00:00
|
|
|
r_list_foreach (refs1, iter, ref) {
|
2017-12-08 02:19:08 +00:00
|
|
|
if (!r_io_is_valid_offset (core->io, ref->addr, !core->anal->opt.noncode)) {
|
2016-08-07 12:07:52 +00:00
|
|
|
continue;
|
|
|
|
}
|
2017-12-08 02:19:08 +00:00
|
|
|
if (ref->type != 'c' && ref->type != 'C') {
|
|
|
|
continue;
|
2018-03-12 12:10:59 +00:00
|
|
|
}
|
2016-08-07 08:17:05 +00:00
|
|
|
r_core_anal_fcn (core, ref->addr, f->addr, R_ANAL_REF_TYPE_CALL, depth);
|
|
|
|
// recursively follow fcn->refs again and again
|
|
|
|
}
|
2018-01-09 19:38:08 +00:00
|
|
|
r_list_free (refs1);
|
2016-08-07 08:17:05 +00:00
|
|
|
} else {
|
2015-12-16 13:35:56 +00:00
|
|
|
f = r_anal_get_fcn_in (core->anal, fcn->addr, 0);
|
|
|
|
if (f) {
|
|
|
|
/* cut function */
|
2018-03-17 13:09:13 +00:00
|
|
|
r_anal_fcn_resize (core->anal, f, addr - fcn->addr);
|
2015-12-16 13:35:56 +00:00
|
|
|
r_core_anal_fcn (core, ref->addr, fcn->addr,
|
2015-09-06 22:30:48 +00:00
|
|
|
R_ANAL_REF_TYPE_CALL, depth);
|
2015-12-16 13:35:56 +00:00
|
|
|
f = r_anal_get_fcn_at (core->anal, fcn->addr, 0);
|
|
|
|
}
|
|
|
|
if (!f) {
|
|
|
|
eprintf ("Cannot find function at 0x%08" PFMT64x "\n", fcn->addr);
|
2015-07-27 21:56:11 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-07 12:07:52 +00:00
|
|
|
#endif
|
2015-07-27 21:56:11 +00:00
|
|
|
}
|
2018-01-09 19:38:08 +00:00
|
|
|
r_list_free (refs);
|
2015-07-27 21:56:11 +00:00
|
|
|
}
|
2014-09-22 13:00:41 +00:00
|
|
|
}
|
2016-04-27 23:38:11 +00:00
|
|
|
|
2015-12-16 13:35:56 +00:00
|
|
|
if (name) {
|
2017-02-06 20:58:01 +00:00
|
|
|
if (*name && !setFunctionName (core, addr, name, true)) {
|
2017-08-29 11:27:24 +00:00
|
|
|
eprintf ("Cannot find function '%s' at 0x%08" PFMT64x "\n", name, (ut64)addr);
|
2017-02-06 20:58:01 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
free (name);
|
|
|
|
}
|
|
|
|
flag_every_function (core);
|
|
|
|
}
|
2016-08-24 14:45:55 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
break;
|
2014-01-23 01:31:51 +00:00
|
|
|
}
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2014-01-23 01:31:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-11 23:53:52 +00:00
|
|
|
// size: 0: bits; -1: any; >0: exact size
|
|
|
|
static void __anal_reg_list(RCore *core, int type, int bits, char mode) {
|
2014-05-25 01:00:24 +00:00
|
|
|
RReg *hack = core->dbg->reg;
|
2014-06-04 20:58:22 +00:00
|
|
|
const char *use_color;
|
2015-12-16 13:35:56 +00:00
|
|
|
int use_colors = r_config_get_i (core->config, "scr.color");
|
2014-06-04 20:58:22 +00:00
|
|
|
if (use_colors) {
|
|
|
|
#undef ConsP
|
|
|
|
#define ConsP(x) (core->cons && core->cons->pal.x)? core->cons->pal.x
|
2017-08-24 11:31:27 +00:00
|
|
|
use_color = ConsP (creg) : Color_BWHITE;
|
2014-06-04 20:58:22 +00:00
|
|
|
} else {
|
|
|
|
use_color = NULL;
|
|
|
|
}
|
2017-09-11 23:53:52 +00:00
|
|
|
if (bits < 0) {
|
|
|
|
// TODO Change the `size` argument of r_debug_reg_list to use -1 for any and 0 for anal->bits
|
|
|
|
bits = 0;
|
|
|
|
} else if (!bits) {
|
|
|
|
bits = core->anal->bits;
|
|
|
|
}
|
2017-08-24 11:31:27 +00:00
|
|
|
if (core->anal) {
|
|
|
|
core->dbg->reg = core->anal->reg;
|
|
|
|
if (core->anal->cur && core->anal->cur->arch) {
|
|
|
|
/* workaround for thumb */
|
|
|
|
if (!strcmp (core->anal->cur->arch, "arm") && bits == 16) {
|
|
|
|
bits = 32;
|
|
|
|
}
|
|
|
|
/* workaround for 6502 */
|
|
|
|
if (!strcmp (core->anal->cur->arch, "6502") && bits == 8) {
|
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 16, mode, use_color); // XXX detect which one is current usage
|
|
|
|
}
|
|
|
|
if (!strcmp (core->anal->cur->arch, "avr") && bits == 8) {
|
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 16, mode, use_color); // XXX detect which one is current usage
|
|
|
|
}
|
2017-02-02 13:02:12 +00:00
|
|
|
}
|
2016-03-13 22:56:23 +00:00
|
|
|
}
|
2017-08-24 11:31:27 +00:00
|
|
|
|
2015-10-14 20:12:58 +00:00
|
|
|
if (mode == '=') {
|
2015-10-14 00:50:08 +00:00
|
|
|
int pcbits = 0;
|
|
|
|
const char *pcname = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
|
|
|
|
RRegItem *reg = r_reg_get (core->anal->reg, pcname, 0);
|
2016-05-11 13:38:26 +00:00
|
|
|
if (bits != reg->size) {
|
2015-10-14 00:50:08 +00:00
|
|
|
pcbits = reg->size;
|
2016-05-11 13:38:26 +00:00
|
|
|
}
|
|
|
|
if (pcbits) {
|
2015-10-14 00:50:08 +00:00
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, pcbits, 2, use_color); // XXX detect which one is current usage
|
2016-05-11 13:38:26 +00:00
|
|
|
}
|
2015-10-14 00:50:08 +00:00
|
|
|
}
|
2014-06-04 20:58:22 +00:00
|
|
|
r_debug_reg_list (core->dbg, type, bits, mode, use_color);
|
2014-05-25 01:00:24 +00:00
|
|
|
core->dbg->reg = hack;
|
|
|
|
}
|
|
|
|
|
2015-11-18 10:29:48 +00:00
|
|
|
// XXX dup from drp :OOO
|
2016-11-15 00:12:37 +00:00
|
|
|
void cmd_anal_reg(RCore *core, const char *str) {
|
2014-05-26 01:06:29 +00:00
|
|
|
int size = 0, i, type = R_REG_TYPE_GPR;
|
2014-05-25 01:00:24 +00:00
|
|
|
int bits = (core->anal->bits & R_SYS_BITS_64)? 64: 32;
|
2015-12-16 13:35:56 +00:00
|
|
|
int use_colors = r_config_get_i (core->config, "scr.color");
|
2014-06-16 03:58:00 +00:00
|
|
|
struct r_reg_item_t *r;
|
2014-06-04 20:58:22 +00:00
|
|
|
const char *use_color;
|
2014-06-16 03:58:00 +00:00
|
|
|
const char *name;
|
|
|
|
char *arg;
|
|
|
|
|
2014-06-04 20:58:22 +00:00
|
|
|
if (use_colors) {
|
|
|
|
#define ConsP(x) (core->cons && core->cons->pal.x)? core->cons->pal.x
|
2015-12-16 13:35:56 +00:00
|
|
|
use_color = ConsP (creg)
|
|
|
|
: Color_BWHITE;
|
2014-06-04 20:58:22 +00:00
|
|
|
} else {
|
|
|
|
use_color = NULL;
|
|
|
|
}
|
2014-05-25 01:00:24 +00:00
|
|
|
switch (str[0]) {
|
2015-11-23 23:58:03 +00:00
|
|
|
case 'l': // "arl"
|
2015-12-16 13:35:56 +00:00
|
|
|
{
|
|
|
|
RRegSet *rs = r_reg_regset_get (core->anal->reg, R_REG_TYPE_GPR);
|
|
|
|
if (rs) {
|
|
|
|
RRegItem *r;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (rs->regs, iter, r) {
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_println (r->name);
|
2014-10-15 00:24:22 +00:00
|
|
|
}
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
} break;
|
2016-03-22 06:32:40 +00:00
|
|
|
case '0': // "ar0"
|
2014-06-19 02:52:28 +00:00
|
|
|
r_reg_arena_zero (core->anal->reg);
|
|
|
|
break;
|
2016-03-22 06:32:40 +00:00
|
|
|
case 'C': // "arC"
|
2016-01-09 02:14:18 +00:00
|
|
|
if (core->anal->reg->reg_profile_cmt) {
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_println (core->anal->reg->reg_profile_cmt);
|
2016-01-09 02:14:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case 'w': // "arw"
|
2016-03-29 18:56:43 +00:00
|
|
|
switch (str[1]) {
|
|
|
|
case '?': {
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_arw);
|
2016-03-29 18:56:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ' ':
|
|
|
|
r_reg_arena_set_bytes (core->anal->reg, str + 1);
|
|
|
|
break;
|
|
|
|
default:
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_arw);
|
2016-03-29 18:56:43 +00:00
|
|
|
break;
|
|
|
|
}
|
2016-08-16 15:35:33 +00:00
|
|
|
break;
|
2015-11-23 23:58:03 +00:00
|
|
|
case 'a': // "ara"
|
|
|
|
switch (str[1]) {
|
2017-09-11 23:53:52 +00:00
|
|
|
case '?': // "ara?"
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_ara);
|
2015-11-25 14:20:25 +00:00
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case 's': // "aras"
|
2015-11-25 14:20:25 +00:00
|
|
|
r_reg_arena_swap (core->anal->reg, false);
|
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case '+': // "ara+"
|
2015-11-23 23:58:03 +00:00
|
|
|
r_reg_arena_push (core->anal->reg);
|
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case '-': // "ara-"
|
2015-11-23 23:58:03 +00:00
|
|
|
r_reg_arena_pop (core->anal->reg);
|
|
|
|
break;
|
2015-12-16 13:35:56 +00:00
|
|
|
default: {
|
|
|
|
int i, j;
|
|
|
|
RRegArena *a;
|
|
|
|
RListIter *iter;
|
|
|
|
for (i = 0; i < R_REG_TYPE_LAST; i++) {
|
|
|
|
RRegSet *rs = &core->anal->reg->regset[i];
|
|
|
|
j = 0;
|
|
|
|
r_list_foreach (rs->pool, iter, a) {
|
|
|
|
r_cons_printf ("%s %p %d %d %s %d\n",
|
|
|
|
(a == rs->arena)? "*": ".", a,
|
|
|
|
i, j, r_reg_get_type (i), a->size);
|
|
|
|
j++;
|
2015-11-23 23:58:03 +00:00
|
|
|
}
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
} break;
|
2015-11-23 23:58:03 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case '?': // "ar?"
|
2014-05-25 01:00:24 +00:00
|
|
|
if (str[1]) {
|
2015-12-16 13:35:56 +00:00
|
|
|
ut64 off = r_reg_getv (core->anal->reg, str + 1);
|
|
|
|
r_cons_printf ("0x%08" PFMT64x "\n", off);
|
2017-07-24 15:41:50 +00:00
|
|
|
} else {
|
|
|
|
r_core_cmd_help (core, help_msg_ar);
|
|
|
|
}
|
2014-05-25 01:00:24 +00:00
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case 'r': // "arr"
|
2015-09-28 00:04:08 +00:00
|
|
|
r_core_debug_rr (core, core->anal->reg);
|
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case 'S': { // "arS"
|
2015-12-16 13:35:56 +00:00
|
|
|
int sz;
|
|
|
|
ut8 *buf = r_reg_get_bytes (
|
|
|
|
core->anal->reg, R_REG_TYPE_GPR, &sz);
|
|
|
|
r_cons_printf ("%d\n", sz);
|
|
|
|
free (buf);
|
2016-11-15 23:28:37 +00:00
|
|
|
} break;
|
2017-08-27 17:07:29 +00:00
|
|
|
case 'b': { // "arb" WORK IN PROGRESS // DEBUG COMMAND
|
2016-11-14 22:58:29 +00:00
|
|
|
int len, type = R_REG_TYPE_GPR;
|
|
|
|
arg = strchr (str, ' ');
|
|
|
|
if (arg) {
|
2018-01-08 02:22:26 +00:00
|
|
|
char *string = r_str_trim (strdup (arg + 1));
|
2016-11-14 22:58:29 +00:00
|
|
|
if (string) {
|
|
|
|
type = r_reg_type_by_name (string);
|
|
|
|
if (type == -1 && string[0] != 'a') {
|
|
|
|
type = R_REG_TYPE_GPR;
|
|
|
|
}
|
|
|
|
free (string);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ut8 *buf = r_reg_get_bytes (core->dbg->reg, type, &len);
|
2017-08-27 17:07:29 +00:00
|
|
|
if (buf) {
|
|
|
|
//r_print_hexdump (core->print, 0LL, buf, len, 16, 16);
|
|
|
|
r_print_hexdump (core->print, 0LL, buf, len, 32, 4, 1);
|
|
|
|
free (buf);
|
|
|
|
}
|
2016-11-15 23:28:37 +00:00
|
|
|
} break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case 'c': // "arc"
|
2014-06-16 03:58:00 +00:00
|
|
|
// TODO: set flag values with drc zf=1
|
2015-12-16 13:35:56 +00:00
|
|
|
{
|
2014-06-16 03:58:00 +00:00
|
|
|
RRegItem *r;
|
2015-12-16 13:35:56 +00:00
|
|
|
const char *name = str + 1;
|
|
|
|
while (*name == ' ') name++;
|
2014-06-16 03:58:00 +00:00
|
|
|
if (*name && name[1]) {
|
|
|
|
r = r_reg_cond_get (core->dbg->reg, name);
|
|
|
|
if (r) {
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_println (r->name);
|
2014-06-16 03:58:00 +00:00
|
|
|
} else {
|
|
|
|
int id = r_reg_cond_from_string (name);
|
2015-12-16 13:35:56 +00:00
|
|
|
RRegFlags *rf = r_reg_cond_retrieve (core->dbg->reg, NULL);
|
2014-06-16 03:58:00 +00:00
|
|
|
if (rf) {
|
|
|
|
int o = r_reg_cond_bits (core->dbg->reg, id, rf);
|
|
|
|
core->num->value = o;
|
|
|
|
// ORLY?
|
|
|
|
r_cons_printf ("%d\n", o);
|
|
|
|
free (rf);
|
2017-01-24 00:41:12 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("unknown conditional or flag register\n");
|
|
|
|
}
|
2014-06-16 03:58:00 +00:00
|
|
|
}
|
2014-05-25 01:00:24 +00:00
|
|
|
} else {
|
2014-06-16 03:58:00 +00:00
|
|
|
RRegFlags *rf = r_reg_cond_retrieve (core->dbg->reg, NULL);
|
2014-05-25 01:00:24 +00:00
|
|
|
if (rf) {
|
2014-06-16 03:58:00 +00:00
|
|
|
r_cons_printf ("| s:%d z:%d c:%d o:%d p:%d\n",
|
|
|
|
rf->s, rf->z, rf->c, rf->o, rf->p);
|
2015-12-16 13:35:56 +00:00
|
|
|
if (*name == '=') {
|
|
|
|
for (i = 0; i < R_REG_COND_LAST; i++) {
|
2014-06-16 03:58:00 +00:00
|
|
|
r_cons_printf ("%s:%d ",
|
|
|
|
r_reg_cond_to_string (i),
|
|
|
|
r_reg_cond_bits (core->dbg->reg, i, rf));
|
|
|
|
}
|
|
|
|
r_cons_newline ();
|
|
|
|
} else {
|
2015-12-16 13:35:56 +00:00
|
|
|
for (i = 0; i < R_REG_COND_LAST; i++) {
|
2014-06-16 03:58:00 +00:00
|
|
|
r_cons_printf ("%d %s\n",
|
|
|
|
r_reg_cond_bits (core->dbg->reg, i, rf),
|
|
|
|
r_reg_cond_to_string (i));
|
|
|
|
}
|
2014-05-25 01:00:24 +00:00
|
|
|
}
|
2014-06-16 03:58:00 +00:00
|
|
|
free (rf);
|
2014-05-25 01:00:24 +00:00
|
|
|
}
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
}
|
2014-05-25 01:00:24 +00:00
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case 's': // "ars"
|
2014-05-25 01:00:24 +00:00
|
|
|
switch (str[1]) {
|
2017-09-11 23:53:52 +00:00
|
|
|
case '-': // "ars-"
|
2014-05-25 01:00:24 +00:00
|
|
|
r_reg_arena_pop (core->dbg->reg);
|
|
|
|
// restore debug registers if in debugger mode
|
2016-11-14 22:58:29 +00:00
|
|
|
r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, true);
|
2014-05-25 01:00:24 +00:00
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case '+': // "ars+"
|
2014-05-25 01:00:24 +00:00
|
|
|
r_reg_arena_push (core->dbg->reg);
|
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case '?': { // "ars?"
|
2017-07-24 15:41:50 +00:00
|
|
|
// TODO #7967 help refactor: dup from drp
|
2015-12-16 13:35:56 +00:00
|
|
|
const char *help_msg[] = {
|
2014-08-17 00:42:17 +00:00
|
|
|
"Usage:", "drs", " # Register states commands",
|
|
|
|
"drs", "", "List register stack",
|
|
|
|
"drs+", "", "Push register state",
|
|
|
|
"drs-", "", "Pop register state",
|
2015-12-16 13:35:56 +00:00
|
|
|
NULL };
|
2014-08-17 00:42:17 +00:00
|
|
|
r_core_cmd_help (core, help_msg);
|
2015-12-16 13:35:56 +00:00
|
|
|
} break;
|
2014-05-25 01:00:24 +00:00
|
|
|
default:
|
|
|
|
r_cons_printf ("%d\n", r_list_length (
|
2015-12-16 13:35:56 +00:00
|
|
|
core->dbg->reg->regset[0].pool));
|
2014-05-25 01:00:24 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case 'p': // "arp"
|
2016-05-03 02:52:41 +00:00
|
|
|
// XXX we have to break out .h for these cmd_xxx files.
|
2016-05-15 00:14:07 +00:00
|
|
|
cmd_reg_profile (core, 'a', str);
|
2014-05-25 01:00:24 +00:00
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case 't': // "art"
|
2015-12-16 13:35:56 +00:00
|
|
|
for (i = 0; (name = r_reg_get_type (i)); i++)
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_println (name);
|
2014-05-25 01:00:24 +00:00
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case 'n': // "arn"
|
2015-12-16 13:35:56 +00:00
|
|
|
if (*(str + 1) == '\0') {
|
2017-09-11 23:53:52 +00:00
|
|
|
eprintf ("Oops. try arn [PC|SP|BP|A0|A1|A2|A3|A4|R0|R1|ZF|SF|NF|OF]\n");
|
2015-06-15 19:20:44 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
name = r_reg_get_name (core->dbg->reg, r_reg_get_name_idx (str + 2));
|
2016-06-26 04:16:57 +00:00
|
|
|
if (name && *name) {
|
|
|
|
r_cons_println (name);
|
|
|
|
} else {
|
2017-09-11 23:53:52 +00:00
|
|
|
eprintf ("Oops. try arn [PC|SP|BP|A0|A1|A2|A3|A4|R0|R1|ZF|SF|NF|OF]\n");
|
2016-06-26 04:16:57 +00:00
|
|
|
}
|
2014-05-25 01:00:24 +00:00
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case 'd': // "ard"
|
2014-06-04 20:58:22 +00:00
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, bits, 3, use_color); // XXX detect which one is current usage
|
2014-05-25 01:00:24 +00:00
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case 'o': // "aro"
|
2015-09-14 10:35:38 +00:00
|
|
|
r_reg_arena_swap (core->dbg->reg, false);
|
2014-06-04 20:58:22 +00:00
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, bits, 0, use_color); // XXX detect which one is current usage
|
2015-09-14 10:35:38 +00:00
|
|
|
r_reg_arena_swap (core->dbg->reg, false);
|
2014-05-25 01:00:24 +00:00
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case '=': // "ar="
|
2017-07-28 13:06:06 +00:00
|
|
|
{
|
2018-03-22 16:32:57 +00:00
|
|
|
char *p = NULL;
|
|
|
|
char *bits = NULL;
|
2017-07-28 13:06:06 +00:00
|
|
|
if (str[1]) {
|
2018-03-22 16:32:57 +00:00
|
|
|
p = strdup (str + 1);
|
|
|
|
if (str[1] != ':') {
|
|
|
|
// Bits were specified
|
|
|
|
bits = strtok (p, ":");
|
|
|
|
if (r_str_isnumber (bits)) {
|
|
|
|
st64 sz = r_num_math (core->num, bits);
|
|
|
|
if (sz > 0) {
|
|
|
|
size = sz;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
r_core_cmd_help (core, help_msg_ar);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int len = bits ? strlen (bits) : 0;
|
|
|
|
if (str[len + 1] == ':') {
|
|
|
|
// We have some regs
|
2018-03-23 11:46:34 +00:00
|
|
|
char *regs = bits ? strtok (NULL, ":") : strtok ((char *)str + 1, ":");
|
2018-03-22 16:32:57 +00:00
|
|
|
char *reg = strtok (regs, " ");
|
|
|
|
RList *q_regs = r_list_new ();
|
|
|
|
if (q_regs) {
|
|
|
|
while (reg) {
|
|
|
|
r_list_append (q_regs, reg);
|
|
|
|
reg = strtok (NULL, " ");
|
|
|
|
}
|
|
|
|
core->dbg->q_regs = q_regs;
|
|
|
|
}
|
2017-07-28 13:06:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
__anal_reg_list (core, type, size, 2);
|
2018-03-22 16:32:57 +00:00
|
|
|
if (!r_list_empty (core->dbg->q_regs)) {
|
|
|
|
r_list_free (core->dbg->q_regs);
|
|
|
|
}
|
|
|
|
core->dbg->q_regs = NULL;
|
|
|
|
free (p);
|
2017-07-28 13:06:06 +00:00
|
|
|
}
|
2014-05-25 01:00:24 +00:00
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case '-': // "ar-"
|
|
|
|
case '*': // "ar*"
|
|
|
|
case 'R': // "arR"
|
|
|
|
case 'j': // "arj"
|
|
|
|
case '\0': // "ar"
|
2014-05-25 01:00:24 +00:00
|
|
|
__anal_reg_list (core, type, size, str[0]);
|
|
|
|
break;
|
2017-09-11 23:53:52 +00:00
|
|
|
case ' ': { // "ar "
|
2015-12-16 13:35:56 +00:00
|
|
|
arg = strchr (str + 1, '=');
|
2014-05-25 01:00:24 +00:00
|
|
|
if (arg) {
|
2014-06-17 08:23:11 +00:00
|
|
|
char *ostr, *regname;
|
2014-05-25 01:00:24 +00:00
|
|
|
*arg = 0;
|
2018-01-08 02:22:26 +00:00
|
|
|
ostr = r_str_trim (strdup (str + 1));
|
2018-01-08 09:23:57 +00:00
|
|
|
regname = r_str_trim_nc (ostr);
|
2015-10-14 20:12:58 +00:00
|
|
|
r = r_reg_get (core->dbg->reg, regname, -1);
|
2015-07-15 16:18:04 +00:00
|
|
|
if (!r) {
|
2017-08-24 11:23:54 +00:00
|
|
|
int role = r_reg_get_name_idx (regname);
|
|
|
|
if (role != -1) {
|
|
|
|
const char *alias = r_reg_get_name (core->dbg->reg, role);
|
2015-07-15 16:18:04 +00:00
|
|
|
r = r_reg_get (core->dbg->reg, alias, -1);
|
|
|
|
}
|
|
|
|
}
|
2014-05-25 01:00:24 +00:00
|
|
|
if (r) {
|
2015-08-20 00:24:46 +00:00
|
|
|
//eprintf ("%s 0x%08"PFMT64x" -> ", str,
|
|
|
|
// r_reg_get_value (core->dbg->reg, r));
|
2014-05-25 01:00:24 +00:00
|
|
|
r_reg_set_value (core->dbg->reg, r,
|
2015-12-16 13:35:56 +00:00
|
|
|
r_num_math (core->num, arg + 1));
|
2016-11-14 22:58:29 +00:00
|
|
|
r_debug_reg_sync (core->dbg, R_REG_TYPE_ALL, true);
|
2015-08-20 00:24:46 +00:00
|
|
|
//eprintf ("0x%08"PFMT64x"\n",
|
|
|
|
// r_reg_get_value (core->dbg->reg, r));
|
2016-11-24 22:05:44 +00:00
|
|
|
r_core_cmdf (core, ".dr*%d", bits);
|
2014-06-17 08:23:11 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("ar: Unknown register '%s'\n", regname);
|
|
|
|
}
|
|
|
|
free (ostr);
|
2014-05-25 01:00:24 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-09-11 23:53:52 +00:00
|
|
|
char name[32];
|
|
|
|
int i = 1, j;
|
|
|
|
while (str[i]) {
|
|
|
|
if (str[i] == ',') {
|
|
|
|
i++;
|
2017-08-18 12:31:56 +00:00
|
|
|
} else {
|
2017-09-11 23:53:52 +00:00
|
|
|
for (j = i; str[++j] && str[j] != ','; );
|
|
|
|
if (j - i + 1 <= sizeof name) {
|
|
|
|
r_str_ncpy (name, str + i, j - i + 1);
|
|
|
|
if (IS_DIGIT (name[0])) { // e.g. ar 32
|
|
|
|
__anal_reg_list (core, R_REG_TYPE_GPR, atoi (name), '\0');
|
|
|
|
} else if (showreg (core, name) > 0) { // e.g. ar rax
|
|
|
|
} else { // e.g. ar gpr ; ar all
|
|
|
|
type = r_reg_type_by_name (name);
|
|
|
|
// TODO differentiate ALL and illegal register types and print error message for the latter
|
|
|
|
__anal_reg_list (core, type, -1, '\0');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
i = j;
|
2017-08-18 12:31:56 +00:00
|
|
|
}
|
2016-08-14 00:23:47 +00:00
|
|
|
}
|
2014-05-25 01:00:24 +00:00
|
|
|
}
|
2017-09-11 23:53:52 +00:00
|
|
|
}
|
2014-05-25 01:00:24 +00:00
|
|
|
}
|
|
|
|
|
2018-02-17 23:14:47 +00:00
|
|
|
static ut64 initializeEsil(RCore *core) {
|
|
|
|
const char *name = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
|
|
|
|
RAnalEsil *esil = core->anal->esil;
|
|
|
|
int romem = r_config_get_i (core->config, "esil.romem");
|
|
|
|
int stats = r_config_get_i (core->config, "esil.stats");
|
|
|
|
int iotrap = r_config_get_i (core->config, "esil.iotrap");
|
|
|
|
int exectrap = r_config_get_i (core->config, "esil.exectrap");
|
|
|
|
int stacksize = r_config_get_i (core->config, "esil.stack.depth");
|
|
|
|
int noNULL = r_config_get_i (core->config, "esil.noNULL");
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
|
|
|
|
if (!(core->anal->esil = r_anal_esil_new (stacksize, iotrap, addrsize))) {
|
2018-02-17 23:14:47 +00:00
|
|
|
return UT64_MAX;
|
|
|
|
}
|
|
|
|
ut64 addr;
|
|
|
|
esil = core->anal->esil;
|
|
|
|
r_anal_esil_setup (esil, core->anal, romem, stats, noNULL); // setup io
|
|
|
|
esil->exectrap = exectrap;
|
|
|
|
RList *entries = r_bin_get_entries (core->bin);
|
|
|
|
RBinAddr *entry = NULL;
|
|
|
|
RBinInfo *info = NULL;
|
|
|
|
if (entries && !r_list_empty (entries)) {
|
|
|
|
entry = (RBinAddr *)r_list_pop (entries);
|
|
|
|
info = r_bin_get_info (core->bin);
|
|
|
|
addr = info->has_va? entry->vaddr: entry->paddr;
|
|
|
|
r_list_push (entries, entry);
|
|
|
|
} else {
|
|
|
|
addr = core->offset;
|
|
|
|
}
|
|
|
|
r_reg_setv (core->anal->reg, name, addr);
|
|
|
|
// set memory read only
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
2017-07-29 10:59:41 +00:00
|
|
|
R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr, ut64 *prev_addr) {
|
2018-02-12 16:27:22 +00:00
|
|
|
#define return_tail(x) { tail_return_value = x; goto tail_return; }
|
|
|
|
int tail_return_value = 0;
|
2014-08-11 01:32:02 +00:00
|
|
|
int ret;
|
2018-02-19 13:27:05 +00:00
|
|
|
ut8 code[32];
|
2017-07-24 07:42:15 +00:00
|
|
|
RAnalOp op = {0};
|
2015-12-06 18:38:50 +00:00
|
|
|
RAnalEsil *esil = core->anal->esil;
|
2015-09-09 22:34:21 +00:00
|
|
|
const char *name = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
|
2017-08-27 01:14:23 +00:00
|
|
|
if (!esil) {
|
2018-02-17 23:14:47 +00:00
|
|
|
// TODO inititalizeEsil (core);
|
|
|
|
|
2017-08-26 23:00:55 +00:00
|
|
|
int stacksize = r_config_get_i (core->config, "esil.stack.depth");
|
|
|
|
int iotrap = r_config_get_i (core->config, "esil.iotrap");
|
2017-08-26 23:52:00 +00:00
|
|
|
int romem = r_config_get_i (core->config, "esil.romem");
|
|
|
|
int stats = r_config_get_i (core->config, "esil.stats");
|
|
|
|
int noNULL = r_config_get_i (core->config, "esil.noNULL");
|
|
|
|
int verbose = r_config_get_i (core->config, "esil.verbose");
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
|
|
|
|
if (!(esil = r_anal_esil_new (stacksize, iotrap, addrsize))) {
|
2017-08-26 23:00:55 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2017-08-26 23:52:00 +00:00
|
|
|
r_anal_esil_setup (esil, core->anal, romem, stats, noNULL); // setup io
|
2017-08-26 23:00:55 +00:00
|
|
|
core->anal->esil = esil;
|
2017-08-26 23:52:00 +00:00
|
|
|
esil->verbose = verbose;
|
|
|
|
{
|
|
|
|
const char *s = r_config_get (core->config, "cmd.esil.intr");
|
|
|
|
if (s) {
|
|
|
|
char *my = strdup (s);
|
|
|
|
if (my) {
|
|
|
|
r_config_set (core->config, "cmd.esil.intr", my);
|
|
|
|
free (my);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-12-09 21:42:43 +00:00
|
|
|
}
|
2018-02-17 23:14:47 +00:00
|
|
|
esil->cmd = r_core_esil_cmd;
|
2014-08-11 01:32:02 +00:00
|
|
|
ut64 addr = r_reg_getv (core->anal->reg, name);
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2015-12-16 13:35:56 +00:00
|
|
|
repeat:
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
2015-12-16 13:35:56 +00:00
|
|
|
eprintf ("[+] ESIL emulation interrupted at 0x%08" PFMT64x "\n", addr);
|
2018-02-12 16:27:22 +00:00
|
|
|
return_tail (0);
|
2014-08-11 01:32:02 +00:00
|
|
|
}
|
2015-12-06 18:38:50 +00:00
|
|
|
if (!esil) {
|
2018-02-17 23:14:47 +00:00
|
|
|
addr = initializeEsil (core);
|
2015-12-06 18:38:50 +00:00
|
|
|
esil = core->anal->esil;
|
2018-02-17 23:14:47 +00:00
|
|
|
if (!esil) {
|
|
|
|
return_tail (0);
|
2014-08-11 01:32:02 +00:00
|
|
|
}
|
|
|
|
} else {
|
2015-12-06 18:38:50 +00:00
|
|
|
esil->trap = 0;
|
2014-08-11 01:32:02 +00:00
|
|
|
addr = r_reg_getv (core->anal->reg, name);
|
2016-03-31 11:21:51 +00:00
|
|
|
//eprintf ("PC=0x%"PFMT64x"\n", (ut64)addr);
|
2014-08-11 01:32:02 +00:00
|
|
|
}
|
2017-07-29 10:59:41 +00:00
|
|
|
if (prev_addr) {
|
|
|
|
*prev_addr = addr;
|
|
|
|
}
|
2015-12-06 18:38:50 +00:00
|
|
|
if (esil->exectrap) {
|
2017-08-23 22:19:57 +00:00
|
|
|
if (!r_io_is_valid_offset (core->io, addr, R_IO_EXEC)) {
|
2015-09-23 10:46:22 +00:00
|
|
|
esil->trap = R_ANAL_TRAP_EXEC_ERR;
|
|
|
|
esil->trap_code = addr;
|
|
|
|
eprintf ("[ESIL] Trap, trying to execute on non-executable memory\n");
|
2018-02-15 07:50:49 +00:00
|
|
|
return_tail (1);
|
2015-09-23 10:46:22 +00:00
|
|
|
}
|
|
|
|
}
|
2017-06-09 13:50:28 +00:00
|
|
|
r_asm_set_pc (core->assembler, addr);
|
|
|
|
// run esil pin command here
|
|
|
|
const char *pincmd = r_anal_pin_call (core->anal, addr);
|
|
|
|
if (pincmd) {
|
|
|
|
r_core_cmd0 (core, pincmd);
|
|
|
|
ut64 pc = r_debug_reg_get (core->dbg, "PC");
|
|
|
|
if (addr != pc) {
|
2018-02-12 16:27:22 +00:00
|
|
|
return_tail (1);
|
2017-06-09 13:50:28 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-28 08:14:42 +00:00
|
|
|
(void)r_io_read_at (core->io, addr, code, sizeof (code));
|
2016-12-12 13:47:42 +00:00
|
|
|
// TODO: sometimes this is dupe
|
2018-03-15 11:31:01 +00:00
|
|
|
ret = r_anal_op (core->anal, &op, addr, code, sizeof (code), R_ANAL_OP_MASK_ALL);
|
2018-01-27 02:16:50 +00:00
|
|
|
// if type is JMP then we execute the next N instructions
|
2017-03-30 15:58:26 +00:00
|
|
|
// update the esil pointer because RAnal.op() can change it
|
|
|
|
esil = core->anal->esil;
|
2017-06-10 16:00:07 +00:00
|
|
|
if (op.size < 1 || ret < 0) {
|
|
|
|
if (esil->cmd && esil->cmd_todo) {
|
|
|
|
esil->cmd (esil, esil->cmd_todo, addr, 0);
|
|
|
|
}
|
2016-11-02 21:59:32 +00:00
|
|
|
op.size = 1; // avoid inverted stepping
|
|
|
|
}
|
2016-12-12 13:47:42 +00:00
|
|
|
{
|
|
|
|
/* apply hint */
|
|
|
|
RAnalHint *hint = r_anal_hint_get (core->anal, addr);
|
|
|
|
r_anal_op_hint (&op, hint);
|
|
|
|
r_anal_hint_free (hint);
|
|
|
|
}
|
2015-12-02 07:11:34 +00:00
|
|
|
r_reg_setv (core->anal->reg, name, addr + op.size);
|
2014-09-20 13:53:29 +00:00
|
|
|
if (ret) {
|
2015-09-14 09:31:54 +00:00
|
|
|
r_anal_esil_set_pc (esil, addr);
|
2016-08-13 10:09:14 +00:00
|
|
|
if (core->dbg->trace->enabled) {
|
|
|
|
RReg *reg = core->dbg->reg;
|
|
|
|
core->dbg->reg = core->anal->reg;
|
|
|
|
r_debug_trace_pc (core->dbg, addr);
|
|
|
|
core->dbg->reg = reg;
|
|
|
|
} else {
|
|
|
|
r_anal_esil_parse (esil, R_STRBUF_SAFEGET (&op.esil));
|
2018-02-12 19:22:11 +00:00
|
|
|
|
2016-08-13 10:09:14 +00:00
|
|
|
if (core->anal->cur && core->anal->cur->esil_post_loop) {
|
|
|
|
core->anal->cur->esil_post_loop (esil, &op);
|
|
|
|
}
|
|
|
|
r_anal_esil_stack_free (esil);
|
2018-02-12 19:22:11 +00:00
|
|
|
}
|
|
|
|
// only support 1 slot for now
|
|
|
|
if (op.delay) {
|
2018-02-12 20:11:01 +00:00
|
|
|
ut8 code2[32];
|
|
|
|
ut64 naddr = addr + op.size;
|
|
|
|
RAnalOp op2 = {0};
|
|
|
|
// emulate only 1 instruction
|
|
|
|
r_anal_esil_set_pc (esil, naddr);
|
|
|
|
(void)r_io_read_at (core->io, naddr, code2, sizeof (code2));
|
|
|
|
// TODO: sometimes this is dupe
|
2018-03-15 11:31:01 +00:00
|
|
|
ret = r_anal_op (core->anal, &op2, naddr, code2, sizeof (code2), R_ANAL_OP_MASK_ALL);
|
2018-02-12 20:11:01 +00:00
|
|
|
switch (op2.type) {
|
|
|
|
case R_ANAL_OP_TYPE_CJMP:
|
|
|
|
case R_ANAL_OP_TYPE_JMP:
|
|
|
|
case R_ANAL_OP_TYPE_CRET:
|
|
|
|
case R_ANAL_OP_TYPE_RET:
|
|
|
|
// branches are illegal in a delay slot
|
|
|
|
esil->trap = R_ANAL_TRAP_EXEC_ERR;
|
|
|
|
esil->trap_code = addr;
|
|
|
|
eprintf ("[ESIL] Trap, trying to execute a branch in a delay slot\n");
|
|
|
|
return_tail (1);
|
|
|
|
break;
|
2015-12-07 20:30:06 +00:00
|
|
|
}
|
2018-02-12 20:11:01 +00:00
|
|
|
r_anal_esil_parse (esil, R_STRBUF_SAFEGET (&op2.esil));
|
|
|
|
r_anal_op_fini (&op2);
|
2015-12-06 18:38:50 +00:00
|
|
|
}
|
2018-02-15 07:50:49 +00:00
|
|
|
tail_return_value = 1;
|
2014-10-03 18:05:33 +00:00
|
|
|
}
|
|
|
|
|
2015-11-23 16:09:46 +00:00
|
|
|
st64 follow = (st64)r_config_get_i (core->config, "dbg.follow");
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
ut64 pc = r_debug_reg_get (core->dbg, "PC");
|
2015-12-16 13:35:56 +00:00
|
|
|
if (follow > 0) {
|
2017-11-14 16:13:29 +00:00
|
|
|
if ((pc < core->offset) || (pc > (core->offset + follow))) {
|
2015-10-31 00:57:52 +00:00
|
|
|
r_core_cmd0 (core, "sr PC");
|
2017-11-14 16:13:29 +00:00
|
|
|
}
|
2014-10-03 18:05:33 +00:00
|
|
|
}
|
2015-09-16 01:51:35 +00:00
|
|
|
|
2014-08-11 01:32:02 +00:00
|
|
|
// check addr
|
|
|
|
if (until_addr != UT64_MAX) {
|
2015-02-28 22:25:11 +00:00
|
|
|
if (r_reg_getv (core->anal->reg, name) == until_addr) {
|
2018-02-12 16:27:22 +00:00
|
|
|
return_tail (0);
|
2016-11-20 18:20:14 +00:00
|
|
|
}
|
2018-02-12 16:27:22 +00:00
|
|
|
goto repeat;
|
2014-08-11 01:32:02 +00:00
|
|
|
}
|
2014-09-26 13:40:17 +00:00
|
|
|
// check esil
|
2017-03-30 15:58:26 +00:00
|
|
|
if (esil && esil->trap) {
|
2016-11-14 00:17:58 +00:00
|
|
|
if (core->anal->esil->verbose) {
|
|
|
|
eprintf ("TRAP\n");
|
|
|
|
}
|
2018-02-12 16:27:22 +00:00
|
|
|
return_tail (0);
|
2015-09-08 23:17:55 +00:00
|
|
|
}
|
2014-08-11 01:32:02 +00:00
|
|
|
if (until_expr) {
|
|
|
|
if (r_anal_esil_condition (core->anal->esil, until_expr)) {
|
2016-11-14 00:17:58 +00:00
|
|
|
if (core->anal->esil->verbose) {
|
|
|
|
eprintf ("ESIL BREAK!\n");
|
|
|
|
}
|
2018-02-12 16:27:22 +00:00
|
|
|
return_tail (0);
|
2016-11-20 18:20:14 +00:00
|
|
|
}
|
2018-02-12 16:27:22 +00:00
|
|
|
goto repeat;
|
2014-08-11 01:32:02 +00:00
|
|
|
}
|
2018-02-12 16:27:22 +00:00
|
|
|
tail_return:
|
2017-07-24 07:42:15 +00:00
|
|
|
r_anal_op_fini (&op);
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_pop ();
|
2018-02-12 16:27:22 +00:00
|
|
|
return tail_return_value;
|
2014-08-11 01:32:02 +00:00
|
|
|
}
|
|
|
|
|
2017-07-29 10:59:41 +00:00
|
|
|
R_API int r_core_esil_step_back(RCore *core) {
|
|
|
|
RAnalEsil *esil = core->anal->esil;
|
|
|
|
RListIter *tail;
|
|
|
|
const char *name = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
|
|
|
|
ut64 prev = 0;
|
|
|
|
ut64 end = r_reg_getv (core->anal->reg, name);
|
|
|
|
|
|
|
|
if (!esil || !(tail = r_list_tail (esil->sessions))) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
RAnalEsilSession *before = (RAnalEsilSession *) tail->data;
|
2017-11-12 03:52:06 +00:00
|
|
|
if (!before) {
|
|
|
|
eprintf ("Cannot find any previous state here\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2017-11-14 16:13:29 +00:00
|
|
|
eprintf ("NOTE: step back in esil is setting an initial state and stepping into pc is the same.\n");
|
|
|
|
eprintf ("NOTE: this is extremely wrong and poorly efficient. so don't use this feature unless\n");
|
|
|
|
eprintf ("NOTE: you are going to fix it by making it consistent with dts, which is also broken as hell\n");
|
|
|
|
eprintf ("Execute until 0x%08"PFMT64x"\n", end);
|
2017-07-29 10:59:41 +00:00
|
|
|
r_anal_esil_session_set (esil, before);
|
|
|
|
r_core_esil_step (core, end, NULL, &prev);
|
2017-11-14 16:13:29 +00:00
|
|
|
eprintf ("Before 0x%08"PFMT64x"\n", prev);
|
2017-07-29 10:59:41 +00:00
|
|
|
r_anal_esil_session_set (esil, before);
|
|
|
|
r_core_esil_step (core, prev, NULL, NULL);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-10-15 00:24:22 +00:00
|
|
|
static void cmd_address_info(RCore *core, const char *addrstr, int fmt) {
|
|
|
|
ut64 addr, type;
|
|
|
|
if (!addrstr || !*addrstr) {
|
|
|
|
addr = core->offset;
|
|
|
|
} else {
|
|
|
|
addr = r_num_math (core->num, addrstr);
|
|
|
|
}
|
|
|
|
type = r_core_anal_address (core, addr);
|
|
|
|
int isp = 0;
|
2015-12-16 13:35:56 +00:00
|
|
|
switch (fmt) {
|
2014-10-15 00:24:22 +00:00
|
|
|
case 'j':
|
2015-12-16 13:35:56 +00:00
|
|
|
#define COMMA isp++? ",": ""
|
2014-10-15 00:24:22 +00:00
|
|
|
r_cons_printf ("{");
|
2014-10-15 14:05:47 +00:00
|
|
|
if (type & R_ANAL_ADDR_TYPE_PROGRAM)
|
|
|
|
r_cons_printf ("%s\"program\":true", COMMA);
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_LIBRARY)
|
|
|
|
r_cons_printf ("%s\"library\":true", COMMA);
|
2014-10-15 00:24:22 +00:00
|
|
|
if (type & R_ANAL_ADDR_TYPE_EXEC)
|
|
|
|
r_cons_printf ("%s\"exec\":true", COMMA);
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_READ)
|
|
|
|
r_cons_printf ("%s\"read\":true", COMMA);
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_WRITE)
|
|
|
|
r_cons_printf ("%s\"write\":true", COMMA);
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_FLAG)
|
|
|
|
r_cons_printf ("%s\"flag\":true", COMMA);
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_FUNC)
|
|
|
|
r_cons_printf ("%s\"func\":true", COMMA);
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_STACK)
|
|
|
|
r_cons_printf ("%s\"stack\":true", COMMA);
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_HEAP)
|
|
|
|
r_cons_printf ("%s\"heap\":true", COMMA);
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_REG)
|
|
|
|
r_cons_printf ("%s\"reg\":true", COMMA);
|
2014-10-24 19:31:46 +00:00
|
|
|
if (type & R_ANAL_ADDR_TYPE_ASCII)
|
|
|
|
r_cons_printf ("%s\"ascii\":true", COMMA);
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_SEQUENCE)
|
|
|
|
r_cons_printf ("%s\"sequence\":true", COMMA);
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_print ("}");
|
2014-10-15 00:24:22 +00:00
|
|
|
break;
|
|
|
|
default:
|
2014-10-15 14:05:47 +00:00
|
|
|
if (type & R_ANAL_ADDR_TYPE_PROGRAM)
|
|
|
|
r_cons_printf ("program\n");
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_LIBRARY)
|
|
|
|
r_cons_printf ("library\n");
|
2014-10-15 00:24:22 +00:00
|
|
|
if (type & R_ANAL_ADDR_TYPE_EXEC)
|
|
|
|
r_cons_printf ("exec\n");
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_READ)
|
|
|
|
r_cons_printf ("read\n");
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_WRITE)
|
|
|
|
r_cons_printf ("write\n");
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_FLAG)
|
|
|
|
r_cons_printf ("flag\n");
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_FUNC)
|
|
|
|
r_cons_printf ("func\n");
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_STACK)
|
|
|
|
r_cons_printf ("stack\n");
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_HEAP)
|
|
|
|
r_cons_printf ("heap\n");
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_REG)
|
|
|
|
r_cons_printf ("reg\n");
|
2014-10-24 19:31:46 +00:00
|
|
|
if (type & R_ANAL_ADDR_TYPE_ASCII)
|
|
|
|
r_cons_printf ("ascii\n");
|
|
|
|
if (type & R_ANAL_ADDR_TYPE_SEQUENCE)
|
|
|
|
r_cons_printf ("sequence\n");
|
2014-10-15 00:24:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-05 06:34:54 +00:00
|
|
|
static void cmd_anal_info(RCore *core, const char *input) {
|
2014-12-05 06:51:21 +00:00
|
|
|
switch (input[0]) {
|
2014-12-05 06:34:54 +00:00
|
|
|
case '?':
|
|
|
|
eprintf ("Usage: ai @ rsp\n");
|
2014-01-23 01:31:51 +00:00
|
|
|
break;
|
2014-12-05 06:34:54 +00:00
|
|
|
case ' ':
|
2014-12-05 06:51:21 +00:00
|
|
|
cmd_address_info (core, input, 0);
|
2014-10-15 00:24:22 +00:00
|
|
|
break;
|
2014-12-05 06:34:54 +00:00
|
|
|
case 'j': // "aij"
|
2015-12-16 13:35:56 +00:00
|
|
|
cmd_address_info (core, input + 1, 'j');
|
2014-05-25 01:00:24 +00:00
|
|
|
break;
|
2014-12-05 06:34:54 +00:00
|
|
|
default:
|
|
|
|
cmd_address_info (core, NULL, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-19 04:58:20 +00:00
|
|
|
static void initialize_stack (RCore *core, ut64 addr, ut64 size) {
|
|
|
|
const char *mode = r_config_get (core->config, "esil.fillstack");
|
|
|
|
if (mode && *mode && *mode != '0') {
|
|
|
|
const int bs = 4096 * 32;
|
|
|
|
ut64 i;
|
|
|
|
for (i = 0; i < size; i += bs) {
|
|
|
|
int left = R_MIN (bs, size - i);
|
|
|
|
// r_core_cmdf (core, "wx 10203040 @ 0x%llx", addr);
|
|
|
|
switch (*mode) {
|
|
|
|
case 'd': // "debrujn"
|
|
|
|
r_core_cmdf (core, "wopD %"PFMT64d" @ 0x%"PFMT64x, left, addr + i);
|
|
|
|
break;
|
|
|
|
case 's': // "seq"
|
|
|
|
r_core_cmdf (core, "woe 1 0xff 1 4 @ 0x%"PFMT64x"!0x%"PFMT64x, addr + i, left);
|
|
|
|
break;
|
|
|
|
case 'r': // "random"
|
|
|
|
r_core_cmdf (core, "woR %"PFMT64d" @ 0x%"PFMT64x"!0x%"PFMT64x, left, addr + i, left);
|
|
|
|
break;
|
|
|
|
case 'z': // "zero"
|
|
|
|
case '0':
|
|
|
|
r_core_cmdf (core, "wow 00 @ 0x%"PFMT64x"!0x%"PFMT64x, addr + i, left);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// eprintf ("[*] Initializing ESIL stack with pattern\n");
|
|
|
|
// r_core_cmdf (core, "woe 0 10 4 @ 0x%"PFMT64x, size, addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-16 13:35:56 +00:00
|
|
|
static void cmd_esil_mem(RCore *core, const char *input) {
|
2017-07-29 10:59:41 +00:00
|
|
|
RAnalEsil *esil = core->anal->esil;
|
2017-08-26 09:33:01 +00:00
|
|
|
RIOMap *stack_map;
|
2015-01-27 11:46:15 +00:00
|
|
|
ut64 curoff = core->offset;
|
2017-04-07 18:00:19 +00:00
|
|
|
const char *patt = "";
|
2015-03-13 23:14:30 +00:00
|
|
|
ut64 addr = 0x100000;
|
|
|
|
ut32 size = 0xf0000;
|
|
|
|
char name[128];
|
2015-01-27 11:46:15 +00:00
|
|
|
RFlagItem *fi;
|
2017-08-27 00:57:34 +00:00
|
|
|
const char *sp, *pc;
|
2015-01-27 11:46:15 +00:00
|
|
|
char uri[32];
|
2015-03-16 00:37:53 +00:00
|
|
|
char nomalloc[256];
|
2015-03-13 23:14:30 +00:00
|
|
|
char *p;
|
2017-08-27 01:14:23 +00:00
|
|
|
if (!esil) {
|
|
|
|
int stacksize = r_config_get_i (core->config, "esil.stack.depth");
|
|
|
|
int iotrap = r_config_get_i (core->config, "esil.iotrap");
|
|
|
|
int romem = r_config_get_i (core->config, "esil.romem");
|
|
|
|
int stats = r_config_get_i (core->config, "esil.stats");
|
|
|
|
int noNULL = r_config_get_i (core->config, "esil.noNULL");
|
|
|
|
int verbose = r_config_get_i (core->config, "esil.verbose");
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
|
|
|
|
if (!(esil = r_anal_esil_new (stacksize, iotrap, addrsize))) {
|
2017-08-27 01:14:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
r_anal_esil_setup (esil, core->anal, romem, stats, noNULL); // setup io
|
|
|
|
core->anal->esil = esil;
|
|
|
|
esil->verbose = verbose;
|
|
|
|
{
|
|
|
|
const char *s = r_config_get (core->config, "cmd.esil.intr");
|
|
|
|
if (s) {
|
|
|
|
char *my = strdup (s);
|
|
|
|
if (my) {
|
|
|
|
r_config_set (core->config, "cmd.esil.intr", my);
|
|
|
|
free (my);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-08-26 05:06:12 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
if (*input == '?') {
|
2016-10-10 07:50:01 +00:00
|
|
|
eprintf ("Usage: aeim [addr] [size] [name] - initialize ESIL VM stack\n");
|
2015-03-13 23:14:30 +00:00
|
|
|
eprintf ("Default: 0x100000 0xf0000\n");
|
2016-10-10 07:50:01 +00:00
|
|
|
eprintf ("See ae? for more help\n");
|
2015-01-27 11:46:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-12-19 04:58:20 +00:00
|
|
|
if (input[0] == 'p') {
|
|
|
|
fi = r_flag_get (core->flags, "aeim.stack");
|
|
|
|
if (fi) {
|
|
|
|
addr = fi->offset;
|
|
|
|
size = fi->size;
|
|
|
|
} else {
|
|
|
|
cmd_esil_mem (core, "");
|
|
|
|
}
|
2017-07-29 10:59:41 +00:00
|
|
|
if (esil) {
|
|
|
|
esil->stack_addr = addr;
|
|
|
|
esil->stack_size = size;
|
|
|
|
}
|
2016-12-19 04:58:20 +00:00
|
|
|
initialize_stack (core, addr, size);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-26 22:42:08 +00:00
|
|
|
if (!*input) {
|
|
|
|
RFlagItem *fi = r_flag_get (core->flags, "aeim.fd");
|
|
|
|
if (fi) {
|
2017-08-26 22:59:57 +00:00
|
|
|
// Close the fd associated with the aeim stack
|
|
|
|
(void)r_io_fd_close (core->io, fi->offset);
|
2017-08-26 22:42:08 +00:00
|
|
|
}
|
|
|
|
}
|
2017-04-07 18:00:19 +00:00
|
|
|
addr = r_config_get_i (core->config, "esil.stack.addr");
|
|
|
|
size = r_config_get_i (core->config, "esil.stack.size");
|
|
|
|
patt = r_config_get (core->config, "esil.stack.pattern");
|
2017-03-27 01:39:13 +00:00
|
|
|
|
2015-03-16 00:37:53 +00:00
|
|
|
p = strncpy (nomalloc, input, 255);
|
|
|
|
if ((p = strchr (p, ' '))) {
|
2015-03-13 23:14:30 +00:00
|
|
|
while (*p == ' ') p++;
|
|
|
|
addr = r_num_math (core->num, p);
|
2015-03-16 00:37:53 +00:00
|
|
|
if ((p = strchr (p, ' '))) {
|
2015-03-13 23:14:30 +00:00
|
|
|
while (*p == ' ') p++;
|
2015-03-14 15:42:14 +00:00
|
|
|
size = (ut32)r_num_math (core->num, p);
|
2016-12-19 04:58:20 +00:00
|
|
|
if (size < 1) {
|
2015-03-14 15:42:14 +00:00
|
|
|
size = 0xf0000;
|
2016-12-19 04:58:20 +00:00
|
|
|
}
|
2015-03-16 00:37:53 +00:00
|
|
|
if ((p = strchr (p, ' '))) {
|
2015-03-14 15:42:14 +00:00
|
|
|
while (*p == ' ') p++;
|
2016-11-10 11:32:34 +00:00
|
|
|
snprintf (name, sizeof (name), "mem.%s", p);
|
|
|
|
} else {
|
|
|
|
snprintf (name, sizeof (name), "mem.0x%" PFMT64x "_0x%x", addr, size);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
snprintf (name, sizeof (name), "mem.0x%" PFMT64x "_0x%x", addr, size);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
snprintf (name, sizeof (name), "mem.0x%" PFMT64x "_0x%x", addr, size);
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
if (*input == '-') {
|
2017-08-26 05:06:12 +00:00
|
|
|
if (esil->stack_fd > 2) { //0, 1, 2 are reserved for stdio/stderr
|
|
|
|
r_io_fd_close (core->io, esil->stack_fd);
|
|
|
|
// no need to kill the maps, r_io_map_cleanup does that for us in the close
|
|
|
|
esil->stack_fd = 0;
|
|
|
|
} else {
|
|
|
|
eprintf ("Cannot deinitialize %s\n", name);
|
|
|
|
}
|
|
|
|
r_flag_unset_name (core->flags, name);
|
|
|
|
// eprintf ("Deinitialized %s\n", name);
|
2015-01-27 11:46:15 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-08-26 22:42:08 +00:00
|
|
|
|
2017-08-26 09:33:01 +00:00
|
|
|
snprintf (uri, sizeof (uri), "malloc://%d", (int)size);
|
|
|
|
esil->stack_fd = r_io_fd_open (core->io, uri, R_IO_RW, 0);
|
|
|
|
if (!(stack_map = r_io_map_add (core->io, esil->stack_fd,
|
2017-08-27 23:27:28 +00:00
|
|
|
R_IO_RW, 0LL, addr, size, true))) {
|
2017-08-26 09:33:01 +00:00
|
|
|
r_io_fd_close (core->io, esil->stack_fd);
|
2017-08-26 22:42:08 +00:00
|
|
|
eprintf ("Cannot create map for tha stack, fd %d got closed again\n", esil->stack_fd);
|
2017-08-26 09:33:01 +00:00
|
|
|
esil->stack_fd = 0;
|
|
|
|
return;
|
2016-11-11 06:26:15 +00:00
|
|
|
}
|
2017-08-26 09:33:01 +00:00
|
|
|
r_io_map_set_name (stack_map, name);
|
2017-08-26 22:42:08 +00:00
|
|
|
// r_flag_set (core->flags, name, addr, size); //why is this here?
|
2017-08-26 09:33:01 +00:00
|
|
|
r_flag_set (core->flags, "aeim.stack", addr, size);
|
2017-08-26 22:42:08 +00:00
|
|
|
r_flag_set (core->flags, "aeim.fd", esil->stack_fd, 1);
|
2017-08-26 09:33:01 +00:00
|
|
|
r_config_set_i (core->config, "io.va", true);
|
2017-04-07 18:32:14 +00:00
|
|
|
if (patt && *patt) {
|
|
|
|
switch (*patt) {
|
2017-04-07 18:00:19 +00:00
|
|
|
case '0':
|
|
|
|
// do nothing
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
r_core_cmdf (core, "wopD %d @ 0x%"PFMT64x, size, addr);
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
r_core_cmdf (core, "woe 0 255 1 @ 0x%"PFMT64x"!%d",addr, size);
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
r_core_cmdf (core, "woe 0 0xffff 1 4 @ 0x%"PFMT64x"!%d",addr, size);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-04-11 00:24:21 +00:00
|
|
|
// SP
|
2015-10-01 10:04:58 +00:00
|
|
|
sp = r_reg_get_name (core->dbg->reg, R_REG_NAME_SP);
|
2015-12-16 13:35:56 +00:00
|
|
|
r_debug_reg_set (core->dbg, sp, addr + (size / 2));
|
2016-04-11 00:24:21 +00:00
|
|
|
// BP
|
|
|
|
sp = r_reg_get_name (core->dbg->reg, R_REG_NAME_BP);
|
|
|
|
r_debug_reg_set (core->dbg, sp, addr + (size / 2));
|
2017-12-18 21:13:58 +00:00
|
|
|
// PC
|
2017-08-27 00:57:34 +00:00
|
|
|
pc = r_reg_get_name (core->dbg->reg, R_REG_NAME_PC);
|
|
|
|
r_debug_reg_set (core->dbg, pc, curoff);
|
2017-12-18 21:13:58 +00:00
|
|
|
r_core_cmd0 (core, ".ar*");
|
2017-08-26 05:06:12 +00:00
|
|
|
#if 0
|
2017-03-30 07:18:03 +00:00
|
|
|
if (!r_io_section_get_name (core->io, ESIL_STACK_NAME)) {
|
2017-08-26 01:13:57 +00:00
|
|
|
r_core_cmdf (core, "om %d 0x%"PFMT64x, cf->fd, addr);
|
2017-03-30 07:18:03 +00:00
|
|
|
r_core_cmdf (core, "S 0x%"PFMT64x" 0x%"PFMT64x" %d %d "
|
|
|
|
ESIL_STACK_NAME, addr, addr, size, size);
|
2016-05-09 21:23:45 +00:00
|
|
|
}
|
2017-08-26 05:06:12 +00:00
|
|
|
#endif
|
2017-07-29 10:59:41 +00:00
|
|
|
if (esil) {
|
|
|
|
esil->stack_addr = addr;
|
|
|
|
esil->stack_size = size;
|
|
|
|
}
|
2016-12-19 04:58:20 +00:00
|
|
|
initialize_stack (core, addr, size);
|
2015-01-27 11:46:15 +00:00
|
|
|
r_core_seek (core, curoff, 0);
|
|
|
|
}
|
|
|
|
|
2017-08-08 09:34:53 +00:00
|
|
|
#if 0
|
2016-01-15 00:50:08 +00:00
|
|
|
static ut64 opc = UT64_MAX;
|
|
|
|
static ut8 *regstate = NULL;
|
|
|
|
|
|
|
|
static void esil_init (RCore *core) {
|
|
|
|
const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
|
2017-08-18 12:31:56 +00:00
|
|
|
int noNULL = r_config_get_i (core->config, "esil.noNULL");
|
2016-01-15 00:50:08 +00:00
|
|
|
opc = r_reg_getv (core->anal->reg, pc);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (!opc || opc==UT64_MAX) {
|
|
|
|
opc = core->offset;
|
|
|
|
}
|
2016-01-15 00:50:08 +00:00
|
|
|
if (!core->anal->esil) {
|
|
|
|
int iotrap = r_config_get_i (core->config, "esil.iotrap");
|
2017-03-27 01:39:13 +00:00
|
|
|
ut64 stackSize = r_config_get_i (core->config, "esil.stack.size");
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
|
|
|
|
if (!(core->anal->esil = r_anal_esil_new (stackSize, iotrap, addrsize))) {
|
2016-01-20 16:13:30 +00:00
|
|
|
R_FREE (regstate);
|
|
|
|
return;
|
|
|
|
}
|
2017-08-18 12:31:56 +00:00
|
|
|
r_anal_esil_setup (core->anal->esil, core->anal, 0, 0, noNULL);
|
2016-01-15 00:50:08 +00:00
|
|
|
}
|
|
|
|
free (regstate);
|
|
|
|
regstate = r_reg_arena_peek (core->anal->reg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void esil_fini(RCore *core) {
|
|
|
|
const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
|
|
|
|
r_reg_arena_poke (core->anal->reg, regstate);
|
|
|
|
r_reg_setv (core->anal->reg, pc, opc);
|
|
|
|
R_FREE (regstate);
|
|
|
|
}
|
2017-07-17 12:49:19 +00:00
|
|
|
#endif
|
2016-01-15 00:50:08 +00:00
|
|
|
|
2016-01-15 01:51:49 +00:00
|
|
|
typedef struct {
|
|
|
|
RList *regs;
|
|
|
|
RList *regread;
|
|
|
|
RList *regwrite;
|
2018-04-11 10:15:14 +00:00
|
|
|
RList *inputregs;
|
2016-01-15 01:51:49 +00:00
|
|
|
} AeaStats;
|
|
|
|
|
|
|
|
static void aea_stats_init (AeaStats *stats) {
|
|
|
|
stats->regs = r_list_newf (free);
|
|
|
|
stats->regread = r_list_newf (free);
|
|
|
|
stats->regwrite = r_list_newf (free);
|
2018-04-11 10:15:14 +00:00
|
|
|
stats->inputregs = r_list_newf (free);
|
2016-01-15 01:51:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void aea_stats_fini (AeaStats *stats) {
|
|
|
|
R_FREE (stats->regs);
|
|
|
|
R_FREE (stats->regread);
|
|
|
|
R_FREE (stats->regwrite);
|
2018-04-11 10:15:14 +00:00
|
|
|
R_FREE (stats->inputregs);
|
2016-01-15 01:51:49 +00:00
|
|
|
}
|
|
|
|
|
2016-01-15 00:50:08 +00:00
|
|
|
static bool contains(RList *list, const char *name) {
|
|
|
|
RListIter *iter;
|
|
|
|
const char *n;
|
|
|
|
r_list_foreach (list, iter, n) {
|
|
|
|
if (!strcmp (name, n))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-01-15 01:51:49 +00:00
|
|
|
static char *oldregread = NULL;
|
2017-07-06 22:22:18 +00:00
|
|
|
static RList *mymemxsr = NULL;
|
|
|
|
static RList *mymemxsw = NULL;
|
|
|
|
|
|
|
|
#define R_NEW_DUP(x) memcpy((void*)malloc(sizeof(x)), &(x), sizeof(x))
|
2017-08-24 11:23:54 +00:00
|
|
|
typedef struct {
|
|
|
|
ut64 addr;
|
|
|
|
int size;
|
|
|
|
} AeaMemItem;
|
2017-07-06 22:22:18 +00:00
|
|
|
|
|
|
|
static int mymemwrite(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) {
|
|
|
|
RListIter *iter;
|
2017-08-24 11:23:54 +00:00
|
|
|
AeaMemItem *n;
|
2017-07-06 22:22:18 +00:00
|
|
|
r_list_foreach (mymemxsw, iter, n) {
|
2017-08-24 11:23:54 +00:00
|
|
|
if (addr == n->addr) {
|
2017-07-06 22:22:18 +00:00
|
|
|
return len;
|
|
|
|
}
|
|
|
|
}
|
2018-04-11 10:15:14 +00:00
|
|
|
if (!r_io_is_valid_offset (esil->anal->iob.io, addr, 0)) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-08-24 11:23:54 +00:00
|
|
|
n = R_NEW (AeaMemItem);
|
|
|
|
if (n) {
|
|
|
|
n->addr = addr;
|
|
|
|
n->size = len;
|
|
|
|
r_list_push (mymemxsw, n);
|
|
|
|
}
|
2017-07-06 22:22:18 +00:00
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mymemread(RAnalEsil *esil, ut64 addr, ut8 *buf, int len) {
|
|
|
|
RListIter *iter;
|
2017-08-24 11:23:54 +00:00
|
|
|
AeaMemItem *n;
|
2017-07-06 22:22:18 +00:00
|
|
|
r_list_foreach (mymemxsr, iter, n) {
|
2017-08-24 11:23:54 +00:00
|
|
|
if (addr == n->addr) {
|
2017-07-06 22:22:18 +00:00
|
|
|
return len;
|
|
|
|
}
|
|
|
|
}
|
2018-04-11 10:15:14 +00:00
|
|
|
if (!r_io_is_valid_offset (esil->anal->iob.io, addr, 0)) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-08-24 11:23:54 +00:00
|
|
|
n = R_NEW (AeaMemItem);
|
|
|
|
if (n) {
|
|
|
|
n->addr = addr;
|
|
|
|
n->size = len;
|
|
|
|
r_list_push (mymemxsr, n);
|
|
|
|
}
|
2017-07-06 22:22:18 +00:00
|
|
|
return len;
|
|
|
|
}
|
2016-01-15 01:51:49 +00:00
|
|
|
|
2016-10-18 14:59:38 +00:00
|
|
|
static int myregwrite(RAnalEsil *esil, const char *name, ut64 *val) {
|
2016-01-15 01:51:49 +00:00
|
|
|
AeaStats *stats = esil->user;
|
|
|
|
if (oldregread && !strcmp (name, oldregread)) {
|
|
|
|
r_list_pop (stats->regread);
|
|
|
|
R_FREE (oldregread)
|
|
|
|
}
|
2017-02-05 21:50:54 +00:00
|
|
|
if (!IS_DIGIT (*name)) {
|
2016-01-15 01:51:49 +00:00
|
|
|
if (!contains (stats->regs, name)) {
|
|
|
|
r_list_push (stats->regs, strdup (name));
|
|
|
|
}
|
|
|
|
if (!contains (stats->regwrite, name)) {
|
|
|
|
r_list_push (stats->regwrite, strdup (name));
|
|
|
|
}
|
2016-01-15 00:50:08 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int myregread(RAnalEsil *esil, const char *name, ut64 *val, int *len) {
|
2016-01-15 01:51:49 +00:00
|
|
|
AeaStats *stats = esil->user;
|
2017-02-05 21:50:54 +00:00
|
|
|
if (!IS_DIGIT (*name)) {
|
2018-04-11 10:15:14 +00:00
|
|
|
if (!contains (stats->inputregs, name)) {
|
|
|
|
if (!contains (stats->regwrite, name)) {
|
|
|
|
r_list_push (stats->inputregs, strdup (name));
|
|
|
|
}
|
|
|
|
}
|
2016-01-15 01:51:49 +00:00
|
|
|
if (!contains (stats->regs, name)) {
|
|
|
|
r_list_push (stats->regs, strdup (name));
|
|
|
|
}
|
|
|
|
if (!contains (stats->regread, name)) {
|
|
|
|
r_list_push (stats->regread, strdup (name));
|
2016-01-15 00:50:08 +00:00
|
|
|
}
|
2016-01-15 01:51:49 +00:00
|
|
|
}
|
2016-01-15 00:50:08 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-15 01:51:49 +00:00
|
|
|
static void showregs (RList *list) {
|
|
|
|
if (!r_list_empty (list)) {
|
|
|
|
char *reg;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (list, iter, reg) {
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_print (reg);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (iter->n) {
|
|
|
|
r_cons_printf (" ");
|
|
|
|
}
|
2016-01-15 01:51:49 +00:00
|
|
|
}
|
|
|
|
}
|
2017-07-06 23:46:24 +00:00
|
|
|
r_cons_newline();
|
2016-01-15 01:51:49 +00:00
|
|
|
}
|
2016-01-18 10:15:02 +00:00
|
|
|
|
2017-03-16 08:54:13 +00:00
|
|
|
static void showregs_json (RList *list) {
|
|
|
|
r_cons_printf ("[");
|
|
|
|
if (!r_list_empty (list)) {
|
|
|
|
char *reg;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (list, iter, reg) {
|
|
|
|
r_cons_printf ("\"%s\"", reg);
|
|
|
|
if (iter->n) {
|
|
|
|
r_cons_printf (",");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_cons_printf ("]");
|
|
|
|
}
|
|
|
|
|
2016-01-15 00:50:08 +00:00
|
|
|
static bool cmd_aea(RCore* core, int mode, ut64 addr, int length) {
|
2016-01-15 01:51:49 +00:00
|
|
|
RAnalEsil *esil;
|
2016-01-18 10:15:02 +00:00
|
|
|
int ptr, ops, ops_end = 0, len, buf_sz, maxopsize;
|
2016-01-15 00:50:08 +00:00
|
|
|
ut64 addr_end;
|
2016-01-15 01:51:49 +00:00
|
|
|
AeaStats stats;
|
2016-01-15 00:50:08 +00:00
|
|
|
const char *esilstr;
|
2017-03-25 01:30:00 +00:00
|
|
|
RAnalOp aop = R_EMPTY;
|
2016-01-15 00:50:08 +00:00
|
|
|
ut8 *buf;
|
2017-03-16 08:54:13 +00:00
|
|
|
RList* regnow;
|
2018-04-11 10:15:14 +00:00
|
|
|
if (!core) {
|
2016-01-15 00:50:08 +00:00
|
|
|
return false;
|
2018-04-11 10:15:14 +00:00
|
|
|
}
|
2016-01-15 00:50:08 +00:00
|
|
|
maxopsize = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_MAX_OP_SIZE);
|
2016-05-11 13:38:26 +00:00
|
|
|
if (maxopsize < 1) {
|
|
|
|
maxopsize = 16;
|
|
|
|
}
|
2016-01-15 01:51:49 +00:00
|
|
|
if (mode & 1) {
|
|
|
|
// number of bytes / length
|
|
|
|
buf_sz = length;
|
|
|
|
} else {
|
|
|
|
// number of instructions / opcodes
|
2016-01-15 00:50:08 +00:00
|
|
|
ops_end = length;
|
2016-11-24 00:56:49 +00:00
|
|
|
if (ops_end < 1) {
|
|
|
|
ops_end = 1;
|
|
|
|
}
|
2016-01-15 00:50:08 +00:00
|
|
|
buf_sz = ops_end * maxopsize;
|
|
|
|
}
|
|
|
|
if (buf_sz < 1) {
|
|
|
|
buf_sz = maxopsize;
|
|
|
|
}
|
|
|
|
addr_end = addr + buf_sz;
|
|
|
|
buf = malloc (buf_sz);
|
|
|
|
if (!buf) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
(void)r_io_read_at (core->io, addr, (ut8 *)buf, buf_sz);
|
2016-01-15 01:51:49 +00:00
|
|
|
aea_stats_init (&stats);
|
|
|
|
|
2017-07-13 23:17:49 +00:00
|
|
|
//esil_init (core);
|
|
|
|
//esil = core->anal->esil;
|
|
|
|
r_reg_arena_push (core->anal->reg);
|
|
|
|
int stacksize = r_config_get_i (core->config, "esil.stack.depth");
|
|
|
|
bool iotrap = r_config_get_i (core->config, "esil.iotrap");
|
|
|
|
int romem = r_config_get_i (core->config, "esil.romem");
|
|
|
|
int stats1 = r_config_get_i (core->config, "esil.stats");
|
2017-08-18 12:31:56 +00:00
|
|
|
int noNULL = r_config_get_i (core->config, "esil.noNULL");
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
|
|
|
|
esil = r_anal_esil_new (stacksize, iotrap, addrsize);
|
2017-08-18 12:31:56 +00:00
|
|
|
r_anal_esil_setup (esil, core->anal, romem, stats1, noNULL); // setup io
|
2016-01-15 01:51:49 +00:00
|
|
|
# define hasNext(x) (x&1) ? (addr<addr_end) : (ops<ops_end)
|
2017-07-06 22:22:18 +00:00
|
|
|
|
|
|
|
mymemxsr = r_list_new ();
|
|
|
|
mymemxsw = r_list_new ();
|
2016-01-15 01:51:49 +00:00
|
|
|
esil->user = &stats;
|
|
|
|
esil->cb.hook_reg_write = myregwrite;
|
|
|
|
esil->cb.hook_reg_read = myregread;
|
2017-07-06 22:22:18 +00:00
|
|
|
esil->cb.hook_mem_write = mymemwrite;
|
|
|
|
esil->cb.hook_mem_read = mymemread;
|
2016-01-15 01:51:49 +00:00
|
|
|
esil->nowrite = true;
|
|
|
|
for (ops = ptr = 0; ptr < buf_sz && hasNext (mode); ops++, ptr += len) {
|
2018-03-15 11:31:01 +00:00
|
|
|
len = r_anal_op (core->anal, &aop, addr + ptr, buf + ptr, buf_sz - ptr, R_ANAL_OP_MASK_ALL);
|
2016-01-15 00:50:08 +00:00
|
|
|
esilstr = R_STRBUF_SAFEGET (&aop.esil);
|
|
|
|
if (len < 1) {
|
|
|
|
eprintf ("Invalid 0x%08"PFMT64x" instruction %02x %02x\n",
|
|
|
|
addr + ptr, buf[ptr], buf[ptr + 1]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
r_anal_esil_parse (esil, esilstr);
|
|
|
|
r_anal_esil_stack_free (esil);
|
|
|
|
}
|
2016-01-15 01:51:49 +00:00
|
|
|
esil->nowrite = false;
|
|
|
|
esil->cb.hook_reg_write = NULL;
|
|
|
|
esil->cb.hook_reg_read = NULL;
|
2017-07-13 23:17:49 +00:00
|
|
|
//esil_fini (core);
|
|
|
|
r_anal_esil_free (esil);
|
|
|
|
r_reg_arena_pop (core->anal->reg);
|
2017-07-06 22:22:18 +00:00
|
|
|
regnow = r_list_newf (free);
|
2017-03-16 08:54:13 +00:00
|
|
|
{
|
2016-01-15 00:50:08 +00:00
|
|
|
RListIter *iter;
|
2016-01-15 01:51:49 +00:00
|
|
|
char *reg;
|
|
|
|
r_list_foreach (stats.regs, iter, reg) {
|
|
|
|
if (!contains (stats.regwrite, reg)) {
|
2017-03-16 08:54:13 +00:00
|
|
|
r_list_push (regnow, strdup (reg));
|
2016-01-15 01:51:49 +00:00
|
|
|
}
|
2016-01-15 00:50:08 +00:00
|
|
|
}
|
2017-03-16 08:54:13 +00:00
|
|
|
}
|
2017-07-06 23:46:24 +00:00
|
|
|
if ((mode >> 5) & 1) {
|
2017-07-06 22:22:18 +00:00
|
|
|
RListIter *iter;
|
2017-08-24 11:23:54 +00:00
|
|
|
AeaMemItem *n;
|
2017-07-06 22:22:18 +00:00
|
|
|
int c = 0;
|
2017-07-06 23:46:24 +00:00
|
|
|
r_cons_printf ("f-mem.*\n");
|
2017-07-06 22:22:18 +00:00
|
|
|
r_list_foreach (mymemxsr, iter, n) {
|
2017-08-24 11:23:54 +00:00
|
|
|
r_cons_printf ("f mem.read.%d 0x%08x @ 0x%08"PFMT64x"\n", c++, n->size, n->addr);
|
2017-07-06 22:22:18 +00:00
|
|
|
}
|
|
|
|
c = 0;
|
|
|
|
r_list_foreach (mymemxsw, iter, n) {
|
2017-08-24 11:23:54 +00:00
|
|
|
r_cons_printf ("f mem.write.%d 0x%08x @ 0x%08"PFMT64x"\n", c++, n->size, n->addr);
|
2017-07-06 22:22:18 +00:00
|
|
|
}
|
|
|
|
}
|
2017-03-16 08:54:13 +00:00
|
|
|
|
|
|
|
/* show registers used */
|
|
|
|
if ((mode >> 1) & 1) {
|
|
|
|
showregs (stats.regread);
|
|
|
|
} else if ((mode >> 2) & 1) {
|
|
|
|
showregs (stats.regwrite);
|
|
|
|
} else if ((mode >> 3) & 1) {
|
|
|
|
showregs (regnow);
|
|
|
|
} else if ((mode >> 4) & 1) {
|
|
|
|
r_cons_printf ("{\"A\":");
|
|
|
|
showregs_json (stats.regs);
|
2018-04-11 10:15:14 +00:00
|
|
|
r_cons_printf (",\"I\":");
|
|
|
|
showregs_json (stats.inputregs);
|
2017-03-16 08:54:13 +00:00
|
|
|
r_cons_printf (",\"R\":");
|
|
|
|
showregs_json (stats.regread);
|
|
|
|
r_cons_printf (",\"W\":");
|
|
|
|
showregs_json (stats.regwrite);
|
|
|
|
r_cons_printf (",\"N\":");
|
|
|
|
showregs_json (regnow);
|
|
|
|
r_cons_printf ("}");
|
2016-01-15 00:50:08 +00:00
|
|
|
r_cons_newline();
|
2017-07-06 23:46:24 +00:00
|
|
|
} else if ((mode >> 5) & 1) {
|
|
|
|
// nothing
|
2016-01-15 01:51:49 +00:00
|
|
|
} else {
|
2018-04-11 10:15:14 +00:00
|
|
|
r_cons_printf (" I: ");
|
|
|
|
showregs (stats.inputregs);
|
2018-02-18 02:31:59 +00:00
|
|
|
r_cons_printf (" A: ");
|
2016-01-15 01:51:49 +00:00
|
|
|
showregs (stats.regs);
|
2018-02-18 02:31:59 +00:00
|
|
|
r_cons_printf (" R: ");
|
2016-01-15 01:51:49 +00:00
|
|
|
showregs (stats.regread);
|
2018-02-18 02:31:59 +00:00
|
|
|
r_cons_printf (" W: ");
|
2016-01-15 01:51:49 +00:00
|
|
|
showregs (stats.regwrite);
|
2018-02-18 02:31:59 +00:00
|
|
|
r_cons_printf ("NW: ");
|
2017-03-16 08:54:13 +00:00
|
|
|
if (r_list_length (regnow)) {
|
|
|
|
showregs (regnow);
|
|
|
|
} else {
|
2016-01-15 01:51:49 +00:00
|
|
|
r_cons_newline();
|
|
|
|
}
|
2017-07-06 23:46:24 +00:00
|
|
|
RListIter *iter;
|
|
|
|
ut64 *n;
|
2018-04-11 10:19:06 +00:00
|
|
|
if (!r_list_empty (mymemxsr)) {
|
|
|
|
r_cons_printf ("@R:");
|
|
|
|
r_list_foreach (mymemxsr, iter, n) {
|
|
|
|
r_cons_printf (" 0x%08"PFMT64x, *n);
|
|
|
|
}
|
|
|
|
r_cons_newline ();
|
2017-07-06 23:46:24 +00:00
|
|
|
}
|
2018-04-11 10:19:06 +00:00
|
|
|
if (!r_list_empty (mymemxsw)) {
|
|
|
|
r_cons_printf ("@W:");
|
|
|
|
r_list_foreach (mymemxsw, iter, n) {
|
|
|
|
r_cons_printf (" 0x%08"PFMT64x, *n);
|
|
|
|
}
|
|
|
|
r_cons_newline ();
|
2017-07-06 23:46:24 +00:00
|
|
|
}
|
2016-01-15 00:50:08 +00:00
|
|
|
}
|
2017-07-07 10:29:14 +00:00
|
|
|
r_list_free (mymemxsr);
|
|
|
|
r_list_free (mymemxsw);
|
|
|
|
mymemxsr = NULL;
|
|
|
|
mymemxsw = NULL;
|
2016-01-15 01:51:49 +00:00
|
|
|
aea_stats_fini (&stats);
|
2016-01-15 00:50:08 +00:00
|
|
|
free (buf);
|
2017-03-16 08:54:13 +00:00
|
|
|
R_FREE (regnow);
|
2016-01-15 00:50:08 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-12-01 12:46:01 +00:00
|
|
|
static void cmd_aespc(RCore *core, ut64 addr, int off) {
|
|
|
|
RAnalEsil *esil = core->anal->esil;
|
|
|
|
int i, j = 0;
|
|
|
|
int instr_size = 0;
|
|
|
|
ut8 *buf;
|
|
|
|
RAnalOp aop = {0};
|
|
|
|
int ret , bsize = R_MAX (64, core->blocksize);
|
|
|
|
const int mininstrsz = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_MIN_OP_SIZE);
|
|
|
|
const int minopcode = R_MAX (1, mininstrsz);
|
|
|
|
const char *pc = r_reg_get_name (core->dbg->reg, R_REG_NAME_PC);
|
2018-03-12 12:10:59 +00:00
|
|
|
RRegItem *r = r_reg_get (core->dbg->reg, pc, -1);
|
2017-12-01 12:46:01 +00:00
|
|
|
int stacksize = r_config_get_i (core->config, "esil.stack.depth");
|
|
|
|
int iotrap = r_config_get_i (core->config, "esil.iotrap");
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
|
2017-12-01 12:46:01 +00:00
|
|
|
|
|
|
|
if (!esil) {
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
if (!(esil = r_anal_esil_new (stacksize, iotrap, addrsize))) {
|
2017-12-01 12:46:01 +00:00
|
|
|
return;
|
2018-03-12 12:10:59 +00:00
|
|
|
}
|
2017-12-01 12:46:01 +00:00
|
|
|
}
|
|
|
|
buf = malloc (bsize);
|
|
|
|
if (!buf) {
|
2017-12-27 17:33:58 +00:00
|
|
|
eprintf ("Cannot allocate %d byte(s)\n", bsize);
|
2017-12-01 12:46:01 +00:00
|
|
|
free (buf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (addr == -1) {
|
|
|
|
addr = r_debug_reg_get (core->dbg, pc);
|
|
|
|
}
|
2018-03-12 12:10:59 +00:00
|
|
|
ut64 curpc = addr;
|
2017-12-01 12:46:01 +00:00
|
|
|
ut64 oldoff = core->offset;
|
|
|
|
for (i = 0, j = 0; j < off ; i++, j++) {
|
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i >= (bsize - 32)) {
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
if (!i) {
|
|
|
|
r_core_read_at (core, addr, buf, bsize);
|
|
|
|
}
|
2018-03-15 11:31:01 +00:00
|
|
|
ret = r_anal_op (core->anal, &aop, addr, buf + i, bsize - i, R_ANAL_OP_MASK_ALL);
|
2017-12-01 12:46:01 +00:00
|
|
|
instr_size += ret;
|
|
|
|
int inc = (core->search->align > 0)? core->search->align - 1: ret - 1;
|
|
|
|
if (inc < 0) {
|
|
|
|
inc = minopcode;
|
|
|
|
}
|
|
|
|
i += inc;
|
|
|
|
addr += inc;
|
2018-03-12 12:10:59 +00:00
|
|
|
r_anal_op_fini (&aop);
|
2017-12-01 12:46:01 +00:00
|
|
|
}
|
2018-03-12 12:10:59 +00:00
|
|
|
r_reg_set_value (core->dbg->reg, r, curpc);
|
2017-12-01 12:46:01 +00:00
|
|
|
r_core_esil_step (core, curpc + instr_size, NULL, NULL);
|
|
|
|
r_core_seek (core, oldoff, 1);
|
2018-03-12 12:10:59 +00:00
|
|
|
}
|
2017-12-01 12:46:01 +00:00
|
|
|
|
2014-12-05 06:34:54 +00:00
|
|
|
static void cmd_anal_esil(RCore *core, const char *input) {
|
2014-12-05 17:56:33 +00:00
|
|
|
RAnalEsil *esil = core->anal->esil;
|
2014-12-05 06:34:54 +00:00
|
|
|
ut64 addr = core->offset;
|
2017-12-01 12:46:01 +00:00
|
|
|
ut64 adr ;
|
|
|
|
char *n, *n1;
|
|
|
|
int off;
|
2017-03-27 01:39:13 +00:00
|
|
|
int stacksize = r_config_get_i (core->config, "esil.stack.depth");
|
2015-09-08 23:17:55 +00:00
|
|
|
int iotrap = r_config_get_i (core->config, "esil.iotrap");
|
2014-12-05 17:56:33 +00:00
|
|
|
int romem = r_config_get_i (core->config, "esil.romem");
|
|
|
|
int stats = r_config_get_i (core->config, "esil.stats");
|
2017-08-18 12:31:56 +00:00
|
|
|
int noNULL = r_config_get_i (core->config, "esil.noNULL");
|
2014-12-05 17:56:33 +00:00
|
|
|
ut64 until_addr = UT64_MAX;
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
|
|
|
|
|
2014-12-05 17:56:33 +00:00
|
|
|
const char *until_expr = NULL;
|
2015-01-30 00:55:21 +00:00
|
|
|
RAnalOp *op;
|
2014-12-05 06:34:54 +00:00
|
|
|
|
2014-12-05 06:51:21 +00:00
|
|
|
switch (input[0]) {
|
2015-06-30 08:50:46 +00:00
|
|
|
case 'p': // "aep"
|
|
|
|
switch (input[1]) {
|
|
|
|
case 'c':
|
|
|
|
if (input[2] == ' ') {
|
|
|
|
// seek to this address
|
2015-12-16 13:35:56 +00:00
|
|
|
r_core_cmdf (core, "ar PC=%s", input + 3);
|
2015-06-30 08:50:46 +00:00
|
|
|
r_core_cmd0 (core, ".ar*");
|
|
|
|
} else {
|
|
|
|
eprintf ("Missing argument\n");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
r_anal_pin_list (core->anal);
|
|
|
|
break;
|
|
|
|
case '-':
|
|
|
|
if (input[2])
|
2015-12-16 13:35:56 +00:00
|
|
|
addr = r_num_math (core->num, input + 2);
|
2015-06-30 08:50:46 +00:00
|
|
|
r_anal_pin_unset (core->anal, addr);
|
|
|
|
break;
|
|
|
|
case ' ':
|
2015-12-16 13:35:56 +00:00
|
|
|
r_anal_pin (core->anal, addr, input + 2);
|
2015-06-30 08:50:46 +00:00
|
|
|
break;
|
|
|
|
default:
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_aep);
|
2015-06-30 08:50:46 +00:00
|
|
|
break;
|
2015-06-16 08:45:54 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-07-28 13:06:06 +00:00
|
|
|
case 'r': // "aer"
|
2014-12-05 06:34:54 +00:00
|
|
|
// 'aer' is an alias for 'ar'
|
2015-12-16 13:35:56 +00:00
|
|
|
cmd_anal_reg (core, input + 1);
|
2015-02-22 10:18:40 +00:00
|
|
|
break;
|
2015-09-08 00:53:33 +00:00
|
|
|
case '*':
|
|
|
|
// XXX: this is wip, not working atm
|
2015-09-09 09:16:49 +00:00
|
|
|
if (core->anal->esil) {
|
2015-09-08 00:53:33 +00:00
|
|
|
r_cons_printf ("trap: %d\n", core->anal->esil->trap);
|
|
|
|
r_cons_printf ("trap-code: %d\n", core->anal->esil->trap_code);
|
|
|
|
} else {
|
|
|
|
eprintf ("esil vm not initialized. run `aei`\n");
|
|
|
|
}
|
|
|
|
break;
|
2014-12-05 06:34:54 +00:00
|
|
|
case ' ':
|
2014-12-05 17:56:33 +00:00
|
|
|
//r_anal_esil_eval (core->anal, input+1);
|
|
|
|
if (!esil) {
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
if (!(core->anal->esil = esil = r_anal_esil_new (stacksize, iotrap, addrsize)))
|
2016-01-20 16:13:30 +00:00
|
|
|
return;
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2017-08-18 12:31:56 +00:00
|
|
|
r_anal_esil_setup (esil, core->anal, romem, stats, noNULL); // setup io
|
2015-09-14 09:31:54 +00:00
|
|
|
r_anal_esil_set_pc (esil, core->offset);
|
2015-12-16 13:35:56 +00:00
|
|
|
r_anal_esil_parse (esil, input + 1);
|
2014-12-05 17:56:33 +00:00
|
|
|
r_anal_esil_dumpstack (esil);
|
|
|
|
r_anal_esil_stack_free (esil);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2017-07-28 13:06:06 +00:00
|
|
|
case 's': // "aes"
|
2015-01-30 00:55:21 +00:00
|
|
|
// "aes" "aeso" "aesu" "aesue"
|
2014-12-05 06:34:54 +00:00
|
|
|
// aes -> single step
|
2017-07-29 10:59:41 +00:00
|
|
|
// aesb -> single step back
|
2015-01-30 00:55:21 +00:00
|
|
|
// aeso -> single step over
|
2014-12-05 06:34:54 +00:00
|
|
|
// aesu -> until address
|
|
|
|
// aesue -> until esil expression
|
2015-01-30 00:55:21 +00:00
|
|
|
switch (input[1]) {
|
2015-08-31 09:53:03 +00:00
|
|
|
case '?':
|
|
|
|
eprintf ("See: ae?~aes\n");
|
|
|
|
break;
|
2015-10-03 12:48:20 +00:00
|
|
|
case 'l': // "aesl"
|
2015-12-16 13:35:56 +00:00
|
|
|
{
|
|
|
|
ut64 pc = r_debug_reg_get (core->dbg, "PC");
|
|
|
|
RAnalOp *op = r_core_anal_op (core, pc);
|
2016-12-12 13:47:42 +00:00
|
|
|
// TODO: honor hint
|
2016-11-02 21:59:32 +00:00
|
|
|
if (!op) {
|
|
|
|
break;
|
|
|
|
}
|
2017-07-29 10:59:41 +00:00
|
|
|
r_core_esil_step (core, UT64_MAX, NULL, NULL);
|
2015-12-16 13:35:56 +00:00
|
|
|
r_debug_reg_set (core->dbg, "PC", pc + op->size);
|
|
|
|
r_anal_esil_set_pc (esil, pc + op->size);
|
|
|
|
r_core_cmd0 (core, ".ar*");
|
|
|
|
} break;
|
2017-07-29 10:59:41 +00:00
|
|
|
case 'b': // "aesb"
|
|
|
|
if (!r_core_esil_step_back (core)) {
|
|
|
|
eprintf ("cannnot step back\n");
|
|
|
|
}
|
|
|
|
r_core_cmd0 (core, ".ar*");
|
|
|
|
break;
|
2015-09-08 23:17:55 +00:00
|
|
|
case 'u': // "aesu"
|
2015-01-30 00:55:21 +00:00
|
|
|
if (input[2] == 'e') {
|
|
|
|
until_expr = input + 3;
|
|
|
|
} else {
|
|
|
|
until_addr = r_num_math (core->num, input + 2);
|
|
|
|
}
|
2017-07-29 10:59:41 +00:00
|
|
|
r_core_esil_step (core, until_addr, until_expr, NULL);
|
2015-06-27 23:42:21 +00:00
|
|
|
r_core_cmd0 (core, ".ar*");
|
2015-01-30 00:55:21 +00:00
|
|
|
break;
|
2015-09-08 23:17:55 +00:00
|
|
|
case 'o': // "aeso"
|
2015-01-30 00:55:21 +00:00
|
|
|
// step over
|
2016-10-03 19:43:55 +00:00
|
|
|
op = r_core_anal_op (core, r_reg_getv (core->anal->reg,
|
|
|
|
r_reg_get_name (core->anal->reg, R_REG_NAME_PC)));
|
2015-01-30 00:55:21 +00:00
|
|
|
if (op && op->type == R_ANAL_OP_TYPE_CALL) {
|
2016-10-03 19:43:55 +00:00
|
|
|
until_addr = op->addr + op->size;
|
2015-01-30 00:55:21 +00:00
|
|
|
}
|
2017-07-29 10:59:41 +00:00
|
|
|
r_core_esil_step (core, until_addr, until_expr, NULL);
|
2015-01-30 00:55:21 +00:00
|
|
|
r_anal_op_free (op);
|
2015-06-27 23:42:21 +00:00
|
|
|
r_core_cmd0 (core, ".ar*");
|
2015-01-30 00:55:21 +00:00
|
|
|
break;
|
2017-12-01 12:46:01 +00:00
|
|
|
case 'p': //"aesp"
|
|
|
|
n = strchr (input, ' ');
|
2018-03-14 12:08:01 +00:00
|
|
|
n1 = n ? strchr (n + 1, ' ') : NULL;
|
|
|
|
if ((!n || !n1) || (!(n + 1) || !(n1 + 1))) {
|
|
|
|
eprintf ("aesp [offset] [num]\n");
|
2017-12-01 12:46:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
adr = r_num_math (core->num, n + 1);
|
|
|
|
off = r_num_math (core->num, n1 + 1);
|
|
|
|
cmd_aespc (core, adr, off);
|
|
|
|
break;
|
|
|
|
case ' ':
|
|
|
|
n = strchr (input, ' ');
|
|
|
|
if (!(n + 1)) {
|
|
|
|
r_core_esil_step (core, until_addr, until_expr, NULL);
|
|
|
|
break;
|
2018-03-12 12:10:59 +00:00
|
|
|
}
|
2017-12-01 12:46:01 +00:00
|
|
|
off = r_num_math (core->num, n + 1);
|
|
|
|
cmd_aespc (core, -1, off);
|
|
|
|
break;
|
2015-01-30 00:55:21 +00:00
|
|
|
default:
|
2017-07-29 10:59:41 +00:00
|
|
|
r_core_esil_step (core, until_addr, until_expr, NULL);
|
2015-06-27 23:42:21 +00:00
|
|
|
r_core_cmd0 (core, ".ar*");
|
2015-01-30 00:55:21 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2017-07-28 13:06:06 +00:00
|
|
|
case 'c': // "aec"
|
2015-09-08 23:17:55 +00:00
|
|
|
if (input[1] == '?') { // "aec?"
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_aec);
|
2015-12-16 13:35:56 +00:00
|
|
|
} else if (input[1] == 's') { // "aecs"
|
2015-09-08 23:17:55 +00:00
|
|
|
const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
|
|
|
|
ut64 newaddr;
|
|
|
|
int ret;
|
|
|
|
for (;;) {
|
|
|
|
op = r_core_anal_op (core, addr);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (!op) {
|
|
|
|
break;
|
|
|
|
}
|
2015-09-08 23:17:55 +00:00
|
|
|
if (op->type == R_ANAL_OP_TYPE_SWI) {
|
2015-12-16 13:35:56 +00:00
|
|
|
eprintf ("syscall at 0x%08" PFMT64x "\n", addr);
|
2015-09-08 23:17:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (op->type == R_ANAL_OP_TYPE_TRAP) {
|
2015-12-16 13:35:56 +00:00
|
|
|
eprintf ("trap at 0x%08" PFMT64x "\n", addr);
|
2015-09-08 23:17:55 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-07-29 10:59:41 +00:00
|
|
|
ret = r_core_esil_step (core, UT64_MAX, NULL, NULL);
|
2015-09-08 23:17:55 +00:00
|
|
|
r_anal_op_free (op);
|
2017-08-28 00:48:17 +00:00
|
|
|
op = NULL;
|
2015-09-08 23:17:55 +00:00
|
|
|
if (core->anal->esil->trap || core->anal->esil->trap_code) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!ret)
|
|
|
|
break;
|
|
|
|
r_core_cmd0 (core, ".ar*");
|
|
|
|
newaddr = r_num_get (core->num, pc);
|
|
|
|
if (addr == newaddr) {
|
|
|
|
addr++;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
addr = newaddr;
|
|
|
|
}
|
|
|
|
}
|
2017-08-28 00:48:17 +00:00
|
|
|
if (op) {
|
|
|
|
r_anal_op_free (op);
|
|
|
|
}
|
2015-09-08 23:17:55 +00:00
|
|
|
} else {
|
|
|
|
// "aec" -> continue until ^C
|
|
|
|
// "aecu" -> until address
|
|
|
|
// "aecue" -> until esil expression
|
|
|
|
if (input[1] == 'u' && input[2] == 'e')
|
|
|
|
until_expr = input + 3;
|
|
|
|
else if (input[1] == 'u')
|
|
|
|
until_addr = r_num_math (core->num, input + 2);
|
|
|
|
else until_expr = "0";
|
2017-07-29 10:59:41 +00:00
|
|
|
r_core_esil_step (core, until_addr, until_expr, NULL);
|
2017-12-19 19:52:24 +00:00
|
|
|
r_core_cmd0 (core, ".ar*");
|
2015-09-08 23:17:55 +00:00
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2015-02-22 10:18:40 +00:00
|
|
|
case 'i': // "aei"
|
2015-12-16 13:35:56 +00:00
|
|
|
switch (input[1]) {
|
2018-04-28 08:00:28 +00:00
|
|
|
case 's': // "aeis"
|
2016-05-09 21:23:45 +00:00
|
|
|
case 'm': // "aeim"
|
2015-12-16 13:35:56 +00:00
|
|
|
cmd_esil_mem (core, input + 2);
|
2015-01-27 11:46:15 +00:00
|
|
|
break;
|
2018-04-28 08:00:28 +00:00
|
|
|
case 'p': // "aeip" // initialize pc = $$
|
2015-11-20 13:46:23 +00:00
|
|
|
r_core_cmd0 (core, "ar PC=$$");
|
2015-07-15 16:18:04 +00:00
|
|
|
break;
|
2015-01-27 11:46:15 +00:00
|
|
|
case '?':
|
2015-03-13 23:14:30 +00:00
|
|
|
cmd_esil_mem (core, "?");
|
2015-01-29 11:16:37 +00:00
|
|
|
break;
|
2015-09-19 17:54:49 +00:00
|
|
|
case '-':
|
|
|
|
if (esil) {
|
|
|
|
sdb_reset (esil->stats);
|
|
|
|
}
|
|
|
|
r_anal_esil_free (esil);
|
|
|
|
core->anal->esil = NULL;
|
|
|
|
break;
|
2017-08-26 23:52:00 +00:00
|
|
|
case 0: //lolololol
|
2015-01-27 11:46:15 +00:00
|
|
|
r_anal_esil_free (esil);
|
|
|
|
// reinitialize
|
2015-07-15 16:18:04 +00:00
|
|
|
{
|
|
|
|
const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
|
|
|
|
if (r_reg_getv (core->anal->reg, pc) == 0LL) {
|
2015-11-05 15:45:45 +00:00
|
|
|
r_core_cmd0 (core, "ar PC=$$");
|
2015-07-15 16:18:04 +00:00
|
|
|
}
|
|
|
|
}
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
if (!(esil = core->anal->esil = r_anal_esil_new (stacksize, iotrap, addrsize))) {
|
2016-01-20 16:13:30 +00:00
|
|
|
return;
|
2017-03-27 01:39:13 +00:00
|
|
|
}
|
2017-08-18 12:31:56 +00:00
|
|
|
r_anal_esil_setup (esil, core->anal, romem, stats, noNULL); // setup io
|
2016-11-14 00:17:58 +00:00
|
|
|
esil->verbose = (int)r_config_get_i (core->config, "esil.verbose");
|
2015-09-08 00:53:33 +00:00
|
|
|
/* restore user settings for interrupt handling */
|
2015-11-05 15:45:45 +00:00
|
|
|
{
|
|
|
|
const char *s = r_config_get (core->config, "cmd.esil.intr");
|
|
|
|
if (s) {
|
|
|
|
char *my = strdup (s);
|
2017-03-25 02:29:03 +00:00
|
|
|
if (my) {
|
2016-01-20 16:13:30 +00:00
|
|
|
r_config_set (core->config, "cmd.esil.intr", my);
|
2017-03-25 02:29:03 +00:00
|
|
|
free (my);
|
|
|
|
}
|
2015-11-05 15:45:45 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-27 11:46:15 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2017-07-28 13:06:06 +00:00
|
|
|
case 'k': // "aek"
|
2014-12-05 06:51:21 +00:00
|
|
|
switch (input[1]) {
|
2014-12-09 16:45:44 +00:00
|
|
|
case '\0':
|
|
|
|
input = "123*";
|
2016-03-16 11:51:26 +00:00
|
|
|
/* fall through */
|
2014-12-09 16:45:44 +00:00
|
|
|
case ' ':
|
2015-04-01 14:06:53 +00:00
|
|
|
if (esil && esil->stats) {
|
2015-12-16 13:35:56 +00:00
|
|
|
char *out = sdb_querys (esil->stats, NULL, 0, input + 2);
|
2014-12-09 16:45:44 +00:00
|
|
|
if (out) {
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_println (out);
|
2014-12-09 16:45:44 +00:00
|
|
|
free (out);
|
|
|
|
}
|
2017-09-30 16:26:29 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("esil.stats is empty. Run 'aei'\n");
|
|
|
|
}
|
2014-12-09 16:45:44 +00:00
|
|
|
break;
|
2016-08-07 15:08:52 +00:00
|
|
|
case '-':
|
2017-09-30 16:26:29 +00:00
|
|
|
if (esil) {
|
|
|
|
sdb_reset (esil->stats);
|
|
|
|
}
|
2016-08-07 15:08:52 +00:00
|
|
|
break;
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
|
|
|
break;
|
2015-10-18 19:38:06 +00:00
|
|
|
case 'f': // "aef"
|
2015-12-16 13:35:56 +00:00
|
|
|
{
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalBlock *bb;
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal,
|
|
|
|
core->offset, R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
|
|
|
if (fcn) {
|
|
|
|
// emulate every instruction in the function recursively across all the basic blocks
|
|
|
|
r_list_foreach (fcn->bbs, iter, bb) {
|
|
|
|
ut64 pc = bb->addr;
|
|
|
|
ut64 end = bb->addr + bb->size;
|
|
|
|
RAnalOp op;
|
|
|
|
ut8 *buf;
|
|
|
|
int ret, bbs = end - pc;
|
|
|
|
if (bbs < 1 || bbs > 0xfffff) {
|
|
|
|
eprintf ("Invalid block size\n");
|
|
|
|
}
|
2017-10-18 01:07:39 +00:00
|
|
|
// eprintf ("[*] Emulating 0x%08"PFMT64x" basic block 0x%08" PFMT64x " - 0x%08" PFMT64x "\r[", fcn->addr, pc, end);
|
2016-08-21 09:39:37 +00:00
|
|
|
buf = calloc (1, bbs + 1);
|
2015-12-16 13:35:56 +00:00
|
|
|
r_io_read_at (core->io, pc, buf, bbs);
|
2016-03-07 00:01:05 +00:00
|
|
|
int left;
|
2015-12-16 13:35:56 +00:00
|
|
|
while (pc < end) {
|
2016-03-07 00:01:05 +00:00
|
|
|
left = R_MIN (end - pc, 32);
|
2015-12-16 13:35:56 +00:00
|
|
|
r_asm_set_pc (core->assembler, pc);
|
2018-03-15 11:31:01 +00:00
|
|
|
ret = r_anal_op (core->anal, &op, addr, buf, left, R_ANAL_OP_MASK_ALL); // read overflow
|
2015-12-16 13:35:56 +00:00
|
|
|
if (ret) {
|
2017-08-26 23:10:19 +00:00
|
|
|
r_reg_set_value_by_role (core->anal->reg, R_REG_NAME_PC, pc);
|
2015-12-16 13:35:56 +00:00
|
|
|
r_anal_esil_parse (esil, R_STRBUF_SAFEGET (&op.esil));
|
|
|
|
r_anal_esil_dumpstack (esil);
|
|
|
|
r_anal_esil_stack_free (esil);
|
|
|
|
pc += op.size;
|
|
|
|
} else {
|
|
|
|
pc += 4; // XXX
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
}
|
2017-10-18 01:07:39 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Cannot find function at 0x%08" PFMT64x "\n", core->offset);
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
} break;
|
2015-04-26 12:35:37 +00:00
|
|
|
case 't': // "aet"
|
2015-03-30 13:15:25 +00:00
|
|
|
switch (input[1]) {
|
2015-09-08 00:53:33 +00:00
|
|
|
case 'r': // "aetr"
|
2015-12-16 13:35:56 +00:00
|
|
|
{
|
|
|
|
// anal ESIL to REIL.
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 09:45:17 +00:00
|
|
|
RAnalEsil *esil = r_anal_esil_new (stacksize, iotrap, addrsize);
|
2018-04-24 07:55:19 +00:00
|
|
|
if (!esil) {
|
2016-01-20 16:13:30 +00:00
|
|
|
return;
|
2018-04-24 07:55:19 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
r_anal_esil_to_reil_setup (esil, core->anal, romem, stats);
|
|
|
|
r_anal_esil_set_pc (esil, core->offset);
|
|
|
|
r_anal_esil_parse (esil, input + 2);
|
|
|
|
r_anal_esil_dumpstack (esil);
|
2016-01-19 23:36:21 +00:00
|
|
|
r_anal_esil_free (esil);
|
2015-12-16 13:35:56 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-07-29 10:59:41 +00:00
|
|
|
case 's': // "aets"
|
|
|
|
switch (input[2]) {
|
|
|
|
case 0:
|
|
|
|
r_anal_esil_session_list (esil);
|
|
|
|
break;
|
|
|
|
case '+':
|
|
|
|
r_anal_esil_session_add (esil);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
r_core_cmd_help (core, help_msg_aets);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2015-09-08 00:53:33 +00:00
|
|
|
default:
|
|
|
|
eprintf ("Unknown command. Use `aetr`.\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2016-01-15 01:51:49 +00:00
|
|
|
case 'A': // "aeA"
|
|
|
|
if (input[1] == '?') {
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_aea);
|
2016-01-15 01:51:49 +00:00
|
|
|
} else if (input[1] == 'r') {
|
|
|
|
cmd_aea (core, 1 + (1<<1), core->offset, r_num_math (core->num, input+2));
|
|
|
|
} else if (input[1] == 'w') {
|
|
|
|
cmd_aea (core, 1 + (1<<2), core->offset, r_num_math (core->num, input+2));
|
|
|
|
} else if (input[1] == 'n') {
|
|
|
|
cmd_aea (core, 1 + (1<<3), core->offset, r_num_math (core->num, input+2));
|
2017-03-16 08:54:13 +00:00
|
|
|
} else if (input[1] == 'j') {
|
|
|
|
cmd_aea (core, 1 + (1<<4), core->offset, r_num_math (core->num, input+2));
|
2017-07-06 23:46:24 +00:00
|
|
|
} else if (input[1] == '*') {
|
|
|
|
cmd_aea (core, 1 + (1<<5), core->offset, r_num_math (core->num, input+2));
|
2016-01-15 01:51:49 +00:00
|
|
|
} else if (input[1] == 'f') {
|
2016-01-15 00:50:08 +00:00
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, -1);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (fcn) {
|
|
|
|
cmd_aea (core, 1, fcn->addr, r_anal_fcn_size (fcn));
|
|
|
|
}
|
2016-01-15 00:50:08 +00:00
|
|
|
} else {
|
|
|
|
cmd_aea (core, 1, core->offset, (int)r_num_math (core->num, input+2));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'a': // "aea"
|
2016-01-15 01:51:49 +00:00
|
|
|
if (input[1] == '?') {
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_aea);
|
2016-01-15 01:51:49 +00:00
|
|
|
} else if (input[1] == 'r') {
|
|
|
|
cmd_aea (core, 1<<1, core->offset, r_num_math (core->num, input+2));
|
|
|
|
} else if (input[1] == 'w') {
|
|
|
|
cmd_aea (core, 1<<2, core->offset, r_num_math (core->num, input+2));
|
|
|
|
} else if (input[1] == 'n') {
|
|
|
|
cmd_aea (core, 1<<3, core->offset, r_num_math (core->num, input+2));
|
2017-03-16 08:54:13 +00:00
|
|
|
} else if (input[1] == 'j') {
|
|
|
|
cmd_aea (core, 1<<4, core->offset, r_num_math (core->num, input+2));
|
2017-07-06 23:46:24 +00:00
|
|
|
} else if (input[1] == '*') {
|
|
|
|
cmd_aea (core, 1<<5, core->offset, r_num_math (core->num, input+2));
|
2016-01-15 01:51:49 +00:00
|
|
|
} else if (input[1] == 'f') {
|
2016-01-15 00:50:08 +00:00
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, -1);
|
2017-09-07 13:08:44 +00:00
|
|
|
// "aeafj"
|
2016-11-24 00:56:49 +00:00
|
|
|
if (fcn) {
|
2017-09-07 13:08:44 +00:00
|
|
|
switch (input[2]) {
|
|
|
|
case 'j': // "aeafj"
|
|
|
|
cmd_aea (core, 1<<4, fcn->addr, r_anal_fcn_size (fcn));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cmd_aea (core, 1, fcn->addr, r_anal_fcn_size (fcn));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2016-11-24 00:56:49 +00:00
|
|
|
}
|
2016-01-15 00:50:08 +00:00
|
|
|
} else {
|
2018-02-19 14:23:16 +00:00
|
|
|
const char *arg = input[1]? input + 2: "";
|
|
|
|
ut64 len = r_num_math (core->num, arg);
|
|
|
|
cmd_aea (core, 0, core->offset, len);
|
2016-01-15 00:50:08 +00:00
|
|
|
}
|
|
|
|
break;
|
2018-03-12 12:10:59 +00:00
|
|
|
case 'x': { // "aex"
|
2018-03-05 08:25:20 +00:00
|
|
|
char *hex;
|
|
|
|
int ret, bufsz;
|
2016-03-22 23:44:56 +00:00
|
|
|
|
2018-03-05 08:25:20 +00:00
|
|
|
input = r_str_trim_ro (input + 1);
|
|
|
|
hex = strdup (input);
|
|
|
|
if (!hex) {
|
|
|
|
break;
|
2016-11-24 00:56:49 +00:00
|
|
|
}
|
2016-03-22 23:44:56 +00:00
|
|
|
|
2017-03-25 01:30:00 +00:00
|
|
|
RAnalOp aop = R_EMPTY;
|
2016-03-22 23:44:56 +00:00
|
|
|
bufsz = r_hex_str2bin (hex, (ut8*)hex);
|
|
|
|
ret = r_anal_op (core->anal, &aop, core->offset,
|
2018-03-15 11:31:01 +00:00
|
|
|
(const ut8*)hex, bufsz, R_ANAL_OP_MASK_ALL);
|
2016-03-22 23:44:56 +00:00
|
|
|
if (ret>0) {
|
2016-03-25 09:18:45 +00:00
|
|
|
const char *str = R_STRBUF_SAFEGET (&aop.esil);
|
|
|
|
char *str2 = r_str_newf (" %s", str);
|
2016-03-22 23:44:56 +00:00
|
|
|
cmd_anal_esil (core, str2);
|
2016-03-25 09:18:45 +00:00
|
|
|
free (str2);
|
2016-03-22 23:44:56 +00:00
|
|
|
}
|
|
|
|
r_anal_op_fini (&aop);
|
|
|
|
break;
|
2018-03-05 08:25:20 +00:00
|
|
|
}
|
2017-07-28 13:06:06 +00:00
|
|
|
case '?': // "ae?"
|
2015-12-16 13:35:56 +00:00
|
|
|
if (input[1] == '?') {
|
2017-07-25 07:11:29 +00:00
|
|
|
r_core_cmd_help (core, help_detail_ae);
|
2015-04-01 01:01:44 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-07-24 15:41:50 +00:00
|
|
|
/* fallthrough */
|
|
|
|
default:
|
|
|
|
r_core_cmd_help (core, help_msg_ae);
|
|
|
|
break;
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-04 21:52:10 +00:00
|
|
|
static void cmd_anal_bytes(RCore *core, const char *input) {
|
|
|
|
int len = core->blocksize;
|
|
|
|
int tbs = len;
|
|
|
|
if (input[0]) {
|
|
|
|
len = (int)r_num_get (core->num, input + 1);
|
|
|
|
if (len > tbs) {
|
|
|
|
r_core_block_size (core, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
core_anal_bytes (core, core->block, len, 0, input[0]);
|
|
|
|
if (tbs != core->blocksize) {
|
|
|
|
r_core_block_size (core, tbs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-05 06:34:54 +00:00
|
|
|
static void cmd_anal_opcode(RCore *core, const char *input) {
|
|
|
|
int l, len = core->blocksize;
|
|
|
|
ut32 tbs = core->blocksize;
|
|
|
|
|
2014-12-05 06:51:21 +00:00
|
|
|
switch (input[0]) {
|
2017-07-24 15:41:50 +00:00
|
|
|
case '?':
|
|
|
|
r_core_cmd_help (core, help_msg_ao);
|
|
|
|
break;
|
2018-04-08 12:00:21 +00:00
|
|
|
case 's': // "aos"
|
2017-07-17 10:58:48 +00:00
|
|
|
case 'j': // "aoj"
|
|
|
|
case 'e': // "aoe"
|
2016-05-31 06:33:18 +00:00
|
|
|
case 'r': {
|
2015-12-16 13:35:56 +00:00
|
|
|
int count = 1;
|
|
|
|
if (input[1] && input[2]) {
|
|
|
|
l = (int)r_num_get (core->num, input + 1);
|
2016-08-01 14:18:24 +00:00
|
|
|
if (l > 0) {
|
|
|
|
count = l;
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
if (l > tbs) {
|
|
|
|
r_core_block_size (core, l * 4);
|
2018-04-08 12:00:21 +00:00
|
|
|
// len = l;
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
} else {
|
|
|
|
len = l = core->blocksize;
|
|
|
|
count = 1;
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2016-05-31 06:33:18 +00:00
|
|
|
core_anal_bytes (core, core->block, len, count, input[0]);
|
2018-01-27 22:32:47 +00:00
|
|
|
}
|
|
|
|
break;
|
2015-05-21 19:05:22 +00:00
|
|
|
case '*':
|
|
|
|
r_core_anal_hint_list (core->anal, input[0]);
|
|
|
|
break;
|
2015-12-16 13:35:56 +00:00
|
|
|
default: {
|
|
|
|
int count = 0;
|
|
|
|
if (input[0]) {
|
|
|
|
l = (int)r_num_get (core->num, input + 1);
|
2016-08-21 09:39:37 +00:00
|
|
|
if (l > 0) {
|
|
|
|
count = l;
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
if (l > tbs) {
|
|
|
|
r_core_block_size (core, l * 4);
|
|
|
|
//len = l;
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
} else {
|
|
|
|
len = l = core->blocksize;
|
|
|
|
count = 1;
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
core_anal_bytes (core, core->block, len, count, 0);
|
2018-01-27 22:32:47 +00:00
|
|
|
break;
|
2015-12-16 13:35:56 +00:00
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-06 22:30:48 +00:00
|
|
|
static void cmd_anal_jumps(RCore *core, const char *input) {
|
|
|
|
r_core_cmdf (core, "af @@= `ax~ref.code.jmp[1]`");
|
|
|
|
}
|
|
|
|
|
2016-11-14 11:09:29 +00:00
|
|
|
// TODO: cleanup to reuse code
|
|
|
|
static void cmd_anal_aftertraps(RCore *core, const char *input) {
|
|
|
|
int bufi, minop = 1; // 4
|
|
|
|
ut8 *buf;
|
|
|
|
RBinFile *binfile;
|
|
|
|
RAnalOp op;
|
|
|
|
ut64 addr, addr_end;
|
|
|
|
ut64 len = r_num_math (core->num, input);
|
|
|
|
if (len > 0xffffff) {
|
|
|
|
eprintf ("Too big\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
binfile = r_core_bin_cur (core);
|
|
|
|
if (!binfile) {
|
2017-08-18 12:31:56 +00:00
|
|
|
eprintf ("cur binfile NULL\n");
|
2016-11-14 11:09:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
addr = core->offset;
|
|
|
|
if (!len) {
|
|
|
|
// ignore search.in to avoid problems. analysis != search
|
2017-10-30 23:20:26 +00:00
|
|
|
RIOSection *sec = r_io_section_vget (core->io, addr);
|
|
|
|
if (sec && sec->flags & 1) {
|
2016-11-14 11:09:29 +00:00
|
|
|
// search in current section
|
2017-10-30 23:20:26 +00:00
|
|
|
if (sec->size > binfile->size) {
|
|
|
|
addr = sec->vaddr;
|
|
|
|
if (binfile->size > sec->paddr) {
|
|
|
|
len = binfile->size - sec->paddr;
|
2016-11-14 11:09:29 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Opps something went wrong aac\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
2017-10-30 23:20:26 +00:00
|
|
|
addr = sec->vaddr;
|
|
|
|
len = sec->size;
|
2016-11-14 11:09:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
2017-10-30 23:20:26 +00:00
|
|
|
if (sec && sec->vaddr != sec->paddr && binfile->size > (core->offset - sec->vaddr + sec->paddr)) {
|
2017-08-22 07:42:16 +00:00
|
|
|
len = binfile->size - (core->offset - sec->vaddr + sec->paddr);
|
2016-11-14 11:09:29 +00:00
|
|
|
} else {
|
|
|
|
if (binfile->size > core->offset) {
|
2017-10-30 23:20:26 +00:00
|
|
|
len = binfile->size - core->offset;
|
2016-11-14 11:09:29 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Oops invalid range\n");
|
|
|
|
len = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
addr_end = addr + len;
|
|
|
|
if (!(buf = malloc (4096))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
bufi = 0;
|
|
|
|
int trapcount = 0;
|
|
|
|
int nopcount = 0;
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2016-11-14 11:09:29 +00:00
|
|
|
while (addr < addr_end) {
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
2016-11-14 11:09:29 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// TODO: too many ioreads here
|
|
|
|
if (bufi > 4000) {
|
|
|
|
bufi = 0;
|
|
|
|
}
|
|
|
|
if (!bufi) {
|
|
|
|
r_io_read_at (core->io, addr, buf, 4096);
|
|
|
|
}
|
2018-03-15 11:31:01 +00:00
|
|
|
if (r_anal_op (core->anal, &op, addr, buf + bufi, 4096 - bufi, R_ANAL_OP_MASK_ALL)) {
|
2016-11-14 11:09:29 +00:00
|
|
|
if (op.size < 1) {
|
|
|
|
// XXX must be +4 on arm/mips/.. like we do in disasm.c
|
|
|
|
op.size = minop;
|
|
|
|
}
|
|
|
|
if (op.type == R_ANAL_OP_TYPE_TRAP) {
|
|
|
|
trapcount ++;
|
|
|
|
} else if (op.type == R_ANAL_OP_TYPE_NOP) {
|
|
|
|
nopcount ++;
|
|
|
|
} else {
|
|
|
|
if (nopcount > 1) {
|
|
|
|
r_cons_printf ("af @ 0x%08"PFMT64x"\n", addr);
|
|
|
|
nopcount = 0;
|
|
|
|
}
|
|
|
|
if (trapcount > 0) {
|
|
|
|
r_cons_printf ("af @ 0x%08"PFMT64x"\n", addr);
|
|
|
|
trapcount = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
op.size = minop;
|
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
addr += (op.size > 0)? op.size : 1;
|
|
|
|
bufi += (op.size > 0)? op.size : 1;
|
2016-11-14 11:09:29 +00:00
|
|
|
r_anal_op_fini (&op);
|
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_pop ();
|
2016-11-14 11:09:29 +00:00
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
|
2017-02-08 13:44:46 +00:00
|
|
|
static void cmd_anal_blocks(RCore *core, const char *input) {
|
2018-01-27 22:10:02 +00:00
|
|
|
ut64 from , to;
|
|
|
|
char *arg = strchr (input, ' ');
|
2017-07-10 20:45:24 +00:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2018-01-27 22:10:02 +00:00
|
|
|
#if 0
|
2017-08-22 07:42:16 +00:00
|
|
|
ls_foreach (core->io->sections, iter, s) {
|
2017-02-09 23:02:39 +00:00
|
|
|
/* is executable */
|
2017-03-15 01:22:54 +00:00
|
|
|
if (!(s->flags & R_IO_EXEC)) {
|
2017-02-09 23:02:39 +00:00
|
|
|
continue;
|
|
|
|
}
|
2017-04-11 22:27:58 +00:00
|
|
|
min = s->vaddr;
|
|
|
|
max = s->vaddr + s->vsize;
|
2017-06-06 16:28:43 +00:00
|
|
|
r_core_cmdf (core, "abb%s 0x%08"PFMT64x" @ 0x%08"PFMT64x, input, (max - min), min);
|
2017-07-10 20:45:24 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
goto ctrl_c;
|
|
|
|
}
|
2017-02-09 23:02:39 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
if (ls_empty (core->io->sections)) {
|
2017-02-09 23:02:39 +00:00
|
|
|
min = core->offset;
|
|
|
|
max = 0xffff + min;
|
2017-06-06 16:28:43 +00:00
|
|
|
r_core_cmdf (core, "abb%s 0x%08"PFMT64x" @ 0x%08"PFMT64x, input, (max - min), min);
|
2017-07-10 20:45:24 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
goto ctrl_c;
|
|
|
|
}
|
2017-02-09 23:02:39 +00:00
|
|
|
}
|
2018-01-27 22:10:02 +00:00
|
|
|
#endif
|
|
|
|
if (!arg) {
|
|
|
|
RList *list = r_core_get_boundaries_prot (core, R_IO_EXEC, NULL, "anal");
|
|
|
|
RListIter *iter;
|
|
|
|
RIOMap* map;
|
|
|
|
r_list_foreach (list, iter, map) {
|
|
|
|
from = map->itv.addr;
|
|
|
|
to = r_itv_end (map->itv);
|
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
goto ctrl_c;
|
|
|
|
}
|
|
|
|
if (!from && !to) {
|
|
|
|
eprintf ("Cannot determine search boundaries\n");
|
|
|
|
} else if (to - from > UT32_MAX) {
|
|
|
|
eprintf ("Skipping huge range\n");
|
|
|
|
} else {
|
|
|
|
r_core_cmdf (core, "abb 0x%08"PFMT64x" @ 0x%08"PFMT64x, (to - from), from);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int sz = r_num_math (core->num, arg + 1);
|
|
|
|
r_core_cmdf (core, "abb 0x%08"PFMT64x" @ 0x%08"PFMT64x, sz, core->offset);
|
|
|
|
}
|
2017-07-10 20:45:24 +00:00
|
|
|
ctrl_c:
|
|
|
|
r_cons_break_pop ();
|
2017-02-08 13:44:46 +00:00
|
|
|
}
|
|
|
|
|
2017-02-19 20:06:32 +00:00
|
|
|
static void _anal_calls(RCore *core, ut64 addr, ut64 addr_end) {
|
|
|
|
RAnalOp op;
|
|
|
|
int depth = r_config_get_i (core->config, "anal.depth");
|
2017-09-04 19:41:09 +00:00
|
|
|
const int addrbytes = core->io->addrbytes;
|
2018-01-15 13:01:26 +00:00
|
|
|
const int bsz = 4096;
|
2018-04-28 08:00:28 +00:00
|
|
|
int bufi = 0;
|
|
|
|
int bufi_max = bsz - 16;
|
2018-01-15 13:01:26 +00:00
|
|
|
if (addr_end - addr > UT32_MAX) {
|
|
|
|
return;
|
|
|
|
}
|
2018-04-28 08:00:28 +00:00
|
|
|
ut8 *buf = malloc (bsz);
|
|
|
|
ut8 *block0 = calloc (1, bsz);
|
|
|
|
ut8 *block1 = malloc (bsz);
|
|
|
|
if (!buf || !block0 || !block1) {
|
2018-02-27 17:40:15 +00:00
|
|
|
eprintf ("Error: cannot allocate buf or block\n");
|
|
|
|
free (buf);
|
2018-04-28 08:00:28 +00:00
|
|
|
free (block0);
|
|
|
|
free (block1);
|
2017-02-20 11:15:58 +00:00
|
|
|
return;
|
2017-02-19 22:48:18 +00:00
|
|
|
}
|
2018-04-28 08:00:28 +00:00
|
|
|
memset (block1, -1, bsz);
|
2018-03-23 11:46:34 +00:00
|
|
|
int minop = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_MIN_OP_SIZE);
|
2018-04-17 19:52:55 +00:00
|
|
|
if (minop < 1) {
|
|
|
|
minop = 1;
|
|
|
|
}
|
2018-04-28 08:00:28 +00:00
|
|
|
int setBits = r_config_get_i (core->config, "asm.bits");
|
|
|
|
r_cons_break_push (NULL, NULL);
|
2017-02-19 20:06:32 +00:00
|
|
|
while (addr < addr_end) {
|
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// TODO: too many ioreads here
|
2018-04-28 08:00:28 +00:00
|
|
|
if (bufi > bufi_max) {
|
2017-02-19 20:06:32 +00:00
|
|
|
bufi = 0;
|
|
|
|
}
|
|
|
|
if (!bufi) {
|
2018-04-28 08:00:28 +00:00
|
|
|
(void)r_io_read_at (core->io, addr, buf, bsz);
|
2017-02-19 20:06:32 +00:00
|
|
|
}
|
2018-04-28 08:00:28 +00:00
|
|
|
if (!memcmp (buf, block0, bsz) || !memcmp (buf, block1, bsz)) {
|
2017-12-14 18:48:04 +00:00
|
|
|
//eprintf ("Error: skipping uninitialized block \n");
|
2018-01-15 13:01:26 +00:00
|
|
|
addr += bsz;
|
|
|
|
continue;
|
2017-12-14 18:48:04 +00:00
|
|
|
}
|
2018-04-28 08:00:28 +00:00
|
|
|
RAnalHint *hint = r_anal_hint_get (core->anal, addr);
|
|
|
|
if (hint && hint->bits) {
|
|
|
|
setBits = hint->bits;
|
|
|
|
}
|
|
|
|
if (setBits != core->assembler->bits) {
|
|
|
|
r_config_set_i (core->config, "asm.bits", setBits);
|
2018-03-12 12:10:59 +00:00
|
|
|
}
|
2018-04-17 19:52:55 +00:00
|
|
|
if (r_anal_op (core->anal, &op, addr, buf + bufi, bsz - bufi, 0) > 0) {
|
2017-02-19 20:06:32 +00:00
|
|
|
if (op.size < 1) {
|
|
|
|
op.size = minop;
|
|
|
|
}
|
|
|
|
if (op.type == R_ANAL_OP_TYPE_CALL) {
|
|
|
|
#if JAYRO_03
|
|
|
|
if (!anal_is_bad_call (core, from, to, addr, buf, bufi)) {
|
|
|
|
fcn = r_anal_get_fcn_in (core->anal, op.jump, R_ANAL_FCN_TYPE_ROOT);
|
|
|
|
if (!fcn) {
|
2018-02-09 21:25:30 +00:00
|
|
|
r_core_anal_fcn (core, op.jump, addr, R_ANAL_REF_TYPE_CALL, depth);
|
2017-02-19 20:06:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
// add xref here
|
2018-02-09 21:25:30 +00:00
|
|
|
r_anal_xrefs_set (core->anal, addr, op.jump, R_ANAL_REF_TYPE_CALL);
|
2017-08-23 22:19:57 +00:00
|
|
|
if (r_io_is_valid_offset (core->io, op.jump, 1)) {
|
2018-02-09 21:25:30 +00:00
|
|
|
r_core_anal_fcn (core, op.jump, addr, R_ANAL_REF_TYPE_CALL, depth);
|
2017-02-19 20:06:32 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
op.size = minop;
|
|
|
|
}
|
2018-04-17 19:52:55 +00:00
|
|
|
if ((int)op.size < 1) {
|
|
|
|
op.size = minop;
|
|
|
|
}
|
2017-08-05 10:20:17 +00:00
|
|
|
addr += op.size;
|
|
|
|
bufi += addrbytes * op.size;
|
2017-02-19 20:06:32 +00:00
|
|
|
r_anal_op_fini (&op);
|
|
|
|
}
|
2018-04-28 08:00:28 +00:00
|
|
|
r_cons_break_pop ();
|
2018-01-15 13:01:26 +00:00
|
|
|
free (buf);
|
2018-04-28 08:00:28 +00:00
|
|
|
free (block0);
|
|
|
|
free (block1);
|
2017-02-19 20:06:32 +00:00
|
|
|
}
|
|
|
|
|
2017-09-08 14:44:37 +00:00
|
|
|
static void cmd_anal_calls(RCore *core, const char *input, bool only_print_flag) {
|
2017-02-18 22:31:04 +00:00
|
|
|
RList *ranges = NULL;
|
|
|
|
RIOMap *r;
|
2015-05-23 11:35:31 +00:00
|
|
|
RBinFile *binfile;
|
2017-09-01 06:41:03 +00:00
|
|
|
ut64 addr;
|
2015-01-18 01:49:19 +00:00
|
|
|
ut64 len = r_num_math (core->num, input);
|
2014-12-13 10:28:17 +00:00
|
|
|
if (len > 0xffffff) {
|
|
|
|
eprintf ("Too big\n");
|
|
|
|
return;
|
|
|
|
}
|
2015-05-23 11:35:31 +00:00
|
|
|
binfile = r_core_bin_cur (core);
|
2015-11-19 22:49:45 +00:00
|
|
|
addr = core->offset;
|
2017-01-30 08:57:07 +00:00
|
|
|
if (binfile) {
|
2017-02-18 22:31:04 +00:00
|
|
|
if (len) {
|
2017-02-19 20:06:32 +00:00
|
|
|
RIOMap *m = R_NEW0 (RIOMap);
|
2017-09-01 06:41:03 +00:00
|
|
|
m->itv.addr = addr;
|
|
|
|
m->itv.size = len;
|
2017-02-18 22:31:04 +00:00
|
|
|
r_list_append (ranges, m);
|
|
|
|
} else {
|
2018-01-27 22:10:02 +00:00
|
|
|
ranges = r_core_get_boundaries_prot (core, R_IO_EXEC, NULL, "anal");
|
2017-02-18 22:31:04 +00:00
|
|
|
}
|
2015-05-23 11:35:31 +00:00
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2017-02-19 22:29:55 +00:00
|
|
|
if (!binfile || !r_list_length (ranges)) {
|
2017-09-11 22:25:01 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RIOMap *map;
|
2017-07-29 11:55:40 +00:00
|
|
|
r_list_free (ranges);
|
2018-01-27 22:10:02 +00:00
|
|
|
ranges = r_core_get_boundaries_prot (core, 0, NULL, "anal");
|
2017-09-11 22:25:01 +00:00
|
|
|
r_list_foreach (ranges, iter, map) {
|
2017-09-01 06:41:03 +00:00
|
|
|
ut64 addr = map->itv.addr;
|
2017-09-11 22:25:01 +00:00
|
|
|
if (only_print_flag) {
|
|
|
|
r_cons_printf ("f fcn.0x%08"PFMT64x" %d 0x%08"PFMT64x"\n",
|
2017-09-01 06:41:03 +00:00
|
|
|
addr, map->itv.size, addr);
|
2017-09-11 22:25:01 +00:00
|
|
|
} else {
|
2017-09-01 06:41:03 +00:00
|
|
|
_anal_calls (core, addr, r_itv_end (map->itv));
|
2017-09-11 22:25:01 +00:00
|
|
|
}
|
2017-09-08 14:44:37 +00:00
|
|
|
}
|
2017-02-19 22:29:55 +00:00
|
|
|
} else {
|
|
|
|
RListIter *iter;
|
|
|
|
if (binfile) {
|
|
|
|
r_list_foreach (ranges, iter, r) {
|
2017-09-01 06:41:03 +00:00
|
|
|
addr = r->itv.addr;
|
2017-02-19 22:29:55 +00:00
|
|
|
//this normally will happen on fuzzed binaries, dunno if with huge
|
|
|
|
//binaries as well
|
2017-12-16 19:39:13 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
2018-03-12 12:10:59 +00:00
|
|
|
}
|
2017-09-08 14:44:37 +00:00
|
|
|
if (only_print_flag) {
|
2017-09-11 22:25:01 +00:00
|
|
|
r_cons_printf ("f fcn.0x%08"PFMT64x" %d 0x%08"PFMT64x"\n",
|
2017-09-01 06:41:03 +00:00
|
|
|
addr, r->itv.size, addr);
|
2017-09-08 14:44:37 +00:00
|
|
|
} else {
|
2017-09-01 06:41:03 +00:00
|
|
|
_anal_calls (core, addr, r_itv_end (r->itv));
|
2017-09-08 14:44:37 +00:00
|
|
|
}
|
2017-02-18 22:31:04 +00:00
|
|
|
}
|
2014-12-13 10:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_pop ();
|
2017-02-19 22:03:38 +00:00
|
|
|
r_list_free (ranges);
|
2014-12-13 10:28:17 +00:00
|
|
|
}
|
|
|
|
|
2015-10-30 02:07:22 +00:00
|
|
|
static void cmd_asf(RCore *core, const char *input) {
|
|
|
|
char *ret;
|
|
|
|
if (input[0] == ' ') {
|
2015-12-16 13:35:56 +00:00
|
|
|
ret = sdb_querys (core->anal->sdb_fcnsign, NULL, 0, input + 1);
|
2015-10-30 02:07:22 +00:00
|
|
|
} else {
|
|
|
|
ret = sdb_querys (core->anal->sdb_fcnsign, NULL, 0, "*");
|
|
|
|
}
|
2016-06-26 04:16:57 +00:00
|
|
|
if (ret && *ret) {
|
|
|
|
r_cons_println (ret);
|
|
|
|
}
|
2015-10-30 02:34:40 +00:00
|
|
|
free (ret);
|
2015-10-30 02:07:22 +00:00
|
|
|
}
|
|
|
|
|
2014-12-05 06:34:54 +00:00
|
|
|
static void cmd_anal_syscall(RCore *core, const char *input) {
|
2014-12-05 17:56:33 +00:00
|
|
|
RSyscallItem *si;
|
|
|
|
RListIter *iter;
|
|
|
|
RList *list;
|
2017-08-14 16:53:22 +00:00
|
|
|
RNum *num = NULL;
|
2015-01-30 00:55:21 +00:00
|
|
|
char *out;
|
|
|
|
int n;
|
2014-12-05 17:56:33 +00:00
|
|
|
|
2014-12-05 06:51:21 +00:00
|
|
|
switch (input[0]) {
|
2016-11-17 15:30:12 +00:00
|
|
|
case 'c': // "asc"
|
|
|
|
if (input[1] == 'a') {
|
|
|
|
if (input[2] == ' ') {
|
2017-08-14 16:53:22 +00:00
|
|
|
if (!isalpha (input[3]) && (n = r_num_math (num, input + 3)) >= 0 ) {
|
2016-11-17 15:30:12 +00:00
|
|
|
si = r_syscall_get (core->anal->syscall, n, -1);
|
|
|
|
if (si)
|
|
|
|
r_cons_printf (".equ SYS_%s %d\n", si->name, n);
|
|
|
|
else eprintf ("Unknown syscall number\n");
|
|
|
|
} else {
|
2017-08-14 16:53:22 +00:00
|
|
|
n = r_syscall_get_num (core->anal->syscall, input + 3);
|
2016-11-17 15:30:12 +00:00
|
|
|
if (n != -1) {
|
2017-08-14 16:53:22 +00:00
|
|
|
r_cons_printf (".equ SYS_%s %d\n", input + 3, n);
|
2016-11-17 15:30:12 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Unknown syscall name\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
list = r_syscall_list (core->anal->syscall);
|
|
|
|
r_list_foreach (list, iter, si) {
|
|
|
|
r_cons_printf (".equ SYS_%s %d\n",
|
|
|
|
si->name, (ut32)si->num);
|
|
|
|
}
|
|
|
|
r_list_free (list);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (input[1] == ' ') {
|
2017-08-14 16:53:22 +00:00
|
|
|
if (!isalpha (input[2]) && (n = r_num_math (num, input + 2)) >= 0 ) {
|
2016-11-17 15:30:12 +00:00
|
|
|
si = r_syscall_get (core->anal->syscall, n, -1);
|
|
|
|
if (si)
|
|
|
|
r_cons_printf ("#define SYS_%s %d\n", si->name, n);
|
|
|
|
else eprintf ("Unknown syscall number\n");
|
|
|
|
} else {
|
|
|
|
n = r_syscall_get_num (core->anal->syscall, input + 2);
|
|
|
|
if (n != -1) {
|
|
|
|
r_cons_printf ("#define SYS_%s %d\n", input + 2, n);
|
|
|
|
} else {
|
|
|
|
eprintf ("Unknown syscall name\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
list = r_syscall_list (core->anal->syscall);
|
|
|
|
r_list_foreach (list, iter, si) {
|
|
|
|
r_cons_printf ("#define SYS_%s %d\n",
|
|
|
|
si->name, (ut32)si->num);
|
|
|
|
}
|
|
|
|
r_list_free (list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2015-10-30 02:07:22 +00:00
|
|
|
case 'f': // "asf"
|
2015-12-16 13:35:56 +00:00
|
|
|
cmd_asf (core, input + 1);
|
2015-10-30 02:07:22 +00:00
|
|
|
break;
|
2014-12-05 06:34:54 +00:00
|
|
|
case 'l': // "asl"
|
2014-12-05 06:51:21 +00:00
|
|
|
if (input[1] == ' ') {
|
2017-08-14 16:53:22 +00:00
|
|
|
if (!isalpha (input[2]) && (n = r_num_math (num, input + 2)) >= 0 ) {
|
2014-12-05 17:56:33 +00:00
|
|
|
si = r_syscall_get (core->anal->syscall, n, -1);
|
2015-12-16 13:35:56 +00:00
|
|
|
if (si)
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_println (si->name);
|
2014-12-05 06:34:54 +00:00
|
|
|
else eprintf ("Unknown syscall number\n");
|
|
|
|
} else {
|
2015-12-16 13:35:56 +00:00
|
|
|
n = r_syscall_get_num (core->anal->syscall, input + 2);
|
2016-11-16 02:02:50 +00:00
|
|
|
if (n != -1) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("%d\n", n);
|
2016-11-16 02:02:50 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Unknown syscall name\n");
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
|
|
|
} else {
|
2014-12-05 17:56:33 +00:00
|
|
|
list = r_syscall_list (core->anal->syscall);
|
2014-12-05 06:34:54 +00:00
|
|
|
r_list_foreach (list, iter, si) {
|
2016-11-16 02:02:50 +00:00
|
|
|
r_cons_printf ("%s = 0x%02x.%u\n",
|
|
|
|
si->name, (ut32)si->swi, (ut32)si->num);
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
|
|
|
r_list_free (list);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'j': // "asj"
|
2014-12-05 17:56:33 +00:00
|
|
|
list = r_syscall_list (core->anal->syscall);
|
|
|
|
r_cons_printf ("[");
|
|
|
|
r_list_foreach (list, iter, si) {
|
|
|
|
r_cons_printf ("{\"name\":\"%s\","
|
2015-12-16 13:35:56 +00:00
|
|
|
"\"swi\":\"%d\",\"num\":\"%d\"}",
|
|
|
|
si->name, si->swi, si->num);
|
2016-11-24 00:56:49 +00:00
|
|
|
if (iter->n) {
|
|
|
|
r_cons_printf (",");
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2014-12-05 17:56:33 +00:00
|
|
|
r_cons_printf ("]\n");
|
|
|
|
r_list_free (list);
|
2014-12-05 06:34:54 +00:00
|
|
|
// JSON support
|
|
|
|
break;
|
|
|
|
case '\0':
|
2015-10-29 10:54:00 +00:00
|
|
|
cmd_syscall_do (core, -1); //n);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
|
|
|
case ' ':
|
2015-12-16 13:35:56 +00:00
|
|
|
cmd_syscall_do (core, (int)r_num_get (core->num, input + 1));
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
|
|
|
case 'k': // "ask"
|
2016-06-17 21:17:24 +00:00
|
|
|
if (input[1] == ' ') {
|
|
|
|
out = sdb_querys (core->anal->syscall->db, NULL, 0, input + 2);
|
|
|
|
if (out) {
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_println (out);
|
2016-06-17 21:17:24 +00:00
|
|
|
free (out);
|
|
|
|
}
|
|
|
|
} else eprintf ("|ERROR| Usage: ask [query]\n");
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case '?':
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_as);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-01 09:50:56 +00:00
|
|
|
static void anal_axg (RCore *core, const char *input, int level, Sdb *db, int opts) {
|
2016-02-23 01:31:53 +00:00
|
|
|
char arg[32], pre[128];
|
|
|
|
RList *xrefs;
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalRef *ref;
|
|
|
|
ut64 addr = core->offset;
|
2018-03-01 09:50:56 +00:00
|
|
|
int is_json = opts & R_CORE_ANAL_JSON;
|
2016-02-23 01:31:53 +00:00
|
|
|
if (input && *input) {
|
|
|
|
addr = r_num_math (core->num, input);
|
|
|
|
}
|
2016-11-16 02:02:50 +00:00
|
|
|
int spaces = (level + 1) * 2;
|
|
|
|
if (spaces > sizeof (pre) - 4) {
|
|
|
|
spaces = sizeof (pre) - 4;
|
2016-02-23 01:31:53 +00:00
|
|
|
}
|
2016-11-16 02:02:50 +00:00
|
|
|
memset (pre, ' ', sizeof (pre));
|
2016-02-23 01:31:53 +00:00
|
|
|
strcpy (pre+spaces, "- ");
|
|
|
|
|
|
|
|
xrefs = r_anal_xrefs_get (core->anal, addr);
|
|
|
|
if (!r_list_empty (xrefs)) {
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, -1);
|
|
|
|
if (fcn) {
|
2018-03-01 09:50:56 +00:00
|
|
|
if (is_json) {
|
2018-03-12 12:10:59 +00:00
|
|
|
r_cons_printf ("{\"%"PFMT64d"\":{\"type\":\"fcn\","
|
2018-03-01 09:50:56 +00:00
|
|
|
"\"fcn_addr\":%"PFMT64d",\"name\":\"%s\",\"refs\":[",
|
|
|
|
addr, fcn->addr, fcn->name);
|
|
|
|
} else {
|
|
|
|
//if (sdb_add (db, fcn->name, "1", 0)) {
|
2016-02-23 01:31:53 +00:00
|
|
|
r_cons_printf ("%s0x%08"PFMT64x" fcn 0x%08"PFMT64x" %s\n",
|
2016-11-16 02:02:50 +00:00
|
|
|
pre + 2, addr, fcn->addr, fcn->name);
|
2018-03-01 09:50:56 +00:00
|
|
|
//}
|
|
|
|
}
|
2016-02-23 01:31:53 +00:00
|
|
|
} else {
|
2018-03-01 09:50:56 +00:00
|
|
|
if (is_json) {
|
|
|
|
r_cons_printf ("{\"%"PFMT64d"\":{\"refs\":[", addr);
|
|
|
|
} else {
|
2016-02-23 01:31:53 +00:00
|
|
|
//snprintf (arg, sizeof (arg), "0x%08"PFMT64x, addr);
|
|
|
|
//if (sdb_add (db, arg, "1", 0)) {
|
|
|
|
r_cons_printf ("%s0x%08"PFMT64x"\n", pre+2, addr);
|
|
|
|
//}
|
2018-03-01 09:50:56 +00:00
|
|
|
}
|
2016-02-23 01:31:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
r_list_foreach (xrefs, iter, ref) {
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, ref->addr, -1);
|
|
|
|
if (fcn) {
|
2018-03-01 09:50:56 +00:00
|
|
|
if (is_json) {
|
|
|
|
if (level == 0) {
|
|
|
|
r_cons_printf ("{\"%"PFMT64d"\":{\"type\":\"fcn\",\"fcn_addr\": %"PFMT64d",\"name\":\"%s\",\"refs\":[", ref->addr, fcn->addr, fcn->name);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("]}},{\"%"PFMT64d"\":{\"type\":\"fcn\",\"fcn_addr\": %"PFMT64d",\"name\":\"%s\",\"refs\":[", ref->addr, fcn->addr, fcn->name);
|
|
|
|
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%s0x%08"PFMT64x" fcn 0x%08"PFMT64x" %s\n", pre, ref->addr, fcn->addr, fcn->name);
|
|
|
|
}
|
2016-02-23 01:31:53 +00:00
|
|
|
if (sdb_add (db, fcn->name, "1", 0)) {
|
|
|
|
snprintf (arg, sizeof (arg), "0x%08"PFMT64x, fcn->addr);
|
2018-03-01 09:50:56 +00:00
|
|
|
anal_axg (core, arg, level+1, db, opts);
|
|
|
|
} else {
|
|
|
|
if (is_json) {
|
|
|
|
r_cons_printf("]}}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (is_json) {
|
|
|
|
if (iter->n) {
|
|
|
|
r_cons_printf (",");
|
|
|
|
}
|
2016-02-23 01:31:53 +00:00
|
|
|
}
|
|
|
|
} else {
|
2018-03-01 09:50:56 +00:00
|
|
|
if (is_json) {
|
|
|
|
r_cons_printf ("{\"%"PFMT64d"\":{\"type\":\"???\",\"refs\":[", ref->addr);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%s0x%08"PFMT64x" ???\n", pre, ref->addr);
|
|
|
|
}
|
2016-02-23 01:31:53 +00:00
|
|
|
snprintf (arg, sizeof (arg), "0x%08"PFMT64x, ref->addr);
|
|
|
|
if (sdb_add (db, arg, "1", 0)) {
|
2018-03-01 09:50:56 +00:00
|
|
|
anal_axg (core, arg, level +1, db, opts);
|
|
|
|
} else {
|
|
|
|
if (is_json) {
|
|
|
|
r_cons_printf("]}}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (is_json) {
|
|
|
|
if (iter->n) {
|
|
|
|
r_cons_printf (",");
|
|
|
|
}
|
2016-02-23 01:31:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-03-01 09:50:56 +00:00
|
|
|
if (is_json) {
|
|
|
|
r_cons_printf("]}}");
|
|
|
|
if (level == 0) {
|
|
|
|
r_cons_printf("\n");
|
|
|
|
}
|
|
|
|
}
|
2017-12-17 08:53:28 +00:00
|
|
|
r_list_free (xrefs);
|
2016-02-23 01:31:53 +00:00
|
|
|
}
|
|
|
|
|
2016-09-12 16:41:11 +00:00
|
|
|
static void cmd_anal_ucall_ref (RCore *core, ut64 addr) {
|
2017-02-18 22:31:04 +00:00
|
|
|
RAnalFunction * fcn = r_anal_get_fcn_at (core->anal, addr, R_ANAL_FCN_TYPE_NULL);
|
2016-09-12 16:41:11 +00:00
|
|
|
if (fcn) {
|
|
|
|
r_cons_printf (" ; %s", fcn->name);
|
|
|
|
} else {
|
|
|
|
r_cons_printf (" ; 0x%" PFMT64x, addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-03 01:05:13 +00:00
|
|
|
static bool cmd_anal_refs(RCore *core, const char *input) {
|
2014-12-05 06:34:54 +00:00
|
|
|
ut64 addr = core->offset;
|
2014-12-05 06:51:21 +00:00
|
|
|
switch (input[0]) {
|
2015-12-16 13:35:56 +00:00
|
|
|
case '-': { // "ax-"
|
2017-02-20 11:15:58 +00:00
|
|
|
RList *list;
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalRef *ref;
|
2017-04-10 21:26:00 +00:00
|
|
|
char *cp_inp = strdup (input + 1);
|
2017-07-17 12:13:13 +00:00
|
|
|
char *ptr = r_str_trim_head (cp_inp);
|
2018-02-09 21:25:30 +00:00
|
|
|
if (!strcmp (ptr, "*")) { // "ax-*"
|
2015-12-16 13:35:56 +00:00
|
|
|
r_anal_xrefs_init (core->anal);
|
|
|
|
} else {
|
2017-04-10 21:26:00 +00:00
|
|
|
int n = r_str_word_set0 (ptr);
|
|
|
|
ut64 from = UT64_MAX, to = UT64_MAX;
|
|
|
|
switch (n) {
|
|
|
|
case 2:
|
|
|
|
from = r_num_math (core->num, r_str_word_get0 (ptr, 1));
|
|
|
|
//fall through
|
|
|
|
case 1: // get addr
|
|
|
|
to = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
to = core->offset;
|
|
|
|
break;
|
2015-07-08 18:43:02 +00:00
|
|
|
}
|
2017-04-10 21:26:00 +00:00
|
|
|
list = r_anal_xrefs_get (core->anal, to);
|
2017-02-20 11:15:58 +00:00
|
|
|
if (list) {
|
|
|
|
r_list_foreach (list, iter, ref) {
|
2017-04-10 21:26:00 +00:00
|
|
|
if (from != UT64_MAX && from == ref->addr) {
|
2018-02-09 21:25:30 +00:00
|
|
|
r_anal_xref_del (core->anal, ref->addr, ref->at);
|
2017-04-10 21:26:00 +00:00
|
|
|
}
|
|
|
|
if (from == UT64_MAX) {
|
2018-02-09 21:25:30 +00:00
|
|
|
r_anal_xref_del (core->anal, ref->addr, ref->at);
|
2017-04-10 21:26:00 +00:00
|
|
|
}
|
2017-02-20 11:15:58 +00:00
|
|
|
}
|
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
r_list_free (list);
|
2015-07-08 18:43:02 +00:00
|
|
|
}
|
2017-04-10 21:26:00 +00:00
|
|
|
free (cp_inp);
|
2015-12-16 13:35:56 +00:00
|
|
|
} break;
|
2016-02-23 01:31:53 +00:00
|
|
|
case 'g': // "axg"
|
|
|
|
{
|
2017-01-14 11:44:03 +00:00
|
|
|
Sdb *db = sdb_new0 ();
|
2018-03-01 09:50:56 +00:00
|
|
|
if(input[1] == '\0') {
|
|
|
|
anal_axg (core, input[1] ? input + 2 : NULL, 0, db, 0);
|
|
|
|
} else if(input[1] == 'j') {
|
|
|
|
anal_axg (core, input[1] ? input + 2 : NULL, 0, db, R_CORE_ANAL_JSON);
|
|
|
|
}
|
2016-02-23 01:31:53 +00:00
|
|
|
sdb_free (db);
|
|
|
|
}
|
|
|
|
break;
|
2016-09-26 21:36:44 +00:00
|
|
|
case '\0': // "ax"
|
2016-01-27 01:49:40 +00:00
|
|
|
case 'j': // "axj"
|
2017-06-17 00:48:25 +00:00
|
|
|
case 'q': // "axq"
|
2016-01-27 01:49:40 +00:00
|
|
|
case '*': // "ax*"
|
2014-12-05 06:51:21 +00:00
|
|
|
r_core_anal_ref_list (core, input[0]);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2016-01-27 01:49:40 +00:00
|
|
|
case 't': { // "axt"
|
2015-12-16 13:35:56 +00:00
|
|
|
const int size = 12;
|
|
|
|
RList *list;
|
2016-10-13 10:17:44 +00:00
|
|
|
RAnalFunction *fcn;
|
2015-12-16 13:35:56 +00:00
|
|
|
RAnalRef *ref;
|
|
|
|
RListIter *iter;
|
|
|
|
ut8 buf[12];
|
|
|
|
RAsmOp asmop;
|
|
|
|
char *buf_asm = NULL;
|
|
|
|
char *space = strchr (input, ' ');
|
|
|
|
|
|
|
|
if (space) {
|
|
|
|
addr = r_num_math (core->num, space + 1);
|
|
|
|
} else {
|
|
|
|
addr = core->offset;
|
|
|
|
}
|
|
|
|
list = r_anal_xrefs_get (core->anal, addr);
|
|
|
|
if (list) {
|
|
|
|
if (input[1] == 'q') { // "axtq"
|
2016-12-19 11:30:17 +00:00
|
|
|
r_list_foreach (list, iter, ref) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("0x%" PFMT64x "\n", ref->addr);
|
2016-12-19 11:30:17 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
} else if (input[1] == 'j') { // "axtj"
|
2016-10-13 10:17:44 +00:00
|
|
|
bool asm_varsub = r_config_get_i (core->config, "asm.varsub");
|
2018-05-11 07:40:25 +00:00
|
|
|
core->parser->pseudo = r_config_get_i (core->config, "asm.pseudo");
|
2016-10-13 10:17:44 +00:00
|
|
|
core->parser->relsub = r_config_get_i (core->config, "asm.relsub");
|
2017-03-17 10:54:34 +00:00
|
|
|
core->parser->localvar_only = r_config_get_i (core->config, "asm.varsub_only");
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("[");
|
|
|
|
r_list_foreach (list, iter, ref) {
|
|
|
|
r_core_read_at (core, ref->addr, buf, size);
|
|
|
|
r_asm_set_pc (core->assembler, ref->addr);
|
|
|
|
r_asm_disassemble (core->assembler, &asmop, buf, size);
|
2014-12-05 06:34:54 +00:00
|
|
|
char str[512];
|
2016-10-13 10:17:44 +00:00
|
|
|
fcn = r_anal_get_fcn_in (core->anal, ref->addr, 0);
|
|
|
|
if (asm_varsub) {
|
|
|
|
r_parse_varsub (core->parser, fcn, ref->addr, asmop.size,
|
|
|
|
asmop.buf_asm, asmop.buf_asm, sizeof (asmop.buf_asm));
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
r_parse_filter (core->parser, core->flags,
|
2016-04-26 09:09:15 +00:00
|
|
|
asmop.buf_asm, str, sizeof (str), core->print->big_endian);
|
2017-10-18 01:07:39 +00:00
|
|
|
|
2018-02-09 21:25:30 +00:00
|
|
|
r_cons_printf ("{\"from\":%" PFMT64u ",\"type\":\"%s\",\"opcode\":\"%s\"", ref->addr, r_anal_xrefs_type_tostring (ref->type), str);
|
2017-10-18 01:07:39 +00:00
|
|
|
if (fcn) {
|
|
|
|
r_cons_printf (",\"fcn_addr\":%"PFMT64d",\"fcn_name\":\"%s\"", fcn->addr, fcn->name);
|
|
|
|
}
|
|
|
|
RFlagItem *fi = r_flag_get_at (core->flags, fcn? fcn->addr: ref->addr, true);
|
|
|
|
if (fi) {
|
|
|
|
if (fcn && strcmp (fcn->name, fi->name)) {
|
|
|
|
r_cons_printf (",\"flag\":\"%s\"", fi->name);
|
|
|
|
}
|
|
|
|
if (fi->realname && strcmp (fi->name, fi->realname)) {
|
|
|
|
r_cons_printf (",\"realname\":\"%s\"", fi->realname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_cons_printf ("}%s", iter->n? ",": "");
|
2015-12-16 13:35:56 +00:00
|
|
|
}
|
|
|
|
r_cons_printf ("]");
|
|
|
|
r_cons_newline ();
|
2017-12-29 10:21:24 +00:00
|
|
|
} else if (input[1] == 'g') { // axtg
|
|
|
|
r_list_foreach (list, iter, ref) {
|
|
|
|
char *str = r_core_cmd_strf (core, "fd 0x%"PFMT64x, ref->addr);
|
|
|
|
if (!str) {
|
|
|
|
str = strdup ("?\n");
|
|
|
|
}
|
|
|
|
r_str_trim_tail (str);
|
|
|
|
r_cons_printf ("agn 0x%" PFMT64x " \"%s\"\n", ref->addr, str);
|
|
|
|
free (str);
|
|
|
|
}
|
|
|
|
if (input[2] != '*') {
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, 0);
|
|
|
|
r_cons_printf ("agn 0x%" PFMT64x " \"%s\"\n", addr, fcn?fcn->name: "$$");
|
|
|
|
}
|
|
|
|
r_list_foreach (list, iter, ref) {
|
|
|
|
r_cons_printf ("age 0x%" PFMT64x " 0x%"PFMT64x"\n", ref->addr, addr);
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
} else if (input[1] == '*') { // axt*
|
|
|
|
// TODO: implement multi-line comments
|
|
|
|
r_list_foreach (list, iter, ref)
|
2016-01-27 01:49:40 +00:00
|
|
|
r_cons_printf ("CCa 0x%" PFMT64x " \"XREF type %d at 0x%" PFMT64x"%s\n",
|
|
|
|
ref->addr, ref->type, addr, iter->n? ",": "");
|
2015-12-16 13:35:56 +00:00
|
|
|
} else { // axt
|
|
|
|
int has_color = core->print->flags & R_PRINT_FLAGS_COLOR;
|
|
|
|
char str[512];
|
|
|
|
RAnalFunction *fcn;
|
|
|
|
char *comment;
|
2016-09-26 21:36:44 +00:00
|
|
|
bool asm_varsub = r_config_get_i (core->config, "asm.varsub");
|
2018-05-11 07:40:25 +00:00
|
|
|
core->parser->pseudo = r_config_get_i (core->config, "asm.pseudo");
|
2016-09-26 21:36:44 +00:00
|
|
|
core->parser->relsub = r_config_get_i (core->config, "asm.relsub");
|
2017-03-17 10:54:34 +00:00
|
|
|
core->parser->localvar_only = r_config_get_i (core->config, "asm.varsub_only");
|
2017-03-07 19:39:30 +00:00
|
|
|
if (core->parser->relsub) {
|
|
|
|
core->parser->relsub_addr = addr;
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
r_list_foreach (list, iter, ref) {
|
|
|
|
r_core_read_at (core, ref->addr, buf, size);
|
2016-09-26 22:50:56 +00:00
|
|
|
r_asm_set_pc (core->assembler, ref->addr);
|
2015-12-16 13:35:56 +00:00
|
|
|
r_asm_disassemble (core->assembler, &asmop, buf, size);
|
2016-09-26 21:36:44 +00:00
|
|
|
|
2016-09-26 21:55:05 +00:00
|
|
|
fcn = r_anal_get_fcn_in (core->anal, ref->addr, 0);
|
2016-09-26 21:36:44 +00:00
|
|
|
if (asm_varsub) {
|
|
|
|
r_parse_varsub (core->parser, fcn, ref->addr, asmop.size,
|
|
|
|
asmop.buf_asm, asmop.buf_asm, sizeof (asmop.buf_asm));
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
r_parse_filter (core->parser, core->flags,
|
2016-04-26 09:09:15 +00:00
|
|
|
asmop.buf_asm, str, sizeof (str), core->print->big_endian);
|
2015-12-16 13:35:56 +00:00
|
|
|
if (has_color) {
|
2017-03-28 20:55:58 +00:00
|
|
|
buf_asm = r_print_colorize_opcode (core->print, str,
|
2017-06-20 20:48:46 +00:00
|
|
|
core->cons->pal.reg, core->cons->pal.num, false);
|
2015-12-16 13:35:56 +00:00
|
|
|
} else {
|
|
|
|
buf_asm = r_str_new (str);
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, ref->addr);
|
2017-10-17 16:33:08 +00:00
|
|
|
char *buf_fcn = comment
|
|
|
|
? r_str_newf ("%s; %s", fcn ? fcn->name : "(nofunc)", strtok (comment, "\n"))
|
|
|
|
: r_str_newf ("%s", fcn ? fcn->name : "(nofunc)");
|
2017-10-18 01:07:39 +00:00
|
|
|
r_cons_printf ("%s 0x%" PFMT64x " [%s] %s\n",
|
2018-02-09 21:25:30 +00:00
|
|
|
buf_fcn, ref->addr, r_anal_xrefs_type_tostring (ref->type), buf_asm);
|
2015-12-16 13:35:56 +00:00
|
|
|
free (buf_asm);
|
|
|
|
free (buf_fcn);
|
2014-01-31 01:40:16 +00:00
|
|
|
}
|
2014-01-31 01:02:51 +00:00
|
|
|
}
|
2017-05-13 20:38:34 +00:00
|
|
|
} else {
|
|
|
|
if (input[1] == 'j') { // "axtj"
|
|
|
|
r_cons_print ("[]\n");
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
r_list_free (list);
|
2015-12-16 13:35:56 +00:00
|
|
|
} break;
|
2016-11-07 02:13:01 +00:00
|
|
|
case 'f': { // "axf"
|
2015-12-16 13:35:56 +00:00
|
|
|
ut8 buf[12];
|
|
|
|
RAsmOp asmop;
|
|
|
|
char *buf_asm = NULL;
|
2016-11-07 23:21:25 +00:00
|
|
|
RList *list, *list_ = NULL;
|
2015-12-16 13:35:56 +00:00
|
|
|
RAnalRef *ref;
|
|
|
|
RListIter *iter;
|
|
|
|
char *space = strchr (input, ' ');
|
|
|
|
|
|
|
|
if (space) {
|
|
|
|
addr = r_num_math (core->num, space + 1);
|
|
|
|
} else {
|
|
|
|
addr = core->offset;
|
|
|
|
}
|
2016-11-07 23:21:25 +00:00
|
|
|
if (input[1] == '.') { // axf.
|
|
|
|
list = list_ = r_anal_xrefs_get_from (core->anal, addr);
|
|
|
|
if (!list) {
|
|
|
|
RAnalFunction * fcn = r_anal_get_fcn_in (core->anal, addr, 0);
|
2018-02-09 21:25:30 +00:00
|
|
|
list = r_anal_fcn_get_refs_sorted (core->anal, fcn);
|
2016-11-07 23:21:25 +00:00
|
|
|
}
|
|
|
|
} else {
|
2017-08-16 06:27:37 +00:00
|
|
|
list = r_anal_refs_get (core->anal, addr);
|
2016-11-07 23:21:25 +00:00
|
|
|
}
|
|
|
|
|
2015-12-16 13:35:56 +00:00
|
|
|
if (list) {
|
|
|
|
if (input[1] == 'q') { // axfq
|
2016-11-07 02:13:01 +00:00
|
|
|
r_list_foreach (list, iter, ref) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("0x%" PFMT64x "\n", ref->at);
|
2016-11-07 02:13:01 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
} else if (input[1] == 'j') { // axfj
|
2016-11-07 02:13:01 +00:00
|
|
|
r_cons_print ("[");
|
2015-12-16 13:35:56 +00:00
|
|
|
r_list_foreach (list, iter, ref) {
|
|
|
|
r_core_read_at (core, ref->at, buf, 12);
|
|
|
|
r_asm_set_pc (core->assembler, ref->at);
|
|
|
|
r_asm_disassemble (core->assembler, &asmop, buf, 12);
|
2017-12-15 00:12:54 +00:00
|
|
|
r_cons_printf ("{\"from\":%" PFMT64d ",\"to\":%" PFMT64d ",\"type\":\"%s\",\"opcode\":\"%s\"}%s",
|
2018-02-09 21:25:30 +00:00
|
|
|
ref->at, ref->addr, r_anal_xrefs_type_tostring (ref->type), asmop.buf_asm, iter->n? ",": "");
|
2015-12-16 13:35:56 +00:00
|
|
|
}
|
2016-11-07 02:13:01 +00:00
|
|
|
r_cons_print ("]\n");
|
2015-12-16 13:35:56 +00:00
|
|
|
} else if (input[1] == '*') { // axf*
|
|
|
|
// TODO: implement multi-line comments
|
2016-11-07 02:13:01 +00:00
|
|
|
r_list_foreach (list, iter, ref) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("CCa 0x%" PFMT64x " \"XREF from 0x%" PFMT64x "\n",
|
|
|
|
ref->at, ref->type, asmop.buf_asm, iter->n? ",": "");
|
2016-11-07 02:13:01 +00:00
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
} else { // axf
|
|
|
|
char str[512];
|
2016-11-07 11:08:55 +00:00
|
|
|
int has_color = core->print->flags & R_PRINT_FLAGS_COLOR;
|
2015-12-16 13:35:56 +00:00
|
|
|
r_list_foreach (list, iter, ref) {
|
|
|
|
r_core_read_at (core, ref->at, buf, 12);
|
|
|
|
r_asm_set_pc (core->assembler, ref->at);
|
|
|
|
r_asm_disassemble (core->assembler, &asmop, buf, 12);
|
|
|
|
r_parse_filter (core->parser, core->flags,
|
2016-04-26 09:09:15 +00:00
|
|
|
asmop.buf_asm, str, sizeof (str), core->print->big_endian);
|
2016-11-07 11:08:55 +00:00
|
|
|
if (has_color) {
|
2017-03-28 20:55:58 +00:00
|
|
|
buf_asm = r_print_colorize_opcode (core->print, str,
|
2017-06-20 20:48:46 +00:00
|
|
|
core->cons->pal.reg, core->cons->pal.num, false);
|
2016-11-07 11:08:55 +00:00
|
|
|
} else {
|
|
|
|
buf_asm = r_str_new (str);
|
|
|
|
}
|
2016-09-12 16:41:11 +00:00
|
|
|
r_cons_printf ("%c 0x%" PFMT64x " %s",
|
2015-12-16 13:35:56 +00:00
|
|
|
ref->type, ref->at, buf_asm);
|
2016-09-12 16:41:11 +00:00
|
|
|
|
|
|
|
if (ref->type == R_ANAL_REF_TYPE_CALL) {
|
|
|
|
RAnalOp aop;
|
2018-03-15 11:31:01 +00:00
|
|
|
r_anal_op (core->anal, &aop, ref->at, buf, 12, R_ANAL_OP_MASK_ALL);
|
2016-09-12 16:41:11 +00:00
|
|
|
if (aop.type == R_ANAL_OP_TYPE_UCALL) {
|
|
|
|
cmd_anal_ucall_ref (core, ref->addr);
|
|
|
|
}
|
|
|
|
}
|
2016-11-07 02:13:01 +00:00
|
|
|
r_cons_newline ();
|
2015-12-16 13:35:56 +00:00
|
|
|
free (buf_asm);
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
|
|
|
}
|
2017-05-13 20:38:34 +00:00
|
|
|
} else {
|
|
|
|
if (input[1] == 'j') { // axfj
|
|
|
|
r_cons_print ("[]\n");
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
r_list_free (list);
|
2015-12-16 13:35:56 +00:00
|
|
|
} break;
|
2014-12-05 06:34:54 +00:00
|
|
|
case 'F':
|
2015-12-16 13:35:56 +00:00
|
|
|
find_refs (core, input + 1);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2016-02-09 17:52:26 +00:00
|
|
|
case 'C': // "axC"
|
|
|
|
case 'c': // "axc"
|
|
|
|
case 'd': // "axd"
|
2018-05-08 06:41:53 +00:00
|
|
|
case 's': // "axs"
|
2017-11-28 09:52:04 +00:00
|
|
|
case ' ': // "ax "
|
2017-01-14 11:44:03 +00:00
|
|
|
{
|
2015-12-16 13:35:56 +00:00
|
|
|
char *ptr = strdup (r_str_trim_head ((char *)input + 1));
|
|
|
|
int n = r_str_word_set0 (ptr);
|
|
|
|
ut64 at = core->offset;
|
|
|
|
ut64 addr = UT64_MAX;
|
2018-02-09 21:25:30 +00:00
|
|
|
RAnalRefType reftype = r_anal_xrefs_type (input[0]);
|
2015-12-16 13:35:56 +00:00
|
|
|
switch (n) {
|
|
|
|
case 2: // get at
|
|
|
|
at = r_num_math (core->num, r_str_word_get0 (ptr, 1));
|
2017-01-14 11:44:03 +00:00
|
|
|
/* fall through */
|
2015-12-16 13:35:56 +00:00
|
|
|
case 1: // get addr
|
|
|
|
addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
|
|
|
break;
|
|
|
|
default:
|
2014-12-05 06:34:54 +00:00
|
|
|
free (ptr);
|
2015-12-16 13:35:56 +00:00
|
|
|
return false;
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
r_anal_xrefs_set (core->anal, at, addr, reftype);
|
2015-12-16 13:35:56 +00:00
|
|
|
free (ptr);
|
2017-02-20 11:15:58 +00:00
|
|
|
}
|
2017-01-14 11:44:03 +00:00
|
|
|
break;
|
2014-12-05 06:34:54 +00:00
|
|
|
default:
|
|
|
|
case '?':
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_ax);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2015-01-30 00:55:21 +00:00
|
|
|
static void cmd_anal_hint(RCore *core, const char *input) {
|
|
|
|
switch (input[0]) {
|
|
|
|
case '?':
|
|
|
|
if (input[1]) {
|
2016-11-01 17:53:09 +00:00
|
|
|
ut64 addr = r_num_math (core->num, input + 1);
|
2016-11-01 18:47:34 +00:00
|
|
|
r_core_anal_hint_print (core->anal, addr, 0);
|
2016-10-05 13:59:41 +00:00
|
|
|
} else {
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_ah);
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
2015-01-30 00:55:21 +00:00
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case '.': // "ah."
|
2016-11-01 18:47:34 +00:00
|
|
|
r_core_anal_hint_print (core->anal, core->offset, 0);
|
2016-05-31 09:50:35 +00:00
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'a': // "aha" set arch
|
2014-12-05 06:51:21 +00:00
|
|
|
if (input[1]) {
|
2014-12-05 06:34:54 +00:00
|
|
|
int i;
|
2015-12-16 13:35:56 +00:00
|
|
|
char *ptr = strdup (input + 2);
|
2014-12-05 06:34:54 +00:00
|
|
|
i = r_str_word_set0 (ptr);
|
2016-11-01 17:53:09 +00:00
|
|
|
if (i == 2) {
|
2014-12-05 06:34:54 +00:00
|
|
|
r_num_math (core->num, r_str_word_get0 (ptr, 1));
|
2016-11-01 17:53:09 +00:00
|
|
|
}
|
|
|
|
r_anal_hint_set_arch (core->anal, core->offset, r_str_word_get0 (ptr, 0));
|
2014-12-05 06:34:54 +00:00
|
|
|
free (ptr);
|
2016-11-01 18:47:34 +00:00
|
|
|
} else if (input[1] == '-') {
|
|
|
|
r_anal_hint_unset_arch (core->anal, core->offset);
|
2016-11-01 17:53:09 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Missing argument\n");
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'b': // "ahb" set bits
|
2014-12-05 06:51:21 +00:00
|
|
|
if (input[1]) {
|
2015-12-16 13:35:56 +00:00
|
|
|
char *ptr = strdup (input + 2);
|
2014-12-05 06:34:54 +00:00
|
|
|
int bits;
|
|
|
|
int i = r_str_word_set0 (ptr);
|
2016-11-01 18:47:34 +00:00
|
|
|
if (i == 2) {
|
2014-12-05 06:34:54 +00:00
|
|
|
r_num_math (core->num, r_str_word_get0 (ptr, 1));
|
2016-11-01 18:47:34 +00:00
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
bits = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
|
|
|
r_anal_hint_set_bits (core->anal, core->offset, bits);
|
|
|
|
free (ptr);
|
2016-11-01 18:47:34 +00:00
|
|
|
} else if (input[1] == '-') {
|
|
|
|
r_anal_hint_unset_bits (core->anal, core->offset);
|
|
|
|
} else {
|
|
|
|
eprintf ("Missing argument\n");
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2016-01-16 23:46:57 +00:00
|
|
|
case 'i': // "ahi"
|
|
|
|
if (input[1] == '?') {
|
2017-08-18 13:04:48 +00:00
|
|
|
r_core_cmd_help (core, help_msg_ahi);
|
2016-06-17 21:17:24 +00:00
|
|
|
} else if (input[1] == ' ') {
|
2016-01-16 23:46:57 +00:00
|
|
|
// You can either specify immbase with letters, or numbers
|
|
|
|
const int base =
|
2017-09-01 10:49:01 +00:00
|
|
|
(input[2] == 's') ? 1 :
|
|
|
|
(input[2] == 'b') ? 2 :
|
2017-11-09 11:57:51 +00:00
|
|
|
(input[2] == 'p') ? 3 :
|
2016-01-16 23:46:57 +00:00
|
|
|
(input[2] == 'o') ? 8 :
|
|
|
|
(input[2] == 'd') ? 10 :
|
|
|
|
(input[2] == 'h') ? 16 :
|
2016-02-03 11:29:32 +00:00
|
|
|
(input[2] == 'i') ? 32 : // ip address
|
2016-02-03 16:05:03 +00:00
|
|
|
(input[2] == 'S') ? 80 : // syscall
|
2016-01-16 23:46:57 +00:00
|
|
|
(int) r_num_math (core->num, input + 1);
|
|
|
|
r_anal_hint_set_immbase (core->anal, core->offset, base);
|
2017-07-24 15:41:50 +00:00
|
|
|
} else if (input[1] == '-') { // "ahi-"
|
2016-11-01 18:47:34 +00:00
|
|
|
r_anal_hint_set_immbase (core->anal, core->offset, 0);
|
2016-10-05 13:59:41 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("|ERROR| Usage: ahi [base]\n");
|
|
|
|
}
|
2015-09-27 23:00:06 +00:00
|
|
|
break;
|
2017-11-14 14:36:04 +00:00
|
|
|
case 'h': // "ahh"
|
|
|
|
if (input[1] == '-') {
|
|
|
|
r_anal_hint_unset_high (core->anal, core->offset);
|
|
|
|
} else if (input[1] == ' ') {
|
|
|
|
r_anal_hint_set_high (core->anal, r_num_math (core->num, input + 1));
|
|
|
|
} else {
|
|
|
|
r_anal_hint_set_high (core->anal, core->offset);
|
|
|
|
}
|
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'c': // "ahc"
|
2016-11-01 18:47:34 +00:00
|
|
|
if (input[1] == ' ') {
|
|
|
|
r_anal_hint_set_jump (
|
|
|
|
core->anal, core->offset,
|
2015-12-16 13:35:56 +00:00
|
|
|
r_num_math (core->num, input + 1));
|
2016-11-01 18:47:34 +00:00
|
|
|
} else if (input[1] == '-') {
|
|
|
|
r_anal_hint_unset_jump (core->anal, core->offset);
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'f': // "ahf"
|
2016-11-01 18:47:34 +00:00
|
|
|
if (input[1] == ' ') {
|
|
|
|
r_anal_hint_set_fail (
|
|
|
|
core->anal, core->offset,
|
2015-12-16 13:35:56 +00:00
|
|
|
r_num_math (core->num, input + 1));
|
2016-11-01 18:47:34 +00:00
|
|
|
} else if (input[1] == '-') {
|
|
|
|
r_anal_hint_unset_fail (core->anal, core->offset);
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 's': // "ahs" set size (opcode length)
|
2016-11-01 18:47:34 +00:00
|
|
|
if (input[1] == ' ') {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_anal_hint_set_size (core->anal, core->offset, atoi (input + 1));
|
2016-11-01 18:47:34 +00:00
|
|
|
} else if (input[1] == '-') {
|
|
|
|
r_anal_hint_unset_size (core->anal, core->offset);
|
2016-10-05 13:59:41 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Usage: ahs 16\n");
|
|
|
|
}
|
2015-05-09 22:12:33 +00:00
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'S': // "ahS" set size (opcode length)
|
2015-12-16 13:35:56 +00:00
|
|
|
if (input[1] == ' ') {
|
|
|
|
r_anal_hint_set_syntax (core->anal, core->offset, input + 2);
|
2016-11-01 18:47:34 +00:00
|
|
|
} else if (input[1] == '-') {
|
|
|
|
r_anal_hint_unset_syntax (core->anal, core->offset);
|
2016-10-05 13:59:41 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Usage: ahS att\n");
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'o': // "aho" set opcode string
|
2015-12-16 13:35:56 +00:00
|
|
|
if (input[1] == ' ') {
|
|
|
|
r_anal_hint_set_opcode (core->anal, core->offset, input + 2);
|
2016-11-01 18:47:34 +00:00
|
|
|
} else if (input[1] == '-') {
|
|
|
|
r_anal_hint_unset_opcode (core->anal, core->offset);
|
2016-10-05 13:59:41 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Usage: aho popall\n");
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'e': // "ahe" set ESIL string
|
2015-12-16 13:35:56 +00:00
|
|
|
if (input[1] == ' ') {
|
|
|
|
r_anal_hint_set_esil (core->anal, core->offset, input + 2);
|
2016-11-01 18:47:34 +00:00
|
|
|
} else if (input[1] == '-') {
|
|
|
|
r_anal_hint_unset_esil (core->anal, core->offset);
|
2016-10-05 13:59:41 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Usage: ahe r0,pc,=\n");
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2016-11-01 18:47:34 +00:00
|
|
|
#if 0
|
2014-12-05 06:34:54 +00:00
|
|
|
case 'e': // set endian
|
2016-11-01 18:47:34 +00:00
|
|
|
if (input[1] == ' ') {
|
|
|
|
r_anal_hint_set_opcode (core->anal, core->offset, atoi (input + 1));
|
|
|
|
} else if (input[1] == '-') {
|
|
|
|
r_anal_hint_unset_opcode (core->anal, core->offset);
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2014-06-16 03:58:00 +00:00
|
|
|
#endif
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'p': // "ahp"
|
2016-11-01 18:47:34 +00:00
|
|
|
if (input[1] == ' ') {
|
|
|
|
r_anal_hint_set_pointer (core->anal, core->offset, r_num_math (core->num, input + 1));
|
2017-07-24 15:41:50 +00:00
|
|
|
} else if (input[1] == '-') { // "ahp-"
|
2016-11-01 18:47:34 +00:00
|
|
|
r_anal_hint_unset_pointer (core->anal, core->offset);
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case '*': // "ah*"
|
2016-11-01 18:47:34 +00:00
|
|
|
if (input[1] == ' ') {
|
2018-01-08 02:29:29 +00:00
|
|
|
char *ptr = strdup (r_str_trim_ro (input + 2));
|
2016-11-01 18:47:34 +00:00
|
|
|
r_str_word_set0 (ptr);
|
|
|
|
ut64 addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
2016-11-24 00:56:49 +00:00
|
|
|
r_core_anal_hint_print (core->anal, addr, '*');
|
2016-11-01 18:47:34 +00:00
|
|
|
} else {
|
|
|
|
r_core_anal_hint_list (core->anal, input[0]);
|
|
|
|
}
|
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'j': // "ahj"
|
|
|
|
case '\0': // "ah"
|
2014-12-05 06:51:21 +00:00
|
|
|
r_core_anal_hint_list (core->anal, input[0]);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2016-04-20 23:52:06 +00:00
|
|
|
case '-': // "ah-"
|
2014-12-05 06:51:21 +00:00
|
|
|
if (input[1]) {
|
2016-04-20 23:52:06 +00:00
|
|
|
if (input[1] == '*') {
|
|
|
|
r_anal_hint_clear (core->anal);
|
|
|
|
} else {
|
2018-01-08 02:29:29 +00:00
|
|
|
char *ptr = strdup (r_str_trim_ro (input + 1));
|
2016-04-20 23:52:06 +00:00
|
|
|
ut64 addr;
|
|
|
|
int size = 1;
|
|
|
|
int i = r_str_word_set0 (ptr);
|
|
|
|
if (i == 2) {
|
|
|
|
size = r_num_math (core->num, r_str_word_get0 (ptr, 1));
|
|
|
|
}
|
|
|
|
const char *a0 = r_str_word_get0 (ptr, 0);
|
|
|
|
if (a0 && *a0) {
|
|
|
|
addr = r_num_math (core->num, a0);
|
|
|
|
} else {
|
|
|
|
addr = core->offset;
|
|
|
|
}
|
|
|
|
r_anal_hint_del (core->anal, addr, size);
|
|
|
|
free (ptr);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
r_anal_hint_clear (core->anal);
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-11 08:58:33 +00:00
|
|
|
static void agraph_print_node_json(RANode *n, void *user) {
|
|
|
|
char *label = strdup (n->body);
|
|
|
|
r_cons_printf ("%s{\"id\":%d,\"title\":\"%s\",\"body\":\"%s\",\"out_nodes\":[",
|
|
|
|
n->gnode->idx > 0 ? "," : "", n->gnode->idx, n->title, label);
|
|
|
|
RListIter *it = NULL;
|
|
|
|
RGraphNode *node = NULL;
|
|
|
|
RList *nodes = n->gnode->out_nodes;
|
|
|
|
r_list_foreach (nodes, it, node) {
|
|
|
|
r_cons_printf ("%s%d", it == nodes->head ? "" : ",", node->idx);
|
|
|
|
}
|
|
|
|
r_cons_printf ("]}");
|
|
|
|
free (label);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void agraph_print_node_gml(RANode *n, void *user) {
|
|
|
|
r_cons_printf (" node [\n"
|
|
|
|
" id %d\n"
|
|
|
|
" label \"%s\"\n"
|
|
|
|
" ]\n", n->gnode->idx, n->title);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void agraph_print_edge_gml(RANode *from, RANode *to, void *user) {
|
|
|
|
r_cons_printf (" edge [\n"
|
|
|
|
" source %d\n"
|
|
|
|
" target %d\n"
|
|
|
|
" ]\n", from->gnode->idx, to->gnode->idx
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-12-14 22:23:08 +00:00
|
|
|
static void agraph_print_node_dot(RANode *n, void *user) {
|
|
|
|
char *label = strdup (n->body);
|
2016-09-22 21:57:16 +00:00
|
|
|
//label = r_str_replace (label, "\n", "\\l", 1);
|
2015-12-14 22:23:08 +00:00
|
|
|
if (!label || !*label) {
|
2018-01-13 08:14:07 +00:00
|
|
|
r_cons_printf ("\"%s\" [URL=\"%s\", color=\"lightgray\", label=\"%s\"]\n",
|
|
|
|
n->title, n->title, n->title);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("\"%s\" [URL=\"%s\", color=\"lightgray\", label=\"%s\\n%s\"]\n",
|
|
|
|
n->title, n->title, n->title, label);
|
2015-12-14 22:23:08 +00:00
|
|
|
}
|
|
|
|
free (label);
|
|
|
|
}
|
|
|
|
|
2015-10-15 07:00:53 +00:00
|
|
|
static void agraph_print_node(RANode *n, void *user) {
|
2015-07-19 12:32:00 +00:00
|
|
|
char *encbody, *cmd;
|
|
|
|
int len = strlen (n->body);
|
|
|
|
|
2016-11-24 00:56:49 +00:00
|
|
|
if (n->body[len - 1] == '\n') {
|
|
|
|
len--;
|
|
|
|
}
|
2015-07-19 12:32:00 +00:00
|
|
|
encbody = r_base64_encode_dyn (n->body, len);
|
|
|
|
cmd = r_str_newf ("agn \"%s\" base64:%s\n", n->title, encbody);
|
|
|
|
r_cons_printf (cmd);
|
|
|
|
free (cmd);
|
|
|
|
free (encbody);
|
|
|
|
}
|
|
|
|
|
2015-12-14 22:23:08 +00:00
|
|
|
static void agraph_print_edge_dot(RANode *from, RANode *to, void *user) {
|
|
|
|
r_cons_printf ("\"%s\" -> \"%s\"\n", from->title, to->title);
|
|
|
|
}
|
2015-07-19 12:32:00 +00:00
|
|
|
|
2015-12-14 22:23:08 +00:00
|
|
|
static void agraph_print_edge(RANode *from, RANode *to, void *user) {
|
|
|
|
r_cons_printf ("age \"%s\" \"%s\"\n", from->title, to->title);
|
2015-07-19 12:32:00 +00:00
|
|
|
}
|
|
|
|
|
2015-10-02 17:28:49 +00:00
|
|
|
static void cmd_agraph_node(RCore *core, const char *input) {
|
2015-07-19 12:32:00 +00:00
|
|
|
switch (*input) {
|
2017-07-24 15:41:50 +00:00
|
|
|
case ' ': { // "agn"
|
2015-07-19 12:32:00 +00:00
|
|
|
char *newbody = NULL;
|
|
|
|
char **args, *body;
|
|
|
|
int n_args, B_LEN = strlen ("base64:");
|
|
|
|
input++;
|
|
|
|
args = r_str_argv (input, &n_args);
|
2015-12-16 13:35:56 +00:00
|
|
|
if (n_args < 1 || n_args > 2) {
|
2015-07-19 12:32:00 +00:00
|
|
|
r_cons_printf ("Wrong arguments\n");
|
|
|
|
r_str_argv_free (args);
|
|
|
|
break;
|
|
|
|
}
|
2016-10-09 08:59:36 +00:00
|
|
|
// strdup cause there is double free in r_str_argv_free due to a realloc call
|
2015-12-16 13:35:56 +00:00
|
|
|
if (n_args > 1) {
|
2015-12-10 21:45:00 +00:00
|
|
|
body = strdup (args[1]);
|
|
|
|
if (strncmp (body, "base64:", B_LEN) == 0) {
|
|
|
|
body = r_str_replace (body, "\\n", "", true);
|
|
|
|
newbody = (char *)r_base64_decode_dyn (body + B_LEN, -1);
|
|
|
|
free (body);
|
2015-12-16 13:35:56 +00:00
|
|
|
if (!newbody) {
|
2016-10-09 08:59:36 +00:00
|
|
|
eprintf ("Cannot allocate buffer\n");
|
2015-12-10 21:45:00 +00:00
|
|
|
r_str_argv_free (args);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
body = newbody;
|
2015-07-24 23:09:13 +00:00
|
|
|
}
|
2017-03-16 21:29:49 +00:00
|
|
|
body = r_str_append (body, "\n");
|
2015-12-10 21:45:00 +00:00
|
|
|
} else {
|
|
|
|
body = strdup ("");
|
2015-07-19 12:32:00 +00:00
|
|
|
}
|
|
|
|
r_agraph_add_node (core->graph, args[0], body);
|
|
|
|
r_str_argv_free (args);
|
2015-07-24 23:09:13 +00:00
|
|
|
free (body);
|
2017-03-16 21:29:49 +00:00
|
|
|
//free newbody it's not necessary since r_str_append reallocate the space
|
2015-07-19 12:32:00 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-07-24 15:41:50 +00:00
|
|
|
case '-': { // "agn-"
|
2015-10-02 17:28:49 +00:00
|
|
|
char **args;
|
|
|
|
int n_args;
|
|
|
|
|
|
|
|
input++;
|
|
|
|
args = r_str_argv (input, &n_args);
|
|
|
|
if (n_args != 1) {
|
|
|
|
r_cons_printf ("Wrong arguments\n");
|
|
|
|
r_str_argv_free (args);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
r_agraph_del_node (core->graph, args[0]);
|
|
|
|
r_str_argv_free (args);
|
|
|
|
break;
|
|
|
|
}
|
2015-07-19 12:32:00 +00:00
|
|
|
case '?':
|
|
|
|
default:
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_agn);
|
2015-07-19 12:32:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-02 17:28:49 +00:00
|
|
|
static void cmd_agraph_edge(RCore *core, const char *input) {
|
2015-07-19 12:32:00 +00:00
|
|
|
switch (*input) {
|
2017-07-24 15:41:50 +00:00
|
|
|
case ' ': // "age"
|
|
|
|
case '-': { // "age-"
|
2015-07-19 12:32:00 +00:00
|
|
|
RANode *u, *v;
|
|
|
|
char **args;
|
|
|
|
int n_args;
|
|
|
|
|
2015-10-02 17:28:49 +00:00
|
|
|
args = r_str_argv (input + 1, &n_args);
|
2015-07-19 12:32:00 +00:00
|
|
|
if (n_args != 2) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("Wrong arguments\n");
|
2015-07-24 21:59:38 +00:00
|
|
|
r_str_argv_free (args);
|
2015-07-19 12:32:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
u = r_agraph_get_node (core->graph, args[0]);
|
|
|
|
v = r_agraph_get_node (core->graph, args[1]);
|
|
|
|
if (!u || !v) {
|
2017-02-06 00:27:03 +00:00
|
|
|
if (!u) {
|
|
|
|
r_cons_printf ("Node %s not found!\n", args[0]);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("Node %s not found!\n", args[1]);
|
|
|
|
}
|
2015-07-24 21:59:38 +00:00
|
|
|
r_str_argv_free (args);
|
2015-07-19 12:32:00 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-10-02 17:28:49 +00:00
|
|
|
if (*input == ' ') {
|
|
|
|
r_agraph_add_edge (core->graph, u, v);
|
|
|
|
} else {
|
|
|
|
r_agraph_del_edge (core->graph, u, v);
|
|
|
|
}
|
2015-07-19 12:32:00 +00:00
|
|
|
r_str_argv_free (args);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case '?':
|
|
|
|
default:
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_age);
|
2015-07-19 12:32:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-02 17:28:49 +00:00
|
|
|
static void cmd_agraph_print(RCore *core, const char *input) {
|
2015-07-19 12:32:00 +00:00
|
|
|
switch (*input) {
|
2018-05-11 08:58:33 +00:00
|
|
|
case 0:
|
|
|
|
core->graph->can->linemode = r_config_get_i (core->config, "graph.linemode");
|
|
|
|
core->graph->can->color = r_config_get_i (core->config, "scr.color");
|
|
|
|
r_agraph_set_title (core->graph,
|
|
|
|
r_config_get (core->config, "graph.title"));
|
|
|
|
r_agraph_print (core->graph);
|
|
|
|
break;
|
|
|
|
case 't':// "aggt" - tiny graph
|
|
|
|
core->graph->is_tiny = true;
|
|
|
|
r_core_visual_graph (core, core->graph, NULL, false);
|
|
|
|
core->graph->is_tiny = false;
|
|
|
|
break;
|
2015-12-14 22:23:08 +00:00
|
|
|
case 'k': // "aggk"
|
2015-07-19 12:32:00 +00:00
|
|
|
{
|
|
|
|
Sdb *db = r_agraph_get_sdb (core->graph);
|
2017-08-18 12:31:56 +00:00
|
|
|
char *o = sdb_querys (db, "null", 0, "*");
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_print (o);
|
2015-07-19 12:32:00 +00:00
|
|
|
free (o);
|
|
|
|
break;
|
|
|
|
}
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'v': // "aggv"
|
2016-01-04 22:00:01 +00:00
|
|
|
case 'i': // "aggi" - open current core->graph in interactive mode
|
|
|
|
{
|
|
|
|
RANode *ran = r_agraph_get_first_node (core->graph);
|
2016-11-17 11:29:57 +00:00
|
|
|
if (ran) {
|
|
|
|
r_agraph_set_title (core->graph, r_config_get (core->config, "graph.title"));
|
|
|
|
r_agraph_set_curnode (core->graph, ran);
|
|
|
|
core->graph->force_update_seek = true;
|
|
|
|
core->graph->need_set_layout = true;
|
2017-08-07 16:35:34 +00:00
|
|
|
core->graph->layout = r_config_get_i (core->config, "graph.layout");
|
2016-11-17 11:29:57 +00:00
|
|
|
int ov = r_config_get_i (core->config, "scr.interactive");
|
|
|
|
core->graph->need_update_dim = true;
|
|
|
|
r_core_visual_graph (core, core->graph, NULL, true);
|
|
|
|
r_config_set_i (core->config, "scr.interactive", ov);
|
|
|
|
r_cons_show_cursor (true);
|
|
|
|
} else {
|
|
|
|
eprintf ("This graph contains no nodes\n");
|
|
|
|
}
|
2016-01-04 22:00:01 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-12-14 22:23:08 +00:00
|
|
|
case 'd': // "aggd" - dot format
|
|
|
|
r_cons_printf ("digraph code {\ngraph [bgcolor=white];\n"
|
|
|
|
"node [color=lightgray, style=filled shape=box "
|
|
|
|
"fontname=\"Courier\" fontsize=\"8\"];\n");
|
|
|
|
r_agraph_foreach (core->graph, agraph_print_node_dot, NULL);
|
|
|
|
r_agraph_foreach_edge (core->graph, agraph_print_edge_dot, NULL);
|
|
|
|
r_cons_printf ("}\n");
|
|
|
|
break;
|
|
|
|
case '*': // "agg*" -
|
2015-10-15 07:00:53 +00:00
|
|
|
r_agraph_foreach (core->graph, agraph_print_node, NULL);
|
|
|
|
r_agraph_foreach_edge (core->graph, agraph_print_edge, NULL);
|
2015-07-19 12:32:00 +00:00
|
|
|
break;
|
2018-05-11 08:58:33 +00:00
|
|
|
case 'J':
|
|
|
|
case 'j':
|
|
|
|
r_cons_printf ("{\"nodes\":[");
|
|
|
|
r_agraph_foreach (core->graph, agraph_print_node_json, NULL);
|
|
|
|
r_cons_printf ("]}\n");
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
r_cons_printf ("graph\n[\n" "hierarchic 1\n" "label \"\"\n" "directed 1\n");
|
|
|
|
r_agraph_foreach (core->graph, agraph_print_node_gml, NULL);
|
|
|
|
r_agraph_foreach_edge (core->graph, agraph_print_edge_gml, NULL);
|
|
|
|
r_cons_print ("]\n");
|
|
|
|
break;
|
|
|
|
case 'w':{ // "aggw"
|
|
|
|
if (r_config_get_i (core->config, "graph.web")) {
|
|
|
|
r_core_cmd0 (core, "=H /graph/");
|
|
|
|
} else {
|
|
|
|
char *cmd = r_core_graph_cmd ("aggd");
|
|
|
|
if (cmd && *cmd) {
|
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
}
|
|
|
|
free (cmd);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-01-04 23:47:41 +00:00
|
|
|
case '?':
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_agg);
|
2016-01-04 23:47:41 +00:00
|
|
|
break;
|
2015-07-19 12:32:00 +00:00
|
|
|
default:
|
2018-05-11 08:58:33 +00:00
|
|
|
eprintf ("Usage: see ag?\n");
|
2015-07-19 12:32:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-05 06:34:54 +00:00
|
|
|
static void cmd_anal_graph(RCore *core, const char *input) {
|
2014-12-05 17:56:33 +00:00
|
|
|
RList *list;
|
2015-01-30 00:55:21 +00:00
|
|
|
const char *arg;
|
2014-12-05 06:51:21 +00:00
|
|
|
switch (input[0]) {
|
2016-12-09 14:29:15 +00:00
|
|
|
case 'f': // "agf"
|
2018-04-19 22:24:21 +00:00
|
|
|
switch (input[1]) {
|
2018-05-07 17:55:54 +00:00
|
|
|
case 0:// "agf"
|
|
|
|
r_core_visual_graph (core, NULL, NULL, false);
|
|
|
|
break;
|
|
|
|
case 'v':// "agfv"
|
|
|
|
eprintf ("\rRendering graph...");
|
|
|
|
r_core_visual_graph (core, NULL, NULL, 1);
|
|
|
|
r_cons_show_cursor (true);
|
|
|
|
break;
|
2018-04-19 22:24:21 +00:00
|
|
|
case 't':// "agft" - tiny graph
|
2017-04-12 00:14:56 +00:00
|
|
|
r_core_visual_graph (core, NULL, NULL, 2);
|
2018-04-19 22:24:21 +00:00
|
|
|
break;
|
2018-05-07 17:55:54 +00:00
|
|
|
case 'd':// "agfd"
|
|
|
|
if (input[2] == 'm') {
|
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input + 2),
|
|
|
|
R_CORE_ANAL_GRAPHLINES);
|
|
|
|
} else {
|
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input + 1),
|
|
|
|
R_CORE_ANAL_GRAPHBODY);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'j':// "agfj"
|
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input + 1), R_CORE_ANAL_JSON);
|
|
|
|
break;
|
|
|
|
case 'J':// "agfJ"
|
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input + 1),
|
|
|
|
R_CORE_ANAL_JSON | R_CORE_ANAL_JSON_FORMAT_DISASM);
|
|
|
|
case 'g':{// "agfg"
|
|
|
|
ut64 off_fcn = (*(input + 2)) ? r_num_math (core->num, input + 2) : core->offset;
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off_fcn, 0);
|
|
|
|
r_core_print_bb_gml (core, fcn);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'k':// "agfk"
|
|
|
|
r_core_cmd0 (core, "ag-; .agf*; aggk");
|
|
|
|
break;
|
|
|
|
case '*':{// "agf*"
|
|
|
|
ut64 off_fcn = (*(input + 2)) ? r_num_math (core->num, input + 2) : core->offset;
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off_fcn, 0);
|
|
|
|
r_core_print_bb_custom (core, fcn);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'w':// "agfw"
|
|
|
|
if (r_config_get_i (core->config, "graph.web")) {
|
|
|
|
r_core_cmd0 (core, "=H /graph/");
|
|
|
|
} else {
|
2018-05-11 08:58:33 +00:00
|
|
|
char *cmd = r_core_graph_cmd ("agfd");
|
2018-05-07 17:55:54 +00:00
|
|
|
if (cmd && *cmd) {
|
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
}
|
2018-05-11 08:58:33 +00:00
|
|
|
free (cmd);
|
2018-05-07 17:55:54 +00:00
|
|
|
}
|
2018-04-19 22:24:21 +00:00
|
|
|
break;
|
|
|
|
default:
|
2018-05-11 08:58:33 +00:00
|
|
|
eprintf ("Usage: see ag?\n");
|
2018-04-19 22:24:21 +00:00
|
|
|
break;
|
2017-04-12 00:14:56 +00:00
|
|
|
}
|
2015-06-25 14:57:15 +00:00
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case '-': // "ag-"
|
2015-07-09 21:56:55 +00:00
|
|
|
r_agraph_reset (core->graph);
|
|
|
|
break;
|
2015-12-10 21:45:00 +00:00
|
|
|
case 'n': // "agn"
|
2015-07-19 12:32:00 +00:00
|
|
|
cmd_agraph_node (core, input + 1);
|
2015-07-09 21:56:55 +00:00
|
|
|
break;
|
2015-12-10 21:45:00 +00:00
|
|
|
case 'e': // "age"
|
2015-07-19 12:32:00 +00:00
|
|
|
cmd_agraph_edge (core, input + 1);
|
2015-07-09 21:56:55 +00:00
|
|
|
break;
|
2015-12-10 21:45:00 +00:00
|
|
|
case 'g': // "agg"
|
2015-07-19 12:32:00 +00:00
|
|
|
cmd_agraph_print (core, input + 1);
|
2015-07-09 21:56:55 +00:00
|
|
|
break;
|
2016-03-22 00:55:37 +00:00
|
|
|
case 's': // "ags"
|
2016-03-23 21:13:55 +00:00
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input + 1), 0);
|
2016-03-22 00:55:37 +00:00
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 't': // "agt"
|
2015-12-16 13:35:56 +00:00
|
|
|
list = r_core_anal_graph_to (core, r_num_math (core->num, input + 1), 0);
|
2014-12-05 17:56:33 +00:00
|
|
|
if (list) {
|
|
|
|
RListIter *iter, *iter2;
|
|
|
|
RList *list2;
|
|
|
|
RAnalBlock *bb;
|
|
|
|
r_list_foreach (list, iter, list2) {
|
|
|
|
r_list_foreach (list2, iter2, bb) {
|
2015-12-16 13:35:56 +00:00
|
|
|
r_cons_printf ("-> 0x%08" PFMT64x "\n", bb->addr);
|
2013-02-11 09:51:45 +00:00
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2014-12-05 17:56:33 +00:00
|
|
|
r_list_purge (list);
|
|
|
|
free (list);
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
|
|
|
break;
|
2016-07-05 13:58:09 +00:00
|
|
|
case 'C': // "agC"
|
|
|
|
r_core_anal_coderefs (core, UT64_MAX, input[1] == 'j'? 2: 1);
|
|
|
|
break;
|
2017-08-06 01:58:38 +00:00
|
|
|
case 'r': // "refs"
|
|
|
|
switch (input[1]) {
|
|
|
|
case '*':
|
|
|
|
case 'j':
|
|
|
|
case ' ':
|
|
|
|
case 0:
|
|
|
|
{
|
|
|
|
ut64 addr = input[2]? r_num_math (core->num, input + 2): core->offset;
|
|
|
|
r_core_anal_codexrefs (core, addr, '*');
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
eprintf ("|ERROR| Usage: agr[*j]\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2016-03-19 01:43:36 +00:00
|
|
|
case 'c': // "agc"
|
2016-05-03 22:11:28 +00:00
|
|
|
if (input[1] == '*') {
|
|
|
|
ut64 addr = input[2]? r_num_math (core->num, input + 2): UT64_MAX;
|
|
|
|
r_core_anal_coderefs (core, addr, '*');
|
2017-01-04 09:44:25 +00:00
|
|
|
} else if (input[1] == 'j') {
|
|
|
|
ut64 addr = input[2]? r_num_math (core->num, input + 2): UT64_MAX;
|
|
|
|
r_core_anal_coderefs (core, addr, 2);
|
2016-06-17 21:17:24 +00:00
|
|
|
} else if (input[1] == ' ') {
|
2016-05-03 22:11:28 +00:00
|
|
|
ut64 addr = input[2]? r_num_math (core->num, input + 1): UT64_MAX;
|
2017-01-04 09:44:25 +00:00
|
|
|
r_core_anal_coderefs (core, addr, 1);
|
2016-07-05 13:58:09 +00:00
|
|
|
} else {
|
2017-12-29 10:19:56 +00:00
|
|
|
eprintf ("|ERROR| Usage: agc[j*] ([addr])\n");
|
2016-07-05 13:58:09 +00:00
|
|
|
}
|
2016-03-22 00:55:37 +00:00
|
|
|
break;
|
2016-03-19 01:43:36 +00:00
|
|
|
case 'j': // "agj"
|
2015-12-16 13:35:56 +00:00
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input + 1), R_CORE_ANAL_JSON);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2018-02-01 14:12:27 +00:00
|
|
|
case 'J': // "agJ"
|
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input + 1), R_CORE_ANAL_JSON | R_CORE_ANAL_JSON_FORMAT_DISASM);
|
|
|
|
break;
|
2016-03-19 01:43:36 +00:00
|
|
|
case 'k': // "agk"
|
2015-12-16 13:35:56 +00:00
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input + 1), R_CORE_ANAL_KEYVALUE);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2016-03-19 01:43:36 +00:00
|
|
|
case 'l': // "agl"
|
2015-12-16 13:35:56 +00:00
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input + 1), R_CORE_ANAL_GRAPHLINES);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2016-03-19 01:43:36 +00:00
|
|
|
case 'a': // "aga"
|
2015-12-16 13:35:56 +00:00
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input + 1), 0);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2016-03-19 01:43:36 +00:00
|
|
|
case 'd': // "agd"
|
2015-12-16 13:35:56 +00:00
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input + 1),
|
|
|
|
R_CORE_ANAL_GRAPHBODY | R_CORE_ANAL_GRAPHDIFF);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2016-09-02 15:14:52 +00:00
|
|
|
case 'v': // "agv"
|
2016-09-02 18:00:16 +00:00
|
|
|
if (r_config_get_i (core->config, "graph.web")) {
|
|
|
|
r_core_cmd0 (core, "=H /graph/");
|
|
|
|
} else {
|
|
|
|
const char *cmd = r_config_get (core->config, "cmd.graph");
|
|
|
|
if (cmd && *cmd) {
|
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
} else {
|
|
|
|
r_core_cmd0 (core, "agf");
|
|
|
|
}
|
|
|
|
}
|
2016-09-02 15:14:52 +00:00
|
|
|
break;
|
2016-03-19 01:43:36 +00:00
|
|
|
case '?': // "ag?"
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_ag);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2016-06-17 21:17:24 +00:00
|
|
|
case ' ': // "ag"
|
2015-01-30 00:55:21 +00:00
|
|
|
arg = strchr (input, ' ');
|
2016-09-02 18:00:16 +00:00
|
|
|
r_core_anal_graph (core, r_num_math (core->num, arg? arg + 1: NULL),
|
2015-01-30 00:55:21 +00:00
|
|
|
R_CORE_ANAL_GRAPHBODY);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2016-06-17 21:17:24 +00:00
|
|
|
case 0:
|
|
|
|
eprintf ("|ERROR| Usage: ag [addr]\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
eprintf ("See ag?\n");
|
|
|
|
break;
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-07 16:20:29 +00:00
|
|
|
R_API int r_core_anal_refs(RCore *core, const char *input) {
|
|
|
|
int cfg_debug = r_config_get_i (core->config, "cfg.debug");
|
|
|
|
ut64 from, to;
|
|
|
|
char *ptr;
|
|
|
|
int rad, n;
|
|
|
|
if (*input == '?') {
|
|
|
|
r_core_cmd_help (core, help_msg_aar);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*input == 'j' || *input == '*') {
|
|
|
|
rad = *input;
|
|
|
|
input++;
|
|
|
|
} else {
|
|
|
|
rad = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
from = to = 0;
|
|
|
|
ptr = r_str_trim_head (strdup (input));
|
|
|
|
n = r_str_word_set0 (ptr);
|
2016-12-05 17:46:45 +00:00
|
|
|
if (!n) {
|
2015-09-07 16:20:29 +00:00
|
|
|
// get boundaries of current memory map, section or io map
|
|
|
|
if (cfg_debug) {
|
|
|
|
RDebugMap *map = r_debug_map_get (core->dbg, core->offset);
|
|
|
|
if (map) {
|
|
|
|
from = map->addr;
|
|
|
|
to = map->addr_end;
|
|
|
|
}
|
|
|
|
} else {
|
2018-01-27 22:10:02 +00:00
|
|
|
RList *list = r_core_get_boundaries_prot (core, R_IO_EXEC, NULL, "anal");
|
2017-12-13 18:38:53 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RIOMap* map;
|
|
|
|
r_list_foreach (list, iter, map) {
|
|
|
|
from = map->itv.addr;
|
|
|
|
to = r_itv_end (map->itv);
|
2017-12-16 19:39:13 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
2018-03-12 12:10:59 +00:00
|
|
|
}
|
2017-12-13 18:38:53 +00:00
|
|
|
if (!from && !to) {
|
|
|
|
eprintf ("Cannot determine xref search boundaries\n");
|
2017-12-14 20:12:23 +00:00
|
|
|
} else if (to - from > UT32_MAX) {
|
|
|
|
eprintf ("Skipping huge range\n");
|
2017-12-13 18:38:53 +00:00
|
|
|
} else {
|
|
|
|
r_core_anal_search_xrefs (core, from, to, rad);
|
2018-03-12 12:10:59 +00:00
|
|
|
}
|
2017-12-13 18:38:53 +00:00
|
|
|
}
|
2018-03-14 16:16:10 +00:00
|
|
|
free (ptr);
|
2018-03-12 12:10:59 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2015-09-07 16:20:29 +00:00
|
|
|
} else if (n == 1) {
|
|
|
|
from = core->offset;
|
|
|
|
to = core->offset + r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
|
|
|
} else {
|
|
|
|
eprintf ("Invalid number of arguments\n");
|
|
|
|
}
|
|
|
|
free (ptr);
|
|
|
|
|
2016-11-24 00:56:49 +00:00
|
|
|
if (from == UT64_MAX && to == UT64_MAX) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-12-05 17:46:45 +00:00
|
|
|
if (!from && !to) {
|
2016-11-24 00:56:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (to - from > r_io_size (core->io)) {
|
|
|
|
return false;
|
|
|
|
}
|
2015-09-07 16:20:29 +00:00
|
|
|
return r_core_anal_search_xrefs (core, from, to, rad);
|
|
|
|
}
|
|
|
|
|
2016-03-07 03:12:11 +00:00
|
|
|
static const char *oldstr = NULL;
|
|
|
|
|
|
|
|
static void rowlog(RCore *core, const char *str) {
|
|
|
|
int use_color = core->print->flags & R_PRINT_FLAGS_COLOR;
|
2016-05-09 15:45:05 +00:00
|
|
|
bool verbose = r_config_get_i (core->config, "scr.prompt");
|
2016-03-07 03:12:11 +00:00
|
|
|
oldstr = str;
|
2016-05-09 15:45:05 +00:00
|
|
|
if (!verbose) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (use_color) {
|
|
|
|
eprintf ("[ ] "Color_YELLOW"%s\r["Color_RESET, str);
|
|
|
|
} else {
|
|
|
|
eprintf ("[ ] %s\r[", str);
|
|
|
|
}
|
2016-03-07 03:12:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void rowlog_done(RCore *core) {
|
|
|
|
int use_color = core->print->flags & R_PRINT_FLAGS_COLOR;
|
2016-05-09 15:45:05 +00:00
|
|
|
bool verbose = r_config_get_i (core->config, "scr.prompt");
|
|
|
|
if (verbose) {
|
|
|
|
if (use_color)
|
|
|
|
eprintf ("\r"Color_GREEN"[x]"Color_RESET" %s\n", oldstr);
|
|
|
|
else eprintf ("\r[x] %s\n", oldstr);
|
|
|
|
}
|
2016-03-07 03:12:11 +00:00
|
|
|
}
|
|
|
|
|
2016-03-28 22:39:50 +00:00
|
|
|
static int compute_coverage(RCore *core) {
|
|
|
|
RListIter *iter;
|
2017-08-22 07:42:16 +00:00
|
|
|
SdbListIter *iter2;
|
2016-03-28 22:39:50 +00:00
|
|
|
RAnalFunction *fcn;
|
2017-03-13 13:09:51 +00:00
|
|
|
RIOSection *sec;
|
2016-03-28 22:39:50 +00:00
|
|
|
int cov = 0;
|
|
|
|
r_list_foreach (core->anal->fcns, iter, fcn) {
|
2017-08-22 07:42:16 +00:00
|
|
|
ls_foreach (core->io->sections, iter2, sec) {
|
2017-03-16 22:15:23 +00:00
|
|
|
if (sec->flags & 1) {
|
|
|
|
ut64 section_end = sec->vaddr + sec->vsize;
|
|
|
|
ut64 s = r_anal_fcn_realsize (fcn);
|
|
|
|
if (fcn->addr >= sec->vaddr && (fcn->addr + s) < section_end) {
|
|
|
|
cov += s;
|
|
|
|
}
|
2017-03-13 13:09:51 +00:00
|
|
|
}
|
|
|
|
}
|
2016-03-28 22:39:50 +00:00
|
|
|
}
|
|
|
|
return cov;
|
|
|
|
}
|
|
|
|
|
2017-03-13 13:09:51 +00:00
|
|
|
static int compute_code (RCore* core) {
|
|
|
|
int code = 0;
|
2017-08-22 07:42:16 +00:00
|
|
|
SdbListIter *iter;
|
2017-03-13 13:09:51 +00:00
|
|
|
RIOSection *sec;
|
2017-08-22 07:42:16 +00:00
|
|
|
ls_foreach (core->io->sections, iter, sec) {
|
2017-03-15 01:22:54 +00:00
|
|
|
if (sec->flags & 1) {
|
2017-03-13 13:09:51 +00:00
|
|
|
code += sec->vsize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
|
2016-03-28 23:13:00 +00:00
|
|
|
static int compute_calls(RCore *core) {
|
2016-03-28 22:39:50 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RAnalFunction *fcn;
|
2018-01-09 19:38:08 +00:00
|
|
|
RList *xrefs;
|
2016-03-28 22:39:50 +00:00
|
|
|
int cov = 0;
|
|
|
|
r_list_foreach (core->anal->fcns, iter, fcn) {
|
2018-01-09 19:38:08 +00:00
|
|
|
xrefs = r_anal_fcn_get_xrefs (core->anal, fcn);
|
|
|
|
if (xrefs) {
|
|
|
|
cov += r_list_length (xrefs);
|
|
|
|
xrefs = NULL;
|
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
r_list_free (xrefs);
|
2016-03-28 22:39:50 +00:00
|
|
|
}
|
|
|
|
return cov;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void r_core_anal_info (RCore *core, const char *input) {
|
|
|
|
int fcns = r_list_length (core->anal->fcns);
|
|
|
|
int strs = r_flag_count (core->flags, "str.*");
|
|
|
|
int syms = r_flag_count (core->flags, "sym.*");
|
|
|
|
int imps = r_flag_count (core->flags, "sym.imp.*");
|
2017-03-13 13:09:51 +00:00
|
|
|
int code = compute_code (core);
|
2016-03-28 22:39:50 +00:00
|
|
|
int covr = compute_coverage (core);
|
2016-03-28 23:13:00 +00:00
|
|
|
int call = compute_calls (core);
|
|
|
|
int xrfs = r_anal_xrefs_count (core->anal);
|
2016-08-04 20:52:33 +00:00
|
|
|
int cvpc = (code > 0)? (covr * 100 / code): 0;
|
2016-03-28 22:39:50 +00:00
|
|
|
if (*input == 'j') {
|
|
|
|
r_cons_printf ("{\"fcns\":%d", fcns);
|
|
|
|
r_cons_printf (",\"xrefs\":%d", xrfs);
|
2016-03-28 23:13:00 +00:00
|
|
|
r_cons_printf (",\"calls\":%d", call);
|
2016-03-28 22:39:50 +00:00
|
|
|
r_cons_printf (",\"strings\":%d", strs);
|
|
|
|
r_cons_printf (",\"symbols\":%d", syms);
|
|
|
|
r_cons_printf (",\"imports\":%d", imps);
|
|
|
|
r_cons_printf (",\"covrage\":%d", covr);
|
|
|
|
r_cons_printf (",\"codesz\":%d", code);
|
2016-03-31 11:21:51 +00:00
|
|
|
r_cons_printf (",\"percent\":%d}\n", cvpc);
|
2016-03-28 22:39:50 +00:00
|
|
|
} else {
|
|
|
|
r_cons_printf ("fcns %d\n", fcns);
|
|
|
|
r_cons_printf ("xrefs %d\n", xrfs);
|
2016-03-28 23:13:00 +00:00
|
|
|
r_cons_printf ("calls %d\n", call);
|
2016-03-28 22:39:50 +00:00
|
|
|
r_cons_printf ("strings %d\n", strs);
|
|
|
|
r_cons_printf ("symbols %d\n", syms);
|
|
|
|
r_cons_printf ("imports %d\n", imps);
|
|
|
|
r_cons_printf ("covrage %d\n", covr);
|
|
|
|
r_cons_printf ("codesz %d\n", code);
|
2016-03-31 11:21:51 +00:00
|
|
|
r_cons_printf ("percent %d%%\n", cvpc);
|
2016-03-28 22:39:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-04 20:52:33 +00:00
|
|
|
static void cmd_anal_aad(RCore *core, const char *input) {
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalRef *ref;
|
|
|
|
RList *list = r_list_newf (NULL);
|
|
|
|
r_anal_xrefs_from (core->anal, list, "xref", R_ANAL_REF_TYPE_DATA, UT64_MAX);
|
|
|
|
r_list_foreach (list, iter, ref) {
|
2017-08-23 22:19:57 +00:00
|
|
|
if (r_io_is_valid_offset (core->io, ref->addr, false)) {
|
2016-08-05 12:41:44 +00:00
|
|
|
r_core_anal_fcn (core, ref->at, ref->addr, R_ANAL_REF_TYPE_NULL, 1);
|
|
|
|
}
|
2016-08-04 20:52:33 +00:00
|
|
|
}
|
|
|
|
r_list_free (list);
|
|
|
|
}
|
|
|
|
|
2017-03-29 02:44:16 +00:00
|
|
|
|
|
|
|
static bool archIsArmOrThumb(RCore *core) {
|
|
|
|
RAsm *as = core ? core->assembler : NULL;
|
|
|
|
if (as && as->cur && as->cur->arch) {
|
2017-08-30 22:24:17 +00:00
|
|
|
if (r_str_startswith (as->cur->arch, "mips")) {
|
|
|
|
return true;
|
|
|
|
}
|
2017-03-29 02:44:16 +00:00
|
|
|
if (r_str_startswith (as->cur->arch, "arm")) {
|
2018-03-21 10:30:11 +00:00
|
|
|
if (as->bits < 64) {
|
2017-03-29 02:44:16 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-09-18 01:22:25 +00:00
|
|
|
const bool archIsMips (RCore *core) {
|
|
|
|
return strstr (core->assembler->cur->name, "mips");
|
|
|
|
}
|
|
|
|
|
2017-03-29 02:44:16 +00:00
|
|
|
void _CbInRangeAav(RCore *core, ut64 from, ut64 to, int vsize, bool asterisk, int count) {
|
|
|
|
bool isarm = archIsArmOrThumb (core);
|
|
|
|
if (isarm) {
|
|
|
|
if (to & 1) {
|
|
|
|
// .dword 0x000080b9 in reality is 0x000080b8
|
|
|
|
to--;
|
|
|
|
r_anal_hint_set_bits (core->anal, to, 16);
|
|
|
|
// can we assume is gonna be always a function?
|
|
|
|
} else {
|
|
|
|
r_core_seek_archbits (core, from);
|
|
|
|
ut64 bits = r_config_get_i (core->config, "asm.bits");
|
|
|
|
r_anal_hint_set_bits (core->anal, from, bits);
|
|
|
|
}
|
2017-09-18 01:22:25 +00:00
|
|
|
} else {
|
|
|
|
bool ismips = archIsMips (core);
|
|
|
|
if (ismips) {
|
|
|
|
if (from % 4 || to % 4) {
|
|
|
|
eprintf ("False positive\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2017-03-29 02:44:16 +00:00
|
|
|
}
|
|
|
|
if (asterisk) {
|
|
|
|
r_cons_printf ("ax 0x%"PFMT64x " 0x%"PFMT64x "\n", to, from);
|
|
|
|
r_cons_printf ("Cd %d @ 0x%"PFMT64x "\n", vsize, from);
|
2017-08-30 22:24:17 +00:00
|
|
|
r_cons_printf ("f+ aav.0x%08"PFMT64x "= 0x%08"PFMT64x, to, to);
|
2017-03-29 02:44:16 +00:00
|
|
|
} else {
|
2017-12-10 11:53:06 +00:00
|
|
|
#if 1
|
2018-02-09 21:25:30 +00:00
|
|
|
r_anal_xrefs_set (core->anal, from, to, R_ANAL_REF_TYPE_NULL);
|
2017-12-10 11:53:06 +00:00
|
|
|
r_meta_add (core->anal, 'd', from, from + vsize, NULL);
|
|
|
|
if (!r_flag_get_at (core->flags, to, false)) {
|
|
|
|
char *name = r_str_newf ("aav.0x%08"PFMT64x, to);
|
|
|
|
r_flag_set (core->flags, name, to, vsize);
|
|
|
|
free (name);
|
|
|
|
}
|
|
|
|
#else
|
2017-03-29 02:44:16 +00:00
|
|
|
r_core_cmdf (core, "ax 0x%"PFMT64x " 0x%"PFMT64x, to, from);
|
|
|
|
r_core_cmdf (core, "Cd %d @ 0x%"PFMT64x, vsize, from);
|
2017-08-30 22:24:17 +00:00
|
|
|
r_core_cmdf (core, "f+ aav.0x%08"PFMT64x "= 0x%08"PFMT64x, to, to);
|
2017-12-10 11:53:06 +00:00
|
|
|
#endif
|
2017-03-29 02:44:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-10 22:02:58 +00:00
|
|
|
static void cmd_anal_aav(RCore *core, const char *input) {
|
|
|
|
#define seti(x,y) r_config_set_i(core->config, x, y);
|
|
|
|
#define geti(x) r_config_get_i(core->config, x);
|
|
|
|
ut64 o_align = geti ("search.align");
|
2016-06-09 19:52:25 +00:00
|
|
|
bool asterisk = strchr (input, '*');;
|
2016-04-22 09:25:42 +00:00
|
|
|
bool is_debug = r_config_get_i (core->config, "cfg.debug");
|
|
|
|
|
2017-09-11 22:25:01 +00:00
|
|
|
// pre
|
2017-12-03 19:10:47 +00:00
|
|
|
int archAlign = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_ALIGN);
|
|
|
|
seti ("search.align", archAlign);
|
2017-09-18 01:22:25 +00:00
|
|
|
|
2016-04-10 22:02:58 +00:00
|
|
|
int vsize = 4; // 32bit dword
|
2016-05-01 21:00:08 +00:00
|
|
|
if (core->assembler->bits == 64) {
|
|
|
|
vsize = 8;
|
|
|
|
}
|
2017-09-11 22:25:01 +00:00
|
|
|
|
|
|
|
// body
|
2017-10-29 10:49:44 +00:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2017-09-11 22:25:01 +00:00
|
|
|
if (is_debug) {
|
2018-01-27 22:10:02 +00:00
|
|
|
RList *list = r_core_get_boundaries_prot (core, 0, "dbg.map", "anal");
|
2017-09-11 22:25:01 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RIOMap *map;
|
|
|
|
r_list_foreach (list, iter, map) {
|
2017-10-29 10:49:44 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
2017-09-01 06:41:03 +00:00
|
|
|
eprintf ("aav: from 0x%"PFMT64x" to 0x%"PFMT64x"\n", map->itv.addr, r_itv_end (map->itv));
|
2017-09-16 06:37:26 +00:00
|
|
|
(void)r_core_search_value_in_range (core, map->itv,
|
2017-09-01 06:41:03 +00:00
|
|
|
map->itv.addr, r_itv_end (map->itv), vsize, asterisk, _CbInRangeAav);
|
2017-09-11 22:25:01 +00:00
|
|
|
}
|
|
|
|
r_list_free (list);
|
|
|
|
} else {
|
2018-01-27 22:10:02 +00:00
|
|
|
RList *list = r_core_get_boundaries_prot (core, 0, NULL, "anal");
|
2017-09-18 01:22:25 +00:00
|
|
|
RListIter *iter, *iter2;
|
|
|
|
RIOMap *map, *map2;
|
|
|
|
ut64 from = UT64_MAX;
|
|
|
|
ut64 to = UT64_MAX;
|
|
|
|
// find values pointing to non-executable regions
|
|
|
|
r_list_foreach (list, iter2, map2) {
|
2017-10-29 10:49:44 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
2018-03-12 12:10:59 +00:00
|
|
|
//TODO: Reduce multiple hits for same addr
|
2017-12-17 08:16:49 +00:00
|
|
|
from = r_itv_begin (map2->itv);
|
|
|
|
to = r_itv_end (map2->itv);
|
|
|
|
eprintf ("Value from 0x%08"PFMT64x " to 0x%08" PFMT64x "\n", from, to);
|
|
|
|
r_list_foreach (list, iter, map) {
|
|
|
|
ut64 begin = map->itv.addr;
|
|
|
|
ut64 end = r_itv_end (map->itv);
|
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
2017-09-18 10:53:42 +00:00
|
|
|
}
|
2017-12-17 08:16:49 +00:00
|
|
|
if (end - begin > UT32_MAX) {
|
|
|
|
eprintf ("Skipping huge range\n");
|
2017-09-18 10:53:42 +00:00
|
|
|
continue;
|
|
|
|
}
|
2017-12-17 08:16:49 +00:00
|
|
|
eprintf ("aav: 0x%08"PFMT64x"-0x%08"PFMT64x" in 0x%"PFMT64x"-0x%"PFMT64x"\n", from, to, begin, end);
|
|
|
|
(void)r_core_search_value_in_range (core, map->itv, from, to, vsize, asterisk, _CbInRangeAav);
|
2017-09-18 01:22:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
r_list_free (list);
|
2017-09-11 22:25:01 +00:00
|
|
|
}
|
2017-10-29 10:49:44 +00:00
|
|
|
r_cons_break_pop ();
|
2017-09-11 22:25:01 +00:00
|
|
|
// end
|
2016-04-10 22:02:58 +00:00
|
|
|
seti ("search.align", o_align);
|
|
|
|
}
|
|
|
|
|
2017-03-22 17:04:26 +00:00
|
|
|
static bool should_aav(RCore *core) {
|
|
|
|
// Don't aav on x86 for now
|
|
|
|
if (r_str_startswith (r_config_get (core->config, "asm.arch"), "x86")) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-12-16 13:35:56 +00:00
|
|
|
static int cmd_anal_all(RCore *core, const char *input) {
|
2015-07-31 10:40:04 +00:00
|
|
|
switch (*input) {
|
|
|
|
case '?': r_core_cmd_help (core, help_msg_aa); break;
|
2018-04-05 07:30:47 +00:00
|
|
|
case 'b': // "aab"
|
|
|
|
cmd_anal_blocks (core, input + 1);
|
|
|
|
break; // "aab"
|
2018-04-11 23:01:51 +00:00
|
|
|
case 'f': // "aaf"
|
|
|
|
{
|
|
|
|
int analHasnext = r_config_get_i (core->config, "anal.hasnext");
|
|
|
|
r_config_set_i (core->config, "anal.hasnext", true);
|
|
|
|
r_core_cmd0 (core, "afr@@c:isq");
|
|
|
|
r_config_set_i (core->config, "anal.hasnext", analHasnext);
|
|
|
|
}
|
|
|
|
break;
|
2018-04-05 07:30:47 +00:00
|
|
|
case 'c': // "aac"
|
2017-09-08 14:44:37 +00:00
|
|
|
switch (input[1]) {
|
|
|
|
case '*':
|
|
|
|
cmd_anal_calls (core, input + 1, true); break; // "aac*"
|
|
|
|
default:
|
|
|
|
cmd_anal_calls (core, input + 1, false); break; // "aac"
|
|
|
|
}
|
2015-12-16 13:35:56 +00:00
|
|
|
case 'j': cmd_anal_jumps (core, input + 1); break; // "aaj"
|
2018-04-05 07:30:47 +00:00
|
|
|
case '*': // "aa*"
|
2015-07-31 10:40:04 +00:00
|
|
|
r_core_cmd0 (core, "af @@ sym.*");
|
2018-03-07 00:56:39 +00:00
|
|
|
r_core_cmd0 (core, "af @@ entry*");
|
2015-07-31 10:40:04 +00:00
|
|
|
break;
|
2016-08-04 20:52:33 +00:00
|
|
|
case 'd': // "aad"
|
|
|
|
cmd_anal_aad (core, input);
|
|
|
|
break;
|
2016-04-10 22:02:58 +00:00
|
|
|
case 'v': // "aav"
|
2016-04-21 22:55:27 +00:00
|
|
|
cmd_anal_aav (core, input);
|
2016-04-10 22:02:58 +00:00
|
|
|
break;
|
2016-04-15 17:39:04 +00:00
|
|
|
case 'u': // "aau" - print areas not covered by functions
|
|
|
|
r_core_anal_nofunclist (core, input + 1);
|
|
|
|
break;
|
2016-03-28 23:13:00 +00:00
|
|
|
case 'i': // "aai"
|
2016-03-28 22:39:50 +00:00
|
|
|
r_core_anal_info (core, input + 1);
|
|
|
|
break;
|
2018-04-05 07:30:47 +00:00
|
|
|
case 's': // "aas"
|
2015-07-31 10:40:04 +00:00
|
|
|
r_core_cmd0 (core, "af @@= `isq~[0]`");
|
2018-03-07 00:56:39 +00:00
|
|
|
r_core_cmd0 (core, "af @@ entry*");
|
2015-07-31 10:40:04 +00:00
|
|
|
break;
|
2018-04-02 18:00:39 +00:00
|
|
|
case 'n': // "aan"
|
2016-08-20 22:53:39 +00:00
|
|
|
r_core_anal_autoname_all_fcns (core);
|
|
|
|
break; //aan
|
2016-02-10 17:45:25 +00:00
|
|
|
case 'p': // "aap"
|
2015-12-16 13:35:56 +00:00
|
|
|
if (*input == '?') {
|
2015-07-31 10:40:04 +00:00
|
|
|
// TODO: accept parameters for ranges
|
2016-01-24 10:33:36 +00:00
|
|
|
eprintf ("Usage: /aap ; find in memory for function preludes");
|
2015-07-31 10:40:04 +00:00
|
|
|
} else {
|
|
|
|
r_core_search_preludes (core);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '\0': // "aa"
|
|
|
|
case 'a':
|
2016-01-25 16:19:30 +00:00
|
|
|
if (input[0] && (input[1] == '?' || (input[1] && input[2] == '?'))) {
|
2017-05-22 00:54:26 +00:00
|
|
|
r_cons_println ("Usage: See aa? for more help");
|
2016-01-24 10:33:36 +00:00
|
|
|
} else {
|
2018-03-01 11:59:13 +00:00
|
|
|
char *dh_orig = NULL;
|
|
|
|
if (!strncmp (input, "aaaaa", 5)) {
|
|
|
|
eprintf ("An r2 developer is coming to your place to manually analyze this program. Please wait for it\n");
|
|
|
|
if (r_config_get_i (core->config, "scr.interactive")) {
|
|
|
|
r_cons_any_key (NULL);
|
|
|
|
}
|
|
|
|
goto jacuzzi;
|
|
|
|
}
|
2016-01-24 10:33:36 +00:00
|
|
|
ut64 curseek = core->offset;
|
2016-03-07 03:12:11 +00:00
|
|
|
rowlog (core, "Analyze all flags starting with sym. and entry0 (aa)");
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2016-12-12 22:57:04 +00:00
|
|
|
r_cons_break_timeout (r_config_get_i (core->config, "anal.timeout"));
|
2016-01-24 10:33:36 +00:00
|
|
|
r_core_anal_all (core);
|
2016-03-07 03:12:11 +00:00
|
|
|
rowlog_done (core);
|
2018-03-01 11:59:13 +00:00
|
|
|
dh_orig = core->dbg->h
|
2017-01-28 15:39:03 +00:00
|
|
|
? strdup (core->dbg->h->name)
|
|
|
|
: strdup ("esil");
|
2017-03-15 10:06:19 +00:00
|
|
|
if (core->io && core->io->desc && core->io->desc->plugin && !core->io->desc->plugin->isdbg) {
|
2017-01-28 15:39:03 +00:00
|
|
|
//use dh_origin if we are debugging
|
|
|
|
R_FREE (dh_orig);
|
2017-02-20 11:15:58 +00:00
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
2015-09-06 22:30:48 +00:00
|
|
|
goto jacuzzi;
|
2016-08-25 15:46:08 +00:00
|
|
|
}
|
2016-01-24 10:33:36 +00:00
|
|
|
r_cons_clear_line (1);
|
|
|
|
if (*input == 'a') { // "aaa"
|
2017-01-24 23:52:36 +00:00
|
|
|
if (dh_orig && strcmp (dh_orig, "esil")) {
|
2017-06-05 12:45:45 +00:00
|
|
|
r_core_cmd0 (core, "dL esil");
|
2017-01-24 23:52:36 +00:00
|
|
|
}
|
2016-01-24 10:33:36 +00:00
|
|
|
int c = r_config_get_i (core->config, "anal.calls");
|
2017-03-22 17:04:26 +00:00
|
|
|
if (should_aav (core)) {
|
2016-10-05 14:01:01 +00:00
|
|
|
rowlog (core, "\nAnalyze value pointers (aav)");
|
|
|
|
r_core_cmd0 (core, "aav");
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
goto jacuzzi;
|
|
|
|
}
|
2016-10-05 14:01:01 +00:00
|
|
|
}
|
2016-01-24 10:33:36 +00:00
|
|
|
r_config_set_i (core->config, "anal.calls", 1);
|
|
|
|
r_core_cmd0 (core, "s $S");
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
2016-01-24 10:33:36 +00:00
|
|
|
goto jacuzzi;
|
2016-08-25 15:46:08 +00:00
|
|
|
}
|
2018-04-24 21:14:10 +00:00
|
|
|
|
2016-03-07 03:12:11 +00:00
|
|
|
rowlog (core, "Analyze function calls (aac)");
|
2017-09-08 14:44:37 +00:00
|
|
|
(void) cmd_anal_calls (core, "", false); // "aac"
|
2017-03-02 09:37:39 +00:00
|
|
|
r_core_seek (core, curseek, 1);
|
2016-08-04 22:30:56 +00:00
|
|
|
// rowlog (core, "Analyze data refs as code (LEA)");
|
|
|
|
// (void) cmd_anal_aad (core, NULL); // "aad"
|
2016-08-04 20:52:33 +00:00
|
|
|
rowlog_done (core);
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
2016-01-24 10:33:36 +00:00
|
|
|
goto jacuzzi;
|
2016-08-04 20:52:33 +00:00
|
|
|
}
|
2018-04-24 21:14:10 +00:00
|
|
|
|
|
|
|
rowlog (core, "Analyze len bytes of instructions for references (aar)");
|
|
|
|
(void)r_core_anal_refs (core, ""); // "aar"
|
|
|
|
rowlog_done (core);
|
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
goto jacuzzi;
|
|
|
|
}
|
|
|
|
|
2016-03-07 03:12:11 +00:00
|
|
|
if (input[1] == 'a') { // "aaaa"
|
2018-03-01 15:34:18 +00:00
|
|
|
bool ioCache = r_config_get_i (core->config, "io.pcache");
|
|
|
|
r_config_set_i (core->config, "io.pcache", 1);
|
2016-03-08 08:05:01 +00:00
|
|
|
rowlog (core, "Emulate code to find computed references (aae)");
|
2016-05-11 02:09:39 +00:00
|
|
|
r_core_cmd0 (core, "aae $SS @ $S");
|
2016-03-07 03:12:11 +00:00
|
|
|
rowlog_done (core);
|
2016-03-08 08:05:01 +00:00
|
|
|
rowlog (core, "Analyze consecutive function (aat)");
|
2016-03-07 03:12:11 +00:00
|
|
|
r_core_cmd0 (core, "aat");
|
|
|
|
rowlog_done (core);
|
2018-03-01 11:49:37 +00:00
|
|
|
// drop cache writes is no cache was
|
|
|
|
if (!ioCache) {
|
|
|
|
r_core_cmd0 (core, "wc-*");
|
|
|
|
}
|
2018-03-01 15:34:18 +00:00
|
|
|
r_config_set_i (core->config, "io.pcache", ioCache);
|
2016-03-12 16:48:53 +00:00
|
|
|
} else {
|
2017-07-26 09:52:51 +00:00
|
|
|
rowlog (core, "Use -AA or aaaa to perform additional experimental analysis.");
|
|
|
|
rowlog_done (core);
|
2016-03-07 03:12:11 +00:00
|
|
|
}
|
2016-01-24 10:33:36 +00:00
|
|
|
r_config_set_i (core->config, "anal.calls", c);
|
2016-03-26 18:42:11 +00:00
|
|
|
rowlog (core, "Constructing a function name for fcn.* and sym.func.* functions (aan)");
|
2016-11-20 18:20:14 +00:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
goto jacuzzi;
|
|
|
|
}
|
2016-04-27 10:45:34 +00:00
|
|
|
if (r_config_get_i (core->config, "anal.autoname")) {
|
|
|
|
r_core_anal_autoname_all_fcns (core);
|
2017-07-28 19:48:14 +00:00
|
|
|
rowlog_done (core);
|
2016-04-27 10:45:34 +00:00
|
|
|
}
|
2016-10-23 17:44:27 +00:00
|
|
|
if (input[1] == 'a') { // "aaaa"
|
2018-03-01 15:34:18 +00:00
|
|
|
bool ioCache = r_config_get_i (core->config, "io.pcache");
|
|
|
|
r_config_set_i (core->config, "io.pcache", 1);
|
2017-09-25 16:36:10 +00:00
|
|
|
if (sdb_count (core->anal->sdb_zigns) > 0) {
|
|
|
|
rowlog (core, "Check for zignature from zigns folder (z/)");
|
|
|
|
r_core_cmd0 (core, "z/");
|
|
|
|
}
|
2016-12-25 17:54:35 +00:00
|
|
|
rowlog (core, "Type matching analysis for all functions (afta)");
|
2016-10-23 17:44:27 +00:00
|
|
|
r_core_cmd0 (core, "afta");
|
|
|
|
rowlog_done (core);
|
2018-03-01 14:37:13 +00:00
|
|
|
if (!ioCache) {
|
|
|
|
r_core_cmd0 (core, "wc-*");
|
|
|
|
}
|
2018-03-01 15:34:18 +00:00
|
|
|
r_config_set_i (core->config, "io.pcache", ioCache);
|
2016-10-23 17:44:27 +00:00
|
|
|
}
|
2016-01-24 10:33:36 +00:00
|
|
|
r_core_cmd0 (core, "s-");
|
2017-01-24 23:52:36 +00:00
|
|
|
if (dh_orig) {
|
2017-06-05 12:45:45 +00:00
|
|
|
r_core_cmdf (core, "dL %s;dpa", dh_orig);
|
2017-01-24 23:52:36 +00:00
|
|
|
}
|
2016-01-24 10:33:36 +00:00
|
|
|
}
|
2017-04-12 00:06:29 +00:00
|
|
|
r_core_seek (core, curseek, 1);
|
2016-01-24 10:33:36 +00:00
|
|
|
jacuzzi:
|
|
|
|
flag_every_function (core);
|
2016-11-20 18:20:14 +00:00
|
|
|
r_cons_break_pop ();
|
2017-01-24 23:52:36 +00:00
|
|
|
R_FREE (dh_orig);
|
2015-07-31 10:40:04 +00:00
|
|
|
}
|
|
|
|
break;
|
2018-03-12 12:10:59 +00:00
|
|
|
case 't': { // "aat"
|
2015-07-31 10:40:04 +00:00
|
|
|
ut64 cur = core->offset;
|
2017-12-13 11:25:37 +00:00
|
|
|
bool hasnext = r_config_get_i (core->config, "anal.hasnext");
|
|
|
|
RListIter *iter;
|
|
|
|
RIOMap* map;
|
2018-01-27 22:10:02 +00:00
|
|
|
RList *list = r_core_get_boundaries_prot (core, R_IO_EXEC, NULL, "anal");
|
2017-12-13 18:38:53 +00:00
|
|
|
r_list_foreach (list, iter, map) {
|
|
|
|
r_core_seek (core, map->itv.addr, 1);
|
2015-07-31 10:40:04 +00:00
|
|
|
r_config_set_i (core->config, "anal.hasnext", 1);
|
2016-09-15 12:18:28 +00:00
|
|
|
r_core_cmd0 (core, "afr");
|
2015-07-31 10:40:04 +00:00
|
|
|
r_config_set_i (core->config, "anal.hasnext", hasnext);
|
2018-03-12 12:10:59 +00:00
|
|
|
}
|
2015-07-31 10:40:04 +00:00
|
|
|
r_core_seek (core, cur, 1);
|
|
|
|
break;
|
|
|
|
}
|
2016-11-14 11:09:29 +00:00
|
|
|
case 'T': // "aaT"
|
|
|
|
cmd_anal_aftertraps (core, input + 1);
|
|
|
|
break;
|
2017-08-27 18:52:35 +00:00
|
|
|
case 'E': // "aaE"
|
|
|
|
r_core_cmd0 (core, "aef @@f");
|
|
|
|
break;
|
2016-02-21 23:22:52 +00:00
|
|
|
case 'e': // "aae"
|
2016-09-07 18:33:41 +00:00
|
|
|
if (input[1]) {
|
2016-09-09 12:52:29 +00:00
|
|
|
const char *len = (char *) input + 1;
|
2016-09-07 18:33:41 +00:00
|
|
|
char *addr = strchr (input + 2, ' ');
|
|
|
|
if (addr) {
|
|
|
|
*addr++ = 0;
|
2016-06-13 23:30:40 +00:00
|
|
|
}
|
2016-09-07 18:33:41 +00:00
|
|
|
r_core_anal_esil (core, len, addr);
|
2016-06-14 21:42:40 +00:00
|
|
|
} else {
|
2016-06-14 22:23:44 +00:00
|
|
|
ut64 at = core->offset;
|
2017-12-13 18:38:53 +00:00
|
|
|
RIOMap* map;
|
|
|
|
RListIter *iter;
|
2018-01-27 22:10:02 +00:00
|
|
|
RList *list = r_core_get_boundaries_prot (core, -1, NULL, "anal");
|
2017-12-13 18:38:53 +00:00
|
|
|
r_list_foreach (list, iter, map) {
|
|
|
|
r_core_seek (core, map->itv.addr, 1);
|
|
|
|
r_core_anal_esil (core, "$SS", NULL);
|
2018-03-12 12:10:59 +00:00
|
|
|
}
|
2016-06-14 22:23:44 +00:00
|
|
|
r_core_seek (core, at, 1);
|
2016-06-13 23:30:40 +00:00
|
|
|
}
|
2015-07-31 10:40:04 +00:00
|
|
|
break;
|
|
|
|
case 'r':
|
2015-09-07 16:20:29 +00:00
|
|
|
(void)r_core_anal_refs (core, input + 1);
|
2015-07-31 10:40:04 +00:00
|
|
|
break;
|
2016-06-14 22:23:44 +00:00
|
|
|
default:
|
|
|
|
r_core_cmd_help (core, help_msg_aa);
|
|
|
|
break;
|
2015-07-31 10:40:04 +00:00
|
|
|
}
|
|
|
|
|
2015-09-14 10:35:38 +00:00
|
|
|
return true;
|
2015-07-31 10:40:04 +00:00
|
|
|
}
|
|
|
|
|
2016-01-25 16:19:30 +00:00
|
|
|
static bool anal_fcn_data (RCore *core, const char *input) {
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, -1);
|
2016-05-15 12:37:22 +00:00
|
|
|
ut32 fcn_size = r_anal_fcn_size (fcn);
|
2016-01-25 16:19:30 +00:00
|
|
|
if (fcn) {
|
|
|
|
int i;
|
2016-01-25 18:19:01 +00:00
|
|
|
bool gap = false;
|
|
|
|
ut64 gap_addr = UT64_MAX;
|
2016-05-15 12:37:22 +00:00
|
|
|
char *bitmap = calloc (1, fcn_size);
|
2016-01-25 16:19:30 +00:00
|
|
|
if (bitmap) {
|
|
|
|
RAnalBlock *b;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (fcn->bbs, iter, b) {
|
|
|
|
int f = b->addr - fcn->addr;
|
2016-05-15 12:37:22 +00:00
|
|
|
int t = R_MIN (f + b->size, fcn_size);
|
2016-08-21 09:39:37 +00:00
|
|
|
if (f >= 0) {
|
2016-01-25 16:19:30 +00:00
|
|
|
while (f < t) {
|
|
|
|
bitmap[f++] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-05-15 12:37:22 +00:00
|
|
|
for (i = 0; i < fcn_size; i++) {
|
2016-01-25 16:19:30 +00:00
|
|
|
ut64 here = fcn->addr + i;
|
2016-02-16 01:08:09 +00:00
|
|
|
if (bitmap && bitmap[i]) {
|
2016-01-25 18:19:01 +00:00
|
|
|
if (gap) {
|
|
|
|
r_cons_printf ("Cd %d @ 0x%08"PFMT64x"\n", here - gap_addr, gap_addr);
|
|
|
|
gap = false;
|
2016-01-25 16:19:30 +00:00
|
|
|
}
|
2016-01-25 18:19:01 +00:00
|
|
|
gap_addr = UT64_MAX;
|
2016-01-25 16:19:30 +00:00
|
|
|
} else {
|
2016-01-25 18:19:01 +00:00
|
|
|
if (!gap) {
|
|
|
|
gap = true;
|
|
|
|
gap_addr = here;
|
|
|
|
}
|
2016-01-25 16:19:30 +00:00
|
|
|
}
|
|
|
|
}
|
2016-01-25 18:19:01 +00:00
|
|
|
if (gap) {
|
2016-05-15 12:37:22 +00:00
|
|
|
r_cons_printf ("Cd %d @ 0x%08"PFMT64x"\n", fcn->addr + fcn_size - gap_addr, gap_addr);
|
2016-01-25 18:19:01 +00:00
|
|
|
gap = false;
|
|
|
|
}
|
2016-01-25 16:19:30 +00:00
|
|
|
free (bitmap);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmpaddr (const void *_a, const void *_b) {
|
2016-10-25 10:03:55 +00:00
|
|
|
const RAnalFunction *a = _a, *b = _b;
|
|
|
|
return a->addr - b->addr;
|
2016-01-25 16:19:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool anal_fcn_data_gaps (RCore *core, const char *input) {
|
|
|
|
ut64 end = UT64_MAX;
|
|
|
|
RAnalFunction *fcn;
|
|
|
|
RListIter *iter;
|
|
|
|
int i, wordsize = (core->assembler->bits == 64)? 8: 4;
|
|
|
|
r_list_sort (core->anal->fcns, cmpaddr);
|
|
|
|
r_list_foreach (core->anal->fcns, iter, fcn) {
|
|
|
|
if (end != UT64_MAX) {
|
|
|
|
int range = fcn->addr - end;
|
|
|
|
if (range > 0) {
|
|
|
|
for (i = 0; i + wordsize < range; i+= wordsize) {
|
|
|
|
r_cons_printf ("Cd %d @ 0x%08"PFMT64x"\n", wordsize, end + i);
|
|
|
|
}
|
|
|
|
r_cons_printf ("Cd %d @ 0x%08"PFMT64x"\n", range - i, end + i);
|
|
|
|
//r_cons_printf ("Cd %d @ 0x%08"PFMT64x"\n", range, end);
|
|
|
|
}
|
|
|
|
}
|
2016-05-15 12:37:22 +00:00
|
|
|
end = fcn->addr + r_anal_fcn_size (fcn);
|
2016-01-25 16:19:30 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-14 12:49:39 +00:00
|
|
|
static void cmd_anal_rtti(RCore *core, const char *input) {
|
|
|
|
switch (input[0]) {
|
|
|
|
case '\0': // "avr"
|
2018-03-20 20:22:40 +00:00
|
|
|
case 'j': // "avrj"
|
|
|
|
r_anal_rtti_print_at_vtable (core->anal, core->offset, input[0]);
|
2018-03-14 12:49:39 +00:00
|
|
|
break;
|
|
|
|
case 'a': // "avra"
|
2018-03-14 15:44:48 +00:00
|
|
|
r_anal_rtti_print_all (core->anal, input[1]);
|
2018-03-14 12:49:39 +00:00
|
|
|
break;
|
|
|
|
default :
|
|
|
|
r_core_cmd_help (core, help_msg_av);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-09 12:02:39 +00:00
|
|
|
static void cmd_anal_virtual_functions(RCore *core, const char* input) {
|
2018-03-08 17:02:47 +00:00
|
|
|
switch (input[0]) {
|
2018-03-10 20:28:27 +00:00
|
|
|
case '\0': // "av"
|
2018-03-14 12:29:44 +00:00
|
|
|
case '*': // "av*"
|
2018-03-08 17:02:47 +00:00
|
|
|
case 'j': // "avj"
|
2018-03-10 20:28:27 +00:00
|
|
|
r_anal_list_vtables (core->anal, input[0]);
|
2018-03-08 17:02:47 +00:00
|
|
|
break;
|
|
|
|
case 'r': // "avr"
|
2018-03-14 12:49:39 +00:00
|
|
|
cmd_anal_rtti (core, input + 1);
|
2018-03-08 17:02:47 +00:00
|
|
|
break;
|
|
|
|
default :
|
2018-03-14 12:29:44 +00:00
|
|
|
r_core_cmd_help (core, help_msg_av);
|
2018-03-08 17:02:47 +00:00
|
|
|
break;
|
2016-08-15 18:57:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-31 10:40:04 +00:00
|
|
|
static int cmd_anal(void *data, const char *input) {
|
|
|
|
const char *r;
|
|
|
|
RCore *core = (RCore *)data;
|
|
|
|
ut32 tbs = core->blocksize;
|
2014-12-05 06:34:54 +00:00
|
|
|
|
|
|
|
switch (input[0]) {
|
2016-01-24 02:05:27 +00:00
|
|
|
case 'p': // "ap"
|
|
|
|
{
|
|
|
|
const ut8 *prelude = (const ut8*)"\xe9\x2d"; //:fffff000";
|
|
|
|
const int prelude_sz = 2;
|
|
|
|
const int bufsz = 4096;
|
|
|
|
ut8 *buf = calloc (1, bufsz);
|
|
|
|
ut64 off = core->offset;
|
|
|
|
if (input[1] == ' ') {
|
|
|
|
off = r_num_math (core->num, input+1);
|
|
|
|
r_io_read_at (core->io, off - bufsz + prelude_sz, buf, bufsz);
|
|
|
|
} else {
|
|
|
|
r_io_read_at (core->io, off - bufsz + prelude_sz, buf, bufsz);
|
|
|
|
}
|
|
|
|
//const char *prelude = "\x2d\xe9\xf0\x47"; //:fffff000";
|
|
|
|
r_mem_reverse (buf, bufsz);
|
|
|
|
//r_print_hexdump (NULL, off, buf, bufsz, 16, -16);
|
|
|
|
const ut8 *pos = r_mem_mem (buf, bufsz, prelude, prelude_sz);
|
|
|
|
if (pos) {
|
|
|
|
int delta = (size_t)(pos - buf);
|
|
|
|
eprintf ("POS = %d\n", delta);
|
|
|
|
eprintf ("HIT = 0x%"PFMT64x"\n", off - delta);
|
|
|
|
r_cons_printf ("0x%08"PFMT64x"\n", off - delta);
|
|
|
|
} else {
|
|
|
|
eprintf ("Cannot find prelude\n");
|
|
|
|
}
|
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
break;
|
2018-04-05 07:30:47 +00:00
|
|
|
case '8':
|
|
|
|
{
|
2015-12-16 13:35:56 +00:00
|
|
|
ut8 *buf = malloc (strlen (input) + 1);
|
2018-04-04 23:45:12 +00:00
|
|
|
if (buf) {
|
2018-04-05 07:30:47 +00:00
|
|
|
int len = r_hex_str2bin (input + 1, buf);
|
2018-04-04 23:45:12 +00:00
|
|
|
if (len > 0) {
|
|
|
|
core_anal_bytes (core, buf, len, 0, input[1]);
|
|
|
|
}
|
|
|
|
free (buf);
|
2016-11-24 00:56:49 +00:00
|
|
|
}
|
2018-04-05 07:30:47 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
if (input[1] == 'b') { // "abb"
|
|
|
|
core_anal_bbs (core, input + 2);
|
|
|
|
} else if (input[1] == 'r') { // "abr"
|
|
|
|
core_anal_bbs_range (core, input + 2);
|
2018-04-04 23:45:12 +00:00
|
|
|
} else if (input[1] == ' ' || !input[1]) {
|
|
|
|
// find block
|
|
|
|
ut64 addr = core->offset;
|
|
|
|
if (input[1]) {
|
|
|
|
addr = r_num_math (core->num, input + 1);
|
|
|
|
}
|
|
|
|
r_core_cmdf (core, "afbi @ 0x%"PFMT64x, addr);
|
2016-11-20 18:20:14 +00:00
|
|
|
} else {
|
2018-04-04 23:45:12 +00:00
|
|
|
r_core_cmd_help (core, help_msg_ab);
|
2016-11-20 18:20:14 +00:00
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2015-12-16 13:35:56 +00:00
|
|
|
case 'i': cmd_anal_info (core, input + 1); break; // "ai"
|
|
|
|
case 'r': cmd_anal_reg (core, input + 1); break; // "ar"
|
|
|
|
case 'e': cmd_anal_esil (core, input + 1); break; // "ae"
|
2016-04-21 01:41:09 +00:00
|
|
|
case 'o': cmd_anal_opcode (core, input + 1); break; // "ao"
|
2016-08-04 21:52:10 +00:00
|
|
|
case 'O': cmd_anal_bytes (core, input + 1); break; // "aO"
|
2017-08-05 10:20:17 +00:00
|
|
|
case 'F': // "aF"
|
2014-07-01 15:01:52 +00:00
|
|
|
r_core_anal_fcn (core, core->offset, UT64_MAX, R_ANAL_REF_TYPE_NULL, 1);
|
2012-11-08 08:49:27 +00:00
|
|
|
break;
|
2016-01-18 23:44:24 +00:00
|
|
|
case 'f': // "af"
|
2017-05-23 21:55:22 +00:00
|
|
|
{
|
|
|
|
int res = cmd_anal_fcn (core, input);
|
|
|
|
if (!res) {
|
2015-09-14 10:35:38 +00:00
|
|
|
return false;
|
2014-09-22 13:00:41 +00:00
|
|
|
}
|
2017-05-23 21:55:22 +00:00
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
2017-11-26 19:10:49 +00:00
|
|
|
case 'n': // 'an'
|
|
|
|
{
|
2017-11-30 13:21:24 +00:00
|
|
|
const char *name = NULL;
|
2017-11-30 15:14:38 +00:00
|
|
|
bool use_json = false;
|
|
|
|
|
|
|
|
if (input[1] == 'j') {
|
|
|
|
use_json = true;
|
|
|
|
input++;
|
|
|
|
}
|
|
|
|
|
2017-11-30 13:21:24 +00:00
|
|
|
if (input[1] == ' ') {
|
|
|
|
name = input + 1;
|
|
|
|
while (name[0] == ' ') {
|
|
|
|
name++;
|
|
|
|
}
|
|
|
|
char *end = strchr (name, ' ');
|
|
|
|
if (end) {
|
|
|
|
*end = '\0';
|
|
|
|
}
|
|
|
|
if (*name == '\0') {
|
|
|
|
name = NULL;
|
|
|
|
}
|
2017-11-26 19:10:49 +00:00
|
|
|
}
|
2017-11-30 15:14:38 +00:00
|
|
|
|
|
|
|
cmd_an (core, use_json, name);
|
2017-11-26 19:10:49 +00:00
|
|
|
}
|
2017-11-30 13:21:24 +00:00
|
|
|
break;
|
2017-08-05 10:20:17 +00:00
|
|
|
case 'g': // "ag"
|
2015-12-16 13:35:56 +00:00
|
|
|
cmd_anal_graph (core, input + 1);
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
2014-10-19 20:43:33 +00:00
|
|
|
case 's': // "as"
|
2015-12-16 13:35:56 +00:00
|
|
|
cmd_anal_syscall (core, input + 1);
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
2017-08-05 10:20:17 +00:00
|
|
|
case 'v': // "av"
|
2018-03-09 12:02:39 +00:00
|
|
|
cmd_anal_virtual_functions (core, input + 1);
|
2016-08-15 18:57:56 +00:00
|
|
|
break;
|
2017-08-05 10:20:17 +00:00
|
|
|
case 'x': // "ax"
|
2015-12-16 13:35:56 +00:00
|
|
|
if (!cmd_anal_refs (core, input + 1)) {
|
2015-09-14 10:35:38 +00:00
|
|
|
return false;
|
2015-01-30 00:55:21 +00:00
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
2017-08-05 10:20:17 +00:00
|
|
|
case 'a': // "aa"
|
2015-07-31 10:40:04 +00:00
|
|
|
if (!cmd_anal_all (core, input + 1))
|
2015-09-14 10:35:38 +00:00
|
|
|
return false;
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
2017-08-05 10:20:17 +00:00
|
|
|
case 'c': // "ac"
|
2016-12-21 08:02:55 +00:00
|
|
|
{
|
|
|
|
RList *hooks;
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalCycleHook *hook;
|
|
|
|
char *instr_tmp = NULL;
|
|
|
|
int ccl = input[1]? r_num_math (core->num, &input[2]): 0; //get cycles to look for
|
2018-02-22 16:59:08 +00:00
|
|
|
int cr = r_config_get_i (core->config, "asm.cmt.right");
|
2016-12-21 08:02:55 +00:00
|
|
|
int fun = r_config_get_i (core->config, "asm.functions");
|
|
|
|
int li = r_config_get_i (core->config, "asm.lines");
|
|
|
|
int xr = r_config_get_i (core->config, "asm.xrefs");
|
|
|
|
|
2018-02-22 16:59:08 +00:00
|
|
|
r_config_set_i (core->config, "asm.cmt.right", true);
|
2016-12-21 08:02:55 +00:00
|
|
|
r_config_set_i (core->config, "asm.functions", false);
|
|
|
|
r_config_set_i (core->config, "asm.lines", false);
|
|
|
|
r_config_set_i (core->config, "asm.xrefs", false);
|
|
|
|
|
|
|
|
hooks = r_core_anal_cycles (core, ccl); //analyse
|
|
|
|
r_cons_clear_line (1);
|
|
|
|
r_list_foreach (hooks, iter, hook) {
|
|
|
|
instr_tmp = r_core_disassemble_instr (core, hook->addr, 1);
|
|
|
|
r_cons_printf ("After %4i cycles:\t%s", (ccl - hook->cycles), instr_tmp);
|
|
|
|
r_cons_flush ();
|
|
|
|
free (instr_tmp);
|
|
|
|
}
|
|
|
|
r_list_free (hooks);
|
|
|
|
|
2018-02-22 16:59:08 +00:00
|
|
|
r_config_set_i (core->config, "asm.cmt.right", cr); //reset settings
|
2016-12-21 08:02:55 +00:00
|
|
|
r_config_set_i (core->config, "asm.functions", fun);
|
|
|
|
r_config_set_i (core->config, "asm.lines", li);
|
|
|
|
r_config_set_i (core->config, "asm.xrefs", xr);
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
2014-03-24 23:48:42 +00:00
|
|
|
break;
|
2017-04-10 00:18:47 +00:00
|
|
|
case 'd': // "ad"
|
2012-11-20 02:59:00 +00:00
|
|
|
switch (input[1]) {
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'f': // "adf"
|
2016-01-25 16:19:30 +00:00
|
|
|
if (input[2] == 'g') {
|
|
|
|
anal_fcn_data_gaps (core, input + 1);
|
|
|
|
} else {
|
|
|
|
anal_fcn_data (core, input + 1);
|
|
|
|
}
|
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 't': // "adt"
|
2015-12-16 13:35:56 +00:00
|
|
|
cmd_anal_trampoline (core, input + 2);
|
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case ' ': { // "ad"
|
2015-12-16 13:35:56 +00:00
|
|
|
const int default_depth = 1;
|
|
|
|
const char *p;
|
|
|
|
int a, b;
|
|
|
|
a = r_num_math (core->num, input + 2);
|
|
|
|
p = strchr (input + 2, ' ');
|
|
|
|
b = p? r_num_math (core->num, p + 1): default_depth;
|
2016-11-24 00:56:49 +00:00
|
|
|
if (a < 1) {
|
|
|
|
a = 1;
|
|
|
|
}
|
|
|
|
if (b < 1) {
|
|
|
|
b = 1;
|
|
|
|
}
|
2017-04-10 00:18:47 +00:00
|
|
|
r_core_anal_data (core, core->offset, a, b, 0);
|
2015-12-16 13:35:56 +00:00
|
|
|
} break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'k': // "adk"
|
2015-01-30 00:55:21 +00:00
|
|
|
r = r_anal_data_kind (core->anal,
|
|
|
|
core->offset, core->block, core->blocksize);
|
2016-06-26 04:16:57 +00:00
|
|
|
r_cons_println (r);
|
2012-11-20 02:59:00 +00:00
|
|
|
break;
|
2017-04-10 00:18:47 +00:00
|
|
|
case '\0': // "ad"
|
|
|
|
r_core_anal_data (core, core->offset, 2 + (core->blocksize / 4), 1, 0);
|
|
|
|
break;
|
|
|
|
case '4': // "ad4"
|
|
|
|
r_core_anal_data (core, core->offset, 2 + (core->blocksize / 4), 1, 4);
|
|
|
|
break;
|
|
|
|
case '8': // "ad8"
|
|
|
|
r_core_anal_data (core, core->offset, 2 + (core->blocksize / 4), 1, 8);
|
2013-01-22 04:06:12 +00:00
|
|
|
break;
|
2014-12-05 06:34:54 +00:00
|
|
|
default:
|
2015-01-30 00:55:21 +00:00
|
|
|
r_core_cmd_help (core, help_msg_ad);
|
2013-01-22 04:06:12 +00:00
|
|
|
break;
|
2014-12-05 06:34:54 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case 'h': // "ah"
|
2015-12-16 13:35:56 +00:00
|
|
|
cmd_anal_hint (core, input + 1);
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
2017-07-24 15:41:50 +00:00
|
|
|
case '!': // "a!"
|
2016-11-20 18:20:14 +00:00
|
|
|
if (core->anal && core->anal->cur && core->anal->cur->cmd_ext) {
|
2015-12-16 13:35:56 +00:00
|
|
|
return core->anal->cur->cmd_ext (core->anal, input + 1);
|
2016-11-20 18:20:14 +00:00
|
|
|
} else {
|
|
|
|
r_cons_printf ("No plugins for this analysis plugin\n");
|
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
|
|
|
default:
|
2017-07-24 15:41:50 +00:00
|
|
|
r_core_cmd_help (core, help_msg_a);
|
2018-01-07 20:54:41 +00:00
|
|
|
#if 0
|
2015-01-30 00:55:21 +00:00
|
|
|
r_cons_printf ("Examples:\n"
|
2015-12-16 13:35:56 +00:00
|
|
|
" f ts @ `S*~text:0[3]`; f t @ section..text\n"
|
|
|
|
" f ds @ `S*~data:0[3]`; f d @ section..data\n"
|
|
|
|
" .ad t t+ts @ d:ds\n",
|
|
|
|
NULL);
|
2018-01-07 20:54:41 +00:00
|
|
|
#endif
|
2014-12-05 06:34:54 +00:00
|
|
|
break;
|
|
|
|
}
|
2016-11-20 18:20:14 +00:00
|
|
|
if (tbs != core->blocksize) {
|
2014-12-05 06:34:54 +00:00
|
|
|
r_core_block_size (core, tbs);
|
2016-11-20 18:20:14 +00:00
|
|
|
}
|
|
|
|
if (r_cons_is_breaked ()) {
|
2014-12-05 06:34:54 +00:00
|
|
|
r_cons_clear_line (1);
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
2014-12-05 06:34:54 +00:00
|
|
|
return 0;
|
|
|
|
}
|