LLVM 20.0.0git
CallSiteInfo.cpp
Go to the documentation of this file.
1//===- CallSiteInfo.cpp -----------------------------------------*- 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
19#include <fstream>
20#include <string>
21#include <unordered_map>
22#include <vector>
23
24using namespace llvm;
25using namespace gsym;
26
27Error CallSiteInfo::encode(FileWriter &O) const {
28 O.writeU64(ReturnOffset);
29 O.writeU8(Flags);
30 O.writeU32(MatchRegex.size());
31 for (uint32_t Entry : MatchRegex)
32 O.writeU32(Entry);
33 return Error::success();
34}
35
38 CallSiteInfo CSI;
39
40 // Read ReturnOffset
41 if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(uint64_t)))
42 return createStringError(std::errc::io_error,
43 "0x%8.8" PRIx64 ": missing ReturnOffset", Offset);
44 CSI.ReturnOffset = Data.getU64(&Offset);
45
46 // Read Flags
47 if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(uint8_t)))
48 return createStringError(std::errc::io_error,
49 "0x%8.8" PRIx64 ": missing Flags", Offset);
50 CSI.Flags = Data.getU8(&Offset);
51
52 // Read number of MatchRegex entries
53 if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(uint32_t)))
54 return createStringError(std::errc::io_error,
55 "0x%8.8" PRIx64 ": missing MatchRegex count",
56 Offset);
57 uint32_t NumEntries = Data.getU32(&Offset);
58
59 CSI.MatchRegex.reserve(NumEntries);
60 for (uint32_t i = 0; i < NumEntries; ++i) {
61 if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(uint32_t)))
62 return createStringError(std::errc::io_error,
63 "0x%8.8" PRIx64 ": missing MatchRegex entry",
64 Offset);
65 uint32_t Entry = Data.getU32(&Offset);
66 CSI.MatchRegex.push_back(Entry);
67 }
68
69 return CSI;
70}
71
73 O.writeU32(CallSites.size());
74 for (const CallSiteInfo &CSI : CallSites)
75 if (Error Err = CSI.encode(O))
76 return Err;
77
78 return Error::success();
79}
80
84 uint64_t Offset = 0;
85
86 // Read number of CallSiteInfo entries
87 if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(uint32_t)))
88 return createStringError(std::errc::io_error,
89 "0x%8.8" PRIx64 ": missing CallSiteInfo count",
90 Offset);
91 uint32_t NumCallSites = Data.getU32(&Offset);
92
93 CSC.CallSites.reserve(NumCallSites);
94 for (uint32_t i = 0; i < NumCallSites; ++i) {
96 if (!ECSI)
97 return ECSI.takeError();
98 CSC.CallSites.emplace_back(*ECSI);
99 }
100
101 return CSC;
102}
103
104/// Structures necessary for reading CallSiteInfo from YAML.
105namespace llvm {
106namespace yaml {
107
109 // The offset of the return address of the call site - relative to the start
110 // of the function.
112 std::vector<std::string> match_regex;
113 std::vector<std::string> flags;
114};
115
117 std::string name;
118 std::vector<CallSiteYAML> callsites;
119};
120
122 std::vector<FunctionYAML> functions;
123};
124
125template <> struct MappingTraits<CallSiteYAML> {
126 static void mapping(IO &io, CallSiteYAML &callsite) {
127 io.mapRequired("return_offset", callsite.return_offset);
128 io.mapRequired("match_regex", callsite.match_regex);
129 io.mapOptional("flags", callsite.flags);
130 }
131};
132
133template <> struct MappingTraits<FunctionYAML> {
134 static void mapping(IO &io, FunctionYAML &func) {
135 io.mapRequired("name", func.name);
136 io.mapOptional("callsites", func.callsites);
137 }
138};
139
140template <> struct MappingTraits<FunctionsYAML> {
141 static void mapping(IO &io, FunctionsYAML &FuncYAMLs) {
142 io.mapRequired("functions", FuncYAMLs.functions);
143 }
144};
145
146} // namespace yaml
147} // namespace llvm
148
151
153 // Step 1: Read YAML file
154 auto BufferOrError = MemoryBuffer::getFile(YAMLFile);
155 if (!BufferOrError)
156 return errorCodeToError(BufferOrError.getError());
157
158 std::unique_ptr<MemoryBuffer> Buffer = std::move(*BufferOrError);
159
160 // Step 2: Parse YAML content
161 yaml::FunctionsYAML FuncsYAML;
162 yaml::Input Yin(Buffer->getMemBufferRef());
163 Yin >> FuncsYAML;
164 if (Yin.error())
165 return createStringError(Yin.error(), "Error parsing YAML file: %s\n",
166 Buffer->getBufferIdentifier().str().c_str());
167
168 // Step 3: Build function map from Funcs
169 auto FuncMap = buildFunctionMap();
170
171 // Step 4: Process parsed YAML functions and update FuncMap
172 return processYAMLFunctions(FuncsYAML, FuncMap);
173}
174
175StringMap<FunctionInfo *> CallSiteInfoLoader::buildFunctionMap() {
176 // If the function name is already in the map, don't update it. This way we
177 // preferentially use the first encountered function. Since symbols are
178 // loaded from dSYM first, we end up preferring keeping track of symbols
179 // from dSYM rather than from the symbol table - which is what we want to
180 // do.
182 for (auto &Func : Funcs) {
183 FuncMap.try_emplace(GCreator.getString(Func.Name), &Func);
184 if (auto &MFuncs = Func.MergedFunctions)
185 for (auto &MFunc : MFuncs->MergedFunctions)
186 FuncMap.try_emplace(GCreator.getString(MFunc.Name), &MFunc);
187 }
188 return FuncMap;
189}
190
191Error CallSiteInfoLoader::processYAMLFunctions(
192 const yaml::FunctionsYAML &FuncYAMLs, StringMap<FunctionInfo *> &FuncMap) {
193 // For each function in the YAML file
194 for (const auto &FuncYAML : FuncYAMLs.functions) {
195 auto It = FuncMap.find(FuncYAML.name);
196 if (It == FuncMap.end())
197 return createStringError(
198 std::errc::invalid_argument,
199 "Can't find function '%s' specified in callsite YAML\n",
200 FuncYAML.name.c_str());
201
202 FunctionInfo *FuncInfo = It->second;
203 // Create a CallSiteInfoCollection if not already present
204 if (!FuncInfo->CallSites)
205 FuncInfo->CallSites = CallSiteInfoCollection();
206 for (const auto &CallSiteYAML : FuncYAML.callsites) {
207 CallSiteInfo CSI;
208 // Since YAML has specifies relative return offsets, add the function
209 // start address to make the offset absolute.
210 CSI.ReturnOffset = CallSiteYAML.return_offset;
211 for (const auto &Regex : CallSiteYAML.match_regex) {
212 uint32_t StrOffset = GCreator.insertString(Regex);
213 CSI.MatchRegex.push_back(StrOffset);
214 }
215
216 // Parse flags and combine them
217 for (const auto &FlagStr : CallSiteYAML.flags) {
218 if (FlagStr == "InternalCall") {
219 CSI.Flags |= static_cast<uint8_t>(CallSiteInfo::InternalCall);
220 } else if (FlagStr == "ExternalCall") {
221 CSI.Flags |= static_cast<uint8_t>(CallSiteInfo::ExternalCall);
222 } else {
223 return createStringError(std::errc::invalid_argument,
224 "Unknown flag in callsite YAML: %s\n",
225 FlagStr.c_str());
226 }
227 }
228 FuncInfo->CallSites->CallSites.push_back(CSI);
229 }
230 }
231 return Error::success();
232}
233
235 OS << " Return=" << HEX64(CSI.ReturnOffset);
236 OS << " Flags=" << HEX8(CSI.Flags);
237
238 OS << " RegEx=";
239 for (uint32_t i = 0; i < CSI.MatchRegex.size(); ++i) {
240 if (i > 0)
241 OS << ",";
242 OS << CSI.MatchRegex[i];
243 }
244 return OS;
245}
246
248 const CallSiteInfoCollection &CSIC) {
249 for (const auto &CS : CSIC.CallSites) {
250 OS << CS;
251 OS << "\n";
252 }
253 return OS;
254}
This file defines CachedHashString and CachedHashStringRef.
#define HEX8(v)
Definition: ExtractRanges.h:17
#define HEX64(v)
Definition: ExtractRanges.h:20
global merge func
static Error loadYAML(sys::fs::file_t Fd, size_t FileSize, StringRef Filename, InstrumentationMap::SledContainer &Sleds, InstrumentationMap::FunctionAddressMap &FunctionAddresses, InstrumentationMap::FunctionAddressReverseMap &FunctionIds)
raw_pwrite_stream & OS
#define LLVM_YAML_IS_SEQUENCE_VECTOR(type)
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:128
iterator end()
Definition: StringMap.h:220
iterator find(StringRef Key)
Definition: StringMap.h:233
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
Definition: StringMap.h:368
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
A simplified binary data writer class that doesn't require targets, target definitions,...
Definition: FileWriter.h:29
uint32_t insertString(StringRef S, bool Copy=true)
Insert a string into the GSYM string table.
StringRef getString(uint32_t Offset)
Retrieve a string from the GSYM string table given its offset.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
raw_ostream & operator<<(raw_ostream &OS, const CallSiteInfo &CSI)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1291
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:111
llvm::Error encode(FileWriter &O) const
Encode this CallSiteInfoCollection object into a FileWriter stream.
std::vector< CallSiteInfo > CallSites
Definition: CallSiteInfo.h:68
static llvm::Expected< CallSiteInfoCollection > decode(DataExtractor &Data)
Decode a CallSiteInfoCollection object from a binary data stream.
std::vector< uint32_t > MatchRegex
Offsets into the string table for function names regex patterns.
Definition: CallSiteInfo.h:47
uint64_t ReturnOffset
The return offset of the call site - relative to the function start.
Definition: CallSiteInfo.h:44
static llvm::Expected< CallSiteInfo > decode(DataExtractor &Data, uint64_t &Offset)
Decode a CallSiteInfo object from a binary data stream.
Function information in GSYM files encodes information for one contiguous address range.
Definition: FunctionInfo.h:92
std::optional< CallSiteInfoCollection > CallSites
Definition: FunctionInfo.h:98
std::vector< std::string > flags
std::vector< std::string > match_regex
std::vector< CallSiteYAML > callsites
std::vector< FunctionYAML > functions
static void mapping(IO &io, CallSiteYAML &callsite)
static void mapping(IO &io, FunctionYAML &func)
static void mapping(IO &io, FunctionsYAML &FuncYAMLs)