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