xref: /llvm-project/bolt/lib/Rewrite/MachORewriteInstance.cpp (revision 290e482342826ee4c65bd6d2aece25736d3f0c7b)
1 //===- bolt/Rewrite/MachORewriteInstance.cpp - MachO rewriter -------------===//
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 
9 #include "bolt/Rewrite/MachORewriteInstance.h"
10 #include "bolt/Core/BinaryContext.h"
11 #include "bolt/Core/BinaryEmitter.h"
12 #include "bolt/Core/BinaryFunction.h"
13 #include "bolt/Core/JumpTable.h"
14 #include "bolt/Core/MCPlusBuilder.h"
15 #include "bolt/Passes/Instrumentation.h"
16 #include "bolt/Passes/PatchEntries.h"
17 #include "bolt/Profile/DataReader.h"
18 #include "bolt/Rewrite/BinaryPassManager.h"
19 #include "bolt/Rewrite/ExecutableFileMemoryManager.h"
20 #include "bolt/RuntimeLibs/InstrumentationRuntimeLibrary.h"
21 #include "bolt/Utils/Utils.h"
22 #include "llvm/MC/MCAsmLayout.h"
23 #include "llvm/MC/MCObjectStreamer.h"
24 #include "llvm/Support/Errc.h"
25 #include "llvm/Support/FileSystem.h"
26 #include "llvm/Support/ToolOutputFile.h"
27 
28 namespace opts {
29 
30 using namespace llvm;
31 extern cl::opt<unsigned> AlignText;
32 //FIXME! Upstream change
33 //extern cl::opt<bool> CheckOverlappingElements;
34 extern cl::opt<bool> ForcePatch;
35 extern cl::opt<bool> Instrument;
36 extern cl::opt<bool> InstrumentCalls;
37 extern cl::opt<bolt::JumpTableSupportLevel> JumpTables;
38 extern cl::opt<bool> KeepTmp;
39 extern cl::opt<bool> NeverPrint;
40 extern cl::opt<std::string> OutputFilename;
41 extern cl::opt<bool> PrintAfterBranchFixup;
42 extern cl::opt<bool> PrintFinalized;
43 extern cl::opt<bool> PrintNormalized;
44 extern cl::opt<bool> PrintReordered;
45 extern cl::opt<bool> PrintSections;
46 extern cl::opt<bool> PrintDisasm;
47 extern cl::opt<bool> PrintCFG;
48 extern cl::opt<std::string> RuntimeInstrumentationLib;
49 extern cl::opt<unsigned> Verbosity;
50 } // namespace opts
51 
52 namespace llvm {
53 namespace bolt {
54 
55 extern MCPlusBuilder *createX86MCPlusBuilder(const MCInstrAnalysis *,
56                                              const MCInstrInfo *,
57                                              const MCRegisterInfo *);
58 extern MCPlusBuilder *createAArch64MCPlusBuilder(const MCInstrAnalysis *,
59                                                  const MCInstrInfo *,
60                                                  const MCRegisterInfo *);
61 
62 namespace {
63 
64 MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch,
65                                    const MCInstrAnalysis *Analysis,
66                                    const MCInstrInfo *Info,
67                                    const MCRegisterInfo *RegInfo) {
68 #ifdef X86_AVAILABLE
69   if (Arch == Triple::x86_64)
70     return createX86MCPlusBuilder(Analysis, Info, RegInfo);
71 #endif
72 
73 #ifdef AARCH64_AVAILABLE
74   if (Arch == Triple::aarch64)
75     return createAArch64MCPlusBuilder(Analysis, Info, RegInfo);
76 #endif
77 
78   llvm_unreachable("architecture unsupported by MCPlusBuilder");
79 }
80 
81 } // anonymous namespace
82 
83 #define DEBUG_TYPE "bolt"
84 
85 MachORewriteInstance::MachORewriteInstance(object::MachOObjectFile *InputFile,
86                                            StringRef ToolPath)
87     : InputFile(InputFile), ToolPath(ToolPath),
88       BC(BinaryContext::createBinaryContext(InputFile, /* IsPIC */ true,
89                                             DWARFContext::create(*InputFile))) {
90   BC->initializeTarget(std::unique_ptr<MCPlusBuilder>(createMCPlusBuilder(
91       BC->TheTriple->getArch(), BC->MIA.get(), BC->MII.get(), BC->MRI.get())));
92   if (opts::Instrument)
93     BC->setRuntimeLibrary(std::make_unique<InstrumentationRuntimeLibrary>());
94 }
95 
96 Error MachORewriteInstance::setProfile(StringRef Filename) {
97   if (!sys::fs::exists(Filename))
98     return errorCodeToError(make_error_code(errc::no_such_file_or_directory));
99 
100   if (ProfileReader) {
101     // Already exists
102     return make_error<StringError>(
103         Twine("multiple profiles specified: ") + ProfileReader->getFilename() +
104         " and " + Filename, inconvertibleErrorCode());
105   }
106 
107   ProfileReader = std::make_unique<DataReader>(Filename);
108   return Error::success();
109 }
110 
111 void MachORewriteInstance::preprocessProfileData() {
112   if (!ProfileReader)
113     return;
114   if (Error E = ProfileReader->preprocessProfile(*BC.get()))
115     report_error("cannot pre-process profile", std::move(E));
116 }
117 
118 void MachORewriteInstance::processProfileDataPreCFG() {
119   if (!ProfileReader)
120     return;
121   if (Error E = ProfileReader->readProfilePreCFG(*BC.get()))
122     report_error("cannot read profile pre-CFG", std::move(E));
123 }
124 
125 void MachORewriteInstance::processProfileData() {
126   if (!ProfileReader)
127     return;
128   if (Error E = ProfileReader->readProfile(*BC.get()))
129     report_error("cannot read profile", std::move(E));
130 }
131 
132 void MachORewriteInstance::readSpecialSections() {
133   for (const object::SectionRef &Section : InputFile->sections()) {
134     Expected<StringRef> SectionName = Section.getName();;
135     check_error(SectionName.takeError(), "cannot get section name");
136     // Only register sections with names.
137     if (!SectionName->empty()) {
138       BC->registerSection(Section);
139       LLVM_DEBUG(
140           dbgs() << "BOLT-DEBUG: registering section " << *SectionName
141                  << " @ 0x" << Twine::utohexstr(Section.getAddress()) << ":0x"
142                  << Twine::utohexstr(Section.getAddress() + Section.getSize())
143                  << "\n");
144     }
145   }
146 
147   if (opts::PrintSections) {
148     outs() << "BOLT-INFO: Sections from original binary:\n";
149     BC->printSections(outs());
150   }
151 }
152 
153 namespace {
154 
155 struct DataInCodeRegion {
156   explicit DataInCodeRegion(DiceRef D) {
157     D.getOffset(Offset);
158     D.getLength(Length);
159     D.getKind(Kind);
160   }
161 
162   uint32_t Offset;
163   uint16_t Length;
164   uint16_t Kind;
165 };
166 
167 std::vector<DataInCodeRegion> readDataInCode(const MachOObjectFile &O) {
168   const MachO::linkedit_data_command DataInCodeLC =
169       O.getDataInCodeLoadCommand();
170   const uint32_t NumberOfEntries =
171       DataInCodeLC.datasize / sizeof(MachO::data_in_code_entry);
172   std::vector<DataInCodeRegion> DataInCode;
173   DataInCode.reserve(NumberOfEntries);
174   for (auto I = O.begin_dices(), E = O.end_dices(); I != E; ++I)
175     DataInCode.emplace_back(*I);
176   std::stable_sort(DataInCode.begin(), DataInCode.end(),
177                    [](DataInCodeRegion LHS, DataInCodeRegion RHS) {
178                      return LHS.Offset < RHS.Offset;
179                    });
180   return DataInCode;
181 }
182 
183 Optional<uint64_t> readStartAddress(const MachOObjectFile &O) {
184   Optional<uint64_t> StartOffset;
185   Optional<uint64_t> TextVMAddr;
186   for (const object::MachOObjectFile::LoadCommandInfo &LC : O.load_commands()) {
187     switch (LC.C.cmd) {
188     case MachO::LC_MAIN: {
189       MachO::entry_point_command LCMain = O.getEntryPointCommand(LC);
190       StartOffset = LCMain.entryoff;
191       break;
192     }
193     case MachO::LC_SEGMENT: {
194       MachO::segment_command LCSeg = O.getSegmentLoadCommand(LC);
195       StringRef SegmentName(LCSeg.segname,
196                             strnlen(LCSeg.segname, sizeof(LCSeg.segname)));
197       if (SegmentName == "__TEXT")
198         TextVMAddr = LCSeg.vmaddr;
199       break;
200     }
201     case MachO::LC_SEGMENT_64: {
202       MachO::segment_command_64 LCSeg = O.getSegment64LoadCommand(LC);
203       StringRef SegmentName(LCSeg.segname,
204                             strnlen(LCSeg.segname, sizeof(LCSeg.segname)));
205       if (SegmentName == "__TEXT")
206         TextVMAddr = LCSeg.vmaddr;
207       break;
208     }
209     default:
210       continue;
211     }
212   }
213   return (TextVMAddr && StartOffset)
214              ? Optional<uint64_t>(*TextVMAddr + *StartOffset)
215              : llvm::None;
216 }
217 
218 } // anonymous namespace
219 
220 void MachORewriteInstance::discoverFileObjects() {
221   std::vector<SymbolRef> FunctionSymbols;
222   for (const SymbolRef &S : InputFile->symbols()) {
223     SymbolRef::Type Type = cantFail(S.getType(), "cannot get symbol type");
224     if (Type == SymbolRef::ST_Function)
225       FunctionSymbols.push_back(S);
226   }
227   if (FunctionSymbols.empty())
228     return;
229   std::stable_sort(FunctionSymbols.begin(), FunctionSymbols.end(),
230                    [](const SymbolRef &LHS, const SymbolRef &RHS) {
231                      return cantFail(LHS.getValue()) < cantFail(RHS.getValue());
232                    });
233   for (size_t Index = 0; Index < FunctionSymbols.size(); ++Index) {
234     const uint64_t Address = cantFail(FunctionSymbols[Index].getValue());
235     ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address);
236     // TODO: It happens for some symbols (e.g. __mh_execute_header).
237     // Add proper logic to handle them correctly.
238     if (!Section) {
239       errs() << "BOLT-WARNING: no section found for address " << Address
240              << "\n";
241       continue;
242     }
243 
244     std::string SymbolName =
245         cantFail(FunctionSymbols[Index].getName(), "cannot get symbol name")
246             .str();
247     // Uniquify names of local symbols.
248     if (!(cantFail(FunctionSymbols[Index].getFlags()) & SymbolRef::SF_Global))
249       SymbolName = NR.uniquify(SymbolName);
250 
251     section_iterator S = cantFail(FunctionSymbols[Index].getSection());
252     uint64_t EndAddress = S->getAddress() + S->getSize();
253 
254     size_t NFIndex = Index + 1;
255     // Skip aliases.
256     while (NFIndex < FunctionSymbols.size() &&
257            cantFail(FunctionSymbols[NFIndex].getValue()) == Address)
258       ++NFIndex;
259     if (NFIndex < FunctionSymbols.size() &&
260         S == cantFail(FunctionSymbols[NFIndex].getSection()))
261       EndAddress = cantFail(FunctionSymbols[NFIndex].getValue());
262 
263     const uint64_t SymbolSize = EndAddress - Address;
264     const auto It = BC->getBinaryFunctions().find(Address);
265     if (It == BC->getBinaryFunctions().end()) {
266       BinaryFunction *Function = BC->createBinaryFunction(
267           std::move(SymbolName), *Section, Address, SymbolSize);
268       if (!opts::Instrument)
269         Function->setOutputAddress(Function->getAddress());
270 
271     } else {
272       It->second.addAlternativeName(std::move(SymbolName));
273     }
274   }
275 
276   const std::vector<DataInCodeRegion> DataInCode = readDataInCode(*InputFile);
277 
278   for (auto &BFI : BC->getBinaryFunctions()) {
279     BinaryFunction &Function = BFI.second;
280     Function.setMaxSize(Function.getSize());
281 
282     ErrorOr<ArrayRef<uint8_t>> FunctionData = Function.getData();
283     if (!FunctionData) {
284       errs() << "BOLT-ERROR: corresponding section is non-executable or "
285              << "empty for function " << Function << '\n';
286       continue;
287     }
288 
289     // Treat zero-sized functions as non-simple ones.
290     if (Function.getSize() == 0) {
291       Function.setSimple(false);
292       continue;
293     }
294 
295     // Offset of the function in the file.
296     const auto *FileBegin =
297         reinterpret_cast<const uint8_t *>(InputFile->getData().data());
298     Function.setFileOffset(FunctionData->begin() - FileBegin);
299 
300     // Treat functions which contain data in code as non-simple ones.
301     const auto It = std::lower_bound(
302         DataInCode.cbegin(), DataInCode.cend(), Function.getFileOffset(),
303         [](DataInCodeRegion D, uint64_t Offset) { return D.Offset < Offset; });
304     if (It != DataInCode.cend() &&
305         It->Offset + It->Length <=
306             Function.getFileOffset() + Function.getMaxSize())
307       Function.setSimple(false);
308   }
309 
310   BC->StartFunctionAddress = readStartAddress(*InputFile);
311 }
312 
313 void MachORewriteInstance::disassembleFunctions() {
314   for (auto &BFI : BC->getBinaryFunctions()) {
315     BinaryFunction &Function = BFI.second;
316     if (!Function.isSimple())
317       continue;
318     Function.disassemble();
319     if (opts::PrintDisasm)
320       Function.print(outs(), "after disassembly", true);
321   }
322 }
323 
324 void MachORewriteInstance::buildFunctionsCFG() {
325   for (auto &BFI : BC->getBinaryFunctions()) {
326     BinaryFunction &Function = BFI.second;
327     if (!Function.isSimple())
328       continue;
329     if (!Function.buildCFG(/*AllocId*/ 0)) {
330       errs() << "BOLT-WARNING: failed to build CFG for the function "
331              << Function << "\n";
332     }
333   }
334 }
335 
336 void MachORewriteInstance::postProcessFunctions() {
337   for (auto &BFI : BC->getBinaryFunctions()) {
338     BinaryFunction &Function = BFI.second;
339     if (Function.empty())
340       continue;
341     Function.postProcessCFG();
342     if (opts::PrintCFG)
343       Function.print(outs(), "after building cfg", true);
344   }
345 }
346 
347 void MachORewriteInstance::runOptimizationPasses() {
348   BinaryFunctionPassManager Manager(*BC);
349   if (opts::Instrument) {
350     Manager.registerPass(std::make_unique<PatchEntries>());
351     Manager.registerPass(std::make_unique<Instrumentation>(opts::NeverPrint));
352   }
353 
354   Manager.registerPass(std::make_unique<ShortenInstructions>(opts::NeverPrint));
355 
356   Manager.registerPass(std::make_unique<RemoveNops>(opts::NeverPrint));
357 
358   Manager.registerPass(std::make_unique<NormalizeCFG>(opts::PrintNormalized));
359 
360   Manager.registerPass(
361       std::make_unique<ReorderBasicBlocks>(opts::PrintReordered));
362   Manager.registerPass(
363       std::make_unique<FixupBranches>(opts::PrintAfterBranchFixup));
364   // This pass should always run last.*
365   Manager.registerPass(
366       std::make_unique<FinalizeFunctions>(opts::PrintFinalized));
367 
368   Manager.runPasses();
369 }
370 
371 void MachORewriteInstance::mapInstrumentationSection(StringRef SectionName) {
372   if (!opts::Instrument)
373     return;
374   ErrorOr<BinarySection &> Section = BC->getUniqueSectionByName(SectionName);
375   if (!Section) {
376     llvm::errs() << "Cannot find " + SectionName + " section\n";
377     exit(1);
378   }
379   if (!Section->hasValidSectionID())
380     return;
381   RTDyld->reassignSectionAddress(Section->getSectionID(),
382                                  Section->getAddress());
383 }
384 
385 void MachORewriteInstance::mapCodeSections() {
386   for (BinaryFunction *Function : BC->getAllBinaryFunctions()) {
387     if (!Function->isEmitted())
388       continue;
389     if (Function->getOutputAddress() == 0)
390       continue;
391     ErrorOr<BinarySection &> FuncSection = Function->getCodeSection();
392     if (!FuncSection)
393       report_error(
394           (Twine("Cannot find section for function ") + Function->getOneName())
395               .str(),
396           FuncSection.getError());
397 
398     FuncSection->setOutputAddress(Function->getOutputAddress());
399     LLVM_DEBUG(dbgs() << "BOLT: mapping 0x"
400                  << Twine::utohexstr(FuncSection->getAllocAddress()) << " to 0x"
401                  << Twine::utohexstr(Function->getOutputAddress()) << '\n');
402     RTDyld->reassignSectionAddress(FuncSection->getSectionID(),
403                                    Function->getOutputAddress());
404     Function->setImageAddress(FuncSection->getAllocAddress());
405     Function->setImageSize(FuncSection->getOutputSize());
406   }
407 
408   if (opts::Instrument) {
409     ErrorOr<BinarySection &> BOLT = BC->getUniqueSectionByName("__bolt");
410     if (!BOLT) {
411       llvm::errs() << "Cannot find __bolt section\n";
412       exit(1);
413     }
414     uint64_t Addr = BOLT->getAddress();
415     for (BinaryFunction *Function : BC->getAllBinaryFunctions()) {
416       if (!Function->isEmitted())
417         continue;
418       if (Function->getOutputAddress() != 0)
419         continue;
420       ErrorOr<BinarySection &> FuncSection = Function->getCodeSection();
421       assert(FuncSection && "cannot find section for function");
422       Addr = llvm::alignTo(Addr, 4);
423       FuncSection->setOutputAddress(Addr);
424       RTDyld->reassignSectionAddress(FuncSection->getSectionID(), Addr);
425       Function->setFileOffset(Addr - BOLT->getAddress() +
426                               BOLT->getInputFileOffset());
427       Function->setImageAddress(FuncSection->getAllocAddress());
428       Function->setImageSize(FuncSection->getOutputSize());
429       BC->registerNameAtAddress(Function->getOneName(), Addr, 0, 0);
430       Addr += FuncSection->getOutputSize();
431     }
432   }
433 }
434 
435 namespace {
436 
437 class BOLTSymbolResolver : public LegacyJITSymbolResolver {
438   BinaryContext &BC;
439 public:
440   BOLTSymbolResolver(BinaryContext &BC) : BC(BC) {}
441 
442   JITSymbol findSymbolInLogicalDylib(const std::string &Name) override {
443     return JITSymbol(nullptr);
444   }
445 
446   JITSymbol findSymbol(const std::string &Name) override {
447     LLVM_DEBUG(dbgs() << "BOLT: looking for " << Name << "\n");
448     if (BinaryData *I = BC.getBinaryDataByName(Name)) {
449       const uint64_t Address = I->isMoved() && !I->isJumpTable()
450                                    ? I->getOutputAddress()
451                                    : I->getAddress();
452       LLVM_DEBUG(dbgs() << "Resolved to address 0x" << Twine::utohexstr(Address)
453                         << "\n");
454       return JITSymbol(Address, JITSymbolFlags());
455     }
456     LLVM_DEBUG(dbgs() << "Resolved to address 0x0\n");
457     return JITSymbol(nullptr);
458   }
459 };
460 
461 } // end anonymous namespace
462 
463 void MachORewriteInstance::emitAndLink() {
464   std::error_code EC;
465   std::unique_ptr<::llvm::ToolOutputFile> TempOut =
466       std::make_unique<::llvm::ToolOutputFile>(
467           opts::OutputFilename + ".bolt.o", EC, sys::fs::OF_None);
468   check_error(EC, "cannot create output object file");
469 
470   if (opts::KeepTmp)
471     TempOut->keep();
472 
473   std::unique_ptr<buffer_ostream> BOS =
474       std::make_unique<buffer_ostream>(TempOut->os());
475   raw_pwrite_stream *OS = BOS.get();
476   auto Streamer = BC->createStreamer(*OS);
477 
478   emitBinaryContext(*Streamer, *BC, getOrgSecPrefix());
479   Streamer->Finish();
480 
481   std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
482       MemoryBuffer::getMemBuffer(BOS->str(), "in-memory object file", false);
483   std::unique_ptr<object::ObjectFile> Obj = cantFail(
484       object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
485       "error creating in-memory object");
486   assert(Obj && "createObjectFile cannot return nullptr");
487 
488   BOLTSymbolResolver Resolver = BOLTSymbolResolver(*BC);
489 
490   MCAsmLayout FinalLayout(
491       static_cast<MCObjectStreamer *>(Streamer.get())->getAssembler());
492 
493   BC->EFMM.reset(new ExecutableFileMemoryManager(*BC, /*AllowStubs*/ false));
494 
495   RTDyld.reset(new decltype(RTDyld)::element_type(*BC->EFMM, Resolver));
496   RTDyld->setProcessAllSections(true);
497   RTDyld->loadObject(*Obj);
498   if (RTDyld->hasError()) {
499     outs() << "BOLT-ERROR: RTDyld failed.\n";
500     exit(1);
501   }
502 
503   // Assign addresses to all sections. If key corresponds to the object
504   // created by ourselves, call our regular mapping function. If we are
505   // loading additional objects as part of runtime libraries for
506   // instrumentation, treat them as extra sections.
507   mapCodeSections();
508   mapInstrumentationSection("__counters");
509   mapInstrumentationSection("__tables");
510 
511           // TODO: Refactor addRuntimeLibSections to work properly on Mach-O
512           // and use it here.
513   //FIXME! Put this in RtLibrary->link
514 //          mapInstrumentationSection("I__setup");
515 //          mapInstrumentationSection("I__fini");
516 //          mapInstrumentationSection("I__data");
517 //          mapInstrumentationSection("I__text");
518 //          mapInstrumentationSection("I__cstring");
519 //          mapInstrumentationSection("I__literal16");
520 
521 //  if (auto *RtLibrary = BC->getRuntimeLibrary()) {
522 //    RtLibrary->link(*BC, ToolPath, *ES, *OLT);
523 //  }
524 }
525 
526 void MachORewriteInstance::writeInstrumentationSection(StringRef SectionName,
527                                                        raw_pwrite_stream &OS) {
528   if (!opts::Instrument)
529     return;
530   ErrorOr<BinarySection &> Section = BC->getUniqueSectionByName(SectionName);
531   if (!Section) {
532     llvm::errs() << "Cannot find " + SectionName + " section\n";
533     exit(1);
534   }
535   if (!Section->hasValidSectionID())
536     return;
537   assert(Section->getInputFileOffset() &&
538          "Section input offset cannot be zero");
539   assert(Section->getAllocAddress() && "Section alloc address cannot be zero");
540   assert(Section->getOutputSize() && "Section output size cannot be zero");
541   OS.pwrite(reinterpret_cast<char *>(Section->getAllocAddress()),
542             Section->getOutputSize(), Section->getInputFileOffset());
543 }
544 
545 void MachORewriteInstance::rewriteFile() {
546   std::error_code EC;
547   Out = std::make_unique<ToolOutputFile>(opts::OutputFilename, EC,
548                                          sys::fs::OF_None);
549   check_error(EC, "cannot create output executable file");
550   raw_fd_ostream &OS = Out->os();
551   OS << InputFile->getData();
552 
553   for (auto &BFI : BC->getBinaryFunctions()) {
554     BinaryFunction &Function = BFI.second;
555     if (!Function.isSimple())
556       continue;
557     assert(Function.isEmitted() && "Simple function has not been emitted");
558     if (!opts::Instrument && (Function.getImageSize() > Function.getMaxSize()))
559       continue;
560     if (opts::Verbosity >= 2)
561       outs() << "BOLT: rewriting function \"" << Function << "\"\n";
562     OS.pwrite(reinterpret_cast<char *>(Function.getImageAddress()),
563               Function.getImageSize(), Function.getFileOffset());
564   }
565 
566   for (const BinaryFunction *Function : BC->getInjectedBinaryFunctions()) {
567     OS.pwrite(reinterpret_cast<char *>(Function->getImageAddress()),
568               Function->getImageSize(), Function->getFileOffset());
569   }
570 
571   writeInstrumentationSection("__counters", OS);
572   writeInstrumentationSection("__tables", OS);
573 
574   // TODO: Refactor addRuntimeLibSections to work properly on Mach-O and
575   // use it here.
576   writeInstrumentationSection("I__setup", OS);
577   writeInstrumentationSection("I__fini", OS);
578   writeInstrumentationSection("I__data", OS);
579   writeInstrumentationSection("I__text", OS);
580   writeInstrumentationSection("I__cstring", OS);
581   writeInstrumentationSection("I__literal16", OS);
582 
583   Out->keep();
584   EC = sys::fs::setPermissions(opts::OutputFilename,
585                                sys::fs::perms::all_all);
586   check_error(EC, "cannot set permissions of output file");
587 }
588 
589 void MachORewriteInstance::adjustCommandLineOptions() {
590 //FIXME! Upstream change
591 //  opts::CheckOverlappingElements = false;
592   if (!opts::AlignText.getNumOccurrences())
593     opts::AlignText = BC->PageAlign;
594   if (opts::Instrument.getNumOccurrences())
595     opts::ForcePatch = true;
596   opts::JumpTables = JTS_MOVE;
597   opts::InstrumentCalls = false;
598   opts::RuntimeInstrumentationLib = "libbolt_rt_instr_osx.a";
599 }
600 
601 void MachORewriteInstance::run() {
602   adjustCommandLineOptions();
603 
604   readSpecialSections();
605 
606   discoverFileObjects();
607 
608   preprocessProfileData();
609 
610   disassembleFunctions();
611 
612   processProfileDataPreCFG();
613 
614   buildFunctionsCFG();
615 
616   processProfileData();
617 
618   postProcessFunctions();
619 
620   runOptimizationPasses();
621 
622   emitAndLink();
623 
624   rewriteFile();
625 }
626 
627 MachORewriteInstance::~MachORewriteInstance() {}
628 
629 } // namespace bolt
630 } // namespace llvm
631