Skip to content

Commit

Permalink
Fix FbReg Operation eval
Browse files Browse the repository at this point in the history
  • Loading branch information
imbillow committed Sep 3, 2023
1 parent abec6b1 commit 882551c
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 28 deletions.
2 changes: 1 addition & 1 deletion librz/analysis/dwarf_process.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 0 additions & 4 deletions librz/bin/dwarf/buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,5 @@ 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;
}
1 change: 1 addition & 0 deletions librz/bin/dwarf/dwarf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
54 changes: 32 additions & 22 deletions librz/bin/dwarf/op.c
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1321,41 +1328,33 @@ 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;
} else {
loc = RZ_NEW0(RzBinDwarfLocation);
loc->kind = RzBinDwarfLocationKind_COMPOSITE;
loc->composite = rz_vector_clone(pieces);
RzBinDwarfPiece *piece = NULL;
rz_vector_foreach(pieces, piece) {
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;
}

/**
Expand All @@ -1372,17 +1371,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) {
Expand Down
1 change: 1 addition & 0 deletions librz/bin/dwarf/op.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ typedef struct operation_evaluation_result_t {
OperationEvaluationResult_PIECE,
OperationEvaluationResult_WAITING,
OperationEvaluationResult_WAITING_RESOLVE,
OperationEvaluationResult_DECODE_ERROR,
} kind;

union {
Expand Down
2 changes: 1 addition & 1 deletion librz/bin/dwarf/unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
3 changes: 3 additions & 0 deletions librz/include/rz_bin_dwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1645,13 +1646,15 @@ typedef enum {
EvaluationStateWaiting_TLS,
EvaluationStateWaiting_AtLocation,
EvaluationStateWaiting_ParameterRef,
EvaluationStateWaiting_FbReg,
} RzBinDwarfEvaluationStateWaiting;

typedef struct {
enum {
EVALUATION_STATE_START,
EVALUATION_STATE_READY,
EVALUATION_STATE_ERROR,
EVALUATION_STATE_DECODE_ERROR,
EVALUATION_STATE_COMPLETE,
EVALUATION_STATE_WAITING,
EVALUATION_STATE_WAITING_RESOLVE,
Expand Down

0 comments on commit 882551c

Please sign in to comment.