| //===- InlineInfo.h ---------------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_DEBUGINFO_GSYM_INLINEINFO_H |
| #define LLVM_DEBUGINFO_GSYM_INLINEINFO_H |
| |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/DebugInfo/GSYM/LineEntry.h" |
| #include "llvm/DebugInfo/GSYM/LookupResult.h" |
| #include "llvm/DebugInfo/GSYM/Range.h" |
| #include "llvm/Support/Error.h" |
| #include <stdint.h> |
| #include <vector> |
| |
| |
| namespace llvm { |
| class raw_ostream; |
| |
| namespace gsym { |
| |
| class GsymReader; |
| /// Inline information stores the name of the inline function along with |
| /// an array of address ranges. It also stores the call file and call line |
| /// that called this inline function. This allows us to unwind inline call |
| /// stacks back to the inline or concrete function that called this |
| /// function. Inlined functions contained in this function are stored in the |
| /// "Children" variable. All address ranges must be sorted and all address |
| /// ranges of all children must be contained in the ranges of this function. |
| /// Any clients that encode information will need to ensure the ranges are |
| /// all contined correctly or lookups could fail. Add ranges in these objects |
| /// must be contained in the top level FunctionInfo address ranges as well. |
| /// |
| /// ENCODING |
| /// |
| /// When saved to disk, the inline info encodes all ranges to be relative to |
| /// a parent address range. This will be the FunctionInfo's start address if |
| /// the InlineInfo is directly contained in a FunctionInfo, or a the start |
| /// address of the containing parent InlineInfo's first "Ranges" member. This |
| /// allows address ranges to be efficiently encoded using ULEB128 encodings as |
| /// we encode the offset and size of each range instead of full addresses. This |
| /// also makes any encoded addresses easy to relocate as we just need to |
| /// relocate the FunctionInfo's start address. |
| /// |
| /// - The AddressRanges member "Ranges" is encoded using an approriate base |
| /// address as described above. |
| /// - UINT8 boolean value that specifies if the InlineInfo object has children. |
| /// - UINT32 string table offset that points to the name of the inline |
| /// function. |
| /// - ULEB128 integer that specifies the file of the call site that called |
| /// this function. |
| /// - ULEB128 integer that specifies the source line of the call site that |
| /// called this function. |
| /// - if this object has children, enocode each child InlineInfo using the |
| /// the first address range's start address as the base address. |
| /// |
| struct InlineInfo { |
| |
| uint32_t Name; ///< String table offset in the string table. |
| uint32_t CallFile; ///< 1 based file index in the file table. |
| uint32_t CallLine; ///< Source line number. |
| AddressRanges Ranges; |
| std::vector<InlineInfo> Children; |
| InlineInfo() : Name(0), CallFile(0), CallLine(0) {} |
| void clear() { |
| Name = 0; |
| CallFile = 0; |
| CallLine = 0; |
| Ranges.clear(); |
| Children.clear(); |
| } |
| bool isValid() const { return !Ranges.empty(); } |
| |
| using InlineArray = std::vector<const InlineInfo *>; |
| |
| /// Lookup a single address within the inline info data. |
| /// |
| /// Clients have the option to decode an entire InlineInfo object (using |
| /// InlineInfo::decode() ) or just find the matching inline info using this |
| /// function. The benefit of using this function is that only the information |
| /// needed for the lookup will be extracted, other info can be skipped and |
| /// parsing can stop as soon as the deepest match is found. This allows |
| /// symbolication tools to be fast and efficient and avoid allocation costs |
| /// when doing lookups. |
| /// |
| /// This function will augment the SourceLocations array \a SrcLocs with any |
| /// inline information that pertains to \a Addr. If no inline information |
| /// exists for \a Addr, then \a SrcLocs will be left untouched. If there is |
| /// inline information for \a Addr, then \a SrcLocs will be modifiied to |
| /// contain the deepest most inline function's SourceLocation at index zero |
| /// in the array and proceed up the the concrete function source file and |
| /// line at the end of the array. |
| /// |
| /// \param GR The GSYM reader that contains the string and file table that |
| /// will be used to fill in the source locations. |
| /// |
| /// \param Data The binary stream to read the data from. This object must |
| /// have the data for the LineTable object starting at offset zero. The data |
| /// can contain more data than needed. |
| /// |
| /// \param BaseAddr The base address to use when decoding the line table. |
| /// This will be the FunctionInfo's start address and will be used to |
| /// decode the correct addresses for the inline information. |
| /// |
| /// \param Addr The address to lookup. |
| /// |
| /// \param SrcLocs The inline source locations that matches \a Addr. This |
| /// array must be initialized with the matching line entry |
| /// from the line table upon entry. The name of the concrete |
| /// function must be supplied since it will get pushed to |
| /// the last SourceLocation entry and the inline information |
| /// will fill in the source file and line from the inline |
| /// information. |
| /// |
| /// \returns An error if the inline information is corrupt, or |
| /// Error::success() for all other cases, even when no information |
| /// is added to \a SrcLocs. |
| static llvm::Error lookup(const GsymReader &GR, DataExtractor &Data, |
| uint64_t BaseAddr, uint64_t Addr, |
| SourceLocations &SrcLocs); |
| |
| /// Lookup an address in the InlineInfo object |
| /// |
| /// This function is used to symbolicate an inline call stack and can |
| /// turn one address in the program into one or more inline call stacks |
| /// and have the stack trace show the original call site from |
| /// non-inlined code. |
| /// |
| /// \param Addr the address to lookup |
| /// |
| /// \returns optional vector of InlineInfo objects that describe the |
| /// inline call stack for a given address, false otherwise. |
| llvm::Optional<InlineArray> getInlineStack(uint64_t Addr) const; |
| |
| /// Decode an InlineInfo object from a binary data stream. |
| /// |
| /// \param Data The binary stream to read the data from. This object must |
| /// have the data for the InlineInfo object starting at offset zero. The data |
| /// can contain more data than needed. |
| /// |
| /// \param BaseAddr The base address to use when decoding all address ranges. |
| /// This will be the FunctionInfo's start address if this object is directly |
| /// contained in a FunctionInfo object, or the start address of the first |
| /// address range in an InlineInfo object of this object is a child of |
| /// another InlineInfo object. |
| /// \returns An InlineInfo or an error describing the issue that was |
| /// encountered during decoding. |
| static llvm::Expected<InlineInfo> decode(DataExtractor &Data, |
| uint64_t BaseAddr); |
| |
| /// Encode this InlineInfo object into FileWriter stream. |
| /// |
| /// \param O The binary stream to write the data to at the current file |
| /// position. |
| /// |
| /// \param BaseAddr The base address to use when encoding all address ranges. |
| /// This will be the FunctionInfo's start address if this object is directly |
| /// contained in a FunctionInfo object, or the start address of the first |
| /// address range in an InlineInfo object of this object is a child of |
| /// another InlineInfo object. |
| /// |
| /// \returns An error object that indicates success or failure or the |
| /// encoding process. |
| llvm::Error encode(FileWriter &O, uint64_t BaseAddr) const; |
| }; |
| |
| inline bool operator==(const InlineInfo &LHS, const InlineInfo &RHS) { |
| return LHS.Name == RHS.Name && LHS.CallFile == RHS.CallFile && |
| LHS.CallLine == RHS.CallLine && LHS.Ranges == RHS.Ranges && |
| LHS.Children == RHS.Children; |
| } |
| |
| raw_ostream &operator<<(raw_ostream &OS, const InlineInfo &FI); |
| |
| } // namespace gsym |
| } // namespace llvm |
| |
| #endif // #ifndef LLVM_DEBUGINFO_GSYM_INLINEINFO_H |