Skip to content

Commit 5f9d0bf

Browse files
Added LLVM Object File support (#72)
* Added LLVM Object File support * Fixed type name and commented deinits.
1 parent d9bd512 commit 5f9d0bf

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed

Sources/LLVM/ObjectFile.swift

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#if !NO_SWIFTPM
2+
import cllvm
3+
#endif
4+
5+
/// An in-memory representation of a platform object file.
6+
public class ObjectFile {
7+
let llvm: LLVMObjectFileRef
8+
9+
/// Creates an `ObjectFile` with the contents of a provided memory buffer.
10+
/// - parameter memoryBuffer: A memory buffer containing a valid binary
11+
/// object file.
12+
public init?(memoryBuffer: MemoryBuffer) {
13+
guard let file = LLVMCreateObjectFile(memoryBuffer.llvm) else {
14+
return nil
15+
}
16+
self.llvm = file
17+
}
18+
19+
/// Creates an `ObjectFile` with the contents of the object file at
20+
/// the provided path.
21+
/// - parameter path: The absolute file path on your filesystem.
22+
public convenience init?(path: String) {
23+
guard let memoryBuffer = try? MemoryBuffer(contentsOf: path) else {
24+
return nil
25+
}
26+
self.init(memoryBuffer: memoryBuffer)
27+
}
28+
29+
/// Returns a sequence of all the sections in this object file.
30+
public var sections: SectionSequence {
31+
return SectionSequence(llvm: LLVMGetSections(llvm), object: self)
32+
}
33+
34+
/// Returns a sequence of all the symbols in this object file.
35+
public var symbols: SymbolSequence {
36+
return SymbolSequence(llvm: LLVMGetSymbols(llvm), object: self)
37+
}
38+
39+
// FIXME: Re-introduce this when disposal becomes safe.
40+
// deinit {
41+
// LLVMDisposeObjectFile(llvm)
42+
// }
43+
}
44+
45+
/// A Section represents one of the binary sections in an object file.
46+
public struct Section {
47+
/// The section's declared name.
48+
public let name: String
49+
/// The size of the contents of the section.
50+
public let size: Int
51+
/// The raw contents of the section.
52+
public let contents: String
53+
/// The address of the section in the object file.
54+
public let address: Int
55+
56+
internal init(fromIterator si: LLVMSectionIteratorRef) {
57+
name = String(cString: LLVMGetSectionName(si))
58+
size = Int(LLVMGetSectionSize(si))
59+
contents = String(cString: LLVMGetSectionContents(si))
60+
address = Int(LLVMGetSectionAddress(si))
61+
}
62+
}
63+
64+
/// A sequence for iterating over the sections in an object file.
65+
public class SectionSequence: Sequence {
66+
let llvm: LLVMSectionIteratorRef
67+
let objectFile: ObjectFile
68+
69+
init(llvm: LLVMSectionIteratorRef, object: ObjectFile) {
70+
self.llvm = llvm
71+
self.objectFile = object
72+
}
73+
74+
/// Makes an iterator that iterates over the sections in an object file.
75+
public func makeIterator() -> AnyIterator<Section> {
76+
return AnyIterator {
77+
if LLVMIsSectionIteratorAtEnd(self.objectFile.llvm, self.llvm) != 0 {
78+
return nil
79+
}
80+
defer { LLVMMoveToNextSection(self.llvm) }
81+
return Section(fromIterator: self.llvm)
82+
}
83+
}
84+
85+
// FIXME: Re-introduce this when disposal becomes safe.
86+
// deinit {
87+
// LLVMDisposeSectionIterator(llvm)
88+
// }
89+
}
90+
91+
/// A symbol is a top-level addressable entity in an object file.
92+
public struct Symbol {
93+
/// The symbol name.
94+
public let name: String
95+
/// The size of the data in the symbol.
96+
public let size: Int
97+
/// The address of the symbol in the object file.
98+
public let address: Int
99+
100+
internal init(fromIterator si: LLVMSymbolIteratorRef) {
101+
self.name = String(cString: LLVMGetSymbolName(si))
102+
self.size = Int(LLVMGetSymbolSize(si))
103+
self.address = Int(LLVMGetSymbolAddress(si))
104+
}
105+
}
106+
107+
/// A Relocation represents the contents of a relocated symbol in the dynamic
108+
/// linker.
109+
public struct Relocation {
110+
public let type: Int
111+
public let offset: Int
112+
public let symbol: Symbol
113+
public let typeName: String
114+
115+
internal init(fromIterator ri: LLVMRelocationIteratorRef) {
116+
self.type = Int(LLVMGetRelocationType(ri))
117+
self.offset = Int(LLVMGetRelocationOffset(ri))
118+
self.symbol = Symbol(fromIterator: LLVMGetRelocationSymbol(ri))
119+
self.typeName = String(cString: LLVMGetRelocationTypeName(ri))
120+
}
121+
}
122+
123+
/// A sequence for iterating over the relocations in an object file.
124+
public class RelocationSequence: Sequence {
125+
let llvm: LLVMRelocationIteratorRef
126+
let sectionIterator: LLVMSectionIteratorRef
127+
128+
init(llvm: LLVMRelocationIteratorRef, sectionIterator: LLVMSectionIteratorRef) {
129+
self.llvm = llvm
130+
self.sectionIterator = sectionIterator
131+
}
132+
133+
/// Creates an iterator that will iterate over all relocations in an object
134+
/// file.
135+
public func makeIterator() -> AnyIterator<Relocation> {
136+
return AnyIterator {
137+
if LLVMIsRelocationIteratorAtEnd(self.sectionIterator, self.llvm) != 0 {
138+
return nil
139+
}
140+
defer { LLVMMoveToNextRelocation(self.llvm) }
141+
return Relocation(fromIterator: self.llvm)
142+
}
143+
}
144+
145+
// FIXME: Re-introduce this when disposal becomes safe.
146+
// deinit {
147+
// LLVMDisposeSectionIterator(llvm)
148+
// }
149+
}
150+
151+
/// A sequence for iterating over the symbols in an object file.
152+
public class SymbolSequence: Sequence {
153+
let llvm: LLVMSymbolIteratorRef
154+
let object: ObjectFile
155+
156+
init(llvm: LLVMSymbolIteratorRef, object: ObjectFile) {
157+
self.llvm = llvm
158+
self.object = object
159+
}
160+
161+
/// Creates an iterator that will iterate over all symbols in an object
162+
/// file.
163+
public func makeIterator() -> AnyIterator<Symbol> {
164+
return AnyIterator {
165+
if LLVMIsSymbolIteratorAtEnd(self.object.llvm, self.llvm) != 0 {
166+
return nil
167+
}
168+
defer { LLVMMoveToNextSymbol(self.llvm) }
169+
return Symbol(fromIterator: self.llvm)
170+
}
171+
}
172+
173+
// FIXME: Re-introduce this when disposal becomes safe.
174+
// deinit {
175+
// LLVMDisposeSymbolIterator(llvm)
176+
// }
177+
}

0 commit comments

Comments
 (0)