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