19
19
#include " llvm/Object/IRObjectFile.h"
20
20
#include " llvm/Object/MachO.h"
21
21
#include " llvm/Object/MachOUniversal.h"
22
- #include " llvm/Support/FileOutputBuffer .h"
22
+ #include " llvm/Support/SmallVectorMemoryBuffer .h"
23
23
24
24
using namespace llvm ;
25
25
using namespace object ;
@@ -258,8 +258,8 @@ buildFatArchList(ArrayRef<Slice> Slices) {
258
258
return FatArchList;
259
259
}
260
260
261
- Error object::writeUniversalBinary (ArrayRef<Slice> Slices,
262
- StringRef OutputFileName ) {
261
+ static Error writeUniversalBinaryToStream (ArrayRef<Slice> Slices,
262
+ raw_ostream &Out ) {
263
263
MachO::fat_header FatHeader;
264
264
FatHeader.magic = MachO::FAT_MAGIC;
265
265
FatHeader.nfat_arch = Slices.size ();
@@ -270,42 +270,63 @@ Error object::writeUniversalBinary(ArrayRef<Slice> Slices,
270
270
return FatArchListOrErr.takeError ();
271
271
SmallVector<MachO::fat_arch, 2 > FatArchList = *FatArchListOrErr;
272
272
273
- const bool IsExecutable = any_of (Slices, [](Slice S) {
274
- return sys::fs::can_execute (S.getBinary ()->getFileName ());
275
- });
276
- const uint64_t OutputFileSize =
277
- static_cast <uint64_t >(FatArchList.back ().offset ) +
278
- FatArchList.back ().size ;
279
- Expected<std::unique_ptr<FileOutputBuffer>> OutFileOrError =
280
- FileOutputBuffer::create (OutputFileName, OutputFileSize,
281
- IsExecutable ? FileOutputBuffer::F_executable
282
- : 0 );
283
- if (!OutFileOrError)
284
- return createFileError (OutputFileName, OutFileOrError.takeError ());
285
- std::unique_ptr<FileOutputBuffer> OutFile = std::move (OutFileOrError.get ());
286
- std::memset (OutFile->getBufferStart (), 0 , OutputFileSize);
287
-
288
273
if (sys::IsLittleEndianHost)
289
274
MachO::swapStruct (FatHeader);
290
- std::memcpy (OutFile->getBufferStart (), &FatHeader, sizeof (MachO::fat_header));
275
+ Out.write (reinterpret_cast <const char *>(&FatHeader),
276
+ sizeof (MachO::fat_header));
291
277
292
- for ( size_t Index = 0 , Size = Slices. size (); Index < Size ; ++Index) {
293
- MemoryBufferRef BufferRef = Slices[Index]. getBinary ()-> getMemoryBufferRef ();
294
- std::copy (BufferRef. getBufferStart (), BufferRef. getBufferEnd (),
295
- OutFile-> getBufferStart () + FatArchList[Index]. offset );
296
- }
278
+ if (sys::IsLittleEndianHost)
279
+ for (MachO::fat_arch &FA : FatArchList)
280
+ MachO::swapStruct (FA);
281
+ Out. write ( reinterpret_cast < const char *>( FatArchList. data ()),
282
+ sizeof (MachO::fat_arch) * FatArchList. size ());
297
283
298
- // FatArchs written after Slices in order to reduce the number of swaps for
299
- // the LittleEndian case
300
284
if (sys::IsLittleEndianHost)
301
285
for (MachO::fat_arch &FA : FatArchList)
302
286
MachO::swapStruct (FA);
303
- std::memcpy (OutFile->getBufferStart () + sizeof (MachO::fat_header),
304
- FatArchList.begin (),
305
- sizeof (MachO::fat_arch) * FatArchList.size ());
306
287
307
- if (Error E = OutFile->commit ())
308
- return createFileError (OutputFileName, std::move (E));
288
+ size_t Offset =
289
+ sizeof (MachO::fat_header) + sizeof (MachO::fat_arch) * FatArchList.size ();
290
+ for (size_t Index = 0 , Size = Slices.size (); Index < Size ; ++Index) {
291
+ MemoryBufferRef BufferRef = Slices[Index].getBinary ()->getMemoryBufferRef ();
292
+ assert ((Offset <= FatArchList[Index].offset ) && " Incorrect slice offset" );
293
+ Out.write_zeros (FatArchList[Index].offset - Offset);
294
+ Out.write (BufferRef.getBufferStart (), BufferRef.getBufferSize ());
295
+ Offset = FatArchList[Index].offset + BufferRef.getBufferSize ();
296
+ }
309
297
298
+ Out.flush ();
310
299
return Error::success ();
311
300
}
301
+
302
+ Error object::writeUniversalBinary (ArrayRef<Slice> Slices,
303
+ StringRef OutputFileName) {
304
+ const bool IsExecutable = any_of (Slices, [](Slice S) {
305
+ return sys::fs::can_execute (S.getBinary ()->getFileName ());
306
+ });
307
+ unsigned Mode = sys::fs::all_read | sys::fs::all_write;
308
+ if (IsExecutable)
309
+ Mode |= sys::fs::all_exe;
310
+ Expected<sys::fs::TempFile> Temp = sys::fs::TempFile::create (
311
+ OutputFileName + " .temp-universal-%%%%%%" , Mode);
312
+ if (!Temp)
313
+ return Temp.takeError ();
314
+ raw_fd_ostream Out (Temp->FD , false );
315
+ if (Error E = writeUniversalBinaryToStream (Slices, Out)) {
316
+ if (Error DiscardError = Temp->discard ())
317
+ return joinErrors (std::move (E), std::move (DiscardError));
318
+ return E;
319
+ }
320
+ return Temp->keep (OutputFileName);
321
+ }
322
+
323
+ Expected<std::unique_ptr<MemoryBuffer>>
324
+ object::writeUniversalBinaryToBuffer (ArrayRef<Slice> Slices) {
325
+ SmallVector<char , 0 > Buffer;
326
+ raw_svector_ostream Out (Buffer);
327
+
328
+ if (Error E = writeUniversalBinaryToStream (Slices, Out))
329
+ return std::move (E);
330
+
331
+ return std::make_unique<SmallVectorMemoryBuffer>(std::move (Buffer));
332
+ }
0 commit comments