1 //===- bolt/Core/BinaryFunction.h - Low-level function ----------*- C++ -*-===// 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 // This file contains the declaration of the BinaryFunction class. It represents 10 // a function at the lowest IR level. Typically, a BinaryFunction represents a 11 // function object in a compiled and linked binary file. However, a 12 // BinaryFunction can also be constructed manually, e.g. for injecting into a 13 // binary file. 14 // 15 // A BinaryFunction could be in one of the several states described in 16 // BinaryFunction::State. While in the disassembled state, it will contain a 17 // list of instructions with their offsets. In the CFG state, it will contain a 18 // list of BinaryBasicBlocks that form a control-flow graph. This state is best 19 // suited for binary analysis and optimizations. However, sometimes it's 20 // impossible to build the precise CFG due to the ambiguity of indirect 21 // branches. 22 // 23 //===----------------------------------------------------------------------===// 24 25 #ifndef BOLT_CORE_BINARY_FUNCTION_H 26 #define BOLT_CORE_BINARY_FUNCTION_H 27 28 #include "bolt/Core/BinaryBasicBlock.h" 29 #include "bolt/Core/BinaryContext.h" 30 #include "bolt/Core/BinaryLoop.h" 31 #include "bolt/Core/BinarySection.h" 32 #include "bolt/Core/DebugData.h" 33 #include "bolt/Core/JumpTable.h" 34 #include "bolt/Core/MCPlus.h" 35 #include "bolt/Utils/NameResolver.h" 36 #include "llvm/ADT/StringRef.h" 37 #include "llvm/ADT/iterator.h" 38 #include "llvm/BinaryFormat/Dwarf.h" 39 #include "llvm/MC/MCContext.h" 40 #include "llvm/MC/MCDwarf.h" 41 #include "llvm/MC/MCInst.h" 42 #include "llvm/MC/MCSymbol.h" 43 #include "llvm/Object/ObjectFile.h" 44 #include "llvm/Support/raw_ostream.h" 45 #include <algorithm> 46 #include <limits> 47 #include <unordered_map> 48 #include <unordered_set> 49 #include <vector> 50 51 using namespace llvm::object; 52 53 namespace llvm { 54 55 class DWARFUnit; 56 57 namespace bolt { 58 59 using InputOffsetToAddressMapTy = std::unordered_multimap<uint64_t, uint64_t>; 60 61 /// Types of macro-fusion alignment corrections. 62 enum MacroFusionType { MFT_NONE, MFT_HOT, MFT_ALL }; 63 64 enum IndirectCallPromotionType : char { 65 ICP_NONE, /// Don't perform ICP. 66 ICP_CALLS, /// Perform ICP on indirect calls. 67 ICP_JUMP_TABLES, /// Perform ICP on jump tables. 68 ICP_ALL /// Perform ICP on calls and jump tables. 69 }; 70 71 /// Information on a single indirect call to a particular callee. 72 struct IndirectCallProfile { 73 MCSymbol *Symbol; 74 uint32_t Offset; 75 uint64_t Count; 76 uint64_t Mispreds; 77 78 IndirectCallProfile(MCSymbol *Symbol, uint64_t Count, uint64_t Mispreds, 79 uint32_t Offset = 0) 80 : Symbol(Symbol), Offset(Offset), Count(Count), Mispreds(Mispreds) {} 81 82 bool operator==(const IndirectCallProfile &Other) const { 83 return Symbol == Other.Symbol && Offset == Other.Offset; 84 } 85 }; 86 87 /// Aggregated information for an indirect call site. 88 using IndirectCallSiteProfile = SmallVector<IndirectCallProfile, 4>; 89 90 inline raw_ostream &operator<<(raw_ostream &OS, 91 const bolt::IndirectCallSiteProfile &ICSP) { 92 std::string TempString; 93 raw_string_ostream SS(TempString); 94 95 const char *Sep = "\n "; 96 uint64_t TotalCount = 0; 97 uint64_t TotalMispreds = 0; 98 for (const IndirectCallProfile &CSP : ICSP) { 99 SS << Sep << "{ " << (CSP.Symbol ? CSP.Symbol->getName() : "<unknown>") 100 << ": " << CSP.Count << " (" << CSP.Mispreds << " misses) }"; 101 Sep = ",\n "; 102 TotalCount += CSP.Count; 103 TotalMispreds += CSP.Mispreds; 104 } 105 SS.flush(); 106 107 OS << TotalCount << " (" << TotalMispreds << " misses) :" << TempString; 108 return OS; 109 } 110 111 /// BinaryFunction is a representation of machine-level function. 112 /// 113 /// In the input binary, an instance of BinaryFunction can represent a fragment 114 /// of a function if the higher-level function was split, e.g. into hot and cold 115 /// parts. The fragment containing the main entry point is called a parent 116 /// or the main fragment. 117 class BinaryFunction { 118 public: 119 enum class State : char { 120 Empty = 0, /// Function body is empty. 121 Disassembled, /// Function have been disassembled. 122 CFG, /// Control flow graph has been built. 123 CFG_Finalized, /// CFG is finalized. No optimizations allowed. 124 EmittedCFG, /// Instructions have been emitted to output. 125 Emitted, /// Same as above plus CFG is destroyed. 126 }; 127 128 /// Types of profile the function can use. Could be a combination. 129 enum { 130 PF_NONE = 0, /// No profile. 131 PF_LBR = 1, /// Profile is based on last branch records. 132 PF_SAMPLE = 2, /// Non-LBR sample-based profile. 133 PF_MEMEVENT = 4, /// Profile has mem events. 134 }; 135 136 /// Struct for tracking exception handling ranges. 137 struct CallSite { 138 const MCSymbol *Start; 139 const MCSymbol *End; 140 const MCSymbol *LP; 141 uint64_t Action; 142 }; 143 144 using CallSitesType = SmallVector<CallSite, 0>; 145 146 using IslandProxiesType = 147 std::map<BinaryFunction *, std::map<const MCSymbol *, MCSymbol *>>; 148 149 struct IslandInfo { 150 /// Temporary holder of offsets that are data markers (used in AArch) 151 /// It is possible to have data in code sections. To ease the identification 152 /// of data in code sections, the ABI requires the symbol table to have 153 /// symbols named "$d" identifying the start of data inside code and "$x" 154 /// identifying the end of a chunk of data inside code. DataOffsets contain 155 /// all offsets of $d symbols and CodeOffsets all offsets of $x symbols. 156 std::set<uint64_t> DataOffsets; 157 std::set<uint64_t> CodeOffsets; 158 159 /// List of relocations associated with data in the constant island 160 std::map<uint64_t, Relocation> Relocations; 161 162 /// Offsets in function that are data values in a constant island identified 163 /// after disassembling 164 std::map<uint64_t, MCSymbol *> Offsets; 165 SmallPtrSet<MCSymbol *, 4> Symbols; 166 DenseMap<const MCSymbol *, BinaryFunction *> ProxySymbols; 167 DenseMap<const MCSymbol *, MCSymbol *> ColdSymbols; 168 /// Keeps track of other functions we depend on because there is a reference 169 /// to the constant islands in them. 170 IslandProxiesType Proxies, ColdProxies; 171 SmallPtrSet<BinaryFunction *, 1> Dependency; // The other way around 172 173 mutable MCSymbol *FunctionConstantIslandLabel{nullptr}; 174 mutable MCSymbol *FunctionColdConstantIslandLabel{nullptr}; 175 176 // Returns constant island alignment 177 uint16_t getAlignment() const { return sizeof(uint64_t); } 178 }; 179 180 static constexpr uint64_t COUNT_NO_PROFILE = 181 BinaryBasicBlock::COUNT_NO_PROFILE; 182 183 /// We have to use at least 2-byte alignment for functions because of C++ ABI. 184 static constexpr unsigned MinAlign = 2; 185 186 static const char TimerGroupName[]; 187 static const char TimerGroupDesc[]; 188 189 using BasicBlockOrderType = SmallVector<BinaryBasicBlock *, 0>; 190 191 /// Mark injected functions 192 bool IsInjected = false; 193 194 using LSDATypeTableTy = SmallVector<uint64_t, 0>; 195 196 /// List of DWARF CFI instructions. Original CFI from the binary must be 197 /// sorted w.r.t. offset that it appears. We rely on this to replay CFIs 198 /// if needed (to fix state after reordering BBs). 199 using CFIInstrMapType = SmallVector<MCCFIInstruction, 0>; 200 using cfi_iterator = CFIInstrMapType::iterator; 201 using const_cfi_iterator = CFIInstrMapType::const_iterator; 202 203 private: 204 /// Current state of the function. 205 State CurrentState{State::Empty}; 206 207 /// A list of symbols associated with the function entry point. 208 /// 209 /// Multiple symbols would typically result from identical code-folding 210 /// optimization. 211 typedef SmallVector<MCSymbol *, 1> SymbolListTy; 212 SymbolListTy Symbols; 213 214 /// The list of names this function is known under. Used for fuzzy-matching 215 /// the function to its name in a profile, command line, etc. 216 SmallVector<std::string, 0> Aliases; 217 218 /// Containing section in the input file. 219 BinarySection *OriginSection = nullptr; 220 221 /// Address of the function in memory. Also could be an offset from 222 /// base address for position independent binaries. 223 uint64_t Address; 224 225 /// Original size of the function. 226 uint64_t Size; 227 228 /// Address of the function in output. 229 uint64_t OutputAddress{0}; 230 231 /// Size of the function in the output file. 232 uint64_t OutputSize{0}; 233 234 /// Offset in the file. 235 uint64_t FileOffset{0}; 236 237 /// Maximum size this function is allowed to have. 238 uint64_t MaxSize{std::numeric_limits<uint64_t>::max()}; 239 240 /// Alignment requirements for the function. 241 uint16_t Alignment{2}; 242 243 /// Maximum number of bytes used for alignment of hot part of the function. 244 uint16_t MaxAlignmentBytes{0}; 245 246 /// Maximum number of bytes used for alignment of cold part of the function. 247 uint16_t MaxColdAlignmentBytes{0}; 248 249 const MCSymbol *PersonalityFunction{nullptr}; 250 uint8_t PersonalityEncoding{dwarf::DW_EH_PE_sdata4 | dwarf::DW_EH_PE_pcrel}; 251 252 BinaryContext &BC; 253 254 std::unique_ptr<BinaryLoopInfo> BLI; 255 256 /// All labels in the function that are referenced via relocations from 257 /// data objects. Typically these are jump table destinations and computed 258 /// goto labels. 259 std::set<uint64_t> ExternallyReferencedOffsets; 260 261 /// Offsets of indirect branches with unknown destinations. 262 std::set<uint64_t> UnknownIndirectBranchOffsets; 263 264 /// A set of local and global symbols corresponding to secondary entry points. 265 /// Each additional function entry point has a corresponding entry in the map. 266 /// The key is a local symbol corresponding to a basic block and the value 267 /// is a global symbol corresponding to an external entry point. 268 DenseMap<const MCSymbol *, MCSymbol *> SecondaryEntryPoints; 269 270 /// False if the function is too complex to reconstruct its control 271 /// flow graph. 272 /// In relocation mode we still disassemble and re-assemble such functions. 273 bool IsSimple{true}; 274 275 /// Indication that the function should be ignored for optimization purposes. 276 /// If we can skip emission of some functions, then ignored functions could 277 /// be not fully disassembled and will not be emitted. 278 bool IsIgnored{false}; 279 280 /// Pseudo functions should not be disassembled or emitted. 281 bool IsPseudo{false}; 282 283 /// True if the original function code has all necessary relocations to track 284 /// addresses of functions emitted to new locations. Typically set for 285 /// functions that we are not going to emit. 286 bool HasExternalRefRelocations{false}; 287 288 /// True if the function has an indirect branch with unknown destination. 289 bool HasUnknownControlFlow{false}; 290 291 /// The code from inside the function references one of the code locations 292 /// from the same function as a data, i.e. it's possible the label is used 293 /// inside an address calculation or could be referenced from outside. 294 bool HasInternalLabelReference{false}; 295 296 /// In AArch64, preserve nops to maintain code equal to input (assuming no 297 /// optimizations are done). 298 bool PreserveNops{false}; 299 300 /// Indicate if this function has associated exception handling metadata. 301 bool HasEHRanges{false}; 302 303 /// True if the function uses DW_CFA_GNU_args_size CFIs. 304 bool UsesGnuArgsSize{false}; 305 306 /// True if the function might have a profile available externally. 307 /// Used to check if processing of the function is required under certain 308 /// conditions. 309 bool HasProfileAvailable{false}; 310 311 bool HasMemoryProfile{false}; 312 313 /// Execution halts whenever this function is entered. 314 bool TrapsOnEntry{false}; 315 316 /// True if the function had an indirect branch with a fixed internal 317 /// destination. 318 bool HasFixedIndirectBranch{false}; 319 320 /// True if the function is a fragment of another function. This means that 321 /// this function could only be entered via its parent or one of its sibling 322 /// fragments. It could be entered at any basic block. It can also return 323 /// the control to any basic block of its parent or its sibling. 324 bool IsFragment{false}; 325 326 /// Indicate that the function body has SDT marker 327 bool HasSDTMarker{false}; 328 329 /// Indicate that the function body has Pseudo Probe 330 bool HasPseudoProbe{BC.getUniqueSectionByName(".pseudo_probe_desc") && 331 BC.getUniqueSectionByName(".pseudo_probe")}; 332 333 /// True if the original entry point was patched. 334 bool IsPatched{false}; 335 336 /// True if the function contains explicit or implicit indirect branch to its 337 /// split fragments, e.g., split jump table, landing pad in split fragment 338 bool HasIndirectTargetToSplitFragment{false}; 339 340 /// True if there are no control-flow edges with successors in other functions 341 /// (i.e. if tail calls have edges to function-local basic blocks). 342 /// Set to false by SCTC. Dynostats can't be reliably computed for 343 /// functions with non-canonical CFG. 344 /// This attribute is only valid when hasCFG() == true. 345 bool HasCanonicalCFG{true}; 346 347 /// The address for the code for this function in codegen memory. 348 /// Used for functions that are emitted in a dedicated section with a fixed 349 /// address. E.g. for functions that are overwritten in-place. 350 uint64_t ImageAddress{0}; 351 352 /// The size of the code in memory. 353 uint64_t ImageSize{0}; 354 355 /// Name for the section this function code should reside in. 356 std::string CodeSectionName; 357 358 /// Name for the corresponding cold code section. 359 std::string ColdCodeSectionName; 360 361 /// Parent function fragment for split function fragments. 362 SmallPtrSet<BinaryFunction *, 1> ParentFragments; 363 364 /// Indicate if the function body was folded into another function. 365 /// Used by ICF optimization. 366 BinaryFunction *FoldedIntoFunction{nullptr}; 367 368 /// All fragments for a parent function. 369 SmallPtrSet<BinaryFunction *, 1> Fragments; 370 371 /// The profile data for the number of times the function was executed. 372 uint64_t ExecutionCount{COUNT_NO_PROFILE}; 373 374 /// Profile match ratio. 375 float ProfileMatchRatio{0.0f}; 376 377 /// Raw branch count for this function in the profile 378 uint64_t RawBranchCount{0}; 379 380 /// Indicates the type of profile the function is using. 381 uint16_t ProfileFlags{PF_NONE}; 382 383 /// For functions with mismatched profile we store all call profile 384 /// information at a function level (as opposed to tying it to 385 /// specific call sites). 386 IndirectCallSiteProfile AllCallSites; 387 388 /// Score of the function (estimated number of instructions executed, 389 /// according to profile data). -1 if the score has not been calculated yet. 390 mutable int64_t FunctionScore{-1}; 391 392 /// Original LSDA address for the function. 393 uint64_t LSDAAddress{0}; 394 395 /// Containing compilation unit for the function. 396 DWARFUnit *DwarfUnit{nullptr}; 397 398 /// Last computed hash value. Note that the value could be recomputed using 399 /// different parameters by every pass. 400 mutable uint64_t Hash{0}; 401 402 /// For PLT functions it contains a symbol associated with a function 403 /// reference. It is nullptr for non-PLT functions. 404 const MCSymbol *PLTSymbol{nullptr}; 405 406 /// Function order for streaming into the destination binary. 407 uint32_t Index{-1U}; 408 409 /// Get basic block index assuming it belongs to this function. 410 unsigned getIndex(const BinaryBasicBlock *BB) const { 411 assert(BB->getIndex() < BasicBlocks.size()); 412 return BB->getIndex(); 413 } 414 415 /// Return basic block that originally contained offset \p Offset 416 /// from the function start. 417 BinaryBasicBlock *getBasicBlockContainingOffset(uint64_t Offset); 418 419 const BinaryBasicBlock *getBasicBlockContainingOffset(uint64_t Offset) const { 420 return const_cast<BinaryFunction *>(this)->getBasicBlockContainingOffset( 421 Offset); 422 } 423 424 /// Return basic block that started at offset \p Offset. 425 BinaryBasicBlock *getBasicBlockAtOffset(uint64_t Offset) { 426 BinaryBasicBlock *BB = getBasicBlockContainingOffset(Offset); 427 return BB && BB->getOffset() == Offset ? BB : nullptr; 428 } 429 430 /// Release memory taken by the list. 431 template <typename T> BinaryFunction &clearList(T &List) { 432 T TempList; 433 TempList.swap(List); 434 return *this; 435 } 436 437 /// Update the indices of all the basic blocks starting at StartIndex. 438 void updateBBIndices(const unsigned StartIndex); 439 440 /// Annotate each basic block entry with its current CFI state. This is 441 /// run right after the construction of CFG while basic blocks are in their 442 /// original order. 443 void annotateCFIState(); 444 445 /// Associate DW_CFA_GNU_args_size info with invoke instructions 446 /// (call instructions with non-empty landing pad). 447 void propagateGnuArgsSizeInfo(MCPlusBuilder::AllocatorIdTy AllocId); 448 449 /// Synchronize branch instructions with CFG. 450 void postProcessBranches(); 451 452 /// The address offset where we emitted the constant island, that is, the 453 /// chunk of data in the function code area (AArch only) 454 int64_t OutputDataOffset{0}; 455 int64_t OutputColdDataOffset{0}; 456 457 /// Map labels to corresponding basic blocks. 458 DenseMap<const MCSymbol *, BinaryBasicBlock *> LabelToBB; 459 460 using BranchListType = SmallVector<std::pair<uint32_t, uint32_t>, 0>; 461 BranchListType TakenBranches; /// All local taken branches. 462 BranchListType IgnoredBranches; /// Branches ignored by CFG purposes. 463 464 /// Map offset in the function to a label. 465 /// Labels are used for building CFG for simple functions. For non-simple 466 /// function in relocation mode we need to emit them for relocations 467 /// referencing function internals to work (e.g. jump tables). 468 using LabelsMapType = std::map<uint32_t, MCSymbol *>; 469 LabelsMapType Labels; 470 471 /// Temporary holder of instructions before CFG is constructed. 472 /// Map offset in the function to MCInst. 473 using InstrMapType = std::map<uint32_t, MCInst>; 474 InstrMapType Instructions; 475 476 /// We don't decode Call Frame Info encoded in DWARF program state 477 /// machine. Instead we define a "CFI State" - a frame information that 478 /// is a result of executing FDE CFI program up to a given point. The 479 /// program consists of opaque Call Frame Instructions: 480 /// 481 /// CFI #0 482 /// CFI #1 483 /// .... 484 /// CFI #N 485 /// 486 /// When we refer to "CFI State K" - it corresponds to a row in an abstract 487 /// Call Frame Info table. This row is reached right before executing CFI #K. 488 /// 489 /// At any point of execution in a function we are in any one of (N + 2) 490 /// states described in the original FDE program. We can't have more states 491 /// without intelligent processing of CFIs. 492 /// 493 /// When the final layout of basic blocks is known, and we finalize CFG, 494 /// we modify the original program to make sure the same state could be 495 /// reached even when basic blocks containing CFI instructions are executed 496 /// in a different order. 497 CFIInstrMapType FrameInstructions; 498 499 /// A map of restore state CFI instructions to their equivalent CFI 500 /// instructions that produce the same state, in order to eliminate 501 /// remember-restore CFI instructions when rewriting CFI. 502 DenseMap<int32_t, SmallVector<int32_t, 4>> FrameRestoreEquivalents; 503 504 // For tracking exception handling ranges. 505 CallSitesType CallSites; 506 CallSitesType ColdCallSites; 507 508 /// Binary blobs representing action, type, and type index tables for this 509 /// function' LSDA (exception handling). 510 ArrayRef<uint8_t> LSDAActionTable; 511 ArrayRef<uint8_t> LSDATypeIndexTable; 512 513 /// Vector of addresses of types referenced by LSDA. 514 LSDATypeTableTy LSDATypeTable; 515 516 /// Vector of addresses of entries in LSDATypeTable used for indirect 517 /// addressing. 518 LSDATypeTableTy LSDATypeAddressTable; 519 520 /// Marking for the beginning of language-specific data area for the function. 521 MCSymbol *LSDASymbol{nullptr}; 522 MCSymbol *ColdLSDASymbol{nullptr}; 523 524 /// Map to discover which CFIs are attached to a given instruction offset. 525 /// Maps an instruction offset into a FrameInstructions offset. 526 /// This is only relevant to the buildCFG phase and is discarded afterwards. 527 std::multimap<uint32_t, uint32_t> OffsetToCFI; 528 529 /// List of CFI instructions associated with the CIE (common to more than one 530 /// function and that apply before the entry basic block). 531 CFIInstrMapType CIEFrameInstructions; 532 533 /// All compound jump tables for this function. This duplicates what's stored 534 /// in the BinaryContext, but additionally it gives quick access for all 535 /// jump tables used by this function. 536 /// 537 /// <OriginalAddress> -> <JumpTable *> 538 std::map<uint64_t, JumpTable *> JumpTables; 539 540 /// All jump table sites in the function before CFG is built. 541 SmallVector<std::pair<uint64_t, uint64_t>, 0> JTSites; 542 543 /// List of relocations in this function. 544 std::map<uint64_t, Relocation> Relocations; 545 546 /// Information on function constant islands. 547 std::unique_ptr<IslandInfo> Islands; 548 549 // Blocks are kept sorted in the layout order. If we need to change the 550 // layout (if BasicBlocksLayout stores a different order than BasicBlocks), 551 // the terminating instructions need to be modified. 552 using BasicBlockListType = SmallVector<BinaryBasicBlock *, 0>; 553 BasicBlockListType BasicBlocks; 554 BasicBlockListType DeletedBasicBlocks; 555 BasicBlockOrderType BasicBlocksLayout; 556 /// Previous layout replaced by modifyLayout 557 BasicBlockOrderType BasicBlocksPreviousLayout; 558 bool ModifiedLayout{false}; 559 560 /// BasicBlockOffsets are used during CFG construction to map from code 561 /// offsets to BinaryBasicBlocks. Any modifications made to the CFG 562 /// after initial construction are not reflected in this data structure. 563 using BasicBlockOffset = std::pair<uint64_t, BinaryBasicBlock *>; 564 struct CompareBasicBlockOffsets { 565 bool operator()(const BasicBlockOffset &A, 566 const BasicBlockOffset &B) const { 567 return A.first < B.first; 568 } 569 }; 570 SmallVector<BasicBlockOffset, 0> BasicBlockOffsets; 571 572 MCSymbol *ColdSymbol{nullptr}; 573 574 /// Symbol at the end of the function. 575 mutable MCSymbol *FunctionEndLabel{nullptr}; 576 577 /// Symbol at the end of the cold part of split function. 578 mutable MCSymbol *FunctionColdEndLabel{nullptr}; 579 580 /// Unique number associated with the function. 581 uint64_t FunctionNumber; 582 583 /// Count the number of functions created. 584 static uint64_t Count; 585 586 /// Map offsets of special instructions to addresses in the output. 587 InputOffsetToAddressMapTy InputOffsetToAddressMap; 588 589 /// Register alternative function name. 590 void addAlternativeName(std::string NewName) { 591 Aliases.push_back(std::move(NewName)); 592 } 593 594 /// Return a label at a given \p Address in the function. If the label does 595 /// not exist - create it. Assert if the \p Address does not belong to 596 /// the function. If \p CreatePastEnd is true, then return the function 597 /// end label when the \p Address points immediately past the last byte 598 /// of the function. 599 /// NOTE: the function always returns a local (temp) symbol, even if there's 600 /// a global symbol that corresponds to an entry at this address. 601 MCSymbol *getOrCreateLocalLabel(uint64_t Address, bool CreatePastEnd = false); 602 603 /// Register an data entry at a given \p Offset into the function. 604 void markDataAtOffset(uint64_t Offset) { 605 if (!Islands) 606 Islands = std::make_unique<IslandInfo>(); 607 Islands->DataOffsets.emplace(Offset); 608 } 609 610 /// Register an entry point at a given \p Offset into the function. 611 void markCodeAtOffset(uint64_t Offset) { 612 if (!Islands) 613 Islands = std::make_unique<IslandInfo>(); 614 Islands->CodeOffsets.emplace(Offset); 615 } 616 617 /// Register secondary entry point at a given \p Offset into the function. 618 /// Return global symbol for use by extern function references. 619 MCSymbol *addEntryPointAtOffset(uint64_t Offset); 620 621 /// Register an internal offset in a function referenced from outside. 622 void registerReferencedOffset(uint64_t Offset) { 623 ExternallyReferencedOffsets.emplace(Offset); 624 } 625 626 /// True if there are references to internals of this function from data, 627 /// e.g. from jump tables. 628 bool hasInternalReference() const { 629 return !ExternallyReferencedOffsets.empty(); 630 } 631 632 /// Return an entry ID corresponding to a symbol known to belong to 633 /// the function. 634 /// 635 /// Prefer to use BinaryContext::getFunctionForSymbol(EntrySymbol, &ID) 636 /// instead of calling this function directly. 637 uint64_t getEntryIDForSymbol(const MCSymbol *EntrySymbol) const; 638 639 /// If the function represents a secondary split function fragment, set its 640 /// parent fragment to \p BF. 641 void addParentFragment(BinaryFunction &BF) { 642 assert(this != &BF); 643 assert(IsFragment && "function must be a fragment to have a parent"); 644 ParentFragments.insert(&BF); 645 } 646 647 /// Register a child fragment for the main fragment of a split function. 648 void addFragment(BinaryFunction &BF) { 649 assert(this != &BF); 650 Fragments.insert(&BF); 651 } 652 653 void addInstruction(uint64_t Offset, MCInst &&Instruction) { 654 Instructions.emplace(Offset, std::forward<MCInst>(Instruction)); 655 } 656 657 /// Convert CFI instructions to a standard form (remove remember/restore). 658 void normalizeCFIState(); 659 660 /// Analyze and process indirect branch \p Instruction before it is 661 /// added to Instructions list. 662 IndirectBranchType processIndirectBranch(MCInst &Instruction, unsigned Size, 663 uint64_t Offset, 664 uint64_t &TargetAddress); 665 666 BinaryFunction &operator=(const BinaryFunction &) = delete; 667 BinaryFunction(const BinaryFunction &) = delete; 668 669 friend class MachORewriteInstance; 670 friend class RewriteInstance; 671 friend class BinaryContext; 672 friend class DataReader; 673 friend class DataAggregator; 674 675 static std::string buildCodeSectionName(StringRef Name, 676 const BinaryContext &BC); 677 static std::string buildColdCodeSectionName(StringRef Name, 678 const BinaryContext &BC); 679 680 /// Creation should be handled by RewriteInstance or BinaryContext 681 BinaryFunction(const std::string &Name, BinarySection &Section, 682 uint64_t Address, uint64_t Size, BinaryContext &BC) 683 : OriginSection(&Section), Address(Address), Size(Size), BC(BC), 684 CodeSectionName(buildCodeSectionName(Name, BC)), 685 ColdCodeSectionName(buildColdCodeSectionName(Name, BC)), 686 FunctionNumber(++Count) { 687 Symbols.push_back(BC.Ctx->getOrCreateSymbol(Name)); 688 } 689 690 /// This constructor is used to create an injected function 691 BinaryFunction(const std::string &Name, BinaryContext &BC, bool IsSimple) 692 : Address(0), Size(0), BC(BC), IsSimple(IsSimple), 693 CodeSectionName(buildCodeSectionName(Name, BC)), 694 ColdCodeSectionName(buildColdCodeSectionName(Name, BC)), 695 FunctionNumber(++Count) { 696 Symbols.push_back(BC.Ctx->getOrCreateSymbol(Name)); 697 IsInjected = true; 698 } 699 700 /// Create a basic block at a given \p Offset in the function and append it 701 /// to the end of list of blocks. Used during CFG construction only. 702 BinaryBasicBlock *addBasicBlockAt(uint64_t Offset, MCSymbol *Label) { 703 assert(CurrentState == State::Disassembled && 704 "Cannot add block with an offset in non-disassembled state."); 705 assert(!getBasicBlockAtOffset(Offset) && 706 "Basic block already exists at the offset."); 707 708 BasicBlocks.emplace_back(createBasicBlock(Label).release()); 709 BinaryBasicBlock *BB = BasicBlocks.back(); 710 711 BB->setIndex(BasicBlocks.size() - 1); 712 BB->setOffset(Offset); 713 714 BasicBlockOffsets.emplace_back(Offset, BB); 715 assert(llvm::is_sorted(BasicBlockOffsets, CompareBasicBlockOffsets()) && 716 llvm::is_sorted(blocks())); 717 718 return BB; 719 } 720 721 /// Clear state of the function that could not be disassembled or if its 722 /// disassembled state was later invalidated. 723 void clearDisasmState(); 724 725 /// Release memory allocated for CFG and instructions. 726 /// We still keep basic blocks for address translation/mapping purposes. 727 void releaseCFG() { 728 for (BinaryBasicBlock *BB : BasicBlocks) 729 BB->releaseCFG(); 730 for (BinaryBasicBlock *BB : DeletedBasicBlocks) 731 BB->releaseCFG(); 732 733 clearList(CallSites); 734 clearList(ColdCallSites); 735 clearList(LSDATypeTable); 736 clearList(LSDATypeAddressTable); 737 738 clearList(LabelToBB); 739 740 if (!isMultiEntry()) 741 clearList(Labels); 742 743 clearList(FrameInstructions); 744 clearList(FrameRestoreEquivalents); 745 } 746 747 public: 748 BinaryFunction(BinaryFunction &&) = default; 749 750 using iterator = pointee_iterator<BasicBlockListType::iterator>; 751 using const_iterator = pointee_iterator<BasicBlockListType::const_iterator>; 752 using reverse_iterator = 753 pointee_iterator<BasicBlockListType::reverse_iterator>; 754 using const_reverse_iterator = 755 pointee_iterator<BasicBlockListType::const_reverse_iterator>; 756 757 typedef BasicBlockOrderType::iterator order_iterator; 758 typedef BasicBlockOrderType::const_iterator const_order_iterator; 759 typedef BasicBlockOrderType::reverse_iterator reverse_order_iterator; 760 typedef BasicBlockOrderType::const_reverse_iterator 761 const_reverse_order_iterator; 762 763 // CFG iterators. 764 iterator begin() { return BasicBlocks.begin(); } 765 const_iterator begin() const { return BasicBlocks.begin(); } 766 iterator end () { return BasicBlocks.end(); } 767 const_iterator end () const { return BasicBlocks.end(); } 768 769 reverse_iterator rbegin() { return BasicBlocks.rbegin(); } 770 const_reverse_iterator rbegin() const { return BasicBlocks.rbegin(); } 771 reverse_iterator rend () { return BasicBlocks.rend(); } 772 const_reverse_iterator rend () const { return BasicBlocks.rend(); } 773 774 size_t size() const { return BasicBlocks.size();} 775 bool empty() const { return BasicBlocks.empty(); } 776 const BinaryBasicBlock &front() const { return *BasicBlocks.front(); } 777 BinaryBasicBlock &front() { return *BasicBlocks.front(); } 778 const BinaryBasicBlock & back() const { return *BasicBlocks.back(); } 779 BinaryBasicBlock & back() { return *BasicBlocks.back(); } 780 inline iterator_range<iterator> blocks() { 781 return iterator_range<iterator>(begin(), end()); 782 } 783 inline iterator_range<const_iterator> blocks() const { 784 return iterator_range<const_iterator>(begin(), end()); 785 } 786 787 // Iterators by pointer. 788 BasicBlockListType::iterator pbegin() { return BasicBlocks.begin(); } 789 BasicBlockListType::iterator pend() { return BasicBlocks.end(); } 790 791 order_iterator layout_begin() { return BasicBlocksLayout.begin(); } 792 const_order_iterator layout_begin() const 793 { return BasicBlocksLayout.begin(); } 794 order_iterator layout_end() { return BasicBlocksLayout.end(); } 795 const_order_iterator layout_end() const 796 { return BasicBlocksLayout.end(); } 797 reverse_order_iterator layout_rbegin() 798 { return BasicBlocksLayout.rbegin(); } 799 const_reverse_order_iterator layout_rbegin() const 800 { return BasicBlocksLayout.rbegin(); } 801 reverse_order_iterator layout_rend() 802 { return BasicBlocksLayout.rend(); } 803 const_reverse_order_iterator layout_rend() const 804 { return BasicBlocksLayout.rend(); } 805 size_t layout_size() const { return BasicBlocksLayout.size(); } 806 bool layout_empty() const { return BasicBlocksLayout.empty(); } 807 const BinaryBasicBlock *layout_front() const 808 { return BasicBlocksLayout.front(); } 809 BinaryBasicBlock *layout_front() { return BasicBlocksLayout.front(); } 810 const BinaryBasicBlock *layout_back() const 811 { return BasicBlocksLayout.back(); } 812 BinaryBasicBlock *layout_back() { return BasicBlocksLayout.back(); } 813 814 inline iterator_range<order_iterator> layout() { 815 return iterator_range<order_iterator>(BasicBlocksLayout.begin(), 816 BasicBlocksLayout.end()); 817 } 818 819 inline iterator_range<const_order_iterator> layout() const { 820 return iterator_range<const_order_iterator>(BasicBlocksLayout.begin(), 821 BasicBlocksLayout.end()); 822 } 823 824 inline iterator_range<reverse_order_iterator> rlayout() { 825 return iterator_range<reverse_order_iterator>(BasicBlocksLayout.rbegin(), 826 BasicBlocksLayout.rend()); 827 } 828 829 inline iterator_range<const_reverse_order_iterator> rlayout() const { 830 return iterator_range<const_reverse_order_iterator>( 831 BasicBlocksLayout.rbegin(), BasicBlocksLayout.rend()); 832 } 833 834 cfi_iterator cie_begin() { return CIEFrameInstructions.begin(); } 835 const_cfi_iterator cie_begin() const { return CIEFrameInstructions.begin(); } 836 cfi_iterator cie_end() { return CIEFrameInstructions.end(); } 837 const_cfi_iterator cie_end() const { return CIEFrameInstructions.end(); } 838 bool cie_empty() const { return CIEFrameInstructions.empty(); } 839 840 inline iterator_range<cfi_iterator> cie() { 841 return iterator_range<cfi_iterator>(cie_begin(), cie_end()); 842 } 843 inline iterator_range<const_cfi_iterator> cie() const { 844 return iterator_range<const_cfi_iterator>(cie_begin(), cie_end()); 845 } 846 847 /// Iterate over all jump tables associated with this function. 848 iterator_range<std::map<uint64_t, JumpTable *>::const_iterator> 849 jumpTables() const { 850 return make_range(JumpTables.begin(), JumpTables.end()); 851 } 852 853 /// Return relocation associated with a given \p Offset in the function, 854 /// or nullptr if no such relocation exists. 855 const Relocation *getRelocationAt(uint64_t Offset) const { 856 assert(CurrentState == State::Empty && 857 "Relocations unavailable in the current function state."); 858 auto RI = Relocations.find(Offset); 859 return (RI == Relocations.end()) ? nullptr : &RI->second; 860 } 861 862 /// Return the first relocation in the function that starts at an address in 863 /// the [StartOffset, EndOffset) range. Return nullptr if no such relocation 864 /// exists. 865 const Relocation *getRelocationInRange(uint64_t StartOffset, 866 uint64_t EndOffset) const { 867 assert(CurrentState == State::Empty && 868 "Relocations unavailable in the current function state."); 869 auto RI = Relocations.lower_bound(StartOffset); 870 if (RI != Relocations.end() && RI->first < EndOffset) 871 return &RI->second; 872 873 return nullptr; 874 } 875 876 /// Returns the raw binary encoding of this function. 877 ErrorOr<ArrayRef<uint8_t>> getData() const; 878 879 BinaryFunction &updateState(BinaryFunction::State State) { 880 CurrentState = State; 881 return *this; 882 } 883 884 /// Update layout of basic blocks used for output. 885 void updateBasicBlockLayout(BasicBlockOrderType &NewLayout) { 886 assert(NewLayout.size() == BasicBlocks.size() && "Layout size mismatch."); 887 888 BasicBlocksPreviousLayout = BasicBlocksLayout; 889 if (NewLayout != BasicBlocksLayout) { 890 ModifiedLayout = true; 891 BasicBlocksLayout.clear(); 892 BasicBlocksLayout.swap(NewLayout); 893 } 894 } 895 896 /// Recompute landing pad information for the function and all its blocks. 897 void recomputeLandingPads(); 898 899 /// Return current basic block layout. 900 const BasicBlockOrderType &getLayout() const { return BasicBlocksLayout; } 901 902 /// Return a list of basic blocks sorted using DFS and update layout indices 903 /// using the same order. Does not modify the current layout. 904 BasicBlockOrderType dfs() const; 905 906 /// Find the loops in the CFG of the function and store information about 907 /// them. 908 void calculateLoopInfo(); 909 910 /// Calculate missed macro-fusion opportunities and update BinaryContext 911 /// stats. 912 void calculateMacroOpFusionStats(); 913 914 /// Returns if loop detection has been run for this function. 915 bool hasLoopInfo() const { return BLI != nullptr; } 916 917 const BinaryLoopInfo &getLoopInfo() { return *BLI.get(); } 918 919 bool isLoopFree() { 920 if (!hasLoopInfo()) 921 calculateLoopInfo(); 922 return BLI->empty(); 923 } 924 925 /// Print loop information about the function. 926 void printLoopInfo(raw_ostream &OS) const; 927 928 /// View CFG in graphviz program 929 void viewGraph() const; 930 931 /// Dump CFG in graphviz format 932 void dumpGraph(raw_ostream &OS) const; 933 934 /// Dump CFG in graphviz format to file. 935 void dumpGraphToFile(std::string Filename) const; 936 937 /// Dump CFG in graphviz format to a file with a filename that is derived 938 /// from the function name and Annotation strings. Useful for dumping the 939 /// CFG after an optimization pass. 940 void dumpGraphForPass(std::string Annotation = "") const; 941 942 /// Return BinaryContext for the function. 943 const BinaryContext &getBinaryContext() const { return BC; } 944 945 /// Return BinaryContext for the function. 946 BinaryContext &getBinaryContext() { return BC; } 947 948 /// Attempt to validate CFG invariants. 949 bool validateCFG() const; 950 951 BinaryBasicBlock *getBasicBlockForLabel(const MCSymbol *Label) { 952 auto I = LabelToBB.find(Label); 953 return I == LabelToBB.end() ? nullptr : I->second; 954 } 955 956 const BinaryBasicBlock *getBasicBlockForLabel(const MCSymbol *Label) const { 957 auto I = LabelToBB.find(Label); 958 return I == LabelToBB.end() ? nullptr : I->second; 959 } 960 961 /// Returns the basic block after the given basic block in the layout or 962 /// nullptr the last basic block is given. 963 const BinaryBasicBlock *getBasicBlockAfter(const BinaryBasicBlock *BB, 964 bool IgnoreSplits = true) const { 965 return const_cast<BinaryFunction *>(this)->getBasicBlockAfter(BB, 966 IgnoreSplits); 967 } 968 969 BinaryBasicBlock *getBasicBlockAfter(const BinaryBasicBlock *BB, 970 bool IgnoreSplits = true) { 971 for (auto I = layout_begin(), E = layout_end(); I != E; ++I) { 972 auto Next = std::next(I); 973 if (*I == BB && Next != E) { 974 return (IgnoreSplits || (*I)->isCold() == (*Next)->isCold()) ? *Next 975 : nullptr; 976 } 977 } 978 return nullptr; 979 } 980 981 /// Retrieve the landing pad BB associated with invoke instruction \p Invoke 982 /// that is in \p BB. Return nullptr if none exists 983 BinaryBasicBlock *getLandingPadBBFor(const BinaryBasicBlock &BB, 984 const MCInst &InvokeInst) const { 985 assert(BC.MIB->isInvoke(InvokeInst) && "must be invoke instruction"); 986 const Optional<MCPlus::MCLandingPad> LP = BC.MIB->getEHInfo(InvokeInst); 987 if (LP && LP->first) { 988 BinaryBasicBlock *LBB = BB.getLandingPad(LP->first); 989 assert(LBB && "Landing pad should be defined"); 990 return LBB; 991 } 992 return nullptr; 993 } 994 995 /// Return instruction at a given offset in the function. Valid before 996 /// CFG is constructed or while instruction offsets are available in CFG. 997 MCInst *getInstructionAtOffset(uint64_t Offset); 998 999 const MCInst *getInstructionAtOffset(uint64_t Offset) const { 1000 return const_cast<BinaryFunction *>(this)->getInstructionAtOffset(Offset); 1001 } 1002 1003 /// Return offset for the first instruction. If there is data at the 1004 /// beginning of a function then offset of the first instruction could 1005 /// be different from 0 1006 uint64_t getFirstInstructionOffset() const { 1007 if (Instructions.empty()) 1008 return 0; 1009 return Instructions.begin()->first; 1010 } 1011 1012 /// Return jump table that covers a given \p Address in memory. 1013 JumpTable *getJumpTableContainingAddress(uint64_t Address) { 1014 auto JTI = JumpTables.upper_bound(Address); 1015 if (JTI == JumpTables.begin()) 1016 return nullptr; 1017 --JTI; 1018 if (JTI->first + JTI->second->getSize() > Address) 1019 return JTI->second; 1020 if (JTI->second->getSize() == 0 && JTI->first == Address) 1021 return JTI->second; 1022 return nullptr; 1023 } 1024 1025 const JumpTable *getJumpTableContainingAddress(uint64_t Address) const { 1026 return const_cast<BinaryFunction *>(this)->getJumpTableContainingAddress( 1027 Address); 1028 } 1029 1030 /// Return the name of the function if the function has just one name. 1031 /// If the function has multiple names - return one followed 1032 /// by "(*#<numnames>)". 1033 /// 1034 /// We should use getPrintName() for diagnostics and use 1035 /// hasName() to match function name against a given string. 1036 /// 1037 /// NOTE: for disambiguating names of local symbols we use the following 1038 /// naming schemes: 1039 /// primary: <function>/<id> 1040 /// alternative: <function>/<file>/<id2> 1041 std::string getPrintName() const { 1042 const size_t NumNames = Symbols.size() + Aliases.size(); 1043 return NumNames == 1 1044 ? getOneName().str() 1045 : (getOneName().str() + "(*" + std::to_string(NumNames) + ")"); 1046 } 1047 1048 /// The function may have many names. For that reason, we avoid having 1049 /// getName() method as most of the time the user needs a different 1050 /// interface, such as forEachName(), hasName(), hasNameRegex(), etc. 1051 /// In some cases though, we need just a name uniquely identifying 1052 /// the function, and that's what this method is for. 1053 StringRef getOneName() const { return Symbols[0]->getName(); } 1054 1055 /// Return the name of the function as getPrintName(), but also trying 1056 /// to demangle it. 1057 std::string getDemangledName() const; 1058 1059 /// Call \p Callback for every name of this function as long as the Callback 1060 /// returns false. Stop if Callback returns true or all names have been used. 1061 /// Return the name for which the Callback returned true if any. 1062 template <typename FType> 1063 Optional<StringRef> forEachName(FType Callback) const { 1064 for (MCSymbol *Symbol : Symbols) 1065 if (Callback(Symbol->getName())) 1066 return Symbol->getName(); 1067 1068 for (const std::string &Name : Aliases) 1069 if (Callback(StringRef(Name))) 1070 return StringRef(Name); 1071 1072 return NoneType(); 1073 } 1074 1075 /// Check if (possibly one out of many) function name matches the given 1076 /// string. Use this member function instead of direct name comparison. 1077 bool hasName(const std::string &FunctionName) const { 1078 auto Res = 1079 forEachName([&](StringRef Name) { return Name == FunctionName; }); 1080 return Res.hasValue(); 1081 } 1082 1083 /// Check if any of function names matches the given regex. 1084 Optional<StringRef> hasNameRegex(const StringRef NameRegex) const; 1085 1086 /// Check if any of restored function names matches the given regex. 1087 /// Restored name means stripping BOLT-added suffixes like "/1", 1088 Optional<StringRef> hasRestoredNameRegex(const StringRef NameRegex) const; 1089 1090 /// Return a vector of all possible names for the function. 1091 const std::vector<StringRef> getNames() const { 1092 std::vector<StringRef> AllNames; 1093 forEachName([&AllNames](StringRef Name) { 1094 AllNames.push_back(Name); 1095 return false; 1096 }); 1097 1098 return AllNames; 1099 } 1100 1101 /// Return a state the function is in (see BinaryFunction::State definition 1102 /// for description). 1103 State getState() const { return CurrentState; } 1104 1105 /// Return true if function has a control flow graph available. 1106 bool hasCFG() const { 1107 return getState() == State::CFG || getState() == State::CFG_Finalized || 1108 getState() == State::EmittedCFG; 1109 } 1110 1111 /// Return true if the function state implies that it includes instructions. 1112 bool hasInstructions() const { 1113 return getState() == State::Disassembled || hasCFG(); 1114 } 1115 1116 bool isEmitted() const { 1117 return getState() == State::EmittedCFG || getState() == State::Emitted; 1118 } 1119 1120 /// Return the section in the input binary this function originated from or 1121 /// nullptr if the function did not originate from the file. 1122 BinarySection *getOriginSection() const { return OriginSection; } 1123 1124 void setOriginSection(BinarySection *Section) { OriginSection = Section; } 1125 1126 /// Return true if the function did not originate from the primary input file. 1127 bool isInjected() const { return IsInjected; } 1128 1129 /// Return original address of the function (or offset from base for PIC). 1130 uint64_t getAddress() const { return Address; } 1131 1132 uint64_t getOutputAddress() const { return OutputAddress; } 1133 1134 uint64_t getOutputSize() const { return OutputSize; } 1135 1136 /// Does this function have a valid streaming order index? 1137 bool hasValidIndex() const { return Index != -1U; } 1138 1139 /// Get the streaming order index for this function. 1140 uint32_t getIndex() const { return Index; } 1141 1142 /// Set the streaming order index for this function. 1143 void setIndex(uint32_t Idx) { 1144 assert(!hasValidIndex()); 1145 Index = Idx; 1146 } 1147 1148 /// Return offset of the function body in the binary file. 1149 uint64_t getFileOffset() const { return FileOffset; } 1150 1151 /// Return (original) byte size of the function. 1152 uint64_t getSize() const { return Size; } 1153 1154 /// Return the maximum size the body of the function could have. 1155 uint64_t getMaxSize() const { return MaxSize; } 1156 1157 /// Return the number of emitted instructions for this function. 1158 uint32_t getNumNonPseudos() const { 1159 uint32_t N = 0; 1160 for (const BinaryBasicBlock &BB : blocks()) 1161 N += BB.getNumNonPseudos(); 1162 return N; 1163 } 1164 1165 /// Return MC symbol associated with the function. 1166 /// All references to the function should use this symbol. 1167 MCSymbol *getSymbol() { return Symbols[0]; } 1168 1169 /// Return MC symbol associated with the function (const version). 1170 /// All references to the function should use this symbol. 1171 const MCSymbol *getSymbol() const { return Symbols[0]; } 1172 1173 /// Return a list of symbols associated with the main entry of the function. 1174 SymbolListTy &getSymbols() { return Symbols; } 1175 const SymbolListTy &getSymbols() const { return Symbols; } 1176 1177 /// If a local symbol \p BBLabel corresponds to a basic block that is a 1178 /// secondary entry point into the function, then return a global symbol 1179 /// that represents the secondary entry point. Otherwise return nullptr. 1180 MCSymbol *getSecondaryEntryPointSymbol(const MCSymbol *BBLabel) const { 1181 auto I = SecondaryEntryPoints.find(BBLabel); 1182 if (I == SecondaryEntryPoints.end()) 1183 return nullptr; 1184 1185 return I->second; 1186 } 1187 1188 /// If the basic block serves as a secondary entry point to the function, 1189 /// return a global symbol representing the entry. Otherwise return nullptr. 1190 MCSymbol *getSecondaryEntryPointSymbol(const BinaryBasicBlock &BB) const { 1191 return getSecondaryEntryPointSymbol(BB.getLabel()); 1192 } 1193 1194 /// Return true if the basic block is an entry point into the function 1195 /// (either primary or secondary). 1196 bool isEntryPoint(const BinaryBasicBlock &BB) const { 1197 if (&BB == BasicBlocks.front()) 1198 return true; 1199 return getSecondaryEntryPointSymbol(BB); 1200 } 1201 1202 /// Return MC symbol corresponding to an enumerated entry for multiple-entry 1203 /// functions. 1204 MCSymbol *getSymbolForEntryID(uint64_t EntryNum); 1205 const MCSymbol *getSymbolForEntryID(uint64_t EntryNum) const { 1206 return const_cast<BinaryFunction *>(this)->getSymbolForEntryID(EntryNum); 1207 } 1208 1209 using EntryPointCallbackTy = function_ref<bool(uint64_t, const MCSymbol *)>; 1210 1211 /// Invoke \p Callback function for every entry point in the function starting 1212 /// with the main entry and using entries in the ascending address order. 1213 /// Stop calling the function after false is returned by the callback. 1214 /// 1215 /// Pass an offset of the entry point in the input binary and a corresponding 1216 /// global symbol to the callback function. 1217 /// 1218 /// Return true of all callbacks returned true, false otherwise. 1219 bool forEachEntryPoint(EntryPointCallbackTy Callback) const; 1220 1221 MCSymbol *getColdSymbol() { 1222 if (ColdSymbol) 1223 return ColdSymbol; 1224 1225 ColdSymbol = BC.Ctx->getOrCreateSymbol( 1226 NameResolver::append(getSymbol()->getName(), ".cold.0")); 1227 1228 return ColdSymbol; 1229 } 1230 1231 /// Return MC symbol associated with the end of the function. 1232 MCSymbol *getFunctionEndLabel() const { 1233 assert(BC.Ctx && "cannot be called with empty context"); 1234 if (!FunctionEndLabel) { 1235 std::unique_lock<std::shared_timed_mutex> Lock(BC.CtxMutex); 1236 FunctionEndLabel = BC.Ctx->createNamedTempSymbol("func_end"); 1237 } 1238 return FunctionEndLabel; 1239 } 1240 1241 /// Return MC symbol associated with the end of the cold part of the function. 1242 MCSymbol *getFunctionColdEndLabel() const { 1243 if (!FunctionColdEndLabel) { 1244 std::unique_lock<std::shared_timed_mutex> Lock(BC.CtxMutex); 1245 FunctionColdEndLabel = BC.Ctx->createNamedTempSymbol("func_cold_end"); 1246 } 1247 return FunctionColdEndLabel; 1248 } 1249 1250 /// Return a label used to identify where the constant island was emitted 1251 /// (AArch only). This is used to update the symbol table accordingly, 1252 /// emitting data marker symbols as required by the ABI. 1253 MCSymbol *getFunctionConstantIslandLabel() const { 1254 assert(Islands && "function expected to have constant islands"); 1255 1256 if (!Islands->FunctionConstantIslandLabel) { 1257 Islands->FunctionConstantIslandLabel = 1258 BC.Ctx->createNamedTempSymbol("func_const_island"); 1259 } 1260 return Islands->FunctionConstantIslandLabel; 1261 } 1262 1263 MCSymbol *getFunctionColdConstantIslandLabel() const { 1264 assert(Islands && "function expected to have constant islands"); 1265 1266 if (!Islands->FunctionColdConstantIslandLabel) { 1267 Islands->FunctionColdConstantIslandLabel = 1268 BC.Ctx->createNamedTempSymbol("func_cold_const_island"); 1269 } 1270 return Islands->FunctionColdConstantIslandLabel; 1271 } 1272 1273 /// Return true if this is a function representing a PLT entry. 1274 bool isPLTFunction() const { return PLTSymbol != nullptr; } 1275 1276 /// Return PLT function reference symbol for PLT functions and nullptr for 1277 /// non-PLT functions. 1278 const MCSymbol *getPLTSymbol() const { return PLTSymbol; } 1279 1280 /// Set function PLT reference symbol for PLT functions. 1281 void setPLTSymbol(const MCSymbol *Symbol) { 1282 assert(Size == 0 && "function size should be 0 for PLT functions"); 1283 PLTSymbol = Symbol; 1284 IsPseudo = true; 1285 } 1286 1287 /// Update output values of the function based on the final \p Layout. 1288 void updateOutputValues(const MCAsmLayout &Layout); 1289 1290 /// Return mapping of input to output addresses. Most users should call 1291 /// translateInputToOutputAddress() for address translation. 1292 InputOffsetToAddressMapTy &getInputOffsetToAddressMap() { 1293 assert(isEmitted() && "cannot use address mapping before code emission"); 1294 return InputOffsetToAddressMap; 1295 } 1296 1297 void addRelocationAArch64(uint64_t Offset, MCSymbol *Symbol, uint64_t RelType, 1298 uint64_t Addend, uint64_t Value, bool IsCI) { 1299 std::map<uint64_t, Relocation> &Rels = 1300 (IsCI) ? Islands->Relocations : Relocations; 1301 switch (RelType) { 1302 case ELF::R_AARCH64_ABS64: 1303 case ELF::R_AARCH64_ABS32: 1304 case ELF::R_AARCH64_ABS16: 1305 case ELF::R_AARCH64_ADD_ABS_LO12_NC: 1306 case ELF::R_AARCH64_ADR_GOT_PAGE: 1307 case ELF::R_AARCH64_ADR_PREL_LO21: 1308 case ELF::R_AARCH64_ADR_PREL_PG_HI21: 1309 case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: 1310 case ELF::R_AARCH64_LD64_GOT_LO12_NC: 1311 case ELF::R_AARCH64_LDST8_ABS_LO12_NC: 1312 case ELF::R_AARCH64_LDST16_ABS_LO12_NC: 1313 case ELF::R_AARCH64_LDST32_ABS_LO12_NC: 1314 case ELF::R_AARCH64_LDST64_ABS_LO12_NC: 1315 case ELF::R_AARCH64_LDST128_ABS_LO12_NC: 1316 case ELF::R_AARCH64_TLSDESC_ADD_LO12: 1317 case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 1318 case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 1319 case ELF::R_AARCH64_TLSDESC_LD64_LO12: 1320 case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 1321 case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 1322 case ELF::R_AARCH64_MOVW_UABS_G0: 1323 case ELF::R_AARCH64_MOVW_UABS_G0_NC: 1324 case ELF::R_AARCH64_MOVW_UABS_G1: 1325 case ELF::R_AARCH64_MOVW_UABS_G1_NC: 1326 case ELF::R_AARCH64_MOVW_UABS_G2: 1327 case ELF::R_AARCH64_MOVW_UABS_G2_NC: 1328 case ELF::R_AARCH64_MOVW_UABS_G3: 1329 case ELF::R_AARCH64_PREL16: 1330 case ELF::R_AARCH64_PREL32: 1331 case ELF::R_AARCH64_PREL64: 1332 Rels[Offset] = Relocation{Offset, Symbol, RelType, Addend, Value}; 1333 return; 1334 case ELF::R_AARCH64_CALL26: 1335 case ELF::R_AARCH64_JUMP26: 1336 case ELF::R_AARCH64_TSTBR14: 1337 case ELF::R_AARCH64_CONDBR19: 1338 case ELF::R_AARCH64_TLSDESC_CALL: 1339 case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: 1340 case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: 1341 return; 1342 default: 1343 llvm_unreachable("Unexpected AArch64 relocation type in code"); 1344 } 1345 } 1346 1347 void addRelocationX86(uint64_t Offset, MCSymbol *Symbol, uint64_t RelType, 1348 uint64_t Addend, uint64_t Value) { 1349 switch (RelType) { 1350 case ELF::R_X86_64_8: 1351 case ELF::R_X86_64_16: 1352 case ELF::R_X86_64_32: 1353 case ELF::R_X86_64_32S: 1354 case ELF::R_X86_64_64: 1355 case ELF::R_X86_64_PC8: 1356 case ELF::R_X86_64_PC32: 1357 case ELF::R_X86_64_PC64: 1358 case ELF::R_X86_64_GOTPCRELX: 1359 case ELF::R_X86_64_REX_GOTPCRELX: 1360 Relocations[Offset] = Relocation{Offset, Symbol, RelType, Addend, Value}; 1361 return; 1362 case ELF::R_X86_64_PLT32: 1363 case ELF::R_X86_64_GOTPCREL: 1364 case ELF::R_X86_64_TPOFF32: 1365 case ELF::R_X86_64_GOTTPOFF: 1366 return; 1367 default: 1368 llvm_unreachable("Unexpected x86 relocation type in code"); 1369 } 1370 } 1371 1372 /// Register relocation type \p RelType at a given \p Address in the function 1373 /// against \p Symbol. 1374 /// Assert if the \p Address is not inside this function. 1375 void addRelocation(uint64_t Address, MCSymbol *Symbol, uint64_t RelType, 1376 uint64_t Addend, uint64_t Value) { 1377 assert(Address >= getAddress() && Address < getAddress() + getMaxSize() && 1378 "address is outside of the function"); 1379 uint64_t Offset = Address - getAddress(); 1380 if (BC.isAArch64()) { 1381 return addRelocationAArch64(Offset, Symbol, RelType, Addend, Value, 1382 isInConstantIsland(Address)); 1383 } 1384 1385 return addRelocationX86(Offset, Symbol, RelType, Addend, Value); 1386 } 1387 1388 /// Return the name of the section this function originated from. 1389 Optional<StringRef> getOriginSectionName() const { 1390 if (!OriginSection) 1391 return NoneType(); 1392 return OriginSection->getName(); 1393 } 1394 1395 /// Return internal section name for this function. 1396 StringRef getCodeSectionName() const { return StringRef(CodeSectionName); } 1397 1398 /// Assign a code section name to the function. 1399 void setCodeSectionName(StringRef Name) { 1400 CodeSectionName = std::string(Name); 1401 } 1402 1403 /// Get output code section. 1404 ErrorOr<BinarySection &> getCodeSection() const { 1405 return BC.getUniqueSectionByName(getCodeSectionName()); 1406 } 1407 1408 /// Return cold code section name for the function. 1409 StringRef getColdCodeSectionName() const { 1410 return StringRef(ColdCodeSectionName); 1411 } 1412 1413 /// Assign a section name for the cold part of the function. 1414 void setColdCodeSectionName(StringRef Name) { 1415 ColdCodeSectionName = std::string(Name); 1416 } 1417 1418 /// Get output code section for cold code of this function. 1419 ErrorOr<BinarySection &> getColdCodeSection() const { 1420 return BC.getUniqueSectionByName(getColdCodeSectionName()); 1421 } 1422 1423 /// Return true iif the function will halt execution on entry. 1424 bool trapsOnEntry() const { return TrapsOnEntry; } 1425 1426 /// Make the function always trap on entry. Other than the trap instruction, 1427 /// the function body will be empty. 1428 void setTrapOnEntry(); 1429 1430 /// Return true if the function could be correctly processed. 1431 bool isSimple() const { return IsSimple; } 1432 1433 /// Return true if the function should be ignored for optimization purposes. 1434 bool isIgnored() const { return IsIgnored; } 1435 1436 /// Return true if the function should not be disassembled, emitted, or 1437 /// otherwise processed. 1438 bool isPseudo() const { return IsPseudo; } 1439 1440 /// Return true if the function contains explicit or implicit indirect branch 1441 /// to its split fragments, e.g., split jump table, landing pad in split 1442 /// fragment. 1443 bool hasIndirectTargetToSplitFragment() const { 1444 return HasIndirectTargetToSplitFragment; 1445 } 1446 1447 /// Return true if all CFG edges have local successors. 1448 bool hasCanonicalCFG() const { return HasCanonicalCFG; } 1449 1450 /// Return true if the original function code has all necessary relocations 1451 /// to track addresses of functions emitted to new locations. 1452 bool hasExternalRefRelocations() const { return HasExternalRefRelocations; } 1453 1454 /// Return true if the function has instruction(s) with unknown control flow. 1455 bool hasUnknownControlFlow() const { return HasUnknownControlFlow; } 1456 1457 /// Return true if the function body is non-contiguous. 1458 bool isSplit() const { 1459 return isSimple() && layout_size() && 1460 layout_front()->isCold() != layout_back()->isCold(); 1461 } 1462 1463 bool shouldPreserveNops() const { return PreserveNops; } 1464 1465 /// Return true if the function has exception handling tables. 1466 bool hasEHRanges() const { return HasEHRanges; } 1467 1468 /// Return true if the function uses DW_CFA_GNU_args_size CFIs. 1469 bool usesGnuArgsSize() const { return UsesGnuArgsSize; } 1470 1471 /// Return true if the function has more than one entry point. 1472 bool isMultiEntry() const { return !SecondaryEntryPoints.empty(); } 1473 1474 /// Return true if the function might have a profile available externally, 1475 /// but not yet populated into the function. 1476 bool hasProfileAvailable() const { return HasProfileAvailable; } 1477 1478 bool hasMemoryProfile() const { return HasMemoryProfile; } 1479 1480 /// Return true if the body of the function was merged into another function. 1481 bool isFolded() const { return FoldedIntoFunction != nullptr; } 1482 1483 /// If this function was folded, return the function it was folded into. 1484 BinaryFunction *getFoldedIntoFunction() const { return FoldedIntoFunction; } 1485 1486 /// Return true if the function uses jump tables. 1487 bool hasJumpTables() const { return !JumpTables.empty(); } 1488 1489 /// Return true if the function has SDT marker 1490 bool hasSDTMarker() const { return HasSDTMarker; } 1491 1492 /// Return true if the function has Pseudo Probe 1493 bool hasPseudoProbe() const { return HasPseudoProbe; } 1494 1495 /// Return true if the original entry point was patched. 1496 bool isPatched() const { return IsPatched; } 1497 1498 const JumpTable *getJumpTable(const MCInst &Inst) const { 1499 const uint64_t Address = BC.MIB->getJumpTable(Inst); 1500 return getJumpTableContainingAddress(Address); 1501 } 1502 1503 JumpTable *getJumpTable(const MCInst &Inst) { 1504 const uint64_t Address = BC.MIB->getJumpTable(Inst); 1505 return getJumpTableContainingAddress(Address); 1506 } 1507 1508 const MCSymbol *getPersonalityFunction() const { return PersonalityFunction; } 1509 1510 uint8_t getPersonalityEncoding() const { return PersonalityEncoding; } 1511 1512 const CallSitesType &getCallSites() const { return CallSites; } 1513 1514 const CallSitesType &getColdCallSites() const { return ColdCallSites; } 1515 1516 const ArrayRef<uint8_t> getLSDAActionTable() const { return LSDAActionTable; } 1517 1518 const LSDATypeTableTy &getLSDATypeTable() const { return LSDATypeTable; } 1519 1520 const LSDATypeTableTy &getLSDATypeAddressTable() const { 1521 return LSDATypeAddressTable; 1522 } 1523 1524 const ArrayRef<uint8_t> getLSDATypeIndexTable() const { 1525 return LSDATypeIndexTable; 1526 } 1527 1528 const LabelsMapType &getLabels() const { return Labels; } 1529 1530 IslandInfo &getIslandInfo() { 1531 assert(Islands && "function expected to have constant islands"); 1532 return *Islands; 1533 } 1534 1535 const IslandInfo &getIslandInfo() const { 1536 assert(Islands && "function expected to have constant islands"); 1537 return *Islands; 1538 } 1539 1540 /// Return true if the function has CFI instructions 1541 bool hasCFI() const { 1542 return !FrameInstructions.empty() || !CIEFrameInstructions.empty(); 1543 } 1544 1545 /// Return unique number associated with the function. 1546 uint64_t getFunctionNumber() const { return FunctionNumber; } 1547 1548 /// Return true if the given address \p PC is inside the function body. 1549 bool containsAddress(uint64_t PC, bool UseMaxSize = false) const { 1550 if (UseMaxSize) 1551 return Address <= PC && PC < Address + MaxSize; 1552 return Address <= PC && PC < Address + Size; 1553 } 1554 1555 /// Create a basic block in the function. The new block is *NOT* inserted 1556 /// into the CFG. The caller must use insertBasicBlocks() to add any new 1557 /// blocks to the CFG. 1558 std::unique_ptr<BinaryBasicBlock> 1559 createBasicBlock(MCSymbol *Label = nullptr) { 1560 if (!Label) { 1561 std::unique_lock<std::shared_timed_mutex> Lock(BC.CtxMutex); 1562 Label = BC.Ctx->createNamedTempSymbol("BB"); 1563 } 1564 auto BB = 1565 std::unique_ptr<BinaryBasicBlock>(new BinaryBasicBlock(this, Label)); 1566 1567 LabelToBB[Label] = BB.get(); 1568 1569 return BB; 1570 } 1571 1572 /// Create a new basic block with an optional \p Label and add it to the list 1573 /// of basic blocks of this function. 1574 BinaryBasicBlock *addBasicBlock(MCSymbol *Label = nullptr) { 1575 assert(CurrentState == State::CFG && "Can only add blocks in CFG state"); 1576 1577 BasicBlocks.emplace_back(createBasicBlock(Label).release()); 1578 BinaryBasicBlock *BB = BasicBlocks.back(); 1579 1580 BB->setIndex(BasicBlocks.size() - 1); 1581 BB->setLayoutIndex(layout_size()); 1582 BasicBlocksLayout.emplace_back(BB); 1583 1584 return BB; 1585 } 1586 1587 /// Add basic block \BB as an entry point to the function. Return global 1588 /// symbol associated with the entry. 1589 MCSymbol *addEntryPoint(const BinaryBasicBlock &BB); 1590 1591 /// Mark all blocks that are unreachable from a root (entry point 1592 /// or landing pad) as invalid. 1593 void markUnreachableBlocks(); 1594 1595 /// Rebuilds BBs layout, ignoring dead BBs. Returns the number of removed 1596 /// BBs and the removed number of bytes of code. 1597 std::pair<unsigned, uint64_t> eraseInvalidBBs(); 1598 1599 /// Get the relative order between two basic blocks in the original 1600 /// layout. The result is > 0 if B occurs before A and < 0 if B 1601 /// occurs after A. If A and B are the same block, the result is 0. 1602 signed getOriginalLayoutRelativeOrder(const BinaryBasicBlock *A, 1603 const BinaryBasicBlock *B) const { 1604 return getIndex(A) - getIndex(B); 1605 } 1606 1607 /// Insert the BBs contained in NewBBs into the basic blocks for this 1608 /// function. Update the associated state of all blocks as needed, i.e. 1609 /// BB offsets and BB indices. The new BBs are inserted after Start. 1610 /// This operation could affect fallthrough branches for Start. 1611 /// 1612 void 1613 insertBasicBlocks(BinaryBasicBlock *Start, 1614 std::vector<std::unique_ptr<BinaryBasicBlock>> &&NewBBs, 1615 const bool UpdateLayout = true, 1616 const bool UpdateCFIState = true, 1617 const bool RecomputeLandingPads = true); 1618 1619 iterator insertBasicBlocks( 1620 iterator StartBB, std::vector<std::unique_ptr<BinaryBasicBlock>> &&NewBBs, 1621 const bool UpdateLayout = true, const bool UpdateCFIState = true, 1622 const bool RecomputeLandingPads = true); 1623 1624 /// Update the basic block layout for this function. The BBs from 1625 /// [Start->Index, Start->Index + NumNewBlocks) are inserted into the 1626 /// layout after the BB indicated by Start. 1627 void updateLayout(BinaryBasicBlock *Start, const unsigned NumNewBlocks); 1628 1629 /// Make sure basic blocks' indices match the current layout. 1630 void updateLayoutIndices() const { 1631 unsigned Index = 0; 1632 for (BinaryBasicBlock *BB : layout()) 1633 BB->setLayoutIndex(Index++); 1634 } 1635 1636 /// Recompute the CFI state for NumNewBlocks following Start after inserting 1637 /// new blocks into the CFG. This must be called after updateLayout. 1638 void updateCFIState(BinaryBasicBlock *Start, const unsigned NumNewBlocks); 1639 1640 /// Return true if we detected ambiguous jump tables in this function, which 1641 /// happen when one JT is used in more than one indirect jumps. This precludes 1642 /// us from splitting edges for this JT unless we duplicate the JT (see 1643 /// disambiguateJumpTables). 1644 bool checkForAmbiguousJumpTables(); 1645 1646 /// Detect when two distinct indirect jumps are using the same jump table and 1647 /// duplicate it, allocating a separate JT for each indirect branch. This is 1648 /// necessary for code transformations on the CFG that change an edge induced 1649 /// by an indirect branch, e.g.: instrumentation or shrink wrapping. However, 1650 /// this is only possible if we are not updating jump tables in place, but are 1651 /// writing it to a new location (moving them). 1652 void disambiguateJumpTables(MCPlusBuilder::AllocatorIdTy AllocId); 1653 1654 /// Change \p OrigDest to \p NewDest in the jump table used at the end of 1655 /// \p BB. Returns false if \p OrigDest couldn't be find as a valid target 1656 /// and no replacement took place. 1657 bool replaceJumpTableEntryIn(BinaryBasicBlock *BB, BinaryBasicBlock *OldDest, 1658 BinaryBasicBlock *NewDest); 1659 1660 /// Split the CFG edge <From, To> by inserting an intermediate basic block. 1661 /// Returns a pointer to this new intermediate basic block. BB "From" will be 1662 /// updated to jump to the intermediate block, which in turn will have an 1663 /// unconditional branch to BB "To". 1664 /// User needs to manually call fixBranches(). This function only creates the 1665 /// correct CFG edges. 1666 BinaryBasicBlock *splitEdge(BinaryBasicBlock *From, BinaryBasicBlock *To); 1667 1668 /// We may have built an overly conservative CFG for functions with calls 1669 /// to functions that the compiler knows will never return. In this case, 1670 /// clear all successors from these blocks. 1671 void deleteConservativeEdges(); 1672 1673 /// Determine direction of the branch based on the current layout. 1674 /// Callee is responsible of updating basic block indices prior to using 1675 /// this function (e.g. by calling BinaryFunction::updateLayoutIndices()). 1676 static bool isForwardBranch(const BinaryBasicBlock *From, 1677 const BinaryBasicBlock *To) { 1678 assert(From->getFunction() == To->getFunction() && 1679 "basic blocks should be in the same function"); 1680 return To->getLayoutIndex() > From->getLayoutIndex(); 1681 } 1682 1683 /// Determine direction of the call to callee symbol relative to the start 1684 /// of this function. 1685 /// Note: this doesn't take function splitting into account. 1686 bool isForwardCall(const MCSymbol *CalleeSymbol) const; 1687 1688 /// Dump function information to debug output. If \p PrintInstructions 1689 /// is true - include instruction disassembly. 1690 void dump(bool PrintInstructions = true) const; 1691 1692 /// Print function information to the \p OS stream. 1693 void print(raw_ostream &OS, std::string Annotation = "", 1694 bool PrintInstructions = true) const; 1695 1696 /// Print all relocations between \p Offset and \p Offset + \p Size in 1697 /// this function. 1698 void printRelocations(raw_ostream &OS, uint64_t Offset, uint64_t Size) const; 1699 1700 /// Return true if function has a profile, even if the profile does not 1701 /// match CFG 100%. 1702 bool hasProfile() const { return ExecutionCount != COUNT_NO_PROFILE; } 1703 1704 /// Return true if function profile is present and accurate. 1705 bool hasValidProfile() const { 1706 return ExecutionCount != COUNT_NO_PROFILE && ProfileMatchRatio == 1.0f; 1707 } 1708 1709 /// Mark this function as having a valid profile. 1710 void markProfiled(uint16_t Flags) { 1711 if (ExecutionCount == COUNT_NO_PROFILE) 1712 ExecutionCount = 0; 1713 ProfileFlags = Flags; 1714 ProfileMatchRatio = 1.0f; 1715 } 1716 1717 /// Return flags describing a profile for this function. 1718 uint16_t getProfileFlags() const { return ProfileFlags; } 1719 1720 void addCFIInstruction(uint64_t Offset, MCCFIInstruction &&Inst) { 1721 assert(!Instructions.empty()); 1722 1723 // Fix CFI instructions skipping NOPs. We need to fix this because changing 1724 // CFI state after a NOP, besides being wrong and inaccurate, makes it 1725 // harder for us to recover this information, since we can create empty BBs 1726 // with NOPs and then reorder it away. 1727 // We fix this by moving the CFI instruction just before any NOPs. 1728 auto I = Instructions.lower_bound(Offset); 1729 if (Offset == getSize()) { 1730 assert(I == Instructions.end() && "unexpected iterator value"); 1731 // Sometimes compiler issues restore_state after all instructions 1732 // in the function (even after nop). 1733 --I; 1734 Offset = I->first; 1735 } 1736 assert(I->first == Offset && "CFI pointing to unknown instruction"); 1737 if (I == Instructions.begin()) { 1738 CIEFrameInstructions.emplace_back(std::forward<MCCFIInstruction>(Inst)); 1739 return; 1740 } 1741 1742 --I; 1743 while (I != Instructions.begin() && BC.MIB->isNoop(I->second)) { 1744 Offset = I->first; 1745 --I; 1746 } 1747 OffsetToCFI.emplace(Offset, FrameInstructions.size()); 1748 FrameInstructions.emplace_back(std::forward<MCCFIInstruction>(Inst)); 1749 return; 1750 } 1751 1752 BinaryBasicBlock::iterator addCFIInstruction(BinaryBasicBlock *BB, 1753 BinaryBasicBlock::iterator Pos, 1754 MCCFIInstruction &&Inst) { 1755 size_t Idx = FrameInstructions.size(); 1756 FrameInstructions.emplace_back(std::forward<MCCFIInstruction>(Inst)); 1757 return addCFIPseudo(BB, Pos, Idx); 1758 } 1759 1760 /// Insert a CFI pseudo instruction in a basic block. This pseudo instruction 1761 /// is a placeholder that refers to a real MCCFIInstruction object kept by 1762 /// this function that will be emitted at that position. 1763 BinaryBasicBlock::iterator addCFIPseudo(BinaryBasicBlock *BB, 1764 BinaryBasicBlock::iterator Pos, 1765 uint32_t Offset) { 1766 MCInst CFIPseudo; 1767 BC.MIB->createCFI(CFIPseudo, Offset); 1768 return BB->insertPseudoInstr(Pos, CFIPseudo); 1769 } 1770 1771 /// Retrieve the MCCFIInstruction object associated with a CFI pseudo. 1772 const MCCFIInstruction *getCFIFor(const MCInst &Instr) const { 1773 if (!BC.MIB->isCFI(Instr)) 1774 return nullptr; 1775 uint32_t Offset = Instr.getOperand(0).getImm(); 1776 assert(Offset < FrameInstructions.size() && "Invalid CFI offset"); 1777 return &FrameInstructions[Offset]; 1778 } 1779 1780 void setCFIFor(const MCInst &Instr, MCCFIInstruction &&CFIInst) { 1781 assert(BC.MIB->isCFI(Instr) && 1782 "attempting to change CFI in a non-CFI inst"); 1783 uint32_t Offset = Instr.getOperand(0).getImm(); 1784 assert(Offset < FrameInstructions.size() && "Invalid CFI offset"); 1785 FrameInstructions[Offset] = std::move(CFIInst); 1786 } 1787 1788 void mutateCFIRegisterFor(const MCInst &Instr, MCPhysReg NewReg); 1789 1790 const MCCFIInstruction *mutateCFIOffsetFor(const MCInst &Instr, 1791 int64_t NewOffset); 1792 1793 BinaryFunction &setFileOffset(uint64_t Offset) { 1794 FileOffset = Offset; 1795 return *this; 1796 } 1797 1798 BinaryFunction &setSize(uint64_t S) { 1799 Size = S; 1800 return *this; 1801 } 1802 1803 BinaryFunction &setMaxSize(uint64_t Size) { 1804 MaxSize = Size; 1805 return *this; 1806 } 1807 1808 BinaryFunction &setOutputAddress(uint64_t Address) { 1809 OutputAddress = Address; 1810 return *this; 1811 } 1812 1813 BinaryFunction &setOutputSize(uint64_t Size) { 1814 OutputSize = Size; 1815 return *this; 1816 } 1817 1818 BinaryFunction &setSimple(bool Simple) { 1819 IsSimple = Simple; 1820 return *this; 1821 } 1822 1823 void setPseudo(bool Pseudo) { IsPseudo = Pseudo; } 1824 1825 BinaryFunction &setUsesGnuArgsSize(bool Uses = true) { 1826 UsesGnuArgsSize = Uses; 1827 return *this; 1828 } 1829 1830 BinaryFunction &setHasProfileAvailable(bool V = true) { 1831 HasProfileAvailable = V; 1832 return *this; 1833 } 1834 1835 /// Mark function that should not be emitted. 1836 void setIgnored(); 1837 1838 void setIsPatched(bool V) { IsPatched = V; } 1839 1840 void setHasIndirectTargetToSplitFragment(bool V) { 1841 HasIndirectTargetToSplitFragment = V; 1842 } 1843 1844 void setHasCanonicalCFG(bool V) { HasCanonicalCFG = V; } 1845 1846 void setFolded(BinaryFunction *BF) { FoldedIntoFunction = BF; } 1847 1848 BinaryFunction &setPersonalityFunction(uint64_t Addr) { 1849 assert(!PersonalityFunction && "can't set personality function twice"); 1850 PersonalityFunction = BC.getOrCreateGlobalSymbol(Addr, "FUNCat"); 1851 return *this; 1852 } 1853 1854 BinaryFunction &setPersonalityEncoding(uint8_t Encoding) { 1855 PersonalityEncoding = Encoding; 1856 return *this; 1857 } 1858 1859 BinaryFunction &setAlignment(uint16_t Align) { 1860 Alignment = Align; 1861 return *this; 1862 } 1863 1864 uint16_t getAlignment() const { return Alignment; } 1865 1866 BinaryFunction &setMaxAlignmentBytes(uint16_t MaxAlignBytes) { 1867 MaxAlignmentBytes = MaxAlignBytes; 1868 return *this; 1869 } 1870 1871 uint16_t getMaxAlignmentBytes() const { return MaxAlignmentBytes; } 1872 1873 BinaryFunction &setMaxColdAlignmentBytes(uint16_t MaxAlignBytes) { 1874 MaxColdAlignmentBytes = MaxAlignBytes; 1875 return *this; 1876 } 1877 1878 uint16_t getMaxColdAlignmentBytes() const { return MaxColdAlignmentBytes; } 1879 1880 BinaryFunction &setImageAddress(uint64_t Address) { 1881 ImageAddress = Address; 1882 return *this; 1883 } 1884 1885 /// Return the address of this function' image in memory. 1886 uint64_t getImageAddress() const { return ImageAddress; } 1887 1888 BinaryFunction &setImageSize(uint64_t Size) { 1889 ImageSize = Size; 1890 return *this; 1891 } 1892 1893 /// Return the size of this function' image in memory. 1894 uint64_t getImageSize() const { return ImageSize; } 1895 1896 /// Return true if the function is a secondary fragment of another function. 1897 bool isFragment() const { return IsFragment; } 1898 1899 /// Returns if the given function is a parent fragment of this function. 1900 bool isParentFragment(BinaryFunction *Parent) const { 1901 return ParentFragments.count(Parent); 1902 } 1903 1904 /// Set the profile data for the number of times the function was called. 1905 BinaryFunction &setExecutionCount(uint64_t Count) { 1906 ExecutionCount = Count; 1907 return *this; 1908 } 1909 1910 /// Adjust execution count for the function by a given \p Count. The value 1911 /// \p Count will be subtracted from the current function count. 1912 /// 1913 /// The function will proportionally adjust execution count for all 1914 /// basic blocks and edges in the control flow graph. 1915 void adjustExecutionCount(uint64_t Count); 1916 1917 /// Set LSDA address for the function. 1918 BinaryFunction &setLSDAAddress(uint64_t Address) { 1919 LSDAAddress = Address; 1920 return *this; 1921 } 1922 1923 /// Set LSDA symbol for the function. 1924 BinaryFunction &setLSDASymbol(MCSymbol *Symbol) { 1925 LSDASymbol = Symbol; 1926 return *this; 1927 } 1928 1929 /// Return the profile information about the number of times 1930 /// the function was executed. 1931 /// 1932 /// Return COUNT_NO_PROFILE if there's no profile info. 1933 uint64_t getExecutionCount() const { return ExecutionCount; } 1934 1935 /// Return the raw profile information about the number of branch 1936 /// executions corresponding to this function. 1937 uint64_t getRawBranchCount() const { return RawBranchCount; } 1938 1939 /// Return the execution count for functions with known profile. 1940 /// Return 0 if the function has no profile. 1941 uint64_t getKnownExecutionCount() const { 1942 return ExecutionCount == COUNT_NO_PROFILE ? 0 : ExecutionCount; 1943 } 1944 1945 /// Return original LSDA address for the function or NULL. 1946 uint64_t getLSDAAddress() const { return LSDAAddress; } 1947 1948 /// Return symbol pointing to function's LSDA. 1949 MCSymbol *getLSDASymbol() { 1950 if (LSDASymbol) 1951 return LSDASymbol; 1952 if (CallSites.empty()) 1953 return nullptr; 1954 1955 LSDASymbol = BC.Ctx->getOrCreateSymbol( 1956 Twine("GCC_except_table") + Twine::utohexstr(getFunctionNumber())); 1957 1958 return LSDASymbol; 1959 } 1960 1961 /// Return symbol pointing to function's LSDA for the cold part. 1962 MCSymbol *getColdLSDASymbol() { 1963 if (ColdLSDASymbol) 1964 return ColdLSDASymbol; 1965 if (ColdCallSites.empty()) 1966 return nullptr; 1967 1968 ColdLSDASymbol = BC.Ctx->getOrCreateSymbol( 1969 Twine("GCC_cold_except_table") + Twine::utohexstr(getFunctionNumber())); 1970 1971 return ColdLSDASymbol; 1972 } 1973 1974 void setOutputDataAddress(uint64_t Address) { OutputDataOffset = Address; } 1975 1976 uint64_t getOutputDataAddress() const { return OutputDataOffset; } 1977 1978 void setOutputColdDataAddress(uint64_t Address) { 1979 OutputColdDataOffset = Address; 1980 } 1981 1982 uint64_t getOutputColdDataAddress() const { return OutputColdDataOffset; } 1983 1984 /// If \p Address represents an access to a constant island managed by this 1985 /// function, return a symbol so code can safely refer to it. Otherwise, 1986 /// return nullptr. First return value is the symbol for reference in the 1987 /// hot code area while the second return value is the symbol for reference 1988 /// in the cold code area, as when the function is split the islands are 1989 /// duplicated. 1990 MCSymbol *getOrCreateIslandAccess(uint64_t Address) { 1991 if (!Islands) 1992 return nullptr; 1993 1994 MCSymbol *Symbol; 1995 if (!isInConstantIsland(Address)) 1996 return nullptr; 1997 1998 // Register our island at global namespace 1999 Symbol = BC.getOrCreateGlobalSymbol(Address, "ISLANDat"); 2000 2001 // Internal bookkeeping 2002 const uint64_t Offset = Address - getAddress(); 2003 assert((!Islands->Offsets.count(Offset) || 2004 Islands->Offsets[Offset] == Symbol) && 2005 "Inconsistent island symbol management"); 2006 if (!Islands->Offsets.count(Offset)) { 2007 Islands->Offsets[Offset] = Symbol; 2008 Islands->Symbols.insert(Symbol); 2009 } 2010 return Symbol; 2011 } 2012 2013 /// Called by an external function which wishes to emit references to constant 2014 /// island symbols of this function. We create a proxy for it, so we emit 2015 /// separate symbols when emitting our constant island on behalf of this other 2016 /// function. 2017 MCSymbol *getOrCreateProxyIslandAccess(uint64_t Address, 2018 BinaryFunction &Referrer) { 2019 MCSymbol *Symbol = getOrCreateIslandAccess(Address); 2020 if (!Symbol) 2021 return nullptr; 2022 2023 MCSymbol *Proxy; 2024 if (!Islands->Proxies[&Referrer].count(Symbol)) { 2025 Proxy = BC.Ctx->getOrCreateSymbol(Symbol->getName() + ".proxy.for." + 2026 Referrer.getPrintName()); 2027 Islands->Proxies[&Referrer][Symbol] = Proxy; 2028 Islands->Proxies[&Referrer][Proxy] = Symbol; 2029 } 2030 Proxy = Islands->Proxies[&Referrer][Symbol]; 2031 return Proxy; 2032 } 2033 2034 /// Make this function depend on \p BF because we have a reference to its 2035 /// constant island. When emitting this function, we will also emit 2036 // \p BF's constants. This only happens in custom AArch64 assembly code. 2037 void createIslandDependency(MCSymbol *Island, BinaryFunction *BF) { 2038 if (!Islands) 2039 Islands = std::make_unique<IslandInfo>(); 2040 2041 Islands->Dependency.insert(BF); 2042 Islands->ProxySymbols[Island] = BF; 2043 } 2044 2045 /// Detects whether \p Address is inside a data region in this function 2046 /// (constant islands). 2047 bool isInConstantIsland(uint64_t Address) const { 2048 if (!Islands) 2049 return false; 2050 2051 if (Address < getAddress()) 2052 return false; 2053 2054 uint64_t Offset = Address - getAddress(); 2055 2056 if (Offset >= getMaxSize()) 2057 return false; 2058 2059 auto DataIter = Islands->DataOffsets.upper_bound(Offset); 2060 if (DataIter == Islands->DataOffsets.begin()) 2061 return false; 2062 DataIter = std::prev(DataIter); 2063 2064 auto CodeIter = Islands->CodeOffsets.upper_bound(Offset); 2065 if (CodeIter == Islands->CodeOffsets.begin()) 2066 return true; 2067 2068 return *std::prev(CodeIter) <= *DataIter; 2069 } 2070 2071 uint16_t getConstantIslandAlignment() const { 2072 return Islands ? Islands->getAlignment() : 1; 2073 } 2074 2075 uint64_t 2076 estimateConstantIslandSize(const BinaryFunction *OnBehalfOf = nullptr) const { 2077 if (!Islands) 2078 return 0; 2079 2080 uint64_t Size = 0; 2081 for (auto DataIter = Islands->DataOffsets.begin(); 2082 DataIter != Islands->DataOffsets.end(); ++DataIter) { 2083 auto NextData = std::next(DataIter); 2084 auto CodeIter = Islands->CodeOffsets.lower_bound(*DataIter); 2085 if (CodeIter == Islands->CodeOffsets.end() && 2086 NextData == Islands->DataOffsets.end()) { 2087 Size += getMaxSize() - *DataIter; 2088 continue; 2089 } 2090 2091 uint64_t NextMarker; 2092 if (CodeIter == Islands->CodeOffsets.end()) 2093 NextMarker = *NextData; 2094 else if (NextData == Islands->DataOffsets.end()) 2095 NextMarker = *CodeIter; 2096 else 2097 NextMarker = (*CodeIter > *NextData) ? *NextData : *CodeIter; 2098 2099 Size += NextMarker - *DataIter; 2100 } 2101 2102 if (!OnBehalfOf) { 2103 for (BinaryFunction *ExternalFunc : Islands->Dependency) { 2104 Size = alignTo(Size, ExternalFunc->getConstantIslandAlignment()); 2105 Size += ExternalFunc->estimateConstantIslandSize(this); 2106 } 2107 } 2108 2109 return Size; 2110 } 2111 2112 bool hasIslandsInfo() const { return !!Islands; } 2113 2114 bool hasConstantIsland() const { 2115 return Islands && !Islands->DataOffsets.empty(); 2116 } 2117 2118 /// Return true iff the symbol could be seen inside this function otherwise 2119 /// it is probably another function. 2120 bool isSymbolValidInScope(const SymbolRef &Symbol, uint64_t SymbolSize) const; 2121 2122 /// Disassemble function from raw data. 2123 /// If successful, this function will populate the list of instructions 2124 /// for this function together with offsets from the function start 2125 /// in the input. It will also populate Labels with destinations for 2126 /// local branches, and TakenBranches with [from, to] info. 2127 /// 2128 /// The Function should be properly initialized before this function 2129 /// is called. I.e. function address and size should be set. 2130 /// 2131 /// Returns true on successful disassembly, and updates the current 2132 /// state to State:Disassembled. 2133 /// 2134 /// Returns false if disassembly failed. 2135 bool disassemble(); 2136 2137 /// Scan function for references to other functions. In relocation mode, 2138 /// add relocations for external references. 2139 /// 2140 /// Return true on success. 2141 bool scanExternalRefs(); 2142 2143 /// Return the size of a data object located at \p Offset in the function. 2144 /// Return 0 if there is no data object at the \p Offset. 2145 size_t getSizeOfDataInCodeAt(uint64_t Offset) const; 2146 2147 /// Verify that starting at \p Offset function contents are filled with 2148 /// zero-value bytes. 2149 bool isZeroPaddingAt(uint64_t Offset) const; 2150 2151 /// Check that entry points have an associated instruction at their 2152 /// offsets after disassembly. 2153 void postProcessEntryPoints(); 2154 2155 /// Post-processing for jump tables after disassembly. Since their 2156 /// boundaries are not known until all call sites are seen, we need this 2157 /// extra pass to perform any final adjustments. 2158 void postProcessJumpTables(); 2159 2160 /// Builds a list of basic blocks with successor and predecessor info. 2161 /// 2162 /// The function should in Disassembled state prior to call. 2163 /// 2164 /// Returns true on success and update the current function state to 2165 /// State::CFG. Returns false if CFG cannot be built. 2166 bool buildCFG(MCPlusBuilder::AllocatorIdTy); 2167 2168 /// Perform post-processing of the CFG. 2169 void postProcessCFG(); 2170 2171 /// Verify that any assumptions we've made about indirect branches were 2172 /// correct and also make any necessary changes to unknown indirect branches. 2173 /// 2174 /// Catch-22: we need to know indirect branch targets to build CFG, and 2175 /// in order to determine the value for indirect branches we need to know CFG. 2176 /// 2177 /// As such, the process of decoding indirect branches is broken into 2 steps: 2178 /// first we make our best guess about a branch without knowing the CFG, 2179 /// and later after we have the CFG for the function, we verify our earlier 2180 /// assumptions and also do our best at processing unknown indirect branches. 2181 /// 2182 /// Return true upon successful processing, or false if the control flow 2183 /// cannot be statically evaluated for any given indirect branch. 2184 bool postProcessIndirectBranches(MCPlusBuilder::AllocatorIdTy AllocId); 2185 2186 /// Return all call site profile info for this function. 2187 IndirectCallSiteProfile &getAllCallSites() { return AllCallSites; } 2188 2189 const IndirectCallSiteProfile &getAllCallSites() const { 2190 return AllCallSites; 2191 } 2192 2193 /// Walks the list of basic blocks filling in missing information about 2194 /// edge frequency for fall-throughs. 2195 /// 2196 /// Assumes the CFG has been built and edge frequency for taken branches 2197 /// has been filled with LBR data. 2198 void inferFallThroughCounts(); 2199 2200 /// Clear execution profile of the function. 2201 void clearProfile(); 2202 2203 /// Converts conditional tail calls to unconditional tail calls. We do this to 2204 /// handle conditional tail calls correctly and to give a chance to the 2205 /// simplify conditional tail call pass to decide whether to re-optimize them 2206 /// using profile information. 2207 void removeConditionalTailCalls(); 2208 2209 // Convert COUNT_NO_PROFILE to 0 2210 void removeTagsFromProfile(); 2211 2212 /// Computes a function hotness score: the sum of the products of BB frequency 2213 /// and size. 2214 uint64_t getFunctionScore() const; 2215 2216 /// Return true if the layout has been changed by basic block reordering, 2217 /// false otherwise. 2218 bool hasLayoutChanged() const; 2219 2220 /// Get the edit distance of the new layout with respect to the previous 2221 /// layout after basic block reordering. 2222 uint64_t getEditDistance() const; 2223 2224 /// Get the number of instructions within this function. 2225 uint64_t getInstructionCount() const; 2226 2227 const CFIInstrMapType &getFDEProgram() const { return FrameInstructions; } 2228 2229 void moveRememberRestorePair(BinaryBasicBlock *BB); 2230 2231 bool replayCFIInstrs(int32_t FromState, int32_t ToState, 2232 BinaryBasicBlock *InBB, 2233 BinaryBasicBlock::iterator InsertIt); 2234 2235 /// unwindCFIState is used to unwind from a higher to a lower state number 2236 /// without using remember-restore instructions. We do that by keeping track 2237 /// of what values have been changed from state A to B and emitting 2238 /// instructions that undo this change. 2239 SmallVector<int32_t, 4> unwindCFIState(int32_t FromState, int32_t ToState, 2240 BinaryBasicBlock *InBB, 2241 BinaryBasicBlock::iterator &InsertIt); 2242 2243 /// After reordering, this function checks the state of CFI and fixes it if it 2244 /// is corrupted. If it is unable to fix it, it returns false. 2245 bool finalizeCFIState(); 2246 2247 /// Return true if this function needs an address-transaltion table after 2248 /// its code emission. 2249 bool requiresAddressTranslation() const; 2250 2251 /// Adjust branch instructions to match the CFG. 2252 /// 2253 /// As it comes to internal branches, the CFG represents "the ultimate source 2254 /// of truth". Transformations on functions and blocks have to update the CFG 2255 /// and fixBranches() would make sure the correct branch instructions are 2256 /// inserted at the end of basic blocks. 2257 /// 2258 /// We do require a conditional branch at the end of the basic block if 2259 /// the block has 2 successors as CFG currently lacks the conditional 2260 /// code support (it will probably stay that way). We only use this 2261 /// branch instruction for its conditional code, the destination is 2262 /// determined by CFG - first successor representing true/taken branch, 2263 /// while the second successor - false/fall-through branch. 2264 /// 2265 /// When we reverse the branch condition, the CFG is updated accordingly. 2266 void fixBranches(); 2267 2268 /// Mark function as finalized. No further optimizations are permitted. 2269 void setFinalized() { CurrentState = State::CFG_Finalized; } 2270 2271 void setEmitted(bool KeepCFG = false) { 2272 CurrentState = State::EmittedCFG; 2273 if (!KeepCFG) { 2274 releaseCFG(); 2275 CurrentState = State::Emitted; 2276 } 2277 } 2278 2279 /// Process LSDA information for the function. 2280 void parseLSDA(ArrayRef<uint8_t> LSDAData, uint64_t LSDAAddress); 2281 2282 /// Update exception handling ranges for the function. 2283 void updateEHRanges(); 2284 2285 /// Traverse cold basic blocks and replace references to constants in islands 2286 /// with a proxy symbol for the duplicated constant island that is going to be 2287 /// emitted in the cold region. 2288 void duplicateConstantIslands(); 2289 2290 /// Merge profile data of this function into those of the given 2291 /// function. The functions should have been proven identical with 2292 /// isIdenticalWith. 2293 void mergeProfileDataInto(BinaryFunction &BF) const; 2294 2295 /// Returns the last computed hash value of the function. 2296 size_t getHash() const { return Hash; } 2297 2298 using OperandHashFuncTy = 2299 function_ref<typename std::string(const MCOperand &)>; 2300 2301 /// Compute the hash value of the function based on its contents. 2302 /// 2303 /// If \p UseDFS is set, process basic blocks in DFS order. Otherwise, use 2304 /// the existing layout order. 2305 /// 2306 /// By default, instruction operands are ignored while calculating the hash. 2307 /// The caller can change this via passing \p OperandHashFunc function. 2308 /// The return result of this function will be mixed with internal hash. 2309 size_t computeHash( 2310 bool UseDFS = false, 2311 OperandHashFuncTy OperandHashFunc = [](const MCOperand &) { 2312 return std::string(); 2313 }) const; 2314 2315 void setDWARFUnit(DWARFUnit *Unit) { DwarfUnit = Unit; } 2316 2317 /// Return DWARF compile unit for this function. 2318 DWARFUnit *getDWARFUnit() const { return DwarfUnit; } 2319 2320 /// Return line info table for this function. 2321 const DWARFDebugLine::LineTable *getDWARFLineTable() const { 2322 return getDWARFUnit() ? BC.DwCtx->getLineTableForUnit(getDWARFUnit()) 2323 : nullptr; 2324 } 2325 2326 /// Finalize profile for the function. 2327 void postProcessProfile(); 2328 2329 /// Returns an estimate of the function's hot part after splitting. 2330 /// This is a very rough estimate, as with C++ exceptions there are 2331 /// blocks we don't move, and it makes no attempt at estimating the size 2332 /// of the added/removed branch instructions. 2333 /// Note that this size is optimistic and the actual size may increase 2334 /// after relaxation. 2335 size_t estimateHotSize(const bool UseSplitSize = true) const { 2336 size_t Estimate = 0; 2337 if (UseSplitSize && isSplit()) { 2338 for (const BinaryBasicBlock &BB : blocks()) 2339 if (!BB.isCold()) 2340 Estimate += BC.computeCodeSize(BB.begin(), BB.end()); 2341 } else { 2342 for (const BinaryBasicBlock &BB : blocks()) 2343 if (BB.getKnownExecutionCount() != 0) 2344 Estimate += BC.computeCodeSize(BB.begin(), BB.end()); 2345 } 2346 return Estimate; 2347 } 2348 2349 size_t estimateColdSize() const { 2350 if (!isSplit()) 2351 return estimateSize(); 2352 size_t Estimate = 0; 2353 for (const BinaryBasicBlock &BB : blocks()) 2354 if (BB.isCold()) 2355 Estimate += BC.computeCodeSize(BB.begin(), BB.end()); 2356 return Estimate; 2357 } 2358 2359 size_t estimateSize() const { 2360 size_t Estimate = 0; 2361 for (const BinaryBasicBlock &BB : blocks()) 2362 Estimate += BC.computeCodeSize(BB.begin(), BB.end()); 2363 return Estimate; 2364 } 2365 2366 /// Return output address ranges for a function. 2367 DebugAddressRangesVector getOutputAddressRanges() const; 2368 2369 /// Given an address corresponding to an instruction in the input binary, 2370 /// return an address of this instruction in output binary. 2371 /// 2372 /// Return 0 if no matching address could be found or the instruction was 2373 /// removed. 2374 uint64_t translateInputToOutputAddress(uint64_t Address) const; 2375 2376 /// Take address ranges corresponding to the input binary and translate 2377 /// them to address ranges in the output binary. 2378 DebugAddressRangesVector translateInputToOutputRanges( 2379 const DWARFAddressRangesVector &InputRanges) const; 2380 2381 /// Similar to translateInputToOutputRanges() but operates on location lists 2382 /// and moves associated data to output location lists. 2383 DebugLocationsVector 2384 translateInputToOutputLocationList(const DebugLocationsVector &InputLL) const; 2385 2386 /// Return true if the function is an AArch64 linker inserted veneer 2387 bool isAArch64Veneer() const; 2388 2389 virtual ~BinaryFunction(); 2390 2391 /// Info for fragmented functions. 2392 class FragmentInfo { 2393 private: 2394 uint64_t Address{0}; 2395 uint64_t ImageAddress{0}; 2396 uint64_t ImageSize{0}; 2397 uint64_t FileOffset{0}; 2398 2399 public: 2400 uint64_t getAddress() const { return Address; } 2401 uint64_t getImageAddress() const { return ImageAddress; } 2402 uint64_t getImageSize() const { return ImageSize; } 2403 uint64_t getFileOffset() const { return FileOffset; } 2404 2405 void setAddress(uint64_t VAddress) { Address = VAddress; } 2406 void setImageAddress(uint64_t Address) { ImageAddress = Address; } 2407 void setImageSize(uint64_t Size) { ImageSize = Size; } 2408 void setFileOffset(uint64_t Offset) { FileOffset = Offset; } 2409 }; 2410 2411 /// Cold fragment of the function. 2412 FragmentInfo ColdFragment; 2413 2414 FragmentInfo &cold() { return ColdFragment; } 2415 2416 const FragmentInfo &cold() const { return ColdFragment; } 2417 }; 2418 2419 inline raw_ostream &operator<<(raw_ostream &OS, 2420 const BinaryFunction &Function) { 2421 OS << Function.getPrintName(); 2422 return OS; 2423 } 2424 2425 } // namespace bolt 2426 2427 // GraphTraits specializations for function basic block graphs (CFGs) 2428 template <> 2429 struct GraphTraits<bolt::BinaryFunction *> 2430 : public GraphTraits<bolt::BinaryBasicBlock *> { 2431 static NodeRef getEntryNode(bolt::BinaryFunction *F) { 2432 return *F->layout_begin(); 2433 } 2434 2435 using nodes_iterator = pointer_iterator<bolt::BinaryFunction::iterator>; 2436 2437 static nodes_iterator nodes_begin(bolt::BinaryFunction *F) { 2438 llvm_unreachable("Not implemented"); 2439 return nodes_iterator(F->begin()); 2440 } 2441 static nodes_iterator nodes_end(bolt::BinaryFunction *F) { 2442 llvm_unreachable("Not implemented"); 2443 return nodes_iterator(F->end()); 2444 } 2445 static size_t size(bolt::BinaryFunction *F) { return F->size(); } 2446 }; 2447 2448 template <> 2449 struct GraphTraits<const bolt::BinaryFunction *> 2450 : public GraphTraits<const bolt::BinaryBasicBlock *> { 2451 static NodeRef getEntryNode(const bolt::BinaryFunction *F) { 2452 return *F->layout_begin(); 2453 } 2454 2455 using nodes_iterator = pointer_iterator<bolt::BinaryFunction::const_iterator>; 2456 2457 static nodes_iterator nodes_begin(const bolt::BinaryFunction *F) { 2458 llvm_unreachable("Not implemented"); 2459 return nodes_iterator(F->begin()); 2460 } 2461 static nodes_iterator nodes_end(const bolt::BinaryFunction *F) { 2462 llvm_unreachable("Not implemented"); 2463 return nodes_iterator(F->end()); 2464 } 2465 static size_t size(const bolt::BinaryFunction *F) { return F->size(); } 2466 }; 2467 2468 template <> 2469 struct GraphTraits<Inverse<bolt::BinaryFunction *>> 2470 : public GraphTraits<Inverse<bolt::BinaryBasicBlock *>> { 2471 static NodeRef getEntryNode(Inverse<bolt::BinaryFunction *> G) { 2472 return *G.Graph->layout_begin(); 2473 } 2474 }; 2475 2476 template <> 2477 struct GraphTraits<Inverse<const bolt::BinaryFunction *>> 2478 : public GraphTraits<Inverse<const bolt::BinaryBasicBlock *>> { 2479 static NodeRef getEntryNode(Inverse<const bolt::BinaryFunction *> G) { 2480 return *G.Graph->layout_begin(); 2481 } 2482 }; 2483 2484 } // namespace llvm 2485 2486 #endif 2487