2020-03-16 13:56:47 +01:00
|
|
|
/* radare - LGPL - Copyright 2009-2020 - pancake */
|
2016-05-17 00:37:47 +02:00
|
|
|
|
2016-05-02 22:52:41 -04:00
|
|
|
#include "r_asm.h"
|
|
|
|
#include "r_core.h"
|
|
|
|
#include "r_config.h"
|
2018-11-14 14:54:22 +05:00
|
|
|
#include "r_util.h"
|
2016-05-02 22:52:41 -04:00
|
|
|
#include "r_types.h"
|
2017-01-31 10:00:24 +01:00
|
|
|
#include <limits.h>
|
2013-11-14 07:52:03 -05:00
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
#define R_CORE_MAX_DISASM (1024 * 1024 * 8)
|
2017-02-08 11:37:31 +00:00
|
|
|
#define PF_USAGE_STR "pf[.k[.f[=v]]|[v]]|[n]|[0|cnt][fmt] [a0 a1 ...]"
|
2018-09-07 16:42:06 +02:00
|
|
|
|
2019-04-16 13:47:22 +02:00
|
|
|
static int printzoomcallback(void *user, int mode, ut64 addr, ut8 *bufz, ut64 size);
|
2018-09-07 16:42:06 +02:00
|
|
|
static const char *help_msg_pa[] = {
|
|
|
|
"Usage: pa[edD]", "[asm|hex]", "print (dis)assembled",
|
2018-09-30 02:56:46 +02:00
|
|
|
"pa", " [assembly]", "print hexpairs of the given assembly expression",
|
|
|
|
"paD", " [hexpairs]", "print assembly expression from hexpairs and show hexpairs",
|
2019-08-18 22:43:41 +02:00
|
|
|
"pad", " [hexpairs]", "print assembly expression from hexpairs (alias for pdx, pix)",
|
2018-09-30 02:56:46 +02:00
|
|
|
"pade", " [hexpairs]", "print ESIL expression from hexpairs",
|
|
|
|
"pae", " [assembly]", "print ESIL expression of the given assembly expression",
|
2018-09-07 16:42:06 +02:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_pdf[] = {
|
|
|
|
"Usage: pdf[bf]", "", "disassemble function",
|
|
|
|
"pdf", "", "disassemble function",
|
|
|
|
"pdfs", "", "disassemble function summary",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2019-06-22 12:58:37 +02:00
|
|
|
static const char *help_msg_pp[] = {
|
|
|
|
"Usage: pp[d]", "", "print patterns",
|
|
|
|
"pp0", "", "print buffer filled with zeros",
|
|
|
|
"pp1", "", "print incremental byte pattern (honor lower bits of cur address and bsize)",
|
|
|
|
"pp2", "", "print incremental word pattern",
|
|
|
|
"pp4", "", "print incremental dword pattern",
|
|
|
|
"pp8", "", "print incremental qword pattern",
|
|
|
|
"ppa", "[lu]", "latin alphabet (lowercase, uppercases restrictions)",
|
2019-07-25 13:21:56 +02:00
|
|
|
"ppd", "", "print debruijn pattern (see ragg2 -P, -q and wopD)",
|
|
|
|
"ppf", "", "print buffer filled with 0xff",
|
2019-06-22 12:58:37 +02:00
|
|
|
"ppn", "", "numeric pin patterns",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2020-05-13 18:44:02 +02:00
|
|
|
static const char *help_msg_pc[] = {
|
|
|
|
"Usage:", "pc", " # Print in code",
|
|
|
|
"pc", "", "C",
|
|
|
|
"pc*", "", "print 'wx' r2 commands",
|
|
|
|
"pcA", "", ".bytes with instructions in comments",
|
|
|
|
"pca", "", "GAS .byte blob",
|
|
|
|
"pcd", "", "C dwords (8 byte)",
|
|
|
|
"pch", "", "C half-words (2 byte)",
|
|
|
|
"pci", "", "C array of bytes with instructions",
|
|
|
|
"pcJ", "", "javascript",
|
|
|
|
"pcj", "", "json",
|
|
|
|
"pck", "", "kotlin",
|
|
|
|
"pco", "", "Objective-C",
|
|
|
|
"pcp", "", "python",
|
|
|
|
"pcr", "", "rust",
|
|
|
|
"pcS", "", "shellscript that reconstructs the bin",
|
|
|
|
"pcs", "", "string",
|
|
|
|
"pcv", "", "JaVa",
|
|
|
|
"pcV", "", "V (vlang.io)",
|
|
|
|
"pcw", "", "C words (4 byte)",
|
|
|
|
"pcy", "", "yara",
|
|
|
|
"pcz", "", "Swift",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2018-09-07 16:28:49 +02:00
|
|
|
static const char *help_msg_p6[] = {
|
|
|
|
"Usage: p6[de]", "[len]", "base64 decoding/encoding",
|
|
|
|
"p6d", "[len]", "decode base64",
|
|
|
|
"p6e", "[len]", "encode base64",
|
|
|
|
NULL
|
|
|
|
};
|
2017-02-08 11:37:31 +00:00
|
|
|
|
2018-09-12 18:43:59 +02:00
|
|
|
static const char *help_msg_pF[] = {
|
2019-11-06 21:55:36 +01:00
|
|
|
"Usage: pF[apdb]", "[len]", "parse ASN1, PKCS, X509, DER, protobuf",
|
2018-09-12 18:43:59 +02:00
|
|
|
"pFa", "[len]", "decode ASN1 from current block",
|
2018-09-20 19:16:33 +02:00
|
|
|
"pFaq", "[len]", "decode ASN1 from current block (quiet output)",
|
2019-11-06 21:55:36 +01:00
|
|
|
"pFb", "[len]", "decode raw proto buffers.",
|
|
|
|
"pFbv", "[len]", "decode raw proto buffers (verbose).",
|
2018-09-13 01:15:18 +02:00
|
|
|
"pFo", "[len]", "decode ASN1 OID",
|
|
|
|
"pFp", "[len]", "decode PKCS7",
|
2018-09-12 18:43:59 +02:00
|
|
|
"pFx", "[len]", "Same with X509",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2018-09-07 16:19:25 +02:00
|
|
|
static const char* help_msg_pr[] = {
|
|
|
|
"Usage: pr[glx]", "[size]", "print N raw bytes",
|
2019-04-16 13:47:22 +02:00
|
|
|
"prc", "[=fep..]", "print bytes as colors in palette",
|
2019-07-25 13:21:56 +02:00
|
|
|
"prg", "[?]", "print raw GUNZIPped block",
|
2019-07-11 06:10:15 +02:00
|
|
|
"pri", "[aA2r]", "print raw image, honor hex.cols",
|
2018-09-07 16:28:49 +02:00
|
|
|
"prl", "", "print raw with lines offsets",
|
|
|
|
"prx", "", "printable chars with real offset (hyew)",
|
|
|
|
"prz", "", "print raw zero terminated string",
|
2018-09-07 16:19:25 +02:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_prg[] = {
|
|
|
|
"Usage: prg[io]", "", "print raw GUNZIPped block",
|
|
|
|
"prg", "", "print gunzipped data of current block",
|
|
|
|
"prgi", "", "show consumed bytes when inflating",
|
|
|
|
"prgo", "", "show output bytes after inflating",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-25 04:20:25 -07:00
|
|
|
static const char *help_msg_amper[] = {
|
2018-06-16 10:51:02 +02:00
|
|
|
"Usage:", "&[-|<cmd>]", "Manage tasks (WARNING: Experimental. Use with caution!)",
|
|
|
|
"&", " <cmd>", "run <cmd> in a new background task",
|
2018-08-23 13:49:28 +02:00
|
|
|
"&t", " <cmd>", "run <cmd> in a new transient background task (auto-delete when it is finished)",
|
2018-06-16 10:51:02 +02:00
|
|
|
"&", "", "list all tasks",
|
|
|
|
"&j", "", "list all tasks (in JSON)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"&=", " 3", "show output of task 3",
|
2018-07-21 13:44:41 +02:00
|
|
|
"&b", " 3", "break task 3",
|
2018-08-23 13:49:28 +02:00
|
|
|
"&-", " 1", "delete task #1 or schedule for deletion when it is finished",
|
2018-06-16 10:51:02 +02:00
|
|
|
"&", "-*", "delete all done tasks",
|
|
|
|
"&?", "", "show this help",
|
|
|
|
"&&", " 3", "wait until task 3 is finished",
|
|
|
|
"&&", "", "wait until all tasks are finished",
|
2017-07-25 04:20:25 -07:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_at[] = {
|
|
|
|
"Usage: [.][#]<cmd>[*] [`cmd`] [@ addr] [~grep] [|syscmd] [>[>]file]", "", "",
|
|
|
|
"0", "", "alias for 's 0'",
|
|
|
|
"0x", "addr", "alias for 's 0x..'",
|
|
|
|
"#", "cmd", "if # is a number repeat the command # times",
|
|
|
|
"/*", "", "start multiline comment",
|
|
|
|
"*/", "", "end multiline comment",
|
|
|
|
".", "cmd", "execute output of command as r2 script",
|
|
|
|
".:", "8080", "wait for commands on port 8080",
|
|
|
|
".!", "rabin2 -re $FILE", "run command output as r2 script",
|
|
|
|
"*", "", "output of command in r2 script format (CC*)",
|
|
|
|
"j", "", "output of command in JSON format (pdj)",
|
|
|
|
"~", "?", "count number of lines (like wc -l)",
|
|
|
|
"~", "??", "show internal grep help",
|
|
|
|
"~", "..", "internal less",
|
|
|
|
"~", "{}", "json indent",
|
|
|
|
"~", "{}..", "json indent and less",
|
|
|
|
"~", "word", "grep for lines matching word",
|
|
|
|
"~", "!word", "grep for lines NOT matching word",
|
|
|
|
"~", "word[2]", "grep 3rd column of lines matching word",
|
|
|
|
"~", "word:3[0]", "grep 1st column from the 4th line matching word",
|
|
|
|
"@", " 0x1024", "temporary seek to this address (sym.main+3)",
|
2017-08-11 02:45:32 -07:00
|
|
|
"@", " [addr]!blocksize", "temporary set a new blocksize",
|
2017-12-18 02:02:29 +01:00
|
|
|
"@..", "addr", "temporary partial address seek (see s..)",
|
2018-08-29 20:52:10 +02:00
|
|
|
"@!", "blocksize", "temporary change the block size (p8@3!3)",
|
2020-03-24 11:05:22 +01:00
|
|
|
"@{", "from to}", "temporary set from and to for commands supporting ranges",
|
2017-07-25 04:20:25 -07:00
|
|
|
"@a:", "arch[:bits]", "temporary set arch and bits",
|
|
|
|
"@b:", "bits", "temporary set asm.bits",
|
2018-08-07 15:00:36 +02:00
|
|
|
"@B:", "nth", "temporary seek to nth instruction in current bb (negative numbers too)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"@e:", "k=v,k=v", "temporary change eval vars",
|
|
|
|
"@f:", "file", "temporary replace block with file contents",
|
2018-03-02 16:11:07 +01:00
|
|
|
"@F:", "flagspace", "temporary change flag space",
|
|
|
|
"@i:", "nth.op", "temporary seek to the Nth relative instruction",
|
|
|
|
"@k:", "k", "temporary seek at value of sdb key `k`",
|
2017-07-25 04:20:25 -07:00
|
|
|
"@o:", "fd", "temporary switch to another fd",
|
2018-03-02 16:11:07 +01:00
|
|
|
"@r:", "reg", "tmp seek to reg value (f.ex pd@r:PC)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"@s:", "string", "same as above but from a string",
|
|
|
|
"@x:", "909192", "from hex pairs string",
|
|
|
|
"@@=", "1 2 3", "run the previous command at offsets 1, 2 and 3",
|
|
|
|
"@@", " hit*", "run the command on every flag matching 'hit*'",
|
|
|
|
"@@?", "[ktfb..]", "show help for the iterator operator",
|
|
|
|
"@@@", " [type]", "run a command on every [type] (see @@@? for help)",
|
|
|
|
">", "file", "pipe output of command to file",
|
|
|
|
">>", "file", "append to file",
|
|
|
|
"H>", "file", "pipe output of command to file in HTML",
|
|
|
|
"H>>", "file", "append to file with the output of command in HTML",
|
|
|
|
"`", "pdi~push:0[0]`", "replace output of command inside the line",
|
|
|
|
"|", "cmd", "pipe output to command (pd|less) (.dr*)",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_at_at[] = {
|
|
|
|
"@@", "", " # foreach iterator command:",
|
|
|
|
"x", " @@ sym.*", "run 'x' over all flags matching 'sym.' in current flagspace",
|
2017-09-05 11:54:41 +02:00
|
|
|
"x", " @@dbt[abs]", "run 'x' command on every backtrace address, bp or sp",
|
|
|
|
"x", " @@.file", "run 'x' over the offsets specified in the file (one offset per line)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"x", " @@=off1 off2 ..", "manual list of offsets",
|
|
|
|
"x", " @@/x 9090", "temporary set cmd.hit to run a command on each search result",
|
2017-09-05 11:54:41 +02:00
|
|
|
"x", " @@k sdbquery", "run 'x' on all offsets returned by that sdbquery",
|
|
|
|
"x", " @@t", "run 'x' on all threads (see dp)",
|
|
|
|
"x", " @@b", "run 'x' on all basic blocks of current function (see afb)",
|
|
|
|
"x", " @@i", "run 'x' on all instructions of the current function (see pdr)",
|
2018-02-27 23:46:47 +01:00
|
|
|
"x", " @@iS", "run 'x' on all sections adjusting blocksize",
|
2017-09-05 11:54:41 +02:00
|
|
|
"x", " @@f", "run 'x' on all functions (see aflq)",
|
|
|
|
"x", " @@f:write", "run 'x' on all functions matching write in the name",
|
|
|
|
"x", " @@s:from to step", "run 'x' on all offsets from, to incrementing by step",
|
2017-07-25 04:20:25 -07:00
|
|
|
"x", " @@c:cmd", "the same as @@=`` without the backticks",
|
|
|
|
"x", " @@=`pdf~call[0]`", "run 'x' at every call offset of the current function",
|
|
|
|
// TODO: Add @@k sdb-query-expression-here
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2018-03-02 18:58:14 +01:00
|
|
|
static const char *help_msg_at_at_at[] = {
|
|
|
|
"@@@", "", " # foreach offset+size iterator command:",
|
2019-04-15 01:49:34 +02:00
|
|
|
"x", " @@@=", "[addr] [size] ([addr] [size] ...)",
|
|
|
|
"x", " @@@b", "basic blocks of current function",
|
|
|
|
"x", " @@@c:cmd", "Same as @@@=`cmd`, without the backticks",
|
|
|
|
"x", " @@@C:cmd", "comments matching",
|
2018-03-02 18:58:14 +01:00
|
|
|
"x", " @@@i", "imports",
|
2019-04-15 01:49:34 +02:00
|
|
|
"x", " @@@r", "registers",
|
2018-03-02 18:58:14 +01:00
|
|
|
"x", " @@@s", "symbols",
|
2019-05-05 11:28:03 +02:00
|
|
|
"x", " @@@st", "strings",
|
2018-03-02 18:58:14 +01:00
|
|
|
"x", " @@@S", "sections",
|
2019-04-15 01:49:34 +02:00
|
|
|
"x", " @@@m", "io.maps",
|
|
|
|
"x", " @@@M", "dbg.maps (See ?$?~size)",
|
2018-03-02 18:58:14 +01:00
|
|
|
"x", " @@@f", "flags",
|
2019-04-15 01:49:34 +02:00
|
|
|
"x", " @@@f:hit*", "flags matching glob expression",
|
|
|
|
"x", " @@@F", "functions (set fcn size which may be incorrect if not linear)",
|
|
|
|
"x", " @@@F:glob", "functions matching glob expression",
|
2018-03-02 18:58:14 +01:00
|
|
|
"x", " @@@t", "threads",
|
|
|
|
"x", " @@@r", "regs",
|
|
|
|
// TODO: Add @@k sdb-query-expression-here
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-25 04:20:25 -07:00
|
|
|
static const char *help_msg_p[] = {
|
|
|
|
"Usage:", "p[=68abcdDfiImrstuxz] [arg|len] [@addr]", "",
|
2019-07-25 13:21:56 +02:00
|
|
|
"p", "[b|B|xb] [len] ([S])", "bindump N bits skipping S bytes",
|
|
|
|
"p", "[iI][df] [len]", "print N ops/bytes (f=func) (see pi? and pdi)",
|
|
|
|
"p", "[kK] [len]", "print key in randomart (K is for mosaic)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"p-", "[?][jh] [mode]", "bar|json|histogram blocks (mode: e?search.in)",
|
|
|
|
"p2", " [len]", "8x8 2bpp-tiles",
|
|
|
|
"p3", " [file]", "print stereogram (3D)",
|
|
|
|
"p6", "[de] [len]", "base64 decode/encode",
|
|
|
|
"p8", "[?][j] [len]", "8bit hexpair list of bytes",
|
2019-07-25 13:21:56 +02:00
|
|
|
"p=", "[?][bep] [N] [L] [b]", "show entropy/printable chars/chars bars",
|
2018-08-06 12:29:48 +02:00
|
|
|
"pa", "[edD] [arg]", "pa:assemble pa[dD]:disasm or pae: esil from hex",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pA", "[n_ops]", "show n_ops address and type",
|
|
|
|
"pb", "[?] [n]", "bitstream of N bits",
|
|
|
|
"pB", "[?] [n]", "bitstream of N bytes",
|
|
|
|
"pc", "[?][p] [len]", "output C (or python) format",
|
2018-12-29 11:17:56 +01:00
|
|
|
"pC", "[aAcdDxw] [rows]", "print disassembly in columns (see hex.cols and pdi)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pd", "[?] [sz] [a] [b]", "disassemble N opcodes (pd) or N bytes (pD)",
|
|
|
|
"pf", "[?][.nam] [fmt]", "print formatted data (pf.name, pf.name $<expr>)",
|
2018-09-13 01:15:18 +02:00
|
|
|
"pF", "[?][apx]", "print asn1, pkcs7 or x509",
|
2019-01-11 09:56:27 +01:00
|
|
|
"pg", "[?][x y w h] [cmd]", "create new visual gadget or print it (see pg? for details)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"ph", "[?][=|hash] ([len])", "calculate hash for a block",
|
2017-10-16 13:31:13 +02:00
|
|
|
"pj", "[?] [len]", "print as indented JSON",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pm", "[?] [magic]", "print libmagic data (see pm? and /m?)",
|
2019-08-31 14:46:07 +00:00
|
|
|
"po", "[?] hex", "print operation applied to block (see po?)",
|
2019-06-22 13:29:21 +02:00
|
|
|
"pp", "[?][sz] [len]", "print patterns, see pp? for more help",
|
2019-03-27 10:23:47 +01:00
|
|
|
"pq", "[?][is] [len]", "print QR code with the first Nbytes",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pr", "[?][glx] [len]", "print N raw bytes (in lines or hexblocks, 'g'unzip)",
|
|
|
|
"ps", "[?][pwz] [len]", "print pascal/wide/zero-terminated strings",
|
|
|
|
"pt", "[?][dn] [len]", "print different timestamps",
|
|
|
|
"pu", "[?][w] [len]", "print N url encoded bytes (w=wide)",
|
|
|
|
"pv", "[?][jh] [mode]", "show variable/pointer/value in memory",
|
|
|
|
"pwd", "", "display current working directory",
|
|
|
|
"px", "[?][owq] [len]", "hexdump of N bytes (o=octal, w=32bit, q=64bit)",
|
|
|
|
"pz", "[?] [len]", "print zoom view (see pz? for help)",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2018-08-28 14:22:09 +02:00
|
|
|
static const char *help_msg_pxd[] = {
|
|
|
|
"Usage:", "pxd[1248] ([len])", "show decimal byte/short/word/dword dumps",
|
|
|
|
"pxd", "", "show decimal hexdumps",
|
|
|
|
"pxd2", "", "show shorts hexdump",
|
|
|
|
"pxd4", "", "show dword hexdump (int)",
|
|
|
|
"pxd8", "", "show qword hexdump (int)",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-25 04:20:25 -07:00
|
|
|
static const char *help_msg_p_equal[] = {
|
2018-08-07 15:00:36 +02:00
|
|
|
"Usage:", "p=[=bep?][qj] [N] ([len]) ([offset]) ", "show entropy/printable chars/chars bars",
|
2018-01-03 22:06:15 +05:30
|
|
|
"e ", "zoom.in", "specify range for zoom",
|
2017-07-25 04:20:25 -07:00
|
|
|
"p=", "", "print bytes of current block in bars",
|
2018-08-07 15:00:36 +02:00
|
|
|
"p==", "[..]", "same subcommands as p=, using column bars instead of rows",
|
2019-07-25 13:21:56 +02:00
|
|
|
"p=", "0", "number of 0x00 bytes for each filesize/blocksize",
|
2018-08-13 11:45:54 +02:00
|
|
|
"p=", "2", "short (signed int16) bars, good for waves",
|
2019-05-07 11:59:38 +02:00
|
|
|
"p=", "a", "analysis bbs maps",
|
|
|
|
"p=", "A", "analysis stats maps (see p-)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"p=", "b", "same as above",
|
2019-05-07 11:59:38 +02:00
|
|
|
"p=", "c", "number of calls per block",
|
|
|
|
"p=", "d", "min/max/number of unique bytes in block",
|
|
|
|
"p=", "e", "entropy for each filesize/blocksize",
|
|
|
|
"p=", "F", "number of 0xFF bytes for each filesize/blocksize",
|
|
|
|
"p=", "i", "number of invalid instructions per block",
|
|
|
|
"p=", "j", "number of jumps and conditional jumps in block",
|
|
|
|
"p=", "m", "number of flags and marks in block",
|
|
|
|
"p=", "p", "number of printable bytes for each filesize/blocksize",
|
2019-06-20 12:45:00 +08:00
|
|
|
"p=", "s", "number of syscall and privileged instructions",
|
2019-05-07 11:59:38 +02:00
|
|
|
"p=", "z", "number of chars in strings in block",
|
2017-07-25 04:20:25 -07:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-10-16 13:31:13 +02:00
|
|
|
static const char *help_msg_pj[] = {
|
|
|
|
"Usage:", "pj[..] [size]", "",
|
|
|
|
"pj", "", "print current block as indented JSON",
|
|
|
|
"pj.", "", "print as indented JSON from 0 to the current offset",
|
|
|
|
"pj..", "", "print JSON path from 0 to the current offset",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-25 04:20:25 -07:00
|
|
|
static const char *help_msg_p_minus[] = {
|
2018-06-29 11:22:11 +02:00
|
|
|
"Usage:", "p-[hj] [nblocks] ", "bar|json|histogram blocks",
|
2017-07-25 04:20:25 -07:00
|
|
|
"p-", "", "show ascii-art bar of metadata in file boundaries",
|
2019-03-19 16:37:23 +00:00
|
|
|
"p-e", "", "show ascii-art bar of entropy per block",
|
2017-07-25 04:20:25 -07:00
|
|
|
"p-h", "", "show histogram analysis of metadata per block",
|
|
|
|
"p-j", "", "show json format",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_pd[] = {
|
2019-09-09 22:33:02 +01:00
|
|
|
"Usage:", "p[dD][ajbrfils] [len]", " # Print Disassembly",
|
2017-07-25 04:20:25 -07:00
|
|
|
"NOTE: ", "len", "parameter can be negative",
|
2018-08-07 15:00:36 +02:00
|
|
|
"NOTE: ", "", "Pressing ENTER on empty command will repeat last print command in next page",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pD", " N", "disassemble N bytes",
|
2019-10-28 02:09:41 +01:00
|
|
|
"pd", " -N", "disassemble N instructions backward",
|
2019-07-25 13:21:56 +02:00
|
|
|
"pd", " N", "disassemble N instructions",
|
|
|
|
"pd--", "[n]", "context disassembly of N instructions",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pda", "", "disassemble all possible opcodes (byte per byte)",
|
|
|
|
"pdb", "", "disassemble basic block",
|
|
|
|
"pdc", "", "pseudo disassembler output in C-like syntax",
|
|
|
|
"pdC", "", "show comments found in N instructions",
|
2020-08-12 23:05:38 -03:00
|
|
|
"pde", "[q|qq|j] [N]", "disassemble N instructions following execution flow from current PC",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pdf", "", "disassemble function",
|
|
|
|
"pdi", "", "like 'pi', with offset and bytes",
|
|
|
|
"pdj", "", "disassemble to json",
|
2017-12-11 15:07:44 +01:00
|
|
|
"pdJ", "", "formatted disassembly like pd as json",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pdk", "", "disassemble all methods of a class",
|
|
|
|
"pdl", "", "show instruction sizes",
|
2018-04-09 02:23:44 +02:00
|
|
|
"pdp", "", "disassemble by following pointers to read ropchains",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pdr", "", "recursive disassemble across the function graph",
|
|
|
|
"pdR", "", "recursive disassemble block size bytes without analyzing functions",
|
2019-07-25 13:21:56 +02:00
|
|
|
"pdr.", "", "recursive disassemble across the function graph (from current basic block)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pds", "[?]", "disassemble summary (strings, calls, jumps, refs) (see pdsf and pdfs)",
|
2019-10-28 02:09:41 +01:00
|
|
|
"pdt", " [n] [query]", "disassemble N instructions in a table (see dtd for debug traces)",
|
|
|
|
"pdx", " [hex]", "alias for pad or pix",
|
2017-07-25 04:20:25 -07:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_pf[] = {
|
|
|
|
"pf:", PF_USAGE_STR, "",
|
|
|
|
"Commands:", "", "",
|
2019-07-25 13:21:56 +02:00
|
|
|
"pf", " fmt", "Show data using the given format-string. See 'pf\?\?' and 'pf\?\?\?'.",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pf", "?", "Show this help",
|
|
|
|
"pf", "??", "Format characters",
|
|
|
|
"pf", "???", "pf usage examples",
|
2019-07-25 13:21:56 +02:00
|
|
|
"pf* ", "fmt_name|fmt", "Show data using (named) format as r2 flag create commands",
|
|
|
|
"pf.", "", "List all format definitions",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pf.", "fmt_name", "Show data using named format",
|
|
|
|
"pf.", "fmt_name.field_name", "Show specific data field using named format",
|
2019-07-25 13:21:56 +02:00
|
|
|
"pf.", "fmt_name.field_name=33", "Set new value for the specified field in named format",
|
2019-09-25 00:09:58 +08:00
|
|
|
"pf.", "fmt_name.field_name[i]", "Show element i of array field_name",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pf.", "name [0|cnt]fmt", "Define a new named format",
|
|
|
|
"pf?", "fmt_name", "Show the definition of a named format",
|
2019-07-25 13:21:56 +02:00
|
|
|
"pfc ", "fmt_name|fmt", "Show data using (named) format as C string",
|
|
|
|
"pfd.", "fmt_name", "Show data using named format as graphviz commands",
|
|
|
|
"pfj ", "fmt_name|fmt", "Show data using (named) format in JSON",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pfo", " fdf_name", "Load a Format Definition File (fdf)",
|
2019-07-25 13:21:56 +02:00
|
|
|
"pfo", "", "List all format definition files (fdf)",
|
2018-12-03 02:35:40 +01:00
|
|
|
"pfq", " fmt ...", "Quiet print format (do now show address)",
|
2018-01-08 03:05:43 +01:00
|
|
|
"pfs", "[.fmt_name| fmt]", "Print the size of (named) format in bytes",
|
2019-07-25 13:21:56 +02:00
|
|
|
"pfv.", "fmt_name[.field]", "Print value(s) only for named format. Useful for one-liners",
|
2017-07-25 04:20:25 -07:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_detail_pf[] = {
|
|
|
|
"pf:", PF_USAGE_STR, "",
|
|
|
|
"Format:", "", "",
|
|
|
|
" ", "b", "byte (unsigned)",
|
|
|
|
" ", "B", "resolve enum bitfield (see t?)",
|
|
|
|
" ", "c", "char (signed byte)",
|
2018-08-05 16:19:52 -07:00
|
|
|
" ", "C", "byte in decimal",
|
2018-04-14 17:22:47 +02:00
|
|
|
" ", "d", "0xHEX value (4 bytes) (see 'i' and 'x')",
|
2017-07-25 04:20:25 -07:00
|
|
|
" ", "D", "disassemble one opcode",
|
|
|
|
" ", "e", "temporally swap endian",
|
|
|
|
" ", "E", "resolve enum name (see t?)",
|
|
|
|
" ", "f", "float value (4 bytes)",
|
2018-02-26 17:11:11 +01:00
|
|
|
" ", "F", "double value (8 bytes)",
|
2018-04-14 17:22:47 +02:00
|
|
|
" ", "i", "signed integer value (4 bytes) (see 'd' and 'x')",
|
2017-07-25 04:20:25 -07:00
|
|
|
" ", "n", "next char specifies size of signed value (1, 2, 4 or 8 byte(s))",
|
|
|
|
" ", "N", "next char specifies size of unsigned value (1, 2, 4 or 8 byte(s))",
|
2018-04-14 17:22:47 +02:00
|
|
|
" ", "o", "octal value (4 byte)",
|
2017-07-25 04:20:25 -07:00
|
|
|
" ", "p", "pointer reference (2, 4 or 8 bytes)",
|
|
|
|
" ", "q", "quadword (8 bytes)",
|
2020-07-24 11:53:13 +02:00
|
|
|
" ", "Q", "uint128_t (16 bytes)",
|
2017-07-25 04:20:25 -07:00
|
|
|
" ", "r", "CPU register `pf r (eax)plop`",
|
|
|
|
" ", "s", "32bit pointer to string (4 bytes)",
|
|
|
|
" ", "S", "64bit pointer to string (8 bytes)",
|
|
|
|
" ", "t", "UNIX timestamp (4 bytes)",
|
|
|
|
" ", "T", "show Ten first bytes of buffer",
|
|
|
|
" ", "u", "uleb128 (variable length)",
|
|
|
|
" ", "w", "word (2 bytes unsigned short in hex)",
|
2018-04-14 17:22:47 +02:00
|
|
|
" ", "x", "0xHEX value and flag (fd @ addr) (see 'd' and 'i')",
|
2017-07-25 04:20:25 -07:00
|
|
|
" ", "X", "show formatted hexpairs",
|
2018-04-14 17:22:47 +02:00
|
|
|
" ", "z", "null terminated string",
|
|
|
|
" ", "Z", "null terminated wide string",
|
2017-07-25 04:20:25 -07:00
|
|
|
" ", "?", "data structure `pf ? (struct_name)example_name`",
|
|
|
|
" ", "*", "next char is pointer (honors asm.bits)",
|
|
|
|
" ", "+", "toggle show flags for each offset",
|
|
|
|
" ", ":", "skip 4 bytes",
|
|
|
|
" ", ".", "skip 1 byte",
|
2018-11-22 03:05:46 +01:00
|
|
|
" ", ";", "rewind 4 bytes",
|
|
|
|
" ", ",", "rewind 1 byte",
|
2017-07-25 04:20:25 -07:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_detail2_pf[] = {
|
|
|
|
"pf:", PF_USAGE_STR, "",
|
|
|
|
"Examples:", "", "",
|
|
|
|
"pf", " 3xi foo bar", "3-array of struct, each with named fields: 'foo' as hex, and 'bar' as int",
|
|
|
|
"pf", " B (BitFldType)arg_name`", "bitfield type",
|
|
|
|
"pf", " E (EnumType)arg_name`", "enum type",
|
|
|
|
"pf", " obj=xxdz prev next size name", "Same as above",
|
2019-02-18 00:06:20 +05:30
|
|
|
"pf", " *z*i*w nb name blob", "Print the pointers with given labels",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pf", " iwq foo bar troll", "Print the iwq format with foo, bar, troll as the respective names for the fields",
|
|
|
|
"pf", " 0iwq foo bar troll", "Same as above, but considered as a union (all fields at offset 0)",
|
2020-07-20 12:18:38 +02:00
|
|
|
"pf.", "obj xxdz prev next size name", "Define the obj format as xxdz",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pf.", "plop ? (troll)mystruct", "Use structure troll previously defined",
|
2019-02-18 00:06:20 +05:30
|
|
|
"pfj.", "plop @ 0x14", "Apply format object at the given offset",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pf", " 10xiz pointer length string", "Print a size 10 array of the xiz struct with its field names",
|
2019-02-18 00:06:20 +05:30
|
|
|
"pf", " 5sqw string quad word", "Print an array with sqw struct along with its field names",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pf", " {integer}? (bifc)", "Print integer times the following format (bifc)",
|
|
|
|
"pf", " [4]w[7]i", "Print an array of 4 words and then an array of 7 integers",
|
2019-02-18 00:06:20 +05:30
|
|
|
"pf", " ic...?i foo bar \"(pf xw yo foo)troll\" yo", "Print nested anonymous structures",
|
|
|
|
"pf", " ;..x", "Print value located 6 bytes from current offset",
|
|
|
|
"pf", " [10]z[3]i[10]Zb", "Print an fixed size str, widechar, and var",
|
|
|
|
"pfj", " +F @ 0x14","Print the content at given offset with flag",
|
2019-06-20 12:45:00 +08:00
|
|
|
"pf", " n2", "print signed short (2 bytes) value. Use N instead of n for printing unsigned values",
|
2019-02-18 00:06:20 +05:30
|
|
|
"pf", " [2]? (plop)structname @ 0", "Prints an array of structs",
|
2019-06-20 12:45:00 +08:00
|
|
|
"pf", " eqew bigWord beef", "Swap endianness and print with given labels",
|
2019-02-18 00:06:20 +05:30
|
|
|
"pf", ".foo rr (eax)reg1 (eip)reg2", "Create object referencing to register values ",
|
|
|
|
"pf", " tt troll plop", "print time stamps with labels troll and plop",
|
2017-07-25 04:20:25 -07:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_pi[] = {
|
|
|
|
"Usage:", "pi[bdefrj] [num]", "",
|
|
|
|
"pia", "", "print all possible opcodes (byte per byte)",
|
|
|
|
"pib", "", "print instructions of basic block",
|
|
|
|
"pid", "", "alias for pdi",
|
|
|
|
"pie", "", "print offset + esil expression",
|
2019-01-23 18:11:11 +02:00
|
|
|
"pif", "[?]", "print instructions of function",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pij", "", "print N instructions in JSON",
|
|
|
|
"pir", "", "like 'pdr' but with 'pI' output",
|
2019-04-25 11:13:20 +02:00
|
|
|
"piu", "[q] [limit]", "disasm until ujmp or ret is found (see pdp)",
|
2019-08-18 22:43:41 +02:00
|
|
|
"pix", " [hexpairs]", "alias for pdx and pad",
|
2017-07-25 04:20:25 -07:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2019-01-23 18:11:11 +02:00
|
|
|
static const char *help_msg_pif[] = {
|
|
|
|
"Usage:", "pif[cj]", "",
|
|
|
|
"pif?", "", "print this help message",
|
|
|
|
"pifc", "", "print all calls from this function",
|
|
|
|
"pifcj", "", "print all calls from this function in JSON format",
|
|
|
|
"pifj", "", "print instructions of function in JSON format",
|
|
|
|
};
|
|
|
|
|
2019-08-31 14:46:07 +00:00
|
|
|
static const char *help_msg_po[] = {
|
|
|
|
"Usage:","po[24aAdlmorsx]"," [hexpairs] @ addr[!bsize]",
|
|
|
|
"po[24aAdlmorsx]","", "without hexpair values, clipboard is used",
|
|
|
|
"po2"," [val]","2= 2 byte endian swap",
|
|
|
|
"po4"," [val]", "4= 4 byte endian swap",
|
|
|
|
"poa"," [val]", "+= addition (f.ex: poa 0102)",
|
|
|
|
"poA"," [val]","&= and",
|
|
|
|
"pod"," [val]", "/= divide",
|
|
|
|
"pol"," [val]","<<= shift left",
|
|
|
|
"pom"," [val]", "*= multiply",
|
|
|
|
"poo"," [val]","|= or",
|
|
|
|
"por"," [val]", ">>= shift right",
|
|
|
|
"pos"," [val]", "-= substraction",
|
|
|
|
"pox"," [val]","^= xor (f.ex: pox 0x90)",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2017-07-25 04:20:25 -07:00
|
|
|
static const char *help_msg_ps[] = {
|
2019-06-13 18:18:35 +02:00
|
|
|
"Usage:", "ps[bijqpsuwWxz+] [N]", "Print String",
|
2017-07-25 04:20:25 -07:00
|
|
|
"ps", "", "print string",
|
2019-07-25 13:21:56 +02:00
|
|
|
"ps+", "[j]", "print libc++ std::string (same-endian, ascii, zero-terminated)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"psb", "", "print strings in current block",
|
|
|
|
"psi", "", "print string inside curseek",
|
|
|
|
"psj", "", "print string in JSON format",
|
2019-06-13 18:18:35 +02:00
|
|
|
"psp", "[j]", "print pascal string",
|
2019-07-25 13:21:56 +02:00
|
|
|
"psq", "", "alias for pqs",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pss", "", "print string in screen (wrap width)",
|
2019-06-13 18:18:35 +02:00
|
|
|
"psu", "[zj]", "print utf16 unicode (json)",
|
|
|
|
"psw", "[j]", "print 16bit wide string",
|
|
|
|
"psW", "[j]", "print 32bit wide string",
|
2017-07-25 04:20:25 -07:00
|
|
|
"psx", "", "show string with escaped chars",
|
2019-06-13 18:18:35 +02:00
|
|
|
"psz", "[j]", "print zero-terminated string",
|
2017-07-25 04:20:25 -07:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_pt[] = {
|
|
|
|
"Usage: pt", "[dn]", "print timestamps",
|
2019-01-11 00:56:18 +01:00
|
|
|
"pt.", "", "print current time",
|
2018-08-07 15:00:36 +02:00
|
|
|
"pt", "", "print UNIX time (32 bit `cfg.bigendian`) Since January 1, 1970",
|
|
|
|
"ptd", "", "print DOS time (32 bit `cfg.bigendian`) Since January 1, 1980",
|
|
|
|
"pth", "", "print HFS time (32 bit `cfg.bigendian`) Since January 1, 1904",
|
|
|
|
"ptn", "", "print NTFS time (64 bit `cfg.bigendian`) Since January 1, 1601",
|
2017-07-25 04:20:25 -07:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_pv[] = {
|
|
|
|
"Usage: pv[j][1,2,4,8,z]", "", "",
|
|
|
|
"pv", "", "print bytes based on asm.bits",
|
|
|
|
"pv1", "", "print 1 byte in memory",
|
|
|
|
"pv2", "", "print 2 bytes in memory",
|
|
|
|
"pv4", "", "print 4 bytes in memory",
|
|
|
|
"pv8", "", "print 8 bytes in memory",
|
|
|
|
"pvz", "", "print value as string (alias for ps)",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *help_msg_px[] = {
|
|
|
|
"Usage:", "px[0afoswqWqQ][f]", " # Print heXadecimal",
|
|
|
|
"px", "", "show hexdump",
|
|
|
|
"px/", "", "same as x/ in gdb (help x)",
|
|
|
|
"px0", "", "8bit hexpair list of bytes until zero byte",
|
|
|
|
"pxa", "", "show annotated hexdump",
|
2018-09-07 11:38:08 +02:00
|
|
|
"pxA", "[?]", "show op analysis color map",
|
2019-04-15 13:22:27 +02:00
|
|
|
"pxb", "", "dump bits in hexdump form", // should be px1?
|
2017-07-25 04:20:25 -07:00
|
|
|
"pxc", "", "show hexdump with comments",
|
2018-09-07 11:38:08 +02:00
|
|
|
"pxd", "[?1248]", "signed integer dump (1 byte, 2 and 4)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pxe", "", "emoji hexdump! :)",
|
|
|
|
"pxf", "", "show hexdump of current function",
|
|
|
|
"pxh", "", "show hexadecimal half-words dump (16bit)",
|
|
|
|
"pxH", "", "same as above, but one per line",
|
|
|
|
"pxi", "", "HexII compact binary representation",
|
|
|
|
"pxl", "", "display N lines (rows) of hexdump",
|
|
|
|
"pxo", "", "show octal dump",
|
|
|
|
"pxq", "", "show hexadecimal quad-words dump (64bit)",
|
2018-04-04 22:42:50 +02:00
|
|
|
"pxQ", "[q]", "same as above, but one per line",
|
2020-10-25 12:35:45 +01:00
|
|
|
"pxr", "[1248][qj]", "show hexword references (q=quiet, j=json)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pxs", "", "show hexadecimal in sparse mode",
|
|
|
|
"pxt", "[*.] [origin]", "show delta pointer table in r2 commands",
|
|
|
|
"pxw", "", "show hexadecimal words dump (32bit)",
|
2018-04-04 22:42:50 +02:00
|
|
|
"pxW", "[q]", "same as above, but one per line (q=quiet)",
|
2017-07-25 04:20:25 -07:00
|
|
|
"pxx", "", "show N bytes of hex-less hexdump",
|
|
|
|
"pxX", "", "show N words of hex-less hexdump",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *help_msg_pz[] = {
|
|
|
|
"Usage: pz [len]", "", "print zoomed blocks (filesize/N)",
|
|
|
|
"e ", "zoom.maxsz", "max size of block",
|
|
|
|
"e ", "zoom.from", "start address",
|
|
|
|
"e ", "zoom.to", "end address",
|
|
|
|
"e ", "zoom.byte", "specify how to calculate each byte",
|
|
|
|
"pzp", "", "number of printable chars",
|
|
|
|
"pzf", "", "count of flags in block",
|
|
|
|
"pzs", "", "strings in range",
|
|
|
|
"pz0", "", "number of bytes with value '0'",
|
|
|
|
"pzF", "", "number of bytes with value 0xFF",
|
|
|
|
"pze", "", "calculate entropy and expand to 0-255 range",
|
|
|
|
"pzh", "", "head (first byte value); This is the default mode",
|
|
|
|
// "WARNING: On big files, use 'zoom.byte=h' or restrict ranges\n");
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2018-09-07 11:38:08 +02:00
|
|
|
const char *help_msg_pxA[] = {
|
|
|
|
"Usage: pxA [len]", "", "show op analysis color map",
|
2019-03-31 18:25:04 +08:00
|
|
|
"$$", "", "int/swi/trap/new\n",
|
|
|
|
"+-*/", "", "math ops\n",
|
|
|
|
"->", "", "push\n",
|
|
|
|
"..", "", "nop\n",
|
|
|
|
"<-", "", "pop\n",
|
|
|
|
"<<>>", "", "shift ops\n",
|
|
|
|
"==", "", "cmp/test\n",
|
|
|
|
"XX", "", "invalid\n",
|
|
|
|
"_C", "", "call\n",
|
|
|
|
"_J", "", "jump\n",
|
|
|
|
"_R", "", "ret\n",
|
|
|
|
"cJ", "", "conditional jump\n",
|
|
|
|
"io", "", "in/out ops\n",
|
|
|
|
"mv", "", "move,lea,li\n",
|
|
|
|
"|&^", "", "bin ops\n",
|
2018-09-07 11:38:08 +02:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2018-04-04 22:42:50 +02:00
|
|
|
static const ut32 colormap[256] = {
|
2017-07-25 04:20:25 -07:00
|
|
|
0x000000, 0x560000, 0x640000, 0x750000, 0x870000, 0x9b0000, 0xb00000, 0xc60000, 0xdd0000, 0xf50000, 0xff0f0f, 0xff2828, 0xff4343, 0xff5e5e, 0xff7979, 0xfe9595,
|
2018-04-04 22:42:50 +02:00
|
|
|
0x4c1600, 0x561900, 0x641e00, 0x752300, 0x872800, 0x9b2e00, 0xb03400, 0xc63b00, 0xdd4200, 0xf54900, 0xff570f, 0xff6928, 0xff7b43, 0xff8e5e, 0xffa179, 0xfeb595,
|
|
|
|
0x4c3900, 0x564000, 0x644b00, 0x755700, 0x876500, 0x9b7400, 0xb08400, 0xc69400, 0xdda600, 0xf5b800, 0xffc30f, 0xffc928, 0xffd043, 0xffd65e, 0xffdd79, 0xfee495,
|
|
|
|
0x4c4c00, 0x565600, 0x646400, 0x757500, 0x878700, 0x9b9b00, 0xb0b000, 0xc6c600, 0xdddd00, 0xf5f500, 0xffff0f, 0xffff28, 0xffff43, 0xffff5e, 0xffff79, 0xfffe95,
|
|
|
|
0x324c00, 0x395600, 0x426400, 0x4e7500, 0x5a8700, 0x679b00, 0x75b000, 0x84c600, 0x93dd00, 0xa3f500, 0xafff0f, 0xb7ff28, 0xc0ff43, 0xc9ff5e, 0xd2ff79, 0xdbfe95,
|
|
|
|
0x1f4c00, 0x235600, 0x296400, 0x307500, 0x388700, 0x409b00, 0x49b000, 0x52c600, 0x5cdd00, 0x66f500, 0x73ff0f, 0x82ff28, 0x91ff43, 0xa1ff5e, 0xb1ff79, 0xc1fe95,
|
|
|
|
0x004c00, 0x005600, 0x006400, 0x007500, 0x008700, 0x009b00, 0x00b000, 0x00c600, 0x00dd00, 0x00f500, 0x0fff0f, 0x28ff28, 0x43ff43, 0x5eff5e, 0x79ff79, 0x95fe95,
|
|
|
|
0x004c19, 0x00561c, 0x006421, 0x007527, 0x00872d, 0x009b33, 0x00b03a, 0x00c642, 0x00dd49, 0x00f551, 0x0fff5f, 0x28ff70, 0x43ff81, 0x5eff93, 0x79ffa6, 0x95feb8,
|
|
|
|
0x004c4c, 0x005656, 0x006464, 0x007575, 0x008787, 0x009b9b, 0x00b0b0, 0x00c6c6, 0x00dddd, 0x00f5f5, 0x0ffffe, 0x28fffe, 0x43fffe, 0x5efffe, 0x79ffff, 0x95fffe,
|
|
|
|
0x00394c, 0x004056, 0x004b64, 0x005775, 0x006587, 0x00749b, 0x0084b0, 0x0094c6, 0x00a6dd, 0x00b8f5, 0x0fc3ff, 0x28c9ff, 0x43d0ff, 0x5ed6ff, 0x79ddff, 0x95e4fe,
|
|
|
|
0x00264c, 0x002b56, 0x003264, 0x003a75, 0x004387, 0x004d9b, 0x0058b0, 0x0063c6, 0x006edd, 0x007af5, 0x0f87ff, 0x2893ff, 0x43a1ff, 0x5eaeff, 0x79bcff, 0x95cafe,
|
|
|
|
0x00134c, 0x001556, 0x001964, 0x001d75, 0x002187, 0x00269b, 0x002cb0, 0x0031c6, 0x0037dd, 0x003df5, 0x0f4bff, 0x285eff, 0x4372ff, 0x5e86ff, 0x799aff, 0x95b0fe,
|
|
|
|
0x19004c, 0x1c0056, 0x210064, 0x270075, 0x2d0087, 0x33009b, 0x3a00b0, 0x4200c6, 0x4900dd, 0x5100f5, 0x5f0fff, 0x7028ff, 0x8143ff, 0x935eff, 0xa679ff, 0xb895fe,
|
|
|
|
0x33004c, 0x390056, 0x420064, 0x4e0075, 0x5a0087, 0x67009b, 0x7500b0, 0x8400c6, 0x9300dd, 0xa300f5, 0xaf0fff, 0xb728ff, 0xc043ff, 0xc95eff, 0xd279ff, 0xdb95fe,
|
|
|
|
0x4c004c, 0x560056, 0x640064, 0x750075, 0x870087, 0x9b009b, 0xb000b0, 0xc600c6, 0xdd00dd, 0xf500f5, 0xfe0fff, 0xfe28ff, 0xfe43ff, 0xfe5eff, 0xfe79ff, 0xfe95fe,
|
|
|
|
0x4c0032, 0x560039, 0x640042, 0x75004e, 0x87005a, 0x9b0067, 0xb00075, 0xc60084, 0xdd0093, 0xf500a3, 0xff0faf, 0xff28b7, 0xff43c0, 0xff5ec9, 0xff79d2, 0xffffff,
|
2017-05-29 03:45:02 +02:00
|
|
|
};
|
|
|
|
|
2020-06-17 21:29:23 +02:00
|
|
|
static void cmd_print_init(RCore *core, RCmdDesc *parent) {
|
2017-07-27 05:52:17 -07:00
|
|
|
DEFINE_CMD_DESCRIPTOR_SPECIAL (core, &, amper);
|
|
|
|
DEFINE_CMD_DESCRIPTOR_SPECIAL (core, @, at);
|
|
|
|
DEFINE_CMD_DESCRIPTOR_SPECIAL (core, @@, at_at);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, p);
|
|
|
|
DEFINE_CMD_DESCRIPTOR_SPECIAL (core, p=, p_equal);
|
|
|
|
DEFINE_CMD_DESCRIPTOR_SPECIAL (core, p-, p_minus);
|
2018-08-02 23:42:35 -07:00
|
|
|
DEFINE_CMD_DESCRIPTOR (core, pc);
|
2017-07-27 05:52:17 -07:00
|
|
|
DEFINE_CMD_DESCRIPTOR (core, pd);
|
|
|
|
DEFINE_CMD_DESCRIPTOR_WITH_DETAIL2 (core, pf);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, pi);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, ps);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, pt);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, pv);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, px);
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, pz);
|
2017-07-25 04:20:25 -07:00
|
|
|
}
|
|
|
|
|
2019-08-18 22:43:41 +02:00
|
|
|
static void __cmd_pad(RCore *core, const char *arg) {
|
|
|
|
if (*arg == '?') {
|
|
|
|
eprintf ("Usage: pad [hexpairs] # disassembly given bytes\n");
|
|
|
|
return;
|
|
|
|
}
|
2020-05-13 01:28:23 +02:00
|
|
|
r_asm_set_pc (core->rasm, core->offset);
|
2019-08-18 22:43:41 +02:00
|
|
|
bool is_pseudo = r_config_get_i (core->config, "asm.pseudo");
|
2020-05-13 01:28:23 +02:00
|
|
|
RAsmCode *acode = r_asm_mdisassemble_hexstr (core->rasm, is_pseudo ? core->parser : NULL, arg);
|
2019-08-18 22:43:41 +02:00
|
|
|
if (acode) {
|
|
|
|
r_cons_print (acode->assembly);
|
|
|
|
r_asm_code_free (acode);
|
|
|
|
} else {
|
|
|
|
eprintf ("Invalid hexstr\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-29 03:45:02 +02:00
|
|
|
// colordump
|
2019-03-31 18:25:04 +08:00
|
|
|
static void cmd_prc(RCore *core, const ut8* block, int len) {
|
2017-10-29 11:00:29 +01:00
|
|
|
const char *chars = " .,:;!O@#";
|
2019-04-16 13:47:22 +02:00
|
|
|
bool square = r_config_get_i (core->config, "scr.square");
|
2017-05-29 03:45:02 +02:00
|
|
|
int i, j;
|
2017-06-10 17:47:26 +02:00
|
|
|
char ch, ch2, *color;
|
2019-04-29 12:51:13 +03:00
|
|
|
int cols = r_config_get_i (core->config, "hex.cols");
|
2017-05-29 21:50:57 +02:00
|
|
|
bool show_color = r_config_get_i (core->config, "scr.color");
|
2017-06-10 17:47:26 +02:00
|
|
|
bool show_flags = r_config_get_i (core->config, "asm.flags");
|
2019-06-23 02:33:24 +02:00
|
|
|
bool show_section = r_config_get_i (core->config, "hex.section");
|
2020-09-09 15:50:37 +02:00
|
|
|
bool show_offset = r_config_get_i (core->config, "hex.offset");
|
2017-05-29 04:36:34 +02:00
|
|
|
bool show_cursor = core->print->cur_enabled;
|
2019-03-31 04:20:52 +08:00
|
|
|
bool show_unalloc = core->print->flags & R_PRINT_FLAGS_UNALLOC;
|
2019-05-15 00:58:25 +02:00
|
|
|
if (cols < 1 || cols > 0xfffff) {
|
|
|
|
cols = 32;
|
|
|
|
}
|
2017-05-29 03:45:02 +02:00
|
|
|
for (i = 0; i < len; i += cols) {
|
2019-06-23 02:33:24 +02:00
|
|
|
if (show_section) {
|
|
|
|
const char * name = r_core_get_section_name (core, core->offset + i);
|
|
|
|
r_cons_printf ("%20s ", name? name: "");
|
|
|
|
}
|
2020-09-09 15:50:37 +02:00
|
|
|
if (show_offset) {
|
|
|
|
r_print_addr (core->print, core->offset + i);
|
|
|
|
}
|
2017-05-29 03:45:02 +02:00
|
|
|
for (j = i; j < i + cols; j ++) {
|
2017-06-01 13:16:55 +02:00
|
|
|
if (j >= len) {
|
2017-05-29 03:45:02 +02:00
|
|
|
break;
|
|
|
|
}
|
2017-06-01 13:16:55 +02:00
|
|
|
if (show_color) {
|
2019-05-04 12:04:46 +08:00
|
|
|
ut32 color_val = colormap[block[j]];
|
|
|
|
int brightness = ((color_val & 0xff0000) >> 16)
|
|
|
|
+ 2 * ((color_val & 0xff00) >> 8) + (color_val & 0xff) / 2;
|
|
|
|
char *str = r_str_newf ("rgb:%s rgb:%06x",
|
|
|
|
brightness <= 0x7f * 3 ? "fff" : "000", color_val);
|
2018-02-23 19:00:47 +01:00
|
|
|
color = r_cons_pal_parse (str, NULL);
|
2017-06-01 13:16:55 +02:00
|
|
|
free (str);
|
2017-10-29 11:00:29 +01:00
|
|
|
if (show_cursor && core->print->cur == j) {
|
|
|
|
ch = '_';
|
|
|
|
} else {
|
|
|
|
ch = ' ';
|
|
|
|
}
|
2017-06-01 13:16:55 +02:00
|
|
|
} else {
|
|
|
|
color = strdup ("");
|
2017-10-29 11:00:29 +01:00
|
|
|
if (show_cursor && core->print->cur == j) {
|
|
|
|
ch = '_';
|
|
|
|
} else {
|
2018-02-19 04:30:32 -08:00
|
|
|
const int idx = ((float)block[j] / 255) * (strlen (chars) - 1);
|
2017-10-29 11:00:29 +01:00
|
|
|
ch = chars[idx];
|
|
|
|
}
|
2017-06-01 13:16:55 +02:00
|
|
|
}
|
2019-03-31 04:20:52 +08:00
|
|
|
if (show_unalloc &&
|
|
|
|
!core->print->iob.is_valid_offset (core->print->iob.io, core->offset + j, false)) {
|
2020-07-22 15:07:05 +08:00
|
|
|
ch = core->print->io_unalloc_ch;
|
2019-03-31 04:20:52 +08:00
|
|
|
if (show_color) {
|
|
|
|
free (color);
|
|
|
|
color = strdup (Color_RESET);
|
|
|
|
if (ch == ' ') {
|
|
|
|
ch = '.';
|
|
|
|
}
|
|
|
|
} else {
|
2020-07-22 15:07:05 +08:00
|
|
|
ch = strchr (chars, ch) ? '?' : ch;
|
2019-03-31 04:20:52 +08:00
|
|
|
}
|
|
|
|
}
|
2017-06-01 13:16:55 +02:00
|
|
|
if (square) {
|
2017-06-10 17:47:26 +02:00
|
|
|
if (show_flags) {
|
|
|
|
RFlagItem *fi = r_flag_get_i (core->flags, core->offset + j);
|
|
|
|
if (fi) {
|
2020-05-25 23:05:37 +08:00
|
|
|
if (fi->name[1]) {
|
|
|
|
ch = fi->name[0];
|
|
|
|
ch2 = fi->name[1];
|
|
|
|
} else {
|
|
|
|
ch = ' ';
|
|
|
|
ch2 = fi->name[0];
|
|
|
|
}
|
2017-06-10 17:47:26 +02:00
|
|
|
} else {
|
|
|
|
ch2 = ch;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ch2 = ch;
|
|
|
|
}
|
|
|
|
r_cons_printf ("%s%c%c", color, ch, ch2);
|
2017-06-01 13:16:55 +02:00
|
|
|
} else {
|
|
|
|
r_cons_printf ("%s%c", color, ch);
|
|
|
|
}
|
|
|
|
free (color);
|
2017-05-29 03:45:02 +02:00
|
|
|
}
|
2019-04-01 07:34:09 +08:00
|
|
|
if (show_color) {
|
|
|
|
r_cons_printf (Color_RESET);
|
|
|
|
}
|
2017-05-29 03:45:02 +02:00
|
|
|
r_cons_newline ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-16 13:47:22 +02:00
|
|
|
static void cmd_prc_zoom(RCore *core, const char *input) {
|
|
|
|
const char *chars = " .,:;!O@#";
|
|
|
|
bool square = r_config_get_i (core->config, "scr.square");
|
|
|
|
int i, j;
|
|
|
|
char ch, ch2, *color;
|
2019-04-29 12:51:13 +03:00
|
|
|
int cols = r_config_get_i (core->config, "hex.cols");
|
2019-04-16 13:47:22 +02:00
|
|
|
bool show_color = r_config_get_i (core->config, "scr.color");
|
|
|
|
bool show_flags = r_config_get_i (core->config, "asm.flags");
|
|
|
|
bool show_cursor = core->print->cur_enabled;
|
2020-09-09 15:50:37 +02:00
|
|
|
bool show_offset = r_config_get_i (core->config, "hex.offset");
|
2019-04-16 13:47:22 +02:00
|
|
|
bool show_unalloc = core->print->flags & R_PRINT_FLAGS_UNALLOC;
|
|
|
|
ut8 *block = core->block;
|
|
|
|
int len = core->blocksize;
|
|
|
|
ut64 from = 0;
|
|
|
|
ut64 to = 0;
|
|
|
|
RIOMap* map;
|
|
|
|
RListIter *iter;
|
2019-05-15 00:58:25 +02:00
|
|
|
|
|
|
|
if (cols < 1 || cols > 0xfffff) {
|
|
|
|
cols = 32;
|
|
|
|
}
|
2019-04-16 13:47:22 +02:00
|
|
|
RList *list = r_core_get_boundaries_prot (core, -1, NULL, "zoom");
|
|
|
|
if (list && r_list_length (list) > 0) {
|
|
|
|
RListIter *iter1 = list->head;
|
|
|
|
RIOMap* map1 = iter1->data;
|
|
|
|
from = map1->itv.addr;
|
|
|
|
r_list_foreach (list, iter, map) {
|
|
|
|
to = r_itv_end (map->itv);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
from = core->offset;
|
|
|
|
to = from + core->blocksize;
|
|
|
|
}
|
|
|
|
|
|
|
|
core->print->zoom->mode = (input && *input)? input[1]: 'e';
|
|
|
|
r_print_zoom_buf (core->print, core, printzoomcallback, from, to, len, len);
|
|
|
|
block = core->print->zoom->buf;
|
|
|
|
switch (core->print->zoom->mode) {
|
|
|
|
case 'f':
|
|
|
|
// scale buffer for proper visualization of small numbers as colors
|
|
|
|
for (i = 0; i < core->print->zoom->size; i++) {
|
|
|
|
block[i] *= 8;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < len; i += cols) {
|
|
|
|
ut64 ea = core->offset + i;
|
2020-09-09 15:50:37 +02:00
|
|
|
if (show_offset) {
|
|
|
|
r_print_addr (core->print, ea);
|
|
|
|
}
|
2019-04-16 13:47:22 +02:00
|
|
|
for (j = i; j < i + cols; j ++) {
|
|
|
|
if (j >= len) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (show_color) {
|
|
|
|
char *str = r_str_newf ("rgb:fff rgb:%06x", colormap[block[j]]);
|
|
|
|
color = r_cons_pal_parse (str, NULL);
|
|
|
|
free (str);
|
|
|
|
if (show_cursor && core->print->cur == j) {
|
|
|
|
ch = '_';
|
|
|
|
} else {
|
|
|
|
ch = ' ';
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
color = strdup ("");
|
|
|
|
if (show_cursor && core->print->cur == j) {
|
|
|
|
ch = '_';
|
|
|
|
} else {
|
|
|
|
const int idx = ((float)block[j] / 255) * (strlen (chars) - 1);
|
|
|
|
ch = chars[idx];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (show_unalloc &&
|
|
|
|
!core->print->iob.is_valid_offset (core->print->iob.io, core->offset + j, false)) {
|
2020-07-22 15:07:05 +08:00
|
|
|
ch = core->print->io_unalloc_ch;
|
2019-04-16 13:47:22 +02:00
|
|
|
if (show_color) {
|
|
|
|
free (color);
|
|
|
|
color = strdup (Color_RESET);
|
|
|
|
if (ch == ' ') {
|
|
|
|
ch = '.';
|
|
|
|
}
|
|
|
|
} else {
|
2020-07-22 15:07:05 +08:00
|
|
|
ch = strchr (chars, ch) ? '?' : ch;
|
2019-04-16 13:47:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (square) {
|
|
|
|
if (show_flags) {
|
|
|
|
RFlagItem *fi = r_flag_get_i (core->flags, core->offset + j);
|
|
|
|
if (fi) {
|
2020-05-25 23:05:37 +08:00
|
|
|
if (fi->name[1]) {
|
|
|
|
ch = fi->name[0];
|
|
|
|
ch2 = fi->name[1];
|
|
|
|
} else {
|
|
|
|
ch = ' ';
|
|
|
|
ch2 = fi->name[0];
|
|
|
|
}
|
2019-04-16 13:47:22 +02:00
|
|
|
} else {
|
|
|
|
ch2 = ch;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ch2 = ch;
|
|
|
|
}
|
|
|
|
r_cons_printf ("%s%c%c", color, ch, ch2);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%s%c", color, ch);
|
|
|
|
}
|
|
|
|
free (color);
|
|
|
|
}
|
|
|
|
if (show_color) {
|
|
|
|
r_cons_printf (Color_RESET);
|
|
|
|
}
|
|
|
|
r_cons_newline ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-08 00:02:47 +02:00
|
|
|
static void cmd_pCd(RCore *core, const char *input) {
|
|
|
|
int h, w = r_cons_get_size (&h);
|
|
|
|
int colwidth = r_config_get_i (core->config, "hex.cols") * 2.5;
|
2018-12-29 11:17:56 +01:00
|
|
|
if (colwidth < 1) {
|
|
|
|
colwidth = 16;
|
|
|
|
}
|
2016-10-08 00:02:47 +02:00
|
|
|
int i, columns = w / colwidth;
|
|
|
|
int rows = h - 2;
|
|
|
|
int obsz = core->blocksize;
|
|
|
|
int user_rows = r_num_math (core->num, input);
|
2016-10-27 01:56:38 +02:00
|
|
|
bool asm_minicols = r_config_get_i (core->config, "asm.minicols");
|
|
|
|
char *o_ao = strdup (r_config_get (core->config, "asm.offset"));
|
|
|
|
char *o_ab = strdup (r_config_get (core->config, "asm.bytes"));
|
|
|
|
if (asm_minicols) {
|
|
|
|
r_config_set (core->config, "asm.offset", "false");
|
2017-03-09 23:29:48 +01:00
|
|
|
// r_config_set (core->config, "asm.bytes", "false");
|
2016-10-27 01:56:38 +02:00
|
|
|
}
|
2016-12-02 21:08:09 +01:00
|
|
|
r_config_set (core->config, "asm.bytes", "false");
|
2016-10-08 00:02:47 +02:00
|
|
|
if (user_rows > 0) {
|
|
|
|
rows = user_rows + 1;
|
|
|
|
}
|
|
|
|
r_cons_push ();
|
|
|
|
RConsCanvas *c = r_cons_canvas_new (w, rows);
|
|
|
|
ut64 osek = core->offset;
|
|
|
|
c->color = r_config_get_i (core->config, "scr.color");
|
|
|
|
r_core_block_size (core, rows * 32);
|
|
|
|
for (i = 0; i < columns; i++) {
|
2017-03-09 23:29:48 +01:00
|
|
|
(void) r_cons_canvas_gotoxy (c, i * (w / columns), 0);
|
2016-10-08 00:02:47 +02:00
|
|
|
char *cmd = r_str_newf ("pid %d @i:%d", rows, rows * i);
|
|
|
|
char *dis = r_core_cmd_str (core, cmd);
|
2017-03-08 14:34:19 +03:00
|
|
|
r_cons_canvas_write (c, dis);
|
2016-10-08 00:02:47 +02:00
|
|
|
free (cmd);
|
|
|
|
free (dis);
|
|
|
|
}
|
|
|
|
r_core_block_size (core, obsz);
|
2020-04-17 12:53:35 +02:00
|
|
|
r_core_seek (core, osek, true);
|
2016-10-08 00:02:47 +02:00
|
|
|
|
|
|
|
r_cons_pop ();
|
2017-03-08 14:34:19 +03:00
|
|
|
r_cons_canvas_print (c);
|
|
|
|
r_cons_canvas_free (c);
|
2016-10-27 01:56:38 +02:00
|
|
|
if (asm_minicols) {
|
|
|
|
r_config_set (core->config, "asm.offset", o_ao);
|
|
|
|
r_config_set (core->config, "asm.bytes", o_ab);
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
r_config_set (core->config, "asm.bytes", o_ab);
|
2016-10-27 01:56:38 +02:00
|
|
|
free (o_ao);
|
|
|
|
free (o_ab);
|
2016-10-08 00:02:47 +02:00
|
|
|
}
|
|
|
|
|
2017-02-28 02:55:00 +01:00
|
|
|
static void findMethodBounds(RList *methods, ut64 *min, ut64 *max) {
|
|
|
|
RBinSymbol *sym;
|
|
|
|
RListIter *iter;
|
|
|
|
ut64 at_min = UT64_MAX;
|
|
|
|
ut64 at_max = 0LL;
|
|
|
|
|
|
|
|
r_list_foreach (methods, iter, sym) {
|
|
|
|
if (sym->vaddr) {
|
|
|
|
if (sym->vaddr < at_min) {
|
|
|
|
at_min = sym->vaddr;
|
|
|
|
}
|
|
|
|
if (sym->vaddr + sym->size > at_max) {
|
|
|
|
at_max = sym->vaddr + sym->size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*min = at_min;
|
|
|
|
*max = at_max;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ut64 findClassBounds(RCore *core, const char *input, int *len) {
|
|
|
|
ut64 min = 0, max = 0;
|
|
|
|
RListIter *iter;
|
|
|
|
RBinClass *c;
|
|
|
|
RList *cs = r_bin_get_classes (core->bin);
|
2019-09-16 18:15:34 +02:00
|
|
|
r_list_foreach (cs, iter, c) {
|
|
|
|
if (!c || !c->name || !c->name[0]) {
|
|
|
|
continue;
|
2017-02-28 02:55:00 +01:00
|
|
|
}
|
2019-09-16 18:15:34 +02:00
|
|
|
findMethodBounds (c->methods, &min, &max);
|
|
|
|
if (len) {
|
|
|
|
*len = (max - min);
|
2017-02-28 02:55:00 +01:00
|
|
|
}
|
2019-09-16 18:15:34 +02:00
|
|
|
return min;
|
2017-02-28 02:55:00 +01:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-21 00:19:15 +01:00
|
|
|
static void cmd_pCD(RCore *core, const char *input) {
|
|
|
|
int h, w = r_cons_get_size (&h);
|
2019-01-03 20:55:14 +00:00
|
|
|
int i;
|
2016-11-21 00:19:15 +01:00
|
|
|
int rows = h - 2;
|
|
|
|
int obsz = core->blocksize;
|
|
|
|
int user_rows = r_num_math (core->num, input);
|
|
|
|
bool asm_minicols = r_config_get_i (core->config, "asm.minicols");
|
|
|
|
char *o_ao = strdup (r_config_get (core->config, "asm.offset"));
|
|
|
|
char *o_ab = strdup (r_config_get (core->config, "asm.bytes"));
|
|
|
|
if (asm_minicols) {
|
|
|
|
r_config_set (core->config, "asm.offset", "false");
|
|
|
|
r_config_set (core->config, "asm.bytes", "false");
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
r_config_set (core->config, "asm.bytes", "false");
|
2016-11-21 00:19:15 +01:00
|
|
|
if (user_rows > 0) {
|
|
|
|
rows = user_rows + 1;
|
|
|
|
}
|
|
|
|
r_cons_push ();
|
|
|
|
RConsCanvas *c = r_cons_canvas_new (w, rows);
|
|
|
|
ut64 osek = core->offset;
|
|
|
|
c->color = r_config_get_i (core->config, "scr.color");
|
|
|
|
r_core_block_size (core, rows * 32);
|
2017-02-05 02:01:53 +00:00
|
|
|
char *cmd = NULL;
|
2019-01-03 20:55:14 +00:00
|
|
|
int columns = 2;
|
2016-11-21 00:19:15 +01:00
|
|
|
for (i = 0; i < columns; i++) {
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
2017-03-09 23:29:48 +01:00
|
|
|
(void) r_cons_canvas_gotoxy (c, 0, 0);
|
2016-11-21 00:19:15 +01:00
|
|
|
cmd = r_str_newf ("dr;?e;?e backtrace:;dbt");
|
|
|
|
break;
|
|
|
|
case 1:
|
2017-03-09 23:29:48 +01:00
|
|
|
(void) r_cons_canvas_gotoxy (c, 28, 0);
|
2017-06-30 11:38:46 +02:00
|
|
|
// cmd = r_str_newf ("pxw 128@r:SP;pd@r:PC");
|
2019-03-23 04:46:37 +09:00
|
|
|
cmd = r_str_newf ("%s 128@r:SP;pd@ 0x%"PFMT64x, core->stkcmd, osek);
|
2016-11-21 00:19:15 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
char *dis = r_core_cmd_str (core, cmd);
|
2017-03-08 14:34:19 +03:00
|
|
|
r_cons_canvas_write (c, dis);
|
2016-11-21 00:19:15 +01:00
|
|
|
free (cmd);
|
|
|
|
free (dis);
|
|
|
|
}
|
|
|
|
r_core_block_size (core, obsz);
|
2020-04-17 12:53:35 +02:00
|
|
|
r_core_seek (core, osek, true);
|
2016-11-21 00:19:15 +01:00
|
|
|
|
|
|
|
r_cons_pop ();
|
2017-03-08 14:34:19 +03:00
|
|
|
r_cons_canvas_print (c);
|
|
|
|
r_cons_canvas_free (c);
|
2016-11-21 00:19:15 +01:00
|
|
|
if (asm_minicols) {
|
|
|
|
r_config_set (core->config, "asm.offset", o_ao);
|
|
|
|
r_config_set (core->config, "asm.bytes", o_ab);
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
r_config_set (core->config, "asm.bytes", o_ab);
|
2016-11-21 00:19:15 +01:00
|
|
|
free (o_ao);
|
|
|
|
free (o_ab);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cmd_pCx(RCore *core, const char *input, const char *xcmd) {
|
|
|
|
int h, w = r_cons_get_size (&h);
|
|
|
|
int hex_cols = r_config_get_i (core->config, "hex.cols");
|
|
|
|
int colwidth = hex_cols * 5;
|
|
|
|
int i, columns = w / (colwidth * 0.9);
|
|
|
|
int rows = h - 2;
|
|
|
|
int user_rows = r_num_math (core->num, input);
|
|
|
|
r_config_set_i (core->config, "hex.cols", colwidth / 5);
|
|
|
|
if (user_rows > 0) {
|
|
|
|
rows = user_rows + 1;
|
|
|
|
}
|
|
|
|
RConsCanvas *c = r_cons_canvas_new (w, rows);
|
2018-04-05 18:27:26 +02:00
|
|
|
if (!c) {
|
|
|
|
eprintf ("Couldn't allocate a canvas with %d rows\n", rows);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2016-11-21 00:19:15 +01:00
|
|
|
ut64 tsek = core->offset;
|
|
|
|
c->color = r_config_get_i (core->config, "scr.color");
|
|
|
|
int bsize = hex_cols * rows;
|
|
|
|
if (!strcmp (xcmd, "pxA")) {
|
|
|
|
bsize *= 12;
|
|
|
|
}
|
|
|
|
for (i = 0; i < columns; i++) {
|
2017-03-09 23:29:48 +01:00
|
|
|
(void) r_cons_canvas_gotoxy (c, i * (w / columns), 0);
|
2018-09-20 21:59:32 +08:00
|
|
|
char *cmd = r_str_newf ("%s %d @ %"PFMT64u, xcmd, bsize, tsek);
|
2016-11-21 00:19:15 +01:00
|
|
|
char *dis = r_core_cmd_str (core, cmd);
|
2018-10-08 00:12:05 +02:00
|
|
|
if (dis) {
|
|
|
|
r_cons_canvas_write (c, dis);
|
|
|
|
free (dis);
|
|
|
|
}
|
2016-11-21 00:19:15 +01:00
|
|
|
free (cmd);
|
|
|
|
tsek += bsize - 32;
|
|
|
|
}
|
|
|
|
|
2017-03-08 14:34:19 +03:00
|
|
|
r_cons_canvas_print (c);
|
|
|
|
r_cons_canvas_free (c);
|
2018-04-05 18:27:26 +02:00
|
|
|
err:
|
2016-11-21 00:19:15 +01:00
|
|
|
r_config_set_i (core->config, "hex.cols", hex_cols);
|
|
|
|
}
|
|
|
|
|
2019-01-29 20:56:23 +01:00
|
|
|
static char get_string_type(const ut8 *buf, ut64 len) {
|
2015-03-23 19:53:19 +01:00
|
|
|
ut64 needle = 0;
|
|
|
|
int rc, i;
|
2015-06-02 10:25:40 +02:00
|
|
|
char str_type = 0;
|
2015-03-23 19:53:19 +01:00
|
|
|
|
2016-10-08 00:02:47 +02:00
|
|
|
if (!buf) {
|
2015-03-23 19:53:19 +01:00
|
|
|
return '?';
|
2016-10-08 00:02:47 +02:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
while (needle < len) {
|
|
|
|
rc = r_utf8_decode (buf + needle, len - needle, NULL);
|
2016-01-11 00:24:18 +01:00
|
|
|
if (!rc) {
|
2015-03-23 19:53:19 +01:00
|
|
|
needle++;
|
|
|
|
continue;
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
if (needle + rc + 2 < len &&
|
|
|
|
buf[needle + rc + 0] == 0x00 &&
|
|
|
|
buf[needle + rc + 1] == 0x00 &&
|
|
|
|
buf[needle + rc + 2] == 0x00) {
|
2015-03-23 19:53:19 +01:00
|
|
|
str_type = 'w';
|
2016-09-01 22:34:28 +02:00
|
|
|
} else {
|
2015-03-23 19:53:19 +01:00
|
|
|
str_type = 'a';
|
2016-09-01 22:34:28 +02:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
for (rc = i = 0; needle < len; i += rc) {
|
2015-03-23 19:53:19 +01:00
|
|
|
RRune r;
|
2017-03-09 23:29:48 +01:00
|
|
|
if (str_type == 'w') {
|
|
|
|
if (needle + 1 < len) {
|
|
|
|
r = buf[needle + 1] << 8 | buf[needle];
|
2015-03-23 19:53:19 +01:00
|
|
|
rc = 2;
|
2015-04-06 00:59:55 +02:00
|
|
|
} else {
|
2015-03-23 19:53:19 +01:00
|
|
|
break;
|
|
|
|
}
|
2015-04-06 00:59:55 +02:00
|
|
|
} else {
|
2017-03-09 23:29:48 +01:00
|
|
|
rc = r_utf8_decode (buf + needle, len - needle, &r);
|
|
|
|
if (rc > 1) {
|
|
|
|
str_type = 'u';
|
|
|
|
}
|
2015-03-23 19:53:19 +01:00
|
|
|
}
|
|
|
|
/*Invalid sequence detected*/
|
2016-09-01 22:34:28 +02:00
|
|
|
if (!rc) {
|
2015-03-23 19:53:19 +01:00
|
|
|
needle++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
needle += rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return str_type;
|
|
|
|
}
|
2015-08-14 13:34:40 +02:00
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
static void cmd_print_eq_dict(RCore *core, const ut8 *block, int bsz) {
|
2015-08-14 13:34:40 +02:00
|
|
|
int i;
|
2018-02-02 23:33:35 +01:00
|
|
|
int min = -1;
|
2015-08-14 13:34:40 +02:00
|
|
|
int max = 0;
|
|
|
|
int dict = 0;
|
|
|
|
int range = 0;
|
2017-09-02 01:45:50 -07:00
|
|
|
bool histogram[256] = {0};
|
2017-01-11 00:22:18 +01:00
|
|
|
for (i = 0; i < bsz; i++) {
|
|
|
|
histogram[block[i]] = true;
|
2015-08-14 13:34:40 +02:00
|
|
|
}
|
2017-09-02 01:45:50 -07:00
|
|
|
for (i = 0; i < 256; i++) {
|
2017-01-11 00:22:18 +01:00
|
|
|
if (histogram[i]) {
|
2018-02-02 23:33:35 +01:00
|
|
|
if (min == -1) {
|
2015-08-14 13:34:40 +02:00
|
|
|
min = i;
|
2017-01-11 00:22:18 +01:00
|
|
|
}
|
2015-08-14 13:34:40 +02:00
|
|
|
max = i;
|
|
|
|
dict++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
range = max - min;
|
2018-02-02 23:33:35 +01:00
|
|
|
r_cons_printf ("min: %d 0x%x\n", min, min);
|
|
|
|
r_cons_printf ("max: %d 0x%x\n", max, max);
|
|
|
|
r_cons_printf ("unique (count): %d 0x%x\n", dict, dict);
|
|
|
|
r_cons_printf ("range (max-min): %d 0x%x\n", range, range);
|
|
|
|
r_cons_printf ("size (of block): %d 0x%x\n", bsz, bsz);
|
2015-08-14 13:34:40 +02:00
|
|
|
}
|
|
|
|
|
2019-01-29 20:56:23 +01:00
|
|
|
R_API void r_core_set_asm_configs(RCore *core, char *arch, ut32 bits, int segoff) {
|
2013-11-14 07:52:03 -05:00
|
|
|
r_config_set (core->config, "asm.arch", arch);
|
|
|
|
r_config_set_i (core->config, "asm.bits", bits);
|
2014-09-26 15:40:17 +02:00
|
|
|
// XXX - this needs to be done here, because
|
2013-11-14 07:52:03 -05:00
|
|
|
// if arch == x86 and bits == 16, segoff automatically changes
|
2013-11-25 02:03:54 +01:00
|
|
|
r_config_set_i (core->config, "asm.segoff", segoff);
|
2013-11-14 07:52:03 -05:00
|
|
|
}
|
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
static void cmd_pDj(RCore *core, const char *arg) {
|
2014-08-22 00:21:37 +02:00
|
|
|
int bsize = r_num_math (core->num, arg);
|
2017-02-05 01:24:50 +01:00
|
|
|
if (bsize < 0) {
|
|
|
|
bsize = -bsize;
|
|
|
|
}
|
2019-02-13 11:44:42 +01:00
|
|
|
PJ *pj = pj_new ();
|
|
|
|
if (!pj) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pj_a (pj);
|
2018-02-26 00:59:41 -08:00
|
|
|
ut8 *buf = malloc (bsize);
|
|
|
|
if (buf) {
|
|
|
|
r_io_read_at (core->io, core->offset, buf, bsize);
|
2019-02-13 11:44:42 +01:00
|
|
|
r_core_print_disasm_json (core, core->offset, buf, bsize, 0, pj);
|
2018-02-26 00:59:41 -08:00
|
|
|
free (buf);
|
2014-12-19 16:57:18 +01:00
|
|
|
} else {
|
2018-02-26 00:59:41 -08:00
|
|
|
eprintf ("cannot allocate %d byte(s)\n", bsize);
|
2014-12-19 16:57:18 +01:00
|
|
|
}
|
2019-02-13 11:44:42 +01:00
|
|
|
pj_end (pj);
|
|
|
|
r_cons_printf ("%s", pj_string (pj));
|
|
|
|
pj_free (pj);
|
2014-08-22 00:00:42 +02:00
|
|
|
}
|
|
|
|
|
2018-02-26 00:59:41 -08:00
|
|
|
static void cmd_pdj(RCore *core, const char *arg, ut8* block) {
|
2015-11-22 21:28:11 +01:00
|
|
|
int nblines = r_num_math (core->num, arg);
|
2019-02-13 11:44:42 +01:00
|
|
|
PJ *pj = pj_new ();
|
|
|
|
if (!pj) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pj_a (pj);
|
|
|
|
r_core_print_disasm_json (core, core->offset, block, core->blocksize, nblines, pj);
|
|
|
|
pj_end (pj);
|
|
|
|
r_cons_printf ("%s\n", pj_string (pj));
|
|
|
|
pj_free (pj);
|
2014-08-22 00:39:31 +02:00
|
|
|
}
|
|
|
|
|
2019-03-19 16:37:23 +00:00
|
|
|
static void cmd_p_minus_e(RCore *core, ut64 at, ut64 ate) {
|
|
|
|
ut8 *blockptr = malloc (ate - at);
|
|
|
|
if (!blockptr) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-01 17:57:42 +02:00
|
|
|
if (r_io_read_at (core->io, at, blockptr, (ate - at))) {
|
2019-03-19 16:37:23 +00:00
|
|
|
ut8 entropy = (ut8)(r_hash_entropy_fraction (blockptr, (ate - at)) * 255);
|
|
|
|
entropy = 9 * entropy / 200; // normalize entropy from 0 to 9
|
|
|
|
if (r_config_get_i (core->config, "scr.color")) {
|
|
|
|
const char *color =
|
|
|
|
(entropy > 6) ? Color_BGRED :
|
|
|
|
(entropy > 3) ? Color_BGGREEN :
|
|
|
|
Color_BGBLUE;
|
|
|
|
r_cons_printf ("%s%d"Color_RESET, color, entropy);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%d", entropy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free (blockptr);
|
|
|
|
}
|
|
|
|
|
2017-03-02 10:39:11 +01:00
|
|
|
static void helpCmdTasks(RCore *core) {
|
2019-06-20 12:45:00 +08:00
|
|
|
// TODO: integrate with =h& and bg anal/string/searches/..
|
2017-07-25 04:20:25 -07:00
|
|
|
r_core_cmd_help (core, help_msg_amper);
|
2017-03-02 10:39:11 +01:00
|
|
|
}
|
|
|
|
|
2015-03-19 22:43:47 +01:00
|
|
|
static void print_format_help_help_help_help(RCore *core) {
|
2017-03-09 23:29:48 +01:00
|
|
|
const char *help_msg[] = {
|
|
|
|
" STAHP IT!!!", "", "",
|
|
|
|
NULL
|
|
|
|
};
|
2015-03-19 22:43:47 +01:00
|
|
|
r_core_cmd_help (core, help_msg);
|
|
|
|
}
|
|
|
|
|
2018-09-12 18:43:59 +02:00
|
|
|
static void cmd_print_fromage(RCore *core, const char *input, const ut8* data, int size) {
|
|
|
|
switch (*input) {
|
2018-09-14 01:44:04 +02:00
|
|
|
case 'a':
|
2018-09-13 01:15:18 +02:00
|
|
|
{
|
2018-09-20 19:16:33 +02:00
|
|
|
asn1_setformat (input[1] != 'q');
|
2018-09-25 11:37:15 +02:00
|
|
|
RASN1Object *asn1 = r_asn1_create_object (data, size, data);
|
2018-09-13 01:15:18 +02:00
|
|
|
if (asn1) {
|
2018-09-14 10:29:49 +02:00
|
|
|
char *res = r_asn1_to_string (asn1, 0, NULL);
|
2018-09-13 01:15:18 +02:00
|
|
|
r_asn1_free_object (asn1);
|
2018-09-14 10:29:49 +02:00
|
|
|
if (res) {
|
|
|
|
r_cons_printf ("%s\n", res);
|
|
|
|
free (res);
|
|
|
|
}
|
2018-09-14 01:44:04 +02:00
|
|
|
} else {
|
|
|
|
eprintf ("Malformed object: did you supply enough data?\ntry to change the block size (see b?)\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'x': // "pFx" x509
|
|
|
|
{
|
2018-09-25 11:37:15 +02:00
|
|
|
RX509Certificate* x509 = r_x509_parse_certificate (r_asn1_create_object (data, size, data));
|
2018-09-14 01:44:04 +02:00
|
|
|
if (x509) {
|
2018-09-14 10:29:49 +02:00
|
|
|
RStrBuf *sb = r_strbuf_new ("");
|
|
|
|
r_x509_certificate_dump (x509, NULL, sb);
|
|
|
|
char *res = r_strbuf_drain (sb);
|
|
|
|
if (res) {
|
|
|
|
r_cons_printf ("%s\n", res);
|
|
|
|
free (res);
|
|
|
|
}
|
2018-09-14 01:44:04 +02:00
|
|
|
r_x509_free_certificate (x509);
|
|
|
|
} else {
|
|
|
|
eprintf ("Malformed object: did you supply enough data?\ntry to change the block size (see b?)\n");
|
2018-09-13 01:15:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'p': // "pFp"
|
2018-09-12 18:43:59 +02:00
|
|
|
{
|
|
|
|
RCMS *cms = r_pkcs7_parse_cms (data, size);
|
|
|
|
if (cms) {
|
2018-09-14 10:29:49 +02:00
|
|
|
char *res = r_pkcs7_cms_to_string (cms);
|
|
|
|
if (res) {
|
|
|
|
r_cons_printf ("%s\n", res);
|
|
|
|
free (res);
|
|
|
|
}
|
2018-09-12 18:43:59 +02:00
|
|
|
r_pkcs7_free_cms (cms);
|
2018-09-14 01:44:04 +02:00
|
|
|
} else {
|
|
|
|
eprintf ("Malformed object: did you supply enough data?\ntry to change the block size (see b?)\n");
|
2018-09-12 18:43:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2019-11-06 21:55:36 +01:00
|
|
|
case 'b': // "pFb"
|
|
|
|
{
|
2019-11-06 23:13:08 +01:00
|
|
|
char *s = r_protobuf_decode(data, size, input[1] == 'v');
|
|
|
|
if (s) {
|
|
|
|
r_cons_printf ("%s", s);
|
|
|
|
free (s);
|
|
|
|
}
|
2019-11-06 21:55:36 +01:00
|
|
|
}
|
|
|
|
break;
|
2018-09-12 18:43:59 +02:00
|
|
|
default:
|
2018-11-23 13:52:53 +01:00
|
|
|
case '?': // "pF?"
|
|
|
|
r_core_cmd_help (core, help_msg_pF);
|
2018-09-12 18:43:59 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-31 18:25:04 +08:00
|
|
|
R_API void r_core_gadget_free(RCoreGadget *g) {
|
2019-01-11 09:56:27 +01:00
|
|
|
free (g->cmd);
|
|
|
|
free (g);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *help_msg_pg[] = {
|
|
|
|
"Usage: pg[-]", "[asm|hex]", "print (dis)assembled",
|
|
|
|
"pg", " [x y w h cmd]", "add a new gadget",
|
|
|
|
"pg", "", "print them all",
|
|
|
|
"pg", "*", "print the gadgets as r2 commands",
|
|
|
|
"pg-", "*", "remove all the gadgets",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static void cmd_print_gadget(RCore *core, const char *_input) {
|
|
|
|
if (*_input == '?') { // "pg?"
|
|
|
|
r_core_cmd_help (core, help_msg_pg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (*_input == '-') { // "pg-"
|
|
|
|
// TODO support selecting one
|
|
|
|
r_list_free (core->gadgets);
|
|
|
|
core->gadgets = r_list_newf ((RListFree)r_core_gadget_free);
|
|
|
|
} else if (*_input == '*') { // "pg*"
|
|
|
|
RCoreGadget *g;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (core->gadgets, iter, g) {
|
|
|
|
r_cons_printf ("\"pg %d %d %d %d %s\"\n", g->x, g->y, g->w, g->h, g->cmd);
|
|
|
|
}
|
|
|
|
} else if (*_input == 'b') { // "pgb"
|
|
|
|
eprintf ("TODO: Change gadget background color\n");
|
|
|
|
} else if (*_input == 'm') { // "pgm"
|
|
|
|
int nth = atoi (_input + 1);
|
|
|
|
RCoreGadget *g = r_list_get_n (core->gadgets, nth);
|
|
|
|
if (g) {
|
|
|
|
char *input = strdup (_input);
|
|
|
|
char *space = strchr (input, ' ');
|
|
|
|
if (space) {
|
|
|
|
space++;
|
|
|
|
} else {
|
|
|
|
space = "";
|
|
|
|
}
|
2019-08-28 22:34:16 +02:00
|
|
|
RList *args = r_str_split_list (space, " ", 0);
|
2019-01-11 09:56:27 +01:00
|
|
|
char *x = r_list_pop_head (args);
|
|
|
|
char *y = r_list_pop_head (args);
|
|
|
|
char *w = r_list_pop_head (args);
|
|
|
|
char *h = r_list_pop_head (args);
|
|
|
|
if (x && y && w && h) {
|
|
|
|
g->x = r_num_math (core->num, x);
|
|
|
|
g->y = r_num_math (core->num, y);
|
|
|
|
g->w = r_num_math (core->num, w);
|
|
|
|
g->h = r_num_math (core->num, h);
|
|
|
|
}
|
|
|
|
r_list_free (args);
|
|
|
|
free (input);
|
|
|
|
}
|
|
|
|
} else if (*_input == ' ') { // "pg "
|
|
|
|
char *input = strdup (_input);
|
2019-08-28 22:34:16 +02:00
|
|
|
RList *args = r_str_split_list (input, " ", 0);
|
2019-01-11 09:56:27 +01:00
|
|
|
char *x = r_list_pop_head (args);
|
|
|
|
char *y = r_list_pop_head (args);
|
|
|
|
char *w = r_list_pop_head (args);
|
|
|
|
char *h = r_list_pop_head (args);
|
|
|
|
if (x && y && w && h) {
|
|
|
|
int X = r_num_math (core->num, x);
|
|
|
|
int Y = r_num_math (core->num, y);
|
|
|
|
int W = r_num_math (core->num, w);
|
|
|
|
int H = r_num_math (core->num, h);
|
|
|
|
char *cmd = r_str_list_join (args, " ");
|
|
|
|
if (cmd) {
|
|
|
|
// eprintf ("%d %d %d %d (%s)\n", X, Y, W, H, cmd);
|
|
|
|
RCoreGadget *g = R_NEW0 (RCoreGadget);
|
|
|
|
g->x = X;
|
|
|
|
g->y = Y;
|
|
|
|
g->w = W;
|
|
|
|
g->h = H;
|
|
|
|
g->cmd = cmd;
|
|
|
|
r_list_append (core->gadgets, g);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_list_free (args);
|
|
|
|
free (input);
|
|
|
|
} else if (!*_input) { // "pg"
|
|
|
|
RCoreGadget *g;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (core->gadgets, iter, g) {
|
|
|
|
char *res = r_core_cmd_str (core, g->cmd);
|
|
|
|
if (res) {
|
|
|
|
r_cons_strcat_at (res, g->x, g->y, g->w, g->h);
|
|
|
|
free (res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
r_core_cmd_help (core, help_msg_pg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 00:59:41 -08:00
|
|
|
static void cmd_print_format(RCore *core, const char *_input, const ut8* block, int len) {
|
2018-12-03 02:35:40 +01:00
|
|
|
char *input = NULL;
|
2015-02-03 03:27:58 +01:00
|
|
|
int mode = R_PRINT_MUSTSEE;
|
2014-10-26 16:26:03 +01:00
|
|
|
switch (_input[1]) {
|
2018-08-05 16:19:52 -07:00
|
|
|
case '*': // "pf*"
|
2014-10-22 15:57:28 +02:00
|
|
|
_input++;
|
2015-02-03 03:27:58 +01:00
|
|
|
mode = R_PRINT_SEEFLAGS;
|
2014-10-26 16:26:03 +01:00
|
|
|
break;
|
2018-12-03 02:35:40 +01:00
|
|
|
case 'q': // "pfq"
|
|
|
|
_input++;
|
|
|
|
mode = R_PRINT_QUIET | R_PRINT_MUSTSEE;
|
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case 'd': // "pfd"
|
2015-10-22 17:19:15 +02:00
|
|
|
_input++;
|
|
|
|
mode = R_PRINT_DOT;
|
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case 'j': // "pfj"
|
2014-10-26 02:22:58 +02:00
|
|
|
_input++;
|
2015-02-03 03:27:58 +01:00
|
|
|
mode = R_PRINT_JSON;
|
2014-10-26 16:26:03 +01:00
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case 'v': // "pfv"
|
2015-07-22 14:33:36 +02:00
|
|
|
_input++;
|
|
|
|
mode = R_PRINT_VALUE | R_PRINT_MUSTSEE;
|
|
|
|
break;
|
2019-04-13 15:09:29 +01:00
|
|
|
case 'c': // "pfc"
|
|
|
|
_input++;
|
|
|
|
mode = R_PRINT_STRUCT;
|
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case 's': { // "pfs"
|
2014-11-01 03:48:41 +01:00
|
|
|
const char *val = NULL;
|
2017-03-09 23:29:48 +01:00
|
|
|
_input += 2;
|
2014-11-01 13:01:42 +01:00
|
|
|
if (*_input == '.') {
|
|
|
|
_input++;
|
2017-02-21 23:14:10 +01:00
|
|
|
val = sdb_get (core->print->formats, _input, NULL);
|
2018-01-08 03:05:43 +01:00
|
|
|
if (val) {
|
2019-09-01 19:12:31 +02:00
|
|
|
r_cons_printf ("%d\n", r_print_format_struct_size (core->print, val, mode, 0));
|
2017-03-09 23:29:48 +01:00
|
|
|
} else {
|
2014-11-01 13:01:42 +01:00
|
|
|
eprintf ("Struct %s not defined\nUsage: pfs.struct_name | pfs format\n", _input);
|
|
|
|
}
|
|
|
|
} else if (*_input == ' ') {
|
2016-10-26 23:22:04 +02:00
|
|
|
while (*_input == ' ' && *_input != '\0') {
|
|
|
|
_input++;
|
|
|
|
}
|
|
|
|
if (*_input) {
|
2019-09-01 19:12:31 +02:00
|
|
|
r_cons_printf ("%d\n", r_print_format_struct_size (core->print, _input, mode, 0));
|
2016-10-26 23:22:04 +02:00
|
|
|
} else {
|
2014-11-01 13:01:42 +01:00
|
|
|
eprintf ("Struct %s not defined\nUsage: pfs.struct_name | pfs format\n", _input);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
eprintf ("Usage: pfs.struct_name | pfs format\n");
|
2014-11-01 03:48:41 +01:00
|
|
|
}
|
|
|
|
return;
|
2018-12-03 02:35:40 +01:00
|
|
|
}
|
2018-08-05 16:19:52 -07:00
|
|
|
case '?': // "pf?"
|
2017-01-20 15:43:25 +01:00
|
|
|
_input += 2;
|
2014-10-28 14:36:19 +01:00
|
|
|
if (*_input) {
|
2015-03-19 22:43:47 +01:00
|
|
|
if (*_input == '?') {
|
|
|
|
_input++;
|
|
|
|
if (_input && *_input == '?') {
|
|
|
|
_input++;
|
|
|
|
if (_input && *_input == '?') {
|
|
|
|
print_format_help_help_help_help (core);
|
|
|
|
} else {
|
2017-07-25 04:20:25 -07:00
|
|
|
r_core_cmd_help (core, help_detail2_pf);
|
2015-03-19 22:43:47 +01:00
|
|
|
}
|
|
|
|
} else {
|
2017-07-25 22:03:52 -07:00
|
|
|
r_core_cmd_help (core, help_detail_pf);
|
2015-03-19 22:43:47 +01:00
|
|
|
}
|
|
|
|
} else {
|
2020-03-02 21:39:37 +01:00
|
|
|
const char *struct_name = r_str_trim_head_ro (_input);
|
2019-04-25 23:14:47 +08:00
|
|
|
const char *val = sdb_get (core->print->formats, struct_name, NULL);
|
|
|
|
if (val) {
|
|
|
|
r_cons_printf ("%s\n", val);
|
|
|
|
} else {
|
|
|
|
eprintf ("Struct %s is not defined\n", _input);
|
2014-10-28 14:36:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2017-07-25 04:20:25 -07:00
|
|
|
r_core_cmd_help (core, help_msg_pf);
|
2014-10-28 14:36:19 +01:00
|
|
|
}
|
2014-10-26 16:26:03 +01:00
|
|
|
return;
|
2018-12-03 02:35:40 +01:00
|
|
|
case 'o': // "pfo"
|
|
|
|
if (_input[2] == '?') {
|
2014-10-29 20:19:28 +01:00
|
|
|
eprintf ("|Usage: pfo [format-file]\n"
|
2018-05-02 16:58:14 +03:00
|
|
|
" " R_JOIN_3_PATHS ("~", R2_HOME_SDB_FORMAT, "") "\n"
|
|
|
|
" " R_JOIN_3_PATHS ("%s", R2_SDB_FORMAT, "") "\n",
|
2018-04-15 20:35:18 +02:00
|
|
|
r_sys_prefix (NULL));
|
2018-12-03 02:35:40 +01:00
|
|
|
} else if (_input[2] == ' ') {
|
2020-03-02 21:39:37 +01:00
|
|
|
const char *fname = r_str_trim_head_ro (_input + 3);
|
2019-05-11 17:52:19 +02:00
|
|
|
char *tmp = r_str_newf (R_JOIN_2_PATHS (R2_HOME_SDB_FORMAT, "%s"), fname);
|
2019-03-29 13:00:49 +01:00
|
|
|
char *home = r_str_home (tmp);
|
|
|
|
free (tmp);
|
2019-05-11 17:52:19 +02:00
|
|
|
tmp = r_str_newf (R_JOIN_2_PATHS (R2_SDB_FORMAT, "%s"), fname);
|
2019-03-29 13:00:49 +01:00
|
|
|
char *path = r_str_r2_prefix (tmp);
|
2019-03-29 16:53:44 +01:00
|
|
|
if (r_str_endswith (_input, ".h")) {
|
|
|
|
char *error_msg = NULL;
|
2019-05-15 07:46:44 +01:00
|
|
|
const char *dir = r_config_get (core->config, "dir.types");
|
|
|
|
char *out = r_parse_c_file (core->anal, path, dir, &error_msg);
|
2019-03-29 16:53:44 +01:00
|
|
|
if (out) {
|
2019-03-30 07:17:15 -05:00
|
|
|
r_anal_save_parsed_type (core->anal, out);
|
2019-03-29 16:53:44 +01:00
|
|
|
r_core_cmd0 (core, ".ts*");
|
|
|
|
free (out);
|
|
|
|
} else {
|
|
|
|
eprintf ("Parse error: %s\n", error_msg);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!r_core_cmd_file (core, home) && !r_core_cmd_file (core, path)) {
|
|
|
|
if (!r_core_cmd_file (core, _input + 3)) {
|
|
|
|
eprintf ("pfo: cannot open format file at '%s'\n", path);
|
|
|
|
}
|
2017-01-20 15:43:25 +01:00
|
|
|
}
|
|
|
|
}
|
2014-10-21 11:49:33 +02:00
|
|
|
free (home);
|
2018-04-15 20:35:18 +02:00
|
|
|
free (path);
|
2019-03-29 13:00:49 +01:00
|
|
|
free (tmp);
|
2014-10-21 11:49:33 +02:00
|
|
|
} else {
|
|
|
|
RList *files;
|
|
|
|
RListIter *iter;
|
|
|
|
const char *fn;
|
2018-04-28 11:02:55 +03:00
|
|
|
char *home = r_str_home (R2_HOME_SDB_FORMAT R_SYS_DIR);
|
2014-10-21 11:49:33 +02:00
|
|
|
if (home) {
|
|
|
|
files = r_sys_dir (home);
|
|
|
|
r_list_foreach (files, iter, fn) {
|
2016-06-26 00:51:17 -04:00
|
|
|
if (*fn && *fn != '.') {
|
|
|
|
r_cons_println (fn);
|
|
|
|
}
|
2014-10-21 11:49:33 +02:00
|
|
|
}
|
|
|
|
r_list_free (files);
|
|
|
|
free (home);
|
|
|
|
}
|
2018-04-28 11:02:55 +03:00
|
|
|
char *path = r_str_r2_prefix (R2_SDB_FORMAT R_SYS_DIR);
|
2018-04-15 20:35:18 +02:00
|
|
|
if (path) {
|
|
|
|
files = r_sys_dir (path);
|
|
|
|
r_list_foreach (files, iter, fn) {
|
|
|
|
if (*fn && *fn != '.') {
|
|
|
|
r_cons_println (fn);
|
|
|
|
}
|
2016-06-26 00:51:17 -04:00
|
|
|
}
|
2018-04-15 20:35:18 +02:00
|
|
|
r_list_free (files);
|
|
|
|
free (path);
|
2014-10-21 11:49:33 +02:00
|
|
|
}
|
|
|
|
}
|
2015-01-16 00:56:54 +01:00
|
|
|
free (input);
|
2014-10-21 11:49:33 +02:00
|
|
|
return;
|
2018-12-03 02:35:40 +01:00
|
|
|
} // switch
|
|
|
|
|
|
|
|
input = strdup (_input);
|
2014-10-21 11:49:33 +02:00
|
|
|
/* syntax aliasing bridge for 'pf foo=xxd' -> 'pf.foo xxd' */
|
2017-03-09 23:29:48 +01:00
|
|
|
if (input[1] == ' ') {
|
2016-12-10 23:29:19 +01:00
|
|
|
char *eq = strchr (input + 2, '=');
|
2014-10-21 11:49:33 +02:00
|
|
|
if (eq) {
|
|
|
|
input[1] = '.';
|
|
|
|
*eq = ' ';
|
|
|
|
}
|
|
|
|
}
|
2015-05-07 12:02:08 +02:00
|
|
|
|
2020-07-20 12:18:38 +02:00
|
|
|
bool listFormats = false;
|
2017-03-09 23:29:48 +01:00
|
|
|
if (input[1] == '.') {
|
2020-07-20 12:18:38 +02:00
|
|
|
listFormats = true;
|
|
|
|
} else if (!strcmp (input, "*") && mode == R_PRINT_SEEFLAGS) {
|
|
|
|
listFormats = true;
|
2017-01-20 15:43:25 +01:00
|
|
|
}
|
2015-05-07 12:02:08 +02:00
|
|
|
|
2015-07-22 14:33:36 +02:00
|
|
|
core->print->reg = core->dbg->reg;
|
|
|
|
core->print->get_register = r_reg_get;
|
|
|
|
core->print->get_register_value = r_reg_get_value;
|
|
|
|
|
2015-07-28 18:28:33 +02:00
|
|
|
int o_blocksize = core->blocksize;
|
|
|
|
|
2015-05-07 12:02:08 +02:00
|
|
|
if (listFormats) {
|
2015-04-27 03:00:09 +02:00
|
|
|
core->print->num = core->num;
|
2015-03-05 20:40:27 -05:00
|
|
|
/* print all stored format */
|
2020-07-20 12:18:38 +02:00
|
|
|
if (!input[1] || !input[2]) { // "pf."
|
2017-02-21 23:14:10 +01:00
|
|
|
SdbListIter *iter;
|
|
|
|
SdbKv *kv;
|
2018-10-26 15:54:32 +02:00
|
|
|
SdbList *sdbls = sdb_foreach_list (core->print->formats, true);
|
2017-02-21 23:14:10 +01:00
|
|
|
ls_foreach (sdbls, iter, kv) {
|
2018-10-05 15:21:46 +02:00
|
|
|
r_cons_printf ("pf.%s %s\n", sdbkv_key (kv), sdbkv_value (kv));
|
2014-10-21 11:49:33 +02:00
|
|
|
}
|
2015-03-05 20:40:27 -05:00
|
|
|
/* delete a format */
|
2020-07-20 12:18:38 +02:00
|
|
|
} else if (input[1] && input[2] == '-') { // "pf-"
|
|
|
|
if (input[3] == '*') { // "pf-*"
|
2017-02-21 23:14:10 +01:00
|
|
|
sdb_free (core->print->formats);
|
|
|
|
core->print->formats = sdb_new0 ();
|
2020-07-20 12:18:38 +02:00
|
|
|
} else { // "pf-xxx"
|
2017-02-21 23:14:10 +01:00
|
|
|
sdb_unset (core->print->formats, input + 3, 0);
|
2017-01-20 15:43:25 +01:00
|
|
|
}
|
2014-10-21 11:49:33 +02:00
|
|
|
} else {
|
2017-01-20 15:43:25 +01:00
|
|
|
char *name = strdup (input + (input[1]? 2: 1));
|
2014-10-21 11:49:33 +02:00
|
|
|
char *space = strchr (name, ' ');
|
2015-10-22 17:39:05 +02:00
|
|
|
char *eq = strchr (name, '=');
|
|
|
|
char *dot = strchr (name, '.');
|
|
|
|
|
|
|
|
if (eq && !dot) {
|
|
|
|
*eq = ' ';
|
|
|
|
space = eq;
|
|
|
|
eq = NULL;
|
|
|
|
}
|
|
|
|
|
2015-03-05 20:40:27 -05:00
|
|
|
/* store a new format */
|
2016-09-19 13:44:47 +01:00
|
|
|
if (space && (!eq || space < eq)) {
|
2014-10-21 11:49:33 +02:00
|
|
|
*space++ = 0;
|
2020-07-20 12:18:38 +02:00
|
|
|
if (strchr (name, '.')) {
|
2015-02-05 22:42:29 +01:00
|
|
|
eprintf ("Struct or fields name can not contain dot symbol (.)\n");
|
2016-08-18 01:47:56 +05:30
|
|
|
} else {
|
2020-07-20 12:18:38 +02:00
|
|
|
// pf.foo=xxx
|
2017-02-21 23:14:10 +01:00
|
|
|
sdb_set (core->print->formats, name, space, 0);
|
2016-08-18 01:47:56 +05:30
|
|
|
}
|
2015-04-11 02:31:34 +03:00
|
|
|
free (name);
|
2014-10-21 11:49:33 +02:00
|
|
|
free (input);
|
|
|
|
return;
|
|
|
|
}
|
2015-03-03 00:34:09 +01:00
|
|
|
|
2017-02-21 23:14:10 +01:00
|
|
|
if (!strchr (name, '.') &&
|
2017-03-09 23:29:48 +01:00
|
|
|
!sdb_get (core->print->formats, name, NULL)) {
|
2015-10-22 17:39:05 +02:00
|
|
|
eprintf ("Cannot find '%s' format.\n", name);
|
2015-03-05 20:40:27 -05:00
|
|
|
free (name);
|
2015-04-11 02:31:34 +03:00
|
|
|
free (input);
|
2015-03-05 20:40:27 -05:00
|
|
|
return;
|
|
|
|
}
|
2015-07-28 18:28:33 +02:00
|
|
|
|
2018-08-30 15:54:04 +02:00
|
|
|
char *delim = strchr (name, '.');
|
|
|
|
if (delim) {
|
|
|
|
int len = delim - name;
|
|
|
|
if (len > 0) {
|
|
|
|
name[len] = '\0';
|
2019-03-31 18:25:04 +08:00
|
|
|
}
|
|
|
|
}
|
2018-08-30 15:54:04 +02:00
|
|
|
|
2015-07-28 18:28:33 +02:00
|
|
|
/* Load format from name into fmt to get the size */
|
|
|
|
/* This make sure the whole structure will be printed */
|
|
|
|
const char *fmt = NULL;
|
2017-02-21 23:14:10 +01:00
|
|
|
fmt = sdb_get (core->print->formats, name, NULL);
|
2018-01-08 03:05:43 +01:00
|
|
|
if (fmt) {
|
2019-09-01 19:12:31 +02:00
|
|
|
int size = r_print_format_struct_size (core->print, fmt, mode, 0) + 10;
|
2017-01-20 15:43:25 +01:00
|
|
|
if (size > core->blocksize) {
|
2015-07-28 18:28:33 +02:00
|
|
|
r_core_block_size (core, size);
|
2017-01-20 15:43:25 +01:00
|
|
|
}
|
2015-07-28 18:28:33 +02:00
|
|
|
}
|
2015-03-05 20:40:27 -05:00
|
|
|
/* display a format */
|
2014-10-21 11:49:33 +02:00
|
|
|
if (dot) {
|
|
|
|
*dot++ = 0;
|
|
|
|
eq = strchr (dot, '=');
|
2015-07-22 14:33:36 +02:00
|
|
|
if (eq) { // Write mode (pf.field=value)
|
2014-12-16 19:33:18 +01:00
|
|
|
*eq++ = 0;
|
2015-02-03 03:27:58 +01:00
|
|
|
mode = R_PRINT_MUSTSET;
|
2014-12-16 19:33:18 +01:00
|
|
|
r_print_format (core->print, core->offset,
|
2018-05-21 01:59:25 +02:00
|
|
|
core->block, core->blocksize, name, mode, eq, dot);
|
2014-10-21 11:49:33 +02:00
|
|
|
} else {
|
2014-12-16 19:33:18 +01:00
|
|
|
r_print_format (core->print, core->offset,
|
2018-05-21 01:59:25 +02:00
|
|
|
core->block, core->blocksize, name, mode, NULL, dot);
|
2014-10-21 11:49:33 +02:00
|
|
|
}
|
|
|
|
} else {
|
2015-03-05 20:40:27 -05:00
|
|
|
r_print_format (core->print, core->offset,
|
2018-05-21 01:59:25 +02:00
|
|
|
core->block, core->blocksize, name, mode, NULL, NULL);
|
2014-10-21 11:49:33 +02:00
|
|
|
}
|
|
|
|
free (name);
|
|
|
|
}
|
2015-07-28 18:28:33 +02:00
|
|
|
} else {
|
|
|
|
/* This make sure the structure will be printed entirely */
|
2020-03-02 21:39:37 +01:00
|
|
|
const char *fmt = r_str_trim_head_ro (input + 1);
|
2019-09-01 19:12:31 +02:00
|
|
|
int struct_sz = r_print_format_struct_size (core->print, fmt, mode, 0);
|
2018-05-22 13:05:54 +05:30
|
|
|
int size = R_MAX (core->blocksize, struct_sz);
|
|
|
|
ut8 *buf = calloc (1, size);
|
|
|
|
if (!buf) {
|
|
|
|
eprintf ("cannot allocate %d byte(s)\n", size);
|
|
|
|
goto stage_left;
|
|
|
|
}
|
|
|
|
memcpy (buf, core->block, core->blocksize);
|
2017-02-09 09:09:54 +00:00
|
|
|
/* check if fmt is '\d+ \d+<...>', common mistake due to usage string*/
|
|
|
|
bool syntax_ok = true;
|
|
|
|
char *args = strdup (fmt);
|
2017-03-09 23:29:48 +01:00
|
|
|
if (!args) {
|
2017-02-09 09:09:54 +00:00
|
|
|
r_cons_printf ("Error: Mem Allocation.");
|
|
|
|
free (args);
|
|
|
|
goto stage_left;
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
const char *arg1 = strtok (args, " ");
|
|
|
|
if (arg1 && r_str_isnumber (arg1)) {
|
2017-02-09 09:09:54 +00:00
|
|
|
syntax_ok = false;
|
|
|
|
r_cons_printf ("Usage: pf [0|cnt][format-string]\n");
|
|
|
|
}
|
|
|
|
free (args);
|
|
|
|
if (syntax_ok) {
|
|
|
|
r_print_format (core->print, core->offset,
|
2018-05-22 13:05:54 +05:30
|
|
|
buf, size, fmt, mode, NULL, NULL);
|
2017-02-09 09:09:54 +00:00
|
|
|
}
|
2018-05-22 13:05:54 +05:30
|
|
|
free (buf);
|
2015-07-28 18:28:33 +02:00
|
|
|
}
|
2017-02-09 09:09:54 +00:00
|
|
|
stage_left:
|
2014-10-21 11:49:33 +02:00
|
|
|
free (input);
|
2015-07-28 18:28:33 +02:00
|
|
|
r_core_block_size (core, o_blocksize);
|
2014-10-21 11:49:33 +02:00
|
|
|
}
|
|
|
|
|
2013-10-16 01:10:27 +02:00
|
|
|
// > pxa
|
2014-08-26 23:52:34 +02:00
|
|
|
/* In this function, most of the buffers have 4 times
|
2014-12-05 18:31:28 -05:00
|
|
|
* the required length. This is because we supports colours,
|
2014-08-26 23:52:34 +02:00
|
|
|
* that are 4 chars long. */
|
2017-03-09 23:29:48 +01:00
|
|
|
#define append(x, y) { strcat (x, y); x += strlen (y); }
|
2013-10-20 00:25:37 +02:00
|
|
|
static void annotated_hexdump(RCore *core, const char *str, int len) {
|
2013-10-16 02:45:03 +02:00
|
|
|
const int usecolor = r_config_get_i (core->config, "scr.color");
|
2014-08-24 05:35:48 +02:00
|
|
|
int nb_cols = r_config_get_i (core->config, "hex.cols");
|
2017-05-23 15:53:58 +02:00
|
|
|
core->print->use_comments = r_config_get_i (core->config, "hex.comments");
|
2014-09-27 03:48:54 +02:00
|
|
|
int flagsz = r_config_get_i (core->config, "hex.flagsz");
|
2019-06-23 02:33:24 +02:00
|
|
|
bool showSection = r_config_get_i (core->config, "hex.section");
|
2013-10-15 03:56:01 +02:00
|
|
|
const ut8 *buf = core->block;
|
|
|
|
ut64 addr = core->offset;
|
2014-09-08 01:33:50 +02:00
|
|
|
int color_idx = 0;
|
2014-08-26 23:52:34 +02:00
|
|
|
char *bytes, *chars;
|
2017-03-09 23:29:48 +01:00
|
|
|
char *ebytes, *echars; // They'll walk over the vars above
|
2013-10-15 03:56:01 +02:00
|
|
|
ut64 fend = UT64_MAX;
|
2014-08-26 23:52:34 +02:00
|
|
|
int i, j, low, max, here, rows;
|
2016-01-03 02:05:13 +01:00
|
|
|
bool marks = false, setcolor = true, hascolor = false;
|
2018-12-16 15:54:40 +02:00
|
|
|
ut8 ch = 0;
|
2017-08-13 05:01:00 -07:00
|
|
|
char *colors[10] = {NULL};
|
2017-05-18 11:43:26 +02:00
|
|
|
for (i = 0; i < 10; i++) {
|
|
|
|
colors[i] = r_cons_rainbow_get (i, 10, false);
|
|
|
|
}
|
2014-08-24 05:35:48 +02:00
|
|
|
const int col = core->print->col;
|
2014-08-26 23:52:34 +02:00
|
|
|
RFlagItem *flag, *current_flag = NULL;
|
2017-03-09 23:29:48 +01:00
|
|
|
char **note;
|
2015-07-10 00:44:16 +02:00
|
|
|
int html = r_config_get_i (core->config, "scr.html");
|
2014-08-26 23:52:34 +02:00
|
|
|
int nb_cons_cols;
|
2017-12-05 21:13:24 +01:00
|
|
|
bool compact = false;
|
2013-10-15 03:56:01 +02:00
|
|
|
|
2017-12-05 21:13:24 +01:00
|
|
|
if (core->print) {
|
|
|
|
compact = core->print->flags & R_PRINT_FLAGS_COMPACT;
|
|
|
|
}
|
|
|
|
char *format = compact ? " %X %X" : " %X %X ";
|
|
|
|
int step = compact ? 4 : 5;
|
2018-07-17 22:05:01 +03:00
|
|
|
|
2014-08-26 23:52:34 +02:00
|
|
|
// Adjust the number of columns
|
2017-03-09 23:29:48 +01:00
|
|
|
if (nb_cols < 1) {
|
2014-08-26 23:52:34 +02:00
|
|
|
nb_cols = 16;
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
nb_cols -= (nb_cols % 2); // nb_cols should be even
|
2019-04-05 02:39:38 +02:00
|
|
|
if (nb_cols < 1) {
|
|
|
|
return;
|
|
|
|
}
|
2014-08-24 05:35:48 +02:00
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
nb_cons_cols = 12 + nb_cols * 2 + (nb_cols / 2);
|
2014-09-24 23:59:36 +02:00
|
|
|
nb_cons_cols += 17;
|
2017-03-09 23:29:48 +01:00
|
|
|
rows = len / nb_cols;
|
2014-08-26 23:52:34 +02:00
|
|
|
|
2018-12-11 01:57:41 +01:00
|
|
|
chars = calloc (nb_cols * 40, sizeof (char));
|
2017-08-13 05:01:00 -07:00
|
|
|
if (!chars) goto err_chars;
|
2017-05-18 11:43:26 +02:00
|
|
|
note = calloc (nb_cols, sizeof (char *));
|
2017-08-13 05:01:00 -07:00
|
|
|
if (!note) goto err_note;
|
2018-12-11 01:57:41 +01:00
|
|
|
bytes = calloc (nb_cons_cols * 40, sizeof (char));
|
2017-08-13 05:01:00 -07:00
|
|
|
if (!bytes) goto err_bytes;
|
2014-09-27 03:48:54 +02:00
|
|
|
#if 1
|
2018-04-10 23:52:47 +02:00
|
|
|
int addrpadlen = strlen (sdb_fmt ("%08"PFMT64x, addr)) - 8;
|
2014-09-27 03:48:54 +02:00
|
|
|
char addrpad[32];
|
2017-03-09 23:29:48 +01:00
|
|
|
if (addrpadlen > 0) {
|
2014-09-28 01:45:35 +02:00
|
|
|
memset (addrpad, ' ', addrpadlen);
|
|
|
|
addrpad[addrpadlen] = 0;
|
2017-03-09 23:29:48 +01:00
|
|
|
// Compute, then show the legend
|
2014-09-28 01:45:35 +02:00
|
|
|
strcpy (bytes, addrpad);
|
|
|
|
} else {
|
|
|
|
*addrpad = 0;
|
|
|
|
addrpadlen = 0;
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
strcpy (bytes + addrpadlen, "- offset - ");
|
2014-09-27 03:48:54 +02:00
|
|
|
#endif
|
|
|
|
j = strlen (bytes);
|
2017-03-09 23:29:48 +01:00
|
|
|
for (i = 0; i < nb_cols; i += 2) {
|
2017-12-05 21:13:24 +01:00
|
|
|
sprintf (bytes + j, format, (i & 0xf), (i + 1) & 0xf);
|
|
|
|
j += step;
|
2014-08-24 05:35:48 +02:00
|
|
|
}
|
2018-12-11 01:57:41 +01:00
|
|
|
j--;
|
|
|
|
strcpy (bytes + j, " ");
|
|
|
|
j += 2;
|
2017-03-09 23:29:48 +01:00
|
|
|
for (i = 0; i < nb_cols; i++) {
|
|
|
|
sprintf (bytes + j + i, "%0X", i % 17);
|
|
|
|
}
|
|
|
|
if (usecolor) {
|
|
|
|
r_cons_strcat (Color_GREEN);
|
2018-12-11 01:57:41 +01:00
|
|
|
r_cons_strcat (bytes);
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_strcat (Color_RESET);
|
2018-12-11 01:57:41 +01:00
|
|
|
} else {
|
|
|
|
r_cons_strcat (bytes);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2014-08-26 23:52:34 +02:00
|
|
|
r_cons_newline ();
|
2014-08-24 05:35:48 +02:00
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
// hexdump
|
|
|
|
for (i = 0; i < rows; i++) {
|
2014-08-26 23:52:34 +02:00
|
|
|
bytes[0] = '\0';
|
|
|
|
chars[0] = '\0';
|
2013-10-15 03:56:01 +02:00
|
|
|
ebytes = bytes;
|
|
|
|
echars = chars;
|
2015-09-14 12:35:38 +02:00
|
|
|
hascolor = false;
|
2019-04-15 13:22:27 +02:00
|
|
|
ut64 ea = addr;
|
|
|
|
if (core->print->pava) {
|
|
|
|
ut64 va = r_io_p2v (core->io, addr);
|
|
|
|
if (va != UT64_MAX) {
|
|
|
|
ea = va;
|
|
|
|
}
|
|
|
|
}
|
2014-08-26 23:52:34 +02:00
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
if (usecolor) {
|
2019-01-18 11:58:49 +01:00
|
|
|
append (ebytes, core->cons->context->pal.offset);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2019-06-23 02:33:24 +02:00
|
|
|
if (showSection) {
|
|
|
|
const char * name = r_core_get_section_name (core, ea);
|
|
|
|
char *s = r_str_newf ("%20s ", name);
|
|
|
|
append (ebytes, s);
|
|
|
|
free (s);
|
|
|
|
}
|
2019-04-15 13:22:27 +02:00
|
|
|
ebytes += sprintf (ebytes, "0x%08"PFMT64x, ea);
|
2017-03-09 23:29:48 +01:00
|
|
|
if (usecolor) {
|
|
|
|
append (ebytes, Color_RESET);
|
|
|
|
}
|
|
|
|
append (ebytes, (col == 1)? " |": " ");
|
2018-12-11 01:57:41 +01:00
|
|
|
bool hadflag = false;
|
2017-03-09 23:29:48 +01:00
|
|
|
for (j = 0; j < nb_cols; j++) {
|
2015-09-14 12:35:38 +02:00
|
|
|
setcolor = true;
|
2018-11-14 00:41:28 +02:00
|
|
|
R_FREE (note[j]);
|
2014-08-26 23:52:34 +02:00
|
|
|
|
2019-04-15 13:22:27 +02:00
|
|
|
// TODO: in pava mode we should read addr or ea? // imho ea. but wat about hdrs and such
|
2020-05-09 20:49:28 +02:00
|
|
|
RIntervalNode *meta_node = r_meta_get_in (core->anal, ea + j, R_META_TYPE_FORMAT);
|
|
|
|
RAnalMetaItem *meta = meta_node ? meta_node->data : NULL;
|
|
|
|
if (meta && meta->type == R_META_TYPE_FORMAT && meta_node->start == addr + j) {
|
2018-12-11 01:57:41 +01:00
|
|
|
r_cons_printf (".format %s ; size=", meta->str);
|
|
|
|
r_core_cmdf (core, "pfs %s", meta->str);
|
2020-05-09 20:49:28 +02:00
|
|
|
r_core_cmdf (core, "pf %s @ 0x%08"PFMT64x, meta->str, meta_node->start);
|
2020-05-15 16:23:59 +02:00
|
|
|
if (usecolor) {
|
|
|
|
append (ebytes, Color_INVERT);
|
|
|
|
append (echars, Color_INVERT);
|
|
|
|
}
|
2018-12-11 01:57:41 +01:00
|
|
|
hadflag = true;
|
|
|
|
}
|
2019-09-07 20:24:14 +03:00
|
|
|
if (meta) {
|
|
|
|
meta = NULL;
|
|
|
|
}
|
2013-10-15 03:56:01 +02:00
|
|
|
// collect comments
|
2020-05-09 20:49:28 +02:00
|
|
|
const char *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, addr + j);
|
2013-10-16 01:10:27 +02:00
|
|
|
if (comment) {
|
2020-10-21 17:27:17 +08:00
|
|
|
note[j] = r_str_newf (";%s", comment);
|
2015-09-14 12:35:38 +02:00
|
|
|
marks = true;
|
2013-10-16 01:10:27 +02:00
|
|
|
}
|
2014-08-26 23:52:34 +02:00
|
|
|
|
2013-10-15 03:56:01 +02:00
|
|
|
// collect flags
|
2017-03-09 23:29:48 +01:00
|
|
|
flag = r_flag_get_i (core->flags, addr + j);
|
2014-12-05 18:31:28 -05:00
|
|
|
if (flag) { // Beginning of a flag
|
2014-09-27 03:48:54 +02:00
|
|
|
if (flagsz) {
|
2017-03-09 23:29:48 +01:00
|
|
|
fend = addr + flagsz; // core->blocksize;
|
2014-09-27 03:48:54 +02:00
|
|
|
} else {
|
|
|
|
fend = addr + j + flag->size;
|
|
|
|
}
|
2020-05-09 20:49:28 +02:00
|
|
|
free (note[j]);
|
2019-05-13 22:16:13 +08:00
|
|
|
note[j] = r_str_prepend (strdup (flag->name), "/");
|
2015-09-14 12:35:38 +02:00
|
|
|
marks = true;
|
2014-09-08 01:33:50 +02:00
|
|
|
color_idx++;
|
2017-05-18 11:43:26 +02:00
|
|
|
color_idx %= 10;
|
2014-08-26 23:52:34 +02:00
|
|
|
current_flag = flag;
|
2019-06-23 02:33:24 +02:00
|
|
|
if (showSection) {
|
|
|
|
r_cons_printf ("%20s ", "");
|
|
|
|
}
|
2018-12-11 01:57:41 +01:00
|
|
|
if (flag->offset == addr + j) {
|
2020-05-15 16:23:59 +02:00
|
|
|
if (usecolor) {
|
|
|
|
append (ebytes, Color_INVERT);
|
|
|
|
append (echars, Color_INVERT);
|
|
|
|
}
|
2018-12-11 01:57:41 +01:00
|
|
|
hadflag = true;
|
|
|
|
}
|
2013-10-16 01:10:27 +02:00
|
|
|
} else {
|
2014-08-26 23:52:34 +02:00
|
|
|
// Are we past the current flag?
|
2017-03-09 23:29:48 +01:00
|
|
|
if (current_flag && addr + j > (current_flag->offset + current_flag->size)) {
|
2015-09-14 12:35:38 +02:00
|
|
|
setcolor = false;
|
2014-08-26 23:52:34 +02:00
|
|
|
current_flag = NULL;
|
|
|
|
}
|
|
|
|
// Turn colour off if we're at the end of the current flag
|
2017-03-09 23:29:48 +01:00
|
|
|
if (fend == UT64_MAX || fend <= addr + j) {
|
2015-09-14 12:35:38 +02:00
|
|
|
setcolor = false;
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2013-10-16 01:10:27 +02:00
|
|
|
}
|
2020-05-15 16:23:59 +02:00
|
|
|
if (usecolor) {
|
|
|
|
if (!setcolor) {
|
|
|
|
const char *bytecolor = r_print_byte_color (core->print, ch);
|
|
|
|
if (bytecolor) {
|
|
|
|
append (ebytes, bytecolor);
|
|
|
|
append (echars, bytecolor);
|
|
|
|
hascolor = true;
|
|
|
|
}
|
|
|
|
} else if (!hascolor) {
|
2018-12-11 01:57:41 +01:00
|
|
|
hascolor = true;
|
2014-08-26 23:52:34 +02:00
|
|
|
if (current_flag && current_flag->color) {
|
2018-02-23 19:00:47 +01:00
|
|
|
char *ansicolor = r_cons_pal_parse (current_flag->color, NULL);
|
2018-12-11 01:57:41 +01:00
|
|
|
if (ansicolor) {
|
|
|
|
append (ebytes, ansicolor);
|
|
|
|
append (echars, ansicolor);
|
|
|
|
free (ansicolor);
|
|
|
|
}
|
2014-08-26 23:52:34 +02:00
|
|
|
} else { // Use "random" colours
|
2014-09-08 01:33:50 +02:00
|
|
|
append (ebytes, colors[color_idx]);
|
|
|
|
append (echars, colors[color_idx]);
|
2014-08-19 01:47:02 +02:00
|
|
|
}
|
2013-10-16 02:45:03 +02:00
|
|
|
}
|
2013-10-15 03:56:01 +02:00
|
|
|
}
|
2014-08-26 23:52:34 +02:00
|
|
|
here = R_MIN ((i * nb_cols) + j, core->blocksize);
|
|
|
|
ch = buf[here];
|
2017-03-09 23:29:48 +01:00
|
|
|
if (core->print->ocur != -1) {
|
2013-10-15 03:56:01 +02:00
|
|
|
low = R_MIN (core->print->cur, core->print->ocur);
|
|
|
|
max = R_MAX (core->print->cur, core->print->ocur);
|
|
|
|
} else {
|
|
|
|
low = max = core->print->cur;
|
|
|
|
}
|
|
|
|
if (core->print->cur_enabled) {
|
2017-03-09 23:29:48 +01:00
|
|
|
if (low == max) {
|
2013-10-16 02:45:03 +02:00
|
|
|
if (low == here) {
|
2020-05-15 16:23:59 +02:00
|
|
|
if (html || !usecolor) {
|
2015-07-10 00:44:16 +02:00
|
|
|
append (ebytes, "[");
|
|
|
|
append (echars, "[");
|
|
|
|
} else {
|
|
|
|
append (echars, Color_INVERT);
|
|
|
|
append (ebytes, Color_INVERT);
|
|
|
|
}
|
2013-10-16 02:45:03 +02:00
|
|
|
}
|
2013-10-16 01:10:27 +02:00
|
|
|
} else {
|
2017-03-09 23:29:48 +01:00
|
|
|
if (here >= low && here < max) {
|
2020-05-15 16:23:59 +02:00
|
|
|
if (html || !usecolor) {
|
2015-07-10 00:44:16 +02:00
|
|
|
append (ebytes, "[");
|
|
|
|
append (echars, "[");
|
|
|
|
} else {
|
2020-05-15 16:23:59 +02:00
|
|
|
if (usecolor) {
|
|
|
|
append (ebytes, Color_INVERT);
|
|
|
|
append (echars, Color_INVERT);
|
|
|
|
}
|
2015-07-10 00:44:16 +02:00
|
|
|
}
|
2013-10-16 02:45:03 +02:00
|
|
|
}
|
2013-10-15 03:56:01 +02:00
|
|
|
}
|
|
|
|
}
|
2013-10-16 01:10:27 +02:00
|
|
|
sprintf (ebytes, "%02x", ch);
|
2018-12-11 01:57:41 +01:00
|
|
|
// r_print_byte (core->print, "%02x ", j, ch);
|
2013-10-15 03:56:01 +02:00
|
|
|
ebytes += strlen (ebytes);
|
2018-12-11 01:57:41 +01:00
|
|
|
if (hadflag) {
|
2020-05-15 16:23:59 +02:00
|
|
|
if (usecolor) {
|
|
|
|
append (ebytes, Color_INVERT_RESET);
|
|
|
|
append (echars, Color_INVERT_RESET);
|
|
|
|
}
|
2018-12-11 01:57:41 +01:00
|
|
|
hadflag = false;
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
sprintf (echars, "%c", IS_PRINTABLE (ch)? ch: '.');
|
2013-10-16 02:45:03 +02:00
|
|
|
echars++;
|
2014-08-26 23:52:34 +02:00
|
|
|
if (core->print->cur_enabled && max == here) {
|
2020-05-15 16:23:59 +02:00
|
|
|
if (!html && usecolor) {
|
2015-07-10 00:44:16 +02:00
|
|
|
append (ebytes, Color_RESET);
|
|
|
|
append (echars, Color_RESET);
|
|
|
|
}
|
2015-09-14 12:35:38 +02:00
|
|
|
hascolor = false;
|
2013-10-15 03:56:01 +02:00
|
|
|
}
|
2013-10-16 01:10:27 +02:00
|
|
|
|
2017-12-05 21:13:24 +01:00
|
|
|
if (j < (nb_cols - 1) && (j % 2) && !compact) {
|
2014-08-24 05:35:48 +02:00
|
|
|
append (ebytes, " ");
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2013-10-16 01:10:27 +02:00
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
if (fend != UT64_MAX && fend == addr + j + 1) {
|
2020-05-15 16:23:59 +02:00
|
|
|
if (!html && usecolor) {
|
2013-10-16 02:45:03 +02:00
|
|
|
append (ebytes, Color_RESET);
|
|
|
|
append (echars, Color_RESET);
|
|
|
|
}
|
2013-10-15 03:56:01 +02:00
|
|
|
fend = UT64_MAX;
|
2015-09-14 12:35:38 +02:00
|
|
|
hascolor = false;
|
2013-10-15 03:56:01 +02:00
|
|
|
}
|
|
|
|
}
|
2020-05-15 16:23:59 +02:00
|
|
|
if (!html && usecolor) {
|
2015-07-10 00:44:16 +02:00
|
|
|
append (ebytes, Color_RESET);
|
|
|
|
append (echars, Color_RESET);
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
append (ebytes, (col == 1)? "| ": (col == 2)? " |": " ");
|
|
|
|
if (col == 2) {
|
|
|
|
append (echars, "|");
|
|
|
|
}
|
2014-08-26 23:52:34 +02:00
|
|
|
|
|
|
|
if (marks) { // show comments and flags
|
2014-09-08 01:59:28 +02:00
|
|
|
int hasline = 0;
|
2017-03-09 23:29:48 +01:00
|
|
|
int out_sz = nb_cons_cols + 20;
|
2018-12-11 01:57:41 +01:00
|
|
|
char *out = calloc (out_sz, sizeof (char));
|
2017-03-09 23:29:48 +01:00
|
|
|
memset (out, ' ', nb_cons_cols - 1);
|
|
|
|
for (j = 0; j < nb_cols; j++) {
|
2013-10-15 03:56:01 +02:00
|
|
|
if (note[j]) {
|
2017-03-09 23:29:48 +01:00
|
|
|
int off = (j * 3) - (j / 2) + 13;
|
2014-09-24 23:59:36 +02:00
|
|
|
int notej_len = strlen (note[j]);
|
2017-03-09 23:29:48 +01:00
|
|
|
int sz = R_MIN (notej_len, nb_cons_cols - off);
|
2019-01-10 19:10:09 +01:00
|
|
|
if (compact) {
|
|
|
|
off -= (j/2);
|
|
|
|
} else {
|
|
|
|
if (j % 2) {
|
|
|
|
off--;
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
memcpy (out + off, note[j], sz);
|
2014-09-24 23:59:36 +02:00
|
|
|
if (sz < notej_len) {
|
2017-03-09 23:29:48 +01:00
|
|
|
out[off + sz - 2] = '.';
|
|
|
|
out[off + sz - 1] = '.';
|
2014-09-24 23:59:36 +02:00
|
|
|
}
|
2014-09-08 01:59:28 +02:00
|
|
|
hasline = (out[off] != ' ');
|
2014-09-27 03:48:54 +02:00
|
|
|
R_FREE (note[j]);
|
2013-10-15 03:56:01 +02:00
|
|
|
}
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
out[out_sz - 1] = 0;
|
2014-09-08 01:59:28 +02:00
|
|
|
if (hasline) {
|
2014-09-27 03:48:54 +02:00
|
|
|
r_cons_strcat (addrpad);
|
2014-09-08 01:59:28 +02:00
|
|
|
r_cons_strcat (out);
|
|
|
|
r_cons_newline ();
|
|
|
|
}
|
2015-09-14 12:35:38 +02:00
|
|
|
marks = false;
|
2014-08-26 23:52:34 +02:00
|
|
|
free (out);
|
2013-10-15 03:56:01 +02:00
|
|
|
}
|
|
|
|
r_cons_strcat (bytes);
|
|
|
|
r_cons_strcat (chars);
|
2017-05-23 15:53:58 +02:00
|
|
|
|
|
|
|
if (core->print->use_comments) {
|
|
|
|
for (j = 0; j < nb_cols; j++) {
|
|
|
|
const char *comment = core->print->get_comments (core->print->user, addr + j);
|
|
|
|
if (comment) {
|
|
|
|
r_cons_printf (" ; %s", comment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-15 03:56:01 +02:00
|
|
|
r_cons_newline ();
|
2014-08-24 05:35:48 +02:00
|
|
|
addr += nb_cols;
|
2013-10-15 03:56:01 +02:00
|
|
|
}
|
2017-08-13 05:01:00 -07:00
|
|
|
|
2014-08-26 23:52:34 +02:00
|
|
|
free (bytes);
|
2017-08-13 05:01:00 -07:00
|
|
|
err_bytes:
|
|
|
|
free (note);
|
|
|
|
err_note:
|
2014-08-26 23:52:34 +02:00
|
|
|
free (chars);
|
2017-08-13 05:01:00 -07:00
|
|
|
err_chars:
|
|
|
|
for (i = 0; i < R_ARRAY_SIZE (colors); i++) {
|
|
|
|
free (colors[i]);
|
|
|
|
}
|
2013-10-15 03:56:01 +02:00
|
|
|
}
|
|
|
|
|
2013-10-14 03:30:12 +02:00
|
|
|
R_API void r_core_print_examine(RCore *core, const char *str) {
|
2013-10-14 22:23:05 +02:00
|
|
|
char cmd[128], *p;
|
|
|
|
ut64 addr = core->offset;
|
2017-03-09 23:29:48 +01:00
|
|
|
int size = (core->anal->bits / 4);
|
2013-10-14 03:30:12 +02:00
|
|
|
int count = atoi (str);
|
2013-10-19 23:10:08 +02:00
|
|
|
int i, n;
|
2017-02-28 02:55:00 +01:00
|
|
|
if (count < 1) {
|
|
|
|
count = 1;
|
|
|
|
}
|
|
|
|
// skipspaces
|
2017-03-09 23:29:48 +01:00
|
|
|
while (*str >= '0' && *str <= '9') {
|
2017-02-28 02:55:00 +01:00
|
|
|
str++;
|
|
|
|
}
|
2014-08-25 22:56:47 +02:00
|
|
|
// "px/" alone isn't a full command.
|
2017-02-28 02:55:00 +01:00
|
|
|
if (!str[0]) {
|
|
|
|
return;
|
|
|
|
}
|
2013-10-14 03:30:12 +02:00
|
|
|
#if 0
|
2017-03-09 23:29:48 +01:00
|
|
|
Size letters are b(byte), h (halfword), w (word), g (giant, 8 bytes).
|
2013-10-14 03:30:12 +02:00
|
|
|
#endif
|
|
|
|
switch (str[1]) {
|
|
|
|
case 'b': size = 1; break;
|
|
|
|
case 'h': size = 2; break;
|
2014-10-23 14:06:37 +02:00
|
|
|
case 'd': size = 4; break;
|
2013-10-14 03:30:12 +02:00
|
|
|
case 'w': size = 4; break;
|
|
|
|
case 'g': size = 8; break;
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
if ((p = strchr (str, ' '))) {
|
2017-05-14 22:35:48 +02:00
|
|
|
*p++ = 0;
|
|
|
|
addr = r_num_math (core->num, p);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2013-10-14 03:30:12 +02:00
|
|
|
switch (*str) {
|
|
|
|
case '?':
|
|
|
|
eprintf (
|
2017-03-09 23:29:48 +01:00
|
|
|
"Format is x/[num][format][size]\n"
|
|
|
|
"Num specifies the number of format elements to display\n"
|
|
|
|
"Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n"
|
|
|
|
" t(binary), f(float), a(address), i(instruction), c(char) and s(string),\n"
|
|
|
|
" T(OSType), A(floating point values in hex).\n"
|
|
|
|
"Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).\n"
|
|
|
|
);
|
2013-10-14 03:30:12 +02:00
|
|
|
break;
|
2017-05-15 01:28:28 +02:00
|
|
|
case 's': // "x/s"
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_cmdf (core, "psb %d @ 0x%"PFMT64x, count * size, addr);
|
2013-10-14 03:30:12 +02:00
|
|
|
break;
|
2017-05-15 01:28:28 +02:00
|
|
|
case 'o': // "x/o"
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_cmdf (core, "pxo %d @ 0x%"PFMT64x, count * size, addr);
|
2013-10-14 03:30:12 +02:00
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
case 'A': // XXX (float in hex wtf)
|
2013-10-19 23:10:08 +02:00
|
|
|
n = 3;
|
|
|
|
snprintf (cmd, sizeof (cmd), "pxo %d @ 0x%"PFMT64x,
|
2017-03-09 23:29:48 +01:00
|
|
|
count * size, addr);
|
2013-10-19 23:10:08 +02:00
|
|
|
strcpy (cmd, "pf ");
|
2017-03-09 23:29:48 +01:00
|
|
|
for (i = 0; i < count && n < sizeof (cmd); i++) {
|
2013-10-19 23:10:08 +02:00
|
|
|
cmd[n++] = 'f';
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2013-10-19 23:10:08 +02:00
|
|
|
cmd[n] = 0;
|
|
|
|
r_core_cmd0 (core, cmd);
|
2013-10-14 03:30:12 +02:00
|
|
|
break;
|
2014-10-23 14:06:37 +02:00
|
|
|
case 'x':
|
2017-06-29 11:38:15 -04:00
|
|
|
switch (size) {
|
|
|
|
default:
|
|
|
|
case 1:
|
|
|
|
r_core_cmdf (core, "px %d @ 0x%"PFMT64x, count, addr);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
r_core_cmdf (core, "px%c %d @ 0x%"PFMT64x,
|
|
|
|
'h', count * 2, addr);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
r_core_cmdf (core, "px%c %d @ 0x%"PFMT64x,
|
|
|
|
'w', count * 4, addr);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
r_core_cmdf (core, "px%c %d @ 0x%"PFMT64x,
|
|
|
|
'q', count * 8, addr);
|
|
|
|
break;
|
|
|
|
}
|
2014-10-23 14:06:37 +02:00
|
|
|
break;
|
2013-10-14 03:30:12 +02:00
|
|
|
case 'a':
|
|
|
|
case 'd':
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_cmdf (core, "pxw %d @ 0x%"PFMT64x, count * size, addr);
|
2013-10-14 03:30:12 +02:00
|
|
|
break;
|
|
|
|
case 'i':
|
2014-10-23 14:06:37 +02:00
|
|
|
r_core_cmdf (core, "pid %d @ 0x%"PFMT64x, count, addr);
|
2013-10-14 03:30:12 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-14 14:15:12 +01:00
|
|
|
struct count_pz_t {
|
2019-02-03 16:06:45 +01:00
|
|
|
RSpace *flagspace;
|
2019-01-14 14:15:12 +01:00
|
|
|
ut64 addr;
|
|
|
|
ut64 size;
|
|
|
|
int *ret;
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool count_pzs(RFlagItem *fi, void *u) {
|
|
|
|
struct count_pz_t *user = (struct count_pz_t *)u;
|
|
|
|
if (fi->space == user->flagspace &&
|
|
|
|
((user->addr <= fi->offset && fi->offset < user->addr + user->size) ||
|
|
|
|
(user->addr <= fi->offset + fi->size && fi->offset + fi->size < user->addr + user->size))) {
|
|
|
|
(*user->ret)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
static bool count_pzf(RFlagItem *fi, void *u) {
|
|
|
|
struct count_pz_t *user = (struct count_pz_t *)u;
|
|
|
|
if (fi->offset <= user->addr && user->addr < fi->offset + fi->size) {
|
|
|
|
(*user->ret)++;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-02-27 02:40:27 +01:00
|
|
|
static int printzoomcallback(void *user, int mode, ut64 addr, ut8 *bufz, ut64 size) {
|
|
|
|
RCore *core = (RCore *) user;
|
|
|
|
int j, ret = 0;
|
2019-01-14 14:15:12 +01:00
|
|
|
struct count_pz_t u;
|
2012-02-27 02:40:27 +01:00
|
|
|
|
|
|
|
switch (mode) {
|
2019-05-07 11:59:38 +02:00
|
|
|
case 'a':
|
|
|
|
{
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, 0);
|
|
|
|
int value = 0;
|
|
|
|
if (fcn) {
|
|
|
|
value = r_list_length (fcn->bbs);
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'A':
|
|
|
|
{
|
|
|
|
RCoreAnalStats *as = r_core_anal_get_stats (core, addr, addr + size * 2, size);
|
|
|
|
int i;
|
|
|
|
int value = 0;
|
|
|
|
for (i = 0; i < 1; i++) {
|
|
|
|
value += as->block[i].functions;
|
|
|
|
value += as->block[i].in_functions;
|
|
|
|
value += as->block[i].comments;
|
|
|
|
value += as->block[i].symbols;
|
|
|
|
value += as->block[i].flags;
|
|
|
|
value += as->block[i].strings;
|
|
|
|
value += as->block[i].blocks;
|
|
|
|
value *= 20;
|
|
|
|
}
|
|
|
|
r_core_anal_stats_free (as);
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case '0': // "pz0"
|
2016-10-27 15:31:46 +02:00
|
|
|
for (j = 0; j < size; j++) {
|
2018-08-05 16:19:52 -07:00
|
|
|
if (bufz[j] == 0) {
|
2012-02-27 02:40:27 +01:00
|
|
|
ret++;
|
2016-10-27 15:31:46 +02:00
|
|
|
}
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case 'e': // "pze"
|
|
|
|
ret = (ut8) (r_hash_entropy_fraction (bufz, size) * 255);
|
|
|
|
break;
|
|
|
|
case 'f': // "pzf"
|
2019-01-14 14:15:12 +01:00
|
|
|
u.addr = addr;
|
|
|
|
u.ret = &ret;
|
|
|
|
r_flag_foreach (core->flags, count_pzf, &u);
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case 'F': // "pzF"
|
|
|
|
for (j = 0; j < size; j++) {
|
|
|
|
if (bufz[j] == 0xff) {
|
2012-02-27 02:40:27 +01:00
|
|
|
ret++;
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case 'p': // "pzp"
|
2017-03-09 23:29:48 +01:00
|
|
|
for (j = 0; j < size; j++) {
|
2018-08-05 16:19:52 -07:00
|
|
|
if (IS_PRINTABLE (bufz[j])) {
|
2012-02-27 02:40:27 +01:00
|
|
|
ret++;
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case 's': // "pzs"
|
2019-02-23 01:31:06 +01:00
|
|
|
u.flagspace = r_flag_space_get (core->flags, R_FLAGS_FS_STRINGS);
|
2019-01-14 14:15:12 +01:00
|
|
|
u.addr = addr;
|
|
|
|
u.size = size;
|
|
|
|
u.ret = &ret;
|
|
|
|
r_flag_foreach (core->flags, count_pzs, &u);
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case 'h': // "pzh" head
|
2012-02-27 02:40:27 +01:00
|
|
|
default:
|
|
|
|
ret = *bufz;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2012-08-13 04:33:01 +02:00
|
|
|
|
|
|
|
R_API void r_core_print_cmp(RCore *core, ut64 from, ut64 to) {
|
|
|
|
long int delta = 0;
|
2016-08-25 20:17:55 +02:00
|
|
|
int col = core->cons->columns > 123;
|
2012-08-13 04:33:01 +02:00
|
|
|
ut8 *b = malloc (core->blocksize);
|
|
|
|
ut64 addr = core->offset;
|
|
|
|
memset (b, 0xff, core->blocksize);
|
|
|
|
delta = addr - from;
|
2018-05-21 23:06:00 +02:00
|
|
|
r_io_read_at (core->io, to + delta, b, core->blocksize);
|
2013-10-04 13:57:49 +02:00
|
|
|
r_print_hexdiff (core->print, core->offset, core->block,
|
2016-08-25 20:17:55 +02:00
|
|
|
to + delta, b, core->blocksize, col);
|
2012-08-13 04:33:01 +02:00
|
|
|
free (b);
|
|
|
|
}
|
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
static void cmd_print_pwn(const RCore *core) {
|
2015-06-28 01:42:21 +02:00
|
|
|
r_cons_printf ("easter egg license has expired\n");
|
2014-08-06 22:55:30 +02:00
|
|
|
}
|
|
|
|
|
2019-04-29 12:51:13 +03:00
|
|
|
static int cmd_print_pxA(RCore *core, int len, const char *input) {
|
2019-01-18 11:58:49 +01:00
|
|
|
RConsPrintablePalette *pal = &core->cons->context->pal;
|
2015-09-14 12:35:38 +02:00
|
|
|
int show_offset = true;
|
2015-03-21 00:27:49 +01:00
|
|
|
int cols = r_config_get_i (core->config, "hex.cols");
|
2015-03-21 03:06:31 +01:00
|
|
|
int show_color = r_config_get_i (core->config, "scr.color");
|
2015-03-22 16:16:51 +01:00
|
|
|
int onechar = r_config_get_i (core->config, "hex.onechar");
|
2020-09-09 15:50:37 +02:00
|
|
|
bool hex_offset = r_config_get_i (core->config, "hex.offset");
|
2015-09-14 12:35:38 +02:00
|
|
|
int bgcolor_in_heap = false;
|
2016-02-07 17:06:39 +01:00
|
|
|
bool show_cursor = core->print->cur_enabled;
|
2015-04-18 23:11:47 +03:00
|
|
|
char buf[2];
|
2015-03-22 16:16:51 +01:00
|
|
|
char *bgcolor, *fgcolor, *text;
|
2015-03-21 01:27:54 +01:00
|
|
|
ut64 i, c, oi;
|
2015-03-21 00:27:49 +01:00
|
|
|
RAnalOp op;
|
2019-04-29 12:51:13 +03:00
|
|
|
ut8 *data;
|
|
|
|
int datalen;
|
|
|
|
if (*input == 'v') {
|
|
|
|
datalen = cols * 8 * core->cons->rows;
|
|
|
|
data = malloc (datalen);
|
|
|
|
r_io_read_at (core->io, core->offset, data, datalen);
|
|
|
|
len = datalen;
|
|
|
|
} else {
|
|
|
|
data = core->block;
|
|
|
|
datalen = core->blocksize;
|
|
|
|
}
|
|
|
|
if (len < 1) {
|
|
|
|
len = datalen;
|
|
|
|
}
|
|
|
|
if (len < 0 || len > datalen) {
|
2015-03-21 00:27:49 +01:00
|
|
|
eprintf ("Invalid length\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2015-03-22 16:16:51 +01:00
|
|
|
if (onechar) {
|
|
|
|
cols *= 4;
|
|
|
|
} else {
|
|
|
|
cols *= 2;
|
|
|
|
}
|
2015-04-09 00:03:46 +02:00
|
|
|
if (show_offset) {
|
|
|
|
char offstr[128];
|
2017-05-29 04:36:34 +02:00
|
|
|
snprintf (offstr, sizeof (offstr),
|
2017-03-09 23:29:48 +01:00
|
|
|
"0x%08"PFMT64x " ", core->offset);
|
|
|
|
if (strlen (offstr) > 12) {
|
|
|
|
cols -= ((strlen (offstr) - 12) * 2);
|
|
|
|
}
|
2015-04-09 00:03:46 +02:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
for (oi = i = c = 0; i < len; c++) {
|
2015-04-11 01:29:28 +03:00
|
|
|
if (i && (cols != 0) && !(c % cols)) {
|
2015-09-14 12:35:38 +02:00
|
|
|
show_offset = true;
|
2020-10-16 13:34:26 +08:00
|
|
|
r_cons_printf (" %" PFMT64u "\n", i - oi);
|
2015-03-21 00:27:49 +01:00
|
|
|
oi = i;
|
|
|
|
}
|
2020-09-09 15:50:37 +02:00
|
|
|
if (show_offset && hex_offset) {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("0x%08"PFMT64x " ", core->offset + i);
|
2015-09-14 12:35:38 +02:00
|
|
|
show_offset = false;
|
2015-03-21 00:27:49 +01:00
|
|
|
}
|
2015-03-22 16:16:51 +01:00
|
|
|
if (bgcolor_in_heap) {
|
|
|
|
free (bgcolor);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = false;
|
2015-03-22 16:16:51 +01:00
|
|
|
}
|
2015-03-21 03:06:31 +01:00
|
|
|
bgcolor = Color_BGBLACK;
|
|
|
|
fgcolor = Color_WHITE;
|
|
|
|
text = NULL;
|
2019-04-29 12:51:13 +03:00
|
|
|
if (r_anal_op (core->anal, &op, core->offset + i, data + i, len - i, R_ANAL_OP_MASK_BASIC) <= 0) {
|
2015-03-21 00:27:49 +01:00
|
|
|
op.type = 0;
|
|
|
|
bgcolor = Color_BGRED;
|
|
|
|
op.size = 1;
|
|
|
|
}
|
|
|
|
switch (op.type) {
|
2015-03-21 03:06:31 +01:00
|
|
|
case R_ANAL_OP_TYPE_LEA:
|
2015-03-21 00:27:49 +01:00
|
|
|
case R_ANAL_OP_TYPE_MOV:
|
2015-03-24 00:08:48 +01:00
|
|
|
case R_ANAL_OP_TYPE_CAST:
|
|
|
|
case R_ANAL_OP_TYPE_LENGTH:
|
2015-03-21 00:27:49 +01:00
|
|
|
case R_ANAL_OP_TYPE_CMOV:
|
2015-04-09 00:03:46 +02:00
|
|
|
text = "mv";
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = pal->mov;
|
2015-04-09 00:03:46 +02:00
|
|
|
fgcolor = Color_YELLOW;
|
2015-03-21 00:27:49 +01:00
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_PUSH:
|
2015-03-21 03:06:31 +01:00
|
|
|
case R_ANAL_OP_TYPE_UPUSH:
|
2019-05-15 15:34:41 +05:30
|
|
|
case R_ANAL_OP_TYPE_RPUSH:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = pal->push;
|
|
|
|
fgcolor = Color_WHITE;
|
|
|
|
text = "->";
|
2015-03-21 00:27:49 +01:00
|
|
|
break;
|
2015-04-09 00:03:46 +02:00
|
|
|
case R_ANAL_OP_TYPE_IO:
|
|
|
|
bgcolor = pal->swi;
|
|
|
|
fgcolor = Color_WHITE;
|
|
|
|
text = "io";
|
|
|
|
break;
|
2015-03-21 00:27:49 +01:00
|
|
|
case R_ANAL_OP_TYPE_TRAP:
|
|
|
|
case R_ANAL_OP_TYPE_SWI:
|
2015-03-24 00:08:48 +01:00
|
|
|
case R_ANAL_OP_TYPE_NEW:
|
2017-03-09 23:29:48 +01:00
|
|
|
// bgcolor = Color_BGRED;
|
|
|
|
bgcolor = pal->trap; // r_cons_swap_ground (pal->trap);
|
2015-03-22 16:16:51 +01:00
|
|
|
fgcolor = Color_WHITE;
|
2015-04-09 00:03:46 +02:00
|
|
|
text = "$$";
|
2015-03-21 00:27:49 +01:00
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_POP:
|
2015-03-21 03:06:31 +01:00
|
|
|
text = "<-";
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->pop);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-03-22 16:16:51 +01:00
|
|
|
fgcolor = Color_WHITE;
|
2015-03-21 00:27:49 +01:00
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_NOP:
|
|
|
|
fgcolor = Color_WHITE;
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->nop);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-03-21 03:06:31 +01:00
|
|
|
text = "..";
|
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_MUL:
|
2015-04-09 00:03:46 +02:00
|
|
|
fgcolor = Color_BLACK;
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->math);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-03-21 03:06:31 +01:00
|
|
|
text = "_*";
|
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_DIV:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->math);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-04-09 00:03:46 +02:00
|
|
|
fgcolor = Color_BLACK;
|
2015-03-21 03:06:31 +01:00
|
|
|
text = "_/";
|
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_AND:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->bin);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-04-09 00:03:46 +02:00
|
|
|
fgcolor = Color_BLACK;
|
2015-03-21 03:06:31 +01:00
|
|
|
text = "_&";
|
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_XOR:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->bin);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-04-09 00:03:46 +02:00
|
|
|
fgcolor = Color_BLACK;
|
2015-03-21 03:06:31 +01:00
|
|
|
text = "_^";
|
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_OR:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->bin);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-04-09 00:03:46 +02:00
|
|
|
fgcolor = Color_BLACK;
|
2015-03-21 03:06:31 +01:00
|
|
|
text = "_|";
|
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_SHR:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->bin);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-04-09 00:03:46 +02:00
|
|
|
fgcolor = Color_BLACK;
|
2015-03-21 03:06:31 +01:00
|
|
|
text = ">>";
|
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_SHL:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->bin);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-04-09 00:03:46 +02:00
|
|
|
fgcolor = Color_BLACK;
|
2015-03-21 03:06:31 +01:00
|
|
|
text = "<<";
|
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_SUB:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->math);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-04-09 00:03:46 +02:00
|
|
|
fgcolor = Color_WHITE;
|
2015-03-21 03:06:31 +01:00
|
|
|
text = "--";
|
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_ADD:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->math);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-04-09 00:03:46 +02:00
|
|
|
fgcolor = Color_WHITE;
|
2015-03-21 03:06:31 +01:00
|
|
|
text = "++";
|
2015-03-21 00:27:49 +01:00
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_JMP:
|
|
|
|
case R_ANAL_OP_TYPE_UJMP:
|
2016-09-22 13:42:06 +02:00
|
|
|
case R_ANAL_OP_TYPE_IJMP:
|
|
|
|
case R_ANAL_OP_TYPE_RJMP:
|
|
|
|
case R_ANAL_OP_TYPE_IRJMP:
|
2016-05-30 00:38:35 +02:00
|
|
|
case R_ANAL_OP_TYPE_MJMP:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->jmp);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-03-21 03:06:31 +01:00
|
|
|
fgcolor = Color_BLACK;
|
|
|
|
text = "_J";
|
|
|
|
break;
|
2015-03-21 00:27:49 +01:00
|
|
|
case R_ANAL_OP_TYPE_CJMP:
|
|
|
|
case R_ANAL_OP_TYPE_UCJMP:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->cjmp);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-03-21 03:06:31 +01:00
|
|
|
fgcolor = Color_BLACK;
|
|
|
|
text = "cJ";
|
|
|
|
break;
|
2015-03-21 00:27:49 +01:00
|
|
|
case R_ANAL_OP_TYPE_CALL:
|
|
|
|
case R_ANAL_OP_TYPE_UCALL:
|
2016-09-22 13:42:06 +02:00
|
|
|
case R_ANAL_OP_TYPE_ICALL:
|
|
|
|
case R_ANAL_OP_TYPE_RCALL:
|
|
|
|
case R_ANAL_OP_TYPE_IRCALL:
|
2015-03-21 00:27:49 +01:00
|
|
|
case R_ANAL_OP_TYPE_UCCALL:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->call);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-04-09 00:03:46 +02:00
|
|
|
fgcolor = Color_WHITE;
|
2015-03-21 03:06:31 +01:00
|
|
|
text = "_C";
|
|
|
|
break;
|
2015-04-09 00:03:46 +02:00
|
|
|
case R_ANAL_OP_TYPE_ACMP:
|
2015-03-21 03:06:31 +01:00
|
|
|
case R_ANAL_OP_TYPE_CMP:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->cmp);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-03-21 03:06:31 +01:00
|
|
|
fgcolor = Color_BLACK;
|
|
|
|
text = "==";
|
2015-03-21 00:27:49 +01:00
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_RET:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->ret);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-03-21 00:27:49 +01:00
|
|
|
fgcolor = Color_WHITE;
|
2015-03-21 03:06:31 +01:00
|
|
|
text = "_R";
|
2015-03-21 00:27:49 +01:00
|
|
|
break;
|
|
|
|
case -1:
|
|
|
|
case R_ANAL_OP_TYPE_ILL:
|
|
|
|
case R_ANAL_OP_TYPE_UNK:
|
2015-03-22 16:16:51 +01:00
|
|
|
bgcolor = r_cons_swap_ground (pal->invalid);
|
2015-09-14 12:35:38 +02:00
|
|
|
bgcolor_in_heap = true;
|
2015-03-21 00:27:49 +01:00
|
|
|
fgcolor = Color_WHITE;
|
2015-04-09 00:03:46 +02:00
|
|
|
text = "XX";
|
2015-03-21 00:27:49 +01:00
|
|
|
break;
|
|
|
|
#if 0
|
|
|
|
default:
|
|
|
|
color = Color_BGCYAN;
|
|
|
|
fgcolor = Color_BLACK;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
}
|
2015-04-09 00:03:46 +02:00
|
|
|
int opsz = R_MAX (op.size, 1);
|
2015-03-21 03:06:31 +01:00
|
|
|
if (show_cursor) {
|
2017-03-09 23:29:48 +01:00
|
|
|
if (core->print->cur >= i && core->print->cur < i + opsz) {
|
2015-03-21 03:06:31 +01:00
|
|
|
r_cons_invert (1, 1);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2015-03-21 03:06:31 +01:00
|
|
|
}
|
2015-03-22 16:16:51 +01:00
|
|
|
if (onechar) {
|
|
|
|
if (text) {
|
2017-03-09 23:29:48 +01:00
|
|
|
if (text[0] == '_' || text[0] == '.') {
|
2015-03-22 16:16:51 +01:00
|
|
|
buf[0] = text[1];
|
2017-03-09 23:29:48 +01:00
|
|
|
} else {
|
|
|
|
buf[0] = text[0];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
buf[0] = '.';
|
|
|
|
}
|
2015-03-22 16:16:51 +01:00
|
|
|
buf[1] = 0;
|
|
|
|
text = buf;
|
|
|
|
}
|
2015-03-21 03:06:31 +01:00
|
|
|
if (show_color) {
|
2017-03-09 23:29:48 +01:00
|
|
|
if (!text) {
|
|
|
|
text = " ";
|
|
|
|
}
|
2015-04-11 13:46:33 +03:00
|
|
|
r_cons_printf ("%s%s%s\x1b[0m", bgcolor, fgcolor, text);
|
2015-03-21 03:06:31 +01:00
|
|
|
} else {
|
2016-06-26 00:51:17 -04:00
|
|
|
if (text) {
|
|
|
|
r_cons_print (text);
|
|
|
|
} else {
|
|
|
|
r_cons_print (" ");
|
|
|
|
}
|
2015-03-21 03:06:31 +01:00
|
|
|
}
|
2015-03-22 16:16:51 +01:00
|
|
|
if (show_cursor) {
|
2017-03-09 23:29:48 +01:00
|
|
|
if (core->print->cur >= i && core->print->cur < i + opsz) {
|
2015-03-22 16:16:51 +01:00
|
|
|
r_cons_invert (0, 1);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2015-03-22 16:16:51 +01:00
|
|
|
}
|
|
|
|
i += opsz;
|
2017-08-13 05:01:00 -07:00
|
|
|
r_anal_op_fini (&op);
|
2015-03-21 00:27:49 +01:00
|
|
|
}
|
2020-10-13 16:26:15 +02:00
|
|
|
r_cons_printf (" %" PFMT64d "\n", i - oi);
|
2017-03-09 23:29:48 +01:00
|
|
|
if (bgcolor_in_heap) {
|
|
|
|
free (bgcolor);
|
|
|
|
}
|
2019-04-29 12:51:13 +03:00
|
|
|
if (data != core->block) {
|
|
|
|
free (data);
|
|
|
|
}
|
2015-04-11 13:46:33 +03:00
|
|
|
|
2015-09-14 12:35:38 +02:00
|
|
|
return true;
|
2015-03-21 00:27:49 +01:00
|
|
|
}
|
2014-08-06 22:55:30 +02:00
|
|
|
|
2019-08-31 14:46:07 +00:00
|
|
|
static void cmd_print_op(RCore *core, const char *input) {
|
|
|
|
ut8 *buf;
|
|
|
|
if (!input[0])
|
|
|
|
return;
|
|
|
|
switch (input[1]) {
|
|
|
|
case 'a':
|
|
|
|
case 's':
|
|
|
|
case 'A':
|
|
|
|
case 'x':
|
|
|
|
case 'r':
|
|
|
|
case 'l':
|
|
|
|
case 'm':
|
|
|
|
case 'd':
|
|
|
|
case 'o':
|
|
|
|
case '2':
|
|
|
|
case '4':
|
|
|
|
if (input[2]) { // parse val from arg
|
|
|
|
buf = r_core_transform_op (core, input+3, input[1]);
|
|
|
|
} else { // use clipboard instead of val
|
|
|
|
buf = r_core_transform_op (core, NULL, input[1]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
buf = r_core_transform_op (core, "ff", 'x');
|
|
|
|
break;
|
|
|
|
case '\0':
|
|
|
|
case '?':
|
|
|
|
default:
|
|
|
|
r_core_cmd_help (core, help_msg_po);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (buf) {
|
|
|
|
r_print_hexdump(core->print, core->offset, buf,
|
|
|
|
core->blocksize, 16, 1, 1);
|
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
static void printraw(RCore *core, int len, int mode) {
|
2015-03-23 01:09:35 +01:00
|
|
|
int obsz = core->blocksize;
|
|
|
|
int restore_obsz = 0;
|
|
|
|
if (len != obsz) {
|
2016-09-23 13:23:32 +02:00
|
|
|
if (!r_core_block_size (core, len)) {
|
2015-03-23 01:09:35 +01:00
|
|
|
len = core->blocksize;
|
2016-09-23 13:23:32 +02:00
|
|
|
} else {
|
|
|
|
restore_obsz = 1;
|
|
|
|
}
|
2015-03-23 01:09:35 +01:00
|
|
|
}
|
|
|
|
r_print_raw (core->print, core->offset, core->block, len, mode);
|
|
|
|
if (restore_obsz) {
|
2017-03-09 23:29:48 +01:00
|
|
|
(void) r_core_block_size (core, obsz);
|
2015-03-23 01:09:35 +01:00
|
|
|
}
|
2019-05-01 02:02:26 +08:00
|
|
|
core->cons->newline = core->cmd_in_backticks ? false : true;
|
2015-03-23 01:09:35 +01:00
|
|
|
}
|
2015-12-21 15:53:53 +01:00
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
static void _handle_call(RCore *core, char *line, char **str) {
|
2020-05-15 16:23:59 +02:00
|
|
|
r_return_if_fail (core && line && str && core->rasm && core->rasm->cur);
|
2020-05-13 01:28:23 +02:00
|
|
|
if (strstr (core->rasm->cur->arch, "x86")) {
|
2017-03-09 23:29:48 +01:00
|
|
|
*str = strstr (line, "call ");
|
2020-05-13 01:28:23 +02:00
|
|
|
} else if (strstr (core->rasm->cur->arch, "arm")) {
|
2016-09-23 13:23:32 +02:00
|
|
|
*str = strstr (line, " b ");
|
2016-10-29 12:33:58 +02:00
|
|
|
if (*str && strstr (*str, " 0x")) {
|
|
|
|
/*
|
2017-03-09 23:29:48 +01:00
|
|
|
* avoid treating branches to
|
|
|
|
* non-symbols as calls
|
|
|
|
*/
|
2016-10-29 12:33:58 +02:00
|
|
|
*str = NULL;
|
|
|
|
}
|
2016-09-23 13:23:32 +02:00
|
|
|
if (!*str) {
|
|
|
|
*str = strstr (line, "bl ");
|
|
|
|
}
|
|
|
|
if (!*str) {
|
|
|
|
*str = strstr (line, "bx ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-21 15:53:53 +01:00
|
|
|
// TODO: this is just a PoC, the disasm loop should be rewritten
|
2016-10-24 14:31:03 +02:00
|
|
|
// TODO: this is based on string matching, it should be written upon RAnalOp to know
|
2016-09-23 13:23:32 +02:00
|
|
|
// when we have a call and such
|
2016-03-23 01:13:16 +01:00
|
|
|
static void disasm_strings(RCore *core, const char *input, RAnalFunction *fcn) {
|
2015-12-21 15:53:53 +01:00
|
|
|
const char *linecolor = NULL;
|
2015-12-31 16:28:16 +01:00
|
|
|
char *ox, *qo, *string = NULL;
|
2016-09-23 13:23:32 +02:00
|
|
|
char *line, *s, *str, *string2 = NULL;
|
2019-04-07 08:58:50 +01:00
|
|
|
char *switchcmp = NULL;
|
2016-09-23 13:23:32 +02:00
|
|
|
int i, count, use_color = r_config_get_i (core->config, "scr.color");
|
2017-05-29 23:15:24 +02:00
|
|
|
bool show_comments = r_config_get_i (core->config, "asm.comments");
|
2017-11-30 00:14:08 +01:00
|
|
|
bool show_offset = r_config_get_i (core->config, "asm.offset");
|
2017-11-30 00:17:01 +01:00
|
|
|
bool asm_tabs = r_config_get_i (core->config, "asm.tabs");
|
2020-05-15 16:23:59 +02:00
|
|
|
bool scr_html = r_config_get_i (core->config, "scr.html");
|
2019-06-16 22:58:48 +02:00
|
|
|
bool asm_dwarf = r_config_get_i (core->config, "asm.dwarf");
|
2017-11-30 01:23:59 +01:00
|
|
|
bool asm_flags = r_config_get_i (core->config, "asm.flags");
|
2018-02-22 17:59:08 +01:00
|
|
|
bool asm_cmt_right = r_config_get_i (core->config, "asm.cmt.right");
|
2018-03-05 02:32:07 +05:30
|
|
|
bool asm_emu = r_config_get_i (core->config, "asm.emu");
|
2018-04-14 12:54:19 +08:00
|
|
|
bool emu_str = r_config_get_i (core->config, "emu.str");
|
|
|
|
r_config_set_i (core->config, "emu.str", true);
|
2019-01-18 11:58:49 +01:00
|
|
|
RConsPrintablePalette *pal = &core->cons->context->pal;
|
2017-11-30 00:14:08 +01:00
|
|
|
// force defaults
|
|
|
|
r_config_set_i (core->config, "asm.offset", true);
|
2019-06-16 22:58:48 +02:00
|
|
|
r_config_set_i (core->config, "asm.dwarf", true);
|
2018-02-24 12:04:43 +01:00
|
|
|
r_config_set_i (core->config, "scr.color", COLOR_MODE_DISABLED);
|
2017-11-30 00:17:01 +01:00
|
|
|
r_config_set_i (core->config, "asm.tabs", 0);
|
2020-05-15 16:23:59 +02:00
|
|
|
r_config_set_i (core->config, "scr.html", 0);
|
2018-02-22 17:59:08 +01:00
|
|
|
r_config_set_i (core->config, "asm.cmt.right", true);
|
2020-05-15 16:23:59 +02:00
|
|
|
|
|
|
|
r_cons_push ();
|
2019-06-16 22:58:48 +02:00
|
|
|
line = NULL;
|
2018-04-05 09:30:47 +02:00
|
|
|
s = NULL;
|
|
|
|
if (!strncmp (input, "dsb", 3)) {
|
|
|
|
RAnalBlock *bb = r_anal_bb_from_offset (core->anal, core->offset);
|
|
|
|
if (bb) {
|
2020-01-15 10:54:37 +01:00
|
|
|
line = s = r_core_cmd_strf (core, "pD %"PFMT64u" @ 0x%08"PFMT64x, bb->size, bb->addr);
|
2018-04-05 09:30:47 +02:00
|
|
|
}
|
|
|
|
} else if (!strncmp (input, "dsf", 3) || !strncmp (input, "dsr", 3)) {
|
2015-12-21 15:53:53 +01:00
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_NULL);
|
|
|
|
if (fcn) {
|
2016-10-29 12:33:58 +02:00
|
|
|
line = s = r_core_cmd_str (core, "pdr");
|
2015-12-21 15:53:53 +01:00
|
|
|
} else {
|
|
|
|
eprintf ("Cannot find function.\n");
|
2016-10-29 12:33:58 +02:00
|
|
|
r_config_set_i (core->config, "scr.color", use_color);
|
2018-02-22 17:59:08 +01:00
|
|
|
r_config_set_i (core->config, "asm.cmt.right", asm_cmt_right);
|
2018-02-20 00:57:42 +01:00
|
|
|
goto restore_conf;
|
2015-12-21 15:53:53 +01:00
|
|
|
}
|
2016-03-23 01:18:27 +01:00
|
|
|
} else if (!strncmp (input, "ds ", 3)) {
|
2018-04-05 09:30:47 +02:00
|
|
|
line = s = r_core_cmd_strf (core, "pD %s", input + 3);
|
2015-12-21 15:53:53 +01:00
|
|
|
} else {
|
|
|
|
line = s = r_core_cmd_str (core, "pd");
|
|
|
|
}
|
2020-05-15 16:23:59 +02:00
|
|
|
r_cons_pop ();
|
|
|
|
|
|
|
|
r_config_set_i (core->config, "scr.html", scr_html);
|
2016-10-29 12:33:58 +02:00
|
|
|
r_config_set_i (core->config, "scr.color", use_color);
|
2018-02-22 17:59:08 +01:00
|
|
|
r_config_set_i (core->config, "asm.cmt.right", asm_cmt_right);
|
2015-12-21 15:53:53 +01:00
|
|
|
count = r_str_split (s, '\n');
|
2016-09-23 13:23:32 +02:00
|
|
|
if (!line || !*line || count < 1) {
|
2018-04-05 09:30:47 +02:00
|
|
|
// R_FREE (s);
|
2018-02-20 00:57:42 +01:00
|
|
|
goto restore_conf;
|
2015-12-21 15:53:53 +01:00
|
|
|
}
|
2016-08-31 03:17:51 +02:00
|
|
|
for (i = 0; i < count; i++) {
|
2015-12-21 15:53:53 +01:00
|
|
|
ut64 addr = UT64_MAX;
|
|
|
|
ox = strstr (line, "0x");
|
2019-12-15 21:05:42 +03:00
|
|
|
qo = strchr (line, '\"');
|
2015-12-31 16:28:16 +01:00
|
|
|
R_FREE (string);
|
2015-12-21 15:53:53 +01:00
|
|
|
if (ox) {
|
|
|
|
addr = r_num_get (NULL, ox);
|
|
|
|
}
|
|
|
|
if (qo) {
|
2017-06-30 23:45:47 +08:00
|
|
|
char *qoe = strrchr (qo + 1, '"');
|
2015-12-21 15:53:53 +01:00
|
|
|
if (qoe) {
|
2017-06-30 23:45:47 +08:00
|
|
|
int raw_len = qoe - qo - 1;
|
|
|
|
int actual_len = 0;
|
|
|
|
char *ptr = qo + 1;
|
|
|
|
for(; ptr < qoe; ptr++) {
|
|
|
|
if (*ptr == '\\' && ptr + 1 < qoe) {
|
2017-07-02 15:46:59 +08:00
|
|
|
int i, body_len;
|
2017-06-30 23:45:47 +08:00
|
|
|
switch (*(ptr + 1)) {
|
|
|
|
case 'x':
|
2017-07-02 15:46:59 +08:00
|
|
|
body_len = 3;
|
2017-06-30 23:45:47 +08:00
|
|
|
break;
|
|
|
|
case 'u':
|
2017-07-02 15:46:59 +08:00
|
|
|
body_len = 5;
|
|
|
|
break;
|
|
|
|
case 'U':
|
|
|
|
body_len = 9;
|
2017-06-30 23:45:47 +08:00
|
|
|
break;
|
|
|
|
default:
|
2017-07-02 15:46:59 +08:00
|
|
|
body_len = 1;
|
|
|
|
}
|
|
|
|
for (i = 0; i < body_len && ptr < qoe; i++) {
|
2017-06-30 23:45:47 +08:00
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
actual_len++;
|
|
|
|
}
|
|
|
|
if (actual_len > 2) {
|
|
|
|
string = r_str_ndup (qo, raw_len + 2);
|
2015-12-21 15:53:53 +01:00
|
|
|
}
|
2017-03-08 14:34:19 +03:00
|
|
|
linecolor = R_CONS_COLOR (comment);
|
2015-12-21 15:53:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ox = strstr (line, "; 0x");
|
2016-09-23 13:23:32 +02:00
|
|
|
if (!ox) {
|
|
|
|
ox = strstr (line, "@ 0x");
|
|
|
|
}
|
2015-12-21 15:53:53 +01:00
|
|
|
if (ox) {
|
2016-09-23 13:23:32 +02:00
|
|
|
char *qoe = strchr (ox + 3, ' ');
|
|
|
|
if (!qoe) {
|
|
|
|
qoe = strchr (ox + 3, '\x1b');
|
|
|
|
}
|
|
|
|
int len = qoe? qoe - ox: strlen (ox + 3);
|
|
|
|
string2 = r_str_ndup (ox + 2, len - 1);
|
2015-12-21 15:53:53 +01:00
|
|
|
if (r_num_get (NULL, string2) < 0x100) {
|
|
|
|
R_FREE (string2);
|
|
|
|
}
|
|
|
|
}
|
2017-11-30 01:23:59 +01:00
|
|
|
if (asm_flags) {
|
|
|
|
str = strstr (line, ";-- ");
|
|
|
|
if (str) {
|
2019-04-07 08:58:50 +01:00
|
|
|
if (!r_str_startswith (str + 4, "case")) {
|
|
|
|
r_cons_printf ("%s\n", str);
|
|
|
|
}
|
2017-11-30 01:23:59 +01:00
|
|
|
}
|
|
|
|
}
|
2018-12-12 22:02:06 +01:00
|
|
|
#define USE_PREFIXES 1
|
|
|
|
#if USE_PREFIXES
|
2017-03-09 23:29:48 +01:00
|
|
|
// XXX leak
|
2018-12-12 22:02:06 +01:00
|
|
|
str = strstr (line, " obj.");
|
|
|
|
if (!str) {
|
|
|
|
str = strstr (line, " str.");
|
|
|
|
if (!str) {
|
|
|
|
str = strstr (line, " imp.");
|
|
|
|
if (!str) {
|
|
|
|
str = strstr (line, " fcn.");
|
|
|
|
if (!str) {
|
|
|
|
str = strstr (line, " sub.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (strchr (line, ';')) {
|
|
|
|
const char *dot = r_str_rchr (line, NULL, '.');
|
|
|
|
if (dot) {
|
|
|
|
const char *o = r_str_rchr (line, dot, ' ');
|
|
|
|
if (o) {
|
|
|
|
str = (char*)o;
|
|
|
|
} else {
|
|
|
|
eprintf ("Warning: missing summary reference: %s\n", dot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2015-12-21 15:53:53 +01:00
|
|
|
if (str) {
|
2017-08-29 15:50:46 +02:00
|
|
|
str = strdup (str);
|
2015-12-21 15:53:53 +01:00
|
|
|
char *qoe = NULL;
|
2016-09-23 13:23:32 +02:00
|
|
|
if (!qoe) {
|
|
|
|
qoe = strchr (str + 1, '\x1b');
|
|
|
|
}
|
|
|
|
if (!qoe) {
|
|
|
|
qoe = strchr (str + 1, ';');
|
|
|
|
}
|
|
|
|
if (!qoe) {
|
|
|
|
qoe = strchr (str + 1, ' ');
|
|
|
|
}
|
2015-12-21 15:53:53 +01:00
|
|
|
if (qoe) {
|
2017-08-29 12:39:49 +02:00
|
|
|
free (string2);
|
2016-09-23 13:23:32 +02:00
|
|
|
string2 = r_str_ndup (str + 1, qoe - str - 1);
|
2015-12-21 15:53:53 +01:00
|
|
|
} else {
|
2017-08-29 12:39:49 +02:00
|
|
|
free (string2);
|
2016-09-23 13:23:32 +02:00
|
|
|
string2 = strdup (str + 1);
|
2015-12-21 15:53:53 +01:00
|
|
|
}
|
2017-03-20 15:27:23 +01:00
|
|
|
if (string2) {
|
2017-08-29 12:39:49 +02:00
|
|
|
R_FREE (string);
|
2015-12-21 15:53:53 +01:00
|
|
|
string = string2;
|
|
|
|
string2 = NULL;
|
|
|
|
}
|
|
|
|
}
|
2017-08-29 12:39:49 +02:00
|
|
|
R_FREE (string2);
|
2016-09-23 13:23:32 +02:00
|
|
|
_handle_call (core, line, &str);
|
2016-08-31 03:17:51 +02:00
|
|
|
if (!str) {
|
2017-08-29 15:50:46 +02:00
|
|
|
str = strstr (line, "sym.");
|
2016-09-23 13:23:32 +02:00
|
|
|
if (!str) {
|
2017-08-29 15:50:46 +02:00
|
|
|
str = strstr (line, "fcn.");
|
2016-09-23 13:23:32 +02:00
|
|
|
}
|
2016-08-31 03:17:51 +02:00
|
|
|
}
|
2016-09-24 00:30:13 +02:00
|
|
|
if (str) {
|
2017-08-29 15:50:46 +02:00
|
|
|
str = strdup (str);
|
2019-12-15 21:05:42 +03:00
|
|
|
char *qoe = strchr (str, ';');
|
2016-09-24 00:30:13 +02:00
|
|
|
if (qoe) {
|
2017-08-29 12:39:49 +02:00
|
|
|
char* t = str;
|
2016-09-24 00:30:13 +02:00
|
|
|
str = r_str_ndup (str, qoe - str);
|
2017-08-29 12:39:49 +02:00
|
|
|
free (t);
|
2016-09-24 00:30:13 +02:00
|
|
|
}
|
|
|
|
}
|
2015-12-21 15:53:53 +01:00
|
|
|
if (str) {
|
2016-09-23 13:23:32 +02:00
|
|
|
string2 = strdup (str);
|
2017-03-08 14:34:19 +03:00
|
|
|
linecolor = R_CONS_COLOR (call);
|
2015-12-21 15:53:53 +01:00
|
|
|
}
|
|
|
|
if (!string && string2) {
|
|
|
|
string = string2;
|
|
|
|
string2 = NULL;
|
|
|
|
}
|
2016-05-17 23:41:49 +02:00
|
|
|
if (strstr (line, "XREF")) {
|
|
|
|
addr = UT64_MAX;
|
|
|
|
}
|
2016-03-23 01:13:16 +01:00
|
|
|
if (addr != UT64_MAX) {
|
2015-12-21 15:53:53 +01:00
|
|
|
const char *str = NULL;
|
2017-05-29 23:15:24 +02:00
|
|
|
if (show_comments) {
|
|
|
|
char *comment = r_core_anal_get_comments (core, addr);
|
|
|
|
if (comment) {
|
2019-04-07 08:58:50 +01:00
|
|
|
if (switchcmp) {
|
|
|
|
if (strcmp (comment, switchcmp)) {
|
|
|
|
if (show_offset) {
|
|
|
|
r_cons_printf ("%s0x%08"PFMT64x" ", use_color? pal->offset: "", addr);
|
|
|
|
}
|
|
|
|
r_cons_printf ("%s%s\n", use_color? pal->comment: "", comment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (show_offset) {
|
|
|
|
r_cons_printf ("%s0x%08"PFMT64x" ", use_color? pal->offset: "", addr);
|
|
|
|
}
|
|
|
|
r_cons_printf ("%s%s\n", use_color? pal->comment: "", comment);
|
|
|
|
}
|
|
|
|
if (r_str_startswith (comment, "switch table")) {
|
|
|
|
switchcmp = strdup (comment);
|
2017-11-30 00:14:08 +01:00
|
|
|
}
|
2017-05-29 23:15:24 +02:00
|
|
|
R_FREE (comment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-23 01:13:16 +01:00
|
|
|
if (fcn) {
|
|
|
|
bool label = false;
|
|
|
|
/* show labels, basic blocks and (conditional) branches */
|
|
|
|
RAnalBlock *bb;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (fcn->bbs, iter, bb) {
|
|
|
|
if (addr == bb->jump) {
|
2017-11-30 00:14:08 +01:00
|
|
|
if (show_offset) {
|
|
|
|
r_cons_printf ("%s0x%08"PFMT64x ":\n", use_color? Color_YELLOW: "", addr);
|
|
|
|
}
|
2016-03-23 01:13:16 +01:00
|
|
|
label = true;
|
|
|
|
break;
|
|
|
|
}
|
2015-12-21 15:53:53 +01:00
|
|
|
}
|
2016-03-23 01:13:16 +01:00
|
|
|
if (!label && strstr (line, "->")) {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("%s0x%08"PFMT64x ":\n", use_color? Color_YELLOW: "", addr);
|
2016-03-23 01:13:16 +01:00
|
|
|
}
|
|
|
|
if (strstr (line, "=<")) {
|
|
|
|
r_list_foreach (fcn->bbs, iter, bb) {
|
|
|
|
if (addr >= bb->addr && addr < bb->addr + bb->size) {
|
|
|
|
const char *op;
|
|
|
|
if (use_color) {
|
2017-03-09 23:29:48 +01:00
|
|
|
op = (bb->fail == UT64_MAX)? Color_GREEN "jmp": "cjmp";
|
2016-03-23 01:13:16 +01:00
|
|
|
} else {
|
|
|
|
op = (bb->fail == UT64_MAX)? "jmp": "cjmp";
|
|
|
|
}
|
2017-11-30 00:14:08 +01:00
|
|
|
if (show_offset) {
|
|
|
|
r_cons_printf ("%s0x%08"PFMT64x" "Color_RESET, use_color? pal->offset: "", addr);
|
|
|
|
}
|
|
|
|
r_cons_printf ("%s 0x%08"PFMT64x "%s\n",
|
|
|
|
op, bb->jump, use_color? Color_RESET: "");
|
2016-03-23 01:13:16 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-12-21 15:53:53 +01:00
|
|
|
}
|
|
|
|
}
|
2016-03-23 01:13:16 +01:00
|
|
|
if (string && *string) {
|
2016-09-23 13:23:32 +02:00
|
|
|
if (string && !strncmp (string, "0x", 2)) {
|
|
|
|
str = string;
|
|
|
|
}
|
|
|
|
if (string2 && !strncmp (string2, "0x", 2)) {
|
|
|
|
str = string2;
|
|
|
|
}
|
2016-03-23 01:13:16 +01:00
|
|
|
ut64 ptr = r_num_math (NULL, str);
|
|
|
|
RFlagItem *flag = NULL;
|
|
|
|
if (str) {
|
2019-03-05 14:43:49 -08:00
|
|
|
flag = r_core_flag_get_by_spaces (core->flags, ptr);
|
2016-03-23 01:13:16 +01:00
|
|
|
}
|
|
|
|
if (!flag) {
|
|
|
|
if (string && !strncmp (string, "0x", 2)) {
|
|
|
|
R_FREE (string);
|
|
|
|
}
|
|
|
|
if (string2 && !strncmp (string2, "0x", 2)) {
|
|
|
|
R_FREE (string2);
|
|
|
|
}
|
|
|
|
}
|
2019-02-13 11:33:24 +01:00
|
|
|
if (string && addr != UT64_MAX && addr != UT32_MAX) {
|
2019-06-16 20:58:40 +02:00
|
|
|
r_str_trim (string);
|
|
|
|
if (string2) {
|
|
|
|
r_str_trim (string2);
|
|
|
|
}
|
2018-02-20 02:09:47 +01:00
|
|
|
//// TODO implememnt avoid duplicated strings
|
|
|
|
// eprintf ("---> %s\n", string);
|
2016-03-23 01:13:16 +01:00
|
|
|
if (use_color) {
|
2017-11-30 00:14:08 +01:00
|
|
|
if (show_offset) {
|
|
|
|
r_cons_printf ("%s0x%08"PFMT64x" "Color_RESET, use_color? pal->offset: "", addr);
|
|
|
|
}
|
|
|
|
r_cons_printf ("%s%s%s%s%s%s%s\n",
|
2017-03-09 23:29:48 +01:00
|
|
|
linecolor? linecolor: "",
|
|
|
|
string2? string2: "", string2? " ": "", string,
|
|
|
|
flag? " ": "", flag? flag->name: "", Color_RESET);
|
2016-03-23 01:13:16 +01:00
|
|
|
} else {
|
2017-11-30 00:14:08 +01:00
|
|
|
if (show_offset) {
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" ", addr);
|
|
|
|
}
|
2018-07-17 22:05:01 +03:00
|
|
|
r_cons_printf ("%s%s%s%s%s\n",
|
2017-03-09 23:29:48 +01:00
|
|
|
string2? string2: "", string2? " ": "", string,
|
|
|
|
flag? " ": "", flag? flag->name: "");
|
2016-03-23 01:13:16 +01:00
|
|
|
}
|
2015-12-21 15:53:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-30 00:17:01 +01:00
|
|
|
line += strlen (line) + 1;
|
2015-12-21 15:53:53 +01:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
// r_cons_printf ("%s", s);
|
2015-12-31 16:28:16 +01:00
|
|
|
free (string2);
|
|
|
|
free (string);
|
2015-12-21 15:53:53 +01:00
|
|
|
free (s);
|
2017-08-29 12:39:49 +02:00
|
|
|
free (str);
|
2019-04-07 08:58:50 +01:00
|
|
|
free (switchcmp);
|
2018-02-20 00:57:42 +01:00
|
|
|
restore_conf:
|
|
|
|
r_config_set_i (core->config, "asm.offset", show_offset);
|
2019-06-16 22:58:48 +02:00
|
|
|
r_config_set_i (core->config, "asm.dwarf", asm_dwarf);
|
2018-02-20 00:57:42 +01:00
|
|
|
r_config_set_i (core->config, "asm.tabs", asm_tabs);
|
2020-05-15 16:23:59 +02:00
|
|
|
r_config_set_i (core->config, "scr.html", scr_html);
|
2018-03-05 02:32:07 +05:30
|
|
|
r_config_set_i (core->config, "asm.emu", asm_emu);
|
2018-04-14 12:54:19 +08:00
|
|
|
r_config_set_i (core->config, "emu.str", emu_str);
|
2015-12-21 15:53:53 +01:00
|
|
|
}
|
|
|
|
|
2016-05-16 01:18:18 +02:00
|
|
|
static void algolist(int mode) {
|
|
|
|
int i;
|
2017-03-09 23:29:48 +01:00
|
|
|
for (i = 0; i < R_HASH_NBITS; i++) {
|
2016-08-28 19:36:59 +02:00
|
|
|
ut64 bits = 1ULL << i;
|
2016-05-16 01:18:18 +02:00
|
|
|
const char *name = r_hash_name (bits);
|
2016-08-28 19:36:59 +02:00
|
|
|
if (name && *name) {
|
2016-11-07 02:33:09 +01:00
|
|
|
if (mode) {
|
|
|
|
r_cons_println (name);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%s ", name);
|
|
|
|
}
|
2016-08-28 19:36:59 +02:00
|
|
|
}
|
2016-05-16 01:18:18 +02:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
if (!mode) {
|
|
|
|
r_cons_newline ();
|
|
|
|
}
|
2016-05-16 01:18:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool cmd_print_ph(RCore *core, const char *input) {
|
|
|
|
char algo[128];
|
|
|
|
ut32 osize = 0, len = core->blocksize;
|
|
|
|
const char *ptr;
|
|
|
|
int pos = 0, handled_cmd = false;
|
|
|
|
|
|
|
|
if (!*input || *input == '?') {
|
|
|
|
algolist (1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (*input == '=') {
|
|
|
|
algolist (0);
|
|
|
|
return true;
|
|
|
|
}
|
2020-03-02 21:39:37 +01:00
|
|
|
input = r_str_trim_head_ro (input);
|
2016-05-16 01:18:18 +02:00
|
|
|
ptr = strchr (input, ' ');
|
|
|
|
sscanf (input, "%31s", algo);
|
2016-11-07 02:33:09 +01:00
|
|
|
if (ptr && ptr[1]) { // && r_num_is_valid_input (core->num, ptr + 1)) {
|
2016-05-16 01:18:18 +02:00
|
|
|
int nlen = r_num_math (core->num, ptr + 1);
|
2016-11-07 02:33:09 +01:00
|
|
|
if (nlen > 0) {
|
|
|
|
len = nlen;
|
|
|
|
}
|
2016-05-16 01:18:18 +02:00
|
|
|
osize = core->blocksize;
|
|
|
|
if (nlen > core->blocksize) {
|
|
|
|
r_core_block_size (core, nlen);
|
|
|
|
if (nlen != core->blocksize) {
|
|
|
|
eprintf ("Invalid block size\n");
|
|
|
|
r_core_block_size (core, osize);
|
|
|
|
return false;
|
|
|
|
}
|
2016-11-07 03:36:49 +01:00
|
|
|
r_core_block_read (core);
|
2016-05-16 01:18:18 +02:00
|
|
|
}
|
2016-11-07 03:36:49 +01:00
|
|
|
} else if (!ptr || !*(ptr + 1)) {
|
2016-05-16 01:18:18 +02:00
|
|
|
osize = len;
|
|
|
|
}
|
|
|
|
/* TODO: Simplify this spaguetti monster */
|
|
|
|
while (osize > 0 && hash_handlers[pos].name) {
|
2017-04-11 22:47:16 +02:00
|
|
|
if (!r_str_ccmp (hash_handlers[pos].name, input, ' ')) {
|
2016-05-16 01:18:18 +02:00
|
|
|
hash_handlers[pos].handler (core->block, len);
|
|
|
|
handled_cmd = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pos++;
|
|
|
|
}
|
|
|
|
if (osize) {
|
|
|
|
r_core_block_size (core, osize);
|
|
|
|
}
|
2016-05-23 21:49:02 +02:00
|
|
|
return handled_cmd;
|
2016-05-16 01:18:18 +02:00
|
|
|
}
|
|
|
|
|
2019-06-22 13:29:21 +02:00
|
|
|
// XXX blocksize is missing
|
2019-06-22 13:31:41 +02:00
|
|
|
static void cmd_print_pv(RCore *core, const char *input, bool useBytes) {
|
2017-03-09 23:29:48 +01:00
|
|
|
const char *stack[] = {
|
|
|
|
"ret", "arg0", "arg1", "arg2", "arg3", "arg4", NULL
|
|
|
|
};
|
2019-06-22 13:29:21 +02:00
|
|
|
ut8 *block = core->block;
|
|
|
|
int blocksize = core->blocksize;
|
|
|
|
ut8 *block_end = core->block + blocksize;
|
2020-05-13 01:28:23 +02:00
|
|
|
int i, n = core->rasm->bits / 8;
|
2015-10-22 00:48:14 +02:00
|
|
|
int type = 'v';
|
2016-04-26 15:04:05 +02:00
|
|
|
bool fixed_size = true;
|
2016-04-26 14:35:51 +02:00
|
|
|
switch (input[0]) {
|
2018-08-05 16:19:52 -07:00
|
|
|
case '1': // "pv1"
|
2016-04-26 14:35:51 +02:00
|
|
|
n = 1;
|
|
|
|
input++;
|
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case '2': // "pv2"
|
2016-04-26 14:35:51 +02:00
|
|
|
n = 2;
|
|
|
|
input++;
|
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case '4': // "pv4"
|
2016-04-26 14:35:51 +02:00
|
|
|
n = 4;
|
|
|
|
input++;
|
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case '8': // "pv8"
|
2016-04-26 14:35:51 +02:00
|
|
|
n = 8;
|
|
|
|
input++;
|
|
|
|
break;
|
2016-04-26 15:04:05 +02:00
|
|
|
default:
|
2019-06-20 12:33:58 +02:00
|
|
|
if (*input && input[1] == 'j') {
|
2018-12-26 20:44:58 -03:00
|
|
|
input++;
|
|
|
|
}
|
2016-04-26 15:04:05 +02:00
|
|
|
fixed_size = false;
|
|
|
|
break;
|
2016-04-26 14:35:51 +02:00
|
|
|
}
|
2019-09-01 18:12:43 +02:00
|
|
|
const char *arg = strchr (input, ' ');
|
|
|
|
if (arg) {
|
2020-03-02 21:39:37 +01:00
|
|
|
arg = r_str_trim_head_ro (arg + 1);
|
2019-09-01 18:12:43 +02:00
|
|
|
} else {
|
|
|
|
arg = input;
|
|
|
|
}
|
|
|
|
st64 repeat = r_num_math (core->num, arg);
|
2019-06-22 13:29:21 +02:00
|
|
|
if (repeat < 0) {
|
|
|
|
repeat = 1;
|
|
|
|
}
|
2019-09-01 18:12:43 +02:00
|
|
|
if (useBytes && n > 0 && repeat > 0) {
|
2019-06-22 13:31:41 +02:00
|
|
|
repeat /= n;
|
|
|
|
}
|
2019-09-01 18:12:43 +02:00
|
|
|
if (repeat < 1) {
|
|
|
|
repeat = 1;
|
|
|
|
}
|
2015-10-22 00:48:14 +02:00
|
|
|
// variables can be
|
|
|
|
switch (input[0]) {
|
2016-07-22 00:48:52 +02:00
|
|
|
case 'z': // "pvz"
|
2015-10-22 00:48:14 +02:00
|
|
|
type = 'z';
|
|
|
|
if (input[1]) {
|
|
|
|
input++;
|
|
|
|
} else {
|
|
|
|
r_core_cmdf (core, "ps");
|
|
|
|
break;
|
|
|
|
}
|
2016-07-22 00:48:52 +02:00
|
|
|
/* fallthrough */
|
2019-06-22 13:29:21 +02:00
|
|
|
// case ' ': // "pv "
|
2016-03-24 17:28:41 +01:00
|
|
|
for (i = 0; stack[i]; i++) {
|
2016-04-26 14:35:51 +02:00
|
|
|
if (!strcmp (input + 1, stack[i])) {
|
2015-10-22 00:48:14 +02:00
|
|
|
if (type == 'z') {
|
|
|
|
r_core_cmdf (core, "ps @ [`drn sp`+%d]", n * i);
|
|
|
|
} else {
|
|
|
|
r_core_cmdf (core, "?v [`drn sp`+%d]", n * i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2019-09-01 18:25:10 +02:00
|
|
|
case '*': { // "pv*"
|
|
|
|
for (i = 0; i < repeat; i++) {
|
|
|
|
const bool be = core->print->big_endian;
|
|
|
|
ut64 at = core->offset + (i * n);
|
|
|
|
ut8 *b = block + (i * n);
|
|
|
|
switch (n) {
|
|
|
|
case 1:
|
2020-10-13 16:26:15 +02:00
|
|
|
r_cons_printf ("f pval.0x%08"PFMT64x"=%d\n", at, r_read_ble8 (b));
|
2019-09-01 18:25:10 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-10-13 16:26:15 +02:00
|
|
|
r_cons_printf ("f pval.0x%08"PFMT64x"=%d\n", at, r_read_ble16 (b, be));
|
2019-09-01 18:25:10 +02:00
|
|
|
break;
|
|
|
|
case 4:
|
2020-10-13 16:26:15 +02:00
|
|
|
r_cons_printf ("f pval.0x%08"PFMT64x"=%d\n", at, r_read_ble32 (b, be));
|
2019-09-01 18:25:10 +02:00
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
default:
|
|
|
|
r_cons_printf ("f pval.0x%08"PFMT64x"=%"PFMT64d"\n", at, r_read_ble64 (b, be));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2018-08-05 16:19:52 -07:00
|
|
|
case 'j': { // "pvj"
|
2019-09-01 18:12:43 +02:00
|
|
|
r_cons_printf ("[");
|
2019-10-11 12:10:33 +02:00
|
|
|
ut64 at = core->offset;
|
|
|
|
ut64 oldAt = at;
|
2019-09-01 18:12:43 +02:00
|
|
|
for (i = 0; i < repeat; i++) {
|
|
|
|
if (i > 0) {
|
|
|
|
r_cons_printf (",");
|
|
|
|
}
|
2020-04-17 12:53:35 +02:00
|
|
|
r_core_seek (core, at, false);
|
2019-10-19 01:22:46 +02:00
|
|
|
char *str = r_core_cmd_str (core, "ps");
|
2019-09-01 18:12:43 +02:00
|
|
|
r_str_trim (str);
|
|
|
|
char *p = str;
|
|
|
|
if (p) {
|
|
|
|
while (*p) {
|
|
|
|
if (*p == '\\' && p[1] == 'x') {
|
|
|
|
memmove (p, p + 4, strlen (p + 4) + 1);
|
|
|
|
}
|
2019-10-11 12:10:33 +02:00
|
|
|
p++;
|
2019-09-01 18:12:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// r_num_get is gonna use a dangling pointer since the internal
|
|
|
|
// token that RNum holds ([$$]) has been already freed by r_core_cmd_str
|
|
|
|
// r_num_math reload a new token so the dangling pointer is gone
|
|
|
|
switch (n) {
|
|
|
|
case 1:
|
|
|
|
pj_fmt (r_cons_printf, "{'value':%i,'string':%s}",
|
|
|
|
r_read_ble8 (block), str);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
pj_fmt (r_cons_printf, "{'value':%i,'string':%s}",
|
|
|
|
r_read_ble16 (block, core->print->big_endian), str);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
pj_fmt (r_cons_printf, "{'value':%n,'string':%s}",
|
|
|
|
(ut64)r_read_ble32 (block, core->print->big_endian), str);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
pj_fmt (r_cons_printf, "{'value':%n,'string':%s}",
|
|
|
|
r_read_ble64 (block, core->print->big_endian), str);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
pj_fmt (r_cons_printf, "{'value':%n,'string':%s}",
|
|
|
|
r_read_ble64 (block, core->print->big_endian), str);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
free (str);
|
2019-09-01 18:25:10 +02:00
|
|
|
at += n;
|
2019-09-01 18:12:43 +02:00
|
|
|
}
|
|
|
|
r_cons_printf ("]\n");
|
2020-04-17 12:53:35 +02:00
|
|
|
r_core_seek (core, oldAt, false);
|
2019-10-11 12:10:33 +02:00
|
|
|
break;
|
|
|
|
}
|
2018-08-05 16:19:52 -07:00
|
|
|
case '?': // "pv?"
|
2019-10-11 12:10:33 +02:00
|
|
|
r_core_cmd_help (core, help_msg_pv);
|
|
|
|
break;
|
2015-10-22 00:48:14 +02:00
|
|
|
default:
|
2019-10-11 12:10:33 +02:00
|
|
|
do {
|
|
|
|
repeat--;
|
|
|
|
if (block + 8 >= block_end) {
|
|
|
|
eprintf ("Truncated. TODO: use r_io_read apis insgtead of depending on blocksize\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ut64 v;
|
|
|
|
if (!fixed_size) {
|
|
|
|
n = 0;
|
|
|
|
}
|
|
|
|
switch (n) {
|
|
|
|
case 1:
|
|
|
|
v = r_read_ble8 (block);
|
|
|
|
r_cons_printf ("0x%02" PFMT64x "\n", v);
|
|
|
|
block += 1;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
v = r_read_ble16 (block, core->print->big_endian);
|
|
|
|
r_cons_printf ("0x%04" PFMT64x "\n", v);
|
|
|
|
block += 2;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
v = r_read_ble32 (block, core->print->big_endian);
|
|
|
|
r_cons_printf ("0x%08" PFMT64x "\n", v);
|
|
|
|
block += 4;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
v = r_read_ble64 (block, core->print->big_endian);
|
|
|
|
r_cons_printf ("0x%016" PFMT64x "\n", v);
|
|
|
|
block += 8;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
v = r_read_ble64 (block, core->print->big_endian);
|
2020-05-13 01:28:23 +02:00
|
|
|
switch (core->rasm->bits / 8) {
|
2019-10-11 12:10:33 +02:00
|
|
|
case 1: r_cons_printf ("0x%02" PFMT64x "\n", v & UT8_MAX); break;
|
|
|
|
case 2: r_cons_printf ("0x%04" PFMT64x "\n", v & UT16_MAX); break;
|
|
|
|
case 4: r_cons_printf ("0x%08" PFMT64x "\n", v & UT32_MAX); break;
|
|
|
|
case 8: r_cons_printf ("0x%016" PFMT64x "\n", v & UT64_MAX); break;
|
|
|
|
default: break;
|
|
|
|
}
|
2020-05-13 01:28:23 +02:00
|
|
|
block += core->rasm->bits / 8;
|
2019-10-11 12:10:33 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (repeat > 0);
|
|
|
|
break;
|
2015-10-22 00:48:14 +02:00
|
|
|
}
|
|
|
|
}
|
2015-03-23 01:09:35 +01:00
|
|
|
|
2020-04-16 14:52:16 +03:00
|
|
|
static bool cmd_print_blocks(RCore *core, const char *input) {
|
|
|
|
bool result = false;
|
2018-06-29 11:22:11 +02:00
|
|
|
char mode = input[0];
|
2020-04-16 14:52:16 +03:00
|
|
|
RList *list = NULL;
|
|
|
|
RCoreAnalStats *as = NULL;
|
|
|
|
RTable *t = NULL;
|
|
|
|
PJ *pj = NULL;
|
2018-06-29 11:22:11 +02:00
|
|
|
if (mode == '?') {
|
|
|
|
r_core_cmd_help (core, help_msg_p_minus);
|
2020-04-16 14:52:16 +03:00
|
|
|
return false;
|
2018-06-29 11:22:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mode && mode != ' ') {
|
|
|
|
input++;
|
|
|
|
}
|
|
|
|
|
2018-12-12 12:21:37 +01:00
|
|
|
int w = (input[0] == ' ')
|
|
|
|
? (int)r_num_math (core->num, input + 1)
|
|
|
|
: (int)(core->print->cols * 2.7);
|
2018-06-29 11:22:11 +02:00
|
|
|
|
2019-01-29 20:56:23 +01:00
|
|
|
if (w == 0) {
|
|
|
|
r_core_cmd_help (core, help_msg_p_minus);
|
2020-04-16 14:52:16 +03:00
|
|
|
return false;
|
2019-01-29 20:56:23 +01:00
|
|
|
}
|
2019-05-15 01:26:32 +02:00
|
|
|
int cols = r_config_get_i (core->config, "hex.cols");
|
|
|
|
//int cols = r_cons_get_size (NULL) - 30;
|
2018-06-29 11:22:11 +02:00
|
|
|
ut64 off = core->offset;
|
2018-12-12 12:21:37 +01:00
|
|
|
ut64 from = UT64_MAX;
|
2018-06-29 11:22:11 +02:00
|
|
|
ut64 to = 0;
|
2020-04-16 14:52:16 +03:00
|
|
|
|
|
|
|
list = r_core_get_boundaries_prot (core, -1, NULL, "search");
|
2018-12-12 12:21:37 +01:00
|
|
|
if (!list) {
|
2020-04-16 14:52:16 +03:00
|
|
|
result = true;
|
|
|
|
goto cleanup;
|
2018-12-12 12:21:37 +01:00
|
|
|
}
|
|
|
|
RListIter *iter;
|
|
|
|
RIOMap *map;
|
|
|
|
r_list_foreach (list, iter, map) {
|
|
|
|
ut64 f = r_itv_begin (map->itv);
|
|
|
|
ut64 t = r_itv_end (map->itv);
|
|
|
|
if (f < from) {
|
|
|
|
from = f;
|
2018-11-15 19:35:47 +01:00
|
|
|
}
|
2018-12-12 12:21:37 +01:00
|
|
|
if (t > to) {
|
|
|
|
to = t;
|
2018-06-29 11:22:11 +02:00
|
|
|
}
|
|
|
|
}
|
2019-08-01 00:33:04 +03:00
|
|
|
r_list_free (list);
|
|
|
|
list = NULL;
|
2019-05-15 04:52:15 +05:30
|
|
|
ut64 piece = R_MAX ((to - from) / R_MAX (cols, w), 1);
|
2020-04-16 14:52:16 +03:00
|
|
|
as = r_core_anal_get_stats (core, from, to, piece);
|
2018-06-29 11:22:11 +02:00
|
|
|
if (!as) {
|
2020-04-16 14:52:16 +03:00
|
|
|
goto cleanup;
|
2018-06-29 11:22:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (mode) {
|
2018-12-12 12:21:37 +01:00
|
|
|
case 'j': // "p-j"
|
2020-04-16 14:52:16 +03:00
|
|
|
pj = pj_new ();
|
|
|
|
if (!pj) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2019-02-23 06:01:19 +05:30
|
|
|
pj_o (pj);
|
|
|
|
pj_kn (pj, "from", from);
|
|
|
|
pj_kn (pj, "to", to);
|
|
|
|
pj_ki (pj, "blocksize", piece);
|
|
|
|
pj_k (pj, "blocks");
|
|
|
|
pj_a (pj);
|
2018-12-12 12:21:37 +01:00
|
|
|
break;
|
2020-04-16 14:52:16 +03:00
|
|
|
case 'h': { // "p-h"
|
|
|
|
t = r_core_table (core);
|
|
|
|
if (!t) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
t->showSum = true;
|
2019-09-24 14:16:06 +05:30
|
|
|
r_table_set_columnsf (t, "sddddd", "offset", "flags", "funcs", "cmts", "syms", "str");
|
2018-12-12 12:21:37 +01:00
|
|
|
break;
|
2020-04-16 14:52:16 +03:00
|
|
|
}
|
2019-03-19 16:37:23 +00:00
|
|
|
case 'e':
|
2018-12-12 12:21:37 +01:00
|
|
|
default:
|
2019-03-19 16:37:23 +00:00
|
|
|
r_cons_printf ("0x%08"PFMT64x " [", from);
|
2018-06-29 11:22:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool use_color = r_config_get_i (core->config, "scr.color");
|
|
|
|
int len = 0;
|
|
|
|
int i;
|
2018-12-12 12:21:37 +01:00
|
|
|
for (i = 0; i < ((to - from) / piece); i++) {
|
2018-06-29 11:22:11 +02:00
|
|
|
ut64 at = from + (piece * i);
|
|
|
|
ut64 ate = at + piece;
|
|
|
|
ut64 p = (at - from) / piece;
|
|
|
|
switch (mode) {
|
2018-12-12 12:21:37 +01:00
|
|
|
case 'j':
|
2019-02-23 06:01:19 +05:30
|
|
|
pj_o (pj);
|
2018-12-12 12:21:37 +01:00
|
|
|
if ((as->block[p].flags)
|
|
|
|
|| (as->block[p].functions)
|
|
|
|
|| (as->block[p].comments)
|
|
|
|
|| (as->block[p].symbols)
|
|
|
|
|| (as->block[p].perm)
|
|
|
|
|| (as->block[p].strings)) {
|
2019-02-23 06:01:19 +05:30
|
|
|
pj_kn (pj, "offset", at);
|
|
|
|
pj_kn (pj, "size", piece);
|
|
|
|
}
|
|
|
|
if (as->block[p].flags) {
|
|
|
|
pj_ki (pj, "flags", as->block[p].flags);
|
|
|
|
}
|
|
|
|
if (as->block[p].functions) {
|
|
|
|
pj_ki (pj, "functions", as->block[p].functions);
|
|
|
|
}
|
|
|
|
if (as->block[p].in_functions) {
|
|
|
|
pj_ki (pj, "in_functions", as->block[p].in_functions);
|
|
|
|
}
|
|
|
|
if (as->block[p].comments) {
|
|
|
|
pj_ki (pj, "comments", as->block[p].comments);
|
|
|
|
}
|
|
|
|
if (as->block[p].symbols) {
|
|
|
|
pj_ki (pj, "symbols", as->block[p].symbols);
|
|
|
|
}
|
|
|
|
if (as->block[p].strings) {
|
|
|
|
pj_ki (pj, "strings", as->block[p].strings);
|
|
|
|
}
|
|
|
|
if (as->block[p].perm) {
|
|
|
|
pj_ks (pj, "perm", r_str_rwx_i (as->block[p].perm));
|
|
|
|
}
|
|
|
|
pj_end (pj);
|
2018-12-12 12:21:37 +01:00
|
|
|
len++;
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
if ((as->block[p].flags)
|
|
|
|
|| (as->block[p].functions)
|
|
|
|
|| (as->block[p].comments)
|
|
|
|
|| (as->block[p].symbols)
|
|
|
|
|| (as->block[p].strings)) {
|
2019-09-24 14:16:06 +05:30
|
|
|
r_table_add_rowf (t, "sddddd", sdb_fmt ("0x%09"PFMT64x"", at), as->block[p].flags,
|
|
|
|
as->block[p].functions, as->block[p].comments, as->block[p].symbols, as->block[p].strings);
|
2018-12-12 12:21:37 +01:00
|
|
|
}
|
|
|
|
break;
|
2019-03-19 16:37:23 +00:00
|
|
|
case 'e': // p-e
|
|
|
|
cmd_p_minus_e (core, at, ate);
|
|
|
|
break;
|
2019-05-15 04:52:15 +05:30
|
|
|
default:{ // p--
|
2018-12-12 12:21:37 +01:00
|
|
|
if (off >= at && off < ate) {
|
|
|
|
r_cons_memcat ("^", 1);
|
|
|
|
} else {
|
2019-01-13 03:07:51 +01:00
|
|
|
RIOMap *s = r_io_map_get (core->io, at);
|
2018-12-12 12:21:37 +01:00
|
|
|
if (use_color) {
|
|
|
|
if (s) {
|
|
|
|
if (s->perm & R_PERM_X) {
|
2019-05-15 04:52:15 +05:30
|
|
|
r_cons_print (r_cons_singleton ()->context->pal.graph_trufae);
|
2018-06-29 11:22:11 +02:00
|
|
|
} else {
|
2019-05-15 04:52:15 +05:30
|
|
|
r_cons_print (r_cons_singleton ()->context->pal.graph_true);
|
2018-06-29 11:22:11 +02:00
|
|
|
}
|
|
|
|
} else {
|
2019-05-15 04:52:15 +05:30
|
|
|
r_cons_print (r_cons_singleton ()->context->pal.graph_false);
|
2018-06-29 11:22:11 +02:00
|
|
|
}
|
|
|
|
}
|
2018-12-12 12:21:37 +01:00
|
|
|
if (as->block[p].strings > 0) {
|
|
|
|
r_cons_memcat ("z", 1);
|
|
|
|
} else if (as->block[p].symbols > 0) {
|
|
|
|
r_cons_memcat ("s", 1);
|
|
|
|
} else if (as->block[p].functions > 0) {
|
|
|
|
r_cons_memcat ("F", 1);
|
|
|
|
} else if (as->block[p].comments > 0) {
|
|
|
|
r_cons_memcat ("c", 1);
|
|
|
|
} else if (as->block[p].flags > 0) {
|
|
|
|
r_cons_memcat (".", 1);
|
|
|
|
} else if (as->block[p].in_functions > 0) {
|
|
|
|
r_cons_memcat ("f", 1);
|
|
|
|
} else {
|
|
|
|
r_cons_memcat ("_", 1);
|
|
|
|
}
|
|
|
|
}
|
2019-05-15 04:52:15 +05:30
|
|
|
}
|
|
|
|
break;
|
2018-06-29 11:22:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (mode) {
|
2020-04-16 14:52:16 +03:00
|
|
|
case 'j':
|
|
|
|
pj_end (pj);
|
|
|
|
pj_end (pj);
|
|
|
|
r_cons_println (pj_string (pj));
|
|
|
|
break;
|
|
|
|
case 'h': {
|
|
|
|
char *table_string = r_table_tofancystring (t);
|
|
|
|
if (!table_string) {
|
|
|
|
goto cleanup;
|
2019-09-24 14:16:06 +05:30
|
|
|
}
|
2020-04-16 14:52:16 +03:00
|
|
|
r_cons_printf ("\n%s\n", table_string);
|
|
|
|
free (table_string);
|
|
|
|
break;
|
2018-06-29 11:22:11 +02:00
|
|
|
}
|
2020-04-16 14:52:16 +03:00
|
|
|
case 'e':
|
|
|
|
default:
|
|
|
|
if (use_color) {
|
|
|
|
r_cons_print (Color_RESET);
|
|
|
|
}
|
|
|
|
r_cons_printf ("] 0x%08"PFMT64x "\n", to);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
result = true;
|
|
|
|
cleanup:
|
|
|
|
pj_free (pj);
|
|
|
|
r_table_free (t);
|
|
|
|
r_list_free (list);
|
2018-06-29 11:22:11 +02:00
|
|
|
r_core_anal_stats_free (as);
|
2020-04-16 14:52:16 +03:00
|
|
|
return result;
|
2018-06-29 11:22:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-29 04:23:14 +02:00
|
|
|
static bool checkAnalType(RAnalOp *op, int t) {
|
|
|
|
if (t == 'c') {
|
|
|
|
switch (op->type) {
|
|
|
|
case R_ANAL_OP_TYPE_RCALL:
|
|
|
|
case R_ANAL_OP_TYPE_UCALL:
|
|
|
|
case R_ANAL_OP_TYPE_CALL:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else if (t == 's') {
|
|
|
|
if (op->family == R_ANAL_OP_FAMILY_PRIV) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
switch (op->type) {
|
|
|
|
case R_ANAL_OP_TYPE_SWI:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else if (t == 'i') {
|
|
|
|
switch (op->type) {
|
|
|
|
case R_ANAL_OP_TYPE_TRAP:
|
|
|
|
case R_ANAL_OP_TYPE_ILL:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else if (t == 'j') {
|
|
|
|
switch (op->type) {
|
|
|
|
case R_ANAL_OP_TYPE_JMP:
|
|
|
|
//case R_ANAL_OP_TYPE_RJMP:
|
|
|
|
//case R_ANAL_OP_TYPE_UJMP:
|
|
|
|
case R_ANAL_OP_TYPE_CJMP:
|
|
|
|
return true;
|
2019-10-23 15:49:54 +02:00
|
|
|
default:
|
|
|
|
break;
|
2017-03-29 04:23:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void matchBar(ut8 *ptr, int i) {
|
|
|
|
if (ptr[i] < 0xff) {
|
|
|
|
ptr[i]++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-12 20:45:24 +02:00
|
|
|
static ut8 *analBars(RCore *core, size_t type, size_t nblocks, size_t blocksize, size_t skipblocks, ut64 from) {
|
|
|
|
size_t j, i = 0;
|
2017-03-29 04:23:14 +02:00
|
|
|
ut8 *ptr = calloc (1, nblocks);
|
|
|
|
if (!ptr) {
|
|
|
|
eprintf ("Error: failed to malloc memory");
|
|
|
|
return NULL;
|
|
|
|
}
|
2019-09-17 03:14:32 +03:00
|
|
|
// XXX: unused memblock
|
2019-05-07 11:59:38 +02:00
|
|
|
ut8 *p = malloc (blocksize);
|
2017-03-29 04:23:14 +02:00
|
|
|
if (!p) {
|
|
|
|
R_FREE (ptr);
|
|
|
|
eprintf ("Error: failed to malloc memory");
|
|
|
|
return NULL;
|
|
|
|
}
|
2019-05-07 11:59:38 +02:00
|
|
|
if (type == 'A') {
|
|
|
|
ut64 to = from + (blocksize * nblocks);
|
|
|
|
RCoreAnalStats *as = r_core_anal_get_stats (core, from, to, blocksize);
|
|
|
|
for (i = 0; i < nblocks; i++) {
|
|
|
|
int value = 0;
|
|
|
|
value += as->block[i].functions;
|
|
|
|
value += as->block[i].in_functions;
|
|
|
|
value += as->block[i].comments;
|
|
|
|
value += as->block[i].symbols;
|
|
|
|
value += as->block[i].flags;
|
|
|
|
value += as->block[i].strings;
|
|
|
|
value += as->block[i].blocks;
|
|
|
|
ptr[i] = R_MIN (255, value);
|
|
|
|
}
|
|
|
|
r_core_anal_stats_free (as);
|
2019-09-17 03:14:32 +03:00
|
|
|
free (p);
|
2019-05-07 11:59:38 +02:00
|
|
|
return ptr;
|
|
|
|
}
|
2017-03-29 04:23:14 +02:00
|
|
|
for (i = 0; i < nblocks; i++) {
|
2017-03-29 04:37:40 +02:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
2018-01-03 22:06:15 +05:30
|
|
|
ut64 off = from + (i + skipblocks) * blocksize;
|
2017-03-29 04:23:14 +02:00
|
|
|
for (j = 0; j < blocksize ; j++) {
|
2019-05-07 11:59:38 +02:00
|
|
|
if (type == 'a') {
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off + j, 0);
|
|
|
|
if (fcn) {
|
|
|
|
ptr[i] = r_list_length (fcn->bbs);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2018-06-08 00:02:00 +05:30
|
|
|
RAnalOp *op = r_core_anal_op (core, off + j, R_ANAL_OP_MASK_BASIC);
|
2017-03-29 04:23:14 +02:00
|
|
|
if (op) {
|
|
|
|
if (op->size < 1) {
|
|
|
|
// do nothing
|
|
|
|
if (type == 'i') {
|
|
|
|
matchBar (ptr, i);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (checkAnalType (op, type)) {
|
|
|
|
matchBar (ptr, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (op->size > 0) {
|
|
|
|
j += op->size - 1;
|
|
|
|
}
|
|
|
|
r_anal_op_free (op);
|
|
|
|
} else {
|
|
|
|
if (type == 'i') {
|
|
|
|
matchBar (ptr, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free (p);
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2016-03-13 01:28:19 +01:00
|
|
|
static void cmd_print_bars(RCore *core, const char *input) {
|
2016-03-11 12:19:37 +01:00
|
|
|
bool print_bars = false;
|
2017-09-04 21:32:39 +02:00
|
|
|
ut8 *ptr = NULL;
|
2016-03-13 01:28:19 +01:00
|
|
|
// p=e [nblocks] [totalsize] [skip]
|
|
|
|
int nblocks = -1;
|
2018-09-20 21:59:32 +08:00
|
|
|
ut64 totalsize = UT64_MAX;
|
2016-03-13 01:28:19 +01:00
|
|
|
int skipblocks = -1;
|
2018-01-03 22:06:15 +05:30
|
|
|
RIOMap* map;
|
|
|
|
RListIter *iter;
|
2018-01-06 23:45:06 +01:00
|
|
|
ut64 from = 0, to = 0;
|
2018-01-28 03:40:02 +05:30
|
|
|
RList *list = r_core_get_boundaries_prot (core, -1, NULL, "zoom");
|
2018-11-15 19:35:47 +01:00
|
|
|
if (!list) {
|
|
|
|
goto beach;
|
|
|
|
}
|
|
|
|
|
2017-08-29 12:39:49 +02:00
|
|
|
ut64 blocksize = 0;
|
2016-03-13 01:28:19 +01:00
|
|
|
int mode = 'b'; // e, p, b, ...
|
|
|
|
int submode = 0; // q, j, ...
|
2018-06-29 11:22:11 +02:00
|
|
|
|
2016-03-11 12:19:37 +01:00
|
|
|
if (input[0]) {
|
2016-03-13 01:28:19 +01:00
|
|
|
char *spc = strchr (input, ' ');
|
2016-03-11 12:19:37 +01:00
|
|
|
if (spc) {
|
2017-06-28 00:24:26 +02:00
|
|
|
nblocks = r_num_math (core->num, spc + 1);
|
2016-04-01 00:02:56 +02:00
|
|
|
if (nblocks < 1) {
|
2018-08-26 09:25:34 -07:00
|
|
|
goto beach;
|
2016-04-01 00:02:56 +02:00
|
|
|
}
|
2016-03-13 01:28:19 +01:00
|
|
|
spc = strchr (spc + 1, ' ');
|
2016-03-11 12:19:37 +01:00
|
|
|
if (spc) {
|
2017-06-28 00:24:26 +02:00
|
|
|
totalsize = r_num_math (core->num, spc + 1);
|
2016-03-13 01:28:19 +01:00
|
|
|
spc = strchr (spc + 1, ' ');
|
2016-03-11 12:19:37 +01:00
|
|
|
if (spc) {
|
2017-06-28 00:24:26 +02:00
|
|
|
skipblocks = r_num_math (core->num, spc + 1);
|
2016-03-11 12:19:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-13 01:28:19 +01:00
|
|
|
mode = input[1];
|
|
|
|
if (mode && mode != ' ' && input[2]) {
|
|
|
|
submode = input[2];
|
|
|
|
}
|
2016-03-11 12:19:37 +01:00
|
|
|
}
|
2016-03-13 02:31:13 +01:00
|
|
|
if (skipblocks < 0) {
|
|
|
|
skipblocks = 0;
|
|
|
|
}
|
2016-03-13 01:28:19 +01:00
|
|
|
if (totalsize == UT64_MAX) {
|
2019-04-19 02:08:02 +02:00
|
|
|
if (r_config_get_i (core->config, "cfg.debug")) {
|
|
|
|
RDebugMap *map = r_debug_map_get (core->dbg, core->offset);
|
|
|
|
if (map) {
|
|
|
|
totalsize = map->addr_end - map->addr;
|
|
|
|
from = map->addr;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (core->file && core->io) {
|
|
|
|
totalsize = r_io_fd_size (core->io, core->file->fd);
|
|
|
|
if ((st64) totalsize < 1) {
|
|
|
|
totalsize = UT64_MAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (totalsize == UT64_MAX) {
|
|
|
|
eprintf ("Cannot determine file size\n");
|
|
|
|
goto beach;
|
2016-03-11 12:19:37 +01:00
|
|
|
}
|
2016-03-13 01:28:19 +01:00
|
|
|
}
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
blocksize = (blocksize > 0)? (totalsize / blocksize): (core->blocksize);
|
2016-03-13 01:28:19 +01:00
|
|
|
if (blocksize < 1) {
|
2017-08-29 13:27:24 +02:00
|
|
|
eprintf ("Invalid block size: %d\n", (int)blocksize);
|
2018-08-26 09:25:34 -07:00
|
|
|
goto beach;
|
2016-03-13 01:28:19 +01:00
|
|
|
}
|
2019-04-19 02:08:02 +02:00
|
|
|
if (!r_config_get_i (core->config, "cfg.debug")) {
|
|
|
|
RIOMap* map1 = r_list_first (list);
|
|
|
|
if (map1) {
|
|
|
|
from = map1->itv.addr;
|
|
|
|
r_list_foreach (list, iter, map) {
|
|
|
|
to = r_itv_end (map->itv);
|
|
|
|
}
|
|
|
|
totalsize = to - from;
|
|
|
|
} else {
|
|
|
|
from = core->offset;
|
2018-01-03 22:06:15 +05:30
|
|
|
}
|
|
|
|
}
|
2016-03-13 01:28:19 +01:00
|
|
|
if (nblocks < 1) {
|
|
|
|
nblocks = totalsize / blocksize;
|
2016-03-11 12:19:37 +01:00
|
|
|
} else {
|
2016-03-13 01:28:19 +01:00
|
|
|
blocksize = totalsize / nblocks;
|
2018-03-14 13:08:01 +01:00
|
|
|
if (blocksize < 1) {
|
|
|
|
eprintf ("Invalid block size: %d\n", (int)blocksize);
|
2018-08-26 09:25:34 -07:00
|
|
|
goto beach;
|
2018-03-14 13:08:01 +01:00
|
|
|
}
|
2016-03-11 12:19:37 +01:00
|
|
|
}
|
2016-03-13 01:28:19 +01:00
|
|
|
switch (mode) {
|
2017-05-23 13:38:19 +02:00
|
|
|
case '?': // bars
|
2017-07-25 04:20:25 -07:00
|
|
|
r_core_cmd_help (core, help_msg_p_equal);
|
2017-03-09 23:29:48 +01:00
|
|
|
break;
|
2017-05-16 03:08:15 +02:00
|
|
|
case '=': // "p=="
|
|
|
|
switch (submode) {
|
2017-07-18 01:24:46 -07:00
|
|
|
case '?':
|
2017-07-25 04:20:25 -07:00
|
|
|
r_core_cmd_help (core, help_msg_p_equal);
|
2017-07-18 01:24:46 -07:00
|
|
|
break;
|
|
|
|
case '0': // 0x00 bytes
|
|
|
|
case 'f': // 0xff bytes
|
|
|
|
case 'F': // 0xff bytes
|
2019-05-07 11:59:38 +02:00
|
|
|
case 'A': // anal stats
|
|
|
|
case 'a': // anal bb
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'p': // printable chars
|
|
|
|
case 'z': // zero terminated strings
|
2019-05-07 11:59:38 +02:00
|
|
|
case 'b': // zero terminated strings
|
2017-07-18 01:24:46 -07:00
|
|
|
{
|
2017-08-29 12:39:49 +02:00
|
|
|
ut64 i, j, k;
|
2017-07-18 01:24:46 -07:00
|
|
|
ptr = calloc (1, nblocks);
|
|
|
|
if (!ptr) {
|
|
|
|
eprintf ("Error: failed to malloc memory");
|
|
|
|
goto beach;
|
|
|
|
}
|
2019-05-07 11:59:38 +02:00
|
|
|
ut8 *p = calloc (1, blocksize);
|
2017-07-18 01:24:46 -07:00
|
|
|
if (!p) {
|
|
|
|
R_FREE (ptr);
|
|
|
|
eprintf ("Error: failed to malloc memory");
|
|
|
|
goto beach;
|
|
|
|
}
|
|
|
|
int len = 0;
|
2019-05-07 11:59:38 +02:00
|
|
|
if (submode == 'A') {
|
|
|
|
ut64 to = from + totalsize; // (blocksize * nblocks);
|
|
|
|
RCoreAnalStats *as = r_core_anal_get_stats (core, from, to, blocksize);
|
|
|
|
for (i = 0; i < nblocks; i++) {
|
|
|
|
int value = 0;
|
|
|
|
value += as->block[i].functions;
|
|
|
|
value += as->block[i].in_functions;
|
|
|
|
value += as->block[i].comments;
|
|
|
|
value += as->block[i].symbols;
|
|
|
|
value += as->block[i].flags;
|
|
|
|
value += as->block[i].strings;
|
|
|
|
value += as->block[i].blocks;
|
|
|
|
ptr[i] = 256 * value / blocksize;
|
|
|
|
ptr[i] *= 3;
|
|
|
|
}
|
|
|
|
r_core_anal_stats_free (as);
|
|
|
|
} else for (i = 0; i < nblocks; i++) {
|
2018-01-03 22:06:15 +05:30
|
|
|
ut64 off = from + blocksize * (i + skipblocks);
|
2018-05-21 23:06:00 +02:00
|
|
|
r_io_read_at (core->io, off, p, blocksize);
|
2017-07-18 01:24:46 -07:00
|
|
|
for (j = k = 0; j < blocksize; j++) {
|
|
|
|
switch (submode) {
|
2019-05-07 11:59:38 +02:00
|
|
|
case 'a':
|
|
|
|
{
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off + j, 0);
|
|
|
|
if (fcn) {
|
|
|
|
k += r_list_length (fcn->bbs);
|
|
|
|
k = R_MAX (255, k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case '0':
|
|
|
|
if (!p[j]) {
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
if (p[j] == 0xff) {
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'z':
|
|
|
|
if ((IS_PRINTABLE (p[j]))) {
|
2019-04-22 11:59:25 +02:00
|
|
|
if ((j + 1) < blocksize && p[j + 1] == 0) {
|
2017-07-18 01:24:46 -07:00
|
|
|
k++;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
if (len++ > 8) {
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
len = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
if ((IS_PRINTABLE (p[j]))) {
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
break;
|
2017-05-16 03:08:15 +02:00
|
|
|
}
|
|
|
|
}
|
2017-07-18 01:24:46 -07:00
|
|
|
ptr[i] = 256 * k / blocksize;
|
2017-05-16 03:08:15 +02:00
|
|
|
}
|
2017-07-18 01:24:46 -07:00
|
|
|
r_print_columns (core->print, ptr, nblocks, 14);
|
|
|
|
free (p);
|
2017-05-16 03:08:15 +02:00
|
|
|
}
|
2017-07-18 01:24:46 -07:00
|
|
|
break;
|
|
|
|
case 'e': // "p=e"
|
|
|
|
{
|
|
|
|
ut8 *p;
|
|
|
|
int i = 0;
|
|
|
|
ptr = calloc (1, nblocks);
|
|
|
|
if (!ptr) {
|
|
|
|
eprintf ("Error: failed to malloc memory");
|
|
|
|
goto beach;
|
|
|
|
}
|
|
|
|
p = malloc (blocksize);
|
|
|
|
if (!p) {
|
|
|
|
R_FREE (ptr);
|
|
|
|
eprintf ("Error: failed to malloc memory");
|
|
|
|
goto beach;
|
|
|
|
}
|
|
|
|
for (i = 0; i < nblocks; i++) {
|
2018-01-03 22:06:15 +05:30
|
|
|
ut64 off = from + (blocksize * (i + skipblocks));
|
2018-05-21 23:06:00 +02:00
|
|
|
r_io_read_at (core->io, off, p, blocksize);
|
2018-04-11 10:17:43 +03:00
|
|
|
ptr[i] = (ut8) (255 * r_hash_entropy_fraction (p, blocksize));
|
2017-07-18 01:24:46 -07:00
|
|
|
}
|
|
|
|
free (p);
|
2018-01-03 22:06:15 +05:30
|
|
|
r_print_columns (core->print, ptr, nblocks, 14);
|
2017-07-18 01:24:46 -07:00
|
|
|
}
|
2017-05-16 03:08:15 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
r_print_columns (core->print, core->block, core->blocksize, 14);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2018-08-13 11:45:54 +02:00
|
|
|
case '2': // "p=2"
|
|
|
|
{
|
|
|
|
short *word = (short*) core->block;
|
|
|
|
int i, words = core->blocksize / 2;
|
|
|
|
int step = r_num_math (core->num, input + 2);
|
|
|
|
ut64 oldword = 0;
|
|
|
|
for (i = 0; i<words; i++) {
|
|
|
|
ut64 word64 = word[i] + ST16_MAX;
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" %8d ", core->offset + (i *2), word[i]);
|
|
|
|
r_print_progressbar (core->print, word64 * 100 / UT16_MAX, 60);
|
2020-10-13 16:26:15 +02:00
|
|
|
r_cons_printf (" %" PFMT64d, word64 - oldword);
|
2018-08-13 11:45:54 +02:00
|
|
|
oldword = word64;
|
|
|
|
r_cons_newline ();
|
|
|
|
i += step;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2017-03-29 04:23:14 +02:00
|
|
|
case 'd': // "p=d"
|
2017-09-02 01:45:50 -07:00
|
|
|
ptr = NULL;
|
|
|
|
if (input[2]) {
|
2017-01-11 00:22:18 +01:00
|
|
|
ut64 bufsz = r_num_math (core->num, input + 3);
|
|
|
|
ut64 curbsz = core->blocksize;
|
2017-01-11 00:45:35 +01:00
|
|
|
if (bufsz < 1) {
|
|
|
|
bufsz = curbsz;
|
|
|
|
}
|
2017-01-11 00:22:18 +01:00
|
|
|
if (bufsz > core->blocksize) {
|
|
|
|
r_core_block_size (core, bufsz);
|
2017-01-11 00:45:35 +01:00
|
|
|
r_core_block_read (core);
|
2017-01-11 00:22:18 +01:00
|
|
|
}
|
|
|
|
cmd_print_eq_dict (core, core->block, bufsz);
|
|
|
|
if (bufsz != curbsz) {
|
|
|
|
r_core_block_size (core, curbsz);
|
|
|
|
}
|
2017-01-11 00:45:35 +01:00
|
|
|
} else {
|
|
|
|
cmd_print_eq_dict (core, core->block, core->blocksize);
|
|
|
|
}
|
2017-01-11 00:22:18 +01:00
|
|
|
break;
|
2017-03-29 04:23:14 +02:00
|
|
|
case 'j': // "p=j" cjmp and jmp
|
2019-09-01 19:42:39 +05:30
|
|
|
case 'A': // "p=A" anal info
|
2019-05-07 11:59:38 +02:00
|
|
|
case 'a': // "p=a" bb info
|
2017-03-29 04:23:14 +02:00
|
|
|
case 'c': // "p=c" calls
|
|
|
|
case 'i': // "p=i" invalid
|
|
|
|
case 's': // "p=s" syscalls
|
2019-05-07 11:59:38 +02:00
|
|
|
if ((ptr = analBars (core, mode, nblocks, blocksize, skipblocks, from))) {
|
2017-03-29 04:23:14 +02:00
|
|
|
print_bars = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
{
|
|
|
|
ut8 *p;
|
|
|
|
int j, i = 0;
|
|
|
|
ptr = calloc (1, nblocks);
|
|
|
|
if (!ptr) {
|
|
|
|
eprintf ("Error: failed to malloc memory");
|
|
|
|
goto beach;
|
|
|
|
}
|
|
|
|
p = malloc (blocksize);
|
|
|
|
if (!p) {
|
|
|
|
R_FREE (ptr);
|
|
|
|
eprintf ("Error: failed to malloc memory");
|
|
|
|
goto beach;
|
|
|
|
}
|
|
|
|
for (i = 0; i < nblocks; i++) {
|
2018-01-03 22:06:15 +05:30
|
|
|
ut64 off = from + (blocksize * (i + skipblocks));
|
2017-03-29 04:23:14 +02:00
|
|
|
for (j = 0; j < blocksize; j++) {
|
|
|
|
if (r_flag_get_at (core->flags, off + j, false)) {
|
|
|
|
matchBar (ptr, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free (p);
|
|
|
|
print_bars = true;
|
|
|
|
}
|
|
|
|
break;
|
2016-04-01 00:02:56 +02:00
|
|
|
case 'e': // "p=e" entropy
|
2017-03-09 23:29:48 +01:00
|
|
|
{
|
|
|
|
ut8 *p;
|
|
|
|
int i = 0;
|
|
|
|
ptr = calloc (1, nblocks);
|
|
|
|
if (!ptr) {
|
|
|
|
eprintf ("Error: failed to malloc memory");
|
|
|
|
goto beach;
|
2016-03-11 12:19:37 +01:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
p = malloc (blocksize);
|
|
|
|
if (!p) {
|
|
|
|
R_FREE (ptr);
|
|
|
|
eprintf ("Error: failed to malloc memory");
|
|
|
|
goto beach;
|
|
|
|
}
|
|
|
|
for (i = 0; i < nblocks; i++) {
|
2018-01-03 22:06:15 +05:30
|
|
|
ut64 off = from + (blocksize * (i + skipblocks));
|
2018-05-21 23:06:00 +02:00
|
|
|
r_io_read_at (core->io, off, p, blocksize);
|
2018-04-11 10:17:43 +03:00
|
|
|
ptr[i] = (ut8) (255 * r_hash_entropy_fraction (p, blocksize));
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
free (p);
|
|
|
|
print_bars = true;
|
|
|
|
}
|
|
|
|
break;
|
2017-03-30 09:14:31 +02:00
|
|
|
case '0': // 0x00 bytes
|
|
|
|
case 'F': // 0xff bytes
|
|
|
|
case 'p': // printable chars
|
|
|
|
case 'z': // zero terminated strings
|
2020-04-07 23:46:16 -04:00
|
|
|
{
|
2017-03-09 23:29:48 +01:00
|
|
|
ut8 *p;
|
2017-08-29 12:39:49 +02:00
|
|
|
ut64 i, j, k;
|
2017-03-09 23:29:48 +01:00
|
|
|
ptr = calloc (1, nblocks);
|
|
|
|
if (!ptr) {
|
|
|
|
eprintf ("Error: failed to malloc memory");
|
|
|
|
goto beach;
|
|
|
|
}
|
|
|
|
p = calloc (1, blocksize);
|
|
|
|
if (!p) {
|
|
|
|
R_FREE (ptr);
|
|
|
|
eprintf ("Error: failed to malloc memory");
|
|
|
|
goto beach;
|
|
|
|
}
|
2017-03-29 04:23:14 +02:00
|
|
|
int len = 0;
|
2017-03-09 23:29:48 +01:00
|
|
|
for (i = 0; i < nblocks; i++) {
|
2018-01-03 22:06:15 +05:30
|
|
|
ut64 off = from + blocksize * (i + skipblocks);
|
2018-05-21 23:06:00 +02:00
|
|
|
r_io_read_at (core->io, off, p, blocksize);
|
2017-03-09 23:29:48 +01:00
|
|
|
for (j = k = 0; j < blocksize; j++) {
|
|
|
|
switch (mode) {
|
|
|
|
case '0':
|
|
|
|
if (!p[j]) {
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
if (p[j] == 0xff) {
|
|
|
|
k++;
|
2016-09-06 05:17:44 +02:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
break;
|
2017-03-29 04:42:01 +02:00
|
|
|
case 'z':
|
2017-03-29 04:23:14 +02:00
|
|
|
if ((IS_PRINTABLE (p[j]))) {
|
2019-04-22 11:31:17 +02:00
|
|
|
if ((j + 1) < blocksize && p[j + 1] == 0) {
|
2017-03-30 09:14:31 +02:00
|
|
|
k++;
|
|
|
|
j++;
|
2017-03-29 04:23:14 +02:00
|
|
|
}
|
|
|
|
if (len++ > 8) {
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
len = 0;
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
break;
|
2017-03-30 09:14:31 +02:00
|
|
|
case 'p':
|
|
|
|
if ((IS_PRINTABLE (p[j]))) {
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
break;
|
2016-03-11 12:19:37 +01:00
|
|
|
}
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
ptr[i] = 256 * k / blocksize;
|
2016-03-11 12:19:37 +01:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
free (p);
|
|
|
|
print_bars = true;
|
|
|
|
}
|
|
|
|
break;
|
2016-03-11 12:19:37 +01:00
|
|
|
case 'b': // bytes
|
|
|
|
case '\0':
|
2018-01-03 22:06:15 +05:30
|
|
|
ptr = calloc (1, nblocks);
|
2018-05-21 23:06:00 +02:00
|
|
|
r_io_read_at (core->io, from, ptr, nblocks);
|
2016-03-13 02:31:13 +01:00
|
|
|
// TODO: support print_bars
|
2018-01-03 22:06:15 +05:30
|
|
|
r_print_fill (core->print, ptr, nblocks, from, blocksize);
|
2016-09-19 00:47:38 +02:00
|
|
|
R_FREE (ptr);
|
2016-03-13 02:31:13 +01:00
|
|
|
break;
|
2016-03-11 12:19:37 +01:00
|
|
|
}
|
|
|
|
if (print_bars) {
|
2020-09-09 15:50:37 +02:00
|
|
|
bool hex_offset = r_config_get_i (core->config, "hex.offset");
|
|
|
|
if (hex_offset) {
|
|
|
|
core->print->flags |= R_PRINT_FLAGS_OFFSET;
|
|
|
|
} else {
|
|
|
|
core->print->flags &= ~R_PRINT_FLAGS_OFFSET;
|
|
|
|
}
|
2016-03-11 12:19:37 +01:00
|
|
|
int i;
|
2016-03-13 01:28:19 +01:00
|
|
|
switch (submode) {
|
2019-02-25 16:00:12 +05:30
|
|
|
case 'j': {
|
|
|
|
PJ *pj = pj_new ();
|
|
|
|
if (!pj) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pj_o (pj);
|
|
|
|
pj_kn (pj, "blocksize", blocksize);
|
|
|
|
pj_kn (pj, "address", from);
|
|
|
|
pj_kn (pj, "size", totalsize);
|
|
|
|
pj_k (pj, "entropy");
|
|
|
|
pj_a (pj);
|
|
|
|
|
2016-03-13 02:31:13 +01:00
|
|
|
for (i = 0; i < nblocks; i++) {
|
2016-03-13 01:28:19 +01:00
|
|
|
ut8 ep = ptr[i];
|
|
|
|
ut64 off = blocksize * i;
|
2018-01-03 22:06:15 +05:30
|
|
|
off += from;
|
2019-02-25 16:00:12 +05:30
|
|
|
pj_o (pj);
|
|
|
|
pj_kn (pj, "addr", off);
|
|
|
|
pj_ki (pj, "value", ep);
|
|
|
|
pj_end (pj);
|
2016-03-11 12:19:37 +01:00
|
|
|
|
|
|
|
}
|
2019-02-25 16:00:12 +05:30
|
|
|
pj_end (pj);
|
|
|
|
pj_end (pj);
|
|
|
|
r_cons_println (pj_string (pj));
|
|
|
|
pj_free (pj);
|
|
|
|
} break;
|
2016-03-11 12:19:37 +01:00
|
|
|
case 'q':
|
2016-03-13 02:31:13 +01:00
|
|
|
for (i = 0; i < nblocks; i++) {
|
2018-01-03 22:06:15 +05:30
|
|
|
ut64 off = from + (blocksize * i);
|
2017-06-28 00:24:26 +02:00
|
|
|
if (core->print->cur_enabled) {
|
|
|
|
if (i == core->print->cur) {
|
|
|
|
r_cons_printf ("> ");
|
|
|
|
core->num->value = off;
|
|
|
|
} else {
|
|
|
|
r_cons_printf (" ");
|
|
|
|
}
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("0x%08"PFMT64x " %d %d\n", off, i, ptr[i]);
|
2016-03-11 12:19:37 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2017-06-28 00:24:26 +02:00
|
|
|
core->print->num = core->num;
|
2018-01-03 22:06:15 +05:30
|
|
|
r_print_fill (core->print, ptr, nblocks, from, blocksize);
|
2016-03-11 12:19:37 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
beach:
|
2018-08-26 09:25:34 -07:00
|
|
|
r_list_free (list);
|
2017-08-29 12:39:49 +02:00
|
|
|
free (ptr);
|
2016-03-11 12:19:37 +01:00
|
|
|
}
|
|
|
|
|
2016-05-16 04:39:37 +02:00
|
|
|
static int bbcmp(RAnalBlock *a, RAnalBlock *b) {
|
|
|
|
return a->addr - b->addr;
|
|
|
|
}
|
|
|
|
|
2016-05-30 04:18:48 +02:00
|
|
|
/* TODO: integrate this into r_anal */
|
2017-03-09 23:29:48 +01:00
|
|
|
static void _pointer_table(RCore *core, ut64 origin, ut64 offset, const ut8 *buf, int len, int step, int mode) {
|
2016-05-30 04:18:48 +02:00
|
|
|
int i;
|
|
|
|
ut64 addr;
|
|
|
|
st32 *delta; // only for step == 4
|
2017-03-09 23:29:48 +01:00
|
|
|
if (step < 1) {
|
2016-05-30 04:18:48 +02:00
|
|
|
step = 4;
|
|
|
|
}
|
2017-08-30 23:11:53 +02:00
|
|
|
if (!r_io_is_valid_offset (core->io, origin, 0) ||
|
2017-09-12 11:45:37 +01:00
|
|
|
!r_io_is_valid_offset (core->io, offset, 0)) {
|
2017-08-30 23:04:40 +02:00
|
|
|
return;
|
|
|
|
}
|
2016-05-30 04:18:48 +02:00
|
|
|
if (origin != offset) {
|
|
|
|
switch (mode) {
|
|
|
|
case '*':
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("CC-@ 0x%08"PFMT64x "\n", origin);
|
|
|
|
r_cons_printf ("CC switch table @ 0x%08"PFMT64x "\n", origin);
|
|
|
|
r_cons_printf ("axd 0x%"PFMT64x " 0x%08"PFMT64x "\n", origin, offset);
|
2016-05-30 04:18:48 +02:00
|
|
|
break;
|
|
|
|
case '.':
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_cmdf (core, "CC-@ 0x%08"PFMT64x "\n", origin);
|
|
|
|
r_core_cmdf (core, "CC switch table @ 0x%08"PFMT64x "\n", origin);
|
2017-05-23 23:55:22 +02:00
|
|
|
r_core_cmdf (core, "f switch.0x%08"PFMT64x"=0x%08"PFMT64x"\n", origin, origin);
|
|
|
|
r_core_cmdf (core, "f jmptbl.0x%08"PFMT64x"=0x%08"PFMT64x"\n", offset, offset); //origin, origin);
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_cmdf (core, "axd 0x%"PFMT64x " 0x%08"PFMT64x "\n", origin, offset);
|
2016-05-30 04:18:48 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (mode == '.') {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_cmdf (core, "CC-@ 0x%08"PFMT64x "\n", origin);
|
2017-05-23 23:55:22 +02:00
|
|
|
r_core_cmdf (core, "CC switch basic block @ 0x%08"PFMT64x "\n", offset);
|
|
|
|
r_core_cmdf (core, "f switch.0x%08"PFMT64x"=0x%08"PFMT64x"\n", offset, offset); // basic block @ 0x%08"PFMT64x "\n", offset);
|
2016-05-30 04:18:48 +02:00
|
|
|
}
|
2017-05-23 23:55:22 +02:00
|
|
|
int n = 0;
|
2017-12-23 02:54:58 +01:00
|
|
|
for (i = 0; (i + sizeof (st32)) <= len; i += step, n++) {
|
2017-03-09 23:29:48 +01:00
|
|
|
delta = (st32 *) (buf + i);
|
2016-05-30 04:18:48 +02:00
|
|
|
addr = offset + *delta;
|
2017-08-23 22:19:57 +00:00
|
|
|
if (!r_io_is_valid_offset (core->io, addr, 0)) {
|
2018-03-07 18:26:31 +08:00
|
|
|
// Lets check for jmptbl with not relative addresses
|
|
|
|
// Like: jmp dword [eax*4 + jmptbl.0x5435345]
|
|
|
|
if (!r_io_is_valid_offset (core->io, *delta, 0)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
addr = *delta;
|
2016-05-30 04:18:48 +02:00
|
|
|
}
|
|
|
|
if (mode == '*') {
|
2018-03-07 18:26:31 +08:00
|
|
|
r_cons_printf ("af case.%d.0x%"PFMT64x " 0x%08"PFMT64x "\n", n, offset, addr);
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("ax 0x%"PFMT64x " 0x%08"PFMT64x "\n", offset, addr);
|
|
|
|
r_cons_printf ("ax 0x%"PFMT64x " 0x%08"PFMT64x "\n", addr, offset); // wrong, but useful because forward xrefs dont work :?
|
2017-05-23 23:55:22 +02:00
|
|
|
r_cons_printf ("aho case 0x%"PFMT64x " 0x%08"PFMT64x " @ 0x%08"PFMT64x "\n", (ut64)i, addr, offset + i); // wrong, but useful because forward xrefs dont work :?
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("ahs %d @ 0x%08"PFMT64x "\n", step, offset + i);
|
2016-05-30 04:18:48 +02:00
|
|
|
} else if (mode == '.') {
|
2017-05-23 23:55:22 +02:00
|
|
|
r_core_cmdf (core, "af case.%d.0x%"PFMT64x " @ 0x%08"PFMT64x "\n", n, offset, addr);
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_cmdf (core, "ax 0x%"PFMT64x " 0x%08"PFMT64x "\n", offset, addr);
|
|
|
|
r_core_cmdf (core, "ax 0x%"PFMT64x " 0x%08"PFMT64x "\n", addr, offset); // wrong, but useful because forward xrefs dont work :?
|
2017-05-23 23:55:22 +02:00
|
|
|
// r_core_cmdf (core, "CC+ case %d: 0x%08"PFMT64x " @ 0x%08"PFMT64x "\n", i / step, addr, origin);
|
|
|
|
r_core_cmdf (core, "CCu case %d: @ 0x%08"PFMT64x "\n", n, addr); //, origin);
|
|
|
|
r_core_cmdf (core, "aho case %d 0x%08"PFMT64x " @ 0x%08"PFMT64x "\n", n, addr, offset + i); // wrong, but useful because forward xrefs dont work :?
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_cmdf (core, "ahs %d @ 0x%08"PFMT64x "\n", step, offset + i);
|
2016-05-30 04:18:48 +02:00
|
|
|
} else {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("0x%08"PFMT64x " -> 0x%08"PFMT64x "\n", offset + i, addr);
|
2016-05-30 04:18:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-22 12:58:37 +02:00
|
|
|
static void __printPattern(RCore *core, const char *_input) {
|
|
|
|
char *input = strdup (_input);
|
|
|
|
const char *arg = r_str_nextword (input, ' ');
|
|
|
|
size_t i, j;
|
2019-06-29 03:12:18 +02:00
|
|
|
st64 len = arg? r_num_math (core->num, arg): core->blocksize;
|
|
|
|
if (len < 1) {
|
|
|
|
eprintf ("Invalid length\n");
|
|
|
|
return;
|
|
|
|
}
|
2019-06-22 12:58:37 +02:00
|
|
|
switch (input[0]) {
|
|
|
|
case 'd': // "ppd"
|
|
|
|
// debruijn pattern
|
|
|
|
{
|
|
|
|
ut8 *buf = (ut8*)r_debruijn_pattern (len, 0, NULL);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
r_cons_printf ("%02x", buf[i]);
|
|
|
|
}
|
|
|
|
r_cons_newline ();
|
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '1': // "pp1"
|
|
|
|
// incremental byte sequence
|
|
|
|
{
|
|
|
|
int min = (core->offset & 0xff);
|
|
|
|
for (i = 0; i < len; i++) {
|
2020-10-13 16:26:15 +02:00
|
|
|
r_cons_printf ("%02zx", i + min);
|
2019-06-22 12:58:37 +02:00
|
|
|
}
|
|
|
|
r_cons_newline ();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '2': // "pp2"
|
|
|
|
// incremental half word sequences
|
|
|
|
{
|
|
|
|
// TODO: honor cfg.bigendian
|
|
|
|
int min = (core->offset & 0xffff);
|
|
|
|
for (i = 0; i < len; i++) {
|
2020-10-13 16:26:15 +02:00
|
|
|
r_cons_printf ("%04zx", i + min);
|
2019-06-22 12:58:37 +02:00
|
|
|
}
|
|
|
|
r_cons_newline ();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '4': // "pp4"
|
|
|
|
// incremental half word sequences
|
|
|
|
{
|
|
|
|
// TODO: honor cfg.bigendian
|
|
|
|
int min = (core->offset & UT32_MAX);
|
|
|
|
for (i = 0; i < len; i++) {
|
2020-10-13 16:26:15 +02:00
|
|
|
r_cons_printf ("%08zx", i + min);
|
2019-06-22 12:58:37 +02:00
|
|
|
}
|
|
|
|
r_cons_newline ();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '8': // "pp8"
|
|
|
|
// incremental half word sequences
|
|
|
|
{
|
|
|
|
// TODO: honor cfg.bigendian
|
|
|
|
ut64 min = (core->offset);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
r_cons_printf ("%016"PFMT64x, i + min);
|
|
|
|
}
|
|
|
|
r_cons_newline ();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'f': // "ppf"
|
|
|
|
// zero ssled
|
|
|
|
{
|
|
|
|
ut8 *buf = (ut8*)r_debruijn_pattern (len, 0, NULL);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
r_cons_printf ("%02x", 0xff);
|
|
|
|
}
|
|
|
|
r_cons_newline ();
|
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '0': // "pp0"
|
|
|
|
// zero ssled
|
|
|
|
{
|
|
|
|
ut8 *buf = (ut8*)r_debruijn_pattern (len, 0, NULL);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
r_cons_printf ("%02x", 0);
|
|
|
|
}
|
|
|
|
r_cons_newline ();
|
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
// TODO
|
|
|
|
{
|
|
|
|
i = core->offset;
|
|
|
|
size_t bs = 4; // XXX hardcoded
|
|
|
|
ut8 *buf = calloc (bs, 1);
|
|
|
|
// for (;i>0;i--) { incDigitBuffer (buf, bs); }
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
incAlphaBuffer (buf, bs);
|
|
|
|
for (j = 0; j < bs; j++) {
|
|
|
|
r_cons_printf ("%c", buf[j]?buf[j]:'A');
|
|
|
|
}
|
|
|
|
r_cons_printf (" ");
|
|
|
|
}
|
|
|
|
r_cons_newline ();
|
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'n': // "ppn"
|
|
|
|
{
|
|
|
|
i = core->offset;
|
|
|
|
size_t bs = 4; // XXX hardcoded
|
|
|
|
ut8 *buf = calloc (bs, 1);
|
|
|
|
// for (;i>0;i--) { incDigitBuffer (buf, bs); }
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
incDigitBuffer (buf, bs);
|
|
|
|
for (j = 0; j < bs; j++) {
|
|
|
|
r_cons_printf ("%c", buf[j]?buf[j]:'0');
|
|
|
|
}
|
|
|
|
r_cons_printf (" ");
|
|
|
|
}
|
|
|
|
r_cons_newline ();
|
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
r_core_cmd_help (core, help_msg_pp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
free (input);
|
|
|
|
}
|
|
|
|
|
2017-11-30 15:45:27 +01:00
|
|
|
static void pr_bb(RCore *core, RAnalFunction *fcn, RAnalBlock *b, bool emu, ut64 saved_gp, ut8 *saved_arena, char p_type, bool fromHere) {
|
2017-11-29 18:56:12 +01:00
|
|
|
bool show_flags = r_config_get_i (core->config, "asm.flags");
|
2018-11-04 02:59:10 +08:00
|
|
|
const char *orig_bb_middle = r_config_get (core->config, "asm.bb.middle");
|
2016-10-24 14:31:03 +02:00
|
|
|
core->anal->gp = saved_gp;
|
2017-11-30 15:45:27 +01:00
|
|
|
if (fromHere) {
|
|
|
|
if (b->addr < core->offset) {
|
|
|
|
core->cons->null = true;
|
|
|
|
} else {
|
|
|
|
core->cons->null = false;
|
|
|
|
}
|
|
|
|
}
|
2016-10-24 14:31:03 +02:00
|
|
|
if (emu) {
|
|
|
|
if (b->parent_reg_arena) {
|
|
|
|
ut64 gp;
|
|
|
|
r_reg_arena_poke (core->anal->reg, b->parent_reg_arena);
|
|
|
|
R_FREE (b->parent_reg_arena);
|
|
|
|
gp = r_reg_getv (core->anal->reg, "gp");
|
|
|
|
if (gp) {
|
|
|
|
core->anal->gp = gp;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
r_reg_arena_poke (core->anal->reg, saved_arena);
|
|
|
|
}
|
|
|
|
}
|
2017-01-31 10:00:24 +01:00
|
|
|
if (b->parent_stackptr != INT_MAX) {
|
|
|
|
core->anal->stackptr = b->parent_stackptr;
|
|
|
|
}
|
2018-11-04 02:59:10 +08:00
|
|
|
r_config_set_i (core->config, "asm.bb.middle", false);
|
2016-12-05 19:41:37 +01:00
|
|
|
p_type == 'D'
|
2020-01-15 10:54:37 +01:00
|
|
|
? r_core_cmdf (core, "pD %"PFMT64u" @0x%"PFMT64x, b->size, b->addr)
|
|
|
|
: r_core_cmdf (core, "pI %"PFMT64u" @0x%"PFMT64x, b->size, b->addr);
|
2018-11-04 02:59:10 +08:00
|
|
|
r_config_set (core->config, "asm.bb.middle", orig_bb_middle);
|
2016-12-05 19:41:37 +01:00
|
|
|
|
2016-10-24 14:31:03 +02:00
|
|
|
if (b->jump != UT64_MAX) {
|
2017-01-31 10:00:24 +01:00
|
|
|
if (b->jump > b->addr) {
|
2020-02-13 20:40:37 +01:00
|
|
|
RAnalBlock *jumpbb = r_anal_get_block_at (b->anal, b->jump);
|
|
|
|
if (jumpbb && r_list_contains (jumpbb->fcns, fcn)) {
|
2018-01-08 03:05:43 +01:00
|
|
|
if (emu && core->anal->last_disasm_reg && !jumpbb->parent_reg_arena) {
|
2017-01-31 10:00:24 +01:00
|
|
|
jumpbb->parent_reg_arena = r_reg_arena_dup (core->anal->reg, core->anal->last_disasm_reg);
|
|
|
|
}
|
|
|
|
if (jumpbb->parent_stackptr == INT_MAX) {
|
|
|
|
jumpbb->parent_stackptr = core->anal->stackptr + b->stackptr;
|
|
|
|
}
|
2016-10-24 14:31:03 +02:00
|
|
|
}
|
|
|
|
}
|
2017-11-29 18:56:12 +01:00
|
|
|
if (p_type == 'D' && show_flags) {
|
2016-12-05 19:41:37 +01:00
|
|
|
r_cons_printf ("| ----------- true: 0x%08"PFMT64x, b->jump);
|
|
|
|
}
|
2016-10-24 14:31:03 +02:00
|
|
|
}
|
|
|
|
if (b->fail != UT64_MAX) {
|
2017-01-31 10:00:24 +01:00
|
|
|
if (b->fail > b->addr) {
|
2020-02-13 20:40:37 +01:00
|
|
|
RAnalBlock *failbb = r_anal_get_block_at (b->anal, b->fail);
|
|
|
|
if (failbb && r_list_contains (failbb->fcns, fcn)) {
|
2018-01-08 03:05:43 +01:00
|
|
|
if (emu && core->anal->last_disasm_reg && !failbb->parent_reg_arena) {
|
2017-01-31 10:00:24 +01:00
|
|
|
failbb->parent_reg_arena = r_reg_arena_dup (core->anal->reg, core->anal->last_disasm_reg);
|
|
|
|
}
|
|
|
|
if (failbb->parent_stackptr == INT_MAX) {
|
|
|
|
failbb->parent_stackptr = core->anal->stackptr + b->stackptr;
|
|
|
|
}
|
2016-10-24 14:31:03 +02:00
|
|
|
}
|
|
|
|
}
|
2017-11-29 18:56:12 +01:00
|
|
|
if (p_type == 'D' && show_flags) {
|
2016-12-05 19:41:37 +01:00
|
|
|
r_cons_printf (" false: 0x%08"PFMT64x, b->fail);
|
|
|
|
}
|
|
|
|
}
|
2017-11-29 18:56:12 +01:00
|
|
|
if (p_type == 'D' && show_flags) {
|
2016-12-05 19:41:37 +01:00
|
|
|
r_cons_newline ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-27 02:56:56 +01:00
|
|
|
#if 0
|
|
|
|
dsmap {
|
|
|
|
r_itv_t addr;
|
|
|
|
ut64 size;
|
|
|
|
ut8 *dis;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-01-18 11:58:49 +01:00
|
|
|
#define P(x) (core->cons && core->cons->context->pal.x)? core->cons->context->pal.x
|
2018-03-14 15:31:08 +01:00
|
|
|
|
2019-04-25 11:13:20 +02:00
|
|
|
static void disasm_until_ret(RCore *core, ut64 addr, char type_print, const char *arg) {
|
2018-04-09 02:23:44 +02:00
|
|
|
int p = 0;
|
2019-04-25 11:13:20 +02:00
|
|
|
const bool show_color = core->print->flags & R_PRINT_FLAGS_COLOR;
|
|
|
|
int i, limit = 1024;
|
|
|
|
if (arg && *arg && arg[1]) {
|
|
|
|
limit = r_num_math (core->num, arg + 1);
|
2018-04-09 02:23:44 +02:00
|
|
|
}
|
2019-04-25 11:13:20 +02:00
|
|
|
for (i = 0; i < limit; i++) {
|
|
|
|
RAnalOp *op = r_core_anal_op (core, addr, R_ANAL_OP_MASK_BASIC | R_ANAL_OP_MASK_DISASM);
|
2018-04-09 02:23:44 +02:00
|
|
|
if (op) {
|
2019-04-25 11:13:20 +02:00
|
|
|
char *mnem = op->mnemonic;
|
|
|
|
char *m = malloc ((strlen (mnem) * 2) + 32);
|
|
|
|
strcpy (m, mnem);
|
2019-04-29 18:08:43 +03:00
|
|
|
//r_parse_parse (core->parser, op->mnemonic, m);
|
2019-04-25 11:13:20 +02:00
|
|
|
if (type_print == 'q') {
|
|
|
|
r_cons_printf ("%s\n", m);
|
|
|
|
} else {
|
|
|
|
if (show_color) {
|
|
|
|
const char *offsetColor = r_cons_singleton ()->context->pal.offset; // TODO etooslow. must cache
|
|
|
|
r_cons_printf ("%s0x%08"PFMT64x""Color_RESET" %10s %s\n",
|
|
|
|
offsetColor, addr + p, "", m);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" %10s %s\n", addr + p, "", m);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (op->type & 0xfffff) {
|
|
|
|
case R_ANAL_OP_TYPE_RET:
|
|
|
|
case R_ANAL_OP_TYPE_UJMP:
|
|
|
|
goto beach;
|
2018-04-09 02:23:44 +02:00
|
|
|
break;
|
2019-04-25 11:13:20 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
if (op->type == R_ANAL_OP_TYPE_JMP) {
|
|
|
|
addr = op->jump;
|
|
|
|
} else {
|
|
|
|
addr += op->size;
|
2018-04-09 02:23:44 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
eprintf ("[pdp] Cannot get op at 0x%08"PFMT64x"\n", addr + p);
|
|
|
|
r_anal_op_free (op);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
//r_io_read_at (core->io, n, rbuf, 512);
|
|
|
|
r_anal_op_free (op);
|
|
|
|
}
|
2019-04-25 11:13:20 +02:00
|
|
|
beach:
|
|
|
|
return;
|
2018-04-09 02:23:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void disasm_ropchain(RCore *core, ut64 addr, char type_print) {
|
|
|
|
int p = 0;
|
|
|
|
ut64 n = 0;
|
|
|
|
ut8 *buf = calloc (core->blocksize, 1);
|
|
|
|
(void)r_io_read_at (core->io, addr, buf, core->blocksize);
|
|
|
|
while (p + 4 < core->blocksize) {
|
2019-04-25 11:13:20 +02:00
|
|
|
const bool be = core->print->big_endian;
|
2020-05-13 01:28:23 +02:00
|
|
|
if (core->rasm->bits == 64) {
|
2019-04-25 11:13:20 +02:00
|
|
|
n = r_read_ble64 (buf + p, be);
|
2018-04-09 02:23:44 +02:00
|
|
|
} else {
|
2019-04-25 11:13:20 +02:00
|
|
|
n = r_read_ble32 (buf + p, be);
|
2018-04-09 02:23:44 +02:00
|
|
|
}
|
|
|
|
r_cons_printf ("[0x%08"PFMT64x"] 0x%08"PFMT64x"\n", addr + p, n);
|
2019-04-25 11:13:20 +02:00
|
|
|
disasm_until_ret (core, n, type_print, NULL);
|
2020-05-13 01:28:23 +02:00
|
|
|
if (core->rasm->bits == 64) {
|
2018-04-09 02:23:44 +02:00
|
|
|
p += 8;
|
|
|
|
} else {
|
|
|
|
p += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
|
2018-05-07 22:33:19 +02:00
|
|
|
static void disasm_recursive(RCore *core, ut64 addr, int count, char type_print) {
|
2018-03-09 02:01:05 +01:00
|
|
|
RAnalOp aop = {0};
|
2018-03-12 19:01:54 +08:00
|
|
|
int ret;
|
2018-03-09 02:01:05 +01:00
|
|
|
ut8 buf[128];
|
2019-02-13 11:44:42 +01:00
|
|
|
PJ *pj = NULL;
|
2018-05-07 22:33:19 +02:00
|
|
|
if (type_print == 'j') {
|
2019-02-13 11:44:42 +01:00
|
|
|
pj = pj_new ();
|
|
|
|
if (!pj) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pj_a (pj);
|
2018-05-07 22:33:19 +02:00
|
|
|
}
|
2018-03-09 02:01:05 +01:00
|
|
|
while (count-- > 0) {
|
|
|
|
r_io_read_at (core->io, addr, buf, sizeof (buf));
|
|
|
|
r_anal_op_fini (&aop);
|
2018-05-28 10:15:53 +05:30
|
|
|
ret = r_anal_op (core->anal, &aop, addr, buf, sizeof (buf), R_ANAL_OP_MASK_BASIC);
|
2018-03-09 02:01:05 +01:00
|
|
|
if (ret < 0 || aop.size < 1) {
|
|
|
|
addr++;
|
|
|
|
continue;
|
|
|
|
}
|
2018-03-09 02:13:09 +01:00
|
|
|
// r_core_cmdf (core, "pD %d @ 0x%08"PFMT64x, aop.size, addr);
|
2018-05-07 22:33:19 +02:00
|
|
|
if (type_print == 'j') {
|
2019-02-13 11:44:42 +01:00
|
|
|
r_core_print_disasm_json (core, addr, buf, sizeof (buf), 1, pj);
|
2018-05-07 22:33:19 +02:00
|
|
|
} else {
|
|
|
|
r_core_cmdf (core, "pd 1 @ 0x%08"PFMT64x, addr);
|
|
|
|
}
|
2018-03-09 02:01:05 +01:00
|
|
|
switch (aop.type) {
|
|
|
|
case R_ANAL_OP_TYPE_JMP:
|
|
|
|
addr = aop.jump;
|
|
|
|
continue;
|
|
|
|
case R_ANAL_OP_TYPE_UCJMP:
|
|
|
|
break;
|
2018-10-26 05:43:32 -07:00
|
|
|
case R_ANAL_OP_TYPE_RET:
|
|
|
|
count = 0; // stop disassembling when hitting RET
|
|
|
|
break;
|
2019-10-23 13:23:11 +02:00
|
|
|
default:
|
|
|
|
break;
|
2018-03-09 02:01:05 +01:00
|
|
|
}
|
|
|
|
addr += aop.size;
|
|
|
|
}
|
2018-05-07 22:33:19 +02:00
|
|
|
if (type_print == 'j') {
|
2019-02-13 11:44:42 +01:00
|
|
|
pj_end (pj);
|
|
|
|
r_cons_printf ("%s\n", pj_string (pj));
|
|
|
|
pj_free (pj);
|
2018-05-07 22:33:19 +02:00
|
|
|
}
|
2018-03-09 02:01:05 +01:00
|
|
|
}
|
2018-01-27 02:56:56 +01:00
|
|
|
|
2017-11-30 15:45:27 +01:00
|
|
|
static void func_walk_blocks(RCore *core, RAnalFunction *f, char input, char type_print, bool fromHere) {
|
2016-12-05 19:41:37 +01:00
|
|
|
RListIter *iter;
|
2018-05-26 19:09:15 +02:00
|
|
|
RAnalBlock *b = NULL;
|
2018-11-16 23:38:36 +08:00
|
|
|
const char *orig_bb_middle = r_config_get (core->config, "asm.bb.middle");
|
|
|
|
r_config_set_i (core->config, "asm.bb.middle", false);
|
2019-02-13 11:44:42 +01:00
|
|
|
PJ *pj = NULL;
|
2017-01-31 10:00:24 +01:00
|
|
|
|
2016-12-05 19:41:37 +01:00
|
|
|
// XXX: hack must be reviewed/fixed in code analysis
|
2018-11-15 23:35:50 +08:00
|
|
|
if (!b) {
|
|
|
|
if (r_list_length (f->bbs) >= 1) {
|
2020-01-15 10:58:30 +01:00
|
|
|
ut32 fcn_size = r_anal_function_realsize (f);
|
2018-05-26 20:26:09 +02:00
|
|
|
b = r_list_get_top (f->bbs);
|
|
|
|
if (b->size > fcn_size) {
|
|
|
|
b->size = fcn_size;
|
|
|
|
}
|
2016-12-05 19:41:37 +01:00
|
|
|
}
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
r_list_sort (f->bbs, (RListComparator) bbcmp);
|
2018-05-26 20:26:09 +02:00
|
|
|
if (input == 'j' && b) {
|
2019-02-13 11:44:42 +01:00
|
|
|
pj = pj_new ();
|
|
|
|
if (!pj) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pj_a (pj);
|
2016-12-05 19:41:37 +01:00
|
|
|
r_list_foreach (f->bbs, iter, b) {
|
2017-11-30 15:45:27 +01:00
|
|
|
if (fromHere) {
|
|
|
|
if (b->addr < core->offset) {
|
|
|
|
core->cons->null = true;
|
|
|
|
} else {
|
|
|
|
core->cons->null = false;
|
|
|
|
}
|
|
|
|
}
|
2017-02-05 02:44:42 +01:00
|
|
|
ut8 *buf = malloc (b->size);
|
|
|
|
if (buf) {
|
|
|
|
r_io_read_at (core->io, b->addr, buf, b->size);
|
2019-02-13 11:44:42 +01:00
|
|
|
r_core_print_disasm_json (core, b->addr, buf, b->size, 0, pj);
|
2017-02-05 02:44:42 +01:00
|
|
|
free (buf);
|
|
|
|
} else {
|
2020-01-15 10:54:37 +01:00
|
|
|
eprintf ("cannot allocate %"PFMT64u" byte(s)\n", b->size);
|
2017-02-05 02:44:42 +01:00
|
|
|
}
|
2016-12-05 19:41:37 +01:00
|
|
|
}
|
2019-02-13 11:44:42 +01:00
|
|
|
pj_end (pj);
|
2020-03-29 18:07:44 +02:00
|
|
|
r_cons_printf ("%s\n", pj_string (pj));
|
2019-02-13 11:44:42 +01:00
|
|
|
pj_free (pj);
|
2016-12-05 19:41:37 +01:00
|
|
|
} else {
|
2018-06-04 16:03:58 +02:00
|
|
|
bool asm_lines = r_config_get_i (core->config, "asm.lines.bb");
|
2016-12-05 19:41:37 +01:00
|
|
|
bool emu = r_config_get_i (core->config, "asm.emu");
|
2016-12-09 15:39:48 +01:00
|
|
|
ut64 saved_gp = 0;
|
2017-02-05 02:01:53 +00:00
|
|
|
ut8 *saved_arena = NULL;
|
2017-01-31 10:00:24 +01:00
|
|
|
int saved_stackptr = core->anal->stackptr;
|
2016-12-05 19:41:37 +01:00
|
|
|
if (emu) {
|
|
|
|
saved_gp = core->anal->gp;
|
|
|
|
saved_arena = r_reg_arena_peek (core->anal->reg);
|
|
|
|
}
|
2018-06-04 16:03:58 +02:00
|
|
|
r_config_set_i (core->config, "asm.lines.bb", 0);
|
2016-12-05 19:41:37 +01:00
|
|
|
r_list_foreach (f->bbs, iter, b) {
|
2017-11-30 15:45:27 +01:00
|
|
|
pr_bb (core, f, b, emu, saved_gp, saved_arena, type_print, fromHere);
|
2016-12-05 19:41:37 +01:00
|
|
|
}
|
|
|
|
if (emu) {
|
|
|
|
core->anal->gp = saved_gp;
|
|
|
|
if (saved_arena) {
|
|
|
|
r_reg_arena_poke (core->anal->reg, saved_arena);
|
|
|
|
R_FREE (saved_arena);
|
|
|
|
}
|
|
|
|
}
|
2017-01-31 10:00:24 +01:00
|
|
|
core->anal->stackptr = saved_stackptr;
|
2018-06-04 16:03:58 +02:00
|
|
|
r_config_set_i (core->config, "asm.lines.bb", asm_lines);
|
2016-10-24 14:31:03 +02:00
|
|
|
}
|
2018-11-16 23:38:36 +08:00
|
|
|
r_config_set (core->config, "asm.bb.middle", orig_bb_middle);
|
2016-10-24 14:31:03 +02:00
|
|
|
}
|
|
|
|
|
2018-11-11 16:18:18 -08:00
|
|
|
static inline char cmd_pxb_p(char input) {
|
2017-03-08 14:34:19 +03:00
|
|
|
return IS_PRINTABLE (input)? input: '.';
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int cmd_pxb_k(const ut8 *buffer, int x) {
|
|
|
|
return buffer[3 - x] << (8 * x);
|
|
|
|
}
|
|
|
|
|
2019-06-13 18:18:35 +02:00
|
|
|
static void print_json_string(RCore *core, const char* block, int len, const char* type) {
|
|
|
|
const char* section_name = r_core_get_section_name (core, core->offset);
|
|
|
|
if (section_name && strlen (section_name) < 1) {
|
|
|
|
section_name = "unknown";
|
|
|
|
} else {
|
|
|
|
// cleaning useless spaces in section name in json data.
|
2020-03-02 21:39:37 +01:00
|
|
|
section_name = r_str_trim_head_ro (section_name);
|
2019-06-13 18:18:35 +02:00
|
|
|
char* p;
|
|
|
|
for (p = (char*) section_name; *p && *p != ' '; p++) {}
|
|
|
|
*p = '\0';
|
|
|
|
}
|
|
|
|
if (!type) {
|
|
|
|
switch (get_string_type (core->block, len)) {
|
|
|
|
case 'w': type = "wide"; break;
|
|
|
|
case 'a': type = "ascii"; break;
|
|
|
|
case 'u': type = "utf"; break;
|
|
|
|
default: type = "unknown"; break;
|
|
|
|
}
|
|
|
|
}
|
2020-03-16 13:56:47 +01:00
|
|
|
#if 0
|
|
|
|
PJ *pj = pj_new ();
|
|
|
|
pj_o (pj);
|
|
|
|
// TODO: add pj_kd for data to pass key(string) and value(data,len) instead of pj_ks which null terminates
|
|
|
|
pj_ks (pj, "string", str);
|
|
|
|
pj_kn (pj, "offset", core->offset);
|
|
|
|
pj_ks (pj, "section", section_name);
|
|
|
|
pj_ki (pj, "legnth", len);
|
|
|
|
r_cons_printf (",\"length\":%d", len);
|
|
|
|
pj_ks (pj, "type", type);
|
|
|
|
pj_end (pj);
|
|
|
|
r_cons_printf ("%s\n", pj_string (pj));
|
|
|
|
pj_free (pj);
|
|
|
|
#else
|
|
|
|
r_cons_printf ("{\"string\":");
|
|
|
|
char *str = r_str_utf16_encode (block, len); // XXX just block + len should be fine, pj takes care of this
|
|
|
|
r_cons_printf ("\"%s\"", str);
|
2019-06-13 18:18:35 +02:00
|
|
|
free (str);
|
2020-03-16 13:56:47 +01:00
|
|
|
r_cons_printf (",\"offset\":%"PFMT64u, core->offset);
|
|
|
|
r_cons_printf (",\"section\":\"%s\"", section_name);
|
|
|
|
r_cons_printf (",\"length\":%d", len);
|
|
|
|
r_cons_printf (",\"type\":\"%s\"}", type);
|
|
|
|
#endif
|
2019-06-13 18:18:35 +02:00
|
|
|
}
|
|
|
|
|
2019-10-29 18:37:27 +01:00
|
|
|
static char *__op_refs(RCore *core, RAnalOp *op, int n) {
|
|
|
|
RStrBuf *sb = r_strbuf_new ("");
|
|
|
|
if (n) {
|
|
|
|
// RList *list = r_anal_xrefs_get_from (core->anal, op->addr);
|
|
|
|
RList *list = r_anal_xrefs_get (core->anal, op->addr);
|
|
|
|
RAnalRef *ref;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (list, iter, ref) {
|
|
|
|
r_strbuf_appendf (sb, "0x%08"PFMT64x" ", ref->at);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (op->jump != UT64_MAX) {
|
|
|
|
r_strbuf_appendf (sb, "0x%08"PFMT64x" ", op->jump);
|
|
|
|
}
|
|
|
|
if (op->fail != UT64_MAX) {
|
|
|
|
r_strbuf_appendf (sb, "0x%08"PFMT64x" ", op->fail);
|
|
|
|
}
|
|
|
|
if (op->ptr != UT64_MAX) {
|
|
|
|
if (r_io_is_valid_offset (core->io, op->ptr, false)) {
|
|
|
|
r_strbuf_appendf (sb, "0x%08"PFMT64x" ", op->ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
char *res = r_strbuf_drain (sb);
|
|
|
|
r_str_trim (res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-10-28 02:09:41 +01:00
|
|
|
static void r_core_disasm_table(RCore * core, int l, const char *input) {
|
|
|
|
int i;
|
|
|
|
RTable *t = r_core_table (core);
|
|
|
|
char *arg = strchr (input, ' ');
|
|
|
|
if (arg) {
|
|
|
|
input = arg + 1;
|
|
|
|
}
|
2019-10-29 18:37:27 +01:00
|
|
|
r_table_set_columnsf (t, "snssssss", "name", "addr", "bytes", "disasm", "comment", "esil", "refs", "xrefs");
|
2019-10-28 02:09:41 +01:00
|
|
|
const int minopsz = 1;
|
2019-10-29 18:37:27 +01:00
|
|
|
const int options = R_ANAL_OP_MASK_BASIC | R_ANAL_OP_MASK_HINT | R_ANAL_OP_MASK_DISASM | R_ANAL_OP_MASK_ESIL;
|
2019-10-28 02:09:41 +01:00
|
|
|
ut64 ea = core->offset;
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
RAnalOp *op = r_core_anal_op (core, ea, options);
|
|
|
|
if (!op || op->size < 1) {
|
|
|
|
i += minopsz;
|
|
|
|
ea += minopsz;
|
|
|
|
continue;
|
|
|
|
}
|
2020-05-09 20:49:28 +02:00
|
|
|
const char *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, ea);
|
2019-10-28 02:09:41 +01:00
|
|
|
// TODO parse/filter op->mnemonic for better disasm
|
|
|
|
ut8 *bytes = malloc (op->size);
|
|
|
|
if (!bytes) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
r_io_read_at (core->io, ea, bytes, op->size); // XXX ranalop should contain the bytes like rasmop do
|
|
|
|
char *sbytes = r_hex_bin2strdup(bytes, op->size);
|
|
|
|
RFlagItem *fi = r_flag_get_i (core->flags, ea);
|
|
|
|
char *fn = fi? fi->name: "";
|
2019-10-29 18:37:27 +01:00
|
|
|
const char *esil = R_STRBUF_SAFEGET (&op->esil);
|
|
|
|
char *refs = __op_refs (core, op, 0);
|
|
|
|
char *xrefs = __op_refs (core, op, 1);
|
|
|
|
r_table_add_rowf (t, "sXssssss", fn, ea, sbytes, op->mnemonic, comment? comment: "", esil, refs, xrefs);
|
2019-10-28 02:09:41 +01:00
|
|
|
free (sbytes);
|
|
|
|
free (bytes);
|
2019-10-29 18:37:27 +01:00
|
|
|
free (xrefs);
|
|
|
|
free (refs);
|
2019-10-28 02:09:41 +01:00
|
|
|
ea += op->size;
|
|
|
|
r_anal_op_free (op);
|
|
|
|
}
|
|
|
|
if (input && *input) {
|
|
|
|
r_table_query (t, input);
|
|
|
|
}
|
|
|
|
char *ts = r_table_tostring (t);
|
|
|
|
r_cons_printf ("%s", ts); // \n?
|
|
|
|
free (ts);
|
|
|
|
r_table_free (t);
|
|
|
|
}
|
|
|
|
|
2020-10-25 12:35:45 +01:00
|
|
|
static void cmd_pxr(RCore *core, int len, int mode, int wordsize, const char *arg) {
|
|
|
|
PJ *pj = NULL;
|
|
|
|
RTable *t = NULL;
|
|
|
|
if (mode == ',') {
|
|
|
|
t = r_table_new ();
|
|
|
|
RTableColumnType *n = r_table_type ("number");
|
|
|
|
RTableColumnType *s = r_table_type ("string");
|
|
|
|
r_table_add_column (t, n, "addr", 0);
|
|
|
|
r_table_add_column (t, n, "value", 0);
|
|
|
|
r_table_add_column (t, s, "refs", 0);
|
|
|
|
}
|
|
|
|
if (mode == 'j') {
|
|
|
|
pj = pj_new ();
|
|
|
|
if (!pj) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mode == 'j' || mode == ',' || mode == '*' || mode == 'q') {
|
|
|
|
size_t i;
|
|
|
|
const int base = core->anal->bits;
|
|
|
|
const int be = core->anal->big_endian;
|
|
|
|
if (pj) {
|
|
|
|
pj_a (pj);
|
|
|
|
}
|
|
|
|
const ut8 *buf = core->block;
|
|
|
|
|
|
|
|
bool withref = false;
|
|
|
|
int end = R_MIN (core->blocksize, len);
|
|
|
|
for (i = 0; i + wordsize < end; i += wordsize) {
|
|
|
|
ut64 addr = core->offset + i;
|
|
|
|
ut64 val;
|
|
|
|
if (base == 64) {
|
|
|
|
val = r_read_ble64 (buf + i, be);
|
|
|
|
} else if (base == 32) {
|
|
|
|
val = r_read_ble32 (buf + i, be);
|
|
|
|
val &= UT32_MAX;
|
|
|
|
} else if (base == 16) {
|
|
|
|
val = r_read_ble16 (buf + i, be);
|
|
|
|
val &= UT16_MAX;
|
|
|
|
} else {
|
|
|
|
val = buf[i];
|
|
|
|
}
|
|
|
|
if (pj) {
|
|
|
|
pj_o (pj);
|
|
|
|
pj_kn (pj, "addr", addr);
|
|
|
|
pj_kn (pj, "value", val);
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX: this only works in little endian
|
|
|
|
withref = false;
|
|
|
|
char *refs = NULL;
|
|
|
|
if (core->print->hasrefs) {
|
|
|
|
char *rstr = core->print->hasrefs (core->print->user, val, true);
|
|
|
|
if (R_STR_ISNOTEMPTY (rstr)) {
|
|
|
|
r_str_trim (rstr);
|
|
|
|
if (pj) {
|
|
|
|
char *ns = r_str_escape (rstr);
|
|
|
|
pj_ks (pj, "ref", r_str_trim_head_ro (ns));
|
|
|
|
pj_end (pj);
|
|
|
|
free (ns);
|
|
|
|
}
|
|
|
|
withref = true;
|
|
|
|
}
|
|
|
|
refs = rstr;
|
|
|
|
}
|
|
|
|
if (mode == '*' && R_STR_ISNOTEMPTY (refs)) {
|
|
|
|
// Show only the mapped ones?
|
|
|
|
r_cons_printf ("f pxr.%"PFMT64x"=0x%"PFMT64x"\n", val, addr);
|
|
|
|
} else if (mode == 'q' && R_STR_ISNOTEMPTY (refs)) {
|
|
|
|
r_cons_printf ("%s\n", refs);
|
|
|
|
}
|
|
|
|
if (t) {
|
|
|
|
r_table_add_rowf (t, "xxs", addr, val, refs);
|
|
|
|
}
|
|
|
|
R_FREE (refs);
|
|
|
|
if (!withref && pj) {
|
|
|
|
pj_end (pj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (t) {
|
|
|
|
r_table_query (t, arg? arg + 1: NULL);
|
|
|
|
char *s = r_table_tostring (t);
|
|
|
|
r_cons_println (s);
|
|
|
|
free (s);
|
|
|
|
r_table_free (t);
|
|
|
|
}
|
|
|
|
if (pj) {
|
|
|
|
pj_end (pj);
|
|
|
|
r_cons_println (pj_string (pj));
|
|
|
|
pj_free (pj);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const int ocols = core->print->cols;
|
|
|
|
int bitsize = core->rasm->bits;
|
|
|
|
/* Thumb is 16bit arm but handles 32bit data */
|
|
|
|
if (bitsize == 16) {
|
|
|
|
bitsize = 32;
|
|
|
|
}
|
|
|
|
core->print->cols = 1;
|
|
|
|
core->print->flags |= R_PRINT_FLAGS_REFS;
|
|
|
|
r_cons_break_push (NULL, NULL);
|
|
|
|
r_print_hexdump (core->print, core->offset,
|
|
|
|
core->block, R_MIN (len, core->blocksize),
|
|
|
|
wordsize * 8, bitsize / 8, 1);
|
|
|
|
r_cons_break_pop ();
|
|
|
|
core->print->flags &= ~R_PRINT_FLAGS_REFS;
|
|
|
|
core->print->cols = ocols;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-27 02:40:27 +01:00
|
|
|
static int cmd_print(void *data, const char *input) {
|
2017-03-09 23:29:48 +01:00
|
|
|
RCore *core = (RCore *) data;
|
2020-09-24 09:37:41 +02:00
|
|
|
st64 l;
|
|
|
|
int i, len, ret;
|
2018-02-26 00:59:41 -08:00
|
|
|
ut8* block;
|
2012-02-27 02:40:27 +01:00
|
|
|
ut32 tbs = core->blocksize;
|
2018-08-10 00:40:46 +02:00
|
|
|
ut64 n, off, from, to, at, ate, piece;
|
2016-05-16 01:18:18 +02:00
|
|
|
ut64 tmpseek = UT64_MAX;
|
2020-09-24 09:37:41 +02:00
|
|
|
const size_t addrbytes = core->io->addrbytes;
|
2018-07-14 10:58:19 +02:00
|
|
|
i = l = len = ret = 0;
|
2018-08-10 00:40:46 +02:00
|
|
|
n = off = from = to = at = ate = piece = 0;
|
2019-02-13 11:44:42 +01:00
|
|
|
PJ *pj = NULL;
|
2012-02-27 02:40:27 +01:00
|
|
|
|
2016-02-07 23:31:24 +01:00
|
|
|
r_print_init_rowoffsets (core->print);
|
2015-06-02 18:06:10 +02:00
|
|
|
off = UT64_MAX;
|
2012-11-20 03:59:00 +01:00
|
|
|
l = len = core->blocksize;
|
2016-11-07 04:52:38 +01:00
|
|
|
if (input[0] && input[1]) {
|
|
|
|
int idx = (input[0] == 'h')? 2: 1;
|
|
|
|
const char *p = off? strchr (input + idx, ' '): NULL;
|
2012-08-19 03:28:17 +02:00
|
|
|
if (p) {
|
2016-11-07 02:33:09 +01:00
|
|
|
l = (int) r_num_math (core->num, p + 1);
|
2019-08-31 14:46:07 +00:00
|
|
|
/* except disasm and memoryfmt (pd, pm) and overlay (po) */
|
2019-10-28 02:09:41 +01:00
|
|
|
if (input[0] != 'd' && input[0] != 't' && input[0] != 'D' && input[0] != 'm' &&
|
2019-08-31 14:46:07 +00:00
|
|
|
input[0] != 'a' && input[0] != 'f' && input[0] != 'i' &&
|
|
|
|
input[0] != 'I' && input[0] != 'o') {
|
2018-08-10 00:40:46 +02:00
|
|
|
if (l < 0) {
|
2018-08-16 16:03:40 -07:00
|
|
|
off = core->offset + l;
|
|
|
|
len = l = -l;
|
2015-04-08 01:08:09 +02:00
|
|
|
tmpseek = core->offset;
|
2018-08-16 16:03:40 -07:00
|
|
|
} else {
|
2018-08-10 00:40:46 +02:00
|
|
|
len = l;
|
2018-08-16 16:03:40 -07:00
|
|
|
if (l > core->blocksize) {
|
2019-04-09 02:56:53 +02:00
|
|
|
if (!r_core_block_size (core, l)) {
|
2018-08-10 00:40:46 +02:00
|
|
|
goto beach;
|
|
|
|
}
|
2013-10-21 12:54:34 +02:00
|
|
|
}
|
2013-10-19 23:10:08 +02:00
|
|
|
}
|
2018-08-16 16:03:40 -07:00
|
|
|
} else {
|
|
|
|
len = l;
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
2017-10-16 13:31:13 +02:00
|
|
|
}
|
2018-08-10 00:40:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (len > core->blocksize) {
|
|
|
|
len = core->blocksize;
|
2016-07-25 18:49:57 +02:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
2019-09-01 19:42:39 +05:30
|
|
|
if (input[0] != 'd' && input[0] != 'm' && input[0] != 'a' && input[0] != 'f' && input[0] != 'i') {
|
2013-11-06 11:15:36 +01:00
|
|
|
n = core->blocksize_max;
|
2017-03-09 23:29:48 +01:00
|
|
|
i = (int) n;
|
|
|
|
if (i != n) {
|
|
|
|
i = 0;
|
|
|
|
}
|
2013-11-06 11:15:36 +01:00
|
|
|
if (i && l > i) {
|
2016-07-25 18:49:57 +02:00
|
|
|
eprintf ("This block size is too big (0x%"PFMT64x
|
2020-09-24 09:37:41 +02:00
|
|
|
" < 0x%" PFMT64x "). Did you mean 'p%c @ %s' instead?\n",
|
2017-03-09 23:29:48 +01:00
|
|
|
n, l, *input, input + 2);
|
2015-06-04 16:53:04 +02:00
|
|
|
goto beach;
|
2013-11-06 11:15:36 +01:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
if (input[0] == 'x' || input[0] == 'D') {
|
|
|
|
if (l > 0 && tmpseek == UT64_MAX) {
|
|
|
|
if (!r_core_block_size (core, l)) {
|
2015-05-10 22:40:02 +02:00
|
|
|
eprintf ("This block size is too big. Did you mean 'p%c @ %s' instead?\n",
|
2017-03-09 23:29:48 +01:00
|
|
|
*input, input + 2);
|
2015-06-04 16:53:04 +02:00
|
|
|
goto beach;
|
2015-05-10 22:40:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
2018-10-04 02:48:15 +02:00
|
|
|
if (input[0] && input[0] != 'z' && input[1] == 'f' && input[2]!='?') {
|
2016-10-05 01:59:58 +02:00
|
|
|
RAnalFunction *f = r_anal_get_fcn_in (core->anal, core->offset, 0);
|
2017-03-09 23:29:48 +01:00
|
|
|
// R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
|
2014-02-21 01:02:47 +01:00
|
|
|
if (f) {
|
2020-01-15 10:58:30 +01:00
|
|
|
len = r_anal_function_linear_size (f);
|
2018-08-16 16:03:40 -07:00
|
|
|
if (len > core->blocksize) {
|
|
|
|
len = core->blocksize;
|
|
|
|
}
|
2014-02-21 01:02:47 +01:00
|
|
|
} else {
|
2017-03-09 23:29:48 +01:00
|
|
|
eprintf ("p: Cannot find function at 0x%08"PFMT64x "\n", core->offset);
|
2016-04-06 02:12:52 +02:00
|
|
|
core->num->value = 0;
|
2015-06-04 16:53:04 +02:00
|
|
|
goto beach;
|
2014-02-21 01:02:47 +01:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
2018-08-16 16:03:40 -07:00
|
|
|
// TODO figure out why `f eax=33; f test=eax; pa call test` misassembles if len is 0
|
|
|
|
core->num->value = len ? len : core->blocksize;
|
2015-06-02 18:06:10 +02:00
|
|
|
if (off != UT64_MAX) {
|
|
|
|
r_core_seek (core, off, SEEK_SET);
|
2016-12-28 12:23:53 +01:00
|
|
|
r_core_block_read (core);
|
2015-04-08 01:08:09 +02:00
|
|
|
}
|
2018-02-19 04:30:32 -08:00
|
|
|
// TODO After core->block is removed, this should be changed to a block read.
|
|
|
|
block = core->block;
|
2012-02-27 02:40:27 +01:00
|
|
|
switch (*input) {
|
2015-10-22 00:48:14 +02:00
|
|
|
case 'w': // "pw"
|
2016-11-20 19:20:14 +01:00
|
|
|
if (input[1] == 'n') {
|
2015-10-22 00:48:14 +02:00
|
|
|
cmd_print_pwn (core);
|
2017-03-09 23:29:48 +01:00
|
|
|
} else if (input[1] == 'd') {
|
2014-06-14 02:59:12 +02:00
|
|
|
if (!r_sandbox_enable (0)) {
|
|
|
|
char *cwd = r_sys_getdir ();
|
|
|
|
if (cwd) {
|
2016-06-26 00:51:17 -04:00
|
|
|
r_cons_println (cwd);
|
2014-06-14 02:59:12 +02:00
|
|
|
free (cwd);
|
|
|
|
}
|
2013-11-19 02:55:22 +01:00
|
|
|
}
|
2014-10-31 19:16:18 +01:00
|
|
|
} else {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("| pwd display current working directory\n");
|
2013-09-18 22:16:18 +02:00
|
|
|
}
|
|
|
|
break;
|
2017-10-16 13:31:13 +02:00
|
|
|
case 'j': // "pj"
|
|
|
|
if (input[1] == '?') {
|
|
|
|
r_core_cmd_help (core, help_msg_pj);
|
|
|
|
} else if (input[1] == '.') {
|
|
|
|
if (input[2] == '.') {
|
|
|
|
ut8 *data = calloc (core->offset + 1, 1);
|
|
|
|
if (data) {
|
|
|
|
data[core->offset] = 0;
|
2018-05-21 23:06:00 +02:00
|
|
|
(void)r_io_read_at (core->io, 0, data, core->offset);
|
2017-10-16 16:38:33 +02:00
|
|
|
char *res = r_print_json_path ((const char *)data, core->offset);
|
2017-10-16 13:31:13 +02:00
|
|
|
if (res) {
|
|
|
|
eprintf ("-> res(%s)\n", res);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
char *res = r_print_json_indent ((char*)data, false, " ", NULL);
|
|
|
|
print_json_path (core, res);
|
|
|
|
free (res);
|
|
|
|
*/
|
|
|
|
} else {
|
|
|
|
eprintf ("Cannot allocate %d\n", (int)(core->offset));
|
|
|
|
}
|
|
|
|
} else {
|
2018-09-20 21:59:32 +08:00
|
|
|
r_core_cmdf (core, "pj %"PFMT64u" @ 0", core->offset);
|
2017-10-16 13:31:13 +02:00
|
|
|
}
|
|
|
|
} else {
|
2018-02-19 04:30:32 -08:00
|
|
|
if (core->blocksize < 4 || !memcmp (core->block, "\xff\xff\xff\xff", 4)) {
|
2017-10-16 13:31:13 +02:00
|
|
|
eprintf ("Cannot read\n");
|
|
|
|
} else {
|
2018-02-19 04:30:32 -08:00
|
|
|
char *res = r_print_json_indent ((const char *)core->block, true, " ", NULL);
|
2017-10-16 13:31:13 +02:00
|
|
|
r_cons_printf ("%s\n", res);
|
|
|
|
free (res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2016-05-16 01:18:18 +02:00
|
|
|
case 'h': // "ph"
|
|
|
|
cmd_print_ph (core, input + 1);
|
|
|
|
break;
|
2015-10-22 00:48:14 +02:00
|
|
|
case 'v': // "pv"
|
2019-06-22 13:31:41 +02:00
|
|
|
cmd_print_pv (core, input + 1, false);
|
|
|
|
break;
|
|
|
|
case 'V': // "pv"
|
|
|
|
cmd_print_pv (core, input + 1, true);
|
2015-10-22 00:48:14 +02:00
|
|
|
break;
|
|
|
|
case '-': // "p-"
|
2018-06-29 11:22:11 +02:00
|
|
|
return cmd_print_blocks (core, input + 1);
|
2017-07-18 01:24:46 -07:00
|
|
|
case '=': // "p="
|
2016-03-11 12:19:37 +01:00
|
|
|
cmd_print_bars (core, input);
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2015-03-04 01:08:47 +01:00
|
|
|
case 'A': // "pA"
|
2017-03-09 23:29:48 +01:00
|
|
|
{
|
2017-09-17 17:04:01 -07:00
|
|
|
const ut64 saved_from = r_config_get_i (core->config, "search.from"),
|
|
|
|
saved_to = r_config_get_i (core->config, "search.to"),
|
|
|
|
saved_maxhits = r_config_get_i (core->config, "search.maxhits");
|
2015-03-04 01:08:47 +01:00
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
int want = r_num_math (core->num, input + 1);
|
|
|
|
if (input[1] == '?') {
|
2015-03-04 01:08:47 +01:00
|
|
|
r_core_cmd0 (core, "/A?");
|
|
|
|
} else {
|
2017-09-17 17:04:01 -07:00
|
|
|
r_config_set_i (core->config, "search.maxhits", want);
|
2015-03-04 01:08:47 +01:00
|
|
|
r_config_set_i (core->config, "search.from", core->offset);
|
2017-03-09 23:29:48 +01:00
|
|
|
r_config_set_i (core->config, "search.to", core->offset + core->blocksize);
|
2015-03-04 01:08:47 +01:00
|
|
|
r_core_cmd0 (core, "/A");
|
2017-09-17 17:04:01 -07:00
|
|
|
r_config_set_i (core->config, "search.maxhits", saved_maxhits);
|
|
|
|
r_config_set_i (core->config, "search.from", saved_from);
|
|
|
|
r_config_set_i (core->config, "search.to", saved_to);
|
2015-03-04 01:08:47 +01:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
break;
|
2015-03-04 01:08:47 +01:00
|
|
|
case 'a': // "pa"
|
2015-03-25 06:56:37 +05:30
|
|
|
{
|
2018-03-05 09:25:20 +01:00
|
|
|
const char *arg = NULL;
|
|
|
|
if (input[1] != '\0') {
|
2020-03-02 21:39:37 +01:00
|
|
|
arg = r_str_trim_head_ro (input + 2);
|
2015-03-25 06:56:37 +05:30
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
if (input[1] == 'e') { // "pae"
|
|
|
|
if (input[2] == '?') {
|
2018-09-30 02:56:46 +02:00
|
|
|
r_cons_printf ("|Usage: pae [asm] print ESIL expression of the given assembly expression\n");
|
2014-10-31 00:20:51 +01:00
|
|
|
} else {
|
2018-09-30 02:56:46 +02:00
|
|
|
int printed = 0;
|
|
|
|
int bufsz;
|
|
|
|
RAnalOp aop = {0};
|
2020-05-13 01:28:23 +02:00
|
|
|
r_asm_set_pc (core->rasm, core->offset);
|
|
|
|
RAsmCode *acode = r_asm_massemble (core->rasm, input + 2);
|
2019-03-26 12:50:13 +01:00
|
|
|
if (acode) {
|
|
|
|
bufsz = acode->len;
|
2018-09-30 02:56:46 +02:00
|
|
|
while (printed < bufsz) {
|
|
|
|
aop.size = 0;
|
|
|
|
if (r_anal_op (core->anal, &aop, core->offset,
|
2019-03-26 12:50:13 +01:00
|
|
|
(const ut8 *)acode->bytes + printed, bufsz - printed, R_ANAL_OP_MASK_ESIL) > 0) {
|
2018-09-30 02:56:46 +02:00
|
|
|
const char *str = R_STRBUF_SAFEGET (&aop.esil);
|
|
|
|
r_cons_println (str);
|
|
|
|
} else {
|
|
|
|
eprintf ("Cannot decode instruction\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (aop.size < 1) {
|
|
|
|
eprintf ("Cannot decode instruction\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
printed += aop.size;
|
|
|
|
r_anal_op_fini (&aop);
|
2018-09-25 13:39:15 -07:00
|
|
|
}
|
2014-10-31 00:20:51 +01:00
|
|
|
}
|
2013-12-23 01:57:43 +01:00
|
|
|
}
|
2018-09-25 13:39:15 -07:00
|
|
|
} else if (input[1] == 'D') { // "paD"
|
2016-09-22 18:06:10 +02:00
|
|
|
if (input[2] == '?') {
|
2018-09-30 02:56:46 +02:00
|
|
|
r_cons_printf ("|Usage: paD [hex] print assembly expression from hexpairs and show hexpairs\n");
|
2015-08-26 02:37:33 +02:00
|
|
|
} else {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_cmdf (core, "pdi@x:%s", input + 2);
|
2015-08-26 02:37:33 +02:00
|
|
|
}
|
2018-09-25 13:39:15 -07:00
|
|
|
} else if (input[1] == 'd') { // "pad*"
|
|
|
|
switch (input[2]) {
|
|
|
|
case 'e': // "pade"
|
2018-09-30 02:56:46 +02:00
|
|
|
if (input[3] == '?') {
|
|
|
|
r_cons_printf ("|Usage: pade [hex] print ESIL expression from hexpairs\n");
|
2017-03-09 23:29:48 +01:00
|
|
|
} else {
|
2018-09-30 02:56:46 +02:00
|
|
|
int printed = 0;
|
|
|
|
int bufsz;
|
2018-10-05 15:22:07 +02:00
|
|
|
RAnalOp aop = { 0 };
|
2018-11-11 16:02:46 -08:00
|
|
|
char *hex_arg = calloc (1, strlen (arg) + 1);
|
2018-09-25 17:35:52 -07:00
|
|
|
if (hex_arg) {
|
2018-09-26 16:48:22 +02:00
|
|
|
bufsz = r_hex_str2bin (arg + 1, (ut8 *)hex_arg);
|
2018-09-30 02:56:46 +02:00
|
|
|
while (printed < bufsz) {
|
|
|
|
aop.size = 0;
|
|
|
|
if (r_anal_op (core->anal, &aop, core->offset,
|
|
|
|
(const ut8 *)hex_arg + printed, bufsz - printed, R_ANAL_OP_MASK_ESIL) > 0) {
|
|
|
|
const char *str = R_STRBUF_SAFEGET (&aop.esil);
|
|
|
|
r_cons_println (str);
|
|
|
|
} else {
|
|
|
|
eprintf ("Cannot decode instruction\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (aop.size < 1) {
|
|
|
|
eprintf ("Cannot decode instruction\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
printed += aop.size;
|
|
|
|
r_anal_op_fini (&aop);
|
2018-09-25 17:35:52 -07:00
|
|
|
}
|
|
|
|
free (hex_arg);
|
2018-09-25 13:39:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ' ': // "pad"
|
2019-08-18 22:43:41 +02:00
|
|
|
__cmd_pad (core, arg);
|
2018-09-25 13:39:15 -07:00
|
|
|
break;
|
2018-09-30 02:56:46 +02:00
|
|
|
case '?': // "pad?"
|
|
|
|
r_cons_printf ("|Usage: pad [hex] print assembly expression from hexpairs\n");
|
|
|
|
break;
|
2018-09-25 13:39:15 -07:00
|
|
|
default:
|
2018-09-30 02:56:46 +02:00
|
|
|
r_cons_printf ("|Usage: pa[edD] [asm|hex] print (dis)assembled\n");
|
2018-09-25 13:39:15 -07:00
|
|
|
break;
|
2014-10-31 00:20:51 +01:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
} else if (input[1] == '?') {
|
2019-01-11 00:32:23 +01:00
|
|
|
r_core_cmd_help (core, help_msg_pa);
|
2012-09-19 03:15:36 +02:00
|
|
|
} else {
|
2016-04-26 19:09:15 +10:00
|
|
|
int i;
|
|
|
|
int bytes;
|
2020-05-13 01:28:23 +02:00
|
|
|
r_asm_set_pc (core->rasm, core->offset);
|
|
|
|
RAsmCode *acode = r_asm_massemble (core->rasm, input + 1);
|
2019-03-26 12:50:13 +01:00
|
|
|
if (acode) {
|
|
|
|
bytes = acode->len;
|
2016-04-26 19:09:15 +10:00
|
|
|
for (i = 0; i < bytes; i++) {
|
2019-03-26 12:50:13 +01:00
|
|
|
ut8 b = acode->bytes[i]; // core->print->big_endian? (bytes - 1 - i): i ];
|
2016-04-26 19:09:15 +10:00
|
|
|
r_cons_printf ("%02x", b);
|
|
|
|
}
|
|
|
|
r_cons_newline ();
|
2012-09-18 03:39:32 +02:00
|
|
|
r_asm_code_free (acode);
|
|
|
|
}
|
|
|
|
}
|
2015-03-25 06:56:37 +05:30
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
break;
|
2015-04-03 02:54:27 +02:00
|
|
|
case 'b': { // "pb"
|
2017-03-09 23:29:48 +01:00
|
|
|
if (input[1] == '?') {
|
|
|
|
r_cons_printf ("|Usage: p[bB] [len] ([skip]) ; see also pB and pxb\n");
|
2016-05-17 00:37:47 +02:00
|
|
|
} else if (l != 0) {
|
2015-04-03 02:54:27 +02:00
|
|
|
int from, to;
|
2017-03-09 23:29:48 +01:00
|
|
|
const int size = len * 8;
|
|
|
|
char *spc, *buf = malloc (size + 1);
|
2015-04-03 02:54:27 +02:00
|
|
|
spc = strchr (input, ' ');
|
|
|
|
if (spc) {
|
2017-03-09 23:29:48 +01:00
|
|
|
len = r_num_math (core->num, spc + 1);
|
|
|
|
if (len < 1) {
|
2015-04-03 02:54:27 +02:00
|
|
|
len = 1;
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
spc = strchr (spc + 1, ' ');
|
2015-04-03 02:54:27 +02:00
|
|
|
if (spc) {
|
2017-03-09 23:29:48 +01:00
|
|
|
from = r_num_math (core->num, spc + 1);
|
2015-04-03 02:54:27 +02:00
|
|
|
} else {
|
|
|
|
from = 0;
|
2014-10-30 23:26:36 +01:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
to = from + len;
|
2015-04-03 02:54:27 +02:00
|
|
|
} else {
|
|
|
|
from = 0;
|
|
|
|
to = size;
|
2014-10-30 23:26:36 +01:00
|
|
|
}
|
2015-04-03 02:54:27 +02:00
|
|
|
if (buf) {
|
|
|
|
int buf_len;
|
2018-02-19 04:30:32 -08:00
|
|
|
r_str_bits (buf, block, size, NULL);
|
2015-04-03 02:54:27 +02:00
|
|
|
buf_len = strlen (buf);
|
2018-12-14 01:17:50 +02:00
|
|
|
if (from >= 0 && to >= 0) {
|
2018-03-19 11:30:25 +01:00
|
|
|
if (from >= buf_len) {
|
|
|
|
from = buf_len;
|
|
|
|
}
|
2018-12-14 01:17:50 +02:00
|
|
|
if (to < buf_len) {
|
2018-03-19 11:30:25 +01:00
|
|
|
buf[to] = 0;
|
|
|
|
//buf[buf_len - 1] = 0;
|
|
|
|
}
|
|
|
|
r_cons_println (buf + from);
|
2015-04-03 02:54:27 +02:00
|
|
|
}
|
|
|
|
free (buf);
|
2017-03-09 23:29:48 +01:00
|
|
|
} else {
|
2017-12-27 21:33:58 +04:00
|
|
|
eprintf ("ERROR: Cannot malloc %d byte(s)\n", size);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2013-07-12 00:29:27 +02:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2013-07-12 00:29:27 +02:00
|
|
|
break;
|
2015-04-03 02:54:27 +02:00
|
|
|
case 'B': { // "pB"
|
2017-03-09 23:29:48 +01:00
|
|
|
if (input[1] == '?') {
|
2014-11-01 23:54:51 +01:00
|
|
|
r_cons_printf ("|Usage: p[bB] [len] bitstream of N bytes\n");
|
2016-05-17 00:37:47 +02:00
|
|
|
} else if (l != 0) {
|
2016-11-06 17:54:25 -03:00
|
|
|
int size;
|
|
|
|
char *buf;
|
|
|
|
if (!r_core_block_size (core, len)) {
|
|
|
|
len = core->blocksize;
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
size = len * 8;
|
|
|
|
buf = malloc (size + 1);
|
2014-10-29 19:04:51 +01:00
|
|
|
if (buf) {
|
|
|
|
r_str_bits (buf, core->block, size, NULL);
|
2016-06-26 00:51:17 -04:00
|
|
|
r_cons_println (buf);
|
2014-10-29 19:04:51 +01:00
|
|
|
free (buf);
|
2017-03-09 23:29:48 +01:00
|
|
|
} else {
|
2017-12-27 21:33:58 +04:00
|
|
|
eprintf ("ERROR: Cannot malloc %d byte(s)\n", size);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-07-12 01:04:05 +02:00
|
|
|
break;
|
2014-10-21 11:49:33 +02:00
|
|
|
case 'I': // "pI"
|
2014-08-23 07:23:55 +02:00
|
|
|
switch (input[1]) {
|
2015-06-15 10:41:34 +02:00
|
|
|
case 'j': // "pIj" is the same as pDj
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
|
|
|
if (input[2]) {
|
|
|
|
cmd_pDj (core, input + 2);
|
|
|
|
} else {
|
2018-04-10 23:52:47 +02:00
|
|
|
cmd_pDj (core, sdb_fmt ("%d", core->blocksize));
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2015-06-15 10:41:34 +02:00
|
|
|
}
|
|
|
|
break;
|
2015-10-21 15:56:03 +02:00
|
|
|
case 'f': // "pIf"
|
2017-03-09 23:29:48 +01:00
|
|
|
{
|
|
|
|
const RAnalFunction *f = r_anal_get_fcn_in (core->anal, core->offset,
|
|
|
|
R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
|
|
|
if (f) {
|
|
|
|
r_core_print_disasm_instructions (core,
|
2020-01-15 10:58:30 +01:00
|
|
|
r_anal_function_linear_size ((RAnalFunction *) f), 0);
|
2017-03-09 23:29:48 +01:00
|
|
|
break;
|
2015-06-15 10:41:34 +02:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2015-06-15 10:41:34 +02:00
|
|
|
case 'd': // "pId" is the same as pDi
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l) {
|
2017-04-16 11:12:41 +02:00
|
|
|
r_core_disasm_pdi (core, 0, l, 0);
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2015-06-15 10:41:34 +02:00
|
|
|
break;
|
|
|
|
case '?': // "pi?"
|
2016-05-17 00:37:47 +02:00
|
|
|
r_cons_printf ("|Usage: p[iI][df] [len] print N instructions/bytes"
|
2017-03-09 23:29:48 +01:00
|
|
|
"(f=func) (see pi? and pdi)\n");
|
2015-06-15 10:41:34 +02:00
|
|
|
break;
|
|
|
|
default:
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l) {
|
|
|
|
r_core_print_disasm_instructions (core, l, 0);
|
|
|
|
}
|
2014-08-23 07:23:55 +02:00
|
|
|
}
|
2013-01-25 03:47:09 +01:00
|
|
|
break;
|
2014-11-07 04:27:57 +01:00
|
|
|
case 'i': // "pi"
|
2013-08-24 23:45:10 +02:00
|
|
|
switch (input[1]) {
|
|
|
|
case '?':
|
2019-04-25 11:13:20 +02:00
|
|
|
// r_cons_printf ("|Usage: pi[defj] [num]\n");
|
2017-07-25 04:20:25 -07:00
|
|
|
r_core_cmd_help (core, help_msg_pi);
|
2019-04-25 11:13:20 +02:00
|
|
|
break;
|
|
|
|
case 'u': // "piu" disasm until ret/jmp . todo: accept arg to specify type
|
|
|
|
disasm_until_ret (core, core->offset, input[2], input + 2);
|
|
|
|
break;
|
2019-08-18 22:43:41 +02:00
|
|
|
case 'x': // "pix"
|
2020-03-02 21:39:37 +01:00
|
|
|
__cmd_pad (core, r_str_trim_head_ro (input + 2));
|
2019-08-18 22:43:41 +02:00
|
|
|
break;
|
2015-04-12 21:12:52 +02:00
|
|
|
case 'a': // "pia" is like "pda", but with "pi" output
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
2016-06-25 03:09:30 +02:00
|
|
|
r_core_print_disasm_all (core, core->offset,
|
|
|
|
l, len, 'i');
|
2015-04-12 21:12:52 +02:00
|
|
|
}
|
|
|
|
break;
|
2017-03-09 23:29:48 +01:00
|
|
|
case 'j': // pij is the same as pdj
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
2018-02-26 00:59:41 -08:00
|
|
|
cmd_pdj (core, input + 2, block);
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2014-08-22 00:00:42 +02:00
|
|
|
break;
|
2016-12-13 02:37:28 +01:00
|
|
|
case 'd': // "pid" is the same as pdi
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
2017-04-16 11:12:41 +02:00
|
|
|
r_core_disasm_pdi (core, l, 0, 0);
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2014-09-16 22:31:49 +02:00
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'e': // "pie"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
2017-04-16 11:12:41 +02:00
|
|
|
r_core_disasm_pdi (core, l, 0, 'e');
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2013-08-24 23:45:10 +02:00
|
|
|
break;
|
2015-07-27 13:30:52 +02:00
|
|
|
case 'f': // "pif"
|
2019-01-23 18:11:11 +02:00
|
|
|
if (input[2] == '?') { // "pif?"
|
|
|
|
r_core_cmd_help(core, help_msg_pif);
|
|
|
|
} else if (input[2] == 'j') {
|
2019-02-10 03:03:47 +01:00
|
|
|
r_core_cmdf (core, "pdfj%s", input + 3);
|
2019-01-23 18:11:11 +02:00
|
|
|
} else if (input[2] == 'c') { // "pifc"
|
2019-02-03 20:05:36 +02:00
|
|
|
RListIter *iter;
|
|
|
|
RAnalRef *refi;
|
|
|
|
RList *refs = NULL;
|
|
|
|
PJ *pj = NULL;
|
2019-01-23 18:11:11 +02:00
|
|
|
|
|
|
|
// check for bounds
|
|
|
|
if (input[3] !=0) {
|
|
|
|
if (input[3] == 'j') { // "pifcj"
|
|
|
|
pj = pj_new ();
|
|
|
|
pj_a (pj);
|
|
|
|
}
|
|
|
|
}
|
2019-02-03 20:05:36 +02:00
|
|
|
// get function in current offset
|
|
|
|
RAnalFunction *f = r_anal_get_fcn_in (core->anal, core->offset,
|
|
|
|
R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
2019-03-31 18:25:04 +08:00
|
|
|
|
2019-02-03 20:05:36 +02:00
|
|
|
// validate that a function was found in the given address
|
|
|
|
if (!f) {
|
|
|
|
// print empty json object
|
2019-01-23 18:11:11 +02:00
|
|
|
if (pj) {
|
|
|
|
pj_end (pj);
|
2019-02-03 20:05:36 +02:00
|
|
|
r_cons_println (pj_string(pj));
|
|
|
|
pj_free (pj);
|
2019-01-23 18:11:11 +02:00
|
|
|
}
|
2019-02-03 20:05:36 +02:00
|
|
|
break;
|
2019-01-23 18:11:11 +02:00
|
|
|
}
|
2019-02-03 20:05:36 +02:00
|
|
|
// get all the calls of the function
|
|
|
|
refs = r_core_anal_fcn_get_calls (core, f);
|
|
|
|
|
|
|
|
// sanity check
|
|
|
|
if (!r_list_empty (refs)) {
|
|
|
|
|
|
|
|
// store current configurations
|
|
|
|
RConfigHold *hc = r_config_hold_new (core->config);
|
2019-03-04 01:24:43 +01:00
|
|
|
r_config_hold_i (hc, "asm.offset", NULL);
|
|
|
|
r_config_hold_i (hc, "asm.comments", NULL);
|
|
|
|
r_config_hold_i (hc, "asm.tabs", NULL);
|
|
|
|
r_config_hold_i (hc, "asm.bytes", NULL);
|
|
|
|
r_config_hold_i (hc, "emu.str", NULL);
|
2019-02-03 20:05:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
// temporarily replace configurations
|
|
|
|
r_config_set_i (core->config, "asm.offset", false);
|
|
|
|
r_config_set_i (core->config, "asm.comments", false);
|
|
|
|
r_config_set_i (core->config, "asm.tabs", 0);
|
|
|
|
r_config_set_i (core->config, "asm.bytes", false);
|
|
|
|
r_config_set_i (core->config, "emu.str", false);
|
|
|
|
|
|
|
|
// iterate over all call references
|
|
|
|
r_list_foreach (refs, iter, refi) {
|
|
|
|
if (pj) {
|
2019-05-10 14:16:11 +03:00
|
|
|
RAnalFunction *f = r_anal_get_fcn_in (core->anal, refi->addr,
|
|
|
|
R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
2019-02-03 20:05:36 +02:00
|
|
|
char *dst = r_str_newf ((f? f->name: "0x%08"PFMT64x), refi->addr);
|
2019-04-24 04:03:54 +05:30
|
|
|
char *dst2 = NULL;
|
|
|
|
RAnalOp *op = r_core_anal_op (core, refi->addr, R_ANAL_OP_MASK_BASIC);
|
|
|
|
RBinReloc *rel = r_core_getreloc (core, refi->addr, op->size);
|
|
|
|
if (rel) {
|
|
|
|
if (rel && rel->import && rel->import->name) {
|
|
|
|
dst2 = rel->import->name;
|
|
|
|
} else if (rel && rel->symbol && rel->symbol->name) {
|
|
|
|
dst2 = rel->symbol->name;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
dst2 = dst;
|
|
|
|
}
|
2019-02-03 20:05:36 +02:00
|
|
|
pj_o (pj);
|
2019-04-24 04:03:54 +05:30
|
|
|
pj_ks (pj, "dest", dst2);
|
2019-02-03 20:05:36 +02:00
|
|
|
pj_kn (pj, "addr", refi->addr);
|
|
|
|
pj_kn (pj, "at", refi->at);
|
|
|
|
pj_end (pj);
|
2019-04-24 04:03:54 +05:30
|
|
|
r_anal_op_free (op);
|
2019-02-03 20:05:36 +02:00
|
|
|
} else {
|
|
|
|
char *s = r_core_cmd_strf (core, "pdi %i @ 0x%08"PFMT64x, 1, refi->at);
|
|
|
|
r_cons_printf ("%s", s);
|
|
|
|
}
|
|
|
|
}
|
2019-01-23 18:11:11 +02:00
|
|
|
|
2019-02-03 20:05:36 +02:00
|
|
|
// restore saved configuration
|
2019-03-04 01:24:43 +01:00
|
|
|
r_config_hold_restore (hc);
|
2019-02-03 20:05:36 +02:00
|
|
|
r_config_hold_free (hc);
|
|
|
|
}
|
2019-01-23 18:11:11 +02:00
|
|
|
// print json object
|
|
|
|
if (pj) {
|
|
|
|
pj_end (pj);
|
2019-02-03 20:05:36 +02:00
|
|
|
r_cons_println (pj_string (pj));
|
2019-01-23 18:11:11 +02:00
|
|
|
pj_free (pj);
|
|
|
|
}
|
2019-02-03 20:05:36 +02:00
|
|
|
} else if (l != 0) {
|
|
|
|
RAnalFunction *f = r_anal_get_fcn_in (core->anal, core->offset,
|
|
|
|
R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
|
|
|
if (f) {
|
|
|
|
ut32 bsz = core->blocksize;
|
2020-01-15 10:58:30 +01:00
|
|
|
// int fsz = r_anal_function_realsize (f);
|
|
|
|
int fsz = r_anal_function_linear_size (f); // we want max-min here
|
2019-02-03 20:05:36 +02:00
|
|
|
r_core_block_size (core, fsz);
|
|
|
|
r_core_print_disasm_instructions (core, fsz, 0);
|
|
|
|
r_core_block_size (core, bsz);
|
|
|
|
} else {
|
|
|
|
r_core_print_disasm_instructions (core,
|
|
|
|
core->blocksize, l);
|
|
|
|
}
|
2019-01-23 18:11:11 +02:00
|
|
|
}
|
2013-08-24 23:45:10 +02:00
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'r': // "pir"
|
2017-03-09 23:29:48 +01:00
|
|
|
{
|
2016-12-05 19:41:37 +01:00
|
|
|
RAnalFunction *f = r_anal_get_fcn_in (core->anal, core->offset,
|
2017-03-09 23:29:48 +01:00
|
|
|
R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
2016-12-05 19:41:37 +01:00
|
|
|
if (f) {
|
2018-11-18 01:20:05 +08:00
|
|
|
func_walk_blocks (core, f, input[2], 'I', input[2] == '.');
|
2016-12-05 19:41:37 +01:00
|
|
|
} else {
|
2017-03-09 23:29:48 +01:00
|
|
|
eprintf ("Cannot find function at 0x%08"PFMT64x "\n", core->offset);
|
2016-12-05 19:41:37 +01:00
|
|
|
core->num->value = 0;
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'b': // "pib"
|
2017-05-17 08:28:57 +02:00
|
|
|
{
|
|
|
|
RAnalBlock *b = r_anal_bb_from_offset (core->anal, core->offset);
|
|
|
|
if (b) {
|
|
|
|
r_core_print_disasm_instructions (core, b->size - (core->offset - b->addr), 0);
|
|
|
|
} else {
|
|
|
|
eprintf ("Cannot find function at 0x%08"PFMT64x "\n", core->offset);
|
|
|
|
core->num->value = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2017-08-05 18:28:23 -07:00
|
|
|
default: // "pi"
|
2017-01-18 22:02:30 +01:00
|
|
|
if (l != 0) {
|
2016-05-17 00:37:47 +02:00
|
|
|
r_core_print_disasm_instructions (core, 0, l);
|
|
|
|
}
|
2013-08-24 23:45:10 +02:00
|
|
|
break;
|
2013-05-01 00:40:26 +02:00
|
|
|
}
|
2015-06-04 16:53:04 +02:00
|
|
|
goto beach;
|
2014-10-21 11:49:33 +02:00
|
|
|
case 'D': // "pD"
|
|
|
|
case 'd': // "pd"
|
2017-03-09 23:29:48 +01:00
|
|
|
{
|
2013-11-23 18:44:00 -06:00
|
|
|
ut64 use_blocksize = core->blocksize;
|
2018-03-05 09:25:20 +01:00
|
|
|
ut8 bw_disassemble = false;
|
2015-09-14 12:35:38 +02:00
|
|
|
ut32 pd_result = false, processed_cmd = false;
|
2017-12-11 15:07:44 +01:00
|
|
|
bool formatted_json = false;
|
2016-02-22 23:29:05 +01:00
|
|
|
if (input[1] && input[2]) {
|
2018-08-12 02:20:52 +02:00
|
|
|
// "pd--" // context disasm
|
|
|
|
if (!strncmp (input + 1, "--", 2)) {
|
2019-01-24 21:32:04 -08:00
|
|
|
char *offs = r_str_newf ("%s", input + 2);
|
|
|
|
if (offs) {
|
|
|
|
ut64 sz = r_num_math (core->num, offs);
|
|
|
|
char *fmt;
|
|
|
|
if (((st64)sz * -1) > core->offset) {
|
|
|
|
// the offset is smaller than the negative value
|
|
|
|
// so only print -offset
|
|
|
|
fmt = r_str_newf ("d %"PFMT64d, -1 * core->offset);
|
|
|
|
} else {
|
|
|
|
fmt = r_str_newf ("d %s", input + 2);
|
|
|
|
}
|
|
|
|
if (fmt) {
|
|
|
|
cmd_print (core, fmt);
|
|
|
|
strcpy (fmt + 2, input + 3);
|
|
|
|
cmd_print (core, fmt);
|
|
|
|
free (fmt);
|
|
|
|
}
|
|
|
|
free (offs);
|
2018-08-18 03:40:59 +02:00
|
|
|
}
|
|
|
|
ret = 0;
|
2018-08-12 02:20:52 +02:00
|
|
|
goto beach;
|
|
|
|
}
|
2018-10-02 05:53:35 +02:00
|
|
|
}
|
2019-09-01 19:42:39 +05:30
|
|
|
|
|
|
|
if (input[1] == 'x') { // pdx
|
2020-03-02 21:39:37 +01:00
|
|
|
__cmd_pad (core, r_str_trim_head_ro (input + 2));
|
2019-09-01 19:42:39 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-06-20 08:51:47 +01:00
|
|
|
const char *sp = NULL;
|
|
|
|
if (input[1] == '.') {
|
|
|
|
sp = input + 2;
|
|
|
|
} else {
|
|
|
|
sp = strchr (input + 1, ' ');
|
|
|
|
}
|
2018-10-02 05:53:35 +02:00
|
|
|
if (!sp && (input[1] == '-' || IS_DIGIT (input[1]))) {
|
|
|
|
sp = input + 1;
|
|
|
|
}
|
2019-06-20 08:51:47 +01:00
|
|
|
if (sp) {
|
2020-03-02 21:39:37 +01:00
|
|
|
int n = (int) r_num_math (core->num, r_str_trim_head_ro (sp));
|
2018-10-02 05:53:35 +02:00
|
|
|
if (!n) {
|
|
|
|
goto beach;
|
2016-09-20 00:11:59 +02:00
|
|
|
}
|
2018-10-02 05:53:35 +02:00
|
|
|
use_blocksize = n;
|
2016-02-22 23:29:05 +01:00
|
|
|
}
|
2013-11-14 07:52:03 -05:00
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
if (core->blocksize_max < use_blocksize && (int) use_blocksize < -core->blocksize_max) {
|
2018-09-20 21:59:32 +08:00
|
|
|
eprintf ("This block size is too big (%"PFMT64u "<%"PFMT64u "). Did you mean 'p%c @ 0x%08"PFMT64x "' instead?\n",
|
2017-03-09 23:29:48 +01:00
|
|
|
(ut64) core->blocksize_max, (ut64) use_blocksize, input[0], (ut64) use_blocksize);
|
2015-06-04 16:53:04 +02:00
|
|
|
goto beach;
|
2017-12-19 00:17:43 +01:00
|
|
|
} else if (core->blocksize_max < use_blocksize && (int) use_blocksize > -(int)core->blocksize_max) {
|
2015-09-14 12:35:38 +02:00
|
|
|
bw_disassemble = true;
|
2017-08-08 03:08:33 -07:00
|
|
|
l = use_blocksize; // negative
|
2013-11-23 18:44:00 -06:00
|
|
|
use_blocksize = -use_blocksize;
|
2017-08-08 03:08:33 -07:00
|
|
|
} else {
|
|
|
|
l = use_blocksize;
|
2013-11-14 07:52:03 -05:00
|
|
|
}
|
2019-04-27 11:08:28 +02:00
|
|
|
// may be unnecessary, fixes 'pd 1;pdj 100;pd 1' bug
|
|
|
|
r_core_block_read (core);
|
2013-11-14 07:52:03 -05:00
|
|
|
|
2012-02-27 02:40:27 +01:00
|
|
|
switch (input[1]) {
|
2016-12-13 13:06:22 +01:00
|
|
|
case 'C': // "pdC"
|
2017-04-16 11:12:41 +02:00
|
|
|
r_core_disasm_pdi (core, l, 0, 'C');
|
2016-12-13 13:06:22 +01:00
|
|
|
pd_result = 0;
|
|
|
|
processed_cmd = true;
|
|
|
|
break;
|
2015-10-21 01:36:24 +02:00
|
|
|
case 'c': // "pdc" // "pDc"
|
2016-09-20 00:11:59 +02:00
|
|
|
r_core_pseudo_code (core, input + 2);
|
2015-04-16 06:42:07 +02:00
|
|
|
pd_result = 0;
|
2015-09-14 12:35:38 +02:00
|
|
|
processed_cmd = true;
|
2015-04-16 06:42:07 +02:00
|
|
|
break;
|
2020-01-08 12:52:00 +08:00
|
|
|
case 't': // "pdt"
|
2020-03-02 21:39:37 +01:00
|
|
|
r_core_disasm_table (core, l, r_str_trim_head_ro (input + 2));
|
2019-10-28 02:09:41 +01:00
|
|
|
pd_result = 0;
|
|
|
|
processed_cmd = true;
|
|
|
|
break;
|
2017-02-28 02:55:00 +01:00
|
|
|
case 'k': // "pdk" -print class
|
2017-03-09 23:29:48 +01:00
|
|
|
{
|
|
|
|
int len = 0;
|
2020-03-02 21:39:37 +01:00
|
|
|
ut64 at = findClassBounds (core, r_str_trim_head_ro (input + 2), &len);
|
2018-09-20 21:59:32 +08:00
|
|
|
return r_core_cmdf (core, "pD %d @ %"PFMT64u, len, at);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2015-10-21 01:36:24 +02:00
|
|
|
case 'i': // "pdi" // "pDi"
|
2015-09-14 12:35:38 +02:00
|
|
|
processed_cmd = true;
|
2016-06-25 03:09:30 +02:00
|
|
|
if (*input == 'D') {
|
2017-04-16 11:12:41 +02:00
|
|
|
r_core_disasm_pdi (core, 0, l, 0);
|
2016-06-25 03:09:30 +02:00
|
|
|
} else {
|
2017-04-16 11:12:41 +02:00
|
|
|
r_core_disasm_pdi (core, l, 0, 0);
|
2016-06-25 03:09:30 +02:00
|
|
|
}
|
2013-11-14 07:52:03 -05:00
|
|
|
pd_result = 0;
|
|
|
|
break;
|
2014-10-21 11:49:33 +02:00
|
|
|
case 'a': // "pda"
|
2015-09-14 12:35:38 +02:00
|
|
|
processed_cmd = true;
|
2016-06-25 03:09:30 +02:00
|
|
|
r_core_print_disasm_all (core, core->offset, l, len, input[2]);
|
|
|
|
pd_result = true;
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2020-08-12 23:05:38 -03:00
|
|
|
case 'e': // "pde"
|
|
|
|
processed_cmd = true;
|
|
|
|
if (!core->fixedblock && !sp) {
|
|
|
|
l /= 4;
|
|
|
|
}
|
|
|
|
int mode = R_MODE_PRINT;
|
|
|
|
if (input[2] == 'j') {
|
|
|
|
mode = R_MODE_JSON;
|
|
|
|
} else if (input[2] == 'q') {
|
|
|
|
if (input[3] == 'q') {
|
|
|
|
mode = R_MODE_SIMPLEST; // Like pi
|
|
|
|
} else {
|
|
|
|
mode = R_MODE_SIMPLE; // Like pdi
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_core_disasm_pde (core, l, mode);
|
|
|
|
pd_result = true;
|
|
|
|
break;
|
2017-05-11 12:27:08 +02:00
|
|
|
case 'R': // "pdR"
|
2017-05-18 22:54:54 +02:00
|
|
|
processed_cmd = true;
|
2018-05-07 22:33:19 +02:00
|
|
|
if (input[2] == 'j') {
|
|
|
|
disasm_recursive (core, core->offset, use_blocksize, 'j');
|
|
|
|
} else {
|
|
|
|
disasm_recursive (core, core->offset, use_blocksize, 'D');
|
|
|
|
}
|
2017-05-18 22:54:54 +02:00
|
|
|
pd_result = true;
|
2017-05-11 12:27:08 +02:00
|
|
|
break;
|
2014-10-21 11:49:33 +02:00
|
|
|
case 'r': // "pdr"
|
2015-09-14 12:35:38 +02:00
|
|
|
processed_cmd = true;
|
2012-08-29 14:46:19 +02:00
|
|
|
{
|
2017-03-09 23:29:48 +01:00
|
|
|
RAnalFunction *f = r_anal_get_fcn_in (core->anal, core->offset, 0);
|
|
|
|
// R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
|
|
|
|
if (f) {
|
2017-11-30 15:45:27 +01:00
|
|
|
func_walk_blocks (core, f, input[2], 'D', input[2] == '.');
|
2017-03-09 23:29:48 +01:00
|
|
|
} else {
|
2017-05-11 12:45:04 +02:00
|
|
|
eprintf ("Cannot find function at 0x%08"PFMT64x "\n", core->offset);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
pd_result = true;
|
2012-08-29 14:46:19 +02:00
|
|
|
}
|
|
|
|
break;
|
2014-10-21 11:49:33 +02:00
|
|
|
case 'b': // "pdb"
|
2015-09-14 12:35:38 +02:00
|
|
|
processed_cmd = true;
|
2018-02-08 11:20:28 +01:00
|
|
|
if (input[2] == '?') {
|
|
|
|
r_cons_printf ("Usage: pdb[j] - disassemble basic block\n");
|
|
|
|
} else {
|
2013-11-14 07:52:03 -05:00
|
|
|
RAnalBlock *b = r_anal_bb_from_offset (core->anal, core->offset);
|
|
|
|
if (b) {
|
2017-03-09 23:29:48 +01:00
|
|
|
ut8 *block = malloc (b->size + 1);
|
2013-11-14 07:52:03 -05:00
|
|
|
if (block) {
|
2018-05-21 23:06:00 +02:00
|
|
|
r_io_read_at (core->io, b->addr, block, b->size);
|
2018-02-08 11:20:28 +01:00
|
|
|
|
|
|
|
if (input[2] == 'j') {
|
2019-02-13 11:44:42 +01:00
|
|
|
pj = pj_new ();
|
|
|
|
if (!pj) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pj_a (pj);
|
|
|
|
r_core_print_disasm_json (core, b->addr, block, b->size, 0, pj);
|
|
|
|
pj_end (pj);
|
|
|
|
r_cons_printf ("%s\n", pj_string (pj));
|
|
|
|
pj_free (pj);
|
2018-02-08 11:20:28 +01:00
|
|
|
} else {
|
|
|
|
core->num->value = r_core_print_disasm (
|
|
|
|
core->print, core, b->addr, block,
|
2019-02-14 22:22:09 +01:00
|
|
|
b->size, 9999, 0, 2, input[2] == 'J', NULL, NULL);
|
2018-02-08 11:20:28 +01:00
|
|
|
}
|
2013-11-14 07:52:03 -05:00
|
|
|
free (block);
|
|
|
|
pd_result = 0;
|
|
|
|
}
|
2015-01-02 15:19:10 +01:00
|
|
|
} else {
|
2017-03-09 23:29:48 +01:00
|
|
|
eprintf ("Cannot find function at 0x%08"PFMT64x "\n", core->offset);
|
2016-04-06 02:12:52 +02:00
|
|
|
core->num->value = 0;
|
2015-01-02 15:19:10 +01:00
|
|
|
}
|
2013-11-14 07:52:03 -05:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2016-03-23 01:13:16 +01:00
|
|
|
case 's': // "pds" and "pdsf"
|
2015-12-21 15:53:53 +01:00
|
|
|
processed_cmd = true;
|
2016-03-23 01:13:16 +01:00
|
|
|
if (input[2] == '?') {
|
2018-04-05 09:30:47 +02:00
|
|
|
r_cons_printf ("Usage: pds[bf] - sumarize N bytes or function (pdfs)\n");
|
2016-03-23 01:13:16 +01:00
|
|
|
} else {
|
|
|
|
disasm_strings (core, input, NULL);
|
|
|
|
}
|
2015-12-21 15:53:53 +01:00
|
|
|
break;
|
2014-10-21 11:49:33 +02:00
|
|
|
case 'f': // "pdf"
|
2015-09-14 12:35:38 +02:00
|
|
|
processed_cmd = true;
|
2016-03-23 01:13:16 +01:00
|
|
|
if (input[2] == '?') {
|
2018-09-07 16:42:06 +02:00
|
|
|
r_core_cmd_help(core, help_msg_pdf);
|
2016-04-06 02:12:52 +02:00
|
|
|
} else if (input[2] == 's') { // "pdfs"
|
2016-03-23 01:13:16 +01:00
|
|
|
ut64 oseek = core->offset;
|
|
|
|
int oblock = core->blocksize;
|
|
|
|
RAnalFunction *f = r_anal_get_fcn_in (core->anal, core->offset,
|
2017-03-09 23:29:48 +01:00
|
|
|
R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
2016-03-23 01:13:16 +01:00
|
|
|
if (f) {
|
2020-01-15 10:58:30 +01:00
|
|
|
ut32 rs = r_anal_function_realsize (f);
|
|
|
|
ut32 fs = r_anal_function_linear_size (f);
|
2016-03-23 01:13:16 +01:00
|
|
|
r_core_seek (core, oseek, SEEK_SET);
|
2018-08-31 03:06:07 +02:00
|
|
|
r_core_block_size (core, R_MAX (rs, fs));
|
2016-03-23 01:13:16 +01:00
|
|
|
disasm_strings (core, input, f);
|
|
|
|
r_core_block_size (core, oblock);
|
|
|
|
r_core_seek (core, oseek, SEEK_SET);
|
|
|
|
}
|
|
|
|
processed_cmd = true;
|
|
|
|
} else {
|
2016-01-20 21:01:05 -05:00
|
|
|
ut32 bsz = core->blocksize;
|
2018-12-20 15:39:36 +01:00
|
|
|
RAnalFunction *f = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_ROOT);
|
|
|
|
if (!f) {
|
|
|
|
f = r_anal_get_fcn_in (core->anal, core->offset, 0);
|
|
|
|
}
|
2016-09-09 19:28:47 +02:00
|
|
|
RListIter *locs_it = NULL;
|
2016-01-20 21:01:05 -05:00
|
|
|
if (f && input[2] == 'j') { // "pdfj"
|
2018-05-25 12:55:15 +02:00
|
|
|
RAnalBlock *b;
|
2020-01-15 10:58:30 +01:00
|
|
|
ut32 fcn_size = r_anal_function_realsize (f);
|
2018-11-14 09:32:00 +08:00
|
|
|
const char *orig_bb_middle = r_config_get (core->config, "asm.bb.middle");
|
|
|
|
r_config_set_i (core->config, "asm.bb.middle", false);
|
2019-02-13 11:44:42 +01:00
|
|
|
pj = pj_new ();
|
|
|
|
if (!pj) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pj_o (pj);
|
|
|
|
pj_ks (pj, "name", f->name);
|
|
|
|
pj_kn (pj, "size", fcn_size);
|
|
|
|
pj_kn (pj, "addr", f->addr);
|
|
|
|
pj_k (pj, "ops");
|
|
|
|
pj_a (pj);
|
2020-01-15 10:58:30 +01:00
|
|
|
r_list_sort (f->bbs, bb_cmpaddr);
|
2018-05-25 12:55:15 +02:00
|
|
|
r_list_foreach (f->bbs, locs_it, b) {
|
2020-04-12 20:45:24 +02:00
|
|
|
|
2018-05-25 12:55:15 +02:00
|
|
|
ut8 *buf = malloc (b->size);
|
|
|
|
if (buf) {
|
|
|
|
r_io_read_at (core->io, b->addr, buf, b->size);
|
2019-02-13 11:44:42 +01:00
|
|
|
r_core_print_disasm_json (core, b->addr, buf, b->size, 0, pj);
|
2018-05-25 12:55:15 +02:00
|
|
|
free (buf);
|
|
|
|
} else {
|
2020-01-15 10:54:37 +01:00
|
|
|
eprintf ("cannot allocate %"PFMT64u" byte(s)\n", b->size);
|
2018-05-25 12:55:15 +02:00
|
|
|
}
|
|
|
|
}
|
2019-02-13 11:44:42 +01:00
|
|
|
pj_end (pj);
|
|
|
|
pj_end (pj);
|
|
|
|
r_cons_printf ("%s\n", pj_string (pj));
|
|
|
|
pj_free (pj);
|
2016-01-20 21:01:05 -05:00
|
|
|
pd_result = 0;
|
2018-11-14 09:32:00 +08:00
|
|
|
r_config_set (core->config, "asm.bb.middle", orig_bb_middle);
|
2016-01-20 21:01:05 -05:00
|
|
|
} else if (f) {
|
2020-01-15 10:58:30 +01:00
|
|
|
ut64 linearsz = r_anal_function_linear_size (f);
|
|
|
|
ut64 realsz = r_anal_function_realsize (f);
|
|
|
|
if (realsz + 4096 < linearsz) {
|
2017-09-30 14:38:18 +02:00
|
|
|
eprintf ("Linear size differs too much from the bbsum, please use pdr instead.\n");
|
|
|
|
} else {
|
2020-01-15 10:58:30 +01:00
|
|
|
ut64 at = f->addr; // TODO: should be min from r_anal_fcn_get_range()?
|
|
|
|
ut64 sz = R_MAX (linearsz, realsz);
|
2018-05-10 17:33:34 +02:00
|
|
|
ut8 *buf = calloc (sz, 1);
|
2020-03-16 13:56:47 +01:00
|
|
|
if (buf) {
|
|
|
|
(void)r_io_read_at (core->io, at, buf, sz);
|
|
|
|
core->num->value = r_core_print_disasm (core->print, core, at, buf, sz, sz, 0, 1, 0, NULL, f);
|
|
|
|
free (buf);
|
|
|
|
// r_core_cmdf (core, "pD %d @ 0x%08" PFMT64x, f->_size > 0 ? f->_size: r_anal_function_realsize (f), f->addr);
|
|
|
|
}
|
2016-09-09 19:28:47 +02:00
|
|
|
}
|
2016-01-20 21:01:05 -05:00
|
|
|
pd_result = 0;
|
|
|
|
} else {
|
2017-03-09 23:29:48 +01:00
|
|
|
eprintf ("pdf: Cannot find function at 0x%08"PFMT64x "\n", core->offset);
|
2016-01-20 21:01:05 -05:00
|
|
|
processed_cmd = true;
|
2016-04-06 02:12:52 +02:00
|
|
|
core->num->value = 0;
|
2016-01-20 21:01:05 -05:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
if (bsz != core->blocksize) {
|
2016-01-20 21:01:05 -05:00
|
|
|
r_core_block_size (core, bsz);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
2013-11-14 07:52:03 -05:00
|
|
|
l = 0;
|
|
|
|
break;
|
2018-04-09 02:23:44 +02:00
|
|
|
case 'p': // "pdp"
|
|
|
|
processed_cmd = true;
|
|
|
|
disasm_ropchain (core, core->offset, 'D');
|
|
|
|
pd_result = true;
|
|
|
|
break;
|
|
|
|
case 'l': // "pdl"
|
2015-09-14 12:35:38 +02:00
|
|
|
processed_cmd = true;
|
2013-11-14 07:52:03 -05:00
|
|
|
{
|
|
|
|
RAsmOp asmop;
|
|
|
|
int j, ret;
|
2016-11-20 19:20:14 +01:00
|
|
|
if (!l) {
|
2017-03-09 23:29:48 +01:00
|
|
|
l = len;
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
|
|
|
r_cons_break_push (NULL, NULL);
|
2017-03-09 23:29:48 +01:00
|
|
|
for (i = j = 0; i < core->blocksize && j < l; i += ret, j++) {
|
2020-05-13 01:28:23 +02:00
|
|
|
ret = r_asm_disassemble (core->rasm, &asmop, block + i, len - i);
|
2016-11-20 19:20:14 +01:00
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
2014-11-19 00:04:28 +01:00
|
|
|
r_cons_printf ("%d\n", ret);
|
2016-11-20 19:20:14 +01:00
|
|
|
if (ret < 1) {
|
|
|
|
ret = 1;
|
|
|
|
}
|
2013-11-14 07:52:03 -05:00
|
|
|
}
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_pop ();
|
2013-11-14 07:52:03 -05:00
|
|
|
pd_result = 0;
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
|
|
|
break;
|
2017-03-09 23:29:48 +01:00
|
|
|
case 'j': // pdj
|
2015-09-14 12:35:38 +02:00
|
|
|
processed_cmd = true;
|
2016-02-22 23:29:05 +01:00
|
|
|
if (*input == 'D') {
|
2017-03-09 23:29:48 +01:00
|
|
|
cmd_pDj (core, input + 2);
|
|
|
|
} else {
|
2018-02-26 00:59:41 -08:00
|
|
|
cmd_pdj (core, input + 2, block);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2014-11-01 23:54:51 +01:00
|
|
|
r_cons_newline ();
|
2013-11-14 07:52:03 -05:00
|
|
|
pd_result = 0;
|
2014-05-21 16:34:06 +02:00
|
|
|
break;
|
2017-12-11 15:07:44 +01:00
|
|
|
case 'J': // pdJ
|
|
|
|
formatted_json = true;
|
|
|
|
break;
|
2019-04-09 02:56:53 +02:00
|
|
|
case 0: // "pd"
|
2014-11-19 00:04:28 +01:00
|
|
|
/* "pd" -> will disassemble blocksize/4 instructions */
|
2019-04-09 02:56:53 +02:00
|
|
|
if (!core->fixedblock && *input == 'd') {
|
2016-09-20 00:11:59 +02:00
|
|
|
l /= 4;
|
2014-11-19 00:04:28 +01:00
|
|
|
}
|
|
|
|
break;
|
2014-11-01 23:54:51 +01:00
|
|
|
case '?': // "pd?"
|
2015-09-14 12:35:38 +02:00
|
|
|
processed_cmd = true;
|
2017-07-25 04:20:25 -07:00
|
|
|
r_core_cmd_help (core, help_msg_pd);
|
2013-11-14 07:52:03 -05:00
|
|
|
pd_result = 0;
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
2020-09-14 10:21:31 +02:00
|
|
|
if (formatted_json) {
|
|
|
|
if (r_cons_singleton ()->is_html) {
|
|
|
|
r_cons_singleton ()->is_html = false;
|
|
|
|
r_cons_singleton ()->was_html = true;
|
|
|
|
}
|
|
|
|
}
|
2013-11-22 12:24:32 -06:00
|
|
|
if (!processed_cmd) {
|
2013-12-02 05:43:29 +01:00
|
|
|
ut64 addr = core->offset;
|
2018-02-26 00:59:41 -08:00
|
|
|
ut8 *block1 = NULL;
|
2016-06-11 02:12:41 +00:00
|
|
|
ut64 start;
|
2014-04-01 16:22:29 -05:00
|
|
|
|
2013-12-02 05:43:29 +01:00
|
|
|
if (bw_disassemble) {
|
2018-02-26 00:59:41 -08:00
|
|
|
block1 = malloc (core->blocksize);
|
2016-08-10 18:49:44 +02:00
|
|
|
if (l < 0) {
|
|
|
|
l = -l;
|
|
|
|
}
|
2018-02-26 00:59:41 -08:00
|
|
|
if (block1) {
|
2017-03-09 23:29:48 +01:00
|
|
|
if (*input == 'D') { // pD
|
2018-02-26 00:59:41 -08:00
|
|
|
free (block1);
|
2018-05-10 17:33:34 +02:00
|
|
|
if (!(block1 = malloc (l))) {
|
2018-02-26 00:59:41 -08:00
|
|
|
break;
|
2018-05-10 17:33:34 +02:00
|
|
|
}
|
2018-05-21 23:06:00 +02:00
|
|
|
r_io_read_at (core->io, addr - l, block1, l); // core->blocksize);
|
2019-02-14 22:22:09 +01:00
|
|
|
core->num->value = r_core_print_disasm (core->print, core, addr - l, block1, l, l, 0, 1, formatted_json, NULL, NULL);
|
2017-03-09 23:29:48 +01:00
|
|
|
} else { // pd
|
2014-08-23 07:23:55 +02:00
|
|
|
int instr_len;
|
2018-12-17 21:02:29 +08:00
|
|
|
if (!r_core_prevop_addr (core, core->offset, l, &start)) {
|
2016-06-11 02:12:41 +00:00
|
|
|
// anal ignorance.
|
2018-12-17 21:02:29 +08:00
|
|
|
start = r_core_prevop_addr_force (core, core->offset, l);
|
2016-06-11 02:12:41 +00:00
|
|
|
}
|
2018-12-17 21:02:29 +08:00
|
|
|
instr_len = core->offset - start;
|
2016-06-06 10:36:09 +02:00
|
|
|
ut64 prevaddr = core->offset;
|
2017-08-08 09:25:44 -07:00
|
|
|
int bs = core->blocksize, bs1 = addrbytes * instr_len;
|
|
|
|
if (bs1 > bs) {
|
2018-12-10 12:56:12 +02:00
|
|
|
ut8 *tmpblock = realloc (block1, bs1);
|
|
|
|
if (!tmpblock) {
|
|
|
|
eprintf ("Memory reallocation failed.\n");
|
|
|
|
free (block1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
block1 = tmpblock;
|
2017-08-08 09:25:44 -07:00
|
|
|
}
|
2016-06-27 23:26:13 +02:00
|
|
|
r_core_seek (core, prevaddr - instr_len, true);
|
2018-02-26 00:59:41 -08:00
|
|
|
memcpy (block1, block, bs);
|
2017-08-08 09:25:44 -07:00
|
|
|
if (bs1 > bs) {
|
2018-05-21 23:06:00 +02:00
|
|
|
r_io_read_at (core->io, addr + bs / addrbytes,
|
2018-05-10 17:33:34 +02:00
|
|
|
block1 + (bs - bs % addrbytes),
|
|
|
|
bs1 - (bs - bs % addrbytes));
|
2017-08-08 09:25:44 -07:00
|
|
|
}
|
2014-08-23 07:23:55 +02:00
|
|
|
core->num->value = r_core_print_disasm (core->print,
|
2019-02-14 22:22:09 +01:00
|
|
|
core, core->offset, block1, R_MAX (bs, bs1), l, 0, 1, formatted_json, NULL, NULL);
|
2016-09-20 00:11:59 +02:00
|
|
|
r_core_seek (core, prevaddr, true);
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
2013-11-23 18:44:00 -06:00
|
|
|
}
|
2013-12-02 05:43:29 +01:00
|
|
|
} else {
|
|
|
|
// XXX: issue with small blocks
|
2019-04-09 02:56:53 +02:00
|
|
|
if (*input == 'D' && use_blocksize > 0) {
|
|
|
|
l = use_blocksize;
|
2016-02-18 11:08:12 +01:00
|
|
|
if (l > R_CORE_MAX_DISASM) { // pD
|
2015-07-09 01:08:47 +02:00
|
|
|
eprintf ("Block size too big\n");
|
|
|
|
return 1;
|
|
|
|
}
|
2018-02-26 00:59:41 -08:00
|
|
|
block1 = malloc (addrbytes * l);
|
|
|
|
if (block1) {
|
2019-04-09 02:56:53 +02:00
|
|
|
r_io_read_at (core->io, addr, block1, addrbytes * l);
|
2015-07-09 01:08:47 +02:00
|
|
|
core->num->value = r_core_print_disasm (core->print,
|
2019-02-14 22:22:09 +01:00
|
|
|
core, addr, block1, addrbytes * l, l, 0, 1, formatted_json, NULL, NULL);
|
2014-01-29 02:55:03 +01:00
|
|
|
} else {
|
2020-09-24 09:37:41 +02:00
|
|
|
eprintf ("Cannot allocate %" PFMT64d " byte(s)\n", addrbytes * l);
|
2014-01-29 02:55:03 +01:00
|
|
|
}
|
2013-12-02 05:43:29 +01:00
|
|
|
} else {
|
2019-04-09 02:56:53 +02:00
|
|
|
ut8 *buf = core->block;
|
|
|
|
const int buf_size = core->blocksize;
|
|
|
|
if (buf) {
|
|
|
|
if (!l) {
|
|
|
|
l = use_blocksize;
|
|
|
|
if (!core->fixedblock) {
|
|
|
|
l /= 4;
|
|
|
|
}
|
2018-05-10 17:33:34 +02:00
|
|
|
}
|
|
|
|
core->num->value = r_core_print_disasm (core->print,
|
2019-04-09 02:56:53 +02:00
|
|
|
core, addr, buf, buf_size, l,
|
|
|
|
0, 0, formatted_json, NULL, NULL);
|
2017-08-08 09:25:44 -07:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
|
|
|
}
|
2018-02-26 00:59:41 -08:00
|
|
|
free (block1);
|
2018-02-01 15:12:27 +01:00
|
|
|
if (formatted_json) {
|
2020-03-16 13:56:47 +01:00
|
|
|
r_cons_newline ();
|
2018-02-01 15:12:27 +01:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
2015-06-19 21:30:57 +02:00
|
|
|
if (processed_cmd) {
|
2015-06-04 16:53:04 +02:00
|
|
|
ret = pd_result;
|
|
|
|
goto beach;
|
2013-11-14 07:52:03 -05:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
break;
|
2019-06-22 12:58:37 +02:00
|
|
|
case 'p': // "pp"
|
|
|
|
__printPattern (core, input + 1);
|
|
|
|
break;
|
2016-05-17 00:37:47 +02:00
|
|
|
case 's': // "ps"
|
2012-08-28 17:50:49 +02:00
|
|
|
switch (input[1]) {
|
2019-06-22 12:58:37 +02:00
|
|
|
case '?': // "ps?"
|
2017-07-25 04:20:25 -07:00
|
|
|
r_core_cmd_help (core, help_msg_ps);
|
2012-08-29 17:24:30 +02:00
|
|
|
break;
|
2017-03-20 23:41:27 +01:00
|
|
|
case 'j': // "psj"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l > 0) {
|
2017-03-09 23:29:48 +01:00
|
|
|
if (input[2] == ' ' && input[3]) {
|
|
|
|
len = r_num_math (core->num, input + 3);
|
2015-03-23 19:53:19 +01:00
|
|
|
len = R_MIN (len, core->blocksize);
|
|
|
|
}
|
2019-06-13 18:18:35 +02:00
|
|
|
print_json_string (core, (const char *) core->block, len, NULL);
|
2015-09-07 12:39:29 +02:00
|
|
|
r_cons_newline ();
|
2015-03-23 19:53:19 +01:00
|
|
|
}
|
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'i': // "psi"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l > 0) {
|
2018-10-23 23:27:01 +03:00
|
|
|
ut8 *buf = malloc (1024 + 1);
|
2017-03-09 23:29:48 +01:00
|
|
|
int delta = 512;
|
|
|
|
ut8 *p, *e, *b;
|
|
|
|
if (!buf) {
|
|
|
|
return 0;
|
2014-06-05 02:17:21 +02:00
|
|
|
}
|
2018-10-23 23:27:01 +03:00
|
|
|
buf[1024] = 0;
|
2017-03-09 23:29:48 +01:00
|
|
|
if (core->offset < delta) {
|
|
|
|
delta = core->offset;
|
2014-06-05 02:17:21 +02:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
p = buf + delta;
|
2018-05-21 23:06:00 +02:00
|
|
|
r_io_read_at (core->io, core->offset - delta, buf, 1024);
|
2017-03-09 23:29:48 +01:00
|
|
|
for (b = p; b > buf; b--) {
|
|
|
|
if (!IS_PRINTABLE (*b)) {
|
|
|
|
b++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (e = p; e < (buf + 1024); e++) {
|
|
|
|
if (!IS_PRINTABLE (*b)) {
|
|
|
|
*e = 0;
|
|
|
|
e--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_cons_strcat ((const char *) b);
|
|
|
|
r_cons_newline ();
|
|
|
|
// r_print_string (core->print, core->offset, b,
|
|
|
|
// (size_t)(e-b), 0);
|
|
|
|
free (buf);
|
2014-06-05 02:17:21 +02:00
|
|
|
}
|
|
|
|
break;
|
2014-10-27 17:23:13 +01:00
|
|
|
case 'x': // "psx"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l > 0) {
|
2018-05-15 19:33:20 +08:00
|
|
|
r_print_string (core->print, core->offset, block, len, R_PRINT_STRING_ESC_NL);
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2013-10-15 00:26:17 +02:00
|
|
|
break;
|
2014-10-27 17:23:13 +01:00
|
|
|
case 'b': // "psb"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l > 0) {
|
2017-05-15 01:28:28 +02:00
|
|
|
int quiet = input[2] == 'q'; // "psbq"
|
2017-03-09 23:29:48 +01:00
|
|
|
char *s = malloc (core->blocksize + 1);
|
2017-06-06 00:20:49 +00:00
|
|
|
int i, j, hasnl = 0;
|
2013-10-14 03:30:12 +02:00
|
|
|
if (s) {
|
2017-05-15 01:28:28 +02:00
|
|
|
if (!quiet) {
|
|
|
|
r_print_offset (core->print, core->offset, 0, 0, 0, 0, NULL);
|
|
|
|
}
|
2013-10-14 03:30:12 +02:00
|
|
|
// TODO: filter more chars?
|
2017-03-09 23:29:48 +01:00
|
|
|
for (i = j = 0; i < core->blocksize; i++) {
|
2018-02-26 00:59:41 -08:00
|
|
|
char ch = (char) block[i];
|
2013-10-14 03:30:12 +02:00
|
|
|
if (!ch) {
|
|
|
|
if (!hasnl) {
|
2014-10-08 02:42:16 +02:00
|
|
|
s[j] = 0;
|
2016-06-26 00:51:17 -04:00
|
|
|
if (*s) {
|
|
|
|
r_cons_println (s);
|
2017-05-15 01:28:28 +02:00
|
|
|
if (!quiet) {
|
|
|
|
r_print_offset (core->print, core->offset + i, 0, 0, 0, 0, NULL);
|
|
|
|
}
|
2016-06-26 00:51:17 -04:00
|
|
|
}
|
2013-10-14 03:30:12 +02:00
|
|
|
j = 0;
|
|
|
|
s[0] = 0;
|
|
|
|
}
|
|
|
|
hasnl = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
hasnl = 0;
|
2017-03-09 23:29:48 +01:00
|
|
|
if (IS_PRINTABLE (ch)) {
|
2013-10-14 03:30:12 +02:00
|
|
|
s[j++] = ch;
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2013-10-14 03:30:12 +02:00
|
|
|
}
|
2014-10-08 02:42:16 +02:00
|
|
|
s[j] = 0;
|
2016-06-26 00:51:17 -04:00
|
|
|
r_cons_print (s); // TODO: missing newline?
|
2013-10-14 03:30:12 +02:00
|
|
|
free (s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2018-09-20 22:56:38 +01:00
|
|
|
case 'z': // "psz"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l > 0) {
|
2016-12-28 12:23:53 +01:00
|
|
|
char *s = malloc (core->blocksize + 1);
|
2012-08-29 17:24:30 +02:00
|
|
|
int i, j;
|
|
|
|
if (s) {
|
|
|
|
// TODO: filter more chars?
|
2017-03-09 23:29:48 +01:00
|
|
|
for (i = j = 0; i < core->blocksize; i++) {
|
|
|
|
char ch = (char) core->block[i];
|
|
|
|
if (!ch) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (IS_PRINTABLE (ch)) {
|
2012-08-29 17:24:30 +02:00
|
|
|
s[j++] = ch;
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2012-08-29 17:24:30 +02:00
|
|
|
}
|
2018-10-23 23:27:01 +03:00
|
|
|
s[j] = '\0';
|
2019-06-13 18:18:35 +02:00
|
|
|
if (input[2] == 'j') { // pszj
|
|
|
|
print_json_string (core, (const char *) s, j, NULL);
|
|
|
|
r_cons_newline ();
|
|
|
|
} else {
|
|
|
|
r_cons_println (s);
|
|
|
|
}
|
2012-08-29 17:24:30 +02:00
|
|
|
free (s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2016-05-17 00:37:47 +02:00
|
|
|
case 'p': // "psp"
|
|
|
|
if (l > 0) {
|
|
|
|
int mylen = core->block[0];
|
|
|
|
// TODO: add support for 2-4 byte length pascal strings
|
|
|
|
if (mylen < core->blocksize) {
|
2019-06-13 18:18:35 +02:00
|
|
|
if (input[2] == 'j') { // pspj
|
|
|
|
print_json_string (core, (const char *) core->block + 1, mylen, NULL);
|
|
|
|
r_cons_newline ();
|
|
|
|
} else {
|
|
|
|
r_print_string (core->print, core->offset,
|
|
|
|
core->block + 1, mylen, R_PRINT_STRING_ZEROEND);
|
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
core->num->value = mylen;
|
2017-03-09 23:29:48 +01:00
|
|
|
} else {
|
|
|
|
core->num->value = 0; // error
|
|
|
|
}
|
2012-08-28 17:50:49 +02:00
|
|
|
}
|
|
|
|
break;
|
2016-05-17 00:37:47 +02:00
|
|
|
case 'w': // "psw"
|
|
|
|
if (l > 0) {
|
2019-06-13 18:18:35 +02:00
|
|
|
if (input[2] == 'j') { // pswj
|
|
|
|
print_json_string (core, (const char *) core->block, len, "wide");
|
|
|
|
r_cons_newline ();
|
|
|
|
} else {
|
|
|
|
r_print_string (core->print, core->offset, core->block, len,
|
|
|
|
R_PRINT_STRING_WIDE | R_PRINT_STRING_ZEROEND);
|
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2012-08-28 17:50:49 +02:00
|
|
|
break;
|
2019-06-13 18:18:35 +02:00
|
|
|
case 'W': // "psW"
|
2017-06-01 15:49:44 +01:00
|
|
|
if (l > 0) {
|
2019-06-13 18:18:35 +02:00
|
|
|
if (input[2] == 'j') { // psWj
|
|
|
|
print_json_string (core, (const char *) core->block, len, "wide32");
|
|
|
|
r_cons_newline ();
|
|
|
|
} else {
|
|
|
|
r_print_string (core->print, core->offset, core->block, len,
|
|
|
|
R_PRINT_STRING_WIDE32 | R_PRINT_STRING_ZEROEND);
|
|
|
|
}
|
2017-06-01 15:49:44 +01:00
|
|
|
}
|
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case ' ': // "ps"
|
2016-05-17 00:37:47 +02:00
|
|
|
r_print_string (core->print, core->offset, core->block, l, 0);
|
2012-08-28 17:50:49 +02:00
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'u': // "psu"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l > 0) {
|
2019-06-13 18:18:35 +02:00
|
|
|
bool json = input[2] == 'j'; // "psuj"
|
|
|
|
if (input[2] == 'z') { // "psuz"
|
|
|
|
int i, z;
|
|
|
|
const char* p = (const char *) core->block;
|
|
|
|
for (i = 0, z = 0; i < len; i++) {
|
|
|
|
// looking for double zeros '\0\0'.
|
|
|
|
if (!p[i] && !z) z = 1;
|
|
|
|
else if (!p[i] && z) {
|
|
|
|
len = i - 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
json = input[3] == 'j'; // "psuzj"
|
|
|
|
}
|
|
|
|
if (json) { // psuj
|
|
|
|
print_json_string (core, (const char *) core->block, len, "utf16");
|
|
|
|
r_cons_newline ();
|
|
|
|
} else {
|
|
|
|
char *str = r_str_utf16_encode ((const char *) core->block, len);
|
|
|
|
r_cons_println (str);
|
|
|
|
free (str);
|
|
|
|
}
|
2015-03-13 13:24:57 +01:00
|
|
|
}
|
|
|
|
break;
|
2019-03-27 10:23:47 +01:00
|
|
|
case 'q': // "psq"
|
|
|
|
r_core_cmd0 (core, "pqs");
|
|
|
|
break;
|
2017-05-03 03:23:05 +02:00
|
|
|
case 's': // "pss"
|
2017-05-03 03:05:01 +02:00
|
|
|
if (l > 0) {
|
2017-05-03 03:23:05 +02:00
|
|
|
int h, w = r_cons_get_size (&h);
|
|
|
|
int colwidth = r_config_get_i (core->config, "hex.cols") * 2;
|
|
|
|
core->print->width = (colwidth == 32)?w: colwidth; // w;
|
|
|
|
int bs = core->blocksize;
|
|
|
|
if (len == bs) {
|
|
|
|
len = (h * w) / 3;
|
|
|
|
r_core_block_size (core, len);
|
|
|
|
}
|
2017-05-03 03:05:01 +02:00
|
|
|
r_print_string (core->print, core->offset, core->block,
|
2017-05-03 03:23:05 +02:00
|
|
|
len, R_PRINT_STRING_WRAP);
|
|
|
|
r_core_block_size (core, bs);
|
2017-05-03 03:05:01 +02:00
|
|
|
}
|
2017-05-03 03:23:05 +02:00
|
|
|
break;
|
2017-09-02 01:22:35 +08:00
|
|
|
case '+': // "ps+"
|
|
|
|
if (l > 0) {
|
2019-10-28 02:09:41 +01:00
|
|
|
const bool json = input[2] == 'j'; // ps+j
|
2017-09-03 19:27:30 +08:00
|
|
|
ut64 bitness = r_config_get_i (core->config, "asm.bits");
|
|
|
|
if (bitness != 32 && bitness != 64) {
|
2018-11-22 03:50:50 +01:00
|
|
|
eprintf ("Error: bitness of %" PFMT64u " not supported\n", bitness);
|
2017-09-03 19:27:30 +08:00
|
|
|
break;
|
|
|
|
}
|
2017-09-02 01:22:35 +08:00
|
|
|
if (*core->block & 0x1) { // "long" string
|
2017-09-03 19:27:30 +08:00
|
|
|
if (bitness == 64) {
|
2019-06-13 18:18:35 +02:00
|
|
|
r_core_cmdf (core, "ps%c @ 0x%" PFMT64x, json ? 'j' : ' ', *((ut64 *)core->block + 2));
|
2017-09-03 19:27:30 +08:00
|
|
|
} else {
|
2019-06-13 18:18:35 +02:00
|
|
|
r_core_cmdf (core, "ps%c @ 0x%" PFMT32x, json ? 'j' : ' ', *((ut32 *)core->block + 2));
|
2017-09-03 19:27:30 +08:00
|
|
|
}
|
2019-06-13 18:18:35 +02:00
|
|
|
} else if (json) {
|
|
|
|
print_json_string (core, (const char *) core->block + 1, len, NULL);
|
|
|
|
r_cons_newline ();
|
2017-09-02 01:22:35 +08:00
|
|
|
} else {
|
|
|
|
r_print_string (core->print, core->offset, core->block + 1,
|
|
|
|
len, R_PRINT_STRING_ZEROEND);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2012-08-28 17:50:49 +02:00
|
|
|
default:
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l > 0) {
|
|
|
|
r_print_string (core->print, core->offset, core->block,
|
2017-03-09 23:29:48 +01:00
|
|
|
len, R_PRINT_STRING_ZEROEND);
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2012-08-28 17:50:49 +02:00
|
|
|
break;
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2016-05-17 00:37:47 +02:00
|
|
|
case 'm': // "pm"
|
2017-03-09 23:29:48 +01:00
|
|
|
if (input[1] == '?') {
|
2013-12-23 01:57:43 +01:00
|
|
|
r_cons_printf ("|Usage: pm [file|directory]\n"
|
|
|
|
"| r_magic will use given file/dir as reference\n"
|
|
|
|
"| output of those magic can contain expressions like:\n"
|
|
|
|
"| foo@0x40 # use 'foo' magic file on address 0x40\n"
|
|
|
|
"| @0x40 # use current magic file on address 0x40\n"
|
|
|
|
"| \\n # append newline\n"
|
2018-07-17 22:05:01 +03:00
|
|
|
"| e dir.magic # defaults to " R_JOIN_2_PATHS ("{R2_PREFIX}", R2_SDB_MAGIC) "\n"
|
2015-07-15 01:30:53 +02:00
|
|
|
"| /m # search for magic signatures\n"
|
2012-02-27 02:40:27 +01:00
|
|
|
);
|
2020-01-21 04:09:04 +05:30
|
|
|
} else if (input[1] == 'j') { // "pmj"
|
2020-04-06 04:02:50 -04:00
|
|
|
const char *filename = r_str_trim_head_ro (input + 2);
|
|
|
|
r_core_magic (core, filename, true, true);
|
2016-05-02 22:52:41 -04:00
|
|
|
} else {
|
|
|
|
// XXX: need cmd_magic header for r_core_magic
|
2020-04-06 04:02:50 -04:00
|
|
|
const char *filename = r_str_trim_head_ro (input + 1);
|
|
|
|
r_core_magic (core, filename, true, false);
|
2016-05-02 22:52:41 -04:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2016-05-17 00:37:47 +02:00
|
|
|
case 'u': // "pu"
|
2016-12-28 12:23:53 +01:00
|
|
|
if (input[1] == '?') {
|
2014-10-29 20:19:28 +01:00
|
|
|
r_cons_printf ("|Usage: pu[w] [len] print N url"
|
2017-03-09 23:29:48 +01:00
|
|
|
"encoded bytes (w=wide)\n");
|
2014-10-29 20:19:28 +01:00
|
|
|
} else {
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l > 0) {
|
|
|
|
r_print_string (core->print, core->offset, core->block, len,
|
2017-03-09 23:29:48 +01:00
|
|
|
R_PRINT_STRING_URLENCODE |
|
|
|
|
((input[1] == 'w')? R_PRINT_STRING_WIDE: 0));
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2014-10-29 19:04:51 +01:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2016-05-10 00:39:31 +02:00
|
|
|
case 'c': // "pc"
|
2020-05-13 18:44:02 +02:00
|
|
|
if (input[1] == '?') {
|
|
|
|
r_core_cmd_help (core, help_msg_pc);
|
|
|
|
} else if (l) {
|
2017-01-05 00:11:57 +01:00
|
|
|
const ut8 *buf = core->block;
|
|
|
|
int i = 0;
|
|
|
|
int j = 0;
|
2017-01-05 00:25:45 +01:00
|
|
|
if (input[1] == 'A') { // "pcA"
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("sub_0x%08"PFMT64x ":\n", core->offset);
|
2017-01-05 00:11:57 +01:00
|
|
|
for (i = 0; i < len; i++) {
|
2017-03-09 23:29:48 +01:00
|
|
|
RAsmOp asmop = {
|
|
|
|
0
|
|
|
|
};
|
2020-05-13 01:28:23 +02:00
|
|
|
(void) r_asm_disassemble (core->rasm, &asmop, buf + i, len - i);
|
2017-01-05 00:18:06 +01:00
|
|
|
int sz = asmop.size;
|
|
|
|
if (sz < 1) {
|
|
|
|
sz = 1;
|
|
|
|
}
|
|
|
|
r_cons_printf (" .byte ");
|
|
|
|
for (j = 0; j < sz; j++) {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("%s0x%02x", j? ", ": "", buf[i]);
|
2017-01-05 00:11:57 +01:00
|
|
|
i++;
|
|
|
|
}
|
2019-01-07 02:29:23 +03:00
|
|
|
r_cons_printf (" // %s\n", r_strbuf_get (&asmop.buf_asm));
|
2017-01-05 00:18:06 +01:00
|
|
|
i--;
|
2017-01-05 00:11:57 +01:00
|
|
|
}
|
|
|
|
r_cons_printf (".equ shellcode_len, %d\n", len);
|
|
|
|
} else {
|
|
|
|
r_print_code (core->print, core->offset, core->block, len, input[1]);
|
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2016-11-21 00:19:15 +01:00
|
|
|
case 'C': // "pC"
|
2016-10-08 00:02:47 +02:00
|
|
|
switch (input[1]) {
|
|
|
|
case 0:
|
2019-01-16 16:21:10 +01:00
|
|
|
cmd_pCd (core, "");
|
|
|
|
break;
|
2016-10-08 00:02:47 +02:00
|
|
|
case ' ':
|
|
|
|
case 'd':
|
|
|
|
cmd_pCd (core, input + 2);
|
|
|
|
break;
|
2016-11-21 00:19:15 +01:00
|
|
|
case 'D':
|
|
|
|
cmd_pCD (core, input + 2);
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
cmd_pCx (core, input + 2, "pxa");
|
|
|
|
break;
|
|
|
|
case 'A':
|
|
|
|
cmd_pCx (core, input + 2, "pxA");
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
cmd_pCx (core, input + 2, "px");
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
cmd_pCx (core, input + 2, "pxw");
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
cmd_pCx (core, input + 2, "pc");
|
|
|
|
break;
|
2016-10-08 00:02:47 +02:00
|
|
|
default:
|
|
|
|
eprintf ("Usage: pCd\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2015-02-19 12:29:57 +01:00
|
|
|
case 'r': // "pr"
|
2014-08-26 03:52:25 +02:00
|
|
|
switch (input[1]) {
|
2019-07-11 06:10:15 +02:00
|
|
|
case 'i': // "pri" // color raw image
|
|
|
|
{
|
|
|
|
// TODO: do colormap and palette conversions here
|
|
|
|
int mode = 0;
|
|
|
|
if (r_config_get (core->config, "scr.color") == 0) {
|
|
|
|
mode = 'a';
|
|
|
|
}
|
|
|
|
int cols = r_config_get_i (core->config, "hex.cols");
|
|
|
|
r_cons_image (core->block, core->blocksize, cols, mode);
|
|
|
|
}
|
|
|
|
break;
|
2017-05-29 03:45:02 +02:00
|
|
|
case 'c': // "prc" // color raw dump
|
2019-04-16 13:47:22 +02:00
|
|
|
if (input[2] == '?') {
|
|
|
|
r_cons_printf ("prc=e # colorblocks of entropy\n");
|
|
|
|
r_core_cmd0 (core, "pz?");
|
|
|
|
} else if (input[2] == '=') {
|
2019-05-07 11:59:38 +02:00
|
|
|
if (input[3] == '?') {
|
|
|
|
r_core_cmd_help (core, help_msg_p_equal);
|
|
|
|
} else {
|
|
|
|
cmd_prc_zoom (core, input + 2);
|
|
|
|
}
|
2019-04-16 13:47:22 +02:00
|
|
|
} else {
|
|
|
|
cmd_prc (core, block, len);
|
|
|
|
}
|
2017-05-29 03:45:02 +02:00
|
|
|
break;
|
2014-08-26 03:52:25 +02:00
|
|
|
case '?':
|
2018-09-07 16:19:25 +02:00
|
|
|
r_core_cmd_help (core, help_msg_pr);
|
2014-08-26 03:52:25 +02:00
|
|
|
break;
|
2015-02-20 01:16:17 +01:00
|
|
|
case 'g': // "prg" // gunzip
|
2015-04-03 03:20:04 +02:00
|
|
|
switch (input[2]) {
|
|
|
|
case '?':
|
2018-09-07 16:19:25 +02:00
|
|
|
r_core_cmd_help (core, help_msg_prg);
|
2015-04-03 03:20:04 +02:00
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'i': // "prgi"
|
2017-03-09 23:29:48 +01:00
|
|
|
{
|
2018-02-19 04:30:32 -08:00
|
|
|
int outlen = 0;
|
2015-04-03 03:20:04 +02:00
|
|
|
int inConsumed = 0;
|
2018-02-19 04:30:32 -08:00
|
|
|
ut8 *out;
|
|
|
|
out = r_inflate (block, core->blocksize, &inConsumed, &outlen);
|
2015-04-03 03:20:04 +02:00
|
|
|
r_cons_printf ("%d\n", inConsumed);
|
|
|
|
free (out);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'o': // "prgo"
|
2017-03-09 23:29:48 +01:00
|
|
|
{
|
2018-02-19 04:30:32 -08:00
|
|
|
int outlen = 0;
|
|
|
|
ut8 *out;
|
|
|
|
out = r_inflate (block, core->blocksize, NULL, &outlen);
|
2015-04-03 03:20:04 +02:00
|
|
|
r_cons_printf ("%d\n", outlen);
|
|
|
|
free (out);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
break;
|
2015-04-03 03:20:04 +02:00
|
|
|
default:
|
2017-03-09 23:29:48 +01:00
|
|
|
{
|
2018-02-19 04:30:32 -08:00
|
|
|
int outlen = 0;
|
|
|
|
ut8 *out;
|
|
|
|
out = r_inflate (block, core->blocksize, NULL, &outlen);
|
2015-02-20 01:16:17 +01:00
|
|
|
if (out) {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_memcat ((const char *) out, outlen);
|
2015-02-20 01:16:17 +01:00
|
|
|
}
|
|
|
|
free (out);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2015-02-20 01:16:17 +01:00
|
|
|
}
|
|
|
|
break;
|
2015-03-23 01:09:35 +01:00
|
|
|
/* TODO: compact */
|
|
|
|
case 'l': // "prl"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
|
|
|
printraw (core, len, 1);
|
|
|
|
}
|
2015-03-23 01:09:35 +01:00
|
|
|
break;
|
|
|
|
case 'x': // "prx"
|
2019-03-18 17:53:47 +01:00
|
|
|
#if 0
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
|
|
|
printraw (core, len, 2);
|
|
|
|
}
|
2019-03-18 17:53:47 +01:00
|
|
|
#else
|
|
|
|
{
|
|
|
|
int a = r_config_get_i (core->config, "hex.bytes");
|
|
|
|
r_config_set_i (core->config, "hex.bytes", false);
|
|
|
|
r_core_cmdf (core, "px%s", input + 1);
|
|
|
|
r_config_set_i (core->config, "hex.bytes", a);
|
|
|
|
}
|
|
|
|
#endif
|
2015-03-23 01:09:35 +01:00
|
|
|
break;
|
2016-05-18 12:21:49 +02:00
|
|
|
case 'z': // "prz"
|
|
|
|
if (l != 0) {
|
2017-03-09 23:29:48 +01:00
|
|
|
printraw (core, strlen ((const char *) core->block), 0);
|
2016-05-18 12:21:49 +02:00
|
|
|
}
|
|
|
|
break;
|
2014-08-26 03:52:25 +02:00
|
|
|
default:
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
|
|
|
printraw (core, len, 0);
|
|
|
|
}
|
2015-03-23 01:09:35 +01:00
|
|
|
break;
|
2014-08-26 03:52:25 +02:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2015-02-14 03:23:21 +01:00
|
|
|
case '3': // "p3" [file]
|
2017-03-09 23:29:48 +01:00
|
|
|
if (input[1] == '?') {
|
2015-02-14 03:23:21 +01:00
|
|
|
eprintf ("Usage: p3 [file] - print 3D stereogram image of current block\n");
|
2018-07-02 12:19:13 +02:00
|
|
|
} else if (input[1] == ' ') {
|
2017-03-09 23:29:48 +01:00
|
|
|
char *data = r_file_slurp (input + 2, NULL);
|
2019-12-15 13:31:23 -03:00
|
|
|
if (!data) {
|
|
|
|
eprintf ("Could not open '%s'.\n", input + 2);
|
|
|
|
break;
|
|
|
|
}
|
2015-02-14 03:23:21 +01:00
|
|
|
char *res = r_print_stereogram (data, 78, 20);
|
|
|
|
r_print_stereogram_print (core->print, res);
|
2017-03-09 23:29:48 +01:00
|
|
|
// if (data) eprintf ("%s\n", data);
|
2015-02-14 03:23:21 +01:00
|
|
|
free (res);
|
|
|
|
free (data);
|
|
|
|
} else {
|
2018-02-19 04:30:32 -08:00
|
|
|
char *res = r_print_stereogram_bytes (block, core->blocksize);
|
2015-02-14 03:23:21 +01:00
|
|
|
r_print_stereogram_print (core->print, res);
|
|
|
|
free (res);
|
|
|
|
}
|
|
|
|
break;
|
2019-08-31 14:46:07 +00:00
|
|
|
case 'o': // "po"
|
|
|
|
cmd_print_op(core, input);
|
|
|
|
break;
|
2014-10-27 17:23:13 +01:00
|
|
|
case 'x': // "px"
|
2017-03-09 23:29:48 +01:00
|
|
|
{
|
2020-03-31 19:44:23 +07:00
|
|
|
bool show_offset = r_config_get_i (core->config, "hex.offset");
|
2013-01-04 10:16:41 +01:00
|
|
|
if (show_offset) {
|
|
|
|
core->print->flags |= R_PRINT_FLAGS_OFFSET;
|
|
|
|
} else {
|
|
|
|
core->print->flags &= ~R_PRINT_FLAGS_OFFSET;
|
2017-03-24 02:57:10 +01:00
|
|
|
}
|
2018-12-10 19:37:25 +01:00
|
|
|
int show_header = r_config_get_i (core->config, "hex.header");
|
|
|
|
if (show_header) {
|
2017-03-24 02:57:10 +01:00
|
|
|
core->print->flags |= R_PRINT_FLAGS_HEADER;
|
|
|
|
} else {
|
2013-01-04 10:16:41 +01:00
|
|
|
core->print->flags &= ~R_PRINT_FLAGS_HEADER;
|
|
|
|
}
|
2017-01-18 16:12:06 +01:00
|
|
|
/* Don't show comments in default case */
|
|
|
|
core->print->use_comments = false;
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2012-09-27 19:35:19 +02:00
|
|
|
switch (input[1]) {
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'j': // "pxj"
|
2017-05-13 18:27:55 +02:00
|
|
|
r_print_jsondump (core->print, core->block, core->blocksize, 8);
|
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case '/': // "px/"
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_print_examine (core, input + 2);
|
2013-10-14 03:30:12 +02:00
|
|
|
break;
|
2017-07-25 04:20:25 -07:00
|
|
|
case '?':
|
|
|
|
r_core_cmd_help (core, help_msg_px);
|
2012-10-25 12:55:28 +02:00
|
|
|
break;
|
2017-05-07 11:51:58 +02:00
|
|
|
case '0': // "px0"
|
|
|
|
if (l) {
|
2017-05-08 10:35:32 +02:00
|
|
|
int len = r_str_nlen ((const char *)core->block, core->blocksize);
|
2017-05-07 11:51:58 +02:00
|
|
|
r_print_bytes (core->print, core->block, len, "%02x");
|
|
|
|
}
|
|
|
|
break;
|
2015-03-21 03:06:31 +01:00
|
|
|
case 'a': // "pxa"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
2016-11-20 19:20:14 +01:00
|
|
|
if (len % 16) {
|
|
|
|
len += 16 - (len % 16);
|
2016-11-04 01:30:35 +01:00
|
|
|
}
|
|
|
|
annotated_hexdump (core, input + 2, len);
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2013-10-15 03:56:01 +02:00
|
|
|
break;
|
2017-02-23 17:34:00 +01:00
|
|
|
case 'x': // "pxx"
|
|
|
|
if (l != 0) {
|
|
|
|
core->print->flags |= R_PRINT_FLAGS_NONHEX;
|
|
|
|
r_print_hexdump (core->print, core->offset,
|
2017-06-06 00:20:49 +00:00
|
|
|
core->block, len, 8, 1, 1);
|
2017-02-23 17:34:00 +01:00
|
|
|
core->print->flags &= ~R_PRINT_FLAGS_NONHEX;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'X': // "pxX"
|
|
|
|
if (l != 0) {
|
|
|
|
ut8 *buf = calloc (len, 4);
|
|
|
|
if (buf) {
|
|
|
|
r_io_read_at (core->io, core->offset, buf, len * 4);
|
|
|
|
core->print->flags |= R_PRINT_FLAGS_NONHEX;
|
2017-06-06 00:20:49 +00:00
|
|
|
r_print_hexdump (core->print, core->offset, buf, len * 4, 8, 1, 1);
|
2017-02-23 17:34:00 +01:00
|
|
|
core->print->flags &= ~R_PRINT_FLAGS_NONHEX;
|
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2015-03-21 03:06:31 +01:00
|
|
|
case 'A': // "pxA"
|
2017-03-09 23:29:48 +01:00
|
|
|
if (input[2] == '?') {
|
2018-12-10 19:37:25 +01:00
|
|
|
r_core_cmd_help (core, help_msg_pxA);
|
2016-11-20 19:20:14 +01:00
|
|
|
} else if (l) {
|
2019-04-29 12:51:13 +03:00
|
|
|
cmd_print_pxA (core, len, input + 2);
|
2015-04-09 00:03:46 +02:00
|
|
|
}
|
2015-03-21 00:27:49 +01:00
|
|
|
break;
|
2015-04-03 02:54:27 +02:00
|
|
|
case 'b': // "pxb"
|
2016-11-20 19:20:14 +01:00
|
|
|
if (l) {
|
2017-03-09 23:29:48 +01:00
|
|
|
ut32 n;
|
|
|
|
int i, c;
|
|
|
|
char buf[32];
|
|
|
|
for (i = c = 0; i < len; i++, c++) {
|
|
|
|
if (c == 0) {
|
2019-04-15 13:22:27 +02:00
|
|
|
ut64 ea = core->offset + i;
|
|
|
|
if (core->print->pava) {
|
|
|
|
ut64 va = r_io_p2v (core->io, ea);
|
|
|
|
if (va != UT64_MAX) {
|
|
|
|
ea = va;
|
|
|
|
}
|
|
|
|
}
|
2019-06-19 12:15:13 +02:00
|
|
|
r_print_section (core->print, ea);
|
2019-04-15 13:22:27 +02:00
|
|
|
r_print_offset (core->print, ea, 0, 0, 0, 0, NULL);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
|
|
|
r_str_bits (buf, core->block + i, 8, NULL);
|
|
|
|
|
|
|
|
// split bits
|
|
|
|
memmove (buf + 5, buf + 4, 5);
|
|
|
|
buf[4] = 0;
|
|
|
|
|
2019-01-02 02:09:31 +01:00
|
|
|
r_print_cursor (core->print, i, 1, 1);
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("%s.%s ", buf, buf + 5);
|
2019-01-02 02:09:31 +01:00
|
|
|
r_print_cursor (core->print, i, 1, 0);
|
2017-03-09 23:29:48 +01:00
|
|
|
if (c == 3) {
|
|
|
|
const ut8 *b = core->block + i - 3;
|
|
|
|
int (*k) (const ut8 *, int) = cmd_pxb_k;
|
2018-11-11 16:48:17 -08:00
|
|
|
char (*p) (char) = cmd_pxb_p;
|
2017-03-09 23:29:48 +01:00
|
|
|
|
|
|
|
n = k (b, 0) | k (b, 1) | k (b, 2) | k (b, 3);
|
|
|
|
r_cons_printf ("0x%08x %c%c%c%c\n",
|
|
|
|
n, p (b[0]), p (b[1]), p (b[2]), p (b[3]));
|
|
|
|
c = -1;
|
|
|
|
}
|
2015-04-03 02:54:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'c': // "pxc"
|
2017-08-23 01:56:54 +02:00
|
|
|
{
|
|
|
|
int ocomments = core->print->use_comments;
|
2017-01-18 16:12:06 +01:00
|
|
|
core->print->use_comments = core->print->flags & R_PRINT_FLAGS_COMMENT;
|
|
|
|
if (l) {
|
|
|
|
ut64 from = r_config_get_i (core->config, "diff.from");
|
|
|
|
ut64 to = r_config_get_i (core->config, "diff.to");
|
|
|
|
if (from == to && !from) {
|
2018-04-02 03:32:53 +02:00
|
|
|
r_core_block_size (core, len);
|
|
|
|
len = core->blocksize;
|
2017-01-18 16:12:06 +01:00
|
|
|
r_print_hexdump (core->print, core->offset,
|
2018-04-02 03:32:53 +02:00
|
|
|
core->block, core->blocksize, 16, 1, 1);
|
2017-01-18 16:12:06 +01:00
|
|
|
} else {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_print_cmp (core, from, to);
|
2017-01-18 16:12:06 +01:00
|
|
|
}
|
|
|
|
core->num->value = len;
|
|
|
|
}
|
2017-08-23 01:56:54 +02:00
|
|
|
core->print->use_comments = ocomments;
|
|
|
|
}
|
2017-01-18 16:12:06 +01:00
|
|
|
break;
|
2016-05-10 00:18:21 +02:00
|
|
|
case 'i': // "pxi"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
2020-03-31 19:44:23 +07:00
|
|
|
core->print->show_offset = r_config_get_i (core->config, "hex.offset");
|
2016-05-17 00:37:47 +02:00
|
|
|
r_print_hexii (core->print, core->offset, core->block,
|
|
|
|
core->blocksize, r_config_get_i (core->config, "hex.cols"));
|
|
|
|
}
|
2016-05-10 00:18:21 +02:00
|
|
|
break;
|
2015-03-21 03:06:31 +01:00
|
|
|
case 'o': // "pxo"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
|
|
|
r_print_hexdump (core->print, core->offset,
|
2017-06-06 00:20:49 +00:00
|
|
|
core->block, len, 8, 1, 1);
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2012-09-27 19:35:19 +02:00
|
|
|
break;
|
2016-05-30 04:18:48 +02:00
|
|
|
case 't': // "pxt"
|
2018-09-07 11:38:08 +02:00
|
|
|
{
|
|
|
|
ut64 origin = core->offset;
|
|
|
|
const char *arg = strchr (input, ' ');
|
|
|
|
if (arg) {
|
|
|
|
origin = r_num_math (core->num, arg + 1);
|
|
|
|
}
|
|
|
|
// _pointer_table does r_core_cmd with @, so it modifies core->block
|
|
|
|
// and this results in an UAF access when iterating over the jmptable
|
|
|
|
// so we do a new allocation to avoid that issue
|
|
|
|
ut8 *block = calloc (len, 1);
|
|
|
|
if (block) {
|
|
|
|
memcpy (block, core->block, len);
|
|
|
|
_pointer_table (core, origin, core->offset, block, len, 4, input[2]);
|
|
|
|
free (block);
|
|
|
|
}
|
2016-05-30 04:18:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2015-04-28 20:46:47 +02:00
|
|
|
case 'd': // "pxd"
|
2018-08-28 14:22:09 +02:00
|
|
|
if (input[2] == '?') {
|
|
|
|
r_core_cmd_help (core, help_msg_pxd);
|
|
|
|
} else if (l != 0) {
|
2017-03-09 23:29:48 +01:00
|
|
|
switch (input[2]) {
|
|
|
|
case '1':
|
|
|
|
// 1 byte signed words (byte)
|
2020-10-09 06:53:51 +02:00
|
|
|
if (input[3] == 'j') {
|
|
|
|
r_print_jsondump (core->print, core->block,
|
|
|
|
len, 8);
|
|
|
|
} else {
|
|
|
|
r_print_hexdump (core->print, core->offset,
|
|
|
|
core->block, len, -1, 4, 1);
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
break;
|
|
|
|
case '2':
|
|
|
|
// 2 byte signed words (short)
|
2020-10-09 06:53:51 +02:00
|
|
|
if (input[3] == 'j') {
|
|
|
|
r_print_jsondump (core->print, core->block,
|
|
|
|
len, 16);
|
|
|
|
} else {
|
|
|
|
r_print_hexdump (core->print, core->offset,
|
|
|
|
core->block, len, -10, 2, 1);
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
break;
|
|
|
|
case '8':
|
2020-10-09 06:53:51 +02:00
|
|
|
if (input[3] == 'j') {
|
|
|
|
r_print_jsondump (core->print, core->block,
|
|
|
|
len, 64);
|
|
|
|
} else {
|
|
|
|
r_print_hexdump (core->print, core->offset,
|
|
|
|
core->block, len, -8, 4, 1);
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
break;
|
|
|
|
case '4':
|
2018-08-28 15:54:04 +02:00
|
|
|
case ' ':
|
2020-10-09 06:53:51 +02:00
|
|
|
case 'j':
|
2018-08-28 14:22:09 +02:00
|
|
|
case 0:
|
2017-03-09 23:29:48 +01:00
|
|
|
// 4 byte signed words
|
2020-10-15 18:14:03 +08:00
|
|
|
if (input[2] == 'j' || (input[2] && input[3] == 'j')) {
|
2020-10-09 06:53:51 +02:00
|
|
|
r_print_jsondump (core->print, core->block,
|
|
|
|
len, 32);
|
|
|
|
} else {
|
|
|
|
r_print_hexdump (core->print, core->offset,
|
|
|
|
core->block, len, 10, 4, 1);
|
|
|
|
}
|
2018-08-13 11:45:54 +02:00
|
|
|
break;
|
2018-08-28 14:22:09 +02:00
|
|
|
default:
|
|
|
|
r_core_cmd_help (core, help_msg_pxd);
|
|
|
|
break;
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2014-04-12 01:13:34 +02:00
|
|
|
break;
|
2016-06-07 00:12:45 +02:00
|
|
|
case 'w': // "pxw"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
2017-05-13 18:27:55 +02:00
|
|
|
if (input[2] == 'j') {
|
|
|
|
r_print_jsondump (core->print, core->block, len, 32);
|
|
|
|
} else {
|
2017-06-06 00:20:49 +00:00
|
|
|
r_print_hexdump (core->print, core->offset, core->block, len, 32, 4, 1);
|
2017-05-13 18:27:55 +02:00
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2012-09-27 19:35:19 +02:00
|
|
|
break;
|
2015-04-28 20:46:47 +02:00
|
|
|
case 'W': // "pxW"
|
2016-11-20 19:20:14 +01:00
|
|
|
if (l) {
|
2020-03-31 19:44:23 +07:00
|
|
|
bool printOffset = (input[2] != 'q' && r_config_get_i (core->config, "hex.offset"));
|
2016-11-20 19:20:14 +01:00
|
|
|
len = len - (len % 4);
|
|
|
|
for (i = 0; i < len; i += 4) {
|
|
|
|
const char *a, *b;
|
|
|
|
char *fn;
|
|
|
|
RPrint *p = core->print;
|
|
|
|
RFlagItem *f;
|
|
|
|
ut32 v = r_read_ble32 (core->block + i, core->print->big_endian);
|
|
|
|
if (p && p->colorfor) {
|
2017-01-13 14:13:53 +01:00
|
|
|
a = p->colorfor (p->user, v, true);
|
2016-11-20 19:20:14 +01:00
|
|
|
if (a && *a) {
|
|
|
|
b = Color_RESET;
|
|
|
|
} else {
|
|
|
|
a = b = "";
|
|
|
|
}
|
2015-10-05 14:43:17 +02:00
|
|
|
} else {
|
|
|
|
a = b = "";
|
|
|
|
}
|
2016-12-01 10:48:00 +01:00
|
|
|
f = r_flag_get_at (core->flags, v, true);
|
2016-11-20 19:20:14 +01:00
|
|
|
fn = NULL;
|
|
|
|
if (f) {
|
|
|
|
st64 delta = (v - f->offset);
|
|
|
|
if (delta >= 0 && delta < 8192) {
|
|
|
|
if (v == f->offset) {
|
|
|
|
fn = strdup (f->name);
|
|
|
|
} else {
|
2020-10-13 16:26:15 +02:00
|
|
|
fn = r_str_newf ("%s+%" PFMT64d,
|
2017-03-09 23:29:48 +01:00
|
|
|
f->name, v - f->offset);
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
2015-10-05 14:43:17 +02:00
|
|
|
}
|
2015-02-01 02:28:49 +01:00
|
|
|
}
|
2018-04-04 22:42:50 +02:00
|
|
|
if (printOffset) {
|
2019-06-19 12:17:08 +02:00
|
|
|
r_print_section (core->print, core->offset +i);
|
2018-04-04 22:42:50 +02:00
|
|
|
r_cons_printf ("0x%08"PFMT64x " %s0x%08"PFMT64x "%s%s%s\n",
|
|
|
|
(ut64) core->offset + i, a, (ut64) v,
|
|
|
|
b, fn? " ": "", fn? fn: "");
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%s0x%08"PFMT64x "%s\n", a, (ut64) v, b);
|
|
|
|
}
|
2016-11-20 19:20:14 +01:00
|
|
|
free (fn);
|
2015-02-01 02:28:49 +01:00
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2012-10-25 12:55:28 +02:00
|
|
|
break;
|
2015-06-04 22:58:08 +02:00
|
|
|
case 'r': // "pxr"
|
2016-11-20 19:20:14 +01:00
|
|
|
if (l) {
|
2020-10-25 12:35:45 +01:00
|
|
|
int mode = input[2];
|
|
|
|
int wordsize = core->anal->bits / 8;
|
|
|
|
if (mode == '?') {
|
|
|
|
eprintf ("Usage: pxr[1248][*,jq] [length]\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (mode && isdigit (mode)) {
|
|
|
|
char tmp[2] = {input[2], 0};
|
|
|
|
wordsize = atoi (tmp);
|
|
|
|
mode = input[3];
|
|
|
|
}
|
|
|
|
switch (wordsize) {
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
case 4:
|
|
|
|
case 8:
|
|
|
|
cmd_pxr (core, len, mode, wordsize, mode? strchr (input, mode): NULL);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
eprintf ("Invalid word size. Use 1, 2, 4 or 8.\n");
|
|
|
|
break;
|
2015-06-04 22:58:08 +02:00
|
|
|
}
|
2014-10-27 17:23:13 +01:00
|
|
|
}
|
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'h': // "pxh"
|
2016-11-20 19:20:14 +01:00
|
|
|
if (l) {
|
2017-05-13 18:27:55 +02:00
|
|
|
if (input[2] == 'j') {
|
|
|
|
r_print_jsondump (core->print, core->block, len, 16);
|
|
|
|
} else {
|
|
|
|
r_print_hexdump (core->print, core->offset,
|
2017-06-06 00:20:49 +00:00
|
|
|
core->block, len, 32, 2, 1);
|
2017-05-13 18:27:55 +02:00
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2015-02-16 02:45:12 +01:00
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'H': // "pxH"
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
2017-03-09 23:29:48 +01:00
|
|
|
len = len - (len % 2);
|
|
|
|
for (i = 0; i < len; i += 2) {
|
|
|
|
const char *a, *b;
|
|
|
|
char *fn;
|
|
|
|
RPrint *p = core->print;
|
|
|
|
RFlagItem *f;
|
|
|
|
ut64 v = (ut64) r_read_ble16 (core->block + i, p->big_endian);
|
|
|
|
if (p && p->colorfor) {
|
|
|
|
a = p->colorfor (p->user, v, true);
|
|
|
|
if (a && *a) {
|
|
|
|
b = Color_RESET;
|
|
|
|
} else {
|
|
|
|
a = b = "";
|
|
|
|
}
|
2017-01-31 10:00:24 +01:00
|
|
|
} else {
|
|
|
|
a = b = "";
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
f = r_flag_get_at (core->flags, v, true);
|
|
|
|
fn = NULL;
|
|
|
|
if (f) {
|
|
|
|
st64 delta = (v - f->offset);
|
|
|
|
if (delta >= 0 && delta < 8192) {
|
|
|
|
if (v == f->offset) {
|
|
|
|
fn = strdup (f->name);
|
|
|
|
} else {
|
2019-12-13 11:25:19 -06:00
|
|
|
fn = r_str_newf ("%s+%"PFMT64d, f->name, v - f->offset);
|
2017-03-09 23:29:48 +01:00
|
|
|
}
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
2015-02-16 02:45:12 +01:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("0x%08"PFMT64x " %s0x%04"PFMT64x "%s %s\n",
|
|
|
|
(ut64) core->offset + i, a, v, b, fn? fn: "");
|
|
|
|
free (fn);
|
2015-02-16 02:45:12 +01:00
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2015-02-16 02:45:12 +01:00
|
|
|
break;
|
2017-05-13 18:27:55 +02:00
|
|
|
case 'q': // "pxq"
|
2016-11-20 19:20:14 +01:00
|
|
|
if (l) {
|
2017-05-13 18:27:55 +02:00
|
|
|
if (input[2] == 'j') {
|
|
|
|
r_print_jsondump (core->print, core->block, len, 64);
|
|
|
|
} else {
|
2017-06-06 00:20:49 +00:00
|
|
|
r_print_hexdump (core->print, core->offset, core->block, len, 64, 8, 1);
|
2017-05-13 18:27:55 +02:00
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2012-09-27 19:35:19 +02:00
|
|
|
break;
|
2017-05-13 18:27:55 +02:00
|
|
|
case 'Q': // "pxQ"
|
2015-01-25 04:30:05 +01:00
|
|
|
// TODO. show if flag name, or inside function
|
2016-11-20 19:20:14 +01:00
|
|
|
if (l) {
|
2020-03-31 19:44:23 +07:00
|
|
|
bool printOffset = (input[2] != 'q' && r_config_get_i (core->config, "hex.offset"));
|
2016-11-20 19:20:14 +01:00
|
|
|
len = len - (len % 8);
|
|
|
|
for (i = 0; i < len; i += 8) {
|
|
|
|
const char *a, *b;
|
|
|
|
char *fn;
|
|
|
|
RPrint *p = core->print;
|
|
|
|
RFlagItem *f;
|
|
|
|
ut64 v = r_read_ble64 (core->block + i, p->big_endian);
|
|
|
|
if (p && p->colorfor) {
|
2017-01-13 14:13:53 +01:00
|
|
|
a = p->colorfor (p->user, v, true);
|
2017-01-31 10:00:24 +01:00
|
|
|
if (a && *a) {
|
|
|
|
b = Color_RESET;
|
|
|
|
} else {
|
|
|
|
a = b = "";
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
2017-01-31 10:00:24 +01:00
|
|
|
} else {
|
|
|
|
a = b = "";
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
2016-12-01 10:48:00 +01:00
|
|
|
f = r_flag_get_at (core->flags, v, true);
|
2016-11-20 19:20:14 +01:00
|
|
|
fn = NULL;
|
|
|
|
if (f) {
|
|
|
|
st64 delta = (v - f->offset);
|
2017-03-09 23:29:48 +01:00
|
|
|
if (delta >= 0 && delta < 8192) {
|
2016-11-20 19:20:14 +01:00
|
|
|
if (v == f->offset) {
|
|
|
|
fn = strdup (f->name);
|
|
|
|
} else {
|
2020-10-13 16:26:15 +02:00
|
|
|
fn = r_str_newf ("%s+%" PFMT64d, f->name, v - f->offset);
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
|
|
|
}
|
2015-02-01 02:28:49 +01:00
|
|
|
}
|
2018-04-04 22:42:50 +02:00
|
|
|
if (printOffset) {
|
2019-06-19 12:17:08 +02:00
|
|
|
r_print_section (core->print, core->offset +i);
|
2018-04-04 22:42:50 +02:00
|
|
|
r_cons_printf ("0x%08"PFMT64x " %s0x%016"PFMT64x "%s %s\n",
|
|
|
|
(ut64) core->offset + i, a, v, b, fn? fn: "");
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%s0x%016"PFMT64x "%s\n", a, v, b);
|
|
|
|
}
|
2016-11-20 19:20:14 +01:00
|
|
|
free (fn);
|
2015-02-01 02:28:49 +01:00
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2012-10-25 12:55:28 +02:00
|
|
|
break;
|
2017-05-13 18:27:55 +02:00
|
|
|
case 's': // "pxs"
|
2016-11-20 19:20:14 +01:00
|
|
|
if (l) {
|
2016-05-17 00:37:47 +02:00
|
|
|
core->print->flags |= R_PRINT_FLAGS_SPARSE;
|
2017-06-06 00:20:49 +00:00
|
|
|
r_print_hexdump (core->print, core->offset, core->block, len, 16, 1, 1);
|
2017-03-09 23:29:48 +01:00
|
|
|
core->print->flags &= (((ut32) - 1) & (~R_PRINT_FLAGS_SPARSE));
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2013-10-19 23:35:39 +02:00
|
|
|
break;
|
2017-05-29 03:45:02 +02:00
|
|
|
case 'e': // "pxe" // emoji dump
|
2016-05-17 00:37:47 +02:00
|
|
|
if (l != 0) {
|
2013-12-13 11:41:23 +01:00
|
|
|
int j;
|
2017-03-09 23:29:48 +01:00
|
|
|
char emoji[] = {
|
|
|
|
'\x8c', '\x80', '\x8c', '\x82', '\x8c', '\x85', '\x8c', '\x88',
|
|
|
|
'\x8c', '\x99', '\x8c', '\x9e', '\x8c', '\x9f', '\x8c', '\xa0',
|
|
|
|
'\x8c', '\xb0', '\x8c', '\xb1', '\x8c', '\xb2', '\x8c', '\xb3',
|
|
|
|
'\x8c', '\xb4', '\x8c', '\xb5', '\x8c', '\xb7', '\x8c', '\xb8',
|
|
|
|
'\x8c', '\xb9', '\x8c', '\xba', '\x8c', '\xbb', '\x8c', '\xbc',
|
|
|
|
'\x8c', '\xbd', '\x8c', '\xbe', '\x8c', '\xbf', '\x8d', '\x80',
|
|
|
|
'\x8d', '\x81', '\x8d', '\x82', '\x8d', '\x83', '\x8d', '\x84',
|
|
|
|
'\x8d', '\x85', '\x8d', '\x86', '\x8d', '\x87', '\x8d', '\x88',
|
|
|
|
'\x8d', '\x89', '\x8d', '\x8a', '\x8d', '\x8b', '\x8d', '\x8c',
|
|
|
|
'\x8d', '\x8d', '\x8d', '\x8e', '\x8d', '\x8f', '\x8d', '\x90',
|
|
|
|
'\x8d', '\x91', '\x8d', '\x92', '\x8d', '\x93', '\x8d', '\x94',
|
|
|
|
'\x8d', '\x95', '\x8d', '\x96', '\x8d', '\x97', '\x8d', '\x98',
|
|
|
|
'\x8d', '\x9c', '\x8d', '\x9d', '\x8d', '\x9e', '\x8d', '\x9f',
|
|
|
|
'\x8d', '\xa0', '\x8d', '\xa1', '\x8d', '\xa2', '\x8d', '\xa3',
|
|
|
|
'\x8d', '\xa4', '\x8d', '\xa5', '\x8d', '\xa6', '\x8d', '\xa7',
|
|
|
|
'\x8d', '\xa8', '\x8d', '\xa9', '\x8d', '\xaa', '\x8d', '\xab',
|
|
|
|
'\x8d', '\xac', '\x8d', '\xad', '\x8d', '\xae', '\x8d', '\xaf',
|
|
|
|
'\x8d', '\xb0', '\x8d', '\xb1', '\x8d', '\xb2', '\x8d', '\xb3',
|
|
|
|
'\x8d', '\xb4', '\x8d', '\xb5', '\x8d', '\xb6', '\x8d', '\xb7',
|
|
|
|
'\x8d', '\xb8', '\x8d', '\xb9', '\x8d', '\xba', '\x8d', '\xbb',
|
|
|
|
'\x8d', '\xbc', '\x8e', '\x80', '\x8e', '\x81', '\x8e', '\x82',
|
|
|
|
'\x8e', '\x83', '\x8e', '\x84', '\x8e', '\x85', '\x8e', '\x88',
|
|
|
|
'\x8e', '\x89', '\x8e', '\x8a', '\x8e', '\x8b', '\x8e', '\x8c',
|
|
|
|
'\x8e', '\x8d', '\x8e', '\x8e', '\x8e', '\x8f', '\x8e', '\x92',
|
|
|
|
'\x8e', '\x93', '\x8e', '\xa0', '\x8e', '\xa1', '\x8e', '\xa2',
|
|
|
|
'\x8e', '\xa3', '\x8e', '\xa4', '\x8e', '\xa5', '\x8e', '\xa6',
|
|
|
|
'\x8e', '\xa7', '\x8e', '\xa8', '\x8e', '\xa9', '\x8e', '\xaa',
|
|
|
|
'\x8e', '\xab', '\x8e', '\xac', '\x8e', '\xad', '\x8e', '\xae',
|
|
|
|
'\x8e', '\xaf', '\x8e', '\xb0', '\x8e', '\xb1', '\x8e', '\xb2',
|
|
|
|
'\x8e', '\xb3', '\x8e', '\xb4', '\x8e', '\xb5', '\x8e', '\xb7',
|
|
|
|
'\x8e', '\xb8', '\x8e', '\xb9', '\x8e', '\xba', '\x8e', '\xbb',
|
|
|
|
'\x8e', '\xbd', '\x8e', '\xbe', '\x8e', '\xbf', '\x8f', '\x80',
|
|
|
|
'\x8f', '\x81', '\x8f', '\x82', '\x8f', '\x83', '\x8f', '\x84',
|
|
|
|
'\x8f', '\x86', '\x8f', '\x87', '\x8f', '\x88', '\x8f', '\x89',
|
|
|
|
'\x8f', '\x8a', '\x90', '\x80', '\x90', '\x81', '\x90', '\x82',
|
|
|
|
'\x90', '\x83', '\x90', '\x84', '\x90', '\x85', '\x90', '\x86',
|
|
|
|
'\x90', '\x87', '\x90', '\x88', '\x90', '\x89', '\x90', '\x8a',
|
|
|
|
'\x90', '\x8b', '\x90', '\x8c', '\x90', '\x8d', '\x90', '\x8e',
|
|
|
|
'\x90', '\x8f', '\x90', '\x90', '\x90', '\x91', '\x90', '\x92',
|
|
|
|
'\x90', '\x93', '\x90', '\x94', '\x90', '\x95', '\x90', '\x96',
|
|
|
|
'\x90', '\x97', '\x90', '\x98', '\x90', '\x99', '\x90', '\x9a',
|
|
|
|
'\x90', '\x9b', '\x90', '\x9c', '\x90', '\x9d', '\x90', '\x9e',
|
|
|
|
'\x90', '\x9f', '\x90', '\xa0', '\x90', '\xa1', '\x90', '\xa2',
|
|
|
|
'\x90', '\xa3', '\x90', '\xa4', '\x90', '\xa5', '\x90', '\xa6',
|
|
|
|
'\x90', '\xa7', '\x90', '\xa8', '\x90', '\xa9', '\x90', '\xaa',
|
|
|
|
'\x90', '\xab', '\x90', '\xac', '\x90', '\xad', '\x90', '\xae',
|
|
|
|
'\x90', '\xaf', '\x90', '\xb0', '\x90', '\xb1', '\x90', '\xb2',
|
|
|
|
'\x90', '\xb3', '\x90', '\xb4', '\x90', '\xb5', '\x90', '\xb6',
|
|
|
|
'\x90', '\xb7', '\x90', '\xb8', '\x90', '\xb9', '\x90', '\xba',
|
|
|
|
'\x90', '\xbb', '\x90', '\xbc', '\x90', '\xbd', '\x90', '\xbe',
|
|
|
|
'\x91', '\x80', '\x91', '\x82', '\x91', '\x83', '\x91', '\x84',
|
|
|
|
'\x91', '\x85', '\x91', '\x86', '\x91', '\x87', '\x91', '\x88',
|
|
|
|
'\x91', '\x89', '\x91', '\x8a', '\x91', '\x8b', '\x91', '\x8c',
|
|
|
|
'\x91', '\x8d', '\x91', '\x8e', '\x91', '\x8f', '\x91', '\x90',
|
|
|
|
'\x91', '\x91', '\x91', '\x92', '\x91', '\x93', '\x91', '\x94',
|
|
|
|
'\x91', '\x95', '\x91', '\x96', '\x91', '\x97', '\x91', '\x98',
|
|
|
|
'\x91', '\x99', '\x91', '\x9a', '\x91', '\x9b', '\x91', '\x9c',
|
|
|
|
'\x91', '\x9d', '\x91', '\x9e', '\x91', '\x9f', '\x91', '\xa0',
|
|
|
|
'\x91', '\xa1', '\x91', '\xa2', '\x91', '\xa3', '\x91', '\xa4',
|
|
|
|
'\x91', '\xa5', '\x91', '\xa6', '\x91', '\xa7', '\x91', '\xa8',
|
|
|
|
'\x91', '\xa9', '\x91', '\xaa', '\x91', '\xae', '\x91', '\xaf',
|
|
|
|
'\x91', '\xba', '\x91', '\xbb', '\x91', '\xbc', '\x91', '\xbd',
|
|
|
|
'\x91', '\xbe', '\x91', '\xbf', '\x92', '\x80', '\x92', '\x81',
|
|
|
|
'\x92', '\x82', '\x92', '\x83', '\x92', '\x84', '\x92', '\x85'
|
|
|
|
};
|
2016-09-15 19:31:25 +02:00
|
|
|
int cols = core->print->cols;
|
|
|
|
if (cols < 1) {
|
|
|
|
cols = 1;
|
|
|
|
}
|
|
|
|
for (i = 0; i < len; i += cols) {
|
2016-11-20 19:20:14 +01:00
|
|
|
r_print_addr (core->print, core->offset + i);
|
2016-09-15 19:31:25 +02:00
|
|
|
for (j = i; j < i + cols; j += 1) {
|
2017-03-09 23:29:48 +01:00
|
|
|
ut8 *p = (ut8 *) core->block + j;
|
2016-11-20 19:20:14 +01:00
|
|
|
if (j < len) {
|
2017-11-22 00:44:29 +01:00
|
|
|
r_cons_printf ("\xf0\x9f%c%c ", emoji[*p * 2], emoji[*p * 2 + 1]);
|
2016-09-15 19:31:25 +02:00
|
|
|
} else {
|
2017-11-22 00:44:29 +01:00
|
|
|
r_cons_print (" ");
|
2016-09-15 19:31:25 +02:00
|
|
|
}
|
2013-12-13 11:41:23 +01:00
|
|
|
}
|
2016-09-15 19:31:25 +02:00
|
|
|
r_cons_print (" ");
|
|
|
|
for (j = i; j < len && j < i + cols; j += 1) {
|
2017-03-09 23:29:48 +01:00
|
|
|
ut8 *p = (ut8 *) core->block + j;
|
2013-12-13 11:41:23 +01:00
|
|
|
r_print_byte (core->print, "%c", j, *p);
|
|
|
|
}
|
2016-09-15 19:31:25 +02:00
|
|
|
r_cons_newline ();
|
2013-12-13 11:41:23 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'l': // "pxl"
|
2016-11-20 19:20:14 +01:00
|
|
|
len = core->print->cols * len;
|
2017-07-18 01:24:46 -07:00
|
|
|
/* fallthrough */
|
2016-05-17 00:37:47 +02:00
|
|
|
default:
|
2016-11-20 19:20:14 +01:00
|
|
|
if (l) {
|
2015-05-10 22:40:02 +02:00
|
|
|
ut64 from = r_config_get_i (core->config, "diff.from");
|
|
|
|
ut64 to = r_config_get_i (core->config, "diff.to");
|
2016-11-20 19:20:14 +01:00
|
|
|
if (from == to && !from) {
|
2019-06-20 08:51:47 +01:00
|
|
|
const char *sp = NULL;
|
|
|
|
if (input[1] == '.') {
|
|
|
|
sp = input + 2;
|
|
|
|
}
|
|
|
|
if (IS_DIGIT (input[1])) {
|
|
|
|
sp = input + 1;
|
|
|
|
}
|
|
|
|
if (sp) {
|
2020-03-02 21:39:37 +01:00
|
|
|
int n = (int) r_num_math (core->num, r_str_trim_head_ro (sp));
|
2019-06-20 08:51:47 +01:00
|
|
|
if (!n) {
|
|
|
|
goto beach;
|
|
|
|
}
|
|
|
|
len = n;
|
|
|
|
}
|
2016-11-06 17:54:25 -03:00
|
|
|
if (!r_core_block_size (core, len)) {
|
2017-03-09 23:29:48 +01:00
|
|
|
len = core->blocksize;
|
2016-11-06 17:54:25 -03:00
|
|
|
}
|
2019-04-09 02:56:53 +02:00
|
|
|
r_core_block_read (core);
|
2018-07-02 12:19:13 +02:00
|
|
|
r_print_hexdump (core->print, r_core_pava (core, core->offset),
|
2017-06-06 00:20:49 +00:00
|
|
|
core->block, len, 16, 1, 1);
|
2015-05-10 22:40:02 +02:00
|
|
|
} else {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_print_cmp (core, from, to);
|
2015-05-10 22:40:02 +02:00
|
|
|
}
|
|
|
|
core->num->value = len;
|
2016-11-04 01:30:35 +01:00
|
|
|
}
|
2012-09-27 19:35:19 +02:00
|
|
|
break;
|
2012-08-13 04:33:01 +02:00
|
|
|
}
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_pop ();
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2016-05-17 00:37:47 +02:00
|
|
|
case '2': // "p2"
|
2016-12-28 12:23:53 +01:00
|
|
|
if (l) {
|
2016-11-20 19:20:14 +01:00
|
|
|
if (input[1] == '?') {
|
2016-05-17 00:37:47 +02:00
|
|
|
r_cons_printf ("|Usage: p2 [number of bytes representing tiles]\n"
|
2017-03-09 23:29:48 +01:00
|
|
|
"NOTE: Only full tiles will be printed\n");
|
2016-11-20 19:20:14 +01:00
|
|
|
} else {
|
2017-02-10 13:43:16 +01:00
|
|
|
r_print_2bpp_tiles (core->print, core->block, len / 16);
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2014-02-09 02:56:54 +01:00
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case '6': // "p6"
|
2016-12-28 12:23:53 +01:00
|
|
|
if (l) {
|
2017-03-09 23:29:48 +01:00
|
|
|
int malen = (core->blocksize * 4) + 1;
|
2016-12-28 12:23:53 +01:00
|
|
|
ut8 *buf = malloc (malen);
|
|
|
|
if (!buf) {
|
|
|
|
break;
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
memset (buf, 0, malen);
|
|
|
|
switch (input[1]) {
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'd': // "p6d"
|
2018-09-07 16:28:49 +02:00
|
|
|
if (r_base64_decode (buf, (const char *) block, len)) {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_println ((const char *) buf);
|
|
|
|
} else {
|
|
|
|
eprintf ("r_base64_decode: invalid stream\n");
|
|
|
|
}
|
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'e': // "p6e"
|
2017-03-09 23:29:48 +01:00
|
|
|
len = len > core->blocksize? core->blocksize: len;
|
2018-02-19 04:30:32 -08:00
|
|
|
r_base64_encode ((char *) buf, block, len);
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_println ((const char *) buf);
|
|
|
|
break;
|
|
|
|
case '?':
|
|
|
|
default:
|
2018-09-07 16:28:49 +02:00
|
|
|
r_core_cmd_help(core, help_msg_p6);
|
2014-10-30 23:26:36 +01:00
|
|
|
break;
|
|
|
|
}
|
2017-03-09 23:29:48 +01:00
|
|
|
free (buf);
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
|
|
|
break;
|
2015-11-05 12:36:59 +01:00
|
|
|
case '8': // "p8"
|
2015-04-03 23:24:09 +02:00
|
|
|
if (input[1] == '?') {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("|Usage: p8[fj] [len] 8bit hexpair list of bytes (see pcj)\n");
|
2019-04-09 02:56:53 +02:00
|
|
|
r_cons_printf (" p8 : print hexpairs string\n");
|
|
|
|
r_cons_printf (" p8f : print hexpairs of function (linear)\n");
|
|
|
|
r_cons_printf (" p8j : print hexpairs in JSON array\n");
|
2016-11-20 19:20:14 +01:00
|
|
|
} else if (l) {
|
2016-11-06 17:54:25 -03:00
|
|
|
if (!r_core_block_size (core, len)) {
|
|
|
|
len = core->blocksize;
|
|
|
|
}
|
2017-07-18 01:24:46 -07:00
|
|
|
if (input[1] == 'j') { // "p8j"
|
2017-03-09 23:29:48 +01:00
|
|
|
r_core_cmdf (core, "pcj %s", input + 2);
|
2017-07-18 01:24:46 -07:00
|
|
|
} else if (input[1] == 'f') { // "p8f"
|
2019-04-09 02:56:53 +02:00
|
|
|
r_core_cmdf (core, "p8 $FS @ $FB");
|
2016-10-09 20:13:32 +02:00
|
|
|
} else {
|
2019-04-09 02:56:53 +02:00
|
|
|
r_core_block_read (core);
|
|
|
|
block = core->block;
|
2018-02-19 04:30:32 -08:00
|
|
|
r_print_bytes (core->print, block, len, "%02x");
|
2016-10-09 20:13:32 +02:00
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2019-01-11 09:56:27 +01:00
|
|
|
case 'g': // "pg"
|
|
|
|
cmd_print_gadget (core, input + 1);
|
|
|
|
break;
|
2015-11-05 12:36:59 +01:00
|
|
|
case 'f': // "pf"
|
2018-02-26 00:59:41 -08:00
|
|
|
cmd_print_format (core, input, block, len);
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2018-09-12 18:43:59 +02:00
|
|
|
case 'F': // "pF"
|
|
|
|
cmd_print_fromage (core, input + 1, block, len);
|
|
|
|
break;
|
2016-05-17 00:37:47 +02:00
|
|
|
case 'k': // "pk"
|
2014-10-29 20:19:28 +01:00
|
|
|
if (input[1] == '?') {
|
2015-06-04 16:53:04 +02:00
|
|
|
r_cons_printf ("|Usage: pk [len] print key in randomart\n");
|
2016-12-09 18:07:06 +01:00
|
|
|
r_cons_printf ("|Usage: pkill [process-name]\n");
|
|
|
|
} else if (!strncmp (input, "kill", 4)) {
|
|
|
|
RListIter *iter;
|
|
|
|
RDebugPid *pid;
|
|
|
|
const char *arg = strchr (input, ' ');
|
|
|
|
RList *pids = (core->dbg->h && core->dbg->h->pids)
|
2017-03-09 23:29:48 +01:00
|
|
|
? core->dbg->h->pids (core->dbg, 0): NULL;
|
2016-12-09 18:07:06 +01:00
|
|
|
if (arg && *++arg) {
|
|
|
|
r_list_foreach (pids, iter, pid) {
|
|
|
|
if (strstr (pid->path, arg)) {
|
|
|
|
r_cons_printf ("dk 9 %d\n", pid->pid);
|
|
|
|
}
|
|
|
|
// r_debug_kill (core->dbg, pid->pid, pid->pid, 9); // kill -9
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_list_free (pids);
|
2016-05-17 00:37:47 +02:00
|
|
|
} else if (l > 0) {
|
2017-03-09 23:29:48 +01:00
|
|
|
len = len > core->blocksize? core->blocksize: len;
|
2018-02-19 04:30:32 -08:00
|
|
|
char *s = r_print_randomart (block, len, core->offset);
|
2016-06-26 00:51:17 -04:00
|
|
|
r_cons_println (s);
|
2014-10-29 20:19:28 +01:00
|
|
|
free (s);
|
2013-02-12 02:42:34 +01:00
|
|
|
}
|
|
|
|
break;
|
2016-05-17 00:37:47 +02:00
|
|
|
case 'K': // "pK"
|
2014-10-29 20:19:28 +01:00
|
|
|
if (input[1] == '?') {
|
2015-06-04 16:53:04 +02:00
|
|
|
r_cons_printf ("|Usage: pK [len] print key in randomart mosaic\n");
|
2016-05-17 00:37:47 +02:00
|
|
|
} else if (l > 0) {
|
2017-03-09 23:29:48 +01:00
|
|
|
len = len > core->blocksize? core->blocksize: len;
|
2014-10-29 20:19:28 +01:00
|
|
|
int w, h;
|
|
|
|
RConsCanvas *c;
|
|
|
|
w = r_cons_get_size (&h);
|
|
|
|
ut64 offset0 = core->offset;
|
2017-03-09 23:29:48 +01:00
|
|
|
int cols = (w / 20);
|
|
|
|
int rows = (h / 12);
|
2014-10-29 20:19:28 +01:00
|
|
|
int i, j;
|
|
|
|
char *s;
|
2016-11-20 19:20:14 +01:00
|
|
|
if (rows < 1) {
|
|
|
|
rows = 1;
|
|
|
|
}
|
|
|
|
c = r_cons_canvas_new (w, rows * 11);
|
|
|
|
for (i = 0; i < rows; i++) {
|
|
|
|
for (j = 0; j < cols; j++) {
|
2017-02-26 23:01:49 +01:00
|
|
|
r_cons_canvas_gotoxy (c, j * 20, i * 11);
|
2014-10-29 20:19:28 +01:00
|
|
|
core->offset += len;
|
2018-05-21 23:06:00 +02:00
|
|
|
r_io_read_at (core->io, core->offset, core->block, len);
|
2014-10-29 20:19:28 +01:00
|
|
|
s = r_print_randomart (core->block, len, core->offset);
|
|
|
|
r_cons_canvas_write (c, s);
|
|
|
|
free (s);
|
|
|
|
}
|
2013-08-26 00:51:36 +02:00
|
|
|
}
|
2014-10-29 20:19:28 +01:00
|
|
|
r_cons_canvas_print (c);
|
|
|
|
r_cons_canvas_free (c);
|
2018-05-21 23:06:00 +02:00
|
|
|
r_io_read_at (core->io, offset0, core->block, len);
|
2014-10-29 20:19:28 +01:00
|
|
|
core->offset = offset0;
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("\n");
|
2013-02-12 02:42:34 +01:00
|
|
|
}
|
|
|
|
break;
|
2015-03-31 00:49:45 +02:00
|
|
|
case 'n': // easter
|
|
|
|
eprintf ("easter egg license has expired\n");
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
2017-02-26 23:01:49 +01:00
|
|
|
case 't': // "pt"
|
2012-02-27 02:40:27 +01:00
|
|
|
switch (input[1]) {
|
2019-01-11 00:56:18 +01:00
|
|
|
case '.':
|
|
|
|
{
|
|
|
|
char nowstr[64] = {0};
|
|
|
|
r_print_date_get_now (core->print, nowstr);
|
|
|
|
r_cons_printf ("%s\n", nowstr);
|
|
|
|
}
|
|
|
|
break;
|
2012-10-25 12:55:28 +02:00
|
|
|
case ' ':
|
|
|
|
case '\0':
|
2017-03-09 23:29:48 +01:00
|
|
|
// len must be multiple of 4 since r_mem_copyendian move data in fours - sizeof(ut32)
|
2016-11-20 19:20:14 +01:00
|
|
|
if (len < sizeof (ut32)) {
|
2017-03-09 23:29:48 +01:00
|
|
|
eprintf ("You should change the block size: b %d\n", (int) sizeof (ut32));
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
|
|
|
if (len % sizeof (ut32)) {
|
|
|
|
len = len - (len % sizeof (ut32));
|
|
|
|
}
|
|
|
|
for (l = 0; l < len; l += sizeof (ut32)) {
|
2018-02-19 04:30:32 -08:00
|
|
|
r_print_date_unix (core->print, block + l, sizeof (ut32));
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
2012-10-25 12:55:28 +02:00
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'h': // "pth"
|
2017-03-09 23:29:48 +01:00
|
|
|
// len must be multiple of 4 since r_mem_copyendian move data in fours - sizeof(ut32)
|
2017-02-26 23:01:49 +01:00
|
|
|
if (len < sizeof (ut32)) {
|
2017-03-09 23:29:48 +01:00
|
|
|
eprintf ("You should change the block size: b %d\n", (int) sizeof (ut32));
|
2017-02-26 23:01:49 +01:00
|
|
|
}
|
|
|
|
if (len % sizeof (ut32)) {
|
|
|
|
len = len - (len % sizeof (ut32));
|
|
|
|
}
|
|
|
|
for (l = 0; l < len; l += sizeof (ut32)) {
|
2018-02-19 04:30:32 -08:00
|
|
|
r_print_date_hfs (core->print, block + l, sizeof (ut32));
|
2017-02-26 23:01:49 +01:00
|
|
|
}
|
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'd': // "ptd"
|
2017-03-09 23:29:48 +01:00
|
|
|
// len must be multiple of 4 since r_print_date_dos read buf+3
|
|
|
|
// if block size is 1 or 5 for example it reads beyond the buffer
|
2016-11-20 19:20:14 +01:00
|
|
|
if (len < sizeof (ut32)) {
|
2017-03-09 23:29:48 +01:00
|
|
|
eprintf ("You should change the block size: b %d\n", (int) sizeof (ut32));
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
|
|
|
if (len % sizeof (ut32)) {
|
|
|
|
len = len - (len % sizeof (ut32));
|
|
|
|
}
|
|
|
|
for (l = 0; l < len; l += sizeof (ut32)) {
|
2018-02-19 04:30:32 -08:00
|
|
|
r_print_date_dos (core->print, block + l, sizeof (ut32));
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
2012-10-25 12:55:28 +02:00
|
|
|
break;
|
2017-07-18 01:24:46 -07:00
|
|
|
case 'n': // "ptn"
|
2016-11-20 19:20:14 +01:00
|
|
|
if (len < sizeof (ut64)) {
|
2017-03-09 23:29:48 +01:00
|
|
|
eprintf ("You should change the block size: b %d\n", (int) sizeof (ut64));
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
|
|
|
if (len % sizeof (ut64)) {
|
|
|
|
len = len - (len % sizeof (ut64));
|
|
|
|
}
|
|
|
|
for (l = 0; l < len; l += sizeof (ut64)) {
|
2018-02-19 04:30:32 -08:00
|
|
|
r_print_date_w32 (core->print, block + l, sizeof (ut64));
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
2012-10-25 12:55:28 +02:00
|
|
|
break;
|
2017-07-25 04:20:25 -07:00
|
|
|
case '?':
|
|
|
|
r_core_cmd_help (core, help_msg_pt);
|
2012-02-27 02:40:27 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2017-07-17 19:03:27 +02:00
|
|
|
case 'q': // "pq"
|
2019-03-27 10:23:47 +01:00
|
|
|
switch (input[1]) {
|
|
|
|
case '?':
|
|
|
|
eprintf ("Usage: pq[s] [len]\n");
|
|
|
|
len = 0;
|
2017-07-17 19:03:27 +02:00
|
|
|
break;
|
2019-03-27 10:23:47 +01:00
|
|
|
case 's': // "pqs"
|
|
|
|
case 'z': // for backward compat
|
2018-02-19 04:30:32 -08:00
|
|
|
len = r_str_nlen ((const char *)block, core->blocksize);
|
2019-03-27 10:23:47 +01:00
|
|
|
break;
|
|
|
|
default:
|
2017-07-17 19:03:27 +02:00
|
|
|
if (len < 1) {
|
|
|
|
len = 0;
|
|
|
|
}
|
|
|
|
if (len > core->blocksize) {
|
|
|
|
len = core->blocksize;
|
|
|
|
}
|
2019-03-27 10:23:47 +01:00
|
|
|
break;
|
2017-07-17 19:03:27 +02:00
|
|
|
}
|
2019-03-27 10:23:47 +01:00
|
|
|
if (len > 0) {
|
|
|
|
bool inverted = (input[1] == 'i'); // pqi -- inverted colors
|
|
|
|
char *res = r_qrcode_gen (block, len, r_config_get_i (core->config, "scr.utf8"), inverted);
|
|
|
|
if (res) {
|
|
|
|
r_cons_printf ("%s\n", res);
|
|
|
|
free (res);
|
|
|
|
}
|
2017-07-17 19:03:27 +02:00
|
|
|
}
|
|
|
|
break;
|
2016-05-17 00:37:47 +02:00
|
|
|
case 'z': // "pz"
|
2017-03-09 23:29:48 +01:00
|
|
|
if (input[1] == '?') {
|
2017-07-25 04:20:25 -07:00
|
|
|
r_core_cmd_help (core, help_msg_pz);
|
2012-02-27 02:40:27 +01:00
|
|
|
} else {
|
2018-01-02 23:07:33 +05:30
|
|
|
RIOMap* map;
|
|
|
|
RListIter *iter;
|
2018-01-28 03:40:02 +05:30
|
|
|
RList *list = r_core_get_boundaries_prot (core, -1, NULL, "zoom");
|
2018-11-15 19:35:47 +01:00
|
|
|
if (list && r_list_length (list) > 0) {
|
2018-02-20 09:00:13 +05:30
|
|
|
RListIter *iter1 = list->head;
|
|
|
|
RIOMap* map1 = iter1->data;
|
|
|
|
from = map1->itv.addr;
|
|
|
|
r_list_foreach (list, iter, map) {
|
|
|
|
to = r_itv_end (map->itv);
|
2018-07-17 22:05:01 +03:00
|
|
|
}
|
2018-02-20 09:00:13 +05:30
|
|
|
} else {
|
|
|
|
from = core->offset;
|
|
|
|
to = from + core->blocksize;
|
2018-07-17 22:05:01 +03:00
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
ut64 maxsize = r_config_get_i (core->config, "zoom.maxsz");
|
|
|
|
int oldva = core->io->va;
|
2017-06-06 00:20:49 +00:00
|
|
|
char *oldmode = NULL;
|
|
|
|
bool do_zoom = true;
|
2012-02-27 02:40:27 +01:00
|
|
|
|
|
|
|
core->io->va = 0;
|
2012-08-02 01:50:39 +02:00
|
|
|
if (input[1] && input[1] != ' ') {
|
2017-06-06 00:20:49 +00:00
|
|
|
oldmode = strdup (r_config_get (core->config, "zoom.byte"));
|
2017-03-09 23:29:48 +01:00
|
|
|
if (!r_config_set (core->config, "zoom.byte", input + 1)) {
|
2017-06-06 00:20:49 +00:00
|
|
|
do_zoom = false;
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
|
|
|
}
|
2016-05-17 00:37:47 +02:00
|
|
|
if (do_zoom && l > 0) {
|
2015-04-08 01:08:09 +02:00
|
|
|
r_print_zoom (core->print, core, printzoomcallback,
|
2017-06-06 00:20:49 +00:00
|
|
|
from, to, l, (int) maxsize);
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
2017-06-06 00:20:49 +00:00
|
|
|
if (oldmode) {
|
|
|
|
r_config_set (core->config, "zoom.byte", oldmode);
|
2016-05-17 00:37:47 +02:00
|
|
|
}
|
2017-06-06 00:20:49 +00:00
|
|
|
core->io->va = oldva;
|
|
|
|
R_FREE (oldmode);
|
2018-08-26 09:25:34 -07:00
|
|
|
r_list_free (list);
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
|
|
|
break;
|
2017-07-25 04:20:25 -07:00
|
|
|
default:
|
|
|
|
r_core_cmd_help (core, help_msg_p);
|
2015-05-10 22:40:02 +02:00
|
|
|
break;
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
2015-06-04 16:53:04 +02:00
|
|
|
beach:
|
2015-04-08 01:08:09 +02:00
|
|
|
if (tmpseek != UT64_MAX) {
|
|
|
|
r_core_seek (core, tmpseek, SEEK_SET);
|
2016-12-28 12:23:53 +01:00
|
|
|
r_core_block_read (core);
|
2015-04-08 01:08:09 +02:00
|
|
|
}
|
2016-11-06 17:54:25 -03:00
|
|
|
if (tbs != core->blocksize) {
|
|
|
|
r_core_block_size (core, tbs);
|
|
|
|
}
|
2015-06-04 16:53:04 +02:00
|
|
|
return ret;
|
2012-02-27 02:40:27 +01:00
|
|
|
}
|
|
|
|
|
2012-02-27 03:07:32 +01:00
|
|
|
static int cmd_hexdump(void *data, const char *input) {
|
2017-03-09 23:29:48 +01:00
|
|
|
return cmd_print (data, input - 1);
|
2012-02-27 03:07:32 +01:00
|
|
|
}
|
2013-07-12 00:29:27 +02:00
|
|
|
|
2017-03-09 23:29:48 +01:00
|
|
|
static int lenof(ut64 off, int two) {
|
2015-01-12 00:11:06 +01:00
|
|
|
char buf[64];
|
|
|
|
buf[0] = 0;
|
2017-03-09 23:29:48 +01:00
|
|
|
if (two) {
|
|
|
|
snprintf (buf, sizeof (buf), "+0x%"PFMT64x, off);
|
|
|
|
} else {
|
|
|
|
snprintf (buf, sizeof (buf), "0x%08"PFMT64x, off);
|
|
|
|
}
|
2015-01-12 00:11:06 +01:00
|
|
|
return strlen (buf);
|
|
|
|
}
|
2015-09-29 00:42:31 +02:00
|
|
|
|
2018-03-12 12:37:35 +01:00
|
|
|
R_API void r_print_offset_sg(RPrint *p, ut64 off, int invert, int offseg, int seggrn, int offdec, int delta, const char *label) {
|
2017-03-09 23:29:48 +01:00
|
|
|
char space[32] = {
|
|
|
|
0
|
|
|
|
};
|
2016-11-01 23:30:36 +01:00
|
|
|
const char *white;
|
2018-04-24 11:32:51 +02:00
|
|
|
const char *reset = p->resetbg? Color_RESET: Color_RESET_NOBG;
|
2016-08-25 20:17:55 +02:00
|
|
|
bool show_color = p->flags & R_PRINT_FLAGS_COLOR;
|
2013-07-12 00:29:27 +02:00
|
|
|
if (show_color) {
|
2017-08-31 01:11:34 +02:00
|
|
|
char rgbstr[32];
|
2019-01-18 11:58:49 +01:00
|
|
|
const char *k = r_cons_singleton ()->context->pal.offset; // TODO etooslow. must cache
|
2019-06-15 17:58:21 +08:00
|
|
|
const char *inv = invert ? R_CONS_INVERT (true, true) : "";
|
2017-08-31 01:11:34 +02:00
|
|
|
if (p->flags & R_PRINT_FLAGS_RAINBOW) {
|
2018-04-21 11:31:24 +02:00
|
|
|
k = r_cons_rgb_str_off (rgbstr, sizeof (rgbstr), off);
|
2017-08-31 01:11:34 +02:00
|
|
|
}
|
2015-01-12 00:11:06 +01:00
|
|
|
if (offseg) {
|
2013-07-12 00:29:27 +02:00
|
|
|
ut32 s, a;
|
|
|
|
a = off & 0xffff;
|
2018-03-12 12:37:35 +01:00
|
|
|
s = (off - a) >> seggrn;
|
2016-11-01 23:30:36 +01:00
|
|
|
if (offdec) {
|
|
|
|
snprintf (space, sizeof (space), "%d:%d", s & 0xffff, a & 0xffff);
|
|
|
|
white = r_str_pad (' ', 9 - strlen (space));
|
2019-06-15 17:58:21 +08:00
|
|
|
r_cons_printf ("%s%s%s%s%s", k, inv, white, space, reset);
|
2016-11-01 23:30:36 +01:00
|
|
|
} else {
|
2019-06-15 17:58:21 +08:00
|
|
|
r_cons_printf ("%s%s%04x:%04x%s", k, inv, s & 0xFFFF, a & 0xFFFF, reset);
|
2016-11-01 23:30:36 +01:00
|
|
|
}
|
2015-01-12 00:11:06 +01:00
|
|
|
} else {
|
|
|
|
int sz = lenof (off, 0);
|
|
|
|
int sz2 = lenof (delta, 1);
|
2016-08-25 20:17:55 +02:00
|
|
|
if (delta > 0 || label) {
|
|
|
|
if (label) {
|
2016-08-25 20:27:52 +02:00
|
|
|
const int label_padding = 10;
|
2016-08-25 20:17:55 +02:00
|
|
|
if (delta > 0) {
|
2016-11-01 23:30:36 +01:00
|
|
|
if (offdec) {
|
|
|
|
const char *pad = r_str_pad (' ', sz - sz2 + label_padding);
|
2019-06-15 17:58:21 +08:00
|
|
|
r_cons_printf ("%s%s%s%s+%d%s", k, inv, label, reset, delta, pad);
|
2016-11-01 23:30:36 +01:00
|
|
|
} else {
|
|
|
|
const char *pad = r_str_pad (' ', sz - sz2 + label_padding);
|
2019-06-15 17:58:21 +08:00
|
|
|
r_cons_printf ("%s%s%s%s+0x%x%s", k, inv, label, reset, delta, pad);
|
2016-11-01 23:30:36 +01:00
|
|
|
}
|
2016-08-25 20:17:55 +02:00
|
|
|
} else {
|
2016-08-25 20:27:52 +02:00
|
|
|
const char *pad = r_str_pad (' ', sz + label_padding);
|
2019-06-15 17:58:21 +08:00
|
|
|
r_cons_printf ("%s%s%s%s%s", k, inv, label, reset, pad);
|
2016-08-25 20:17:55 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const char *pad = r_str_pad (' ', sz - sz2);
|
2016-11-01 23:30:36 +01:00
|
|
|
if (offdec) {
|
2018-04-24 11:32:51 +02:00
|
|
|
r_cons_printf ("%s+%d%s", pad, delta, reset);
|
2016-11-01 23:30:36 +01:00
|
|
|
} else {
|
2018-04-24 11:32:51 +02:00
|
|
|
r_cons_printf ("%s+0x%x%s", pad, delta, reset);
|
2016-11-01 23:30:36 +01:00
|
|
|
}
|
2016-08-25 20:17:55 +02:00
|
|
|
}
|
|
|
|
} else {
|
2016-11-01 23:30:36 +01:00
|
|
|
if (offdec) {
|
2018-09-20 21:59:32 +08:00
|
|
|
snprintf (space, sizeof (space), "%"PFMT64u, off);
|
2016-11-01 23:30:36 +01:00
|
|
|
white = r_str_pad (' ', 10 - strlen (space));
|
2019-06-15 17:58:21 +08:00
|
|
|
r_cons_printf ("%s%s%s%s%s", k, inv, white, space, reset);
|
2016-11-01 23:30:36 +01:00
|
|
|
} else {
|
2018-12-31 03:06:05 +01:00
|
|
|
if (p->wide_offsets) {
|
2019-06-15 17:58:21 +08:00
|
|
|
r_cons_printf ("%s%s0x%016"PFMT64x "%s", k, inv, off, reset);
|
2018-12-31 03:06:05 +01:00
|
|
|
} else {
|
2019-06-15 17:58:21 +08:00
|
|
|
r_cons_printf ("%s%s0x%08"PFMT64x "%s", k, inv, off, reset);
|
2018-12-31 03:06:05 +01:00
|
|
|
}
|
2016-11-01 23:30:36 +01:00
|
|
|
}
|
2016-08-25 20:17:55 +02:00
|
|
|
}
|
2015-01-12 00:11:06 +01:00
|
|
|
}
|
2016-06-25 13:49:58 -04:00
|
|
|
r_cons_print (" ");
|
2013-11-04 04:07:58 +01:00
|
|
|
} else {
|
2015-01-12 00:11:06 +01:00
|
|
|
if (offseg) {
|
2013-11-04 04:07:58 +01:00
|
|
|
ut32 s, a;
|
|
|
|
a = off & 0xffff;
|
2018-03-12 12:37:35 +01:00
|
|
|
s = (off - a) >> seggrn;
|
2016-11-01 23:30:36 +01:00
|
|
|
if (offdec) {
|
|
|
|
snprintf (space, sizeof (space), "%d:%d", s & 0xffff, a & 0xffff);
|
|
|
|
white = r_str_pad (' ', 9 - strlen (space));
|
2018-04-24 11:32:51 +02:00
|
|
|
r_cons_printf ("%s%s%s", white, space, reset);
|
2016-11-01 23:30:36 +01:00
|
|
|
} else {
|
|
|
|
r_cons_printf ("%04x:%04x", s & 0xFFFF, a & 0xFFFF);
|
|
|
|
}
|
2013-11-04 04:07:58 +01:00
|
|
|
} else {
|
2015-01-12 00:11:06 +01:00
|
|
|
int sz = lenof (off, 0);
|
|
|
|
int sz2 = lenof (delta, 1);
|
2016-08-25 20:17:55 +02:00
|
|
|
const char *pad = r_str_pad (' ', sz - 5 - sz2 - 3);
|
2016-11-01 23:30:36 +01:00
|
|
|
if (delta > 0) {
|
|
|
|
if (offdec) {
|
2018-04-24 11:32:51 +02:00
|
|
|
r_cons_printf ("%s+%d%s", pad, delta, reset);
|
2016-11-01 23:30:36 +01:00
|
|
|
} else {
|
2018-04-24 11:32:51 +02:00
|
|
|
r_cons_printf ("%s+0x%x%s", pad, delta, reset);
|
2016-11-01 23:30:36 +01:00
|
|
|
}
|
2016-08-25 20:17:55 +02:00
|
|
|
} else {
|
2016-11-01 23:30:36 +01:00
|
|
|
if (offdec) {
|
2018-09-20 21:59:32 +08:00
|
|
|
snprintf (space, sizeof (space), "%"PFMT64u, off);
|
2016-11-01 23:30:36 +01:00
|
|
|
white = r_str_pad (' ', 10 - strlen (space));
|
|
|
|
r_cons_printf ("%s%s", white, space);
|
|
|
|
} else {
|
2017-03-09 23:29:48 +01:00
|
|
|
r_cons_printf ("0x%08"PFMT64x " ", off);
|
2016-11-01 23:30:36 +01:00
|
|
|
}
|
2016-08-25 20:17:55 +02:00
|
|
|
}
|
2013-11-04 04:07:58 +01:00
|
|
|
}
|
|
|
|
}
|
2013-07-12 00:29:27 +02:00
|
|
|
}
|
2018-03-12 12:37:35 +01:00
|
|
|
|
|
|
|
// TODO : move to r_util? .. depends on r_cons...
|
|
|
|
// XXX: dupe of r_print_addr
|
|
|
|
R_API void r_print_offset(RPrint *p, ut64 off, int invert, int offseg, int offdec, int delta, const char *label) {
|
|
|
|
r_print_offset_sg(p, off, invert, offseg, 4, offdec, delta, label);
|
|
|
|
}
|