Skip to content

Commit 8130a96

Browse files
committed
read/macho: implement dyld slide version 2 and 3
1 parent b82e433 commit 8130a96

File tree

3 files changed

+418
-0
lines changed

3 files changed

+418
-0
lines changed

crates/examples/src/readobj/macho.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,26 @@ pub(super) fn print_dyld_cache_mapping_and_slide_info(
9898

9999
if let Some(slide) = mapping.slide(endian, data).print_err(p) {
100100
match slide {
101+
DyldCacheSlideInfo::V2 { slide, .. } => {
102+
p.group("DyldCacheSlideInfo2", |p| {
103+
p.field("Version", slide.version.get(endian));
104+
p.field("PageSize", slide.page_size.get(endian));
105+
p.field_hex("PageStartsOffset", slide.page_starts_offset.get(endian));
106+
p.field_hex("PageStartsCount", slide.page_starts_count.get(endian));
107+
p.field_hex("PageExtrasOffset", slide.page_extras_offset.get(endian));
108+
p.field_hex("PageExtrasCount", slide.page_extras_count.get(endian));
109+
p.field_hex("DeltaMask", slide.delta_mask.get(endian));
110+
p.field_hex("ValueAdd", slide.value_add.get(endian));
111+
});
112+
}
113+
DyldCacheSlideInfo::V3 { slide, .. } => {
114+
p.group("DyldCacheSlideInfo3", |p| {
115+
p.field("Version", slide.version.get(endian));
116+
p.field("PageSize", slide.page_size.get(endian));
117+
p.field_hex("PageStartsCount", slide.page_starts_count.get(endian));
118+
p.field_hex("AuthValueAdd", slide.auth_value_add.get(endian));
119+
});
120+
}
101121
DyldCacheSlideInfo::V5 { slide, .. } => {
102122
p.group("DyldCacheSlideInfo5", |p| {
103123
p.field("Version", slide.version.get(endian));

src/macho.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,102 @@ pub struct DyldCacheImageInfo<E: Endian> {
496496
pub pad: U32<E>,
497497
}
498498

499+
/// Corresponds to struct dyld_cache_slide_info2 from dyld_cache_format.h.
500+
#[derive(Debug, Clone, Copy)]
501+
#[repr(C)]
502+
pub struct DyldCacheSlideInfo2<E: Endian> {
503+
pub version: U32<E>, // currently 2
504+
pub page_size: U32<E>, // currently 4096 (may also be 16384)
505+
pub page_starts_offset: U32<E>,
506+
pub page_starts_count: U32<E>,
507+
pub page_extras_offset: U32<E>,
508+
pub page_extras_count: U32<E>,
509+
pub delta_mask: U64<E>, // which (contiguous) set of bits contains the delta to the next rebase location
510+
pub value_add: U64<E>,
511+
}
512+
513+
pub const DYLD_CACHE_SLIDE_PAGE_ATTRS: u16 = 0xC000;
514+
// Index is into extras array (not starts array).
515+
pub const DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA: u16 = 0x8000;
516+
// Page has no rebasing.
517+
pub const DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE: u16 = 0x4000;
518+
// Last chain entry for page.
519+
pub const DYLD_CACHE_SLIDE_PAGE_ATTR_END: u16 = 0x8000;
520+
521+
/// Corresponds to struct dyld_cache_slide_info3 from dyld_cache_format.h.
522+
#[derive(Debug, Clone, Copy)]
523+
#[repr(C)]
524+
pub struct DyldCacheSlideInfo3<E: Endian> {
525+
pub version: U32<E>, // currently 3
526+
pub page_size: U32<E>, // currently 4096 (may also be 16384)
527+
pub page_starts_count: U32<E>,
528+
reserved1: [u8; 4],
529+
pub auth_value_add: U64<E>,
530+
}
531+
532+
/// Page has no rebasing.
533+
pub const DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE: u16 = 0xFFFF;
534+
535+
/// Corresponds to union dyld_cache_slide_pointer3 from dyld_cache_format.h.
536+
#[derive(Debug, Clone, Copy)]
537+
pub struct DyldCacheSlidePointer3(pub u64);
538+
539+
impl DyldCacheSlidePointer3 {
540+
/// Whether the pointer is authenticated.
541+
pub fn is_auth(&self) -> bool {
542+
((self.0 >> 63) & 1) != 0
543+
}
544+
545+
/// The target of the pointer.
546+
///
547+
/// Only valid if `is_auth` is false.
548+
pub fn target(&self) -> u64 {
549+
self.0 & ((1 << 43) - 1)
550+
}
551+
552+
/// The high 8 bits of the pointer.
553+
///
554+
/// Only valid if `is_auth` is false.
555+
pub fn high8(&self) -> u64 {
556+
(self.0 >> 43) & 0xff
557+
}
558+
559+
/// The target of the pointer as an offset from the start of the shared cache.
560+
///
561+
/// Only valid if `is_auth` is true.
562+
pub fn runtime_offset(&self) -> u64 {
563+
self.0 & ((1 << 32) - 1)
564+
}
565+
566+
/// The diversity value for authentication.
567+
///
568+
/// Only valid if `is_auth` is true.
569+
pub fn diversity(&self) -> u16 {
570+
((self.0 >> 32) & 0xffff) as u16
571+
}
572+
573+
/// Whether to use address diversity for authentication.
574+
///
575+
/// Only valid if `is_auth` is true.
576+
pub fn addr_div(&self) -> bool {
577+
((self.0 >> 48) & 1) != 0
578+
}
579+
580+
/// The key for authentication.
581+
///
582+
/// Only valid if `is_auth` is true.
583+
pub fn key(&self) -> u8 {
584+
((self.0 >> 49) & 3) as u8
585+
}
586+
587+
/// The offset to the next slide pointer in 8-byte units.
588+
///
589+
/// 0 if no next slide pointer.
590+
pub fn next(&self) -> u64 {
591+
(self.0 >> 51) & ((1 << 11) - 1)
592+
}
593+
}
594+
499595
/// Corresponds to struct dyld_cache_slide_info5 from dyld_cache_format.h.
500596
#[derive(Debug, Clone, Copy)]
501597
#[repr(C)]
@@ -3450,6 +3546,8 @@ unsafe_impl_endian_pod!(
34503546
DyldCacheMappingInfo,
34513547
DyldCacheMappingAndSlideInfo,
34523548
DyldCacheImageInfo,
3549+
DyldCacheSlideInfo2,
3550+
DyldCacheSlideInfo3,
34533551
DyldCacheSlideInfo5,
34543552
DyldSubCacheEntryV1,
34553553
DyldSubCacheEntryV2,

0 commit comments

Comments
 (0)