MachOObjcopy.cpp 20 KB

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