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