rizin/librz/core/cmd/cmd_regs.c
Dean 59b38e6efa
Add /*<type>*/ comments everywhere (#2986)
Adds /*<type>*/ comments and a linter check from rz-bindgen to enforce
their existence and consistency

Also includes the following fixes made when adding the annotations:
* removed unused intern_table arguments in pyc_dis.c, pyc_dis.h, asm_pyc.c
* removed unused classes argument from place_nodes in agraph.c
* removed unused recurse and recurse_bb functions in canalysis.c
* removed unused vars field from RzPrint struct
* removed unused RzAnalysisType* structs from rz_analysis.h
* removed unused list field from RzEgg struct
* fixed bug in bp_plugin.c where duplication-checking logic iterates over the wrong list
* removed unused q_regs field from RzDebug struct
* removed unused backtrace field from RzDebugPlugin struct
* removed unused classes_list field from RzBinNXOObj struct
* removed unused methods_list and classes_list fields from RzBinZimgObj struct
2022-09-11 13:04:53 +08:00

888 lines
24 KiB
C

// SPDX-FileCopyrightText: 2021 Florian Märkl <info@florianmaerkl.de>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_core.h>
#include "../core_private.h"
HEAPTYPE(ut64);
#define SYNC_READ(type, failed) \
do { \
failed = false; \
if (sync_cb && !sync_cb(core, type, false)) { \
RZ_LOG_ERROR("Failed to read registers.\n"); \
failed = true; \
} \
} while (0)
#define SYNC_READ_LIST(ritems, failed) \
do { \
failed = false; \
if (rz_list_length(ritems) == 1) { \
SYNC_READ(((RzRegItem *)rz_list_head(ritems))->type, failed); \
} else if (rz_list_length(ritems) > 1) { \
SYNC_READ(RZ_REG_TYPE_ANY, failed); \
} \
} while (0)
#define SYNC_WRITE(type, failed) \
do { \
failed = false; \
if (sync_cb && !sync_cb(core, type, true)) { \
RZ_LOG_ERROR("Failed to write registers.\n"); \
failed = true; \
} \
rz_core_reg_update_flags(core); \
} while (0)
static RzList /*<RzRegItem *>*/ *filter_reg_items(RzReg *reg, RZ_NULLABLE const char *filter) {
rz_return_val_if_fail(reg, NULL);
// default
if (RZ_STR_ISEMPTY(filter)) {
// default selection (only gpr, omit smaller regs that are fully covered by larger ones)
return rz_reg_filter_items_covered(reg->regset[RZ_REG_TYPE_GPR].regs);
}
// all
if (!strcmp(filter, "all")) {
return rz_list_clone(reg->allregs);
}
// bit size
char *end = NULL;
unsigned long bits = strtoul(filter, &end, 0);
if (!*end) {
RzList *ret = rz_list_new();
if (!ret) {
return NULL;
}
RzListIter *iter;
RzRegItem *ri;
rz_list_foreach (reg->regset[RZ_REG_TYPE_GPR].regs, iter, ri) {
if (ri->size == bits) {
rz_list_push(ret, ri);
}
}
return ret;
}
// type
int type = rz_reg_type_by_name(filter);
if (type >= 0) {
return rz_list_clone(reg->regset[type].regs);
}
// role
int role = rz_reg_role_by_name(filter);
if (role >= 0) {
const char *itemname = rz_reg_get_name(reg, role);
if (!itemname) {
return NULL;
}
filter = itemname; // fallthrough to the below query with the resolved reg name
}
// single register name
RzRegItem *ri = rz_reg_get(reg, filter, RZ_REG_TYPE_ANY);
if (!ri) {
return NULL;
}
return rz_list_new_from_array((const void **)&ri, 1);
}
/// Format the value of a register as a nice hex string
static void format_reg_value(RzReg *reg, RzRegItem *item, char *out, size_t out_size) {
// TODO: This could be done much nicer with RzBitVector, but it's not in RzUtil yet :-(
if (item->size < 80) {
ut64 value = rz_reg_get_value(reg, item);
snprintf(out, out_size, "0x%08" PFMT64x, value);
} else {
utX valueBig;
rz_reg_get_value_big(reg, item, &valueBig);
switch (item->size) {
case 80:
snprintf(out, out_size, "0x%04x%016" PFMT64x "", valueBig.v80.High, valueBig.v80.Low);
break;
case 96:
snprintf(out, out_size, "0x%08x%016" PFMT64x "", valueBig.v96.High, valueBig.v96.Low);
break;
case 128:
snprintf(out, out_size, "0x%016" PFMT64x "%016" PFMT64x "", valueBig.v128.High, valueBig.v128.Low);
break;
case 256:
snprintf(out, out_size, "0x%016" PFMT64x "%016" PFMT64x "%016" PFMT64x "%016" PFMT64x "",
valueBig.v256.High.High, valueBig.v256.High.Low, valueBig.v256.Low.High, valueBig.v256.Low.Low);
break;
default:
snprintf(out, out_size, "ERROR");
}
}
}
/// Check whether the given item's value has changed in the last step
static bool reg_has_changed(RzReg *reg, RzRegItem *item) {
ut64 value = rz_reg_get_value(reg, item);
rz_reg_arena_swap(reg, false);
ut64 old = rz_reg_get_value(reg, item);
rz_reg_arena_swap(reg, false);
return old != value;
}
static void print_reg_not_found(const char *arg) {
RZ_LOG_ERROR("No such register or register type: \"%s\"\n", rz_str_get(arg));
}
/**
* Register assignment like reg=0x42
*
* \param core The RzCore instance
* \param reg The RzReg instance
* \param sync_cb Callback for synchronizing register state in command
* \param name Register name
* \param val Value
* \return success
*/
RZ_API bool rz_core_reg_assign_sync(RZ_NONNULL RzCore *core, RZ_NONNULL RzReg *reg, RzCmdRegSync sync_cb, RZ_NONNULL const char *name, ut64 val) {
rz_return_val_if_fail(core && reg && name, false);
RzRegItem *ri = rz_reg_get(reg, name, RZ_REG_TYPE_ANY);
if (!ri) {
return false;
}
bool failed;
SYNC_READ(ri->type, failed);
if (failed) {
return false;
}
rz_reg_set_value(reg, ri, val);
SYNC_WRITE(ri->type, failed);
return true;
}
/**
* \brief (Sub)handler for register assignments like reg=0x42
* \param arg the full argument string, like "reg = 0x42"
* \param eq_pos index of the '=' in arg
*/
static RzCmdStatus assign_reg(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, RZ_NONNULL const char *arg, size_t eq_pos) {
char *str = strdup(arg);
if (!str) {
return RZ_CMD_STATUS_ERROR;
}
str[eq_pos] = 0;
char *val = str + eq_pos + 1;
rz_str_trim(str);
rz_str_trim(val);
ut64 nval = rz_num_math(core->num, val);
return rz_core_reg_assign_sync(core, reg, sync_cb, str, nval) ? RZ_CMD_STATUS_OK : RZ_CMD_STATUS_ERROR;
}
static const char *get_reg_color(RzCore *core, RzReg *reg, RzRegItem *item) {
if (!rz_config_get_i(core->config, "scr.color")) {
return NULL;
}
if (reg_has_changed(reg, item)) {
return (core->cons && core->cons->context->pal.creg)
? core->cons->context->pal.creg
: Color_BWHITE;
}
return NULL;
}
static const char *get_reg_role_name(RzReg *reg, RzRegItem *item) {
for (int i = 0; i < RZ_REG_NAME_LAST; i++) {
const char *t = rz_reg_get_name(reg, i);
if (t && !strcmp(t, item->name)) {
return rz_reg_get_role(i);
}
}
return NULL;
}
/**
* Filter a list of RzRegItem and sync read
*
* \param core The RzCore instance
* \param reg The RzReg instance
* \param sync_cb Callback for synchronizing register state in command
* \param filter Filter registers
* \return List of RzRegItem
*/
RZ_API RZ_OWN RzList /*<RzRegItem *>*/ *rz_core_reg_filter_items_sync(RZ_NONNULL RzCore *core, RZ_NONNULL RzReg *reg, RzCmdRegSync sync_cb, RZ_NULLABLE const char *filter) {
rz_return_val_if_fail(core && reg, NULL);
RzList *ritems = filter_reg_items(reg, filter);
if (!ritems) {
return NULL;
}
bool failed;
SYNC_READ_LIST(ritems, failed);
if (failed) {
rz_list_free(ritems);
return NULL;
}
return ritems;
}
static RzCmdStatus show_regs_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, const char *filter, RzCmdStateOutput *state) {
RzList *ritems = rz_core_reg_filter_items_sync(core, reg, sync_cb, filter);
if (!ritems) {
print_reg_not_found(filter);
return RZ_CMD_STATUS_ERROR;
}
if (state->mode == RZ_OUTPUT_MODE_TABLE) {
rz_table_set_columnsf(state->d.t, "ssXxs", "role", "name", "value", "size", "type");
} else if (state->mode == RZ_OUTPUT_MODE_JSON) {
pj_o(state->d.pj);
}
RzListIter *iter;
RzRegItem *item;
char buf[256] = { 0 };
rz_list_foreach (ritems, iter, item) {
switch (state->mode) {
case RZ_OUTPUT_MODE_STANDARD: {
format_reg_value(reg, item, buf, sizeof(buf));
const char *color = get_reg_color(core, reg, item);
if (color) {
rz_cons_print(color);
}
rz_cons_printf("%s = %s", item->name, buf);
if (color) {
rz_cons_print(Color_RESET);
}
rz_cons_print("\n");
break;
}
case RZ_OUTPUT_MODE_QUIET:
format_reg_value(reg, item, buf, sizeof(buf));
rz_cons_printf("%s\n", buf);
break;
case RZ_OUTPUT_MODE_RIZIN:
format_reg_value(reg, item, buf, sizeof(buf));
rz_cons_printf("ar %s = %s\n", item->name, buf);
break;
case RZ_OUTPUT_MODE_TABLE:
rz_table_add_rowf(state->d.t, "ssXxs",
rz_str_get(get_reg_role_name(reg, item)),
item->name, rz_reg_get_value(reg, item), (ut64)item->size, rz_reg_get_type(item->type));
break;
case RZ_OUTPUT_MODE_JSON:
if (item->size <= 64) {
pj_kn(state->d.pj, item->name, rz_reg_get_value(reg, item));
} else {
format_reg_value(reg, item, buf, sizeof(buf));
pj_ks(state->d.pj, item->name, buf);
}
break;
default:
break;
}
}
rz_list_free(ritems);
if (state->mode == RZ_OUTPUT_MODE_JSON) {
pj_end(state->d.pj);
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_regs_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv, RzCmdStateOutput *state) {
const char *filter = argc > 1 ? argv[1] : NULL;
// check if the argument is an assignment like reg=0x42
if (filter) {
char *eq = strchr(filter, '=');
if (eq) {
return assign_reg(core, reg, sync_cb, filter, eq - filter);
}
}
// just show
return show_regs_handler(core, reg, sync_cb, filter, state);
}
RZ_IPI RzCmdStatus rz_regs_columns_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv) {
const char *filter = argc > 1 ? argv[1] : NULL;
RzList *ritems = rz_core_reg_filter_items_sync(core, reg, sync_cb, filter);
if (!ritems) {
print_reg_not_found(filter);
return RZ_CMD_STATUS_ERROR;
}
int cols = 4; // how many registers in a row
int colwidth = 24;
RzListIter *iter;
RzRegItem *item;
char whites[32], content[300];
char strvalue[256] = { 0 };
size_t idx = 0;
rz_list_foreach (ritems, iter, item) {
const char *color = get_reg_color(core, reg, item);
if (color) {
rz_cons_print(color);
}
format_reg_value(reg, item, strvalue, sizeof(strvalue));
int len = snprintf(content, sizeof(content), "%7s %s", item->name, strvalue);
if (len < 0) {
break;
}
rz_cons_print(content);
if (color) {
rz_cons_print(Color_RESET);
}
if ((idx + 1) % cols) {
int rem = colwidth - strlen(content);
rem = RZ_MIN(sizeof(whites) - 1, RZ_MAX(0, rem));
memset(whites, ' ', rem);
whites[rem] = 0;
rz_cons_print(whites);
} else {
rz_cons_print("\n");
}
idx++;
}
if (idx % cols) {
// only print newline if not already done in the loop above
rz_cons_print("\n");
}
rz_list_free(ritems);
return RZ_CMD_STATUS_OK;
}
static RzCmdStatus references_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, RzList /*<RzRegItem *>*/ *ritems, RzOutputMode mode) {
bool failed;
SYNC_READ_LIST(ritems, failed);
if (failed) {
return RZ_CMD_STATUS_ERROR;
}
int use_colors = rz_config_get_i(core->config, "scr.color");
int had_colors = use_colors;
if (use_colors && mode == RZ_OUTPUT_MODE_JSON) {
use_colors = 0;
// for rz_core_analysis_hasrefs() below
rz_config_set_i(core->config, "scr.color", 0);
}
RzTable *t = rz_core_table(core);
rz_table_set_columnsf(t, "ssss", "role", "reg", "value", "refstr");
RzListIter *iter;
RzRegItem *r;
rz_list_foreach (ritems, iter, r) {
ut64 value = rz_reg_get_value(reg, r);
const char *color = mode == RZ_OUTPUT_MODE_JSON ? NULL : get_reg_color(core, reg, r);
char *namestr = rz_str_newf("%s%s%s", rz_str_get(color), r->name, color ? Color_RESET : "");
char *valuestr = rz_str_newf("%s0x%" PFMT64x "%s", rz_str_get(color), value, color ? Color_RESET : "");
char *rrstr = rz_core_analysis_hasrefs(core, value, true);
rz_table_add_rowf(t, "ssss", rz_str_get(get_reg_role_name(reg, r)), namestr, valuestr, rz_str_get(rrstr));
free(namestr);
free(valuestr);
free(rrstr);
}
if (mode == RZ_OUTPUT_MODE_JSON && had_colors) {
rz_config_set_i(core->config, "scr.color", had_colors);
}
char *s = (mode == RZ_OUTPUT_MODE_JSON) ? rz_table_tojson(t) : rz_table_tostring(t);
rz_cons_print(s);
if (mode == RZ_OUTPUT_MODE_JSON) {
rz_cons_print("\n");
}
free(s);
rz_table_free(t);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_regs_references_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv, RzOutputMode mode) {
const char *filter = argc > 1 ? argv[1] : NULL;
RzList *ritems = filter_reg_items(reg, filter);
if (!ritems) {
print_reg_not_found(filter);
return RZ_CMD_STATUS_ERROR;
}
RzCmdStatus r = references_handler(core, reg, sync_cb, ritems, mode);
rz_list_free(ritems);
return r;
}
static int valgroup_regcmp(const void *a, const void *b) {
const ut64 *A = (const ut64 *)a;
const ut64 *B = (const ut64 *)b;
if (*A > *B) {
return 1;
}
if (*A == *B) {
return 0;
}
return -1;
}
static bool valgroup_regcb(void *u, const ut64 k, const void *v) {
RzList *sorted = (RzList *)u;
ut64 *n = ut64_new(k);
rz_list_add_sorted(sorted, n, valgroup_regcmp);
return true;
}
RZ_IPI void rz_regs_show_valgroup(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, const RzList /*<RzRegItem *>*/ *list) {
int use_colors = rz_config_get_i(core->config, "scr.color");
RzListIter *iter;
RzRegItem *r;
HtUP *db = ht_up_new0();
rz_list_foreach (list, iter, r) {
if (r->size != core->rasm->bits) {
continue;
}
ut64 value = rz_reg_get_value(reg, r);
RzList *list = ht_up_find(db, value, NULL);
if (!list) {
list = rz_list_newf(NULL);
ht_up_update(db, value, list);
}
rz_list_append(list, r->name);
}
RzList *sorted = rz_list_newf(free);
ht_up_foreach(db, valgroup_regcb, sorted);
ut64 *addr;
rz_list_foreach (sorted, iter, addr) {
rz_cons_printf("0x%08" PFMT64x " ", *addr);
RzList *list = ht_up_find(db, *addr, NULL);
if (list) {
RzListIter *iter;
const char *r;
if (use_colors) {
rz_cons_strcat(Color_YELLOW);
}
rz_list_foreach (list, iter, r) {
rz_cons_printf(" %s", r);
}
if (use_colors) {
rz_cons_strcat(Color_RESET);
}
char *rrstr = rz_core_analysis_hasrefs(core, *addr, true);
if (rrstr && *rrstr && strchr(rrstr, 'R')) {
rz_cons_printf(" ;%s%s", rrstr, use_colors ? Color_RESET : "");
}
rz_cons_newline();
}
}
rz_list_free(sorted);
ht_up_free(db);
}
RZ_IPI RzCmdStatus rz_regs_valgroup_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv) {
const char *filter = argc > 1 ? argv[1] : NULL;
RzList *list = filter_reg_items(reg, filter);
if (!list) {
print_reg_not_found(filter);
return RZ_CMD_STATUS_ERROR;
}
rz_regs_show_valgroup(core, reg, sync_cb, list);
rz_list_free(list);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_arenas_handler(RzCore *core, RzReg *reg, int argc, const char **argv) {
int i, j;
RzRegArena *a;
RzListIter *iter;
for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
RzRegSet *rs = &reg->regset[i];
j = 0;
rz_list_foreach (rs->pool, iter, a) {
rz_cons_printf("%s %p %d %d %s %d\n",
(a == rs->arena) ? "*" : ".", a,
i, j, rz_reg_get_type(i), a->size);
j++;
}
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_arenas_push_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv) {
bool failed;
SYNC_READ(RZ_REG_TYPE_ANY, failed);
if (failed) {
return RZ_CMD_STATUS_ERROR;
}
rz_reg_arena_push(reg);
SYNC_WRITE(RZ_REG_TYPE_ANY, failed);
return failed ? RZ_CMD_STATUS_ERROR : RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_arenas_pop_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv) {
rz_reg_arena_pop(reg);
bool failed;
SYNC_WRITE(RZ_REG_TYPE_ANY, failed);
return failed ? RZ_CMD_STATUS_ERROR : RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_arenas_swap_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv) {
bool failed;
SYNC_READ(RZ_REG_TYPE_ANY, failed);
if (failed) {
return RZ_CMD_STATUS_ERROR;
}
rz_reg_arena_swap(reg, false);
SYNC_WRITE(RZ_REG_TYPE_ANY, failed);
return failed ? RZ_CMD_STATUS_ERROR : RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_arenas_zero_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv) {
int t = RZ_REG_TYPE_ANY;
if (argc > 1) {
t = rz_reg_type_by_name(argv[1]);
if (t < 0) {
RZ_LOG_ERROR("No such register type: \"%s\"\n", argv[2]);
return RZ_CMD_STATUS_ERROR;
}
}
rz_reg_arena_zero(reg, t);
bool failed;
SYNC_WRITE(t, failed);
return failed ? RZ_CMD_STATUS_ERROR : RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_arenas_hexdump_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv) {
int t = RZ_REG_TYPE_GPR;
if (argc > 1) {
t = rz_reg_type_by_name(argv[1]);
if (t < 0) {
RZ_LOG_ERROR("No such register type: \"%s\"\n", argv[2]);
return RZ_CMD_STATUS_ERROR;
}
}
bool failed;
SYNC_READ(t, failed);
if (failed) {
return RZ_CMD_STATUS_ERROR;
}
int len = 0;
ut8 *buf = rz_reg_get_bytes(reg, t, &len);
if (buf) {
rz_core_print_hexdump(core, 0LL, buf, len, 32, 4, 1);
free(buf);
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_arenas_stack_size_handler(RzCore *core, RzReg *reg, int argc, const char **argv) {
rz_cons_printf("%d\n", (int)rz_list_length(reg->regset[0].pool));
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_arenas_write_hex_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv) {
rz_return_val_if_fail(argc > 1, RZ_CMD_STATUS_WRONG_ARGS);
RzRegisterType type = RZ_REG_TYPE_GPR;
if (argc > 2) {
type = rz_reg_type_by_name(argv[2]);
if (type < 0 || type >= RZ_REG_TYPE_LAST) {
RZ_LOG_ERROR("No such register type: \"%s\"\n", argv[2]);
return RZ_CMD_STATUS_ERROR;
}
}
bool failed;
SYNC_READ(type, failed);
if (failed) {
return RZ_CMD_STATUS_ERROR;
}
const char *hex = argv[1];
size_t maxsz = (strlen(hex) + 1) / 2;
if (!maxsz) {
return RZ_CMD_STATUS_ERROR;
}
ut8 *buf = malloc(maxsz);
if (!buf) {
return RZ_CMD_STATUS_ERROR;
}
int sz = rz_hex_str2bin(hex, buf);
if (sz <= 0) {
RZ_LOG_ERROR("Invalid hex string given.\n");
free(buf);
return RZ_CMD_STATUS_ERROR;
}
RzRegArena *a = reg->regset[type].arena;
if (!a || !a->bytes) {
free(buf);
// nothing to write, this is fine
return RZ_CMD_STATUS_OK;
}
memcpy(a->bytes, buf, RZ_MIN(sz, a->size));
free(buf);
SYNC_WRITE(type, failed);
return failed ? RZ_CMD_STATUS_ERROR : RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_regs_args_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv, RzOutputMode mode) {
RzList *ritems = rz_list_new();
if (!ritems) {
return RZ_CMD_STATUS_ERROR;
}
for (int i = RZ_REG_NAME_A0; i <= RZ_REG_NAME_A9; i++) {
const char *name = rz_reg_get_name(reg, i);
if (!name) {
break;
}
RzRegItem *item = rz_reg_get(reg, name, RZ_REG_TYPE_ANY);
if (!item) {
continue;
}
rz_list_push(ritems, item);
}
RzCmdStatus r = RZ_CMD_STATUS_OK;
if (rz_list_empty(ritems)) {
RZ_LOG_ERROR("core: No argument roles defined.\n");
} else {
r = references_handler(core, reg, sync_cb, ritems, mode);
}
rz_list_free(ritems);
return r;
}
RZ_IPI RzCmdStatus rz_reg_types_handler(RzCore *core, RzReg *reg, int argc, const char **argv) {
for (int i = 0; i < RZ_REG_TYPE_LAST; i++) {
rz_cons_println(rz_reg_get_type(i));
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_roles_handler(RzCore *core, RzReg *reg, int argc, const char **argv) {
for (int i = 0; i < RZ_REG_NAME_LAST; i++) {
rz_cons_print(rz_reg_get_role(i));
if (reg->name[i]) {
rz_cons_printf(" -> %s", reg->name[i]);
}
rz_cons_print("\n");
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_flags_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv, bool unset) {
const char *filter = argc > 1 && *argv[1] ? argv[1] : NULL;
RzList *ritems;
if (filter) {
ritems = filter_reg_items(reg, filter);
if (!ritems) {
print_reg_not_found(filter);
return RZ_CMD_STATUS_ERROR;
}
} else {
ritems = rz_core_reg_flags_candidates(core, reg);
if (!ritems) {
return RZ_CMD_STATUS_ERROR;
}
}
if (!unset) {
rz_cons_print("fss+ " RZ_FLAGS_FS_REGISTERS "\n");
bool failed;
SYNC_READ_LIST(ritems, failed);
if (failed) {
rz_list_free(ritems);
return RZ_CMD_STATUS_ERROR;
}
}
RzListIter *iter;
RzRegItem *item;
rz_list_foreach (ritems, iter, item) {
if (!unset) {
ut64 v = rz_reg_get_value(reg, item);
rz_cons_printf("f+ %s @ 0x%" PFMT64x "\n", item->name, v);
} else {
rz_cons_printf("f- %s\n", item->name);
}
}
if (!unset) {
rz_cons_print("fss-\n");
}
rz_list_free(ritems);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_profile_handler(RzCore *core, RzReg *reg, int argc, const char **argv, RzCmdStateOutput *state) {
switch (state->mode) {
case RZ_OUTPUT_MODE_STANDARD:
if (reg->reg_profile_str) {
rz_cons_println(reg->reg_profile_str);
} else {
RZ_LOG_ERROR("core: No register profile defined.\n");
}
break;
case RZ_OUTPUT_MODE_JSON: {
RzListIter *iter;
RzRegItem *r;
int i;
PJ *pj = state->d.pj;
pj_o(pj);
pj_k(pj, "alias_info");
pj_a(pj);
for (i = 0; i < RZ_REG_NAME_LAST; i++) {
if (reg->name[i]) {
pj_o(pj);
pj_kn(pj, "role", i);
pj_ks(pj, "role_str", rz_reg_get_role(i));
pj_ks(pj, "reg", reg->name[i]);
pj_end(pj);
}
}
pj_end(pj);
pj_k(pj, "reg_info");
pj_a(pj);
for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
rz_list_foreach (reg->regset[i].regs, iter, r) {
pj_o(pj);
pj_kn(pj, "type", r->type);
pj_ks(pj, "type_str", rz_reg_get_type(r->type));
pj_ks(pj, "name", r->name);
pj_kn(pj, "size", r->size);
pj_kn(pj, "offset", r->offset);
pj_end(pj);
}
}
pj_end(pj);
pj_end(pj);
break;
}
default:
break;
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_profile_comments_handler(RzCore *core, RzReg *reg, int argc, const char **argv) {
if (reg->reg_profile_cmt) {
rz_cons_println(reg->reg_profile_cmt);
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_profile_open_handler(RzCore *core, RzReg *reg, int argc, const char **argv) {
rz_return_val_if_fail(argc > 1, RZ_CMD_STATUS_WRONG_ARGS);
rz_reg_set_profile(reg, argv[1]);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_profile_gdb_handler(RzCore *core, RzReg *reg, int argc, const char **argv) {
rz_return_val_if_fail(argc > 1, RZ_CMD_STATUS_WRONG_ARGS);
char *rz_profile = rz_reg_parse_gdb_profile(argv[1]);
if (!rz_profile) {
RZ_LOG_ERROR("Cannot parse gdb profile.\n");
core->num->value = 1;
return RZ_CMD_STATUS_ERROR;
}
rz_cons_println(rz_profile);
core->num->value = 0;
free(rz_profile);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_cond_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv) {
bool failed;
SYNC_READ(RZ_REG_TYPE_ANY, failed);
if (failed) {
return RZ_CMD_STATUS_ERROR;
}
RzRegFlags *rf = rz_reg_cond_retrieve(reg, NULL);
if (!rf) {
return RZ_CMD_STATUS_ERROR;
}
rz_cons_printf("| s:%d z:%d c:%d o:%d p:%d\n",
rf->s, rf->z, rf->c, rf->o, rf->p);
for (int i = 0; i < RZ_REG_COND_LAST; i++) {
rz_cons_printf("%d %s\n",
rz_reg_cond_bits(reg, i, rf),
rz_reg_cond_to_string(i));
}
free(rf);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_reg_cc_handler(RzCore *core, RzReg *reg, int argc, const char **argv) {
char *s = rz_reg_profile_to_cc(reg);
if (s) {
rz_cons_printf("%s\n", s);
free(s);
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_regs_diff_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv) {
bool failed;
SYNC_READ(RZ_REG_TYPE_ANY, failed);
if (failed) {
return RZ_CMD_STATUS_ERROR;
}
rz_core_reg_print_diff(reg, reg->allregs);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_regs_prev_handler(RzCore *core, RzReg *reg, int argc, const char **argv, RzCmdStateOutput *state) {
const char *filter = argc > 1 ? argv[1] : NULL;
rz_reg_arena_swap(reg, false);
RzCmdStatus r = show_regs_handler(core, reg, NULL, filter, state); // sync_cb = NULL on purpose to not overwrite
rz_reg_arena_swap(reg, false);
return r;
}
RZ_IPI RzCmdStatus rz_regs_fpu_handler(RzCore *core, RzReg *reg, RzCmdRegSync sync_cb, int argc, const char **argv) {
// TODO: everything here needs to be rewritten. It was taken from the old "drf" command.
bool failed;
if (argc <= 1) {
// TODO: Do not use this hack to print fpu register:
// By sending a negative value, this is signalling all the way through to the debug plugin,
// which then does the printing.
// This should be rewritten directly above the RzReg.
SYNC_READ(-RZ_REG_TYPE_FPU, failed);
if (failed) {
return RZ_CMD_STATUS_ERROR;
}
return RZ_CMD_STATUS_OK;
}
char *name = rz_str_trim_dup(argv[1]);
char *eq = strchr(name, '=');
if (eq) {
*eq++ = 0;
}
char *p = strchr(name, ' ');
if (p) {
*p++ = 0;
}
RzCmdStatus ret = RZ_CMD_STATUS_ERROR;
SYNC_READ(RZ_REG_TYPE_GPR, failed);
if (failed) {
goto error;
}
SYNC_READ(RZ_REG_TYPE_FPU, failed);
if (failed) {
goto error;
}
RzRegItem *item = rz_reg_get(reg, name, -1);
if (item) {
if (eq) {
long double val = 0.0f;
#if __windows__
double dval = 0.0f;
sscanf(eq, "%lf", (double *)&dval);
val = dval;
#else
sscanf(eq, "%Lf", &val);
#endif
rz_reg_set_double(reg, item, val);
SYNC_WRITE(RZ_REG_TYPE_GPR, failed);
if (failed) {
goto error;
}
SYNC_WRITE(RZ_REG_TYPE_FPU, failed);
if (failed) {
goto error;
}
} else {
long double res = rz_reg_get_longdouble(reg, item);
rz_cons_printf("%Lf\n", res);
}
} else {
/* note, that negative type forces sync to print the regs from the backend */
RZ_LOG_ERROR("core: cannot find multimedia register '%s'\n", name);
}
error:
free(name);
return ret;
}