From 9f2a20b20182ff40ac0856803a1a183a0b8f01ed Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Sat, 17 Feb 2024 16:38:42 +0900 Subject: [PATCH 01/25] fix raw value of `DyldChainedPointerFormat` --- .../DyldChain/DyldChainedPointerFormat.swift | 50 +++++++++++++++++-- Sources/MachOKitC/include/chained_fixups.h | 22 ++++++++ 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedPointerFormat.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedPointerFormat.swift index 2bc7290..7e0e529 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedPointerFormat.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedPointerFormat.swift @@ -8,9 +8,9 @@ import Foundation -public enum DyldChainedPointerFormat: UInt16 { +public enum DyldChainedPointerFormat { /// DYLD_CHAINED_PTR_ARM64E - case arm64e = 1 + case arm64e /// DYLD_CHAINED_PTR_64 case _64 /// DYLD_CHAINED_PTR_32 @@ -21,8 +21,8 @@ public enum DyldChainedPointerFormat: UInt16 { case _32_firmware /// DYLD_CHAINED_PTR_64_OFFSET case _64_offset - /// DYLD_CHAINED_PTR_ARM64E_OFFSET - case arm64e_offset +// /// DYLD_CHAINED_PTR_ARM64E_OFFSET +// case arm64e_offset /// DYLD_CHAINED_PTR_ARM64E_KERNEL case arm64e_kernel /// DYLD_CHAINED_PTR_64_KERNEL_CACHE @@ -46,7 +46,7 @@ extension DyldChainedPointerFormat: CustomStringConvertible { case ._32_cache: "DYLD_CHAINED_PTR_32_CACHE" case ._32_firmware: "DYLD_CHAINED_PTR_32_FIRMWARE" case ._64_offset: "DYLD_CHAINED_PTR_64_OFFSET" - case .arm64e_offset: "DYLD_CHAINED_PTR_ARM64E_OFFSET" +// case .arm64e_offset: "DYLD_CHAINED_PTR_ARM64E_OFFSET" case .arm64e_kernel: "DYLD_CHAINED_PTR_ARM64E_KERNEL" case ._64_kernel_cache: "DYLD_CHAINED_PTR_64_KERNEL_CACHE" case .arm64e_userland: "DYLD_CHAINED_PTR_ARM64E_USERLAND" @@ -56,3 +56,43 @@ extension DyldChainedPointerFormat: CustomStringConvertible { } } } + +extension DyldChainedPointerFormat: RawRepresentable { + public typealias RawValue = UInt16 + + public init?(rawValue: RawValue) { + switch rawValue { + case UInt16(DYLD_CHAINED_PTR_ARM64E): self = .arm64e + case UInt16(DYLD_CHAINED_PTR_64): self = ._64 + case UInt16(DYLD_CHAINED_PTR_32): self = ._32 + case UInt16(DYLD_CHAINED_PTR_32_CACHE): self = ._32_cache + case UInt16(DYLD_CHAINED_PTR_32_FIRMWARE): self = ._32_firmware + case UInt16(DYLD_CHAINED_PTR_64_OFFSET): self = ._64_offset +// case UInt16(DYLD_CHAINED_PTR_ARM64E_OFFSET): self = .arm64e_offset + case UInt16(DYLD_CHAINED_PTR_ARM64E_KERNEL): self = .arm64e_kernel + case UInt16(DYLD_CHAINED_PTR_64_KERNEL_CACHE): self = ._64_kernel_cache + case UInt16(DYLD_CHAINED_PTR_ARM64E_USERLAND): self = .arm64e_userland + case UInt16(DYLD_CHAINED_PTR_ARM64E_FIRMWARE): self = .arm64e_firmware + case UInt16(DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE): self = .x86_64_kernel_cache + case UInt16(DYLD_CHAINED_PTR_ARM64E_USERLAND24): self = .arm64e_userland24 + default: return nil + } + } + public var rawValue: RawValue { + switch self { + case .arm64e: UInt16(DYLD_CHAINED_PTR_ARM64E) + case ._64: UInt16(DYLD_CHAINED_PTR_64) + case ._32: UInt16(DYLD_CHAINED_PTR_32) + case ._32_cache: UInt16(DYLD_CHAINED_PTR_32_CACHE) + case ._32_firmware: UInt16(DYLD_CHAINED_PTR_32_FIRMWARE) + case ._64_offset: UInt16(DYLD_CHAINED_PTR_64_OFFSET) +// case .arm64e_offset: UInt16(DYLD_CHAINED_PTR_ARM64E_OFFSET) + case .arm64e_kernel: UInt16(DYLD_CHAINED_PTR_ARM64E_KERNEL) + case ._64_kernel_cache: UInt16(DYLD_CHAINED_PTR_64_KERNEL_CACHE) + case .arm64e_userland: UInt16(DYLD_CHAINED_PTR_ARM64E_USERLAND) + case .arm64e_firmware: UInt16(DYLD_CHAINED_PTR_ARM64E_FIRMWARE) + case .x86_64_kernel_cache: UInt16(DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE) + case .arm64e_userland24: UInt16(DYLD_CHAINED_PTR_ARM64E_USERLAND24) + } + } +} diff --git a/Sources/MachOKitC/include/chained_fixups.h b/Sources/MachOKitC/include/chained_fixups.h index 6f366b0..c9f0a07 100644 --- a/Sources/MachOKitC/include/chained_fixups.h +++ b/Sources/MachOKitC/include/chained_fixups.h @@ -51,6 +51,12 @@ struct dyld_chained_starts_in_segment // the last of which has the high bit set }; +enum { + DYLD_CHAINED_PTR_START_NONE = 0xFFFF, // used in page_start[] to denote a page with no fixups + DYLD_CHAINED_PTR_START_MULTI = 0x8000, // used in page_start[] to denote a page which has multiple starts + DYLD_CHAINED_PTR_START_LAST = 0x8000, // used in chain_starts[] to denote last start in list for page +}; + // This struct is embedded in __TEXT,__chain_starts section in firmware struct dyld_chained_starts_offsets { @@ -59,6 +65,22 @@ struct dyld_chained_starts_offsets uint32_t chain_starts[1]; // array chain start offsets }; +enum { + DYLD_CHAINED_PTR_ARM64E = 1, // stride 8, unauth target is vmaddr + DYLD_CHAINED_PTR_64 = 2, // target is vmaddr + DYLD_CHAINED_PTR_32 = 3, + DYLD_CHAINED_PTR_32_CACHE = 4, + DYLD_CHAINED_PTR_32_FIRMWARE = 5, + DYLD_CHAINED_PTR_64_OFFSET = 6, // target is vm offset + DYLD_CHAINED_PTR_ARM64E_OFFSET = 7, // old name + DYLD_CHAINED_PTR_ARM64E_KERNEL = 7, // stride 4, unauth target is vm offset + DYLD_CHAINED_PTR_64_KERNEL_CACHE = 8, + DYLD_CHAINED_PTR_ARM64E_USERLAND = 9, // stride 8, unauth target is vm offset + DYLD_CHAINED_PTR_ARM64E_FIRMWARE = 10, // stride 4, unauth target is vmaddr + DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE = 11, // stride 1, x86_64 kernel caches + DYLD_CHAINED_PTR_ARM64E_USERLAND24 = 12, // stride 8, unauth target is vm offset, 24-bit bind +}; + // DYLD_CHAINED_PTR_ARM64E struct dyld_chained_ptr_arm64e_rebase { From 85163f15e9fd04c4cd3dd6dd6d674e9e0b883d91 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Sat, 17 Feb 2024 21:31:46 +0900 Subject: [PATCH 02/25] add parameter for page index to `DyldChainedPage` --- Sources/MachOKit/MachOFile+DyldChainedFixups.swift | 2 +- Sources/MachOKit/MachOImage+DyldChainedFixups..swift | 2 +- .../MachOKit/Model/DyldChain/DyldChainedSymbolsFormat.swift | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Sources/MachOKit/MachOFile+DyldChainedFixups.swift b/Sources/MachOKit/MachOFile+DyldChainedFixups.swift index 41a6f3c..22a0925 100644 --- a/Sources/MachOKit/MachOFile+DyldChainedFixups.swift +++ b/Sources/MachOKit/MachOFile+DyldChainedFixups.swift @@ -105,7 +105,7 @@ extension MachOFile.DyldChainedFixups: DyldChainedFixupsProtocol { .map { isSwapped ? $0.byteSwapped : $0 } - .map { .init(offset: $0) } + .enumerated().map { .init(offset: $1, index: $0) } } } diff --git a/Sources/MachOKit/MachOImage+DyldChainedFixups..swift b/Sources/MachOKit/MachOImage+DyldChainedFixups..swift index 47a7743..26ad4f7 100644 --- a/Sources/MachOKit/MachOImage+DyldChainedFixups..swift +++ b/Sources/MachOKit/MachOImage+DyldChainedFixups..swift @@ -125,7 +125,7 @@ extension MachOImage.DyldChainedFixups: DyldChainedFixupsProtocol { count: numericCast( startsInSegment.page_count ) - ).map { .init(offset: $0) } + ).enumerated().map { .init(offset: $1, index: $0) } } public var imports: [DyldChainedImport] { diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedSymbolsFormat.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedSymbolsFormat.swift index 0c82e88..bb183e9 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedSymbolsFormat.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedSymbolsFormat.swift @@ -15,12 +15,13 @@ public enum DyldChainedSymbolsFormat: UInt32 { public struct DyldChainedPage { public let offset: UInt16 + public let index: Int public var isNone: Bool { - offset == 0xFFFF // DYLD_CHAINED_PTR_START_NONE + offset == DYLD_CHAINED_PTR_START_NONE } public var isMulti: Bool { - offset & 0x8000 > 0 // DYLD_CHAINED_PTR_START_MULTI + offset & UInt16(DYLD_CHAINED_PTR_START_MULTI) > 0 } } From c65fff62cebb673d9030e3537239138325b98614 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Sat, 17 Feb 2024 21:33:32 +0900 Subject: [PATCH 03/25] move `DyldChainedPage` to other file --- .../Model/DyldChain/DyldChainedPage.swift | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Sources/MachOKit/Model/DyldChain/DyldChainedPage.swift diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedPage.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedPage.swift new file mode 100644 index 0000000..9ae7319 --- /dev/null +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedPage.swift @@ -0,0 +1,22 @@ +// +// DyldChainedPage.swift +// +// +// Created by p-x9 on 2024/02/17. +// +// + +import Foundation + +public struct DyldChainedPage { + public let offset: UInt16 + public let index: Int + + public var isNone: Bool { + offset == DYLD_CHAINED_PTR_START_NONE + } + + public var isMulti: Bool { + offset & UInt16(DYLD_CHAINED_PTR_START_MULTI) > 0 + } +} From 74d8b3b69dfc7cd6c23605dfc797606534dffbc0 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Sun, 18 Feb 2024 16:29:35 +0900 Subject: [PATCH 04/25] implemented `DyldChainedFixupPointer` --- .../DyldChain/DyldChainedFixupPointer.swift | 243 ++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift new file mode 100644 index 0000000..fd9f7ba --- /dev/null +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift @@ -0,0 +1,243 @@ +// +// DyldChainedFixupPointer.swift +// +// +// Created by p-x9 on 2024/02/17. +// +// + +import Foundation + +// https://github.com/apple-oss-distributions/dyld/blob/d1a0f6869ece370913a3f749617e457f3b4cd7c4/common/MachOLayout.cpp#L2094 + +public enum DyldChainedFixupPointer { + /// DYLD_CHAINED_PTR_ARM64E + case arm64e(ARM64E) + /// DYLD_CHAINED_PTR_64 + case _64(General64) + /// DYLD_CHAINED_PTR_32 + case _32(General32) + /// DYLD_CHAINED_PTR_32_CACHE + case _32_cache(General32Cache) + /// DYLD_CHAINED_PTR_32_FIRMWARE + case _32_firmware(General32Firmware) + /// DYLD_CHAINED_PTR_64_OFFSET + case _64_offset(General64) + /// DYLD_CHAINED_PTR_ARM64E_KERNEL + case arm64e_kernel(ARM64E) + /// DYLD_CHAINED_PTR_64_KERNEL_CACHE + case _64_kernel_cache(General64Cache) + /// DYLD_CHAINED_PTR_ARM64E_USERLAND + case arm64e_userland(ARM64E) + /// DYLD_CHAINED_PTR_ARM64E_FIRMWARE + case arm64e_firmware(ARM64E) + /// DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE + case x86_64_kernel_cache(General64Cache) + /// DYLD_CHAINED_PTR_ARM64E_USERLAND24 + case arm64e_userland24(ARM64E) +} + +extension DyldChainedFixupPointer { + public var pointerFormat: DyldChainedPointerFormat { + switch self { + case .arm64e: .arm64e + case ._64: ._64 + case ._32: ._32 + case ._32_cache: ._32_cache + case ._32_firmware: ._32_firmware + case ._64_offset: ._64_offset + case .arm64e_kernel: .arm64e_kernel + case ._64_kernel_cache: ._64_kernel_cache + case .arm64e_userland: .arm64e_userland + case .arm64e_firmware: .arm64e_firmware + case .x86_64_kernel_cache: .x86_64_kernel_cache + case .arm64e_userland24: .arm64e_userland24 + } + } +} + +extension DyldChainedFixupPointer { + public enum ARM64E { + case rebase(DyldChainedPtrArm64eRebase) + case bind(DyldChainedPtrArm64eBind) + case authRebase(DyldChainedPtrArm64eAuthRebase) + case authBind(DyldChainedPtrArm64eAuthBind) + + var next: Int { + switch self { + case let .rebase(info): numericCast(info.layout.next) + case let .bind(info): numericCast(info.layout.next) + case let .authRebase(info): numericCast(info.layout.next) + case let .authBind(info): numericCast(info.layout.next) + } + } + + init(rawValue: UInt64) { + let tmp = DyldChainedPtrArm64eRebase(layout: autoBitCast(rawValue)) + let isBind = tmp.layout.bind == 1 + let isAuth = tmp.layout.auth == 1 + + switch (isBind, isAuth) { + case (true, false): self = .bind(autoBitCast(rawValue)) + case (false, false): self = .rebase(autoBitCast(rawValue)) + case (true, true): self = .authBind(autoBitCast(rawValue)) + case (false, true): self = .authRebase(autoBitCast(rawValue)) + } + } + } + + public enum General64 { + case rebase(DyldChainedPtr64Rebase) + case bind(DyldChainedPtr64Bind) + + var next: Int { + switch self { + case let .rebase(info): numericCast(info.layout.next) + case let .bind(info): numericCast(info.layout.next) + } + } + + init(rawValue: UInt64) { + let tmp = DyldChainedPtr64Rebase(layout: autoBitCast(rawValue)) + let isBind = tmp.layout.bind == 1 + + if isBind { + self = .bind(autoBitCast(rawValue)) + } else { + self = .rebase(autoBitCast(rawValue)) + } + } + } + + public enum General64Cache { + case rebase(DyldChainedPtr64KernelCacheRebase) + + var next: Int { + switch self { + case let .rebase(info): numericCast(info.layout.next) + } + } + + init(rawValue: UInt64) { + self = .rebase(autoBitCast(rawValue)) + } + } + + public enum General32 { + case rebase(DyldChainedPtr32Rebase) + case bind(DyldChainedPtr32Bind) + + var next: Int { + switch self { + case let .rebase(info): numericCast(info.layout.next) + case let .bind(info): numericCast(info.layout.next) + } + } + + init(rawValue: UInt32) { + let tmp = DyldChainedPtr32Rebase(layout: autoBitCast(rawValue)) + let isBind = tmp.layout.bind == 1 + + if isBind { + self = .bind(autoBitCast(rawValue)) + } else { + self = .rebase(autoBitCast(rawValue)) + } + } + } + + public enum General32Cache { + case rebase(DyldChainedPtr32CacheRebase) + + var next: Int { + switch self { + case let .rebase(info): numericCast(info.layout.next) + } + } + + init(rawValue: UInt32) { + self = .rebase(autoBitCast(rawValue)) + } + } + + public enum General32Firmware { + case rebase(DyldChainedPtr32FirmwareRebase) + + var next: Int { + switch self { + case let .rebase(info): numericCast(info.layout.next) + } + } + + init(rawValue: UInt32) { + self = .rebase(autoBitCast(rawValue)) + } + } +} + +public struct DyldChainedPtrArm64eRebase: LayoutWrapper { + public typealias Layout = dyld_chained_ptr_arm64e_rebase + public var layout: Layout +} + +public struct DyldChainedPtrArm64eBind: LayoutWrapper { + public typealias Layout = dyld_chained_ptr_arm64e_bind + public var layout: Layout +} + +public struct DyldChainedPtrArm64eAuthRebase: LayoutWrapper { + public typealias Layout = dyld_chained_ptr_arm64e_auth_rebase + public var layout: Layout + + public var keyName: String { + ["IA", "IB", "DA", "DB"][Int(layout.key)] + } +} + +public struct DyldChainedPtrArm64eAuthBind: LayoutWrapper { + public typealias Layout = dyld_chained_ptr_arm64e_auth_bind + public var layout: Layout + + public var keyName: String { + ["IA", "IB", "DA", "DB"][Int(layout.key)] + } +} + +public struct DyldChainedPtr64Rebase: LayoutWrapper { + public typealias Layout = dyld_chained_ptr_64_rebase + public var layout: Layout +} + +public struct DyldChainedPtr64Bind: LayoutWrapper { + public typealias Layout = dyld_chained_ptr_64_bind + public var layout: Layout +} + +public struct DyldChainedPtr64KernelCacheRebase: LayoutWrapper { + public typealias Layout = dyld_chained_ptr_64_kernel_cache_rebase + public var layout: Layout + + public var keyName: String { + ["IA", "IB", "DA", "DB"][Int(layout.key)] + } +} + +public struct DyldChainedPtr32Rebase: LayoutWrapper { + public typealias Layout = dyld_chained_ptr_32_rebase + public var layout: Layout +} + +public struct DyldChainedPtr32Bind: LayoutWrapper { + public typealias Layout = dyld_chained_ptr_32_bind + public var layout: Layout +} + +public struct DyldChainedPtr32CacheRebase: LayoutWrapper { + public typealias Layout = dyld_chained_ptr_32_cache_rebase + public var layout: Layout +} + +public struct DyldChainedPtr32FirmwareRebase: LayoutWrapper { + public typealias Layout = dyld_chained_ptr_32_firmware_rebase + public var layout: Layout +} From 2455a1989bfec9d828c657ae068d135fd55bdd05 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Sun, 18 Feb 2024 16:30:15 +0900 Subject: [PATCH 05/25] add stride info to pointer format --- .../DyldChain/DyldChainedPointerFormat.swift | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedPointerFormat.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedPointerFormat.swift index 7e0e529..c30e826 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedPointerFormat.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedPointerFormat.swift @@ -3,7 +3,7 @@ // // // Created by p-x9 on 2024/01/11. -// +// // import Foundation @@ -21,8 +21,8 @@ public enum DyldChainedPointerFormat { case _32_firmware /// DYLD_CHAINED_PTR_64_OFFSET case _64_offset -// /// DYLD_CHAINED_PTR_ARM64E_OFFSET -// case arm64e_offset + // /// DYLD_CHAINED_PTR_ARM64E_OFFSET + // case arm64e_offset /// DYLD_CHAINED_PTR_ARM64E_KERNEL case arm64e_kernel /// DYLD_CHAINED_PTR_64_KERNEL_CACHE @@ -46,7 +46,7 @@ extension DyldChainedPointerFormat: CustomStringConvertible { case ._32_cache: "DYLD_CHAINED_PTR_32_CACHE" case ._32_firmware: "DYLD_CHAINED_PTR_32_FIRMWARE" case ._64_offset: "DYLD_CHAINED_PTR_64_OFFSET" -// case .arm64e_offset: "DYLD_CHAINED_PTR_ARM64E_OFFSET" + // case .arm64e_offset: "DYLD_CHAINED_PTR_ARM64E_OFFSET" case .arm64e_kernel: "DYLD_CHAINED_PTR_ARM64E_KERNEL" case ._64_kernel_cache: "DYLD_CHAINED_PTR_64_KERNEL_CACHE" case .arm64e_userland: "DYLD_CHAINED_PTR_ARM64E_USERLAND" @@ -68,7 +68,7 @@ extension DyldChainedPointerFormat: RawRepresentable { case UInt16(DYLD_CHAINED_PTR_32_CACHE): self = ._32_cache case UInt16(DYLD_CHAINED_PTR_32_FIRMWARE): self = ._32_firmware case UInt16(DYLD_CHAINED_PTR_64_OFFSET): self = ._64_offset -// case UInt16(DYLD_CHAINED_PTR_ARM64E_OFFSET): self = .arm64e_offset + // case UInt16(DYLD_CHAINED_PTR_ARM64E_OFFSET): self = .arm64e_offset case UInt16(DYLD_CHAINED_PTR_ARM64E_KERNEL): self = .arm64e_kernel case UInt16(DYLD_CHAINED_PTR_64_KERNEL_CACHE): self = ._64_kernel_cache case UInt16(DYLD_CHAINED_PTR_ARM64E_USERLAND): self = .arm64e_userland @@ -78,6 +78,7 @@ extension DyldChainedPointerFormat: RawRepresentable { default: return nil } } + public var rawValue: RawValue { switch self { case .arm64e: UInt16(DYLD_CHAINED_PTR_ARM64E) @@ -86,7 +87,7 @@ extension DyldChainedPointerFormat: RawRepresentable { case ._32_cache: UInt16(DYLD_CHAINED_PTR_32_CACHE) case ._32_firmware: UInt16(DYLD_CHAINED_PTR_32_FIRMWARE) case ._64_offset: UInt16(DYLD_CHAINED_PTR_64_OFFSET) -// case .arm64e_offset: UInt16(DYLD_CHAINED_PTR_ARM64E_OFFSET) + // case .arm64e_offset: UInt16(DYLD_CHAINED_PTR_ARM64E_OFFSET) case .arm64e_kernel: UInt16(DYLD_CHAINED_PTR_ARM64E_KERNEL) case ._64_kernel_cache: UInt16(DYLD_CHAINED_PTR_64_KERNEL_CACHE) case .arm64e_userland: UInt16(DYLD_CHAINED_PTR_ARM64E_USERLAND) @@ -96,3 +97,34 @@ extension DyldChainedPointerFormat: RawRepresentable { } } } + +extension DyldChainedPointerFormat { + // byte + var is64Bit: Bool { + switch self { + case .arm64e, .arm64e_userland, .arm64e_userland24, + .arm64e_kernel, .arm64e_firmware, + ._64, ._64_offset, ._64_kernel_cache, + .x86_64_kernel_cache: + return true + case ._32, ._32_firmware, ._32_cache: + return false + } + } +} + +extension DyldChainedPointerFormat { + // https://github.com/apple-oss-distributions/dyld/blob/d1a0f6869ece370913a3f749617e457f3b4cd7c4/common/MachOLayout.cpp#L2145 + var stride: Int { + switch self { + case .arm64e, .arm64e_userland, .arm64e_userland24: + return 8 + case .arm64e_kernel, .arm64e_firmware, + ._32, ._32_firmware, ._32_cache, + ._64, ._64_offset, ._64_kernel_cache: + return 4 + case .x86_64_kernel_cache: + return 1 + } + } +} From 1f459944e044a4d5d8404561eef7e39902f67284 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Sun, 18 Feb 2024 16:32:38 +0900 Subject: [PATCH 06/25] add wrap function for `unsafeBitCast` named `autoBitCast` --- Sources/MachOKit/Util/global.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Sources/MachOKit/Util/global.swift diff --git a/Sources/MachOKit/Util/global.swift b/Sources/MachOKit/Util/global.swift new file mode 100644 index 0000000..fa58b80 --- /dev/null +++ b/Sources/MachOKit/Util/global.swift @@ -0,0 +1,13 @@ +// +// global.swift +// +// +// Created by p-x9 on 2024/02/17. +// +// + +import Foundation + +public func autoBitCast(_ x: T) -> U { + unsafeBitCast(x, to: U.self) +} From d00fb60f2a4ecba9536053b8222e8317dc996520 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Sun, 18 Feb 2024 16:36:33 +0900 Subject: [PATCH 07/25] add `segmentIndex` to `DyldChainedStartsInSegment` --- Sources/MachOKit/MachOFile+DyldChainedFixups.swift | 9 +++++---- Sources/MachOKit/MachOImage+DyldChainedFixups..swift | 12 ++++++++---- .../Model/DyldChain/DyldChainedStartsInSegment.swift | 3 ++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Sources/MachOKit/MachOFile+DyldChainedFixups.swift b/Sources/MachOKit/MachOFile+DyldChainedFixups.swift index 22a0925..c3c4d81 100644 --- a/Sources/MachOKit/MachOFile+DyldChainedFixups.swift +++ b/Sources/MachOKit/MachOFile+DyldChainedFixups.swift @@ -69,14 +69,15 @@ extension MachOFile.DyldChainedFixups: DyldChainedFixupsProtocol { guard let basePtr = $0.baseAddress else { return [] } let ptr = UnsafeRawPointer(basePtr) .advanced(by: startsInImage.offset) - return offsets.map { - let layout = ptr.advanced(by: $0) + return offsets.enumerated().map { index, offset in + let layout = ptr.advanced(by: offset) .assumingMemoryBound(to: DyldChainedStartsInSegment.Layout.self) .pointee - let offset: Int = startsInImage.offset + $0 + let offset: Int = startsInImage.offset + offset let ret: DyldChainedStartsInSegment = .init( layout: layout, - offset: offset + offset: offset, + segmentIndex: index ) return isSwapped ? ret.swapped : ret } diff --git a/Sources/MachOKit/MachOImage+DyldChainedFixups..swift b/Sources/MachOKit/MachOImage+DyldChainedFixups..swift index 1658ab1..01982f8 100644 --- a/Sources/MachOKit/MachOImage+DyldChainedFixups..swift +++ b/Sources/MachOKit/MachOImage+DyldChainedFixups..swift @@ -102,12 +102,16 @@ extension MachOImage.DyldChainedFixups: DyldChainedFixupsProtocol { let ptr = UnsafeRawPointer(basePointer) .advanced(by: startsInImage.offset) - return offsets.map { - let layout = ptr.advanced(by: $0) + return offsets.enumerated().map { index, offset in + let layout = ptr.advanced(by: offset) .assumingMemoryBound(to: DyldChainedStartsInSegment.Layout.self) .pointee - let offset: Int = startsInImage.offset + $0 - return .init(layout: layout, offset: offset) + let offset: Int = startsInImage.offset + offset + return .init( + layout: layout, + offset: offset, + segmentIndex: index + ) } } diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedStartsInSegment.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedStartsInSegment.swift index 5b4c9b5..d4b38c6 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedStartsInSegment.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedStartsInSegment.swift @@ -14,6 +14,7 @@ public struct DyldChainedStartsInSegment: LayoutWrapper { public var layout: Layout public let offset: Int + public let segmentIndex: Int public var pointerFormat: DyldChainedPointerFormat? { .init(rawValue: layout.pointer_format) @@ -30,6 +31,6 @@ extension DyldChainedStartsInSegment { layout.max_valid_pointer = layout.max_valid_pointer.byteSwapped layout.page_count = layout.page_count.byteSwapped layout.page_start = layout.page_start.byteSwapped - return .init(layout: layout, offset: offset) + return .init(layout: layout, offset: offset, segmentIndex: segmentIndex) } } From 70c38e3eb31d112237165c51b38f078050d7c54f Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Sun, 18 Feb 2024 16:37:59 +0900 Subject: [PATCH 08/25] delete old `DyldChainedPage` --- .../Model/DyldChain/DyldChainedSymbolsFormat.swift | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedSymbolsFormat.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedSymbolsFormat.swift index bb183e9..eb222f0 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedSymbolsFormat.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedSymbolsFormat.swift @@ -12,16 +12,3 @@ public enum DyldChainedSymbolsFormat: UInt32 { case uncompressed case zlibCompressed } - -public struct DyldChainedPage { - public let offset: UInt16 - public let index: Int - - public var isNone: Bool { - offset == DYLD_CHAINED_PTR_START_NONE - } - - public var isMulti: Bool { - offset & UInt16(DYLD_CHAINED_PTR_START_MULTI) > 0 - } -} From 71133e33ed09d123e40b523e79ca46a6030f046c Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Mon, 19 Feb 2024 14:09:49 +0900 Subject: [PATCH 09/25] implemented `DyldChainedFixupPointerContent` protocol --- .../DyldChain/DyldChainedFixupPointer.swift | 82 ++++++++++++++++--- 1 file changed, 70 insertions(+), 12 deletions(-) diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift index fd9f7ba..91fe76e 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift @@ -57,13 +57,30 @@ extension DyldChainedFixupPointer { } extension DyldChainedFixupPointer { - public enum ARM64E { + public enum ContentType { + case bind + case rebase + } +} + +public protocol DyldChainedFixupPointerContent { + var type: DyldChainedFixupPointer.ContentType { get } + var next: Int { get } +} + +extension DyldChainedFixupPointerContent { + public var isBind: Bool { type == .bind } + public var isRebase: Bool { type == .rebase } +} + +extension DyldChainedFixupPointer { + public enum ARM64E: DyldChainedFixupPointerContent { case rebase(DyldChainedPtrArm64eRebase) case bind(DyldChainedPtrArm64eBind) case authRebase(DyldChainedPtrArm64eAuthRebase) case authBind(DyldChainedPtrArm64eAuthBind) - var next: Int { + public var next: Int { switch self { case let .rebase(info): numericCast(info.layout.next) case let .bind(info): numericCast(info.layout.next) @@ -72,6 +89,15 @@ extension DyldChainedFixupPointer { } } + public var type: DyldChainedFixupPointer.ContentType { + switch self { + case .rebase: .rebase + case .bind: .bind + case .authRebase: .rebase + case .authBind: .bind + } + } + init(rawValue: UInt64) { let tmp = DyldChainedPtrArm64eRebase(layout: autoBitCast(rawValue)) let isBind = tmp.layout.bind == 1 @@ -86,17 +112,24 @@ extension DyldChainedFixupPointer { } } - public enum General64 { + public enum General64: DyldChainedFixupPointerContent { case rebase(DyldChainedPtr64Rebase) case bind(DyldChainedPtr64Bind) - var next: Int { + public var next: Int { switch self { case let .rebase(info): numericCast(info.layout.next) case let .bind(info): numericCast(info.layout.next) } } + public var type: DyldChainedFixupPointer.ContentType { + switch self { + case .rebase: .rebase + case .bind: .bind + } + } + init(rawValue: UInt64) { let tmp = DyldChainedPtr64Rebase(layout: autoBitCast(rawValue)) let isBind = tmp.layout.bind == 1 @@ -109,31 +142,44 @@ extension DyldChainedFixupPointer { } } - public enum General64Cache { + public enum General64Cache: DyldChainedFixupPointerContent { case rebase(DyldChainedPtr64KernelCacheRebase) - var next: Int { + public var next: Int { switch self { case let .rebase(info): numericCast(info.layout.next) } } + public var type: DyldChainedFixupPointer.ContentType { + switch self { + case .rebase: .rebase + } + } + init(rawValue: UInt64) { self = .rebase(autoBitCast(rawValue)) } } - public enum General32 { + public enum General32: DyldChainedFixupPointerContent { case rebase(DyldChainedPtr32Rebase) case bind(DyldChainedPtr32Bind) - var next: Int { + public var next: Int { switch self { case let .rebase(info): numericCast(info.layout.next) case let .bind(info): numericCast(info.layout.next) } } + public var type: DyldChainedFixupPointer.ContentType { + switch self { + case .rebase: .rebase + case .bind: .bind + } + } + init(rawValue: UInt32) { let tmp = DyldChainedPtr32Rebase(layout: autoBitCast(rawValue)) let isBind = tmp.layout.bind == 1 @@ -146,29 +192,41 @@ extension DyldChainedFixupPointer { } } - public enum General32Cache { + public enum General32Cache: DyldChainedFixupPointerContent { case rebase(DyldChainedPtr32CacheRebase) - var next: Int { + public var next: Int { switch self { case let .rebase(info): numericCast(info.layout.next) } } + public var type: DyldChainedFixupPointer.ContentType { + switch self { + case .rebase: .rebase + } + } + init(rawValue: UInt32) { self = .rebase(autoBitCast(rawValue)) } } - public enum General32Firmware { + public enum General32Firmware: DyldChainedFixupPointerContent { case rebase(DyldChainedPtr32FirmwareRebase) - var next: Int { + public var next: Int { switch self { case let .rebase(info): numericCast(info.layout.next) } } + public var type: DyldChainedFixupPointer.ContentType { + switch self { + case .rebase: .rebase + } + } + init(rawValue: UInt32) { self = .rebase(autoBitCast(rawValue)) } From e0ed999e5eaa4de2a529afa5c50db923224d1d00 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Mon, 19 Feb 2024 15:52:29 +0900 Subject: [PATCH 10/25] add `DyldChainedPointerContentRebase` and `DyldChainedPointerContentBind` protocol --- .../DyldChain/DyldChainedFixupPointer.swift | 142 +++++++++++++++--- 1 file changed, 120 insertions(+), 22 deletions(-) diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift index 91fe76e..9436c7e 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift @@ -82,10 +82,10 @@ extension DyldChainedFixupPointer { public var next: Int { switch self { - case let .rebase(info): numericCast(info.layout.next) - case let .bind(info): numericCast(info.layout.next) - case let .authRebase(info): numericCast(info.layout.next) - case let .authBind(info): numericCast(info.layout.next) + case let .rebase(info): info.next + case let .bind(info): info.next + case let .authRebase(info): info.next + case let .authBind(info): info.next } } @@ -118,8 +118,8 @@ extension DyldChainedFixupPointer { public var next: Int { switch self { - case let .rebase(info): numericCast(info.layout.next) - case let .bind(info): numericCast(info.layout.next) + case let .rebase(info): info.next + case let .bind(info): info.next } } @@ -147,7 +147,7 @@ extension DyldChainedFixupPointer { public var next: Int { switch self { - case let .rebase(info): numericCast(info.layout.next) + case let .rebase(info): info.next } } @@ -168,8 +168,8 @@ extension DyldChainedFixupPointer { public var next: Int { switch self { - case let .rebase(info): numericCast(info.layout.next) - case let .bind(info): numericCast(info.layout.next) + case let .rebase(info): info.next + case let .bind(info): info.next } } @@ -197,7 +197,7 @@ extension DyldChainedFixupPointer { public var next: Int { switch self { - case let .rebase(info): numericCast(info.layout.next) + case let .rebase(info): info.next } } @@ -217,7 +217,7 @@ extension DyldChainedFixupPointer { public var next: Int { switch self { - case let .rebase(info): numericCast(info.layout.next) + case let .rebase(info): info.next } } @@ -233,69 +233,167 @@ extension DyldChainedFixupPointer { } } -public struct DyldChainedPtrArm64eRebase: LayoutWrapper { +public protocol DyldChainedPointerContentRebase: LayoutWrapper { + var target: Int { get } + var next: Int { get } +} + +public protocol DyldChainedPointerContentBind: LayoutWrapper { + var ordinal: Int { get } + var next: Int { get } +} + +public struct DyldChainedPtrArm64eRebase: DyldChainedPointerContentRebase { public typealias Layout = dyld_chained_ptr_arm64e_rebase public var layout: Layout + + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } } -public struct DyldChainedPtrArm64eBind: LayoutWrapper { +public struct DyldChainedPtrArm64eBind: DyldChainedPointerContentBind { public typealias Layout = dyld_chained_ptr_arm64e_bind public var layout: Layout + + public var ordinal: Int { + numericCast(layout.ordinal) + } + + public var next: Int { + numericCast(layout.next) + } } -public struct DyldChainedPtrArm64eAuthRebase: LayoutWrapper { +public struct DyldChainedPtrArm64eAuthRebase: DyldChainedPointerContentRebase { public typealias Layout = dyld_chained_ptr_arm64e_auth_rebase public var layout: Layout + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } + public var keyName: String { ["IA", "IB", "DA", "DB"][Int(layout.key)] } } -public struct DyldChainedPtrArm64eAuthBind: LayoutWrapper { +public struct DyldChainedPtrArm64eAuthBind: DyldChainedPointerContentBind { public typealias Layout = dyld_chained_ptr_arm64e_auth_bind public var layout: Layout + public var ordinal: Int { + numericCast(layout.ordinal) + } + + public var next: Int { + numericCast(layout.next) + } + public var keyName: String { ["IA", "IB", "DA", "DB"][Int(layout.key)] } } -public struct DyldChainedPtr64Rebase: LayoutWrapper { +public struct DyldChainedPtr64Rebase: DyldChainedPointerContentRebase { public typealias Layout = dyld_chained_ptr_64_rebase public var layout: Layout + + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } } -public struct DyldChainedPtr64Bind: LayoutWrapper { +public struct DyldChainedPtr64Bind: DyldChainedPointerContentBind { public typealias Layout = dyld_chained_ptr_64_bind public var layout: Layout + + public var ordinal: Int { + numericCast(layout.ordinal) + } + + public var next: Int { + numericCast(layout.next) + } } -public struct DyldChainedPtr64KernelCacheRebase: LayoutWrapper { +public struct DyldChainedPtr64KernelCacheRebase: DyldChainedPointerContentRebase { public typealias Layout = dyld_chained_ptr_64_kernel_cache_rebase public var layout: Layout + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } + public var keyName: String { ["IA", "IB", "DA", "DB"][Int(layout.key)] } } -public struct DyldChainedPtr32Rebase: LayoutWrapper { +public struct DyldChainedPtr32Rebase: DyldChainedPointerContentRebase { public typealias Layout = dyld_chained_ptr_32_rebase public var layout: Layout + + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } } -public struct DyldChainedPtr32Bind: LayoutWrapper { +public struct DyldChainedPtr32Bind: DyldChainedPointerContentBind { public typealias Layout = dyld_chained_ptr_32_bind public var layout: Layout + + public var ordinal: Int { + numericCast(layout.ordinal) + } + + public var next: Int { + numericCast(layout.next) + } } -public struct DyldChainedPtr32CacheRebase: LayoutWrapper { +public struct DyldChainedPtr32CacheRebase: DyldChainedPointerContentRebase { public typealias Layout = dyld_chained_ptr_32_cache_rebase public var layout: Layout + + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } } -public struct DyldChainedPtr32FirmwareRebase: LayoutWrapper { +public struct DyldChainedPtr32FirmwareRebase: DyldChainedPointerContentRebase { public typealias Layout = dyld_chained_ptr_32_firmware_rebase public var layout: Layout + + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } } From 4e1ebf70b213ccd19917bfe9023540a30f376dba Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:13:10 +0900 Subject: [PATCH 11/25] rename `DyldChainedFixupPointer` to `DyldChainedFixupPointerInfo` --- ...wift => DyldChainedFixupPointerInfo.swift} | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) rename Sources/MachOKit/Model/DyldChain/{DyldChainedFixupPointer.swift => DyldChainedFixupPointerInfo.swift} (93%) diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift similarity index 93% rename from Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift rename to Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift index 9436c7e..8fa7a0d 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift @@ -1,5 +1,5 @@ // -// DyldChainedFixupPointer.swift +// DyldChainedFixupPointerInfo.swift // // // Created by p-x9 on 2024/02/17. @@ -10,7 +10,7 @@ import Foundation // https://github.com/apple-oss-distributions/dyld/blob/d1a0f6869ece370913a3f749617e457f3b4cd7c4/common/MachOLayout.cpp#L2094 -public enum DyldChainedFixupPointer { +public enum DyldChainedFixupPointerInfo { /// DYLD_CHAINED_PTR_ARM64E case arm64e(ARM64E) /// DYLD_CHAINED_PTR_64 @@ -37,7 +37,7 @@ public enum DyldChainedFixupPointer { case arm64e_userland24(ARM64E) } -extension DyldChainedFixupPointer { +extension DyldChainedFixupPointerInfo { public var pointerFormat: DyldChainedPointerFormat { switch self { case .arm64e: .arm64e @@ -56,7 +56,7 @@ extension DyldChainedFixupPointer { } } -extension DyldChainedFixupPointer { +extension DyldChainedFixupPointerInfo { public enum ContentType { case bind case rebase @@ -64,7 +64,7 @@ extension DyldChainedFixupPointer { } public protocol DyldChainedFixupPointerContent { - var type: DyldChainedFixupPointer.ContentType { get } + var type: DyldChainedFixupPointerInfo.ContentType { get } var next: Int { get } } @@ -73,7 +73,7 @@ extension DyldChainedFixupPointerContent { public var isRebase: Bool { type == .rebase } } -extension DyldChainedFixupPointer { +extension DyldChainedFixupPointerInfo { public enum ARM64E: DyldChainedFixupPointerContent { case rebase(DyldChainedPtrArm64eRebase) case bind(DyldChainedPtrArm64eBind) @@ -89,7 +89,7 @@ extension DyldChainedFixupPointer { } } - public var type: DyldChainedFixupPointer.ContentType { + public var type: DyldChainedFixupPointerInfo.ContentType { switch self { case .rebase: .rebase case .bind: .bind @@ -123,7 +123,7 @@ extension DyldChainedFixupPointer { } } - public var type: DyldChainedFixupPointer.ContentType { + public var type: DyldChainedFixupPointerInfo.ContentType { switch self { case .rebase: .rebase case .bind: .bind @@ -151,7 +151,7 @@ extension DyldChainedFixupPointer { } } - public var type: DyldChainedFixupPointer.ContentType { + public var type: DyldChainedFixupPointerInfo.ContentType { switch self { case .rebase: .rebase } @@ -173,7 +173,7 @@ extension DyldChainedFixupPointer { } } - public var type: DyldChainedFixupPointer.ContentType { + public var type: DyldChainedFixupPointerInfo.ContentType { switch self { case .rebase: .rebase case .bind: .bind @@ -201,7 +201,7 @@ extension DyldChainedFixupPointer { } } - public var type: DyldChainedFixupPointer.ContentType { + public var type: DyldChainedFixupPointerInfo.ContentType { switch self { case .rebase: .rebase } @@ -221,7 +221,7 @@ extension DyldChainedFixupPointer { } } - public var type: DyldChainedFixupPointer.ContentType { + public var type: DyldChainedFixupPointerInfo.ContentType { switch self { case .rebase: .rebase } From 8284104eb7c3270244a19f71a131d4da3c0deb6b Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:34:17 +0900 Subject: [PATCH 12/25] add `DyldChainedFixupPointer` --- .../Model/DyldChain/DyldChainedFixupPointer.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift new file mode 100644 index 0000000..2a9d331 --- /dev/null +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointer.swift @@ -0,0 +1,14 @@ +// +// DyldChainedFixupPointer.swift +// +// +// Created by p-x9 on 2024/02/19. +// +// + +import Foundation + +public struct DyldChainedFixupPointer { + public let offset: Int + public let fixupInfo: DyldChainedFixupPointerInfo +} From 27f164cdb6de515adeac179df912d7fdd3cf0e4c Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:38:09 +0900 Subject: [PATCH 13/25] add some convenient accessor to `DyldChainedFixupPointerInfo` --- .../DyldChainedFixupPointerInfo.swift | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift index 8fa7a0d..84e3dba 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift @@ -56,6 +56,42 @@ extension DyldChainedFixupPointerInfo { } } +extension DyldChainedFixupPointerInfo { + public var next: Int { + switch self { + case let .arm64e(info): info.next + case let ._64(info): info.next + case let ._32(info): info.next + case let ._32_cache(info): info.next + case let ._32_firmware(info): info.next + case let ._64_offset(info): info.next + case let .arm64e_kernel(info): info.next + case let ._64_kernel_cache(info): info.next + case let .arm64e_userland(info): info.next + case let .arm64e_firmware(info): info.next + case let .x86_64_kernel_cache(info): info.next + case let .arm64e_userland24(info): info.next + } + } + + public var type: ContentType { + switch self { + case let .arm64e(info): info.type + case let ._64(info): info.type + case let ._32(info): info.type + case let ._32_cache(info): info.type + case let ._32_firmware(info): info.type + case let ._64_offset(info): info.type + case let .arm64e_kernel(info): info.type + case let ._64_kernel_cache(info): info.type + case let .arm64e_userland(info): info.type + case let .arm64e_firmware(info): info.type + case let .x86_64_kernel_cache(info): info.type + case let .arm64e_userland24(info): info.type + } + } +} + extension DyldChainedFixupPointerInfo { public enum ContentType { case bind From 1d0e235c4a0bd598823f6c31babaddb5065a46bd Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Mon, 19 Feb 2024 17:25:02 +0900 Subject: [PATCH 14/25] implemented fixup pointers parser --- .../MachOFile+DyldChainedFixups.swift | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/Sources/MachOKit/MachOFile+DyldChainedFixups.swift b/Sources/MachOKit/MachOFile+DyldChainedFixups.swift index c3c4d81..175a89b 100644 --- a/Sources/MachOKit/MachOFile+DyldChainedFixups.swift +++ b/Sources/MachOKit/MachOFile+DyldChainedFixups.swift @@ -167,3 +167,145 @@ extension MachOFile.DyldChainedFixups: DyldChainedFixupsProtocol { } } } + +extension MachOFile.DyldChainedFixups { + // https://github.com/apple-oss-distributions/dyld/blob/d1a0f6869ece370913a3f749617e457f3b4cd7c4/common/MachOLoaded.cpp#L884 + public func pointers( + of startsInSegment: DyldChainedStartsInSegment, + in machO: MachOFile + ) -> [DyldChainedFixupPointer] { + let pages = pages(of: startsInSegment) + + let pagesData = machO.fileHandle.readData( + offset: numericCast(machO.headerStartOffset) + startsInSegment.segment_offset, + size: pages.count * numericCast(startsInSegment.page_size) + ) + + var pointers: [DyldChainedFixupPointer] = [] + + for (index, page) in pages.enumerated() { + var offsetInPage = page.offset + + if page.isNone { continue } + if page.isMulti { + var overflowIndex = Int(offsetInPage & ~UInt16(DYLD_CHAINED_PTR_START_MULTI)) + var chainEnd = false + while !chainEnd { + chainEnd = pages[overflowIndex].offset & UInt16(DYLD_CHAINED_PTR_START_LAST) != 0 + offsetInPage = pages[overflowIndex].offset & ~UInt16(DYLD_CHAINED_PTR_START_LAST) + let pageContentStart: Int = index * numericCast(startsInSegment.page_size) + let chainOffset = pageContentStart + numericCast(offsetInPage) + walkChain(offset: chainOffset, data: pagesData, of: startsInSegment, in: machO, pointers: &pointers) + overflowIndex += 1 + } + } else { + let pageContentStart: Int = index * numericCast(startsInSegment.page_size) + let chainOffset = pageContentStart + numericCast(offsetInPage) + walkChain(offset: chainOffset, data: pagesData, of: startsInSegment, in: machO, pointers: &pointers) + } + } + + return pointers + } + + private func walkChain( + offset: Int, + data: Data, + of startsInSegment: DyldChainedStartsInSegment, + in machO: MachOFile, + pointers: inout [DyldChainedFixupPointer] + ) { + guard let pointerFormat = startsInSegment.pointerFormat else { + return + } + var offset = offset + + let stride = pointerFormat.stride + var stop = false + var chainEnd = false + + while !stop && !chainEnd { + data.withUnsafeBytes { + guard let baseAddress = $0.baseAddress else { return } + let ptr = baseAddress.advanced(by: offset) + + var fixupInfo: DyldChainedFixupPointerInfo? + + if pointerFormat.is64Bit { + let rawValue = ptr.load(as: UInt64.self) + switch pointerFormat { + case .arm64e, .arm64e_kernel, .arm64e_userland, .arm64e_firmware, .arm64e_userland24: + let content = DyldChainedFixupPointerInfo.ARM64E(rawValue: rawValue) + switch pointerFormat { + case .arm64e: + fixupInfo = .arm64e(content) + case .arm64e_kernel: + fixupInfo = .arm64e_kernel(content) + case .arm64e_userland: + fixupInfo = .arm64e_userland(content) + case .arm64e_firmware: + fixupInfo = .arm64e_firmware(content) + case .arm64e_userland24: + fixupInfo = .arm64e_userland24(content) + default: break + } + + case ._64, ._64_offset: + let content = DyldChainedFixupPointerInfo.General64(rawValue: rawValue) + switch pointerFormat { + case ._64: fixupInfo = ._64(content) + case ._64_offset: fixupInfo = ._64_offset(content) + default: break + } + + case ._64_kernel_cache, .x86_64_kernel_cache: + let content = DyldChainedFixupPointerInfo.General64Cache(rawValue: rawValue) + switch pointerFormat { + case ._64_kernel_cache: + fixupInfo = ._64_kernel_cache(content) + case .x86_64_kernel_cache: + fixupInfo = .x86_64_kernel_cache(content) + default: break + } + + default: + // unknown format + stop = true + } + + + } else { + let rawValue = ptr.load(as: UInt32.self) + switch pointerFormat { + case ._32: + let content = DyldChainedFixupPointerInfo.General32(rawValue: rawValue) + fixupInfo = ._32(content) + case ._32_cache: + let content = DyldChainedFixupPointerInfo.General32Cache(rawValue: rawValue) + fixupInfo = ._32_cache(content) + case ._32_firmware: + let content = DyldChainedFixupPointerInfo.General32Firmware(rawValue: rawValue) + fixupInfo = ._32_firmware(content) + default: + // unknown format + stop = true + } + } + + if let fixupInfo { + let pointerOffset = numericCast(startsInSegment.segment_offset) + offset + + pointers.append( + DyldChainedFixupPointer( + offset: pointerOffset, + fixupInfo: fixupInfo + ) + ) + + if fixupInfo.next == 0 { chainEnd = true } + else { offset += stride * fixupInfo.next } + } + } + } + } +} From 91c17ca198b077c023997454c75d094d7bc1219c Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Mon, 19 Feb 2024 17:47:19 +0900 Subject: [PATCH 15/25] demangled symbol name --- .../MachOKit/Protocol/DyldChainedFixupsProtocol.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Sources/MachOKit/Protocol/DyldChainedFixupsProtocol.swift b/Sources/MachOKit/Protocol/DyldChainedFixupsProtocol.swift index f462595..5d0c9b7 100644 --- a/Sources/MachOKit/Protocol/DyldChainedFixupsProtocol.swift +++ b/Sources/MachOKit/Protocol/DyldChainedFixupsProtocol.swift @@ -22,4 +22,14 @@ public protocol DyldChainedFixupsProtocol { ) -> [DyldChainedPage] func symbolName(for nameOffset: Int) -> String? + func demangledSymbolName(for nameOffset: Int) -> String? +} + +extension DyldChainedFixupsProtocol { + public func demangledSymbolName(for nameOffset: Int) -> String? { + guard let symbolName = symbolName(for: nameOffset) else { + return nil + } + return stdlib_demangleName(symbolName) + } } From 9d1446c2034b3cc6d2c2dadb4cda695eccfd3e46 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Tue, 20 Feb 2024 13:46:29 +0900 Subject: [PATCH 16/25] conform to CustomStringConvertible --- .../Extension/dyld_chained_ptr+.swift | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 Sources/MachOKit/Extension/dyld_chained_ptr+.swift diff --git a/Sources/MachOKit/Extension/dyld_chained_ptr+.swift b/Sources/MachOKit/Extension/dyld_chained_ptr+.swift new file mode 100644 index 0000000..6e58fae --- /dev/null +++ b/Sources/MachOKit/Extension/dyld_chained_ptr+.swift @@ -0,0 +1,76 @@ +// +// dyld_chained_ptr+.swift +// +// +// Created by p-x9 on 2024/02/19. +// +// + +import Foundation +import MachOKitC + +extension dyld_chained_ptr_arm64e_rebase: CustomStringConvertible { + public var description: String { + "dyld_chained_ptr_arm64e_rebase(target: \(target), high8: \(high8), next: \(next), bind: \(bind), auth: \(auth))" + } +} + +extension dyld_chained_ptr_arm64e_bind: CustomStringConvertible { + public var description: String { + "dyld_chained_ptr_arm64e_bind(ordinal: \(ordinal), zero: \(zero), addend: \(addend), next: \(next), bind: \(bind), auth: \(auth))" + } +} + +extension dyld_chained_ptr_arm64e_auth_rebase: CustomStringConvertible { + public var description: String { + "dyld_chained_ptr_arm64e_auth_rebase(target: \(target), diversity: \(diversity), addrDiv: \(addrDiv), key: \(key), next: \(next), bind: \(bind), auth: \(auth))" + } +} + +extension dyld_chained_ptr_arm64e_auth_bind: CustomStringConvertible { + public var description: String { + "dyld_chained_ptr_arm64e_auth_bind(ordinal: \(ordinal), zero: \(zero), diversity: \(diversity), addrDiv: \(addrDiv), key: \(key), next: \(next), bind: \(bind), auth: \(auth))" + } +} + +extension dyld_chained_ptr_64_rebase: CustomStringConvertible { + public var description: String { + "dyld_chained_ptr_64_rebase(target: \(target), high8: \(high8), reserved: \(reserved), next: \(next), bind: \(bind))" + } +} + +extension dyld_chained_ptr_64_bind: CustomStringConvertible { + public var description: String { + "dyld_chained_ptr_64_bind(ordinal: \(ordinal), addend: \(addend), reserved: \(reserved), next: \(next), bind: \(bind))" + } +} + +extension dyld_chained_ptr_64_kernel_cache_rebase: CustomStringConvertible { + public var description: String { + "dyld_chained_ptr_64_kernel_cache_rebase(target: \(target), cacheLevel: \(cacheLevel), diversity: \(diversity), addrDiv: \(addrDiv), key: \(key), next: \(next), isAuth: \(isAuth))" + } +} + +extension dyld_chained_ptr_32_rebase: CustomStringConvertible { + public var description: String { + "dyld_chained_ptr_32_rebase(target: \(target), next: \(next), bind: \(bind))" + } +} + +extension dyld_chained_ptr_32_bind: CustomStringConvertible { + public var description: String { + "dyld_chained_ptr_32_bind(ordinal: \(ordinal), addend: \(addend), next: \(next), bind: \(bind))" + } +} + +extension dyld_chained_ptr_32_cache_rebase: CustomStringConvertible { + public var description: String { + "dyld_chained_ptr_32_cache_rebase(target: \(target), next: \(next))" + } +} + +extension dyld_chained_ptr_32_firmware_rebase: CustomStringConvertible { + public var description: String { + "dyld_chained_ptr_32_firmware_rebase(target: \(target), next: \(next))" + } +} From 4117194b9070fe2c8a6cd895d1a3b43a93e2e7bf Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Tue, 20 Feb 2024 17:59:42 +0900 Subject: [PATCH 17/25] add `rebase` and `bind` to `DyldChainedFixupPointerContent` protocol --- .../DyldChainedFixupPointerInfo.swift | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift index 84e3dba..df636a2 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift @@ -90,6 +90,40 @@ extension DyldChainedFixupPointerInfo { case let .arm64e_userland24(info): info.type } } + + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .arm64e(info): info.rebase + case let ._64(info): info.rebase + case let ._32(info): info.rebase + case let ._32_cache(info): info.rebase + case let ._32_firmware(info): info.rebase + case let ._64_offset(info): info.rebase + case let .arm64e_kernel(info): info.rebase + case let ._64_kernel_cache(info): info.rebase + case let .arm64e_userland(info): info.rebase + case let .arm64e_firmware(info): info.rebase + case let .x86_64_kernel_cache(info): info.rebase + case let .arm64e_userland24(info): info.rebase + } + } + + public var bind: (any DyldChainedPointerContentBind)? { + switch self { + case let .arm64e(info): info.bind + case let ._64(info): info.bind + case let ._32(info): info.bind + case let ._32_cache(info): info.bind + case let ._32_firmware(info): info.bind + case let ._64_offset(info): info.bind + case let .arm64e_kernel(info): info.bind + case let ._64_kernel_cache(info): info.bind + case let .arm64e_userland(info): info.bind + case let .arm64e_firmware(info): info.bind + case let .x86_64_kernel_cache(info): info.bind + case let .arm64e_userland24(info): info.bind + } + } } extension DyldChainedFixupPointerInfo { @@ -102,6 +136,9 @@ extension DyldChainedFixupPointerInfo { public protocol DyldChainedFixupPointerContent { var type: DyldChainedFixupPointerInfo.ContentType { get } var next: Int { get } + + var rebase: (any DyldChainedPointerContentRebase)? { get } + var bind: (any DyldChainedPointerContentBind)? { get } } extension DyldChainedFixupPointerContent { @@ -134,6 +171,22 @@ extension DyldChainedFixupPointerInfo { } } + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .rebase(info): info + case let .authRebase(info): info + default: nil + } + } + + public var bind: (any DyldChainedPointerContentBind)? { + switch self { + case let .bind(info): info + case let .authBind(info): info + default: nil + } + } + init(rawValue: UInt64) { let tmp = DyldChainedPtrArm64eRebase(layout: autoBitCast(rawValue)) let isBind = tmp.layout.bind == 1 @@ -166,6 +219,20 @@ extension DyldChainedFixupPointerInfo { } } + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .rebase(info): info + default: nil + } + } + + public var bind: (any DyldChainedPointerContentBind)? { + switch self { + case let .bind(info): info + default: nil + } + } + init(rawValue: UInt64) { let tmp = DyldChainedPtr64Rebase(layout: autoBitCast(rawValue)) let isBind = tmp.layout.bind == 1 @@ -193,6 +260,14 @@ extension DyldChainedFixupPointerInfo { } } + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .rebase(info): info + } + } + + public var bind: (any DyldChainedPointerContentBind)? { nil } + init(rawValue: UInt64) { self = .rebase(autoBitCast(rawValue)) } @@ -216,6 +291,20 @@ extension DyldChainedFixupPointerInfo { } } + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .rebase(info): info + default: nil + } + } + + public var bind: (any DyldChainedPointerContentBind)? { + switch self { + case let .bind(info): info + default: nil + } + } + init(rawValue: UInt32) { let tmp = DyldChainedPtr32Rebase(layout: autoBitCast(rawValue)) let isBind = tmp.layout.bind == 1 @@ -243,6 +332,14 @@ extension DyldChainedFixupPointerInfo { } } + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .rebase(info): info + } + } + + public var bind: (any DyldChainedPointerContentBind)? { nil } + init(rawValue: UInt32) { self = .rebase(autoBitCast(rawValue)) } @@ -263,6 +360,14 @@ extension DyldChainedFixupPointerInfo { } } + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .rebase(info): info + } + } + + public var bind: (any DyldChainedPointerContentBind)? { nil } + init(rawValue: UInt32) { self = .rebase(autoBitCast(rawValue)) } From c7f20574907cb4174b303cf4bcab9e0f7307b75a Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Tue, 20 Feb 2024 18:06:48 +0900 Subject: [PATCH 18/25] refactor --- .../DyldChainedFixupPointerContent.swift | 417 ++++++++++++++++++ .../DyldChainedFixupPointerInfo.swift | 406 ----------------- 2 files changed, 417 insertions(+), 406 deletions(-) create mode 100644 Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerContent.swift diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerContent.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerContent.swift new file mode 100644 index 0000000..9ee7790 --- /dev/null +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerContent.swift @@ -0,0 +1,417 @@ +// +// DyldChainedFixupPointerContent.swift +// +// +// Created by p-x9 on 2024/02/20. +// +// + +import Foundation + +public protocol DyldChainedFixupPointerContent { + var type: DyldChainedFixupPointerInfo.ContentType { get } + var next: Int { get } + + var rebase: (any DyldChainedPointerContentRebase)? { get } + var bind: (any DyldChainedPointerContentBind)? { get } +} + +extension DyldChainedFixupPointerContent { + public var isBind: Bool { type == .bind } + public var isRebase: Bool { type == .rebase } +} + +extension DyldChainedFixupPointerInfo { + public enum ARM64E: DyldChainedFixupPointerContent { + case rebase(DyldChainedPtrArm64eRebase) + case bind(DyldChainedPtrArm64eBind) + case authRebase(DyldChainedPtrArm64eAuthRebase) + case authBind(DyldChainedPtrArm64eAuthBind) + + public var next: Int { + switch self { + case let .rebase(info): info.next + case let .bind(info): info.next + case let .authRebase(info): info.next + case let .authBind(info): info.next + } + } + + public var type: DyldChainedFixupPointerInfo.ContentType { + switch self { + case .rebase: .rebase + case .bind: .bind + case .authRebase: .rebase + case .authBind: .bind + } + } + + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .rebase(info): info + case let .authRebase(info): info + default: nil + } + } + + public var bind: (any DyldChainedPointerContentBind)? { + switch self { + case let .bind(info): info + case let .authBind(info): info + default: nil + } + } + + init(rawValue: UInt64) { + let tmp = DyldChainedPtrArm64eRebase(layout: autoBitCast(rawValue)) + let isBind = tmp.layout.bind == 1 + let isAuth = tmp.layout.auth == 1 + + switch (isBind, isAuth) { + case (true, false): self = .bind(autoBitCast(rawValue)) + case (false, false): self = .rebase(autoBitCast(rawValue)) + case (true, true): self = .authBind(autoBitCast(rawValue)) + case (false, true): self = .authRebase(autoBitCast(rawValue)) + } + } + } + + public enum General64: DyldChainedFixupPointerContent { + case rebase(DyldChainedPtr64Rebase) + case bind(DyldChainedPtr64Bind) + + public var next: Int { + switch self { + case let .rebase(info): info.next + case let .bind(info): info.next + } + } + + public var type: DyldChainedFixupPointerInfo.ContentType { + switch self { + case .rebase: .rebase + case .bind: .bind + } + } + + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .rebase(info): info + default: nil + } + } + + public var bind: (any DyldChainedPointerContentBind)? { + switch self { + case let .bind(info): info + default: nil + } + } + + init(rawValue: UInt64) { + let tmp = DyldChainedPtr64Rebase(layout: autoBitCast(rawValue)) + let isBind = tmp.layout.bind == 1 + + if isBind { + self = .bind(autoBitCast(rawValue)) + } else { + self = .rebase(autoBitCast(rawValue)) + } + } + } + + public enum General64Cache: DyldChainedFixupPointerContent { + case rebase(DyldChainedPtr64KernelCacheRebase) + + public var next: Int { + switch self { + case let .rebase(info): info.next + } + } + + public var type: DyldChainedFixupPointerInfo.ContentType { + switch self { + case .rebase: .rebase + } + } + + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .rebase(info): info + } + } + + public var bind: (any DyldChainedPointerContentBind)? { nil } + + init(rawValue: UInt64) { + self = .rebase(autoBitCast(rawValue)) + } + } + + public enum General32: DyldChainedFixupPointerContent { + case rebase(DyldChainedPtr32Rebase) + case bind(DyldChainedPtr32Bind) + + public var next: Int { + switch self { + case let .rebase(info): info.next + case let .bind(info): info.next + } + } + + public var type: DyldChainedFixupPointerInfo.ContentType { + switch self { + case .rebase: .rebase + case .bind: .bind + } + } + + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .rebase(info): info + default: nil + } + } + + public var bind: (any DyldChainedPointerContentBind)? { + switch self { + case let .bind(info): info + default: nil + } + } + + init(rawValue: UInt32) { + let tmp = DyldChainedPtr32Rebase(layout: autoBitCast(rawValue)) + let isBind = tmp.layout.bind == 1 + + if isBind { + self = .bind(autoBitCast(rawValue)) + } else { + self = .rebase(autoBitCast(rawValue)) + } + } + } + + public enum General32Cache: DyldChainedFixupPointerContent { + case rebase(DyldChainedPtr32CacheRebase) + + public var next: Int { + switch self { + case let .rebase(info): info.next + } + } + + public var type: DyldChainedFixupPointerInfo.ContentType { + switch self { + case .rebase: .rebase + } + } + + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .rebase(info): info + } + } + + public var bind: (any DyldChainedPointerContentBind)? { nil } + + init(rawValue: UInt32) { + self = .rebase(autoBitCast(rawValue)) + } + } + + public enum General32Firmware: DyldChainedFixupPointerContent { + case rebase(DyldChainedPtr32FirmwareRebase) + + public var next: Int { + switch self { + case let .rebase(info): info.next + } + } + + public var type: DyldChainedFixupPointerInfo.ContentType { + switch self { + case .rebase: .rebase + } + } + + public var rebase: (any DyldChainedPointerContentRebase)? { + switch self { + case let .rebase(info): info + } + } + + public var bind: (any DyldChainedPointerContentBind)? { nil } + + init(rawValue: UInt32) { + self = .rebase(autoBitCast(rawValue)) + } + } +} + +// MARK: - Rebase & Bind Layout + +public protocol DyldChainedPointerContentRebase: LayoutWrapper { + var target: Int { get } + var next: Int { get } +} + +public protocol DyldChainedPointerContentBind: LayoutWrapper { + var ordinal: Int { get } + var next: Int { get } +} + +public struct DyldChainedPtrArm64eRebase: DyldChainedPointerContentRebase { + public typealias Layout = dyld_chained_ptr_arm64e_rebase + public var layout: Layout + + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } +} + +public struct DyldChainedPtrArm64eBind: DyldChainedPointerContentBind { + public typealias Layout = dyld_chained_ptr_arm64e_bind + public var layout: Layout + + public var ordinal: Int { + numericCast(layout.ordinal) + } + + public var next: Int { + numericCast(layout.next) + } +} + +public struct DyldChainedPtrArm64eAuthRebase: DyldChainedPointerContentRebase { + public typealias Layout = dyld_chained_ptr_arm64e_auth_rebase + public var layout: Layout + + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } + + public var keyName: String { + ["IA", "IB", "DA", "DB"][Int(layout.key)] + } +} + +public struct DyldChainedPtrArm64eAuthBind: DyldChainedPointerContentBind { + public typealias Layout = dyld_chained_ptr_arm64e_auth_bind + public var layout: Layout + + public var ordinal: Int { + numericCast(layout.ordinal) + } + + public var next: Int { + numericCast(layout.next) + } + + public var keyName: String { + ["IA", "IB", "DA", "DB"][Int(layout.key)] + } +} + +public struct DyldChainedPtr64Rebase: DyldChainedPointerContentRebase { + public typealias Layout = dyld_chained_ptr_64_rebase + public var layout: Layout + + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } +} + +public struct DyldChainedPtr64Bind: DyldChainedPointerContentBind { + public typealias Layout = dyld_chained_ptr_64_bind + public var layout: Layout + + public var ordinal: Int { + numericCast(layout.ordinal) + } + + public var next: Int { + numericCast(layout.next) + } +} + +public struct DyldChainedPtr64KernelCacheRebase: DyldChainedPointerContentRebase { + public typealias Layout = dyld_chained_ptr_64_kernel_cache_rebase + public var layout: Layout + + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } + + public var keyName: String { + ["IA", "IB", "DA", "DB"][Int(layout.key)] + } +} + +public struct DyldChainedPtr32Rebase: DyldChainedPointerContentRebase { + public typealias Layout = dyld_chained_ptr_32_rebase + public var layout: Layout + + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } +} + +public struct DyldChainedPtr32Bind: DyldChainedPointerContentBind { + public typealias Layout = dyld_chained_ptr_32_bind + public var layout: Layout + + public var ordinal: Int { + numericCast(layout.ordinal) + } + + public var next: Int { + numericCast(layout.next) + } +} + +public struct DyldChainedPtr32CacheRebase: DyldChainedPointerContentRebase { + public typealias Layout = dyld_chained_ptr_32_cache_rebase + public var layout: Layout + + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } +} + +public struct DyldChainedPtr32FirmwareRebase: DyldChainedPointerContentRebase { + public typealias Layout = dyld_chained_ptr_32_firmware_rebase + public var layout: Layout + + public var target: Int { + numericCast(layout.target) + } + + public var next: Int { + numericCast(layout.next) + } +} diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift index df636a2..d62e5e5 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift @@ -132,409 +132,3 @@ extension DyldChainedFixupPointerInfo { case rebase } } - -public protocol DyldChainedFixupPointerContent { - var type: DyldChainedFixupPointerInfo.ContentType { get } - var next: Int { get } - - var rebase: (any DyldChainedPointerContentRebase)? { get } - var bind: (any DyldChainedPointerContentBind)? { get } -} - -extension DyldChainedFixupPointerContent { - public var isBind: Bool { type == .bind } - public var isRebase: Bool { type == .rebase } -} - -extension DyldChainedFixupPointerInfo { - public enum ARM64E: DyldChainedFixupPointerContent { - case rebase(DyldChainedPtrArm64eRebase) - case bind(DyldChainedPtrArm64eBind) - case authRebase(DyldChainedPtrArm64eAuthRebase) - case authBind(DyldChainedPtrArm64eAuthBind) - - public var next: Int { - switch self { - case let .rebase(info): info.next - case let .bind(info): info.next - case let .authRebase(info): info.next - case let .authBind(info): info.next - } - } - - public var type: DyldChainedFixupPointerInfo.ContentType { - switch self { - case .rebase: .rebase - case .bind: .bind - case .authRebase: .rebase - case .authBind: .bind - } - } - - public var rebase: (any DyldChainedPointerContentRebase)? { - switch self { - case let .rebase(info): info - case let .authRebase(info): info - default: nil - } - } - - public var bind: (any DyldChainedPointerContentBind)? { - switch self { - case let .bind(info): info - case let .authBind(info): info - default: nil - } - } - - init(rawValue: UInt64) { - let tmp = DyldChainedPtrArm64eRebase(layout: autoBitCast(rawValue)) - let isBind = tmp.layout.bind == 1 - let isAuth = tmp.layout.auth == 1 - - switch (isBind, isAuth) { - case (true, false): self = .bind(autoBitCast(rawValue)) - case (false, false): self = .rebase(autoBitCast(rawValue)) - case (true, true): self = .authBind(autoBitCast(rawValue)) - case (false, true): self = .authRebase(autoBitCast(rawValue)) - } - } - } - - public enum General64: DyldChainedFixupPointerContent { - case rebase(DyldChainedPtr64Rebase) - case bind(DyldChainedPtr64Bind) - - public var next: Int { - switch self { - case let .rebase(info): info.next - case let .bind(info): info.next - } - } - - public var type: DyldChainedFixupPointerInfo.ContentType { - switch self { - case .rebase: .rebase - case .bind: .bind - } - } - - public var rebase: (any DyldChainedPointerContentRebase)? { - switch self { - case let .rebase(info): info - default: nil - } - } - - public var bind: (any DyldChainedPointerContentBind)? { - switch self { - case let .bind(info): info - default: nil - } - } - - init(rawValue: UInt64) { - let tmp = DyldChainedPtr64Rebase(layout: autoBitCast(rawValue)) - let isBind = tmp.layout.bind == 1 - - if isBind { - self = .bind(autoBitCast(rawValue)) - } else { - self = .rebase(autoBitCast(rawValue)) - } - } - } - - public enum General64Cache: DyldChainedFixupPointerContent { - case rebase(DyldChainedPtr64KernelCacheRebase) - - public var next: Int { - switch self { - case let .rebase(info): info.next - } - } - - public var type: DyldChainedFixupPointerInfo.ContentType { - switch self { - case .rebase: .rebase - } - } - - public var rebase: (any DyldChainedPointerContentRebase)? { - switch self { - case let .rebase(info): info - } - } - - public var bind: (any DyldChainedPointerContentBind)? { nil } - - init(rawValue: UInt64) { - self = .rebase(autoBitCast(rawValue)) - } - } - - public enum General32: DyldChainedFixupPointerContent { - case rebase(DyldChainedPtr32Rebase) - case bind(DyldChainedPtr32Bind) - - public var next: Int { - switch self { - case let .rebase(info): info.next - case let .bind(info): info.next - } - } - - public var type: DyldChainedFixupPointerInfo.ContentType { - switch self { - case .rebase: .rebase - case .bind: .bind - } - } - - public var rebase: (any DyldChainedPointerContentRebase)? { - switch self { - case let .rebase(info): info - default: nil - } - } - - public var bind: (any DyldChainedPointerContentBind)? { - switch self { - case let .bind(info): info - default: nil - } - } - - init(rawValue: UInt32) { - let tmp = DyldChainedPtr32Rebase(layout: autoBitCast(rawValue)) - let isBind = tmp.layout.bind == 1 - - if isBind { - self = .bind(autoBitCast(rawValue)) - } else { - self = .rebase(autoBitCast(rawValue)) - } - } - } - - public enum General32Cache: DyldChainedFixupPointerContent { - case rebase(DyldChainedPtr32CacheRebase) - - public var next: Int { - switch self { - case let .rebase(info): info.next - } - } - - public var type: DyldChainedFixupPointerInfo.ContentType { - switch self { - case .rebase: .rebase - } - } - - public var rebase: (any DyldChainedPointerContentRebase)? { - switch self { - case let .rebase(info): info - } - } - - public var bind: (any DyldChainedPointerContentBind)? { nil } - - init(rawValue: UInt32) { - self = .rebase(autoBitCast(rawValue)) - } - } - - public enum General32Firmware: DyldChainedFixupPointerContent { - case rebase(DyldChainedPtr32FirmwareRebase) - - public var next: Int { - switch self { - case let .rebase(info): info.next - } - } - - public var type: DyldChainedFixupPointerInfo.ContentType { - switch self { - case .rebase: .rebase - } - } - - public var rebase: (any DyldChainedPointerContentRebase)? { - switch self { - case let .rebase(info): info - } - } - - public var bind: (any DyldChainedPointerContentBind)? { nil } - - init(rawValue: UInt32) { - self = .rebase(autoBitCast(rawValue)) - } - } -} - -public protocol DyldChainedPointerContentRebase: LayoutWrapper { - var target: Int { get } - var next: Int { get } -} - -public protocol DyldChainedPointerContentBind: LayoutWrapper { - var ordinal: Int { get } - var next: Int { get } -} - -public struct DyldChainedPtrArm64eRebase: DyldChainedPointerContentRebase { - public typealias Layout = dyld_chained_ptr_arm64e_rebase - public var layout: Layout - - public var target: Int { - numericCast(layout.target) - } - - public var next: Int { - numericCast(layout.next) - } -} - -public struct DyldChainedPtrArm64eBind: DyldChainedPointerContentBind { - public typealias Layout = dyld_chained_ptr_arm64e_bind - public var layout: Layout - - public var ordinal: Int { - numericCast(layout.ordinal) - } - - public var next: Int { - numericCast(layout.next) - } -} - -public struct DyldChainedPtrArm64eAuthRebase: DyldChainedPointerContentRebase { - public typealias Layout = dyld_chained_ptr_arm64e_auth_rebase - public var layout: Layout - - public var target: Int { - numericCast(layout.target) - } - - public var next: Int { - numericCast(layout.next) - } - - public var keyName: String { - ["IA", "IB", "DA", "DB"][Int(layout.key)] - } -} - -public struct DyldChainedPtrArm64eAuthBind: DyldChainedPointerContentBind { - public typealias Layout = dyld_chained_ptr_arm64e_auth_bind - public var layout: Layout - - public var ordinal: Int { - numericCast(layout.ordinal) - } - - public var next: Int { - numericCast(layout.next) - } - - public var keyName: String { - ["IA", "IB", "DA", "DB"][Int(layout.key)] - } -} - -public struct DyldChainedPtr64Rebase: DyldChainedPointerContentRebase { - public typealias Layout = dyld_chained_ptr_64_rebase - public var layout: Layout - - public var target: Int { - numericCast(layout.target) - } - - public var next: Int { - numericCast(layout.next) - } -} - -public struct DyldChainedPtr64Bind: DyldChainedPointerContentBind { - public typealias Layout = dyld_chained_ptr_64_bind - public var layout: Layout - - public var ordinal: Int { - numericCast(layout.ordinal) - } - - public var next: Int { - numericCast(layout.next) - } -} - -public struct DyldChainedPtr64KernelCacheRebase: DyldChainedPointerContentRebase { - public typealias Layout = dyld_chained_ptr_64_kernel_cache_rebase - public var layout: Layout - - public var target: Int { - numericCast(layout.target) - } - - public var next: Int { - numericCast(layout.next) - } - - public var keyName: String { - ["IA", "IB", "DA", "DB"][Int(layout.key)] - } -} - -public struct DyldChainedPtr32Rebase: DyldChainedPointerContentRebase { - public typealias Layout = dyld_chained_ptr_32_rebase - public var layout: Layout - - public var target: Int { - numericCast(layout.target) - } - - public var next: Int { - numericCast(layout.next) - } -} - -public struct DyldChainedPtr32Bind: DyldChainedPointerContentBind { - public typealias Layout = dyld_chained_ptr_32_bind - public var layout: Layout - - public var ordinal: Int { - numericCast(layout.ordinal) - } - - public var next: Int { - numericCast(layout.next) - } -} - -public struct DyldChainedPtr32CacheRebase: DyldChainedPointerContentRebase { - public typealias Layout = dyld_chained_ptr_32_cache_rebase - public var layout: Layout - - public var target: Int { - numericCast(layout.target) - } - - public var next: Int { - numericCast(layout.next) - } -} - -public struct DyldChainedPtr32FirmwareRebase: DyldChainedPointerContentRebase { - public typealias Layout = dyld_chained_ptr_32_firmware_rebase - public var layout: Layout - - public var target: Int { - numericCast(layout.target) - } - - public var next: Int { - numericCast(layout.next) - } -} From 736bc65b837a3329b1dd99cdb2adf91259ba3aac Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Tue, 20 Feb 2024 18:09:05 +0900 Subject: [PATCH 19/25] rename `DyldChainedPointerFormat` -> `DyldChainedFixupPointerFormat` --- ...mat.swift => DyldChainedFixupPointerFormat.swift} | 12 ++++++------ .../DyldChain/DyldChainedFixupPointerInfo.swift | 2 +- .../Model/DyldChain/DyldChainedStartsInSegment.swift | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) rename Sources/MachOKit/Model/DyldChain/{DyldChainedPointerFormat.swift => DyldChainedFixupPointerFormat.swift} (93%) diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedPointerFormat.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerFormat.swift similarity index 93% rename from Sources/MachOKit/Model/DyldChain/DyldChainedPointerFormat.swift rename to Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerFormat.swift index c30e826..c0e1832 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedPointerFormat.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerFormat.swift @@ -1,5 +1,5 @@ // -// DyldChainedPointerFormat.swift +// DyldChainedFixupPointerFormat.swift // // // Created by p-x9 on 2024/01/11. @@ -8,7 +8,7 @@ import Foundation -public enum DyldChainedPointerFormat { +public enum DyldChainedFixupPointerFormat { /// DYLD_CHAINED_PTR_ARM64E case arm64e /// DYLD_CHAINED_PTR_64 @@ -37,7 +37,7 @@ public enum DyldChainedPointerFormat { case arm64e_userland24 } -extension DyldChainedPointerFormat: CustomStringConvertible { +extension DyldChainedFixupPointerFormat: CustomStringConvertible { public var description: String { switch self { case .arm64e: "DYLD_CHAINED_PTR_ARM64E" @@ -57,7 +57,7 @@ extension DyldChainedPointerFormat: CustomStringConvertible { } } -extension DyldChainedPointerFormat: RawRepresentable { +extension DyldChainedFixupPointerFormat: RawRepresentable { public typealias RawValue = UInt16 public init?(rawValue: RawValue) { @@ -98,7 +98,7 @@ extension DyldChainedPointerFormat: RawRepresentable { } } -extension DyldChainedPointerFormat { +extension DyldChainedFixupPointerFormat { // byte var is64Bit: Bool { switch self { @@ -113,7 +113,7 @@ extension DyldChainedPointerFormat { } } -extension DyldChainedPointerFormat { +extension DyldChainedFixupPointerFormat { // https://github.com/apple-oss-distributions/dyld/blob/d1a0f6869ece370913a3f749617e457f3b4cd7c4/common/MachOLayout.cpp#L2145 var stride: Int { switch self { diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift index d62e5e5..6ace4de 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedFixupPointerInfo.swift @@ -38,7 +38,7 @@ public enum DyldChainedFixupPointerInfo { } extension DyldChainedFixupPointerInfo { - public var pointerFormat: DyldChainedPointerFormat { + public var pointerFormat: DyldChainedFixupPointerFormat { switch self { case .arm64e: .arm64e case ._64: ._64 diff --git a/Sources/MachOKit/Model/DyldChain/DyldChainedStartsInSegment.swift b/Sources/MachOKit/Model/DyldChain/DyldChainedStartsInSegment.swift index d4b38c6..3c62b6c 100644 --- a/Sources/MachOKit/Model/DyldChain/DyldChainedStartsInSegment.swift +++ b/Sources/MachOKit/Model/DyldChain/DyldChainedStartsInSegment.swift @@ -16,7 +16,7 @@ public struct DyldChainedStartsInSegment: LayoutWrapper { public let offset: Int public let segmentIndex: Int - public var pointerFormat: DyldChainedPointerFormat? { + public var pointerFormat: DyldChainedFixupPointerFormat? { .init(rawValue: layout.pointer_format) } } From 78a853ae06318b0cbd295a4e8f71b302ca88e421 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:39:53 +0900 Subject: [PATCH 20/25] add test cases for `DyldChainedFixupPointer` --- Tests/MachOKitTests/MachOFilePrintTests.swift | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Tests/MachOKitTests/MachOFilePrintTests.swift b/Tests/MachOKitTests/MachOFilePrintTests.swift index ca02d6b..51e2f58 100644 --- a/Tests/MachOKitTests/MachOFilePrintTests.swift +++ b/Tests/MachOKitTests/MachOFilePrintTests.swift @@ -533,4 +533,37 @@ extension MachOFilePrintTests { if let name { print("Name:", name) } } } + + func testChainedFixUpPointers() { + guard let chainedFixups = machO.dyldChainedFixups, + let startsInImage = chainedFixups.startsInImage else { + return + } + let segments = machO.segments + + let startsInSegments = chainedFixups.startsInSegments(of: startsInImage) + for (i, startsInSegment) in startsInSegments.enumerated() { + print("----") + let segment = segments[i] + print(segment.segmentName) + + let pointers = chainedFixups.pointers(of: startsInSegment, in: machO) + let imports = chainedFixups.imports + + for pointer in pointers { + let fixupInfo = pointer.fixupInfo + let offset = String(pointer.offset, radix: 16) + + if let rebase = fixupInfo.rebase { + print(offset, "rebase:", String(rebase.target, radix: 16)) + } + if let bind = fixupInfo.bind { + print(offset, "bind :", terminator: " ") + print( + chainedFixups.demangledSymbolName(for: imports[bind.ordinal].info.nameOffset) ?? "" + ) + } + } + } + } } From 1dd4c6c8b5f864dbd5eed5b84255ca811f9514c8 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Wed, 21 Feb 2024 09:32:02 +0900 Subject: [PATCH 21/25] add comments --- Sources/MachOKit/MachOFile+DyldChainedFixups.swift | 3 +++ Tests/MachOKitTests/MachOFilePrintTests.swift | 1 + 2 files changed, 4 insertions(+) diff --git a/Sources/MachOKit/MachOFile+DyldChainedFixups.swift b/Sources/MachOKit/MachOFile+DyldChainedFixups.swift index 175a89b..b4594f4 100644 --- a/Sources/MachOKit/MachOFile+DyldChainedFixups.swift +++ b/Sources/MachOKit/MachOFile+DyldChainedFixups.swift @@ -84,6 +84,7 @@ extension MachOFile.DyldChainedFixups: DyldChainedFixupsProtocol { } } + // xcrun dyld_info -fixup_chains "Path to Binary" public func pages( of startsInSegment: DyldChainedStartsInSegment? ) -> [DyldChainedPage] { @@ -170,6 +171,8 @@ extension MachOFile.DyldChainedFixups: DyldChainedFixupsProtocol { extension MachOFile.DyldChainedFixups { // https://github.com/apple-oss-distributions/dyld/blob/d1a0f6869ece370913a3f749617e457f3b4cd7c4/common/MachOLoaded.cpp#L884 + // xcrun dyld_info -fixup_chain_details "Path to Binary" + // xcrun dyld_info -fixups "Path to Binary" public func pointers( of startsInSegment: DyldChainedStartsInSegment, in machO: MachOFile diff --git a/Tests/MachOKitTests/MachOFilePrintTests.swift b/Tests/MachOKitTests/MachOFilePrintTests.swift index 51e2f58..fbae3b4 100644 --- a/Tests/MachOKitTests/MachOFilePrintTests.swift +++ b/Tests/MachOKitTests/MachOFilePrintTests.swift @@ -534,6 +534,7 @@ extension MachOFilePrintTests { } } + // xcrun dyld_info -fixups /System/Applications/Freeform.app/Contents/MacOS/Freeform func testChainedFixUpPointers() { guard let chainedFixups = machO.dyldChainedFixups, let startsInImage = chainedFixups.startsInImage else { From d71bf0ae9f4ace88aedcabdc8b19dfd5d9a04285 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:20:18 +0900 Subject: [PATCH 22/25] implemented function to get section at the specified offset --- .../MachOKit/LoadCommand/SegmentCommand.swift | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/Sources/MachOKit/LoadCommand/SegmentCommand.swift b/Sources/MachOKit/LoadCommand/SegmentCommand.swift index decc0a8..0919f1a 100644 --- a/Sources/MachOKit/LoadCommand/SegmentCommand.swift +++ b/Sources/MachOKit/LoadCommand/SegmentCommand.swift @@ -208,3 +208,109 @@ extension SegmentCommand64 { ) } } + +extension SegmentCommand { + private func _section( + at offset: UInt, + segmentStart: UInt, + sections: any Sequence
+ ) -> Section? { + sections.first(where: { section in + let sectionStart = UInt(section.layout.offset) + let size = UInt(section.layout.size) + if sectionStart <= segmentStart + offset && + segmentStart + offset < sectionStart + size { + return true + } else { + return false + } + }) + } + + /// Section at the specified offset + /// - Parameters: + /// - offset: offset from start of segment + /// - cmdsStart: pointer at load commands start + /// - Returns: located section + public func section( + at offset: UInt, + cmdsStart: UnsafeRawPointer + ) -> Section? { + let sections = sections(cmdsStart: cmdsStart) + return _section( + at: offset, + segmentStart: UInt(layout.vmaddr), + sections: sections + ) + } + + /// Section at the specified offset + /// - Parameters: + /// - offset: offset from start of segment + /// - machO: machO file + /// - Returns: located section + public func section( + at offset: UInt, + in machO: MachOFile + ) -> Section? { + let sections = sections(in: machO) + return _section( + at: offset, + segmentStart: UInt(layout.fileoff), + sections: sections + ) + } +} + +extension SegmentCommand64 { + private func _section( + at offset: UInt, + segmentStart: UInt, + sections: any Sequence + ) -> Section64? { + sections.first(where: { section in + let sectionStart = UInt(section.layout.offset) + let size = UInt(section.layout.size) + if sectionStart <= segmentStart + offset && + segmentStart + offset < sectionStart + size { + return true + } else { + return false + } + }) + } + + /// Section at the specified offset + /// - Parameters: + /// - offset: offset from start of segment + /// - cmdsStart: pointer at load commands start + /// - Returns: located section + public func section( + at offset: UInt, + cmdsStart: UnsafeRawPointer + ) -> Section64? { + let sections = sections(cmdsStart: cmdsStart) + return _section( + at: offset, + segmentStart: UInt(layout.vmaddr), + sections: sections + ) + } + + /// Section at the specified offset + /// - Parameters: + /// - offset: offset from start of segment + /// - machO: machO file + /// - Returns: located section + public func section( + at offset: UInt, + in machO: MachOFile + ) -> Section64? { + let sections = sections(in: machO) + return _section( + at: offset, + segmentStart: UInt(layout.fileoff), + sections: sections + ) + } +} From b1bbdc6337f6b594d30406de7d7be8b59fb27748 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:20:30 +0900 Subject: [PATCH 23/25] refactor --- Sources/MachOKit/Model/BindingSymbol.swift | 62 ++++------------------ 1 file changed, 10 insertions(+), 52 deletions(-) diff --git a/Sources/MachOKit/Model/BindingSymbol.swift b/Sources/MachOKit/Model/BindingSymbol.swift index f2b3fca..6ea6b22 100644 --- a/Sources/MachOKit/Model/BindingSymbol.swift +++ b/Sources/MachOKit/Model/BindingSymbol.swift @@ -86,70 +86,28 @@ extension BindingSymbol { extension BindingSymbol { public func section64(in machO: MachOImage) -> Section64? { guard let segment = segment64(in: machO) else { return nil } - let sections = segment.sections(cmdsStart: machO.cmdsStartPtr) - - let segmentStart = UInt(segment.vmaddr) - return sections.first(where: { section in - let offset = UInt(section.layout.offset) - let size = UInt(section.layout.size) - if offset <= segmentStart + segmentOffset && - segmentStart + segmentOffset < offset + size { - return true - } else { - return false - } - }) + return segment.section( + at: segmentOffset, + cmdsStart: machO.cmdsStartPtr + ) } public func section32(in machO: MachOImage) -> Section? { guard let segment = segment32(in: machO) else { return nil } - let sections = segment.sections(cmdsStart: machO.cmdsStartPtr) - - let segmentStart = UInt(segment.vmaddr) - return sections.first(where: { section in - let offset = UInt(section.layout.offset) - let size = UInt(section.layout.size) - if offset <= segmentStart + segmentOffset && - segmentStart + segmentOffset < offset + size { - return true - } else { - return false - } - }) + return segment.section( + at: segmentOffset, + cmdsStart: machO.cmdsStartPtr + ) } public func section64(in machO: MachOFile) -> Section64? { guard let segment = segment64(in: machO) else { return nil } - let sections = segment.sections(in: machO) - - let segmentStart = UInt(segment.fileoff) - return sections.first(where: { section in - let offset = UInt(section.layout.offset) - let size = UInt(section.layout.size) - if offset <= segmentStart + segmentOffset && - segmentStart + segmentOffset < offset + size { - return true - } else { - return false - } - }) + return segment.section(at: segmentOffset, in: machO) } public func section32(in machO: MachOFile) -> Section? { guard let segment = segment32(in: machO) else { return nil } - let sections = segment.sections(in: machO) - - let segmentStart = UInt(segment.fileoff) - return sections.first(where: { section in - let offset = UInt(section.layout.offset) - let size = UInt(section.layout.size) - if offset <= segmentStart + segmentOffset && - segmentStart + segmentOffset < offset + size { - return true - } else { - return false - } - }) + return segment.section(at: segmentOffset, in: machO) } } From 571a2bf1114388a0de1b40a10122192c0fc76e19 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:31:49 +0900 Subject: [PATCH 24/25] fix constraint of `SectionType` --- Sources/MachOKit/LoadCommand/SegmentCommand.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/MachOKit/LoadCommand/SegmentCommand.swift b/Sources/MachOKit/LoadCommand/SegmentCommand.swift index 0919f1a..dc603a9 100644 --- a/Sources/MachOKit/LoadCommand/SegmentCommand.swift +++ b/Sources/MachOKit/LoadCommand/SegmentCommand.swift @@ -9,7 +9,7 @@ import Foundation public protocol SegmentCommandProtocol: LoadCommandWrapper { - associatedtype SectionType: LayoutWrapper + associatedtype SectionType: SectionProtocol var segmentName: String { get } var virtualMemoryAddress: Int { get } var virtualMemorySize: Int { get } @@ -23,6 +23,8 @@ public protocol SegmentCommandProtocol: LoadCommandWrapper { func endPtr(vmaddrSlide: Int) -> UnsafeRawPointer? func sections(cmdsStart: UnsafeRawPointer) -> MemorySequence func sections(in machO: MachOFile) -> DataSequence + func section(at offset: UInt, cmdsStart: UnsafeRawPointer) -> SectionType? + func section(at offset: UInt, in machO: MachOFile) -> SectionType? } extension SegmentCommandProtocol { From 0dbcad5fd1f33bc9eb5c7d106bb00b6268c351ba Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:32:08 +0900 Subject: [PATCH 25/25] fix to print section name --- Tests/MachOKitTests/MachOFilePrintTests.swift | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Tests/MachOKitTests/MachOFilePrintTests.swift b/Tests/MachOKitTests/MachOFilePrintTests.swift index fbae3b4..4b8a396 100644 --- a/Tests/MachOKitTests/MachOFilePrintTests.swift +++ b/Tests/MachOKitTests/MachOFilePrintTests.swift @@ -555,11 +555,17 @@ extension MachOFilePrintTests { let fixupInfo = pointer.fixupInfo let offset = String(pointer.offset, radix: 16) + let section = segment.section( + at: UInt(pointer.offset - segment.fileOffset), + in: machO + ) + let sectionName = section?.sectionName ?? "unknown" + if let rebase = fixupInfo.rebase { - print(offset, "rebase:", String(rebase.target, radix: 16)) + print(sectionName, offset, "rebase:", String(rebase.target, radix: 16)) } if let bind = fixupInfo.bind { - print(offset, "bind :", terminator: " ") + print(sectionName, offset, "bind:", terminator: " ") print( chainedFixups.demangledSymbolName(for: imports[bind.ordinal].info.nameOffset) ?? "" )