Skip to content

Commit b1ac128

Browse files
authored
Merge pull request #22 from p-x9/feature/relocation-info
Section Relocation Info
2 parents 14d629e + 325f56c commit b1ac128

File tree

7 files changed

+531
-0
lines changed

7 files changed

+531
-0
lines changed

Sources/MachOKit/LoadCommand/Model/Section.swift

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ public protocol SectionProtocol: LayoutWrapper {
2121

2222
/// returns nil except when type is `cstring_literals
2323
func strings(in machO: MachOFile) -> MachOFile.Strings?
24+
25+
/// relocation informations.
26+
/// (contains only in object file (.o))
27+
///
28+
/// It can also be obtained with the following command
29+
/// ```sh
30+
/// otool -r <path to object file>
31+
/// ```
32+
func relocations(in machO: MachOFile) -> DataSequence<Relocation>
2433
}
2534

2635
public struct Section: SectionProtocol {
@@ -170,3 +179,56 @@ extension Section64 {
170179
_strings(in: machO, sectionOffset: layout.offset, sectionSize: UInt64(layout.size))
171180
}
172181
}
182+
183+
extension SectionProtocol {
184+
fileprivate func _relocations(
185+
in machO: MachOFile,
186+
reloff: UInt32,
187+
nreloc: UInt32
188+
) -> DataSequence<Relocation> {
189+
machO.fileHandle.seek(
190+
toFileOffset: numericCast(reloff)
191+
)
192+
var data = machO.fileHandle.readData(
193+
ofLength: numericCast(nreloc) * MemoryLayout<relocation_info>.size
194+
)
195+
196+
if machO.isSwapped {
197+
data.withUnsafeMutableBytes {
198+
guard let baseAddress = $0.baseAddress else { return }
199+
let ptr = baseAddress
200+
.assumingMemoryBound(to: relocation_info.self)
201+
swap_relocation_info(ptr, nreloc, NXHostByteOrder())
202+
}
203+
}
204+
205+
return DataSequence<Relocation>(
206+
data: data,
207+
numberOfElements: numericCast(nreloc)
208+
)
209+
}
210+
}
211+
212+
extension Section64 {
213+
public func relocations(
214+
in machO: MachOFile
215+
) -> DataSequence<Relocation> {
216+
_relocations(
217+
in: machO,
218+
reloff: layout.reloff,
219+
nreloc: layout.nreloc
220+
)
221+
}
222+
}
223+
224+
extension Section {
225+
public func relocations(
226+
in machO: MachOFile
227+
) -> DataSequence<Relocation> {
228+
_relocations(
229+
in: machO,
230+
reloff: layout.reloff,
231+
nreloc: layout.nreloc
232+
)
233+
}
234+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//
2+
// Relocation.swift
3+
//
4+
//
5+
// Created by p-x9 on 2024/01/10.
6+
//
7+
//
8+
9+
import Foundation
10+
11+
public struct Relocation {
12+
public enum Info {
13+
case general(RelocationInfo)
14+
case scattered(ScatteredRelocationInfo)
15+
}
16+
17+
public let _data: UInt64
18+
19+
public var isScattered: Bool {
20+
_data & UInt64(R_SCATTERED) != 0
21+
}
22+
23+
public var info: Info {
24+
var buffer = _data
25+
if isScattered {
26+
let info: ScatteredRelocationInfo = withUnsafePointer(
27+
to: &buffer,
28+
{
29+
let ptr = UnsafeRawPointer($0)
30+
return ptr.autoBoundPointee()
31+
}
32+
)
33+
return .scattered(info)
34+
} else {
35+
let info: RelocationInfo = withUnsafePointer(
36+
to: &buffer,
37+
{
38+
let ptr = UnsafeRawPointer($0)
39+
return ptr.autoBoundPointee()
40+
}
41+
)
42+
return .general(info)
43+
}
44+
}
45+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//
2+
// RelocationInfo.swift
3+
//
4+
//
5+
// Created by p-x9 on 2024/01/10.
6+
//
7+
//
8+
9+
import Foundation
10+
11+
public struct RelocationInfo: LayoutWrapper {
12+
public typealias Layout = relocation_info
13+
14+
public var layout: Layout
15+
}
16+
17+
extension RelocationInfo {
18+
public var isRelocatedPCRelative: Bool {
19+
layout.r_pcrel != 0
20+
}
21+
22+
public var length: RelocationLength? {
23+
.init(rawValue: layout.r_length)
24+
}
25+
26+
public var isExternal: Bool {
27+
layout.r_extern != 0
28+
}
29+
30+
public var isScattered: Bool {
31+
UInt32(bitPattern: layout.r_address) & R_SCATTERED != 0
32+
}
33+
34+
public var symbolIndex: Int? {
35+
isExternal ? numericCast(layout.r_symbolnum) : nil
36+
}
37+
38+
public var sectionOrdinal: Int? {
39+
isExternal ? nil : numericCast(layout.r_symbolnum)
40+
}
41+
42+
public func type(for cpuType: CPUType) -> RelocationType? {
43+
.init(rawValue: layout.r_type, for: cpuType)
44+
}
45+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// RelocationLength.swift
3+
//
4+
//
5+
// Created by p-x9 on 2024/01/10.
6+
//
7+
//
8+
9+
import Foundation
10+
11+
public enum RelocationLength: UInt32 {
12+
case byte
13+
case word
14+
case long
15+
case quad
16+
}
17+
18+
extension RelocationLength: CustomStringConvertible {
19+
public var description: String {
20+
switch self {
21+
case .byte: "byte"
22+
case .word: "word"
23+
case .long: "long"
24+
case .quad: "quad"
25+
}
26+
}
27+
}

0 commit comments

Comments
 (0)