Skip to content

Commit aed1dc8

Browse files
committed
Added LLVM Object File support
1 parent fabfcc7 commit aed1dc8

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

Sources/LLVM/ObjectFile.swift

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#if !NO_SWIFTPM
2+
import cllvm
3+
#endif
4+
5+
public enum ObjectFileError: Error {
6+
case couldNotCreateFromBuffer(MemoryBuffer)
7+
}
8+
9+
/// An in-memory representation of a platform object file.
10+
public class ObjectFile {
11+
let llvm: LLVMObjectFileRef
12+
13+
public init?(memoryBuffer: MemoryBuffer) {
14+
guard let file = LLVMCreateObjectFile(memoryBuffer.llvm) else {
15+
return nil
16+
}
17+
self.llvm = file
18+
}
19+
20+
public convenience init?(path: String) throws {
21+
guard let memoryBuffer = try? MemoryBuffer(contentsOf: path) else {
22+
return nil
23+
}
24+
self.init(memoryBuffer: memoryBuffer)
25+
}
26+
27+
public var sections: SectionSequence {
28+
return SectionSequence(llvm: LLVMGetSections(llvm), object: self)
29+
}
30+
31+
public var symbols: SymbolSequence {
32+
return SymbolSequence(llvm: LLVMGetSymbols(llvm), object: self)
33+
}
34+
35+
deinit {
36+
LLVMDisposeObjectFile(llvm)
37+
}
38+
}
39+
40+
public struct Section {
41+
public let name: String
42+
public let size: Int
43+
public let contents: String
44+
public let address: Int
45+
46+
internal init(fromIterator si: LLVMSectionIteratorRef) {
47+
name = String(cString: LLVMGetSectionName(si))
48+
size = Int(LLVMGetSectionSize(si))
49+
contents = String(cString: LLVMGetSectionContents(si))
50+
address = Int(LLVMGetSectionAddress(si))
51+
}
52+
}
53+
54+
public class SectionSequence: Sequence {
55+
let llvm: LLVMSectionIteratorRef
56+
let objectFile: ObjectFile
57+
58+
init(llvm: LLVMSectionIteratorRef, object: ObjectFile) {
59+
self.llvm = llvm
60+
self.objectFile = object
61+
}
62+
63+
public func makeIterator() -> AnyIterator<Section> {
64+
return AnyIterator {
65+
if LLVMIsSectionIteratorAtEnd(self.objectFile.llvm, self.llvm) != 0 {
66+
return nil
67+
}
68+
defer { LLVMMoveToNextSection(self.llvm) }
69+
return Section(fromIterator: self.llvm)
70+
}
71+
}
72+
73+
deinit {
74+
LLVMDisposeSectionIterator(llvm)
75+
}
76+
}
77+
78+
public struct Symbol {
79+
public let name: String
80+
public let size: Int
81+
public let address: Int
82+
83+
internal init(fromIterator si: LLVMSymbolIteratorRef) {
84+
self.name = String(cString: LLVMGetSymbolName(si))
85+
self.size = Int(LLVMGetSymbolSize(si))
86+
self.address = Int(LLVMGetSymbolAddress(si))
87+
}
88+
}
89+
90+
public struct Relocation {
91+
public let type: Int
92+
public let offset: Int
93+
public let symbol: Symbol
94+
public let typeName: String
95+
96+
internal init(fromIterator ri: LLVMRelocationIteratorRef) {
97+
self.type = Int(LLVMGetRelocationType(ri))
98+
self.offset = Int(LLVMGetRelocationOffset(ri))
99+
self.symbol = Symbol(fromIterator: LLVMGetRelocationSymbol(ri))
100+
self.typeName = String(cString: LLVMGetRelocationTypeName(ri))
101+
}
102+
}
103+
104+
public class RelocationSequence: Sequence {
105+
let llvm: LLVMRelocationIteratorRef
106+
let sectionIterator: LLVMSectionIteratorRef
107+
108+
init(llvm: LLVMRelocationIteratorRef, sectionIterator: LLVMSectionIteratorRef) {
109+
self.llvm = llvm
110+
self.sectionIterator = sectionIterator
111+
}
112+
113+
public func makeIterator() -> AnyIterator<Relocation> {
114+
return AnyIterator {
115+
if LLVMIsRelocationIteratorAtEnd(self.sectionIterator, self.llvm) != 0 {
116+
return nil
117+
}
118+
defer { LLVMMoveToNextRelocation(self.llvm) }
119+
return Relocation(fromIterator: self.llvm)
120+
}
121+
}
122+
123+
deinit {
124+
LLVMDisposeSectionIterator(llvm)
125+
}
126+
}
127+
128+
public class SymbolSequence: Sequence {
129+
let llvm: LLVMSymbolIteratorRef
130+
let object: ObjectFile
131+
132+
init(llvm: LLVMRelocationIteratorRef, object: ObjectFile) {
133+
self.llvm = llvm
134+
self.object = object
135+
}
136+
137+
public func makeIterator() -> AnyIterator<Symbol> {
138+
return AnyIterator {
139+
if LLVMIsSymbolIteratorAtEnd(self.object.llvm, self.llvm) != 0 {
140+
return nil
141+
}
142+
defer { LLVMMoveToNextSymbol(self.llvm) }
143+
return Symbol(fromIterator: self.llvm)
144+
}
145+
}
146+
147+
deinit {
148+
LLVMDisposeSymbolIterator(llvm)
149+
}
150+
}

0 commit comments

Comments
 (0)