mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-28 07:30:33 +00:00
Intial implementation of function call argument display (#9411)
* Cleanup disasm code * Move this to new command afal and few bug fix * Wrap the command with config var
This commit is contained in:
parent
53df70fbd3
commit
8ca0d327e4
@ -10,7 +10,7 @@ PCLIBS=@SSL_LDFLAGS@ @CAPSTONE_LDFLAGS@
|
||||
|
||||
OBJS=core.o cmd.o file.o cconfig.o visual.o cio.o yank.o libs.o graph.o
|
||||
OBJS+=fortune.o hack.o vasm.o patch.o cbin.o log.o rtr.o cmd_api.o
|
||||
OBJS+=canal.o project.o gdiff.o asm.o vmenus.o disasm.o plugin.o
|
||||
OBJS+=carg.o canal.o project.o gdiff.o asm.o vmenus.o disasm.o plugin.o
|
||||
OBJS+=task.o panels.o pseudo.o vmarks.o anal_tp.o blaze.o
|
||||
|
||||
CFLAGS+=-I../../shlr/heap/include
|
||||
|
258
libr/core/carg.c
Normal file
258
libr/core/carg.c
Normal file
@ -0,0 +1,258 @@
|
||||
/* radare - LGPL - Copyright 2009-2018 - pancake */
|
||||
|
||||
#include <r_core.h>
|
||||
|
||||
#define MAXSTRLEN 50
|
||||
|
||||
static void set_fcn_args_info(RAnalFuncArg *arg, RAnal *anal, const char *fcn_name, const char *cc, int arg_num) {
|
||||
if (!fcn_name || !arg || !anal) {
|
||||
return;
|
||||
}
|
||||
arg->name = r_anal_type_func_args_name (anal, fcn_name, arg_num);
|
||||
arg->orig_c_type = r_anal_type_func_args_type (anal, fcn_name, arg_num);
|
||||
if (!strncmp ("const ", arg->orig_c_type, 6)) {
|
||||
arg->c_type = arg->orig_c_type + 6;
|
||||
} else {
|
||||
arg->c_type = arg->orig_c_type;
|
||||
}
|
||||
const char *query = sdb_fmt (-1, "type.%s", arg->c_type);
|
||||
arg->fmt = sdb_const_get (anal->sdb_types, query, 0);
|
||||
const char *t_query = sdb_fmt (-1, "type.%s.size", arg->c_type);
|
||||
arg->size = sdb_num_get (anal->sdb_types, t_query, 0) / 8;
|
||||
arg->cc_source = r_anal_cc_arg (anal, cc, arg_num + 1);
|
||||
}
|
||||
|
||||
static char *resolve_fcn_name(RAnal *anal, const char *func_name) {
|
||||
const char *str = func_name;
|
||||
const char *name = func_name;
|
||||
if (r_anal_type_func_exist (anal, func_name)) {
|
||||
return strdup (func_name);
|
||||
}
|
||||
while ((str = strchr (str, '.'))) {
|
||||
name = str + 1;
|
||||
str++;
|
||||
}
|
||||
if (r_anal_type_func_exist (anal, name)) {
|
||||
return strdup (name);
|
||||
}
|
||||
return r_anal_type_func_guess (anal, (char*)func_name);
|
||||
}
|
||||
|
||||
static ut64 get_buf_val(ut8 *buf, int endian, int width) {
|
||||
return (width == 8)? r_read_ble64 (buf, endian) : (ut64) r_read_ble32 (buf,endian);
|
||||
}
|
||||
|
||||
static void print_arg_str(int argcnt, const char *name, bool color) {
|
||||
if (color) {
|
||||
r_cons_printf (Color_BYELLOW" arg [%d]"Color_RESET" -"Color_BCYAN" %s"Color_RESET" : ",
|
||||
argcnt, name);
|
||||
} else {
|
||||
r_cons_printf (" arg [%d] - %s : ", argcnt, name);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_format_values(RCore *core, const char *fmt, bool onstack, ut64 src, bool color) {
|
||||
char opt;
|
||||
ut64 bval = src;
|
||||
int i;
|
||||
int endian = core->print->big_endian;
|
||||
int width = (core->anal->bits == 64)? 8: 4;
|
||||
int bsize = R_MIN (64, core->blocksize);
|
||||
|
||||
ut8 *buf = malloc (bsize);
|
||||
if (!buf) {
|
||||
eprintf ("Cannot allocate %d byte(s)\n", bsize);
|
||||
free (buf);
|
||||
return;
|
||||
}
|
||||
if (fmt) {
|
||||
opt = *fmt;
|
||||
} else {
|
||||
opt = 'p'; // void *ptr
|
||||
}
|
||||
if (onstack || ((opt != 'd' && opt != 'x') && !onstack)) {
|
||||
if (color) {
|
||||
r_cons_printf (Color_BGREEN"0x%08"PFMT64x Color_RESET" --> ", bval);
|
||||
} else {
|
||||
r_cons_printf ("0x%08"PFMT64x" --> ", bval);
|
||||
}
|
||||
r_core_read_at (core, bval, buf, bsize);
|
||||
}
|
||||
if (onstack) { // Fetch value from stack
|
||||
bval = get_buf_val (buf, endian, width);
|
||||
if (opt != 'd' && opt != 'x') {
|
||||
r_core_read_at (core, bval, buf, bsize); // update buf with val from stack
|
||||
}
|
||||
}
|
||||
r_cons_print (color? Color_BGREEN: "");
|
||||
switch (opt) {
|
||||
case 'z' : // Null terminated string
|
||||
r_cons_print (color ?Color_RESET Color_BWHITE:"");
|
||||
r_cons_print ("\"");
|
||||
for (i = 0; i < MAXSTRLEN; i++) {
|
||||
if (buf[i] == '\0') {
|
||||
break;
|
||||
}
|
||||
ut8 b = buf[i];
|
||||
if (IS_PRINTABLE (b)) {
|
||||
r_cons_printf ("%c", b);
|
||||
} else {
|
||||
r_cons_printf ("\\x%02x", b);
|
||||
}
|
||||
if (i == MAXSTRLEN - 1) {
|
||||
r_cons_print ("..."); // To show string is truncated
|
||||
}
|
||||
}
|
||||
r_cons_print ("\"");
|
||||
r_cons_newline ();
|
||||
break;
|
||||
case 'd' : // integer
|
||||
case 'x' :
|
||||
r_cons_printf ("0x%08" PFMT64x, bval);
|
||||
r_cons_newline ();
|
||||
break;
|
||||
case 'c' : // char
|
||||
r_cons_print ("\'");
|
||||
ut8 ch = buf[0];
|
||||
if (IS_PRINTABLE (ch)) {
|
||||
r_cons_printf ("%c", ch);
|
||||
} else {
|
||||
r_cons_printf ("\\x%02x", ch);
|
||||
}
|
||||
r_cons_print ("\'");
|
||||
r_cons_newline ();
|
||||
break;
|
||||
case 'p' : // pointer
|
||||
{
|
||||
// Try to deref the pointer once again
|
||||
r_cons_printf ("0x%08"PFMT64x, get_buf_val (buf, endian, width));
|
||||
r_cons_newline ();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//TODO: support types like structs and unions
|
||||
r_cons_println ("unk_format");
|
||||
}
|
||||
r_cons_print (Color_RESET);
|
||||
free (buf);
|
||||
}
|
||||
|
||||
/* This functon display list of arg with some colors */
|
||||
|
||||
R_API void r_core_print_func_args(RCore *core) {
|
||||
RListIter *iter;
|
||||
bool color = r_config_get_i (core->config, "scr.color");
|
||||
if (!core->anal) {
|
||||
return;
|
||||
}
|
||||
if (!core->anal->reg) {
|
||||
return;
|
||||
}
|
||||
const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
|
||||
ut64 cur_addr = r_reg_getv (core->anal->reg, pc);
|
||||
RAnalOp *op = r_core_anal_op (core, cur_addr);
|
||||
if (!op) {
|
||||
return;
|
||||
}
|
||||
if (op->type == R_ANAL_OP_TYPE_CALL) {
|
||||
RAnalFunction *fcn;
|
||||
RAnalFuncArg *arg;
|
||||
int i;
|
||||
int nargs = 0;
|
||||
bool onstack = false;
|
||||
const char *fcn_name = NULL;
|
||||
ut64 pcv = op->jump;
|
||||
if (pcv == UT64_MAX) {
|
||||
pcv = op->ptr;
|
||||
}
|
||||
fcn = r_anal_get_fcn_at (core->anal, pcv, 0);
|
||||
if (fcn) {
|
||||
fcn_name = fcn->name;
|
||||
} else {
|
||||
if (core->flags) {
|
||||
RFlagItem *item = r_flag_get_i (core->flags, pcv);
|
||||
if (item) {
|
||||
fcn_name = item->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
RList *list = r_core_get_func_args (core, fcn_name);
|
||||
if (!r_list_empty (list)) {
|
||||
int argcnt = 0;
|
||||
r_list_foreach (list, iter, arg) {
|
||||
if (arg->cc_source && !strncmp (arg->cc_source, "stack", 5)) {
|
||||
onstack = true;
|
||||
}
|
||||
print_arg_str (argcnt, arg->name, color);
|
||||
print_format_values (core, arg->fmt, onstack, arg->src, color);
|
||||
argcnt++;
|
||||
}
|
||||
} else {
|
||||
if (fcn) {
|
||||
nargs = fcn->nargs;
|
||||
}
|
||||
if (nargs > 0) {
|
||||
for (i = 0; i < nargs; i++) {
|
||||
ut64 v = r_debug_arg_get (core->dbg, R_ANAL_CC_TYPE_STDCALL, i);
|
||||
print_arg_str (i, "", color);
|
||||
r_cons_printf ("0x%08" PFMT64x, v);
|
||||
r_cons_newline ();
|
||||
}
|
||||
} else {
|
||||
print_arg_str (0, "void", color);
|
||||
}
|
||||
}
|
||||
}
|
||||
r_anal_op_fini (op);
|
||||
}
|
||||
|
||||
/* Returns a list of RAnalFuncArg */
|
||||
R_API RList *r_core_get_func_args(RCore *core, const char *fcn_name) {
|
||||
if (!fcn_name || !core->anal) {
|
||||
return NULL;
|
||||
}
|
||||
RList *list = r_list_new ();
|
||||
char *key = resolve_fcn_name (core->anal, fcn_name);
|
||||
if (!key) {
|
||||
return NULL;
|
||||
}
|
||||
const char *sp = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
|
||||
int nargs = r_anal_type_func_args_count (core->anal, key);
|
||||
const char *cc = r_anal_type_func_cc (core->anal, key);
|
||||
const char *src = r_anal_cc_arg (core->anal, cc, 1); // src of first argument
|
||||
if (!cc) {
|
||||
// unsupported calling convention
|
||||
return NULL;
|
||||
}
|
||||
int i;
|
||||
ut64 spv = r_reg_getv (core->anal->reg, sp);
|
||||
ut64 s_width = (core->anal->bits == 64)? 8: 4;
|
||||
if (src && !strcmp (src, "stack_rev")) {
|
||||
for (i = nargs - 1; i >= 0; i--) {
|
||||
RAnalFuncArg *arg = R_NEW0 (RAnalFuncArg);
|
||||
set_fcn_args_info (arg, core->anal, key, cc, i);
|
||||
arg->src = spv;
|
||||
spv += arg->size? arg->size : s_width;
|
||||
r_list_append (list, arg);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < nargs; i++) {
|
||||
RAnalFuncArg *arg = R_NEW0 (RAnalFuncArg);
|
||||
if (!arg) {
|
||||
return NULL;
|
||||
}
|
||||
set_fcn_args_info (arg, core->anal, key, cc, i);
|
||||
if (src && !strncmp (src, "stack", 5)) {
|
||||
arg->src = spv;
|
||||
if (!arg->size) {
|
||||
arg->size = s_width;
|
||||
}
|
||||
spv += arg->size;
|
||||
} else {
|
||||
arg->src = r_reg_getv (core->anal->reg, arg->cc_source);
|
||||
}
|
||||
r_list_append (list, arg);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
@ -2543,6 +2543,7 @@ R_API int r_core_config_init(RCore *core) {
|
||||
SETI ("dbg.hwbp", 0, "Set HW or SW breakpoints");
|
||||
SETCB ("dbg.unlibs", "", &cb_dbg_unlibs, "If set stop when unloading matching libname");
|
||||
SETPREF ("dbg.slow", "false", "Show stack and regs in visual mode in a slow but verbose mode");
|
||||
SETPREF ("dbg.funcarg", "false", "Display arguments to function call in visual mode");
|
||||
|
||||
SETPREF ("dbg.bpinmaps", "true", "Force breakpoints to be inside a valid map");
|
||||
SETCB ("dbg.forks", "false", &cb_dbg_forks, "Stop execution if fork() is done (see dbg.threads)");
|
||||
|
@ -2026,6 +2026,14 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
|
||||
case 'f': // "aff"
|
||||
r_anal_fcn_fit_overlaps (core->anal, NULL);
|
||||
break;
|
||||
case 'a':
|
||||
if (input[2] == 'l') { // afal : list function call arguments
|
||||
int show_args = r_config_get_i (core->config, "dbg.funcarg");
|
||||
if (show_args) {
|
||||
r_core_print_func_args (core);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'd': // "afd"
|
||||
{
|
||||
ut64 addr = 0;
|
||||
|
@ -3737,22 +3737,6 @@ static void ds_print_bbline(RDisasmState *ds, bool force) {
|
||||
}
|
||||
}
|
||||
|
||||
static void get_fcn_args_info(RAnal *anal, const char *fcn_name, int arg_num, const char * cc, const char **name,
|
||||
char **orig_c_type, char **c_type, const char **fmt, ut64 *size, const char **source) {
|
||||
*name = r_anal_type_func_args_name (anal, fcn_name, arg_num);
|
||||
*orig_c_type = r_anal_type_func_args_type (anal, fcn_name, arg_num);
|
||||
if (!strncmp ("const ", *orig_c_type, 6)) {
|
||||
*c_type = *orig_c_type+6;
|
||||
} else {
|
||||
*c_type = *orig_c_type;
|
||||
}
|
||||
const char *query = sdb_fmt (-1, "type.%s", *c_type);
|
||||
*fmt = sdb_const_get (anal->sdb_types, query, 0);
|
||||
const char *t_query = sdb_fmt (-1, "type.%s.size", *c_type);
|
||||
*size = sdb_num_get (anal->sdb_types, t_query, 0) / 8;
|
||||
*source = r_anal_cc_arg (anal, cc, arg_num+1);
|
||||
}
|
||||
|
||||
static void print_fcn_arg(RCore *core, const char *type, const char *name,
|
||||
const char *fmt, const ut64 addr,
|
||||
const int on_stack) {
|
||||
@ -3890,7 +3874,11 @@ static void ds_print_esil_anal(RDisasmState *ds) {
|
||||
case R_ANAL_OP_TYPE_CALL:
|
||||
{
|
||||
RAnalFunction *fcn;
|
||||
RAnalFuncArg *arg;
|
||||
RListIter *iter;
|
||||
RListIter *nextele;
|
||||
const char *fcn_name = NULL;
|
||||
char *key;
|
||||
ut64 pcv = ds->analop.jump;
|
||||
if (pcv == UT64_MAX) {
|
||||
pcv = ds->analop.ptr; // call [reloc-addr] // windows style
|
||||
@ -3911,118 +3899,62 @@ static void ds_print_esil_anal(RDisasmState *ds) {
|
||||
}
|
||||
}
|
||||
if (fcn_name) {
|
||||
char * key = resolve_fcn_name (core->anal, fcn_name);
|
||||
if (key) {
|
||||
const char *sp = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
|
||||
const char *fcn_type = r_anal_type_func_ret (core->anal, key);
|
||||
const char * cc;
|
||||
nargs = r_anal_type_func_args_count (core->anal, key);
|
||||
// HACK: remove other comments
|
||||
delete_last_comment (ds);
|
||||
if (ds->show_color) {
|
||||
ds_comment_esil (ds, true, false, ds->pal_comment);
|
||||
}
|
||||
key = resolve_fcn_name (core->anal, fcn_name);
|
||||
}
|
||||
if (key) {
|
||||
const char *fcn_type = r_anal_type_func_ret (core->anal, key);
|
||||
int nargs = r_anal_type_func_args_count (core->anal, key);
|
||||
// remove other comments
|
||||
delete_last_comment (ds);
|
||||
if (ds->show_color) {
|
||||
ds_comment_esil (ds, true, false, ds->pal_comment);
|
||||
}
|
||||
if (fcn_type) {
|
||||
ds_comment_esil (ds, ds->show_color? false : true, false,
|
||||
"; %s%s%s(", r_str_get (fcn_type), (fcn_type && *fcn_type &&
|
||||
"; %s%s%s(", r_str_get (fcn_type), (*fcn_type &&
|
||||
fcn_type[strlen (fcn_type) - 1] == '*') ? "" : " ",
|
||||
r_str_get (key));
|
||||
if (!nargs) {
|
||||
ds_comment_esil (ds, false, true, "void)");
|
||||
break;
|
||||
}
|
||||
cc = r_anal_type_func_cc (core->anal, key);
|
||||
if (!cc) {
|
||||
// unsupported calling convention
|
||||
break;
|
||||
}
|
||||
ut64 spv = r_reg_getv (core->anal->reg, sp);
|
||||
ut64 s_width = (core->anal->bits == 64)? 8: 4;
|
||||
spv += s_width;
|
||||
ut64 arg_addr = UT64_MAX;
|
||||
//this should be taken out on its own function
|
||||
for (i = 0; i < nargs; i++) {
|
||||
const char *arg_name, *fmt, *cc_source = NULL;
|
||||
char *arg_orig_c_type, *arg_c_type;
|
||||
ut64 arg_size;
|
||||
int on_stack = 0, warning = 0;
|
||||
get_fcn_args_info (core->anal, key, i, cc, &arg_name,
|
||||
&arg_orig_c_type, &arg_c_type, &fmt,
|
||||
&arg_size, &cc_source);
|
||||
if (cc_source && !strcmp (cc_source, "stack_rev")) {
|
||||
int j;
|
||||
free (arg_orig_c_type);
|
||||
on_stack = 1;
|
||||
for (j = nargs - 1; j >= i; j--) {
|
||||
warning = 0;
|
||||
get_fcn_args_info (core->anal, key, j, cc,
|
||||
&arg_name, &arg_orig_c_type, &arg_c_type,
|
||||
&fmt, &arg_size, &cc_source);
|
||||
arg_addr = spv;
|
||||
if (!arg_size) {
|
||||
ds_comment_esil (ds, false, "%s: unk_size", arg_c_type);
|
||||
warning = 1;
|
||||
arg_size = s_width;
|
||||
}
|
||||
spv += arg_size;
|
||||
if (!fmt) {
|
||||
if (!warning) {
|
||||
ds_comment_esil (ds, false, false, "%s : unk_format", arg_c_type);
|
||||
} else {
|
||||
ds_comment_esil (ds, false, false, "_format");
|
||||
}
|
||||
ds_comment_esil (ds, false, false, j!=i?", ":")");
|
||||
free (arg_orig_c_type);
|
||||
continue;
|
||||
}
|
||||
if (fmt) {
|
||||
//print_fcn_arg may need ds_comment_esil
|
||||
print_fcn_arg (core, arg_orig_c_type,
|
||||
arg_name, fmt, arg_addr, on_stack);
|
||||
ds_comment_esil (ds, false, false, j!=i?", ":")");
|
||||
}
|
||||
free (arg_orig_c_type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (cc_source && !strncmp (cc_source, "stack", 5)) {
|
||||
arg_addr = spv;
|
||||
if (!arg_size) {
|
||||
ds_comment_esil (ds, false, false, "%s: unk_size", arg_c_type);
|
||||
warning = 1;
|
||||
arg_size = s_width;
|
||||
}
|
||||
spv += arg_size;
|
||||
on_stack = 1;
|
||||
} else {
|
||||
arg_addr = r_reg_getv (core->anal->reg, cc_source);
|
||||
}
|
||||
if (!fmt) {
|
||||
if (!warning) {
|
||||
ds_comment_esil (ds, false, false, "%s : unk_format", arg_c_type);
|
||||
} else {
|
||||
ds_comment_esil (ds, false, false, "_format");
|
||||
}
|
||||
ds_comment_esil (ds, false, false, i!=(nargs-1)?", ":")");
|
||||
free (arg_orig_c_type);
|
||||
continue;
|
||||
}
|
||||
if (fmt) {
|
||||
//it may need ds_comment_esil
|
||||
print_fcn_arg (core, arg_orig_c_type, arg_name,
|
||||
fmt, arg_addr, on_stack);
|
||||
ds_comment_esil (ds, false, false, i!=(nargs - 1)?", ":")");
|
||||
}
|
||||
free (arg_orig_c_type);
|
||||
}
|
||||
ds_comment_esil (ds, false, true, "");
|
||||
free (key);
|
||||
} else {
|
||||
// function not in sdb
|
||||
goto callfallback;
|
||||
}
|
||||
}
|
||||
ut64 s_width = (core->anal->bits == 64)? 8: 4;
|
||||
const char *sp = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
|
||||
ut64 spv = r_reg_getv (core->anal->reg, sp);
|
||||
r_reg_setv (core->anal->reg, sp, spv + s_width); // temporarily set stack ptr to sync with carg.c
|
||||
RList *list = r_core_get_func_args (core, fcn_name);
|
||||
if (!r_list_empty (list)) {
|
||||
bool warning = false;
|
||||
bool on_stack = false;
|
||||
r_list_foreach (list, iter, arg) {
|
||||
if (arg->cc_source && !strncmp (arg->cc_source, "stack", 5)) {
|
||||
on_stack = true;
|
||||
}
|
||||
if (!arg->size) {
|
||||
ds_comment_esil (ds, false, false, "%s: unk_size", arg->c_type);
|
||||
warning = true;
|
||||
}
|
||||
nextele = r_list_iter_get_next (iter);
|
||||
if (!arg->fmt) {
|
||||
if (!warning) {
|
||||
ds_comment_esil (ds, false, false, "%s : unk_format", arg->c_type);
|
||||
} else {
|
||||
ds_comment_esil (ds, false, false, "_format");
|
||||
}
|
||||
ds_comment_esil (ds, false, false, nextele?", ":")");
|
||||
} else {
|
||||
//print_fcn_arg may need ds_comment_esil
|
||||
print_fcn_arg (core, arg->orig_c_type,
|
||||
arg->name, arg->fmt, arg->src, on_stack);
|
||||
ds_comment_esil (ds, false, false, nextele?", ":")");
|
||||
}
|
||||
}
|
||||
break;
|
||||
ds_comment_esil (ds, false, true, "");
|
||||
} else {
|
||||
// function name not resolved
|
||||
callfallback:
|
||||
nargs = DEFAULT_NARGS;
|
||||
if (fcn) {
|
||||
nargs = fcn->nargs;
|
||||
@ -4036,6 +3968,7 @@ callfallback:
|
||||
ds_comment_esil (ds, false, true, "");
|
||||
}
|
||||
}
|
||||
r_reg_setv (core->anal->reg, sp, spv); // reset stack ptr
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ files = [
|
||||
'p/core_anal.c',
|
||||
'blaze.c',
|
||||
'canal.c',
|
||||
'carg.c',
|
||||
'cbin.c',
|
||||
'cconfig.c',
|
||||
'cio.c',
|
||||
|
@ -3029,7 +3029,7 @@ dodo:
|
||||
snprintf (debugstr, sizeof (debugstr),
|
||||
"?0;f tmp;ssr SP;%s %d@$$%c%d;"
|
||||
"?1;%s;"
|
||||
"?1;ss tmp;f-tmp;pd $r",
|
||||
"?1;ss tmp;f-tmp;afal;pd $r",
|
||||
pxa? "pxa": pxw, size, sign, absdelta,
|
||||
ref? "drr": "dr=");
|
||||
}
|
||||
|
@ -305,6 +305,16 @@ typedef struct r_anal_type_function_t {
|
||||
RBNode rb;
|
||||
} RAnalFunction;
|
||||
|
||||
typedef struct r_anal_func_arg_t {
|
||||
const char *name;
|
||||
const char *fmt;
|
||||
const char *cc_source;
|
||||
char *orig_c_type;
|
||||
char *c_type;
|
||||
ut64 size;
|
||||
ut64 src; //Function-call argument value or pointer to it
|
||||
} RAnalFuncArg;
|
||||
|
||||
struct r_anal_type_t {
|
||||
char *name;
|
||||
ut32 type;
|
||||
|
@ -365,6 +365,8 @@ R_API char *r_core_disassemble_instr(RCore *core, ut64 addr, int l);
|
||||
R_API char *r_core_disassemble_bytes(RCore *core, ut64 addr, int b);
|
||||
|
||||
R_API int r_core_process_input_pade(RCore *core, const char *input, char** hex, char **asm_arch, ut32 *bits);
|
||||
R_API RList *r_core_get_func_args(RCore *core, const char *func_name);
|
||||
R_API void r_core_print_func_args(RCore *core);
|
||||
|
||||
/* anal.c */
|
||||
R_API RAnalOp* r_core_anal_op(RCore *core, ut64 addr);
|
||||
|
Loading…
Reference in New Issue
Block a user