InlineInfo.h revision 360784
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
21namespace llvm {
22class raw_ostream;
23
24namespace gsym {
25
26class 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 approriate 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///
61struct 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
171inline 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
177raw_ostream &operator<<(raw_ostream &OS, const InlineInfo &FI);
178
179} // namespace gsym
180} // namespace llvm
181
182#endif // #ifndef LLVM_DEBUGINFO_GSYM_INLINEINFO_H
183