LLVM 24.0.0git
FunctionInfo.h
Go to the documentation of this file.
1//===- FunctionInfo.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_FUNCTIONINFO_H
10#define LLVM_DEBUGINFO_GSYM_FUNCTIONINFO_H
11
22#include <cstdint>
23
24namespace llvm {
25class raw_ostream;
26
27namespace gsym {
28
29class GsymCreator;
30class GsymReader;
32
33/// Byte-size accounting for a FunctionInfo, broken down by field / InfoType.
34/// Populated by FunctionInfo::parseStatistics. Every value is a byte count and
35/// each on-disk byte of a FunctionInfo is attributed to exactly one member:
36/// FunctionInfo = SizeAndName + LineTableInfo + InlineInfo + CallSiteInfo +
37/// MergedFuncInfo + EndOfList
38/// (the per-InfoType members include that section's 8-byte InfoType+InfoLength
39/// header). InfoTypeInfoLengthCountAndFnSize is only used for the inner
40/// (merged) breakdown and captures the MergedFunctionsInfo structural bytes:
41/// its own InfoType+InfoLength (8) plus Count (4) plus each FnSize (4).
51
52/// Function information in GSYM files encodes information for one contiguous
53/// address range. If a function has discontiguous address ranges, they will
54/// need to be encoded using multiple FunctionInfo objects.
55///
56/// ENCODING
57///
58/// The function information gets the function start address as an argument
59/// to the FunctionInfo::decode(...) function. This information is calculated
60/// from the GSYM header and an address offset from the GSYM address offsets
61/// table. The encoded FunctionInfo information must be aligned to a 4 byte
62/// boundary.
63///
64/// The encoded data for a FunctionInfo starts with fixed data that all
65/// function info objects have:
66///
67/// ENCODING NAME DESCRIPTION
68/// ========= =========== ====================================================
69/// uint32_t Size The size in bytes of this function.
70/// uint32_t Name The string table offset of the function name.
71///
72/// The optional data in a FunctionInfo object follows this fixed information
73/// and consists of a stream of tuples that consist of:
74///
75/// ENCODING NAME DESCRIPTION
76/// ========= =========== ====================================================
77/// uint32_t InfoType An "InfoType" enumeration that describes the type
78/// of optional data that is encoded.
79/// uint32_t InfoLength The size in bytes of the encoded data that
80/// immediately follows this length if this value is
81/// greater than zero.
82/// uint8_t[] InfoData Encoded bytes that represent the data for the
83/// "InfoType". These bytes are only present if
84/// "InfoLength" is greater than zero.
85///
86/// The "InfoType" is an enumeration:
87///
88/// enum InfoType {
89/// EndOfList = 0u,
90/// LineTableInfo = 1u,
91/// InlineInfo = 2u,
92/// MergedFunctionsInfo = 3u,
93/// CallSiteInfo = 4u
94/// };
95///
96/// This stream of tuples is terminated by a "InfoType" whose value is
97/// InfoType::EndOfList and a zero for "InfoLength". This signifies the end of
98/// the optional information list. This format allows us to add new optional
99/// information data to a FunctionInfo object over time and allows older
100/// clients to still parse the format and skip over any data that they don't
101/// understand or want to parse.
102///
103/// So the function information encoding essentially looks like:
104///
105/// struct {
106/// uint32_t Size;
107/// uint32_t Name;
108/// struct {
109/// uint32_t InfoType;
110/// uint32_t InfoLength;
111/// uint8_t InfoData[InfoLength];
112/// }[N];
113/// }
114///
115/// Where "N" is the number of tuples.
118 gsym_strp_t Name; ///< String table offset in the string table.
119 std::optional<LineTable> OptLineTable;
120 std::optional<InlineInfo> Inline;
121 std::optional<MergedFunctionsInfo> MergedFunctions;
122 std::optional<CallSiteInfoCollection> CallSites;
123 /// If we encode a FunctionInfo during segmenting so we know its size, we can
124 /// cache that encoding here so we don't need to re-encode it when saving the
125 /// GSYM file.
127
129 : Range(Addr, Addr + Size), Name(Name) {}
130
131 /// Query if a FunctionInfo has rich debug info.
132 ///
133 /// \returns A bool that indicates if this object has something else than
134 /// range and name. When converting information from a symbol table and from
135 /// debug info, we might end up with multiple FunctionInfo objects for the
136 /// same range and we need to be able to tell which one is the better object
137 /// to use.
138 bool hasRichInfo() const { return OptLineTable || Inline || CallSites; }
139
140 /// Query if a FunctionInfo object is valid.
141 ///
142 /// Address and size can be zero and there can be no line entries for a
143 /// symbol so the only indication this entry is valid is if the name is
144 /// not zero. This can happen when extracting information from symbol
145 /// tables that do not encode symbol sizes. In that case only the
146 /// address and name will be filled in.
147 ///
148 /// \returns A boolean indicating if this FunctionInfo is valid.
149 bool isValid() const {
150 return Name != 0;
151 }
152
153 /// Decode an object from a binary data stream.
154 ///
155 /// \param Data The binary stream to read the data from. This object must
156 /// have the data for the object starting at offset zero. The data
157 /// can contain more data than needed.
158 ///
159 /// \param BaseAddr The FunctionInfo's start address and will be used as the
160 /// base address when decoding any contained information like the line table
161 /// and the inline info.
162 ///
163 /// \returns An FunctionInfo or an error describing the issue that was
164 /// encountered during decoding.
166 uint64_t BaseAddr);
167
168 /// Encode this object into FileWriter stream.
169 ///
170 /// \param O The binary stream to write the data to at the current file
171 /// position.
172 ///
173 /// \param NoPadding Directly write the FunctionInfo data, without any padding
174 /// By default, FunctionInfo will be 4-byte aligned by padding with
175 /// 0's at the start. This is OK since the function will return the offset of
176 /// actual data in the stream. However when writing FunctionInfo's as a
177 /// stream, the padding will break the decoding of the data - since the offset
178 /// where the FunctionInfo starts is not kept in this scenario.
179 ///
180 /// \returns An error object that indicates failure or the offset of the
181 /// function info that was successfully written into the stream.
183 bool NoPadding = false) const;
184
185 /// Encode this function info into the internal byte cache and return the size
186 /// in bytes.
187 ///
188 /// When segmenting GSYM files we need to know how big each FunctionInfo will
189 /// encode into so we can generate segments of the right size. We don't want
190 /// to have to encode a FunctionInfo twice, so we can cache the encoded bytes
191 /// and re-use then when calling FunctionInfo::encode(...).
192 ///
193 /// \returns The size in bytes of the FunctionInfo if it were to be encoded
194 /// into a byte stream.
196
197 /// Lookup an address within a FunctionInfo object's data stream.
198 ///
199 /// Instead of decoding an entire FunctionInfo object when doing lookups,
200 /// we can decode only the information we need from the FunctionInfo's data
201 /// for the specific address. The lookup result information is returned as
202 /// a LookupResult.
203 ///
204 /// \param Data The binary stream to read the data from. This object must
205 /// have the data for the object starting at offset zero. The data
206 /// can contain more data than needed.
207 ///
208 /// \param GR The GSYM reader that contains the string and file table that
209 /// will be used to fill in information in the returned result.
210 ///
211 /// \param FuncAddr The function start address decoded from the GsymReader.
212 ///
213 /// \param Addr The address to lookup.
214 ///
215 /// \param MergedFuncsData A pointer to an optional GsymDataExtractor that, if
216 /// non-null, will be set to the raw data of the MergedFunctionInfo, if
217 /// present.
218 ///
219 /// \returns An LookupResult or an error describing the issue that was
220 /// encountered during decoding. An error should only be returned if the
221 /// address is not contained in the FunctionInfo or if the data is corrupted.
223 lookup(GsymDataExtractor &Data, const GsymReader &GR, uint64_t FuncAddr,
224 uint64_t Addr,
225 std::optional<GsymDataExtractor> *MergedFuncsData = nullptr);
226
227 /// Parse the function info data and accumulate the byte size of each field /
228 /// InfoType into \a Stats.
229 ///
230 /// \param Data The binary stream to read the data from. Its string-offset
231 /// size is used to size the FunctionInfo Name field (4 bytes in GSYM v1,
232 /// 1-8 bytes in v2).
233 ///
234 /// \param Stats Updated with the per-field byte sizes for this FunctionInfo.
235 ///
236 /// \param MergedFuncInfoStats If non-null, and a MergedFunctionsInfo section
237 /// is present, this is updated with the byte breakdown of the inner
238 /// FunctionInfos plus the MergedFunctionsInfo structural bytes
239 /// (InfoTypeInfoLengthCountAndFnSize).
240 LLVM_ABI static void
242 FunctionInfoStats *MergedFuncInfoStats = nullptr);
243
244 uint64_t startAddress() const { return Range.start(); }
245 uint64_t endAddress() const { return Range.end(); }
246 uint64_t size() const { return Range.size(); }
247
248 void clear() {
249 Range = {0, 0};
250 Name = 0;
251 OptLineTable = std::nullopt;
252 Inline = std::nullopt;
253 }
254};
255
256inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) {
257 return LHS.Range == RHS.Range && LHS.Name == RHS.Name &&
258 LHS.OptLineTable == RHS.OptLineTable && LHS.Inline == RHS.Inline &&
259 LHS.CallSites == RHS.CallSites;
260}
261inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) {
262 return !(LHS == RHS);
263}
264/// This sorting will order things consistently by address range first, but
265/// then followed by increasing levels of debug info like inline information
266/// and line tables. We might end up with a FunctionInfo from debug info that
267/// will have the same range as one from the symbol table, but we want to
268/// quickly be able to sort and use the best version when creating the final
269/// GSYM file. This function compares the inline information as we have seen
270/// cases where LTO can generate a wide array of differing inline information,
271/// mostly due to messing up the address ranges for inlined functions, so the
272/// inline information with the most entries will appeear last. If the inline
273/// information match, either by both function infos not having any or both
274/// being exactly the same, we will then compare line tables. Comparing line
275/// tables allows the entry with the most line entries to appear last. As a
276/// final tiebreaker, an entry that has call site information sorts after one
277/// that does not, so that within a single address range the entry with the
278/// most debug info always appears last. This ensures we are able to save the
279/// FunctionInfo with the most debug info into the GSYM file.
280inline bool operator<(const FunctionInfo &LHS, const FunctionInfo &RHS) {
281 // First sort by address range
282 const bool LHSHasCallSites = LHS.CallSites.has_value();
283 const bool RHSHasCallSites = RHS.CallSites.has_value();
284 return std::tie(LHS.Range, LHS.Inline, LHS.OptLineTable, LHSHasCallSites) <
285 std::tie(RHS.Range, RHS.Inline, RHS.OptLineTable, RHSHasCallSites);
286}
287
288LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const FunctionInfo &R);
289
290} // namespace gsym
291} // namespace llvm
292
293#endif // LLVM_DEBUGINFO_GSYM_FUNCTIONINFO_H
#define LLVM_ABI
Definition Compiler.h:215
block placement Basic Block Placement Stats
This file defines the SmallString class.
Value * RHS
Value * LHS
A class that represents an address range.
Tagged union holding either a T or a Error.
Definition Error.h:485
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
A simplified binary data writer class that doesn't require targets, target definitions,...
Definition FileWriter.h:30
GsymCreator is used to emit GSYM data to a stand alone file or section within a file.
A DataExtractor subclass that adds GSYM-specific string offset support.
GsymReader is used to read GSYM data from a file or buffer.
Definition GsymReader.h:48
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
uint64_t gsym_strp_t
The type of string offset used in the code.
Definition GsymTypes.h:21
LLVM_ABI raw_ostream & operator<<(raw_ostream &OS, const CallSiteInfo &CSI)
bool operator<(const FunctionInfo &LHS, const FunctionInfo &RHS)
This sorting will order things consistently by address range first, but then followed by increasing l...
bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS)
bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS)
This is an optimization pass for GlobalISel generic memory operations.
Byte-size accounting for a FunctionInfo, broken down by field / InfoType.
Function information in GSYM files encodes information for one contiguous address range.
std::optional< InlineInfo > Inline
std::optional< MergedFunctionsInfo > MergedFunctions
uint64_t startAddress() const
uint64_t endAddress() const
static LLVM_ABI llvm::Expected< FunctionInfo > decode(GsymDataExtractor &Data, uint64_t BaseAddr)
Decode an object from a binary data stream.
bool isValid() const
Query if a FunctionInfo object is valid.
std::optional< CallSiteInfoCollection > CallSites
bool hasRichInfo() const
Query if a FunctionInfo has rich debug info.
uint64_t size() const
FunctionInfo(uint64_t Addr=0, uint64_t Size=0, gsym_strp_t Name=0)
static LLVM_ABI void parseStatistics(GsymDataExtractor &Data, FunctionInfoStats &Stats, FunctionInfoStats *MergedFuncInfoStats=nullptr)
Parse the function info data and accumulate the byte size of each field / InfoType into Stats.
gsym_strp_t Name
String table offset in the string table.
LLVM_ABI llvm::Expected< uint64_t > encode(FileWriter &O, bool NoPadding=false) const
Encode this object into FileWriter stream.
SmallString< 32 > EncodingCache
If we encode a FunctionInfo during segmenting so we know its size, we can cache that encoding here so...
std::optional< LineTable > OptLineTable
LLVM_ABI uint64_t cacheEncoding(GsymCreator &GC)
Encode this function info into the internal byte cache and return the size in bytes.
static LLVM_ABI llvm::Expected< LookupResult > lookup(GsymDataExtractor &Data, const GsymReader &GR, uint64_t FuncAddr, uint64_t Addr, std::optional< GsymDataExtractor > *MergedFuncsData=nullptr)
Lookup an address within a FunctionInfo object's data stream.