Add autocomplete function and cmd arg type for global variables (#1577)

* Add autocomplete function and cmd arg type for global variables
* Add unit tests for global var auto completion

Co-authored-by: Riccardo Schirone <ret2libc@users.noreply.github.com>
This commit is contained in:
Dhruv Maroo 2021-09-03 13:19:23 +05:30 committed by GitHub
parent cba3f0b763
commit aed6854bdf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 10 deletions

View file

@ -276,6 +276,19 @@ static void autocmplt_cmd_arg_any_type(RzCore *core, RzLineNSCompletionResult *r
rz_list_free(list);
}
static void autocmplt_cmd_arg_global_var(RzCore *core, RzLineNSCompletionResult *res, const char *s, size_t len) {
RzAnalysisVarGlobal *glob;
RzListIter *iter;
RzList *list = rz_analysis_var_global_get_all(core->analysis);
rz_list_foreach (list, iter, glob) {
char *name = glob->name;
if (!strncmp(name, s, len)) {
rz_line_ns_completion_result_add(res, name);
}
}
rz_list_free(list);
}
static void autocmplt_cmd_arg_help_var(RzCore *core, RzLineNSCompletionResult *res, const char *s, size_t len) {
const char **vars = rz_core_help_vars_get(core);
while (*vars) {
@ -521,6 +534,9 @@ static void autocmplt_cmd_arg(RzCore *core, RzLineNSCompletionResult *res, const
case RZ_CMD_ARG_TYPE_ANY_TYPE:
autocmplt_cmd_arg_any_type(core, res, s, len);
break;
case RZ_CMD_ARG_TYPE_GLOBAL_VAR:
autocmplt_cmd_arg_global_var(core, res, s, len);
break;
default:
break;
}

View file

@ -406,7 +406,7 @@ commands:
- RZ_OUTPUT_MODE_JSON
args:
- name: var_name
type: RZ_CMD_ARG_TYPE_STRING
type: RZ_CMD_ARG_TYPE_GLOBAL_VAR
optional: true
- name: avga
summary: add global variable manually
@ -432,14 +432,14 @@ commands:
cname: analysis_global_variable_delete_byname
args:
- name: name
type: RZ_CMD_ARG_TYPE_STRING
type: RZ_CMD_ARG_TYPE_GLOBAL_VAR
- name: avgn
summary: rename the global variable
type: RZ_CMD_DESC_TYPE_ARGV
cname: analysis_global_variable_rename
args:
- name: old_var_name
type: RZ_CMD_ARG_TYPE_STRING
type: RZ_CMD_ARG_TYPE_GLOBAL_VAR
- name: new_var_name
type: RZ_CMD_ARG_TYPE_STRING
- name: avgt
@ -448,7 +448,7 @@ commands:
cname: analysis_global_variable_retype
args:
- name: var_name
type: RZ_CMD_ARG_TYPE_STRING
type: RZ_CMD_ARG_TYPE_GLOBAL_VAR
- name: type
type: RZ_CMD_ARG_TYPE_ANY_TYPE
- name: avr

View file

@ -1510,8 +1510,7 @@ static const RzCmdDescHelp avg_help = {
static const RzCmdDescArg analysis_print_global_variable_args[] = {
{
.name = "var_name",
.type = RZ_CMD_ARG_TYPE_STRING,
.flags = RZ_CMD_ARG_FLAG_LAST,
.type = RZ_CMD_ARG_TYPE_GLOBAL_VAR,
.optional = true,
},
@ -1562,8 +1561,7 @@ static const RzCmdDescHelp analysis_global_variable_delete_byaddr_help = {
static const RzCmdDescArg analysis_global_variable_delete_byname_args[] = {
{
.name = "name",
.type = RZ_CMD_ARG_TYPE_STRING,
.flags = RZ_CMD_ARG_FLAG_LAST,
.type = RZ_CMD_ARG_TYPE_GLOBAL_VAR,
},
{ 0 },
@ -1576,7 +1574,7 @@ static const RzCmdDescHelp analysis_global_variable_delete_byname_help = {
static const RzCmdDescArg analysis_global_variable_rename_args[] = {
{
.name = "old_var_name",
.type = RZ_CMD_ARG_TYPE_STRING,
.type = RZ_CMD_ARG_TYPE_GLOBAL_VAR,
},
{
@ -1595,7 +1593,7 @@ static const RzCmdDescHelp analysis_global_variable_rename_help = {
static const RzCmdDescArg analysis_global_variable_retype_args[] = {
{
.name = "var_name",
.type = RZ_CMD_ARG_TYPE_STRING,
.type = RZ_CMD_ARG_TYPE_GLOBAL_VAR,
},
{

View file

@ -57,6 +57,7 @@ typedef enum rz_cmd_arg_type_t {
RZ_CMD_ARG_TYPE_ALIAS_TYPE, ///< Argument is a C typedef (alias) name
RZ_CMD_ARG_TYPE_CLASS_TYPE, ///< Argument is a C++/etc class name
RZ_CMD_ARG_TYPE_ANY_TYPE, ///< Argument is the any of the C or C++ type name
RZ_CMD_ARG_TYPE_GLOBAL_VAR, ///< Argument is a user defined global variable
} RzCmdArgType;
/**

View file

@ -400,6 +400,45 @@ static bool test_autocmplt_seek(void) {
mu_end;
}
static bool test_autocmplt_global(void) {
RzCore *core = rz_core_new();
mu_assert_notnull(core, "core should not be null");
RzAnalysisVarGlobal *glob1 = rz_analysis_var_global_new("GINT", 0x1337); // untyped global
mu_assert_notnull(glob1, "glob1 null");
bool added = rz_analysis_var_global_add(core->analysis, glob1);
mu_assert_true(added, "unable to add glob1");
RzAnalysisVarGlobal *glob2 = rz_analysis_var_global_new("GCHR", 0xd3ad); // typed global
mu_assert_notnull(glob2, "glob2 null");
added = rz_analysis_var_global_add(core->analysis, glob2);
mu_assert_true(added, "unable to add glob2");
RzTypeParser *parser = rz_type_parser_new();
mu_assert_notnull(parser, "create type parser");
char *errmsg = NULL;
RzType *typ = rz_type_parse_string_single(parser, "int", &errmsg);
mu_assert_notnull(typ, "parsed type");
rz_analysis_var_global_set_type(glob2, typ);
RzLineBuffer *buf = &core->cons->line->buffer;
const char *s = "avg ";
strcpy(buf->data, s);
buf->length = strlen(s);
buf->index = buf->length;
RzLineNSCompletionResult *r = rz_core_autocomplete_rzshell(core, buf, RZ_LINE_PROMPT_DEFAULT);
mu_assert_notnull(r, "r should not be null");
mu_assert_eq(r->start, strlen("avg "), "should autocomplete the last arg");
mu_assert_eq(r->end, buf->length, "should autocomplete ending at end of buffer");
mu_assert_eq(rz_pvector_len(&r->options), 2, "there are 2 global vars");
mu_assert_streq(rz_pvector_at(&r->options, 0), "GINT", "GINT found");
mu_assert_streq(rz_pvector_at(&r->options, 1), "GCHR", "GCHR found");
rz_line_ns_completion_result_free(r);
rz_core_free(core);
mu_end;
}
bool all_tests() {
mu_run_test(test_autocmplt_cmdid);
mu_run_test(test_autocmplt_newcommand);
@ -409,6 +448,7 @@ bool all_tests() {
mu_run_test(test_autocmplt_fcn);
mu_run_test(test_autocmplt_eval);
mu_run_test(test_autocmplt_seek);
mu_run_test(test_autocmplt_global);
return tests_passed != tests_run;
}