@@ -240,25 +240,48 @@ Expected<Slice> Slice::create(const IRObjectFile &IRO, uint32_t Align) {
240
240
return Slice{IRO, CPUType, CPUSubType, std::move (ArchName), Align};
241
241
}
242
242
243
- static Expected<SmallVector<MachO::fat_arch, 2 >>
243
+ template <typename FatArchTy> struct FatArchTraits {
244
+ static const uint64_t OffsetLimit;
245
+ static const std::string StructName;
246
+ static const uint8_t BitCount;
247
+ };
248
+
249
+ template <> struct FatArchTraits <MachO::fat_arch> {
250
+ static const uint64_t OffsetLimit = UINT32_MAX;
251
+ static const std::string StructName;
252
+ static const uint8_t BitCount = 32 ;
253
+ };
254
+ const std::string FatArchTraits<MachO::fat_arch>::StructName = " fat_arch" ;
255
+
256
+ template <> struct FatArchTraits <MachO::fat_arch_64> {
257
+ static const uint64_t OffsetLimit = UINT64_MAX;
258
+ static const std::string StructName;
259
+ static const uint8_t BitCount = 64 ;
260
+ };
261
+ const std::string FatArchTraits<MachO::fat_arch_64>::StructName = " fat_arch_64" ;
262
+
263
+ template <typename FatArchTy>
264
+ static Expected<SmallVector<FatArchTy, 2 >>
244
265
buildFatArchList (ArrayRef<Slice> Slices) {
245
- SmallVector<MachO::fat_arch , 2 > FatArchList;
266
+ SmallVector<FatArchTy , 2 > FatArchList;
246
267
uint64_t Offset =
247
- sizeof (MachO::fat_header) + Slices.size () * sizeof (MachO::fat_arch );
268
+ sizeof (MachO::fat_header) + Slices.size () * sizeof (FatArchTy );
248
269
249
270
for (const auto &S : Slices) {
250
271
Offset = alignTo (Offset, 1ull << S.getP2Alignment ());
251
- if (Offset > UINT32_MAX )
272
+ if (Offset > FatArchTraits<FatArchTy>::OffsetLimit )
252
273
return createStringError (
253
274
std::errc::invalid_argument,
254
- (" fat file too large to be created because the offset "
255
- " field in struct fat_arch is only 32-bits and the offset " +
275
+ (" fat file too large to be created because the offset field in the "
276
+ " struct " +
277
+ Twine (FatArchTraits<FatArchTy>::StructName) + " is only " +
278
+ Twine (FatArchTraits<FatArchTy>::BitCount) + " -bits and the offset " +
256
279
Twine (Offset) + " for " + S.getBinary ()->getFileName () +
257
280
" for architecture " + S.getArchString () + " exceeds that." )
258
281
.str ()
259
282
.c_str ());
260
283
261
- MachO::fat_arch FatArch;
284
+ FatArchTy FatArch;
262
285
FatArch.cputype = S.getCPUType ();
263
286
FatArch.cpusubtype = S.getCPUSubType ();
264
287
FatArch.offset = Offset;
@@ -270,35 +293,33 @@ buildFatArchList(ArrayRef<Slice> Slices) {
270
293
return FatArchList;
271
294
}
272
295
273
- Error object::writeUniversalBinaryToStream (ArrayRef<Slice> Slices,
274
- raw_ostream &Out) {
275
- MachO::fat_header FatHeader;
276
- FatHeader.magic = MachO::FAT_MAGIC;
277
- FatHeader.nfat_arch = Slices.size ();
278
-
279
- Expected<SmallVector<MachO::fat_arch, 2 >> FatArchListOrErr =
280
- buildFatArchList (Slices);
296
+ template <typename FatArchTy>
297
+ static Error writeUniversalArchsToStream (MachO::fat_header FatHeader,
298
+ ArrayRef<Slice> Slices,
299
+ raw_ostream &Out) {
300
+ Expected<SmallVector<FatArchTy, 2 >> FatArchListOrErr =
301
+ buildFatArchList<FatArchTy>(Slices);
281
302
if (!FatArchListOrErr)
282
303
return FatArchListOrErr.takeError ();
283
- SmallVector<MachO::fat_arch , 2 > FatArchList = *FatArchListOrErr;
304
+ SmallVector<FatArchTy , 2 > FatArchList = *FatArchListOrErr;
284
305
285
306
if (sys::IsLittleEndianHost)
286
307
MachO::swapStruct (FatHeader);
287
308
Out.write (reinterpret_cast <const char *>(&FatHeader),
288
309
sizeof (MachO::fat_header));
289
310
290
311
if (sys::IsLittleEndianHost)
291
- for (MachO::fat_arch &FA : FatArchList)
312
+ for (FatArchTy &FA : FatArchList)
292
313
MachO::swapStruct (FA);
293
314
Out.write (reinterpret_cast <const char *>(FatArchList.data ()),
294
- sizeof (MachO::fat_arch ) * FatArchList.size ());
315
+ sizeof (FatArchTy ) * FatArchList.size ());
295
316
296
317
if (sys::IsLittleEndianHost)
297
- for (MachO::fat_arch &FA : FatArchList)
318
+ for (FatArchTy &FA : FatArchList)
298
319
MachO::swapStruct (FA);
299
320
300
321
size_t Offset =
301
- sizeof (MachO::fat_header) + sizeof (MachO::fat_arch ) * FatArchList.size ();
322
+ sizeof (MachO::fat_header) + sizeof (FatArchTy ) * FatArchList.size ();
302
323
for (size_t Index = 0 , Size = Slices.size (); Index < Size; ++Index) {
303
324
MemoryBufferRef BufferRef = Slices[Index].getBinary ()->getMemoryBufferRef ();
304
325
assert ((Offset <= FatArchList[Index].offset ) && " Incorrect slice offset" );
@@ -311,8 +332,30 @@ Error object::writeUniversalBinaryToStream(ArrayRef<Slice> Slices,
311
332
return Error::success ();
312
333
}
313
334
335
+ Error object::writeUniversalBinaryToStream (ArrayRef<Slice> Slices,
336
+ raw_ostream &Out,
337
+ FatHeaderType HeaderType) {
338
+ MachO::fat_header FatHeader;
339
+ FatHeader.nfat_arch = Slices.size ();
340
+
341
+ switch (HeaderType) {
342
+ case FatHeaderType::Fat64Header:
343
+ FatHeader.magic = MachO::FAT_MAGIC_64;
344
+ return writeUniversalArchsToStream<MachO::fat_arch_64>(FatHeader, Slices,
345
+ Out);
346
+ break ;
347
+ case FatHeaderType::FatHeader:
348
+ FatHeader.magic = MachO::FAT_MAGIC;
349
+ return writeUniversalArchsToStream<MachO::fat_arch>(FatHeader, Slices, Out);
350
+ break ;
351
+ default :
352
+ llvm_unreachable (" Invalid fat header type" );
353
+ }
354
+ }
355
+
314
356
Error object::writeUniversalBinary (ArrayRef<Slice> Slices,
315
- StringRef OutputFileName) {
357
+ StringRef OutputFileName,
358
+ FatHeaderType HeaderType) {
316
359
const bool IsExecutable = any_of (Slices, [](Slice S) {
317
360
return sys::fs::can_execute (S.getBinary ()->getFileName ());
318
361
});
@@ -324,7 +367,7 @@ Error object::writeUniversalBinary(ArrayRef<Slice> Slices,
324
367
if (!Temp)
325
368
return Temp.takeError ();
326
369
raw_fd_ostream Out (Temp->FD , false );
327
- if (Error E = writeUniversalBinaryToStream (Slices, Out)) {
370
+ if (Error E = writeUniversalBinaryToStream (Slices, Out, HeaderType )) {
328
371
if (Error DiscardError = Temp->discard ())
329
372
return joinErrors (std::move (E), std::move (DiscardError));
330
373
return E;
0 commit comments