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