Rizin
unix-like reverse engineering framework and cli tools
mach0.c File Reference
#include <stdio.h>
#include <rz_types.h>
#include <rz_util.h>
#include "mach0.h"
#include <rz_hash.h>
#include "mach0_utils.inc"

Go to the source code of this file.

Classes

struct  RSymCtx
 
struct  RTrieState
 

Macros

#define bprintf
 
#define Eprintf
 
#define mach0_endian   1
 
#define Error(x)
 
#define READFIELD(x)   cscd.x = rz_read_ble32(p + rz_offsetof(CS_CodeDirectory, x), 1)
 
#define READFIELD8(x)   cscd.x = p[rz_offsetof(CS_CodeDirectory, x)]
 
#define READWORD()
 

Typedefs

typedef void(* RExportsIterator) (struct MACH0_(obj_t) *bin, const char *name, ut64 flags, ut64 offset, void *ctx)
 

Functions

static ut64 entry_to_vaddr (struct MACH0_(obj_t) *bin)
 
RZ_API ut64 MACH0_() vaddr_to_paddr (struct MACH0_(obj_t) *bin, ut64 addr)
 
RZ_API ut64 MACH0_() paddr_to_vaddr (struct MACH0_(obj_t) *bin, ut64 offset)
 
static ut64 pa2va (RzBinFile *bf, ut64 offset)
 
static void init_sdb_formats (struct MACH0_(obj_t) *bin)
 
static bool init_hdr (struct MACH0_(obj_t) *bin)
 
static bool parse_segments (struct MACH0_(obj_t) *bin, ut64 off)
 
static bool parse_symtab (struct MACH0_(obj_t) *mo, ut64 off)
 
static bool parse_dysymtab (struct MACH0_(obj_t) *bin, ut64 off)
 
static char * readString (ut8 *p, int off, int len)
 
static void parseCodeDirectory (struct MACH0_(obj_t) *mo, RzBuffer *b, int offset, int datasize)
 
static bool parse_signature (struct MACH0_(obj_t) *bin, ut64 off)
 
static int parse_thread (struct MACH0_(obj_t) *bin, struct load_command *lc, ut64 off, bool is_first_thread)
 
static int parse_function_starts (struct MACH0_(obj_t) *bin, ut64 off)
 
static int parse_dylib (struct MACH0_(obj_t) *bin, ut64 off)
 
static const char * cmd_to_string (ut32 cmd)
 
static const char * cmd_to_pf_definition (ut32 cmd)
 
static const char * build_version_platform_to_string (ut32 platform)
 
static const char * build_version_tool_to_string (ut32 tool)
 
static bool parse_chained_fixups (struct MACH0_(obj_t) *bin, ut32 offset, ut32 size)
 
static bool reconstruct_chained_fixup (struct MACH0_(obj_t) *bin)
 
static int init_items (struct MACH0_(obj_t) *bin)
 
static bool init (struct MACH0_(obj_t) *mo)
 
void *MACH0_() mach0_free (struct MACH0_(obj_t) *mo)
 
void MACH0_() opts_set_default (struct MACH0_(opts_t) *options, RzBinFile *bf)
 
struct MACH0_ (obj_t)
 
static int prot2perm (int x)
 
static bool __isDataSection (RzBinSection *sect)
 
RzList *MACH0_() get_virtual_files (RzBinFile *bf)
 
RzList *MACH0_() get_maps_unpatched (RzBinFile *bf)
 
RzList *MACH0_() get_maps (RzBinFile *bf)
 
RzList *MACH0_() get_segments (RzBinFile *bf)
 
char *MACH0_() section_type_to_string (ut64 type)
 
RzList *MACH0_() section_flag_to_rzlist (ut64 flag)
 
struct section_t *MACH0_() get_sections (struct MACH0_(obj_t) *bin)
 
static bool parse_import_stub (struct MACH0_(obj_t) *bin, struct symbol_t *symbol, int idx)
 
static int inSymtab (HtPP *hash, const char *name, ut64 addr)
 
RZ_API RZ_OWN char *MACH0_() get_name (struct MACH0_(obj_t) *mo, ut32 stridx, bool filter)
 Get a string from the string table referenced by the LC_SYMTAB command. More...
 
static int walk_exports (struct MACH0_(obj_t) *bin, RExportsIterator iterator, void *ctx)
 
static void fill_exports_list (struct MACH0_(obj_t) *bin, const char *name, ut64 flags, ut64 offset, void *ctx)
 
const RzList *MACH0_() get_symbols_list (struct MACH0_(obj_t) *bin)
 
static void assign_export_symbol_t (struct MACH0_(obj_t) *bin, const char *name, ut64 flags, ut64 offset, void *ctx)
 
const struct symbol_t *MACH0_() get_symbols (struct MACH0_(obj_t) *bin)
 
struct import_t *MACH0_() get_imports (struct MACH0_(obj_t) *bin)
 
struct addr_t *MACH0_() get_entrypoint (struct MACH0_(obj_t) *bin)
 
void MACH0_() kv_loadlibs (struct MACH0_(obj_t) *bin)
 
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)
 
int MACH0_() get_bits_from_hdr (struct MACH0_(mach_header) *hdr)
 
bool MACH0_() is_big_endian (struct MACH0_(obj_t) *bin)
 
const char *MACH0_() get_intrp (struct MACH0_(obj_t) *bin)
 
const char *MACH0_() get_os (struct MACH0_(obj_t) *bin)
 
const char *MACH0_() get_cputype_from_hdr (struct MACH0_(mach_header) *hdr)
 
const char *MACH0_() get_cputype (struct MACH0_(obj_t) *bin)
 
static const char * cpusubtype_tostring (ut32 cputype, ut32 cpusubtype)
 
char *MACH0_() get_cpusubtype_from_hdr (struct MACH0_(mach_header) *hdr)
 
char *MACH0_() get_cpusubtype (struct MACH0_(obj_t) *bin)
 
bool MACH0_() is_pie (struct MACH0_(obj_t) *bin)
 
bool MACH0_() has_nx (struct MACH0_(obj_t) *bin)
 
char *MACH0_() get_filetype_from_hdr (struct MACH0_(mach_header) *hdr)
 
char *MACH0_() get_filetype (struct MACH0_(obj_t) *bin)
 
ut64 MACH0_() get_main (struct MACH0_(obj_t) *bin)
 
void MACH0_() mach_headerfields (RzBinFile *bf)
 
RzList *MACH0_() mach_fields (RzBinFile *bf)
 
struct MACH0_ (mach_header)
 

Macro Definition Documentation

◆ bprintf

#define bprintf
Value:
if (bin->options.verbose) \
eprintf
Definition: malloc.c:26

Definition at line 14 of file mach0.c.

◆ Eprintf

#define Eprintf
Value:
if (mo->options.verbose) \
eprintf

Definition at line 17 of file mach0.c.

◆ Error

#define Error (   x)
Value:
error_message = x; \
goto error;
int x
Definition: mipsasm.c:20
void error(const char *msg)
Definition: untgz.c:593

Definition at line 439 of file mach0.c.

◆ mach0_endian

#define mach0_endian   1

Definition at line 39 of file mach0.c.

◆ READFIELD

#define READFIELD (   x)    cscd.x = rz_read_ble32(p + rz_offsetof(CS_CodeDirectory, x), 1)

◆ READFIELD8

#define READFIELD8 (   x)    cscd.x = p[rz_offsetof(CS_CodeDirectory, x)]

◆ READWORD

#define READWORD ( )
Value:
if (rz_buf_read_at(buf, addr, (ut8 *)wordbuf, 4) != 4) { \
eprintf("Invalid address in buffer."); \
break; \
} \
addr += 4; \
pvaddr += 4; \
word = isBe ? rz_read_be32(wordbuf) : rz_read_le32(wordbuf);
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
static ut32 rz_read_le32(const void *src)
Definition: rz_endian.h:239
static ut32 rz_read_be32(const void *src)
Definition: rz_endian.h:87
static int addr
Definition: z80asm.c:58

Typedef Documentation

◆ RExportsIterator

typedef void(* RExportsIterator) (struct MACH0_(obj_t) *bin, const char *name, ut64 flags, ut64 offset, void *ctx)

Definition at line 28 of file mach0.c.

Function Documentation

◆ __isDataSection()

static bool __isDataSection ( RzBinSection sect)
static

Definition at line 2146 of file mach0.c.

2146  {
2147  if (strstr(sect->name, "_cstring")) {
2148  return true;
2149  }
2150  if (strstr(sect->name, "_objc_methname")) {
2151  return true;
2152  }
2153  if (strstr(sect->name, "_objc_classname")) {
2154  return true;
2155  }
2156  if (strstr(sect->name, "_objc_methtype")) {
2157  return true;
2158  }
2159  return false;
2160 }
char * name
Definition: rz_bin.h:619

References rz_bin_section_t::name.

Referenced by get_segments().

◆ assign_export_symbol_t()

static void assign_export_symbol_t ( struct MACH0_(obj_t) *  bin,
const char *  name,
ut64  flags,
ut64  offset,
void *  ctx 
)
static

Definition at line 2943 of file mach0.c.

2943  {
2944  RSymCtx *sym_ctx = (RSymCtx *)ctx;
2945  int j = sym_ctx->j;
2946  if (j < sym_ctx->symbols_count) {
2947  sym_ctx->symbols[j].offset = offset;
2948  sym_ctx->symbols[j].addr = MACH0_(paddr_to_vaddr)(bin, offset);
2949  if (inSymtab(sym_ctx->hash, name, sym_ctx->symbols[j].addr)) {
2950  return;
2951  }
2952  sym_ctx->symbols[j].size = 0;
2954  sym_ctx->symbols[j].name = strdup(name);
2955  sym_ctx->j++;
2956  }
2957 }
voidpf uLong offset
Definition: ioapi.h:144
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RZ_API ut64 MACH0_() paddr_to_vaddr(struct MACH0_(obj_t) *bin, ut64 offset)
Definition: mach0.c:67
struct MACH0_(obj_t)
Definition: mach0.c:2111
static int inSymtab(HtPP *hash, const char *name, ut64 addr)
Definition: mach0.c:2545
#define RZ_BIN_MACH0_SYMBOL_TYPE_EXT
Definition: mach0_specs.h:25
Definition: mach0.c:21
struct symbol_t * symbols
Definition: mach0.c:22
int j
Definition: mach0.c:23
HtPP * hash
Definition: mach0.c:25
Definition: z80asm.h:102
ut64 size
Definition: mach0.h:57
ut64 addr
Definition: mach0.h:56
ut64 offset
Definition: mach0.h:55
int type
Definition: mach0.h:59
char * name
Definition: mach0.h:61

References symbol_t::addr, RSymCtx::hash, inSymtab(), RSymCtx::j, MACH0_(), symbol_t::name, symbol_t::offset, paddr_to_vaddr(), RZ_BIN_MACH0_SYMBOL_TYPE_EXT, symbol_t::size, strdup(), RSymCtx::symbols, and symbol_t::type.

Referenced by get_symbols().

◆ build_version_platform_to_string()

static const char* build_version_platform_to_string ( ut32  platform)
static

Definition at line 1436 of file mach0.c.

1436  {
1437  switch (platform) {
1438  case 1:
1439  return "macOS";
1440  case 2:
1441  return "iOS";
1442  case 3:
1443  return "tvOS";
1444  case 4:
1445  return "watchOS";
1446  case 5:
1447  return "bridgeOS";
1448  case 6:
1449  return "iOSmac";
1450  case 7:
1451  return "iOS Simulator";
1452  case 8:
1453  return "tvOS Simulator";
1454  case 9:
1455  return "watchOS Simulator";
1456  default:
1457  return "unknown";
1458  }
1459 }

Referenced by mach_headerfields().

◆ build_version_tool_to_string()

static const char* build_version_tool_to_string ( ut32  tool)
static

Definition at line 1461 of file mach0.c.

1461  {
1462  switch (tool) {
1463  case 1:
1464  return "clang";
1465  case 2:
1466  return "swift";
1467  case 3:
1468  return "ld";
1469  default:
1470  return "unknown";
1471  }
1472 }

Referenced by mach_headerfields().

◆ cmd_to_pf_definition()

static const char* cmd_to_pf_definition ( ut32  cmd)
static

Definition at line 1336 of file mach0.c.

1336  {
1337  switch (cmd) {
1338  case LC_BUILD_VERSION:
1339  return "mach0_build_version_command";
1340  case LC_CODE_SIGNATURE:
1341  return "mach0_code_signature_command";
1342  case LC_DATA_IN_CODE:
1343  return "mach0_data_in_code_command";
1344  case LC_DYLD_INFO:
1345  case LC_DYLD_INFO_ONLY:
1346  return "mach0_dyld_info_only_command";
1347  case LC_DYLD_ENVIRONMENT:
1348  return NULL;
1350  return NULL;
1351  case LC_DYSYMTAB:
1352  return "mach0_dysymtab_command";
1353  case LC_ENCRYPTION_INFO:
1354  return "mach0_encryption_info_command";
1355  case LC_ENCRYPTION_INFO_64:
1356  return "mach0_encryption_info64_command";
1357  case LC_FUNCTION_STARTS:
1358  return "mach0_function_starts_command";
1359  case LC_FVMFILE:
1360  return NULL;
1361  case LC_ID_DYLIB:
1362  return "mach0_id_dylib_command";
1363  case LC_ID_DYLINKER:
1364  return "mach0_id_dylinker_command";
1365  case LC_IDENT:
1366  return NULL;
1367  case LC_IDFVMLIB:
1368  return NULL;
1369  case LC_LINKER_OPTION:
1370  return NULL;
1372  return NULL;
1373  case LC_LOAD_DYLINKER:
1374  return "mach0_load_dylinker_command";
1375  case LC_LAZY_LOAD_DYLIB:
1376  case LC_LOAD_WEAK_DYLIB:
1377  case LC_LOAD_DYLIB:
1378  return "mach0_dylib_command";
1379  case LC_LOADFVMLIB:
1380  return NULL;
1381  case LC_MAIN:
1382  return "mach0_entry_point_command";
1383  case LC_NOTE:
1384  return NULL;
1385  case LC_PREBIND_CKSUM:
1386  return NULL;
1387  case LC_PREBOUND_DYLIB:
1388  return NULL;
1389  case LC_PREPAGE:
1390  return NULL;
1391  case LC_REEXPORT_DYLIB:
1392  return NULL;
1393  case LC_ROUTINES:
1394  return NULL;
1395  case LC_ROUTINES_64:
1396  return NULL;
1397  case LC_RPATH:
1398  return "mach0_rpath_command";
1399  case LC_SEGMENT:
1400  return "mach0_segment";
1401  case LC_SEGMENT_64:
1402  return "mach0_segment64";
1403  case LC_SEGMENT_SPLIT_INFO:
1404  return "mach0_segment_split_info_command";
1405  case LC_SOURCE_VERSION:
1406  return "mach0_source_version_command";
1407  case LC_SUB_FRAMEWORK:
1408  return NULL;
1409  case LC_SUB_UMBRELLA:
1410  return NULL;
1411  case LC_SUB_CLIENT:
1412  return NULL;
1413  case LC_SUB_LIBRARY:
1414  return NULL;
1415  case LC_SYMTAB:
1416  return "mach0_symtab_command";
1417  case LC_SYMSEG:
1418  return NULL;
1419  case LC_TWOLEVEL_HINTS:
1420  return NULL;
1421  case LC_UUID:
1422  return "mach0_uuid_command";
1423  case LC_VERSION_MIN_MACOSX:
1425  case LC_VERSION_MIN_TVOS:
1427  return "mach0_version_min_command";
1428  case LC_THREAD:
1429  return NULL;
1430  case LC_UNIXTHREAD:
1431  return "mach0_unixthread_command";
1432  }
1433  return NULL;
1434 }
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
Definition: sflib.h:79
@ LC_FVMFILE
@ LC_DYSYMTAB
@ LC_SEGMENT
@ LC_VERSION_MIN_IPHONEOS
@ LC_IDENT
@ LC_NOTE
@ LC_ROUTINES
@ LC_LOAD_WEAK_DYLIB
@ LC_ID_DYLINKER
@ LC_MAIN
@ LC_THREAD
@ LC_DYLD_INFO
@ LC_DYLD_INFO_ONLY
@ LC_DYLIB_CODE_SIGN_DRS
@ LC_SUB_CLIENT
@ LC_PREBOUND_DYLIB
@ LC_ENCRYPTION_INFO_64
@ LC_BUILD_VERSION
@ LC_LOADFVMLIB
@ LC_DATA_IN_CODE
@ LC_RPATH
@ LC_VERSION_MIN_WATCHOS
@ LC_UNIXTHREAD
@ LC_SUB_UMBRELLA
@ LC_LOAD_DYLIB
@ LC_SYMTAB
@ LC_TWOLEVEL_HINTS
@ LC_LAZY_LOAD_DYLIB
@ LC_ENCRYPTION_INFO
@ LC_SUB_FRAMEWORK
@ LC_ID_DYLIB
@ LC_PREPAGE
@ LC_PREBIND_CKSUM
@ LC_SUB_LIBRARY
@ LC_LOAD_DYLINKER
@ LC_FUNCTION_STARTS
@ LC_SOURCE_VERSION
@ LC_LINKER_OPTIMIZATION_HINT
@ LC_SEGMENT_64
@ LC_VERSION_MIN_TVOS
@ LC_ROUTINES_64
@ LC_SYMSEG
@ LC_IDFVMLIB
@ LC_VERSION_MIN_MACOSX
@ LC_SEGMENT_SPLIT_INFO
@ LC_DYLD_ENVIRONMENT
@ LC_UUID
@ LC_LINKER_OPTION
@ LC_CODE_SIGNATURE
@ LC_REEXPORT_DYLIB

References cmd, LC_BUILD_VERSION, LC_CODE_SIGNATURE, LC_DATA_IN_CODE, LC_DYLD_ENVIRONMENT, LC_DYLD_INFO, LC_DYLD_INFO_ONLY, LC_DYLIB_CODE_SIGN_DRS, LC_DYSYMTAB, LC_ENCRYPTION_INFO, LC_ENCRYPTION_INFO_64, LC_FUNCTION_STARTS, LC_FVMFILE, LC_ID_DYLIB, LC_ID_DYLINKER, LC_IDENT, LC_IDFVMLIB, LC_LAZY_LOAD_DYLIB, LC_LINKER_OPTIMIZATION_HINT, LC_LINKER_OPTION, LC_LOAD_DYLIB, LC_LOAD_DYLINKER, LC_LOAD_WEAK_DYLIB, LC_LOADFVMLIB, LC_MAIN, LC_NOTE, LC_PREBIND_CKSUM, LC_PREBOUND_DYLIB, LC_PREPAGE, LC_REEXPORT_DYLIB, LC_ROUTINES, LC_ROUTINES_64, LC_RPATH, LC_SEGMENT, LC_SEGMENT_64, LC_SEGMENT_SPLIT_INFO, LC_SOURCE_VERSION, LC_SUB_CLIENT, LC_SUB_FRAMEWORK, LC_SUB_LIBRARY, LC_SUB_UMBRELLA, LC_SYMSEG, LC_SYMTAB, LC_THREAD, LC_TWOLEVEL_HINTS, LC_UNIXTHREAD, LC_UUID, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_TVOS, LC_VERSION_MIN_WATCHOS, and NULL.

Referenced by init_items(), MACH0_(), and mach_headerfields().

◆ cmd_to_string()

static const char* cmd_to_string ( ut32  cmd)
static

Definition at line 1230 of file mach0.c.

1230  {
1231  switch (cmd) {
1232  case LC_DATA_IN_CODE:
1233  return "LC_DATA_IN_CODE";
1234  case LC_CODE_SIGNATURE:
1235  return "LC_CODE_SIGNATURE";
1236  case LC_RPATH:
1237  return "LC_RPATH";
1238  case LC_TWOLEVEL_HINTS:
1239  return "LC_TWOLEVEL_HINTS";
1240  case LC_PREBIND_CKSUM:
1241  return "LC_PREBIND_CKSUM";
1242  case LC_SEGMENT:
1243  return "LC_SEGMENT";
1244  case LC_SEGMENT_64:
1245  return "LC_SEGMENT_64";
1246  case LC_SYMTAB:
1247  return "LC_SYMTAB";
1248  case LC_SYMSEG:
1249  return "LC_SYMSEG";
1250  case LC_DYSYMTAB:
1251  return "LC_DYSYMTAB";
1252  case LC_PREBOUND_DYLIB:
1253  return "LC_PREBOUND_DYLIB";
1254  case LC_ROUTINES:
1255  return "LC_ROUTINES";
1256  case LC_ROUTINES_64:
1257  return "LC_ROUTINES_64";
1258  case LC_SUB_FRAMEWORK:
1259  return "LC_SUB_FRAMEWORK";
1260  case LC_SUB_UMBRELLA:
1261  return "LC_SUB_UMBRELLA";
1262  case LC_SUB_CLIENT:
1263  return "LC_SUB_CLIENT";
1264  case LC_SUB_LIBRARY:
1265  return "LC_SUB_LIBRARY";
1266  case LC_FUNCTION_STARTS:
1267  return "LC_FUNCTION_STARTS";
1269  return "LC_DYLIB_CODE_SIGN_DRS";
1270  case LC_NOTE:
1271  return "LC_NOTE";
1272  case LC_BUILD_VERSION:
1273  return "LC_BUILD_VERSION";
1274  case LC_VERSION_MIN_MACOSX:
1275  return "LC_VERSION_MIN_MACOSX";
1277  return "LC_VERSION_MIN_IPHONEOS";
1278  case LC_VERSION_MIN_TVOS:
1279  return "LC_VERSION_MIN_TVOS";
1281  return "LC_VERSION_MIN_WATCHOS";
1282  case LC_DYLD_INFO:
1283  return "LC_DYLD_INFO";
1284  case LC_DYLD_INFO_ONLY:
1285  return "LC_DYLD_INFO_ONLY";
1286  case LC_DYLD_ENVIRONMENT:
1287  return "LC_DYLD_ENVIRONMENT";
1288  case LC_SOURCE_VERSION:
1289  return "LC_SOURCE_VERSION";
1290  case LC_MAIN:
1291  return "LC_MAIN";
1292  case LC_UUID:
1293  return "LC_UUID";
1294  case LC_ID_DYLIB:
1295  return "LC_ID_DYLIB";
1296  case LC_ID_DYLINKER:
1297  return "LC_ID_DYLINKER";
1298  case LC_LAZY_LOAD_DYLIB:
1299  return "LC_LAZY_LOAD_DYLIB";
1300  case LC_ENCRYPTION_INFO:
1301  return "LC_ENCRYPTION_INFO";
1302  case LC_ENCRYPTION_INFO_64:
1303  return "LC_ENCRYPTION_INFO_64";
1304  case LC_SEGMENT_SPLIT_INFO:
1305  return "LC_SEGMENT_SPLIT_INFO";
1306  case LC_REEXPORT_DYLIB:
1307  return "LC_REEXPORT_DYLIB";
1308  case LC_LINKER_OPTION:
1309  return "LC_LINKER_OPTION";
1311  return "LC_LINKER_OPTIMIZATION_HINT";
1312  case LC_LOAD_DYLINKER:
1313  return "LC_LOAD_DYLINKER";
1314  case LC_LOAD_DYLIB:
1315  return "LC_LOAD_DYLIB";
1316  case LC_LOAD_WEAK_DYLIB:
1317  return "LC_LOAD_WEAK_DYLIB";
1318  case LC_THREAD:
1319  return "LC_THREAD";
1320  case LC_UNIXTHREAD:
1321  return "LC_UNIXTHREAD";
1322  case LC_LOADFVMLIB:
1323  return "LC_LOADFVMLIB";
1324  case LC_IDFVMLIB:
1325  return "LC_IDFVMLIB";
1326  case LC_IDENT:
1327  return "LC_IDENT";
1328  case LC_FVMFILE:
1329  return "LC_FVMFILE";
1330  case LC_PREPAGE:
1331  return "LC_PREPAGE";
1332  }
1333  return "";
1334 }

References cmd, LC_BUILD_VERSION, LC_CODE_SIGNATURE, LC_DATA_IN_CODE, LC_DYLD_ENVIRONMENT, LC_DYLD_INFO, LC_DYLD_INFO_ONLY, LC_DYLIB_CODE_SIGN_DRS, LC_DYSYMTAB, LC_ENCRYPTION_INFO, LC_ENCRYPTION_INFO_64, LC_FUNCTION_STARTS, LC_FVMFILE, LC_ID_DYLIB, LC_ID_DYLINKER, LC_IDENT, LC_IDFVMLIB, LC_LAZY_LOAD_DYLIB, LC_LINKER_OPTIMIZATION_HINT, LC_LINKER_OPTION, LC_LOAD_DYLIB, LC_LOAD_DYLINKER, LC_LOAD_WEAK_DYLIB, LC_LOADFVMLIB, LC_MAIN, LC_NOTE, LC_PREBIND_CKSUM, LC_PREBOUND_DYLIB, LC_PREPAGE, LC_REEXPORT_DYLIB, LC_ROUTINES, LC_ROUTINES_64, LC_RPATH, LC_SEGMENT, LC_SEGMENT_64, LC_SEGMENT_SPLIT_INFO, LC_SOURCE_VERSION, LC_SUB_CLIENT, LC_SUB_FRAMEWORK, LC_SUB_LIBRARY, LC_SUB_UMBRELLA, LC_SYMSEG, LC_SYMTAB, LC_THREAD, LC_TWOLEVEL_HINTS, LC_UNIXTHREAD, LC_UUID, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_TVOS, and LC_VERSION_MIN_WATCHOS.

Referenced by MACH0_(), and mach_headerfields().

◆ cpusubtype_tostring()

static const char* cpusubtype_tostring ( ut32  cputype,
ut32  cpusubtype 
)
static

Definition at line 3387 of file mach0.c.

3387  {
3388  switch (cputype) {
3389  case CPU_TYPE_VAX:
3390  switch (cpusubtype) {
3391  case CPU_SUBTYPE_VAX_ALL: return "all";
3392  case CPU_SUBTYPE_VAX780: return "vax780";
3393  case CPU_SUBTYPE_VAX785: return "vax785";
3394  case CPU_SUBTYPE_VAX750: return "vax750";
3395  case CPU_SUBTYPE_VAX730: return "vax730";
3396  case CPU_SUBTYPE_UVAXI: return "uvaxI";
3397  case CPU_SUBTYPE_UVAXII: return "uvaxII";
3398  case CPU_SUBTYPE_VAX8200: return "vax8200";
3399  case CPU_SUBTYPE_VAX8500: return "vax8500";
3400  case CPU_SUBTYPE_VAX8600: return "vax8600";
3401  case CPU_SUBTYPE_VAX8650: return "vax8650";
3402  case CPU_SUBTYPE_VAX8800: return "vax8800";
3403  case CPU_SUBTYPE_UVAXIII: return "uvaxIII";
3404  default: return "Unknown vax subtype";
3405  }
3406  case CPU_TYPE_MC680x0:
3407  switch (cpusubtype) {
3408  case CPU_SUBTYPE_MC68030: return "mc68030";
3409  case CPU_SUBTYPE_MC68040: return "mc68040";
3410  case CPU_SUBTYPE_MC68030_ONLY: return "mc68030 only";
3411  default: return "Unknown mc680x0 subtype";
3412  }
3413  case CPU_TYPE_I386:
3414  switch (cpusubtype) {
3415  case CPU_SUBTYPE_386: return "386";
3416  case CPU_SUBTYPE_486: return "486";
3417  case CPU_SUBTYPE_486SX: return "486sx";
3418  case CPU_SUBTYPE_PENT: return "Pentium";
3419  case CPU_SUBTYPE_PENTPRO: return "Pentium Pro";
3420  case CPU_SUBTYPE_PENTII_M3: return "Pentium 3 M3";
3421  case CPU_SUBTYPE_PENTII_M5: return "Pentium 3 M5";
3422  case CPU_SUBTYPE_CELERON: return "Celeron";
3423  case CPU_SUBTYPE_CELERON_MOBILE: return "Celeron Mobile";
3424  case CPU_SUBTYPE_PENTIUM_3: return "Pentium 3";
3425  case CPU_SUBTYPE_PENTIUM_3_M: return "Pentium 3 M";
3426  case CPU_SUBTYPE_PENTIUM_3_XEON: return "Pentium 3 Xeon";
3427  case CPU_SUBTYPE_PENTIUM_M: return "Pentium Mobile";
3428  case CPU_SUBTYPE_PENTIUM_4: return "Pentium 4";
3429  case CPU_SUBTYPE_PENTIUM_4_M: return "Pentium 4 M";
3430  case CPU_SUBTYPE_ITANIUM: return "Itanium";
3431  case CPU_SUBTYPE_ITANIUM_2: return "Itanium 2";
3432  case CPU_SUBTYPE_XEON: return "Xeon";
3433  case CPU_SUBTYPE_XEON_MP: return "Xeon MP";
3434  default: return "Unknown i386 subtype";
3435  }
3436  case CPU_TYPE_X86_64:
3437  switch (cpusubtype & 0xff) {
3438  case CPU_SUBTYPE_X86_64_ALL: return "x86 64 all";
3439  case CPU_SUBTYPE_X86_ARCH1: return "x86 arch 1";
3440  default: return "Unknown x86 subtype";
3441  }
3442  case CPU_TYPE_MC88000:
3443  switch (cpusubtype & 0xff) {
3444  case CPU_SUBTYPE_MC88000_ALL: return "all";
3445  case CPU_SUBTYPE_MC88100: return "mc88100";
3446  case CPU_SUBTYPE_MC88110: return "mc88110";
3447  default: return "Unknown mc88000 subtype";
3448  }
3449  case CPU_TYPE_MC98000:
3450  switch (cpusubtype & 0xff) {
3451  case CPU_SUBTYPE_MC98000_ALL: return "all";
3452  case CPU_SUBTYPE_MC98601: return "mc98601";
3453  default: return "Unknown mc98000 subtype";
3454  }
3455  case CPU_TYPE_HPPA:
3456  switch (cpusubtype & 0xff) {
3457  case CPU_SUBTYPE_HPPA_7100: return "hppa7100";
3458  case CPU_SUBTYPE_HPPA_7100LC: return "hppa7100LC";
3459  default: return "Unknown hppa subtype";
3460  }
3461  case CPU_TYPE_ARM64:
3462  switch (cpusubtype & 0xff) {
3463  case CPU_SUBTYPE_ARM64_ALL: return "all";
3464  case CPU_SUBTYPE_ARM64_V8: return "arm64v8";
3465  case CPU_SUBTYPE_ARM64E: return "arm64e";
3466  default: return "Unknown arm64 subtype";
3467  }
3468  case CPU_TYPE_ARM:
3469  switch (cpusubtype & 0xff) {
3470  case CPU_SUBTYPE_ARM_ALL:
3471  return "all";
3472  case CPU_SUBTYPE_ARM_V4T:
3473  return "v4t";
3474  case CPU_SUBTYPE_ARM_V5:
3475  return "v5";
3476  case CPU_SUBTYPE_ARM_V6:
3477  return "v6";
3479  return "xscale";
3480  case CPU_SUBTYPE_ARM_V7:
3481  return "v7";
3482  case CPU_SUBTYPE_ARM_V7F:
3483  return "v7f";
3484  case CPU_SUBTYPE_ARM_V7S:
3485  return "v7s";
3486  case CPU_SUBTYPE_ARM_V7K:
3487  return "v7k";
3488  case CPU_SUBTYPE_ARM_V7M:
3489  return "v7m";
3490  case CPU_SUBTYPE_ARM_V7EM:
3491  return "v7em";
3492  default:
3493  eprintf("Unknown arm subtype %d\n", cpusubtype & 0xff);
3494  return "unknown arm subtype";
3495  }
3496  case CPU_TYPE_SPARC:
3497  switch (cpusubtype & 0xff) {
3498  case CPU_SUBTYPE_SPARC_ALL: return "all";
3499  default: return "Unknown sparc subtype";
3500  }
3501  case CPU_TYPE_MIPS:
3502  switch (cpusubtype & 0xff) {
3503  case CPU_SUBTYPE_MIPS_ALL: return "all";
3504  case CPU_SUBTYPE_MIPS_R2300: return "r2300";
3505  case CPU_SUBTYPE_MIPS_R2600: return "r2600";
3506  case CPU_SUBTYPE_MIPS_R2800: return "r2800";
3507  case CPU_SUBTYPE_MIPS_R2000a: return "r2000a";
3508  case CPU_SUBTYPE_MIPS_R2000: return "r2000";
3509  case CPU_SUBTYPE_MIPS_R3000a: return "r3000a";
3510  case CPU_SUBTYPE_MIPS_R3000: return "r3000";
3511  default: return "Unknown mips subtype";
3512  }
3513  case CPU_TYPE_I860:
3514  switch (cpusubtype & 0xff) {
3515  case CPU_SUBTYPE_I860_ALL: return "all";
3516  case CPU_SUBTYPE_I860_860: return "860";
3517  default: return "Unknown i860 subtype";
3518  }
3519  case CPU_TYPE_POWERPC:
3520  case CPU_TYPE_POWERPC64:
3521  switch (cpusubtype & 0xff) {
3522  case CPU_SUBTYPE_POWERPC_ALL: return "all";
3523  case CPU_SUBTYPE_POWERPC_601: return "601";
3524  case CPU_SUBTYPE_POWERPC_602: return "602";
3525  case CPU_SUBTYPE_POWERPC_603: return "603";
3526  case CPU_SUBTYPE_POWERPC_603e: return "603e";
3527  case CPU_SUBTYPE_POWERPC_603ev: return "603ev";
3528  case CPU_SUBTYPE_POWERPC_604: return "604";
3529  case CPU_SUBTYPE_POWERPC_604e: return "604e";
3530  case CPU_SUBTYPE_POWERPC_620: return "620";
3531  case CPU_SUBTYPE_POWERPC_750: return "750";
3532  case CPU_SUBTYPE_POWERPC_7400: return "7400";
3533  case CPU_SUBTYPE_POWERPC_7450: return "7450";
3534  case CPU_SUBTYPE_POWERPC_970: return "970";
3535  default: return "Unknown ppc subtype";
3536  }
3537  }
3538  return "Unknown cputype";
3539 }
@ CPU_SUBTYPE_ARM64_V8
@ CPU_SUBTYPE_ARM64E
@ CPU_SUBTYPE_ARM64_ALL
@ CPU_SUBTYPE_SPARC_ALL
@ CPU_SUBTYPE_ARM_XSCALE
@ CPU_SUBTYPE_ARM_V7
@ CPU_SUBTYPE_ARM_V5
@ CPU_SUBTYPE_ARM_V7M
@ CPU_SUBTYPE_ARM_V7K
@ CPU_SUBTYPE_ARM_V7EM
@ CPU_SUBTYPE_ARM_V7F
@ CPU_SUBTYPE_ARM_V4T
@ CPU_SUBTYPE_ARM_ALL
@ CPU_SUBTYPE_ARM_V7S
@ CPU_SUBTYPE_ARM_V6
@ CPU_SUBTYPE_MC68030
@ CPU_SUBTYPE_MC68030_ONLY
@ CPU_SUBTYPE_MC68040
@ CPU_SUBTYPE_HPPA_7100
@ CPU_SUBTYPE_HPPA_7100LC
@ CPU_SUBTYPE_MC88000_ALL
@ CPU_SUBTYPE_MC88100
@ CPU_SUBTYPE_MC88110
@ CPU_SUBTYPE_PENTIUM_M
@ CPU_SUBTYPE_X86_64_ALL
@ CPU_SUBTYPE_ITANIUM
@ CPU_SUBTYPE_PENTIUM_3
@ CPU_SUBTYPE_PENT
@ CPU_SUBTYPE_PENTIUM_3_XEON
@ CPU_SUBTYPE_PENTII_M3
@ CPU_SUBTYPE_PENTIUM_3_M
@ CPU_SUBTYPE_PENTII_M5
@ CPU_SUBTYPE_486
@ CPU_SUBTYPE_PENTIUM_4_M
@ CPU_SUBTYPE_X86_ARCH1
@ CPU_SUBTYPE_CELERON
@ CPU_SUBTYPE_ITANIUM_2
@ CPU_SUBTYPE_486SX
@ CPU_SUBTYPE_XEON_MP
@ CPU_SUBTYPE_CELERON_MOBILE
@ CPU_SUBTYPE_XEON
@ CPU_SUBTYPE_PENTPRO
@ CPU_SUBTYPE_PENTIUM_4
@ CPU_SUBTYPE_386
@ CPU_SUBTYPE_I860_860
@ CPU_SUBTYPE_I860_ALL
@ CPU_SUBTYPE_VAX8800
@ CPU_SUBTYPE_UVAXIII
@ CPU_SUBTYPE_VAX_ALL
@ CPU_SUBTYPE_VAX750
@ CPU_SUBTYPE_VAX780
@ CPU_SUBTYPE_VAX730
@ CPU_SUBTYPE_UVAXI
@ CPU_SUBTYPE_VAX8500
@ CPU_SUBTYPE_VAX8650
@ CPU_SUBTYPE_VAX785
@ CPU_SUBTYPE_VAX8600
@ CPU_SUBTYPE_UVAXII
@ CPU_SUBTYPE_VAX8200
@ CPU_TYPE_POWERPC
@ CPU_TYPE_VAX
@ CPU_TYPE_POWERPC64
@ CPU_TYPE_I386
@ CPU_TYPE_MC680x0
@ CPU_TYPE_MC98000
@ CPU_TYPE_ARM
@ CPU_TYPE_X86_64
@ CPU_TYPE_SPARC
@ CPU_TYPE_MIPS
@ CPU_TYPE_ARM64
@ CPU_TYPE_I860
@ CPU_TYPE_HPPA
@ CPU_TYPE_MC88000
@ CPU_SUBTYPE_POWERPC_604e
@ CPU_SUBTYPE_POWERPC_601
@ CPU_SUBTYPE_POWERPC_ALL
@ CPU_SUBTYPE_POWERPC_603e
@ CPU_SUBTYPE_POWERPC_970
@ CPU_SUBTYPE_POWERPC_603ev
@ CPU_SUBTYPE_POWERPC_7400
@ CPU_SUBTYPE_POWERPC_620
@ CPU_SUBTYPE_POWERPC_7450
@ CPU_SUBTYPE_POWERPC_603
@ CPU_SUBTYPE_POWERPC_602
@ CPU_SUBTYPE_POWERPC_604
@ CPU_SUBTYPE_MC98601
@ CPU_SUBTYPE_MC98000_ALL
@ CPU_SUBTYPE_POWERPC_750
@ CPU_SUBTYPE_MIPS_R2000a
@ CPU_SUBTYPE_MIPS_R2000
@ CPU_SUBTYPE_MIPS_R2800
@ CPU_SUBTYPE_MIPS_R2300
@ CPU_SUBTYPE_MIPS_R3000a
@ CPU_SUBTYPE_MIPS_ALL
@ CPU_SUBTYPE_MIPS_R3000
@ CPU_SUBTYPE_MIPS_R2600
#define eprintf(x, y...)
Definition: rlcc.c:7

References CPU_SUBTYPE_386, CPU_SUBTYPE_486, CPU_SUBTYPE_486SX, CPU_SUBTYPE_ARM64_ALL, CPU_SUBTYPE_ARM64_V8, CPU_SUBTYPE_ARM64E, CPU_SUBTYPE_ARM_ALL, CPU_SUBTYPE_ARM_V4T, CPU_SUBTYPE_ARM_V5, CPU_SUBTYPE_ARM_V6, CPU_SUBTYPE_ARM_V7, CPU_SUBTYPE_ARM_V7EM, CPU_SUBTYPE_ARM_V7F, CPU_SUBTYPE_ARM_V7K, CPU_SUBTYPE_ARM_V7M, CPU_SUBTYPE_ARM_V7S, CPU_SUBTYPE_ARM_XSCALE, CPU_SUBTYPE_CELERON, CPU_SUBTYPE_CELERON_MOBILE, CPU_SUBTYPE_HPPA_7100, CPU_SUBTYPE_HPPA_7100LC, CPU_SUBTYPE_I860_860, CPU_SUBTYPE_I860_ALL, CPU_SUBTYPE_ITANIUM, CPU_SUBTYPE_ITANIUM_2, CPU_SUBTYPE_MC68030, CPU_SUBTYPE_MC68030_ONLY, CPU_SUBTYPE_MC68040, CPU_SUBTYPE_MC88000_ALL, CPU_SUBTYPE_MC88100, CPU_SUBTYPE_MC88110, CPU_SUBTYPE_MC98000_ALL, CPU_SUBTYPE_MC98601, CPU_SUBTYPE_MIPS_ALL, CPU_SUBTYPE_MIPS_R2000, CPU_SUBTYPE_MIPS_R2000a, CPU_SUBTYPE_MIPS_R2300, CPU_SUBTYPE_MIPS_R2600, CPU_SUBTYPE_MIPS_R2800, CPU_SUBTYPE_MIPS_R3000, CPU_SUBTYPE_MIPS_R3000a, CPU_SUBTYPE_PENT, CPU_SUBTYPE_PENTII_M3, CPU_SUBTYPE_PENTII_M5, CPU_SUBTYPE_PENTIUM_3, CPU_SUBTYPE_PENTIUM_3_M, CPU_SUBTYPE_PENTIUM_3_XEON, CPU_SUBTYPE_PENTIUM_4, CPU_SUBTYPE_PENTIUM_4_M, CPU_SUBTYPE_PENTIUM_M, CPU_SUBTYPE_PENTPRO, CPU_SUBTYPE_POWERPC_601, CPU_SUBTYPE_POWERPC_602, CPU_SUBTYPE_POWERPC_603, CPU_SUBTYPE_POWERPC_603e, CPU_SUBTYPE_POWERPC_603ev, CPU_SUBTYPE_POWERPC_604, CPU_SUBTYPE_POWERPC_604e, CPU_SUBTYPE_POWERPC_620, CPU_SUBTYPE_POWERPC_7400, CPU_SUBTYPE_POWERPC_7450, CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_970, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_SPARC_ALL, CPU_SUBTYPE_UVAXI, CPU_SUBTYPE_UVAXII, CPU_SUBTYPE_UVAXIII, CPU_SUBTYPE_VAX730, CPU_SUBTYPE_VAX750, CPU_SUBTYPE_VAX780, CPU_SUBTYPE_VAX785, CPU_SUBTYPE_VAX8200, CPU_SUBTYPE_VAX8500, CPU_SUBTYPE_VAX8600, CPU_SUBTYPE_VAX8650, CPU_SUBTYPE_VAX8800, CPU_SUBTYPE_VAX_ALL, CPU_SUBTYPE_X86_64_ALL, CPU_SUBTYPE_X86_ARCH1, CPU_SUBTYPE_XEON, CPU_SUBTYPE_XEON_MP, CPU_TYPE_ARM, CPU_TYPE_ARM64, CPU_TYPE_HPPA, CPU_TYPE_I386, CPU_TYPE_I860, CPU_TYPE_MC680x0, CPU_TYPE_MC88000, CPU_TYPE_MC98000, CPU_TYPE_MIPS, CPU_TYPE_POWERPC, CPU_TYPE_POWERPC64, CPU_TYPE_SPARC, CPU_TYPE_VAX, CPU_TYPE_X86_64, and eprintf.

Referenced by get_cpusubtype_from_hdr().

◆ entry_to_vaddr()

static ut64 entry_to_vaddr ( struct MACH0_(obj_t) *  bin)
static

Definition at line 41 of file mach0.c.

41  {
42  switch (bin->main_cmd.cmd) {
43  case LC_MAIN:
44  return bin->entry + bin->baddr;
45  case LC_UNIXTHREAD:
46  case LC_THREAD:
47  return bin->entry;
48  default:
49  return 0;
50  }
51 }

References LC_MAIN, LC_THREAD, and LC_UNIXTHREAD.

Referenced by get_entrypoint().

◆ fill_exports_list()

static void fill_exports_list ( struct MACH0_(obj_t) *  bin,
const char *  name,
ut64  flags,
ut64  offset,
void *  ctx 
)
static

Definition at line 2746 of file mach0.c.

2746  {
2747  RzList *list = (RzList *)ctx;
2749  if (!sym) {
2750  return;
2751  }
2752  sym->vaddr = MACH0_(paddr_to_vaddr)(bin, offset);
2753  sym->paddr = offset;
2754  sym->type = "EXT";
2755  sym->name = strdup(name);
2757  rz_list_append(list, sym);
2758 }
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
#define RZ_BIN_BIND_GLOBAL_STR
Definition: rz_bin.h:107
#define RZ_NEW0(x)
Definition: rz_types.h:284
const char * bind
Definition: rz_bin.h:681
const char * type
Definition: rz_bin.h:682
char * name
Definition: rz_bin.h:675

References rz_bin_symbol_t::bind, list(), MACH0_(), rz_bin_symbol_t::name, rz_bin_symbol_t::paddr, paddr_to_vaddr(), RZ_BIN_BIND_GLOBAL_STR, rz_list_append(), RZ_NEW0, strdup(), rz_bin_symbol_t::type, and rz_bin_symbol_t::vaddr.

Referenced by get_symbols_list().

◆ get_baddr()

ut64 MACH0_() get_baddr ( struct MACH0_(obj_t) *  bin)

Definition at line 3262 of file mach0.c.

3262  {
3263  int i;
3264 
3265  if (bin->hdr.filetype != MH_EXECUTE && bin->hdr.filetype != MH_DYLINKER &&
3266  bin->hdr.filetype != MH_FILESET) {
3267  return 0;
3268  }
3269  for (i = 0; i < bin->nsegs; i++) {
3270  if (bin->segs[i].fileoff == 0 && bin->segs[i].filesize != 0) {
3271  return bin->segs[i].vmaddr;
3272  }
3273  }
3274  return 0;
3275 }
lzma_index ** i
Definition: index.h:629
@ MH_EXECUTE
Definition: mach0_defines.h:73
@ MH_DYLINKER
Definition: mach0_defines.h:78
@ MH_FILESET
Definition: mach0_defines.h:83

References i, MH_DYLINKER, MH_EXECUTE, and MH_FILESET.

Referenced by baddr(), and init().

◆ get_bits()

int MACH0_() get_bits ( struct MACH0_(obj_t) *  bin)

Definition at line 3288 of file mach0.c.

3288  {
3289  if (bin) {
3290  int bits = MACH0_(get_bits_from_hdr)(&bin->hdr);
3291  if (bin->hdr.cputype == CPU_TYPE_ARM && bin->entry & 1) {
3292  return 16;
3293  }
3294  return bits;
3295  }
3296  return 32;
3297 }
int bits(struct state *s, int need)
Definition: blast.c:72
int MACH0_() get_bits_from_hdr(struct MACH0_(mach_header) *hdr)
Definition: mach0.c:3299

References bits(), CPU_TYPE_ARM, get_bits_from_hdr(), and MACH0_().

◆ get_bits_from_hdr()

int MACH0_() get_bits_from_hdr ( struct MACH0_(mach_header) *  hdr)

Definition at line 3299 of file mach0.c.

3299  {
3300  if (hdr->magic == MH_MAGIC_64 || hdr->magic == MH_CIGAM_64) {
3301  return 64;
3302  }
3303  if (hdr->cputype == CPU_TYPE_ARM64_32) { // new apple watch aka arm64_32
3304  return 64;
3305  }
3306  if ((hdr->cpusubtype & CPU_SUBTYPE_MASK) == (CPU_SUBTYPE_ARM_V7K << 24)) {
3307  return 16;
3308  }
3309  return 32;
3310 }
@ MH_MAGIC_64
Definition: mach0_defines.h:63
@ MH_CIGAM_64
Definition: mach0_defines.h:64
@ CPU_SUBTYPE_MASK
@ CPU_TYPE_ARM64_32

References CPU_SUBTYPE_ARM_V7K, CPU_SUBTYPE_MASK, CPU_TYPE_ARM64_32, MH_CIGAM_64, and MH_MAGIC_64.

Referenced by fill_metadata_info_from_hdr(), get_bits(), get_symbols(), get_symbols_list(), and reloc_target_size().

◆ get_class()

char* MACH0_() get_class ( struct MACH0_(obj_t) *  bin)

Definition at line 3277 of file mach0.c.

3277  {
3278 #if RZ_BIN_MACH064
3279  return rz_str_new("MACH064");
3280 #else
3281  return rz_str_new("MACH0");
3282 #endif
3283 }
RZ_API char * rz_str_new(const char *str)
Definition: str.c:865

References rz_str_new().

Referenced by info().

◆ get_cpusubtype()

char* MACH0_() get_cpusubtype ( struct MACH0_(obj_t) *  bin)

Definition at line 3546 of file mach0.c.

3546  {
3547  return bin ? MACH0_(get_cpusubtype_from_hdr)(&bin->hdr) : strdup("Unknown");
3548 }
char *MACH0_() get_cpusubtype_from_hdr(struct MACH0_(mach_header) *hdr)
Definition: mach0.c:3541

References get_cpusubtype_from_hdr(), MACH0_(), and strdup().

Referenced by info().

◆ get_cpusubtype_from_hdr()

char* MACH0_() get_cpusubtype_from_hdr ( struct MACH0_(mach_header) *  hdr)

Definition at line 3541 of file mach0.c.

3541  {
3543  return strdup(cpusubtype_tostring(hdr->cputype, hdr->cpusubtype));
3544 }
static const char * cpusubtype_tostring(ut32 cputype, ut32 cpusubtype)
Definition: mach0.c:3387
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108

References cpusubtype_tostring(), NULL, rz_return_val_if_fail, and strdup().

Referenced by fill_metadata_info_from_hdr(), and get_cpusubtype().

◆ get_cputype()

const char* MACH0_() get_cputype ( struct MACH0_(obj_t) *  bin)

Definition at line 3383 of file mach0.c.

3383  {
3384  return bin ? MACH0_(get_cputype_from_hdr)(&bin->hdr) : "unknown";
3385 }
const char *MACH0_() get_cputype_from_hdr(struct MACH0_(mach_header) *hdr)
Definition: mach0.c:3336

References get_cputype_from_hdr(), and MACH0_().

Referenced by info().

◆ get_cputype_from_hdr()

const char* MACH0_() get_cputype_from_hdr ( struct MACH0_(mach_header) *  hdr)

Definition at line 3336 of file mach0.c.

3336  {
3337  const char *archstr = "unknown";
3338  switch (hdr->cputype) {
3339  case CPU_TYPE_VAX:
3340  archstr = "vax";
3341  break;
3342  case CPU_TYPE_MC680x0:
3343  archstr = "mc680x0";
3344  break;
3345  case CPU_TYPE_I386:
3346  case CPU_TYPE_X86_64:
3347  archstr = "x86";
3348  break;
3349  case CPU_TYPE_MC88000:
3350  archstr = "mc88000";
3351  break;
3352  case CPU_TYPE_MC98000:
3353  archstr = "mc98000";
3354  break;
3355  case CPU_TYPE_HPPA:
3356  archstr = "hppa";
3357  break;
3358  case CPU_TYPE_ARM:
3359  case CPU_TYPE_ARM64:
3360  case CPU_TYPE_ARM64_32:
3361  archstr = "arm";
3362  break;
3363  case CPU_TYPE_SPARC:
3364  archstr = "sparc";
3365  break;
3366  case CPU_TYPE_MIPS:
3367  archstr = "mips";
3368  break;
3369  case CPU_TYPE_I860:
3370  archstr = "i860";
3371  break;
3372  case CPU_TYPE_POWERPC:
3373  case CPU_TYPE_POWERPC64:
3374  archstr = "ppc";
3375  break;
3376  default:
3377  eprintf("Unknown arch %d\n", hdr->cputype);
3378  break;
3379  }
3380  return archstr;
3381 }

References CPU_TYPE_ARM, CPU_TYPE_ARM64, CPU_TYPE_ARM64_32, CPU_TYPE_HPPA, CPU_TYPE_I386, CPU_TYPE_I860, CPU_TYPE_MC680x0, CPU_TYPE_MC88000, CPU_TYPE_MC98000, CPU_TYPE_MIPS, CPU_TYPE_POWERPC, CPU_TYPE_POWERPC64, CPU_TYPE_SPARC, CPU_TYPE_VAX, CPU_TYPE_X86_64, and eprintf.

Referenced by _patch_reloc(), fill_metadata_info_from_hdr(), and get_cputype().

◆ get_entrypoint()

struct addr_t* MACH0_() get_entrypoint ( struct MACH0_(obj_t) *  bin)

Definition at line 3196 of file mach0.c.

3196  {
3198 
3199  ut64 ea = entry_to_vaddr(bin);
3200  if (ea == 0 || ea == UT64_MAX) {
3201  return NULL;
3202  }
3203  struct addr_t *entry = RZ_NEW0(struct addr_t);
3204  if (!entry) {
3205  return NULL;
3206  }
3207  entry->addr = ea;
3208  entry->offset = MACH0_(vaddr_to_paddr)(bin, entry->addr);
3209  entry->haddr = sdb_num_get(bin->kv, "mach0.entry.offset", 0);
3210  sdb_num_set(bin->kv, "mach0.entry.vaddr", entry->addr, 0);
3211  sdb_num_set(bin->kv, "mach0.entry.paddr", bin->entry, 0);
3212 
3213  if (entry->offset == 0 && !bin->sects) {
3214  int i;
3215  for (i = 0; i < bin->nsects; i++) {
3216  // XXX: section name shoudnt matter .. just check for exec flags
3217  if (!strncmp(bin->sects[i].sectname, "__text", 6)) {
3218  entry->offset = (ut64)bin->sects[i].offset;
3219  sdb_num_set(bin->kv, "mach0.entry", entry->offset, 0);
3220  entry->addr = (ut64)bin->sects[i].addr;
3221  if (!entry->addr) { // workaround for object files
3222  eprintf("entrypoint is 0...\n");
3223  // XXX(lowlyw) there's technically not really entrypoints
3224  // for .o files, so ignore this...
3225  // entry->addr = entry->offset;
3226  }
3227  break;
3228  }
3229  }
3230  bin->entry = entry->addr;
3231  }
3232  return entry;
3233 }
static ut64 entry_to_vaddr(struct MACH0_(obj_t) *bin)
Definition: mach0.c:41
RZ_API ut64 MACH0_() vaddr_to_paddr(struct MACH0_(obj_t) *bin, ut64 addr)
Definition: mach0.c:53
RZ_API int sdb_num_set(Sdb *s, const char *key, ut64 v, ut32 cas)
Definition: num.c:25
RZ_API ut64 sdb_num_get(Sdb *s, const char *key, ut32 *cas)
Definition: num.c:13
#define UT64_MAX
Definition: rz_types_base.h:86
Definition: mach0.h:85
Definition: zipcmp.c:77
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References entry_to_vaddr(), eprintf, i, if(), MACH0_(), NULL, RZ_NEW0, rz_return_val_if_fail, sdb_num_get(), sdb_num_set(), ut64(), UT64_MAX, and vaddr_to_paddr().

Referenced by entries(), and get_main().

◆ get_filetype()

char* MACH0_() get_filetype ( struct MACH0_(obj_t) *  bin)

Definition at line 3578 of file mach0.c.

3578  {
3579  return bin ? MACH0_(get_filetype_from_hdr)(&bin->hdr) : strdup("Unknown");
3580 }
char *MACH0_() get_filetype_from_hdr(struct MACH0_(mach_header) *hdr)
Definition: mach0.c:3559

References get_filetype_from_hdr(), MACH0_(), and strdup().

Referenced by info().

◆ get_filetype_from_hdr()

char* MACH0_() get_filetype_from_hdr ( struct MACH0_(mach_header) *  hdr)

Definition at line 3559 of file mach0.c.

3559  {
3560  const char *mhtype = "Unknown";
3561  switch (hdr->filetype) {
3562  case MH_OBJECT: mhtype = "Relocatable object"; break;
3563  case MH_EXECUTE: mhtype = "Executable file"; break;
3564  case MH_FVMLIB: mhtype = "Fixed VM shared library"; break;
3565  case MH_CORE: mhtype = "Core file"; break;
3566  case MH_PRELOAD: mhtype = "Preloaded executable file"; break;
3567  case MH_DYLIB: mhtype = "Dynamically bound shared library"; break;
3568  case MH_DYLINKER: mhtype = "Dynamic link editor"; break;
3569  case MH_BUNDLE: mhtype = "Dynamically bound bundle file"; break;
3570  case MH_DYLIB_STUB: mhtype = "Shared library stub for static linking (no sections)"; break;
3571  case MH_DSYM: mhtype = "Companion file with only debug sections"; break;
3572  case MH_KEXT_BUNDLE: mhtype = "Kernel extension bundle file"; break;
3573  case MH_FILESET: mhtype = "Kernel cache file"; break;
3574  }
3575  return strdup(mhtype);
3576 }
@ MH_FVMLIB
Definition: mach0_defines.h:74
@ MH_KEXT_BUNDLE
Definition: mach0_defines.h:82
@ MH_DSYM
Definition: mach0_defines.h:81
@ MH_PRELOAD
Definition: mach0_defines.h:76
@ MH_DYLIB_STUB
Definition: mach0_defines.h:80
@ MH_BUNDLE
Definition: mach0_defines.h:79
@ MH_OBJECT
Definition: mach0_defines.h:72
@ MH_CORE
Definition: mach0_defines.h:75
@ MH_DYLIB
Definition: mach0_defines.h:77

References MH_BUNDLE, MH_CORE, MH_DSYM, MH_DYLIB, MH_DYLIB_STUB, MH_DYLINKER, MH_EXECUTE, MH_FILESET, MH_FVMLIB, MH_KEXT_BUNDLE, MH_OBJECT, MH_PRELOAD, and strdup().

Referenced by fill_metadata_info_from_hdr(), and get_filetype().

◆ get_imports()

struct import_t* MACH0_() get_imports ( struct MACH0_(obj_t) *  bin)

Definition at line 3146 of file mach0.c.

3146  {
3148 
3149  int i, j, idx, stridx;
3150  if (!bin->sects || !bin->symtab || !bin->symstr || !bin->indirectsyms) {
3151  return NULL;
3152  }
3153 
3154  if (bin->dysymtab.nundefsym < 1 || bin->dysymtab.nundefsym > 0xfffff) {
3155  return NULL;
3156  }
3157 
3158  struct import_t *imports = calloc(bin->dysymtab.nundefsym + 1, sizeof(struct import_t));
3159  if (!imports) {
3160  return NULL;
3161  }
3162  for (i = j = 0; i < bin->dysymtab.nundefsym; i++) {
3163  idx = bin->dysymtab.iundefsym + i;
3164  if (idx < 0 || idx >= bin->nsymtab) {
3165  bprintf("WARNING: Imports index out of bounds. Ignoring relocs\n");
3166  free(imports);
3167  return NULL;
3168  }
3169  stridx = bin->symtab[idx].n_strx;
3170  char *imp_name = MACH0_(get_name)(bin, stridx, false);
3171  if (imp_name) {
3173  free(imp_name);
3174  } else {
3175  // imports[j].name[0] = 0;
3176  continue;
3177  }
3178  imports[j].ord = i;
3179  imports[j++].last = 0;
3180  }
3181  imports[j].last = 1;
3182 
3183  if (!bin->imports_by_ord_size) {
3184  if (j > 0) {
3185  bin->imports_by_ord_size = j;
3186  bin->imports_by_ord = (RzBinImport **)calloc(j, sizeof(RzBinImport *));
3187  } else {
3188  bin->imports_by_ord_size = 0;
3189  bin->imports_by_ord = NULL;
3190  }
3191  }
3192 
3193  return imports;
3194 }
RzList * imports(RzBinFile *bf)
Definition: bin_ne.c:106
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
RZ_API RZ_OWN char *MACH0_() get_name(struct MACH0_(obj_t) *mo, ut32 stridx, bool filter)
Get a string from the string table referenced by the LC_SYMTAB command.
Definition: mach0.c:2563
#define bprintf
Definition: mach0.c:14
#define RZ_BIN_MACH0_STRING_LENGTH
Definition: mach0.h:15
int idx
Definition: setup.py:197
RZ_API size_t rz_str_ncpy(char *dst, const char *src, size_t n)
Secure string copy with null terminator.
Definition: str.c:923
Definition: mach0.h:65

References bprintf, calloc(), free(), get_name(), i, setup::idx, imports(), MACH0_(), NULL, RZ_BIN_MACH0_STRING_LENGTH, rz_return_val_if_fail, and rz_str_ncpy().

Referenced by imports().

◆ get_intrp()

const char* MACH0_() get_intrp ( struct MACH0_(obj_t) *  bin)

Definition at line 3320 of file mach0.c.

3320  {
3321  return bin ? bin->intrp : NULL;
3322 }

References NULL.

Referenced by info().

◆ get_libs()

struct lib_t* MACH0_() get_libs ( struct MACH0_(obj_t) *  bin)

Definition at line 3242 of file mach0.c.

3242  {
3243  struct lib_t *libs;
3244  int i;
3245 
3246  if (!bin->nlibs) {
3247  return NULL;
3248  }
3249  if (!(libs = calloc((bin->nlibs + 1), sizeof(struct lib_t)))) {
3250  return NULL;
3251  }
3252  for (i = 0; i < bin->nlibs; i++) {
3253  sdb_set(bin->kv, sdb_fmt("libs.%d.name", i), bin->libs[i], 0);
3254  strncpy(libs[i].name, bin->libs[i], RZ_BIN_MACH0_STRING_LENGTH - 1);
3255  libs[i].name[RZ_BIN_MACH0_STRING_LENGTH - 1] = '\0';
3256  libs[i].last = 0;
3257  }
3258  libs[i].last = 1;
3259  return libs;
3260 }
static RzList * libs(RzBinFile *bf)
Definition: bin_coff.c:379
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
Definition: mach0.h:92

References calloc(), i, libs(), NULL, RZ_BIN_MACH0_STRING_LENGTH, sdb_fmt(), and sdb_set().

Referenced by libs().

◆ get_main()

ut64 MACH0_() get_main ( struct MACH0_(obj_t) *  bin)

Definition at line 3582 of file mach0.c.

3582  {
3583  ut64 addr = UT64_MAX;
3584  int i;
3585 
3586  // 0 = sscanned but no main found
3587  // -1 = not scanned, so no main
3588  // other = valid main addr
3589  if (bin->main_addr == UT64_MAX) {
3590 #if FEATURE_SYMLIST
3591  (void)MACH0_(get_symbols_list)(bin);
3592 #else
3593  (void)MACH0_(get_symbols)(bin);
3594 #endif
3595  }
3596  if (bin->main_addr != 0 && bin->main_addr != UT64_MAX) {
3597  return bin->main_addr;
3598  }
3599  // dummy call to initialize things
3601 
3602  bin->main_addr = 0;
3603 
3604  if (addr == UT64_MAX && bin->main_cmd.cmd == LC_MAIN) {
3605  addr = bin->entry + bin->baddr;
3606  }
3607 
3608  if (!addr) {
3609  ut8 b[128];
3610  ut64 entry = MACH0_(vaddr_to_paddr)(bin, bin->entry);
3611  // XXX: X86 only and hacky!
3612  if (entry > bin->size || entry + sizeof(b) > bin->size) {
3613  return UT64_MAX;
3614  }
3615  i = rz_buf_read_at(bin->b, entry, b, sizeof(b));
3616  if (i < 80) {
3617  return UT64_MAX;
3618  }
3619  for (i = 0; i < 64; i++) {
3620  if (b[i] == 0xe8 && !b[i + 3] && !b[i + 4]) {
3621  int delta = b[i + 1] | (b[i + 2] << 8) | (b[i + 3] << 16) | (b[i + 4] << 24);
3622  addr = bin->entry + i + 5 + delta;
3623  break;
3624  }
3625  }
3626  if (!addr) {
3627  addr = entry;
3628  }
3629  }
3630  return bin->main_addr = addr;
3631 }
const RzList *MACH0_() get_symbols_list(struct MACH0_(obj_t) *bin)
Definition: mach0.c:2761
const struct symbol_t *MACH0_() get_symbols(struct MACH0_(obj_t) *bin)
Definition: mach0.c:2959
struct addr_t *MACH0_() get_entrypoint(struct MACH0_(obj_t) *bin)
Definition: mach0.c:3196
#define b(i)
Definition: sha256.c:42
static st64 delta
Definition: vmenus.c:2425

References addr, b, delta, free(), get_entrypoint(), get_symbols(), get_symbols_list(), i, LC_MAIN, MACH0_(), rz_buf_read_at(), ut64(), UT64_MAX, and vaddr_to_paddr().

Referenced by binsym().

◆ get_maps()

RzList* MACH0_() get_maps ( RzBinFile bf)

Definition at line 2252 of file mach0.c.

2252  {
2253  RzList *ret = MACH0_(get_maps_unpatched)(bf);
2254  if (!ret) {
2255  return NULL;
2256  }
2257  struct MACH0_(obj_t) *obj = bf->o->bin_obj;
2258  // clang-format off
2259  MACH0_(patch_relocs)(bf, obj);
2260  // clang-format on
2261  rz_bin_relocs_patch_maps(ret, obj->buf_patched, bf->o->boffset,
2264  return ret;
2265 }
RzList *MACH0_() get_maps_unpatched(RzBinFile *bf)
Definition: mach0.c:2217
RZ_API ut64 MACH0_() reloc_targets_map_base(RzBinFile *bf, struct MACH0_(obj_t) *obj)
base vaddr where to map the artificial reloc target vfile
Definition: mach0_relocs.c:556
#define MACH0_VFILE_NAME_PATCHED
Definition: mach0.h:197
RZ_API ut64 MACH0_() reloc_targets_vfile_size(struct MACH0_(obj_t) *obj)
size of the artificial reloc target vfile
Definition: mach0_relocs.c:547
#define MACH0_VFILE_NAME_RELOC_TARGETS
Definition: mach0.h:196
RZ_API void MACH0_() patch_relocs(RzBinFile *bf, struct MACH0_(obj_t) *obj)
Patching of external relocs in a sparse overlay buffer.
Definition: mach0_relocs.c:614
RZ_API void rz_bin_relocs_patch_maps(RZ_NONNULL RzList *maps, RZ_NULLABLE RzBuffer *buf_patched, ut64 buf_patched_offset, ut64 target_vfile_base, ut64 target_vfile_size, RZ_NONNULL const char *vfile_name_patched, RZ_NONNULL const char *vfile_name_reloc_targets)
Change file-mapped maps to the patched vfile if covered by the buffer and add the reloc target map.
Definition: relocs_patch.c:86
RzBinObject * o
Definition: rz_bin.h:305
ut64 boffset
Definition: rz_bin.h:262
void * bin_obj
Definition: rz_bin.h:293

References get_maps_unpatched(), MACH0_(), MACH0_VFILE_NAME_PATCHED, MACH0_VFILE_NAME_RELOC_TARGETS, NULL, patch_relocs(), reloc_targets_map_base(), reloc_targets_vfile_size(), and rz_bin_relocs_patch_maps().

Referenced by maps().

◆ get_maps_unpatched()

RzList* MACH0_() get_maps_unpatched ( RzBinFile bf)

Definition at line 2217 of file mach0.c.

2217  {
2219  struct MACH0_(obj_t) *bin = bf->o->bin_obj;
2221  if (!ret) {
2222  return NULL;
2223  }
2224  for (size_t i = 0; i < bin->nsegs; i++) {
2225  struct MACH0_(segment_command) *seg = &bin->segs[i];
2226  if (!seg->initprot) {
2227  continue;
2228  }
2230  if (!map) {
2231  break;
2232  }
2233  map->psize = seg->vmsize;
2234  map->vaddr = seg->vmaddr;
2235  map->vsize = seg->vmsize;
2236  map->name = rz_str_ndup(seg->segname, 16);
2237  rz_str_filter(map->name);
2238  map->perm = prot2perm(seg->initprot);
2241  map->paddr = seg->fileoff;
2242  } else {
2243  // boffset is relevant for fatmach0 where the mach0 is located boffset into the whole file
2244  // the rebasing vfile above however is based at the mach0 already
2245  map->paddr = seg->fileoff + bf->o->boffset;
2246  }
2247  rz_list_append(ret, map);
2248  }
2249  return ret;
2250 }
RZ_API void rz_bin_map_free(RzBinMap *map)
Definition: bin.c:1023
size_t map(int syms, int left, int len)
Definition: enough.c:237
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
static int prot2perm(int x)
Definition: mach0.c:2132
#define MACH0_VFILE_NAME_REBASED_STRIPPED
Definition: mach0.h:195
RZ_API bool MACH0_() segment_needs_rebasing_and_stripping(struct MACH0_(obj_t) *obj, size_t seg_index)
Definition: mach0_rebase.c:232
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
RZ_API char * rz_str_ndup(RZ_NULLABLE const char *ptr, int len)
Create new copy of string ptr limited to size len.
Definition: str.c:1006
RZ_API void rz_str_filter(char *str)
Convert all non-printable characters in str with '.'.
Definition: str.c:2359
Description of a single memory mapping into virtual memory from a binary.
Definition: rz_bin.h:602

References i, MACH0_(), MACH0_VFILE_NAME_REBASED_STRIPPED, map(), NULL, prot2perm(), rz_bin_map_free(), rz_list_append(), rz_list_newf(), RZ_NEW0, rz_return_val_if_fail, rz_str_filter(), rz_str_ndup(), segment_needs_rebasing_and_stripping(), and strdup().

Referenced by get_maps(), and reloc_targets_map_base().

◆ get_name()

RZ_API RZ_OWN char* MACH0_() get_name ( struct MACH0_(obj_t) *  mo,
ut32  stridx,
bool  filter 
)

Get a string from the string table referenced by the LC_SYMTAB command.

Parameters
stridxthe index into the string table, such as n_strx from a nlist symbol entry
filterwhether to call rz_str_filter() on the string before returning

Definition at line 2563 of file mach0.c.

2563  {
2564  size_t i = 0;
2565  if (!mo->symstr || stridx >= mo->symstrlen) {
2566  return NULL;
2567  }
2568  int len = mo->symstrlen - stridx;
2569  const char *symstr = (const char *)mo->symstr + stridx;
2570  for (i = 0; i < len; i++) {
2571  if ((ut8)(symstr[i] & 0xff) == 0xff || !symstr[i]) {
2572  len = i;
2573  break;
2574  }
2575  }
2576  if (len > 0) {
2577  char *res = rz_str_ndup(symstr, len);
2578  if (filter) {
2579  rz_str_filter(res);
2580  }
2581  return res;
2582  }
2583  return NULL;
2584 }
size_t len
Definition: 6502dis.c:15

References i, len, NULL, rz_str_filter(), and rz_str_ndup().

Referenced by get_imports(), get_operator_code(), get_symbols(), get_symbols_list(), and parse_relocation_info().

◆ get_os()

const char* MACH0_() get_os ( struct MACH0_(obj_t) *  bin)

Definition at line 3324 of file mach0.c.

3324  {
3325  if (bin) {
3326  switch (bin->os) {
3327  case 1: return "macos";
3328  case 2: return "ios";
3329  case 3: return "watchos";
3330  case 4: return "tvos";
3331  }
3332  }
3333  return "darwin";
3334 }

Referenced by info().

◆ get_sections()

struct section_t* MACH0_() get_sections ( struct MACH0_(obj_t) *  bin)

Definition at line 2411 of file mach0.c.

2411  {
2413  struct section_t *sections;
2414  char sectname[64], raw_segname[17];
2415  size_t i, j, to;
2416 
2417  /* for core files */
2418  if (bin->nsects < 1 && bin->nsegs > 0) {
2419  struct MACH0_(segment_command) * seg;
2420  if (!(sections = calloc((bin->nsegs + 1), sizeof(struct section_t)))) {
2421  return NULL;
2422  }
2423  for (i = 0; i < bin->nsegs; i++) {
2424  seg = &bin->segs[i];
2425  sections[i].addr = seg->vmaddr;
2426  sections[i].offset = seg->fileoff;
2427  sections[i].size = seg->vmsize;
2428  sections[i].vsize = seg->vmsize;
2429  sections[i].align = 4096;
2430  sections[i].flags = seg->flags;
2431  rz_strf(sectname, "%.16s", seg->segname);
2432  sectname[16] = 0;
2433  rz_str_filter(sectname);
2434  // hack to support multiple sections with same name
2435  sections[i].perm = prot2perm(seg->initprot);
2436  sections[i].last = 0;
2437  }
2438  sections[i].last = 1;
2439  return sections;
2440  }
2441 
2442  if (!bin->sects) {
2443  return NULL;
2444  }
2445  to = RZ_MIN(bin->nsects, 128); // limit number of sections here to avoid fuzzed bins
2446  if (to < 1) {
2447  return NULL;
2448  }
2449  if (!(sections = calloc(bin->nsects + 1, sizeof(struct section_t)))) {
2450  return NULL;
2451  }
2452  for (i = 0; i < to; i++) {
2453  sections[i].offset = (ut64)bin->sects[i].offset;
2454  sections[i].addr = (ut64)bin->sects[i].addr;
2455  sections[i].size = (bin->sects[i].flags == S_ZEROFILL) ? 0 : (ut64)bin->sects[i].size;
2456  sections[i].vsize = (ut64)bin->sects[i].size;
2457  sections[i].align = bin->sects[i].align;
2458  sections[i].flags = bin->sects[i].flags;
2459  rz_strf(sectname, "%.16s", bin->sects[i].sectname);
2460  rz_str_filter(sectname);
2461  rz_strf(raw_segname, "%.16s", bin->sects[i].segname);
2462  for (j = 0; j < bin->nsegs; j++) {
2463  if (sections[i].addr >= bin->segs[j].vmaddr &&
2464  sections[i].addr < (bin->segs[j].vmaddr + bin->segs[j].vmsize)) {
2465  sections[i].perm = prot2perm(bin->segs[j].initprot);
2466  break;
2467  }
2468  }
2469  snprintf(sections[i].name, sizeof(sections[i].name),
2470  "%d.%s.%s", (int)i, raw_segname, sectname);
2471  sections[i].last = 0;
2472  }
2473  sections[i].last = 1;
2474  return sections;
2475 }
RzList * sections(RzBinFile *bf)
Definition: bin_ne.c:110
snprintf
Definition: kernel.h:364
@ S_ZEROFILL
S_ZEROFILL - Zero fill on demand section.
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
Definition: rz_str.h:59
#define RZ_MIN(x, y)
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125

References addr, calloc(), i, NULL, prot2perm(), RZ_MIN, rz_return_val_if_fail, rz_str_filter(), rz_strf, S_ZEROFILL, sections(), snprintf, to, and ut64().

Referenced by carve_kexts(), classes(), estimate_slide(), get_prelink_info_range_from_mach0(), get_stubs_info(), parse_categories(), parse_classes(), process_constructors(), process_kmod_init_term(), rebase_info_populate(), resolve_mig_subsystem(), resolve_syscalls(), rz_dyldcache_get_objc_opt_info(), rz_kext_fill_text_range(), rz_rebase_info_new_from_mach0(), sections_from_bin(), and sections_from_mach0().

◆ get_segments()

RzList* MACH0_() get_segments ( RzBinFile bf)

Definition at line 2267 of file mach0.c.

2267  {
2268  struct MACH0_(obj_t) *bin = bf->o->bin_obj;
2269  if (bin->sections_cache) {
2270  return bin->sections_cache;
2271  }
2273  size_t i, j;
2274 
2275  if (bin->nsegs > 0) {
2276  struct MACH0_(segment_command) * seg;
2277  for (i = 0; i < bin->nsegs; i++) {
2278  seg = &bin->segs[i];
2279  if (!seg->initprot) {
2280  continue;
2281  }
2283  if (!s) {
2284  break;
2285  }
2286  s->vaddr = seg->vmaddr;
2287  s->vsize = seg->vmsize;
2288  s->size = seg->vmsize;
2289  s->paddr = seg->fileoff;
2290  s->paddr += bf->o->boffset;
2291  // TODO s->flags = seg->flags;
2292  s->name = rz_str_ndup(seg->segname, 16);
2293  s->is_segment = true;
2294  rz_str_filter(s->name);
2295  s->perm = prot2perm(seg->initprot);
2296  rz_list_append(list, s);
2297  }
2298  }
2299  if (bin->nsects > 0) {
2300  int last_section = RZ_MIN(bin->nsects, 128); // maybe drop this limit?
2301  for (i = 0; i < last_section; i++) {
2303  if (!s) {
2304  break;
2305  }
2306  s->vaddr = (ut64)bin->sects[i].addr;
2307  s->vsize = (ut64)bin->sects[i].size;
2308  s->align = (ut64)(1ULL << (bin->sects[i].align & 63));
2309  s->is_segment = false;
2310  s->size = (bin->sects[i].flags == S_ZEROFILL) ? 0 : (ut64)bin->sects[i].size;
2311  // The bottom byte of flags is the section type
2312  s->type = bin->sects[i].flags & 0xFF;
2313  s->flags = bin->sects[i].flags & 0xFFFFFF00;
2314  // XXX flags
2315  s->paddr = (ut64)bin->sects[i].offset;
2316  int segment_index = 0;
2317  // s->perm =prot2perm (bin->segs[j].initprot);
2318  for (j = 0; j < bin->nsegs; j++) {
2319  if (s->vaddr >= bin->segs[j].vmaddr &&
2320  s->vaddr < (bin->segs[j].vmaddr + bin->segs[j].vmsize)) {
2321  s->perm = prot2perm(bin->segs[j].initprot);
2322  segment_index = j;
2323  break;
2324  }
2325  }
2326  char *section_name = rz_str_ndup(bin->sects[i].sectname, 16);
2327  char *segment_name = rz_str_newf("%zu.%s", i, bin->segs[segment_index].segname);
2328  s->name = rz_str_newf("%s.%s", segment_name, section_name);
2329  s->is_data = __isDataSection(s);
2330  if (strstr(section_name, "interpos") || strstr(section_name, "__mod_")) {
2331 #if RZ_BIN_MACH064
2332  const int ws = 8;
2333 #else
2334  const int ws = 4;
2335 #endif
2336  s->format = rz_str_newf("Cd %d[%" PFMT64d "]", ws, s->vsize / ws);
2337  }
2338  rz_list_append(list, s);
2339  free(segment_name);
2340  free(section_name);
2341  }
2342  }
2343  bin->sections_cache = list;
2344  return list;
2345 }
RZ_API RzBinSection * rz_bin_section_new(const char *name)
Definition: bin.c:1108
RZ_API void rz_bin_section_free(RzBinSection *bs)
Definition: bin.c:1116
static bool __isDataSection(RzBinSection *sect)
Definition: mach0.c:2146
static RzSocket * s
Definition: rtr.c:28
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define PFMT64d
Definition: rz_types.h:394

References __isDataSection(), free(), i, list(), NULL, PFMT64d, prot2perm(), rz_bin_section_free(), rz_bin_section_new(), rz_list_append(), rz_list_newf(), RZ_MIN, RZ_NEW0, rz_str_filter(), rz_str_ndup(), rz_str_newf(), s, S_ZEROFILL, and ut64().

Referenced by sections().

◆ get_symbols()

const struct symbol_t* MACH0_() get_symbols ( struct MACH0_(obj_t) *  bin)

Definition at line 2959 of file mach0.c.

2959  {
2960  struct symbol_t *symbols;
2961  int j, s, stridx, symbols_size, symbols_count;
2962  ut32 to, from, i;
2963 
2964  if (bin->symbols) {
2965  return bin->symbols;
2966  }
2967 
2968  HtPP *hash = ht_pp_new0();
2969  if (!hash) {
2970  return NULL;
2971  }
2972 
2974  int n_exports = walk_exports(bin, NULL, NULL);
2975 
2976  symbols_count = n_exports;
2977  j = 0; // symbol_idx
2978 
2979  int bits = MACH0_(get_bits_from_hdr)(&bin->hdr);
2980  if (bin->symtab && bin->symstr) {
2981  /* parse dynamic symbol table */
2982  symbols_count = (bin->dysymtab.nextdefsym +
2983  bin->dysymtab.nlocalsym +
2984  bin->dysymtab.nundefsym);
2985  symbols_count += bin->nsymtab;
2986  if (symbols_count < 0 || ((st64)symbols_count * 2) > ST32_MAX) {
2987  eprintf("Symbols count overflow\n");
2988  ht_pp_free(hash);
2989  return NULL;
2990  }
2991  symbols_size = (symbols_count + 1) * 2 * sizeof(struct symbol_t);
2992 
2993  if (symbols_size < 1) {
2994  ht_pp_free(hash);
2995  return NULL;
2996  }
2997  if (!(symbols = calloc(1, symbols_size))) {
2998  ht_pp_free(hash);
2999  return NULL;
3000  }
3001  bin->main_addr = 0;
3002  for (s = 0; s < 2; s++) {
3003  switch (s) {
3004  case 0:
3005  from = bin->dysymtab.iextdefsym;
3006  to = from + bin->dysymtab.nextdefsym;
3007  break;
3008  case 1:
3009  from = bin->dysymtab.ilocalsym;
3010  to = from + bin->dysymtab.nlocalsym;
3011  break;
3012 #if NOT_USED
3013  case 2:
3014  from = bin->dysymtab.iundefsym;
3015  to = from + bin->dysymtab.nundefsym;
3016  break;
3017 #endif
3018  }
3019  if (from == to) {
3020  continue;
3021  }
3022 
3023  from = RZ_MIN(RZ_MAX(0, from), symbols_size / sizeof(struct symbol_t));
3024  to = RZ_MIN(RZ_MIN(to, bin->nsymtab), symbols_size / sizeof(struct symbol_t));
3025 
3026  ut32 maxsymbols = symbols_size / sizeof(struct symbol_t);
3027  if (symbols_count >= maxsymbols) {
3028  symbols_count = maxsymbols - 1;
3029  eprintf("macho warning: Symbol table truncated\n");
3030  }
3031  for (i = from; i < to && j < symbols_count; i++, j++) {
3032  symbols[j].offset = MACH0_(vaddr_to_paddr)(bin, bin->symtab[i].n_value);
3033  symbols[j].addr = bin->symtab[i].n_value;
3034  symbols[j].size = 0; /* TODO: Is it anywhere? */
3035  symbols[j].bits = bin->symtab[i].n_desc & N_ARM_THUMB_DEF ? 16 : bits;
3036  symbols[j].is_imported = false;
3037  symbols[j].type = (bin->symtab[i].n_type & N_EXT)
3040  stridx = bin->symtab[i].n_strx;
3041  symbols[j].name = MACH0_(get_name)(bin, stridx, false);
3042  symbols[j].last = false;
3043 
3044  const char *name = symbols[j].name;
3045  if (bin->main_addr == 0 && name) {
3046  if (!strcmp(name, "__Dmain")) {
3047  bin->main_addr = symbols[j].addr;
3048  } else if (strstr(name, "4main") && !strstr(name, "STATIC")) {
3049  bin->main_addr = symbols[j].addr;
3050  } else if (!strcmp(name, "_main")) {
3051  bin->main_addr = symbols[j].addr;
3052  } else if (!strcmp(name, "main")) {
3053  bin->main_addr = symbols[j].addr;
3054  }
3055  }
3056  if (inSymtab(hash, symbols[j].name, symbols[j].addr)) {
3057  free(symbols[j].name);
3058  symbols[j].name = NULL;
3059  j--;
3060  }
3061  }
3062  }
3063  to = RZ_MIN((ut32)bin->nsymtab, bin->dysymtab.iundefsym + bin->dysymtab.nundefsym);
3064  for (i = bin->dysymtab.iundefsym; i < to; i++) {
3065  if (j > symbols_count) {
3066  bprintf("mach0-get-symbols: error\n");
3067  break;
3068  }
3069  if (parse_import_stub(bin, &symbols[j], i)) {
3070  symbols[j++].last = false;
3071  }
3072  }
3073 
3074  for (i = 0; i < bin->nsymtab && i < symbols_count; i++) {
3075  struct MACH0_(nlist) *st = &bin->symtab[i];
3076  if (st->n_type & N_STAB) {
3077  continue;
3078  }
3079  // 0 is for imports
3080  // 1 is for symbols
3081  // 2 is for func.eh (exception handlers?)
3082  int section = st->n_sect;
3083  if (section == 1 && j < symbols_count) {
3084  // check if symbol exists already
3085  /* is symbol */
3086  symbols[j].addr = st->n_value;
3087  symbols[j].offset = MACH0_(vaddr_to_paddr)(bin, symbols[j].addr);
3088  symbols[j].size = 0; /* find next symbol and crop */
3089  symbols[j].type = (st->n_type & N_EXT)
3092  char *sym_name = MACH0_(get_name)(bin, st->n_strx, false);
3093  if (sym_name) {
3094  symbols[j].name = sym_name;
3095  } else {
3096  symbols[j].name = rz_str_newf("entry%d", i);
3097  }
3098  symbols[j].last = 0;
3099  if (inSymtab(hash, symbols[j].name, symbols[j].addr)) {
3100  RZ_FREE(symbols[j].name);
3101  } else {
3102  j++;
3103  }
3104 
3105  const char *name = symbols[i].name;
3106  if (bin->main_addr == 0 && name) {
3107  if (name && !strcmp(name, "__Dmain")) {
3108  bin->main_addr = symbols[i].addr;
3109  } else if (name && strstr(name, "4main") && !strstr(name, "STATIC")) {
3110  bin->main_addr = symbols[i].addr;
3111  } else if (symbols[i].name && !strcmp(symbols[i].name, "_main")) {
3112  bin->main_addr = symbols[i].addr;
3113  }
3114  }
3115  }
3116  }
3117  } else if (!n_exports) {
3118  ht_pp_free(hash);
3119  return NULL;
3120  } else {
3121  symbols_size = (symbols_count + 1) * sizeof(struct symbol_t);
3122  if (symbols_size < 1) {
3123  ht_pp_free(hash);
3124  return NULL;
3125  }
3126  if (!(symbols = calloc(1, symbols_size))) {
3127  ht_pp_free(hash);
3128  return NULL;
3129  }
3130  }
3131  if (n_exports && (symbols_count - j) >= n_exports) {
3132  RSymCtx sym_ctx;
3133  sym_ctx.symbols = symbols;
3134  sym_ctx.j = j;
3135  sym_ctx.symbols_count = symbols_count;
3136  sym_ctx.hash = hash;
3138  j = sym_ctx.j;
3139  }
3140  ht_pp_free(hash);
3141  symbols[j].last = true;
3142  bin->symbols = symbols;
3143  return symbols;
3144 }
RzList * symbols(RzBinFile *bf)
Definition: bin_ne.c:102
uint32_t ut32
static int walk_exports(struct MACH0_(obj_t) *bin, RExportsIterator iterator, void *ctx)
Definition: mach0.c:2586
static bool parse_import_stub(struct MACH0_(obj_t) *bin, struct symbol_t *symbol, int idx)
Definition: mach0.c:2477
static void assign_export_symbol_t(struct MACH0_(obj_t) *bin, const char *name, ut64 flags, ut64 offset, void *ctx)
Definition: mach0.c:2943
@ N_STAB
@ N_EXT
@ N_ARM_THUMB_DEF
#define RZ_BIN_MACH0_SYMBOL_TYPE_LOCAL
Definition: mach0_specs.h:26
#define RZ_FREE(x)
Definition: rz_types.h:369
#define st64
Definition: rz_types_base.h:10
#define ST32_MAX
Definition: rz_types_base.h:97
#define RZ_MAX(x, y)
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
int symbols_count
Definition: mach0.c:24
Definition: mach0.h:54

References addr, assign_export_symbol_t(), bits(), bprintf, calloc(), eprintf, free(), from, get_bits_from_hdr(), get_name(), RSymCtx::hash, i, inSymtab(), RSymCtx::j, MACH0_(), N_ARM_THUMB_DEF, N_EXT, N_STAB, NULL, parse_import_stub(), RZ_BIN_MACH0_SYMBOL_TYPE_EXT, RZ_BIN_MACH0_SYMBOL_TYPE_LOCAL, RZ_FREE, RZ_MAX, RZ_MIN, rz_return_val_if_fail, rz_str_newf(), s, ST32_MAX, st64, RSymCtx::symbols, symbols(), RSymCtx::symbols_count, to, vaddr_to_paddr(), and walk_exports().

Referenced by get_main(), symbols(), symbols_from_bin(), and symbols_from_mach0().

◆ get_symbols_list()

const RzList* MACH0_() get_symbols_list ( struct MACH0_(obj_t) *  bin)

Definition at line 2761 of file mach0.c.

2761  {
2762  static RzList *cache = NULL; // XXX DONT COMMIT WITH THIS
2763  struct symbol_t *symbols;
2764  size_t j, s, symbols_size, symbols_count;
2765  ut32 to, from;
2766  size_t i;
2767 
2769  if (cache) {
2770  return cache;
2771  }
2773  cache = list;
2774 
2775  HtPP *hash = ht_pp_new0();
2776  if (!hash) {
2777  return NULL;
2778  }
2779 
2781  if (rz_list_length(list)) {
2782  RzListIter *it;
2783  RzBinSymbol *s;
2784  rz_list_foreach (list, it, s) {
2785  inSymtab(hash, s->name, s->vaddr);
2786  }
2787  }
2788 
2789  if (!bin->symtab || !bin->symstr) {
2790  ht_pp_free(hash);
2791  return list;
2792  }
2793  /* parse dynamic symbol table */
2794  symbols_count = (bin->dysymtab.nextdefsym +
2795  bin->dysymtab.nlocalsym +
2796  bin->dysymtab.nundefsym);
2797  symbols_count += bin->nsymtab;
2798  symbols_size = (symbols_count + 1) * 2 * sizeof(struct symbol_t);
2799 
2800  if (symbols_size < 1) {
2801  return NULL;
2802  }
2803  if (!(symbols = calloc(1, symbols_size))) {
2804  return NULL;
2805  }
2806  j = 0; // symbol_idx
2807  bin->main_addr = 0;
2808  int bits = MACH0_(get_bits_from_hdr)(&bin->hdr);
2809  for (s = 0; s < 2; s++) {
2810  switch (s) {
2811  case 0:
2812  from = bin->dysymtab.iextdefsym;
2813  to = from + bin->dysymtab.nextdefsym;
2814  break;
2815  case 1:
2816  from = bin->dysymtab.ilocalsym;
2817  to = from + bin->dysymtab.nlocalsym;
2818  break;
2819 #if NOT_USED
2820  case 2:
2821  from = bin->dysymtab.iundefsym;
2822  to = from + bin->dysymtab.nundefsym;
2823  break;
2824 #endif
2825  }
2826  if (from == to) {
2827  continue;
2828  }
2829 
2830  from = RZ_MIN(RZ_MAX(0, from), symbols_size / sizeof(struct symbol_t));
2831  to = RZ_MIN(RZ_MIN(to, bin->nsymtab), symbols_size / sizeof(struct symbol_t));
2832 
2833  ut32 maxsymbols = symbols_size / sizeof(struct symbol_t);
2834  if (symbols_count >= maxsymbols) {
2835  symbols_count = maxsymbols - 1;
2836  eprintf("macho warning: Symbol table truncated\n");
2837  }
2838  for (i = from; i < to && j < symbols_count; i++, j++) {
2840  sym->vaddr = bin->symtab[i].n_value;
2841  sym->paddr = MACH0_(vaddr_to_paddr)(bin, sym->vaddr);
2842  symbols[j].size = 0; /* TODO: Is it anywhere? */
2843  sym->bits = bin->symtab[i].n_desc & N_ARM_THUMB_DEF ? 16 : bits;
2844 
2845  if (bin->symtab[i].n_type & N_EXT) {
2846  sym->type = "EXT";
2847  } else {
2848  sym->type = "LOCAL";
2849  }
2850  int stridx = bin->symtab[i].n_strx;
2851  char *sym_name = MACH0_(get_name)(bin, stridx, false);
2852  if (sym_name) {
2853  sym->name = sym_name;
2854  if (!bin->main_addr || bin->main_addr == UT64_MAX) {
2855  const char *name = sym->name;
2856  if (!strcmp(name, "__Dmain")) {
2857  bin->main_addr = symbols[j].addr;
2858  } else if (strstr(name, "4main") && !strstr(name, "STATIC")) {
2859  bin->main_addr = symbols[j].addr;
2860  } else if (!strcmp(name, "_main")) {
2861  bin->main_addr = symbols[j].addr;
2862  } else if (!strcmp(name, "main")) {
2863  bin->main_addr = symbols[j].addr;
2864  }
2865  }
2866  } else {
2867  sym->name = rz_str_newf("unk%zu", i);
2868  }
2869  if (!inSymtab(hash, sym->name, sym->vaddr)) {
2870  rz_list_append(list, sym);
2871  } else {
2872  rz_bin_symbol_free(sym);
2873  }
2874  }
2875  }
2876  to = RZ_MIN((ut32)bin->nsymtab, bin->dysymtab.iundefsym + bin->dysymtab.nundefsym);
2877  for (i = bin->dysymtab.iundefsym; i < to; i++) {
2878  struct symbol_t symbol;
2879  if (j > symbols_count) {
2880  bprintf("mach0-get-symbols: error\n");
2881  break;
2882  }
2883  if (parse_import_stub(bin, &symbol, i)) {
2884  j++;
2886  sym->vaddr = symbol.addr;
2887  sym->paddr = symbol.offset;
2888  sym->name = symbol.name;
2889  if (!sym->name) {
2890  sym->name = rz_str_newf("unk%zu", i);
2891  }
2892  sym->is_imported = symbol.is_imported;
2893  rz_list_append(list, sym);
2894  }
2895  }
2896 
2897  for (i = 0; i < bin->nsymtab; i++) {
2898  struct MACH0_(nlist) *st = &bin->symtab[i];
2899  // 0 is for imports
2900  // 1 is for symbols
2901  // 2 is for func.eh (exception handlers?)
2902  int section = st->n_sect;
2903  if (section == 1 && j < symbols_count) { // text ??st->n_type == 1) maybe wrong
2905  /* is symbol */
2906  sym->vaddr = st->n_value;
2907  sym->paddr = MACH0_(vaddr_to_paddr)(bin, symbols[j].addr);
2908  sym->is_imported = symbols[j].is_imported;
2909  if (st->n_type & N_EXT) {
2910  sym->type = "EXT";
2911  } else {
2912  sym->type = "LOCAL";
2913  }
2914  char *sym_name = MACH0_(get_name)(bin, st->n_strx, false);
2915  if (sym_name) {
2916  sym->name = sym_name;
2917  if (inSymtab(hash, sym->name, sym->vaddr)) {
2918  rz_bin_symbol_free(sym);
2919  continue;
2920  }
2921  if (!bin->main_addr || bin->main_addr == UT64_MAX) {
2922  const char *name = sym->name;
2923  if (!strcmp(name, "__Dmain")) {
2924  bin->main_addr = symbols[i].addr;
2925  } else if (strstr(name, "4main") && !strstr(name, "STATIC")) {
2926  bin->main_addr = symbols[i].addr;
2927  } else if (!strcmp(symbols[i].name, "_main")) {
2928  bin->main_addr = symbols[i].addr;
2929  }
2930  }
2931  } else {
2932  sym->name = rz_str_newf("unk%zu", i);
2933  }
2934  rz_list_append(list, sym);
2935  j++;
2936  }
2937  }
2938  ht_pp_free(hash);
2939  free(symbols);
2940  return list;
2941 }
RZ_API void rz_bin_symbol_free(RzBinSymbol *sym)
Definition: bin.c:175
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
static void fill_exports_list(struct MACH0_(obj_t) *bin, const char *name, ut64 flags, ut64 offset, void *ctx)
Definition: mach0.c:2746
bool is_imported
Definition: rz_bin.h:684

References symbol_t::addr, rz_bin_symbol_t::bits, bits(), bprintf, calloc(), eprintf, fill_exports_list(), free(), from, get_bits_from_hdr(), get_name(), i, inSymtab(), symbol_t::is_imported, rz_bin_symbol_t::is_imported, list(), MACH0_(), N_ARM_THUMB_DEF, N_EXT, symbol_t::name, rz_bin_symbol_t::name, NULL, symbol_t::offset, rz_bin_symbol_t::paddr, parse_import_stub(), rz_bin_symbol_free(), rz_list_append(), rz_list_length(), rz_list_newf(), RZ_MAX, RZ_MIN, RZ_NEW0, rz_return_val_if_fail, rz_str_newf(), s, symbols(), to, rz_bin_symbol_t::type, UT64_MAX, rz_bin_symbol_t::vaddr, vaddr_to_paddr(), and walk_exports().

Referenced by get_main().

◆ get_virtual_files()

RzList* MACH0_() get_virtual_files ( RzBinFile bf)

Definition at line 2162 of file mach0.c.

2162  {
2165  if (!ret) {
2166  return NULL;
2167  }
2168 
2169  // rebasing+stripping for arm64e
2170  struct MACH0_(obj_t) *obj = bf->o->bin_obj;
2173  if (!vf) {
2174  return ret;
2175  }
2177  vf->buf_owned = true;
2179  rz_list_push(ret, vf);
2180  }
2181 
2182  // clang-format off
2183  // relocs
2184  MACH0_(patch_relocs)(bf, obj);
2185  // clang-format: on
2186  // virtual file for reloc targets (where the relocs will point into)
2187  ut64 rtmsz = MACH0_(reloc_targets_vfile_size)(obj);
2188  if (rtmsz) {
2189  RzBuffer *buf = rz_buf_new_empty(rtmsz);
2190  if (!buf) {
2191  return ret;
2192  }
2194  if (!vf) {
2195  rz_buf_free(buf);
2196  return ret;
2197  }
2198  vf->buf = buf;
2199  vf->buf_owned = true;
2201  rz_list_push(ret, vf);
2202  }
2203  // virtual file mirroring the raw file, but with relocs patched
2204  if (obj->buf_patched) {
2206  if (!vf) {
2207  return ret;
2208  }
2209  vf->buf = obj->buf_patched;
2210  vf->buf_owned = false;
2212  rz_list_push(ret, vf);
2213  }
2214  return ret;
2215 }
RZ_API void rz_bin_virtual_file_free(RzBinVirtualFile *vfile)
Definition: bin.c:1012
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
RZ_API RzBuffer *MACH0_() new_rebasing_and_stripping_buf(struct MACH0_(obj_t) *obj)
Definition: mach0_rebase.c:224
RZ_API bool MACH0_() needs_rebasing_and_stripping(struct MACH0_(obj_t) *obj)
Definition: mach0_rebase.c:228
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
RZ_API RZ_OWN RzBuffer * rz_buf_new_empty(ut64 len)
Creates a new empty buffer with a predefined size;.
Definition: buf.c:285
RZ_NONNULL RzBuffer * buf
Definition: rz_bin.h:597
bool buf_owned
whether buf is owned and freed by this RzBinVirtualFile
Definition: rz_bin.h:598
RZ_OWN RZ_NONNULL char * name
Definition: rz_bin.h:596

References rz_bin_virtual_file_t::buf, rz_bin_virtual_file_t::buf_owned, MACH0_(), MACH0_VFILE_NAME_PATCHED, MACH0_VFILE_NAME_REBASED_STRIPPED, MACH0_VFILE_NAME_RELOC_TARGETS, rz_bin_virtual_file_t::name, needs_rebasing_and_stripping(), new_rebasing_and_stripping_buf(), NULL, patch_relocs(), reloc_targets_vfile_size(), rz_bin_virtual_file_free(), rz_buf_free(), rz_buf_new_empty(), rz_list_newf(), rz_list_push(), RZ_NEW0, rz_return_val_if_fail, strdup(), and ut64().

Referenced by virtual_files().

◆ has_nx()

bool MACH0_() has_nx ( struct MACH0_(obj_t) *  bin)

Definition at line 3554 of file mach0.c.

3554  {
3555  return (bin && bin->hdr.filetype == MH_EXECUTE &&
3556  bin->hdr.flags & MH_NO_HEAP_EXECUTION);
3557 }
@ MH_NO_HEAP_EXECUTION

References MH_EXECUTE, and MH_NO_HEAP_EXECUTION.

Referenced by info().

◆ init()

static bool init ( struct MACH0_(obj_t) *  mo)
static

Definition at line 2046 of file mach0.c.

2046  {
2047  if (!init_hdr(mo)) {
2048  return false;
2049  }
2050  if (!init_items(mo)) {
2051  Eprintf("Warning: Cannot initialize items\n");
2052  }
2053  mo->baddr = MACH0_(get_baddr)(mo);
2054  return true;
2055 }
#define Eprintf
Definition: mach0.c:17
static bool init_hdr(struct MACH0_(obj_t) *bin)
Definition: mach0.c:234
static int init_items(struct MACH0_(obj_t) *bin)
Definition: mach0.c:1678
ut64 MACH0_() get_baddr(struct MACH0_(obj_t) *bin)
Definition: mach0.c:3262

References Eprintf, get_baddr(), init_hdr(), init_items(), and MACH0_().

◆ init_hdr()

static bool init_hdr ( struct MACH0_(obj_t) *  bin)
static

Definition at line 234 of file mach0.c.

234  {
235  ut8 magicbytes[4] = { 0 };
236  ut8 machohdrbytes[sizeof(struct MACH0_(mach_header))] = { 0 };
237  int len;
238 
239  if (rz_buf_read_at(bin->b, 0 + bin->options.header_at, magicbytes, 4) < 1) {
240  return false;
241  }
242  if (rz_read_le32(magicbytes) == 0xfeedface) {
243  bin->big_endian = false;
244  } else if (rz_read_be32(magicbytes) == 0xfeedface) {
245  bin->big_endian = true;
246  } else if (rz_read_le32(magicbytes) == FAT_MAGIC) {
247  bin->big_endian = false;
248  } else if (rz_read_be32(magicbytes) == FAT_MAGIC) {
249  bin->big_endian = true;
250  } else if (rz_read_le32(magicbytes) == 0xfeedfacf) {
251  bin->big_endian = false;
252  } else if (rz_read_be32(magicbytes) == 0xfeedfacf) {
253  bin->big_endian = true;
254  } else {
255  return false; // object files are magic == 0, but body is different :?
256  }
257  len = rz_buf_read_at(bin->b, 0 + bin->options.header_at, machohdrbytes, sizeof(machohdrbytes));
258  if (len != sizeof(machohdrbytes)) {
259  bprintf("Error: read (hdr)\n");
260  return false;
261  }
262  bin->hdr.magic = rz_read_ble(&machohdrbytes[0], bin->big_endian, 32);
263  bin->hdr.cputype = rz_read_ble(&machohdrbytes[4], bin->big_endian, 32);
264  bin->hdr.cpusubtype = rz_read_ble(&machohdrbytes[8], bin->big_endian, 32);
265  bin->hdr.filetype = rz_read_ble(&machohdrbytes[12], bin->big_endian, 32);
266  bin->hdr.ncmds = rz_read_ble(&machohdrbytes[16], bin->big_endian, 32);
267  bin->hdr.sizeofcmds = rz_read_ble(&machohdrbytes[20], bin->big_endian, 32);
268  bin->hdr.flags = rz_read_ble(&machohdrbytes[24], bin->big_endian, 32);
269 #if RZ_BIN_MACH064
270  bin->hdr.reserved = rz_read_ble(&machohdrbytes[28], bin->big_endian, 32);
271 #endif
273  sdb_num_set(bin->kv, "mach0_header.offset", 0, 0); // wat about fatmach0?
274  return true;
275 }
static void init_sdb_formats(struct MACH0_(obj_t) *bin)
Definition: mach0.c:91
@ FAT_MAGIC
Definition: mach0_defines.h:65
static ut64 rz_read_ble(const void *src, bool big_endian, int size)
Definition: rz_endian.h:517

References bprintf, FAT_MAGIC, init_sdb_formats(), len, rz_buf_read_at(), rz_read_be32(), rz_read_ble(), rz_read_le32(), and sdb_num_set().

Referenced by init().

◆ init_items()

static int init_items ( struct MACH0_(obj_t) *  bin)
static

Definition at line 1678 of file mach0.c.

1678  {
1679  struct load_command lc = { 0, 0 };
1680  ut8 loadc[sizeof(struct load_command)] = { 0 };
1681  bool is_first_thread = true;
1682  ut64 off = 0LL;
1683  int i, len;
1684 
1685  bin->uuidn = 0;
1686  bin->os = 0;
1687  bin->has_crypto = 0;
1688  if (bin->hdr.sizeofcmds > bin->size) {
1689  bprintf("Warning: chopping hdr.sizeofcmds\n");
1690  bin->hdr.sizeofcmds = bin->size - 128;
1691  // return false;
1692  }
1693  // bprintf ("Commands: %d\n", bin->hdr.ncmds);
1694  for (i = 0, off = sizeof(struct MACH0_(mach_header)) + bin->options.header_at;
1695  i < bin->hdr.ncmds; i++, off += lc.cmdsize) {
1696  if (off > bin->size || off + sizeof(struct load_command) > bin->size) {
1697  bprintf("mach0: out of bounds command\n");
1698  return false;
1699  }
1700  len = rz_buf_read_at(bin->b, off, loadc, sizeof(struct load_command));
1701  if (len < 1) {
1702  bprintf("Error: read (lc) at 0x%08" PFMT64x "\n", off);
1703  return false;
1704  }
1705  lc.cmd = rz_read_ble32(&loadc[0], bin->big_endian);
1706  lc.cmdsize = rz_read_ble32(&loadc[4], bin->big_endian);
1707 
1708  if (lc.cmdsize < 1 || off + lc.cmdsize > bin->size) {
1709  bprintf("Warning: mach0_header %d = cmdsize<1. (0x%llx vs 0x%llx)\n", i,
1710  (ut64)(off + lc.cmdsize), (ut64)(bin->size));
1711  break;
1712  }
1713 
1714  sdb_num_set(bin->kv, sdb_fmt("mach0_cmd_%d.offset", i), off, 0);
1715  const char *format_name = cmd_to_pf_definition(lc.cmd);
1716  if (format_name) {
1717  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.format", i), format_name, 0);
1718  } else {
1719  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.format", i), "[4]Ed (mach_load_command_type)cmd size", 0);
1720  }
1721 
1722  switch (lc.cmd) {
1723  case LC_DATA_IN_CODE:
1724  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "data_in_code", 0);
1725  break;
1726  case LC_RPATH:
1727  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "rpath", 0);
1728  // bprintf ("--->\n");
1729  break;
1730  case LC_SEGMENT_64:
1731  case LC_SEGMENT:
1732  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "segment", 0);
1733  bin->nsegs++;
1734  if (!parse_segments(bin, off)) {
1735  bprintf("error parsing segment\n");
1736  bin->nsegs--;
1737  return false;
1738  }
1739  break;
1740  case LC_SYMTAB:
1741  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "symtab", 0);
1742  if (!parse_symtab(bin, off)) {
1743  bprintf("error parsing symtab\n");
1744  return false;
1745  }
1746  break;
1747  case LC_DYSYMTAB:
1748  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "dysymtab", 0);
1749  if (!parse_dysymtab(bin, off)) {
1750  bprintf("error parsing dysymtab\n");
1751  return false;
1752  }
1753  break;
1755  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "dylib_code_sign_drs", 0);
1756  // bprintf ("[mach0] code is signed\n");
1757  break;
1758  case LC_VERSION_MIN_MACOSX:
1759  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "version_min_macosx", 0);
1760  bin->os = 1;
1761  // set OS = osx
1762  // bprintf ("[mach0] Requires OSX >= x\n");
1763  break;
1765  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "version_min_iphoneos", 0);
1766  bin->os = 2;
1767  // set OS = ios
1768  // bprintf ("[mach0] Requires iOS >= x\n");
1769  break;
1770  case LC_VERSION_MIN_TVOS:
1771  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "version_min_tvos", 0);
1772  bin->os = 4;
1773  break;
1775  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "version_min_watchos", 0);
1776  bin->os = 3;
1777  break;
1778  case LC_UUID:
1779  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "uuid", 0);
1780  {
1781  struct uuid_command uc = { 0 };
1782  if (off + sizeof(struct uuid_command) > bin->size) {
1783  bprintf("UUID out of bounds\n");
1784  return false;
1785  }
1786  if (rz_buf_fread_at(bin->b, off, (ut8 *)&uc, "24c", 1) != -1) {
1787  char key[128];
1788  char val[128];
1789  snprintf(key, sizeof(key) - 1, "uuid.%d", bin->uuidn++);
1790  rz_hex_bin2str((ut8 *)&uc.uuid, 16, val);
1791  sdb_set(bin->kv, key, val, 0);
1792  // for (i=0;i<16; i++) bprintf ("%02x%c", uc.uuid[i], (i==15)?'\n':'-');
1793  }
1794  }
1795  break;
1796  case LC_ENCRYPTION_INFO_64:
1797  /* TODO: the struct is probably different here */
1798  case LC_ENCRYPTION_INFO:
1799  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "encryption_info", 0);
1800  {
1801  struct MACH0_(encryption_info_command) eic = { 0 };
1802  ut8 seic[sizeof(struct MACH0_(encryption_info_command))] = { 0 };
1803  if (off + sizeof(struct MACH0_(encryption_info_command)) > bin->size) {
1804  bprintf("encryption info out of bounds\n");
1805  return false;
1806  }
1807  if (rz_buf_read_at(bin->b, off, seic, sizeof(struct MACH0_(encryption_info_command))) != -1) {
1808  eic.cmd = rz_read_ble32(&seic[0], bin->big_endian);
1809  eic.cmdsize = rz_read_ble32(&seic[4], bin->big_endian);
1810  eic.cryptoff = rz_read_ble32(&seic[8], bin->big_endian);
1811  eic.cryptsize = rz_read_ble32(&seic[12], bin->big_endian);
1812  eic.cryptid = rz_read_ble32(&seic[16], bin->big_endian);
1813 
1814  bin->has_crypto = eic.cryptid;
1815  sdb_set(bin->kv, "crypto", "true", 0);
1816  sdb_num_set(bin->kv, "cryptid", eic.cryptid, 0);
1817  sdb_num_set(bin->kv, "cryptoff", eic.cryptoff, 0);
1818  sdb_num_set(bin->kv, "cryptsize", eic.cryptsize, 0);
1819  sdb_num_set(bin->kv, "cryptheader", off, 0);
1820  }
1821  }
1822  break;
1823  case LC_LOAD_DYLINKER: {
1824  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "dylinker", 0);
1825  RZ_FREE(bin->intrp);
1826  // bprintf ("[mach0] load dynamic linker\n");
1827  struct dylinker_command dy = { 0 };
1828  ut8 sdy[sizeof(struct dylinker_command)] = { 0 };
1829  if (off + sizeof(struct dylinker_command) > bin->size) {
1830  bprintf("Warning: Cannot parse dylinker command\n");
1831  return false;
1832  }
1833  if (rz_buf_read_at(bin->b, off, sdy, sizeof(struct dylinker_command)) == -1) {
1834  bprintf("Warning: read (LC_DYLD_INFO) at 0x%08" PFMT64x "\n", off);
1835  } else {
1836  dy.cmd = rz_read_ble32(&sdy[0], bin->big_endian);
1837  dy.cmdsize = rz_read_ble32(&sdy[4], bin->big_endian);
1838  dy.name = rz_read_ble32(&sdy[8], bin->big_endian);
1839 
1840  int len = dy.cmdsize;
1841  char *buf = malloc(len + 1);
1842  if (buf) {
1843  // wtf @ off + 0xc ?
1844  rz_buf_read_at(bin->b, off + 0xc, (ut8 *)buf, len);
1845  buf[len] = 0;
1846  free(bin->intrp);
1847  bin->intrp = buf;
1848  }
1849  }
1850  } break;
1851  case LC_MAIN: {
1852  struct {
1853  ut64 eo;
1854  ut64 ss;
1855  } ep = { 0 };
1856  ut8 sep[2 * sizeof(ut64)] = { 0 };
1857  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "main", 0);
1858 
1859  if (!is_first_thread) {
1860  bprintf("Error: LC_MAIN with other threads\n");
1861  return false;
1862  }
1863  if (off + 8 > bin->size || off + sizeof(ep) > bin->size) {
1864  bprintf("invalid command size for main\n");
1865  return false;
1866  }
1867  rz_buf_read_at(bin->b, off + 8, sep, 2 * sizeof(ut64));
1868  ep.eo = rz_read_ble64(&sep[0], bin->big_endian);
1869  ep.ss = rz_read_ble64(&sep[8], bin->big_endian);
1870 
1871  bin->entry = ep.eo;
1872  bin->main_cmd = lc;
1873 
1874  sdb_num_set(bin->kv, "mach0.entry.offset", off + 8, 0);
1875  sdb_num_set(bin->kv, "stacksize", ep.ss, 0);
1876 
1877  is_first_thread = false;
1878  } break;
1879  case LC_UNIXTHREAD:
1880  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "unixthread", 0);
1881  if (!is_first_thread) {
1882  bprintf("Error: LC_UNIXTHREAD with other threads\n");
1883  return false;
1884  }
1885  // fallthrough
1886  case LC_THREAD:
1887  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "thread", 0);
1888  if (!parse_thread(bin, &lc, off, is_first_thread)) {
1889  bprintf("Cannot parse thread\n");
1890  return false;
1891  }
1892  is_first_thread = false;
1893  break;
1894  case LC_LOAD_DYLIB:
1895  case LC_LOAD_WEAK_DYLIB:
1896  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "load_dylib", 0);
1897  bin->nlibs++;
1898  if (!parse_dylib(bin, off)) {
1899  bprintf("Cannot parse dylib\n");
1900  bin->nlibs--;
1901  return false;
1902  }
1903  break;
1904  case LC_DYLD_INFO:
1905  case LC_DYLD_INFO_ONLY: {
1906  ut8 dyldi[sizeof(struct dyld_info_command)] = { 0 };
1907  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "dyld_info", 0);
1908  bin->dyld_info = calloc(1, sizeof(struct dyld_info_command));
1909  if (bin->dyld_info) {
1910  if (off + sizeof(struct dyld_info_command) > bin->size) {
1911  bprintf("Cannot parse dyldinfo\n");
1912  RZ_FREE(bin->dyld_info);
1913  return false;
1914  }
1915  if (rz_buf_read_at(bin->b, off, dyldi, sizeof(struct dyld_info_command)) == -1) {
1916  RZ_FREE(bin->dyld_info);
1917  bprintf("Error: read (LC_DYLD_INFO) at 0x%08" PFMT64x "\n", off);
1918  } else {
1919  bin->dyld_info->cmd = rz_read_ble32(&dyldi[0], bin->big_endian);
1920  bin->dyld_info->cmdsize = rz_read_ble32(&dyldi[4], bin->big_endian);
1921  bin->dyld_info->rebase_off = rz_read_ble32(&dyldi[8], bin->big_endian);
1922  bin->dyld_info->rebase_size = rz_read_ble32(&dyldi[12], bin->big_endian);
1923  bin->dyld_info->bind_off = rz_read_ble32(&dyldi[16], bin->big_endian);
1924  bin->dyld_info->bind_size = rz_read_ble32(&dyldi[20], bin->big_endian);
1925  bin->dyld_info->weak_bind_off = rz_read_ble32(&dyldi[24], bin->big_endian);
1926  bin->dyld_info->weak_bind_size = rz_read_ble32(&dyldi[28], bin->big_endian);
1927  bin->dyld_info->lazy_bind_off = rz_read_ble32(&dyldi[32], bin->big_endian);
1928  bin->dyld_info->lazy_bind_size = rz_read_ble32(&dyldi[36], bin->big_endian);
1929  bin->dyld_info->export_off = rz_read_ble32(&dyldi[40], bin->big_endian) + bin->options.symbols_off;
1930  bin->dyld_info->export_size = rz_read_ble32(&dyldi[44], bin->big_endian);
1931  }
1932  }
1933  } break;
1934  case LC_CODE_SIGNATURE:
1936  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "signature", 0);
1937  /* ut32 dataoff
1938  // ut32 datasize */
1939  break;
1940  case LC_SOURCE_VERSION:
1941  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "version", 0);
1942  /* uint64_t version; */
1943  /* A.B.C.D.E packed as a24.b10.c10.d10.e10 */
1944  // bprintf ("mach0: TODO: Show source version\n");
1945  break;
1946  case LC_SEGMENT_SPLIT_INFO:
1947  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "split_info", 0);
1948  /* TODO */
1949  break;
1950  case LC_FUNCTION_STARTS:
1951  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "function_starts", 0);
1952  if (!parse_function_starts(bin, off)) {
1953  bprintf("Cannot parse LC_FUNCTION_STARTS\n");
1954  }
1955  break;
1956  case LC_REEXPORT_DYLIB:
1957  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "dylib", 0);
1958  /* TODO */
1959  break;
1960  default:
1961  // bprintf ("mach0: Unknown header command %x\n", lc.cmd);
1962  break;
1963  }
1964  }
1965  bool has_chained_fixups = false;
1966  for (i = 0, off = sizeof(struct MACH0_(mach_header)) + bin->options.header_at;
1967  i < bin->hdr.ncmds; i++, off += lc.cmdsize) {
1968  len = rz_buf_read_at(bin->b, off, loadc, sizeof(struct load_command));
1969  if (len < 1) {
1970  bprintf("Error: read (lc) at 0x%08" PFMT64x "\n", off);
1971  return false;
1972  }
1973  lc.cmd = rz_read_ble32(&loadc[0], bin->big_endian);
1974  lc.cmdsize = rz_read_ble32(&loadc[4], bin->big_endian);
1975 
1976  if (lc.cmdsize < 1 || off + lc.cmdsize > bin->size) {
1977  bprintf("Warning: mach0_header %d = cmdsize<1. (0x%llx vs 0x%llx)\n", i,
1978  (ut64)(off + lc.cmdsize), (ut64)(bin->size));
1979  break;
1980  }
1981 
1982  sdb_num_set(bin->kv, sdb_fmt("mach0_cmd_%d.offset", i), off, 0);
1983  const char *format_name = cmd_to_pf_definition(lc.cmd);
1984  if (format_name) {
1985  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.format", i), format_name, 0);
1986  } else {
1987  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.format", i), "[4]Ed (mach_load_command_type)cmd size", 0);
1988  }
1989 
1990  switch (lc.cmd) {
1991  case LC_DATA_IN_CODE:
1992  sdb_set(bin->kv, sdb_fmt("mach0_cmd_%d.cmd", i), "data_in_code", 0);
1993  if (bin->options.verbose) {
1994  ut8 buf[8];
1995  rz_buf_read_at(bin->b, off + 8, buf, sizeof(buf));
1996  ut32 dataoff = rz_read_ble32(buf, bin->big_endian);
1997  ut32 datasize = rz_read_ble32(buf + 4, bin->big_endian);
1998  eprintf("data-in-code at 0x%x size %d\n", dataoff, datasize);
1999  ut8 *db = (ut8 *)malloc(datasize);
2000  if (db) {
2001  rz_buf_read_at(bin->b, dataoff, db, datasize);
2002  // TODO table of non-instructions regions in __text
2003  int j;
2004  for (j = 0; j < datasize; j += 8) {
2005  ut32 dw = rz_read_ble32(db + j, bin->big_endian);
2006  // int kind = rz_read_ble16 (db + i + 4 + 2, bin->big_endian);
2007  int len = rz_read_ble16(db + j + 4, bin->big_endian);
2008  ut64 va = MACH0_(paddr_to_vaddr)(bin, dw);
2009  // eprintf ("# 0x%d -> 0x%x\n", dw, va);
2010  // eprintf ("0x%x kind %d len %d\n", dw, kind, len);
2011  eprintf("Cd 4 %d @ 0x%" PFMT64x "\n", len / 4, va);
2012  }
2013  }
2014  }
2015  break;
2016  case LC_DYLD_EXPORTS_TRIE:
2017  if (bin->options.verbose) {
2018  ut8 buf[8];
2019  rz_buf_read_at(bin->b, off + 8, buf, sizeof(buf));
2020  ut32 dataoff = rz_read_ble32(buf, bin->big_endian);
2021  ut32 datasize = rz_read_ble32(buf + 4, bin->big_endian);
2022  eprintf("exports trie at 0x%x size %d\n", dataoff, datasize);
2023  }
2024  break;
2025  case LC_DYLD_CHAINED_FIXUPS: {
2026  ut8 buf[8];
2027  if (rz_buf_read_at(bin->b, off + 8, buf, sizeof(buf)) == sizeof(buf)) {
2028  ut32 dataoff = rz_read_ble32(buf, bin->big_endian);
2029  ut32 datasize = rz_read_ble32(buf + 4, bin->big_endian);
2030  if (bin->options.verbose) {
2031  eprintf("chained fixups at 0x%x size %d\n", dataoff, datasize);
2032  }
2033  has_chained_fixups = parse_chained_fixups(bin, dataoff, datasize);
2034  }
2035  } break;
2036  }
2037  }
2038 
2039  if (!has_chained_fixups && bin->hdr.cputype == CPU_TYPE_ARM64 &&
2040  (bin->hdr.cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM64E) {
2042  }
2043  return true;
2044 }
ut16 val
Definition: armass64_const.h:6
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
void * malloc(size_t size)
Definition: malloc.c:123
static int parse_thread(struct MACH0_(obj_t) *bin, struct load_command *lc, ut64 off, bool is_first_thread)
Definition: mach0.c:975
static bool parse_chained_fixups(struct MACH0_(obj_t) *bin, ut32 offset, ut32 size)
Definition: mach0.c:1474
static bool parse_segments(struct MACH0_(obj_t) *bin, ut64 off)
Definition: mach0.c:277
static bool parse_dysymtab(struct MACH0_(obj_t) *bin, ut64 off)
Definition: mach0.c:519
static bool reconstruct_chained_fixup(struct MACH0_(obj_t) *bin)
Definition: mach0.c:1532
static bool parse_signature(struct MACH0_(obj_t) *bin, ut64 off)
Definition: mach0.c:817
static bool parse_symtab(struct MACH0_(obj_t) *mo, ut64 off)
Definition: mach0.c:442
static int parse_dylib(struct MACH0_(obj_t) *bin, ut64 off)
Definition: mach0.c:1186
static int parse_function_starts(struct MACH0_(obj_t) *bin, ut64 off)
Definition: mach0.c:1138
static const char * cmd_to_pf_definition(ut32 cmd)
Definition: mach0.c:1336
@ LC_DYLD_EXPORTS_TRIE
@ LC_DYLD_CHAINED_FIXUPS
int off
Definition: pal.c:13
RZ_API st64 rz_buf_fread_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL ut8 *buf, RZ_NONNULL const char *fmt, int n)
...
Definition: buf.c:1001
static ut64 rz_read_ble64(const void *src, bool big_endian)
Definition: rz_endian.h:501
static ut32 rz_read_ble32(const void *src, bool big_endian)
Definition: rz_endian.h:497
static ut16 rz_read_ble16(const void *src, bool big_endian)
Definition: rz_endian.h:493
RZ_API int rz_hex_bin2str(const ut8 *in, int len, char *out)
Definition: hex.c:382
#define PFMT64x
Definition: rz_types.h:393
uint32_t cmdsize
uint32_t cmd

References bprintf, calloc(), load_command::cmd, dylinker_command::cmd, cmd_to_pf_definition(), load_command::cmdsize, dylinker_command::cmdsize, CPU_SUBTYPE_ARM64E, CPU_SUBTYPE_MASK, CPU_TYPE_ARM64, eprintf, free(), i, key, LC_CODE_SIGNATURE, LC_DATA_IN_CODE, LC_DYLD_CHAINED_FIXUPS, LC_DYLD_EXPORTS_TRIE, LC_DYLD_INFO, LC_DYLD_INFO_ONLY, LC_DYLIB_CODE_SIGN_DRS, LC_DYSYMTAB, LC_ENCRYPTION_INFO, LC_ENCRYPTION_INFO_64, LC_FUNCTION_STARTS, LC_LOAD_DYLIB, LC_LOAD_DYLINKER, LC_LOAD_WEAK_DYLIB, LC_MAIN, LC_REEXPORT_DYLIB, LC_RPATH, LC_SEGMENT, LC_SEGMENT_64, LC_SEGMENT_SPLIT_INFO, LC_SOURCE_VERSION, LC_SYMTAB, LC_THREAD, LC_UNIXTHREAD, LC_UUID, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_TVOS, LC_VERSION_MIN_WATCHOS, len, MACH0_(), malloc(), dylinker_command::name, off, paddr_to_vaddr(), parse_chained_fixups(), parse_dylib(), parse_dysymtab(), parse_function_starts(), parse_segments(), parse_signature(), parse_symtab(), parse_thread(), PFMT64x, reconstruct_chained_fixup(), rz_buf_fread_at(), rz_buf_read_at(), RZ_FREE, rz_hex_bin2str(), rz_read_ble16(), rz_read_ble32(), rz_read_ble64(), sdb_fmt(), sdb_num_set(), sdb_set(), snprintf, ut64(), uuid_command::uuid, and val.

Referenced by init().

◆ init_sdb_formats()

static void init_sdb_formats ( struct MACH0_(obj_t) *  bin)
static

Definition at line 91 of file mach0.c.

91  {
92  /*
93  * These definitions are used by rz -nn
94  * must be kept in sync with librz/bin/d/macho
95  */
96  sdb_set(bin->kv, "mach0_build_platform.cparse",
97  "enum mach0_build_platform"
98  "{MACOS=1, IOS=2, TVOS=3, WATCHOS=4, BRIDGEOS=5, IOSMAC=6, IOSSIMULATOR=7, TVOSSIMULATOR=8, WATCHOSSIMULATOR=9};",
99  0);
100  sdb_set(bin->kv, "mach0_build_tool.cparse",
101  "enum mach0_build_tool"
102  "{CLANG=1, SWIFT=2, LD=3};",
103  0);
104  sdb_set(bin->kv, "mach0_load_command_type.cparse",
105  "enum mach0_load_command_type"
106  "{ LC_SEGMENT=0x00000001ULL, LC_SYMTAB=0x00000002ULL, LC_SYMSEG=0x00000003ULL, LC_THREAD=0x00000004ULL, LC_UNIXTHREAD=0x00000005ULL, LC_LOADFVMLIB=0x00000006ULL, LC_IDFVMLIB=0x00000007ULL, LC_IDENT=0x00000008ULL, LC_FVMFILE=0x00000009ULL, LC_PREPAGE=0x0000000aULL, LC_DYSYMTAB=0x0000000bULL, LC_LOAD_DYLIB=0x0000000cULL, LC_ID_DYLIB=0x0000000dULL, LC_LOAD_DYLINKER=0x0000000eULL, LC_ID_DYLINKER=0x0000000fULL, LC_PREBOUND_DYLIB=0x00000010ULL, LC_ROUTINES=0x00000011ULL, LC_SUB_FRAMEWORK=0x00000012ULL, LC_SUB_UMBRELLA=0x00000013ULL, LC_SUB_CLIENT=0x00000014ULL, LC_SUB_LIBRARY=0x00000015ULL, LC_TWOLEVEL_HINTS=0x00000016ULL, LC_PREBIND_CKSUM=0x00000017ULL, LC_LOAD_WEAK_DYLIB=0x80000018ULL, LC_SEGMENT_64=0x00000019ULL, LC_ROUTINES_64=0x0000001aULL, LC_UUID=0x0000001bULL, LC_RPATH=0x8000001cULL, LC_CODE_SIGNATURE=0x0000001dULL, LC_SEGMENT_SPLIT_INFO=0x0000001eULL, LC_REEXPORT_DYLIB=0x8000001fULL, LC_LAZY_LOAD_DYLIB=0x00000020ULL, LC_ENCRYPTION_INFO=0x00000021ULL, LC_DYLD_INFO=0x00000022ULL, LC_DYLD_INFO_ONLY=0x80000022ULL, LC_LOAD_UPWARD_DYLIB=0x80000023ULL, LC_VERSION_MIN_MACOSX=0x00000024ULL, LC_VERSION_MIN_IPHONEOS=0x00000025ULL, LC_FUNCTION_STARTS=0x00000026ULL, LC_DYLD_ENVIRONMENT=0x00000027ULL, LC_MAIN=0x80000028ULL, LC_DATA_IN_CODE=0x00000029ULL, LC_SOURCE_VERSION=0x0000002aULL, LC_DYLIB_CODE_SIGN_DRS=0x0000002bULL, LC_ENCRYPTION_INFO_64=0x0000002cULL, LC_LINKER_OPTION=0x0000002dULL, LC_LINKER_OPTIMIZATION_HINT=0x0000002eULL, LC_VERSION_MIN_TVOS=0x0000002fULL, LC_VERSION_MIN_WATCHOS=0x00000030ULL, LC_NOTE=0x00000031ULL, LC_BUILD_VERSION=0x00000032ULL };",
107  0);
108  sdb_set(bin->kv, "mach0_header_filetype.cparse",
109  "enum mach0_header_filetype"
110  "{MH_OBJECT=1, MH_EXECUTE=2, MH_FVMLIB=3, MH_CORE=4, MH_PRELOAD=5, MH_DYLIB=6, MH_DYLINKER=7, MH_BUNDLE=8, MH_DYLIB_STUB=9, MH_DSYM=10, MH_KEXT_BUNDLE=11};",
111  0);
112  sdb_set(bin->kv, "mach0_header_flags.cparse",
113  "enum mach0_header_flags"
114  "{MH_NOUNDEFS=1, MH_INCRLINK=2,MH_DYLDLINK=4,MH_BINDATLOAD=8,MH_PREBOUND=0x10, MH_SPLIT_SEGS=0x20,MH_LAZY_INIT=0x40,MH_TWOLEVEL=0x80, MH_FORCE_FLAT=0x100,MH_NOMULTIDEFS=0x200,MH_NOFIXPREBINDING=0x400, MH_PREBINDABLE=0x800, MH_ALLMODSBOUND=0x1000, MH_SUBSECTIONS_VIA_SYMBOLS=0x2000, MH_CANONICAL=0x4000,MH_WEAK_DEFINES=0x8000, MH_BINDS_TO_WEAK=0x10000,MH_ALLOW_STACK_EXECUTION=0x20000, MH_ROOT_SAFE=0x40000,MH_SETUID_SAFE=0x80000, MH_NO_REEXPORTED_DYLIBS=0x100000,MH_PIE=0x200000, MH_DEAD_STRIPPABLE_DYLIB=0x400000, MH_HAS_TLV_DESCRIPTORS=0x800000, MH_NO_HEAP_EXECUTION=0x1000000};",
115  0);
116  sdb_set(bin->kv, "mach0_section_types.cparse",
117  "enum mach0_section_types"
118  "{S_REGULAR=0, S_ZEROFILL=1, S_CSTRING_LITERALS=2, S_4BYTE_LITERALS=3, S_8BYTE_LITERALS=4, S_LITERAL_POINTERS=5, S_NON_LAZY_SYMBOL_POINTERS=6, S_LAZY_SYMBOL_POINTERS=7, S_SYMBOL_STUBS=8, S_MOD_INIT_FUNC_POINTERS=9, S_MOD_TERM_FUNC_POINTERS=0xa, S_COALESCED=0xb, S_GB_ZEROFILL=0xc, S_INTERPOSING=0xd, S_16BYTE_LITERALS=0xe, S_DTRACE_DOF=0xf, S_LAZY_DYLIB_SYMBOL_POINTERS=0x10, S_THREAD_LOCAL_REGULAR=0x11, S_THREAD_LOCAL_ZEROFILL=0x12, S_THREAD_LOCAL_VARIABLES=0x13, S_THREAD_LOCAL_VARIABLE_POINTERS=0x14, S_THREAD_LOCAL_INIT_FUNCTION_POINTERS=0x15, S_INIT_FUNC_OFFSETS=0x16};",
119  0);
120  sdb_set(bin->kv, "mach0_section_attrs.cparse",
121  "enum mach0_section_attrs"
122  "{S_ATTR_PURE_INSTRUCTIONS=0x800000ULL, S_ATTR_NO_TOC=0x400000ULL, S_ATTR_STRIP_STATIC_SYMS=0x200000ULL, S_ATTR_NO_DEAD_STRIP=0x100000ULL, S_ATTR_LIVE_SUPPORT=0x080000ULL, S_ATTR_SELF_MODIFYING_CODE=0x040000ULL, S_ATTR_DEBUG=0x020000ULL, S_ATTR_SOME_INSTRUCTIONS=0x000004ULL, S_ATTR_EXT_RELOC=0x000002ULL, S_ATTR_LOC_RELOC=0x000001ULL};",
123  0);
124  sdb_set(bin->kv, "mach0_header.format",
125  "xxx[4]Edd[4]B "
126  "magic cputype cpusubtype (mach0_header_filetype)filetype ncmds sizeofcmds (mach0_header_flags)flags",
127  0);
128  sdb_set(bin->kv, "mach0_segment.format",
129  "[4]Ed[16]zxxxxoodx "
130  "(mach0_load_command_type)cmd cmdsize segname vmaddr vmsize fileoff filesize maxprot initprot nsects flags",
131  0);
132  sdb_set(bin->kv, "mach0_segment64.format",
133  "[4]Ed[16]zqqqqoodx "
134  "(mach0_load_command_type)cmd cmdsize segname vmaddr vmsize fileoff filesize maxprot initprot nsects flags",
135  0);
136  sdb_set(bin->kv, "mach0_symtab_command.format",
137  "[4]Edxdxd "
138  "(mach0_load_command_type)cmd cmdsize symoff nsyms stroff strsize",
139  0);
140  sdb_set(bin->kv, "mach0_dysymtab_command.format",
141  "[4]Edddddddddddxdxdxxxd "
142  "(mach0_load_command_type)cmd cmdsize ilocalsym nlocalsym iextdefsym nextdefsym iundefsym nundefsym tocoff ntoc moddtaboff nmodtab extrefsymoff nextrefsyms inddirectsymoff nindirectsyms extreloff nextrel locreloff nlocrel",
143  0);
144  sdb_set(bin->kv, "mach0_section.format",
145  "[16]z[16]zxxxxxx[1]E[3]Bxx "
146  "sectname segname addr size offset align reloff nreloc (mach0_section_types)flags_type (mach0_section_attrs)flags_attr reserved1 reserved2",
147  0);
148  sdb_set(bin->kv, "mach0_section64.format",
149  "[16]z[16]zqqxxxx[1]E[3]Bxxx "
150  "sectname segname addr size offset align reloff nreloc (mach0_section_types)flags_type (mach0_section_attrs)flags_attr reserved1 reserved2 reserved3",
151  0);
152  sdb_set(bin->kv, "mach0_dylib.format",
153  "xxxxz "
154  "name_offset timestamp current_version compatibility_version name",
155  0);
156  sdb_set(bin->kv, "mach0_dylib_command.format",
157  "[4]Ed? "
158  "(mach0_load_command_type)cmd cmdsize (mach0_dylib)dylib",
159  0);
160  sdb_set(bin->kv, "mach0_id_dylib_command.format",
161  "[4]Ed? "
162  "(mach0_load_command_type)cmd cmdsize (mach0_dylib)dylib",
163  0);
164  sdb_set(bin->kv, "mach0_uuid_command.format",
165  "[4]Ed[16]b "
166  "(mach0_load_command_type)cmd cmdsize uuid",
167  0);
168  sdb_set(bin->kv, "mach0_rpath_command.format",
169  "[4]Edxz "
170  "(mach0_load_command_type)cmd cmdsize path_offset path",
171  0);
172  sdb_set(bin->kv, "mach0_entry_point_command.format",
173  "[4]Edqq "
174  "(mach0_load_command_type)cmd cmdsize entryoff stacksize",
175  0);
176  sdb_set(bin->kv, "mach0_encryption_info64_command.format",
177  "[4]Edxddx "
178  "(mach0_load_command_type)cmd cmdsize offset size id padding",
179  0);
180  sdb_set(bin->kv, "mach0_encryption_info_command.format",
181  "[4]Edxdd "
182  "(mach0_load_command_type)cmd cmdsize offset size id",
183  0);
184  sdb_set(bin->kv, "mach0_code_signature_command.format",
185  "[4]Edxd "
186  "(mach0_load_command_type)cmd cmdsize offset size",
187  0);
188  sdb_set(bin->kv, "mach0_dyld_info_only_command.format",
189  "[4]Edxdxdxdxdxd "
190  "(mach0_load_command_type)cmd cmdsize rebase_off rebase_size bind_off bind_size weak_bind_off weak_bind_size lazy_bind_off lazy_bind_size export_off export_size",
191  0);
192  sdb_set(bin->kv, "mach0_load_dylinker_command.format",
193  "[4]Edxz "
194  "(mach0_load_command_type)cmd cmdsize name_offset name",
195  0);
196  sdb_set(bin->kv, "mach0_id_dylinker_command.format",
197  "[4]Edxzi "
198  "(mach0_load_command_type)cmd cmdsize name_offset name",
199  0);
200  sdb_set(bin->kv, "mach0_build_version_command.format",
201  "[4]Ed[4]Exxd "
202  "(mach0_load_command_type)cmd cmdsize (mach0_build_platform)platform minos sdk ntools",
203  0);
204  sdb_set(bin->kv, "mach0_build_version_tool.format",
205  "[4]Ex "
206  "(mach0_build_tool)tool version",
207  0);
208  sdb_set(bin->kv, "mach0_source_version_command.format",
209  "[4]Edq "
210  "(mach0_load_command_type)cmd cmdsize version",
211  0);
212  sdb_set(bin->kv, "mach0_function_starts_command.format",
213  "[4]Edxd "
214  "(mach0_load_command_type)cmd cmdsize offset size",
215  0);
216  sdb_set(bin->kv, "mach0_data_in_code_command.format",
217  "[4]Edxd "
218  "(mach0_load_command_type)cmd cmdsize offset size",
219  0);
220  sdb_set(bin->kv, "mach0_version_min_command.format",
221  "[4]Edxx "
222  "(mach0_load_command_type)cmd cmdsize version reserved",
223  0);
224  sdb_set(bin->kv, "mach0_segment_split_info_command.format",
225  "[4]Edxd "
226  "(mach0_load_command_type)cmd cmdsize offset size",
227  0);
228  sdb_set(bin->kv, "mach0_unixthread_command.format",
229  "[4]Eddd "
230  "(mach0_load_command_type)cmd cmdsize flavor count",
231  0);
232 }

References sdb_set().

Referenced by init_hdr().

◆ inSymtab()

static int inSymtab ( HtPP *  hash,
const char *  name,
ut64  addr 
)
static

Definition at line 2545 of file mach0.c.

2545  {
2546  bool found = false;
2547  char *key = rz_str_newf("%" PFMT64x ".%s", addr, name);
2548  ht_pp_find(hash, key, &found);
2549  if (found) {
2550  free(key);
2551  return true;
2552  }
2553  ht_pp_insert(hash, key, "1");
2554  free(key);
2555  return false;
2556 }
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130

References addr, found, free(), key, PFMT64x, and rz_str_newf().

Referenced by assign_export_symbol_t(), get_symbols(), and get_symbols_list().

◆ is_big_endian()

bool MACH0_() is_big_endian ( struct MACH0_(obj_t) *  bin)

Definition at line 3312 of file mach0.c.

3312  {
3313  if (bin) {
3314  const int cpu = bin->hdr.cputype;
3315  return cpu == CPU_TYPE_POWERPC || cpu == CPU_TYPE_POWERPC64;
3316  }
3317  return false;
3318 }
static ut32 cpu[32]
Definition: analysis_or1k.c:21

References cpu, CPU_TYPE_POWERPC, and CPU_TYPE_POWERPC64.

Referenced by info(), and rz_debruijn_offset().

◆ is_pie()

bool MACH0_() is_pie ( struct MACH0_(obj_t) *  bin)

Definition at line 3550 of file mach0.c.

3550  {
3551  return (bin && bin->hdr.filetype == MH_EXECUTE && bin->hdr.flags & MH_PIE);
3552 }
@ MH_PIE

References MH_EXECUTE, and MH_PIE.

Referenced by info().

◆ kv_loadlibs()

void MACH0_() kv_loadlibs ( struct MACH0_(obj_t) *  bin)

Definition at line 3235 of file mach0.c.

3235  {
3236  int i;
3237  for (i = 0; i < bin->nlibs; i++) {
3238  sdb_set(bin->kv, sdb_fmt("libs.%d.name", i), bin->libs[i], 0);
3239  }
3240 }

References i, sdb_fmt(), and sdb_set().

◆ MACH0_() [1/2]

struct MACH0_ ( mach_header  )

Definition at line 3969 of file mach0.c.

4069  {
4070  ut8 magicbytes[sizeof(ut32)] = { 0 };
4071  ut8 machohdrbytes[sizeof(struct MACH0_(mach_header))] = { 0 };
4072  int len;
4073  struct MACH0_(mach_header) *macho_hdr = RZ_NEW0(struct MACH0_(mach_header));
4074  bool big_endian = false;
4075  if (!macho_hdr) {
4076  return NULL;
4077  }
4078  if (rz_buf_read_at(buf, 0, magicbytes, 4) < 1) {
4079  free(macho_hdr);
4080  return false;
4081  }
4082 
4083  if (rz_read_le32(magicbytes) == 0xfeedface) {
4084  big_endian = false;
4085  } else if (rz_read_be32(magicbytes) == 0xfeedface) {
4086  big_endian = true;
4087  } else if (rz_read_le32(magicbytes) == FAT_MAGIC) {
4088  big_endian = false;
4089  } else if (rz_read_be32(magicbytes) == FAT_MAGIC) {
4090  big_endian = true;
4091  } else if (rz_read_le32(magicbytes) == 0xfeedfacf) {
4092  big_endian = false;
4093  } else if (rz_read_be32(magicbytes) == 0xfeedfacf) {
4094  big_endian = true;
4095  } else {
4096  /* also extract non-mach0s */
4097 #if 0
4098  free (macho_hdr);
4099  return NULL;
4100 #endif
4101  }
4102  len = rz_buf_read_at(buf, 0, machohdrbytes, sizeof(machohdrbytes));
4103  if (len != sizeof(struct MACH0_(mach_header))) {
4104  free(macho_hdr);
4105  return NULL;
4106  }
4107  macho_hdr->magic = rz_read_ble(&machohdrbytes[0], big_endian, 32);
4108  macho_hdr->cputype = rz_read_ble(&machohdrbytes[4], big_endian, 32);
4109  macho_hdr->cpusubtype = rz_read_ble(&machohdrbytes[8], big_endian, 32);
4110  macho_hdr->filetype = rz_read_ble(&machohdrbytes[12], big_endian, 32);
4111  macho_hdr->ncmds = rz_read_ble(&machohdrbytes[16], big_endian, 32);
4112  macho_hdr->sizeofcmds = rz_read_ble(&machohdrbytes[20], big_endian, 32);
4113  macho_hdr->flags = rz_read_ble(&machohdrbytes[24], big_endian, 32);
4114 #if RZ_BIN_MACH064
4115  macho_hdr->reserved = rz_read_ble(&machohdrbytes[28], big_endian, 32);
4116 #endif
4117  return macho_hdr;
4118 }

References addr, cmd_to_pf_definition(), cmd_to_string(), CPU_TYPE_POWERPC, CPU_TYPE_POWERPC64, eprintf, f, free(), i, LC_BUILD_VERSION, LC_SEGMENT, LC_SEGMENT_64, length, MACH0_(), n, NULL, off, pa2va(), rz_bin_field_free(), rz_bin_field_new(), rz_buf_read_le32_at, rz_buf_size(), rz_list_append(), rz_list_newf(), sdb_fmt(), and ut64().

◆ MACH0_() [2/2]

static struct MACH0_ ( obj_t  )

Definition at line 2103 of file mach0.c.

2111  {
2113  struct MACH0_(obj_t) *bin = RZ_NEW0(struct MACH0_(obj_t));
2114  if (bin) {
2115  bin->b = rz_buf_ref(buf);
2116  bin->main_addr = UT64_MAX;
2117  bin->kv = sdb_new(NULL, "bin.mach0", 0);
2118  bin->hash = rz_hash_new();
2119  bin->size = rz_buf_size(bin->b);
2120  if (options) {
2121  bin->options = *options;
2122  }
2123  if (!init(bin)) {
2124  return MACH0_(mach0_free)(bin);
2125  }
2126  }
2127  return bin;
2128 }
RZ_API RzHash * rz_hash_new(void)
Definition: hash.c:585
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
static bool init(struct MACH0_(obj_t) *mo)
Definition: mach0.c:2046
void *MACH0_() mach0_free(struct MACH0_(obj_t) *mo)
Definition: mach0.c:2057
RZ_API RzBuffer * rz_buf_ref(RzBuffer *b)
Increment the reference count of the buffer.
Definition: buf.c:668
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
RZ_API Sdb * sdb_new(const char *path, const char *name, int lock)
Definition: sdb.c:47

References options, and rz_return_if_fail.

Referenced by assign_export_symbol_t(), fill_exports_list(), get_bits(), get_cpusubtype(), get_cputype(), get_entrypoint(), get_filetype(), get_imports(), get_main(), get_maps(), get_maps_unpatched(), get_symbols(), get_symbols_list(), get_virtual_files(), init(), init_items(), MACH0_(), mach_headerfields(), pa2va(), parse_dysymtab(), parse_segments(), and parse_symtab().

◆ mach0_free()

void* MACH0_() mach0_free ( struct MACH0_(obj_t) *  mo)

Definition at line 2057 of file mach0.c.

2057  {
2058  if (!mo) {
2059  return NULL;
2060  }
2061 
2062  size_t i;
2063  if (mo->symbols) {
2064  for (i = 0; !mo->symbols[i].last; i++) {
2065  free(mo->symbols[i].name);
2066  }
2067  free(mo->symbols);
2068  }
2069  free(mo->segs);
2070  free(mo->sects);
2071  free(mo->symtab);
2072  free(mo->symstr);
2073  free(mo->indirectsyms);
2074  free(mo->imports_by_ord);
2075  if (mo->imports_by_name) {
2076  ht_pp_free(mo->imports_by_name);
2077  }
2078  free(mo->dyld_info);
2079  free(mo->toc);
2080  free(mo->modtab);
2081  free(mo->libs);
2082  free(mo->func_start);
2083  free(mo->signature);
2084  free(mo->intrp);
2085  free(mo->compiler);
2086  if (mo->chained_starts) {
2087  for (i = 0; i < mo->nchained_starts; i++) {
2088  if (mo->chained_starts[i]) {
2089  free(mo->chained_starts[i]->page_start);
2090  free(mo->chained_starts[i]);
2091  }
2092  }
2093  free(mo->chained_starts);
2094  }
2095  rz_pvector_free(mo->patchable_relocs);
2096  rz_skiplist_free(mo->relocs);
2097  rz_hash_free(mo->hash);
2098  rz_buf_free(mo->b);
2099  free(mo);
2100  return NULL;
2101 }
RZ_API void rz_hash_free(RzHash *rh)
Definition: hash.c:597
RZ_API void rz_skiplist_free(RzSkipList *list)
Definition: skiplist.c:145
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336

References free(), i, NULL, rz_buf_free(), rz_hash_free(), rz_pvector_free(), and rz_skiplist_free().

Referenced by classes(), destroy(), estimate_slide(), rz_dyldcache_get_objc_opt_info(), rz_kernel_cache_free(), rz_kext_free(), sections_from_bin(), and symbols_from_bin().

◆ mach_fields()

RzList* MACH0_() mach_fields ( RzBinFile bf)

Definition at line 3969 of file mach0.c.

3969  {
3970  RzBuffer *buf = bf->buf;
3972  struct MACH0_(mach_header) *mh = MACH0_(get_hdr)(buf);
3973  if (!mh) {
3974  return NULL;
3975  }
3977  if (!ret) {
3978  free(mh);
3979  return NULL;
3980  }
3981  ut64 addr = pa2va(bf, 0);
3982  ut64 paddr = 0;
3983 
3984  rz_list_append(ret, rz_bin_field_new(addr, addr, 1, "header", "mach0_header", "mach0_header", true));
3985  addr += 0x20 - 4;
3986  paddr += 0x20 - 4;
3987  bool is64 = mh->cputype >> 16;
3988  if (is64) {
3989  addr += 4;
3990  paddr += 4;
3991  }
3992 
3993  bool isBe = false;
3994  switch (mh->cputype) {
3995  case CPU_TYPE_POWERPC:
3996  case CPU_TYPE_POWERPC64:
3997  isBe = true;
3998  break;
3999  }
4000 
4001  int n;
4002  for (n = 0; n < mh->ncmds; n++) {
4003  ut32 lcType;
4004  if (!rz_buf_read_ble32_at(buf, paddr, &lcType, isBe)) {
4005  break;
4006  }
4007  ut32 word;
4008  if (!rz_buf_read_ble32_at(buf, paddr + 4, &word, isBe)) {
4009  break;
4010  }
4011  if (paddr + 8 > length) {
4012  break;
4013  }
4014  ut32 lcSize = word;
4015  word &= 0xFFFFFF;
4016  if (lcSize < 1) {
4017  eprintf("Invalid size for a load command\n");
4018  break;
4019  }
4020  if (word == 0) {
4021  break;
4022  }
4023  const char *pf_definition = cmd_to_pf_definition(lcType);
4024  if (pf_definition) {
4025  rz_list_append(ret, rz_bin_field_new(addr, addr, 1, sdb_fmt("load_command_%d_%s", n, cmd_to_string(lcType)), pf_definition, pf_definition, true));
4026  }
4027  switch (lcType) {
4028  case LC_BUILD_VERSION: {
4029  ut32 ntools;
4030  if (!rz_buf_read_le32_at(buf, paddr + 20, &ntools)) {
4031  break;
4032  }
4033  ut64 off = 24;
4034  int j = 0;
4035  while (off < lcSize && ntools--) {
4036  rz_list_append(ret, rz_bin_field_new(addr + off, addr + off, 1, sdb_fmt("tool_%d", j++), "mach0_build_version_tool", "mach0_build_version_tool", true));
4037  off += 8;
4038  }
4039  break;
4040  }
4041  case LC_SEGMENT:
4042  case LC_SEGMENT_64: {
4043  ut32 nsects;
4044  if (!rz_buf_read_le32_at(buf, addr + (is64 ? 64 : 48), &nsects)) {
4045  break;
4046  }
4047  ut64 off = is64 ? 72 : 56;
4048  size_t i, j = 0;
4049  for (i = 0; i < nsects && (addr + off) < length && off < lcSize; i++) {
4050  const char *sname = is64 ? "mach0_section64" : "mach0_section";
4052  sdb_fmt("section_%zu", j++), sname, sname, true);
4053  rz_list_append(ret, f);
4054  off += is64 ? 80 : 68;
4055  }
4056  break;
4057  default:
4058  // TODO
4059  break;
4060  }
4061  }
4062  addr += word;
4063  paddr += word;
4064  }
4065  free(mh);
4066  return ret;
4067 }
RZ_API void rz_bin_field_free(RzBinField *field)
Definition: bin.c:950
RZ_API RzBinField * rz_bin_field_new(ut64 paddr, ut64 vaddr, int size, const char *name, const char *comment, const char *format, bool format_named)
Definition: bin.c:935
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
static ut64 pa2va(RzBinFile *bf, ut64 offset)
Definition: mach0.c:81
static const char * cmd_to_string(ut32 cmd)
Definition: mach0.c:1230
int n
Definition: mipsasm.c:19
#define rz_buf_read_le32_at(b, addr, result)
Definition: rz_buf.h:271
#define f(i)
Definition: sha256.c:46
RzBuffer * buf
Definition: rz_bin.h:303

◆ mach_headerfields()

void MACH0_() mach_headerfields ( RzBinFile bf)

Definition at line 3633 of file mach0.c.

3633  {
3634  PrintfCallback cb_printf = bf->rbin->cb_printf;
3635  if (!cb_printf) {
3636  cb_printf = printf;
3637  }
3638  RzBuffer *buf = bf->buf;
3640  int n = 0;
3641  struct MACH0_(mach_header) *mh = MACH0_(get_hdr)(buf);
3642  if (!mh) {
3643  return;
3644  }
3645  ut64 pvaddr = pa2va(bf, 0);
3646  cb_printf("pf.mach0_header @ 0x%08" PFMT64x "\n", pvaddr);
3647  cb_printf("0x%08" PFMT64x " Magic 0x%x\n", pvaddr, mh->magic);
3648  pvaddr += 4;
3649  cb_printf("0x%08" PFMT64x " CpuType 0x%x\n", pvaddr, mh->cputype);
3650  pvaddr += 4;
3651  cb_printf("0x%08" PFMT64x " CpuSubType 0x%x\n", pvaddr, mh->cpusubtype);
3652  pvaddr += 4;
3653  cb_printf("0x%08" PFMT64x " FileType 0x%x\n", pvaddr, mh->filetype);
3654  pvaddr += 4;
3655  cb_printf("0x%08" PFMT64x " nCmds %d\n", pvaddr, mh->ncmds);
3656  pvaddr += 4;
3657  cb_printf("0x%08" PFMT64x " sizeOfCmds %d\n", pvaddr, mh->sizeofcmds);
3658  pvaddr += 4;
3659  cb_printf("0x%08" PFMT64x " Flags 0x%x\n", pvaddr, mh->flags);
3660  pvaddr += 4;
3661  bool is64 = mh->cputype >> 16;
3662 
3663  ut64 addr = 0x20 - 4;
3664  ut32 word = 0;
3665  ut8 wordbuf[sizeof(word)];
3666  bool isBe = false;
3667  switch (mh->cputype) {
3668  case CPU_TYPE_POWERPC:
3669  case CPU_TYPE_POWERPC64:
3670  isBe = true;
3671  break;
3672  }
3673 #define READWORD() \
3674  if (rz_buf_read_at(buf, addr, (ut8 *)wordbuf, 4) != 4) { \
3675  eprintf("Invalid address in buffer."); \
3676  break; \
3677  } \
3678  addr += 4; \
3679  pvaddr += 4; \
3680  word = isBe ? rz_read_be32(wordbuf) : rz_read_le32(wordbuf);
3681  if (is64) {
3682  addr += 4;
3683  pvaddr += 4;
3684  }
3685  for (n = 0; n < mh->ncmds; n++) {
3686  READWORD();
3687  ut32 lcType = word;
3688  const char *pf_definition = cmd_to_pf_definition(lcType);
3689  if (pf_definition) {
3690  cb_printf("pf.%s @ 0x%08" PFMT64x "\n", pf_definition, pvaddr - 4);
3691  }
3692  cb_printf("0x%08" PFMT64x " cmd %7d 0x%x %s\n",
3693  pvaddr - 4, n, lcType, cmd_to_string(lcType));
3694  READWORD();
3695  if (addr > length) {
3696  break;
3697  }
3698  int lcSize = word;
3699  word &= 0xFFFFFF;
3700  cb_printf("0x%08" PFMT64x " cmdsize %d\n", pvaddr - 4, word);
3701  if (lcSize < 1) {
3702  eprintf("Invalid size for a load command\n");
3703  break;
3704  }
3705  switch (lcType) {
3706  case LC_BUILD_VERSION: {
3707  ut32 platform;
3708  if (!rz_buf_read_le32_at(buf, addr, &platform)) {
3709  break;
3710  }
3711  cb_printf("0x%08" PFMT64x " platform %s\n", pvaddr, build_version_platform_to_string(platform));
3712 
3713  ut16 minos1;
3714  if (!rz_buf_read_le16_at(buf, addr + 6, &minos1)) {
3715  break;
3716  }
3717  ut8 minos2;
3718  if (!rz_buf_read8_at(buf, addr + 5, &minos2)) {
3719  break;
3720  }
3721  ut8 minos3;
3722  if (!rz_buf_read8_at(buf, addr + 4, &minos3)) {
3723  break;
3724  }
3725  cb_printf("0x%08" PFMT64x " minos %d.%d.%d\n", pvaddr + 4, minos1, minos2, minos3);
3726 
3727  ut16 sdk1;
3728  if (!rz_buf_read_le16_at(buf, addr + 10, &sdk1)) {
3729  break;
3730  }
3731  ut8 sdk2;
3732  if (!rz_buf_read8_at(buf, addr + 9, &sdk2)) {
3733  break;
3734  }
3735  ut8 sdk3;
3736  if (!rz_buf_read8_at(buf, addr + 8, &sdk3)) {
3737  break;
3738  }
3739  cb_printf("0x%08" PFMT64x " sdk %d.%d.%d\n", pvaddr + 8, sdk1, sdk2, sdk3);
3740 
3741  ut32 ntools;
3742  if (!rz_buf_read_le32_at(buf, addr + 12, &ntools)) {
3743  break;
3744  }
3745  cb_printf("0x%08" PFMT64x " ntools %d\n", pvaddr + 12, ntools);
3746 
3747  ut64 off = 16;
3748  while (off < (lcSize - 8) && ntools--) {
3749  cb_printf("pf.mach0_build_version_tool @ 0x%08" PFMT64x "\n", pvaddr + off);
3750 
3751  ut32 tool;
3752  if (!rz_buf_read_le32_at(buf, addr + off, &tool)) {
3753  break;
3754  }
3755  cb_printf("0x%08" PFMT64x " tool %s\n", pvaddr + off, build_version_tool_to_string(tool));
3756 
3757  off += 4;
3758  if (off >= (lcSize - 8)) {
3759  break;
3760  }
3761 
3762  ut16 version1;
3763  if (!rz_buf_read_le16_at(buf, addr + off + 2, &version1)) {
3764  break;
3765  }
3766  ut8 version2;
3767  if (!rz_buf_read8_at(buf, addr + off + 1, &version2)) {
3768  break;
3769  }
3770  ut8 version3;
3771  if (!rz_buf_read8_at(buf, addr + off, &version3)) {
3772  break;
3773  }
3774  cb_printf("0x%08" PFMT64x " version %d.%d.%d\n", pvaddr + off, version1, version2, version3);
3775 
3776  off += 4;
3777  }
3778  break;
3779  }
3780  case LC_MAIN: {
3781  ut8 data[64] = { 0 };
3782  rz_buf_read_at(buf, addr, data, sizeof(data));
3783 #if RZ_BIN_MACH064
3784  ut64 ep = rz_read_ble64(&data, false); // bin->big_endian);
3785  cb_printf("0x%08" PFMT64x " entry0 0x%" PFMT64x "\n", pvaddr, ep);
3786  ut64 ss = rz_read_ble64(&data[8], false); // bin->big_endian);
3787  cb_printf("0x%08" PFMT64x " stacksize 0x%" PFMT64x "\n", pvaddr + 8, ss);
3788 #else
3789  ut32 ep = rz_read_ble32(&data, false); // bin->big_endian);
3790  cb_printf("0x%08" PFMT32x " entry0 0x%" PFMT32x "\n", (ut32)pvaddr, ep);
3791  ut32 ss = rz_read_ble32(&data[4], false); // bin->big_endian);
3792  cb_printf("0x%08" PFMT32x " stacksize 0x%" PFMT32x "\n", (ut32)pvaddr + 4, ss);
3793 #endif
3794  } break;
3795  case LC_SYMTAB:
3796 #if 0
3797  {
3798  char *id = rz_buf_get_string (buf, addr + 20);
3799  cb_printf ("0x%08"PFMT64x" id 0x%x\n", addr + 20, id? id: "");
3800  cb_printf ("0x%08"PFMT64x" symooff 0x%x\n", addr + 20, id? id: "");
3801  cb_printf ("0x%08"PFMT64x" nsyms %d\n", addr + 20, id? id: "");
3802  cb_printf ("0x%08"PFMT64x" stroff 0x%x\n", addr + 20, id? id: "");
3803  cb_printf ("0x%08"PFMT64x" strsize 0x%x\n", addr + 20, id? id: "");
3804  free (id);
3805  }
3806 #endif
3807  break;
3808  case LC_ID_DYLIB: { // install_name_tool
3809  ut32 str_off;
3810  if (!rz_buf_read_ble32_at(buf, addr, &str_off, isBe)) {
3811  break;
3812  }
3813 
3814  char *id = rz_buf_get_string(buf, addr + str_off - 8);
3815 
3816  ut16 current1;
3817  if (!rz_buf_read_le16_at(buf, addr + 10, &current1)) {
3818  free(id);
3819  break;
3820  }
3821  ut8 current2;
3822  if (!rz_buf_read8_at(buf, addr + 9, &current2)) {
3823  free(id);
3824  break;
3825  }
3826  ut8 current3;
3827  if (!rz_buf_read8_at(buf, addr + 8, &current3)) {
3828  free(id);
3829  break;
3830  }
3831  cb_printf("0x%08" PFMT64x " current %d.%d.%d\n", pvaddr + 8, current1, current2, current3);
3832 
3833  ut16 compat1;
3834  if (!rz_buf_read_le16_at(buf, addr + 14, &compat1)) {
3835  free(id);
3836  break;
3837  }
3838  ut8 compat2;
3839  if (!rz_buf_read8_at(buf, addr + 13, &compat2)) {
3840  free(id);
3841  break;
3842  }
3843  ut8 compat3;
3844  if (!rz_buf_read8_at(buf, addr + 12, &compat3)) {
3845  free(id);
3846  break;
3847  }
3848  cb_printf("0x%08" PFMT64x " compat %d.%d.%d\n", pvaddr + 12, compat1, compat2, compat3);
3849 
3850  cb_printf("0x%08" PFMT64x " id %s\n",
3851  pvaddr + str_off - 8, id ? id : "");
3852  free(id);
3853  break;
3854  }
3855  case LC_UUID: {
3856  ut8 i, uuid[16];
3857  rz_buf_read_at(buf, addr, uuid, sizeof(uuid));
3858  cb_printf("0x%08" PFMT64x " uuid ", pvaddr);
3859  for (i = 0; i < sizeof(uuid); i++) {
3860  cb_printf("%02x", uuid[i]);
3861  }
3862  cb_printf("\n");
3863  } break;
3864  case LC_SEGMENT:
3865  case LC_SEGMENT_64: {
3866  ut8 name[17] = { 0 };
3867  rz_buf_read_at(buf, addr, name, sizeof(name) - 1);
3868  cb_printf("0x%08" PFMT64x " name %s\n", pvaddr, name);
3869  ut32 nsects;
3870  if (!rz_buf_read_le32_at(buf, addr - 8 + (is64 ? 64 : 48), &nsects)) {
3871  break;
3872  }
3873  ut64 off = is64 ? 72 : 56;
3874  while (off < lcSize && nsects--) {
3875  if (is64) {
3876  cb_printf("pf.mach0_section64 @ 0x%08" PFMT64x "\n", pvaddr - 8 + off);
3877  off += 80;
3878  } else {
3879  cb_printf("pf.mach0_section @ 0x%08" PFMT64x "\n", pvaddr - 8 + off);
3880  off += 68;
3881  }
3882  }
3883  } break;
3884  case LC_LOAD_DYLIB:
3885  case LC_LOAD_WEAK_DYLIB: {
3886  ut32 str_off;
3887  if (!rz_buf_read_ble32_at(buf, addr, &str_off, isBe)) {
3888  break;
3889  }
3890  char *load_dylib = rz_buf_get_string(buf, addr + str_off - 8);
3891  ut16 current1;
3892  if (!rz_buf_read_le16_at(buf, addr + 10, &current1)) {
3893  free(load_dylib);
3894  break;
3895  }
3896  ut8 current2;
3897  if (!rz_buf_read8_at(buf, addr + 9, &current2)) {
3898  free(load_dylib);
3899  break;
3900  }
3901  ut8 current3;
3902  if (!rz_buf_read8_at(buf, addr + 8, &current3)) {
3903  free(load_dylib);
3904  break;
3905  }
3906  cb_printf("0x%08" PFMT64x " current %d.%d.%d\n", pvaddr + 8, current1, current2, current3);
3907  ut16 compat1;
3908  if (!rz_buf_read_le16_at(buf, addr + 14, &compat1)) {
3909  free(load_dylib);
3910  break;
3911  }
3912  ut8 compat2;
3913  if (!rz_buf_read8_at(buf, addr + 13, &compat2)) {
3914  free(load_dylib);
3915  break;
3916  }
3917  ut8 compat3;
3918  if (!rz_buf_read8_at(buf, addr + 12, &compat3)) {
3919  free(load_dylib);
3920  break;
3921  }
3922  cb_printf("0x%08" PFMT64x " compat %d.%d.%d\n", pvaddr + 12, compat1, compat2, compat3);
3923  cb_printf("0x%08" PFMT64x " load_dylib %s\n",
3924  pvaddr + str_off - 8, load_dylib ? load_dylib : "");
3925  free(load_dylib);
3926  break;
3927  }
3928  case LC_RPATH: {
3929  char *rpath = rz_buf_get_string(buf, addr + 4);
3930  cb_printf("0x%08" PFMT64x " rpath %s\n",
3931  pvaddr + 4, rpath ? rpath : "");
3932  free(rpath);
3933  break;
3934  }
3935  case LC_ENCRYPTION_INFO:
3936  case LC_ENCRYPTION_INFO_64: {
3937  ut32 word;
3938  if (!rz_buf_read_le32_at(buf, addr, &word)) {
3939  break;
3940  }
3941  cb_printf("0x%08" PFMT64x " cryptoff 0x%08x\n", pvaddr, word);
3942 
3943  if (!rz_buf_read_le32_at(buf, addr + 4, &word)) {
3944  break;
3945  }
3946  cb_printf("0x%08" PFMT64x " cryptsize %d\n", pvaddr + 4, word);
3947 
3948  if (!rz_buf_read_le32_at(buf, addr + 8, &word)) {
3949  break;
3950  }
3951  cb_printf("0x%08" PFMT64x " cryptid %d\n", pvaddr + 8, word);
3952  break;
3953  }
3954  case LC_CODE_SIGNATURE: {
3955  ut32 words[2];
3956  rz_buf_read_at(buf, addr, (ut8 *)words, sizeof(words));
3957  cb_printf("0x%08" PFMT64x " dataoff 0x%08x\n", pvaddr, words[0]);
3958  cb_printf("0x%08" PFMT64x " datasize %d\n", pvaddr + 4, words[1]);
3959  cb_printf("# wtf mach0.sign %d @ 0x%x\n", words[1], words[0]);
3960  break;
3961  }
3962  }
3963  addr += word - 8;
3964  pvaddr += word - 8;
3965  }
3966  free(mh);
3967 }
#define PFMT32x
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
uint16_t ut16
static const char * build_version_platform_to_string(ut32 platform)
Definition: mach0.c:1436
#define READWORD()
static const char * build_version_tool_to_string(ut32 tool)
Definition: mach0.c:1461
#define rz_buf_read_le16_at(b, addr, result)
Definition: rz_buf.h:270
RZ_API RZ_OWN char * rz_buf_get_string(RZ_NONNULL RzBuffer *b, ut64 addr)
Get a string from the buffer.
Definition: buf.c:628
RZ_API bool rz_buf_read8_at(RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *result)
Read a byte at the specified address in the buffer.
Definition: buf.c:876
int(* PrintfCallback)(const char *str,...) RZ_PRINTF_CHECK(1
Definition: rz_types.h:233
struct rz_bin_t * rbin
Definition: rz_bin.h:316
PrintfCallback cb_printf
Definition: rz_bin.h:345

References addr, build_version_platform_to_string(), build_version_tool_to_string(), cmd_to_pf_definition(), cmd_to_string(), CPU_TYPE_POWERPC, CPU_TYPE_POWERPC64, eprintf, free(), i, LC_BUILD_VERSION, LC_CODE_SIGNATURE, LC_ENCRYPTION_INFO, LC_ENCRYPTION_INFO_64, LC_ID_DYLIB, LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, LC_MAIN, LC_RPATH, LC_SEGMENT, LC_SEGMENT_64, LC_SYMTAB, LC_UUID, length, MACH0_(), n, off, pa2va(), PFMT32x, PFMT64x, printf(), READWORD, rz_buf_get_string(), rz_buf_read8_at(), rz_buf_read_at(), rz_buf_read_le16_at, rz_buf_read_le32_at, rz_buf_size(), rz_read_ble32(), rz_read_ble64(), and ut64().

◆ opts_set_default()

void MACH0_() opts_set_default ( struct MACH0_(opts_t) *  options,
RzBinFile bf 
)

Definition at line 2103 of file mach0.c.

2103  {
2104  rz_return_if_fail(options && bf && bf->rbin);
2105  options->header_at = 0;
2106  options->symbols_off = 0;
2107  options->verbose = bf->rbin->verbose;
2108  options->patch_relocs = true;
2109 }
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
bool verbose
Definition: rz_bin.h:359

Referenced by load_buffer().

◆ pa2va()

static ut64 pa2va ( RzBinFile bf,
ut64  offset 
)
static

Definition at line 81 of file mach0.c.

81  {
82  rz_return_val_if_fail(bf && bf->rbin, offset);
83  RzIO *io = bf->rbin->iob.io;
84  if (!io || !io->va) {
85  return offset;
86  }
87  struct MACH0_(obj_t) *bin = bf->o->bin_obj;
88  return bin ? MACH0_(paddr_to_vaddr)(bin, offset) : offset;
89 }
RzIOBind iob
Definition: rz_bin.h:347
RzIO * io
Definition: rz_io.h:232
Definition: rz_io.h:59
int va
Definition: rz_io.h:63

References rz_bin_object_t::bin_obj, rz_io_bind_t::io, rz_bin_t::iob, MACH0_(), rz_bin_file_t::o, paddr_to_vaddr(), rz_bin_file_t::rbin, rz_return_val_if_fail, and rz_io_t::va.

Referenced by MACH0_(), and mach_headerfields().

◆ paddr_to_vaddr()

RZ_API ut64 MACH0_() paddr_to_vaddr ( struct MACH0_(obj_t) *  bin,
ut64  offset 
)

Definition at line 67 of file mach0.c.

67  {
68  if (bin->segs) {
69  size_t i;
70  for (i = 0; i < bin->nsegs; i++) {
71  ut64 segment_base = (ut64)bin->segs[i].fileoff;
72  ut64 segment_size = (ut64)bin->segs[i].filesize;
73  if (offset >= segment_base && offset < segment_base + segment_size) {
74  return bin->segs[i].vmaddr + (offset - segment_base);
75  }
76  }
77  }
78  return 0;
79 }

References i, and ut64().

Referenced by assign_export_symbol_t(), fill_exports_list(), init_items(), pa2va(), and parse_relocation_info().

◆ parse_chained_fixups()

static bool parse_chained_fixups ( struct MACH0_(obj_t) *  bin,
ut32  offset,
ut32  size 
)
static

Definition at line 1474 of file mach0.c.

1474  {
1476  if (size < sizeof(header)) {
1477  return false;
1478  }
1479  if (rz_buf_fread_at(bin->b, offset, (ut8 *)&header, "7i", 1) != sizeof(header)) {
1480  return false;
1481  }
1482  if (header.fixups_version > 0) {
1483  eprintf("Unsupported fixups version: %u\n", header.fixups_version);
1484  return false;
1485  }
1486  ut64 starts_at = offset + header.starts_offset;
1487  if (header.starts_offset > size) {
1488  return false;
1489  }
1490  if (!rz_buf_read_le32_at(bin->b, starts_at, &bin->nchained_starts)) {
1491  return false;
1492  }
1493  bin->chained_starts = RZ_NEWS0(struct rz_dyld_chained_starts_in_segment *, bin->nchained_starts);
1494  if (!bin->chained_starts) {
1495  return false;
1496  }
1497  size_t i;
1498  ut64 cursor = starts_at + sizeof(ut32);
1499  for (i = 0; i < bin->nchained_starts; i++) {
1500  ut32 seg_off;
1501  if (!rz_buf_read_le32_at(bin->b, cursor, &seg_off) || !seg_off) {
1502  cursor += sizeof(ut32);
1503  continue;
1504  }
1505  if (i >= bin->nsegs) {
1506  break;
1507  }
1509  if (!cur_seg) {
1510  return false;
1511  }
1512  bin->chained_starts[i] = cur_seg;
1513  if (rz_buf_fread_at(bin->b, starts_at + seg_off, (ut8 *)cur_seg, "isslis", 1) != 22) {
1514  return false;
1515  }
1516  if (cur_seg->page_count > 0) {
1517  ut16 *page_start = malloc(sizeof(ut16) * cur_seg->page_count);
1518  if (!page_start) {
1519  return false;
1520  }
1521  if (rz_buf_fread_at(bin->b, starts_at + seg_off + 22, (ut8 *)page_start, "s", cur_seg->page_count) != cur_seg->page_count * 2) {
1522  return false;
1523  }
1524  cur_seg->page_start = page_start;
1525  }
1526  cursor += sizeof(ut32);
1527  }
1528  /* TODO: handle also imports, symbols and multiple starts (32-bit only) */
1529  return true;
1530 }
voidpf void uLong size
Definition: ioapi.h:138
#define header(is_bt, len_min, ret_op)
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282

References eprintf, header, i, malloc(), rz_dyld_chained_starts_in_segment::page_count, rz_dyld_chained_starts_in_segment::page_start, rz_buf_fread_at(), rz_buf_read_le32_at, RZ_NEW0, RZ_NEWS0, and ut64().

Referenced by init_items().

◆ parse_dylib()

static int parse_dylib ( struct MACH0_(obj_t) *  bin,
ut64  off 
)
static

Definition at line 1186 of file mach0.c.

1186  {
1187  struct dylib_command dl;
1188  int lib, len;
1189  ut8 sdl[sizeof(struct dylib_command)] = { 0 };
1190 
1191  if (off > bin->size || off + sizeof(struct dylib_command) > bin->size) {
1192  return false;
1193  }
1194  lib = bin->nlibs - 1;
1195 
1196  void *relibs = realloc(bin->libs, bin->nlibs * RZ_BIN_MACH0_STRING_LENGTH);
1197  if (!relibs) {
1198  perror("realloc (libs)");
1199  return false;
1200  }
1201  bin->libs = relibs;
1202  len = rz_buf_read_at(bin->b, off, sdl, sizeof(struct dylib_command));
1203  if (len < 1) {
1204  bprintf("Error: read (dylib)\n");
1205  return false;
1206  }
1207  dl.cmd = rz_read_ble32(&sdl[0], bin->big_endian);
1208  dl.cmdsize = rz_read_ble32(&sdl[4], bin->big_endian);
1209  dl.dylib.name = rz_read_ble32(&sdl[8], bin->big_endian);
1210  dl.dylib.timestamp = rz_read_ble32(&sdl[12], bin->big_endian);
1211  dl.dylib.current_version = rz_read_ble32(&sdl[16], bin->big_endian);
1212  dl.dylib.compatibility_version = rz_read_ble32(&sdl[20], bin->big_endian);
1213 
1214  if (off + dl.dylib.name > bin->size ||
1215  off + dl.dylib.name + RZ_BIN_MACH0_STRING_LENGTH > bin->size) {
1216  return false;
1217  }
1218 
1219  memset(bin->libs[lib], 0, RZ_BIN_MACH0_STRING_LENGTH);
1220  len = rz_buf_read_at(bin->b, off + dl.dylib.name,
1221  (ut8 *)bin->libs[lib], RZ_BIN_MACH0_STRING_LENGTH);
1222  bin->libs[lib][RZ_BIN_MACH0_STRING_LENGTH - 1] = 0;
1223  if (len < 1) {
1224  bprintf("Error: read (dylib str)");
1225  return false;
1226  }
1227  return true;
1228 }
return memset(p, 0, total)
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144

References bprintf, dylib_command::cmd, dylib_command::cmdsize, dylib::compatibility_version, dylib::current_version, dylib_command::dylib, len, memset(), dylib::name, off, realloc(), RZ_BIN_MACH0_STRING_LENGTH, rz_buf_read_at(), rz_read_ble32(), and dylib::timestamp.

Referenced by init_items().

◆ parse_dysymtab()

static bool parse_dysymtab ( struct MACH0_(obj_t) *  bin,
ut64  off 
)
static

Definition at line 519 of file mach0.c.

519  {
520  size_t len, i;
521  ut32 size_tab;
522  ut8 dysym[sizeof(struct dysymtab_command)] = { 0 };
523  ut8 dytoc[sizeof(struct dylib_table_of_contents)] = { 0 };
524  ut8 dymod[sizeof(struct MACH0_(dylib_module))] = { 0 };
525  ut8 idsyms[sizeof(ut32)] = { 0 };
526 
527  if (off > bin->size || off + sizeof(struct dysymtab_command) > bin->size) {
528  return false;
529  }
530 
531  len = rz_buf_read_at(bin->b, off, dysym, sizeof(struct dysymtab_command));
532  if (len != sizeof(struct dysymtab_command)) {
533  bprintf("Error: read (dysymtab)\n");
534  return false;
535  }
536 
537  bin->dysymtab.cmd = rz_read_ble32(&dysym[0], bin->big_endian);
538  bin->dysymtab.cmdsize = rz_read_ble32(&dysym[4], bin->big_endian);
539  bin->dysymtab.ilocalsym = rz_read_ble32(&dysym[8], bin->big_endian);
540  bin->dysymtab.nlocalsym = rz_read_ble32(&dysym[12], bin->big_endian);
541  bin->dysymtab.iextdefsym = rz_read_ble32(&dysym[16], bin->big_endian);
542  bin->dysymtab.nextdefsym = rz_read_ble32(&dysym[20], bin->big_endian);
543  bin->dysymtab.iundefsym = rz_read_ble32(&dysym[24], bin->big_endian);
544  bin->dysymtab.nundefsym = rz_read_ble32(&dysym[28], bin->big_endian);
545  bin->dysymtab.tocoff = rz_read_ble32(&dysym[32], bin->big_endian);
546  bin->dysymtab.ntoc = rz_read_ble32(&dysym[36], bin->big_endian);
547  bin->dysymtab.modtaboff = rz_read_ble32(&dysym[40], bin->big_endian);
548  bin->dysymtab.nmodtab = rz_read_ble32(&dysym[44], bin->big_endian);
549  bin->dysymtab.extrefsymoff = rz_read_ble32(&dysym[48], bin->big_endian);
550  bin->dysymtab.nextrefsyms = rz_read_ble32(&dysym[52], bin->big_endian);
551  bin->dysymtab.indirectsymoff = rz_read_ble32(&dysym[56], bin->big_endian);
552  bin->dysymtab.nindirectsyms = rz_read_ble32(&dysym[60], bin->big_endian);
553  bin->dysymtab.extreloff = rz_read_ble32(&dysym[64], bin->big_endian);
554  bin->dysymtab.nextrel = rz_read_ble32(&dysym[68], bin->big_endian);
555  bin->dysymtab.locreloff = rz_read_ble32(&dysym[72], bin->big_endian);
556  bin->dysymtab.nlocrel = rz_read_ble32(&dysym[76], bin->big_endian);
557 
558  bin->ntoc = bin->dysymtab.ntoc;
559  if (bin->ntoc > 0) {
560  if (!(bin->toc = calloc(bin->ntoc, sizeof(struct dylib_table_of_contents)))) {
561  perror("calloc (toc)");
562  return false;
563  }
564  if (!UT32_MUL(&size_tab, bin->ntoc, sizeof(struct dylib_table_of_contents))) {
565  RZ_FREE(bin->toc);
566  return false;
567  }
568  if (!size_tab) {
569  RZ_FREE(bin->toc);
570  return false;
571  }
572  if (bin->dysymtab.tocoff > bin->size || bin->dysymtab.tocoff + size_tab > bin->size) {
573  RZ_FREE(bin->toc);
574  return false;
575  }
576  for (i = 0; i < bin->ntoc; i++) {
577  len = rz_buf_read_at(bin->b, bin->dysymtab.tocoff + i * sizeof(struct dylib_table_of_contents),
578  dytoc, sizeof(struct dylib_table_of_contents));
579  if (len != sizeof(struct dylib_table_of_contents)) {
580  bprintf("Error: read (toc)\n");
581  RZ_FREE(bin->toc);
582  return false;
583  }
584  bin->toc[i].symbol_index = rz_read_ble32(&dytoc[0], bin->big_endian);
585  bin->toc[i].module_index = rz_read_ble32(&dytoc[4], bin->big_endian);
586  }
587  }
588  bin->nmodtab = bin->dysymtab.nmodtab;
589  if (bin->nmodtab > 0) {
590  if (!(bin->modtab = calloc(bin->nmodtab, sizeof(struct MACH0_(dylib_module))))) {
591  perror("calloc (modtab)");
592  return false;
593  }
594  if (!UT32_MUL(&size_tab, bin->nmodtab, sizeof(struct MACH0_(dylib_module)))) {
595  RZ_FREE(bin->modtab);
596  return false;
597  }
598  if (!size_tab) {
599  RZ_FREE(bin->modtab);
600  return false;
601  }
602  if (bin->dysymtab.modtaboff > bin->size ||
603  bin->dysymtab.modtaboff + size_tab > bin->size) {
604  RZ_FREE(bin->modtab);
605  return false;
606  }
607  for (i = 0; i < bin->nmodtab; i++) {
608  len = rz_buf_read_at(bin->b, bin->dysymtab.modtaboff + i * sizeof(struct MACH0_(dylib_module)),
609  dymod, sizeof(struct MACH0_(dylib_module)));
610  if (len == -1) {
611  bprintf("Error: read (modtab)\n");
612  RZ_FREE(bin->modtab);
613  return false;
614  }
615 
616  bin->modtab[i].module_name = rz_read_ble32(&dymod[0], bin->big_endian);
617  bin->modtab[i].iextdefsym = rz_read_ble32(&dymod[4], bin->big_endian);
618  bin->modtab[i].nextdefsym = rz_read_ble32(&dymod[8], bin->big_endian);
619  bin->modtab[i].irefsym = rz_read_ble32(&dymod[12], bin->big_endian);
620  bin->modtab[i].nrefsym = rz_read_ble32(&dymod[16], bin->big_endian);
621  bin->modtab[i].ilocalsym = rz_read_ble32(&dymod[20], bin->big_endian);
622  bin->modtab[i].nlocalsym = rz_read_ble32(&dymod[24], bin->big_endian);
623  bin->modtab[i].iextrel = rz_read_ble32(&dymod[28], bin->big_endian);
624  bin->modtab[i].nextrel = rz_read_ble32(&dymod[32], bin->big_endian);
625  bin->modtab[i].iinit_iterm = rz_read_ble32(&dymod[36], bin->big_endian);
626  bin->modtab[i].ninit_nterm = rz_read_ble32(&dymod[40], bin->big_endian);
627 #if RZ_BIN_MACH064
628  bin->modtab[i].objc_module_info_size = rz_read_ble32(&dymod[44], bin->big_endian);
629  bin->modtab[i].objc_module_info_addr = rz_read_ble64(&dymod[48], bin->big_endian);
630 #else
631  bin->modtab[i].objc_module_info_addr = rz_read_ble32(&dymod[44], bin->big_endian);
632  bin->modtab[i].objc_module_info_size = rz_read_ble32(&dymod[48], bin->big_endian);
633 #endif
634  }
635  }
636  bin->nindirectsyms = bin->dysymtab.nindirectsyms;
637  if (bin->nindirectsyms > 0) {
638  if (!(bin->indirectsyms = calloc(bin->nindirectsyms, sizeof(ut32)))) {
639  perror("calloc (indirectsyms)");
640  return false;
641  }
642  if (!UT32_MUL(&size_tab, bin->nindirectsyms, sizeof(ut32))) {
643  RZ_FREE(bin->indirectsyms);
644  return false;
645  }
646  if (!size_tab) {
647  RZ_FREE(bin->indirectsyms);
648  return false;
649  }
650  if (bin->dysymtab.indirectsymoff > bin->size ||
651  bin->dysymtab.indirectsymoff + size_tab > bin->size) {
652  RZ_FREE(bin->indirectsyms);
653  return false;
654  }
655  for (i = 0; i < bin->nindirectsyms; i++) {
656  len = rz_buf_read_at(bin->b, bin->dysymtab.indirectsymoff + i * sizeof(ut32), idsyms, 4);
657  if (len == -1) {
658  bprintf("Error: read (indirect syms)\n");
659  RZ_FREE(bin->indirectsyms);
660  return false;
661  }
662  bin->indirectsyms[i] = rz_read_ble32(&idsyms[0], bin->big_endian);
663  }
664  }
665  /* TODO extrefsyms, extrel, locrel */
666  return true;
667 }
static int UT32_MUL(ut32 *r, ut32 a, ut32 b)
Definition: rz_endian.h:643

References bprintf, calloc(), i, len, MACH0_(), off, rz_buf_read_at(), RZ_FREE, rz_read_ble32(), rz_read_ble64(), and UT32_MUL().

Referenced by init_items().

◆ parse_function_starts()

static int parse_function_starts ( struct MACH0_(obj_t) *  bin,
ut64  off 
)
static

Definition at line 1138 of file mach0.c.

1138  {
1139  struct linkedit_data_command fc;
1140  ut8 sfc[sizeof(struct linkedit_data_command)] = { 0 };
1141  int len;
1142 
1143  if (off > bin->size || off + sizeof(struct linkedit_data_command) > bin->size) {
1144  bprintf("Likely overflow while parsing"
1145  " LC_FUNCTION_STARTS command\n");
1146  }
1147  bin->func_start = NULL;
1148  len = rz_buf_read_at(bin->b, off, sfc, sizeof(struct linkedit_data_command));
1149  if (len < 1) {
1150  bprintf("Failed to get data while parsing"
1151  " LC_FUNCTION_STARTS command\n");
1152  }
1153  fc.cmd = rz_read_ble32(&sfc[0], bin->big_endian);
1154  fc.cmdsize = rz_read_ble32(&sfc[4], bin->big_endian);
1155  fc.dataoff = rz_read_ble32(&sfc[8], bin->big_endian);
1156  fc.datasize = rz_read_ble32(&sfc[12], bin->big_endian);
1157 
1158  if ((int)fc.datasize > 0) {
1159  ut8 *buf = calloc(1, fc.datasize + 1);
1160  if (!buf) {
1161  bprintf("Failed to allocate buffer\n");
1162  return false;
1163  }
1164  bin->func_size = fc.datasize;
1165  if (fc.dataoff > bin->size || fc.dataoff + fc.datasize > bin->size) {
1166  free(buf);
1167  bprintf("Likely overflow while parsing "
1168  "LC_FUNCTION_STARTS command\n");
1169  return false;
1170  }
1171  len = rz_buf_read_at(bin->b, fc.dataoff, buf, fc.datasize);
1172  if (len != fc.datasize) {
1173  free(buf);
1174  bprintf("Failed to get data while parsing"
1175  " LC_FUNCTION_STARTS\n");
1176  return false;
1177  }
1178  buf[fc.datasize] = 0; // null-terminated buffer
1179  bin->func_start = buf;
1180  return true;
1181  }
1182  bin->func_start = NULL;
1183  return false;
1184 }

References bprintf, calloc(), linkedit_data_command::cmd, linkedit_data_command::cmdsize, linkedit_data_command::dataoff, linkedit_data_command::datasize, free(), len, NULL, off, rz_buf_read_at(), and rz_read_ble32().

Referenced by init_items().

◆ parse_import_stub()

static bool parse_import_stub ( struct MACH0_(obj_t) *  bin,
struct symbol_t symbol,
int  idx 
)
static

Definition at line 2477 of file mach0.c.

2477  {
2478  size_t i, j, nsyms, stridx;
2479  const char *symstr;
2480  if (idx < 0) {
2481  return false;
2482  }
2483  symbol->offset = 0LL;
2484  symbol->addr = 0LL;
2485  symbol->name = NULL;
2486  symbol->is_imported = true;
2487 
2488  if (!bin || !bin->sects) {
2489  return false;
2490  }
2491  for (i = 0; i < bin->nsects; i++) {
2492  if ((bin->sects[i].flags & SECTION_TYPE) == S_SYMBOL_STUBS && bin->sects[i].reserved2 > 0) {
2493  ut64 sect_size = bin->sects[i].size;
2494  ut32 sect_fragment = bin->sects[i].reserved2;
2495  if (bin->sects[i].offset > bin->size) {
2496  bprintf("mach0: section offset starts way beyond the end of the file\n");
2497  continue;
2498  }
2499  if (sect_size > bin->size) {
2500  bprintf("mach0: Invalid symbol table size\n");
2501  sect_size = bin->size - bin->sects[i].offset;
2502  }
2503  nsyms = (int)(sect_size / sect_fragment);
2504  for (j = 0; j < nsyms; j++) {
2505  if (bin->sects) {
2506  if (bin->sects[i].reserved1 + j >= bin->nindirectsyms) {
2507  continue;
2508  }
2509  }
2510  if (bin->indirectsyms) {
2511  if (idx != bin->indirectsyms[bin->sects[i].reserved1 + j]) {
2512  continue;
2513  }
2514  }
2515  if (idx > bin->nsymtab) {
2516  continue;
2517  }
2519  int delta = j * bin->sects[i].reserved2;
2520  if (delta < 0) {
2521  bprintf("mach0: corrupted reserved2 value leads to int overflow.\n");
2522  continue;
2523  }
2524  symbol->offset = bin->sects[i].offset + delta;
2525  symbol->addr = bin->sects[i].addr + delta;
2526  symbol->size = 0;
2527  stridx = bin->symtab[idx].n_strx;
2528  if (stridx < bin->symstrlen) {
2529  symstr = (char *)bin->symstr + stridx;
2530  } else {
2531  symstr = "???";
2532  }
2533  // Remove the extra underscore that every import seems to have in Mach-O.
2534  if (*symstr == '_') {
2535  symstr++;
2536  }
2537  symbol->name = strdup(symstr);
2538  return true;
2539  }
2540  }
2541  }
2542  return false;
2543 }
@ S_SYMBOL_STUBS
@ SECTION_TYPE
static int
Definition: sfsocketcall.h:114
bool is_imported
Definition: mach0.h:60

References symbol_t::addr, bprintf, delta, i, setup::idx, int, symbol_t::is_imported, symbol_t::name, NULL, symbol_t::offset, RZ_BIN_MACH0_SYMBOL_TYPE_LOCAL, S_SYMBOL_STUBS, SECTION_TYPE, symbol_t::size, strdup(), symbol_t::type, and ut64().

Referenced by get_symbols(), and get_symbols_list().

◆ parse_segments()

static bool parse_segments ( struct MACH0_(obj_t) *  bin,
ut64  off 
)
static

Definition at line 277 of file mach0.c.

277  {
278  size_t i, j, k, sect, len;
279  ut32 size_sects;
280  ut8 segcom[sizeof(struct MACH0_(segment_command))] = { 0 };
281  ut8 sec[sizeof(struct MACH0_(section))] = { 0 };
282 
283  if (!UT32_MUL(&size_sects, bin->nsegs, sizeof(struct MACH0_(segment_command)))) {
284  return false;
285  }
286  if (!size_sects || size_sects > bin->size) {
287  return false;
288  }
289  if (off > bin->size || off + sizeof(struct MACH0_(segment_command)) > bin->size) {
290  return false;
291  }
292  if (!(bin->segs = realloc(bin->segs, bin->nsegs * sizeof(struct MACH0_(segment_command))))) {
293  perror("realloc (seg)");
294  return false;
295  }
296  j = bin->nsegs - 1;
297  len = rz_buf_read_at(bin->b, off, segcom, sizeof(struct MACH0_(segment_command)));
298  if (len != sizeof(struct MACH0_(segment_command))) {
299  bprintf("Error: read (seg)\n");
300  return false;
301  }
302  i = 0;
303  bin->segs[j].cmd = rz_read_ble32(&segcom[i], bin->big_endian);
304  i += sizeof(ut32);
305  bin->segs[j].cmdsize = rz_read_ble32(&segcom[i], bin->big_endian);
306  i += sizeof(ut32);
307  memcpy(&bin->segs[j].segname, &segcom[i], 16);
308  i += 16;
309 #if RZ_BIN_MACH064
310  bin->segs[j].vmaddr = rz_read_ble64(&segcom[i], bin->big_endian);
311  i += sizeof(ut64);
312  bin->segs[j].vmsize = rz_read_ble64(&segcom[i], bin->big_endian);
313  i += sizeof(ut64);
314  bin->segs[j].fileoff = rz_read_ble64(&segcom[i], bin->big_endian);
315  i += sizeof(ut64);
316  bin->segs[j].filesize = rz_read_ble64(&segcom[i], bin->big_endian);
317  i += sizeof(ut64);
318 #else
319  bin->segs[j].vmaddr = rz_read_ble32(&segcom[i], bin->big_endian);
320  i += sizeof(ut32);
321  bin->segs[j].vmsize = rz_read_ble32(&segcom[i], bin->big_endian);
322  i += sizeof(ut32);
323  bin->segs[j].fileoff = rz_read_ble32(&segcom[i], bin->big_endian);
324  i += sizeof(ut32);
325  bin->segs[j].filesize = rz_read_ble32(&segcom[i], bin->big_endian);
326  i += sizeof(ut32);
327 #endif
328  bin->segs[j].maxprot = rz_read_ble32(&segcom[i], bin->big_endian);
329  i += sizeof(ut32);
330  bin->segs[j].initprot = rz_read_ble32(&segcom[i], bin->big_endian);
331  i += sizeof(ut32);
332  bin->segs[j].nsects = rz_read_ble32(&segcom[i], bin->big_endian);
333  i += sizeof(ut32);
334  bin->segs[j].flags = rz_read_ble32(&segcom[i], bin->big_endian);
335 
336 #if RZ_BIN_MACH064
337  sdb_num_set(bin->kv, sdb_fmt("mach0_segment64_%zu.offset", j), off, 0);
338 #else
339  sdb_num_set(bin->kv, sdb_fmt("mach0_segment_%zu.offset", j), off, 0);
340 #endif
341 
342  sdb_num_set(bin->kv, "mach0_segments.count", 0, 0);
343 
344  if (bin->segs[j].nsects > 0) {
345  sect = bin->nsects;
346  bin->nsects += bin->segs[j].nsects;
347  if (bin->nsects > 128) {
348  int new_nsects = bin->nsects & 0xf;
349  bprintf("WARNING: mach0 header contains too many sections (%d). Wrapping to %d\n",
350  bin->nsects, new_nsects);
351  bin->nsects = new_nsects;
352  }
353  if ((int)bin->nsects < 1) {
354  bprintf("Warning: Invalid number of sections\n");
355  bin->nsects = sect;
356  return false;
357  }
358  if (!UT32_MUL(&size_sects, bin->nsects - sect, sizeof(struct MACH0_(section)))) {
359  bin->nsects = sect;
360  return false;
361  }
362  if (!size_sects || size_sects > bin->size) {
363  bin->nsects = sect;
364  return false;
365  }
366 
367  if (bin->segs[j].cmdsize != sizeof(struct MACH0_(segment_command)) + (sizeof(struct MACH0_(section)) * bin->segs[j].nsects)) {
368  bin->nsects = sect;
369  return false;
370  }
371 
372  if (off + sizeof(struct MACH0_(segment_command)) > bin->size ||
373  off + sizeof(struct MACH0_(segment_command)) + size_sects > bin->size) {
374  bin->nsects = sect;
375  return false;
376  }
377 
378  if (!(bin->sects = realloc(bin->sects, bin->nsects * sizeof(struct MACH0_(section))))) {
379  perror("realloc (sects)");
380  bin->nsects = sect;
381  return false;
382  }
383 
384  for (k = sect, j = 0; k < bin->nsects; k++, j++) {
385  ut64 offset = off + sizeof(struct MACH0_(segment_command)) + j * sizeof(struct MACH0_(section));
386  len = rz_buf_read_at(bin->b, offset, sec, sizeof(struct MACH0_(section)));
387  if (len != sizeof(struct MACH0_(section))) {
388  bprintf("Error: read (sects)\n");
389  bin->nsects = sect;
390  return false;
391  }
392 
393  i = 0;
394  memcpy(&bin->sects[k].sectname, &sec[i], 16);
395  i += 16;
396  memcpy(&bin->sects[k].segname, &sec[i], 16);
397  i += 16;
398 
399  sdb_num_set(bin->kv, sdb_fmt("mach0_section_%.16s_%.16s.offset", bin->sects[k].segname, bin->sects[k].sectname), offset, 0);
400 #if RZ_BIN_MACH064
401  sdb_set(bin->kv, sdb_fmt("mach0_section_%.16s_%.16s.format", bin->sects[k].segname, bin->sects[k].sectname), "mach0_section64", 0);
402 #else
403  sdb_set(bin->kv, sdb_fmt("mach0_section_%.16s_%.16s.format", bin->sects[k].segname, bin->sects[k].sectname), "mach0_section", 0);
404 #endif
405 
406 #if RZ_BIN_MACH064
407  bin->sects[k].addr = rz_read_ble64(&sec[i], bin->big_endian);
408  i += sizeof(ut64);
409  bin->sects[k].size = rz_read_ble64(&sec[i], bin->big_endian);
410  i += sizeof(ut64);
411 #else
412  bin->sects[k].addr = rz_read_ble32(&sec[i], bin->big_endian);
413  i += sizeof(ut32);
414  bin->sects[k].size = rz_read_ble32(&sec[i], bin->big_endian);
415  i += sizeof(ut32);
416 #endif
417  bin->sects[k].offset = rz_read_ble32(&sec[i], bin->big_endian);
418  i += sizeof(ut32);
419  bin->sects[k].align = rz_read_ble32(&sec[i], bin->big_endian);
420  i += sizeof(ut32);
421  bin->sects[k].reloff = rz_read_ble32(&sec[i], bin->big_endian);
422  i += sizeof(ut32);
423  bin->sects[k].nreloc = rz_read_ble32(&sec[i], bin->big_endian);
424  i += sizeof(ut32);
425  bin->sects[k].flags = rz_read_ble32(&sec[i], bin->big_endian);
426  i += sizeof(ut32);
427  bin->sects[k].reserved1 = rz_read_ble32(&sec[i], bin->big_endian);
428  i += sizeof(ut32);
429  bin->sects[k].reserved2 = rz_read_ble32(&sec[i], bin->big_endian);
430 #if RZ_BIN_MACH064
431  i += sizeof(ut32);
432  bin->sects[k].reserved3 = rz_read_ble32(&sec[i], bin->big_endian);
433 #endif
434  }
435  }
436  return true;
437 }
const char * k
Definition: dsignal.c:11
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))

References bprintf, i, k, len, MACH0_(), memcpy(), off, realloc(), rz_buf_read_at(), rz_read_ble32(), rz_read_ble64(), sdb_fmt(), sdb_num_set(), sdb_set(), UT32_MUL(), and ut64().

Referenced by init_items().

◆ parse_signature()

static bool parse_signature ( struct MACH0_(obj_t) *  bin,
ut64  off 
)
static

Definition at line 817 of file mach0.c.

817  {
818  int i, len;
819  ut32 data;
820  bin->signature = NULL;
821  struct linkedit_data_command link = { 0 };
822  ut8 lit[sizeof(struct linkedit_data_command)] = { 0 };
823  struct blob_index_t idx = { 0 };
824  struct super_blob_t super = { { 0 } };
825 
826  if (off > bin->size || off + sizeof(struct linkedit_data_command) > bin->size) {
827  return false;
828  }
829  len = rz_buf_read_at(bin->b, off, lit, sizeof(struct linkedit_data_command));
830  if (len != sizeof(struct linkedit_data_command)) {
831  bprintf("Failed to get data while parsing LC_CODE_SIGNATURE command\n");
832  return false;
833  }
834  link.cmd = rz_read_ble32(&lit[0], bin->big_endian);
835  link.cmdsize = rz_read_ble32(&lit[4], bin->big_endian);
836  link.dataoff = rz_read_ble32(&lit[8], bin->big_endian);
837  link.datasize = rz_read_ble32(&lit[12], bin->big_endian);
838 
839  data = link.dataoff;
840  if (data > bin->size || data + sizeof(struct super_blob_t) > bin->size) {
841  bin->signature = (ut8 *)strdup("Malformed entitlement");
842  return true;
843  }
844 
845  if (!rz_buf_read_ble32_at(bin->b, data, &super.blob.magic, mach0_endian) ||
846  !rz_buf_read_ble32_at(bin->b, data + 4, &super.blob.length, mach0_endian) ||
847  !rz_buf_read_ble32_at(bin->b, data + 8, &super.count, mach0_endian)) {
848  return false;
849  }
850 
851  char *verbose = rz_sys_getenv("RZ_BIN_CODESIGN_VERBOSE");
852  bool isVerbose = false;
853  if (verbose) {
854  isVerbose = *verbose;
855  free(verbose);
856  }
857  // to dump all certificates
858  // [0x00053f75]> b 5K;/x 30800609;wtf @@ hit*
859  // then do this:
860  // $ openssl asn1parse -inform der -in a|less
861  // $ openssl pkcs7 -inform DER -print_certs -text -in a
862  for (i = 0; i < super.count; i++) {
863  if (data + i > bin->size) {
864  bin->signature = (ut8 *)strdup("Malformed entitlement");
865  break;
866  }
867  struct blob_index_t bi;
868  if (rz_buf_read_at(bin->b, data + 12 + (i * sizeof(struct blob_index_t)),
869  (ut8 *)&bi, sizeof(struct blob_index_t)) < sizeof(struct blob_index_t)) {
870  break;
871  }
872  idx.type = rz_read_ble32(&bi.type, mach0_endian);
873  idx.offset = rz_read_ble32(&bi.offset, mach0_endian);
874  switch (idx.type) {
875  case CSSLOT_ENTITLEMENTS:
876  if (true || isVerbose) {
877  ut64 off = data + idx.offset;
878  if (off > bin->size || off + sizeof(struct blob_t) > bin->size) {
879  bin->signature = (ut8 *)strdup("Malformed entitlement");
880  break;
881  }
882  struct blob_t entitlements = { 0 };
883  if (!rz_buf_read_ble32_at(bin->b, off, &entitlements.magic, mach0_endian) ||
884  !rz_buf_read_ble32_at(bin->b, off + 4, &entitlements.length, mach0_endian)) {
885  break;
886  }
887  len = entitlements.length - sizeof(struct blob_t);
888  if (len <= bin->size && len > 1) {
889  bin->signature = calloc(1, len + 1);
890  if (!bin->signature) {
891  break;
892  }
893  if (off + sizeof(struct blob_t) + len < rz_buf_size(bin->b)) {
894  rz_buf_read_at(bin->b, off + sizeof(struct blob_t), (ut8 *)bin->signature, len);
895  if (len >= 0) {
896  bin->signature[len] = '\0';
897  }
898  } else {
899  bin->signature = (ut8 *)strdup("Malformed entitlement");
900  }
901  } else {
902  bin->signature = (ut8 *)strdup("Malformed entitlement");
903  }
904  }
905  break;
907  if (isVerbose) {
908  parseCodeDirectory(bin, bin->b, data + idx.offset, link.datasize);
909  }
910  break;
911  case 0x1000:
912  // unknown
913  break;
914  case CSSLOT_CMS_SIGNATURE: // ASN1/DER certificate
915  if (isVerbose) {
916  ut8 header[8] = { 0 };
917  rz_buf_read_at(bin->b, data + idx.offset, header, sizeof(header));
919  ut8 *p = calloc(length, 1);
920  if (p) {
921  rz_buf_read_at(bin->b, data + idx.offset + 0, p, length);
922  ut32 *words = (ut32 *)p;
923  eprintf("Magic: %x\n", words[0]);
924  eprintf("wtf DUMP @%d!%d\n",
925  (int)data + idx.offset + 8, (int)length);
926  eprintf("openssl pkcs7 -print_certs -text -inform der -in DUMP\n");
927  eprintf("openssl asn1parse -offset %d -length %d -inform der -in /bin/ls\n",
928  (int)data + idx.offset + 8, (int)length);
929  eprintf("pFp@%d!%d\n",
930  (int)data + idx.offset + 8, (int)length);
931  free(p);
932  }
933  }
934  break;
935  case CSSLOT_REQUIREMENTS: // 2
936  {
937  ut8 p[256];
938  rz_buf_read_at(bin->b, data + idx.offset + 16, p, sizeof(p));
939  p[sizeof(p) - 1] = 0;
940  ut32 slot_size = rz_read_ble32(p + 8, 1);
941  if (slot_size < sizeof(p)) {
942  ut32 ident_size = rz_read_ble32(p + 8, 1);
943  char *ident = rz_str_ndup((const char *)p + 28, ident_size);
944  if (ident) {
945  sdb_set(bin->kv, "mach0.ident", ident, 0);
946  free(ident);
947  }
948  } else {
949  if (bin->options.verbose) {
950  eprintf("Invalid code slot size\n");
951  }
952  }
953  } break;
954  case CSSLOT_INFOSLOT: // 1;
955  case CSSLOT_RESOURCEDIR: // 3;
956  case CSSLOT_APPLICATION: // 4;
957  // TODO: parse those codesign slots
958  if (bin->options.verbose) {
959  eprintf("TODO: Some codesign slots are not yet supported\n");
960  }
961  break;
962  default:
963  if (bin->options.verbose) {
964  eprintf("Unknown Code signature slot %d\n", idx.type);
965  }
966  break;
967  }
968  }
969  if (!bin->signature) {
970  bin->signature = (ut8 *)strdup("No entitlement found");
971  }
972  return true;
973 }
static char * entitlements(RzBinFile *bf, bool json)
Definition: bin_mach0.c:27
static static fork const void static count static fd link
Definition: sflib.h:33
void * p
Definition: libc.cpp:67
#define mach0_endian
Definition: mach0.c:39
static void parseCodeDirectory(struct MACH0_(obj_t) *mo, RzBuffer *b, int offset, int datasize)
Definition: mach0.c:676
#define CSSLOT_CMS_SIGNATURE
Definition: mach0.h:40
#define CSSLOT_CODEDIRECTORY
Definition: mach0.h:34
#define CSSLOT_RESOURCEDIR
Definition: mach0.h:37
#define CSSLOT_INFOSLOT
Definition: mach0.h:35
#define CSSLOT_APPLICATION
Definition: mach0.h:38
#define CSSLOT_REQUIREMENTS
Definition: mach0.h:36
#define CSSLOT_ENTITLEMENTS
Definition: mach0.h:39
RZ_API char * rz_sys_getenv(const char *key)
Get the value of an environment variable named key or NULL if none exists.
Definition: sys.c:483
#define UT16_MAX
Definition: mach0.h:102
ut32 length
Definition: mach0.h:104
ut32 magic
Definition: mach0.h:103
ut32 count
Definition: mach0.h:109
struct blob_t blob
Definition: mach0.h:108
static int verbose
Definition: z80asm.c:73

References super_blob_t::blob, bprintf, calloc(), super_blob_t::count, CSSLOT_APPLICATION, CSSLOT_CMS_SIGNATURE, CSSLOT_CODEDIRECTORY, CSSLOT_ENTITLEMENTS, CSSLOT_INFOSLOT, CSSLOT_REQUIREMENTS, CSSLOT_RESOURCEDIR, entitlements(), eprintf, free(), header, i, setup::idx, len, blob_t::length, length, link, mach0_endian, blob_t::magic, NULL, off, blob_index_t::offset, p, parseCodeDirectory(), rz_buf_read_at(), rz_buf_size(), RZ_MIN, rz_read_ble32(), rz_str_ndup(), rz_sys_getenv(), sdb_set(), strdup(), blob_index_t::type, UT16_MAX, ut64(), and verbose.

Referenced by init_items().

◆ parse_symtab()

static bool parse_symtab ( struct MACH0_(obj_t) *  mo,
ut64  off 
)
static

Definition at line 442 of file mach0.c.

442  {
443  struct symtab_command st;
444  ut32 size_sym;
445  size_t i;
446  const char *error_message = "";
447  ut8 symt[sizeof(struct symtab_command)] = { 0 };
448  ut8 nlst[sizeof(struct MACH0_(nlist))] = { 0 };
449  const bool be = mo->big_endian;
450 
451  if (off > (ut64)mo->size || off + sizeof(struct symtab_command) > (ut64)mo->size) {
452  return false;
453  }
454  int len = rz_buf_read_at(mo->b, off, symt, sizeof(struct symtab_command));
455  if (len != sizeof(struct symtab_command)) {
456  Eprintf("Error: read (symtab)\n");
457  return false;
458  }
459  st.cmd = rz_read_ble32(symt, be);
460  st.cmdsize = rz_read_ble32(symt + 4, be);
461  st.symoff = rz_read_ble32(symt + 8, be) + mo->options.symbols_off;
462  st.nsyms = rz_read_ble32(symt + 12, be);
463  st.stroff = rz_read_ble32(symt + 16, be) + mo->options.symbols_off;
464  st.strsize = rz_read_ble32(symt + 20, be);
465 
466  mo->symtab = NULL;
467  mo->nsymtab = 0;
468  if (st.strsize > 0 && st.strsize < mo->size && st.nsyms > 0) {
469  mo->nsymtab = st.nsyms;
470  if (st.stroff > mo->size || st.stroff + st.strsize > mo->size) {
471  Error("fail");
472  }
473  if (!UT32_MUL(&size_sym, mo->nsymtab, sizeof(struct MACH0_(nlist)))) {
474  Error("fail2");
475  }
476  if (!size_sym) {
477  Error("symbol size is zero");
478  }
479  if (st.symoff > mo->size || st.symoff + size_sym > mo->size) {
480  Error("symoff is out of bounds");
481  }
482  if (!(mo->symstr = calloc(1, st.strsize + 2))) {
483  Error("symoff is out of bounds");
484  }
485  mo->symstrlen = st.strsize;
486  len = rz_buf_read_at(mo->b, st.stroff, (ut8 *)mo->symstr, st.strsize);
487  if (len != st.strsize) {
488  Error("Error: read (symstr)");
489  }
490  if (!(mo->symtab = calloc(mo->nsymtab, sizeof(struct MACH0_(nlist))))) {
491  goto error;
492  }
493  for (i = 0; i < mo->nsymtab; i++) {
494  ut64 at = st.symoff + (i * sizeof(struct MACH0_(nlist)));
495  len = rz_buf_read_at(mo->b, at, nlst, sizeof(struct MACH0_(nlist)));
496  if (len != sizeof(struct MACH0_(nlist))) {
497  Error("read (nlist)");
498  }
499  // XXX not very safe what if is n_un.n_name instead?
500  mo->symtab[i].n_strx = rz_read_ble32(nlst, be);
501  mo->symtab[i].n_type = rz_read_ble8(nlst + 4);
502  mo->symtab[i].n_sect = rz_read_ble8(nlst + 5);
503  mo->symtab[i].n_desc = rz_read_ble16(nlst + 6, be);
504 #if RZ_BIN_MACH064
505  mo->symtab[i].n_value = rz_read_ble64(&nlst[8], be);
506 #else
507  mo->symtab[i].n_value = rz_read_ble32(&nlst[8], be);
508 #endif
509  }
510  }
511  return true;
512 error:
513  RZ_FREE(mo->symstr);
514  RZ_FREE(mo->symtab);
515  Eprintf("%s\n", error_message);
516  return false;
517 }
#define Error(x)
Definition: mach0.c:439
static ut8 rz_read_ble8(const void *src)
Definition: rz_endian.h:12

References calloc(), symtab_command::cmd, symtab_command::cmdsize, Eprintf, error(), Error, i, len, MACH0_(), symtab_command::nsyms, NULL, off, rz_buf_read_at(), RZ_FREE, rz_read_ble16(), rz_read_ble32(), rz_read_ble64(), rz_read_ble8(), symtab_command::stroff, symtab_command::strsize, symtab_command::symoff, UT32_MUL(), and ut64().

Referenced by init_items().

◆ parse_thread()

static int parse_thread ( struct MACH0_(obj_t) *  bin,
struct load_command lc,
ut64  off,
bool  is_first_thread 
)
static

Definition at line 975 of file mach0.c.

975  {
976  ut64 ptr_thread, pc = UT64_MAX, pc_offset = UT64_MAX;
977  ut32 flavor, count;
978  ut8 *arw_ptr = NULL;
979  int arw_sz, len = 0;
980  ut8 thc[sizeof(struct thread_command)] = { 0 };
981  ut8 tmp[4];
982 
983  if (off > bin->size || off + sizeof(struct thread_command) > bin->size) {
984  return false;
985  }
986 
987  len = rz_buf_read_at(bin->b, off, thc, 8);
988  if (len < 1) {
989  goto wrong_read;
990  }
991  bin->thread.cmd = rz_read_ble32(&thc[0], bin->big_endian);
992  bin->thread.cmdsize = rz_read_ble32(&thc[4], bin->big_endian);
993  if (rz_buf_read_at(bin->b, off + sizeof(struct thread_command), tmp, 4) < 4) {
994  goto wrong_read;
995  }
996  flavor = rz_read_ble32(tmp, bin->big_endian);
997 
998  if (off + sizeof(struct thread_command) + sizeof(flavor) > bin->size ||
999  off + sizeof(struct thread_command) + sizeof(flavor) + sizeof(ut32) > bin->size) {
1000  return false;
1001  }
1002 
1003  // TODO: use count for checks
1004  if (rz_buf_read_at(bin->b, off + sizeof(struct thread_command) + sizeof(flavor), tmp, 4) < 4) {
1005  goto wrong_read;
1006  }
1007  ptr_thread = off + sizeof(struct thread_command) + sizeof(flavor) + sizeof(count);
1008 
1009  if (ptr_thread > bin->size) {
1010  return false;
1011  }
1012 
1013  switch (bin->hdr.cputype) {
1014  case CPU_TYPE_I386:
1015  case CPU_TYPE_X86_64:
1016  switch (flavor) {
1017  case X86_THREAD_STATE32:
1018  if (ptr_thread + sizeof(struct x86_thread_state32) > bin->size) {
1019  return false;
1020  }
1021  if (rz_buf_fread_at(bin->b, ptr_thread,
1022  (ut8 *)&bin->thread_state.x86_32, "16i", 1) == -1) {
1023  bprintf("Error: read (thread state x86_32)\n");
1024  return false;
1025  }
1026  pc = bin->thread_state.x86_32.eip;
1027  pc_offset = ptr_thread + rz_offsetof(struct x86_thread_state32, eip);
1028  arw_ptr = (ut8 *)&bin->thread_state.x86_32;
1029  arw_sz = sizeof(struct x86_thread_state32);
1030  break;
1031  case X86_THREAD_STATE64:
1032  if (ptr_thread + sizeof(struct x86_thread_state64) > bin->size) {
1033  return false;
1034  }
1035  if (rz_buf_fread_at(bin->b, ptr_thread,
1036  (ut8 *)&bin->thread_state.x86_64, "32l", 1) == -1) {
1037  bprintf("Error: read (thread state x86_64)\n");
1038  return false;
1039  }
1040  pc = bin->thread_state.x86_64.rip;
1041  pc_offset = ptr_thread + rz_offsetof(struct x86_thread_state64, rip);
1042  arw_ptr = (ut8 *)&bin->thread_state.x86_64;
1043  arw_sz = sizeof(struct x86_thread_state64);
1044  break;
1045  // default: bprintf ("Unknown type\n");
1046  }
1047  break;
1048  case CPU_TYPE_POWERPC:
1049  case CPU_TYPE_POWERPC64:
1050  if (flavor == X86_THREAD_STATE32) {
1051  if (ptr_thread + sizeof(struct ppc_thread_state32) > bin->size) {
1052  return false;
1053  }
1054  if (rz_buf_fread_at(bin->b, ptr_thread,
1055  (ut8 *)&bin->thread_state.ppc_32, bin->big_endian ? "40I" : "40i", 1) == -1) {
1056  bprintf("Error: read (thread state ppc_32)\n");
1057  return false;
1058  }
1059  pc = bin->thread_state.ppc_32.srr0;
1060  pc_offset = ptr_thread + rz_offsetof(struct ppc_thread_state32, srr0);
1061  arw_ptr = (ut8 *)&bin->thread_state.ppc_32;
1062  arw_sz = sizeof(struct ppc_thread_state32);
1063  } else if (flavor == X86_THREAD_STATE64) {
1064  if (ptr_thread + sizeof(struct ppc_thread_state64) > bin->size) {
1065  return false;
1066  }
1067  if (rz_buf_fread_at(bin->b, ptr_thread,
1068  (ut8 *)&bin->thread_state.ppc_64, bin->big_endian ? "34LI3LI" : "34li3li", 1) == -1) {
1069  bprintf("Error: read (thread state ppc_64)\n");
1070  return false;
1071  }
1072  pc = bin->thread_state.ppc_64.srr0;
1073  pc_offset = ptr_thread + rz_offsetof(struct ppc_thread_state64, srr0);
1074  arw_ptr = (ut8 *)&bin->thread_state.ppc_64;
1075  arw_sz = sizeof(struct ppc_thread_state64);
1076  }
1077  break;
1078  case CPU_TYPE_ARM:
1079  if (ptr_thread + sizeof(struct arm_thread_state32) > bin->size) {
1080  return false;
1081  }
1082  if (rz_buf_fread_at(bin->b, ptr_thread,
1083  (ut8 *)&bin->thread_state.arm_32, bin->big_endian ? "17I" : "17i", 1) == -1) {
1084  bprintf("Error: read (thread state arm)\n");
1085  return false;
1086  }
1087  pc = bin->thread_state.arm_32.r15;
1088  pc_offset = ptr_thread + rz_offsetof(struct arm_thread_state32, r15);
1089  arw_ptr = (ut8 *)&bin->thread_state.arm_32;
1090  arw_sz = sizeof(struct arm_thread_state32);
1091  break;
1092  case CPU_TYPE_ARM64:
1093  if (ptr_thread + sizeof(struct arm_thread_state64) > bin->size) {
1094  return false;
1095  }
1096  if (rz_buf_fread_at(bin->b, ptr_thread,
1097  (ut8 *)&bin->thread_state.arm_64, bin->big_endian ? "34LI1I" : "34Li1i", 1) == -1) {
1098  bprintf("Error: read (thread state arm)\n");
1099  return false;
1100  }
1101  pc = rz_read_be64(&bin->thread_state.arm_64.pc);
1102  pc_offset = ptr_thread + rz_offsetof(struct arm_thread_state64, pc);
1103  arw_ptr = (ut8 *)&bin->thread_state.arm_64;
1104  arw_sz = sizeof(struct arm_thread_state64);
1105  break;
1106  default:
1107  bprintf("Error: read (unknown thread state structure)\n");
1108  return false;
1109  }
1110 
1111  // TODO: this shouldnt be an bprintf...
1112  if (arw_ptr && arw_sz > 0) {
1113  int i;
1114  ut8 *p = arw_ptr;
1115  bprintf("arw ");
1116  for (i = 0; i < arw_sz; i++) {
1117  bprintf("%02x", 0xff & p[i]);
1118  }
1119  bprintf("\n");
1120  }
1121 
1122  if (is_first_thread) {
1123  bin->main_cmd = *lc;
1124  if (pc != UT64_MAX) {
1125  bin->entry = pc;
1126  }
1127  if (pc_offset != UT64_MAX) {
1128  sdb_num_set(bin->kv, "mach0.entry.offset", pc_offset, 0);
1129  }
1130  }
1131 
1132  return true;
1133 wrong_read:
1134  bprintf("Error: read (thread)\n");
1135  return false;
1136 }
void rip(char *fname, off_t offset, unsigned int length)
Definition: cabrip.c:18
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
#define X86_THREAD_STATE64
Definition: mach0_specs.h:72
#define X86_THREAD_STATE32
Definition: mach0_specs.h:71
static ut64 rz_read_be64(const void *src)
Definition: rz_endian.h:108
#define rz_offsetof(type, member)
Definition: rz_types.h:360

References bprintf, count, CPU_TYPE_ARM, CPU_TYPE_ARM64, CPU_TYPE_I386, CPU_TYPE_POWERPC, CPU_TYPE_POWERPC64, CPU_TYPE_X86_64, i, len, NULL, off, p, pc, r15, rip(), rz_buf_fread_at(), rz_buf_read_at(), rz_offsetof, rz_read_be64(), rz_read_ble32(), sdb_num_set(), autogen_x86imm::tmp, ut64(), UT64_MAX, X86_THREAD_STATE32, and X86_THREAD_STATE64.

Referenced by init_items().

◆ parseCodeDirectory()

static void parseCodeDirectory ( struct MACH0_(obj_t) *  mo,
RzBuffer b,
int  offset,
int  datasize 
)
static

Definition at line 676 of file mach0.c.

676  {
677  typedef struct __CodeDirectory {
678  uint32_t magic; /* magic number (CSMAGIC_CODEDIRECTORY) */
679  uint32_t length; /* total length of CodeDirectory blob */
680  uint32_t version; /* compatibility version */
681  uint32_t flags; /* setup and mode flags */
682  uint32_t hashOffset; /* offset of hash slot element at index zero */
683  uint32_t identOffset; /* offset of identifier string */
684  uint32_t nSpecialSlots; /* number of special hash slots */
685  uint32_t nCodeSlots; /* number of ordinary (code) hash slots */
686  uint32_t codeLimit; /* limit to main image signature range */
687  uint8_t hashSize; /* size of each hash in bytes */
688  uint8_t hashType; /* type of hash (cdHashType* constants) */
689  uint8_t platform; /* unused (must be zero) */
690  uint8_t pageSize; /* log2(page size in bytes); 0 => infinite */
691  uint32_t spare2; /* unused (must be zero) */
692  /* followed by dynamic content as located by offset fields above */
693  uint32_t scatterOffset;
694  uint32_t teamIDOffset;
695  uint32_t spare3;
696  ut64 codeLimit64;
697  ut64 execSegBase;
698  ut64 execSegLimit;
699  ut64 execSegFlags;
700  } CS_CodeDirectory;
701  ut64 off = offset;
702  int psize = datasize;
703  ut8 *p = calloc(1, psize);
704  if (!p) {
705  return;
706  }
707  eprintf("Offset: 0x%08" PFMT64x "\n", off);
708  rz_buf_read_at(b, off, p, datasize);
709  CS_CodeDirectory cscd = { 0 };
710 #define READFIELD(x) cscd.x = rz_read_ble32(p + rz_offsetof(CS_CodeDirectory, x), 1)
711 #define READFIELD8(x) cscd.x = p[rz_offsetof(CS_CodeDirectory, x)]
712  READFIELD(length);
714  READFIELD(flags);
715  READFIELD(hashOffset);
716  READFIELD(identOffset);
717  READFIELD(nSpecialSlots);
718  READFIELD(nCodeSlots);
719  READFIELD(hashSize);
720  READFIELD(teamIDOffset);
721  READFIELD8(hashType);
722  READFIELD(pageSize);
723  READFIELD(codeLimit);
724  eprintf("Version: %x\n", cscd.version);
725  eprintf("Flags: %x\n", cscd.flags);
726  eprintf("Length: %d\n", cscd.length);
727  eprintf("PageSize: %d\n", cscd.pageSize);
728  eprintf("hashOffset: %d\n", cscd.hashOffset);
729  eprintf("codeLimit: %d\n", cscd.codeLimit);
730  eprintf("hashSize: %d\n", cscd.hashSize);
731  eprintf("hashType: %d\n", cscd.hashType);
732  char *identity = readString(p, cscd.identOffset, psize);
733  eprintf("Identity: %s\n", identity);
734  char *teamId = readString(p, cscd.teamIDOffset, psize);
735  eprintf("TeamID: %s\n", teamId);
736  eprintf("CodeSlots: %d\n", cscd.nCodeSlots);
737  free(identity);
738  free(teamId);
739 
740  const char *digest_algo = "sha1";
741  switch (cscd.hashType) {
742  case 0: // SHA1 == 20 bytes
743  case 1: // SHA1 == 20 bytes
744  digest_algo = "sha1";
745  break;
746  case 2: // SHA256 == 32 bytes
747  digest_algo = "sha256";
748  break;
749  }
750 
751  // computed cdhash
752  RzHashSize digest_size = 0;
753  ut8 *digest = NULL;
754 
755  int fofsz = cscd.length;
756  ut8 *fofbuf = calloc(fofsz, 1);
757  if (fofbuf) {
758  int i;
759  if (rz_buf_read_at(b, off, fofbuf, fofsz) != fofsz) {
760  eprintf("Invalid cdhash offset/length values\n");
761  goto parseCodeDirectory_end;
762  }
763 
764  digest = rz_hash_cfg_calculate_small_block(mo->hash, digest_algo, fofbuf, fofsz, &digest_size);
765  if (!digest) {
766  goto parseCodeDirectory_end;
767  }
768 
769  eprintf("ph %s @ 0x%" PFMT64x "!%d\n", digest_algo, off, fofsz);
770  eprintf("ComputedCDHash: ");
771  for (i = 0; i < digest_size; i++) {
772  eprintf("%02x", digest[i]);
773  }
774  eprintf("\n");
775  RZ_FREE(digest);
776  free(fofbuf);
777  }
778  // show and check the rest of hashes
779  ut8 *hash = p + cscd.hashOffset;
780  int j = 0;
781  int k = 0;
782  eprintf("Hashed region: 0x%08" PFMT64x " - 0x%08" PFMT64x "\n", (ut64)0, (ut64)cscd.codeLimit);
783  for (j = 0; j < cscd.nCodeSlots; j++) {
784  int fof = 4096 * j;
785  int idx = j * digest_size;
786  eprintf("0x%08" PFMT64x " ", off + cscd.hashOffset + idx);
787  for (k = 0; k < digest_size; k++) {
788  eprintf("%02x", hash[idx + k]);
789  }
790  ut8 fofbuf[4096];
791  int fofsz = RZ_MIN(sizeof(fofbuf), cscd.codeLimit - fof);
792  rz_buf_read_at(b, fof, fofbuf, sizeof(fofbuf));
793 
794  digest = rz_hash_cfg_calculate_small_block(mo->hash, digest_algo, fofbuf, fofsz, &digest_size);
795  if (!digest) {
796  goto parseCodeDirectory_end;
797  }
798 
799  if (memcmp(hash + idx, digest, digest_size)) {
800  eprintf(" wx ");
801  int i;
802  for (i = 0; i < digest_size; i++) {
803  eprintf("%02x", digest[i]);
804  }
805  } else {
806  eprintf(" OK");
807  }
808  eprintf("\n");
809  free(digest);
810  }
811 
812 parseCodeDirectory_end:
813  free(p);
814 }
static char * version
Definition: acr.h:4
RZ_API RZ_OWN ut8 * rz_hash_cfg_calculate_small_block(RZ_NONNULL RzHash *rh, RZ_NONNULL const char *name, RZ_NONNULL const ut8 *buffer, ut64 bsize, RZ_NONNULL RzHashSize *osize)
Returns the digest size of the requested algorithm name.
Definition: hash.c:529
#define READFIELD8(x)
static char * readString(ut8 *p, int off, int len)
Definition: mach0.c:669
#define READFIELD(x)
ut32 RzHashSize
Definition: rz_hash.h:24
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
unsigned int uint32_t
Definition: sftypes.h:29
unsigned char uint8_t
Definition: sftypes.h:31

References b, calloc(), eprintf, flags, free(), i, setup::idx, k, length, NULL, off, p, PFMT64x, READFIELD, READFIELD8, readString(), rz_buf_read_at(), RZ_FREE, rz_hash_cfg_calculate_small_block(), RZ_MIN, ut64(), and version.

Referenced by parse_signature().

◆ prot2perm()

static int prot2perm ( int  x)
static

Definition at line 2132 of file mach0.c.

2132  {
2133  int r = 0;
2134  if (x & 1) {
2135  r |= 4;
2136  }
2137  if (x & 2) {
2138  r |= 2;
2139  }
2140  if (x & 4) {
2141  r |= 1;
2142  }
2143  return r;
2144 }
#define r
Definition: crypto_rc6.c:12

References r, and x.

Referenced by get_maps_unpatched(), get_sections(), and get_segments().

◆ readString()

static char* readString ( ut8 p,
int  off,
int  len 
)
static

Definition at line 669 of file mach0.c.

669  {
670  if (off < 0 || off >= len) {
671  return NULL;
672  }
673  return rz_str_ndup((const char *)p + off, len - off);
674 }

References len, NULL, off, p, and rz_str_ndup().

Referenced by parseCodeDirectory().

◆ reconstruct_chained_fixup()

static bool reconstruct_chained_fixup ( struct MACH0_(obj_t) *  bin)
static

Definition at line 1532 of file mach0.c.

1532  {
1533  if (!bin->dyld_info) {
1534  return false;
1535  }
1536  if (!bin->nsegs) {
1537  return false;
1538  }
1539  bin->nchained_starts = bin->nsegs;
1540  bin->chained_starts = RZ_NEWS0(struct rz_dyld_chained_starts_in_segment *, bin->nchained_starts);
1541  if (!bin->chained_starts) {
1542  return false;
1543  }
1544  size_t wordsize = get_word_size(bin);
1545  ut8 *p = NULL;
1546  size_t j, count, skip, bind_size;
1547  int seg_idx = 0;
1548  ut64 seg_off = 0;
1549  bind_size = bin->dyld_info->bind_size;
1550  if (!bind_size || bind_size < 1) {
1551  return false;
1552  }
1553  if (bin->dyld_info->bind_off > bin->size) {
1554  return false;
1555  }
1556  if (bin->dyld_info->bind_off + bind_size > bin->size) {
1557  return false;
1558  }
1559  ut8 *opcodes = calloc(1, bind_size + 1);
1560  if (!opcodes) {
1561  return false;
1562  }
1563  if (rz_buf_read_at(bin->b, bin->dyld_info->bind_off, opcodes, bind_size) != bind_size) {
1564  bprintf("Error: read (dyld_info bind) at 0x%08" PFMT64x "\n", (ut64)(size_t)bin->dyld_info->bind_off);
1565  RZ_FREE(opcodes);
1566  return false;
1567  }
1568  struct rz_dyld_chained_starts_in_segment *cur_seg = NULL;
1569  size_t cur_seg_idx = 0;
1570  ut8 *end;
1571  bool done = false;
1572  for (p = opcodes, end = opcodes + bind_size; !done && p < end;) {
1574  p++;
1575  switch (op) {
1576  case BIND_OPCODE_DONE:
1577  done = true;
1578  break;
1579  case BIND_OPCODE_THREADED: {
1580  switch (imm) {
1582  read_uleb128(&p, end);
1583  break;
1584  }
1586  const size_t ps = 0x1000;
1587  if (!cur_seg || cur_seg_idx != seg_idx) {
1588  cur_seg_idx = seg_idx;
1589  cur_seg = bin->chained_starts[seg_idx];
1590  if (!cur_seg) {
1591  cur_seg = RZ_NEW0(struct rz_dyld_chained_starts_in_segment);
1592  if (!cur_seg) {
1593  break;
1594  }
1595  bin->chained_starts[seg_idx] = cur_seg;
1597  cur_seg->page_size = ps;
1598  cur_seg->page_count = ((bin->segs[seg_idx].vmsize + (ps - 1)) & ~(ps - 1)) / ps;
1599  if (cur_seg->page_count > 0) {
1600  cur_seg->page_start = malloc(sizeof(ut16) * cur_seg->page_count);
1601  if (!cur_seg->page_start) {
1602  break;
1603  }
1604  memset(cur_seg->page_start, 0xff, sizeof(ut16) * cur_seg->page_count);
1605  }
1606  }
1607  }
1608  if (cur_seg) {
1609  ut32 page_index = (ut32)(seg_off / ps);
1610  size_t maxsize = cur_seg->page_count * sizeof(ut16);
1611  if (page_index < maxsize) {
1612  cur_seg->page_start[page_index] = seg_off & 0xfff;
1613  }
1614  }
1615  break;
1616  }
1617  default:
1618  bprintf("Error: Unexpected BIND_OPCODE_THREADED sub-opcode: 0x%x\n", imm);
1619  }
1620  break;
1621  }
1625  break;
1627  read_uleb128(&p, end);
1628  break;
1630  while (*p++ && p < end) {
1631  /* empty loop */
1632  }
1633  break;
1635  rz_sleb128((const ut8 **)&p, end);
1636  break;
1638  seg_idx = imm;
1639  if (seg_idx >= bin->nsegs) {
1640  bprintf("Error: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB"
1641  " has unexistent segment %d\n",
1642  seg_idx);
1643  RZ_FREE(opcodes);
1644  return false;
1645  } else {
1646  seg_off = read_uleb128(&p, end);
1647  }
1648  break;
1650  seg_off += read_uleb128(&p, end);
1651  break;
1652  case BIND_OPCODE_DO_BIND:
1653  break;
1655  seg_off += read_uleb128(&p, end) + wordsize;
1656  break;
1658  seg_off += (ut64)imm * (ut64)wordsize + wordsize;
1659  break;
1661  count = read_uleb128(&p, end);
1662  skip = read_uleb128(&p, end);
1663  for (j = 0; j < count; j++) {
1664  seg_off += skip + wordsize;
1665  }
1666  break;
1667  default:
1668  bprintf("Error: unknown bind opcode 0x%02x in dyld_info\n", *p);
1669  RZ_FREE(opcodes);
1670  return false;
1671  }
1672  }
1673  RZ_FREE(opcodes);
1674 
1675  return true;
1676 }
#define imm
OPCODE_DESC opcodes[]
Definition: avr_esil.c:1270
struct tab * done
Definition: enough.c:233
void skip(file *in, unsigned n)
Definition: gzappend.c:202
static const char * page_index
Definition: rz-agent.c:8
@ BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB
@ BIND_SUBOPCODE_THREADED_APPLY
@ BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
@ BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
@ BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
@ BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
@ BIND_OPCODE_ADD_ADDR_ULEB
@ BIND_OPCODE_SET_TYPE_IMM
@ BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
@ BIND_OPCODE_DO_BIND
@ BIND_OPCODE_SET_ADDEND_SLEB
@ BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
@ BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
@ BIND_OPCODE_THREADED
@ BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
@ BIND_OPCODE_DONE
@ DYLD_CHAINED_PTR_ARM64E
@ BIND_OPCODE_MASK
@ BIND_IMMEDIATE_MASK
RZ_API st64 rz_sleb128(const ut8 **data, const ut8 *end)
Definition: uleb128.c:145
Definition: dis.c:32

References BIND_IMMEDIATE_MASK, BIND_OPCODE_ADD_ADDR_ULEB, BIND_OPCODE_DO_BIND, BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED, BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB, BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB, BIND_OPCODE_DONE, BIND_OPCODE_MASK, BIND_OPCODE_SET_ADDEND_SLEB, BIND_OPCODE_SET_DYLIB_ORDINAL_IMM, BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB, BIND_OPCODE_SET_DYLIB_SPECIAL_IMM, BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM, BIND_OPCODE_SET_TYPE_IMM, BIND_OPCODE_THREADED, BIND_SUBOPCODE_THREADED_APPLY, BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB, bprintf, calloc(), count, done, DYLD_CHAINED_PTR_ARM64E, test_evm::end, imm, malloc(), memset(), NULL, opcodes, p, rz_dyld_chained_starts_in_segment::page_count, page_index, rz_dyld_chained_starts_in_segment::page_size, rz_dyld_chained_starts_in_segment::page_start, PFMT64x, rz_dyld_chained_starts_in_segment::pointer_format, rz_buf_read_at(), RZ_FREE, RZ_NEW0, RZ_NEWS0, rz_sleb128(), skip(), and ut64().

Referenced by init_items().

◆ section_flag_to_rzlist()

RzList* MACH0_() section_flag_to_rzlist ( ut64  flag)

Definition at line 2378 of file mach0.c.

2378  {
2379  RzList *flag_list = rz_list_new();
2380  if (flag & S_ATTR_PURE_INSTRUCTIONS) {
2381  rz_list_append(flag_list, "PURE_INSTRUCTIONS");
2382  }
2383  if (flag & S_ATTR_NO_TOC) {
2384  rz_list_append(flag_list, "NO_TOC");
2385  }
2386  if (flag & S_ATTR_SOME_INSTRUCTIONS) {
2387  rz_list_append(flag_list, "SOME_INSTRUCTIONS");
2388  }
2389  if (flag & S_ATTR_EXT_RELOC) {
2390  rz_list_append(flag_list, "EXT_RELOC");
2391  }
2392  if (flag & S_ATTR_SELF_MODIFYING_CODE) {
2393  rz_list_append(flag_list, "SELF_MODIFYING_CODE");
2394  }
2395  if (flag & S_ATTR_DEBUG) {
2396  rz_list_append(flag_list, "DEBUG");
2397  }
2398  if (flag & S_ATTR_LIVE_SUPPORT) {
2399  rz_list_append(flag_list, "LIVE_SUPPORT");
2400  }
2401  if (flag & S_ATTR_STRIP_STATIC_SYMS) {
2402  rz_list_append(flag_list, "STRIP_STATIC_SYMS");
2403  }
2404  if (flag & S_ATTR_NO_DEAD_STRIP) {
2405  rz_list_append(flag_list, "NO_DEAD_STRIP");
2406  }
2407  return flag_list;
2408 }
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
@ S_ATTR_SOME_INSTRUCTIONS
S_ATTR_SOME_INSTRUCTIONS - Section contains some machine instructions.
@ S_ATTR_NO_TOC
@ S_ATTR_STRIP_STATIC_SYMS
@ S_ATTR_EXT_RELOC
S_ATTR_EXT_RELOC - Section has external relocation entries.
@ S_ATTR_DEBUG
S_ATTR_DEBUG - A debug section.
@ S_ATTR_LIVE_SUPPORT
S_ATTR_LIVE_SUPPORT - Blocks are live if they reference live blocks.
@ S_ATTR_NO_DEAD_STRIP
S_ATTR_NO_DEAD_STRIP - No dead stripping.
@ S_ATTR_PURE_INSTRUCTIONS
@ S_ATTR_SELF_MODIFYING_CODE

References rz_list_append(), rz_list_new(), S_ATTR_DEBUG, S_ATTR_EXT_RELOC, S_ATTR_LIVE_SUPPORT, S_ATTR_NO_DEAD_STRIP, S_ATTR_NO_TOC, S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SELF_MODIFYING_CODE, S_ATTR_SOME_INSTRUCTIONS, and S_ATTR_STRIP_STATIC_SYMS.

◆ section_type_to_string()

char* MACH0_() section_type_to_string ( ut64  type)

Definition at line 2347 of file mach0.c.

2347  {
2348  switch (type) {
2349  case S_REGULAR:
2350  return rz_str_new("REGULAR");
2351  case S_ZEROFILL:
2352  return rz_str_new("ZEROFILL");
2353  case S_CSTRING_LITERALS:
2354  return rz_str_new("CSTRING_LITERALS");
2355  case S_4BYTE_LITERALS:
2356  return rz_str_new("4BYTE_LITERALS");
2357  case S_LITERAL_POINTERS:
2358  return rz_str_new("LITERAL_POINTERS");
2360  return rz_str_new("NON_LAZY_SYMBOL_POINTERS");
2362  return rz_str_new("LAZY_SYMBOL_POINTERS");
2363  case S_SYMBOL_STUBS:
2364  return rz_str_new("SYMBOL_STUBS");
2366  return rz_str_new("MOD_INIT_FUNC_POINTERS");
2368  return rz_str_new("MOD_TERM_FUNC_POINTERS");
2369  case S_COALESCED:
2370  return rz_str_new("COALESCED");
2371  case S_GB_ZEROFILL:
2372  return rz_str_new("GB_ZEROFILL");
2373  default:
2374  return rz_str_newf("0x%" PFMT64x, type);
2375  }
2376 }
@ S_LITERAL_POINTERS
S_LITERAL_POINTERS - Section with pointers to literals.
@ S_MOD_INIT_FUNC_POINTERS
@ S_CSTRING_LITERALS
S_CSTRING_LITERALS - Section with literal C strings.
@ S_4BYTE_LITERALS
S_4BYTE_LITERALS - Section with 4 byte literals.
@ S_NON_LAZY_SYMBOL_POINTERS
S_NON_LAZY_SYMBOL_POINTERS - Section with non-lazy symbol pointers.
@ S_COALESCED
S_COALESCED - Section contains symbols that are to be coalesced.
@ S_MOD_TERM_FUNC_POINTERS
@ S_GB_ZEROFILL
@ S_LAZY_SYMBOL_POINTERS
S_LAZY_SYMBOL_POINTERS - Section with lazy symbol pointers.
@ S_REGULAR
S_REGULAR - Regular section.
int type
Definition: mipsasm.c:17

References PFMT64x, rz_str_new(), rz_str_newf(), S_4BYTE_LITERALS, S_COALESCED, S_CSTRING_LITERALS, S_GB_ZEROFILL, S_LAZY_SYMBOL_POINTERS, S_LITERAL_POINTERS, S_MOD_INIT_FUNC_POINTERS, S_MOD_TERM_FUNC_POINTERS, S_NON_LAZY_SYMBOL_POINTERS, S_REGULAR, S_SYMBOL_STUBS, S_ZEROFILL, and type.

◆ vaddr_to_paddr()

RZ_API ut64 MACH0_() vaddr_to_paddr ( struct MACH0_(obj_t) *  bin,
ut64  addr 
)

Definition at line 53 of file mach0.c.

53  {
54  if (bin->segs) {
55  size_t i;
56  for (i = 0; i < bin->nsegs; i++) {
57  const ut64 segment_base = (ut64)bin->segs[i].vmaddr;
58  const ut64 segment_size = (ut64)bin->segs[i].vmsize;
59  if (addr >= segment_base && addr < segment_base + segment_size) {
60  return bin->segs[i].fileoff + (addr - segment_base);
61  }
62  }
63  }
64  return 0;
65 }

References addr, i, and ut64().

Referenced by get_entrypoint(), get_main(), get_symbols(), and get_symbols_list().

◆ walk_exports()

static int walk_exports ( struct MACH0_(obj_t) *  bin,
RExportsIterator  iterator,
void *  ctx 
)
static

Definition at line 2586 of file mach0.c.

2586  {
2588  if (!bin->dyld_info) {
2589  return 0;
2590  }
2591 
2592  size_t count = 0;
2593  ut8 *p = NULL;
2594  ut8 *trie = NULL;
2595  RzList *states = NULL;
2596  ut64 size = bin->dyld_info->export_size;
2597  if (!size || size >= SIZE_MAX) {
2598  return count;
2599  }
2600  trie = calloc(size + 1, 1);
2601  if (!trie) {
2602  return count;
2603  }
2604  ut8 *end = trie + size;
2605 
2606  if (rz_buf_read_at(bin->b, bin->dyld_info->export_off, trie, bin->dyld_info->export_size) != size) {
2607  goto beach;
2608  }
2609 
2611  if (!states) {
2612  goto beach;
2613  }
2614 
2616  if (!root) {
2617  goto beach;
2618  }
2619  root->node = trie;
2620  root->i = 0;
2621  root->label = NULL;
2623 
2624  do {
2626  p = state->node;
2627  ut64 len = read_uleb128(&p, end);
2628  if (len == UT64_MAX) {
2629  break;
2630  }
2631  if (len) {
2632  ut64 flags = read_uleb128(&p, end);
2633  if (flags == UT64_MAX) {
2634  break;
2635  }
2636  ut64 offset = read_uleb128(&p, end);
2637  if (offset == UT64_MAX) {
2638  break;
2639  }
2640  ut64 resolver = 0;
2641  bool isReexport = flags & EXPORT_SYMBOL_FLAGS_REEXPORT;
2642  bool hasResolver = flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER;
2643  if (hasResolver) {
2644  ut64 res = read_uleb128(&p, end);
2645  if (res == UT64_MAX) {
2646  break;
2647  }
2648  resolver = res + bin->options.header_at;
2649  } else if (isReexport) {
2650  p += strlen((char *)p) + 1;
2651  // TODO: handle this
2652  }
2653  if (!isReexport) {
2654  offset += bin->options.header_at;
2655  }
2656  if (iterator && !isReexport) {
2657  char *name = NULL;
2658  RzListIter *iter;
2659  RTrieState *s;
2660  rz_list_foreach (states, iter, s) {
2661  if (!s->label) {
2662  continue;
2663  }
2664  name = rz_str_append(name, s->label);
2665  }
2666  if (!name) {
2667  RZ_LOG_ERROR("malformed export trie\n");
2668  goto beach;
2669  }
2670  if (hasResolver) {
2671  char *stub_name = rz_str_newf("stub.%s", name);
2672  iterator(bin, stub_name, flags, offset, ctx);
2673  iterator(bin, name, flags, resolver, ctx);
2674  RZ_FREE(stub_name);
2675  } else {
2677  }
2678  RZ_FREE(name);
2679  }
2680  if (!isReexport) {
2681  if (hasResolver) {
2682  count++;
2683  }
2684  count++;
2685  }
2686  }
2687  ut64 child_count = read_uleb128(&p, end);
2688  if (child_count == UT64_MAX) {
2689  goto beach;
2690  }
2691  if (state->i == child_count) {
2693  continue;
2694  }
2695  if (!state->next_child) {
2696  state->next_child = p;
2697  } else {
2698  p = state->next_child;
2699  }
2700  RTrieState *next = RZ_NEW0(RTrieState);
2701  if (!next) {
2702  goto beach;
2703  }
2704  next->label = (char *)p;
2705  p += strlen(next->label) + 1;
2706  if (p >= end) {
2707  RZ_LOG_ERROR("malformed export trie\n");
2708  RZ_FREE(next);
2709  goto beach;
2710  }
2711  ut64 tr = read_uleb128(&p, end);
2712  if (tr == UT64_MAX) {
2713  RZ_FREE(next);
2714  goto beach;
2715  }
2716  if (tr >= size) {
2717  RZ_LOG_ERROR("malformed export trie\n");
2718  RZ_FREE(next);
2719  goto beach;
2720  }
2721  next->node = trie + (size_t)tr;
2722  {
2723  // avoid loops
2724  RzListIter *it;
2725  RTrieState *s;
2726  rz_list_foreach (states, it, s) {
2727  if (s->node == next->node) {
2728  RZ_LOG_ERROR("malformed export trie\n");
2729  RZ_FREE(next);
2730  goto beach;
2731  }
2732  }
2733  }
2734  next->i = 0;
2735  state->i++;
2736  state->next_child = p;
2737  rz_list_push(states, next);
2738  } while (rz_list_length(states));
2739 
2740 beach:
2742  RZ_FREE(trie);
2743  return count;
2744 }
const MCPhysReg * iterator
int root
Definition: enough.c:226
RZ_API RZ_BORROW void * rz_list_get_top(RZ_NONNULL const RzList *list)
Returns the last element of the list.
Definition: list.c:457
RZ_API RZ_OWN void * rz_list_pop(RZ_NONNULL RzList *list)
Removes and returns the last element of the list.
Definition: list.c:376
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
@ EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
@ EXPORT_SYMBOL_FLAGS_REEXPORT
#define states
Definition: regexec.c:104
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API char * rz_str_append(char *ptr, const char *string)
Definition: str.c:1063
int size_t
Definition: sftypes.h:40
#define tr(opcode, mask, lose, flags)
#define SIZE_MAX
char * label
Definition: mach0.c:32
ut8 * node
Definition: mach0.c:31
int i
Definition: mach0.c:33
Definition: dis.h:43

References calloc(), count, test_evm::end, EXPORT_SYMBOL_FLAGS_REEXPORT, EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, flags, free(), RTrieState::i, RTrieState::label, len, RTrieState::node, NULL, p, root, rz_buf_read_at(), RZ_FREE, rz_list_free(), rz_list_get_top(), rz_list_length(), rz_list_newf(), rz_list_pop(), rz_list_push(), RZ_LOG_ERROR, RZ_NEW0, rz_return_val_if_fail, rz_str_append(), rz_str_newf(), s, SIZE_MAX, states, tr, ut64(), and UT64_MAX.

Referenced by get_symbols(), and get_symbols_list().