@@ -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.
152152public 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.
223256public 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.
322359public 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
0 commit comments