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