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