Skip to content

Commit 7f55442

Browse files
authored
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
1 parent 1e33f52 commit 7f55442

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1797
-1251
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,6 @@ script:
5252
pip3 install --user 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python'
5353
pip3 install --user requests
5454
$SHELL travis-script
55+
after_script:
56+
# always cleanup
57+
- rm -rf "${TRAVIS_BUILD_DIR}/install" build test/bins

librz/arch/asm.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,11 @@ RZ_DEPRECATE RZ_API int rz_asm_set_bits(RzAsm *a, int bits) {
555555
return false;
556556
}
557557

558+
RZ_API ut32 rz_asm_get_endianness(RzAsm *a) {
559+
rz_return_val_if_fail(a && a->cur, RZ_SYS_ENDIAN_NONE);
560+
return a->cur->endian;
561+
}
562+
558563
RZ_API bool rz_asm_set_big_endian(RzAsm *a, bool b) {
559564
rz_return_val_if_fail(a && a->cur, false);
560565
a->big_endian = false; // little endian by default

librz/arch/p/analysis/analysis_m68k_cs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ static int m68k_analyze_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8
187187
cs_m68k *m68k;
188188
cs_detail *detail;
189189

190-
int mode = a->big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN;
190+
cs_mode mode = 0;
191191

192192
// mode |= (a->bits==64)? CS_MODE_64: CS_MODE_32;
193193
if (mode != ctx->omode || a->bits != ctx->obits) {

librz/arch/p/analysis/analysis_riscv_cs.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,20 @@
3737

3838
#define SET_SRC_DST_3_REGS(op) \
3939
CREATE_SRC_DST_3(op); \
40-
(op)->dst->reg = rz_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \
41-
(op)->src[0]->reg = rz_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR); \
42-
(op)->src[1]->reg = rz_reg_get(analysis->reg, REG(2), RZ_REG_TYPE_GPR);
40+
(op)->dst->reg = riscv_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \
41+
(op)->src[0]->reg = riscv_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR); \
42+
(op)->src[1]->reg = riscv_reg_get(analysis->reg, REG(2), RZ_REG_TYPE_GPR);
4343

4444
#define SET_SRC_DST_3_IMM(op) \
4545
CREATE_SRC_DST_3(op); \
46-
(op)->dst->reg = rz_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \
47-
(op)->src[0]->reg = rz_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR); \
46+
(op)->dst->reg = riscv_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \
47+
(op)->src[0]->reg = riscv_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR); \
4848
(op)->src[1]->imm = IMM(2);
4949

5050
#define SET_SRC_DST_2_REGS(op) \
5151
CREATE_SRC_DST_2(op); \
52-
(op)->dst->reg = rz_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \
53-
(op)->src[0]->reg = rz_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR);
52+
(op)->dst->reg = riscv_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \
53+
(op)->src[0]->reg = riscv_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR);
5454

5555
#define SET_SRC_DST_3_REG_OR_IMM(op) \
5656
if (OPERAND(2).type == RISCV_OP_IMM) { \
@@ -61,6 +61,14 @@
6161

6262
static void set_stack_effect(RzAnalysisOp *op, cs_insn *insn);
6363

64+
static RzRegItem *riscv_reg_get(const RzReg *reg, const char *name, int type) {
65+
if (!reg || RZ_STR_ISEMPTY(name)) {
66+
RZ_LOG_DEBUG("riscv: reg (%p) or name (%p) is null (type %d)\n", reg, name, type);
67+
return NULL;
68+
}
69+
return rz_reg_get(reg, name, type);
70+
}
71+
6472
static RzStructuredData *riscv_opex(csh handle, cs_insn *insn) {
6573
if (!insn->detail) {
6674
return NULL;
@@ -150,7 +158,7 @@ static void op_fillval(RzAnalysis *analysis, RzAnalysisOp *op, csh *handle, cs_i
150158
ZERO_FILL(ctx->reg);
151159
op->dst = rz_analysis_value_new();
152160
op->dst->type = RZ_ANALYSIS_VAL_REG;
153-
op->dst->reg = rz_reg_get(analysis->reg, cs_reg_name(*handle, FIRST_WRITTEN_REGID(insn)), RZ_REG_TYPE_GPR);
161+
op->dst->reg = riscv_reg_get(analysis->reg, cs_reg_name(*handle, FIRST_WRITTEN_REGID(insn)), RZ_REG_TYPE_GPR);
154162
op->src[0] = rz_analysis_value_new();
155163
op->src[0]->type = RZ_ANALYSIS_VAL_MEM;
156164
op->src[0]->reg = &ctx->reg;
@@ -170,7 +178,7 @@ static void op_fillval(RzAnalysis *analysis, RzAnalysisOp *op, csh *handle, cs_i
170178
op->dst->memref = op->refptr;
171179
op->src[0] = rz_analysis_value_new();
172180
op->src[0]->type = RZ_ANALYSIS_VAL_REG;
173-
op->src[0]->reg = rz_reg_get(analysis->reg, cs_reg_name(*handle, FIRST_READ_REGID(insn)), RZ_REG_TYPE_GPR);
181+
op->src[0]->reg = riscv_reg_get(analysis->reg, cs_reg_name(*handle, FIRST_READ_REGID(insn)), RZ_REG_TYPE_GPR);
174182
}
175183
break;
176184
case RZ_ANALYSIS_OP_TYPE_SHL:
Lines changed: 44 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,110 @@
11
// SPDX-FileCopyrightText: 2024-2026 moste00 <ubermenchun@gmail.com>
22
// SPDX-License-Identifier: BSD-3-Clause
33

4-
#include <rz_analysis.h>
4+
#ifndef ANALYSIS_RISCV_UTILS_H
5+
#define ANALYSIS_RISCV_UTILS_H
56

6-
#include "cs_operand.h"
7-
#include "rz_util/rz_log.h"
7+
#include <rz_analysis.h>
88

99
#include <capstone/capstone.h>
1010
#include <capstone/riscv.h>
1111
#include <stdint.h>
1212

13-
// A more high-level alternative to direct indexing that can get immediates and operands without exact
14-
// indices
15-
// While also enforcing high-level constraints such as "exactly one immediate operand is present"
16-
// or "at most one operand is present" or "get the single register that is read/written"
13+
// A more high-level alternative to direct indexing that can get immediates and operands without exact indices
14+
// While also enforcing high-level constraints such as "exactly one immediate operand is present" or "at most
15+
// one operand is present" or "get the single register that is read/written"
1716

18-
static inline int find_at_most_one_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type, const char *type_str) {
19-
int first = -1;
20-
for (int i = 0; i < op_count; i++) {
17+
static inline ut32 find_at_most_one_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type, const char *type_str) {
18+
ut32 first = UT32_MAX;
19+
for (ut32 i = 0; i < op_count; i++) {
2120
if (operands[i].type == type) {
22-
if (first == -1) {
21+
if (first == UT32_MAX) {
2322
first = i;
2423
} else {
25-
RZ_LOG_FATAL("Expected exactly one %s operand, two elements matched (the %ith and %ith elements)", type_str, first, i);
26-
exit(-1);
24+
RZ_LOG_DEBUG("Expected exactly one %s operand, two elements matched (the %ith and %ith elements)", type_str, first, i);
2725
}
2826
}
2927
}
3028
return first;
3129
}
3230

33-
static inline int find_at_most_one_imm(cs_riscv_op *operands, uint8_t op_count) {
31+
static inline ut32 find_at_most_one_imm(cs_riscv_op *operands, uint8_t op_count) {
3432
return find_at_most_one_op(operands, op_count, RISCV_OP_IMM, "immediate");
3533
}
3634

37-
static inline int find_exactly_one_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type, const char *type_str) {
38-
int first = find_at_most_one_op(operands, op_count, type, type_str);
39-
if (first == -1) {
40-
RZ_LOG_FATAL("Expected exactly one %s operand, found none", type_str);
41-
exit(-1);
42-
}
43-
return first;
35+
static inline ut32 find_exactly_one_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type, const char *type_str) {
36+
return find_at_most_one_op(operands, op_count, type, type_str);
4437
}
4538

46-
static inline int find_exactly_one_imm(cs_riscv_op *operands, uint8_t op_count) {
39+
static inline ut32 find_exactly_one_imm(cs_riscv_op *operands, uint8_t op_count) {
4740
return find_exactly_one_op(operands, op_count, RISCV_OP_IMM, "immediate");
4841
}
4942

5043
static inline int64_t get_exactly_one_immediate(cs_riscv_op *operands, uint8_t op_count) {
51-
return operands[find_exactly_one_imm(operands, op_count)].imm;
44+
ut32 idx = find_exactly_one_imm(operands, op_count);
45+
if (idx < op_count) {
46+
return operands[idx].imm;
47+
}
48+
return INT64_MAX;
5249
}
5350

5451
static inline int64_t get_at_most_one_immediate(cs_riscv_op *operands, uint8_t op_count) {
55-
int64_t idx = find_at_most_one_imm(operands, op_count);
56-
if (idx == -1) {
57-
return INT64_MAX;
52+
ut32 idx = find_at_most_one_imm(operands, op_count);
53+
if (idx < op_count) {
54+
return operands[idx].imm;
5855
}
59-
return operands[idx].imm;
56+
return INT64_MAX;
6057
}
6158

6259
#define SINGLE_IMM(insn) get_exactly_one_immediate(insn->detail->riscv.operands, insn->detail->riscv.op_count);
6360
#define MAYBE_IMM(insn) get_at_most_one_immediate(insn->detail->riscv.operands, insn->detail->riscv.op_count);
6461

65-
static inline int find_first_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type) {
66-
for (int i = 0; i < op_count; i++) {
62+
static inline ut32 find_first_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type) {
63+
for (ut32 i = 0; i < op_count; i++) {
6764
if (operands[i].type == type) {
6865
return i;
6966
}
7067
}
71-
return -1;
68+
return UT32_MAX;
7269
}
7370

74-
static inline int find_first_imm(cs_riscv_op *operands, uint8_t op_count) {
71+
static inline ut32 find_first_imm(cs_riscv_op *operands, uint8_t op_count) {
7572
return find_first_op(operands, op_count, RISCV_OP_IMM);
7673
}
7774

7875
static inline int64_t get_first_immediate(cs_riscv_op *operands, uint8_t op_count) {
79-
int idx = find_first_imm(operands, op_count);
80-
if (idx == -1) {
81-
return INT64_MAX;
76+
ut32 idx = find_first_imm(operands, op_count);
77+
if (idx < op_count) {
78+
return operands[idx].imm;
8279
}
83-
return operands[idx].imm;
80+
return INT64_MAX;
8481
}
8582

8683
#define FIRST_IMM(insn) get_first_immediate(insn->detail->riscv.operands, insn->detail->riscv.op_count);
8784

88-
static inline unsigned int get_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_count, cs_ac_type access) {
89-
for (int i = 0; i < op_count; i++) {
85+
static inline ut32 get_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_count, cs_ac_type access) {
86+
for (ut32 i = 0; i < op_count; i++) {
9087
if (operands[i].type == RISCV_OP_REG && (operands[i].access & access)) {
9188
return operands[i].reg;
9289
}
9390
}
94-
RZ_LOG_FATAL("Expected at least one register with %s access, found none", access == CS_AC_READ ? "read" : "write");
95-
exit(-1);
91+
RZ_LOG_DEBUG("Expected at least one register with %s access, found none", access == CS_AC_READ ? "read" : "write");
9692
return 0; // dummy for type checking, never reached
9793
}
9894

99-
static inline unsigned int first_read_register(cs_riscv_op *operands, uint8_t op_count) {
95+
static inline ut32 first_read_register(cs_riscv_op *operands, uint8_t op_count) {
10096
return get_any_reg_accessed_as(operands, op_count, CS_AC_READ);
10197
}
10298

103-
static inline unsigned int first_written_register(cs_riscv_op *operands, uint8_t op_count) {
99+
static inline ut32 first_written_register(cs_riscv_op *operands, uint8_t op_count) {
104100
return get_any_reg_accessed_as(operands, op_count, CS_AC_WRITE);
105101
}
106102

107103
#define FIRST_READ_REGID(insn) first_read_register(insn->detail->riscv.operands, insn->detail->riscv.op_count)
108104
#define FIRST_WRITTEN_REGID(insn) first_written_register(insn->detail->riscv.operands, insn->detail->riscv.op_count)
109105

110106
// check if a certain reg is ever accessed as read/write register
111-
static inline bool is_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_count, unsigned int reg, cs_ac_type access) {
107+
static inline bool is_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_count, ut32 reg, cs_ac_type access) {
112108
for (int i = 0; i < op_count; i++) {
113109
if (operands[i].type == RISCV_OP_REG && operands[i].reg == reg && (operands[i].access & access)) {
114110
return true;
@@ -117,23 +113,25 @@ static inline bool is_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_coun
117113
return false;
118114
}
119115

120-
static inline bool is_reg_written(cs_riscv_op *operands, uint8_t op_count, unsigned int reg) {
116+
static inline bool is_reg_written(cs_riscv_op *operands, uint8_t op_count, ut32 reg) {
121117
return is_any_reg_accessed_as(operands, op_count, reg, CS_AC_WRITE);
122118
}
123-
static inline bool is_reg_read(cs_riscv_op *operands, uint8_t op_count, unsigned int reg) {
119+
static inline bool is_reg_read(cs_riscv_op *operands, uint8_t op_count, ut32 reg) {
124120
return is_any_reg_accessed_as(operands, op_count, reg, CS_AC_READ);
125121
}
126122

127123
#define IS_REG_WRITTEN(insn, reg) is_reg_written(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg)
128124
#define IS_REG_READ(insn, reg) is_reg_read(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg)
129125

130126
static inline bool is_any_reg_memory_base(cs_riscv_op *operands, uint8_t op_count, unsigned int reg) {
131-
for (int i = 0; i < op_count; i++) {
127+
for (ut32 i = 0; i < op_count; i++) {
132128
if (operands[i].type == RISCV_OP_MEM && operands[i].mem.base == reg) {
133129
return true;
134130
}
135131
}
136132
return false;
137133
}
138134

139-
#define MEM_BASE(insn, reg) is_any_reg_memory_base(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg)
135+
#define MEM_BASE(insn, reg) is_any_reg_memory_base(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg)
136+
137+
#endif /* ANALYSIS_RISCV_UTILS_H */

librz/arch/p/arch_riscv_cs.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ cs_mode cs_mode_from_feature_flag(ut64 feature_flag) {
5454
size_t expect_str(const char *arch_str, const char *expected, size_t curr) {
5555
size_t l = strlen(expected);
5656
if (strncmp(&arch_str[curr], expected, l) != 0) {
57-
RZ_LOG_ERROR("Invalid architecture string: expected %s to equal %s",
57+
RZ_LOG_ERROR("Invalid architecture string: expected %s to equal %s\n",
5858
arch_str, expected);
5959
return curr;
6060
}
@@ -205,7 +205,7 @@ bool expect_extension(const char *arch_str, size_t *curr, cs_mode *cs_mode) {
205205
}
206206

207207
// unreachable
208-
RZ_LOG_ERROR("UNREACHABLE STATE WHEN PARSING RISCV ARCH STRING");
208+
rz_warn_if_reached();
209209
return true; // done, this is a bad state and we should terminate parsing immediately
210210
}
211211

@@ -233,8 +233,8 @@ bool check_all_whitespace(const char *str) {
233233
return true;
234234
}
235235
size_t mode_from_arch_string(const char *arch_str) {
236-
if (!arch_str || check_all_whitespace(arch_str)) {
237-
RZ_LOG_WARN("RISCV: empty architecture string, no non-default extensions enabled\n");
236+
if (!arch_str || check_all_whitespace(arch_str) || RZ_STR_EQ(arch_str, "riscv")) {
237+
RZ_LOG_INFO("RISCV: empty architecture string, no non-default extensions enabled\n");
238238
return 0;
239239
}
240240
size_t curr = expect_architecture_string_header(arch_str);

librz/arch/p/asm/asm_m68k_cs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ static int m68k_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) {
2020
char *buf_asm = NULL;
2121
cs_insn *insn = NULL;
2222
int ret = 0, n = 0;
23-
cs_mode mode = a->big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN;
23+
cs_mode mode = 0;
2424

2525
// replace this with the asm.features?
2626
if (a->cpu && strstr(a->cpu, "68000")) {

0 commit comments

Comments
 (0)