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