From c10d9c4a344ad254ca2ed8715c42aca51b88746d Mon Sep 17 00:00:00 2001 From: Alok Kumar Mishra <152197161+IndAlok@users.noreply.github.com> Date: Sat, 21 Mar 2026 13:22:21 +0530 Subject: [PATCH] analysis: add enum immediate hints with `ahie` command (#6052) --- librz/arch/filter.c | 51 +++++++++++-- librz/arch/hint.c | 22 ++++++ librz/arch/serialize_analysis.c | 15 +++- librz/core/canalysis.c | 6 ++ librz/core/cmd/cmd_analysis.c | 16 +++- librz/core/cmd_descs/cmd_analysis.yaml | 100 +++++++++++++++---------- librz/core/cmd_descs/cmd_descs.c | 44 ++++++++++- librz/core/cmd_descs/cmd_descs.h | 6 +- librz/include/rz_analysis.h | 7 +- librz/type/parser/types_parser.c | 12 +++ test/db/cmd/cmd_ahi | 84 +++++++++++++++++++++ test/unit/test_analysis_hints.c | 12 ++- test/unit/test_serialize_analysis.c | 5 +- test/unit/test_type.c | 27 +++++++ 14 files changed, 349 insertions(+), 58 deletions(-) diff --git a/librz/arch/filter.c b/librz/arch/filter.c index 0c73be93f6..0332165619 100644 --- a/librz/arch/filter.c +++ b/librz/arch/filter.c @@ -9,6 +9,7 @@ #include #include #include +#include #define isx86separator(x) ( \ (x) == ' ' || (x) == '\t' || (x) == '\n' || (x) == '\r' || (x) == ' ' || \ @@ -42,6 +43,39 @@ static void insert(char *dst, const char *src) { free(endNum); } +static void replace_number_token(char *out, size_t out_len, char *data, char *num_start, char *num_end, const char *value) { + *num_start = 0; + snprintf(out, out_len, "%s%s%s", data, value, (num_start != num_end) ? num_end : ""); +} + +static bool replace_enum_hint(RzParse *p, RzAnalysisHint *hint, ut64 off, char *data, char *out, size_t out_len, char *num_start, char *num_end) { + if (RZ_STR_ISEMPTY(hint->enum_name) || !p->analb.analysis || !p->analb.analysis->typedb) { + return false; + } + + const char *member = rz_type_db_enum_member_by_val( + p->analb.analysis->typedb, hint->enum_name, off); + if (!member) { + return false; + } + + char ename[512] = ""; + size_t ename_len = strlen(hint->enum_name) + strlen(member) + 2; + if (ename_len <= sizeof(ename)) { + rz_strf(ename, "%s.%s", hint->enum_name, member); + replace_number_token(out, out_len, data, num_start, num_end, ename); + return true; + } + + char *ename_dyn = rz_str_newf("%s.%s", hint->enum_name, member); + if (!ename_dyn) { + return false; + } + replace_number_token(out, out_len, data, num_start, num_end, ename_dyn); + free(ename_dyn); + return true; +} + static int parse_number(const char *str) { const char *p = str; // Parse as hexadecmial (0x notation) @@ -405,6 +439,8 @@ static bool filter(RzParse *p, ut64 addr, RzFlag *f, RzAnalysisHint *hint, char } } if (hint) { + char *num_start = ptr; + char *num_end = ptr2; const int nw = hint->nword; if (count != nw) { ptr = ptr2; @@ -414,11 +450,13 @@ static bool filter(RzParse *p, ut64 addr, RzFlag *f, RzAnalysisHint *hint, char char num[256] = { 0 }, *pnum, *tmp; int tmp_count; if (hint->offset) { - *ptr = 0; - snprintf(str, len, "%s%s%s", data, hint->offset, (ptr != ptr2) ? ptr2 : ""); + replace_number_token(str, len, data, num_start, num_end, hint->offset); return true; } - strncpy(num, ptr, sizeof(num) - 2); + if (replace_enum_hint(p, hint, off, data, str, len, num_start, num_end)) { + return true; + } + strncpy(num, num_start, sizeof(num) - 2); pnum = num + parse_number(num); *pnum = 0; switch (immbase) { @@ -427,9 +465,9 @@ static bool filter(RzParse *p, ut64 addr, RzFlag *f, RzAnalysisHint *hint, char break; case 1: // hack for ascii tmp_count = 0; - for (tmp = data; tmp < ptr; tmp++) { + for (tmp = data; tmp < num_start; tmp++) { if (*tmp == 0x1b) { - while (tmp < ptr - 1 && *tmp != 'm') { + while (tmp < num_start - 1 && *tmp != 'm') { tmp++; } continue; @@ -545,8 +583,7 @@ static bool filter(RzParse *p, ut64 addr, RzFlag *f, RzAnalysisHint *hint, char snprintf(num, sizeof(num), "0x%" PFMT64x, (ut64)off); break; } - *ptr = 0; - snprintf(str, len, "%s%s%s", data, num, (ptr != ptr2) ? ptr2 : ""); + replace_number_token(str, len, data, num_start, num_end, num); return true; } ptr = ptr2; diff --git a/librz/arch/hint.c b/librz/arch/hint.c index 8e5048ca96..51079cea5b 100644 --- a/librz/arch/hint.c +++ b/librz/arch/hint.c @@ -49,6 +49,9 @@ static void addr_hint_record_fini(void *element, void *user) { case RZ_ANALYSIS_ADDR_HINT_TYPE_ESIL: free(record->esil); break; + case RZ_ANALYSIS_ADDR_HINT_TYPE_ENUM: + free(record->enum_name); + break; default: break; } @@ -230,6 +233,16 @@ RZ_API void rz_analysis_hint_set_immbase(RzAnalysis *a, ut64 addr, int base) { } } +RZ_API void rz_analysis_hint_set_enum(RzAnalysis *a, ut64 addr, const char *enum_name) { + if (RZ_STR_ISEMPTY(enum_name)) { + rz_analysis_hint_unset_enum(a, addr); + return; + } + SET_HINT(RZ_ANALYSIS_ADDR_HINT_TYPE_ENUM, + free(r->enum_name); + r->enum_name = rz_str_dup(enum_name);); +} + RZ_API void rz_analysis_hint_set_pointer(RzAnalysis *a, ut64 addr, ut64 ptr) { SET_HINT(RZ_ANALYSIS_ADDR_HINT_TYPE_PTR, r->ptr = ptr;); } @@ -312,6 +325,10 @@ RZ_API void rz_analysis_hint_unset_immbase(RzAnalysis *a, ut64 addr) { unset_addr_hint_record(a, RZ_ANALYSIS_ADDR_HINT_TYPE_IMMBASE, addr); } +RZ_API void rz_analysis_hint_unset_enum(RzAnalysis *a, ut64 addr) { + unset_addr_hint_record(a, RZ_ANALYSIS_ADDR_HINT_TYPE_ENUM, addr); +} + RZ_API void rz_analysis_hint_unset_nword(RzAnalysis *a, ut64 addr) { unset_addr_hint_record(a, RZ_ANALYSIS_ADDR_HINT_TYPE_NWORD, addr); } @@ -371,6 +388,7 @@ RZ_API void rz_analysis_hint_free(RzAnalysisHint *h) { free(h->opcode); free(h->syntax); free(h->offset); + free(h->enum_name); free(h); } } @@ -496,6 +514,10 @@ static void hint_merge(RzAnalysisHint *hint, RzAnalysisAddrHintRecord *record) { case RZ_ANALYSIS_ADDR_HINT_TYPE_VAL: hint->val = record->val; break; + case RZ_ANALYSIS_ADDR_HINT_TYPE_ENUM: + free(hint->enum_name); + hint->enum_name = rz_str_dup(record->enum_name); + break; } } diff --git a/librz/arch/serialize_analysis.c b/librz/arch/serialize_analysis.c index 8ddf9e71a2..4dae7d63ab 100644 --- a/librz/arch/serialize_analysis.c +++ b/librz/arch/serialize_analysis.c @@ -1848,6 +1848,11 @@ static bool hints_acc_store_cb(void *user, const ut64 addr, const void *v) { case RZ_ANALYSIS_ADDR_HINT_TYPE_VAL: pj_kn(j, "val", record->val); break; + case RZ_ANALYSIS_ADDR_HINT_TYPE_ENUM: + if (!RZ_STR_ISEMPTY(record->enum_name)) { + pj_ks(j, "enum", record->enum_name); + } + break; } } } @@ -1884,7 +1889,8 @@ enum { HINTS_FIELD_TYPE_OFFSET, HINTS_FIELD_ESIL, HINTS_FIELD_HIGH, - HINTS_FIELD_VAL + HINTS_FIELD_VAL, + HINTS_FIELD_ENUM }; typedef struct { @@ -2015,6 +2021,12 @@ static bool hints_load_cb(void *user, const SdbKv *kv) { } rz_analysis_hint_set_val(analysis, addr, child->num.u_value); break; + case HINTS_FIELD_ENUM: + if (child->type != RZ_JSON_STRING) { + break; + } + rz_analysis_hint_set_enum(analysis, addr, child->str_value); + break; default: break; }) @@ -2054,6 +2066,7 @@ RZ_API bool rz_serialize_analysis_hints_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAn rz_key_parser_add(ctx.parser, "esil", HINTS_FIELD_ESIL); rz_key_parser_add(ctx.parser, "high", HINTS_FIELD_HIGH); rz_key_parser_add(ctx.parser, "val", HINTS_FIELD_VAL); + rz_key_parser_add(ctx.parser, "enum", HINTS_FIELD_ENUM); ret = sdb_foreach(db, hints_load_cb, &ctx); if (!ret) { RZ_SERIALIZE_ERR(res, "hints parsing failed"); diff --git a/librz/core/canalysis.c b/librz/core/canalysis.c index 77b09fbb70..1bc6cbd94d 100644 --- a/librz/core/canalysis.c +++ b/librz/core/canalysis.c @@ -1118,6 +1118,9 @@ static void print_hint_h_format(HintNode *node) { case RZ_ANALYSIS_ADDR_HINT_TYPE_VAL: rz_cons_printf(" val=0x%08" PFMT64x, record->val); break; + case RZ_ANALYSIS_ADDR_HINT_TYPE_ENUM: + rz_cons_printf(" enum='%s'", rz_str_get(record->enum_name)); + break; } } break; @@ -1199,6 +1202,9 @@ static void hint_node_print(HintNode *node, RzOutputMode mode, PJ *pj) { case RZ_ANALYSIS_ADDR_HINT_TYPE_VAL: pj_kn(pj, "val", record->val); break; + case RZ_ANALYSIS_ADDR_HINT_TYPE_ENUM: + pj_ks(pj, "enum", rz_str_get(record->enum_name)); + break; } } break; diff --git a/librz/core/cmd/cmd_analysis.c b/librz/core/cmd/cmd_analysis.c index 4ab372e439..7f857aa92d 100644 --- a/librz/core/cmd/cmd_analysis.c +++ b/librz/core/cmd/cmd_analysis.c @@ -4601,7 +4601,7 @@ RZ_IPI RzCmdStatus rz_analysis_hint_del_optype_handler(RzCore *core, int argc, c return RZ_CMD_STATUS_OK; } -RZ_IPI RzCmdStatus rz_analysis_hint_set_immbase_handler(RzCore *core, int argc, const char **argv) { +RZ_IPI RzCmdStatus rz_analysis_hint_set_immbase_handler(RzCore *core, int argc, const char **argv, RzOutputMode mode RZ_UNUSED) { int base = rz_num_base_of_string(core->num, argv[1]); if (argc == 3) { ut64 nword = rz_num_math(core->num, argv[2]); @@ -4616,6 +4616,20 @@ RZ_IPI RzCmdStatus rz_analysis_hint_del_immbase_handler(RzCore *core, int argc, return RZ_CMD_STATUS_OK; } +RZ_IPI RzCmdStatus rz_analysis_hint_set_enum_handler(RzCore *core, int argc, const char **argv) { + if (argc == 3) { + ut64 nword = rz_num_math(core->num, argv[2]); + rz_analysis_hint_set_nword(core->analysis, core->offset, (int)(nword)); + } + rz_analysis_hint_set_enum(core->analysis, core->offset, argv[1]); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_analysis_hint_del_enum_handler(RzCore *core, int argc, const char **argv) { + rz_analysis_hint_unset_enum(core->analysis, core->offset); + return RZ_CMD_STATUS_OK; +} + RZ_IPI RzCmdStatus rz_analysis_hint_set_offset_handler(RzCore *core, int argc, const char **argv) { return bool2status(rz_core_analysis_hint_set_offset(core, argv[1])); } diff --git a/librz/core/cmd_descs/cmd_analysis.yaml b/librz/core/cmd_descs/cmd_analysis.yaml index eeb34ec9c3..78d8b88e8b 100644 --- a/librz/core/cmd_descs/cmd_analysis.yaml +++ b/librz/core/cmd_descs/cmd_analysis.yaml @@ -1980,47 +1980,65 @@ commands: cname: analysis_hint_del_optype args: [] - name: ahi - summary: Set immediate base hint - cname: analysis_hint_set_immbase - args: - - name: type - type: RZ_CMD_ARG_TYPE_CHOICES - choices: ["2", "8", "10", "10u", "16", "b", "o", "h", "i", "p", "S", "s"] - - name: nword - type: RZ_CMD_ARG_TYPE_NUM - optional: true - details: - - name: "" - entries: - - text: "ahi " - arg_str: - comment: Set numeric (2, 8, 10, 16) - - text: ahi 10|d - comment: Set base to signed decimal (10), sign bit should depend on receiver size - - text: ahi 10u|du - comment: Set base to unsigned decimal (11) - - text: ahi b - comment: Set base to binary (2) - - text: ahi o - comment: Set base to octal (8) - - text: ahi h - comment: Set base to hexadecimal (16) - - text: ahi i - comment: Set base to IP address (32) - - text: ahi p - comment: Set base to htons(port) (3) - - text: ahi S - comment: Set base to syscall (80) - - text: ahi s - comment: Set base to string (1) - - name: Set base of the N-th immediate (indexing starts from 0) - entries: - - text: ahi 16 1 - comment: Set base of the 1-st immediate to hexadecimal - - name: ahi- - summary: Delete immediate base hint - cname: analysis_hint_del_immbase - args: [] + summary: Manage immediate operand hints + subcommands: + - name: ahi + summary: Set immediate base hint + cname: analysis_hint_set_immbase + modes: + - RZ_OUTPUT_MODE_STANDARD + args: + - name: type + type: RZ_CMD_ARG_TYPE_CHOICES + choices: ["2", "8", "10", "10u", "16", "b", "o", "h", "i", "p", "S", "s"] + - name: nword + type: RZ_CMD_ARG_TYPE_NUM + optional: true + details: + - name: "" + entries: + - text: "ahi " + arg_str: + comment: Set numeric (2, 8, 10, 16) + - text: ahi 10|d + comment: Set base to signed decimal (10), sign bit should depend on receiver size + - text: ahi 10u|du + comment: Set base to unsigned decimal (11) + - text: ahi b + comment: Set base to binary (2) + - text: ahi o + comment: Set base to octal (8) + - text: ahi h + comment: Set base to hexadecimal (16) + - text: ahi i + comment: Set base to IP address (32) + - text: ahi p + comment: Set base to htons(port) (3) + - text: ahi S + comment: Set base to syscall (80) + - text: ahi s + comment: Set base to string (1) + - name: Set base of the N-th immediate (indexing starts from 0) + entries: + - text: ahi 16 1 + comment: Set base of the 1-st immediate to hexadecimal + - name: ahi- + summary: Delete immediate base hint + cname: analysis_hint_del_immbase + args: [] + - name: ahie + summary: Set enum type hint for operand + cname: analysis_hint_set_enum + args: + - name: enum + type: RZ_CMD_ARG_TYPE_ENUM_TYPE + - name: nword + type: RZ_CMD_ARG_TYPE_NUM + optional: true + - name: ahie- + summary: Delete enum type hint + cname: analysis_hint_del_enum + args: [] - name: aht summary: Set structure offset hint cname: analysis_hint_set_offset diff --git a/librz/core/cmd_descs/cmd_descs.c b/librz/core/cmd_descs/cmd_descs.c index c8cff94245..c080a9a92d 100644 --- a/librz/core/cmd_descs/cmd_descs.c +++ b/librz/core/cmd_descs/cmd_descs.c @@ -356,6 +356,7 @@ static const RzCmdDescArg analysis_hint_set_ret_args[2]; static const RzCmdDescArg analysis_hint_set_val_args[2]; static const RzCmdDescArg analysis_hint_set_optype_args[2]; static const RzCmdDescArg analysis_hint_set_immbase_args[3]; +static const RzCmdDescArg analysis_hint_set_enum_args[3]; static const RzCmdDescArg analysis_hint_set_offset_args[2]; static const RzCmdDescArg analysis_list_struct_offsets_args[2]; static const RzCmdDescArg analysis_class_add_args[2]; @@ -6996,6 +6997,9 @@ static const RzCmdDescHelp analysis_hint_del_optype_help = { .args = analysis_hint_del_optype_args, }; +static const RzCmdDescHelp ahi_help = { + .summary = "Manage immediate operand hints", +}; static const RzCmdDescDetailEntry analysis_hint_set_immbase_empty_detail_entries[] = { { .text = "ahi ", .arg_str = "", .comment = "Set numeric (2, 8, 10, 16)" }, { .text = "ahi 10|d", .arg_str = NULL, .comment = "Set base to signed decimal (10), sign bit should depend on receiver size" }, @@ -7049,6 +7053,33 @@ static const RzCmdDescHelp analysis_hint_del_immbase_help = { .args = analysis_hint_del_immbase_args, }; +static const RzCmdDescArg analysis_hint_set_enum_args[] = { + { + .name = "enum", + .type = RZ_CMD_ARG_TYPE_ENUM_TYPE, + + }, + { + .name = "nword", + .type = RZ_CMD_ARG_TYPE_NUM, + .optional = true, + + }, + { 0 }, +}; +static const RzCmdDescHelp analysis_hint_set_enum_help = { + .summary = "Set enum type hint for operand", + .args = analysis_hint_set_enum_args, +}; + +static const RzCmdDescArg analysis_hint_del_enum_args[] = { + { 0 }, +}; +static const RzCmdDescHelp analysis_hint_del_enum_help = { + .summary = "Delete enum type hint", + .args = analysis_hint_del_enum_args, +}; + static const RzCmdDescDetailEntry analysis_hint_set_offset_empty_detail_entries[] = { { .text = "aht ", .arg_str = "struct.member", .comment = "Replace immediate with " }, { 0 }, @@ -22654,12 +22685,17 @@ RZ_IPI void rzshell_cmddescs_init(RzCore *core) { RzCmdDesc *analysis_hint_del_optype_cd = rz_cmd_desc_argv_new(core->rcmd, ah_cd, "aho-", rz_analysis_hint_del_optype_handler, &analysis_hint_del_optype_help); rz_warn_if_fail(analysis_hint_del_optype_cd); - RzCmdDesc *analysis_hint_set_immbase_cd = rz_cmd_desc_argv_new(core->rcmd, ah_cd, "ahi", rz_analysis_hint_set_immbase_handler, &analysis_hint_set_immbase_help); - rz_warn_if_fail(analysis_hint_set_immbase_cd); - - RzCmdDesc *analysis_hint_del_immbase_cd = rz_cmd_desc_argv_new(core->rcmd, ah_cd, "ahi-", rz_analysis_hint_del_immbase_handler, &analysis_hint_del_immbase_help); + RzCmdDesc *ahi_cd = rz_cmd_desc_group_modes_new(core->rcmd, ah_cd, "ahi", RZ_OUTPUT_MODE_STANDARD, rz_analysis_hint_set_immbase_handler, &analysis_hint_set_immbase_help, &ahi_help); + rz_warn_if_fail(ahi_cd); + RzCmdDesc *analysis_hint_del_immbase_cd = rz_cmd_desc_argv_new(core->rcmd, ahi_cd, "ahi-", rz_analysis_hint_del_immbase_handler, &analysis_hint_del_immbase_help); rz_warn_if_fail(analysis_hint_del_immbase_cd); + RzCmdDesc *analysis_hint_set_enum_cd = rz_cmd_desc_argv_new(core->rcmd, ahi_cd, "ahie", rz_analysis_hint_set_enum_handler, &analysis_hint_set_enum_help); + rz_warn_if_fail(analysis_hint_set_enum_cd); + + RzCmdDesc *analysis_hint_del_enum_cd = rz_cmd_desc_argv_new(core->rcmd, ahi_cd, "ahie-", rz_analysis_hint_del_enum_handler, &analysis_hint_del_enum_help); + rz_warn_if_fail(analysis_hint_del_enum_cd); + RzCmdDesc *analysis_hint_set_offset_cd = rz_cmd_desc_argv_new(core->rcmd, ah_cd, "aht", rz_analysis_hint_set_offset_handler, &analysis_hint_set_offset_help); rz_warn_if_fail(analysis_hint_set_offset_cd); diff --git a/librz/core/cmd_descs/cmd_descs.h b/librz/core/cmd_descs/cmd_descs.h index f33055123d..22122ce9ca 100644 --- a/librz/core/cmd_descs/cmd_descs.h +++ b/librz/core/cmd_descs/cmd_descs.h @@ -800,9 +800,13 @@ RZ_IPI RzCmdStatus rz_analysis_hint_set_optype_handler(RzCore *core, int argc, c // "aho-" RZ_IPI RzCmdStatus rz_analysis_hint_del_optype_handler(RzCore *core, int argc, const char **argv); // "ahi" -RZ_IPI RzCmdStatus rz_analysis_hint_set_immbase_handler(RzCore *core, int argc, const char **argv); +RZ_IPI RzCmdStatus rz_analysis_hint_set_immbase_handler(RzCore *core, int argc, const char **argv, RzOutputMode mode); // "ahi-" RZ_IPI RzCmdStatus rz_analysis_hint_del_immbase_handler(RzCore *core, int argc, const char **argv); +// "ahie" +RZ_IPI RzCmdStatus rz_analysis_hint_set_enum_handler(RzCore *core, int argc, const char **argv); +// "ahie-" +RZ_IPI RzCmdStatus rz_analysis_hint_del_enum_handler(RzCore *core, int argc, const char **argv); // "aht" RZ_IPI RzCmdStatus rz_analysis_hint_set_offset_handler(RzCore *core, int argc, const char **argv); // "aht-" diff --git a/librz/include/rz_analysis.h b/librz/include/rz_analysis.h index 02ef84cfb0..b315c46c86 100644 --- a/librz/include/rz_analysis.h +++ b/librz/include/rz_analysis.h @@ -571,7 +571,8 @@ typedef enum rz_analysis_addr_hint_type_t { RZ_ANALYSIS_ADDR_HINT_TYPE_TYPE_OFFSET, RZ_ANALYSIS_ADDR_HINT_TYPE_ESIL, RZ_ANALYSIS_ADDR_HINT_TYPE_HIGH, - RZ_ANALYSIS_ADDR_HINT_TYPE_VAL + RZ_ANALYSIS_ADDR_HINT_TYPE_VAL, + RZ_ANALYSIS_ADDR_HINT_TYPE_ENUM } RzAnalysisAddrHintType; typedef struct rz_analysis_addr_hint_record_t { @@ -592,6 +593,7 @@ typedef struct rz_analysis_addr_hint_record_t { ut64 size; ut64 stackframe; ut64 val; + char *enum_name; }; } RzAnalysisAddrHintRecord; @@ -615,6 +617,7 @@ typedef struct rz_analysis_hint_t { bool high; // highlight hint int nword; ut64 stackframe; + char *enum_name; } RzAnalysisHint; typedef RzAnalysisFunction *(*RzAnalysisGetFcnIn)(RzAnalysis *analysis, ut64 addr, int type); @@ -2179,6 +2182,7 @@ RZ_API void rz_analysis_hint_set_newbits(RzAnalysis *a, ut64 addr, int bits); RZ_API void rz_analysis_hint_set_nword(RzAnalysis *a, ut64 addr, int nword); RZ_API void rz_analysis_hint_set_offset(RzAnalysis *a, ut64 addr, const char *typeoff); RZ_API void rz_analysis_hint_set_immbase(RzAnalysis *a, ut64 addr, int base); +RZ_API void rz_analysis_hint_set_enum(RzAnalysis *a, ut64 addr, const char *enum_name); RZ_API void rz_analysis_hint_set_size(RzAnalysis *a, ut64 addr, ut64 size); RZ_API void rz_analysis_hint_set_opcode(RzAnalysis *a, ut64 addr, const char *str); RZ_API void rz_analysis_hint_set_esil(RzAnalysis *a, ut64 addr, const char *str); @@ -2192,6 +2196,7 @@ RZ_API void rz_analysis_hint_set_bits(RzAnalysis *a, ut64 addr, int bits); // bi RZ_API void rz_analysis_hint_unset_val(RzAnalysis *a, ut64 addr); RZ_API void rz_analysis_hint_unset_high(RzAnalysis *a, ut64 addr); RZ_API void rz_analysis_hint_unset_immbase(RzAnalysis *a, ut64 addr); +RZ_API void rz_analysis_hint_unset_enum(RzAnalysis *a, ut64 addr); RZ_API void rz_analysis_hint_unset_nword(RzAnalysis *a, ut64 addr); RZ_API void rz_analysis_hint_unset_size(RzAnalysis *a, ut64 addr); RZ_API void rz_analysis_hint_unset_type(RzAnalysis *a, ut64 addr); diff --git a/librz/type/parser/types_parser.c b/librz/type/parser/types_parser.c index 78c2e20ab6..2a21be0bd9 100644 --- a/librz/type/parser/types_parser.c +++ b/librz/type/parser/types_parser.c @@ -114,6 +114,12 @@ int parse_primitive_type(CParserState *state, TSNode node, const char *text, Par free(real_type); return 0; } + if ((*tpair = c_parser_get_typedef(state, real_type))) { + (*tpair)->type->identifier.is_const = is_const; + parser_debug(state, "Fetched type alias: \"%s\"\n", real_type); + free(real_type); + return 0; + } // If not - we form both RzType and RzBaseType to store in the Types database ParserTypePair *type_pair = c_parser_new_primitive_type(state, real_type, is_const); if (!type_pair) { @@ -150,6 +156,12 @@ int parse_sized_primitive_type(CParserState *state, TSNode node, const char *tex free(real_type); return 0; } + if ((*tpair = c_parser_get_typedef(state, real_type))) { + (*tpair)->type->identifier.is_const = is_const; + parser_debug(state, "Fetched type alias: \"%s\"\n", real_type); + free(real_type); + return 0; + } // If not - we form both RzType and RzBaseType to store in the Types database ParserTypePair *type_pair = c_parser_new_primitive_type(state, real_type, is_const); if (!type_pair) { diff --git a/test/db/cmd/cmd_ahi b/test/db/cmd/cmd_ahi index 09678f84dd..47c29cf6f8 100644 --- a/test/db/cmd/cmd_ahi +++ b/test/db/cmd/cmd_ahi @@ -380,3 +380,87 @@ EXPECT=<esil, "13,29,+", "esil hint")); assert_addr_hint(0x2c0, HIGH, ); assert_addr_hint(0x2d0, VAL, mu_assert_eq(record->val, 54323, "val hint")); + assert_addr_hint(0x2e0, ENUM, mu_assert_streq(record->enum_name, "BLA", "enum hint")); size_t i; for (i = 0; i < ALL_OPTYPES_COUNT; i++) { diff --git a/test/unit/test_type.c b/test/unit/test_type.c index 2fb8180b9a..f285b368bf 100644 --- a/test/unit/test_type.c +++ b/test/unit/test_type.c @@ -762,6 +762,32 @@ static bool test_array_types(void) { mu_end; } +static bool test_single_typedef_aliases(void) { + RzTypeDB *typedb = rz_type_db_new(); + mu_assert_notnull(typedb, "Couldn't create new RzTypeDB"); + mu_assert_notnull(typedb->types, "Couldn't create new types hashtable"); + const char *types_dir = TEST_BUILD_TYPES_DIR; + const char *src[] = { "size_t", "uint32_t", "uint64_t", "const size_t" }; + const char *name[] = { "size_t", "uint32_t", "uint64_t", "size_t" }; + const bool cnst[] = { false, false, false, true }; + rz_type_db_init(typedb, types_dir, "x86", 64, "linux"); + rz_type_db_set_bits(typedb, 64); + + for (size_t i = 0; i < RZ_ARRAY_SIZE(src); i++) { + char *error_msg = NULL; + RzType *ttype = rz_type_parse_string_single(typedb->parser, src[i], &error_msg); + mu_assert_notnull(ttype, "typedef alias parse successful"); + mu_assert_null(error_msg, "parsing errors"); + mu_assert_eq(ttype->kind, RZ_TYPE_KIND_IDENTIFIER, "parsed type"); + mu_assert_streq(ttype->identifier.name, name[i], "parsed type"); + mu_assert_eq(ttype->identifier.is_const, cnst[i], "parsed const"); + rz_type_free(ttype); + } + + rz_type_db_free(typedb); + mu_end; +} + static char *func_ptr_struct = "struct bla { int a; wchar_t (*func)(int a, const char *b); }"; static char *func_double_ptr_struct = "struct blabla { int a; wchar_t (**funk)(int a, const char *b); }"; @@ -1866,6 +1892,7 @@ int all_tests() { mu_run_test(test_enum_types); mu_run_test(test_const_types); mu_run_test(test_array_types); + mu_run_test(test_single_typedef_aliases); mu_run_test(test_struct_func_types); mu_run_test(test_struct_array_types); mu_run_test(test_struct_identifier_without_specifier);