From 7f55442dc2f7e9987920e107bcad6696c776bbaf Mon Sep 17 00:00:00 2001 From: Giovanni <561184+wargio@users.noreply.github.com> Date: Thu, 19 Feb 2026 23:13:18 +0800 Subject: [PATCH] Fix endianness issues on s390x (#5940) * Refactor of bflt to guess arch & fix m68k code * Fix endianness issues * Always cleanup at the end on travis ci --- .travis.yml | 3 + librz/arch/asm.c | 5 + librz/arch/p/analysis/analysis_m68k_cs.c | 2 +- librz/arch/p/analysis/analysis_riscv_cs.c | 26 +- librz/arch/p/analysis/analysis_riscv_utils.h | 90 ++- librz/arch/p/arch_riscv_cs.c | 8 +- librz/arch/p/asm/asm_m68k_cs.c | 2 +- librz/bin/format/bflt/bflt.c | 96 +-- librz/bin/format/bflt/bflt.h | 3 +- librz/bin/format/elf/elf_info.c | 40 +- librz/bin/format/wasm/wasm.c | 20 +- librz/bin/format/wasm/wasm.h | 18 +- librz/bin/p/bin_bflt.c | 42 +- librz/core/carch.c | 115 +++- librz/core/cio.c | 4 +- librz/core/cmd/cmd.c | 2 +- librz/core/rtr.c | 2 +- librz/include/rz_asm.h | 1 + test/db/analysis/arc | 67 ++- test/db/analysis/arm | 43 +- test/db/analysis/arm64 | 2 + test/db/analysis/avr | 24 + test/db/analysis/mips | 21 +- test/db/analysis/pic | 3 + test/db/analysis/ppc | 1 + test/db/analysis/riscv | 402 ++++--------- test/db/analysis/thumb | 1 + test/db/analysis/xtensa | 3 + test/db/cmd/cmd_ao | 1 + test/db/cmd/cmd_avg | 2 + test/db/cmd/cmd_basefind | 1 + test/db/cmd/cmd_flags | 1 + test/db/cmd/cmd_p_capital_c | 2 + test/db/cmd/cmd_pd | 16 +- test/db/cmd/cmd_pdr | 1 + test/db/cmd/cmd_pf | 48 +- test/db/cmd/cmd_pf2 | 33 +- test/db/cmd/cmd_pf_elf | 15 +- test/db/cmd/cmd_pf_write | 1 + test/db/cmd/cmd_pfd | 1 + test/db/cmd/cmd_plf | 1 + test/db/cmd/cmd_pointer | 8 + test/db/cmd/cmd_ps | 2 + test/db/cmd/cmd_px | 3 + test/db/cmd/cmd_pxd | 103 +--- test/db/cmd/cmd_rop | 9 + test/db/cmd/cmd_search_v | 1 + test/db/cmd/cmd_w | 1 + test/db/cmd/cmd_wD | 1 + test/db/cmd/feat_arithmetic | 8 + test/db/cmd/feat_redirect | 1 + test/db/cmd/metadata | 1 + test/db/cmd/print | 13 +- test/db/cmd/types | 8 +- test/db/cmd/write | 6 +- test/db/esil/8051 | 595 +++++++++++++++---- test/db/esil/arm_16 | 183 ++---- test/db/esil/arm_32 | 168 ++++++ test/db/esil/arm_64 | 69 ++- test/db/esil/avr | 11 + test/db/esil/esil | 14 - test/db/esil/math | 44 -- test/db/esil/mips_32 | 368 +++--------- test/db/esil/x86_16 | 15 +- test/db/esil/x86_32 | 33 - test/db/esil/x86_64 | 15 - test/db/esil/xtensa_32 | 16 +- test/db/formats/bflt | 154 ++++- test/db/rzil/arm32 | 6 +- test/db/rzil/avr | 15 + test/unit/test_yank.c | 10 +- 71 files changed, 1798 insertions(+), 1252 deletions(-) diff --git a/.travis.yml b/.travis.yml index 98fbac9f90..84827ef8be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,3 +52,6 @@ script: pip3 install --user 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python' pip3 install --user requests $SHELL travis-script +after_script: + # always cleanup + - rm -rf "${TRAVIS_BUILD_DIR}/install" build test/bins \ No newline at end of file diff --git a/librz/arch/asm.c b/librz/arch/asm.c index a946711324..f88b2912c6 100644 --- a/librz/arch/asm.c +++ b/librz/arch/asm.c @@ -555,6 +555,11 @@ RZ_DEPRECATE RZ_API int rz_asm_set_bits(RzAsm *a, int bits) { return false; } +RZ_API ut32 rz_asm_get_endianness(RzAsm *a) { + rz_return_val_if_fail(a && a->cur, RZ_SYS_ENDIAN_NONE); + return a->cur->endian; +} + RZ_API bool rz_asm_set_big_endian(RzAsm *a, bool b) { rz_return_val_if_fail(a && a->cur, false); a->big_endian = false; // little endian by default diff --git a/librz/arch/p/analysis/analysis_m68k_cs.c b/librz/arch/p/analysis/analysis_m68k_cs.c index b442a28435..590593ccd3 100644 --- a/librz/arch/p/analysis/analysis_m68k_cs.c +++ b/librz/arch/p/analysis/analysis_m68k_cs.c @@ -187,7 +187,7 @@ static int m68k_analyze_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 cs_m68k *m68k; cs_detail *detail; - int mode = a->big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN; + cs_mode mode = 0; // mode |= (a->bits==64)? CS_MODE_64: CS_MODE_32; if (mode != ctx->omode || a->bits != ctx->obits) { diff --git a/librz/arch/p/analysis/analysis_riscv_cs.c b/librz/arch/p/analysis/analysis_riscv_cs.c index 1c7cb74435..afa6c2c1b9 100644 --- a/librz/arch/p/analysis/analysis_riscv_cs.c +++ b/librz/arch/p/analysis/analysis_riscv_cs.c @@ -37,20 +37,20 @@ #define SET_SRC_DST_3_REGS(op) \ CREATE_SRC_DST_3(op); \ - (op)->dst->reg = rz_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \ - (op)->src[0]->reg = rz_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR); \ - (op)->src[1]->reg = rz_reg_get(analysis->reg, REG(2), RZ_REG_TYPE_GPR); + (op)->dst->reg = riscv_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \ + (op)->src[0]->reg = riscv_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR); \ + (op)->src[1]->reg = riscv_reg_get(analysis->reg, REG(2), RZ_REG_TYPE_GPR); #define SET_SRC_DST_3_IMM(op) \ CREATE_SRC_DST_3(op); \ - (op)->dst->reg = rz_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \ - (op)->src[0]->reg = rz_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR); \ + (op)->dst->reg = riscv_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \ + (op)->src[0]->reg = riscv_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR); \ (op)->src[1]->imm = IMM(2); #define SET_SRC_DST_2_REGS(op) \ CREATE_SRC_DST_2(op); \ - (op)->dst->reg = rz_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \ - (op)->src[0]->reg = rz_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR); + (op)->dst->reg = riscv_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \ + (op)->src[0]->reg = riscv_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR); #define SET_SRC_DST_3_REG_OR_IMM(op) \ if (OPERAND(2).type == RISCV_OP_IMM) { \ @@ -61,6 +61,14 @@ static void set_stack_effect(RzAnalysisOp *op, cs_insn *insn); +static RzRegItem *riscv_reg_get(const RzReg *reg, const char *name, int type) { + if (!reg || RZ_STR_ISEMPTY(name)) { + RZ_LOG_DEBUG("riscv: reg (%p) or name (%p) is null (type %d)\n", reg, name, type); + return NULL; + } + return rz_reg_get(reg, name, type); +} + static RzStructuredData *riscv_opex(csh handle, cs_insn *insn) { if (!insn->detail) { return NULL; @@ -150,7 +158,7 @@ static void op_fillval(RzAnalysis *analysis, RzAnalysisOp *op, csh *handle, cs_i ZERO_FILL(ctx->reg); op->dst = rz_analysis_value_new(); op->dst->type = RZ_ANALYSIS_VAL_REG; - op->dst->reg = rz_reg_get(analysis->reg, cs_reg_name(*handle, FIRST_WRITTEN_REGID(insn)), RZ_REG_TYPE_GPR); + op->dst->reg = riscv_reg_get(analysis->reg, cs_reg_name(*handle, FIRST_WRITTEN_REGID(insn)), RZ_REG_TYPE_GPR); op->src[0] = rz_analysis_value_new(); op->src[0]->type = RZ_ANALYSIS_VAL_MEM; op->src[0]->reg = &ctx->reg; @@ -170,7 +178,7 @@ static void op_fillval(RzAnalysis *analysis, RzAnalysisOp *op, csh *handle, cs_i op->dst->memref = op->refptr; op->src[0] = rz_analysis_value_new(); op->src[0]->type = RZ_ANALYSIS_VAL_REG; - op->src[0]->reg = rz_reg_get(analysis->reg, cs_reg_name(*handle, FIRST_READ_REGID(insn)), RZ_REG_TYPE_GPR); + op->src[0]->reg = riscv_reg_get(analysis->reg, cs_reg_name(*handle, FIRST_READ_REGID(insn)), RZ_REG_TYPE_GPR); } break; case RZ_ANALYSIS_OP_TYPE_SHL: diff --git a/librz/arch/p/analysis/analysis_riscv_utils.h b/librz/arch/p/analysis/analysis_riscv_utils.h index 6687ad774d..753190849a 100644 --- a/librz/arch/p/analysis/analysis_riscv_utils.h +++ b/librz/arch/p/analysis/analysis_riscv_utils.h @@ -1,106 +1,102 @@ // SPDX-FileCopyrightText: 2024-2026 moste00 // SPDX-License-Identifier: BSD-3-Clause -#include +#ifndef ANALYSIS_RISCV_UTILS_H +#define ANALYSIS_RISCV_UTILS_H -#include "cs_operand.h" -#include "rz_util/rz_log.h" +#include #include #include #include -// A more high-level alternative to direct indexing that can get immediates and operands without exact -// indices -// While also enforcing high-level constraints such as "exactly one immediate operand is present" -// or "at most one operand is present" or "get the single register that is read/written" +// A more high-level alternative to direct indexing that can get immediates and operands without exact indices +// While also enforcing high-level constraints such as "exactly one immediate operand is present" or "at most +// one operand is present" or "get the single register that is read/written" -static inline int find_at_most_one_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type, const char *type_str) { - int first = -1; - for (int i = 0; i < op_count; i++) { +static inline ut32 find_at_most_one_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type, const char *type_str) { + ut32 first = UT32_MAX; + for (ut32 i = 0; i < op_count; i++) { if (operands[i].type == type) { - if (first == -1) { + if (first == UT32_MAX) { first = i; } else { - RZ_LOG_FATAL("Expected exactly one %s operand, two elements matched (the %ith and %ith elements)", type_str, first, i); - exit(-1); + RZ_LOG_DEBUG("Expected exactly one %s operand, two elements matched (the %ith and %ith elements)", type_str, first, i); } } } return first; } -static inline int find_at_most_one_imm(cs_riscv_op *operands, uint8_t op_count) { +static inline ut32 find_at_most_one_imm(cs_riscv_op *operands, uint8_t op_count) { return find_at_most_one_op(operands, op_count, RISCV_OP_IMM, "immediate"); } -static inline int find_exactly_one_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type, const char *type_str) { - int first = find_at_most_one_op(operands, op_count, type, type_str); - if (first == -1) { - RZ_LOG_FATAL("Expected exactly one %s operand, found none", type_str); - exit(-1); - } - return first; +static inline ut32 find_exactly_one_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type, const char *type_str) { + return find_at_most_one_op(operands, op_count, type, type_str); } -static inline int find_exactly_one_imm(cs_riscv_op *operands, uint8_t op_count) { +static inline ut32 find_exactly_one_imm(cs_riscv_op *operands, uint8_t op_count) { return find_exactly_one_op(operands, op_count, RISCV_OP_IMM, "immediate"); } static inline int64_t get_exactly_one_immediate(cs_riscv_op *operands, uint8_t op_count) { - return operands[find_exactly_one_imm(operands, op_count)].imm; + ut32 idx = find_exactly_one_imm(operands, op_count); + if (idx < op_count) { + return operands[idx].imm; + } + return INT64_MAX; } static inline int64_t get_at_most_one_immediate(cs_riscv_op *operands, uint8_t op_count) { - int64_t idx = find_at_most_one_imm(operands, op_count); - if (idx == -1) { - return INT64_MAX; + ut32 idx = find_at_most_one_imm(operands, op_count); + if (idx < op_count) { + return operands[idx].imm; } - return operands[idx].imm; + return INT64_MAX; } #define SINGLE_IMM(insn) get_exactly_one_immediate(insn->detail->riscv.operands, insn->detail->riscv.op_count); #define MAYBE_IMM(insn) get_at_most_one_immediate(insn->detail->riscv.operands, insn->detail->riscv.op_count); -static inline int find_first_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type) { - for (int i = 0; i < op_count; i++) { +static inline ut32 find_first_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type) { + for (ut32 i = 0; i < op_count; i++) { if (operands[i].type == type) { return i; } } - return -1; + return UT32_MAX; } -static inline int find_first_imm(cs_riscv_op *operands, uint8_t op_count) { +static inline ut32 find_first_imm(cs_riscv_op *operands, uint8_t op_count) { return find_first_op(operands, op_count, RISCV_OP_IMM); } static inline int64_t get_first_immediate(cs_riscv_op *operands, uint8_t op_count) { - int idx = find_first_imm(operands, op_count); - if (idx == -1) { - return INT64_MAX; + ut32 idx = find_first_imm(operands, op_count); + if (idx < op_count) { + return operands[idx].imm; } - return operands[idx].imm; + return INT64_MAX; } #define FIRST_IMM(insn) get_first_immediate(insn->detail->riscv.operands, insn->detail->riscv.op_count); -static inline unsigned int get_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_count, cs_ac_type access) { - for (int i = 0; i < op_count; i++) { +static inline ut32 get_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_count, cs_ac_type access) { + for (ut32 i = 0; i < op_count; i++) { if (operands[i].type == RISCV_OP_REG && (operands[i].access & access)) { return operands[i].reg; } } - RZ_LOG_FATAL("Expected at least one register with %s access, found none", access == CS_AC_READ ? "read" : "write"); - exit(-1); + RZ_LOG_DEBUG("Expected at least one register with %s access, found none", access == CS_AC_READ ? "read" : "write"); return 0; // dummy for type checking, never reached } -static inline unsigned int first_read_register(cs_riscv_op *operands, uint8_t op_count) { +static inline ut32 first_read_register(cs_riscv_op *operands, uint8_t op_count) { return get_any_reg_accessed_as(operands, op_count, CS_AC_READ); } -static inline unsigned int first_written_register(cs_riscv_op *operands, uint8_t op_count) { +static inline ut32 first_written_register(cs_riscv_op *operands, uint8_t op_count) { return get_any_reg_accessed_as(operands, op_count, CS_AC_WRITE); } @@ -108,7 +104,7 @@ static inline unsigned int first_written_register(cs_riscv_op *operands, uint8_t #define FIRST_WRITTEN_REGID(insn) first_written_register(insn->detail->riscv.operands, insn->detail->riscv.op_count) // check if a certain reg is ever accessed as read/write register -static inline bool is_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_count, unsigned int reg, cs_ac_type access) { +static inline bool is_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_count, ut32 reg, cs_ac_type access) { for (int i = 0; i < op_count; i++) { if (operands[i].type == RISCV_OP_REG && operands[i].reg == reg && (operands[i].access & access)) { return true; @@ -117,10 +113,10 @@ static inline bool is_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_coun return false; } -static inline bool is_reg_written(cs_riscv_op *operands, uint8_t op_count, unsigned int reg) { +static inline bool is_reg_written(cs_riscv_op *operands, uint8_t op_count, ut32 reg) { return is_any_reg_accessed_as(operands, op_count, reg, CS_AC_WRITE); } -static inline bool is_reg_read(cs_riscv_op *operands, uint8_t op_count, unsigned int reg) { +static inline bool is_reg_read(cs_riscv_op *operands, uint8_t op_count, ut32 reg) { return is_any_reg_accessed_as(operands, op_count, reg, CS_AC_READ); } @@ -128,7 +124,7 @@ static inline bool is_reg_read(cs_riscv_op *operands, uint8_t op_count, unsigned #define IS_REG_READ(insn, reg) is_reg_read(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg) static inline bool is_any_reg_memory_base(cs_riscv_op *operands, uint8_t op_count, unsigned int reg) { - for (int i = 0; i < op_count; i++) { + for (ut32 i = 0; i < op_count; i++) { if (operands[i].type == RISCV_OP_MEM && operands[i].mem.base == reg) { return true; } @@ -136,4 +132,6 @@ static inline bool is_any_reg_memory_base(cs_riscv_op *operands, uint8_t op_coun return false; } -#define MEM_BASE(insn, reg) is_any_reg_memory_base(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg) \ No newline at end of file +#define MEM_BASE(insn, reg) is_any_reg_memory_base(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg) + +#endif /* ANALYSIS_RISCV_UTILS_H */ diff --git a/librz/arch/p/arch_riscv_cs.c b/librz/arch/p/arch_riscv_cs.c index b73fb9311c..d60dfa0f12 100644 --- a/librz/arch/p/arch_riscv_cs.c +++ b/librz/arch/p/arch_riscv_cs.c @@ -54,7 +54,7 @@ cs_mode cs_mode_from_feature_flag(ut64 feature_flag) { size_t expect_str(const char *arch_str, const char *expected, size_t curr) { size_t l = strlen(expected); if (strncmp(&arch_str[curr], expected, l) != 0) { - RZ_LOG_ERROR("Invalid architecture string: expected %s to equal %s", + RZ_LOG_ERROR("Invalid architecture string: expected %s to equal %s\n", arch_str, expected); return curr; } @@ -205,7 +205,7 @@ bool expect_extension(const char *arch_str, size_t *curr, cs_mode *cs_mode) { } // unreachable - RZ_LOG_ERROR("UNREACHABLE STATE WHEN PARSING RISCV ARCH STRING"); + rz_warn_if_reached(); return true; // done, this is a bad state and we should terminate parsing immediately } @@ -233,8 +233,8 @@ bool check_all_whitespace(const char *str) { return true; } size_t mode_from_arch_string(const char *arch_str) { - if (!arch_str || check_all_whitespace(arch_str)) { - RZ_LOG_WARN("RISCV: empty architecture string, no non-default extensions enabled\n"); + if (!arch_str || check_all_whitespace(arch_str) || RZ_STR_EQ(arch_str, "riscv")) { + RZ_LOG_INFO("RISCV: empty architecture string, no non-default extensions enabled\n"); return 0; } size_t curr = expect_architecture_string_header(arch_str); diff --git a/librz/arch/p/asm/asm_m68k_cs.c b/librz/arch/p/asm/asm_m68k_cs.c index 71032e05d2..0170eff471 100644 --- a/librz/arch/p/asm/asm_m68k_cs.c +++ b/librz/arch/p/asm/asm_m68k_cs.c @@ -20,7 +20,7 @@ static int m68k_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) { char *buf_asm = NULL; cs_insn *insn = NULL; int ret = 0, n = 0; - cs_mode mode = a->big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN; + cs_mode mode = 0; // replace this with the asm.features? if (a->cpu && strstr(a->cpu, "68000")) { diff --git a/librz/bin/format/bflt/bflt.c b/librz/bin/format/bflt/bflt.c index b27e9958c6..8b1ff60ed7 100644 --- a/librz/bin/format/bflt/bflt.c +++ b/librz/bin/format/bflt/bflt.c @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2026 deroad // SPDX-FileCopyrightText: 2021 Florian Märkl // SPDX-FileCopyrightText: 2016 Oscar Salvador // SPDX-License-Identifier: LGPL-3.0-only @@ -19,41 +20,28 @@ #define MAX_SHARED_LIBS 1 // this may be 4 depending on kernel config #define FLAT_DATA_ALIGN 0x20 -#define READ(x, i) \ - rz_read_be32((x) + (i)); \ - (i) += 4; +static bool bflt_parse_hdr(RzBuffer *buf, ut64 off, RzBfltHdr *h, bool big_endian) { + return rz_buf_read_offset(buf, &off, (ut8 *)h->magic, sizeof(h->magic)) && + rz_buf_read_ble32_offset(buf, &off, &h->rev, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->entry, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->data_start, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->data_end, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->bss_end, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->stack_size, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->reloc_start, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->reloc_count, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->flags, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->build_date, big_endian) && + rz_buf_read_offset(buf, &off, (ut8 *)h->padding, sizeof(h->padding)); +} static bool bflt_init_hdr(RzBfltObj *bin) { - ut8 bhdr[BFLT_HDR_SIZE] = { 0 }; - st64 len = rz_buf_read_at(bin->b, 0, bhdr, BFLT_HDR_SIZE); - if (len != BFLT_HDR_SIZE) { - RZ_LOG_WARN("read bFLT hdr failed\n"); + if (!bflt_parse_hdr(bin->b, 0, &bin->hdr, true)) { return false; - } - - if (strncmp((const char *)bhdr, "bFLT", 4)) { - RZ_LOG_WARN("wrong magic number in bFLT file\n"); - return false; - } - - memcpy(bin->hdr.magic, bhdr, 4); - size_t i = 4; - bin->hdr.rev = READ(bhdr, i); - bin->hdr.entry = READ(bhdr, i); - bin->hdr.data_start = READ(bhdr, i); - bin->hdr.data_end = READ(bhdr, i); - bin->hdr.bss_end = READ(bhdr, i); - bin->hdr.stack_size = READ(bhdr, i); - bin->hdr.reloc_start = READ(bhdr, i); - bin->hdr.reloc_count = READ(bhdr, i); - bin->hdr.flags = READ(bhdr, i); - bin->hdr.build_date = READ(bhdr, i); - - if (bin->hdr.rev != FLAT_VERSION) { + } else if (bin->hdr.rev != FLAT_VERSION) { RZ_LOG_WARN("only bFLT v4 is supported! This file has version %" PFMT32u "\n", bin->hdr.rev); return false; - } - if (bin->hdr.flags & FLAT_FLAG_GZIP || bin->hdr.flags & FLAT_FLAG_GZDATA) { + } else if (bin->hdr.flags & FLAT_FLAG_GZIP || bin->hdr.flags & FLAT_FLAG_GZDATA) { RZ_LOG_WARN("this bFLT file is compressed. This is not (yet) supported.\n"); } return true; @@ -62,9 +50,7 @@ static bool bflt_init_hdr(RzBfltObj *bin) { static bool bflt_reloc_big_endian(RzBfltObj *bin) { // if bin->hdr.flags & FLAT_FLAG_GOTPIC, then all relocs // are already in target order, otherwise they are always be - return (bin->hdr.flags & FLAT_FLAG_GOTPIC) - ? bin->big_endian - : true; + return (bin->hdr.flags & FLAT_FLAG_GOTPIC) ? bin->big_endian : true; } static void bflt_load_relocs(RzBfltObj *bin) { @@ -79,7 +65,7 @@ static void bflt_load_relocs(RzBfltObj *bin) { break; } ut32 value; - if (!rz_buf_read_ble32_at(bin->b, paddr, &value, big_endian)) { + if (!rz_buf_read_ble32_at(bin->b, paddr, &value, bin->big_endian)) { break; } if (value == 0xffffffff) { @@ -145,6 +131,47 @@ static void bflt_patch_relocs(RzBfltObj *bin) { rz_buf_sparse_set_write_mode(bin->buf_patched, RZ_BUF_SPARSE_WRITE_MODE_THROUGH); } +static void bflt_guess_arch(RzBuffer *buf, ut64 entry, const char **arch, bool *big_endian) { + *arch = "arm"; + *big_endian = false; + + ut8 code[4] = { 0 }; + if (rz_buf_read_at(buf, entry, code, sizeof(code)) != sizeof(code)) { + return; + } + +#define IS_BYTE(i, b, m) ((code[i] & m) == b) +#define IS_1_BYTES(b0, m0) IS_BYTE(0, b0, m0) +#define IS_2_BYTES(b0, m0, b1, m1) (IS_BYTE(0, b0, m0) && IS_BYTE(1, b1, m1)) +#define IS_4_BYTES(b0, m0, b1, m1, b2, m2, b3, m3) (IS_BYTE(0, b0, m0) && IS_BYTE(1, b1, m1) && IS_BYTE(2, b2, m2) && IS_BYTE(3, b3, m3)) + + if (IS_2_BYTES(0x20, 0xf1, 0x00, 0x40 /* move.l */) || + IS_2_BYTES(0x20, 0xf1, 0x40, 0x40 /* movea.l */) || + IS_2_BYTES(0x30, 0xf1, 0x40, 0x40 /* move.w */) || + IS_2_BYTES(0x48, 0xff, 0xe0, 0xff /* movem.l */) || + IS_2_BYTES(0x4e, 0xff, 0x50, 0xf8 /* link.w */) || + IS_2_BYTES(0x90, 0xf0, 0x80, 0xc0 /* sub.l */) || + IS_2_BYTES(0x90, 0xf0, 0x40, 0xc0 /* sub.w */) || + IS_2_BYTES(0x91, 0xf1, 0x80, 0xa0 /* suba.l */) || + IS_2_BYTES(0x90, 0xf1, 0x80, 0xa0 /* suba.w */) || + IS_1_BYTES(0x70, 0xff /* moveq */)) { + *arch = "m68k"; + *big_endian = true; + return; + } else if (IS_4_BYTES(0xe1, 0xfd, 0xa0, 0xff, 0x00, 0x00, 0x00, 0x00 /* mov */) || + IS_4_BYTES(0xe9, 0xfd, 0x2d, 0xff, 0x00, 0x00, 0x00, 0x00 /* push */)) { + // it's arm32:be + *big_endian = true; + return; + } + // it's arm32:le + +#undef IS_BYTE +#undef IS_1_BYTES +#undef IS_2_BYTES +#undef IS_4_BYTES +} + static bool rz_bflt_init(RzBfltObj *obj, RzBuffer *buf, ut64 baddr, bool big_endian, bool patch_relocs) { obj->b = rz_buf_ref(buf); obj->size = rz_buf_size(buf); @@ -155,6 +182,7 @@ static bool rz_bflt_init(RzBfltObj *obj, RzBuffer *buf, ut64 baddr, bool big_end if (!bflt_init_hdr(obj)) { return false; } + bflt_guess_arch(obj->b, 0x44, &obj->arch, &obj->big_endian); bflt_load_relocs(obj); if (patch_relocs) { bflt_patch_relocs(obj); diff --git a/librz/bin/format/bflt/bflt.h b/librz/bin/format/bflt/bflt.h index d5bb465551..daa7abbb6a 100644 --- a/librz/bin/format/bflt/bflt.h +++ b/librz/bin/format/bflt/bflt.h @@ -30,7 +30,7 @@ typedef struct rz_bflt_hdr_t { ut32 reloc_count; ut32 flags; ut32 build_date; - ut32 filler[5]; + ut8 padding[20]; } RzBfltHdr; typedef struct rz_bflt_reloc_t { @@ -46,6 +46,7 @@ typedef struct rz_bflt_obj_t { RzBuffer *buf_patched; ///< overlay over the original file with relocs patched ut64 baddr; bool big_endian; + const char *arch; size_t size; uint32_t n_got; } RzBfltObj; diff --git a/librz/bin/format/elf/elf_info.c b/librz/bin/format/elf/elf_info.c index c22207a7c9..26ea973df2 100644 --- a/librz/bin/format/elf/elf_info.c +++ b/librz/bin/format/elf/elf_info.c @@ -768,7 +768,7 @@ typedef enum { * \param [out] result_len The length of usable data in the result buffer, always <= result_maxlen * \return riscv_attr_type The type of the found attribute, indicating whether it's a string or uleb128 integer and whether it was truncated */ -static riscv_attr_type get_riscv_attribute_from_section(RzBuffer *sec, ut64 attr_tag, int result_maxlen, ut8 *result, int *result_len) { +static riscv_attr_type get_riscv_attribute_from_section(RzBuffer *sec, ut64 attr_tag, size_t result_maxlen, ut8 *result, size_t *result_len) { // format: /* * */ @@ -778,14 +778,14 @@ static riscv_attr_type get_riscv_attribute_from_section(RzBuffer *sec, ut64 attr ut64 curr = 0; // format byte - ut8 format; + ut8 format = 0; if (!sec || !rz_buf_read8_offset(sec, &curr, &format) || format != 'A') { RZ_LOG_ERROR("Can't read the format byte of the RISCV attrbiute section or found a different format (expected 'A' at section start)\n"); return RISCV_ATTR_NONE; } // subsection length - ut32 subsec_len; + ut32 subsec_len = 0; if (!rz_buf_read_ble32_offset(sec, &curr, &subsec_len, /* big endian? */ false)) { RZ_LOG_ERROR("Can't read the subsection length of the RISCV attribute section\n"); return RISCV_ATTR_NONE; @@ -802,7 +802,7 @@ static riscv_attr_type get_riscv_attribute_from_section(RzBuffer *sec, ut64 attr // now parse the tag-value array while (curr < rz_buf_size(sec)) { - ut64 tag; + ut64 tag = 0; ut32 num_bytes_read = rz_buf_uleb128_at(sec, curr, &tag); curr += num_bytes_read; @@ -822,7 +822,7 @@ static riscv_attr_type get_riscv_attribute_from_section(RzBuffer *sec, ut64 attr // Like ARM but even simpler, no special cases for tags below 32 bool tag_is_odd = tag & 0x1; - int result_curr = 0; + size_t result_curr = 0; // value is a null-terminated string if (tag_is_odd) { int string_starts_at = curr; @@ -840,7 +840,7 @@ static riscv_attr_type get_riscv_attribute_from_section(RzBuffer *sec, ut64 attr bool result_overflow = false; // have we filled the buffer ? - if (result_curr == result_maxlen) { + if (result_curr >= result_maxlen) { result_overflow = result[result_maxlen - 1] != '\0'; // must force the last byte to null, in case the original string was too long result[result_maxlen - 1] = '\0'; @@ -863,7 +863,7 @@ static riscv_attr_type get_riscv_attribute_from_section(RzBuffer *sec, ut64 attr bool result_overflow = false; // have we filled the buffer ? - if (result_curr == result_maxlen) { + if (result_curr >= result_maxlen) { result_overflow = result[result_maxlen - 1] & 0x80; // must force the last byte to a terminal byte, in case the original number was too long result[result_maxlen - 1] = result[result_maxlen - 1] & 0x7F; @@ -926,8 +926,8 @@ static inline bool arch_is_parisc(ELFOBJ *bin) { return arch_is(bin, EM_PARISC); } -static bool arch_is_riscv(ELFOBJ *bin) { - return bin->ehdr.e_machine == EM_RISCV; +static inline bool arch_is_riscv(ELFOBJ *bin) { + return arch_is(bin, EM_RISCV); } static char *read_elf_intrp(ELFOBJ *bin, ut64 addr, size_t size) { @@ -1523,6 +1523,19 @@ static char *get_cpu_h8xx(ELFOBJ *bin) { return rz_str_dup("h8300"); } +static char *get_cpu_riscv(ELFOBJ *bin) { + char bin_arch[256] = { 0 }; + size_t len = 0; + riscv_attr_type typ = get_riscv_attribute_from_section(get_riscv_attributes_section(bin), T_RISCV_arch, sizeof(bin_arch), (ut8 *)bin_arch, &len); + len = RZ_MIN(len, sizeof(bin_arch)); + if (typ == RISCV_ATTR_NT_STRING) { + return rz_str_ndup((const char *)bin_arch, len); + } + + // some hardcoded fallback, the mafd + vector + return strdup("rv64i2p0_c2p0_m2p0_a2p0_f2p0_d2p0_v2p0"); +} + /** * \brief List all imported lib * \param elf binary @@ -2117,14 +2130,7 @@ RZ_OWN char *Elf_(rz_bin_elf_get_cpu)(RZ_NONNULL ELFOBJ *bin) { } else if (arch_is_h8xx(bin)) { return get_cpu_h8xx(bin); } else if (arch_is_riscv(bin)) { - ut8 archstr[256]; - int archstr_len; - riscv_attr_type typ = get_riscv_attribute_from_section(get_riscv_attributes_section(bin), T_RISCV_arch, 256, archstr, &archstr_len); - if (typ == RISCV_ATTR_NT_STRING) { - return rz_str_dup((const char *)archstr); - } - // some hardcoded fallback, the mafd + vector - return strdup("rv64i2p0_c2p0_m2p0_a2p0_f2p0_d2p0_v2p0"); + return get_cpu_riscv(bin); } return NULL; } diff --git a/librz/bin/format/wasm/wasm.c b/librz/bin/format/wasm/wasm.c index 4d3c1d99a4..9087dcb20b 100644 --- a/librz/bin/format/wasm/wasm.c +++ b/librz/bin/format/wasm/wasm.c @@ -127,7 +127,7 @@ static size_t consume_locals_r(RzBuffer *b, ut64 max, RzBinWasmCodeEntry *out) { if (!(consume_u32_r(b, max, &out->locals[j].count))) { goto beach; } - if (!(consume_s7_r(b, max, (st8 *)&out->locals[j].type))) { + if (!(consume_s7_r(b, max, &out->locals[j].type))) { goto beach; } j++; @@ -314,24 +314,24 @@ static void *parse_type_entry(RzBuffer *b, ut64 max) { goto beach; } if (count > 0) { - if (!(ptr->param_types = RZ_NEWS0(RzBinWasmValueType, count))) { + if (!(ptr->param_types = RZ_NEWS0(st8, count))) { goto beach; } } int j; for (j = 0; j < count; j++) { - if (!(consume_s7_r(b, max, (st8 *)&ptr->param_types[j]))) { + if (!(consume_s7_r(b, max, &ptr->param_types[j]))) { goto beach; } } - if (!(consume_u1_r(b, max, (ut8 *)&ptr->return_count))) { + if (!(consume_u1_r(b, max, &ptr->return_count))) { goto beach; } if (ptr->return_count > 1) { goto beach; } if (ptr->return_count == 1) { - if (!(consume_s7_r(b, max, (st8 *)&ptr->return_type))) { + if (!(consume_s7_r(b, max, &ptr->return_type))) { goto beach; } } @@ -363,7 +363,7 @@ static void *parse_import_entry(RzBuffer *b, ut64 max) { } break; case RZ_BIN_WASM_EXTERNALKIND_Table: - if (!(consume_s7_r(b, max, (st8 *)&ptr->type_t.elem_type))) { + if (!(consume_s7_r(b, max, &ptr->type_t.elem_type))) { goto beach; } if (!(consume_limits_r(b, max, &ptr->type_t.limits))) { @@ -376,10 +376,10 @@ static void *parse_import_entry(RzBuffer *b, ut64 max) { } break; case RZ_BIN_WASM_EXTERNALKIND_Global: - if (!(consume_s7_r(b, max, (st8 *)&ptr->type_g.content_type))) { + if (!(consume_s7_r(b, max, &ptr->type_g.content_type))) { goto beach; } - if (!(consume_u1_r(b, max, (ut8 *)&ptr->type_g.mutability))) { + if (!(consume_u1_r(b, max, &ptr->type_g.mutability))) { goto beach; } break; @@ -614,7 +614,7 @@ static void *parse_table_entry(RzBuffer *b, ut64 max) { if (!ptr) { return NULL; } - if (!(consume_s7_r(b, max, (st8 *)&ptr->element_type))) { + if (!(consume_s7_r(b, max, &ptr->element_type))) { goto beach; } if (!(consume_limits_r(b, max, &ptr->limits))) { @@ -632,7 +632,7 @@ static void *parse_global_entry(RzBuffer *b, ut64 max) { if (!ptr) { return NULL; } - if (!(consume_u7_r(b, max, (ut8 *)&ptr->content_type))) { + if (!(consume_u7_r(b, max, &ptr->content_type))) { goto beach; } if (!(consume_u1_r(b, max, &ptr->mutability))) { diff --git a/librz/bin/format/wasm/wasm.h b/librz/bin/format/wasm/wasm.h index c1502ae4b0..09a7c230af 100644 --- a/librz/bin/format/wasm/wasm.h +++ b/librz/bin/format/wasm/wasm.h @@ -84,19 +84,19 @@ typedef struct rz_bin_wasm_section_t { typedef struct rz_bin_wasm_type_t { ut8 form; ut32 param_count; - RzBinWasmValueType *param_types; - st8 return_count; // MVP = 1 - RzBinWasmValueType return_type; + st8 /* RzBinWasmValueType */ *param_types; + ut8 return_count; // MVP = 1 + st8 /* RzBinWasmValueType */ return_type; } RzBinWasmTypeEntry; // Other Types typedef struct rz_bin_wasm_global_type_t { - RzBinWasmValueType content_type; + st8 /* RzBinWasmValueType */ content_type; ut8 mutability; } RzBinWasmGlobalType; typedef struct rz_bin_wasm_table_type_t { - RzBinWasmValueType elem_type; + st8 /* RzBinWasmValueType */ elem_type; RzBinWasmResizableLimits limits; } RzBinWasmTableType; @@ -124,7 +124,7 @@ typedef struct rz_bin_wasm_function_t { } RzBinWasmFunctionEntry; typedef struct rz_bin_wasm_table_t { - ut8 element_type; // only anyfunc + st8 element_type; // only anyfunc RzBinWasmResizableLimits limits; } RzBinWasmTableEntry; @@ -133,7 +133,7 @@ typedef struct rz_bin_wasm_memory_t { } RzBinWasmMemoryEntry; typedef struct rz_bin_wasm_global_t { - RzBinWasmValueType content_type; + ut8 /* RzBinWasmValueType */ content_type; ut8 mutability; // 0 if immutable, 1 if mutable RzBinWasmInitExpr init; } RzBinWasmGlobalEntry; @@ -151,7 +151,7 @@ typedef struct rz_bin_wasm_start_t { typedef struct rz_bin_wasm_local_entry_t { ut32 count; - RzBinWasmValueType type; + st8 /* RzBinWasmValueType */ type; } RzBinWasmLocalEntry; typedef struct rz_bin_wasm_element_t { @@ -164,7 +164,7 @@ typedef struct rz_bin_wasm_element_t { typedef struct rz_bin_wasm_code_t { ut32 body_size; ut32 local_count; // numer of local entries - struct rz_bin_wasm_local_entry_t *locals; + RzBinWasmLocalEntry *locals; ut32 code; // offset ut32 len; // real bytecode length ut8 byte; // 0xb, indicating end of the body diff --git a/librz/bin/p/bin_bflt.c b/librz/bin/p/bin_bflt.c index 14feafb1f7..a9e3b2c5d2 100644 --- a/librz/bin/p/bin_bflt.c +++ b/librz/bin/p/bin_bflt.c @@ -11,12 +11,12 @@ #define VFILE_NAME_PATCHED "patched" -static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb) { +static bool bflt_load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb) { obj->bin_obj = rz_bflt_new_buf(buf, obj->opts.baseaddr, obj->opts.big_endian, obj->opts.patch_relocs); return obj->bin_obj; } -static RzPVector /**/ *entries(RzBinFile *bf) { +static RzPVector /**/ *bflt_entries(RzBinFile *bf) { RzBfltObj *obj = bf->o->bin_obj; RzPVector *ret; RzBinAddr *ptr; @@ -33,7 +33,7 @@ static RzPVector /**/ *entries(RzBinFile *bf) { return ret; } -static RzPVector /**/ *maps(RzBinFile *bf) { +static RzPVector /**/ *bflt_maps(RzBinFile *bf) { RzBfltObj *obj = bf->o->bin_obj; RzPVector *ret = rz_pvector_new((RzPVectorFree)rz_bin_map_free); if (!ret) { @@ -71,7 +71,7 @@ static RzPVector /**/ *maps(RzBinFile *bf) { return ret; } -static RzPVector /**/ *sections(RzBinFile *bf) { +static RzPVector /**/ *bflt_sections(RzBinFile *bf) { RzBfltObj *obj = bf->o->bin_obj; RzPVector *ret = rz_pvector_new((RzPVectorFree)rz_bin_section_free); if (!ret) { @@ -164,7 +164,7 @@ beach: return NULL; } -static RzPVector /**/ *virtual_files(RzBinFile *bf) { +static RzPVector /**/ *bflt_virtual_files(RzBinFile *bf) { RzBfltObj *obj = bf->o->bin_obj; RzPVector *r = rz_pvector_new((RzPVectorFree)rz_bin_virtual_file_free); if (!r) { @@ -200,7 +200,7 @@ static void convert_relocs(RzBfltObj *bin, RzPVector /**/ *out, Rz } } -static RzPVector /**/ *relocs(RzBinFile *bf) { +static RzPVector /**/ *bflt_relocs(RzBinFile *bf) { RzBfltObj *obj = (RzBfltObj *)bf->o->bin_obj; RzPVector *vec = rz_pvector_new((RzPVectorFree)rz_bin_reloc_free); if (!vec || !obj) { @@ -212,7 +212,7 @@ static RzPVector /**/ *relocs(RzBinFile *bf) { return vec; } -static RzBinInfo *info(RzBinFile *bf) { +static RzBinInfo *bflt_info(RzBinFile *bf) { RzBfltObj *obj = NULL; RzBinInfo *info = NULL; if (!bf || !bf->o || !bf->o->bin_obj) { @@ -228,7 +228,7 @@ static RzBinInfo *info(RzBinFile *bf) { info->type = rz_str_dup("bFLT (Executable file)"); info->os = rz_str_dup("Linux"); info->subsystem = rz_str_dup("uClinux"); - info->arch = rz_str_dup("arm"); // this is a wild guess, the format does not specify any arch, but arm is probably the most popular + info->arch = rz_str_dup(obj->arch); info->big_endian = obj->big_endian; info->bits = 32; info->has_va = true; @@ -238,13 +238,13 @@ static RzBinInfo *info(RzBinFile *bf) { return info; } -static bool check_buffer(RzBuffer *buf) { +static bool bflt_check_buffer(RzBuffer *buf) { ut8 tmp[4]; int r = rz_buf_read_at(buf, 0, tmp, sizeof(tmp)); return r == sizeof(tmp) && !memcmp(tmp, "bFLT", 4); } -static void destroy(RzBinFile *bf) { +static void bflt_destroy(RzBinFile *bf) { rz_bflt_free(bf->o->bin_obj); } @@ -267,7 +267,8 @@ static RzStructuredData *bflt_structure(RzBinFile *bf) { return NULL; } - rz_structured_data_map_add_bytes(bflt_sd, "Magic", (const ut8 *)bin->hdr.magic, 4, RZ_STRUCTURED_DATA_FORMAT_HEXDUMP); + rz_structured_data_map_add_string(bflt_sd, "guessed_arch", bin->arch); + rz_structured_data_map_add_bytes(bflt_sd, "Magic", (const ut8 *)bin->hdr.magic, sizeof(bin->hdr.magic), RZ_STRUCTURED_DATA_FORMAT_HEXDUMP); rz_structured_data_map_add_unsigned(bflt_sd, "Revision", bin->hdr.rev, true); rz_structured_data_map_add_unsigned(bflt_sd, "Entry", bin->hdr.entry, true); @@ -279,6 +280,7 @@ static RzStructuredData *bflt_structure(RzBinFile *bf) { rz_structured_data_map_add_unsigned(bflt_sd, "RelocCount", bin->hdr.reloc_count, false); rz_structured_data_map_add_unsigned(bflt_sd, "Flags", bin->hdr.flags, true); rz_structured_data_map_add_unsigned(bflt_sd, "BuildDate", bin->hdr.build_date, false); + rz_structured_data_map_add_bytes(bflt_sd, "Padding", (const ut8 *)bin->hdr.padding, sizeof(bin->hdr.padding), RZ_STRUCTURED_DATA_FORMAT_HEXDUMP); return info; } @@ -287,16 +289,16 @@ RzBinPlugin rz_bin_plugin_bflt = { .desc = "bFLT uClinux binary", .license = "LGPL3", .author = "Oscar Salvador", - .load_buffer = &load_buffer, - .destroy = &destroy, - .check_buffer = &check_buffer, - .virtual_files = &virtual_files, - .maps = &maps, - .entries = &entries, - .sections = §ions, - .info = &info, + .load_buffer = &bflt_load_buffer, + .destroy = &bflt_destroy, + .check_buffer = &bflt_check_buffer, + .virtual_files = &bflt_virtual_files, + .maps = &bflt_maps, + .entries = &bflt_entries, + .sections = &bflt_sections, + .info = &bflt_info, .bin_structure = &bflt_structure, - .relocs = &relocs + .relocs = &bflt_relocs }; #ifndef RZ_PLUGIN_INCORE diff --git a/librz/core/carch.c b/librz/core/carch.c index f3561310cf..03b5fd4a63 100644 --- a/librz/core/carch.c +++ b/librz/core/carch.c @@ -19,6 +19,7 @@ #define core_update_config_s core_update_config_node_without_callback_string #define core_update_config_i core_update_config_node_without_callback_int +#define core_update_config_b core_update_config_node_without_callback_bool RZ_DEPRECATE RZ_IPI const char *rz_core_get_arch(RzCore *core) { rz_return_val_if_fail(core && core->rasm, CORE_DEFAULT_ARCH); @@ -179,6 +180,73 @@ static void core_update_config_features_options(RzCore *core, const char *name) core_update_config_options(node, core->rasm->cur->features); } +RZ_DEPRECATE static const RzBinInfo *core_arch_find_bin_info(RzCore *core, const char *arch) { + if (RZ_STR_ISEMPTY(arch)) { + return NULL; + } + const RzCoreFile *cf = NULL; + RzListIter *lit; + void **vit; + + rz_list_foreach (core->files, lit, cf) { + rz_pvector_foreach (&cf->binfiles, vit) { + const RzBinFile *bf = *vit; + const RzBinInfo *info = rz_bin_object_get_info(bf->o); + if (info && info->arch && RZ_STR_EQ(info->arch, arch)) { + return info; + } + } + } + + return NULL; +} + +static bool core_arch_default_is_big_endian(RzCore *core) { + bool big_endian = core->rasm->big_endian; + const char *arch = rz_core_get_arch(core); + + const RzBinInfo *info = core_arch_find_bin_info(core, arch); + if (info) { + // always follow what the RzBin says first. + big_endian = info->big_endian; + } + + ut32 endian = rz_asm_get_endianness(core->rasm); + if (endian == RZ_SYS_ENDIAN_NONE || endian == RZ_SYS_ENDIAN_BI) { + // always return what the bin or default endianness of the system + return big_endian; + } + + if (big_endian && endian & RZ_SYS_ENDIAN_BIG) { + // the endianness must be big endian. + return true; + } + + // the user must have asked for an arch that does not follow + // what the bin says (or is just little endian) so, we return + // as little endian. + return false; +} + +RZ_DEPRECATE static void core_update_endianness(RzCore *core) { + bool big_endian = core_arch_default_is_big_endian(core); + + rz_asm_set_big_endian(core->rasm, big_endian); + rz_analysis_set_big_endian(core->analysis, big_endian); + + // While analysis sets endianess for TypesDB there might + // be cases when it isn't availble for the chosen analysis + // plugin but types and printing commands still need the + // corresponding endianness. Thus we set these explicitly: + rz_type_db_set_endian(core->analysis->typedb, big_endian); + core->print->big_endian = big_endian; + + // the big endian should also be assigned to dbg->bp->endian + if (core->dbg && core->dbg->bp) { + core->dbg->bp->endian = big_endian; + } +} + // most of this code is a copy from cconfig RZ_DEPRECATE static void core_update_syscall_db(RzCore *core) { if (core->analysis->syscall->db) { @@ -254,30 +322,12 @@ RZ_DEPRECATE static bool core_arch_set_cpu(RzCore *core, const char *arch, const return true; } -static ut32 core_arch_find_bits_via_bin(RzCore *core, const char *arch) { - const RzCoreFile *cf = NULL; - RzListIter *lit; - void **vit; - - rz_list_foreach (core->files, lit, cf) { - rz_pvector_foreach (&cf->binfiles, vit) { - const RzBinFile *bf = *vit; - const RzBinInfo *info = rz_bin_object_get_info(bf->o); - if (info && info->arch && RZ_STR_EQ(info->arch, arch)) { - return info->bits; - } - } - } - - return 0; -} - static ut32 core_arch_get_default_bits(RzCore *core, const char *arch) { - const ut32 bits = core_arch_find_bits_via_bin(core, arch); - if (bits) { - return bits; + const RzBinInfo *info = core_arch_find_bin_info(core, arch); + if (!info || info->bits < 1) { + return core->rasm->bits; } - return core->rasm->bits; + return info->bits; } RZ_DEPRECATE static bool core_update_arch(RzCore *core, const char *arch, ut32 bits, const char *cpu, const char *os, const char *platform) { @@ -311,6 +361,9 @@ RZ_DEPRECATE static bool core_update_arch(RzCore *core, const char *arch, ut32 b bits = rz_core_get_bits(core); } + // always update the endianness + core_update_endianness(core); + if (RZ_STR_ISEMPTY(arch)) { // we now need the current arch. arch = rz_core_get_arch(core); @@ -341,6 +394,7 @@ RZ_DEPRECATE static bool core_update_arch(RzCore *core, const char *arch, ut32 b } core_arch_set_os(core, arch, bits, cpu, os); + return true; } @@ -381,6 +435,22 @@ RZ_DEPRECATE static void core_update_config_node_without_callback_int(RzCore *co node->setter = setter; } +// this is a ugly hack +RZ_DEPRECATE static void core_update_config_node_without_callback_bool(RzCore *core, const char *name, bool value) { + RzConfigNode *node = rz_config_node_get(core->config, name); + if (!node) { + // the node does not exist yet and we can set stuff without worring about the callback + rz_config_set_b(core->config, name, value); + return; + } + + RzConfigCallback setter = node->setter; + + node->setter = NULL; + rz_config_set_b(core->config, name, value); + node->setter = setter; +} + RZ_DEPRECATE static void core_update_config_from_arch(RzCore *core, bool new_arch) { // this is a terrible way to update the values but the current config // does weird callback calls which should not be done in this way and @@ -406,6 +476,7 @@ RZ_DEPRECATE static void core_update_config_from_arch(RzCore *core, bool new_arc core_update_config_s(core, "analysis.arch", arch); core_update_config_s(core, "analysis.cpu", cpu); core_update_config_i(core, "analysis.bits", bits); + core_update_config_b(core, "cfg.bigendian", core->rasm->big_endian); if (new_arch) { core_update_config_bits_options(core, "asm.bits"); diff --git a/librz/core/cio.c b/librz/core/cio.c index f051cf19e9..c857ded5ef 100644 --- a/librz/core/cio.c +++ b/librz/core/cio.c @@ -518,7 +518,7 @@ RZ_API RzCmdStatus rz_core_io_plugins_print(RZ_NONNULL RZ_BORROW RzIO *io, RzCmd RZ_API bool rz_core_write_value_at(RzCore *core, ut64 addr, ut64 value, int sz) { rz_return_val_if_fail(sz == 0 || sz == 1 || sz == 2 || sz == 4 || sz == 8, false); ut8 buf[sizeof(ut64)]; - bool be = rz_config_get_i(core->config, "cfg.bigendian"); + bool be = rz_config_get_b(core->config, "cfg.bigendian"); core->num->value = 0; if (sz == 0) { @@ -564,7 +564,7 @@ RZ_API bool rz_core_write_value_inc_at(RzCore *core, ut64 addr, st64 value, int rz_return_val_if_fail(sz == 1 || sz == 2 || sz == 4 || sz == 8, false); ut8 buf[sizeof(ut64)]; - bool be = rz_config_get_i(core->config, "cfg.bigendian"); + bool be = rz_config_get_b(core->config, "cfg.bigendian"); if (!rz_io_read_at_mapped(core->io, addr, buf, sz)) { return false; diff --git a/librz/core/cmd/cmd.c b/librz/core/cmd/cmd.c index 3bc2c73bf3..d76b8306d2 100644 --- a/librz/core/cmd/cmd.c +++ b/librz/core/cmd/cmd.c @@ -1851,7 +1851,7 @@ DEFINE_HANDLE_TS_FCN_AND_SYMBOL(tmp_value_op) { ut64 v = rz_num_math(core->num, arg_str); ut8 buf[8] = { 0 }; - int be = rz_config_get_i(core->config, "cfg.bigendian"); + int be = rz_config_get_b(core->config, "cfg.bigendian"); int bi = rz_config_get_i(core->config, "asm.bits"); rz_write_ble(buf, v, be, bi); diff --git a/librz/core/rtr.c b/librz/core/rtr.c index a06a89940c..da09259194 100644 --- a/librz/core/rtr.c +++ b/librz/core/rtr.c @@ -300,7 +300,7 @@ static int rz_core_rtr_gdb_cb(libgdbr_t *g, void *core_ptr, const char *cmd, break; case 'r': // dr rz_debug_reg_sync(core->dbg, RZ_REG_TYPE_ANY, false); - be = rz_config_get_i(core->config, "cfg.bigendian"); + be = rz_config_get_b(core->config, "cfg.bigendian"); if (isspace((ut8)cmd[2])) { // dr reg const char *name, *val_ptr; char new_cmd[128] = { 0 }; diff --git a/librz/include/rz_asm.h b/librz/include/rz_asm.h index 3f9cae0758..36a4d2b498 100644 --- a/librz/include/rz_asm.h +++ b/librz/include/rz_asm.h @@ -177,6 +177,7 @@ RZ_API bool rz_asm_use_assembler(RzAsm *a, const char *name); RZ_API bool rz_asm_set_arch(RzAsm *a, const char *name, int bits); RZ_DEPRECATE RZ_API int rz_asm_set_bits(RzAsm *a, int bits); RZ_DEPRECATE RZ_API void rz_asm_set_cpu(RzAsm *a, const char *cpu); +RZ_API ut32 rz_asm_get_endianness(RzAsm *a); RZ_API bool rz_asm_set_big_endian(RzAsm *a, bool big_endian); RZ_API bool rz_asm_set_syntax(RzAsm *a, int syntax); RZ_API int rz_asm_syntax_from_string(const char *name); diff --git a/test/db/analysis/arc b/test/db/analysis/arc index 9cec4ad30b..825ecde484 100644 --- a/test/db/analysis/arc +++ b/test/db/analysis/arc @@ -2,8 +2,8 @@ NAME=arc: [B] FILE=malloc://512 CMDS=< 0x00002016] (ANAL) FILE=malloc://4096 CMDS=< call] - jump check FILE=malloc://4096 CMDS=< 0x00000008 8146 li a3, 0 -EOF -RUN - -NAME=branch with compress instruction -FILE== -CMDS=< 0x00000002 8280 ret :`-> 0x00000004 9d06 addi a3, a3, 7 @@ -660,14 +654,85 @@ EOF RUN -NAME=Vector instructions: symbol table +NAME=Vector instructions FILE=bins/elf/riscv_vec_arith CMDS=< /dev/null pfn~NT_TIB @@ -806,6 +844,7 @@ RUN NAME=Infinite Recursion segfault 2 FILE=malloc://1024 CMDS=< /dev/null pfn~NT_TIB @@ -819,6 +858,7 @@ NAME=One byte enum endianness BROKEN=1 FILE=malloc://1024 CMDS=< /dev/null f obj.empty_str 12 @ 0x0804a064 f obj.long_str1 12 @ 0x0804a04c @@ -28,6 +29,7 @@ NAME=ps+ libc++ 64bit FILE=bins/elf/stdstring64-libc++.LOAD1 ARGS=-n -m 0x00600dc8 CMDS=< /dev/null f obj.empty_str 24 @ 0x006010b8 f obj.long_str1 24 @ 0x00601088 diff --git a/test/db/cmd/cmd_px b/test/db/cmd/cmd_px index 4e61e116dc..dfd1c970c2 100644 --- a/test/db/cmd/cmd_px +++ b/test/db/cmd/cmd_px @@ -107,6 +107,7 @@ RUN NAME=pxdw 16 FILE=malloc://1024 CMDS=<10" echo "================================" /R | grep -A 8 0x000010cc @@ -2774,6 +2782,7 @@ FILE=bins/arm/crackme.arm32.bin CMDS=<=10" echo "================================" /R | grep -A 8 0x000010cc diff --git a/test/db/cmd/cmd_search_v b/test/db/cmd/cmd_search_v index 0c0a871f26..284534aba9 100644 --- a/test/db/cmd/cmd_search_v +++ b/test/db/cmd/cmd_search_v @@ -240,6 +240,7 @@ RUN NAME=/vj 4a search 4 byte in range with json FILE== CMDS=<x;!dos2unix x;cat x;rm x EOF diff --git a/test/db/cmd/metadata b/test/db/cmd/metadata index 8f69137a08..e2fd2454f1 100644 --- a/test/db/cmd/metadata +++ b/test/db/cmd/metadata @@ -175,6 +175,7 @@ RUN NAME=format memory metadata FILE== CMDS=< /dev/null ar r0=4 ar r1=2 @@ -162,6 +170,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar r3=4 # address ar r1=0 # init with dummy values @@ -288,6 +302,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar r2=4 # address ar r1=0x11111111 @@ -328,6 +344,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar r0=0x11223344 wx c0f30722 @@ -344,6 +361,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar r1=0x80000001 ar r2=0x1 @@ -501,6 +529,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar r1=-8 ar r2=2 @@ -525,6 +554,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar r4=-8 wx a410 @@ -541,6 +571,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar r0=0 ar r1=1 @@ -541,6 +573,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar r0=0 wx 070090e5 @@ -558,6 +591,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar r0=4 ar r1=2 @@ -576,6 +610,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar sp=4 wx f91740f9 @@ -21,6 +22,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar sp=0x2c wx f9835df8 @@ -39,6 +41,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar sp=4 wx f91740f9 @@ -57,6 +60,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar sp=4 wx ec1f40b9 @@ -92,6 +96,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x16=4 wx 0a024039 @@ -109,6 +114,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x16=4 wx 0c064039 @@ -126,6 +132,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x19=4 ar x23=2 @@ -144,6 +151,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x8=4 wx 170140f9 @@ -161,6 +169,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x15=4 wx e80140b9 @@ -178,6 +187,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x10=4 ar x9=2 @@ -196,6 +206,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x11=4 ar w10=2 @@ -214,6 +225,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x13=4 ar x9=4 @@ -232,6 +244,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x13=4 ar x9=4 @@ -250,6 +263,7 @@ FILE=malloc://0x200 CMDS=< /dev/null wx 0c008012 aes @@ -265,6 +279,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar w15=0xaabbccdd ar w13=0x000000ff @@ -282,6 +297,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar w15=0xaabbccdd ar w12=0xffffffff @@ -299,6 +315,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar w11=4 wx 6b7d8b4a @@ -315,6 +332,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar w11=-4 wx 6b7d8b4a @@ -331,6 +349,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x21=-4 wx b4fe95ca @@ -347,6 +366,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar w11=-4 wx 6b010152 @@ -363,6 +383,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar w11=-4 ar w13=0x11223344 @@ -380,6 +401,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar w11=0xffeeddcc ar w15=0x7ffffffc @@ -397,6 +419,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x14=0xf982834129348123 wx cdb52eca @@ -413,6 +436,7 @@ FILE=malloc://0x200 CMDS=< /dev/null wx ed1f0032 aes @@ -428,6 +452,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar w0=0xffffffff wx 1f000153 @@ -444,6 +469,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x14=0xf982834129348123 ar x19=0xf982834129348123 @@ -461,6 +487,7 @@ FILE=malloc://0x200 CMDS=< /dev/null wx 000000915c000014 2aes @@ -476,6 +503,7 @@ FILE=malloc://0x200 CMDS=< /dev/null wx 400080d2210080d21f0001eb4d000054 4aes @@ -486,31 +514,12 @@ pc = 0x0000000000000010 EOF RUN -NAME=subs x0, x0, x1; csel x0, x2, x3, mi -FILE=malloc://0x200 -BROKEN=1 -CMDS=< /dev/null -ar x0=0 -ar x1=1 -ar x2=0x100 -ar x3=0x200 -wx 000001eb4040839a -2aes -ar x0 -EOF -EXPECT=< /dev/null ar x0=0 ar x1=1 @@ -538,6 +547,7 @@ FILE=malloc://0x200 CMDS=< /dev/null ar x8=0x140 wx 0415ffa8020dffa9000540a9061d7fa9 @@ -565,6 +575,7 @@ FILE=malloc://0x200 CMDS=< data reloc pi 1 @ 0x6908000+0x0000016c EOF EXPECT=<config, "cfg.bigendian", false); + rz_core_bin_load(core, NULL, 0); + // the default arch depends by the RZ_SYS_ARCH, and + // some archs allows different endianness, like ARM, but + // x86 is always LE, s390x is always BE, so we cannot set + // the endianness to a value not supported by the arch. + // ARM can be LE and BE, so we change the arch first + // then change the endianness. + rz_config_set(core->config, "asm.arch", "arm"); + rz_config_set_b(core->config, "cfg.bigendian", false); return core; }