mirror of
https://github.com/rizinorg/rizin.git
synced 2026-10-12 02:21:57 +00:00
Fix DWARF FbReg Operation eval and fuzz test (#3825)
* Fix FbReg Operation eval * Fix RzBinDwarfEvaluationResult_to_loc and debug_line directories parse
This commit is contained in:
@@ -1250,7 +1250,7 @@ static void function_apply_specification(Context *ctx, const RzBinDwarfDie *die,
|
||||
}
|
||||
|
||||
static void RzBinDwarfBlock_log(Context *ctx, const RzBinDwarfBlock *block, ut64 offset, const RzBinDwarfRange *range) {
|
||||
char *expr_str = rz_bin_dwarf_expression_to_string(&ctx->dw->encoding, block, ctx->dw->loc->big_endian);
|
||||
char *expr_str = rz_bin_dwarf_expression_to_string(&ctx->dw->encoding, block, ctx->dw->big_endian);
|
||||
if (RZ_STR_ISNOTEMPTY(expr_str)) {
|
||||
if (!range) {
|
||||
RZ_LOG_VERBOSE("Location parse failed: 0x%" PFMT64x " [%s]\n", offset, expr_str);
|
||||
|
||||
@@ -70,9 +70,13 @@ RZ_IPI char *buf_get_string(RzBuffer *buffer) {
|
||||
RET_NULL_IF_FAIL(x);
|
||||
ut64 len = strlen(x) + 1;
|
||||
rz_buf_seek(buffer, (st64)len, SEEK_CUR);
|
||||
if (len <= 1) {
|
||||
free(x);
|
||||
return NULL;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
RZ_IPI char *buf_get_string_not_empty(RzBuffer *buffer) {
|
||||
char *str = buf_get_string(buffer);
|
||||
if (RZ_STR_ISEMPTY(str)) {
|
||||
RZ_FREE(str);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@ RZ_API RZ_OWN RzBinDWARF *rz_bin_dwarf_from_file(
|
||||
RET_NULL_IF_FAIL(dw);
|
||||
dw->addr = DebugAddr_from_file(bf);
|
||||
dw->str = RzBinDwarfDebugStr_from_file(bf);
|
||||
dw->big_endian = bf_bigendian(bf);
|
||||
|
||||
if (opt->flags & RZ_BIN_DWARF_ABBREVS) {
|
||||
dw->abbrev = rz_bin_dwarf_abbrev_from_file(bf);
|
||||
|
||||
@@ -44,6 +44,7 @@ RZ_IPI bool buf_read_initial_length(RzBuffer *buffer, RZ_OUT bool *is_64bit, ut6
|
||||
RZ_IPI bool buf_read_offset(RzBuffer *buffer, ut64 *out, bool is_64bit, bool big_endian);
|
||||
RZ_IPI bool buf_read_block(RzBuffer *buffer, RzBinDwarfBlock *block);
|
||||
RZ_IPI char *buf_get_string(RzBuffer *buffer);
|
||||
RZ_IPI char *buf_get_string_not_empty(RzBuffer *buffer);
|
||||
|
||||
RZ_IPI bool RzBinDwarfAttr_parse(RzBuffer *buffer, RzBinDwarfAttr *value, DwAttrOption *opt);
|
||||
RZ_IPI void RzBinDwarfAttr_fini(RzBinDwarfAttr *val);
|
||||
|
||||
@@ -136,7 +136,7 @@ err:
|
||||
}
|
||||
|
||||
static bool RzBinDwarfFileEntry_parse_v4(RzBuffer *buffer, RzBinDwarfFileEntry *entry) {
|
||||
entry->path_name = buf_get_string(buffer);
|
||||
entry->path_name = buf_get_string_not_empty(buffer);
|
||||
ERR_IF_FAIL(entry->path_name);
|
||||
ULE128_OR_GOTO(entry->directory_index, err);
|
||||
ULE128_OR_GOTO(entry->timestamp, err);
|
||||
@@ -177,7 +177,7 @@ static bool RzBinDwarfLineHeader_parse_v5(RzBuffer *buffer, RzBinDwarfLineHeader
|
||||
|
||||
static bool RzBinDwarfLineHeader_parse_v4(RzBuffer *buffer, RzBinDwarfLineHeader *hdr, bool big_endian) {
|
||||
while (true) {
|
||||
char *str = buf_get_string(buffer);
|
||||
char *str = buf_get_string_not_empty(buffer);
|
||||
if (!str) {
|
||||
break;
|
||||
}
|
||||
|
||||
+33
-24
@@ -795,7 +795,9 @@ static bool Evaluation_evaluate_one_operation(RzBinDwarfEvaluation *self, Operat
|
||||
Operation operation = { 0 };
|
||||
bool ret = false;
|
||||
ut64 offset = rz_buf_tell(self->pc);
|
||||
ERR_IF_FAIL(Operation_parse(&operation, self->pc, self->big_endian, self->encoding));
|
||||
OK_OR(Operation_parse(&operation, self->pc, self->big_endian, self->encoding),
|
||||
out->kind = OperationEvaluationResult_DECODE_ERROR;
|
||||
goto ok);
|
||||
|
||||
switch (operation.kind) {
|
||||
case OPERATION_KIND_DEREF: {
|
||||
@@ -982,8 +984,10 @@ static bool Evaluation_evaluate_one_operation(RzBinDwarfEvaluation *self, Operat
|
||||
loc->kind = RzBinDwarfLocationKind_REGISTER_OFFSET;
|
||||
loc->offset += operation.frame_offset.offset;
|
||||
} else {
|
||||
RZ_LOG_ERROR("Unsupported frame base location kind: %d\n", loc->kind);
|
||||
goto err;
|
||||
self->state.kind = EVALUATION_STATE_WAITING;
|
||||
out->kind = OperationEvaluationResult_WAITING;
|
||||
out->waiting._1 = EvaluationStateWaiting_FbReg;
|
||||
goto ok;
|
||||
}
|
||||
RzBinDwarfValue v = {
|
||||
.type = RzBinDwarfValueType_LOCATION,
|
||||
@@ -1208,6 +1212,9 @@ RZ_API bool rz_bin_dwarf_evaluation_evaluate(RZ_BORROW RZ_NONNULL RzBinDwarfEval
|
||||
switch (op_result.kind) {
|
||||
case OperationEvaluationResult_PIECE:
|
||||
break;
|
||||
case OperationEvaluationResult_DECODE_ERROR:
|
||||
self->state.kind = EVALUATION_STATE_DECODE_ERROR;
|
||||
goto err;
|
||||
case OperationEvaluationResult_INCOMPLETE:
|
||||
if (Evaluation_end_of_expression(self) && !rz_vector_empty(&self->result)) {
|
||||
self->state.kind = EVALUATION_STATE_ERROR;
|
||||
@@ -1271,7 +1278,7 @@ RZ_API bool rz_bin_dwarf_evaluation_evaluate(RZ_BORROW RZ_NONNULL RzBinDwarfEval
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rz_vector_empty(&self->result)) {
|
||||
if (rz_vector_empty(&self->result) && !rz_vector_empty(&self->stack)) {
|
||||
RzBinDwarfValue entry = { 0 };
|
||||
bool status = Evaluation_pop(self, &entry);
|
||||
RzBinDwarfLocation *location = NULL;
|
||||
@@ -1321,19 +1328,18 @@ RZ_API RZ_BORROW RzVector /*<RzBinDwarfPiece>*/ *rz_bin_dwarf_evaluation_result(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static RzBinDwarfLocation *RzBinDwarfEvaluationResult_to_loc(RzBinDwarfEvaluation *eval, RzBinDwarfEvaluationResult *result) {
|
||||
RzBinDwarfLocation *loc = NULL;
|
||||
static bool RzBinDwarfEvaluationResult_to_loc(
|
||||
RzBinDwarfEvaluation *eval, RzBinDwarfEvaluationResult *result, Location *loc) {
|
||||
rz_return_val_if_fail(loc, false);
|
||||
if (eval->state.kind == EVALUATION_STATE_COMPLETE && result->kind == EvaluationResult_COMPLETE) {
|
||||
RzVector *pieces = rz_bin_dwarf_evaluation_result(eval);
|
||||
if (!pieces || rz_vector_empty(pieces)) {
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
if (rz_vector_len(pieces) == 1) {
|
||||
RzBinDwarfPiece *piece = rz_vector_index_ptr(pieces, 0);
|
||||
loc = piece->location;
|
||||
piece->location = NULL;
|
||||
OK_OR(RzBinDwarfLocation_move(piece->location, loc), return false);
|
||||
} else {
|
||||
loc = RZ_NEW0(RzBinDwarfLocation);
|
||||
loc->kind = RzBinDwarfLocationKind_COMPOSITE;
|
||||
loc->composite = rz_vector_clone(pieces);
|
||||
RzBinDwarfPiece *piece = NULL;
|
||||
@@ -1341,21 +1347,13 @@ static RzBinDwarfLocation *RzBinDwarfEvaluationResult_to_loc(RzBinDwarfEvaluatio
|
||||
piece->location = NULL;
|
||||
}
|
||||
}
|
||||
rz_bin_dwarf_evaluation_free(eval);
|
||||
RzBinDwarfEvaluationResult_free(result);
|
||||
return loc;
|
||||
return true;
|
||||
}
|
||||
|
||||
loc = RZ_NEW0(RzBinDwarfLocation);
|
||||
if (!loc) {
|
||||
rz_bin_dwarf_evaluation_free(eval);
|
||||
RzBinDwarfEvaluationResult_free(result);
|
||||
return NULL;
|
||||
}
|
||||
loc->kind = RzBinDwarfLocationKind_EVALUATION_WAITING;
|
||||
loc->eval_waiting.eval = eval;
|
||||
loc->eval_waiting.result = result;
|
||||
return loc;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1372,17 +1370,28 @@ RZ_API RZ_OWN RzBinDwarfLocation *rz_bin_dwarf_location_from_block(
|
||||
RZ_BORROW RZ_NULLABLE const RzBinDwarfCompUnit *unit,
|
||||
RZ_BORROW RZ_NULLABLE const RzBinDwarfDie *die) {
|
||||
rz_return_val_if_fail(block && dw, NULL);
|
||||
Location *loc = RZ_NEW0(Location);
|
||||
OK_OR(loc, return NULL);
|
||||
RzBinDwarfEvaluationResult *result = RZ_NEW0(RzBinDwarfEvaluationResult);
|
||||
RET_NULL_IF_FAIL(result);
|
||||
RzBinDwarfEvaluation *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));
|
||||
|
||||
return RzBinDwarfEvaluationResult_to_loc(eval, result);
|
||||
ERR_IF_FAIL(rz_bin_dwarf_evaluation_evaluate(eval, result) &&
|
||||
RzBinDwarfEvaluationResult_to_loc(eval, result, loc));
|
||||
ok:
|
||||
return loc;
|
||||
err:
|
||||
if (eval && eval->state.kind == EVALUATION_STATE_DECODE_ERROR) {
|
||||
loc->kind = RzBinDwarfLocationKind_DECODE_ERROR;
|
||||
goto cleanup;
|
||||
} else {
|
||||
rz_bin_dwarf_location_free(loc);
|
||||
loc = NULL;
|
||||
}
|
||||
cleanup:
|
||||
rz_bin_dwarf_evaluation_free(eval);
|
||||
RzBinDwarfEvaluationResult_free(result);
|
||||
return NULL;
|
||||
goto ok;
|
||||
}
|
||||
|
||||
static void Operation_dump(Operation *op, RzStrBuf *buf) {
|
||||
|
||||
@@ -215,6 +215,7 @@ typedef struct operation_evaluation_result_t {
|
||||
OperationEvaluationResult_PIECE,
|
||||
OperationEvaluationResult_WAITING,
|
||||
OperationEvaluationResult_WAITING_RESOLVE,
|
||||
OperationEvaluationResult_DECODE_ERROR,
|
||||
} kind;
|
||||
|
||||
union {
|
||||
|
||||
@@ -49,7 +49,7 @@ static bool RzBinDwarfDie_attrs_parse(
|
||||
.big_endian = ctx->big_endian,
|
||||
};
|
||||
if (!RzBinDwarfAttr_parse(buffer, &attr, &opt)) {
|
||||
RZ_LOG_ERROR("0x%" PFMT64x ":\tfailed die: 0x%" PFMT64x " %s [%s]\n ",
|
||||
RZ_LOG_ERROR("0x%" PFMT64x ":\tfailed die attr: 0x%" PFMT64x " %s [%s]\n ",
|
||||
rz_buf_tell(buffer), die->offset, rz_bin_dwarf_attr(def->name), rz_bin_dwarf_form(def->form));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1490,6 +1490,7 @@ typedef struct {
|
||||
|
||||
typedef struct rz_core_bin_dwarf_t {
|
||||
RzBinDwarfEncoding encoding;
|
||||
bool big_endian : 1;
|
||||
RzBinDwarfARanges *aranges;
|
||||
RzBinDwarfLineInfo *line;
|
||||
RzBinDwarfLocListTable *loc;
|
||||
@@ -1645,6 +1646,7 @@ typedef enum {
|
||||
EvaluationStateWaiting_TLS,
|
||||
EvaluationStateWaiting_AtLocation,
|
||||
EvaluationStateWaiting_ParameterRef,
|
||||
EvaluationStateWaiting_FbReg,
|
||||
} RzBinDwarfEvaluationStateWaiting;
|
||||
|
||||
typedef struct {
|
||||
@@ -1652,6 +1654,7 @@ typedef struct {
|
||||
EVALUATION_STATE_START,
|
||||
EVALUATION_STATE_READY,
|
||||
EVALUATION_STATE_ERROR,
|
||||
EVALUATION_STATE_DECODE_ERROR,
|
||||
EVALUATION_STATE_COMPLETE,
|
||||
EVALUATION_STATE_WAITING,
|
||||
EVALUATION_STATE_WAITING_RESOLVE,
|
||||
|
||||
Reference in New Issue
Block a user