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:
billow
2023-09-03 17:30:02 +08:00
committed by GitHub
parent abec6b127d
commit 71e6f5d450
9 changed files with 51 additions and 32 deletions
+1 -1
View File
@@ -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);
+8 -4
View File
@@ -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;
}
+1
View File
@@ -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);
+1
View File
@@ -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);
+2 -2
View File
@@ -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
View File
@@ -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) {
+1
View File
@@ -215,6 +215,7 @@ typedef struct operation_evaluation_result_t {
OperationEvaluationResult_PIECE,
OperationEvaluationResult_WAITING,
OperationEvaluationResult_WAITING_RESOLVE,
OperationEvaluationResult_DECODE_ERROR,
} kind;
union {
+1 -1
View File
@@ -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;
}
+3
View File
@@ -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,