Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create global variable from DWARF #3985

Merged
merged 5 commits into from
Nov 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 61 additions & 9 deletions librz/analysis/dwarf_process.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include "analysis_private.h"

typedef struct dwarf_parse_context_t {
const RzAnalysis *analysis;
RzAnalysis *analysis;
RzBinDwarfCompUnit *unit;
RzBinDWARF *dw;
} Context;
Expand Down Expand Up @@ -1390,7 +1390,12 @@ static bool function_var_parse(
v->kind = RZ_ANALYSIS_VAR_KIND_VARIABLE;
break;
case DW_TAG_unspecified_parameters:
*has_unspecified_parameters = f->has_unspecified_parameters = true;
if (f) {
f->has_unspecified_parameters = true;
}
if (has_unspecified_parameters) {
*has_unspecified_parameters = true;
}
return true;
default:
return false;
Expand Down Expand Up @@ -1444,7 +1449,8 @@ static bool function_var_parse(
return true;
}

static bool function_children_parse(Context *ctx, const RzBinDwarfDie *die, RzCallable *callable, RzAnalysisDwarfFunction *fn) {
static bool function_children_parse(
Context *ctx, const RzBinDwarfDie *die, RzCallable *callable, RzAnalysisDwarfFunction *fn) {
if (!die->has_children) {
return false;
}
Expand All @@ -1462,16 +1468,16 @@ static bool function_children_parse(Context *ctx, const RzBinDwarfDie *die, RzCa
RzAnalysisDwarfVariable v = { 0 };
bool has_unspecified_parameters = false;
if (!function_var_parse(ctx, fn, die, &v, child_die, &has_unspecified_parameters)) {
goto err;
goto loop_end;
}
if (has_unspecified_parameters) {
callable->has_unspecified_parameters = true;
goto err;
goto loop_end;
}
if (!v.type) {
RZ_LOG_ERROR("DWARF function %s variable %s failed\n",
fn->prefer_name, v.prefer_name);
goto err;
goto loop_end;
}
if (v.kind == RZ_ANALYSIS_VAR_KIND_FORMAL_PARAMETER) {
RzCallableArg *arg = rz_type_callable_arg_new(
Expand All @@ -1481,7 +1487,7 @@ static bool function_children_parse(Context *ctx, const RzBinDwarfDie *die, RzCa
rz_vector_push(&fn->variables, &v);
ht_up_insert(ctx->analysis->debug_info->variable_by_offset, v.offset, &v);
continue;
err:
loop_end:
variable_fini(&v);
}
rz_pvector_free(children);
Expand Down Expand Up @@ -1622,7 +1628,45 @@ static bool function_from_die(
return false;
}

static bool variable_exist_global(RzAnalysis *a, RzAnalysisDwarfVariable *v) {
RzAnalysisVarGlobal *existing_glob = NULL;
if ((existing_glob = rz_analysis_var_global_get_byaddr_in(a, v->location->address))) {
return true;
}
if ((existing_glob = rz_analysis_var_global_get_byname(a, v->prefer_name))) {
return true;
}
return false;
}

static bool variable_from_die(
RZ_BORROW RZ_IN RZ_NONNULL Context *ctx,
RZ_BORROW RZ_IN RZ_NONNULL const RzBinDwarfDie *die) {
RzAnalysisDwarfVariable v = { 0 };
if (!function_var_parse(ctx, NULL, NULL, &v, die, NULL)) {
return false;
}
if (!(v.type && v.location->kind == RzBinDwarfLocationKind_ADDRESS)) {
return false;
}

if (variable_exist_global(ctx->analysis, &v)) {
return false;
}

bool result = rz_analysis_var_global_create(
ctx->analysis, v.prefer_name, v.type, v.location->address);

v.type = NULL;
variable_fini(&v);
return result;
}

static void parse_die(Context *ctx, RzBinDwarfDie *die) {
if (set_u_contains(ctx->analysis->debug_info->visited, die->offset)) {
return;
}
set_u_add(ctx->analysis->debug_info->visited, die->offset);
switch (die->tag) {
case DW_TAG_structure_type:
case DW_TAG_union_type:
Expand All @@ -1638,6 +1682,9 @@ static void parse_die(Context *ctx, RzBinDwarfDie *die) {
case DW_TAG_subprogram:
function_from_die(ctx, die);
break;
case DW_TAG_variable:
variable_from_die(ctx, die);
break;
default:
break;
}
Expand All @@ -1650,7 +1697,7 @@ static void parse_die(Context *ctx, RzBinDwarfDie *die) {
* \param dw RzBinDwarf pointer
*/
RZ_API void rz_analysis_dwarf_preprocess_info(
RZ_NONNULL RZ_BORROW const RzAnalysis *analysis,
RZ_NONNULL RZ_BORROW RzAnalysis *analysis,
RZ_NONNULL RZ_BORROW RzBinDWARF *dw) {
rz_return_if_fail(analysis && dw);
if (!dw->info) {
Expand Down Expand Up @@ -1767,7 +1814,7 @@ static bool store_callable(void *u, ut64 k, const void *v) {
* \param analysis RzAnalysis pointer
* \param dw RzBinDwarf pointer
*/
RZ_API void rz_analysis_dwarf_process_info(const RzAnalysis *analysis, RzBinDWARF *dw) {
RZ_API void rz_analysis_dwarf_process_info(RzAnalysis *analysis, RzBinDWARF *dw) {
rz_return_if_fail(analysis && dw);
rz_analysis_dwarf_preprocess_info(analysis, dw);
ht_pp_foreach(analysis->debug_info->base_type_by_name, store_base_type, (void *)analysis);
Expand Down Expand Up @@ -1866,6 +1913,9 @@ static bool RzBinDwarfLocation_as_RzAnalysisVarStorage(
break;
}
case RzBinDwarfLocationKind_ADDRESS: {
if (variable_exist_global(a, dw_var)) {
return false;
}
rz_analysis_var_global_create(a, dw_var->prefer_name,
rz_type_clone(dw_var->type), loc->address);
rz_analysis_var_fini(var);
Expand Down Expand Up @@ -2007,6 +2057,7 @@ RZ_API RzAnalysisDebugInfo *rz_analysis_debug_info_new() {
debug_info->callable_by_offset = ht_up_new(NULL, HtUP_RzCallable_free, NULL);
debug_info->base_type_by_offset = ht_up_new(NULL, HtUP_RzBaseType_free, NULL);
debug_info->base_type_by_name = ht_pp_new(NULL, HtPP_RzPVector_free, NULL);
debug_info->visited = set_u_new();
return debug_info;
}

Expand All @@ -2026,5 +2077,6 @@ RZ_API void rz_analysis_debug_info_free(RzAnalysisDebugInfo *debuginfo) {
ht_up_free(debuginfo->base_type_by_offset);
ht_pp_free(debuginfo->base_type_by_name);
rz_bin_dwarf_free(debuginfo->dw);
set_u_free(debuginfo->visited);
free(debuginfo);
}
38 changes: 26 additions & 12 deletions librz/bin/dwarf/op.c
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ RZ_API RZ_OWN RzBinDwarfEvaluation *rz_bin_dwarf_evaluation_new(
RZ_OWN RZ_NONNULL RzBinEndianReader *byte_code,
RZ_BORROW RZ_NONNULL const RzBinDWARF *dw,
RZ_BORROW RZ_NULLABLE const RzBinDwarfCompUnit *unit,
RZ_BORROW RZ_NULLABLE const RzBinDwarfDie *die) {
RZ_BORROW RZ_NULLABLE const RzBinDwarfDie *fn_die) {
rz_return_val_if_fail(byte_code && dw && unit, NULL);
RzBinDwarfEvaluation *self = RZ_NEW0(RzBinDwarfEvaluation);
RET_NULL_IF_FAIL(self);
Expand All @@ -704,7 +704,7 @@ RZ_API RZ_OWN RzBinDwarfEvaluation *rz_bin_dwarf_evaluation_new(
self->pc = RzBinEndianReader_clone(byte_code);
self->dw = dw;
self->unit = unit;
self->die = die;
self->fn_die = fn_die;
rz_vector_init(&self->stack, sizeof(RzBinDwarfValue), vec_Value_fini, NULL);
rz_vector_init(&self->expression_stack, sizeof(RzBinDwarfExprStackItem), vec_RzBinDwarfExprStackItem_fini, NULL);
rz_vector_init(&self->result, sizeof(RzBinDwarfPiece), (RzVectorFree)RzBinDwarfPiece_fini, NULL);
Expand Down Expand Up @@ -802,7 +802,8 @@ RZ_API void RzBinDwarfEvaluationResult_free(RZ_OWN RzBinDwarfEvaluationResult *s
break; \
}

static bool Evaluation_evaluate_one_operation(RzBinDwarfEvaluation *self, OperationEvaluationResult *out) {
static bool Evaluation_evaluate_one_operation(
RzBinDwarfEvaluation *self, OperationEvaluationResult *out) {
RzBinEndianReader *reader = self->pc;
Operation operation = { 0 };
bool ret = false;
Expand Down Expand Up @@ -968,7 +969,13 @@ static bool Evaluation_evaluate_one_operation(RzBinDwarfEvaluation *self, Operat
break;
}
case OPERATION_KIND_FRAME_OFFSET: {
RzBinDwarfAttr *fb_attr = rz_bin_dwarf_die_get_attr(self->die, DW_AT_frame_base);
if (!self->fn_die) {
out->kind = OperationEvaluationResult_WAITING;
out->waiting._1 = EvaluationStateWaiting_FbReg;
goto ok;
}

RzBinDwarfAttr *fb_attr = rz_bin_dwarf_die_get_attr(self->fn_die, DW_AT_frame_base);
ERR_IF_FAIL(fb_attr);
if (fb_attr->value.kind == RzBinDwarfAttr_UConstant) {
RzBinDwarfValue v = {
Expand All @@ -982,7 +989,7 @@ static bool Evaluation_evaluate_one_operation(RzBinDwarfEvaluation *self, Operat
rz_bin_dwarf_location_free(v.location));
break;
} else if (fb_attr->value.kind == RzBinDwarfAttr_Block) {
RzBinDwarfLocation *loc = rz_bin_dwarf_location_from_block(rz_bin_dwarf_attr_block(fb_attr), self->dw, self->unit, self->die);
RzBinDwarfLocation *loc = rz_bin_dwarf_location_from_block(rz_bin_dwarf_attr_block(fb_attr), self->dw, self->unit, self->fn_die);
if (!loc) {
RzBinDWARFDumpOption opt = {
.loclist_indent = "",
Expand Down Expand Up @@ -1107,16 +1114,23 @@ static bool Evaluation_evaluate_one_operation(RzBinDwarfEvaluation *self, Operat
goto ok;
}
case OPERATION_KIND_ADDRESS: {
out->kind = OperationEvaluationResult_WAITING;
out->waiting._1 = EvaluationStateWaiting_RelocatedAddress;
out->waiting._2.requires_relocated_address = operation.address.address;
out->kind = OperationEvaluationResult_COMPLETE;
out->complete.kind = RzBinDwarfLocationKind_ADDRESS;
out->complete.address = operation.address.address;
goto ok;
}
case OPERATION_KIND_ADDRESS_INDEX: {
out->kind = OperationEvaluationResult_WAITING;
out->waiting._1 = EvaluationStateWaiting_IndexedAddress;
out->waiting._2.requires_indexed_address.index = operation.address_index.index;
out->waiting._2.requires_indexed_address.relocate = true;
ut64 addr = 0;
if (self->dw && self->unit && rz_bin_dwarf_addr_get(self->dw->addr, &addr, self->unit->hdr.encoding.address_size, self->unit->addr_base, operation.address_index.index)) {
out->kind = OperationEvaluationResult_COMPLETE;
out->complete.kind = RzBinDwarfLocationKind_ADDRESS;
out->complete.address = addr;
} else {
out->kind = OperationEvaluationResult_WAITING;
out->waiting._1 = EvaluationStateWaiting_IndexedAddress;
out->waiting._2.requires_indexed_address.index = operation.address_index.index;
out->waiting._2.requires_indexed_address.relocate = true;
}
goto ok;
}
case OPERATION_KIND_CONSTANT_INDEX: {
Expand Down
5 changes: 5 additions & 0 deletions librz/core/cbin.c
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,11 @@ RZ_API bool rz_core_bin_apply_dwarf(RzCore *core, RzBinFile *binfile) {
return false;
}

rz_type_db_purge(core->analysis->typedb);
char *types_dir = rz_path_system(RZ_SDB_TYPES);
rz_type_db_reload(core->analysis->typedb, types_dir);
free(types_dir);

rz_analysis_debug_info_free(core->analysis->debug_info);
core->analysis->debug_info = rz_analysis_debug_info_new();
core->analysis->debug_info->dw = dw;
Expand Down
1 change: 1 addition & 0 deletions librz/core/cdwarf.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ static bool htup_loclists_cb(void *u, ut64 k, const void *v) {
RzBinDWARFDumpOption dump_opt = {
.loclist_sep = ",\t",
.loclist_indent = "",
.expr_sep = ", "
};
rz_bin_dwarf_expression_dump(
&ctx->cu->hdr.encoding, entry->expression, ctx->sb, &dump_opt);
Expand Down
5 changes: 3 additions & 2 deletions librz/include/rz_analysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ typedef struct {
HtPP /*<const char*, RzPVector<const RzBaseType *>>*/ *base_type_by_name; ///< Store all RzBaseType parsed from DWARF by DIE offset
DWARF_RegisterMapping dwarf_register_mapping; ///< Store the mapping function between DWARF registers number and register name in current architecture
RzBinDWARF *dw; ///< Holds ownership of RzBinDwarf, avoid releasing it prematurely
SetU *visited;
} RzAnalysisDebugInfo;

typedef struct rz_analysis_t {
Expand Down Expand Up @@ -2284,9 +2285,9 @@ RZ_API void rz_parse_pdb_types(const RzTypeDB *typedb, const RzPdb *pdb);

/* DWARF */
RZ_API void rz_analysis_dwarf_preprocess_info(
RZ_NONNULL RZ_BORROW const RzAnalysis *analysis,
RZ_NONNULL RZ_BORROW RzAnalysis *analysis,
RZ_NONNULL RZ_BORROW RzBinDWARF *dw);
RZ_API void rz_analysis_dwarf_process_info(const RzAnalysis *analysis, RzBinDWARF *dw);
RZ_API void rz_analysis_dwarf_process_info(RzAnalysis *analysis, RzBinDWARF *dw);
RZ_API void rz_analysis_dwarf_integrate_functions(RzAnalysis *analysis, RzFlag *flags);
RZ_API RzAnalysisDebugInfo *rz_analysis_debug_info_new();
RZ_API void rz_analysis_debug_info_free(RzAnalysisDebugInfo *debuginfo);
Expand Down
4 changes: 2 additions & 2 deletions librz/include/rz_bin_dwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -1608,7 +1608,7 @@ typedef struct {
typedef struct {
const RzBinDWARF *dw;
const RzBinDwarfCompUnit *unit;
const RzBinDwarfDie *die;
const RzBinDwarfDie *fn_die;
RzBinEndianReader *bytecode;
const RzBinDwarfEncoding *encoding;
ut64 *object_address;
Expand Down Expand Up @@ -1709,7 +1709,7 @@ RZ_API RZ_OWN RzBinDwarfEvaluation *rz_bin_dwarf_evaluation_new(
RZ_OWN RZ_NONNULL RzBinEndianReader *byte_code,
RZ_BORROW RZ_NONNULL const RzBinDWARF *dw,
RZ_BORROW RZ_NULLABLE const RzBinDwarfCompUnit *unit,
RZ_BORROW RZ_NULLABLE const RzBinDwarfDie *die);
RZ_BORROW RZ_NULLABLE const RzBinDwarfDie *fn_die);
RZ_API RZ_OWN RzBinDwarfEvaluation *rz_bin_dwarf_evaluation_new_from_block(
RZ_BORROW RZ_NONNULL const RzBinDwarfBlock *block,
RZ_BORROW RZ_NONNULL const RzBinDWARF *dw,
Expand Down
2 changes: 1 addition & 1 deletion test/db/abi/compilers/clang
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ CMDS=<<EOF
id~?
EOF
EXPECT=<<EOF
22327
22330
EOF
RUN

Expand Down
2 changes: 1 addition & 1 deletion test/db/abi/compilers/clang_64
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ CMDS=<<EOF
id~?
EOF
EXPECT=<<EOF
22442
22445
EOF
RUN

Expand Down
2 changes: 1 addition & 1 deletion test/db/abi/compilers/gcc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ CMDS=<<EOF
id~?
EOF
EXPECT=<<EOF
25788
25791
EOF
RUN

Expand Down
2 changes: 1 addition & 1 deletion test/db/abi/compilers/gcc_64
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ CMDS=<<EOF
id~?
EOF
EXPECT=<<EOF
25945
25948
EOF
RUN

Expand Down
2 changes: 1 addition & 1 deletion test/db/cmd/cmd_flags
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ fs *
fsl~?*
EOF
EXPECT=<<EOF
8
9
EOF
RUN

Expand Down
Loading
Loading