Fix stack location in composite

This commit is contained in:
billow
2023-11-29 10:29:01 +08:00
committed by Anton Kochkov
parent 7842557ac0
commit 8b8d5c7769
12 changed files with 320 additions and 181 deletions
+28 -25
View File
@@ -39,7 +39,7 @@ static bool function_from_die(
RZ_BORROW RZ_IN RZ_NONNULL Context *ctx,
RZ_BORROW RZ_IN RZ_NONNULL const RzBinDwarfDie *die);
static void parse_die(Context *ctx, RzBinDwarfDie *die);
static void die_parse(Context *ctx, RzBinDwarfDie *die);
/* For some languages linkage name is more informative like C++,
but for Rust it's rubbish and the normal name is fine */
@@ -735,10 +735,10 @@ static RzBaseType *RzBaseType_from_die(Context *ctx, const RzBinDwarfDie *die) {
btype->name, die->offset);
}
RzPVector *btypes = ht_pp_find(ctx->analysis->debug_info->base_type_by_name, btype->name, NULL);
RzPVector *btypes = ht_pp_find(ctx->analysis->debug_info->base_types_by_name, btype->name, NULL);
if (!btypes) {
btypes = rz_pvector_new(NULL);
ht_pp_insert(ctx->analysis->debug_info->base_type_by_name, btype->name, btypes);
ht_pp_insert(ctx->analysis->debug_info->base_types_by_name, btype->name, btypes);
rz_pvector_push(btypes, btype);
} else {
void **it;
@@ -1158,7 +1158,7 @@ static bool struct_union_children_parse(
// we take only direct descendats of the structure
if (!(child_die->depth == die->depth + 1 &&
child_die->tag == DW_TAG_member)) {
parse_die(ctx, child_die);
die_parse(ctx, child_die);
continue;
}
RzTypeStructMember member = { 0 };
@@ -1217,7 +1217,7 @@ static bool enum_children_parse(
RzBinDwarfDie *child_die = *it;
if (!(child_die->depth == die->depth + 1 &&
child_die->tag == DW_TAG_enumerator)) {
parse_die(ctx, child_die);
die_parse(ctx, child_die);
continue;
}
RzTypeEnumCase cas = { 0 };
@@ -1354,18 +1354,18 @@ static RzBinDwarfLocation *location_parse(
}
if (rz_pvector_len(&loclist->entries) > 1) {
return location_list_parse(ctx, loclist, fn);
} else if (rz_pvector_len(&loclist->entries) == 1) {
}
if (rz_pvector_len(&loclist->entries) == 1) {
RzBinDwarfLocListEntry *entry = rz_pvector_at(&loclist->entries, 0);
return rz_bin_dwarf_location_from_block(entry->expression, ctx->dw, ctx->unit, fn);
} else {
RzBinDwarfLocation *loc = RZ_NEW0(RzBinDwarfLocation);
if (!loc) {
return NULL;
}
loc->kind = RzBinDwarfLocationKind_EMPTY;
loc->encoding = ctx->unit->hdr.encoding;
return loc;
}
RzBinDwarfLocation *loc = RZ_NEW0(RzBinDwarfLocation);
if (!loc) {
return NULL;
}
loc->kind = RzBinDwarfLocationKind_EMPTY;
loc->encoding = ctx->unit->hdr.encoding;
return loc;
err_find:
RZ_LOG_ERROR("Location parse failed 0x%" PFMT64x " <Cannot find loclist>\n", offset);
return NULL;
@@ -1462,7 +1462,7 @@ static bool function_children_parse(
rz_pvector_foreach (children, it) {
RzBinDwarfDie *child_die = *it;
if (child_die->depth != die->depth + 1) {
parse_die(ctx, child_die);
die_parse(ctx, child_die);
continue;
}
RzAnalysisDwarfVariable v = { 0 };
@@ -1662,7 +1662,7 @@ static bool variable_from_die(
return result;
}
static void parse_die(Context *ctx, RzBinDwarfDie *die) {
static void die_parse(Context *ctx, RzBinDwarfDie *die) {
if (set_u_contains(ctx->analysis->debug_info->visited, die->offset)) {
return;
}
@@ -1690,6 +1690,12 @@ static void parse_die(Context *ctx, RzBinDwarfDie *die) {
}
}
static RzBinDwarfDie *die_next(RzBinDwarfDie *die, RzBinDWARF *dw) {
return (die->sibling > die->offset)
? ht_up_find(dw->info->die_by_offset, die->sibling, NULL)
: die + 1;
}
/**
* \brief Parses type and function information out of DWARF entries
* and stores them to analysis->debug_info
@@ -1717,10 +1723,8 @@ RZ_API void rz_analysis_dwarf_preprocess_info(
ctx.unit = unit;
for (RzBinDwarfDie *die = rz_vector_head(&unit->dies);
die && (ut8 *)die < (ut8 *)unit->dies.a + unit->dies.len * unit->dies.elem_size;
(die->sibling > die->offset)
? die = ht_up_find(dw->info->die_by_offset, die->sibling, NULL)
: ++die) {
parse_die(&ctx, die);
die = die_next(die, dw)) {
die_parse(&ctx, die);
}
}
}
@@ -1758,7 +1762,7 @@ static bool store_base_type(void *u, const void *k, const void *v) {
RzAnalysis *analysis = u;
const char *name = k;
RzPVector *types = (RzPVector *)v;
ut32 len = rz_pvector_len(types);
const ut32 len = rz_pvector_len(types);
if (len == 0) {
RZ_LOG_WARN("BaseType %s has nothing", name);
} else if (len == 1) {
@@ -1792,7 +1796,6 @@ static bool store_base_type(void *u, const void *k, const void *v) {
db_save_renamed(analysis->typedb, rz_base_type_clone(b), newname);
} else {
RZ_LOG_WARN("BaseType: same name [%s] type count is more than 3\n", name);
goto beach;
}
beach:
return true;
@@ -1817,7 +1820,7 @@ static bool store_callable(void *u, ut64 k, const void *v) {
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);
ht_pp_foreach(analysis->debug_info->base_types_by_name, store_base_type, (void *)analysis);
ht_up_foreach(analysis->debug_info->callable_by_offset, store_callable, (void *)analysis);
}
@@ -2056,7 +2059,7 @@ RZ_API RzAnalysisDebugInfo *rz_analysis_debug_info_new() {
debug_info->type_by_offset = ht_up_new(NULL, HtUP_RzType_free, NULL);
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->base_types_by_name = ht_pp_new(NULL, HtPP_RzPVector_free, NULL);
debug_info->visited = set_u_new();
return debug_info;
}
@@ -2075,7 +2078,7 @@ RZ_API void rz_analysis_debug_info_free(RzAnalysisDebugInfo *debuginfo) {
ht_up_free(debuginfo->type_by_offset);
ht_up_free(debuginfo->callable_by_offset);
ht_up_free(debuginfo->base_type_by_offset);
ht_pp_free(debuginfo->base_type_by_name);
ht_pp_free(debuginfo->base_types_by_name);
rz_bin_dwarf_free(debuginfo->dw);
set_u_free(debuginfo->visited);
free(debuginfo);
+5 -53
View File
@@ -6,7 +6,7 @@
#include <rz_util.h>
#include <rz_bin_dwarf.h>
#include "macro.inc"
#include "macro.h"
typedef struct {
ut64 unit_offset;
@@ -63,58 +63,10 @@ RZ_IPI void Range_free(RzBinDwarfRange *self);
RZ_IPI void DebugRngLists_free(RzBinDwarfRngLists *self);
/// value
RZ_IPI bool ValueType_from_encoding(DW_ATE encoding, ut64 byte_size, RzBinDwarfValueType *out_type);
RZ_IPI bool ValueType_from_entry(RzBinDwarfDie *entry, RzBinDwarfValueType *out);
RZ_IPI bool Value_parse_into(
RzBinDwarfValue *value, RzBinDwarfValueType value_type, RzBinEndianReader *reader);
RZ_IPI RzBinDwarfValueType Value_type(RzBinDwarfValue *ptr);
RZ_IPI bool Value_to_u64(RzBinDwarfValue *self, ut64 addr_mask, ut64 *result);
RZ_IPI bool Value_from_u64(RzBinDwarfValueType value_type, ut64 value, RzBinDwarfValue *result);
RZ_IPI bool Value_from_f32(RzBinDwarfValueType value_type, float value, RzBinDwarfValue *result);
RZ_IPI bool Value_from_f64(RzBinDwarfValueType value_type, double value, RzBinDwarfValue *result);
RZ_IPI bool Value_convert(RzBinDwarfValue *self, RzBinDwarfValueType typ, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_reinterpret(RzBinDwarfValue *self, RzBinDwarfValueType value_type, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_abs(RzBinDwarfValue *self, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_neg(RzBinDwarfValue *self, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_add(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_sub(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_mul(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_div(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_rem(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_not(RzBinDwarfValue *self, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_and(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_or(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_xor(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_shift_length(RzBinDwarfValue *self, ut64 *result);
RZ_IPI bool Value_shl(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_shr(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_shra(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_eq(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_ge(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_gt(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_le(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_lt(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_ne(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI void Value_fini(RzBinDwarfValue *self);
RZ_IPI void Value_free(RzBinDwarfValue *self);
RZ_IPI RzBinDwarfValue *Value_clone(RzBinDwarfValue *self);
RZ_IPI bool Value_clone_into(RzBinDwarfValue *self, RzBinDwarfValue *val);
RZ_IPI void Value_dump(
const RzBinDwarfValue *self,
RzStrBuf *sb,
const RzBinDWARFDumpOption *opt);
/// op
#include "value.h"
#include "op.h"
RZ_IPI void rz_bin_dwarf_evaluation_cpy(RzBinDwarfEvaluation *dst, RzBinDwarfEvaluation *src);
RZ_IPI void RzBinDwarfEvaluationResult_cpy(RzBinDwarfEvaluationResult *dst, RzBinDwarfEvaluationResult *src);
#endif
+30 -1
View File
@@ -422,10 +422,39 @@ RZ_API RZ_OWN RzBinDwarfLocation *rz_bin_dwarf_location_clone(RZ_BORROW RZ_NONNU
RzBinDwarfLocation *loc = RZ_NEWCOPY(RzBinDwarfLocation, self);
switch (loc->kind) {
case RzBinDwarfLocationKind_COMPOSITE:
loc->composite = rz_vector_clone(self->composite);
loc->composite = rz_vector_clonef(self->composite, (RzVectorItemCpyFunc)RzBinDwarfPiece_cpy);
break;
default:
break;
}
return loc;
}
RZ_IPI void Location_cpy(Location *dst, Location *src) {
rz_return_if_fail(dst && src);
memcpy(dst, src, sizeof(Location));
switch (src->kind) {
case RzBinDwarfLocationKind_BYTES:
RzBinDwarfBlock_cpy(&dst->bytes, &src->bytes);
break;
case RzBinDwarfLocationKind_EVALUATION_WAITING:
rz_bin_dwarf_evaluation_cpy(dst->eval_waiting.eval, src->eval_waiting.eval);
RzBinDwarfEvaluationResult_cpy(dst->eval_waiting.result, src->eval_waiting.result);
break;
case RzBinDwarfLocationKind_COMPOSITE:
rz_vector_clone_intof(dst->composite, src->composite, (RzVectorItemCpyFunc)RzBinDwarfPiece_cpy);
break;
case RzBinDwarfLocationKind_LOCLIST:
rz_warn_if_reached();
break;
case RzBinDwarfLocationKind_EMPTY: break;
case RzBinDwarfLocationKind_DECODE_ERROR: break;
case RzBinDwarfLocationKind_REGISTER: break;
case RzBinDwarfLocationKind_REGISTER_OFFSET: break;
case RzBinDwarfLocationKind_ADDRESS: break;
case RzBinDwarfLocationKind_VALUE: break;
case RzBinDwarfLocationKind_IMPLICIT_POINTER: break;
case RzBinDwarfLocationKind_CFA_OFFSET: break;
case RzBinDwarfLocationKind_FB_OFFSET: break;
}
}
+11
View File
@@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: 2023 billow <[email protected]>
// SPDX-License-Identifier: LGPL-3.0-only
#ifndef LOCLISTS_H
#define LOCLISTS_H
#include "op.h"
RZ_IPI void Location_cpy(Location *dst, Location *src);
#endif // LOCLISTS_H
@@ -7,26 +7,20 @@
#define MEM_CPY(T, dst, src) rz_mem_copy((dst), sizeof(T), (src), sizeof(T))
#define OK_OR(x, E) \
do { \
if (!(x)) { \
E; \
} \
} while (0)
if (!(x)) { \
E; \
}
#define OK_OR_ERR(x, E) \
do { \
if (!(x)) { \
E; \
goto err; \
} \
} while (0)
if (!(x)) { \
E; \
goto err; \
}
#define AND_DO(x, E) \
do { \
if ((x)) { \
E; \
} \
} while (0)
if ((x)) { \
E; \
}
#define RET_FALSE_IF_FAIL(x) OK_OR(x, return false)
#define RET_NULL_IF_FAIL(x) OK_OR(x, return NULL)
@@ -63,3 +57,8 @@
static void Ht##V##_##T##_free(Ht##V##Kv *kv) { \
f(kv->value); \
}
#define RZ_VECTOR_FINI_T(T, f) \
static void RzVector_##T##_fini(void *v, void *u) { \
f(v); \
}
+129 -71
View File
@@ -32,8 +32,6 @@ static bool RzBinDwarfLocation_move(RzBinDwarfLocation *self, RzBinDwarfLocation
case RzBinDwarfLocationKind_LOCLIST:
self->loclist = NULL;
break;
default:
return false;
}
return true;
}
@@ -544,7 +542,7 @@ static bool Evaluation_pop(RzBinDwarfEvaluation *self, RzBinDwarfValue *value) {
}
static bool Evaluation_push(RzBinDwarfEvaluation *self, RzBinDwarfValue *value) {
bool status = rz_vector_push(&self->stack, value) != NULL;
const bool status = rz_vector_push(&self->stack, value) != NULL;
if (!status) {
Value_fini(value);
}
@@ -611,8 +609,8 @@ static RzBinDwarfValueType ValueType_from_name(const char *name, ut8 byte_size)
}
static RzBinDwarfValueType ValueType_from_die(
RzBinDwarfEvaluation *eval, const RzBinDWARF *dw, UnitOffset offset) {
RzBinDwarfDie *die = ht_up_find(dw->info->die_by_offset, eval->unit->offset + offset, NULL);
const RzBinDwarfEvaluation *eval, const RzBinDWARF *dw, UnitOffset offset) {
const RzBinDwarfDie *die = ht_up_find(dw->info->die_by_offset, eval->unit->offset + offset, NULL);
if (!die) {
return RzBinDwarfValueType_GENERIC;
}
@@ -659,24 +657,13 @@ static RzBinDwarfValueType ValueType_from_die(
return value_type;
}
static void RzBinDwarfPiece_fini(RzBinDwarfPiece *x) {
if (!x) {
return;
}
rz_bin_dwarf_location_free(x->location);
}
static inline ut64 addrmask_from_size(uint8_t size) {
static ut64 addrmask_from_size(uint8_t size) {
return size == 0 ? 0xffffffffffffffffULL
: (size == 8 ? 0xffffffffffffffffULL
: (1ULL << (size * 8)) - 1);
}
static void vec_Value_fini(void *v, void *u) {
Value_fini(v);
}
static void RzBinDwarfExprStackItem_fini(RzBinDwarfExprStackItem *self) {
static void RzBinDwarfExprStackItem_fini(RzBinDwarfExprStackItem const *self) {
if (!self) {
return;
}
@@ -684,8 +671,29 @@ static void RzBinDwarfExprStackItem_fini(RzBinDwarfExprStackItem *self) {
RzBinEndianReader_free(self->pc);
}
static void vec_RzBinDwarfExprStackItem_fini(void *v, void *u) {
RzBinDwarfExprStackItem_fini(v);
static void RzBinDwarfExprStackItem_cpy(RzBinDwarfExprStackItem *dst, RzBinDwarfExprStackItem *src) {
rz_return_if_fail(dst && src);
memcpy(dst, src, sizeof(RzBinDwarfExprStackItem));
dst->pc = RzBinEndianReader_clone(src->pc);
dst->bytecode = RzBinEndianReader_clone(src->bytecode);
}
RZ_IPI void RzBinDwarfPiece_fini(RzBinDwarfPiece *x) {
if (!x) {
return;
}
rz_bin_dwarf_location_free(x->location);
}
RZ_VECTOR_FINI_T(Value, Value_fini);
RZ_VECTOR_FINI_T(RzBinDwarfExprStackItem, RzBinDwarfExprStackItem_fini);
RZ_VECTOR_FINI_T(RzBinDwarfPiece, RzBinDwarfPiece_fini);
RZ_IPI void RzBinDwarfPiece_cpy(RzBinDwarfPiece *dst, RzBinDwarfPiece *src) {
rz_return_if_fail(dst && src);
memcpy(dst, src, sizeof(RzBinDwarfPiece));
dst->location = RZ_NEW0(Location);
Location_cpy(dst->location, src->location);
}
RZ_API RZ_OWN RzBinDwarfEvaluation *rz_bin_dwarf_evaluation_new(
@@ -697,7 +705,7 @@ RZ_API RZ_OWN RzBinDwarfEvaluation *rz_bin_dwarf_evaluation_new(
RzBinDwarfEvaluation *self = RZ_NEW0(RzBinDwarfEvaluation);
RET_NULL_IF_FAIL(self);
const RzBinDwarfEncoding *encoding = &unit->hdr.encoding;
ut64 addr_mask = addrmask_from_size(encoding->address_size);
const ut64 addr_mask = addrmask_from_size(encoding->address_size);
self->addr_mask = addr_mask;
self->bytecode = byte_code;
self->encoding = encoding;
@@ -705,9 +713,9 @@ RZ_API RZ_OWN RzBinDwarfEvaluation *rz_bin_dwarf_evaluation_new(
self->dw = dw;
self->unit = unit;
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);
rz_vector_init(&self->stack, sizeof(RzBinDwarfValue), RzVector_Value_fini, NULL);
rz_vector_init(&self->expression_stack, sizeof(RzBinDwarfExprStackItem), RzVector_RzBinDwarfExprStackItem_fini, NULL);
rz_vector_init(&self->result, sizeof(RzBinDwarfPiece), RzVector_RzBinDwarfPiece_fini, NULL);
return self;
}
@@ -736,6 +744,19 @@ RZ_API void rz_bin_dwarf_evaluation_free(RZ_OWN RzBinDwarfEvaluation *self) {
free(self);
}
RZ_IPI void rz_bin_dwarf_evaluation_cpy(RzBinDwarfEvaluation *dst, RzBinDwarfEvaluation *src) {
rz_return_if_fail(dst && src);
memcpy(dst, src, sizeof(RzBinDwarfEvaluation));
dst->pc = RzBinEndianReader_clone(src->pc);
dst->bytecode = RzBinEndianReader_clone(src->bytecode);
rz_vector_clone_intof(&dst->stack, &src->stack,
(RzVectorItemCpyFunc)Value_cpy);
rz_vector_clone_intof(&dst->expression_stack, &src->expression_stack,
(RzVectorItemCpyFunc)RzBinDwarfExprStackItem_cpy);
rz_vector_clone_intof(&dst->result, &src->result,
(RzVectorItemCpyFunc)RzBinDwarfPiece_cpy);
}
RZ_IPI void RzBinDwarfEvaluationResult_fini(RzBinDwarfEvaluationResult *self) {
if (self->kind == EvaluationResult_REQUIRES_ENTRY_VALUE) {
RzBinDwarfBlock_fini(&self->requires_entry_value.expression);
@@ -750,6 +771,15 @@ RZ_API void RzBinDwarfEvaluationResult_free(RZ_OWN RzBinDwarfEvaluationResult *s
free(self);
}
RZ_IPI void RzBinDwarfEvaluationResult_cpy(RzBinDwarfEvaluationResult *dst, RzBinDwarfEvaluationResult *src) {
rz_return_if_fail(dst && src);
memcpy(dst, src, sizeof(RzBinDwarfEvaluationResult));
if (src->kind == EvaluationResult_REQUIRES_ENTRY_VALUE) {
RzBinDwarfBlock_cpy(&dst->requires_entry_value.expression,
&src->requires_entry_value.expression);
}
}
#define CHECK_DEFER \
do { \
if (rz_vector_len(&self->stack) >= 1) { \
@@ -851,12 +881,15 @@ static bool Evaluation_evaluate_one_operation(
break;
}
Value *value = rz_vector_index_ptr(&self->stack, len - operation.pick.index - 1);
if (!value) {
goto err;
}
Value clone = { 0 };
OK_OR_ERR(value &&
Value_clone_into(value, &clone) &&
Evaluation_push(self, &clone),
Value_fini(&clone);
goto err);
if (!Value_clone_into(value, &clone) &&
Evaluation_push(self, &clone)) {
Value_fini(&clone);
goto err;
}
break;
}
case OPERATION_KIND_SWAP: {
@@ -985,10 +1018,13 @@ static bool Evaluation_evaluate_one_operation(
ERR_IF_FAIL(v.location);
v.location->kind = RzBinDwarfLocationKind_FB_OFFSET;
v.location->offset = rz_bin_dwarf_attr_sdata(fb_attr);
OK_OR_ERR(Evaluation_push(self, &v),
rz_bin_dwarf_location_free(v.location));
if (!Evaluation_push(self, &v)) {
rz_bin_dwarf_location_free(v.location);
goto err;
}
break;
} else if (fb_attr->value.kind == RzBinDwarfAttr_Block) {
}
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->fn_die);
if (!loc) {
RzBinDWARFDumpOption opt = {
@@ -996,8 +1032,9 @@ static bool Evaluation_evaluate_one_operation(
.loclist_sep = ",\t",
.dwarf_register_mapping = NULL,
};
const RzBinDwarfEncoding *enc = self->unit ? &self->unit->hdr.encoding : NULL;
char *expr_str = rz_bin_dwarf_expression_to_string(
&self->unit->hdr.encoding, rz_bin_dwarf_attr_block(fb_attr), &opt);
enc, rz_bin_dwarf_attr_block(fb_attr), &opt);
RZ_LOG_ERROR("Failed eval frame base: [%s]\n", rz_str_get_null(expr_str));
free(expr_str);
goto err;
@@ -1279,9 +1316,11 @@ RZ_API bool rz_bin_dwarf_evaluation_evaluate(RZ_BORROW RZ_NONNULL RzBinDwarfEval
.has_size_in_bits = false,
.has_bit_offset = false,
};
OK_OR_ERR(RzBinDwarfLocation_move(&op_result.complete, piece.location) &&
rz_vector_push(&self->result, &piece),
rz_bin_dwarf_location_free(location));
if (!(RzBinDwarfLocation_move(&op_result.complete, piece.location) &&
rz_vector_push(&self->result, &piece))) {
rz_bin_dwarf_location_free(location);
goto err;
}
} else {
Operation operation = { 0 };
ERR_IF_FAIL(Operation_parse(&operation, self->pc, self->encoding));
@@ -1297,9 +1336,11 @@ RZ_API bool rz_bin_dwarf_evaluation_evaluate(RZ_BORROW RZ_NONNULL RzBinDwarfEval
.bit_offset = operation.piece.bit_offset,
};
ERR_IF_FAIL(piece.location);
OK_OR_ERR(RzBinDwarfLocation_move(&op_result.complete, piece.location) &&
rz_vector_push(&self->result, &piece),
rz_bin_dwarf_location_free(piece.location));
if (!(RzBinDwarfLocation_move(&op_result.complete, piece.location) &&
rz_vector_push(&self->result, &piece))) {
rz_bin_dwarf_location_free(piece.location);
goto err;
}
}
break;
}
@@ -1317,19 +1358,21 @@ RZ_API bool rz_bin_dwarf_evaluation_evaluate(RZ_BORROW RZ_NONNULL RzBinDwarfEval
switch (entry.type) {
case RzBinDwarfValueType_LOCATION:
status = status && entry.location;
AND_DO(status,
if (status) {
location = entry.location;
entry.location = NULL);
entry.location = NULL;
}
break;
default: {
ut64 addr = 0;
AND_DO(status,
if (status) {
location = RZ_NEW0(RzBinDwarfLocation);
status = location &&
Value_to_u64(&entry, self->addr_mask, &addr);
AND_DO(status,
ut64 addr = 0;
status = location && Value_to_u64(&entry, self->addr_mask, &addr);
if (status) {
location->kind = RzBinDwarfLocationKind_ADDRESS;
location->address = addr));
location->address = addr;
}
}
break;
}
}
@@ -1342,9 +1385,10 @@ RZ_API bool rz_bin_dwarf_evaluation_evaluate(RZ_BORROW RZ_NONNULL RzBinDwarfEval
};
status = rz_vector_push(&self->result, &piece);
}
OK_OR(status,
if (!status) {
rz_bin_dwarf_location_free(location);
return false);
return false;
}
}
self->state.kind = EVALUATION_STATE_COMPLETE;
@@ -1362,7 +1406,9 @@ RZ_API RZ_BORROW RzVector /*<RzBinDwarfPiece>*/ *rz_bin_dwarf_evaluation_result(
static bool RzBinDwarfEvaluationResult_to_loc(
RzBinDwarfEvaluation *eval, RzBinDwarfEvaluationResult *eval_result, Location *loc) {
rz_warn_if_fail(loc);
if (!loc) {
return false;
}
if (eval->state.kind != EVALUATION_STATE_COMPLETE || eval_result->kind != EvaluationResult_COMPLETE) {
loc->kind = RzBinDwarfLocationKind_EVALUATION_WAITING;
loc->eval_waiting.eval = eval;
@@ -1376,18 +1422,12 @@ static bool RzBinDwarfEvaluationResult_to_loc(
goto beach;
}
if (rz_vector_len(pieces) == 1) {
RzBinDwarfPiece *piece = rz_vector_index_ptr(pieces, 0);
result = piece && RzBinDwarfLocation_move(piece->location, loc);
goto beach;
Location_cpy(loc, ((RzBinDwarfPiece *)rz_vector_index_ptr(pieces, 0))->location);
result = true;
} else {
loc->kind = RzBinDwarfLocationKind_COMPOSITE;
loc->composite = rz_vector_clone(pieces);
RzBinDwarfPiece *piece = NULL;
rz_vector_foreach(pieces, piece) {
piece->location = NULL;
}
loc->composite = rz_vector_clonef(pieces, (RzVectorItemCpyFunc)RzBinDwarfPiece_cpy);
result = true;
goto beach;
}
beach:
rz_bin_dwarf_evaluation_free(eval);
@@ -1415,7 +1455,9 @@ RZ_API RZ_OWN RzBinDwarfLocation *rz_bin_dwarf_location_from_block(
RzBinDwarfEvaluation *eval = NULL;
Location *loc = RZ_NEW0(Location);
OK_OR(loc, return NULL);
if (!loc) {
return NULL;
}
loc->encoding = unit->hdr.encoding;
if (rz_bin_dwarf_block_empty(block)) {
@@ -1427,8 +1469,10 @@ RZ_API RZ_OWN RzBinDwarfLocation *rz_bin_dwarf_location_from_block(
RET_NULL_IF_FAIL(result);
eval = rz_bin_dwarf_evaluation_new_from_block(block, dw, unit, die);
ERR_IF_FAIL(eval);
ERR_IF_FAIL(rz_bin_dwarf_evaluation_evaluate(eval, result) &&
RzBinDwarfEvaluationResult_to_loc(eval, result, loc));
if (!(rz_bin_dwarf_evaluation_evaluate(eval, result) &&
RzBinDwarfEvaluationResult_to_loc(eval, result, loc))) {
goto err;
};
}
return loc;
err:
@@ -1441,7 +1485,7 @@ err:
return loc;
}
static void Operation_dump(Operation *op, RzStrBuf *buf) {
static void Operation_dump(Operation const *op, RzStrBuf *buf) {
rz_strbuf_append(buf, rz_str_get_null(rz_bin_dwarf_op(op->opcode)));
switch (op->kind) {
case OPERATION_KIND_DROP:
@@ -1593,7 +1637,7 @@ RZ_API void rz_bin_dwarf_expression_dump(
Operation *op = NULL;
ut32 i;
ut32 end = rz_vector_len(exprs) - 1;
const ut32 end = rz_vector_len(exprs) - 1;
rz_vector_enumerate(exprs, op, i) {
rz_strbuf_append(sb, rz_str_get(opt->expr_indent));
Operation_dump(op, sb);
@@ -1636,10 +1680,10 @@ RZ_API void rz_bin_dwarf_loclist_dump(
}
ut32 i = 0;
ut32 end = rz_pvector_len(&loclist->entries) - 1;
const ut32 end = rz_pvector_len(&loclist->entries) - 1;
void **it = NULL;
rz_pvector_foreach (&loclist->entries, it) {
RzBinDwarfLocListEntry *entry = *it;
const RzBinDwarfLocListEntry *entry = *it;
rz_strbuf_appendf(sb, "%s(0x%" PFMT64x ", %" PFMT64d "):",
rz_str_get(opt->loclist_indent), entry->range->begin, entry->range->end - entry->range->begin);
@@ -1661,7 +1705,7 @@ RZ_API void rz_bin_dwarf_loclist_dump(
}
RZ_API void rz_bin_dwarf_location_composite_dump(
RZ_BORROW RZ_NONNULL RzVector /*<RzBinDwarfPiece>*/ *composite,
RZ_BORROW RZ_NONNULL const RzVector /*<RzBinDwarfPiece>*/ *composite,
RZ_BORROW RZ_NONNULL RzStrBuf *sb,
RZ_BORROW RZ_NONNULL const RzBinDWARFDumpOption *opt) {
rz_return_if_fail(opt && composite && sb);
@@ -1671,13 +1715,17 @@ RZ_API void rz_bin_dwarf_location_composite_dump(
}
ut32 i = 0;
ut32 end = rz_vector_len(composite) - 1;
const ut32 end = rz_vector_len(composite) - 1;
RzBinDwarfPiece *piece = NULL;
rz_vector_enumerate(composite, piece, i) {
rz_strbuf_append(sb, rz_str_get(opt->composite_indent));
rz_strbuf_appendf(sb, "(.%" PFMT64u ", %" PFMT64u "): ", piece->bit_offset, piece->size_in_bits);
rz_bin_dwarf_location_dump(piece->location, sb, opt);
if (piece->location) {
rz_bin_dwarf_location_dump(piece->location, sb, opt);
} else {
rz_strbuf_appendf(sb, "<err:null-location>");
}
if (i < end) {
rz_strbuf_append(sb, rz_str_get(opt->composite_sep));
}
@@ -1701,15 +1749,25 @@ RZ_API void rz_bin_dwarf_location_dump(
rz_strbuf_append(sb, "<decoding error>");
break;
case RzBinDwarfLocationKind_REGISTER:
rz_strbuf_append(sb, opt->dwarf_register_mapping(loc->register_number));
if (opt->dwarf_register_mapping) {
rz_strbuf_append(sb, opt->dwarf_register_mapping(loc->register_number));
} else {
rz_strbuf_appendf(sb, "reg%" PFMT64d, loc->register_number);
}
break;
case RzBinDwarfLocationKind_REGISTER_OFFSET:
rz_strbuf_appendf(sb, "%s%+" PFMT64d, opt->dwarf_register_mapping(loc->register_number), loc->offset);
if (opt->dwarf_register_mapping) {
rz_strbuf_append(sb, opt->dwarf_register_mapping(loc->register_number));
} else {
rz_strbuf_appendf(sb, "reg%" PFMT64d, loc->register_number);
}
rz_strbuf_appendf(sb, "%+" PFMT64d, loc->offset);
break;
case RzBinDwarfLocationKind_ADDRESS:
rz_strbuf_appendf(sb, "address 0x%" PFMT64x, loc->address);
break;
case RzBinDwarfLocationKind_VALUE:
rz_strbuf_append(sb, "stack");
Value_dump(&loc->value, sb, opt);
break;
case RzBinDwarfLocationKind_BYTES:
+6
View File
@@ -4,6 +4,8 @@
#ifndef RIZIN_OP_H
#define RIZIN_OP_H
#include "loclists.h"
typedef enum {
OPERATION_KIND_DEREF,
OPERATION_KIND_DROP,
@@ -234,4 +236,8 @@ typedef struct {
RZ_IPI void RzBinDwarfEvaluationResult_fini(RzBinDwarfEvaluationResult *self);
RZ_IPI void RzBinDwarfPiece_fini(RzBinDwarfPiece *x);
RZ_IPI void RzBinDwarfPiece_cpy(RzBinDwarfPiece *dst, RzBinDwarfPiece *src);
#endif // RIZIN_OP_H
+12 -10
View File
@@ -1060,40 +1060,42 @@ RZ_IPI void Value_dump(
RzStrBuf *sb,
const RzBinDWARFDumpOption *opt) {
rz_warn_if_fail(self && sb);
if (self->type <= 0 || self->type >= RZ_ARRAY_SIZE(Value_strings)) {
if (self->type < 0 || self->type >= RZ_ARRAY_SIZE(Value_strings)) {
rz_strbuf_append(sb, "<err:invalid value type>");
return;
}
rz_strbuf_append(sb, Value_strings[self->type]);
rz_strbuf_append(sb, rz_str_get(opt->loclist_sep));
switch (self->type) {
case RzBinDwarfValueType_GENERIC:
rz_strbuf_appendf(sb, "%" PFMT64x, self->generic);
rz_strbuf_appendf(sb, "+%" PFMT64x, self->generic);
break;
case RzBinDwarfValueType_I8:
case RzBinDwarfValueType_I16:
case RzBinDwarfValueType_I32:
rz_strbuf_appendf(sb, "%" PFMT32d, self->i32);
rz_strbuf_appendf(sb, "%+" PFMT32d, self->i32);
break;
case RzBinDwarfValueType_U8:
case RzBinDwarfValueType_U16:
case RzBinDwarfValueType_U32:
rz_strbuf_appendf(sb, "%" PFMT32u, self->u32);
rz_strbuf_appendf(sb, "+%" PFMT32u, self->u32);
break;
case RzBinDwarfValueType_I64:
rz_strbuf_appendf(sb, "%" PFMT64d, self->i64);
rz_strbuf_appendf(sb, "%+" PFMT64d, self->i64);
break;
case RzBinDwarfValueType_U64:
rz_strbuf_appendf(sb, "%" PFMT64u, self->u64);
rz_strbuf_appendf(sb, "+%" PFMT64u, self->u64);
break;
case RzBinDwarfValueType_F32:
case RzBinDwarfValueType_F64:
rz_strbuf_appendf(sb, "%f", self->f64);
rz_strbuf_appendf(sb, "%+f", self->f64);
break;
case RzBinDwarfValueType_LOCATION:
rz_bin_dwarf_location_dump(self->location, sb, opt);
break;
default:
rz_strbuf_append(sb, "unimplemented");
rz_strbuf_append(sb, "<unimplemented>");
break;
}
if (opt->value_detail) {
rz_strbuf_appendf(sb, " : %s", Value_strings[self->type]);
}
}
+59
View File
@@ -0,0 +1,59 @@
// SPDX-FileCopyrightText: 2023 billow <[email protected]>
// SPDX-License-Identifier: LGPL-3.0-only
#ifndef VALUE_H
#define VALUE_H
RZ_IPI bool ValueType_from_encoding(DW_ATE encoding, ut64 byte_size, RzBinDwarfValueType *out_type);
RZ_IPI bool ValueType_from_entry(RzBinDwarfDie *entry, RzBinDwarfValueType *out);
RZ_IPI bool Value_parse_into(
RzBinDwarfValue *value, RzBinDwarfValueType value_type, RzBinEndianReader *reader);
RZ_IPI RzBinDwarfValueType Value_type(RzBinDwarfValue *ptr);
RZ_IPI bool Value_to_u64(RzBinDwarfValue *self, ut64 addr_mask, ut64 *result);
RZ_IPI bool Value_from_u64(RzBinDwarfValueType value_type, ut64 value, RzBinDwarfValue *result);
RZ_IPI bool Value_from_f32(RzBinDwarfValueType value_type, float value, RzBinDwarfValue *result);
RZ_IPI bool Value_from_f64(RzBinDwarfValueType value_type, double value, RzBinDwarfValue *result);
RZ_IPI bool Value_convert(RzBinDwarfValue *self, RzBinDwarfValueType typ, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_reinterpret(RzBinDwarfValue *self, RzBinDwarfValueType value_type, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_abs(RzBinDwarfValue *self, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_neg(RzBinDwarfValue *self, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_add(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_sub(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_mul(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_div(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_rem(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_not(RzBinDwarfValue *self, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_and(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_or(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_xor(RzBinDwarfValue *lhs, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_shift_length(RzBinDwarfValue *self, ut64 *result);
RZ_IPI bool Value_shl(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_shr(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_shra(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_eq(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_ge(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_gt(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_le(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_lt(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI bool Value_ne(RzBinDwarfValue *self, RzBinDwarfValue *rhs, ut64 addr_mask, RzBinDwarfValue *result);
RZ_IPI void Value_fini(RzBinDwarfValue *self);
RZ_IPI void Value_free(RzBinDwarfValue *self);
RZ_IPI RzBinDwarfValue *Value_clone(RzBinDwarfValue *self);
RZ_IPI bool Value_clone_into(RzBinDwarfValue *self, RzBinDwarfValue *val);
static inline void Value_cpy(RzBinDwarfValue *dst, RzBinDwarfValue *src) {
Value_clone_into(src, dst);
}
RZ_IPI void Value_dump(
const RzBinDwarfValue *self,
RzStrBuf *sb,
const RzBinDWARFDumpOption *opt);
#endif // VALUE_H
+1 -1
View File
@@ -453,7 +453,7 @@ typedef struct {
HtUP /*<ut64, RzCallable *>*/ *callable_by_offset; ///< Store all callables parsed from DWARF by DIE offset
HtUP /*<ut64, RzType *>*/ *type_by_offset; ///< Store all RzType parsed from DWARF by DIE offset
HtUP /*<ut64, RzBaseType *>*/ *base_type_by_offset; ///< Store all RzBaseType parsed from DWARF by DIE offset
HtPP /*<const char*, RzPVector<const RzBaseType *>>*/ *base_type_by_name; ///< Store all RzBaseType parsed from DWARF by DIE offset
HtPP /*<const char*, RzPVector<const RzBaseType *>>*/ *base_types_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;
+5 -4
View File
@@ -1408,7 +1408,7 @@ typedef struct {
ut64 offset;
bool has_location;
RzPVector /*<RzBinDwarfRawLocListEntry *>*/ raw_entries;
RzPVector /*<RzBinDwarfLocationListEntry *>*/ entries;
RzPVector /*<RzBinDwarfLocListEntry *>*/ entries;
} RzBinDwarfLocList;
typedef struct {
@@ -1739,6 +1739,7 @@ typedef struct {
const char *composite_sep;
const char *composite_indent;
const bool compose_breaklines;
const bool value_detail;
} RzBinDWARFDumpOption;
RZ_API void rz_bin_dwarf_expression_dump(
@@ -1755,7 +1756,7 @@ RZ_API void rz_bin_dwarf_loclist_dump(
RZ_BORROW RZ_NONNULL RzStrBuf *sb,
RZ_BORROW RZ_NONNULL const RzBinDWARFDumpOption *opt);
RZ_API void rz_bin_dwarf_location_composite_dump(
RZ_BORROW RZ_NONNULL RzVector /*<RzBinDwarfPiece>*/ *composite,
RZ_BORROW RZ_NONNULL const RzVector /*<RzBinDwarfPiece>*/ *composite,
RZ_BORROW RZ_NONNULL RzStrBuf *sb,
RZ_BORROW RZ_NONNULL const RzBinDWARFDumpOption *opt);
RZ_API void rz_bin_dwarf_location_dump(
@@ -1819,7 +1820,7 @@ RZ_API RZ_OWN RzBinDwarfAddr *rz_bin_dwarf_addr_from_file(RZ_BORROW RZ_NONNULL R
*/
static inline char *rz_bin_dwarf_attr_string(
const RzBinDwarfAttr *attr,
RzBinDWARF *dw,
const RzBinDWARF *dw,
ut64 str_offsets_base) {
rz_return_val_if_fail(attr, NULL);
const RzBinDwarfAttrValue *v = &attr->value;
@@ -1837,7 +1838,7 @@ static inline char *rz_bin_dwarf_attr_string(
static inline ut64 rz_bin_dwarf_attr_addr(
const RzBinDwarfAttr *attr,
RzBinDWARF *dw,
const RzBinDWARF *dw,
ut64 addr_size, ut64 base) {
rz_return_val_if_fail(attr, UT64_MAX);
+19
View File
@@ -238,6 +238,25 @@ static bool test_dwarf_function_parsing_rust(void) {
check_fn(0x5270, "bubble_sort<i32>", "void bubble_sort<i32>(struct &mut [i32] values)");
check_fn(0x8730, "lang_start_internal", "isize lang_start_internal(struct &Fn<()> main, isize argc, u8 **argv)");
RzBinDwarfCompUnit *cu = ht_up_find(dw->info->unit_by_offset, 0x4151, NULL);
mu_assert_notnull(cu, "Couldn't get compunit");
RzBinDwarfLocList *loclist = rz_bin_dwarf_loclists_get(dw->loclists, dw->addr, cu, 0xd973);
mu_assert_notnull(loclist, "Couldn't get loclist");
RzBinDwarfLocListEntry *entry = rz_pvector_at(&loclist->entries, 0);
mu_assert_notnull(entry, "Couldn't get entry");
mu_assert_notnull(entry->range, "Couldn't get entry range");
mu_assert_notnull(entry->expression, "Couldn't get entry expression");
mu_assert_eq(entry->range->begin, 0x84e1, "Err entry begin");
mu_assert_eq(entry->range->end, 0x84fc, "Err entry end");
RzBinDwarfLocation *loc = rz_bin_dwarf_location_from_block(entry->expression, dw, cu, NULL);
mu_assert_notnull(loc, "Couldn't get location");
RzBinDWARFDumpOption dump_option = {
.composite_sep = ", "
};
char *locstr = rz_bin_dwarf_location_to_string(loc, &dump_option);
mu_assert_streq_free(locstr, "composite: [(.0, 64): stack+18, (.0, 64): stack+8]", "Error location string");
rz_bin_dwarf_location_free(loc);
rz_bin_dwarf_free(dw);
rz_core_free(core);
mu_end;