Skip to content

Conversation

@p-x9
Copy link
Owner

@p-x9 p-x9 commented Sep 28, 2025

In the iOS dyld shared cache, the DATA and LINKEDIT sections are separated into distinct subcaches.
Fixed to account for these cases when reading sections.

Additionally, parts that had not undergone rebase processing have been corrected to ensure they are processed correctly.

p-x9 added 14 commits September 28, 2025 18:35
- Returns nil if not loaded from DyldCache
- Constructs FullDyldCache using the URL without its extensions
- Implemented a computed property in MachOFile to retrieve the offset.
- Added a similar property in DyldCacheRepresentable for consistency.
- Updated ObjCMethodList to utilize the new property from MachOFile.
- Ensure offset method returns nil if layout.offset is not positive
- Ensure type method returns nil if layout.type is not positive
- Simplifies the code by eliminating unnecessary functionality
- Implement the `layoutOffset(of:)` method using kayPath as the default implementation.
- Introduce the `UnresolvedValue` structure to resolve rebase/bind
- Changed dependency versioning for MachOKit in Package.swift
- Updated revision in Package.resolved to match the latest state
- Introduced ResolvedValue struct to encapsulate address and offset information, improving clarity in the resolution process.
- Removed deprecated code related to cache handling and rebase resolution, ensuring cleaner and more maintainable code.
- Deleted `fullCache` and `cache` properties as they were redundant
- Changed dependency from branch 'main' to version '0.40.0'
- Updated revision in Package.resolved to match the new version
@p-x9 p-x9 requested a review from Copilot November 6, 2025 16:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the Mach-O Objective-C section handling to support split dyld cache layouts. The key changes involve centralizing fixup resolution through a new abstraction layer and adapting file I/O operations to work across multiple cache files.

  • Introduces UnresolvedValue and ResolvedValue types to represent pre- and post-fixup values
  • Refactors the _FixupResolvable protocol to use field-based resolution instead of offset-based
  • Updates MachOKit dependency from 0.34.0 to 0.40.0

Reviewed Changes

Copilot reviewed 31 out of 32 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
Sources/MachOObjCSection/Util/FixupResolvable.swift Adds value types and refactors protocol to use field-based resolution with keyPath approach
Sources/MachOObjCSection/Protocol/Protocol/_ObjCProtocolLayoutProtocol.swift Comments out unused size and flags fields
Sources/MachOObjCSection/Protocol/Protocol/ObjCProtocolProtocol.swift Migrates to field-based resolution pattern using unresolvedValue/resolveRebase
Sources/MachOObjCSection/Protocol/Ivar/_ObjCIvarLayoutProtocol.swift Comments out unused alignment and size fields
Sources/MachOObjCSection/Protocol/Ivar/ObjCIvarProtocol.swift Adopts new resolution pattern for ivar fields
Sources/MachOObjCSection/Protocol/Class/_ObjCClassLayoutProtocol.swift Comments out unused swiftClassFlags field
Sources/MachOObjCSection/Protocol/Class/RO/_ObjCClassRODataLayoutProtocol.swift Comments out unused flags, instanceStart, and instanceSize fields
Sources/MachOObjCSection/Protocol/Class/RO/ObjCClassRODataProtocol.swift Refactors all field access to use new resolution pattern
Sources/MachOObjCSection/Protocol/Class/ObjCClassProtocol.swift Updates class reading methods to use field-based resolution
Sources/MachOObjCSection/Protocol/Category/ObjCCategoryProtocol.swift Migrates category protocol handling to new resolution pattern
Sources/MachOObjCSection/Model/Protocol/ObjCProtocolList64.swift Refactors protocol list iteration to use UnresolvedValue approach
Sources/MachOObjCSection/Model/Protocol/ObjCProtocolList32.swift Applies same protocol list refactoring for 32-bit architecture
Sources/MachOObjCSection/Model/Protocol/ObjCProtocol64.swift Changes layoutOffset method to return KeyPath instead
Sources/MachOObjCSection/Model/Protocol/ObjCProtocol32.swift Applies same keyPath change for 32-bit protocol
Sources/MachOObjCSection/Model/Property/ObjCPropertyList.swift Rewrites property list parsing to use resolution pattern
Sources/MachOObjCSection/Model/Property/ObjCProperty.swift Adds UnresolvedProperty and ResolvedProperty types
Sources/MachOObjCSection/Model/Method/ObjCMethodList.swift Refactors method list parsing for new file I/O approach
Sources/MachOObjCSection/Model/Ivar/ObjCIvar64.swift Updates to return KeyPath and removes layout offset calculation
Sources/MachOObjCSection/Model/Ivar/ObjCIvar32.swift Applies same keyPath changes for 32-bit ivar
Sources/MachOObjCSection/Model/Class/RO/ObjCClassROData64.swift Simplifies keyPath switch to only include used fields
Sources/MachOObjCSection/Model/Class/RO/ObjCClassROData32.swift Applies same simplification for 32-bit class RO data
Sources/MachOObjCSection/Model/Class/ObjCClass64.swift Refactors classROData loading with new resolution pattern
Sources/MachOObjCSection/Model/Class/ObjCClass32.swift Applies same classROData refactoring for 32-bit
Sources/MachOObjCSection/Model/Category/ObjCCategory64.swift Simplifies keyPath method for category fields
Sources/MachOObjCSection/Model/Category/ObjCCategory32.swift Applies same category keyPath changes for 32-bit
Sources/MachOObjCSection/MachOFile+ObjectiveC.swift Adds _fileSliceForSection helper and updates section parsing
Sources/MachOObjCSection/Extension/MachOFile+.swift Adds file handle resolution and rebase helper methods
Sources/MachOObjCSection/Extension/FullDyldCache+.swift New file adding fileHandle and fileSegment support
Sources/MachOObjCSection/Extension/DyldCacheRepresentable+.swift New file adding relativeMethodSelectorBaseAddressOffset property
Sources/MachOObjCSection/Extension/DyldCache+.swift Removes unused mainCache property
Package.swift Updates MachOKit dependency to version 0.40.0

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

p-x9 and others added 2 commits November 7, 2025 01:16
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@p-x9 p-x9 requested a review from Copilot November 6, 2025 16:16
@p-x9 p-x9 marked this pull request as ready for review November 6, 2025 16:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 31 out of 32 changed files in this pull request and generated 13 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

#endif

extension _FixupResolvable {
#if false
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code block (lines 102-133) should be removed rather than commented out with #if false. If this code needs to be preserved for reference, consider documenting why in a comment or moving it to version control history.

Copilot uses AI. Check for mistakes.
}
}

#if false
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code block (lines 193-207) should be removed rather than commented out with #if false. Consider removing this unused extension entirely.

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +40
// case size
// case flags
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out enum cases should be removed if they are no longer needed. If they need to be preserved for future use, add a TODO comment explaining why.

Suggested change
// case size
// case flags

Copilot uses AI. Check for mistakes.
associatedtype ObjCProtocolList: ObjCProtocolListProtocol where ObjCProtocolList.ObjCProtocol == Self

var layout: Layout { get }
// var layout: Layout { get }
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out protocol requirement should be removed if no longer needed. The layout property is already inherited from LayoutWrapper protocol.

Suggested change
// var layout: Layout { get }

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +26
// case alignment
// case size
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out enum cases should be removed if they are no longer needed. If they need to be preserved for future use, add a TODO comment explaining why.

Suggested change
// case alignment
// case size

Copilot uses AI. Check for mistakes.
associatedtype ObjCProtocolRelativeListList: ObjCProtocolRelativeListListProtocol where ObjCProtocolRelativeListList.List == ObjCProtocolList

var layout: Layout { get }
// var layout: Layout { get }
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out protocol requirement should be removed if no longer needed. The layout property is already inherited from LayoutWrapper protocol.

Suggested change
// var layout: Layout { get }

Copilot uses AI. Check for mistakes.
associatedtype ClassRWData: LayoutWrapper, ObjCClassRWDataProtocol where ClassRWData.Layout.Pointer == Layout.Pointer, ClassRWData.ObjCClassROData == ClassROData

var layout: Layout { get }
// var layout: Layout { get }
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out protocol requirement should be removed if no longer needed. The layout property is already inherited from LayoutWrapper protocol.

Suggested change
// var layout: Layout { get }

Copilot uses AI. Check for mistakes.
typealias ObjCProtocolList = ObjCClass.ClassROData.ObjCProtocolList

var layout: Layout { get }
// var layout: Layout { get }
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out protocol requirement should be removed if no longer needed. The layout property is already inherited from LayoutWrapper protocol.

Suggested change
// var layout: Layout { get }

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +57
case .isa: \.isa
case .mangledName: \.mangledName
case .protocols: \.protocols
case .instanceMethods: \.instanceMethods
case .classMethods: \.classMethods
case .optionalInstanceMethods: \.optionalInstanceMethods
case .optionalClassMethods: \.optionalClassMethods
case .instanceProperties: \.instanceProperties
case ._extendedMethodTypes: \._extendedMethodTypes
case ._demangledName: \._demangledName
case ._classProperties: \._classProperties
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The switch statement should use return explicitly for each case rather than relying on implicit return. This improves clarity and follows Swift best practices for non-trivial switch statements.

Suggested change
case .isa: \.isa
case .mangledName: \.mangledName
case .protocols: \.protocols
case .instanceMethods: \.instanceMethods
case .classMethods: \.classMethods
case .optionalInstanceMethods: \.optionalInstanceMethods
case .optionalClassMethods: \.optionalClassMethods
case .instanceProperties: \.instanceProperties
case ._extendedMethodTypes: \._extendedMethodTypes
case ._demangledName: \._demangledName
case ._classProperties: \._classProperties
case .isa: return \.isa
case .mangledName: return \.mangledName
case .protocols: return \.protocols
case .instanceMethods: return \.instanceMethods
case .classMethods: return \.classMethods
case .optionalInstanceMethods: return \.optionalInstanceMethods
case .optionalClassMethods: return \.optionalClassMethods
case .instanceProperties: return \.instanceProperties
case ._extendedMethodTypes: return \._extendedMethodTypes
case ._demangledName: return \._demangledName
case ._classProperties: return \._classProperties

Copilot uses AI. Check for mistakes.

return .init(
address: unresolvedValue.value,
offset: fileOffset(of: unresolvedValue.value)!
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Force unwrapping could crash if fileOffset returns nil. Add proper error handling or document why this is guaranteed to succeed.

Suggested change
offset: fileOffset(of: unresolvedValue.value)!
// If fileOffset returns nil, fallback to 0 to avoid crash.
offset: fileOffset(of: unresolvedValue.value) ?? 0

Copilot uses AI. Check for mistakes.
p-x9 added 4 commits November 7, 2025 01:24
- Updated ObjCClass32, ObjCClass64, and ObjCMethodList extensions
- Improved code clarity and consistency
- Simplified offset handling in readString calls for better clarity
- Simplified offset calculation by removing unnecessary variables
- Used guard statement for fileHandle and fileOffset retrieval
…machokit-objc-support into feature/support-split-cache-layout
Comment on lines -31 to -42
extension DyldCache {
var mainCache: DyldCache? {
if url.lastPathComponent.contains(".") {
var url = url
url.deletePathExtension()
return try? .init(url: url)
} else {
return self
}
}
}

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in MachOKit.

Comment on lines -26 to -38
var cache: DyldCache? {
guard isLoadedFromDyldCache else { return nil }
guard let cache = try? DyldCache(url: url) else {
return nil
}
if let mainCache = cache.mainCache {
return try? .init(
subcacheUrl: cache.url,
mainCacheHeader: mainCache.header
)
}
return cache
}
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in MachOKit.

@p-x9 p-x9 merged commit 7dbedd2 into main Nov 7, 2025
2 checks passed
@p-x9 p-x9 deleted the feature/support-split-cache-layout branch November 7, 2025 18:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants