RzAsm/RzAnalysis pointer sharing changes before RzArch and Hexagon fixes (#4667)

* Attempt of passing pointers from RzAsm to RzAnalysis and wise versa.
* Refactor Hexagon module to make use of hacky pointer sharing.
* Refactor plugin specific configutations.
Because static values are no longer allowed, it has to be sure
that the 'user' pointer for the config value setter is always the plugin data.
So the plugin can change its internal state, according to the configuration value.
This was not possible before.
Also it adds a seperated hash map for plugin values. So they are logically more separated.

* Fix the whole pre-decoding logic for Hexagon.
Also resolves the problems with not knowing what is a valid instruction and which one not.
Leads to way more stability in decoding.

* Formatting and docs.
* Save utf8 flag to state to save memcpy.
* Fix inconsistency in function declaration.
* Fix token tests and fix hexagon plugin to handle none IO buffers.
* Fix test. Empty buffer before printing same instruction again.
* Assign state to rz_reverse struct so it can be passed o hex_get_il_op() in analysis_hexagon.c
* Rename and document alignment fields better.
* Add test for out of order packet decoding.
* Add ownership information
* Import relative headers.
This commit is contained in:
Rot127 2024-10-17 07:30:40 +00:00 committed by GitHub
parent 4fd556c2a3
commit 9e2de0dd50
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 625 additions and 274 deletions

View file

@ -406,22 +406,15 @@ RZ_API bool rz_asm_use_assembler(RzAsm *a, const char *name) {
}
/**
* \brief Copies all config nodes in \p pcfg to the config in \p rz_asm.
* \brief Appends the plugin configuration \p pcfg to the core plugin_config vector.
*
* \param rz_asm Pointer to RzAsm struct.
* \param pcfg Pointer to the plugins RzConfig struct.
*/
static void set_plugin_configs(RZ_BORROW RzAsm *rz_asm, RZ_BORROW RzConfig *pcfg) {
rz_return_if_fail(pcfg && rz_asm);
RzConfig *conf = ((RzCore *)(rz_asm->core))->config;
RzConfigNode *n;
RzListIter *it;
rz_list_foreach (pcfg->nodes, it, n) {
if (!rz_config_add_node(conf, rz_config_node_clone(n))) {
RZ_LOG_WARN("Failed to add \"%s\" to the global config.\n", n->name)
}
}
static void set_plugin_configs(RZ_BORROW RzCore *core, const char *plugin_name, RZ_OWN RzConfig *pcfg) {
rz_return_if_fail(pcfg && core);
rz_config_lock(pcfg, 1);
ht_sp_insert(core->plugin_configs, plugin_name, pcfg);
}
/**
@ -430,17 +423,9 @@ static void set_plugin_configs(RZ_BORROW RzAsm *rz_asm, RZ_BORROW RzConfig *pcfg
* \param rz_asm Pointer to RzAsm struct.
* \param pcfg Pointer to the plugins RzConfig struct.
*/
static void unset_plugins_config(RZ_BORROW RzAsm *rz_asm, RZ_BORROW RzConfig *pcfg) {
rz_return_if_fail(pcfg && rz_asm && rz_asm->core);
RzConfig *conf = ((RzCore *)(rz_asm->core))->config;
RzConfigNode *n;
RzListIter *it;
rz_list_foreach (pcfg->nodes, it, n) {
if (!rz_config_rm(conf, n->name)) {
RZ_LOG_WARN("Failed to remove \"%s\" from the global config.\n", n->name)
}
}
static void remove_plugin_config(RZ_BORROW RzCore *core, const char *plugin_name) {
rz_return_if_fail(core && plugin_name);
ht_sp_delete(core->plugin_configs, plugin_name);
}
// TODO: this can be optimized using rz_str_hash()
@ -482,14 +467,10 @@ RZ_API bool rz_asm_use(RzAsm *a, const char *name) {
}
if (a->cur && a->cur->get_config && core) {
rz_config_lock(core->config, false);
unset_plugins_config(a, a->cur->get_config());
rz_config_lock(core->config, true);
remove_plugin_config(core, a->cur->name);
}
if (h->get_config && core) {
rz_config_lock(core->config, false);
set_plugin_configs(a, h->get_config());
rz_config_lock(core->config, true);
set_plugin_configs(core, h->name, h->get_config(a->plugin_data));
}
a->cur = h;
return true;

View file

@ -266,9 +266,9 @@ typedef struct {
bool just_init; ///< Flag indicates if IL VM was just initialized.
HexPkt pkts[HEXAGON_STATE_PKTS]; // buffered instructions
RzList /*<HexConstExt *>*/ *const_ext_l; // Constant extender values.
RzAsm rz_asm; // Copy of RzAsm struct. Holds certain flags of interesed for disassembly formatting.
RzConfig *cfg;
RzPVector /*<RzAsmTokenPattern *>*/ *token_patterns; ///< PVector with token patterns. Priority ordered.
bool utf8_enabled; ///< If set, print UTF-8 characters.
} HexState;
/**
@ -833,7 +833,7 @@ const char *hex_get_sys_regs(int reg_num, bool get_alias, bool get_new, bool reg
const char *hex_get_sys_regs64(int reg_num, bool get_alias, bool get_new, bool reg_num_is_enum);
RZ_API const char *hex_get_reg_in_class(HexRegClass cls, int reg_num, bool get_alias, bool get_new, bool reg_num_is_enum);
RZ_API RZ_BORROW RzConfig *hexagon_get_config();
RZ_API RZ_OWN RzConfig *hexagon_get_config(void *plugin_data);
RZ_API void hex_extend_op(HexState *state, RZ_INOUT HexOp *op, const bool set_new_extender, const ut32 addr);
int resolve_n_register(const int reg_num, const ut32 addr, const HexPkt *p);
int hexagon_disasm_instruction(HexState *state, const ut32 hi_u32, RZ_INOUT HexInsnContainer *hi, HexPkt *pkt);

View file

@ -9,6 +9,9 @@
// Do not edit. Repository of code generator:
// https://github.com/rizinorg/rz-hexagon
#include "rz_types.h"
#include <rz_util/rz_log.h>
#include <rz_util/rz_buf.h>
#include <rz_list.h>
#include <rz_util/rz_assert.h>
#include <rz_asm.h>
@ -20,6 +23,21 @@
#include <hexagon/hexagon_arch.h>
#include <hexagon/hexagon_il.h>
RZ_IPI void hexagon_state_fini(RZ_NULLABLE HexState *state) {
if (!state) {
return;
}
rz_config_free(state->cfg);
rz_pvector_free(state->token_patterns);
rz_list_free(state->const_ext_l);
for (size_t i = 0; i < HEXAGON_STATE_PKTS; ++i) {
rz_list_free(state->pkts[i].bin);
rz_pvector_free(state->pkts[i].il_ops);
hex_il_pkt_stats_fini(&state->pkts[i].il_op_stats);
}
return;
}
static inline bool is_invalid_insn_data(ut32 data) {
return data == HEX_INVALID_INSN_0 || data == HEX_INVALID_INSN_F;
}
@ -91,6 +109,10 @@ RZ_API HexInsnContainer *hex_get_hic_at_addr(HexState *state, const ut32 addr) {
p = &state->pkts[i];
HexInsnContainer *hic = NULL;
RzListIter *iter = NULL;
if (p->last_access == 0) {
// Just initialized packets without any instructions.
continue;
}
rz_list_foreach (p->bin, iter, hic) {
if (addr == hic->addr) {
p->last_access = rz_time_now_mono();
@ -224,7 +246,7 @@ static void hex_clear_pkt(RZ_NONNULL HexPkt *p) {
p->last_access = 0;
rz_list_purge(p->bin);
rz_pvector_clear(p->il_ops);
hex_reset_il_pkt_stats(&p->il_op_stats);
hex_il_pkt_stats_reset(&p->il_op_stats);
}
/**
@ -259,6 +281,9 @@ RZ_API HexPkt *hex_get_pkt(RZ_BORROW HexState *state, const ut32 addr) {
RzListIter *iter = NULL;
for (ut8 i = 0; i < HEXAGON_STATE_PKTS; ++i) {
p = &state->pkts[i];
if (rz_list_length(p->bin) == 0) {
continue;
}
rz_list_foreach (p->bin, iter, hic) {
if (hic_at_addr(hic, addr)) {
p->last_access = rz_time_now_mono();
@ -339,17 +364,8 @@ static ut8 get_state_pkt_index(HexState *state, const HexPkt *p) {
*
* \return The initialized state of the plugins or NULL if \p reset = true.
*/
RZ_API HexState *hexagon_state(bool reset) {
static HexState *state = NULL;
if (reset) {
state = NULL;
return NULL;
}
if (state) {
return state;
}
state = RZ_NEW0(HexState);
RZ_IPI RZ_OWN HexState *hexagon_state_new() {
HexState *state = RZ_NEW0(HexState);
if (!state) {
RZ_LOG_FATAL("Could not allocate memory for HexState!");
return NULL;
@ -516,11 +532,10 @@ void hex_set_hic_text(RZ_INOUT HexInsnContainer *hic) {
* \param pkt The packet the instruction belongs to.
* \param k The index of the instruction within the packet.
*/
static void hex_set_pkt_info(const RzAsm *rz_asm, RZ_INOUT HexInsnContainer *hic, const HexPkt *pkt, const ut8 k, const bool update_text) {
rz_return_if_fail(hic && pkt);
static void hex_set_pkt_info(RZ_INOUT HexInsnContainer *hic, const HexPkt *pkt, const ut8 k, const bool update_text, HexState *state) {
rz_return_if_fail(hic && pkt && state);
bool is_first = (k == 0);
HexPktInfo *hi_pi = &hic->pkt_info;
HexState *state = hexagon_state(false);
bool sdk_form = rz_config_get_b(state->cfg, "plugins.hexagon.sdk");
strncpy(hi_pi->text_postfix, "", 16);
@ -529,9 +544,9 @@ static void hex_set_pkt_info(const RzAsm *rz_asm, RZ_INOUT HexInsnContainer *hic
hi_pi->first_insn = true;
hi_pi->last_insn = true;
if (pkt->is_valid) {
strncpy(hi_pi->text_prefix, get_pkt_indicator(rz_asm->utf8, sdk_form, true, SINGLE_IN_PKT), 8);
strncpy(hi_pi->text_prefix, get_pkt_indicator(state->utf8_enabled, sdk_form, true, SINGLE_IN_PKT), 8);
if (sdk_form) {
strncpy(hi_pi->text_postfix, get_pkt_indicator(rz_asm->utf8, sdk_form, false, SINGLE_IN_PKT), 8);
strncpy(hi_pi->text_postfix, get_pkt_indicator(state->utf8_enabled, sdk_form, false, SINGLE_IN_PKT), 8);
}
} else {
strncpy(hi_pi->text_prefix, HEX_PKT_UNK, 8);
@ -540,7 +555,7 @@ static void hex_set_pkt_info(const RzAsm *rz_asm, RZ_INOUT HexInsnContainer *hic
hi_pi->first_insn = true;
hi_pi->last_insn = false;
if (pkt->is_valid) {
strncpy(hi_pi->text_prefix, get_pkt_indicator(rz_asm->utf8, sdk_form, true, FIRST_IN_PKT), 8);
strncpy(hi_pi->text_prefix, get_pkt_indicator(state->utf8_enabled, sdk_form, true, FIRST_IN_PKT), 8);
} else {
strncpy(hi_pi->text_prefix, HEX_PKT_UNK, 8);
}
@ -548,22 +563,22 @@ static void hex_set_pkt_info(const RzAsm *rz_asm, RZ_INOUT HexInsnContainer *hic
hi_pi->first_insn = false;
hi_pi->last_insn = true;
if (pkt->is_valid) {
strncpy(hi_pi->text_prefix, get_pkt_indicator(rz_asm->utf8, sdk_form, true, LAST_IN_PKT), 8);
strncpy(hi_pi->text_prefix, get_pkt_indicator(state->utf8_enabled, sdk_form, true, LAST_IN_PKT), 8);
if (sdk_form) {
strncpy(hi_pi->text_postfix, get_pkt_indicator(rz_asm->utf8, sdk_form, false, LAST_IN_PKT), 8);
strncpy(hi_pi->text_postfix, get_pkt_indicator(state->utf8_enabled, sdk_form, false, LAST_IN_PKT), 8);
}
switch (hex_get_loop_flag(pkt)) {
default:
break;
case HEX_LOOP_01:
strncat(hi_pi->text_postfix, get_pkt_indicator(rz_asm->utf8, sdk_form, false, ELOOP_01_PKT), 23 - strlen(hi_pi->text_postfix));
strncat(hi_pi->text_postfix, get_pkt_indicator(state->utf8_enabled, sdk_form, false, ELOOP_01_PKT), 23 - strlen(hi_pi->text_postfix));
break;
case HEX_LOOP_0:
strncat(hi_pi->text_postfix, get_pkt_indicator(rz_asm->utf8, sdk_form, false, ELOOP_0_PKT), 23 - strlen(hi_pi->text_postfix));
strncat(hi_pi->text_postfix, get_pkt_indicator(state->utf8_enabled, sdk_form, false, ELOOP_0_PKT), 23 - strlen(hi_pi->text_postfix));
break;
case HEX_LOOP_1:
strncat(hi_pi->text_postfix, get_pkt_indicator(rz_asm->utf8, sdk_form, false, ELOOP_1_PKT), 23 - strlen(hi_pi->text_postfix));
strncat(hi_pi->text_postfix, get_pkt_indicator(state->utf8_enabled, sdk_form, false, ELOOP_1_PKT), 23 - strlen(hi_pi->text_postfix));
break;
}
} else {
@ -573,7 +588,7 @@ static void hex_set_pkt_info(const RzAsm *rz_asm, RZ_INOUT HexInsnContainer *hic
hi_pi->first_insn = false;
hi_pi->last_insn = false;
if (pkt->is_valid) {
strncpy(hi_pi->text_prefix, get_pkt_indicator(rz_asm->utf8, sdk_form, true, MID_IN_PKT), 8);
strncpy(hi_pi->text_prefix, get_pkt_indicator(state->utf8_enabled, sdk_form, true, MID_IN_PKT), 8);
} else {
strncpy(hi_pi->text_prefix, HEX_PKT_UNK, 8);
}
@ -627,7 +642,7 @@ static void make_packet_valid(RZ_BORROW HexState *state, RZ_BORROW HexPkt *pkt)
ut8 i = 0;
ut8 slot = 0;
rz_list_foreach (pkt->bin, it, hi) {
hex_set_pkt_info(&state->rz_asm, hi, pkt, i, true);
hex_set_pkt_info(hi, pkt, i, true, state);
if (hi->is_duplex) {
hi->bin.sub[0]->slot = 0;
hi->bin.sub[1]->slot = 1;
@ -720,10 +735,10 @@ static HexInsnContainer *hex_add_to_pkt(HexState *state, const HexInsnContainer
}
pkt->last_instr_present |= is_last_instr(hic->parse_bits);
ut32 p_l = rz_list_length(pkt->bin);
hex_set_pkt_info(&state->rz_asm, hic, pkt, k, false);
hex_set_pkt_info(hic, pkt, k, false, state);
if (k == 0 && p_l > 1) {
// Update the instruction which was previously the first one.
hex_set_pkt_info(&state->rz_asm, rz_list_get_n(pkt->bin, 1), pkt, 1, true);
hex_set_pkt_info(rz_list_get_n(pkt->bin, 1), pkt, 1, true, state);
}
pkt->last_access = rz_time_now_mono();
if (pkt->last_instr_present) {
@ -755,7 +770,7 @@ static HexInsnContainer *hex_to_new_pkt(HexState *state, const HexInsnContainer
new_pkt->is_valid = (pkt->is_valid || pkt->last_instr_present);
new_pkt->pkt_addr = hic->addr;
new_pkt->last_access = rz_time_now_mono();
hex_set_pkt_info(&state->rz_asm, hic, new_pkt, 0, false);
hex_set_pkt_info(hic, new_pkt, 0, false, state);
if (new_pkt->last_instr_present) {
make_next_packet_valid(state, new_pkt);
}
@ -781,7 +796,7 @@ static HexInsnContainer *hex_add_to_stale_pkt(HexState *state, const HexInsnCont
pkt->pkt_addr = new_hic->addr;
// p->is_valid = true; // Setting it true also detects a lot of data as valid assembly.
pkt->last_access = rz_time_now_mono();
hex_set_pkt_info(&state->rz_asm, hic, pkt, 0, false);
hex_set_pkt_info(hic, pkt, 0, false, state);
if (pkt->last_instr_present) {
make_next_packet_valid(state, pkt);
}
@ -1050,8 +1065,9 @@ RZ_API void hex_extend_op(HexState *state, RZ_INOUT HexOp *op, const bool set_ne
}
}
static void copy_asm_ana_ops(const HexState *state, RZ_BORROW HexReversedOpcode *rz_reverse, RZ_BORROW HexInsnContainer *hic) {
static void copy_asm_ana_ops(HexState *state, RZ_BORROW HexReversedOpcode *rz_reverse, RZ_BORROW HexInsnContainer *hic) {
rz_return_if_fail(state && rz_reverse && hic);
rz_reverse->state = state;
switch (rz_reverse->action) {
default:
memcpy(rz_reverse->asm_op, &hic->asm_op, sizeof(RzAsmOp));
@ -1121,6 +1137,119 @@ RZ_IPI void hexagon_pkt_mark_tail_calls(HexPkt *pkt) {
hic->ana_op.type = RZ_ANALYSIS_OP_TYPE_TAIL | RZ_ANALYSIS_OP_TYPE_RET;
}
static RZ_BORROW HexInsnContainer *decode_hic(HexState *state, HexReversedOpcode *rz_reverse, RZ_BORROW RzBuffer *buffer, const ut64 addr) {
ut8 tmp[HEX_INSN_SIZE] = { 0 };
ut32 bytes = rz_buf_read(buffer, tmp, 4);
if (bytes != HEX_INSN_SIZE) {
RZ_LOG_DEBUG("Failed to read from buffer!\n");
return NULL;
}
ut32 data = rz_read_le32(tmp);
ut8 parse_bits = HEX_PARSE_BITS_FROM_UT32(data);
HexInsnContainer hic_new = { 0 };
setup_new_hic(&hic_new, rz_reverse, addr, parse_bits, data);
// Add to state as not yet fully decoded packet.
HexInsnContainer *hic = hex_add_hic_to_state(state, &hic_new);
if (!hic) {
RZ_LOG_ERROR("Could not add incsturction container to state.\n");
return NULL;
}
HexPkt *p = hex_get_pkt(state, hic->addr);
// Do disassembly and analysis
hexagon_disasm_instruction(state, data, hic, p);
return hic;
}
/**
* \brief Returns the address at which the decoding must start to get a valid packet at \p addr.
* The \p buffer seek is set to the position to start reading from.
*
* \param buffer The buffer to search in and update its seek.
* \param addr The address to start searching for the pre-decoding start.
*
* \return The address to start decoding. It always returns an address <= \p addr
* and with an offset with an multiple of HEX_INSN_SIZE.
*/
static ut64 get_pre_decoding_start(RZ_BORROW RzBuffer *buffer, ut64 addr) {
rz_return_val_if_fail(buffer, addr);
if (addr < HEX_INSN_SIZE) {
return addr;
}
size_t seek = rz_buf_tell(buffer);
size_t look_back = 0;
bool is_last_insn = false;
// Search until we cross a boundary or have found a last instruction.
while (addr >= HEX_INSN_SIZE && seek >= HEX_INSN_SIZE && look_back < 4 && !is_last_insn) {
seek = rz_buf_seek(buffer, -HEX_INSN_SIZE, RZ_BUF_CUR);
addr -= HEX_INSN_SIZE;
look_back++;
ut8 tmp[HEX_INSN_SIZE] = { 0 };
ut32 bytes = rz_buf_read(buffer, tmp, 4);
if (bytes != HEX_INSN_SIZE) {
return addr;
}
ut32 data = rz_read_le32(tmp);
is_last_insn = is_last_instr(HEX_PARSE_BITS_FROM_UT32(data));
}
return addr;
}
/**
* \brief Performs pointer passing hacks to set up the \p buffer and assign RzAsm::plugin_data to \p state.
* It will take either a valid RzAsm OR RzAnalysis pointer. It assumes that RzCore and RzAsm is initialized.
*
* If RzAnlysis is initialized and set in the current RzCore object, it will initialize the \p buffer with RzAnalysis::iob.
* If no RzAnalysis object is initialized, it sets up the \p buffer with the bytes given via \p rz_reverse.
*
* This function guarantees to set \p state, \p buffer and \p rz_asm to valid objects.
*
* This function does not return any status. It will do only asserts because every failure is critical and means memory miss-alignment.
*/
static void perform_hacks(RZ_NONNULL HexState **state,
RZ_NONNULL RzBuffer **buffer,
RZ_NONNULL RzAsm **rz_asm,
RZ_NONNULL RzAnalysis **rz_analysis,
RZ_NONNULL HexReversedOpcode *rz_reverse) {
if (*rz_analysis) {
*rz_asm = rz_analysis_to_rz_asm(*rz_analysis);
assert(*rz_asm && (*rz_asm)->cur && (*rz_analysis)->cur && RZ_STR_EQ((*rz_asm)->cur->arch, (*rz_analysis)->cur->arch));
} else if (*rz_asm) {
*rz_analysis = rz_asm_to_rz_analysis(*rz_asm);
if (*rz_analysis && (*rz_analysis)->cur) {
assert(RZ_STR_EQ((*rz_asm)->cur->arch, (*rz_analysis)->cur->arch));
}
} else {
assert(0 && "Requires either RzAsm or RzAnalysis");
}
// Set Buffer
if (!((*rz_analysis) && (*rz_analysis)->cur)) {
// Only RzAsm present (rz-test, rz-asm etc.). So also likely a test situation without IO.
*buffer = rz_buf_new_with_bytes(rz_reverse->bytes_buf, rz_reverse->bytes_buf_len);
assert(*buffer);
} else {
*buffer = rz_buf_new_with_io(&(*rz_analysis)->iob);
assert(*buffer);
}
*state = (*rz_asm)->plugin_data;
assert(*state);
(*state)->utf8_enabled = (*rz_asm)->utf8;
rz_reverse->state = *state;
return;
}
static inline bool do_decoding_loop(ut64 current_addr, ut64 requested_addr, const HexInsnContainer *prev_hic) {
// Loop as long as:
// - pre_addr < requested_addr: pre_decoding hasn't finished.
// - We have not seen a last instruction of a packet (max. check +4 insn after address).
return (current_addr <= requested_addr) ||
(prev_hic && ((current_addr < (requested_addr + (HEX_INSN_SIZE * HEX_MAX_INSN_PER_PKT))) && !prev_hic->pkt_info.last_insn));
}
/**
* \brief Reverses a given opcode and copies the result into one of the rizin structs in rz_reverse
* if \p copy_result is set.
@ -1130,50 +1259,60 @@ RZ_IPI void hexagon_pkt_mark_tail_calls(HexPkt *pkt) {
* \param addr The address of the current opcode.
* \param copy_result If set, it copies the result. Otherwise it only buffers it in the internal state.
*/
RZ_API void hexagon_reverse_opcode(const RzAsm *rz_asm, HexReversedOpcode *rz_reverse, const ut8 *buf, const ut64 addr, const bool copy_result) {
HexState *state = hexagon_state(false);
if (!state) {
RZ_LOG_FATAL("HexState was NULL.");
return;
}
if (rz_asm) {
memcpy(&state->rz_asm, rz_asm, sizeof(RzAsm));
}
HexInsnContainer *hic = hex_get_hic_at_addr(state, addr);
if (hic && !is_invalid_insn_data(hic->bytes)) {
// Code was already reversed and is still in the state. Copy the result and return.
//
// We never return buffered instructions of 0x00000000 and 0xffffffff.
// Because Rizin's IO layer is not a transparent view into the binary.
// Sometimes it passes a buffer for address `a` of size `n`, which has only
// `m` bytes of actual binary data set (where `m < n`).
// Although, there are still valid instructions bytes at `a + m` in the
// actual binary. So the IO layer only passes a certain window of `n - m` valid bytes
// and sets the rest to `0x0` or `0xff`.
// So previously we might have disassembled and buffered those invalid bytes
// at `a + m`. Although in the actual binary there are valid
// instructions at this address.
if (copy_result) {
copy_asm_ana_ops(state, rz_reverse, hic);
}
RZ_API void hexagon_reverse_opcode(HexReversedOpcode *rz_reverse, const ut64 addr, RzAsm *rz_asm, RzAnalysis *rz_analysis) {
rz_return_if_fail(rz_reverse);
HexState *state;
RzBuffer *buffer;
perform_hacks(&state, &buffer, &rz_asm, &rz_analysis, rz_reverse);
// Seek to initial position for IO buffers.
// Only for IO buffers an address is a valid seek.
// For bytes buffers (e.g. given in case of `rz-asm`) the address is not a valid seek, but distinct.
if (buffer->type == RZ_BUFFER_IO && rz_buf_seek(buffer, addr, RZ_BUF_SET) != addr) {
RZ_LOG_DEBUG("Could not seek to address: 0x%" PFMT64x ". Attempting to read out of mapped memory region?\n", addr);
return;
}
ut32 data = rz_read_le32(buf);
ut8 parse_bits = (data & HEX_PARSE_BITS_MASK) >> 14;
HexInsnContainer hic_new = { 0 };
setup_new_hic(&hic_new, rz_reverse, addr, parse_bits, data);
// Add to state
hic = hex_add_hic_to_state(state, &hic_new);
ut64 current_addr = get_pre_decoding_start(buffer, addr);
HexInsnContainer *hic = NULL;
// Do pre- and post-decoding to know the context.
while (do_decoding_loop(current_addr, addr, hic)) {
if (hex_get_hic_at_addr(state, current_addr)) {
// Already decoded and still in buffer.
rz_buf_seek(buffer, HEX_INSN_SIZE, RZ_BUF_CUR);
current_addr += HEX_INSN_SIZE;
continue;
}
hic = decode_hic(state, rz_reverse, buffer, current_addr);
if (rz_buf_tell(buffer) == current_addr + HEX_INSN_SIZE) {
// Update current_addr only if it read successful.
current_addr += HEX_INSN_SIZE;
}
if (!hic) {
break;
}
}
if (current_addr > addr) {
// Go back to bytes of the actual instruction.
rz_buf_seek(buffer, -(current_addr - addr), RZ_BUF_CUR);
}
hic = hex_get_hic_at_addr(state, addr);
if (!hic) {
// Should have been decoded before. Maybe a race condition
// if the same RzCore is used by several threads via a plugin and
// the hic was already pushed out of the buffer by other decodings.
hic = decode_hic(state, rz_reverse, buffer, addr);
}
if (!hic) {
RZ_LOG_DEBUG("Could not decode packet.\n");
rz_buf_free(buffer);
return;
}
HexPkt *p = hex_get_pkt(state, hic->addr);
// Do disassembly and analysis
hexagon_disasm_instruction(state, data, hic, p);
if (copy_result) {
copy_asm_ana_ops(state, rz_reverse, hic);
}
rz_reverse->pkt_fully_decoded = p && p->is_valid;
copy_asm_ana_ops(state, rz_reverse, hic);
rz_buf_free(buffer);
}

View file

@ -38,6 +38,10 @@ typedef struct {
HexReverseAction action; // Whether ana_op, asm_op or both should be filled.
RzAnalysisOp *ana_op;
RzAsmOp *asm_op;
HexState *state;
bool pkt_fully_decoded;
const ut8 *bytes_buf; ///< Deprecated. Raw byte buffer provided to analysis and asm.
size_t bytes_buf_len; ///< Deprecated.
} HexReversedOpcode;
#define HEX_PKT_UNK "? "
@ -62,14 +66,16 @@ typedef struct {
#define HEX_PKT_ELOOP_1_SDK ":endloop1"
#define HEX_PKT_ELOOP_0_SDK ":endloop0"
#define HEX_PARSE_BITS_FROM_UT32(data) ((data & HEX_PARSE_BITS_MASK) >> 14)
RZ_API HexInsn *hexagon_alloc_instr();
RZ_API void hex_insn_free(RZ_NULLABLE HexInsn *i);
RZ_API HexInsnContainer *hexagon_alloc_instr_container();
RZ_API void hex_insn_container_free(RZ_NULLABLE HexInsnContainer *c);
RZ_API void hex_const_ext_free(RZ_NULLABLE HexConstExt *ce);
RZ_API HexState *hexagon_state(bool reset);
RZ_IPI void hexagon_state_fini(HexState *state);
RZ_API void hexagon_reverse_opcode(const RzAsm *rz_asm, HexReversedOpcode *rz_reverse, const ut8 *buf, const ut64 addr, const bool copy_result);
RZ_IPI RZ_OWN HexState *hexagon_state_new();
RZ_IPI void hexagon_state_fini(RZ_NULLABLE HexState *state);
RZ_API void hexagon_reverse_opcode(HexReversedOpcode *rz_reverse, const ut64 addr, RzAsm *rz_asm, RzAnalysis *rz_analysis);
RZ_API ut8 hexagon_get_pkt_index_of_addr(const ut32 addr, const HexPkt *p);
RZ_API HexLoopAttr hex_get_loop_flag(const HexPkt *p);
RZ_API const HexOp *hex_isa_to_reg(const HexInsn *hi, const char isa_id, bool new_reg);

View file

@ -240,7 +240,7 @@ static RZ_OWN RzILOpEffect *hex_pkt_to_il_seq(HexPkt *pkt) {
static bool set_pkt_il_ops(RZ_INOUT HexPkt *p) {
rz_return_val_if_fail(p, false);
hex_reset_il_pkt_stats(&p->il_op_stats);
hex_il_pkt_stats_reset(&p->il_op_stats);
// This function is a lot of unnecessary overhead so:
// TODO The assignment of IL instructions to their actual instructions should be done in the instruction template.
// But with the current separation between Asm and Analysis plugins this is not possible.
@ -347,13 +347,9 @@ static inline bool pkt_at_addr_is_emu_ready(const HexPkt *pkt, const ut32 addr)
* If false, the behavior is as documented above.
* \return RzILOpEffect* Sequence of operations to emulate the packet.
*/
RZ_IPI RzILOpEffect *hex_get_il_op(const ut32 addr, const bool get_pkt_op) {
RZ_IPI RZ_OWN RzILOpEffect *hex_get_il_op(const ut32 addr, const bool get_pkt_op, RZ_NONNULL HexState *state) {
rz_return_val_if_fail(state, NULL);
static bool might_has_jumped = false;
HexState *state = hexagon_state(false);
if (!state) {
RZ_LOG_WARN("Failed to get hexagon plugin state data!\n");
return NULL;
}
HexPkt *p = hex_get_pkt(state, addr);
if (!p) {
RZ_LOG_WARN("Packet was NULL although it should have been disassembled at this point.\n");
@ -855,7 +851,8 @@ RzILOpPure *hex_get_corresponding_cs(RZ_BORROW HexPkt *pkt, const HexOp *Mu) {
return NULL;
}
RZ_IPI void hex_reset_il_pkt_stats(HexILExecData *stats) {
RZ_IPI void hex_il_pkt_stats_fini(HexILExecData *stats) {
rz_return_if_fail(stats);
rz_bv_free(stats->slot_cancelled);
rz_bv_free(stats->ctr_written);
rz_bv_free(stats->gpr_written);
@ -866,6 +863,10 @@ RZ_IPI void hex_reset_il_pkt_stats(HexILExecData *stats) {
rz_bv_free(stats->ctr_tmp_read);
rz_bv_free(stats->gpr_tmp_read);
rz_bv_free(stats->pred_tmp_read);
}
RZ_IPI void hex_il_pkt_stats_init(HexILExecData *stats) {
rz_return_if_fail(stats);
stats->slot_cancelled = rz_bv_new(64);
stats->ctr_written = rz_bv_new(64);
stats->gpr_written = rz_bv_new(64);
@ -878,4 +879,9 @@ RZ_IPI void hex_reset_il_pkt_stats(HexILExecData *stats) {
stats->pred_tmp_read = rz_bv_new(32);
}
RZ_IPI void hex_il_pkt_stats_reset(HexILExecData *stats) {
hex_il_pkt_stats_fini(stats);
hex_il_pkt_stats_init(stats);
}
#include <rz_il/rz_il_opbuilder_end.h>

View file

@ -56,7 +56,7 @@ static const ut64 hex_ctr_immut_masks[32] = {
};
RZ_IPI bool hex_shuffle_insns(RZ_INOUT HexPkt *p);
RZ_IPI RzILOpEffect *hex_get_il_op(const ut32 addr, const bool get_pkt_op);
RZ_IPI RZ_OWN RzILOpEffect *hex_get_il_op(const ut32 addr, const bool get_pkt_op, RZ_NONNULL HexState *state);
RZ_IPI RZ_OWN RzILOpPure *hex_get_rf_property_val(const HexRegFieldProperty property, const HexRegField field);
RZ_IPI RZ_OWN RzILOpEffect *hex_get_npc(const HexPkt *pkt);
RZ_IPI RZ_OWN RzILOpEffect *hex_il_op_jump_flag_init(HexInsnPktBundle *bundle);
@ -65,7 +65,9 @@ RZ_IPI RZ_OWN RzILOpEffect *hex_commit_packet(HexInsnPktBundle *bundle);
RZ_IPI RZ_OWN RzILOpEffect *hex_write_reg(RZ_BORROW HexInsnPktBundle *bundle, const HexOp *op, RzILOpPure *val);
RZ_IPI RZ_OWN RzILOpPure *hex_read_reg(RZ_BORROW HexPkt *pkt, const HexOp *op, bool tmp_reg);
RZ_IPI RZ_OWN RzILOpEffect *hex_cancel_slot(RZ_BORROW HexPkt *pkt, ut8 slot);
RZ_IPI void hex_reset_il_pkt_stats(HexILExecData *stats);
RZ_IPI void hex_il_pkt_stats_reset(HexILExecData *stats);
RZ_IPI void hex_il_pkt_stats_init(HexILExecData *stats);
RZ_IPI void hex_il_pkt_stats_fini(HexILExecData *stats);
RzILOpPure *hex_get_corresponding_cs(RZ_BORROW HexPkt *pkt, const HexOp *Mu);
RzILOpEffect *hex_il_op_a2_abs(HexInsnPktBundle *bundle);
RzILOpEffect *hex_il_op_a2_absp(HexInsnPktBundle *bundle);

View file

@ -945,7 +945,7 @@ RZ_IPI RZ_OWN RzILOpEffect *hex_commit_packet(HexInsnPktBundle *bundle) {
commit_seq = SEQ2(commit_seq, SETG(dest_reg, VARG(src_reg)));
}
hex_reset_il_pkt_stats(stats);
hex_il_pkt_stats_reset(stats);
return commit_seq;
}

View file

@ -20,7 +20,7 @@
#include <hexagon/hexagon_il.h>
RZ_API int hexagon_v6_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) {
rz_return_val_if_fail(analysis && op && buf, -1);
rz_return_val_if_fail(analysis && op, -1);
if (len < HEX_INSN_SIZE) {
return -1;
}
@ -29,31 +29,22 @@ RZ_API int hexagon_v6_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, cons
}
// Disassemble as many instructions as possible from the buffer.
ut32 buf_offset = 0;
while (buf_offset + HEX_INSN_SIZE <= len && buf_offset <= HEX_INSN_SIZE * HEX_MAX_INSN_PER_PKT) {
const ut32 buf_ptr = rz_read_at_le32(buf, buf_offset);
if (buf_offset > 0 && (buf_ptr == HEX_INVALID_INSN_0 || buf_ptr == HEX_INVALID_INSN_F)) {
// Do not disassemble invalid instructions, if we already have a valid one.
break;
}
HexReversedOpcode rev = { .action = HEXAGON_ANALYSIS, .ana_op = op, .asm_op = NULL };
hexagon_reverse_opcode(NULL, &rev, buf + buf_offset, addr + buf_offset, false);
buf_offset += HEX_INSN_SIZE;
}
// Copy operation actually requested.
HexReversedOpcode rev = { .action = HEXAGON_ANALYSIS, .ana_op = op, .asm_op = NULL };
hexagon_reverse_opcode(NULL, &rev, buf, addr, true);
bool decoded_packet = len > HEX_INSN_SIZE;
HexReversedOpcode rev = { .action = HEXAGON_ANALYSIS, .ana_op = op, .asm_op = NULL, .state = NULL, .pkt_fully_decoded = false, .bytes_buf = buf, .bytes_buf_len = len };
hexagon_reverse_opcode(&rev, addr, NULL, analysis);
if (mask & RZ_ANALYSIS_OP_MASK_IL) {
op->il_op = hex_get_il_op(addr, decoded_packet);
op->il_op = hex_get_il_op(addr, rev.pkt_fully_decoded, rev.state);
}
return HEX_INSN_SIZE;
}
static RzAnalysisILConfig *rz_hexagon_il_config(RzAnalysis *a) {
HexState *state = hexagon_state(false);
rz_return_val_if_fail(a, NULL);
// Hacky getter for the plugin data until RzArch is implemented
RzAsm *rasm = rz_analysis_to_rz_asm(a);
HexState *state = rasm->plugin_data;
rz_return_val_if_fail(state, NULL);
state->just_init = true;
return rz_analysis_il_config_new(32, a->big_endian, 32);
}

View file

@ -116,10 +116,7 @@ static RZ_OWN RzPVector /*<RzAsmTokenPattern *>*/ *get_token_patterns() {
*/
static bool hex_cfg_set(void *user, void *data) {
rz_return_val_if_fail(user && data, false);
HexState *state = hexagon_state(false);
if (!state) {
return false;
}
HexState *state = user;
RzConfig *pcfg = state->cfg;
RzConfigNode *cnode = (RzConfigNode *)data; // Config node from core.
@ -129,30 +126,21 @@ static bool hex_cfg_set(void *user, void *data) {
}
if (cnode) {
pnode->i_value = cnode->i_value;
free(pnode->value);
pnode->value = rz_str_dup(cnode->value);
return true;
}
return false;
}
RZ_IPI void hexagon_state_fini(HexState *state) {
if (!state) {
return;
}
rz_config_free(state->cfg);
rz_pvector_free(state->token_patterns);
rz_list_free(state->const_ext_l);
return;
}
static bool hexagon_fini(void *user) {
hexagon_state_fini(hexagon_state(false));
hexagon_state(true);
hexagon_state_fini(user);
free(user);
return true;
}
static bool hexagon_init(void **user) {
HexState *state = hexagon_state(false);
static bool hexagon_init(void **plugin_data) {
HexState *state = hexagon_state_new();
rz_return_val_if_fail(state, false);
state->cfg = rz_config_new(state);
@ -170,13 +158,14 @@ static bool hexagon_init(void **user) {
}
rz_asm_compile_token_patterns(state->token_patterns);
*plugin_data = state;
return true;
}
RZ_API RZ_BORROW RzConfig *hexagon_get_config() {
HexState *state = hexagon_state(false);
rz_return_val_if_fail(state, NULL);
return state->cfg;
RZ_API RZ_OWN RzConfig *hexagon_get_config(void *plugin_data) {
rz_return_val_if_fail(plugin_data, NULL);
HexState *state = plugin_data;
return rz_config_clone(state->cfg);
}
/**
@ -189,27 +178,14 @@ RZ_API RZ_BORROW RzConfig *hexagon_get_config() {
* \return int Size of the reversed opcode.
*/
static int disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int l) {
rz_return_val_if_fail(a && op && buf, -1);
rz_return_val_if_fail(a && op, -1);
if (l < HEX_INSN_SIZE) {
return -1;
}
ut32 addr = (ut32)a->pc;
// Disassemble as many instructions as possible from the buffer.
ut32 buf_offset = 0;
while (buf_offset + HEX_INSN_SIZE <= l && buf_offset <= HEX_INSN_SIZE * HEX_MAX_INSN_PER_PKT) {
const ut32 buf_ptr = rz_read_at_le32(buf, buf_offset);
if (buf_offset > 0 && (buf_ptr == HEX_INVALID_INSN_0 || buf_ptr == HEX_INVALID_INSN_F)) {
// Do not disassemble invalid instructions, if we already have a valid one.
break;
}
HexReversedOpcode rev = { .action = HEXAGON_DISAS, .ana_op = NULL, .asm_op = op };
hexagon_reverse_opcode(a, &rev, buf + buf_offset, addr + buf_offset, false);
buf_offset += HEX_INSN_SIZE;
}
// Copy operation actually requested.
HexReversedOpcode rev = { .action = HEXAGON_DISAS, .ana_op = NULL, .asm_op = op };
hexagon_reverse_opcode(a, &rev, buf, addr, true);
ut32 addr = (ut32)a->pc;
HexReversedOpcode rev = { .action = HEXAGON_DISAS, .ana_op = NULL, .asm_op = op, .state = NULL, .pkt_fully_decoded = false, .bytes_buf = buf, .bytes_buf_len = l };
hexagon_reverse_opcode(&rev, addr, a, NULL);
return HEX_INSN_SIZE;
}

View file

@ -17,7 +17,7 @@ RZ_API RZ_OWN RzConfigNode *rz_config_node_new(RZ_NONNULL const char *name, RZ_N
return node;
}
RZ_API RZ_OWN RzConfigNode *rz_config_node_clone(RzConfigNode *n) {
RZ_API RZ_OWN RzConfigNode *rz_config_node_clone(RZ_BORROW RzConfigNode *n) {
rz_return_val_if_fail(n, NULL);
RzConfigNode *cn = RZ_NEW0(RzConfigNode);
if (!cn) {
@ -45,7 +45,7 @@ RZ_API void rz_config_node_free(RZ_NULLABLE void *n) {
free(node);
}
RZ_API RZ_BORROW RzConfigNode *rz_config_node_get(RzConfig *cfg, RZ_NONNULL const char *name) {
RZ_API RZ_BORROW RzConfigNode *rz_config_node_get(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name) {
rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), NULL);
return ht_sp_find(cfg->ht, name, NULL);
}
@ -94,7 +94,7 @@ RZ_API RZ_BORROW const char *rz_config_get(RzConfig *cfg, RZ_NONNULL const char
* the variable is boolean, then tries to write back the inverted value.
* Returns true in case of success.
*/
RZ_API bool rz_config_toggle(RzConfig *cfg, RZ_NONNULL const char *name) {
RZ_API bool rz_config_toggle(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name) {
rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), false);
RzConfigNode *node = rz_config_node_get(cfg, name);
if (!node) {
@ -170,7 +170,7 @@ RZ_API const char *rz_config_node_type(RzConfigNode *node) {
return "";
}
RZ_API RzConfigNode *rz_config_set_cb(RzConfig *cfg, const char *name, const char *value, RzConfigCallback cb) {
RZ_API RZ_BORROW RzConfigNode *rz_config_set_cb(RZ_BORROW RzConfig *cfg, const char *name, const char *value, RzConfigCallback cb) {
RzConfigNode *node = rz_config_set(cfg, name, value);
if (node && (node->setter = cb)) {
if (!cb(cfg->user, node)) {
@ -180,7 +180,7 @@ RZ_API RzConfigNode *rz_config_set_cb(RzConfig *cfg, const char *name, const cha
return node;
}
RZ_API RzConfigNode *rz_config_set_i_cb(RzConfig *cfg, const char *name, int ivalue, RzConfigCallback cb) {
RZ_API RZ_BORROW RzConfigNode *rz_config_set_i_cb(RZ_BORROW RzConfig *cfg, const char *name, int ivalue, RzConfigCallback cb) {
RzConfigNode *node = rz_config_set_i(cfg, name, ivalue);
if (node && (node->setter = cb)) {
if (!node->setter(cfg->user, node)) {
@ -198,7 +198,7 @@ static bool __is_true_or_false(const char *s) {
* Writes the boolean \p value in the config variable of \p name only and only if
* the variable is boolean.
*/
RZ_API RzConfigNode *rz_config_set_b(RzConfig *cfg, RZ_NONNULL const char *name, bool value) {
RZ_API RZ_BORROW RzConfigNode *rz_config_set_b(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name, bool value) {
rz_return_val_if_fail(cfg && cfg->ht, NULL);
rz_return_val_if_fail(RZ_STR_ISNOTEMPTY(name), NULL);
@ -264,7 +264,7 @@ beach:
/**
* Writes the string \p value in the config variable of \p name.
*/
RZ_API RzConfigNode *rz_config_set(RzConfig *cfg, RZ_NONNULL const char *name, const char *value) {
RZ_API RZ_BORROW RzConfigNode *rz_config_set(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name, const char *value) {
rz_return_val_if_fail(cfg && cfg->ht, NULL);
rz_return_val_if_fail(RZ_STR_ISNOTEMPTY(name), NULL);
@ -400,7 +400,7 @@ RZ_API bool rz_config_rm(RzConfig *cfg, RZ_NONNULL const char *name) {
return false;
}
RZ_API void rz_config_node_value_format_i(char *buf, size_t buf_size, const ut64 i, RZ_NULLABLE RzConfigNode *node) {
RZ_API void rz_config_node_value_format_i(RZ_OUT char *buf, size_t buf_size, const ut64 i, RZ_NULLABLE RzConfigNode *node) {
if (node && rz_config_node_is_bool(node)) {
rz_str_ncpy(buf, rz_str_bool((int)i), buf_size);
return;
@ -416,7 +416,7 @@ RZ_API void rz_config_node_value_format_i(char *buf, size_t buf_size, const ut64
* Writes the integer \p value in the config variable of \p name only and only if
* the variable is integer.
*/
RZ_API RzConfigNode *rz_config_set_i(RzConfig *cfg, RZ_NONNULL const char *name, const ut64 i) {
RZ_API RZ_BORROW RzConfigNode *rz_config_set_i(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name, const ut64 i) {
char buf[128], *ov = NULL;
rz_return_val_if_fail(cfg && name, NULL);
RzConfigNode *node = rz_config_node_get(cfg, name);
@ -473,12 +473,12 @@ static int cmp(RzConfigNode *a, RzConfigNode *b, void *user) {
return strcmp(a->name, b->name);
}
RZ_API void rz_config_lock(RzConfig *cfg, int l) {
RZ_API void rz_config_lock(RZ_BORROW RzConfig *cfg, int l) {
rz_list_sort(cfg->nodes, (RzListComparator)cmp, NULL);
cfg->lock = l;
}
RZ_API bool rz_config_readonly(RzConfig *cfg, const char *key) {
RZ_API bool rz_config_readonly(RZ_BORROW RzConfig *cfg, const char *key) {
RzConfigNode *n = rz_config_node_get(cfg, key);
if (n) {
n->flags |= CN_RO;
@ -487,7 +487,7 @@ RZ_API bool rz_config_readonly(RzConfig *cfg, const char *key) {
return false;
}
RZ_API RzConfig *rz_config_new(void *user) {
RZ_API RZ_OWN RzConfig *rz_config_new(RZ_BORROW void *user) {
RzConfig *cfg = RZ_NEW0(RzConfig);
if (!cfg) {
return NULL;
@ -504,7 +504,8 @@ RZ_API RzConfig *rz_config_new(void *user) {
return cfg;
}
RZ_API RzConfig *rz_config_clone(RzConfig *cfg) {
RZ_API RZ_OWN RzConfig *rz_config_clone(RZ_BORROW RzConfig *cfg) {
rz_return_val_if_fail(cfg, NULL);
RzListIter *iter;
RzConfigNode *node;
RzConfig *c = rz_config_new(cfg->user);
@ -520,7 +521,7 @@ RZ_API RzConfig *rz_config_clone(RzConfig *cfg) {
return c;
}
RZ_API void rz_config_free(RzConfig *cfg) {
RZ_API void rz_config_free(RZ_OWN RzConfig *cfg) {
if (cfg) {
cfg->nodes->free = rz_config_node_free;
rz_list_free(cfg->nodes);
@ -536,7 +537,7 @@ RZ_API void rz_config_visual_hit_i(RzConfig *cfg, const char *name, int delta) {
}
}
RZ_API void rz_config_bump(RzConfig *cfg, const char *key) {
RZ_API void rz_config_bump(RZ_BORROW RzConfig *cfg, const char *key) {
char *orig = rz_str_dup(rz_config_get(cfg, key));
if (orig) {
rz_config_set(cfg, key, orig);

View file

@ -555,6 +555,16 @@ static void autocmplt_cmd_arg_eval_key(RzCore *core, RzLineNSCompletionResult *r
rz_line_ns_completion_result_add(res, bt->name);
}
}
RzConfig **plugin_cfg;
RzIterator *it = ht_sp_as_iter(core->plugin_configs);
rz_iterator_foreach(it, plugin_cfg) {
rz_list_foreach ((*plugin_cfg)->nodes, iter, bt) {
if (!strncmp(bt->name, s, len)) {
rz_line_ns_completion_result_add(res, bt->name);
}
}
}
rz_iterator_free(it);
}
static void autocmplt_cmd_arg_eval_full(RzCore *core, RzLineNSCompletionResult *res, const char *s, size_t len) {

View file

@ -5,6 +5,7 @@
#include <stdbool.h>
#include <rz_core.h>
#include <rz_util/rz_set.h>
#include <rz_util/rz_str.h>
#include "../core_private.h"
static bool load_theme(RzCore *core, const char *path) {
@ -346,6 +347,48 @@ RZ_IPI RzCmdStatus rz_cmd_eval_color_highlight_remove_current_handler(RzCore *co
return RZ_CMD_STATUS_OK;
}
static void print_all_plugin_configs(const RzCore *core) {
// Incomplete plugin config key.
RzConfig **cfg;
RzCmdStateOutput state = { 0 };
rz_cmd_state_output_init(&state, RZ_OUTPUT_MODE_QUIET);
RzIterator *it = ht_sp_as_iter(core->plugin_configs);
rz_iterator_foreach(it, cfg) {
rz_core_config_print_all(*cfg, "", &state);
}
rz_iterator_free(it);
rz_cmd_state_output_print(&state);
rz_cmd_state_output_fini(&state);
}
static RZ_BORROW RzConfig *eval_get_config_obj_by_key(const RzCore *core, const char *config_str) {
rz_return_val_if_fail(core && config_str, NULL);
RzConfig *cfg = NULL;
if (!rz_str_startswith(config_str, "plugins")) {
return core->config;
}
// Plugin config. Check for name.
const char *first_dot = strchr(config_str, '.');
if (!first_dot) {
return NULL;
}
const char *second_dot = strchr(first_dot + 1, '.');
bool cfg_found = false;
if (!second_dot) {
cfg = ht_sp_find(core->plugin_configs, first_dot + 1, &cfg_found);
} else {
char *config_name = rz_sub_str_ptr(config_str, first_dot + 1, second_dot - 1);
cfg = ht_sp_find(core->plugin_configs, config_name, &cfg_found);
free(config_name);
}
if (!cfg_found) {
RZ_LOG_DEBUG("Did not find plugin config with name '%s'\n", config_str);
return NULL;
}
return cfg;
}
RZ_IPI RzCmdStatus rz_eval_getset_handler(RzCore *core, int argc, const char **argv) {
int i;
for (i = 1; i < argc; i++) {
@ -364,16 +407,21 @@ RZ_IPI RzCmdStatus rz_eval_getset_handler(RzCore *core, int argc, const char **a
continue;
}
RzConfig *cfg = NULL;
if (!(cfg = eval_get_config_obj_by_key(core, key))) {
print_all_plugin_configs(core);
return RZ_CMD_STATUS_OK;
}
if (llen == 1 && rz_str_endswith(key, ".")) {
// no value was set, only key with ".". List possible sub-keys.
RzCmdStateOutput state = { 0 };
rz_cmd_state_output_init(&state, RZ_OUTPUT_MODE_QUIET);
rz_core_config_print_all(core->config, key, &state);
rz_core_config_print_all(cfg, key, &state);
rz_cmd_state_output_print(&state);
rz_cmd_state_output_fini(&state);
} else if (llen == 1) {
// no value was set, show the value of the key
const char *v = rz_config_get(core->config, key);
const char *v = rz_config_get(cfg, key);
if (!v) {
RZ_LOG_ERROR("core: Invalid config key '%s'\n", key);
rz_list_free(l);
@ -382,7 +430,7 @@ RZ_IPI RzCmdStatus rz_eval_getset_handler(RzCore *core, int argc, const char **a
rz_cons_printf("%s\n", v);
} else if (llen == 2) {
char *value = rz_list_get_n(l, 1);
rz_config_set(core->config, key, value);
rz_config_set(cfg, key, value);
}
rz_list_free(l);
}
@ -391,7 +439,12 @@ RZ_IPI RzCmdStatus rz_eval_getset_handler(RzCore *core, int argc, const char **a
RZ_IPI RzCmdStatus rz_eval_list_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
const char *arg = argc > 1 ? argv[1] : "";
rz_core_config_print_all(core->config, arg, state);
RzConfig *cfg = NULL;
if (!(cfg = eval_get_config_obj_by_key(core, arg))) {
print_all_plugin_configs(core);
return RZ_CMD_STATUS_OK;
}
rz_core_config_print_all(cfg, arg, state);
return RZ_CMD_STATUS_OK;
}
@ -400,7 +453,12 @@ RZ_IPI RzCmdStatus rz_eval_reset_handler(RzCore *core, int argc, const char **ar
}
RZ_IPI RzCmdStatus rz_eval_bool_invert_handler(RzCore *core, int argc, const char **argv) {
if (!rz_config_toggle(core->config, argv[1])) {
RzConfig *cfg = NULL;
if (!(cfg = eval_get_config_obj_by_key(core, argv[1]))) {
print_all_plugin_configs(core);
return RZ_CMD_STATUS_OK;
}
if (!rz_config_toggle(cfg, argv[1])) {
RZ_LOG_ERROR("core: Cannot toggle config key '%s'\n", argv[1]);
return RZ_CMD_STATUS_ERROR;
}
@ -408,7 +466,12 @@ RZ_IPI RzCmdStatus rz_eval_bool_invert_handler(RzCore *core, int argc, const cha
}
RZ_IPI RzCmdStatus rz_eval_editor_handler(RzCore *core, int argc, const char **argv) {
const char *val = rz_config_get(core->config, argv[1]);
RzConfig *cfg = NULL;
if (!(cfg = eval_get_config_obj_by_key(core, argv[1]))) {
print_all_plugin_configs(core);
return RZ_CMD_STATUS_OK;
}
const char *val = rz_config_get(cfg, argv[1]);
if (!val) {
RZ_LOG_ERROR("core: Invalid config key '%s'\n", argv[1]);
return RZ_CMD_STATUS_ERROR;
@ -418,12 +481,17 @@ RZ_IPI RzCmdStatus rz_eval_editor_handler(RzCore *core, int argc, const char **a
return RZ_CMD_STATUS_ERROR;
}
rz_str_replace_char(p, '\n', ';');
rz_config_set(core->config, argv[1], p);
rz_config_set(cfg, argv[1], p);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_eval_readonly_handler(RzCore *core, int argc, const char **argv) {
if (!rz_config_readonly(core->config, argv[1])) {
RzConfig *cfg = NULL;
if (!(cfg = eval_get_config_obj_by_key(core, argv[1]))) {
print_all_plugin_configs(core);
return RZ_CMD_STATUS_OK;
}
if (!rz_config_readonly(cfg, argv[1])) {
RZ_LOG_ERROR("core: Cannot make eval '%s' readonly.\n", argv[1]);
return RZ_CMD_STATUS_ERROR;
}
@ -446,7 +514,12 @@ RZ_IPI RzCmdStatus rz_eval_spaces_handler(RzCore *core, int argc, const char **a
}
RZ_IPI RzCmdStatus rz_eval_type_handler(RzCore *core, int argc, const char **argv) {
RzConfigNode *node = rz_config_node_get(core->config, argv[1]);
RzConfig *cfg = NULL;
if (!(cfg = eval_get_config_obj_by_key(core, argv[1]))) {
print_all_plugin_configs(core);
return RZ_CMD_STATUS_OK;
}
RzConfigNode *node = rz_config_node_get(cfg, argv[1]);
if (!node) {
RZ_LOG_ERROR("core: Cannot find eval '%s'.\n", argv[1]);
return RZ_CMD_STATUS_ERROR;

View file

@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2009-2020 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_config.h>
#include <rz_util/ht_sp.h>
#include <rz_util/rz_regex.h>
#include <rz_vector.h>
#include <rz_core.h>
@ -1506,6 +1508,7 @@ RZ_API bool rz_core_init(RzCore *core) {
core->cmdremote = 0;
core->incomment = false;
core->config = NULL;
core->plugin_configs = ht_sp_new(HT_STR_DUP, NULL, (HtSPFreeValue)rz_config_free);
core->http_up = false;
ZERO_FILL(core->root_cmd_descriptor);
core->print = rz_print_new();

View file

@ -21,6 +21,7 @@ RZ_API bool rz_core_plugin_fini(RzCore *core) {
}
}
rz_list_free(core->plugins);
ht_sp_free(core->plugin_configs);
core->plugins = NULL;
return true;
}
@ -28,6 +29,7 @@ RZ_API bool rz_core_plugin_fini(RzCore *core) {
RZ_API bool rz_core_plugin_add(RzCore *core, RZ_NONNULL RzCorePlugin *plugin) {
rz_return_val_if_fail(core, false);
rz_return_val_if_fail(plugin && plugin->init && plugin->name && plugin->author && plugin->license, false);
// TODO: Add config from core plugin.
RZ_PLUGIN_CHECK_AND_ADD(core->plugins, plugin, RzCorePlugin);
if (!plugin->init(core)) {
RZ_PLUGIN_REMOVE(core->plugins, plugin);
@ -38,6 +40,7 @@ RZ_API bool rz_core_plugin_add(RzCore *core, RZ_NONNULL RzCorePlugin *plugin) {
RZ_API bool rz_core_plugin_del(RzCore *core, RZ_NONNULL RzCorePlugin *plugin) {
rz_return_val_if_fail(core && plugin, false);
ht_sp_delete(core->plugin_configs, plugin->name);
if (plugin->fini && !plugin->fini(core)) {
return false;
}

View file

@ -462,6 +462,10 @@ typedef struct {
} RzAnalysisDebugInfo;
typedef struct rz_analysis_t {
void *core;
ut8 ptr_alignment_I;
// NOTE: Do not change the order of fields above!
// They are used in pointer passing hacks in rz_types.h.
char *cpu; // analysis.cpu
char *os; // asm.os
int bits; // asm.bits
@ -470,7 +474,6 @@ typedef struct rz_analysis_t {
int sleep; // analysis.sleep, sleep some usecs before analyzing more (avoid 100% cpu usages)
RzAnalysisCPPABI cpp_abi; // analysis.cpp.abi
void *plugin_data;
void *core;
ut64 gp; // analysis.gp, global pointer. used for mips. but can be used by other arches too in the future
RBTree bb_tree; // all basic blocks by address. They can overlap each other, but must never start at the same address.
RzList /*<RzAnalysisFunction *>*/ *fcns;

View file

@ -95,13 +95,17 @@ typedef struct {
#define _RzAsmPlugin struct rz_asm_plugin_t
typedef struct rz_asm_t {
void *core;
ut8 ptr_alignment_I;
void *plugin_data;
ut8 ptr_alignment_II;
// NOTE: Do not change the order of fields above!
// They are used in pointer passing hacks in rz_types.h.
char *cpu;
int bits;
int big_endian;
int syntax;
ut64 pc;
void *core;
void *plugin_data;
_RzAsmPlugin *cur;
_RzAsmPlugin *acur;
RzList /*<RzAsmPlugin *>*/ *plugins;
@ -140,7 +144,7 @@ typedef struct rz_asm_plugin_t {
int (*disassemble)(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len);
int (*assemble)(RzAsm *a, RzAsmOp *op, const char *buf);
char *(*mnemonics)(RzAsm *a, int id, bool json);
RzConfig *(*get_config)(void);
RZ_OWN RzConfig *(*get_config)(void *plugin_data);
const char *features;
const char *platforms;
} RzAsmPlugin;

View file

@ -82,16 +82,16 @@ RZ_API bool rz_config_hold_s(RzConfigHold *h, ...);
RZ_API void rz_config_hold_restore(RzConfigHold *h);
RZ_API RzConfig *rz_config_new(void *user);
RZ_API RzConfig *rz_config_clone(RzConfig *cfg);
RZ_API void rz_config_free(RzConfig *cfg);
RZ_API void rz_config_lock(RzConfig *cfg, int l);
RZ_API void rz_config_bump(RzConfig *cfg, const char *key);
RZ_API RzConfigNode *rz_config_set_i(RzConfig *cfg, RZ_NONNULL const char *name, const ut64 i);
RZ_API RzConfigNode *rz_config_set_b(RzConfig *cfg, RZ_NONNULL const char *name, bool value);
RZ_API RzConfigNode *rz_config_set_cb(RzConfig *cfg, const char *name, const char *value, bool (*callback)(void *user, void *data));
RZ_API RzConfigNode *rz_config_set_i_cb(RzConfig *cfg, const char *name, int ivalue, bool (*callback)(void *user, void *data));
RZ_API RzConfigNode *rz_config_set(RzConfig *cfg, RZ_NONNULL const char *name, const char *value);
RZ_API RZ_OWN RzConfig *rz_config_new(RZ_BORROW void *user);
RZ_API RZ_OWN RzConfig *rz_config_clone(RZ_BORROW RzConfig *cfg);
RZ_API void rz_config_free(RZ_OWN RzConfig *cfg);
RZ_API void rz_config_lock(RZ_BORROW RzConfig *cfg, int l);
RZ_API void rz_config_bump(RZ_BORROW RzConfig *cfg, const char *key);
RZ_API RZ_BORROW RzConfigNode *rz_config_set_i(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name, const ut64 i);
RZ_API RZ_BORROW RzConfigNode *rz_config_set_b(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name, bool value);
RZ_API RZ_BORROW RzConfigNode *rz_config_set_cb(RZ_BORROW RzConfig *cfg, const char *name, const char *value, bool (*callback)(void *user, void *data));
RZ_API RZ_BORROW RzConfigNode *rz_config_set_i_cb(RZ_BORROW RzConfig *cfg, const char *name, int ivalue, bool (*callback)(void *user, void *data));
RZ_API RZ_BORROW RzConfigNode *rz_config_set(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name, const char *value);
RZ_API bool rz_config_add_node(RZ_BORROW RzConfig *cfg, RZ_OWN RzConfigNode *node);
RZ_API bool rz_config_rm(RzConfig *cfg, RZ_NONNULL const char *name);
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name);
@ -99,13 +99,13 @@ RZ_API bool rz_config_get_b(RzConfig *cfg, RZ_NONNULL const char *name);
RZ_API RZ_BORROW const char *rz_config_get(RzConfig *cfg, RZ_NONNULL const char *name);
RZ_API const char *rz_config_desc(RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc);
RZ_API const char *rz_config_node_desc(RzConfigNode *node, RZ_NULLABLE const char *desc);
RZ_API RZ_BORROW RzConfigNode *rz_config_node_get(RzConfig *cfg, RZ_NONNULL const char *name);
RZ_API RZ_BORROW RzConfigNode *rz_config_node_get(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name);
RZ_API RZ_OWN RzConfigNode *rz_config_node_new(RZ_NONNULL const char *name, RZ_NONNULL const char *value);
RZ_API RZ_OWN RzConfigNode *rz_config_node_clone(RzConfigNode *n);
RZ_API RZ_OWN RzConfigNode *rz_config_node_clone(RZ_BORROW RzConfigNode *n);
RZ_API void rz_config_node_free(RZ_NULLABLE void *n);
RZ_API void rz_config_node_value_format_i(char *buf, size_t buf_size, const ut64 i, RZ_NULLABLE RzConfigNode *node);
RZ_API bool rz_config_toggle(RzConfig *cfg, RZ_NONNULL const char *name);
RZ_API bool rz_config_readonly(RzConfig *cfg, const char *key);
RZ_API void rz_config_node_value_format_i(RZ_OUT char *buf, size_t buf_size, const ut64 i, RZ_NULLABLE RzConfigNode *node);
RZ_API bool rz_config_toggle(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name);
RZ_API bool rz_config_readonly(RZ_BORROW RzConfig *cfg, const char *key);
RZ_API bool rz_config_eval(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *str);
RZ_API bool rz_config_set_setter(RzConfig *cfg, const char *key, RzConfigCallback cb);

View file

@ -243,9 +243,18 @@ typedef struct rz_core_seek_history_t {
} RzCoreSeekHistory;
struct rz_core_t {
RzAsm *rasm;
ut8 ptr_alignment_I;
RzAnalysis *analysis;
ut8 ptr_alignment_II;
RzBin *bin;
ut8 ptr_alignment_III;
// NOTE: Do not change the order of fields above!
// They are used in pointer passing hacks in rz_types.h.
RzIO *io;
RzList /*<RzCorePlugin *>*/ *plugins; ///< List of registered core plugins
RzConfig *config;
HtSP /*<plugins.<plugin_name>: RzConfig>*/ *plugin_configs; ///< Pointers to plugin configurations. Indexed by "plugins.<name>"
ut64 offset; // current seek
ut64 prompt_offset; // temporarily set to offset to have $$ in expressions always stay the same during temp seeks
ut32 blocksize;
@ -258,7 +267,6 @@ struct rz_core_t {
int interrupted; // XXX IS THIS DUPPED SOMEWHERE?
/* files */
RzCons *cons;
RzIO *io;
RzCoreFile *file;
RzList /*<RzCoreFile *>*/ *files;
RzNum *num;
@ -267,8 +275,6 @@ struct rz_core_t {
RzCmd *rcmd;
RzCmdDescriptor root_cmd_descriptor;
RzList /*<RzCmdDescriptor *>*/ *cmd_descriptors;
RzAnalysis *analysis;
RzAsm *rasm;
/* ^^ */
RzCoreTimes *times;
RzParse *parser;

View file

@ -663,4 +663,70 @@ typedef int RzRef;
typedef struct rz_core_t RzCore;
// Mimics order in RzCore.
struct dummy_rz_core_t {
void *rasm;
ut8 ptr_alignment_I;
void *analysis;
ut8 ptr_alignment_II;
void *bin;
ut8 ptr_alignment_III;
};
// Mimics order in RzAsm.
struct dummy_rz_asm_t {
void *core;
ut8 ptr_alignment_I;
void *plugin_data;
ut8 ptr_alignment_II;
};
// Mimics order in RzAnalysis.
struct dummy_rz_analysis_t {
void *core;
ut8 ptr_alignment_I;
};
/**
* \brief The hacky way to get the RzAsm pointer from RzAnalysis.
* Will be removed with the RzArch refactor.
*/
static inline void /*<RzAsm>*/ *rz_analysis_to_rz_asm(RZ_NONNULL void /*<RzAnalysis>*/ *rz_analysis) {
assert(rz_analysis && "This function can only be used if RzAnalysis and RzAsm were set up before.");
struct dummy_rz_analysis_t *analysis = (struct dummy_rz_analysis_t *)rz_analysis;
struct dummy_rz_core_t *core = (struct dummy_rz_core_t *)analysis->core;
if (!core) {
return NULL;
}
void *rasm = core->rasm;
assert(rasm && "This function can only be used if RzAnalysis and RzAsm were set up before.");
return rasm;
}
/**
* \brief The hacky way to get the RzAnalysis pointer from RzAsm.
* Will be removed with the RzArch refactor.
*/
static inline void /*<RzAnalysis>*/ *rz_asm_to_rz_analysis(RZ_NONNULL void /*<RzAsm>*/ *rz_asm) {
assert(rz_asm && "This function can only be used if RzAnalysis and RzAsm were set up before.");
struct dummy_rz_asm_t *rasm = (struct dummy_rz_asm_t *)rz_asm;
struct dummy_rz_core_t *core = (struct dummy_rz_core_t *)rasm->core;
if (!core) {
return NULL;
}
void *analysis = core->analysis;
return analysis;
}
/**
* \brief The hacky way to get the plugin data from RzAsm via RzAnalysis.
* Will be removed with the RzArch refactor.
*/
static inline void *rz_asm_plugin_data_from_rz_analysis(RZ_NONNULL void /*<RzAnalysis>*/ *rz_analysis) {
assert(rz_analysis && "This function can only be used if RzAnalysis and RzAsm were set up before.");
struct dummy_rz_asm_t *rasm = (struct dummy_rz_asm_t *)rz_analysis_to_rz_asm(rz_analysis);
assert(rasm && "This function can only be used if RzAnalysis and RzAsm were set up before.");
return rasm->plugin_data;
}
#endif // RZ_TYPES_H

View file

@ -8,7 +8,7 @@ aaa
afx
EOF
EXPECT=<<EOF
c 0x00005124 -> 0x00005128 ? jump 0x5128
c 0x00005124 -> 0x00005128 [ jump 0x5128
c 0x00005130 -> 0x00005134 [ if (P0) jump:nt 0x5154
c 0x00005130 -> 0x00005154 [ if (P0) jump:nt 0x5154
c 0x00005134 -> 0x00005138 [ jump 0x5138
@ -29,12 +29,12 @@ s 0x0000539c
pi 4
EOF
EXPECT=<<EOF
? immext(##0xb0c0)
? R0 = ##loc._MSG_BASE
? immext(##0xd180)
? R2 = ##0xd1ac
? immext(##0xfe105000)
? R3 = ##-0x1efb000
/ immext(##0xb0c0)
\ R0 = ##loc._MSG_BASE
/ immext(##0xd180)
| R2 = ##0xd1ac
| immext(##0xfe105000)
\ R3 = ##-0x1efb000
EOF
RUN
@ -102,7 +102,6 @@ RUN
NAME=hexagon extended immediate search
FILE=bins/elf/analysis/hexagon-hello-loop
BROKEN=1
CMDS=<<EOF
b 0x100000
aar
@ -110,12 +109,12 @@ aar
/ai sym.coredump
EOF
EXPECT=<<EOF
0x000051d4 # 4: ? R1 = ##0x5410
0x00000b70 # 4: ? jump sym.coredump
0x00000b7c # 4: ? jump sym.coredump
0x00000b8c # 4: ? jump sym.coredump
0x00000f48 # 4: ? jump sym.coredump
0x000051f0 # 4: ? R28 = ##sym.coredump
0x000051d4 # 4: \ R1 = ##sym.sys_TLSFreeAll
0x00000b70 # 4: [ jump sym.coredump
0x00000b7c # 4: [ jump sym.coredump
0x00000b8c # 4: [ jump sym.coredump
0x00000f48 # 4: [ jump sym.coredump
0x000051f0 # 4: | R28 = ##sym.coredump
EOF
RUN
@ -452,7 +451,7 @@ EXPECT=<<EOF
; CALL XREF from sym.__libc_start_main @ 0x5e98
/ int main(int argc, char **argv, char **envp);
| ; arg int argc @ R0
| 0x00005110 ? allocframe(SP,#0x8):raw
| 0x00005110 [ allocframe(SP,#0x8):raw
EOF
RUN
@ -469,7 +468,7 @@ EXPECT=<<EOF
| ; CALL XREF from sym.__libc_start_main @ 0x5e98 |
| int main(int argc, char **argv, char **envp); |
| ; arg int argc @ R0 |
| ? allocframe(SP,#0x8):raw |
| [ allocframe(SP,#0x8):raw |
| [ R2 = add(FP,##-0x4) |
| [ memw(R2+#0x0) = ##0x0 |
| [ R2 = add(FP,##-0x8) |
@ -496,7 +495,7 @@ EXPECT=<<EOF
|.------------------------------------. .-----------------.
|| 0x5154 | | 0x5134 |
|| ; DATA XREF from main @ 0x5130 | | [ jump 0x5138 |
|| ? R0 = ##0x0 | `-----------------'
|| [ R0 = ##0x0 | `-----------------'
|| [ LR:FP = dealloc_return(FP):raw | v
|`------------------------------------' |
| |
@ -536,8 +535,8 @@ pd 12
EOF
EXPECT=<<EOF
/ sym.thread_join();
| 0x00005200 ? R1 = HTID
| 0x00005204 ? R3 = ##0x1
| 0x00005200 / R1 = HTID
| 0x00005204 \ R3 = ##0x1
| 0x00005208 [ R1 = asl(R3,R1)
| 0x0000520c [ R1 = sub(##-0x1,R1)
| 0x00005210 [ R0 = and(R0,R1)
@ -565,7 +564,7 @@ pd 11
EOF
EXPECT=<<EOF
/ sym.sys_deinit_tls();
| 0x00005344 ? R2 = UGP
| 0x00005344 [ R2 = UGP
| 0x00005348 / immext(##loc.CoreDump) ; 0x1100
| 0x0000534c | R3 = memw(GP+##loc._TLSEnd) ; 0x1110
| 0x00005350 | immext(##loc.CoreDump) ; 0x1100
@ -588,7 +587,7 @@ s 0x00005abc
pd 22
EOF
EXPECT=<<EOF
| ,=< 0x00005abc ? if (P3) jump:nt 0x5b1c
| ,=< 0x00005abc [ if (P3) jump:nt 0x5b1c
| | ; CODE XREF from sym.memcpy @ 0x5abc
| ,==< 0x00005ac0 / loop0(0x5acc,R4)
| || 0x00005ac4 | P0 = cmp.gtu(R4,##0x1)
@ -625,11 +624,11 @@ s 0x00008df4
axt
EOF
EXPECT=<<EOF
sym._Mbtowcx 0x8df0 [CODE] ? loop0(0x8df4,R2)
sym._Mbtowcx 0x8e3c [CODE] ? R6 = ##0x1 ; R7 = add(R7,#1)
sym._Mbtowcx 0x8e54 [CODE] ? R6 = ##0x2 ; R7 = add(R7,#1)
sym._Mbtowcx 0x8e70 [CODE] ? R6 = ##0x3 ; R7 = add(R7,#1)
sym._Mbtowcx 0x8e98 [CODE] ? nop
sym._Mbtowcx 0x8df0 [CODE] [ loop0(0x8df4,R2)
sym._Mbtowcx 0x8e3c [CODE] \ R6 = ##0x1 ; R7 = add(R7,#1) < endloop0
sym._Mbtowcx 0x8e54 [CODE] \ R6 = ##0x2 ; R7 = add(R7,#1) < endloop0
sym._Mbtowcx 0x8e70 [CODE] \ R6 = ##0x3 ; R7 = add(R7,#1) < endloop0
sym._Mbtowcx 0x8e98 [CODE] \ nop < endloop0
EOF
RUN
@ -1400,7 +1399,7 @@ s loc.r_hex_32
px 16~[1-8]
EOF
EXPECT=<<EOF
? nop
[ nop
[ nop
[ nop
[ nop
@ -1444,8 +1443,8 @@ pdf
EOF
EXPECT=<<EOF
/ sym._Mbtowc();
| 0x00008f04 ? R17:16 = combine(R2,R3)
| 0x00008f08 ? memd(R29+#-0x10) = R17:16 ; allocframe(#0x10)
| 0x00008f04 / R17:16 = combine(R2,R3)
| 0x00008f08 \ memd(R29+#-0x10) = R17:16 ; allocframe(#0x10)
| 0x00008f0c [ R4 = memw(GP+##0x18)
| 0x00008f10 / R19:18 = combine(R0,R1)
| 0x00008f14 \ memd(SP+##0x0) = R19:18
@ -1460,3 +1459,47 @@ EXPECT=<<EOF
\ 0x00008f38 \ LR:FP = deallocframe(FP):raw
EOF
RUN
NAME=hexagon instructions buffer edge cases. 4 instr.
FILE=bins/elf/analysis/hexagon-hello-loop
CMDS=<<EOF
# Check if the instruction packet is disassembled correctly,
# Although, they are decoded in a chaotic order (not from low to high address).
pi 1 @ 0x000053cc # instr. 1
pi 1 @ 0x000053d4 # instr. 3
pi 5 @ 0x000053c4 # instr 0 - 3 and one before
aoi @ 0x000053c8
EOF
EXPECT=<<EOF
| R4 = add(R4,##0x4)
\ if (P0.new) R16 = ##0xb
? R2 = add(R2,##0x18) ; R3 = add(R3,#1)
/ if (!P0.new) jump:t 0x53b4
| R4 = add(R4,##0x4)
| P0 = cmp.gtu(R5,##0x3f)
\ if (P0.new) R16 = ##0xb
0x53c8 (seq empty (set jump_flag false) (set jump_target (bv 32 0xffffffff)) (set s (bv 32 0x4)) (set R4_tmp (cast 32 false (cast 32 false (+ (var R4) (var s))))) (set u (bv 32 0x3f)) (set P0_tmp (cast 8 false (cast 8 (msb (ite (! (ule (cast 32 false (var R5)) (var u))) (bv 32 0xff) (bv 32 0x0))) (ite (! (ule (cast 32 false (var R5)) (var u))) (bv 32 0xff) (bv 32 0x0))))) (set s (bv 32 0xb)) (branch (! (is_zero (& (cast 32 (msb (var P0_tmp)) (var P0_tmp)) (bv 32 0x1)))) (set R16_tmp (cast 32 false (cast 32 false (var s)))) nop) (set r (bv 32 0xffffffec)) (branch (! (! (is_zero (& (cast 32 (msb (var P0_tmp)) (var P0_tmp)) (bv 32 0x1))))) (seq (set r (& (var r) (bv 32 0xfffffffc))) (set jump_flag true) (set jump_target (+ (bv 32 0x53c8) (cast 32 false (var r))))) empty) empty (set R4 (var R4_tmp)) (set R16 (var R16_tmp)) (set P0 (var P0_tmp)) (branch (var jump_flag) (jmp (var jump_target)) (jmp (bv 32 0x53d8))))
EOF
RUN
NAME=hexagon instructions buffer edge cases. 4 instr. Rev
FILE=bins/elf/analysis/hexagon-hello-loop
CMDS=<<EOF
# Check if the instruction packet is disassembled correctly,
# Although, they are decoded in a chaotic order (not from low to high address).
pi 1 @ 0x000053d4 # instr. 3
pi 1 @ 0x000053cc # instr. 1
pi 5 @ 0x000053c4 # instr 0 - 3 and one before
aoi @ 0x000053c8
EOF
EXPECT=<<EOF
\ if (P0.new) R16 = ##0xb
| R4 = add(R4,##0x4)
? R2 = add(R2,##0x18) ; R3 = add(R3,#1)
/ if (!P0.new) jump:t 0x53b4
| R4 = add(R4,##0x4)
| P0 = cmp.gtu(R5,##0x3f)
\ if (P0.new) R16 = ##0xb
0x53c8 (seq empty (set jump_flag false) (set jump_target (bv 32 0xffffffff)) (set s (bv 32 0x4)) (set R4_tmp (cast 32 false (cast 32 false (+ (var R4) (var s))))) (set u (bv 32 0x3f)) (set P0_tmp (cast 8 false (cast 8 (msb (ite (! (ule (cast 32 false (var R5)) (var u))) (bv 32 0xff) (bv 32 0x0))) (ite (! (ule (cast 32 false (var R5)) (var u))) (bv 32 0xff) (bv 32 0x0))))) (set s (bv 32 0xb)) (branch (! (is_zero (& (cast 32 (msb (var P0_tmp)) (var P0_tmp)) (bv 32 0x1)))) (set R16_tmp (cast 32 false (cast 32 false (var s)))) nop) (set r (bv 32 0xffffffec)) (branch (! (! (is_zero (& (cast 32 (msb (var P0_tmp)) (var P0_tmp)) (bv 32 0x1))))) (seq (set r (& (var r) (bv 32 0xfffffffc))) (set jump_flag true) (set jump_target (+ (bv 32 0x53c8) (cast 32 false (var r))))) empty) empty (set R4 (var R4_tmp)) (set R16 (var R16_tmp)) (set P0 (var P0_tmp)) (branch (var jump_flag) (jmp (var jump_target)) (jmp (bv 32 0x53d8))))
EOF
RUN

View file

@ -24,7 +24,7 @@ d "? GELR = LR" 00c01f62 0x0
d "? R11:10 = memb_fifo(R12++M0:brev)" 0a408c9e 0x0
d "? R15:14 = memb_fifo(R7=##0x3)" 6ed0879a 0x0
dB "? C21:20 = R19:18" 14c03263 0x0
d "? C21:20 = R19:18" 14c03263 0x0
d "? C17:16 = R19:18" 10c03263 0x0
d "? PKTCOUNT = LR:FP" 12c03e63 0x0

View file

@ -136,3 +136,39 @@ zoom.maxsz=512
zoom.to=0
EOF
RUN
NAME=List and set plugin configurations
FILE==
CMDS=<<EOF
el plugins
# Should print nothing
el plugins
e asm.arch=hexagon
# Now it should print the hexagon options.
el plugins.
# Check if it only prints a specific sub-category.
el plugins.hexagon.imm
# Check if a value change is performed properly.
wx 01c09da0
pi 1
# Empty buffer
pi 1000~nothing
# Check if option was set
e plugins.hexagon.imm.hash=false
pi 1
# Disable plugin.
e asm.arch=x86
# Should print no hexagon options anymore
el plugins.
EOF
EXPECT=<<EOF
plugins.hexagon.imm.hash=true
plugins.hexagon.imm.sign=true
plugins.hexagon.reg.alias=true
plugins.hexagon.sdk=false
plugins.hexagon.imm.hash: Display ## before 32bit immediates and # before immidiates with other width.
plugins.hexagon.imm.sign: True: Print them with sign. False: Print signed immediates in unsigned representation.
? allocframe(SP,#0x8):raw
? allocframe(SP,0x8):raw
EOF
RUN

View file

@ -532,22 +532,22 @@ static bool test_rz_colorize_generic_4(void) {
}
static bool test_rz_colorize_custom_hexagon_0(void) {
RzAnalysis *a = setup_hexagon_analysis();
RzAsm *d = setup_hexagon_asm();
ut32 pc = hexagon_set_next_pc(d);
struct dummy_rz_core_t core = { 0 };
core.rasm = d;
d->core = &core;
RzPrint *p = setup_print();
RzAsmOp *asmop = rz_asm_op_new();
RzAnalysisOp *anaop = rz_analysis_op_new();
// "\ if (P0.new) jump:nt 0x18
// "? if (P0.new) jump:nt 0x18
ut8 buf[] = "\x08\xe8\x00\x5c";
rz_asm_disassemble(d, asmop, buf, sizeof(buf));
rz_analysis_op(a, anaop, pc, buf, sizeof(buf), RZ_ANALYSIS_OP_MASK_ALL);
RzStrBuf *colored_asm = rz_print_colorize_asm_str(p, asmop->asm_toks);
RzStrBuf *expected = rz_strbuf_new("\x1b[90m\\\x1b[0m\x1b[37m \x1b[0m\x1b[32mif\x1b[0m\x1b[37m \x1b[0m\x1b[37m(\x1b[0m\x1b[36mP0\x1b[0m\x1b[90m.new\x1b[0m\x1b[37m)\x1b[0m\x1b[37m \x1b[0m\x1b[32mjump\x1b[0m\x1b[90m:nt\x1b[0m\x1b[37m \x1b[0m\x1b[33m0x218\x1b[0m");
RzStrBuf *expected = rz_strbuf_new("\x1b[90m?\x1b[0m\x1b[37m \x1b[0m\x1b[32mif\x1b[0m\x1b[37m \x1b[0m\x1b[37m(\x1b[0m\x1b[36mP0\x1b[0m\x1b[90m.new\x1b[0m\x1b[37m)\x1b[0m\x1b[37m \x1b[0m\x1b[32mjump\x1b[0m\x1b[90m:nt\x1b[0m\x1b[37m \x1b[0m\x1b[33m0x210\x1b[0m");
char err_msg[2048];
snprintf(err_msg, sizeof(err_msg), "Colors of \"%s\" are incorrect. Should be \"%s\"\n.", rz_strbuf_get(colored_asm), rz_strbuf_get(expected));
mu_assert_true(rz_strbuf_equals(colored_asm, expected), err_msg);
@ -562,28 +562,26 @@ static bool test_rz_colorize_custom_hexagon_0(void) {
}
static bool test_rz_colorize_custom_hexagon_1(void) {
RzAnalysis *a = setup_hexagon_analysis();
RzAsm *d = setup_hexagon_asm();
ut32 pc = hexagon_set_next_pc(d);
struct dummy_rz_core_t core = { 0 };
core.rasm = d;
d->core = &core;
RzPrint *p = setup_print();
RzAsmOp *asmop = rz_asm_op_new();
RzAnalysisOp *anaop = rz_analysis_op_new();
// "[ LR:FP = dealloc_return(FP):raw" 1ec01e96
ut8 buf[] = "\x1e\xc0\x1e\x96";
rz_asm_disassemble(d, asmop, buf, sizeof(buf));
rz_analysis_op(a, anaop, pc, buf, sizeof(buf), RZ_ANALYSIS_OP_MASK_ALL);
RzStrBuf *colored_asm = rz_print_colorize_asm_str(p, asmop->asm_toks);
RzStrBuf *expected = rz_strbuf_new("\x1b[90m[\x1b[0m\x1b[37m \x1b[0m\x1b[36mLR\x1b[0m\x1b[37m:\x1b[0m\x1b[36mFP\x1b[0m\x1b[37m \x1b[0m\x1b[37m=\x1b[0m\x1b[37m \x1b[0m\x1b[31mdealloc_return\x1b[0m\x1b[37m(\x1b[0m\x1b[36mFP\x1b[0m\x1b[37m)\x1b[0m\x1b[90m:raw\x1b[0m");
RzStrBuf *expected = rz_strbuf_new("\x1b[90m?\x1b[0m\x1b[37m \x1b[0m\x1b[36mLR\x1b[0m\x1b[37m:\x1b[0m\x1b[36mFP\x1b[0m\x1b[37m \x1b[0m\x1b[37m=\x1b[0m\x1b[37m \x1b[0m\x1b[31mdealloc_return\x1b[0m\x1b[37m(\x1b[0m\x1b[36mFP\x1b[0m\x1b[37m)\x1b[0m\x1b[90m:raw\x1b[0m");
char err_msg[2048];
snprintf(err_msg, sizeof(err_msg), "Colors of \"%s\" are incorrect. Should be \"%s\"\n.", rz_strbuf_get(colored_asm), rz_strbuf_get(expected));
mu_assert_true(rz_strbuf_equals(colored_asm, expected), err_msg);
rz_asm_op_fini(asmop);
rz_analysis_op_free(anaop);
rz_cons_context_free(p->cons->context);
rz_print_free(p);
rz_strbuf_free(expected);
@ -592,13 +590,14 @@ static bool test_rz_colorize_custom_hexagon_1(void) {
}
static bool test_rz_colorize_custom_hexagon_2(void) {
RzAnalysis *a = setup_hexagon_analysis();
RzAsm *d = setup_hexagon_asm();
d->utf8 = true;
struct dummy_rz_core_t core = { 0 };
core.rasm = d;
d->core = &core;
RzPrint *p = setup_print();
RzAsmOp *asmop;
RzAnalysisOp *anaop;
RzStrBuf *colored_asm;
RzStrBuf *expected;
char err_msg[2048];
@ -609,7 +608,7 @@ static bool test_rz_colorize_custom_hexagon_2(void) {
// └ memd(R0++#0x8) = R7:6 ∎ endloop0
ut8 buf[] = "\x08\xd2\xc0\xab\x46\x8c\x0a\xc2\x20\x40\x84\x75\x2a\x40\xc1\x9b\x08\xc6\xc0\xab";
const char *expected_str[] = {
"\x1b[90m[\x1b[0m\x1b[37m \x1b[0m\x1b[37mmemd\x1b[0m\x1b[37m(\x1b[0m\x1b[36mR0\x1b[0m\x1b[37m++\x1b[0m\x1b[90m#\x1b[0m\x1b[33m0x8\x1b[0m\x1b[37m)\x1b[0m\x1b[37m \x1b[0m\x1b[37m=\x1b[0m\x1b[37m \x1b[0m\x1b[36mR19:18\x1b[0m",
"\x1b[90m?\x1b[0m\x1b[37m \x1b[0m\x1b[37mmemd\x1b[0m\x1b[37m(\x1b[0m\x1b[36mR0\x1b[0m\x1b[37m++\x1b[0m\x1b[90m#\x1b[0m\x1b[33m0x8\x1b[0m\x1b[37m)\x1b[0m\x1b[37m \x1b[0m\x1b[37m=\x1b[0m\x1b[37m \x1b[0m\x1b[36mR19:18\x1b[0m",
"\x1b[90m┌\x1b[0m\x1b[37m \x1b[0m\x1b[36mR7:6\x1b[0m\x1b[37m \x1b[0m\x1b[37m=\x1b[0m\x1b[37m \x1b[0m\x1b[37mvalignb\x1b[0m\x1b[37m(\x1b[0m\x1b[36mR13:12\x1b[0m\x1b[37m,\x1b[0m\x1b[36mR11:10\x1b[0m\x1b[37m,\x1b[0m\x1b[36mP2\x1b[0m\x1b[37m)\x1b[0m",
"\x1b[90m│\x1b[0m\x1b[37m \x1b[0m\x1b[36mP0\x1b[0m\x1b[37m \x1b[0m\x1b[37m=\x1b[0m\x1b[37m \x1b[0m\x1b[37mcmp\x1b[0m\x1b[37m.\x1b[0m\x1b[37mgtu\x1b[0m\x1b[37m(\x1b[0m\x1b[36mR4\x1b[0m\x1b[37m,\x1b[0m\x1b[90m##\x1b[0m\x1b[33m0x1\x1b[0m\x1b[37m)\x1b[0m",
"\x1b[90m│\x1b[0m\x1b[37m \x1b[0m\x1b[36mR11:10\x1b[0m\x1b[37m \x1b[0m\x1b[37m=\x1b[0m\x1b[37m \x1b[0m\x1b[37mmemd\x1b[0m\x1b[37m(\x1b[0m\x1b[36mR1\x1b[0m\x1b[37m++\x1b[0m\x1b[90m#\x1b[0m\x1b[33m0x8\x1b[0m\x1b[37m)\x1b[0m",
@ -617,11 +616,9 @@ static bool test_rz_colorize_custom_hexagon_2(void) {
};
for (int i = 0; i < 0x14; i += 4) {
ut32 pc = hexagon_set_next_pc(d);
asmop = rz_asm_op_new();
anaop = rz_analysis_op_new();
rz_asm_set_pc(d, i);
rz_asm_disassemble(d, asmop, buf + i, 4);
rz_analysis_op(a, anaop, pc, buf + i, 4, RZ_ANALYSIS_OP_MASK_ALL);
colored_asm = rz_print_colorize_asm_str(p, asmop->asm_toks);
expected = rz_strbuf_new(expected_str[i / 4]);
snprintf(err_msg, sizeof(err_msg), "Colors of \"%s\" are incorrect. Should be \"%s\"\n.", rz_strbuf_get(colored_asm), rz_strbuf_get(expected));
@ -631,38 +628,44 @@ static bool test_rz_colorize_custom_hexagon_2(void) {
}
rz_asm_op_fini(asmop);
rz_analysis_op_free(anaop);
rz_cons_context_free(p->cons->context);
rz_print_free(p);
mu_end;
}
static bool test_rz_colorize_custom_hexagon_3(void) {
RzAnalysis *a = setup_hexagon_analysis();
RzAsm *d = setup_hexagon_asm();
d->utf8 = true;
struct dummy_rz_core_t core = { 0 };
core.rasm = d;
d->core = &core;
RzPrint *p = setup_print();
RzAsmOp *asmop;
RzAnalysisOp *anaop;
RzStrBuf *colored_asm;
RzStrBuf *expected;
char err_msg[2048];
// {
// r25 = convert_df2w(r1:0):chop
// if (!p1) jump:nt 0x24
// }
// {
// r3:2 = convert_w2df(r25)
// r4 = p1
// }
ut8 buf[] = "\x39\x40\xe0\x88\x12\xc1\x20\x5c\x42\x40\x99\x84\x04\xc0\x41\x89";
const char *expected_str[] = {
"\x1b[90m┌\x1b[0m\x1b[37m \x1b[0m\x1b[36mR25\x1b[0m\x1b[37m \x1b[0m\x1b[37m=\x1b[0m\x1b[37m \x1b[0m\x1b[37mconvert_df2w\x1b[0m\x1b[37m(\x1b[0m\x1b[36mR1:0\x1b[0m\x1b[37m)\x1b[0m\x1b[37m:\x1b[0m\x1b[37mchop\x1b[0m",
"\x1b[90m└\x1b[0m\x1b[37m \x1b[0m\x1b[32mif\x1b[0m\x1b[37m \x1b[0m\x1b[37m(\x1b[0m\x1b[37m!\x1b[0m\x1b[36mP1\x1b[0m\x1b[37m)\x1b[0m\x1b[37m \x1b[0m\x1b[32mjump\x1b[0m\x1b[90m:nt\x1b[0m\x1b[37m \x1b[0m\x1b[33m0x4c\x1b[0m",
"\x1b[90m?\x1b[0m\x1b[37m \x1b[0m\x1b[36mR25\x1b[0m\x1b[37m \x1b[0m\x1b[37m=\x1b[0m\x1b[37m \x1b[0m\x1b[37mconvert_df2w\x1b[0m\x1b[37m(\x1b[0m\x1b[36mR1:0\x1b[0m\x1b[37m)\x1b[0m\x1b[37m:\x1b[0m\x1b[37mchop\x1b[0m",
"\x1b[90m?\x1b[0m\x1b[37m \x1b[0m\x1b[32mif\x1b[0m\x1b[37m \x1b[0m\x1b[37m(\x1b[0m\x1b[37m!\x1b[0m\x1b[36mP1\x1b[0m\x1b[37m)\x1b[0m\x1b[37m \x1b[0m\x1b[32mjump\x1b[0m\x1b[90m:nt\x1b[0m\x1b[37m \x1b[0m\x1b[33m0x24\x1b[0m",
"\x1b[90m┌\x1b[0m\x1b[37m \x1b[0m\x1b[36mR3:2\x1b[0m\x1b[37m \x1b[0m\x1b[37m=\x1b[0m\x1b[37m \x1b[0m\x1b[37mconvert_W2df\x1b[0m\x1b[37m(\x1b[0m\x1b[36mR25\x1b[0m\x1b[37m)\x1b[0m",
"\x1b[90m└\x1b[0m\x1b[37m \x1b[0m\x1b[36mR4\x1b[0m\x1b[37m \x1b[0m\x1b[37m=\x1b[0m\x1b[37m \x1b[0m\x1b[36mP1\x1b[0m",
};
for (int i = 0; i < 0x10; i += 4) {
ut32 pc = hexagon_set_next_pc(d);
asmop = rz_asm_op_new();
anaop = rz_analysis_op_new();
rz_asm_set_pc(d, i);
rz_asm_disassemble(d, asmop, buf + i, 4);
rz_analysis_op(a, anaop, pc, buf + i, 4, RZ_ANALYSIS_OP_MASK_ALL);
colored_asm = rz_print_colorize_asm_str(p, asmop->asm_toks);
expected = rz_strbuf_new(expected_str[i / 4]);
@ -673,7 +676,6 @@ static bool test_rz_colorize_custom_hexagon_3(void) {
}
rz_asm_op_fini(asmop);
rz_analysis_op_free(anaop);
rz_cons_context_free(p->cons->context);
rz_print_free(p);
mu_end;