Skip to content

Commit 17e19ac

Browse files
authored
Log an error when endianness change is not compatible with arch (#5945)
1 parent 42dbdd7 commit 17e19ac

File tree

35 files changed

+245
-291
lines changed

35 files changed

+245
-291
lines changed

librz/arch/asm.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,17 @@ RZ_API ut32 rz_asm_get_endianness(RzAsm *a) {
560560
return a->cur->endian;
561561
}
562562

563+
RZ_API bool rz_asm_support_endianness(RzAsm *a, ut32 endian) {
564+
rz_return_val_if_fail(a && a->cur, false);
565+
566+
if (a->cur->endian == RZ_SYS_ENDIAN_NONE || a->cur->endian == RZ_SYS_ENDIAN_BI) {
567+
// always return what the bin or default endianness of the system
568+
return true;
569+
}
570+
571+
return endian & a->cur->endian;
572+
}
573+
563574
RZ_API bool rz_asm_set_big_endian(RzAsm *a, bool b) {
564575
rz_return_val_if_fail(a && a->cur, false);
565576
a->big_endian = false; // little endian by default

librz/bin/bfile_string.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,8 @@ RZ_API RZ_OWN RzPVector /*<RzBinString *>*/ *rz_bin_file_strings(RZ_NONNULL RzBi
643643

644644
if (bf->o) {
645645
const RzBinInfo *binfo = rz_bin_object_get_info(bf->o);
646-
prefer_big_endian = binfo ? binfo->big_endian : false;
646+
// follow what RzBinInfo says only if the arch is set.
647+
prefer_big_endian = binfo && binfo->arch ? binfo->big_endian : false;
647648
}
648649

649650
SharedData shared = {

librz/bin/p/bin_any.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
#include <rz_bin.h>
99
#include <rz_magic.h>
1010

11+
#if RZ_SYS_ENDIAN == RZ_SYS_ENDIAN_LITTLE
12+
#define ANY_DEFAULT_ENDIANNESS false
13+
#else
14+
#define ANY_DEFAULT_ENDIANNESS true
15+
#endif
16+
1117
static char *get_filetype(RzBuffer *b) {
1218
ut8 buf[4096] = { 0 };
1319
char *res = NULL;
@@ -49,13 +55,8 @@ static RzBinInfo *info(RzBinFile *bf) {
4955
ret->lang = "";
5056
ret->file = rz_str_dup(bf->file);
5157
ret->type = get_filetype(bf->buf);
52-
ret->has_pi = 0;
53-
ret->has_canary = 0;
5458
ret->has_retguard = -1;
55-
ret->big_endian = 0;
56-
ret->has_va = 0;
57-
ret->has_nx = 0;
58-
ret->dbg_info = 0;
59+
ret->big_endian = ANY_DEFAULT_ENDIANNESS;
5960
return ret;
6061
}
6162

librz/core/carch.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,7 @@ static bool core_arch_default_is_big_endian(RzCore *core) {
228228
return false;
229229
}
230230

231-
RZ_DEPRECATE static void core_update_endianness(RzCore *core) {
232-
bool big_endian = core_arch_default_is_big_endian(core);
233-
231+
RZ_DEPRECATE static void core_set_endianness(RzCore *core, bool big_endian) {
234232
rz_asm_set_big_endian(core->rasm, big_endian);
235233
rz_analysis_set_big_endian(core->analysis, big_endian);
236234

@@ -247,6 +245,11 @@ RZ_DEPRECATE static void core_update_endianness(RzCore *core) {
247245
}
248246
}
249247

248+
RZ_DEPRECATE static void core_update_endianness(RzCore *core) {
249+
bool big_endian = core_arch_default_is_big_endian(core);
250+
core_set_endianness(core, big_endian);
251+
}
252+
250253
// most of this code is a copy from cconfig
251254
RZ_DEPRECATE static void core_update_syscall_db(RzCore *core) {
252255
if (core->analysis->syscall->db) {
@@ -555,4 +558,30 @@ RZ_DEPRECATE RZ_API bool rz_core_arch_configure(RZ_NONNULL RzCore *core, RZ_NULL
555558

556559
core_update_config_from_arch(core, is_new_arch);
557560
return true;
558-
}
561+
}
562+
563+
/**
564+
* \brief Sets the endianness a given RzCore
565+
*
566+
* \param core The core
567+
* \param[in] big_endian When true, tries to set the endianness to big endian, otherwise little endian
568+
*
569+
* \return On success returns true, otherwise false
570+
*/
571+
RZ_DEPRECATE RZ_API bool rz_core_set_endianness(RZ_NONNULL RzCore *core, bool big_endian) {
572+
rz_return_val_if_fail(core && core->config && core->bin && core->rasm && core->analysis && core->parser && core->dbg && core->egg, false);
573+
574+
ut32 endianness = big_endian ? RZ_SYS_ENDIAN_BIG : RZ_SYS_ENDIAN_LITTLE;
575+
576+
if (!rz_asm_support_endianness(core->rasm, endianness)) {
577+
const char *arch = rz_core_get_arch(core);
578+
const char *want = big_endian ? "big" : "little";
579+
const char *supported = (!big_endian) ? "big" : "little";
580+
RZ_LOG_ERROR("core: cannot change to %s endian (arch '%s' supports only %s endian)\n", want, arch, supported);
581+
return false;
582+
}
583+
584+
core_set_endianness(core, big_endian);
585+
core_update_config_b(core, "cfg.bigendian", core->rasm->big_endian);
586+
return true;
587+
}

librz/core/cbin.c

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,6 @@ static void sdb_concat_by_path(Sdb *s, const char *path) {
547547

548548
RZ_API bool rz_core_bin_apply_config(RzCore *r, RzBinFile *binfile) {
549549
rz_return_val_if_fail(r && binfile, false);
550-
int v;
551-
char str[RZ_FLAG_NAME_SIZE];
552550
RzBinObject *obj = binfile->o;
553551
if (!obj) {
554552
return false;
@@ -558,38 +556,44 @@ RZ_API bool rz_core_bin_apply_config(RzCore *r, RzBinFile *binfile) {
558556
return false;
559557
}
560558
rz_config_set(r->config, "file.type", rz_str_get(info->rclass));
561-
rz_config_set(r->config, "cfg.bigendian",
562-
info->big_endian ? "true" : "false");
563-
if (info->lang) {
564-
rz_config_set(r->config, "bin.lang", info->lang);
565-
}
566-
rz_config_set(r->config, "asm.os", info->os);
559+
rz_config_set(r->config, "bin.lang", rz_str_get(info->lang));
567560
if (info->rclass && !strcmp(info->rclass, "pe")) {
568561
rz_config_set(r->config, "analysis.cpp.abi", "msvc");
569562
} else {
570563
rz_config_set(r->config, "analysis.cpp.abi", "itanium");
571564
}
572-
rz_config_set(r->config, "asm.arch", info->arch);
565+
if (RZ_STR_ISNOTEMPTY(info->os)) {
566+
rz_config_set(r->config, "asm.os", info->os);
567+
}
568+
if (RZ_STR_ISNOTEMPTY(info->arch)) {
569+
// update the arch & bits only if really set.
570+
rz_config_set(r->config, "asm.arch", info->arch);
571+
rz_config_set_i(r->config, "asm.bits", info->bits);
572+
}
573573
if (RZ_STR_ISNOTEMPTY(info->cpu)) {
574+
// update the CPU only if really set.
574575
rz_config_set(r->config, "asm.cpu", info->cpu);
575576
}
576577
if (RZ_STR_ISNOTEMPTY(info->features)) {
578+
// update the CPU features only if really set.
577579
rz_config_set(r->config, "asm.features", info->features);
578580
}
579-
rz_config_set(r->config, "analysis.arch", info->arch);
580-
snprintf(str, RZ_FLAG_NAME_SIZE, "%i", info->bits);
581-
rz_config_set(r->config, "asm.bits", str);
582-
rz_config_set(r->config, "asm.debuginfo",
583-
(RZ_BIN_DBG_STRIPPED & info->dbg_info) ? "false" : "true");
584-
v = rz_analysis_archinfo(r->analysis, RZ_ANALYSIS_ARCHINFO_TEXT_ALIGN);
585-
if (v != -1) {
586-
rz_config_set_i(r->config, "asm.pcalign", v);
581+
if (RZ_STR_ISNOTEMPTY(info->arch)) {
582+
// update the endianness only if the arch value is set.
583+
ut32 endianness = info->big_endian ? RZ_SYS_ENDIAN_BIG : RZ_SYS_ENDIAN_LITTLE;
584+
if (rz_asm_support_endianness(r->rasm, endianness)) {
585+
// change only if the current arch supports it.
586+
rz_config_set_b(r->config, "cfg.bigendian", info->big_endian);
587+
}
587588
}
589+
rz_config_set_b(r->config, "asm.debuginfo", (RZ_BIN_DBG_STRIPPED & info->dbg_info) ? false : true);
590+
588591
rz_core_analysis_type_init(r);
589592
rz_core_analysis_cc_init(r);
590593
if (info->default_cc && rz_analysis_cc_exist(r->analysis, info->default_cc)) {
591594
rz_config_set(r->config, "analysis.cc", info->default_cc);
592595
}
596+
593597
char *types_dir = rz_path_system(r->sys_path, RZ_SDB_TYPES);
594598
if (!types_dir) {
595599
return false;

librz/core/cconfig.c

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313

1414
#include "core_private.h"
1515

16+
#if RZ_SYS_ENDIAN == RZ_SYS_ENDIAN_LITTLE
17+
#define CFG_DEFAULT_ENDIANNESS "false"
18+
#else
19+
#define CFG_DEFAULT_ENDIANNESS "true"
20+
#endif
21+
1622
typedef struct config_opt_descr {
1723
const char *option;
1824
const char *description;
@@ -790,21 +796,7 @@ static bool cb_asmsyntax(void *user, void *data) {
790796
static bool cb_bigendian(void *user, void *data) {
791797
RzCore *core = (RzCore *)user;
792798
RzConfigNode *node = (RzConfigNode *)data;
793-
// Try to set endian based on preference, restrict by RzAsmPlugin
794-
bool isbig = rz_asm_set_big_endian(core->rasm, node->i_value);
795-
// Set analysis endianness the same as asm
796-
rz_analysis_set_big_endian(core->analysis, isbig);
797-
// While analysis sets endianess for TypesDB there might
798-
// be cases when it isn't availble for the chosen analysis
799-
// plugin but types and printing commands still need the
800-
// corresponding endianness. Thus we set these explicitly:
801-
rz_type_db_set_endian(core->analysis->typedb, node->i_value);
802-
core->print->big_endian = node->i_value;
803-
// the big endian should also be assigned to dbg->bp->endian
804-
if (core->dbg && core->dbg->bp) {
805-
core->dbg->bp->endian = isbig;
806-
}
807-
return true;
799+
return rz_core_set_endianness(core, node->i_value);
808800
}
809801

810802
static bool cb_cfgdatefmt(void *user, void *data) {
@@ -3197,7 +3189,7 @@ RZ_API int rz_core_config_init(RzCore *core) {
31973189
SETBPREF("cfg.wseek", "false", "Seek after write");
31983190
SETICB("cfg.seek.histsize", 63, NULL, "Maximum size of the seek history");
31993191
SETCB("cfg.seek.silent", "false", NULL, "When true, seek movements are not logged in seek history");
3200-
SETCB("cfg.bigendian", "false", &cb_bigendian, "Use little (false) or big (true) endianness");
3192+
SETCB("cfg.bigendian", CFG_DEFAULT_ENDIANNESS, &cb_bigendian, "Use little (false) or big (true) endianness");
32013193
SETI("cfg.cpuaffinity", 0, "Run on cpuid");
32023194

32033195
/* log */

librz/include/rz_asm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ RZ_API bool rz_asm_set_arch(RzAsm *a, const char *name, int bits);
178178
RZ_DEPRECATE RZ_API int rz_asm_set_bits(RzAsm *a, int bits);
179179
RZ_DEPRECATE RZ_API void rz_asm_set_cpu(RzAsm *a, const char *cpu);
180180
RZ_API ut32 rz_asm_get_endianness(RzAsm *a);
181+
RZ_API bool rz_asm_support_endianness(RzAsm *a, ut32 endian);
181182
RZ_API bool rz_asm_set_big_endian(RzAsm *a, bool big_endian);
182183
RZ_API bool rz_asm_set_syntax(RzAsm *a, int syntax);
183184
RZ_API int rz_asm_syntax_from_string(const char *name);

librz/include/rz_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ typedef enum {
785785
RZ_CORE_ANALYSIS_EXPERIMENTAL, ///< aaaa
786786
} RzCoreAnalysisType;
787787

788+
RZ_DEPRECATE RZ_API bool rz_core_set_endianness(RZ_NONNULL RzCore *core, bool big_endian);
788789
RZ_DEPRECATE RZ_API bool rz_core_arch_configure(RZ_NONNULL RzCore *core, RZ_NULLABLE const char *arch, int bits, RZ_NULLABLE const char *cpu, RZ_NULLABLE const char *os, RZ_NULLABLE const char *platform);
789790

790791
RZ_API RzAnalysisOp *rz_core_analysis_op(RzCore *core, ut64 addr, int mask);

librz/main/rizin.c

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ static int main_help(RZ_BORROW RZ_NONNULL RzCore *core, int line) {
110110
"-d", "", "Debug the executable 'file' or running process 'pid'",
111111
"-D", "backend", "Enable debug mode (e cfg.debug=true)",
112112
"-e", "k=v", "Evaluate config var",
113+
"-E", "endian", "Endianness -E big or -E little",
113114
"-f", "", "Block size = file size",
114115
"-F", "binplug", "Force to use that rbin plugin",
115116
"-h, -hh", "", "Show help message, -hh for long",
@@ -434,6 +435,7 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
434435
ut64 mapaddr = 0LL;
435436
bool quiet = false;
436437
int is_gdb = false;
438+
ut32 endianness = RZ_SYS_ENDIAN_NONE;
437439
const char *s_seek = NULL;
438440
bool compute_hashes = true;
439441
RzList *cmds = rz_list_new();
@@ -502,7 +504,7 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
502504
char *debugbackend = rz_str_dup("native");
503505

504506
RzGetopt opt;
505-
rz_getopt_init(&opt, argc, argv, "=012AMCwxfF:H:hm:e:nk:NdqQs:p:b:B:a:Lui:I:l:R:r:c:D:vVSTzuXt");
507+
rz_getopt_init(&opt, argc, argv, "=012AMCwxfF:H:hm:E:e:nk:NdqQs:p:b:B:a:Lui:I:l:R:r:c:D:vVSTzuXt");
506508
while (argc >= 2 && (c = rz_getopt_next(&opt)) != -1) {
507509
switch (c) {
508510
case '-':
@@ -581,11 +583,38 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
581583
case 'e':
582584
if (!strcmp(opt.arg, "q")) {
583585
rz_core_cmd0(r, "eq");
586+
} else if (rz_str_startswith(opt.arg, "asm.arch")) {
587+
RZ_LOG_ERROR("use -a argument for setting the arch name\n");
588+
ret = 1;
589+
goto beach;
590+
} else if (rz_str_startswith(opt.arg, "asm.bits")) {
591+
RZ_LOG_ERROR("use -b argument for setting the arch bits\n");
592+
ret = 1;
593+
goto beach;
594+
} else if (rz_str_startswith(opt.arg, "asm.os")) {
595+
RZ_LOG_ERROR("use -k argument for setting the OS/kern\n");
596+
ret = 1;
597+
goto beach;
598+
} else if (rz_str_startswith(opt.arg, "cfg.bigendian")) {
599+
RZ_LOG_ERROR("use -E argument for setting the endianness\n");
600+
ret = 1;
601+
goto beach;
584602
} else {
585-
rz_config_eval(r->config, opt.arg);
603+
rz_config_eval(r->config, (void *)opt.arg);
586604
rz_list_append(evals, (void *)opt.arg);
587605
}
588606
break;
607+
case 'E':
608+
if (RZ_STR_EQ(opt.arg, "big")) {
609+
endianness = RZ_SYS_ENDIAN_BIG;
610+
} else if (RZ_STR_EQ(opt.arg, "little")) {
611+
endianness = RZ_SYS_ENDIAN_LITTLE;
612+
} else {
613+
RZ_LOG_ERROR("Invalid endianness value '%s'\n", opt.arg);
614+
ret = 1;
615+
goto beach;
616+
}
617+
break;
589618
case 'f':
590619
fullfile = true;
591620
break;
@@ -956,6 +985,9 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
956985
if (asmos) {
957986
rz_config_set(r->config, "asm.os", asmos);
958987
}
988+
if (endianness != RZ_SYS_ENDIAN_NONE) {
989+
rz_config_set_b(r->config, "cfg.bigendian", endianness == RZ_SYS_ENDIAN_BIG);
990+
}
959991
// TODO: load rbin thing
960992
} else {
961993
RZ_LOG_ERROR("Cannot slurp from stdin\n");
@@ -1089,7 +1121,9 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
10891121
if (asmos) {
10901122
rz_config_set(r->config, "asm.os", asmos);
10911123
}
1092-
1124+
if (endianness != RZ_SYS_ENDIAN_NONE) {
1125+
rz_config_set_b(r->config, "cfg.bigendian", endianness == RZ_SYS_ENDIAN_BIG);
1126+
}
10931127
if (!debug || debug == 2) {
10941128
const char *dbg_profile = rz_config_get(r->config, "dbg.profile");
10951129
if (opt.ind == argc && dbg_profile && *dbg_profile) {
@@ -1249,10 +1283,6 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
12491283
if (mapaddr) {
12501284
rz_core_seek(r, mapaddr, true);
12511285
}
1252-
rz_list_foreach (evals, iter, cmdn) {
1253-
rz_config_eval(r->config, cmdn);
1254-
rz_cons_flush();
1255-
}
12561286
if (asmarch) {
12571287
rz_config_set(r->config, "asm.arch", asmarch);
12581288
}
@@ -1262,7 +1292,13 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
12621292
if (asmos) {
12631293
rz_config_set(r->config, "asm.os", asmos);
12641294
}
1265-
1295+
if (endianness != RZ_SYS_ENDIAN_NONE) {
1296+
rz_config_set_b(r->config, "cfg.bigendian", endianness == RZ_SYS_ENDIAN_BIG);
1297+
}
1298+
rz_list_foreach (evals, iter, cmdn) {
1299+
rz_config_eval(r->config, cmdn);
1300+
rz_cons_flush();
1301+
}
12661302
debug = r->file && iod && (r->file->fd == iod->fd) && iod->plugin &&
12671303
(iod->plugin->isdbg || (debug == 2 && !strcmp(iod->plugin->name, "dmp")));
12681304
if (debug) {
@@ -1336,10 +1372,6 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
13361372
} else {
13371373
rz_core_block_read(r);
13381374

1339-
rz_list_foreach (evals, iter, cmdn) {
1340-
rz_config_eval(r->config, cmdn);
1341-
rz_cons_flush();
1342-
}
13431375
if (asmarch) {
13441376
rz_config_set(r->config, "asm.arch", asmarch);
13451377
}
@@ -1349,6 +1381,13 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
13491381
if (asmos) {
13501382
rz_config_set(r->config, "asm.os", asmos);
13511383
}
1384+
if (endianness != RZ_SYS_ENDIAN_NONE) {
1385+
rz_config_set_b(r->config, "cfg.bigendian", endianness == RZ_SYS_ENDIAN_BIG);
1386+
}
1387+
rz_list_foreach (evals, iter, cmdn) {
1388+
rz_config_eval(r->config, cmdn);
1389+
rz_cons_flush();
1390+
}
13521391
}
13531392
{
13541393
char *global_rc = rz_path_system_rc(r->sys_path);

0 commit comments

Comments
 (0)