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