Skip to content

Commit 2d03dc1

Browse files
committed
Update for reviewed APIs
1 parent dd26f01 commit 2d03dc1

File tree

5 files changed

+141
-33
lines changed

5 files changed

+141
-33
lines changed

Sources/LLVM/ObjectFile.swift

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public class BinaryFile {
118118
}
119119

120120
/// An in-memory representation of a format-independent object file.
121-
public final class ObjectFile: BinaryFile {
121+
public class ObjectFile: BinaryFile {
122122
override init(llvm: LLVMBinaryRef, buffer: MemoryBuffer) {
123123
super.init(llvm: llvm, buffer: buffer)
124124
precondition(self.kind != .machOUniversalBinary,
@@ -139,17 +139,27 @@ public final class ObjectFile: BinaryFile {
139139

140140
/// Returns a sequence of all the sections in this object file.
141141
public var sections: SectionSequence {
142-
return SectionSequence(llvm: LLVMObjectFileGetSections(llvm), object: self)
142+
return SectionSequence(llvm: LLVMObjectFileCopySectionIterator(llvm), object: self)
143143
}
144144

145145
/// Returns a sequence of all the symbols in this object file.
146146
public var symbols: SymbolSequence {
147-
return SymbolSequence(llvm: LLVMObjectFileGetSymbols(llvm), object: self)
147+
return SymbolSequence(llvm: LLVMObjectFileCopySymbolIterator(llvm), object: self)
148148
}
149149
}
150150

151151
/// An in-memory representation of a Mach-O universal binary file.
152152
public final class MachOUniversalBinaryFile: BinaryFile {
153+
/// Creates an `MachOUniversalBinaryFile` with the contents of the object file at
154+
/// the provided path.
155+
/// - parameter path: The absolute file path on your filesystem.
156+
/// - throws: `MemoryBufferError` or `BinaryFileError` if there was an error
157+
/// on creation
158+
public convenience init(path: String) throws {
159+
let memoryBuffer = try MemoryBuffer(contentsOf: path)
160+
try self.init(memoryBuffer: memoryBuffer)
161+
}
162+
153163
/// Creates a Mach-O universal binary file with the contents of a provided
154164
/// memory buffer.
155165
///
@@ -159,7 +169,9 @@ public final class MachOUniversalBinaryFile: BinaryFile {
159169
/// - throws: `BinaryFileError` if there was an error on creation.
160170
public override init(memoryBuffer: MemoryBuffer, in context: Context = .global) throws {
161171
try super.init(memoryBuffer: memoryBuffer, in: context)
162-
precondition(self.kind == .machOUniversalBinary)
172+
guard self.kind == .machOUniversalBinary else {
173+
throw BinaryFileError.couldNotCreate("File is not a Mach-O universal binary")
174+
}
163175
}
164176

165177
/// Retrieves the object file for a specific architecture, if it exists.
@@ -169,16 +181,37 @@ public final class MachOUniversalBinaryFile: BinaryFile {
169181
/// universal binary file.
170182
/// - Returns: An object file for the given architecture if it exists.
171183
/// - throws: `BinaryFileError` if there was an error on creation.
172-
public func objectFile(for architecture: Triple.Architecture) throws -> ObjectFile {
184+
public func objectFile(for architecture: Triple.Architecture) throws -> Slice {
173185
var error: UnsafeMutablePointer<Int8>?
174186
let archName = architecture.rawValue
175187
let archFile: LLVMBinaryRef = LLVMUniversalBinaryCopyObjectForArchitecture(self.llvm, archName, archName.count, &error)
176188
if let error = error {
177189
defer { LLVMDisposeMessage(error) }
178190
throw BinaryFileError.couldNotCreate(String(cString: error))
179191
}
180-
let buffer = MemoryBuffer(llvm: LLVMBinaryGetMemoryBuffer(archFile))
181-
return ObjectFile(llvm: archFile, buffer: buffer)
192+
let buffer = MemoryBuffer(llvm: LLVMBinaryCopyMemoryBuffer(archFile))
193+
return Slice(parent: self, llvm: archFile, buffer: buffer)
194+
}
195+
196+
/// Represents an architecture-specific slice of a Mach-O universal binary
197+
/// file.
198+
public final class Slice: ObjectFile {
199+
// Maintain a strong reference to our parent binary so the backing buffer
200+
// doesn't disappear on us.
201+
private let parent: MachOUniversalBinaryFile
202+
203+
fileprivate init(parent: MachOUniversalBinaryFile, llvm: LLVMBinaryRef, buffer: MemoryBuffer) {
204+
self.parent = parent
205+
super.init(llvm: llvm, buffer: buffer)
206+
}
207+
208+
private override init(llvm: LLVMBinaryRef, buffer: MemoryBuffer) {
209+
fatalError()
210+
}
211+
212+
private override init(memoryBuffer: MemoryBuffer, in context: Context = .global) throws {
213+
fatalError()
214+
}
182215
}
183216
}
184217

@@ -221,22 +254,26 @@ public struct Section {
221254

222255
/// A sequence for iterating over the sections in an object file.
223256
public class SectionSequence: Sequence {
224-
let llvm: LLVMSectionIteratorRef
257+
let llvm: LLVMSectionIteratorRef?
225258
let objectFile: ObjectFile
226259

227-
init(llvm: LLVMSectionIteratorRef, object: ObjectFile) {
260+
init(llvm: LLVMSectionIteratorRef?, object: ObjectFile) {
228261
self.llvm = llvm
229262
self.objectFile = object
230263
}
231264

232265
/// Makes an iterator that iterates over the sections in an object file.
233266
public func makeIterator() -> AnyIterator<Section> {
234267
return AnyIterator {
235-
if LLVMObjectFileIsSectionIteratorAtEnd(self.objectFile.llvm, self.llvm) != 0 {
268+
guard let it = self.llvm else {
236269
return nil
237270
}
238-
defer { LLVMMoveToNextSection(self.llvm) }
239-
return Section(fromIterator: self.llvm)
271+
272+
if LLVMObjectFileIsSectionIteratorAtEnd(self.objectFile.llvm, it) != 0 {
273+
return nil
274+
}
275+
defer { LLVMMoveToNextSection(it) }
276+
return Section(fromIterator: it)
240277
}
241278
}
242279

@@ -320,10 +357,10 @@ public class RelocationSequence: Sequence {
320357

321358
/// A sequence for iterating over the symbols in an object file.
322359
public class SymbolSequence: Sequence {
323-
let llvm: LLVMSymbolIteratorRef
360+
let llvm: LLVMSymbolIteratorRef?
324361
let object: ObjectFile
325362

326-
init(llvm: LLVMSymbolIteratorRef, object: ObjectFile) {
363+
init(llvm: LLVMSymbolIteratorRef?, object: ObjectFile) {
327364
self.llvm = llvm
328365
self.object = object
329366
}
@@ -332,11 +369,14 @@ public class SymbolSequence: Sequence {
332369
/// file.
333370
public func makeIterator() -> AnyIterator<Symbol> {
334371
return AnyIterator {
335-
if LLVMObjectFileIsSymbolIteratorAtEnd(self.object.llvm, self.llvm) != 0 {
372+
guard let it = self.llvm else {
373+
return nil
374+
}
375+
if LLVMObjectFileIsSymbolIteratorAtEnd(self.object.llvm, it) != 0 {
336376
return nil
337377
}
338-
defer { LLVMMoveToNextSymbol(self.llvm) }
339-
return Symbol(fromIterator: self.llvm)
378+
defer { LLVMMoveToNextSymbol(it) }
379+
return Symbol(fromIterator: it)
340380
}
341381
}
342382

Sources/llvmshims/include/shim.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,16 @@ typedef struct LLVMOpaqueBinary *LLVMBinaryRef;
5757

5858
LLVMBinaryType LLVMBinaryGetType(LLVMBinaryRef BR);
5959
LLVMBinaryRef LLVMCreateBinary(LLVMMemoryBufferRef MemBuf, LLVMContextRef Context, char **ErrorMessage);
60-
LLVMMemoryBufferRef LLVMBinaryGetMemoryBuffer(LLVMBinaryRef BR);
60+
LLVMMemoryBufferRef LLVMBinaryCopyMemoryBuffer(LLVMBinaryRef BR);
6161
void LLVMDisposeBinary(LLVMBinaryRef BR);
6262

6363
LLVMBinaryRef LLVMUniversalBinaryCopyObjectForArchitecture(LLVMBinaryRef BR, const char *Arch, size_t ArchLen, char **ErrorMessage);
6464

65-
LLVMSectionIteratorRef LLVMObjectFileGetSections(LLVMBinaryRef BR);
65+
LLVMSectionIteratorRef LLVMObjectFileCopySectionIterator(LLVMBinaryRef BR);
6666

6767
LLVMBool LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR,
6868
LLVMSectionIteratorRef SI);
69-
LLVMSymbolIteratorRef LLVMObjectFileGetSymbols(LLVMBinaryRef BR);
69+
LLVMSymbolIteratorRef LLVMObjectFileCopySymbolIterator(LLVMBinaryRef BR);
7070

7171
LLVMBool LLVMObjectFileIsSymbolIteratorAtEnd(LLVMBinaryRef BR,
7272
LLVMSymbolIteratorRef SI);

Sources/llvmshims/src/shim.cpp

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,16 @@
99
extern "C" {
1010
typedef struct LLVMOpaqueBinary *LLVMBinaryRef;
1111

12-
size_t LLVMSwiftCountIntrinsics(void);
13-
const char *LLVMSwiftGetIntrinsicAtIndex(size_t index);
12+
// https://reviews.llvm.org/D59697
1413
unsigned LLVMLookupIntrinsicID(const char *Name, size_t NameLen);
14+
15+
// Not to be upstreamed: They support the hacks that power our dynamic member
16+
// lookup machinery for intrinsics.
17+
const char *LLVMSwiftGetIntrinsicAtIndex(size_t index);
18+
size_t LLVMSwiftCountIntrinsics(void);
19+
20+
// Not to be upstreamed: There's no value in this without a full Triple
21+
// API. And we have chosen to port instead of wrap.
1522
const char *LLVMGetARMCanonicalArchName(const char *Name, size_t NameLen);
1623

1724
typedef enum {
@@ -24,6 +31,7 @@ extern "C" {
2431
LLVMARMProfileKind LLVMARMParseArchProfile(const char *Name, size_t NameLen);
2532
unsigned LLVMARMParseArchVersion(const char *Name, size_t NameLen);
2633

34+
// https://reviews.llvm.org/D60366
2735
typedef enum {
2836
LLVMBinaryTypeArchive,
2937
LLVMBinaryTypeMachOUniversalBinary,
@@ -59,17 +67,21 @@ extern "C" {
5967
} LLVMBinaryType;
6068

6169
LLVMBinaryType LLVMBinaryGetType(LLVMBinaryRef BR);
70+
71+
// https://reviews.llvm.org/D60322
6272
LLVMBinaryRef LLVMCreateBinary(LLVMMemoryBufferRef MemBuf, LLVMContextRef Context, char **ErrorMessage);
63-
LLVMMemoryBufferRef LLVMBinaryGetMemoryBuffer(LLVMBinaryRef BR);
73+
LLVMMemoryBufferRef LLVMBinaryCopyMemoryBuffer(LLVMBinaryRef BR);
6474
void LLVMDisposeBinary(LLVMBinaryRef BR);
6575

76+
// https://reviews.llvm.org/D60378
6677
LLVMBinaryRef LLVMUniversalBinaryCopyObjectForArchitecture(LLVMBinaryRef BR, const char *Arch, size_t ArchLen, char **ErrorMessage);
6778

68-
LLVMSectionIteratorRef LLVMObjectFileGetSections(LLVMBinaryRef BR);
79+
// https://reviews.llvm.org/D60407
80+
LLVMSectionIteratorRef LLVMObjectFileCopySectionIterator(LLVMBinaryRef BR);
6981

7082
LLVMBool LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR,
7183
LLVMSectionIteratorRef SI);
72-
LLVMSymbolIteratorRef LLVMObjectFileGetSymbols(LLVMBinaryRef BR);
84+
LLVMSymbolIteratorRef LLVMObjectFileCopySymbolIterator(LLVMBinaryRef BR);
7385

7486
LLVMBool LLVMObjectFileIsSymbolIteratorAtEnd(LLVMBinaryRef BR,
7587
LLVMSymbolIteratorRef SI);
@@ -107,7 +119,7 @@ wrap(const symbol_iterator *SI) {
107119
}
108120

109121
LLVMBinaryType LLVMBinaryGetType(LLVMBinaryRef BR) {
110-
class BinaryTypeMapper : public Binary {
122+
class BinaryTypeMapper final : public Binary {
111123
public:
112124
static LLVMBinaryType mapBinaryTypeToLLVMBinaryType(unsigned Kind) {
113125
switch (Kind) {
@@ -160,7 +172,7 @@ LLVMBinaryRef LLVMCreateBinary(LLVMMemoryBufferRef MemBuf, LLVMContextRef Contex
160172
return wrap(ObjOrErr.get().release());
161173
}
162174

163-
LLVMMemoryBufferRef LLVMBinaryGetMemoryBuffer(LLVMBinaryRef BR) {
175+
LLVMMemoryBufferRef LLVMBinaryCopyMemoryBuffer(LLVMBinaryRef BR) {
164176
auto Buf = unwrap(BR)->getMemoryBufferRef();
165177
return wrap(llvm::MemoryBuffer::getMemBuffer(
166178
Buf.getBuffer(), Buf.getBufferIdentifier(),
@@ -183,10 +195,12 @@ LLVMBinaryRef LLVMUniversalBinaryCopyObjectForArchitecture(LLVMBinaryRef BR, con
183195
return wrap(ObjOrErr.get().release());
184196
}
185197

186-
LLVMSectionIteratorRef LLVMObjectFileGetSections(LLVMBinaryRef BR) {
198+
LLVMSectionIteratorRef LLVMObjectFileCopySectionIterator(LLVMBinaryRef BR) {
187199
auto OF = cast<ObjectFile>(unwrap(BR));
188-
section_iterator SI = OF->section_begin();
189-
return wrap(new section_iterator(SI));
200+
auto sections = OF->sections();
201+
if (sections.begin() == sections.end())
202+
return nullptr;
203+
return wrap(new section_iterator(sections.begin()));
190204
}
191205

192206
LLVMBool LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR,
@@ -195,10 +209,12 @@ LLVMBool LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR,
195209
return (*unwrap(SI) == OF->section_end()) ? 1 : 0;
196210
}
197211

198-
LLVMSymbolIteratorRef LLVMObjectFileGetSymbols(LLVMBinaryRef BR) {
212+
LLVMSymbolIteratorRef LLVMObjectFileCopySymbolIterator(LLVMBinaryRef BR) {
199213
auto OF = cast<ObjectFile>(unwrap(BR));
200-
symbol_iterator SI = OF->symbol_begin();
201-
return wrap(new symbol_iterator(SI));
214+
auto symbols = OF->symbols();
215+
if (symbols.begin() == symbols.end())
216+
return nullptr;
217+
return wrap(new symbol_iterator(symbols.begin()));
202218
}
203219

204220
LLVMBool LLVMObjectFileIsSymbolIteratorAtEnd(LLVMBinaryRef BR,

Tests/LLVMTests/BinarySpec.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import LLVM
2+
import XCTest
3+
import FileCheck
4+
import Foundation
5+
6+
class BinarySpec : XCTestCase {
7+
private func readThisObjectFile() -> ObjectFile {
8+
let result = Result<MachOUniversalBinaryFile, Error>(catching: {
9+
try MachOUniversalBinaryFile(path: Bundle.main.executablePath!)
10+
})
11+
switch result {
12+
case .failure(_):
13+
guard let objectFile = try? ObjectFile(path: Bundle.main.executablePath!) else {
14+
fatalError("Missing object file for host architecture?")
15+
}
16+
return objectFile
17+
case let .success(binary):
18+
guard let objectFile = try? binary.objectFile(for: Triple.default.architecture) else {
19+
fatalError("Missing object file for host architecture?")
20+
}
21+
return objectFile
22+
}
23+
}
24+
25+
func testBinaryLifetimes() {
26+
let objectFile = self.readThisObjectFile()
27+
28+
#if !os(Linux) // Linux has some trouble reading ELF sections.
29+
var hasSections = false
30+
for _ in objectFile.sections {
31+
hasSections = true
32+
break
33+
}
34+
XCTAssertTrue(hasSections)
35+
#endif
36+
37+
var hasSymbols = false
38+
for _ in objectFile.symbols {
39+
hasSymbols = true
40+
break
41+
}
42+
XCTAssertTrue(hasSymbols)
43+
}
44+
45+
#if !os(macOS)
46+
static var allTests = testCase([
47+
("testBinaryLifetimes", testBinaryLifetimes),
48+
])
49+
#endif
50+
}
51+

Tests/LinuxMain.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import XCTest
55
#if !os(macOS)
66
XCTMain([
77
APIntSpec.allTests,
8+
BinarySpec.allTests,
89
BFCSpec.allTests,
910
ConstantSpec.allTests,
1011
DIBuilderSpec.allTests,

0 commit comments

Comments
 (0)