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

Fix DWARF FbReg Operation eval #3824

Closed
wants to merge 2 commits into from
Closed
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
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
12 changes: 8 additions & 4 deletions librz/bin/dwarf/buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 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
1 change: 1 addition & 0 deletions librz/bin/dwarf/dwarf_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions librz/bin/dwarf/line.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ static RzBinDwarfFileEntry *RzBinDwarfFileEntry_parse_v5(
}

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);
Expand Down Expand Up @@ -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;
}
Expand Down
57 changes: 33 additions & 24 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,32 @@ 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;
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 +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) {
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
Loading