@@ -35,9 +35,10 @@ extension MachOFile.ObjectiveC {
3535 return nil
3636 }
3737
38- return try ! machO. fileHandle. read (
39- offset: numericCast ( __objc_imageinfo. offset + machO. headerStartOffset)
40- )
38+ guard let fileSlice = machO. _fileSliceForSection ( section: __objc_imageinfo) else {
39+ return nil
40+ }
41+ return try ? fileSlice. read ( offset: 0 )
4142 }
4243}
4344
@@ -272,8 +273,11 @@ extension MachOFile.ObjectiveC {
272273 in machO: MachOFile ,
273274 isCatlist2: Bool = false
274275 ) -> [ Categgory ] ? {
275- let data = try ! machO. fileHandle. readData (
276- offset: numericCast ( section. offset + machO. headerStartOffset) ,
276+ guard let fileSlice = machO. _fileSliceForSection ( section: section) else {
277+ return nil
278+ }
279+ let data = try ! fileSlice. readData (
280+ offset: 0 ,
277281 length: section. size
278282 )
279283
@@ -311,8 +315,11 @@ extension MachOFile.ObjectiveC {
311315 from section: any SectionProtocol ,
312316 in machO: MachOFile
313317 ) -> [ Class ] ? {
314- let data = try ! machO. fileHandle. readData (
315- offset: numericCast ( section. offset + machO. headerStartOffset) ,
318+ guard let fileSlice = machO. _fileSliceForSection ( section: section) else {
319+ return nil
320+ }
321+ let data = try ! fileSlice. readData (
322+ offset: 0 ,
316323 length: section. size
317324 )
318325
@@ -346,8 +353,11 @@ extension MachOFile.ObjectiveC {
346353 from section: any SectionProtocol ,
347354 in machO: MachOFile
348355 ) -> [ Protocol ] ? {
349- let data = try ! machO. fileHandle. readData (
350- offset: numericCast ( section. offset + machO. headerStartOffset) ,
356+ guard let fileSlice = machO. _fileSliceForSection ( section: section) else {
357+ return nil
358+ }
359+ let data = try ! fileSlice. readData (
360+ offset: 0 ,
351361 length: section. size
352362 )
353363
@@ -373,3 +383,45 @@ extension MachOFile.ObjectiveC {
373383 }
374384 }
375385}
386+
387+ extension MachOFile {
388+ fileprivate func _fileSliceForSection(
389+ section: any SectionProtocol
390+ ) -> File . FileSlice ? {
391+ let text : ( any SegmentCommandProtocol ) ? = loadCommands. text64 ?? loadCommands. text
392+ guard let text else { return nil }
393+
394+ let maxFileOffsetToCheck = text. fileOffset + section. address - text. virtualMemoryAddress
395+ let isWithinFileRange : Bool = fileHandle. size >= maxFileOffsetToCheck
396+
397+ // 1) text.vmaddr < linkedit.vmaddr
398+ // 2) fileoff_diff <= vmaddr_diff
399+ // 3) If both exist in the same file
400+ // text.fileoff < linkedit.fileoff <= text.fileoff + vmaddr_diff
401+ // 4) if fileHandle.size < text.fileoff + vmaddr_diff
402+ // both exist in the same file
403+
404+ // The linkedit data in iOS is stored together in a separate, independent cache.
405+ // (.0x.linkeditdata)
406+ if isLoadedFromDyldCache && !isWithinFileRange {
407+ guard let fullCache = self . fullCache,
408+ let fileOffset = fullCache. fileOffset (
409+ of: numericCast ( section. address)
410+ ) ,
411+ let segment = fullCache. fileSegment (
412+ forOffset: fileOffset
413+ ) else {
414+ return nil
415+ }
416+ return try ? segment. _file. fileSlice (
417+ offset: numericCast ( fileOffset) - segment. offset,
418+ length: section. size
419+ )
420+ } else {
421+ return try ? fileHandle. fileSlice (
422+ offset: headerStartOffset + section. offset,
423+ length: section. size
424+ )
425+ }
426+ }
427+ }
0 commit comments