Skip to content

Commit

Permalink
Merge pull request #80 from p-x9/feature/external-relocation
Browse files Browse the repository at this point in the history
External relocation infos
  • Loading branch information
p-x9 authored May 13, 2024
2 parents 934929b + 5fcf566 commit d356902
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 0 deletions.
21 changes: 21 additions & 0 deletions Sources/MachOKit/MachOFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,27 @@ extension MachOFile {
}
}

extension MachOFile {
public var externalRelocations: DataSequence<Relocation>? {
guard let dysymtab = loadCommands.dysymtab else {
return nil
}
return fileHandle.readDataSequence(
offset: numericCast(dysymtab.extreloff),
numberOfElements: numericCast(dysymtab.nextrel),
swapHandler: { data in
guard self.isSwapped else { return }
data.withUnsafeMutableBytes {
guard let baseAddress = $0.baseAddress else { return }
let ptr = baseAddress
.assumingMemoryBound(to: relocation_info.self)
swap_relocation_info(ptr, dysymtab.nextrel, NXHostByteOrder())
}
}
)
}
}

extension MachOFile {
public var isEncrypted: Bool {
if let encryptionInfo = loadCommands.encryptionInfo {
Expand Down
22 changes: 22 additions & 0 deletions Sources/MachOKit/MachOImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,28 @@ extension MachOImage {
}
}

extension MachOImage {
public var externalRelocations: MemorySequence<Relocation>? {
guard let dysymtab = loadCommands.dysymtab else { return nil }

let linkedit: (any SegmentCommandProtocol)? = loadCommands.linkedit64 ?? loadCommands.linkedit

guard let linkedit,
let vmaddrSlide,
let start = linkedit.startPtr(vmaddrSlide: vmaddrSlide) else {
return nil
}

return .init(
basePointer: start
.advanced(by: -linkedit.fileOffset)
.advanced(by: numericCast(dysymtab.extreloff))
.assumingMemoryBound(to: Relocation.self),
numberOfElements: numericCast(dysymtab.nextrel)
)
}
}

extension MachOImage {
public var codeSign: CodeSign? {
guard let vmaddrSlide,
Expand Down
4 changes: 4 additions & 0 deletions Sources/MachOKit/Protocol/MachORepresentable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public protocol MachORepresentable {
associatedtype FunctionStarts: Sequence<FunctionStart>
associatedtype DataInCode: RandomAccessCollection<DataInCodeEntry>
associatedtype DyldChainedFixups: DyldChainedFixupsProtocol
associatedtype ExternalRelocations: RandomAccessCollection<Relocation>
associatedtype CodeSign: CodeSignProtocol

/// A boolean value that indicates whether MachO is a 64-bit architecture.
Expand Down Expand Up @@ -133,6 +134,9 @@ public protocol MachORepresentable {

/// Chained fixup infos
var dyldChainedFixups: DyldChainedFixups? { get }

/// Sequence of external relocation infos
var externalRelocations: ExternalRelocations? { get }

/// Code sign infos
var codeSign: CodeSign? { get }
Expand Down
43 changes: 43 additions & 0 deletions Tests/MachOKitTests/MachOFilePrintTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,49 @@ final class MachOFilePrintTests: XCTestCase {
}
}

func testExternalRelocations() {
guard let relocations = machO.externalRelocations else {
return
}
let symbols = machO.symbols
for relocation in relocations {
print("--")
switch relocation.info {
case let .general(info):
print("Offset:", "0x" + String(info.r_address, radix: 16))
if let length = info.length {
print("Length:", length)
}
print("isExternal:", info.isExternal)
print("isScatted:", info.isScattered)
print("pcRelative:", info.isRelocatedPCRelative)
if let symbolIndex = info.symbolIndex {
print("SymbolIndex:", symbolIndex)
print("SymbolName:", symbols[AnyIndex(symbolIndex)].name)
}
if let sectionOrdinal = info.sectionOrdinal {
print("SectionOrdinal:", sectionOrdinal)
}
if let cpuType = machO.header.cpuType,
let type = info.type(for: cpuType) {
print("Type:", type)
}
case let .scattered(info):
print("Offset:", "0x" + String(info.layout.r_address, radix: 16))
if let length = info.length {
print("Length:", length)
}
print("isScatted:", info.isScattered)
print("pcRelative:", info.isRelocatedPCRelative)
if let cpuType = machO.header.cpuType,
let type = info.type(for: cpuType) {
print("Type:", type)
}
print("Value:", "0x" + String(info.r_value, radix: 16))
}
}
}

func testDependencies() throws {
for dependency in machO.dependencies {
let dependency = dependency.dylib
Expand Down
43 changes: 43 additions & 0 deletions Tests/MachOKitTests/MachOPrintTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,49 @@ final class MachOPrintTests: XCTestCase {
}
}

func testExternalRelocations() {
guard let relocations = machO.externalRelocations else {
return
}
let symbols = machO.symbols
for relocation in relocations {
print("--")
switch relocation.info {
case let .general(info):
print("Offset:", "0x" + String(info.r_address, radix: 16))
if let length = info.length {
print("Length:", length)
}
print("isExternal:", info.isExternal)
print("isScatted:", info.isScattered)
print("pcRelative:", info.isRelocatedPCRelative)
if let symbolIndex = info.symbolIndex {
print("SymbolIndex:", symbolIndex)
print("SymbolName:", symbols[AnyIndex(symbolIndex)].name)
}
if let sectionOrdinal = info.sectionOrdinal {
print("SectionOrdinal:", sectionOrdinal)
}
if let cpuType = machO.header.cpuType,
let type = info.type(for: cpuType) {
print("Type:", type)
}
case let .scattered(info):
print("Offset:", "0x" + String(info.layout.r_address, radix: 16))
if let length = info.length {
print("Length:", length)
}
print("isScatted:", info.isScattered)
print("pcRelative:", info.isRelocatedPCRelative)
if let cpuType = machO.header.cpuType,
let type = info.type(for: cpuType) {
print("Type:", type)
}
print("Value:", "0x" + String(info.r_value, radix: 16))
}
}
}

func testDependencies() throws {
for dependency in machO.dependencies {
let dependency = dependency.dylib
Expand Down

0 comments on commit d356902

Please sign in to comment.