From fcd956155df4598513d87eb836aa256a5a23d8fc Mon Sep 17 00:00:00 2001 From: Mx-Iris Date: Thu, 23 Apr 2026 18:22:48 +0800 Subject: [PATCH 1/2] refactor(MachOSwiftSection): extract _sectionOffsetAndSize helper Dedupe repeated section offset/size computation across _readDescriptors, _readRelativeDescriptors, _readTypeMetadataRecords, and _readProtocolRecords in both MachOFile.Swift and MachOImage.Swift. --- .../MachOSwiftSection/MachOFile+Swift.swift | 38 +++++++------------ .../MachOSwiftSection/MachOImage+Swift.swift | 32 +++++++--------- 2 files changed, 28 insertions(+), 42 deletions(-) diff --git a/Sources/MachOSwiftSection/MachOFile+Swift.swift b/Sources/MachOSwiftSection/MachOFile+Swift.swift index ac5c20ac..5c740fd9 100644 --- a/Sources/MachOSwiftSection/MachOFile+Swift.swift +++ b/Sources/MachOSwiftSection/MachOFile+Swift.swift @@ -89,16 +89,21 @@ extension MachOFile.Swift: SwiftSectionRepresentable { } extension MachOFile.Swift { - private func _readDescriptors(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOFile) throws -> [Descriptor] { + private func _sectionOffsetAndSize(of swiftMachOSection: MachOSwiftSectionName, in machO: MachOFile) throws -> (offset: Int, size: Int) { let section = try machO.section(for: swiftMachOSection) - var descriptors: [Descriptor] = [] let offset = if let cache = machO.cache { section.address - cache.mainCacheHeader.sharedRegionStart.cast() } else { section.offset } + return (offset, section.size) + } + + private func _readDescriptors(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOFile) throws -> [Descriptor] { + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) + var descriptors: [Descriptor] = [] var currentOffset = offset - let endOffset = offset + section.size + let endOffset = offset + size while currentOffset < endOffset { let descriptor: Descriptor = try machO.readWrapperElement(offset: currentOffset) currentOffset += descriptor.actualSize @@ -108,38 +113,23 @@ extension MachOFile.Swift { } private func _readRelativeDescriptors(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOFile) throws -> [Descriptor] { - let section = try machO.section(for: swiftMachOSection) + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) let pointerSize: Int = MemoryLayout>.size - let offset = if let cache = machO.cache { - section.address - cache.mainCacheHeader.sharedRegionStart.cast() - } else { - section.offset - } - let data: [AnyLocatableLayoutWrapper>] = try machO.readWrapperElements(offset: offset, numberOfElements: section.size / pointerSize) + let data: [AnyLocatableLayoutWrapper>] = try machO.readWrapperElements(offset: offset, numberOfElements: size / pointerSize) return try data.map { try $0.layout.resolve(from: $0.offset, in: machO) } } private func _readTypeMetadataRecords(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOFile) throws -> [ContextDescriptorWrapper] { - let section = try machO.section(for: swiftMachOSection) - let offset = if let cache = machO.cache { - section.address - cache.mainCacheHeader.sharedRegionStart.cast() - } else { - section.offset - } + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) let recordSize = MemoryLayout.size - let records: [TypeMetadataRecord] = try machO.readWrapperElements(offset: offset, numberOfElements: section.size / recordSize) + let records: [TypeMetadataRecord] = try machO.readWrapperElements(offset: offset, numberOfElements: size / recordSize) return try records.compactMap { try $0.contextDescriptor(in: machO) } } private func _readProtocolRecords(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOFile) throws -> [ProtocolDescriptor] { - let section = try machO.section(for: swiftMachOSection) - let offset = if let cache = machO.cache { - section.address - cache.mainCacheHeader.sharedRegionStart.cast() - } else { - section.offset - } + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) let recordSize = MemoryLayout.size - let records: [ProtocolRecord] = try machO.readWrapperElements(offset: offset, numberOfElements: section.size / recordSize) + let records: [ProtocolRecord] = try machO.readWrapperElements(offset: offset, numberOfElements: size / recordSize) return try records.compactMap { try $0.protocolDescriptor(in: machO) } } } diff --git a/Sources/MachOSwiftSection/MachOImage+Swift.swift b/Sources/MachOSwiftSection/MachOImage+Swift.swift index bdf7c1ba..39046ca3 100644 --- a/Sources/MachOSwiftSection/MachOImage+Swift.swift +++ b/Sources/MachOSwiftSection/MachOImage+Swift.swift @@ -89,14 +89,19 @@ extension MachOImage.Swift: SwiftSectionRepresentable { } extension MachOImage.Swift { - private func _readDescriptors(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOImage) throws -> [Descriptor] { + private func _sectionOffsetAndSize(of swiftMachOSection: MachOSwiftSectionName, in machO: MachOImage) throws -> (offset: Int, size: Int) { let section = try machO.section(for: swiftMachOSection) - var descriptors: [Descriptor] = [] let vmaddrSlide = try required(machO.vmaddrSlide) let start = try required(UnsafeRawPointer(bitPattern: section.address + vmaddrSlide)) let offset = start.bitPattern.int - machO.ptr.bitPattern.int + return (offset, section.size) + } + + private func _readDescriptors(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOImage) throws -> [Descriptor] { + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) + var descriptors: [Descriptor] = [] var currentOffset = offset - let endOffset = offset + section.size + let endOffset = offset + size while currentOffset < endOffset { let descriptor: Descriptor = try machO.readWrapperElement(offset: currentOffset) currentOffset += descriptor.actualSize @@ -106,32 +111,23 @@ extension MachOImage.Swift { } private func _readRelativeDescriptors(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOImage) throws -> [Descriptor] { - let section = try machO.section(for: swiftMachOSection) - let vmaddrSlide = try required(machO.vmaddrSlide) - let start = try required(UnsafeRawPointer(bitPattern: section.address + vmaddrSlide)) - let offset = start.bitPattern.int - machO.ptr.bitPattern.int + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) let pointerSize: Int = MemoryLayout>.size - let data: [AnyLocatableLayoutWrapper>] = try machO.readWrapperElements(offset: offset, numberOfElements: section.size / pointerSize) + let data: [AnyLocatableLayoutWrapper>] = try machO.readWrapperElements(offset: offset, numberOfElements: size / pointerSize) return try data.map { try $0.layout.resolve(from: $0.offset, in: machO) } } private func _readTypeMetadataRecords(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOImage) throws -> [ContextDescriptorWrapper] { - let section = try machO.section(for: swiftMachOSection) - let vmaddrSlide = try required(machO.vmaddrSlide) - let start = try required(UnsafeRawPointer(bitPattern: section.address + vmaddrSlide)) - let offset = start.bitPattern.int - machO.ptr.bitPattern.int + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) let recordSize = MemoryLayout.size - let records: [TypeMetadataRecord] = try machO.readWrapperElements(offset: offset, numberOfElements: section.size / recordSize) + let records: [TypeMetadataRecord] = try machO.readWrapperElements(offset: offset, numberOfElements: size / recordSize) return try records.compactMap { try $0.contextDescriptor(in: machO) } } private func _readProtocolRecords(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOImage) throws -> [ProtocolDescriptor] { - let section = try machO.section(for: swiftMachOSection) - let vmaddrSlide = try required(machO.vmaddrSlide) - let start = try required(UnsafeRawPointer(bitPattern: section.address + vmaddrSlide)) - let offset = start.bitPattern.int - machO.ptr.bitPattern.int + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) let recordSize = MemoryLayout.size - let records: [ProtocolRecord] = try machO.readWrapperElements(offset: offset, numberOfElements: section.size / recordSize) + let records: [ProtocolRecord] = try machO.readWrapperElements(offset: offset, numberOfElements: size / recordSize) return try records.compactMap { try $0.protocolDescriptor(in: machO) } } } From 79f394535b28fcfeb3fed48ea8c2a6d5b9f3fc12 Mon Sep 17 00:00:00 2001 From: Mx-Iris Date: Sun, 26 Apr 2026 21:17:20 +0800 Subject: [PATCH 2/2] refactor(MachOSwiftSection): simplify Swift section helpers - Drop redundant machO parameter from private _read* and _sectionOffsetAndSize helpers since self.machO is already available. - Use UnsafeRawPointer.distance(to:) in place of manual bitPattern subtraction in MachOImage variant. - Move `extension RelativeDirectPointer: LayoutProtocol` into a dedicated file under MachOPointers, alongside the pointer definition. --- ...RelativeDirectPointer+LayoutProtocol.swift | 3 ++ .../MachOSwiftSection/MachOFile+Swift.swift | 32 +++++++++---------- .../MachOSwiftSection/MachOImage+Swift.swift | 32 +++++++++---------- 3 files changed, 34 insertions(+), 33 deletions(-) create mode 100644 Sources/MachOPointers/RelativeDirectPointer+LayoutProtocol.swift diff --git a/Sources/MachOPointers/RelativeDirectPointer+LayoutProtocol.swift b/Sources/MachOPointers/RelativeDirectPointer+LayoutProtocol.swift new file mode 100644 index 00000000..089782c1 --- /dev/null +++ b/Sources/MachOPointers/RelativeDirectPointer+LayoutProtocol.swift @@ -0,0 +1,3 @@ +import MachOExtensions + +extension RelativeDirectPointer: LayoutProtocol {} diff --git a/Sources/MachOSwiftSection/MachOFile+Swift.swift b/Sources/MachOSwiftSection/MachOFile+Swift.swift index 5c740fd9..1b6a64a6 100644 --- a/Sources/MachOSwiftSection/MachOFile+Swift.swift +++ b/Sources/MachOSwiftSection/MachOFile+Swift.swift @@ -47,7 +47,7 @@ extension MachOFile.Swift: SwiftSectionRepresentable { public var contextDescriptors: [ContextDescriptorWrapper] { get throws { - return try _readTypeMetadataRecords(from: .__swift5_types, in: machO) + (try? _readTypeMetadataRecords(from: .__swift5_types2, in: machO)) + return try _readTypeMetadataRecords(from: .__swift5_types) + (try? _readTypeMetadataRecords(from: .__swift5_types2)) } } @@ -59,37 +59,37 @@ extension MachOFile.Swift: SwiftSectionRepresentable { public var protocolDescriptors: [ProtocolDescriptor] { get throws { - return try _readProtocolRecords(from: .__swift5_protos, in: machO) + return try _readProtocolRecords(from: .__swift5_protos) } } public var protocolConformanceDescriptors: [ProtocolConformanceDescriptor] { get throws { - return try _readRelativeDescriptors(from: .__swift5_proto, in: machO) + return try _readRelativeDescriptors(from: .__swift5_proto) } } public var associatedTypeDescriptors: [AssociatedTypeDescriptor] { get throws { - return try _readDescriptors(from: .__swift5_assocty, in: machO) + return try _readDescriptors(from: .__swift5_assocty) } } public var builtinTypeDescriptors: [BuiltinTypeDescriptor] { get throws { - return try _readDescriptors(from: .__swift5_builtin, in: machO) + return try _readDescriptors(from: .__swift5_builtin) } } public var multiPayloadEnumDescriptors: [MultiPayloadEnumDescriptor] { get throws { - return try _readDescriptors(from: .__swift5_mpenum, in: machO) + return try _readDescriptors(from: .__swift5_mpenum) } } } extension MachOFile.Swift { - private func _sectionOffsetAndSize(of swiftMachOSection: MachOSwiftSectionName, in machO: MachOFile) throws -> (offset: Int, size: Int) { + private func _sectionOffsetAndSize(of swiftMachOSection: MachOSwiftSectionName) throws -> (offset: Int, size: Int) { let section = try machO.section(for: swiftMachOSection) let offset = if let cache = machO.cache { section.address - cache.mainCacheHeader.sharedRegionStart.cast() @@ -99,8 +99,8 @@ extension MachOFile.Swift { return (offset, section.size) } - private func _readDescriptors(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOFile) throws -> [Descriptor] { - let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) + private func _readDescriptors(from swiftMachOSection: MachOSwiftSectionName) throws -> [Descriptor] { + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection) var descriptors: [Descriptor] = [] var currentOffset = offset let endOffset = offset + size @@ -112,26 +112,24 @@ extension MachOFile.Swift { return descriptors } - private func _readRelativeDescriptors(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOFile) throws -> [Descriptor] { - let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) + private func _readRelativeDescriptors(from swiftMachOSection: MachOSwiftSectionName) throws -> [Descriptor] { + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection) let pointerSize: Int = MemoryLayout>.size let data: [AnyLocatableLayoutWrapper>] = try machO.readWrapperElements(offset: offset, numberOfElements: size / pointerSize) return try data.map { try $0.layout.resolve(from: $0.offset, in: machO) } } - private func _readTypeMetadataRecords(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOFile) throws -> [ContextDescriptorWrapper] { - let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) + private func _readTypeMetadataRecords(from swiftMachOSection: MachOSwiftSectionName) throws -> [ContextDescriptorWrapper] { + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection) let recordSize = MemoryLayout.size let records: [TypeMetadataRecord] = try machO.readWrapperElements(offset: offset, numberOfElements: size / recordSize) return try records.compactMap { try $0.contextDescriptor(in: machO) } } - private func _readProtocolRecords(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOFile) throws -> [ProtocolDescriptor] { - let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) + private func _readProtocolRecords(from swiftMachOSection: MachOSwiftSectionName) throws -> [ProtocolDescriptor] { + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection) let recordSize = MemoryLayout.size let records: [ProtocolRecord] = try machO.readWrapperElements(offset: offset, numberOfElements: size / recordSize) return try records.compactMap { try $0.protocolDescriptor(in: machO) } } } - -extension RelativeDirectPointer: LayoutProtocol {} diff --git a/Sources/MachOSwiftSection/MachOImage+Swift.swift b/Sources/MachOSwiftSection/MachOImage+Swift.swift index 39046ca3..e17e4c2b 100644 --- a/Sources/MachOSwiftSection/MachOImage+Swift.swift +++ b/Sources/MachOSwiftSection/MachOImage+Swift.swift @@ -47,7 +47,7 @@ extension MachOImage.Swift: SwiftSectionRepresentable { public var contextDescriptors: [ContextDescriptorWrapper] { get throws { - return try _readTypeMetadataRecords(from: .__swift5_types, in: machO) + (try? _readTypeMetadataRecords(from: .__swift5_types2, in: machO)) + return try _readTypeMetadataRecords(from: .__swift5_types) + (try? _readTypeMetadataRecords(from: .__swift5_types2)) } } @@ -59,46 +59,46 @@ extension MachOImage.Swift: SwiftSectionRepresentable { public var protocolDescriptors: [ProtocolDescriptor] { get throws { - return try _readProtocolRecords(from: .__swift5_protos, in: machO) + return try _readProtocolRecords(from: .__swift5_protos) } } public var protocolConformanceDescriptors: [ProtocolConformanceDescriptor] { get throws { - return try _readRelativeDescriptors(from: .__swift5_proto, in: machO) + return try _readRelativeDescriptors(from: .__swift5_proto) } } public var associatedTypeDescriptors: [AssociatedTypeDescriptor] { get throws { - return try _readDescriptors(from: .__swift5_assocty, in: machO) + return try _readDescriptors(from: .__swift5_assocty) } } public var builtinTypeDescriptors: [BuiltinTypeDescriptor] { get throws { - return try _readDescriptors(from: .__swift5_builtin, in: machO) + return try _readDescriptors(from: .__swift5_builtin) } } public var multiPayloadEnumDescriptors: [MultiPayloadEnumDescriptor] { get throws { - return try _readDescriptors(from: .__swift5_mpenum, in: machO) + return try _readDescriptors(from: .__swift5_mpenum) } } } extension MachOImage.Swift { - private func _sectionOffsetAndSize(of swiftMachOSection: MachOSwiftSectionName, in machO: MachOImage) throws -> (offset: Int, size: Int) { + private func _sectionOffsetAndSize(of swiftMachOSection: MachOSwiftSectionName) throws -> (offset: Int, size: Int) { let section = try machO.section(for: swiftMachOSection) let vmaddrSlide = try required(machO.vmaddrSlide) let start = try required(UnsafeRawPointer(bitPattern: section.address + vmaddrSlide)) - let offset = start.bitPattern.int - machO.ptr.bitPattern.int + let offset = machO.ptr.distance(to: start) return (offset, section.size) } - private func _readDescriptors(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOImage) throws -> [Descriptor] { - let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) + private func _readDescriptors(from swiftMachOSection: MachOSwiftSectionName) throws -> [Descriptor] { + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection) var descriptors: [Descriptor] = [] var currentOffset = offset let endOffset = offset + size @@ -110,22 +110,22 @@ extension MachOImage.Swift { return descriptors } - private func _readRelativeDescriptors(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOImage) throws -> [Descriptor] { - let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) + private func _readRelativeDescriptors(from swiftMachOSection: MachOSwiftSectionName) throws -> [Descriptor] { + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection) let pointerSize: Int = MemoryLayout>.size let data: [AnyLocatableLayoutWrapper>] = try machO.readWrapperElements(offset: offset, numberOfElements: size / pointerSize) return try data.map { try $0.layout.resolve(from: $0.offset, in: machO) } } - private func _readTypeMetadataRecords(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOImage) throws -> [ContextDescriptorWrapper] { - let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) + private func _readTypeMetadataRecords(from swiftMachOSection: MachOSwiftSectionName) throws -> [ContextDescriptorWrapper] { + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection) let recordSize = MemoryLayout.size let records: [TypeMetadataRecord] = try machO.readWrapperElements(offset: offset, numberOfElements: size / recordSize) return try records.compactMap { try $0.contextDescriptor(in: machO) } } - private func _readProtocolRecords(from swiftMachOSection: MachOSwiftSectionName, in machO: MachOImage) throws -> [ProtocolDescriptor] { - let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection, in: machO) + private func _readProtocolRecords(from swiftMachOSection: MachOSwiftSectionName) throws -> [ProtocolDescriptor] { + let (offset, size) = try _sectionOffsetAndSize(of: swiftMachOSection) let recordSize = MemoryLayout.size let records: [ProtocolRecord] = try machO.readWrapperElements(offset: offset, numberOfElements: size / recordSize) return try records.compactMap { try $0.protocolDescriptor(in: machO) }