Rizin
unix-like reverse engineering framework and cli tools
mach0.h File Reference
#include <rz_bin.h>
#include <rz_types.h>
#include "mach0_specs.h"

Go to the source code of this file.

Classes

struct  section_t
 
struct  symbol_t
 
struct  import_t
 
struct  reloc_t
 
struct  addr_t
 
struct  lib_t
 
struct  blob_index_t
 
struct  blob_t
 
struct  super_blob_t
 

Macros

#define FEATURE_SYMLIST   0
 
#define RZ_BIN_MACH0_STRING_LENGTH   256
 
#define CSMAGIC_CODEDIRECTORY   0xfade0c02
 
#define CSMAGIC_EMBEDDED_SIGNATURE   0xfade0cc0
 
#define CSMAGIC_DETACHED_SIGNATURE   0xfade0cc1 /* multi-arch collection of embedded signatures */
 
#define CSMAGIC_ENTITLEMENTS   0xfade7171
 
#define CSMAGIC_REQUIREMENT   0xfade0c00 /* single Requirement blob */
 
#define CSMAGIC_REQUIREMENTS   0xfade0c01 /* Requirements vector (internal requirements) */
 
#define CS_PAGE_SIZE   4096
 
#define CS_HASHTYPE_SHA1   1
 
#define CS_HASHTYPE_SHA256   2
 
#define CS_HASHTYPE_SHA256_TRUNCATED   3
 
#define CS_HASH_SIZE_SHA1   20
 
#define CS_HASH_SIZE_SHA256   32
 
#define CS_HASH_SIZE_SHA256_TRUNCATED   20
 
#define CSSLOT_CODEDIRECTORY   0
 
#define CSSLOT_INFOSLOT   1
 
#define CSSLOT_REQUIREMENTS   2
 
#define CSSLOT_RESOURCEDIR   3
 
#define CSSLOT_APPLICATION   4
 
#define CSSLOT_ENTITLEMENTS   5
 
#define CSSLOT_CMS_SIGNATURE   0x10000
 
#define MACH0_VFILE_NAME_REBASED_STRIPPED   "rebased_stripped"
 
#define MACH0_VFILE_NAME_RELOC_TARGETS   "reloc-targets"
 
#define MACH0_VFILE_NAME_PATCHED   "patched"
 

Functions

struct MACH0_ (opts_t)
 
struct MACH0_ (obj_t)
 
void MACH0_() opts_set_default (struct MACH0_(opts_t) *options, RzBinFile *bf)
 
void *MACH0_() mach0_free (struct MACH0_(obj_t) *bin)
 
struct section_t *MACH0_() get_sections (struct MACH0_(obj_t) *bin)
 
char *MACH0_() section_type_to_string (ut64 type)
 
RzList *MACH0_() section_flag_to_rzlist (ut64 flag)
 
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)
 
const struct symbol_t *MACH0_() get_symbols (struct MACH0_(obj_t) *bin)
 
const RzList *MACH0_() get_symbols_list (struct MACH0_(obj_t) *bin)
 
void MACH0_() pull_symbols (struct MACH0_(obj_t) *mo, RzBinSymbolCallback cb, void *user)
 
struct import_t *MACH0_() get_imports (struct MACH0_(obj_t) *bin)
 
RZ_BORROW RzSkipList *MACH0_() get_relocs (struct MACH0_(obj_t) *bin)
 
struct addr_t *MACH0_() get_entrypoint (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)
 
bool MACH0_() is_big_endian (struct MACH0_(obj_t) *bin)
 
bool MACH0_() is_pie (struct MACH0_(obj_t) *bin)
 
bool MACH0_() has_nx (struct MACH0_(obj_t) *bin)
 
const char *MACH0_() get_intrp (struct MACH0_(obj_t) *bin)
 
const char *MACH0_() get_os (struct MACH0_(obj_t) *bin)
 
const char *MACH0_() get_cputype (struct MACH0_(obj_t) *bin)
 
char *MACH0_() get_cpusubtype (struct MACH0_(obj_t) *bin)
 
char *MACH0_() get_cpusubtype_from_hdr (struct MACH0_(mach_header) *hdr)
 
char *MACH0_() get_filetype (struct MACH0_(obj_t) *bin)
 
char *MACH0_() get_filetype_from_hdr (struct MACH0_(mach_header) *hdr)
 
ut64 MACH0_() get_main (struct MACH0_(obj_t) *bin)
 
const char *MACH0_() get_cputype_from_hdr (struct MACH0_(mach_header) *hdr)
 
int MACH0_() get_bits_from_hdr (struct MACH0_(mach_header) *hdr)
 
struct MACH0_ (mach_header) *MACH0_(get_hdr)(RzBuffer *buf)
 
void MACH0_() mach_headerfields (RzBinFile *bf)
 
RzList *MACH0_() mach_fields (RzBinFile *bf)
 
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...
 
RZ_API ut64 MACH0_() paddr_to_vaddr (struct MACH0_(obj_t) *bin, ut64 offset)
 
RZ_API ut64 MACH0_() vaddr_to_paddr (struct MACH0_(obj_t) *bin, ut64 addr)
 
RZ_API void MACH0_() rebase_buffer (struct MACH0_(obj_t) *obj, ut64 off, ut8 *buf, ut64 count)
 
RZ_API RzBuffer *MACH0_() new_rebasing_and_stripping_buf (struct MACH0_(obj_t) *obj)
 
RZ_API bool MACH0_() needs_rebasing_and_stripping (struct MACH0_(obj_t) *obj)
 
RZ_API bool MACH0_() segment_needs_rebasing_and_stripping (struct MACH0_(obj_t) *obj, size_t seg_index)
 
RZ_API bool MACH0_() needs_reloc_patching (struct MACH0_(obj_t) *obj)
 
RZ_API ut64 MACH0_() reloc_targets_vfile_size (struct MACH0_(obj_t) *obj)
 size of the artificial reloc target vfile More...
 
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 More...
 
RZ_API void MACH0_() patch_relocs (RzBinFile *bf, struct MACH0_(obj_t) *obj)
 Patching of external relocs in a sparse overlay buffer. More...
 

Macro Definition Documentation

◆ CS_HASH_SIZE_SHA1

#define CS_HASH_SIZE_SHA1   20

Definition at line 30 of file mach0.h.

◆ CS_HASH_SIZE_SHA256

#define CS_HASH_SIZE_SHA256   32

Definition at line 31 of file mach0.h.

◆ CS_HASH_SIZE_SHA256_TRUNCATED

#define CS_HASH_SIZE_SHA256_TRUNCATED   20

Definition at line 32 of file mach0.h.

◆ CS_HASHTYPE_SHA1

#define CS_HASHTYPE_SHA1   1

Definition at line 26 of file mach0.h.

◆ CS_HASHTYPE_SHA256

#define CS_HASHTYPE_SHA256   2

Definition at line 27 of file mach0.h.

◆ CS_HASHTYPE_SHA256_TRUNCATED

#define CS_HASHTYPE_SHA256_TRUNCATED   3

Definition at line 28 of file mach0.h.

◆ CS_PAGE_SIZE

#define CS_PAGE_SIZE   4096

Definition at line 24 of file mach0.h.

◆ CSMAGIC_CODEDIRECTORY

#define CSMAGIC_CODEDIRECTORY   0xfade0c02

Definition at line 17 of file mach0.h.

◆ CSMAGIC_DETACHED_SIGNATURE

#define CSMAGIC_DETACHED_SIGNATURE   0xfade0cc1 /* multi-arch collection of embedded signatures */

Definition at line 19 of file mach0.h.

◆ CSMAGIC_EMBEDDED_SIGNATURE

#define CSMAGIC_EMBEDDED_SIGNATURE   0xfade0cc0

Definition at line 18 of file mach0.h.

◆ CSMAGIC_ENTITLEMENTS

#define CSMAGIC_ENTITLEMENTS   0xfade7171

Definition at line 20 of file mach0.h.

◆ CSMAGIC_REQUIREMENT

#define CSMAGIC_REQUIREMENT   0xfade0c00 /* single Requirement blob */

Definition at line 21 of file mach0.h.

◆ CSMAGIC_REQUIREMENTS

#define CSMAGIC_REQUIREMENTS   0xfade0c01 /* Requirements vector (internal requirements) */

Definition at line 22 of file mach0.h.

◆ CSSLOT_APPLICATION

#define CSSLOT_APPLICATION   4

Definition at line 38 of file mach0.h.

◆ CSSLOT_CMS_SIGNATURE

#define CSSLOT_CMS_SIGNATURE   0x10000

Definition at line 40 of file mach0.h.

◆ CSSLOT_CODEDIRECTORY

#define CSSLOT_CODEDIRECTORY   0

Definition at line 34 of file mach0.h.

◆ CSSLOT_ENTITLEMENTS

#define CSSLOT_ENTITLEMENTS   5

Definition at line 39 of file mach0.h.

◆ CSSLOT_INFOSLOT

#define CSSLOT_INFOSLOT   1

Definition at line 35 of file mach0.h.

◆ CSSLOT_REQUIREMENTS

#define CSSLOT_REQUIREMENTS   2

Definition at line 36 of file mach0.h.

◆ CSSLOT_RESOURCEDIR

#define CSSLOT_RESOURCEDIR   3

Definition at line 37 of file mach0.h.

◆ FEATURE_SYMLIST

#define FEATURE_SYMLIST   0

Definition at line 13 of file mach0.h.

◆ MACH0_VFILE_NAME_PATCHED

#define MACH0_VFILE_NAME_PATCHED   "patched"

Definition at line 197 of file mach0.h.

◆ MACH0_VFILE_NAME_REBASED_STRIPPED

#define MACH0_VFILE_NAME_REBASED_STRIPPED   "rebased_stripped"

Definition at line 195 of file mach0.h.

◆ MACH0_VFILE_NAME_RELOC_TARGETS

#define MACH0_VFILE_NAME_RELOC_TARGETS   "reloc-targets"

Definition at line 196 of file mach0.h.

◆ RZ_BIN_MACH0_STRING_LENGTH

#define RZ_BIN_MACH0_STRING_LENGTH   256

Definition at line 15 of file mach0.h.

Function Documentation

◆ 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
Definition: malloc.c:26

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
struct MACH0_(obj_t)
Definition: mach0.c:2111
@ CPU_TYPE_ARM

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_ARM_V7K
@ 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 }
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")
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 }
#define NULL
Definition: cris-opc.c:27
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 }
@ CPU_TYPE_POWERPC
@ CPU_TYPE_VAX
@ CPU_TYPE_POWERPC64
@ CPU_TYPE_I386
@ CPU_TYPE_MC680x0
@ CPU_TYPE_MC98000
@ CPU_TYPE_X86_64
@ CPU_TYPE_SPARC
@ CPU_TYPE_MIPS
@ CPU_TYPE_ARM64
@ CPU_TYPE_I860
@ CPU_TYPE_HPPA
@ CPU_TYPE_MC88000
#define eprintf(x, y...)
Definition: rlcc.c:7

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 RZ_NEW0(x)
Definition: rz_types.h:284
#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
Definition: z80asm.h:102

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 }
uint8_t ut8
Definition: lh5801.h:11
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
@ LC_MAIN
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
#define b(i)
Definition: sha256.c:42
static st64 delta
Definition: vmenus.c:2425
static int addr
Definition: z80asm.c:58

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
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
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_relocs()

RZ_BORROW RzSkipList* MACH0_() get_relocs ( struct MACH0_(obj_t) *  bin)

Definition at line 120 of file mach0_relocs.c.

120  {
122  if (bin->relocs_parsed) {
123  return bin->relocs;
124  }
125  bin->relocs_parsed = true;
127  RzPVector *threaded_binds = NULL;
128  size_t wordsize = get_word_size(bin);
129  if (bin->dyld_info) {
130  ut8 *opcodes, rel_type = 0;
131  size_t bind_size, lazy_size, weak_size;
132 
133 #define CASE(T) \
134  case ((T) / 8): rel_type = RZ_BIN_RELOC_##T; break
135  switch (wordsize) {
136  CASE(8);
137  CASE(16);
138  CASE(32);
139  CASE(64);
140  default: return NULL;
141  }
142 #undef CASE
143  bind_size = bin->dyld_info->bind_size;
144  lazy_size = bin->dyld_info->lazy_bind_size;
145  weak_size = bin->dyld_info->weak_bind_size;
146 
147  if (!bind_size && !lazy_size) {
148  return NULL;
149  }
150 
151  if ((bind_size + lazy_size) < 1) {
152  return NULL;
153  }
154  if (bin->dyld_info->bind_off > bin->size || bin->dyld_info->bind_off + bind_size > bin->size) {
155  return NULL;
156  }
157  if (bin->dyld_info->lazy_bind_off > bin->size ||
158  bin->dyld_info->lazy_bind_off + lazy_size > bin->size) {
159  return NULL;
160  }
161  if (bin->dyld_info->bind_off + bind_size + lazy_size > bin->size) {
162  return NULL;
163  }
164  if (bin->dyld_info->weak_bind_off + weak_size > bin->size) {
165  return NULL;
166  }
167  ut64 amount = bind_size + lazy_size + weak_size;
168  if (amount == 0 || amount > UT32_MAX) {
169  return NULL;
170  }
171  if (!bin->segs) {
172  return NULL;
173  }
175  if (!relocs) {
176  return NULL;
177  }
178  opcodes = calloc(1, amount + 1);
179  if (!opcodes) {
181  return NULL;
182  }
183 
184  int len = rz_buf_read_at(bin->b, bin->dyld_info->bind_off, opcodes, bind_size);
185  len += rz_buf_read_at(bin->b, bin->dyld_info->lazy_bind_off, opcodes + bind_size, lazy_size);
186  len += rz_buf_read_at(bin->b, bin->dyld_info->weak_bind_off, opcodes + bind_size + lazy_size, weak_size);
187  if (len < amount) {
188  RZ_LOG_ERROR("Error: read (dyld_info bind) at 0x%08" PFMT64x "\n", (ut64)(size_t)bin->dyld_info->bind_off);
189  RZ_FREE(opcodes);
191  return NULL;
192  }
193 
194  size_t partition_sizes[] = { bind_size, lazy_size, weak_size };
195  size_t pidx;
196  int opcodes_offset = 0;
197  for (pidx = 0; pidx < RZ_ARRAY_SIZE(partition_sizes); pidx++) {
198  size_t partition_size = partition_sizes[pidx];
199 
200  ut8 type = 0;
201  int lib_ord = 0, seg_idx = -1, sym_ord = -1;
202  char *sym_name = NULL;
203  size_t j, count, skip;
204  st64 addend = 0;
205  ut64 addr = bin->segs[0].vmaddr;
206  ut64 segment_end_addr = addr + bin->segs[0].vmsize;
207 
208  ut8 *p = opcodes + opcodes_offset;
209  ut8 *end = p + partition_size;
210  bool done = false;
211  while (!done && p < end) {
213  ut8 op = *p & BIND_OPCODE_MASK;
214  p++;
215  switch (op) {
216  case BIND_OPCODE_DONE: {
217  bool in_lazy_binds = pidx == 1;
218  if (!in_lazy_binds) {
219  done = true;
220  }
221  break;
222  }
223  case BIND_OPCODE_THREADED: {
224  switch (imm) {
226  ut64 table_size = read_uleb128(&p, end);
227  if (!is_valid_ordinal_table_size(table_size)) {
228  RZ_LOG_ERROR("Error: BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB size is wrong\n");
229  break;
230  }
231  if (threaded_binds) {
232  rz_pvector_free(threaded_binds);
233  }
234  threaded_binds = rz_pvector_new_with_len((RzPVectorFree)&free, table_size);
235  if (threaded_binds) {
236  sym_ord = 0;
237  }
238  break;
239  }
241  if (threaded_binds) {
242  int cur_seg_idx = (seg_idx != -1) ? seg_idx : 0;
243  size_t n_threaded_binds = rz_pvector_len(threaded_binds);
244  while (addr < segment_end_addr) {
245  ut8 tmp[8];
246  ut64 paddr = addr - bin->segs[cur_seg_idx].vmaddr + bin->segs[cur_seg_idx].fileoff;
247  if (rz_buf_read_at(bin->b, paddr, tmp, 8) != 8) {
248  break;
249  }
250  ut64 raw_ptr = rz_read_le64(tmp);
251  bool is_auth = (raw_ptr & (1ULL << 63)) != 0;
252  bool is_bind = (raw_ptr & (1ULL << 62)) != 0;
253  int ordinal = -1;
254  int addend = -1;
255  ut64 delta;
256  if (is_auth && is_bind) {
258  (struct dyld_chained_ptr_arm64e_auth_bind *)&raw_ptr;
259  delta = p->next;
260  ordinal = p->ordinal;
261  } else if (!is_auth && is_bind) {
263  (struct dyld_chained_ptr_arm64e_bind *)&raw_ptr;
264  delta = p->next;
265  ordinal = p->ordinal;
266  addend = p->addend;
267  } else if (is_auth && !is_bind) {
269  (struct dyld_chained_ptr_arm64e_auth_rebase *)&raw_ptr;
270  delta = p->next;
271  } else {
273  (struct dyld_chained_ptr_arm64e_rebase *)&raw_ptr;
274  delta = p->next;
275  }
276  if (ordinal != -1) {
277  if (ordinal >= n_threaded_binds) {
278  RZ_LOG_ERROR("Error: Malformed bind chain\n");
279  break;
280  }
281  struct reloc_t *ref = rz_pvector_at(threaded_binds, ordinal);
282  if (!ref) {
283  RZ_LOG_ERROR("Error: Inconsistent bind opcodes\n");
284  break;
285  }
286  struct reloc_t *reloc = RZ_NEW0(struct reloc_t);
287  if (!reloc) {
288  break;
289  }
290  *reloc = *ref;
291  reloc->addr = addr;
292  reloc->offset = paddr;
293  if (addend != -1) {
294  reloc->addend = addend;
295  }
296  rz_skiplist_insert(relocs, reloc);
297  }
298  addr += delta * wordsize;
299  if (!delta) {
300  break;
301  }
302  }
303  }
304  break;
305  default:
306  RZ_LOG_ERROR("Error: Unexpected BIND_OPCODE_THREADED sub-opcode: 0x%x\n", imm);
307  }
308  break;
309  }
311  lib_ord = imm;
312  break;
314  lib_ord = read_uleb128(&p, end);
315  break;
317  lib_ord = imm ? (st8)(BIND_OPCODE_MASK | imm) : 0;
318  break;
320  sym_name = (char *)p;
321  while (*p++ && p < end) {
322  /* empty loop */
323  }
324  if (threaded_binds) {
325  break;
326  }
327  sym_ord = -1;
328  if (bin->symtab && bin->dysymtab.nundefsym < UT16_MAX) {
329  for (j = 0; j < bin->dysymtab.nundefsym; j++) {
330  size_t stridx = 0;
331  bool found = false;
332  int iundefsym = bin->dysymtab.iundefsym;
333  if (iundefsym >= 0 && iundefsym < bin->nsymtab) {
334  int sidx = iundefsym + j;
335  if (sidx < 0 || sidx >= bin->nsymtab) {
336  continue;
337  }
338  stridx = bin->symtab[sidx].n_strx;
339  if (stridx >= bin->symstrlen) {
340  continue;
341  }
342  found = true;
343  }
344  if (found && !strcmp((const char *)bin->symstr + stridx, sym_name)) {
345  sym_ord = j;
346  break;
347  }
348  }
349  }
350  break;
351  }
353  type = imm;
354  break;
356  addend = rz_sleb128((const ut8 **)&p, end);
357  break;
359  seg_idx = imm;
360  if (seg_idx >= bin->nsegs) {
361  RZ_LOG_ERROR("Error: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB"
362  " has unexistent segment %d\n",
363  seg_idx);
364  free(opcodes);
366  rz_pvector_free(threaded_binds);
367  return NULL; // early exit to avoid future mayhem
368  }
369  addr = bin->segs[seg_idx].vmaddr + read_uleb128(&p, end);
370  segment_end_addr = bin->segs[seg_idx].vmaddr + bin->segs[seg_idx].vmsize;
371  break;
373  addr += read_uleb128(&p, end);
374  break;
375 #define DO_BIND() \
376  do { \
377  if (sym_ord < 0 && !sym_name) \
378  break; \
379  if (!threaded_binds) { \
380  if (seg_idx < 0) \
381  break; \
382  if (!addr) \
383  break; \
384  } \
385  struct reloc_t *reloc = RZ_NEW0(struct reloc_t); \
386  reloc->addr = addr; \
387  if (seg_idx >= 0) { \
388  reloc->offset = addr - bin->segs[seg_idx].vmaddr + bin->segs[seg_idx].fileoff; \
389  if (type == BIND_TYPE_TEXT_PCREL32) \
390  reloc->addend = addend - (bin->baddr + addr); \
391  else \
392  reloc->addend = addend; \
393  } else { \
394  reloc->addend = addend; \
395  } \
396  /* library ordinal ??? */ \
397  reloc->ord = lib_ord; \
398  reloc->ord = sym_ord; \
399  reloc->type = rel_type; \
400  if (sym_name) \
401  rz_str_ncpy(reloc->name, sym_name, 256); \
402  if (threaded_binds) \
403  rz_pvector_set(threaded_binds, sym_ord, reloc); \
404  else \
405  rz_skiplist_insert(relocs, reloc); \
406  } while (0)
407  case BIND_OPCODE_DO_BIND:
408  if (!threaded_binds && addr >= segment_end_addr) {
409  RZ_LOG_ERROR("Error: Malformed DO bind opcode 0x%" PFMT64x "\n", addr);
410  goto beach;
411  }
412  DO_BIND();
413  if (!threaded_binds) {
414  addr += wordsize;
415  } else {
416  sym_ord++;
417  }
418  break;
420  if (addr >= segment_end_addr) {
421  RZ_LOG_ERROR("Error: Malformed ADDR ULEB bind opcode\n");
422  goto beach;
423  }
424  DO_BIND();
425  addr += read_uleb128(&p, end) + wordsize;
426  break;
428  if (addr >= segment_end_addr) {
429  RZ_LOG_ERROR("Error: Malformed IMM SCALED bind opcode\n");
430  goto beach;
431  }
432  DO_BIND();
433  addr += (ut64)imm * (ut64)wordsize + wordsize;
434  break;
436  count = read_uleb128(&p, end);
437  skip = read_uleb128(&p, end);
438  for (j = 0; j < count; j++) {
439  if (addr >= segment_end_addr) {
440  RZ_LOG_ERROR("Error: Malformed ULEB TIMES bind opcode\n");
441  goto beach;
442  }
443  DO_BIND();
444  addr += skip + wordsize;
445  }
446  break;
447 #undef DO_BIND
448  default:
449  RZ_LOG_ERROR("Error: unknown bind opcode 0x%02x in dyld_info\n", *p);
450  RZ_FREE(opcodes);
451  goto beach;
452  }
453  }
454 
455  opcodes_offset += partition_size;
456  }
457 
458  RZ_FREE(opcodes);
459  rz_pvector_free(threaded_binds);
460  threaded_binds = NULL;
461  }
462 
463  if (bin->symtab && bin->symstr && bin->sects && bin->indirectsyms) {
464  int j;
465  int amount = bin->dysymtab.nundefsym;
466  if (amount < 0) {
467  amount = 0;
468  }
469  if (!relocs) {
471  if (!relocs) {
472  return NULL;
473  }
474  }
475  for (j = 0; j < amount; j++) {
476  struct reloc_t *reloc = RZ_NEW0(struct reloc_t);
477  if (!reloc) {
478  break;
479  }
480  if (parse_import_ptr(bin, reloc, bin->dysymtab.iundefsym + j)) {
481  reloc->ord = j;
482  rz_skiplist_insert(relocs, reloc);
483  } else {
484  RZ_FREE(reloc);
485  }
486  }
487  }
488 
489  if (bin->symtab && bin->dysymtab.extreloff && bin->dysymtab.nextrel) {
490  if (!relocs) {
492  if (!relocs) {
493  return NULL;
494  }
495  }
496  parse_relocation_info(bin, relocs, bin->dysymtab.extreloff, bin->dysymtab.nextrel);
497  }
498 beach:
499  rz_pvector_free(threaded_binds);
500  bin->relocs = relocs;
501  return relocs;
502 }
#define imm
OPCODE_DESC opcodes[]
Definition: avr_esil.c:1270
RzList * relocs(RzBinFile *bf)
Definition: bin_ne.c:114
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
struct tab * done
Definition: enough.c:233
void skip(file *in, unsigned n)
Definition: gzappend.c:202
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
void * p
Definition: libc.cpp:67
@ 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
@ BIND_OPCODE_MASK
@ BIND_IMMEDIATE_MASK
static void parse_relocation_info(struct MACH0_(obj_t) *bin, RzSkipList *relocs, ut32 offset, ut32 num)
Definition: mach0_relocs.c:17
static bool is_valid_ordinal_table_size(ut64 size)
Definition: mach0_relocs.c:68
#define DO_BIND()
#define CASE(T)
static int parse_import_ptr(struct MACH0_(obj_t) *bin, struct reloc_t *reloc, int idx)
Definition: mach0_relocs.c:72
static int reloc_comparator(struct reloc_t *a, struct reloc_t *b)
Definition: mach0_relocs.c:13
int type
Definition: mipsasm.c:17
static ut64 rz_read_le64(const void *src)
Definition: rz_endian.h:266
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API RzSkipList * rz_skiplist_new(RzListFree freefn, RzListComparator comparefn)
Definition: skiplist.c:107
RZ_API void rz_skiplist_free(RzSkipList *list)
Definition: skiplist.c:145
RZ_API RzSkipListNode * rz_skiplist_insert(RzSkipList *list, void *data)
Definition: skiplist.c:156
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define st8
Definition: rz_types_base.h:16
#define st64
Definition: rz_types_base.h:10
#define UT32_MAX
Definition: rz_types_base.h:99
#define UT16_MAX
RZ_API st64 rz_sleb128(const ut8 **data, const ut8 *end)
Definition: uleb128.c:145
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
void(* RzPVectorFree)(void *e)
Definition: rz_vector.h:43
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
RZ_API RzPVector * rz_pvector_new_with_len(RzPVectorFree free, size_t length)
Definition: vector.c:311
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236
Definition: mach0.h:71
ut64 addr
Definition: mach0.h:73
int ord
Definition: mach0.h:76
ut64 offset
Definition: mach0.h:72
st64 addend
Definition: mach0.h:74
Definition: dis.c:32

References reloc_t::addend, dyld_chained_ptr_arm64e_bind::addend, addr, reloc_t::addr, 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, calloc(), CASE, count, delta, DO_BIND, done, test_evm::end, found, free(), imm, is_valid_ordinal_table_size(), len, NULL, reloc_t::offset, opcodes, reloc_t::ord, dyld_chained_ptr_arm64e_bind::ordinal, dyld_chained_ptr_arm64e_auth_bind::ordinal, p, parse_import_ptr(), parse_relocation_info(), PFMT64x, reloc_comparator(), relocs(), RZ_ARRAY_SIZE, rz_buf_read_at(), RZ_FREE, RZ_LOG_ERROR, RZ_NEW0, rz_pvector_at(), rz_pvector_free(), rz_pvector_len(), rz_pvector_new_with_len(), rz_read_le64(), rz_return_val_if_fail, rz_skiplist_free(), rz_skiplist_insert(), rz_skiplist_new(), rz_sleb128(), skip(), st64, st8, autogen_x86imm::tmp, type, UT16_MAX, UT32_MAX, and ut64().

Referenced by get_patchable_relocs(), parse_classes(), and relocs().

◆ 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 void list(RzEgg *egg)
Definition: rz-gg.c:52
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 int inSymtab(HtPP *hash, const char *name, ut64 addr)
Definition: mach0.c:2545
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_EXT
Definition: mach0_specs.h:25
#define RZ_BIN_MACH0_SYMBOL_TYPE_LOCAL
Definition: mach0_specs.h:26
#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
Definition: mach0.c:21
int symbols_count
Definition: mach0.c:24
struct symbol_t * symbols
Definition: mach0.c:22
int j
Definition: mach0.c:23
HtPP * hash
Definition: mach0.c:25
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
const char * type
Definition: rz_bin.h:682
char * name
Definition: rz_bin.h:675

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
voidpf void * buf
Definition: ioapi.h:138
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().

◆ 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().

◆ MACH0_() [1/3]

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 }
@ FAT_MAGIC
Definition: mach0_defines.h:65
static ut32 rz_read_le32(const void *src)
Definition: rz_endian.h:239
static ut64 rz_read_ble(const void *src, bool big_endian, int size)
Definition: rz_endian.h:517
static ut32 rz_read_be32(const void *src)
Definition: rz_endian.h:87

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/3]

struct MACH0_ ( obj_t  )

< lazily loaded, use only MACH0_(get_relocs)() to access this

< whether relocs have already been parsed and relocs is filled (or NULL on error)

< weak pointers to relocs in relocs which should be patched

Definition at line 1 of file mach0.h.

120  {
121  struct MACH0_(opts_t) options;
122  struct MACH0_(mach_header) hdr;
123  struct MACH0_(segment_command) * segs;
124  char *intrp;
125  char *compiler;
126  int nsegs;
127  struct rz_dyld_chained_starts_in_segment **chained_starts;
128  ut32 nchained_starts;
129  struct MACH0_(section) * sects;
130  int nsects;
131  struct MACH0_(nlist) * symtab;
132  ut8 *symstr;
133  ut8 *func_start; // buffer that hold the data from LC_FUNCTION_STARTS
134  int symstrlen;
135  int nsymtab;
136  ut32 *indirectsyms;
137  int nindirectsyms;
138 
139  RzBinImport **imports_by_ord;
140  size_t imports_by_ord_size;
141  HtPP *imports_by_name;
142 
143  struct dysymtab_command dysymtab;
144  struct load_command main_cmd;
145  struct dyld_info_command *dyld_info;
146  struct dylib_table_of_contents *toc;
147  int ntoc;
148  struct MACH0_(dylib_module) * modtab;
149  int nmodtab;
150  struct thread_command thread;
151  ut8 *signature;
152  union {
153  struct x86_thread_state32 x86_32;
154  struct x86_thread_state64 x86_64;
155  struct ppc_thread_state32 ppc_32;
156  struct ppc_thread_state64 ppc_64;
157  struct arm_thread_state32 arm_32;
158  struct arm_thread_state64 arm_64;
159  } thread_state;
161  int nlibs;
162  int size;
163  ut64 baddr;
164  ut64 entry;
165  bool big_endian;
166  const char *file;
167  RzBuffer *b;
168  int os;
169  Sdb *kv;
170  int has_crypto;
171  int has_canary;
172  int has_retguard;
173  int has_sanitizers;
174  int has_blocks_ext;
175  int dbg_info;
176  const char *lang;
177  int uuidn;
178  int func_size;
179  void *user;
180  ut64 (*va2pa)(ut64 p, ut32 *offset, ut32 *left, RzBinFile *bf);
181  struct symbol_t *symbols;
182  ut64 main_addr;
183 
184  RzList *sections_cache;
185  RzSkipList *relocs;
186  bool relocs_parsed;
187  bool reloc_targets_map_base_calculated;
188  bool relocs_patched;
189  RzBuffer *buf_patched;
191  RzPVector /* <struct reloc_t> */ *patchable_relocs;
192  RzHash *hash;
193 };
static ut64 baddr(RzBinFile *bf)
Definition: bin_any.c:58
static char * signature(RzBinFile *bf, bool json)
Definition: bin_pe.c:117
static ut64 va2pa(uint64_t addr, ut32 n_maps, cache_map_t *maps, RzBuffer *cache_buf, ut64 slide, ut32 *offset, ut32 *left)
Definition: dyldcache.c:22
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
XX curplugin == o->plugin.
Definition: rz_bin.h:298
Definition: sdb.h:63
static registers_t x86_32[]
Definition: core.c:27
static int file
Definition: z80asm.c:58

◆ MACH0_() [3/3]

struct struct MACH0_ ( opts_t  )

Definition at line 1 of file mach0.h.

113  {
114  bool verbose;
115  ut64 header_at;
116  ut64 symbols_off;
117  bool patch_relocs;
118 };
static int verbose
Definition: z80asm.c:73

◆ mach0_free()

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

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

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_pf_definition(ut32 cmd)
Definition: mach0.c:1336
static const char * cmd_to_string(ut32 cmd)
Definition: mach0.c:1230
@ LC_SEGMENT
@ LC_BUILD_VERSION
@ LC_SEGMENT_64
int n
Definition: mipsasm.c:19
int off
Definition: pal.c:13
#define rz_buf_read_le32_at(b, addr, result)
Definition: rz_buf.h:271
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
#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
@ LC_LOAD_WEAK_DYLIB
@ LC_ENCRYPTION_INFO_64
@ LC_RPATH
@ LC_LOAD_DYLIB
@ LC_SYMTAB
@ LC_ENCRYPTION_INFO
@ LC_ID_DYLIB
@ LC_UUID
@ LC_CODE_SIGNATURE
#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
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
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().

◆ needs_rebasing_and_stripping()

RZ_API bool MACH0_() needs_rebasing_and_stripping ( struct MACH0_(obj_t) *  obj)

Definition at line 228 of file mach0_rebase.c.

228  {
229  return !!obj->chained_starts;
230 }

Referenced by get_virtual_files(), and parse_classes().

◆ needs_reloc_patching()

RZ_API bool MACH0_() needs_reloc_patching ( struct MACH0_(obj_t) *  obj)

Definition at line 532 of file mach0_relocs.c.

532  {
533  rz_return_val_if_fail(obj, false);
534  RzPVector *patchable_relocs = get_patchable_relocs(obj);
535  return patchable_relocs && rz_pvector_len(patchable_relocs);
536 }
static RzPVector * get_patchable_relocs(struct MACH0_(obj_t) *obj)
Definition: mach0_relocs.c:504

References get_patchable_relocs(), rz_pvector_len(), and rz_return_val_if_fail.

Referenced by patch_relocs().

◆ new_rebasing_and_stripping_buf()

RZ_API RzBuffer* MACH0_() new_rebasing_and_stripping_buf ( struct MACH0_(obj_t) *  obj)

Definition at line 224 of file mach0_rebase.c.

224  {
225  return rz_buf_new_with_methods(&buf_methods, obj);
226 }
static const RzBufferMethods buf_methods
Definition: mach0_rebase.c:213
RZ_API RZ_OWN RzBuffer * rz_buf_new_with_methods(RZ_NONNULL const RzBufferMethods *methods, void *init_user)
Creates a new buffer with a specific back end.
Definition: buf.c:525

References buf_methods, and rz_buf_new_with_methods().

Referenced by get_virtual_files(), and parse_classes().

◆ 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().

◆ 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().

◆ patch_relocs()

RZ_API void MACH0_() patch_relocs ( RzBinFile bf,
struct MACH0_(obj_t) *  obj 
)

Patching of external relocs in a sparse overlay buffer.

see also mach0_rebase.c for additional modification of the data that might happen.

Definition at line 614 of file mach0_relocs.c.

614  {
615  rz_return_if_fail(obj);
616  if (obj->relocs_patched || !MACH0_(needs_reloc_patching)(obj)) {
617  return;
618  }
619  obj->relocs_patched = true; // run this function just once (lazy relocs patching)
620  ut64 cdsz = reloc_target_size(obj);
622  if (!size) {
623  return;
624  }
625  RzBinRelocTargetBuilder *targets = rz_bin_reloc_target_builder_new(cdsz, MACH0_(reloc_targets_map_base)(bf, obj));
626  if (!targets) {
627  return;
628  }
630  if (!obj->buf_patched) {
632  return;
633  }
634  RzPVector *patchable_relocs = get_patchable_relocs(obj);
635  void **it;
636  rz_pvector_foreach (patchable_relocs, it) {
637  struct reloc_t *reloc = *it;
638  ut64 sym_addr = rz_bin_reloc_target_builder_get_target(targets, reloc->ord);
639  reloc->target = sym_addr;
640  _patch_reloc(obj, reloc, sym_addr);
641  }
643  // from now on, all writes should propagate through to the actual file
645 }
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
static ut64 reloc_target_size(struct MACH0_(obj_t) *obj)
Definition: mach0_relocs.c:538
static bool _patch_reloc(struct MACH0_(obj_t) *bin, struct reloc_t *reloc, ut64 symbol_at)
Definition: mach0_relocs.c:567
RZ_API bool MACH0_() needs_reloc_patching(struct MACH0_(obj_t) *obj)
Definition: mach0_relocs.c:532
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_(name)
Definition: mach0_specs.h:20
RZ_API ut64 rz_bin_reloc_target_builder_get_target(RzBinRelocTargetBuilder *builder, ut64 sym)
obtain the address of the target for a given symbol
Definition: relocs_patch.c:69
RZ_API void rz_bin_reloc_target_builder_free(RzBinRelocTargetBuilder *builder)
Definition: relocs_patch.c:51
RZ_API RzBinRelocTargetBuilder * rz_bin_reloc_target_builder_new(ut64 target_size, ut64 target_base)
Definition: relocs_patch.c:35
RZ_API void rz_buf_sparse_set_write_mode(RzBuffer *b, RzBufferSparseWriteMode mode)
Only for sparse RzBuffers.
Definition: buf_sparse.c:325
@ RZ_BUF_SPARSE_WRITE_MODE_SPARSE
all writes are performed in the sparse overlay
Definition: rz_buf.h:60
@ RZ_BUF_SPARSE_WRITE_MODE_THROUGH
all writes are performed in the underlying base buffer
Definition: rz_buf.h:61
RZ_API RZ_OWN RzBuffer * rz_buf_new_sparse_overlay(RzBuffer *b, RzBufferSparseWriteMode write_mode)
Creates a sparse buffer from a already populated buffer.
Definition: buf.c:426
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
ut64 target
Definition: mach0.h:82

References _patch_reloc(), get_patchable_relocs(), MACH0_, needs_reloc_patching(), reloc_t::ord, reloc_target_size(), reloc_targets_map_base(), reloc_targets_vfile_size(), rz_bin_reloc_target_builder_free(), rz_bin_reloc_target_builder_get_target(), rz_bin_reloc_target_builder_new(), rz_buf_new_sparse_overlay(), rz_buf_sparse_set_write_mode(), RZ_BUF_SPARSE_WRITE_MODE_SPARSE, RZ_BUF_SPARSE_WRITE_MODE_THROUGH, rz_pvector_foreach, rz_return_if_fail, reloc_t::target, and ut64().

Referenced by get_maps(), get_virtual_files(), rz_bflt_init(), rz_bflt_new_buf(), rz_bin_options_init(), rz_bin_reload(), and rz_core_bin_options_init().

◆ pull_symbols()

void MACH0_() pull_symbols ( struct MACH0_(obj_t) *  mo,
RzBinSymbolCallback  cb,
void *  user 
)

◆ rebase_buffer()

RZ_API void MACH0_() rebase_buffer ( struct MACH0_(obj_t) *  obj,
ut64  off,
ut8 buf,
ut64  count 
)

Definition at line 24 of file mach0_rebase.c.

24  {
25  rz_return_if_fail(obj && buf);
26  ut64 eob = off + count;
27  int nsegs_to_rebase = RZ_MIN(obj->nchained_starts, obj->nsegs);
28  for (int i = 0; i < nsegs_to_rebase; i++) {
29  if (!obj->chained_starts[i]) {
30  continue;
31  }
32  ut64 page_size = obj->chained_starts[i]->page_size;
33  ut64 start = obj->segs[i].fileoff;
34  ut64 end = start + obj->segs[i].filesize;
35  if (end < off || start > eob) {
36  continue;
37  }
38  ut64 page_idx = (RZ_MAX(start, off) - start) / page_size;
39  ut64 page_end_idx = (RZ_MIN(eob, end) - start) / page_size;
40  for (; page_idx <= page_end_idx; page_idx++) {
41  if (page_idx >= obj->chained_starts[i]->page_count) {
42  break;
43  }
44  ut16 page_start = obj->chained_starts[i]->page_start[page_idx];
45  if (page_start == DYLD_CHAINED_PTR_START_NONE) {
46  continue;
47  }
48  ut64 cursor = start + page_idx * page_size + page_start;
49  while (cursor < eob && cursor < end) {
50  ut8 tmp[8];
51  if (rz_buf_read_at(obj->b, cursor, tmp, 8) != 8) {
52  break;
53  }
54  ut64 raw_ptr = rz_read_le64(tmp);
55  bool is_auth = IS_PTR_AUTH(raw_ptr);
56  ut64 ptr_value = raw_ptr;
57  ut64 delta;
58  ut64 stride = 8;
59  switch (obj->chained_starts[i]->pointer_format) {
61  bool is_bind = IS_PTR_BIND(raw_ptr);
62  if (is_auth && is_bind) {
64  (struct dyld_chained_ptr_arm64e_auth_bind *)&raw_ptr;
65  delta = p->next;
66  } else if (!is_auth && is_bind) {
68  (struct dyld_chained_ptr_arm64e_bind *)&raw_ptr;
69  delta = p->next;
70  } else if (is_auth && !is_bind) {
72  (struct dyld_chained_ptr_arm64e_auth_rebase *)&raw_ptr;
73  delta = p->next;
74  ptr_value = p->target + obj->baddr;
75  } else {
77  (struct dyld_chained_ptr_arm64e_rebase *)&raw_ptr;
78  delta = p->next;
79  ptr_value = ((ut64)p->high8 << 56) | p->target;
80  }
81  break;
82  }
85  stride = 4;
86  if (is_auth) {
89  delta = p->next;
90  ptr_value = p->target + obj->baddr;
91  } else {
93  (struct dyld_chained_ptr_arm64e_cache_rebase *)&raw_ptr;
94  delta = p->next;
95  ptr_value = ((ut64)p->high8 << 56) | p->target;
96  ptr_value += obj->baddr;
97  }
98  break;
99  }
101  stride = 4;
103  (struct dyld_chained_ptr_64_bind *)&raw_ptr;
104  if (bind->bind) {
105  delta = bind->next;
106  } else {
107  struct dyld_chained_ptr_64_rebase *p =
108  (struct dyld_chained_ptr_64_rebase *)&raw_ptr;
109  delta = p->next;
110  ptr_value = obj->baddr + (((ut64)p->high8 << 56) | p->target);
111  }
112  break;
113  }
115  stride = 8;
117  (struct dyld_chained_ptr_arm64e_bind24 *)&raw_ptr;
118  if (bind->bind) {
119  delta = bind->next;
120  } else {
121  if (bind->auth) {
123  (struct dyld_chained_ptr_arm64e_auth_rebase *)&raw_ptr;
124  delta = p->next;
125  ptr_value = p->target + obj->baddr;
126  } else {
128  (struct dyld_chained_ptr_arm64e_rebase *)&raw_ptr;
129  delta = p->next;
130  ptr_value = obj->baddr + (((ut64)p->high8 << 56) | p->target);
131  }
132  }
133  break;
134  }
135  default:
136  RZ_LOG_WARN("Unsupported Mach-O pointer format: %u at paddr 0x%" PFMT64x "\n",
137  obj->chained_starts[i]->pointer_format, cursor);
138  goto break_it_all;
139  }
140  ut64 in_buf = cursor - off;
141  if (cursor >= off && cursor <= eob - 8) {
142  rz_write_le64(&buf[in_buf], ptr_value);
143  }
144  cursor += delta * stride;
145  if (!delta) {
146  break;
147  }
148  continue;
149  break_it_all:
150  break;
151  }
152  }
153  }
154 }
static io_buf in_buf
Input and output buffers.
Definition: coder.c:39
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 start
Definition: sflib.h:133
@ DYLD_CHAINED_PTR_START_NONE
@ DYLD_CHAINED_PTR_64_OFFSET
@ DYLD_CHAINED_PTR_ARM64E_USERLAND24
@ DYLD_CHAINED_PTR_ARM64E
@ DYLD_CHAINED_PTR_64_KERNEL_CACHE
@ DYLD_CHAINED_PTR_ARM64E_KERNEL
#define IS_PTR_BIND(x)
Definition: mach0_rebase.c:22
#define IS_PTR_AUTH(x)
Definition: mach0_rebase.c:21
static void rz_write_le64(void *dest, ut64 val)
Definition: rz_endian.h:277
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
static bind
Definition: sfsocketcall.h:114

References bind, count, delta, DYLD_CHAINED_PTR_64_KERNEL_CACHE, DYLD_CHAINED_PTR_64_OFFSET, DYLD_CHAINED_PTR_ARM64E, DYLD_CHAINED_PTR_ARM64E_KERNEL, DYLD_CHAINED_PTR_ARM64E_USERLAND24, DYLD_CHAINED_PTR_START_NONE, test_evm::end, i, in_buf, IS_PTR_AUTH, IS_PTR_BIND, off, p, PFMT64x, rz_buf_read_at(), RZ_LOG_WARN, RZ_MAX, RZ_MIN, rz_read_le64(), rz_return_if_fail, rz_write_le64(), start, autogen_x86imm::tmp, and ut64().

Referenced by buf_read().

◆ reloc_targets_map_base()

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 at line 556 of file mach0_relocs.c.

556  {
557  if (obj->reloc_targets_map_base_calculated) {
558  return obj->reloc_targets_map_base;
559  }
561  obj->reloc_targets_map_base = rz_bin_relocs_patch_find_targets_map_base(maps, reloc_target_size(obj));
563  obj->reloc_targets_map_base_calculated = true;
564  return obj->reloc_targets_map_base;
565 }
static RzList * maps(RzBinFile *bf)
Definition: bin_bf.c:116
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API ut64 rz_bin_relocs_patch_find_targets_map_base(RzList *maps, ut64 target_sz)
Finm a suitable location for putting the artificial reloc targets map.
Definition: relocs_patch.c:8

References get_maps_unpatched(), MACH0_, maps(), reloc_target_size(), rz_bin_relocs_patch_find_targets_map_base(), and rz_list_free().

Referenced by get_maps(), and patch_relocs().

◆ reloc_targets_vfile_size()

RZ_API ut64 MACH0_() reloc_targets_vfile_size ( struct MACH0_(obj_t) *  obj)

size of the artificial reloc target vfile

Definition at line 547 of file mach0_relocs.c.

547  {
548  RzPVector *patchable_relocs = get_patchable_relocs(obj);
549  if (!patchable_relocs) {
550  return 0;
551  }
552  return rz_pvector_len(patchable_relocs) * reloc_target_size(obj);
553 }

References get_patchable_relocs(), reloc_target_size(), and rz_pvector_len().

Referenced by get_maps(), get_virtual_files(), and patch_relocs().

◆ 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

◆ 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_SYMBOL_STUBS
@ 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.

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.

◆ segment_needs_rebasing_and_stripping()

RZ_API bool MACH0_() segment_needs_rebasing_and_stripping ( struct MACH0_(obj_t) *  obj,
size_t  seg_index 
)

Definition at line 232 of file mach0_rebase.c.

232  {
233  if (seg_index >= obj->nsegs || seg_index >= obj->nchained_starts) {
234  return false;
235  }
236  return obj->chained_starts && obj->chained_starts[seg_index];
237 }

Referenced by get_maps_unpatched().

◆ 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().