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