MachOObjcopy.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. //===- MachOObjcopy.cpp -----------------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "MachOObjcopy.h"
  9. #include "../llvm-objcopy.h"
  10. #include "CommonConfig.h"
  11. #include "MachO/MachOConfig.h"
  12. #include "MachOReader.h"
  13. #include "MachOWriter.h"
  14. #include "MultiFormatConfig.h"
  15. #include "llvm/ADT/DenseSet.h"
  16. #include "llvm/Object/ArchiveWriter.h"
  17. #include "llvm/Object/MachOUniversal.h"
  18. #include "llvm/Object/MachOUniversalWriter.h"
  19. #include "llvm/Support/Errc.h"
  20. #include "llvm/Support/Error.h"
  21. #include "llvm/Support/FileOutputBuffer.h"
  22. #include "llvm/Support/Path.h"
  23. #include "llvm/Support/SmallVectorMemoryBuffer.h"
  24. using namespace llvm;
  25. using namespace llvm::objcopy;
  26. using namespace llvm::objcopy::macho;
  27. using namespace llvm::object;
  28. using SectionPred = std::function<bool(const std::unique_ptr<Section> &Sec)>;
  29. using LoadCommandPred = std::function<bool(const LoadCommand &LC)>;
  30. #ifndef NDEBUG
  31. static bool isLoadCommandWithPayloadString(const LoadCommand &LC) {
  32. // TODO: Add support for LC_REEXPORT_DYLIB, LC_LOAD_UPWARD_DYLIB and
  33. // LC_LAZY_LOAD_DYLIB
  34. return LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_RPATH ||
  35. LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_ID_DYLIB ||
  36. LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_LOAD_DYLIB ||
  37. LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_LOAD_WEAK_DYLIB;
  38. }
  39. #endif
  40. static StringRef getPayloadString(const LoadCommand &LC) {
  41. assert(isLoadCommandWithPayloadString(LC) &&
  42. "unsupported load command encountered");
  43. return StringRef(reinterpret_cast<const char *>(LC.Payload.data()),
  44. LC.Payload.size())
  45. .rtrim('\0');
  46. }
  47. static Error removeSections(const CommonConfig &Config, Object &Obj) {
  48. SectionPred RemovePred = [](const std::unique_ptr<Section> &) {
  49. return false;
  50. };
  51. if (!Config.ToRemove.empty()) {
  52. RemovePred = [&Config, RemovePred](const std::unique_ptr<Section> &Sec) {
  53. return Config.ToRemove.matches(Sec->CanonicalName);
  54. };
  55. }
  56. if (Config.StripAll || Config.StripDebug) {
  57. // Remove all debug sections.
  58. RemovePred = [RemovePred](const std::unique_ptr<Section> &Sec) {
  59. if (Sec->Segname == "__DWARF")
  60. return true;
  61. return RemovePred(Sec);
  62. };
  63. }
  64. if (!Config.OnlySection.empty()) {
  65. // Overwrite RemovePred because --only-section takes priority.
  66. RemovePred = [&Config](const std::unique_ptr<Section> &Sec) {
  67. return !Config.OnlySection.matches(Sec->CanonicalName);
  68. };
  69. }
  70. return Obj.removeSections(RemovePred);
  71. }
  72. static void markSymbols(const CommonConfig &, Object &Obj) {
  73. // Symbols referenced from the indirect symbol table must not be removed.
  74. for (IndirectSymbolEntry &ISE : Obj.IndirectSymTable.Symbols)
  75. if (ISE.Symbol)
  76. (*ISE.Symbol)->Referenced = true;
  77. }
  78. static void updateAndRemoveSymbols(const CommonConfig &Config,
  79. const MachOConfig &MachOConfig,
  80. Object &Obj) {
  81. for (SymbolEntry &Sym : Obj.SymTable) {
  82. auto I = Config.SymbolsToRename.find(Sym.Name);
  83. if (I != Config.SymbolsToRename.end())
  84. Sym.Name = std::string(I->getValue());
  85. }
  86. auto RemovePred = [Config, MachOConfig,
  87. &Obj](const std::unique_ptr<SymbolEntry> &N) {
  88. if (N->Referenced)
  89. return false;
  90. if (MachOConfig.KeepUndefined && N->isUndefinedSymbol())
  91. return false;
  92. if (N->n_desc & MachO::REFERENCED_DYNAMICALLY)
  93. return false;
  94. if (Config.StripAll)
  95. return true;
  96. if (Config.DiscardMode == DiscardType::All && !(N->n_type & MachO::N_EXT))
  97. return true;
  98. // This behavior is consistent with cctools' strip.
  99. if (MachOConfig.StripSwiftSymbols &&
  100. (Obj.Header.Flags & MachO::MH_DYLDLINK) && Obj.SwiftVersion &&
  101. *Obj.SwiftVersion && N->isSwiftSymbol())
  102. return true;
  103. return false;
  104. };
  105. Obj.SymTable.removeSymbols(RemovePred);
  106. }
  107. template <typename LCType>
  108. static void updateLoadCommandPayloadString(LoadCommand &LC, StringRef S) {
  109. assert(isLoadCommandWithPayloadString(LC) &&
  110. "unsupported load command encountered");
  111. uint32_t NewCmdsize = alignTo(sizeof(LCType) + S.size() + 1, 8);
  112. LC.MachOLoadCommand.load_command_data.cmdsize = NewCmdsize;
  113. LC.Payload.assign(NewCmdsize - sizeof(LCType), 0);
  114. std::copy(S.begin(), S.end(), LC.Payload.begin());
  115. }
  116. static LoadCommand buildRPathLoadCommand(StringRef Path) {
  117. LoadCommand LC;
  118. MachO::rpath_command RPathLC;
  119. RPathLC.cmd = MachO::LC_RPATH;
  120. RPathLC.path = sizeof(MachO::rpath_command);
  121. RPathLC.cmdsize = alignTo(sizeof(MachO::rpath_command) + Path.size() + 1, 8);
  122. LC.MachOLoadCommand.rpath_command_data = RPathLC;
  123. LC.Payload.assign(RPathLC.cmdsize - sizeof(MachO::rpath_command), 0);
  124. std::copy(Path.begin(), Path.end(), LC.Payload.begin());
  125. return LC;
  126. }
  127. static Error processLoadCommands(const MachOConfig &MachOConfig, Object &Obj) {
  128. // Remove RPaths.
  129. DenseSet<StringRef> RPathsToRemove(MachOConfig.RPathsToRemove.begin(),
  130. MachOConfig.RPathsToRemove.end());
  131. LoadCommandPred RemovePred = [&RPathsToRemove,
  132. &MachOConfig](const LoadCommand &LC) {
  133. if (LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_RPATH) {
  134. // When removing all RPaths we don't need to care
  135. // about what it contains
  136. if (MachOConfig.RemoveAllRpaths)
  137. return true;
  138. StringRef RPath = getPayloadString(LC);
  139. if (RPathsToRemove.count(RPath)) {
  140. RPathsToRemove.erase(RPath);
  141. return true;
  142. }
  143. }
  144. return false;
  145. };
  146. if (Error E = Obj.removeLoadCommands(RemovePred))
  147. return E;
  148. // Emit an error if the Mach-O binary does not contain an rpath path name
  149. // specified in -delete_rpath.
  150. for (StringRef RPath : MachOConfig.RPathsToRemove) {
  151. if (RPathsToRemove.count(RPath))
  152. return createStringError(errc::invalid_argument,
  153. "no LC_RPATH load command with path: %s",
  154. RPath.str().c_str());
  155. }
  156. DenseSet<StringRef> RPaths;
  157. // Get all existing RPaths.
  158. for (LoadCommand &LC : Obj.LoadCommands) {
  159. if (LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_RPATH)
  160. RPaths.insert(getPayloadString(LC));
  161. }
  162. // Throw errors for invalid RPaths.
  163. for (const auto &OldNew : MachOConfig.RPathsToUpdate) {
  164. StringRef Old = OldNew.getFirst();
  165. StringRef New = OldNew.getSecond();
  166. if (!RPaths.contains(Old))
  167. return createStringError(errc::invalid_argument,
  168. "no LC_RPATH load command with path: " + Old);
  169. if (RPaths.contains(New))
  170. return createStringError(errc::invalid_argument,
  171. "rpath '" + New +
  172. "' would create a duplicate load command");
  173. }
  174. // Update load commands.
  175. for (LoadCommand &LC : Obj.LoadCommands) {
  176. switch (LC.MachOLoadCommand.load_command_data.cmd) {
  177. case MachO::LC_ID_DYLIB:
  178. if (MachOConfig.SharedLibId)
  179. updateLoadCommandPayloadString<MachO::dylib_command>(
  180. LC, *MachOConfig.SharedLibId);
  181. break;
  182. case MachO::LC_RPATH: {
  183. StringRef RPath = getPayloadString(LC);
  184. StringRef NewRPath = MachOConfig.RPathsToUpdate.lookup(RPath);
  185. if (!NewRPath.empty())
  186. updateLoadCommandPayloadString<MachO::rpath_command>(LC, NewRPath);
  187. break;
  188. }
  189. // TODO: Add LC_REEXPORT_DYLIB, LC_LAZY_LOAD_DYLIB, and LC_LOAD_UPWARD_DYLIB
  190. // here once llvm-objcopy supports them.
  191. case MachO::LC_LOAD_DYLIB:
  192. case MachO::LC_LOAD_WEAK_DYLIB:
  193. StringRef InstallName = getPayloadString(LC);
  194. StringRef NewInstallName =
  195. MachOConfig.InstallNamesToUpdate.lookup(InstallName);
  196. if (!NewInstallName.empty())
  197. updateLoadCommandPayloadString<MachO::dylib_command>(LC,
  198. NewInstallName);
  199. break;
  200. }
  201. }
  202. // Add new RPaths.
  203. for (StringRef RPath : MachOConfig.RPathToAdd) {
  204. if (RPaths.contains(RPath))
  205. return createStringError(errc::invalid_argument,
  206. "rpath '" + RPath +
  207. "' would create a duplicate load command");
  208. RPaths.insert(RPath);
  209. Obj.LoadCommands.push_back(buildRPathLoadCommand(RPath));
  210. }
  211. for (StringRef RPath : MachOConfig.RPathToPrepend) {
  212. if (RPaths.contains(RPath))
  213. return createStringError(errc::invalid_argument,
  214. "rpath '" + RPath +
  215. "' would create a duplicate load command");
  216. RPaths.insert(RPath);
  217. Obj.LoadCommands.insert(Obj.LoadCommands.begin(),
  218. buildRPathLoadCommand(RPath));
  219. }
  220. // Unlike appending rpaths, the indexes of subsequent load commands must
  221. // be recalculated after prepending one.
  222. if (!MachOConfig.RPathToPrepend.empty())
  223. Obj.updateLoadCommandIndexes();
  224. return Error::success();
  225. }
  226. static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
  227. Object &Obj) {
  228. for (LoadCommand &LC : Obj.LoadCommands)
  229. for (const std::unique_ptr<Section> &Sec : LC.Sections) {
  230. if (Sec->CanonicalName == SecName) {
  231. Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
  232. FileOutputBuffer::create(Filename, Sec->Content.size());
  233. if (!BufferOrErr)
  234. return BufferOrErr.takeError();
  235. std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
  236. llvm::copy(Sec->Content, Buf->getBufferStart());
  237. if (Error E = Buf->commit())
  238. return E;
  239. return Error::success();
  240. }
  241. }
  242. return createStringError(object_error::parse_failed, "section '%s' not found",
  243. SecName.str().c_str());
  244. }
  245. static Error addSection(StringRef SecName, StringRef Filename, Object &Obj) {
  246. ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
  247. MemoryBuffer::getFile(Filename);
  248. if (!BufOrErr)
  249. return createFileError(Filename, errorCodeToError(BufOrErr.getError()));
  250. std::unique_ptr<MemoryBuffer> Buf = std::move(*BufOrErr);
  251. std::pair<StringRef, StringRef> Pair = SecName.split(',');
  252. StringRef TargetSegName = Pair.first;
  253. Section Sec(TargetSegName, Pair.second);
  254. Sec.Content = Obj.NewSectionsContents.save(Buf->getBuffer());
  255. Sec.Size = Sec.Content.size();
  256. // Add the a section into an existing segment.
  257. for (LoadCommand &LC : Obj.LoadCommands) {
  258. Optional<StringRef> SegName = LC.getSegmentName();
  259. if (SegName && SegName == TargetSegName) {
  260. uint64_t Addr = *LC.getSegmentVMAddr();
  261. for (const std::unique_ptr<Section> &S : LC.Sections)
  262. Addr = std::max(Addr, S->Addr + S->Size);
  263. LC.Sections.push_back(std::make_unique<Section>(Sec));
  264. LC.Sections.back()->Addr = Addr;
  265. return Error::success();
  266. }
  267. }
  268. // There's no segment named TargetSegName. Create a new load command and
  269. // Insert a new section into it.
  270. LoadCommand &NewSegment =
  271. Obj.addSegment(TargetSegName, alignTo(Sec.Size, 16384));
  272. NewSegment.Sections.push_back(std::make_unique<Section>(Sec));
  273. NewSegment.Sections.back()->Addr = *NewSegment.getSegmentVMAddr();
  274. return Error::success();
  275. }
  276. static Expected<Section &> findSection(StringRef SecName, Object &O) {
  277. StringRef SegName;
  278. std::tie(SegName, SecName) = SecName.split(",");
  279. auto FoundSeg =
  280. llvm::find_if(O.LoadCommands, [SegName](const LoadCommand &LC) {
  281. return LC.getSegmentName() == SegName;
  282. });
  283. if (FoundSeg == O.LoadCommands.end())
  284. return createStringError(errc::invalid_argument,
  285. "could not find segment with name '%s'",
  286. SegName.str().c_str());
  287. auto FoundSec = llvm::find_if(FoundSeg->Sections,
  288. [SecName](const std::unique_ptr<Section> &Sec) {
  289. return Sec->Sectname == SecName;
  290. });
  291. if (FoundSec == FoundSeg->Sections.end())
  292. return createStringError(errc::invalid_argument,
  293. "could not find section with name '%s'",
  294. SecName.str().c_str());
  295. assert(FoundSec->get()->CanonicalName == (SegName + "," + SecName).str());
  296. return *FoundSec->get();
  297. }
  298. static Error updateSection(StringRef SecName, StringRef Filename, Object &O) {
  299. Expected<Section &> SecToUpdateOrErr = findSection(SecName, O);
  300. if (!SecToUpdateOrErr)
  301. return SecToUpdateOrErr.takeError();
  302. Section &Sec = *SecToUpdateOrErr;
  303. ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
  304. MemoryBuffer::getFile(Filename);
  305. if (!BufOrErr)
  306. return createFileError(Filename, errorCodeToError(BufOrErr.getError()));
  307. std::unique_ptr<MemoryBuffer> Buf = std::move(*BufOrErr);
  308. if (Buf->getBufferSize() > Sec.Size)
  309. return createStringError(
  310. errc::invalid_argument,
  311. "new section cannot be larger than previous section");
  312. Sec.Content = O.NewSectionsContents.save(Buf->getBuffer());
  313. Sec.Size = Sec.Content.size();
  314. return Error::success();
  315. }
  316. // isValidMachOCannonicalName returns success if Name is a MachO cannonical name
  317. // ("<segment>,<section>") and lengths of both segment and section names are
  318. // valid.
  319. static Error isValidMachOCannonicalName(StringRef Name) {
  320. if (Name.count(',') != 1)
  321. return createStringError(errc::invalid_argument,
  322. "invalid section name '%s' (should be formatted "
  323. "as '<segment name>,<section name>')",
  324. Name.str().c_str());
  325. std::pair<StringRef, StringRef> Pair = Name.split(',');
  326. if (Pair.first.size() > 16)
  327. return createStringError(errc::invalid_argument,
  328. "too long segment name: '%s'",
  329. Pair.first.str().c_str());
  330. if (Pair.second.size() > 16)
  331. return createStringError(errc::invalid_argument,
  332. "too long section name: '%s'",
  333. Pair.second.str().c_str());
  334. return Error::success();
  335. }
  336. static Error handleArgs(const CommonConfig &Config,
  337. const MachOConfig &MachOConfig, Object &Obj) {
  338. // Dump sections before add/remove for compatibility with GNU objcopy.
  339. for (StringRef Flag : Config.DumpSection) {
  340. StringRef SectionName;
  341. StringRef FileName;
  342. std::tie(SectionName, FileName) = Flag.split('=');
  343. if (Error E = dumpSectionToFile(SectionName, FileName, Obj))
  344. return E;
  345. }
  346. if (Error E = removeSections(Config, Obj))
  347. return E;
  348. // Mark symbols to determine which symbols are still needed.
  349. if (Config.StripAll)
  350. markSymbols(Config, Obj);
  351. updateAndRemoveSymbols(Config, MachOConfig, Obj);
  352. if (Config.StripAll)
  353. for (LoadCommand &LC : Obj.LoadCommands)
  354. for (std::unique_ptr<Section> &Sec : LC.Sections)
  355. Sec->Relocations.clear();
  356. for (const auto &Flag : Config.AddSection) {
  357. std::pair<StringRef, StringRef> SecPair = Flag.split("=");
  358. StringRef SecName = SecPair.first;
  359. StringRef File = SecPair.second;
  360. if (Error E = isValidMachOCannonicalName(SecName))
  361. return E;
  362. if (Error E = addSection(SecName, File, Obj))
  363. return E;
  364. }
  365. for (const auto &Flag : Config.UpdateSection) {
  366. StringRef SectionName;
  367. StringRef FileName;
  368. std::tie(SectionName, FileName) = Flag.split('=');
  369. if (Error E = isValidMachOCannonicalName(SectionName))
  370. return E;
  371. if (Error E = updateSection(SectionName, FileName, Obj))
  372. return E;
  373. }
  374. if (Error E = processLoadCommands(MachOConfig, Obj))
  375. return E;
  376. return Error::success();
  377. }
  378. Error objcopy::macho::executeObjcopyOnBinary(const CommonConfig &Config,
  379. const MachOConfig &MachOConfig,
  380. object::MachOObjectFile &In,
  381. raw_ostream &Out) {
  382. MachOReader Reader(In);
  383. Expected<std::unique_ptr<Object>> O = Reader.create();
  384. if (!O)
  385. return createFileError(Config.InputFilename, O.takeError());
  386. if (O->get()->Header.FileType == MachO::HeaderFileType::MH_PRELOAD)
  387. return createStringError(std::errc::not_supported,
  388. "%s: MH_PRELOAD files are not supported",
  389. Config.InputFilename.str().c_str());
  390. if (Error E = handleArgs(Config, MachOConfig, **O))
  391. return createFileError(Config.InputFilename, std::move(E));
  392. // Page size used for alignment of segment sizes in Mach-O executables and
  393. // dynamic libraries.
  394. uint64_t PageSize;
  395. switch (In.getArch()) {
  396. case Triple::ArchType::arm:
  397. case Triple::ArchType::aarch64:
  398. case Triple::ArchType::aarch64_32:
  399. PageSize = 16384;
  400. break;
  401. default:
  402. PageSize = 4096;
  403. }
  404. MachOWriter Writer(**O, In.is64Bit(), In.isLittleEndian(),
  405. sys::path::filename(Config.OutputFilename), PageSize, Out);
  406. if (auto E = Writer.finalize())
  407. return E;
  408. return Writer.write();
  409. }
  410. Error objcopy::macho::executeObjcopyOnMachOUniversalBinary(
  411. const MultiFormatConfig &Config, const MachOUniversalBinary &In,
  412. raw_ostream &Out) {
  413. SmallVector<OwningBinary<Binary>, 2> Binaries;
  414. SmallVector<Slice, 2> Slices;
  415. for (const auto &O : In.objects()) {
  416. Expected<std::unique_ptr<Archive>> ArOrErr = O.getAsArchive();
  417. if (ArOrErr) {
  418. Expected<std::vector<NewArchiveMember>> NewArchiveMembersOrErr =
  419. createNewArchiveMembers(Config, **ArOrErr);
  420. if (!NewArchiveMembersOrErr)
  421. return NewArchiveMembersOrErr.takeError();
  422. Expected<std::unique_ptr<MemoryBuffer>> OutputBufferOrErr =
  423. writeArchiveToBuffer(*NewArchiveMembersOrErr,
  424. (*ArOrErr)->hasSymbolTable(), (*ArOrErr)->kind(),
  425. Config.getCommonConfig().DeterministicArchives,
  426. (*ArOrErr)->isThin());
  427. if (!OutputBufferOrErr)
  428. return OutputBufferOrErr.takeError();
  429. Expected<std::unique_ptr<Binary>> BinaryOrErr =
  430. object::createBinary(**OutputBufferOrErr);
  431. if (!BinaryOrErr)
  432. return BinaryOrErr.takeError();
  433. Binaries.emplace_back(std::move(*BinaryOrErr),
  434. std::move(*OutputBufferOrErr));
  435. Slices.emplace_back(*cast<Archive>(Binaries.back().getBinary()),
  436. O.getCPUType(), O.getCPUSubType(),
  437. O.getArchFlagName(), O.getAlign());
  438. continue;
  439. }
  440. // The methods getAsArchive, getAsObjectFile, getAsIRObject of the class
  441. // ObjectForArch return an Error in case of the type mismatch. We need to
  442. // check each in turn to see what kind of slice this is, so ignore errors
  443. // produced along the way.
  444. consumeError(ArOrErr.takeError());
  445. Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = O.getAsObjectFile();
  446. if (!ObjOrErr) {
  447. consumeError(ObjOrErr.takeError());
  448. return createStringError(
  449. std::errc::invalid_argument,
  450. "slice for '%s' of the universal Mach-O binary "
  451. "'%s' is not a Mach-O object or an archive",
  452. O.getArchFlagName().c_str(),
  453. Config.getCommonConfig().InputFilename.str().c_str());
  454. }
  455. std::string ArchFlagName = O.getArchFlagName();
  456. SmallVector<char, 0> Buffer;
  457. raw_svector_ostream MemStream(Buffer);
  458. Expected<const MachOConfig &> MachO = Config.getMachOConfig();
  459. if (!MachO)
  460. return MachO.takeError();
  461. if (Error E = executeObjcopyOnBinary(Config.getCommonConfig(), *MachO,
  462. **ObjOrErr, MemStream))
  463. return E;
  464. auto MB = std::make_unique<SmallVectorMemoryBuffer>(
  465. std::move(Buffer), ArchFlagName, /*RequiresNullTerminator=*/false);
  466. Expected<std::unique_ptr<Binary>> BinaryOrErr = object::createBinary(*MB);
  467. if (!BinaryOrErr)
  468. return BinaryOrErr.takeError();
  469. Binaries.emplace_back(std::move(*BinaryOrErr), std::move(MB));
  470. Slices.emplace_back(*cast<MachOObjectFile>(Binaries.back().getBinary()),
  471. O.getAlign());
  472. }
  473. if (Error Err = writeUniversalBinaryToStream(Slices, Out))
  474. return Err;
  475. return Error::success();
  476. }