123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- GsymReader.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_GSYMREADER_H
- #define LLVM_DEBUGINFO_GSYM_GSYMREADER_H
- #include "llvm/ADT/ArrayRef.h"
- #include "llvm/DebugInfo/GSYM/FileEntry.h"
- #include "llvm/DebugInfo/GSYM/FunctionInfo.h"
- #include "llvm/DebugInfo/GSYM/Header.h"
- #include "llvm/DebugInfo/GSYM/LineEntry.h"
- #include "llvm/DebugInfo/GSYM/StringTable.h"
- #include "llvm/Support/DataExtractor.h"
- #include "llvm/Support/Endian.h"
- #include "llvm/Support/ErrorOr.h"
- #include <inttypes.h>
- #include <memory>
- #include <stdint.h>
- #include <vector>
- namespace llvm {
- class MemoryBuffer;
- class raw_ostream;
- namespace gsym {
- /// GsymReader is used to read GSYM data from a file or buffer.
- ///
- /// This class is optimized for very quick lookups when the endianness matches
- /// the host system. The Header, address table, address info offsets, and file
- /// table is designed to be mmap'ed as read only into memory and used without
- /// any parsing needed. If the endianness doesn't match, we swap these objects
- /// and tables into GsymReader::SwappedData and then point our header and
- /// ArrayRefs to this swapped internal data.
- ///
- /// GsymReader objects must use one of the static functions to create an
- /// instance: GsymReader::openFile(...) and GsymReader::copyBuffer(...).
- class GsymReader {
- GsymReader(std::unique_ptr<MemoryBuffer> Buffer);
- llvm::Error parse();
- std::unique_ptr<MemoryBuffer> MemBuffer;
- StringRef GsymBytes;
- llvm::support::endianness Endian;
- const Header *Hdr = nullptr;
- ArrayRef<uint8_t> AddrOffsets;
- ArrayRef<uint32_t> AddrInfoOffsets;
- ArrayRef<FileEntry> Files;
- StringTable StrTab;
- /// When the GSYM file's endianness doesn't match the host system then
- /// we must decode all data structures that need to be swapped into
- /// local storage and set point the ArrayRef objects above to these swapped
- /// copies.
- struct SwappedData {
- Header Hdr;
- std::vector<uint8_t> AddrOffsets;
- std::vector<uint32_t> AddrInfoOffsets;
- std::vector<FileEntry> Files;
- };
- std::unique_ptr<SwappedData> Swap;
- public:
- GsymReader(GsymReader &&RHS);
- ~GsymReader();
- /// Construct a GsymReader from a file on disk.
- ///
- /// \param Path The file path the GSYM file to read.
- /// \returns An expected GsymReader that contains the object or an error
- /// object that indicates reason for failing to read the GSYM.
- static llvm::Expected<GsymReader> openFile(StringRef Path);
- /// Construct a GsymReader from a buffer.
- ///
- /// \param Bytes A set of bytes that will be copied and owned by the
- /// returned object on success.
- /// \returns An expected GsymReader that contains the object or an error
- /// object that indicates reason for failing to read the GSYM.
- static llvm::Expected<GsymReader> copyBuffer(StringRef Bytes);
- /// Access the GSYM header.
- /// \returns A native endian version of the GSYM header.
- const Header &getHeader() const;
- /// Get the full function info for an address.
- ///
- /// This should be called when a client will store a copy of the complete
- /// FunctionInfo for a given address. For one off lookups, use the lookup()
- /// function below.
- ///
- /// Symbolication server processes might want to parse the entire function
- /// info for a given address and cache it if the process stays around to
- /// service many symbolication addresses, like for parsing profiling
- /// information.
- ///
- /// \param Addr A virtual address from the orignal object file to lookup.
- ///
- /// \returns An expected FunctionInfo that contains the function info object
- /// or an error object that indicates reason for failing to lookup the
- /// address.
- llvm::Expected<FunctionInfo> getFunctionInfo(uint64_t Addr) const;
- /// Lookup an address in the a GSYM.
- ///
- /// Lookup just the information needed for a specific address \a Addr. This
- /// function is faster that calling getFunctionInfo() as it will only return
- /// information that pertains to \a Addr and allows the parsing to skip any
- /// extra information encoded for other addresses. For example the line table
- /// parsing can stop when a matching LineEntry has been fouhnd, and the
- /// InlineInfo can stop parsing early once a match has been found and also
- /// skip information that doesn't match. This avoids memory allocations and
- /// is much faster for lookups.
- ///
- /// \param Addr A virtual address from the orignal object file to lookup.
- /// \returns An expected LookupResult that contains only the information
- /// needed for the current address, or an error object that indicates reason
- /// for failing to lookup the address.
- llvm::Expected<LookupResult> lookup(uint64_t Addr) const;
- /// Get a string from the string table.
- ///
- /// \param Offset The string table offset for the string to retrieve.
- /// \returns The string from the strin table.
- StringRef getString(uint32_t Offset) const { return StrTab[Offset]; }
- /// Get the a file entry for the suppplied file index.
- ///
- /// Used to convert any file indexes in the FunctionInfo data back into
- /// files. This function can be used for iteration, but is more commonly used
- /// for random access when doing lookups.
- ///
- /// \param Index An index into the file table.
- /// \returns An optional FileInfo that will be valid if the file index is
- /// valid, or std::nullopt if the file index is out of bounds,
- std::optional<FileEntry> getFile(uint32_t Index) const {
- if (Index < Files.size())
- return Files[Index];
- return std::nullopt;
- }
- /// Dump the entire Gsym data contained in this object.
- ///
- /// \param OS The output stream to dump to.
- void dump(raw_ostream &OS);
- /// Dump a FunctionInfo object.
- ///
- /// This function will convert any string table indexes and file indexes
- /// into human readable format.
- ///
- /// \param OS The output stream to dump to.
- ///
- /// \param FI The object to dump.
- void dump(raw_ostream &OS, const FunctionInfo &FI);
- /// Dump a LineTable object.
- ///
- /// This function will convert any string table indexes and file indexes
- /// into human readable format.
- ///
- ///
- /// \param OS The output stream to dump to.
- ///
- /// \param LT The object to dump.
- void dump(raw_ostream &OS, const LineTable <);
- /// Dump a InlineInfo object.
- ///
- /// This function will convert any string table indexes and file indexes
- /// into human readable format.
- ///
- /// \param OS The output stream to dump to.
- ///
- /// \param II The object to dump.
- ///
- /// \param Indent The indentation as number of spaces. Used for recurive
- /// dumping.
- void dump(raw_ostream &OS, const InlineInfo &II, uint32_t Indent = 0);
- /// Dump a FileEntry object.
- ///
- /// This function will convert any string table indexes into human readable
- /// format.
- ///
- /// \param OS The output stream to dump to.
- ///
- /// \param FE The object to dump.
- void dump(raw_ostream &OS, std::optional<FileEntry> FE);
- /// Get the number of addresses in this Gsym file.
- uint32_t getNumAddresses() const {
- return Hdr->NumAddresses;
- }
- /// Gets an address from the address table.
- ///
- /// Addresses are stored as offsets frrom the gsym::Header::BaseAddress.
- ///
- /// \param Index A index into the address table.
- /// \returns A resolved virtual address for adddress in the address table
- /// or std::nullopt if Index is out of bounds.
- std::optional<uint64_t> getAddress(size_t Index) const;
- protected:
- /// Get an appropriate address info offsets array.
- ///
- /// The address table in the GSYM file is stored as array of 1, 2, 4 or 8
- /// byte offsets from the The gsym::Header::BaseAddress. The table is stored
- /// internally as a array of bytes that are in the correct endianness. When
- /// we access this table we must get an array that matches those sizes. This
- /// templatized helper function is used when accessing address offsets in the
- /// AddrOffsets member variable.
- ///
- /// \returns An ArrayRef of an appropriate address offset size.
- template <class T> ArrayRef<T>
- getAddrOffsets() const {
- return ArrayRef<T>(reinterpret_cast<const T *>(AddrOffsets.data()),
- AddrOffsets.size()/sizeof(T));
- }
- /// Get an appropriate address from the address table.
- ///
- /// The address table in the GSYM file is stored as array of 1, 2, 4 or 8
- /// byte address offsets from the The gsym::Header::BaseAddress. The table is
- /// stored internally as a array of bytes that are in the correct endianness.
- /// In order to extract an address from the address table we must access the
- /// address offset using the correct size and then add it to the BaseAddress
- /// in the header.
- ///
- /// \param Index An index into the AddrOffsets array.
- /// \returns An virtual address that matches the original object file for the
- /// address as the specified index, or std::nullopt if Index is out of bounds.
- template <class T>
- std::optional<uint64_t> addressForIndex(size_t Index) const {
- ArrayRef<T> AIO = getAddrOffsets<T>();
- if (Index < AIO.size())
- return AIO[Index] + Hdr->BaseAddress;
- return std::nullopt;
- }
- /// Lookup an address offset in the AddrOffsets table.
- ///
- /// Given an address offset, look it up using a binary search of the
- /// AddrOffsets table.
- ///
- /// \param AddrOffset An address offset, that has already been computed by
- /// subtracting the gsym::Header::BaseAddress.
- /// \returns The matching address offset index. This index will be used to
- /// extract the FunctionInfo data's offset from the AddrInfoOffsets array.
- template <class T>
- std::optional<uint64_t>
- getAddressOffsetIndex(const uint64_t AddrOffset) const {
- ArrayRef<T> AIO = getAddrOffsets<T>();
- const auto Begin = AIO.begin();
- const auto End = AIO.end();
- auto Iter = std::lower_bound(Begin, End, AddrOffset);
- // Watch for addresses that fall between the gsym::Header::BaseAddress and
- // the first address offset.
- if (Iter == Begin && AddrOffset < *Begin)
- return std::nullopt;
- if (Iter == End || AddrOffset < *Iter)
- --Iter;
- return std::distance(Begin, Iter);
- }
- /// Create a GSYM from a memory buffer.
- ///
- /// Called by both openFile() and copyBuffer(), this function does all of the
- /// work of parsing the GSYM file and returning an error.
- ///
- /// \param MemBuffer A memory buffer that will transfer ownership into the
- /// GsymReader.
- /// \returns An expected GsymReader that contains the object or an error
- /// object that indicates reason for failing to read the GSYM.
- static llvm::Expected<llvm::gsym::GsymReader>
- create(std::unique_ptr<MemoryBuffer> &MemBuffer);
- /// Given an address, find the address index.
- ///
- /// Binary search the address table and find the matching address index.
- ///
- /// \param Addr A virtual address that matches the original object file
- /// to lookup.
- /// \returns An index into the address table. This index can be used to
- /// extract the FunctionInfo data's offset from the AddrInfoOffsets array.
- /// Returns an error if the address isn't in the GSYM with details of why.
- Expected<uint64_t> getAddressIndex(const uint64_t Addr) const;
- /// Given an address index, get the offset for the FunctionInfo.
- ///
- /// Looking up an address is done by finding the corresponding address
- /// index for the address. This index is then used to get the offset of the
- /// FunctionInfo data that we will decode using this function.
- ///
- /// \param Index An index into the address table.
- /// \returns An optional GSYM data offset for the offset of the FunctionInfo
- /// that needs to be decoded.
- std::optional<uint64_t> getAddressInfoOffset(size_t Index) const;
- };
- } // namespace gsym
- } // namespace llvm
- #endif // LLVM_DEBUGINFO_GSYM_GSYMREADER_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|