1 //===- InlineInfo.h ---------------------------------------------*- 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 #ifndef LLVM_DEBUGINFO_GSYM_INLINEINFO_H 10 #define LLVM_DEBUGINFO_GSYM_INLINEINFO_H 11 12 #include "llvm/ADT/Optional.h" 13 #include "llvm/DebugInfo/GSYM/ExtractRanges.h" 14 #include "llvm/DebugInfo/GSYM/LineEntry.h" 15 #include "llvm/DebugInfo/GSYM/LookupResult.h" 16 #include "llvm/Support/Error.h" 17 #include <stdint.h> 18 #include <vector> 19 20 namespace llvm { 21 class raw_ostream; 22 23 namespace gsym { 24 25 class GsymReader; 26 /// Inline information stores the name of the inline function along with 27 /// an array of address ranges. It also stores the call file and call line 28 /// that called this inline function. This allows us to unwind inline call 29 /// stacks back to the inline or concrete function that called this 30 /// function. Inlined functions contained in this function are stored in the 31 /// "Children" variable. All address ranges must be sorted and all address 32 /// ranges of all children must be contained in the ranges of this function. 33 /// Any clients that encode information will need to ensure the ranges are 34 /// all contined correctly or lookups could fail. Add ranges in these objects 35 /// must be contained in the top level FunctionInfo address ranges as well. 36 /// 37 /// ENCODING 38 /// 39 /// When saved to disk, the inline info encodes all ranges to be relative to 40 /// a parent address range. This will be the FunctionInfo's start address if 41 /// the InlineInfo is directly contained in a FunctionInfo, or a the start 42 /// address of the containing parent InlineInfo's first "Ranges" member. This 43 /// allows address ranges to be efficiently encoded using ULEB128 encodings as 44 /// we encode the offset and size of each range instead of full addresses. This 45 /// also makes any encoded addresses easy to relocate as we just need to 46 /// relocate the FunctionInfo's start address. 47 /// 48 /// - The AddressRanges member "Ranges" is encoded using an appropriate base 49 /// address as described above. 50 /// - UINT8 boolean value that specifies if the InlineInfo object has children. 51 /// - UINT32 string table offset that points to the name of the inline 52 /// function. 53 /// - ULEB128 integer that specifies the file of the call site that called 54 /// this function. 55 /// - ULEB128 integer that specifies the source line of the call site that 56 /// called this function. 57 /// - if this object has children, enocode each child InlineInfo using the 58 /// the first address range's start address as the base address. 59 /// 60 struct InlineInfo { 61 62 uint32_t Name; ///< String table offset in the string table. 63 uint32_t CallFile; ///< 1 based file index in the file table. 64 uint32_t CallLine; ///< Source line number. 65 AddressRanges Ranges; 66 std::vector<InlineInfo> Children; 67 InlineInfo() : Name(0), CallFile(0), CallLine(0) {} 68 void clear() { 69 Name = 0; 70 CallFile = 0; 71 CallLine = 0; 72 Ranges.clear(); 73 Children.clear(); 74 } 75 bool isValid() const { return !Ranges.empty(); } 76 77 using InlineArray = std::vector<const InlineInfo *>; 78 79 /// Lookup a single address within the inline info data. 80 /// 81 /// Clients have the option to decode an entire InlineInfo object (using 82 /// InlineInfo::decode() ) or just find the matching inline info using this 83 /// function. The benefit of using this function is that only the information 84 /// needed for the lookup will be extracted, other info can be skipped and 85 /// parsing can stop as soon as the deepest match is found. This allows 86 /// symbolication tools to be fast and efficient and avoid allocation costs 87 /// when doing lookups. 88 /// 89 /// This function will augment the SourceLocations array \a SrcLocs with any 90 /// inline information that pertains to \a Addr. If no inline information 91 /// exists for \a Addr, then \a SrcLocs will be left untouched. If there is 92 /// inline information for \a Addr, then \a SrcLocs will be modifiied to 93 /// contain the deepest most inline function's SourceLocation at index zero 94 /// in the array and proceed up the the concrete function source file and 95 /// line at the end of the array. 96 /// 97 /// \param GR The GSYM reader that contains the string and file table that 98 /// will be used to fill in the source locations. 99 /// 100 /// \param Data The binary stream to read the data from. This object must 101 /// have the data for the LineTable object starting at offset zero. The data 102 /// can contain more data than needed. 103 /// 104 /// \param BaseAddr The base address to use when decoding the line table. 105 /// This will be the FunctionInfo's start address and will be used to 106 /// decode the correct addresses for the inline information. 107 /// 108 /// \param Addr The address to lookup. 109 /// 110 /// \param SrcLocs The inline source locations that matches \a Addr. This 111 /// array must be initialized with the matching line entry 112 /// from the line table upon entry. The name of the concrete 113 /// function must be supplied since it will get pushed to 114 /// the last SourceLocation entry and the inline information 115 /// will fill in the source file and line from the inline 116 /// information. 117 /// 118 /// \returns An error if the inline information is corrupt, or 119 /// Error::success() for all other cases, even when no information 120 /// is added to \a SrcLocs. 121 static llvm::Error lookup(const GsymReader &GR, DataExtractor &Data, 122 uint64_t BaseAddr, uint64_t Addr, 123 SourceLocations &SrcLocs); 124 125 /// Lookup an address in the InlineInfo object 126 /// 127 /// This function is used to symbolicate an inline call stack and can 128 /// turn one address in the program into one or more inline call stacks 129 /// and have the stack trace show the original call site from 130 /// non-inlined code. 131 /// 132 /// \param Addr the address to lookup 133 /// 134 /// \returns optional vector of InlineInfo objects that describe the 135 /// inline call stack for a given address, false otherwise. 136 llvm::Optional<InlineArray> getInlineStack(uint64_t Addr) const; 137 138 /// Decode an InlineInfo object from a binary data stream. 139 /// 140 /// \param Data The binary stream to read the data from. This object must 141 /// have the data for the InlineInfo object starting at offset zero. The data 142 /// can contain more data than needed. 143 /// 144 /// \param BaseAddr The base address to use when decoding all address ranges. 145 /// This will be the FunctionInfo's start address if this object is directly 146 /// contained in a FunctionInfo object, or the start address of the first 147 /// address range in an InlineInfo object of this object is a child of 148 /// another InlineInfo object. 149 /// \returns An InlineInfo or an error describing the issue that was 150 /// encountered during decoding. 151 static llvm::Expected<InlineInfo> decode(DataExtractor &Data, 152 uint64_t BaseAddr); 153 154 /// Encode this InlineInfo object into FileWriter stream. 155 /// 156 /// \param O The binary stream to write the data to at the current file 157 /// position. 158 /// 159 /// \param BaseAddr The base address to use when encoding all address ranges. 160 /// This will be the FunctionInfo's start address if this object is directly 161 /// contained in a FunctionInfo object, or the start address of the first 162 /// address range in an InlineInfo object of this object is a child of 163 /// another InlineInfo object. 164 /// 165 /// \returns An error object that indicates success or failure or the 166 /// encoding process. 167 llvm::Error encode(FileWriter &O, uint64_t BaseAddr) const; 168 }; 169 170 inline bool operator==(const InlineInfo &LHS, const InlineInfo &RHS) { 171 return LHS.Name == RHS.Name && LHS.CallFile == RHS.CallFile && 172 LHS.CallLine == RHS.CallLine && LHS.Ranges == RHS.Ranges && 173 LHS.Children == RHS.Children; 174 } 175 176 raw_ostream &operator<<(raw_ostream &OS, const InlineInfo &FI); 177 178 } // namespace gsym 179 } // namespace llvm 180 181 #endif // LLVM_DEBUGINFO_GSYM_INLINEINFO_H 182