Fix SPARC/MC680x0 Mach-O fat binary issues (#5338)

* Add thread_state register layouts for Mac-O Sparc and MC680x0 binaries.

* Prevent hitting assert by passing NULL in some cases.

If name is not a valid arch identifier, it should complain later.

* Switch to m68k name, to match the asm.arch plugin name.

* Don't ignore endianess of fat Mach-O binaries.

And if it isn't ignored check for actual endianess,
not for being a PPC binary.

* Add `obs` command to select the different versions of fat binaries.
* Fix import tests of mach-o
* Properly rest xtr_data->loaded
* Update doxygen and remove RZ_DEPRECATED flag
This commit is contained in:
Rot127 2025-09-09 03:51:17 +00:00 committed by GitHub
parent eefb34bcd5
commit cb3e09aa4e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 738 additions and 241 deletions

View file

@ -728,52 +728,52 @@ static char *get_reg_profile(RzAnalysis *analysis) {
"=A1 a1\n"
"=A2 a2\n"
"=A3 a3\n"
"gpr d0 .32 0 0\n"
"gpr d1 .32 4 0\n"
"gpr d2 .32 8 0\n"
"gpr d3 .32 12 0\n"
"gpr d4 .32 16 0\n"
"gpr d5 .32 20 0\n"
"gpr d6 .32 24 0\n"
"gpr d7 .32 28 0\n"
"gpr a0 .32 32 0\n"
"gpr a1 .32 36 0\n"
"gpr a2 .32 40 0\n"
"gpr a3 .32 44 0\n"
"gpr a4 .32 48 0\n"
"gpr a5 .32 52 0\n"
"gpr a6 .32 56 0\n"
"gpr a7 .32 60 0\n"
"gpr fp0 .32 64 0\n" // FPU register 0, 96bits to write and read max
"gpr fp1 .32 68 0\n" // FPU register 1, 96bits to write and read max
"gpr fp2 .32 72 0\n" // FPU register 2, 96bits to write and read max
"gpr fp3 .32 76 0\n" // FPU register 3, 96bits to write and read max
"gpr fp4 .32 80 0\n" // FPU register 4, 96bits to write and read max
"gpr fp5 .32 84 0\n" // FPU register 5, 96bits to write and read max
"gpr fp6 .32 88 0\n" // FPU register 6, 96bits to write and read max
"gpr fp7 .32 92 0\n" // FPU register 7, 96bits to write and read max
"gpr pc .32 96 0\n"
"gpr sr .32 100 0\n" // only available for read and write access during supervisor mode 16bit
"gpr ccr .32 104 0\n" // subset of the SR, available from any mode
"gpr sfc .32 108 0\n" // source function code register
"gpr dfc .32 112 0\n" // destination function code register
"gpr usp .32 116 0\n" // user stack point this is an shadow register of A7 user mode, SR bit 0xD is 0
"gpr vbr .32 120 0\n" // vector base register, this is a Address pointer
"gpr cacr .32 124 0\n" // cache control register, implementation specific
"gpr caar .32 128 0\n" // cache address register, 68020, 68EC020, 68030 and 68EC030 only.
"gpr msp .32 132 0\n" // master stack pointer, this is an shadow register of A7 supervisor mode, SR bits 0xD && 0xC are set
"gpr isp .32 136 0\n" // interrupt stack pointer, this is an shadow register of A7 supervisor mode, SR bit 0xD is set, 0xC is not.
"gpr tc .32 140 0\n"
"gpr itt0 .32 144 0\n" // in 68EC040 this is IACR0
"gpr itt1 .32 148 0\n" // in 68EC040 this is IACR1
"gpr dtt0 .32 156 0\n" // in 68EC040 this is DACR0
"gpr dtt1 .32 160 0\n" // in 68EC040 this is DACR1
"gpr mmusr .32 164 0\n"
"gpr urp .32 168 0\n"
"gpr srp .32 172 0\n"
"gpr fpcr .32 176 0\n"
"gpr fpsr .32 180 0\n"
"gpr fpiar .32 184 0\n";
"gpr d0 .32 0 0\n"
"gpr d1 .32 4 0\n"
"gpr d2 .32 8 0\n"
"gpr d3 .32 12 0\n"
"gpr d4 .32 16 0\n"
"gpr d5 .32 20 0\n"
"gpr d6 .32 24 0\n"
"gpr d7 .32 28 0\n"
"gpr a0 .32 32 0\n"
"gpr a1 .32 36 0\n"
"gpr a2 .32 40 0\n"
"gpr a3 .32 44 0\n"
"gpr a4 .32 48 0\n"
"gpr a5 .32 52 0\n"
"gpr a6 .32 56 0\n"
"gpr a7 .32 60 0\n"
"gpr pc .32 64 0\n"
"gpr ccr .8 68 0\n" // subset of the SR, available from any mode
"gpr fp0 .32 69 0\n" // FPU register 0, 96bits to write and read max
"gpr fp1 .32 73 0\n" // FPU register 1, 96bits to write and read max
"gpr fp2 .32 77 0\n" // FPU register 2, 96bits to write and read max
"gpr fp3 .32 81 0\n" // FPU register 3, 96bits to write and read max
"gpr fp4 .32 85 0\n" // FPU register 4, 96bits to write and read max
"gpr fp5 .32 89 0\n" // FPU register 5, 96bits to write and read max
"gpr fp6 .32 93 0\n" // FPU register 6, 96bits to write and read max
"gpr fp7 .32 97 0\n" // FPU register 7, 96bits to write and read max
"gpr fpcr .32 101 0\n"
"gpr fpsr .32 105 0\n"
"gpr fpiar .32 109 0\n"
"gpr sr .32 113 0\n" // only available for read and write access during supervisor mode 16bit
"gpr sfc .32 117 0\n" // source function code register
"gpr dfc .32 121 0\n" // destination function code register
"gpr usp .32 125 0\n" // user stack point this is an shadow register of A7 user mode, SR bit 0xD is 0
"gpr vbr .32 129 0\n" // vector base register, this is a Address pointer
"gpr cacr .32 133 0\n" // cache control register, implementation specific
"gpr caar .32 137 0\n" // cache address register, 68020, 68EC020, 68030 and 68EC030 only.
"gpr msp .32 141 0\n" // master stack pointer, this is an shadow register of A7 supervisor mode, SR bits 0xD && 0xC are set
"gpr isp .32 145 0\n" // interrupt stack pointer, this is an shadow register of A7 supervisor mode, SR bit 0xD is set, 0xC is not.
"gpr tc .32 149 0\n"
"gpr itt0 .32 153 0\n" // in 68EC040 this is IACR0
"gpr itt1 .32 157 0\n" // in 68EC040 this is IACR1
"gpr dtt0 .32 161 0\n" // in 68EC040 this is DACR0
"gpr dtt1 .32 165 0\n" // in 68EC040 this is DACR1
"gpr mmusr .32 169 0\n"
"gpr urp .32 173 0\n"
"gpr srp .32 177 0\n";
return rz_str_dup(p);
}

View file

@ -80,8 +80,48 @@ static RzBinPlugin *get_plugin_from_buffer(RzBin *bin, const char *pluginname, R
return rz_bin_get_binplugin_by_name(bin, "any");
}
RZ_API bool rz_bin_file_object_new_from_xtr_data(RzBin *bin, RzBinFile *bf, RzBinObjectLoadOptions *opts, RzBinXtrData *data) {
rz_return_val_if_fail(bin && bf && data, false);
static inline void mark_all_xtr_as_unloaded(RzBin *bin) {
RzListIter *iter;
RzBinFile *binfile = NULL;
rz_list_foreach (bin->binfiles, iter, binfile) {
if (!binfile->xtr_data) {
continue;
}
RzBinXtrData *xtr_data;
RzListIter *iter_xtr;
rz_list_foreach (binfile->xtr_data, iter_xtr, xtr_data) {
xtr_data->loaded = false;
}
}
}
/**
* \brief Updates the current active object of the binfile \p bf
* with the RzBinXtrData \p data.
* It creates a new RzBinObj instance according to \p data
* and loads it as current object.
*
* NOTE: It will mark all other RzBinXtrData insances in all RzBinFiles
* as unloaded. This is a required side effect of Rizin only supporting
* one active object at a time.
* NOTE: \p data must be an element from the bf->xtr_data list.
* Otherwise the result is undefined.
*
* \param bin The current RzBin isntance.
* \param bf The RzBinFile to update.
* \param opts Loading options for the new object.
* \param data The RzBinXtrData to load.
*
* \return True if the loading was successful. False otherwise.
*/
RZ_API bool rz_bin_file_set_xtr_data_as_current_obj(
RZ_BORROW RZ_NONNULL RzBin *bin,
RZ_BORROW RZ_NONNULL RzBinFile *bf,
RZ_BORROW RZ_NONNULL RzBinObjectLoadOptions *opts,
RZ_BORROW RZ_NONNULL RzBinXtrData *data) {
rz_return_val_if_fail(bin && bf && data && opts, false);
mark_all_xtr_as_unloaded(bin);
ut64 offset = data->offset;
ut64 sz = data->size;
@ -111,18 +151,19 @@ RZ_API bool rz_bin_file_object_new_from_xtr_data(RzBin *bin, RzBinFile *bf, RzBi
o->info->machine = rz_str_dup(data->metadata->machine);
o->info->type = rz_str_dup(data->metadata->type);
o->info->bits = data->metadata->bits;
o->info->big_endian = data->metadata->big_endian;
o->info->has_crypto = bf->o->info->has_crypto;
data->loaded = true;
return true;
}
static bool xtr_metadata_match(RzBinXtrData *xtr_data, const char *arch, int bits) {
static bool xtr_metadata_match(RzBinXtrData *xtr_data, const char *arch, int bits, RZ_NULLABLE const char *machine) {
if (!xtr_data->metadata || !xtr_data->metadata->arch) {
return false;
}
const char *iter_arch = xtr_data->metadata->arch;
int iter_bits = xtr_data->metadata->bits;
return bits == iter_bits && !strcmp(iter_arch, arch) && !xtr_data->loaded;
return bits == iter_bits && !strcmp(iter_arch, arch) && (!machine || RZ_STR_EQ(machine, xtr_data->metadata->machine)) && !xtr_data->loaded;
}
RZ_IPI RzBinFile *rz_bin_file_new_from_buffer(RzBin *bin, const char *file, RzBuffer *buf, RzBinObjectLoadOptions *opts, int fd, const char *pluginname) {
@ -149,7 +190,17 @@ RZ_IPI RzBinFile *rz_bin_file_new_from_buffer(RzBin *bin, const char *file, RzBu
return bf;
}
RZ_API RzBinFile *rz_bin_file_find_by_arch_bits(RzBin *bin, const char *arch, int bits) {
/**
* \brief Search the matching binary file for \p arch \p bits and \p machine (optional).
*
* \param bin The current RzBin instance.
* \param arch The architecture of the binary file.
* \param bits The architecture bits of the binary file.
* \param machine (Optional) The machine the binary file is for.
*
* \return The binary file or NULL if no matching exists.
*/
RZ_API RZ_BORROW RzBinFile *rz_bin_file_find_by_arch_bits(RzBin *bin, const char *arch, int bits, RZ_NULLABLE const char *machine, RZ_NULLABLE const char *filename) {
RzListIter *iter;
RzBinFile *binfile = NULL;
RzBinXtrData *xtr_data;
@ -163,8 +214,8 @@ RZ_API RzBinFile *rz_bin_file_find_by_arch_bits(RzBin *bin, const char *arch, in
}
// look for sub-bins in Xtr Data and Load if we need to
rz_list_foreach (binfile->xtr_data, iter_xtr, xtr_data) {
if (xtr_metadata_match(xtr_data, arch, bits)) {
if (!rz_bin_file_object_new_from_xtr_data(bin, binfile, &xtr_data->obj_opts, xtr_data)) {
if (xtr_metadata_match(xtr_data, arch, bits, machine)) {
if (!rz_bin_file_set_xtr_data_as_current_obj(bin, binfile, &xtr_data->obj_opts, xtr_data)) {
return NULL;
}
return binfile;

View file

@ -822,16 +822,27 @@ trashbin:
return NULL;
}
RZ_API bool rz_bin_use_arch(RzBin *bin, const char *arch, int bits, const char *name) {
/**
* \brief Sets the object file matching the \p arch, \p bits and optionally the \p machine and \p filename.
*
* \param bin The current RzBin instance.
* \param arch The architecture of the binary file.
* \param bits The architecture bits of the binary file.
* \param machine (Optional) The machine of the binary file.
* \param filename (Optional) The filename of the RzBinFile to load. Can be NULL.
*
* \return True if the binary file was successfully set according to the parameters. False otherwise.
*/
RZ_API bool rz_bin_use_arch(RzBin *bin, const char *arch, int bits, RZ_NULLABLE const char *machine, RZ_NULLABLE const char *filename) {
rz_return_val_if_fail(bin && arch, false);
RzBinFile *binfile = rz_bin_file_find_by_arch_bits(bin, arch, bits);
RzBinFile *binfile = rz_bin_file_find_by_arch_bits(bin, arch, bits, machine, filename);
if (!binfile) {
RZ_LOG_WARN("Cannot find binfile with arch/bits %s/%d\n", arch, bits);
return false;
}
RzBinObject *obj = rz_bin_object_find_by_arch_bits(binfile, arch, bits, name);
RzBinObject *obj = rz_bin_object_find_by_arch_bits(binfile, arch, bits, machine, filename);
if (!obj && binfile->xtr_data) {
RzBinXtrData *xtr_data = rz_list_get_n(binfile->xtr_data, 0);
if (xtr_data && !xtr_data->loaded) {
@ -839,7 +850,7 @@ RZ_API bool rz_bin_use_arch(RzBin *bin, const char *arch, int bits, const char *
.baseaddr = UT64_MAX,
.loadaddr = rz_bin_get_laddr(bin)
};
if (!rz_bin_file_object_new_from_xtr_data(bin, binfile, &obj_opts, xtr_data)) {
if (!rz_bin_file_set_xtr_data_as_current_obj(bin, binfile, &obj_opts, xtr_data)) {
return false;
}
}
@ -851,15 +862,25 @@ RZ_API bool rz_bin_use_arch(RzBin *bin, const char *arch, int bits, const char *
return rz_bin_set_cur_binfile(bin, binfile);
}
RZ_API bool rz_bin_select(RzBin *bin, const char *arch, int bits, const char *name) {
rz_return_val_if_fail(bin, false);
/**
* \brief Selects the binfile matching \p arch, \p bits and optionally \p machine
* and \p filename and sets it as current binfile in RzBin.
*
* \param bin The current RzBin instance.
* \param arch The architecture of the binary file.
* \param bits The architecture bits of the binary file.
* \param machine (Optional) The machine of the binary file.
* \param filename (Optional) The filename of RzBinFile to load.
*
* \return True if the binary file was successfully set according to the parameters. False otherwise.
*/
RZ_API bool rz_bin_select(RzBin *bin, RZ_NONNULL const char *arch, int bits, RZ_NULLABLE const char *machine, RZ_NULLABLE const char *filename) {
rz_return_val_if_fail(bin && arch, false);
RzBinFile *cur = rz_bin_cur(bin);
RzBinObject *obj = NULL;
name = !name && cur ? cur->file : name;
RzBinFile *binfile = rz_bin_file_find_by_arch_bits(bin, arch, bits);
if (binfile && name) {
obj = rz_bin_object_find_by_arch_bits(binfile, arch, bits, name);
RzBinFile *binfile = rz_bin_file_find_by_arch_bits(bin, arch, bits, machine, filename);
if (binfile) {
obj = rz_bin_object_find_by_arch_bits(binfile, arch, bits, machine, filename);
}
if (!rz_bin_file_set_obj(binfile, obj)) {
return NULL;

View file

@ -598,14 +598,15 @@ RZ_IPI RzBinObject *rz_bin_object_get_cur(RzBin *bin) {
return bin->cur->o;
}
RZ_IPI RzBinObject *rz_bin_object_find_by_arch_bits(RzBinFile *bf, const char *arch, int bits, const char *name) {
rz_return_val_if_fail(bf && arch && name, NULL);
RZ_IPI RzBinObject *rz_bin_object_find_by_arch_bits(RzBinFile *bf, RZ_NONNULL const char *arch, int bits, RZ_NULLABLE const char *machine, RZ_NULLABLE const char *filename) {
rz_return_val_if_fail(bf && arch, NULL);
if (bf->o) {
RzBinInfo *info = bf->o->info;
if (info && info->arch && info->file &&
(bits == info->bits) &&
!strcmp(info->arch, arch) &&
!strcmp(info->file, name)) {
(!filename || RZ_STR_EQ(info->file, filename)) &&
(!machine || RZ_STR_EQ(info->machine, machine))) {
return bf->o;
}
}

View file

@ -1070,8 +1070,36 @@ static int parse_thread(struct MACH0_(obj_t) * bin, struct load_command *lc, ut6
arw_ptr = (ut8 *)&bin->thread_state.arm_64;
arw_sz = sizeof(struct arm_thread_state64);
break;
case CPU_TYPE_MC680x0:
if (ptr_thread + sizeof(struct mc680x0_thread_state) > bin->size) {
return false;
}
if (rz_buf_fread_at(bin->b, ptr_thread,
(ut8 *)&bin->thread_state.mc680x0, bin->big_endian ? "17I1c" : "17i1c", 1) == -1) {
RZ_LOG_ERROR("read thread state mc680x064\n");
return false;
}
pc = bin->thread_state.mc680x0.pc;
pc_offset = ptr_thread + rz_offsetof(struct mc680x0_thread_state, pc);
arw_ptr = (ut8 *)&bin->thread_state.mc680x0;
arw_sz = sizeof(struct mc680x0_thread_state);
break;
case CPU_TYPE_SPARC:
if (ptr_thread + sizeof(struct sparc_thread_state64) > bin->size) {
return false;
}
if (rz_buf_fread_at(bin->b, ptr_thread,
(ut8 *)&bin->thread_state.sparc_64, bin->big_endian ? "36L" : "36l", 1) == -1) {
RZ_LOG_ERROR("read thread state sparc64\n");
return false;
}
pc = bin->thread_state.sparc_64.tpc;
pc_offset = ptr_thread + rz_offsetof(struct sparc_thread_state64, tpc);
arw_ptr = (ut8 *)&bin->thread_state.sparc_64;
arw_sz = sizeof(struct sparc_thread_state64);
break;
default:
RZ_LOG_ERROR("unknown thread state structure\n");
RZ_LOG_ERROR("unknown thread state structure %" PFMT32u "\n", bin->hdr.cputype);
return false;
}
@ -2845,12 +2873,11 @@ int MACH0_(get_bits_from_hdr)(struct MACH0_(mach_header) * hdr) {
return 32;
}
bool MACH0_(is_big_endian)(struct MACH0_(obj_t) * bin) {
if (bin) {
const int cpu = bin->hdr.cputype;
return cpu == CPU_TYPE_POWERPC || cpu == CPU_TYPE_POWERPC64;
}
return false;
bool MACH0_(is_big_endian)(RZ_NONNULL RzBuffer *buf) {
rz_return_val_if_fail(buf, false);
bool big_endian;
free(MACH0_(get_hdr)(buf, &big_endian));
return big_endian;
}
const char *MACH0_(get_intrp)(struct MACH0_(obj_t) * bin) {
@ -2967,7 +2994,8 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
RzBuffer *buf = bf->buf;
ut64 length = rz_buf_size(buf);
int n = 0;
struct MACH0_(mach_header) *mh = MACH0_(get_hdr)(buf);
bool big_endian;
struct MACH0_(mach_header) *mh = MACH0_(get_hdr)(buf, &big_endian);
if (!mh) {
return;
}
@ -2992,13 +3020,6 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
ut64 addr = 0x20 - 4;
ut32 word = 0;
ut8 wordbuf[sizeof(word)];
bool isBe = false;
switch (mh->cputype) {
case CPU_TYPE_POWERPC:
case CPU_TYPE_POWERPC64:
isBe = true;
break;
}
#define READWORD() \
if (rz_buf_read_at(buf, addr, (ut8 *)wordbuf, 4) != 4) { \
eprintf("Invalid address in buffer."); \
@ -3006,7 +3027,7 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
} \
addr += 4; \
pvaddr += 4; \
word = isBe ? rz_read_be32(wordbuf) : rz_read_le32(wordbuf);
word = rz_read_ble32(wordbuf, big_endian);
if (is64) {
addr += 4;
@ -3035,13 +3056,13 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
switch (lcType) {
case LC_BUILD_VERSION: {
ut32 platform;
if (!rz_buf_read_le32_at(buf, addr, &platform)) {
if (!rz_buf_read_ble32_at(buf, addr, &platform, big_endian)) {
break;
}
cb_printf("0x%08" PFMT64x " platform %s\n", pvaddr, rz_mach0_platform_to_string(platform));
ut16 minos1;
if (!rz_buf_read_le16_at(buf, addr + 6, &minos1)) {
if (!rz_buf_read_ble16_at(buf, addr + 6, &minos1, big_endian)) {
break;
}
ut8 minos2;
@ -3055,7 +3076,7 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
cb_printf("0x%08" PFMT64x " minos %d.%d.%d\n", pvaddr + 4, minos1, minos2, minos3);
ut16 sdk1;
if (!rz_buf_read_le16_at(buf, addr + 10, &sdk1)) {
if (!rz_buf_read_ble16_at(buf, addr + 10, &sdk1, big_endian)) {
break;
}
ut8 sdk2;
@ -3069,7 +3090,7 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
cb_printf("0x%08" PFMT64x " sdk %d.%d.%d\n", pvaddr + 8, sdk1, sdk2, sdk3);
ut32 ntools;
if (!rz_buf_read_le32_at(buf, addr + 12, &ntools)) {
if (!rz_buf_read_ble32_at(buf, addr + 12, &ntools, big_endian)) {
break;
}
cb_printf("0x%08" PFMT64x " ntools %d\n", pvaddr + 12, ntools);
@ -3079,7 +3100,7 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
cb_printf("pf.mach0_build_version_tool @ 0x%08" PFMT64x "\n", pvaddr + off);
ut32 tool;
if (!rz_buf_read_le32_at(buf, addr + off, &tool)) {
if (!rz_buf_read_ble32_at(buf, addr + off, &tool, big_endian)) {
break;
}
cb_printf("0x%08" PFMT64x " tool %s\n", pvaddr + off, rz_mach0_build_version_tool_to_string(tool));
@ -3090,7 +3111,7 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
}
ut16 version1;
if (!rz_buf_read_le16_at(buf, addr + off + 2, &version1)) {
if (!rz_buf_read_ble16_at(buf, addr + off + 2, &version1, big_endian)) {
break;
}
ut8 version2;
@ -3111,14 +3132,14 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
ut8 data[64] = { 0 };
rz_buf_read_at(buf, addr, data, sizeof(data));
#if RZ_BIN_MACH064
ut64 ep = rz_read_ble64(&data, false); // bin->big_endian);
ut64 ep = rz_read_ble64(&data, big_endian);
cb_printf("0x%08" PFMT64x " entry0 0x%" PFMT64x "\n", pvaddr, ep);
ut64 ss = rz_read_ble64(&data[8], false); // bin->big_endian);
ut64 ss = rz_read_ble64(&data[8], big_endian);
cb_printf("0x%08" PFMT64x " stacksize 0x%" PFMT64x "\n", pvaddr + 8, ss);
#else
ut32 ep = rz_read_ble32(&data, false); // bin->big_endian);
ut32 ep = rz_read_ble32(&data, big_endian);
cb_printf("0x%08" PFMT32x " entry0 0x%" PFMT32x "\n", (ut32)pvaddr, ep);
ut32 ss = rz_read_ble32(&data[4], false); // bin->big_endian);
ut32 ss = rz_read_ble32(&data[4], big_endian);
cb_printf("0x%08" PFMT32x " stacksize 0x%" PFMT32x "\n", (ut32)pvaddr + 4, ss);
#endif
} break;
@ -3126,14 +3147,14 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
break;
case LC_ID_DYLIB: { // install_name_tool
ut32 str_off;
if (!rz_buf_read_ble32_at(buf, addr, &str_off, isBe)) {
if (!rz_buf_read_ble32_at(buf, addr, &str_off, big_endian)) {
break;
}
char *id = rz_buf_get_string(buf, addr + str_off - 8);
ut16 current1;
if (!rz_buf_read_le16_at(buf, addr + 10, &current1)) {
if (!rz_buf_read_ble16_at(buf, addr + 10, &current1, big_endian)) {
free(id);
break;
}
@ -3150,7 +3171,7 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
cb_printf("0x%08" PFMT64x " current %d.%d.%d\n", pvaddr + 8, current1, current2, current3);
ut16 compat1;
if (!rz_buf_read_le16_at(buf, addr + 14, &compat1)) {
if (!rz_buf_read_ble16_at(buf, addr + 14, &compat1, big_endian)) {
free(id);
break;
}
@ -3186,7 +3207,7 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
rz_buf_read_at(buf, addr, name, sizeof(name) - 1);
cb_printf("0x%08" PFMT64x " name %s\n", pvaddr, name);
ut32 nsects;
if (!rz_buf_read_le32_at(buf, addr - 8 + (is64 ? 64 : 48), &nsects)) {
if (!rz_buf_read_ble32_at(buf, addr - 8 + (is64 ? 64 : 48), &nsects, big_endian)) {
break;
}
ut64 off = is64 ? 72 : 56;
@ -3203,12 +3224,12 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
case LC_LOAD_DYLIB:
case LC_LOAD_WEAK_DYLIB: {
ut32 str_off;
if (!rz_buf_read_ble32_at(buf, addr, &str_off, isBe)) {
if (!rz_buf_read_ble32_at(buf, addr, &str_off, big_endian)) {
break;
}
char *load_dylib = rz_buf_get_string(buf, addr + str_off - 8);
ut16 current1;
if (!rz_buf_read_le16_at(buf, addr + 10, &current1)) {
if (!rz_buf_read_ble16_at(buf, addr + 10, &current1, big_endian)) {
free(load_dylib);
break;
}
@ -3224,7 +3245,7 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
}
cb_printf("0x%08" PFMT64x " current %d.%d.%d\n", pvaddr + 8, current1, current2, current3);
ut16 compat1;
if (!rz_buf_read_le16_at(buf, addr + 14, &compat1)) {
if (!rz_buf_read_ble16_at(buf, addr + 14, &compat1, big_endian)) {
free(load_dylib);
break;
}
@ -3254,17 +3275,17 @@ void MACH0_(mach_headerfields)(RzBinFile *bf) {
case LC_ENCRYPTION_INFO:
case LC_ENCRYPTION_INFO_64: {
ut32 word;
if (!rz_buf_read_le32_at(buf, addr, &word)) {
if (!rz_buf_read_ble32_at(buf, addr, &word, big_endian)) {
break;
}
cb_printf("0x%08" PFMT64x " cryptoff 0x%08x\n", pvaddr, word);
if (!rz_buf_read_le32_at(buf, addr + 4, &word)) {
if (!rz_buf_read_ble32_at(buf, addr + 4, &word, big_endian)) {
break;
}
cb_printf("0x%08" PFMT64x " cryptsize %d\n", pvaddr + 4, word);
if (!rz_buf_read_le32_at(buf, addr + 8, &word)) {
if (!rz_buf_read_ble32_at(buf, addr + 8, &word, big_endian)) {
break;
}
cb_printf("0x%08" PFMT64x " cryptid %d\n", pvaddr + 8, word);
@ -3290,8 +3311,9 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
RzBuffer *buf = bf->buf;
ut64 length = rz_buf_size(buf);
bool big_endian;
struct MACH0_(mach_header) *mh = MACH0_(get_hdr)(buf);
struct MACH0_(mach_header) *mh = MACH0_(get_hdr)(buf, &big_endian);
if (!mh) {
return NULL;
}
@ -3300,7 +3322,6 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
ut32 word = 0;
char tmp[256] = { 0 };
bool big_endian = (mh->cputype & CPU_TYPE_POWERPC) != 0;
bool is_64bit = mh->cputype >> 16;
RzStructuredData *info = rz_structured_data_new_map();
@ -3324,7 +3345,7 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
rz_structured_data_map_add_string(mach0, "CpuType", "vax");
break;
case CPU_TYPE_MC680x0:
rz_structured_data_map_add_string(mach0, "CpuType", "mc680x0");
rz_structured_data_map_add_string(mach0, "CpuType", "m68k");
break;
case CPU_TYPE_X86:
rz_structured_data_map_add_string(mach0, "CpuType", "x86");
@ -3432,13 +3453,13 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
switch (lcType) {
case LC_BUILD_VERSION: {
ut32 platform;
if (!rz_buf_read_le32_at(buf, addr, &platform)) {
if (!rz_buf_read_ble32_at(buf, addr, &platform, big_endian)) {
break;
}
rz_structured_data_map_add_string(lc_info, "Platform", rz_mach0_platform_to_string(platform));
ut16 minos1;
if (!rz_buf_read_le16_at(buf, addr + 6, &minos1)) {
if (!rz_buf_read_ble16_at(buf, addr + 6, &minos1, big_endian)) {
break;
}
ut8 minos2;
@ -3453,7 +3474,7 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
rz_structured_data_map_add_string(lc_info, "MinOS", tmp);
ut16 sdk1;
if (!rz_buf_read_le16_at(buf, addr + 10, &sdk1)) {
if (!rz_buf_read_ble16_at(buf, addr + 10, &sdk1, big_endian)) {
break;
}
ut8 sdk2;
@ -3468,7 +3489,7 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
rz_structured_data_map_add_string(lc_info, "SDK", tmp);
ut32 ntools;
if (!rz_buf_read_le32_at(buf, addr + 12, &ntools)) {
if (!rz_buf_read_ble32_at(buf, addr + 12, &ntools, big_endian)) {
break;
}
rz_structured_data_map_add_unsigned(lc_info, "nTools", ntools, false);
@ -3490,7 +3511,7 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
}
ut32 tool;
if (!rz_buf_read_le32_at(buf, addr + off, &tool)) {
if (!rz_buf_read_ble32_at(buf, addr + off, &tool, big_endian)) {
break;
}
rz_structured_data_map_add_string(build, "Tool", rz_mach0_build_version_tool_to_string(tool));
@ -3501,7 +3522,7 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
}
ut16 version1;
if (!rz_buf_read_le16_at(buf, addr + off + 2, &version1)) {
if (!rz_buf_read_ble16_at(buf, addr + off + 2, &version1, big_endian)) {
break;
}
ut8 version2;
@ -3524,11 +3545,11 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
ut8 data[64] = { 0 };
rz_buf_read_at(buf, addr, data, sizeof(data));
#if RZ_BIN_MACH064
ut64 ep = rz_read_ble64(&data, false); // bin->big_endian);
ut64 ss = rz_read_ble64(&data[8], false); // bin->big_endian);
ut64 ep = rz_read_ble64(&data, big_endian);
ut64 ss = rz_read_ble64(&data[8], big_endian);
#else
ut32 ep = rz_read_ble32(&data, false); // bin->big_endian);
ut32 ss = rz_read_ble32(&data[4], false); // bin->big_endian);
ut32 ep = rz_read_ble32(&data, big_endian);
ut32 ss = rz_read_ble32(&data[4], big_endian);
#endif
rz_structured_data_map_add_unsigned(lc_info, "Entry", ep, true);
rz_structured_data_map_add_unsigned(lc_info, "StackSize", ss, false);
@ -3548,7 +3569,7 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
free(id);
ut16 current1;
if (!rz_buf_read_le16_at(buf, addr + 10, &current1)) {
if (!rz_buf_read_ble16_at(buf, addr + 10, &current1, big_endian)) {
break;
}
ut8 current2;
@ -3563,7 +3584,7 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
rz_structured_data_map_add_string(lc_info, "Current", tmp);
ut16 compat1;
if (!rz_buf_read_le16_at(buf, addr + 14, &compat1)) {
if (!rz_buf_read_ble16_at(buf, addr + 14, &compat1, big_endian)) {
break;
}
ut8 compat2;
@ -3596,7 +3617,7 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
rz_structured_data_map_add_string(lc_info, "Name", name);
ut32 nsects;
if (!rz_buf_read_le32_at(buf, addr - 8 + (is_64bit ? 64 : 48), &nsects)) {
if (!rz_buf_read_ble32_at(buf, addr - 8 + (is_64bit ? 64 : 48), &nsects, big_endian)) {
break;
}
rz_structured_data_map_add_unsigned(lc_info, "nSects", nsects, false);
@ -3615,7 +3636,7 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
free(load_dylib);
ut16 current1;
if (!rz_buf_read_le16_at(buf, addr + 10, &current1)) {
if (!rz_buf_read_ble16_at(buf, addr + 10, &current1, big_endian)) {
break;
}
ut8 current2;
@ -3630,7 +3651,7 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
rz_structured_data_map_add_string(lc_info, "Current", tmp);
ut16 compat1;
if (!rz_buf_read_le16_at(buf, addr + 14, &compat1)) {
if (!rz_buf_read_ble16_at(buf, addr + 14, &compat1, big_endian)) {
break;
}
ut8 compat2;
@ -3656,17 +3677,17 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
case LC_ENCRYPTION_INFO:
case LC_ENCRYPTION_INFO_64: {
ut32 word;
if (!rz_buf_read_le32_at(buf, addr, &word)) {
if (!rz_buf_read_ble32_at(buf, addr, &word, big_endian)) {
break;
}
rz_structured_data_map_add_unsigned(lc_info, "CryptOffset", word, true);
if (!rz_buf_read_le32_at(buf, addr + 4, &word)) {
if (!rz_buf_read_ble32_at(buf, addr + 4, &word, big_endian)) {
break;
}
rz_structured_data_map_add_unsigned(lc_info, "CryptSize", word, false);
if (!rz_buf_read_le32_at(buf, addr + 8, &word)) {
if (!rz_buf_read_ble32_at(buf, addr + 8, &word, big_endian)) {
break;
}
rz_structured_data_map_add_unsigned(lc_info, "CryptId", word, false);
@ -3693,7 +3714,8 @@ RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf) {
RzPVector /*<RzBinField *>*/ *MACH0_(mach_fields)(RzBinFile *bf) {
RzBuffer *buf = bf->buf;
ut64 length = rz_buf_size(buf);
struct MACH0_(mach_header) *mh = MACH0_(get_hdr)(buf);
bool big_endian;
struct MACH0_(mach_header) *mh = MACH0_(get_hdr)(buf, &big_endian);
if (!mh) {
return NULL;
}
@ -3714,23 +3736,15 @@ RzPVector /*<RzBinField *>*/ *MACH0_(mach_fields)(RzBinFile *bf) {
paddr += 4;
}
bool isBe = false;
switch (mh->cputype) {
case CPU_TYPE_POWERPC:
case CPU_TYPE_POWERPC64:
isBe = true;
break;
}
int n;
char tmpbuf[128];
for (n = 0; n < mh->ncmds; n++) {
ut32 lcType;
if (!rz_buf_read_ble32_at(buf, paddr, &lcType, isBe)) {
if (!rz_buf_read_ble32_at(buf, paddr, &lcType, big_endian)) {
break;
}
ut32 word;
if (!rz_buf_read_ble32_at(buf, paddr + 4, &word, isBe)) {
if (!rz_buf_read_ble32_at(buf, paddr + 4, &word, big_endian)) {
break;
}
if (paddr + 8 > length) {
@ -3752,7 +3766,7 @@ RzPVector /*<RzBinField *>*/ *MACH0_(mach_fields)(RzBinFile *bf) {
switch (lcType) {
case LC_BUILD_VERSION: {
ut32 ntools;
if (!rz_buf_read_le32_at(buf, paddr + 20, &ntools)) {
if (!rz_buf_read_ble32_at(buf, paddr + 20, &ntools, big_endian)) {
break;
}
ut64 off = 24;
@ -3766,7 +3780,7 @@ RzPVector /*<RzBinField *>*/ *MACH0_(mach_fields)(RzBinFile *bf) {
case LC_SEGMENT:
case LC_SEGMENT_64: {
ut32 nsects;
if (!rz_buf_read_le32_at(buf, addr + (is64 ? 64 : 48), &nsects)) {
if (!rz_buf_read_ble32_at(buf, addr + (is64 ? 64 : 48), &nsects, big_endian)) {
break;
}
ut64 off = is64 ? 72 : 56;
@ -3791,7 +3805,7 @@ RzPVector /*<RzBinField *>*/ *MACH0_(mach_fields)(RzBinFile *bf) {
return ret;
}
struct MACH0_(mach_header) * MACH0_(get_hdr)(RzBuffer *buf) {
struct MACH0_(mach_header) * MACH0_(get_hdr)(RzBuffer *buf, RZ_NULLABLE RZ_OUT bool *is_big_endian) {
ut8 magicbytes[sizeof(ut32)] = { 0 };
ut8 machohdrbytes[sizeof(struct MACH0_(mach_header))] = { 0 };
int len;
@ -3818,6 +3832,9 @@ struct MACH0_(mach_header) * MACH0_(get_hdr)(RzBuffer *buf) {
} else if (rz_read_be32(magicbytes) == 0xfeedfacf) {
big_endian = true;
}
if (is_big_endian) {
*is_big_endian = big_endian;
}
len = rz_buf_read_at(buf, 0, machohdrbytes, sizeof(machohdrbytes));
if (len != sizeof(struct MACH0_(mach_header))) {
free(macho_hdr);

View file

@ -188,6 +188,8 @@ struct MACH0_(obj_t) {
struct ppc_thread_state64 ppc_64;
struct arm_thread_state32 arm_32;
struct arm_thread_state64 arm_64;
struct sparc_thread_state64 sparc_64;
struct mc680x0_thread_state mc680x0;
} thread_state;
char (*libs)[RZ_BIN_MACH0_STRING_LENGTH];
int nlibs;
@ -247,7 +249,7 @@ struct lib_t *MACH0_(get_libs)(struct MACH0_(obj_t) * bin);
ut64 MACH0_(get_baddr)(struct MACH0_(obj_t) * bin);
char *MACH0_(get_class)(struct MACH0_(obj_t) * bin);
int MACH0_(get_bits)(struct MACH0_(obj_t) * bin);
bool MACH0_(is_big_endian)(struct MACH0_(obj_t) * bin);
bool MACH0_(is_big_endian)(RZ_NONNULL RzBuffer *buf);
bool MACH0_(is_pie)(struct MACH0_(obj_t) * bin);
bool MACH0_(has_nx)(struct MACH0_(obj_t) * bin);
const char *MACH0_(get_intrp)(struct MACH0_(obj_t) * bin);
@ -260,7 +262,7 @@ char *MACH0_(get_filetype_from_hdr)(struct MACH0_(mach_header) * hdr);
ut64 MACH0_(get_main)(struct MACH0_(obj_t) * bin);
const char *MACH0_(get_cputype_from_hdr)(struct MACH0_(mach_header) * hdr);
int MACH0_(get_bits_from_hdr)(struct MACH0_(mach_header) * hdr);
struct MACH0_(mach_header) * MACH0_(get_hdr)(RzBuffer *buf);
struct MACH0_(mach_header) * MACH0_(get_hdr)(RzBuffer *buf, RZ_NULLABLE RZ_OUT bool *is_big_endian);
RzStructuredData *MACH0_(mach_structure)(RzBinFile *bf);
RzPVector /*<RzBinField *>*/ *MACH0_(mach_fields)(RzBinFile *bf);
RZ_API RZ_OWN char *MACH0_(get_name)(struct MACH0_(obj_t) * mo, ut32 stridx, bool filter);

View file

@ -46,7 +46,7 @@ RZ_API RZ_NONNULL const char *rz_mach0_cputype_to_string(ut32 cputype) {
case CPU_TYPE_VAX:
return "vax";
case CPU_TYPE_MC680x0:
return "mc680x0";
return "m68k";
case CPU_TYPE_I386:
case CPU_TYPE_X86_64:
return "x86";

View file

@ -190,6 +190,38 @@ struct arm_thread_state64 {
ut32 flags;
};
/**
* \brief This layout is guessed. I couldn't find a reference online
* implementing linking of Mach-O Sparc binaries and has the layout of the thread state.
* The layout below is the one used for the registers in the ELF core dumps.
* I use this in the hope the Mach-O and ELF devs had some
* commen documentation they were refering to.
*/
struct sparc_thread_state64 {
ut64 g[8];
ut64 o[8];
ut64 l[8];
ut64 i[8];
ut64 tstate;
ut64 tpc;
ut64 tnpc;
ut64 y;
};
/**
* \brief Assume layout of register file from the ISA:
*
* Figure 2-1:
* https://www.nxp.com/docs/en/reference-manual/MC68000UM.pdf
* https://web.archive.org/web/20250716224705/https://www.nxp.com/docs/en/reference-manual/MC68000UM.pdf
*/
struct mc680x0_thread_state {
ut32 d[8];
ut32 a[8];
ut32 pc;
ut8 ccr;
};
typedef struct {
uint8_t uuid[16];
uint64_t loadAddress;

View file

@ -26,7 +26,7 @@ RZ_IPI void rz_bin_object_free(RzBinObject *o);
RZ_IPI ut64 rz_bin_object_get_baddr(RzBinObject *o);
RZ_IPI RzBinObject *rz_bin_object_new(RzBinFile *binfile, RzBinPlugin *plugin, RzBinObjectLoadOptions *opts, ut64 offset, ut64 sz);
RZ_IPI RzBinObject *rz_bin_object_get_cur(RzBin *bin);
RZ_IPI RzBinObject *rz_bin_object_find_by_arch_bits(RzBinFile *binfile, const char *arch, int bits, const char *name);
RZ_IPI RzBinObject *rz_bin_object_find_by_arch_bits(RzBinFile *bf, RZ_NONNULL const char *arch, int bits, RZ_NULLABLE const char *machine, RZ_NULLABLE const char *filename);
RZ_IPI RzBinFile *rz_bin_file_xtr_load_buffer(RzBin *bin, RzBinXtrPlugin *xtr, const char *filename, RzBuffer *buf, RzBinObjectLoadOptions *obj_opts, int idx, int fd);
RZ_IPI RzBinFile *rz_bin_file_new_from_buffer(RzBin *bin, const char *file, RzBuffer *buf, RzBinObjectLoadOptions *opts, int fd, const char *pluginname);

View file

@ -474,7 +474,7 @@ static RzBinInfo *mach0_info(RzBinFile *bf) {
ret->cpu = MACH0_(get_cpusubtype)(bf->o->bin_obj);
ret->machine = MACH0_(get_cpusubtype)(bf->o->bin_obj);
ret->type = MACH0_(get_filetype)(bf->o->bin_obj);
ret->big_endian = MACH0_(is_big_endian)(bf->o->bin_obj);
ret->big_endian = MACH0_(is_big_endian)(bf->buf);
ret->bits = 32;
if (bf && bf->o && bf->o->bin_obj) {
ret->has_crypto = ((struct MACH0_(obj_t) *)

View file

@ -59,11 +59,12 @@ static int size(RzBin *bin) {
return 0;
}
static inline void fill_metadata_info_from_hdr(RzBinXtrMetadata *meta, struct MACH0_(mach_header) * hdr) {
static inline void fill_metadata_info_from_hdr(RzBinXtrMetadata *meta, struct MACH0_(mach_header) * hdr, bool is_big_endian) {
meta->arch = rz_str_dup(MACH0_(get_cputype_from_hdr)(hdr));
meta->bits = MACH0_(get_bits_from_hdr)(hdr);
meta->machine = MACH0_(get_cpusubtype_from_hdr)(hdr);
meta->type = MACH0_(get_filetype_from_hdr)(hdr);
meta->big_endian = is_big_endian;
meta->libname = NULL;
meta->xtr_type = "fat";
}
@ -82,14 +83,15 @@ static RzBinXtrData *extract(RzBin *bin, int idx) {
free(arch);
return NULL;
}
struct MACH0_(mach_header) *hdr = MACH0_(get_hdr)(arch->b);
bool big_endian;
struct MACH0_(mach_header) *hdr = MACH0_(get_hdr)(arch->b, &big_endian);
if (!hdr) {
free(metadata);
free(arch);
free(hdr);
return NULL;
}
fill_metadata_info_from_hdr(metadata, hdr);
fill_metadata_info_from_hdr(metadata, hdr, big_endian);
RzBinXtrData *res = rz_bin_xtrdata_new(arch->b, arch->offset, arch->size, narch, metadata);
rz_buf_free(arch->b);
free(arch);
@ -106,23 +108,27 @@ static RzBinXtrData *oneshot_buffer(RzBin *bin, RzBuffer *b, int idx) {
int narch;
struct rz_bin_fatmach0_obj_t *fb = bin->cur->xtr_obj;
struct rz_bin_fatmach0_arch_t *arch = rz_bin_fatmach0_extract(fb, idx, &narch);
if (arch) {
RzBinXtrMetadata *metadata = RZ_NEW0(RzBinXtrMetadata);
if (metadata) {
struct MACH0_(mach_header) *hdr = MACH0_(get_hdr)(arch->b);
if (hdr) {
fill_metadata_info_from_hdr(metadata, hdr);
RzBinXtrData *res = rz_bin_xtrdata_new(arch->b, arch->offset, arch->size, narch, metadata);
rz_buf_free(arch->b);
free(arch);
free(hdr);
return res;
}
free(metadata);
}
free(arch);
if (!arch) {
return NULL;
}
return NULL;
RzBinXtrMetadata *metadata = RZ_NEW0(RzBinXtrMetadata);
if (!metadata) {
free(arch);
return NULL;
}
bool big_endian;
struct MACH0_(mach_header) *hdr = MACH0_(get_hdr)(arch->b, &big_endian);
if (!hdr) {
free(metadata);
free(arch);
return NULL;
}
fill_metadata_info_from_hdr(metadata, hdr, big_endian);
RzBinXtrData *res = rz_bin_xtrdata_new(arch->b, arch->offset, arch->size, narch, metadata);
rz_buf_free(arch->b);
free(arch);
free(hdr);
return res;
}
static RzList /*<RzBinXtrData *>*/ *oneshotall_buffer(RzBin *bin, RzBuffer *b) {

View file

@ -301,6 +301,9 @@ RZ_API bool rz_core_bin_apply_all_info(RzCore *r, RzBinFile *binfile) {
r->dbg->bp->baddr = baseaddr;
rz_config_set(r->config, "asm.arch", arch);
rz_config_set_i(r->config, "asm.bits", bits);
if (info->cpu) {
rz_config_set(r->config, "asm.cpu", info->cpu);
}
rz_config_set(r->config, "analysis.arch", arch);
if (RZ_STR_ISNOTEMPTY(info->cpu)) {
rz_config_set(r->config, "analysis.cpu", info->cpu);
@ -4649,37 +4652,37 @@ static int bin_versioninfo(RzCore *r, PJ *pj, int mode) {
return true;
}
RZ_API int rz_core_bin_set_arch_bits(RzCore *r, const char *name, const char *arch, ut16 bits) {
int fd = rz_io_fd_get_current(r->io);
RzIODesc *desc = rz_io_desc_get(r->io, fd);
/**
* \brief Sets the current architecture and bits to the given values.
* If there is a RzBinFile with \p filename, and/or an object for \p arch and \p bits,
* it will load it and set it as main object file.
*
* \param r The current RzCore isntance to update.
* \param filename (Optional) The filename of the RzBinFile to load.
* \param arch The architecture name.
* \param bits The architecture bits.
*
* \return True if loading the binary file was successful. False otherwise.
*/
RZ_API bool rz_core_bin_set_arch_bits(RZ_NONNULL RzCore *r, RZ_NULLABLE const char *filename, RZ_NULLABLE const char *arch, ut16 bits) {
rz_return_val_if_fail(r, false);
RzBinFile *curfile, *binfile = NULL;
if (!name) {
if (!desc || !desc->name) {
return false;
}
name = desc->name;
}
/* Check if the arch name is a valid name */
if (!rz_asm_is_valid(r->rasm, arch)) {
return false;
}
/* Find a file with the requested name/arch/bits */
binfile = rz_bin_file_find_by_arch_bits(r->bin, arch, bits);
binfile = rz_bin_file_find_by_arch_bits(r->bin, arch, bits, NULL, filename);
if (!binfile) {
return false;
}
if (!rz_bin_use_arch(r->bin, arch, bits, name)) {
if (!rz_bin_use_arch(r->bin, arch, bits, NULL, filename)) {
return false;
}
curfile = rz_bin_cur(r->bin);
// set env if the binfile changed or we are dealing with xtr
if (curfile != binfile || binfile->curxtr) {
rz_core_bin_set_cur(r, binfile);
if (binfile->o && binfile->o->info) {
free(binfile->o->info->arch);
binfile->o->info->arch = rz_str_dup(arch);
binfile->o->info->bits = bits;
}
return rz_core_bin_apply_all_info(r, binfile);
}
return true;
@ -5394,12 +5397,13 @@ struct arch_ctx {
ut64 size;
const char *arch;
int bits;
bool big_endian;
const char *machine;
};
static void print_arch(RzBin *bin, RzCmdStateOutput *state, struct arch_ctx *ctx, const char *flag, RzBinInfo *info) {
char str_fmt[30];
const char *fmt = "Xnss";
const char *fmt = "Xnsisb";
switch (state->mode) {
case RZ_OUTPUT_MODE_QUIET:
@ -5409,6 +5413,7 @@ static void print_arch(RzBin *bin, RzCmdStateOutput *state, struct arch_ctx *ctx
pj_o(state->d.pj);
pj_ks(state->d.pj, "arch", ctx->arch);
pj_ki(state->d.pj, "bits", ctx->bits);
pj_kb(state->d.pj, "big_endian", ctx->big_endian);
pj_kn(state->d.pj, "offset", ctx->offset);
pj_kn(state->d.pj, "size", ctx->size);
if (info) {
@ -5422,11 +5427,11 @@ static void print_arch(RzBin *bin, RzCmdStateOutput *state, struct arch_ctx *ctx
break;
case RZ_OUTPUT_MODE_TABLE:
if (flag && strcmp(flag, "unknown_flag")) {
rz_strf(str_fmt, "%s_%i %s", ctx->arch, ctx->bits, flag);
rz_strf(str_fmt, "%s %s", ctx->arch, flag);
} else {
rz_strf(str_fmt, "%s_%i", ctx->arch, ctx->bits);
rz_strf(str_fmt, "%s", ctx->arch);
}
rz_table_add_rowf(state->d.t, fmt, ctx->offset, ctx->size, str_fmt, ctx->machine);
rz_table_add_rowf(state->d.t, fmt, ctx->offset, ctx->size, str_fmt, ctx->bits, ctx->machine, ctx->big_endian);
break;
default:
rz_warn_if_reached();
@ -5442,9 +5447,9 @@ RZ_API bool rz_core_bin_archs_print(RZ_NONNULL RzBin *bin, RZ_NONNULL RzCmdState
return false;
}
const char *fmt = "Xnss";
const char *fmt = "Xnsisb";
rz_cmd_state_output_array_start(state);
rz_cmd_state_output_set_columnsf(state, fmt, "offset", "size", "arch", "machine", NULL);
rz_cmd_state_output_set_columnsf(state, fmt, "offset", "size", "arch", "bits", "machine", "big_endian", NULL);
if (binfile->curxtr) {
RzListIter *iter_xtr;
@ -5459,6 +5464,7 @@ RZ_API bool rz_core_bin_archs_print(RZ_NONNULL RzBin *bin, RZ_NONNULL RzCmdState
ctx.size = xtr_data->size;
ctx.arch = xtr_data->metadata->arch;
ctx.bits = xtr_data->metadata->bits;
ctx.big_endian = xtr_data->metadata->big_endian;
ctx.machine = xtr_data->metadata->machine;
print_arch(bin, state, &ctx, NULL, NULL);
@ -5471,6 +5477,7 @@ RZ_API bool rz_core_bin_archs_print(RZ_NONNULL RzBin *bin, RZ_NONNULL RzCmdState
ctx.size = obj->obj_size;
ctx.arch = (info && info->arch) ? info->arch : "unk_0";
ctx.bits = info ? info->bits : 0;
ctx.big_endian = info ? info->big_endian : false;
ctx.machine = info ? info->machine : "unknown_machine";
const char *h_flag = info ? info->head_flag : NULL;

View file

@ -757,6 +757,58 @@ RZ_IPI RzCmdStatus rz_open_binary_file_handler(RzCore *core, int argc, const cha
return RZ_CMD_STATUS_OK;
}
static inline bool xtr_selection_matches(RzList /*<const char *>*/ *selection, const RzBinXtrMetadata *metadata) {
rz_return_val_if_fail(selection && metadata && rz_list_length(selection) >= 2, false);
return (RZ_STR_EQ(rz_list_get_n(selection, 0), metadata->arch) &&
atoi(rz_list_get_n(selection, 1)) == metadata->bits &&
(rz_list_length(selection) < 3 || RZ_STR_ISEMPTY(metadata->machine) || RZ_STR_EQ(rz_list_get_n(selection, 2), metadata->machine)));
}
RZ_IPI RzCmdStatus rz_open_binary_select_handler(RzCore *core, int argc, const char **argv) {
RzBin *bin = core->bin;
if (!bin) {
return RZ_CMD_STATUS_ERROR;
}
bool list_existing = argc == 1;
RzListIter *iter;
RzBinFile *binfile = NULL;
RzBinXtrData *xtr_data;
size_t bits = 0;
rz_list_foreach (bin->binfiles, iter, binfile) {
RzListIter *iter_xtr;
if (!binfile->xtr_data) {
continue;
}
rz_list_foreach (binfile->xtr_data, iter_xtr, xtr_data) {
if (list_existing) {
rz_cons_printf("%s_%i_%s\n", xtr_data->metadata->arch, xtr_data->metadata->bits, xtr_data->metadata->machine);
continue;
}
RzList *selection = rz_str_split_duplist(argv[1], "_", 0);
if (rz_list_length(selection) < 2) {
RZ_LOG_WARN("Invalid argument.\n");
return RZ_CMD_STATUS_ERROR;
}
if (xtr_selection_matches(selection, xtr_data->metadata)) {
bits = xtr_data->metadata->bits;
const char *mach = rz_list_length(selection) > 2 ? rz_list_get_n(selection, 2) : NULL;
if (!rz_bin_select(bin, rz_list_get_n(selection, 0), bits, mach, NULL)) {
rz_list_free(selection);
return RZ_CMD_STATUS_ERROR;
}
if (!rz_core_bin_apply_all_info(core, binfile)) {
rz_list_free(selection);
return RZ_CMD_STATUS_ERROR;
}
break;
}
rz_list_free(selection);
}
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_open_binary_reload_handler(RzCore *core, int argc, const char **argv) {
// XXX: this will reload the bin using the buffer.
// An assumption is made that assumes there is an underlying

View file

@ -78,6 +78,7 @@ static const RzCmdDescDetail history_list_or_exec_details[2];
static const RzCmdDescDetail cmd_info_query_details[2];
static const RzCmdDescDetail query_sdb_get_set_details[2];
static const RzCmdDescDetail plugins_asm_print_details[2];
static const RzCmdDescDetail open_binary_select_details[2];
static const RzCmdDescDetail cmd_print_byte_array_details[3];
static const RzCmdDescDetail pf_details[3];
static const RzCmdDescDetail print_string_details[2];
@ -648,6 +649,7 @@ static const RzCmdDescArg open_binary_select_fd_args[2];
static const RzCmdDescArg open_binary_del_args[2];
static const RzCmdDescArg open_binary_add_args[2];
static const RzCmdDescArg open_binary_file_args[2];
static const RzCmdDescArg open_binary_select_args[2];
static const RzCmdDescArg open_binary_reload_args[2];
static const RzCmdDescArg open_use_args[2];
static const RzCmdDescArg open_prioritize_args[2];
@ -14224,6 +14226,31 @@ static const RzCmdDescHelp open_binary_file_help = {
.args = open_binary_file_args,
};
static const RzCmdDescDetailEntry open_binary_select_Examples_detail_entries[] = {
{ .text = "obs", .arg_str = NULL, .comment = "List all architectures the fat binary supports contains." },
{ .text = "obs sparc", .arg_str = NULL, .comment = "Select and load the binary for Sparc" },
{ 0 },
};
static const RzCmdDescDetail open_binary_select_details[] = {
{ .name = "Examples", .entries = open_binary_select_Examples_detail_entries },
{ 0 },
};
static const RzCmdDescArg open_binary_select_args[] = {
{
.name = "arch",
.type = RZ_CMD_ARG_TYPE_STRING,
.flags = RZ_CMD_ARG_FLAG_LAST,
.optional = true,
},
{ 0 },
};
static const RzCmdDescHelp open_binary_select_help = {
.summary = "Select the binary version for the specified architecture from the fat binary.",
.details = open_binary_select_details,
.args = open_binary_select_args,
};
static const RzCmdDescArg open_binary_reload_args[] = {
{
.name = "baddr",
@ -24050,6 +24077,9 @@ RZ_IPI void rzshell_cmddescs_init(RzCore *core) {
RzCmdDesc *open_binary_file_cd = rz_cmd_desc_argv_new(core->rcmd, ob_cd, "obf", rz_open_binary_file_handler, &open_binary_file_help);
rz_warn_if_fail(open_binary_file_cd);
RzCmdDesc *open_binary_select_cd = rz_cmd_desc_argv_new(core->rcmd, ob_cd, "obs", rz_open_binary_select_handler, &open_binary_select_help);
rz_warn_if_fail(open_binary_select_cd);
RzCmdDesc *open_binary_reload_cd = rz_cmd_desc_argv_new(core->rcmd, ob_cd, "obR", rz_open_binary_reload_handler, &open_binary_reload_help);
rz_warn_if_fail(open_binary_reload_cd);

View file

@ -1870,6 +1870,8 @@ RZ_IPI RzCmdStatus rz_open_binary_show_handler(RzCore *core, int argc, const cha
RZ_IPI RzCmdStatus rz_open_binary_add_handler(RzCore *core, int argc, const char **argv);
// "obf"
RZ_IPI RzCmdStatus rz_open_binary_file_handler(RzCore *core, int argc, const char **argv);
// "obs"
RZ_IPI RzCmdStatus rz_open_binary_select_handler(RzCore *core, int argc, const char **argv);
// "obR"
RZ_IPI RzCmdStatus rz_open_binary_reload_handler(RzCore *core, int argc, const char **argv);
// "ou"

View file

@ -256,6 +256,20 @@ commands:
- name: file
type: RZ_CMD_ARG_TYPE_FILE
optional: true
- name: obs
cname: open_binary_select
summary: Select the binary version for the specified architecture from the fat binary.
args:
- name: arch
type: RZ_CMD_ARG_TYPE_STRING
optional: true
details:
- name: Examples
entries:
- text: "obs"
comment: "List all architectures the fat binary supports contains."
- text: "obs sparc"
comment: "Select and load the binary for Sparc"
- name: obR
cname: open_binary_reload
summary: Reload the current buffer for setting of the bin (use once only)

View file

@ -425,6 +425,7 @@ typedef struct rz_bin_xtr_metadata_t {
char *libname;
char *machine;
char *type;
bool big_endian;
const char *xtr_type;
} RzBinXtrMetadata;
@ -998,21 +999,25 @@ RZ_API RzBinFile *rz_bin_cur(RzBin *bin);
RZ_API RzBinObject *rz_bin_cur_object(RzBin *bin);
// select/list binfiles functions
RZ_API bool rz_bin_select(RzBin *bin, const char *arch, int bits, const char *name);
RZ_API bool rz_bin_select(RzBin *bin, RZ_NONNULL const char *arch, int bits, RZ_NULLABLE const char *machine, RZ_NULLABLE const char *filename);
RZ_API bool rz_bin_select_bfid(RzBin *bin, ut32 bf_id);
RZ_API bool rz_bin_use_arch(RzBin *bin, const char *arch, int bits, const char *name);
RZ_API bool rz_bin_use_arch(RzBin *bin, const char *arch, int bits, RZ_NULLABLE const char *machine, RZ_NULLABLE const char *filename);
RZ_API RzBuffer *rz_bin_create(RzBin *bin, const char *plugin_name, const ut8 *code, int codelen, const ut8 *data, int datalen, RzBinArchOptions *opt);
RZ_API const char *rz_bin_entry_type_string(int etype);
RZ_API ut64 rz_bin_get_first_entrypoint(RZ_NULLABLE RzBinObject *obj);
RZ_API bool rz_bin_file_object_new_from_xtr_data(RzBin *bin, RzBinFile *bf, RzBinObjectLoadOptions *opts, RzBinXtrData *data);
RZ_API bool rz_bin_file_set_xtr_data_as_current_obj(
RZ_BORROW RZ_NONNULL RzBin *bin,
RZ_BORROW RZ_NONNULL RzBinFile *bf,
RZ_BORROW RZ_NONNULL RzBinObjectLoadOptions *opts,
RZ_BORROW RZ_NONNULL RzBinXtrData *data);
// RzBinFile.get
RZ_API RzBinFile *rz_bin_file_at(RzBin *bin, ut64 addr);
RZ_API RzPVector /*<RzBinSymbol *>*/ *rz_bin_file_get_symbols(RzBinFile *bf);
// RzBinFile.find
RZ_API RzBinFile *rz_bin_file_find_by_arch_bits(RzBin *bin, const char *arch, int bits);
RZ_API RZ_BORROW RzBinFile *rz_bin_file_find_by_arch_bits(RzBin *bin, const char *arch, int bits, RZ_NULLABLE const char *machine, RZ_NULLABLE const char *filename);
RZ_API RzBinFile *rz_bin_file_find_by_id(RzBin *bin, ut32 bin_id);
RZ_API RzBinFile *rz_bin_file_find_by_fd(RzBin *bin, ut32 bin_fd);
RZ_API RzBinFile *rz_bin_file_find_by_name(RzBin *bin, const char *name);

View file

@ -993,7 +993,7 @@ typedef struct rz_core_bin_filter_t {
const char *name;
} RzCoreBinFilter;
RZ_API int rz_core_bin_set_arch_bits(RzCore *r, const char *name, const char *arch, ut16 bits);
RZ_API bool rz_core_bin_set_arch_bits(RZ_NONNULL RzCore *r, RZ_NULLABLE const char *filename, RZ_NULLABLE const char *arch, ut16 bits);
RZ_API int rz_core_bin_update_arch_bits(RzCore *r);
RZ_API RZ_OWN char *rz_core_bin_class_build_flag_name(RZ_NONNULL RzBinClass *cls);
RZ_API RZ_OWN char *rz_core_bin_super_build_flag_name(RZ_NONNULL RzBinClass *cls);

View file

@ -172,7 +172,7 @@ static int rzbin_show_help(int v) {
"-e", "", "Entrypoint",
"-ee", "", "Constructor/destructor entrypoints",
"-E", "", "Globally exportable symbols",
"-f", "[str]", "Select sub-bin named str",
"-f", "[mach]", "Select sub-binary for the machine [mach].",
"-F", "[binfmt]", "Force to use that bin plugin (ignore header check)",
"-g", "", "Same as -SMZIHVResizcld -SS -SSS -ee (show all info)",
"-G", "[addr]", "Load address . offset to header",
@ -554,7 +554,7 @@ static int rzbin_do_operation(RzBin *bin, const char *op, int rad, const char *o
.baseaddr = UT64_MAX,
.loadaddr = rz_bin_get_laddr(bin)
};
if (xtr_data && !xtr_data->loaded && !rz_bin_file_object_new_from_xtr_data(bin, cur, &obj_opts, xtr_data)) {
if (xtr_data && !xtr_data->loaded && !rz_bin_file_set_xtr_data_as_current_obj(bin, cur, &obj_opts, xtr_data)) {
break;
}
}
@ -717,7 +717,7 @@ RZ_API int rz_main_rz_bin(int argc, const char **argv) {
int c, bits = 0, actions = 0;
char *create = NULL;
ut64 action = RZ_BIN_REQ_UNK;
char *tmp, *ptr, *arch_name = NULL;
char *tmp, *ptr, *machine = NULL;
const char *arch = NULL;
const char *forcebin = NULL;
const char *chksum = NULL;
@ -858,7 +858,7 @@ RZ_API int rz_main_rz_bin(int argc, const char **argv) {
set_action(RZ_BIN_REQ_CLASSES);
}
break;
case 'f': arch_name = rz_str_dup(opt.arg); break;
case 'f': machine = rz_str_dup(opt.arg); break;
case 'F': forcebin = opt.arg; break;
case 'b': bits = rz_num_math(NULL, opt.arg); break;
case 'm':
@ -1004,6 +1004,10 @@ RZ_API int rz_main_rz_bin(int argc, const char **argv) {
break;
}
}
if (machine && !(arch && bits)) {
RZ_LOG_ERROR("Selecting a machine requires [arch] and [bits].")
RZ_FREE(machine);
}
if (is_active(RZ_BIN_REQ_LISTPLUGINS)) {
const char *plugin_name = NULL;
@ -1297,12 +1301,12 @@ RZ_API int rz_main_rz_bin(int argc, const char **argv) {
start_state(&state);
// List fatmach0 sub-binaries, etc
if (action & RZ_BIN_REQ_LISTARCHS || ((arch || bits || arch_name) && !rz_bin_select(bin, arch, bits, arch_name))) {
if (action & RZ_BIN_REQ_LISTARCHS || (arch && bits && !rz_bin_select(bin, arch, bits, machine, NULL))) {
RzCmdStateOutput *st = add_header(&state, mode == RZ_OUTPUT_MODE_STANDARD ? RZ_OUTPUT_MODE_TABLE : mode, "archs");
rz_core_bin_archs_print(bin, st);
add_footer(&state, st);
free(arch_name);
}
free(machine);
if (action & RZ_BIN_REQ_PDB_DWNLD) {
SPDBOptions pdbopts;
pdbopts.symbol_server = (char *)rz_config_get(core.config, "pdb.server");
@ -1339,7 +1343,7 @@ RZ_API int rz_main_rz_bin(int argc, const char **argv) {
}
if (action & RZ_BIN_REQ_EXTRACT) {
if (bf->xtr_data) {
rzbin_extract(bin, (!arch && !arch_name && !bits));
rzbin_extract(bin, (!arch && !machine && !bits));
} else {
eprintf(
"Cannot extract bins from '%s'. No supported "

View file

@ -105,6 +105,8 @@ a4 = 0x00000000
a5 = 0x00000000
a6 = 0x00000000
a7 = 0x00000000
pc = 0x00000000
ccr = 0x00
fp0 = 0x00000000
fp1 = 0x00000000
fp2 = 0x00000000
@ -113,9 +115,10 @@ fp4 = 0x00000000
fp5 = 0x00000000
fp6 = 0x00000000
fp7 = 0x00000000
pc = 0x00000000
fpcr = 0x00000000
fpsr = 0x00000000
fpiar = 0x00000000
sr = 0x00000000
ccr = 0x00000000
sfc = 0x00000000
dfc = 0x00000000
usp = 0x00000000
@ -132,8 +135,5 @@ dtt1 = 0x00000000
mmusr = 0x00000000
urp = 0x00000000
srp = 0x00000000
fpcr = 0x00000000
fpsr = 0x00000000
fpiar = 0x00000000
EOF
RUN

View file

@ -319,10 +319,10 @@ iA
iAj
EOF
EXPECT=<<EOF
offset size arch machine
----------------------------------------------------------------------
0x00000000 266108 mips_32 mips32 noreorder pic MIPS R3000 big-endian
[{"arch":"mips","bits":32,"offset":0,"size":266108,"cpu":"mips32","features":"noreorder pic cpic o32 n32","machine":"MIPS R3000 big-endian"}]
offset size arch bits machine big_endian
--------------------------------------------------------------------------------------
0x00000000 266108 mips mips32 noreorder pic cpi 32 MIPS R3000 big-endian true
[{"arch":"mips","bits":32,"big_endian":true,"offset":0,"size":266108,"cpu":"mips32","features":"noreorder pic cpic o32 n32","machine":"MIPS R3000 big-endian"}]
EOF
RUN
@ -333,10 +333,10 @@ iA
iAj
EOF
EXPECT=<<EOF
offset size arch machine
-----------------------------------------------------------------------
0x00000000 1039368 mips_64 mips64r2 noreorder pi MIPS R3000 big-endian
[{"arch":"mips","bits":64,"offset":0,"size":1039368,"cpu":"mips64r2","features":"noreorder pic cpic n64","machine":"MIPS R3000 big-endian"}]
offset size arch bits machine big_endian
---------------------------------------------------------------------------------------
0x00000000 1039368 mips mips64r2 noreorder pic c 64 MIPS R3000 big-endian false
[{"arch":"mips","bits":64,"big_endian":false,"offset":0,"size":1039368,"cpu":"mips64r2","features":"noreorder pic cpic n64","machine":"MIPS R3000 big-endian"}]
EOF
RUN
@ -344,9 +344,9 @@ NAME=iA (file x86)
FILE=bins/elf/analysis/x86-helloworld-gcc
CMDS=iA
EXPECT=<<EOF
offset size arch machine
-----------------------------------
0x00000000 4899 x86_32 Intel 80386
offset size arch bits machine big_endian
-------------------------------------------------
0x00000000 4899 x86 32 Intel 80386 false
EOF
RUN
@ -3350,9 +3350,9 @@ NAME=iA (file x86_64)
FILE=bins/elf/analysis/hello-linux-x86_64
CMDS=iA
EXPECT=<<EOF
offset size arch machine
-----------------------------------------------
0x00000000 6710 x86_64 AMD x86-64 architecture
offset size arch bits machine big_endian
-------------------------------------------------------------
0x00000000 6710 x86 64 AMD x86-64 architecture false
EOF
RUN

View file

@ -707,3 +707,183 @@ EXPECT=<<EOF
1 fd: 3 +0x00000000 0x00000000 * 0x000001ff rwx
EOF
RUN
NAME=M68k, HPPA, Sparc, x86
FILE=bins/mach0/2048-NeXTSTEP
CMDS=<<EOF
iA
EOF
EXPECT=<<EOF
offset size arch bits machine big_endian
------------------------------------------------
0x00002000 49152 m68k 32 mc68030 true
0x0000e000 40960 x86 32 386 false
0x00018000 49152 hppa 32 hppa7100 true
0x00024000 49152 sparc 32 all true
EOF
EXPECT_ERR=
RUN
NAME=M68k, HPPA, Sparc, x86
FILE=bins/mach0/2048-NeXTSTEP
CMDS=<<EOF
# Test if sane defaults were selected
echo default (m68k)
e asm.arch
e asm.cpu
e asm.bits
e cfg.bigendian
pd 10 @ section.0.__TEXT.__text
obs hppa_32_hppa7100
e asm.arch
e asm.cpu
e asm.bits
e cfg.bigendian
pd 10 @ section.0.__TEXT.__text
obs sparc_32_all
e asm.arch
e asm.cpu
e asm.bits
e cfg.bigendian
pd 10 @ section.0.__TEXT.__text
obs x86_32_386
e asm.arch
e asm.cpu
e asm.bits
e cfg.bigendian
pd 10 @ section.0.__TEXT.__text
obs m68k_32_mc68030
e asm.arch
e asm.cpu
e asm.bits
e cfg.bigendian
pd 10 @ section.0.__TEXT.__text
EOF
EXPECT=<<EOF
default (m68k)
m68k
mc68030
32
true
;-- section.0.__TEXT.__text:
0x000049c0 movea.l a7, a0 ; [00] -r-x section size 6638 named 0.__TEXT.__text
0x000049c2 suba.w 0xc, a7
0x000049c6 move.l (a0)+, d0
0x000049c8 move.l d0, (a7)
0x000049ca move.l d0, 0x8004.l
0x000049d0 move.l a0, 0x4(a7)
0x000049d4 move.l a0, 0x8008.l
0x000049da addq.l 0x1, d0
0x000049dc asl.l 0x2, d0
0x000049de adda.l d0, a0
hppa
hppa7100
32
true
;-- section.0.__TEXT.__text:
0x000039e8 ldw 0(sp),r26 ; [00] -r-x section size 10588 named 0.__TEXT.__text
0x000039ec ldo 7f(sp),sp
0x000039f0 ldil L%3800,r1
0x000039f4 be 1fc(sr4,r1)
0x000039f8 depwi 0,31,6,sp
0x000039fc stw rp,-14(sp)
0x00003a00 stw,ma r5,80(sp)
0x00003a04 stw r4,-7c(sp)
0x00003a08 stw r3,-78(sp)
0x00003a0c copy r26,r4
sparc
all
32
true
;-- section.0.__TEXT.__text:
0x0000441c mov sp, o0 ; [00] -r-x section size 7912 named 0.__TEXT.__text
0x00004420 sethi 0x11, o5
0x00004424 or o5, 0x30, o5
0x00004428 jmp o5
0x0000442c nop
0x00004430 save sp, -0x70, sp
0x00004434 add i0, 0x44, o1
0x00004438 sethi 0x20, o2
0x0000443c st o1, [o2+8]
0x00004440 ld [i0+0x40], o0
x86
386
32
false
;-- section.0.__TEXT.__text:
0x00002a24 push ebp ; [00] -r-x section size 6524 named 0.__TEXT.__text
0x00002a25 mov ebp, esp
0x00002a27 push edi
0x00002a28 push esi
0x00002a29 push ebx
0x00002a2a lea esi, dword [ebp+0x04]
0x00002a2d mov edx, dword [esi]
0x00002a2f mov dword [0x6004], edx
0x00002a35 lea eax, dword [esi+0x04]
0x00002a38 mov dword [0x6008], eax
m68k
mc68030
32
true
;-- section.0.__TEXT.__text:
0x000049c0 movea.l a7, a0 ; [00] -r-x section size 6638 named 0.__TEXT.__text
0x000049c2 suba.w 0xc, a7
0x000049c6 move.l (a0)+, d0
0x000049c8 move.l d0, (a7)
0x000049ca move.l d0, 0x8004.l
0x000049d0 move.l a0, 0x4(a7)
0x000049d4 move.l a0, 0x8008.l
0x000049da addq.l 0x1, d0
0x000049dc asl.l 0x2, d0
0x000049de adda.l d0, a0
EOF
EXPECT_ERR=<<EOF
ERROR: unknown thread state structure 11
ERROR: mach0: Cannot parse thread
EOF
RUN
NAME=Switch between same archs, with different bits and machine
FILE=bins/mach0/AppIOSEntitlements.ios
CMDS=<<EOF
obs
echo "# default"
e asm.arch
e asm.bits
e asm.cpu
obs arm_64_all
echo "# arm_64_all"
e asm.arch
e asm.bits
e asm.cpu
obs arm_32_v7
echo "# arm_32_v7"
e asm.arch
e asm.bits
e asm.cpu
EOF
EXPECT=<<EOF
arm_32_v7
arm_64_all
# default
arm
32
v7
# arm_64_all
arm
64
all
# arm_32_v7
arm
32
v7
EOF
EXPECT_ERR=
RUN

View file

@ -181,12 +181,12 @@ iA
iAj
EOF
EXPECT=<<EOF
offset size arch machine
-----------------------------------
0x00001000 13792 x86_64 x86 64 all
0x00005000 13760 x86_32 386
0x00009000 13616 ppc_32 7400
[{"arch":"x86","bits":64,"offset":4096,"size":13792,"machine":"x86 64 all"},{"arch":"x86","bits":32,"offset":20480,"size":13760,"machine":"386"},{"arch":"ppc","bits":32,"offset":36864,"size":13616,"machine":"7400"}]
offset size arch bits machine big_endian
-------------------------------------------------
0x00001000 13792 x86 64 x86 64 all false
0x00005000 13760 x86 32 386 false
0x00009000 13616 ppc 32 7400 true
[{"arch":"x86","bits":64,"big_endian":false,"offset":4096,"size":13792,"machine":"x86 64 all"},{"arch":"x86","bits":32,"big_endian":false,"offset":20480,"size":13760,"machine":"386"},{"arch":"ppc","bits":32,"big_endian":true,"offset":36864,"size":13616,"machine":"7400"}]
EOF
RUN
@ -198,13 +198,13 @@ CMDS=<<EOF
EOF
EXPECT=<<EOF
[Archs]
offset size arch machine
-----------------------------------
0x00001000 13792 x86_64 x86 64 all
0x00005000 13760 x86_32 386
0x00009000 13616 ppc_32 7400
offset size arch bits machine big_endian
-------------------------------------------------
0x00001000 13792 x86 64 x86 64 all false
0x00005000 13760 x86 32 386 false
0x00009000 13616 ppc 32 7400 true
{"archs":[{"arch":"x86","bits":64,"offset":4096,"size":13792,"machine":"x86 64 all"},{"arch":"x86","bits":32,"offset":20480,"size":13760,"machine":"386"},{"arch":"ppc","bits":32,"offset":36864,"size":13616,"machine":"7400"}]}
{"archs":[{"arch":"x86","bits":64,"big_endian":false,"offset":4096,"size":13792,"machine":"x86 64 all"},{"arch":"x86","bits":32,"big_endian":false,"offset":20480,"size":13760,"machine":"386"},{"arch":"ppc","bits":32,"big_endian":true,"offset":36864,"size":13616,"machine":"7400"}]}
EOF
RUN
@ -309,3 +309,19 @@ EXPECT=<<EOF
0x100004090 0x0000000100009338 8....... 4295004984 18.__DATA.__objc_data class SceneDelegate R 0x100009310
EOF
RUN
NAME=M68k, HPPA, Sparc, x86
FILE=bins/mach0/2048-NeXTSTEP
CMDS=<<EOF
iA
EOF
EXPECT=<<EOF
offset size arch bits machine big_endian
------------------------------------------------
0x00002000 49152 m68k 32 mc68030 true
0x0000e000 40960 x86 32 386 false
0x00018000 49152 hppa 32 hppa7100 true
0x00024000 49152 sparc 32 all true
EOF
EXPECT_ERR=
RUN

View file

@ -112,12 +112,12 @@ RUN
NAME=mach0 arm64e legacy chained imports (BIND_OPCODE_THREADED)
FILE=bins/mach0/imports-arm64e-threaded
ARGS=-a arm -b 64
CMDS=<<EOF
obs arm_64_arm64e
ii
ir
pxr 0x10 @ section.13.__DATA.__objc_classrefs
pD 0x10 @ section.13.__DATA.__objc_classrefs
pxr 0x10 @ section.15.__DATA.__objc_classrefs
pD 0x10 @ section.15.__DATA.__objc_classrefs
ic
EOF
EXPECT=<<EOF
@ -157,12 +157,14 @@ nth vaddr bind type lib name
0x100008108 0x00008108 0x100010048 SET_64 NSObject
0x100008110 0x00008110 0x100010040 SET_64 _objc_empty_cache
0x100008120 0x00008120 0x00000000 SET_64
0x1000080c0 0x0000000100008100 ........ @ section.13.__DATA.__objc_classrefs 4295000320 15.__DATA.__objc_data class Stub R 0x1000080d8
0x1000080c8 0x0000000100010030 0....... @ reloc.NSString 4295032880 NSString R 0x0
;-- section.13.__DATA.__objc_classrefs:
0x1000080c0 .qword 0x0000000100008100 ; sym.class_Stub; RELOC 64 ; [13] -rw- section size 16 named 13.__DATA.__objc_classrefs
0x1000080e0 0x0000000100010038 8....... @ reloc.NSObject.1000080e0 4295032888 NSObject R 0x0
0x1000080e8 0x0000000100010040 @....... @ reloc._objc_empty_cache.1000080e8 4295032896 _objc_empty_cache R 0x0
;-- section.15.__DATA.__objc_classrefs:
;-- NSObject:
0x1000080e0 .qword 0x0000000100010038 ; reloc.target.NSObject; RELOC 64 NSObject ; [15] -rw- section size 16 named 15.__DATA.__objc_classrefs
;-- NSString:
0x1000080c8 .qword 0x0000000100010030 ; reloc.target.NSString; RELOC 64 NSString
;-- _objc_empty_cache:
0x1000080e8 .qword 0x0000000100010040 ; reloc.target._objc_empty_cache; RELOC 64 _objc_empty_cache
address min max name super
--------------------------------------------------
0x1000080d8 0x1000080d8 0x1000080d8 Stub NSObject
@ -171,9 +173,9 @@ RUN
NAME=mach0 arm64e chained imports
FILE=bins/mach0/imports-arm64e-chained
ARGS=-a arm -b 64
CMDS=<<EOF
ii
pd 3 @ 0x100003f48
ir
pxr 0x10 @ section.13.__DATA.__objc_classrefs
pD 0x10 @ section.13.__DATA.__objc_classrefs
@ -182,15 +184,19 @@ EOF
EXPECT=<<EOF
nth vaddr bind type lib name
-----------------------------------------------------------------
0 0x100003f20 NONE FUNC objc_alloc
1 0x100003f30 NONE FUNC objc_alloc_init
2 0x100003f40 NONE FUNC objc_autoreleasePoolPop
3 0x100003f50 NONE FUNC objc_autoreleasePoolPush
0 0x100003f30 NONE FUNC objc_alloc
1 0x100003f3c NONE FUNC objc_alloc_init
2 0x100003f48 NONE FUNC objc_autoreleasePoolPop
3 0x100003f54 NONE FUNC objc_autoreleasePoolPush
4 ---------- NONE FUNC objc_msgSend
5 ---------- NONE OBJC_CLASS NSString
6 ---------- NONE FUNC _objc_empty_cache
7 ---------- NONE OBJC_METACLASS NSObject
8 ---------- NONE OBJC_CLASS NSObject
;-- objc_autoreleasePoolPop:
0x100003f48 adrp x16, reloc.objc_alloc ; 0x100004000
0x100003f4c ldr x16, [x16, 0x10] ; [0x10:4]=0x400000
0x100003f50 br x16
vaddr paddr target type name
-------------------------------------------------------------------
0x100004000 0x00004000 0x100010008 SET_64 objc_alloc

View file

@ -5,6 +5,5 @@ EOF
EXPECT_ERR=<<EOF
ERROR: malformed uleb128
ERROR: malformed uleb128
ERROR: Invalid size for a load command
EOF
RUN

View file

@ -1272,3 +1272,55 @@ paddr vaddr len size section type string
EOF
EXPECT_ERR=
RUN
NAME=fat binary - endianness
FILE=bins/mach0/2048-NeXTSTEP
CMDS=!rz-bin -I -A ${RZ_FILE}
EXPECT=<<EOF
[Archs]
offset size arch bits machine big_endian
------------------------------------------------
0x00002000 49152 m68k 32 mc68030 true
0x0000e000 40960 x86 32 386 false
0x00018000 49152 hppa 32 hppa7100 true
0x00024000 49152 sparc 32 all true
[Info]
arch m68k
cpu mc68030
features N/A
baddr 0x00002000
binsz 0x0000e000
bintype mach0
bits 32
class MACH0
compiler N/A
dbg_file N/A
endian BE
hdr.csum N/A
guid N/A
intrp N/A
laddr 0x00000000
lang c
machine mc68030
minopsz 1
os darwin
cc N/A
rpath N/A
subsys unknown
stripped false
crypto false
havecode true
va true
sanitiz false
static true
linenum false
lsyms false
canary false
PIE false
RELROCS false
NX false
EOF
EXPECT_ERR=
RUN