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