LLVM 17.0.0git
RawMemProfReader.cpp
Go to the documentation of this file.
1//===- RawMemProfReader.cpp - Instrumented memory profiling reader --------===//
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// This file contains support for reading MemProf profiling data.
10//
11//===----------------------------------------------------------------------===//
12
13#include <algorithm>
14#include <cstdint>
15#include <memory>
16#include <type_traits>
17
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/SetVector.h"
26#include "llvm/Object/Binary.h"
33#include "llvm/Support/Endian.h"
34#include "llvm/Support/Path.h"
35
36#define DEBUG_TYPE "memprof"
37
38namespace llvm {
39namespace memprof {
40namespace {
41template <class T = uint64_t> inline T alignedRead(const char *Ptr) {
42 static_assert(std::is_pod<T>::value, "Not a pod type.");
43 assert(reinterpret_cast<size_t>(Ptr) % sizeof(T) == 0 && "Unaligned Read");
44 return *reinterpret_cast<const T *>(Ptr);
45}
46
47Error checkBuffer(const MemoryBuffer &Buffer) {
48 if (!RawMemProfReader::hasFormat(Buffer))
49 return make_error<InstrProfError>(instrprof_error::bad_magic);
50
51 if (Buffer.getBufferSize() == 0)
52 return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
53
54 if (Buffer.getBufferSize() < sizeof(Header)) {
55 return make_error<InstrProfError>(instrprof_error::truncated);
56 }
57
58 // The size of the buffer can be > header total size since we allow repeated
59 // serialization of memprof profiles to the same file.
60 uint64_t TotalSize = 0;
61 const char *Next = Buffer.getBufferStart();
62 while (Next < Buffer.getBufferEnd()) {
63 auto *H = reinterpret_cast<const Header *>(Next);
64 if (H->Version != MEMPROF_RAW_VERSION) {
65 return make_error<InstrProfError>(instrprof_error::unsupported_version);
66 }
67
68 TotalSize += H->TotalSize;
69 Next += H->TotalSize;
70 }
71
72 if (Buffer.getBufferSize() != TotalSize) {
73 return make_error<InstrProfError>(instrprof_error::malformed);
74 }
75 return Error::success();
76}
77
78llvm::SmallVector<SegmentEntry> readSegmentEntries(const char *Ptr) {
79 using namespace support;
80
81 const uint64_t NumItemsToRead =
82 endian::readNext<uint64_t, little, unaligned>(Ptr);
84 for (uint64_t I = 0; I < NumItemsToRead; I++) {
85 Items.push_back(*reinterpret_cast<const SegmentEntry *>(
86 Ptr + I * sizeof(SegmentEntry)));
87 }
88 return Items;
89}
90
92readMemInfoBlocks(const char *Ptr) {
93 using namespace support;
94
95 const uint64_t NumItemsToRead =
96 endian::readNext<uint64_t, little, unaligned>(Ptr);
98 for (uint64_t I = 0; I < NumItemsToRead; I++) {
99 const uint64_t Id = endian::readNext<uint64_t, little, unaligned>(Ptr);
100 const MemInfoBlock MIB = *reinterpret_cast<const MemInfoBlock *>(Ptr);
101 Items.push_back({Id, MIB});
102 // Only increment by size of MIB since readNext implicitly increments.
103 Ptr += sizeof(MemInfoBlock);
104 }
105 return Items;
106}
107
108CallStackMap readStackInfo(const char *Ptr) {
109 using namespace support;
110
111 const uint64_t NumItemsToRead =
112 endian::readNext<uint64_t, little, unaligned>(Ptr);
113 CallStackMap Items;
114
115 for (uint64_t I = 0; I < NumItemsToRead; I++) {
116 const uint64_t StackId = endian::readNext<uint64_t, little, unaligned>(Ptr);
117 const uint64_t NumPCs = endian::readNext<uint64_t, little, unaligned>(Ptr);
118
119 SmallVector<uint64_t> CallStack;
120 for (uint64_t J = 0; J < NumPCs; J++) {
121 CallStack.push_back(endian::readNext<uint64_t, little, unaligned>(Ptr));
122 }
123
124 Items[StackId] = CallStack;
125 }
126 return Items;
127}
128
129// Merges the contents of stack information in \p From to \p To. Returns true if
130// any stack ids observed previously map to a different set of program counter
131// addresses.
132bool mergeStackMap(const CallStackMap &From, CallStackMap &To) {
133 for (const auto &IdStack : From) {
134 auto I = To.find(IdStack.first);
135 if (I == To.end()) {
136 To[IdStack.first] = IdStack.second;
137 } else {
138 // Check that the PCs are the same (in order).
139 if (IdStack.second != I->second)
140 return true;
141 }
142 }
143 return false;
144}
145
146Error report(Error E, const StringRef Context) {
148 std::move(E));
149}
150
151bool isRuntimePath(const StringRef Path) {
152 const StringRef Filename = llvm::sys::path::filename(Path);
153 // This list should be updated in case new files with additional interceptors
154 // are added to the memprof runtime.
155 return Filename.equals("memprof_malloc_linux.cpp") ||
156 Filename.equals("memprof_interceptors.cpp") ||
157 Filename.equals("memprof_new_delete.cpp");
158}
159
160std::string getBuildIdString(const SegmentEntry &Entry) {
161 // If the build id is unset print a helpful string instead of all zeros.
162 if (Entry.BuildIdSize == 0)
163 return "<None>";
164
165 std::string Str;
166 raw_string_ostream OS(Str);
167 for (size_t I = 0; I < Entry.BuildIdSize; I++) {
168 OS << format_hex_no_prefix(Entry.BuildId[I], 2);
169 }
170 return OS.str();
171}
172} // namespace
173
174Expected<std::unique_ptr<RawMemProfReader>>
175RawMemProfReader::create(const Twine &Path, const StringRef ProfiledBinary,
176 bool KeepName) {
177 auto BufferOr = MemoryBuffer::getFileOrSTDIN(Path);
178 if (std::error_code EC = BufferOr.getError())
179 return report(errorCodeToError(EC), Path.getSingleStringRef());
180
181 std::unique_ptr<MemoryBuffer> Buffer(BufferOr.get().release());
182 if (Error E = checkBuffer(*Buffer))
183 return report(std::move(E), Path.getSingleStringRef());
184
185 if (ProfiledBinary.empty())
186 return report(
187 errorCodeToError(make_error_code(std::errc::invalid_argument)),
188 "Path to profiled binary is empty!");
189
190 auto BinaryOr = llvm::object::createBinary(ProfiledBinary);
191 if (!BinaryOr) {
192 return report(BinaryOr.takeError(), ProfiledBinary);
193 }
194
195 // Use new here since constructor is private.
196 std::unique_ptr<RawMemProfReader> Reader(
197 new RawMemProfReader(std::move(BinaryOr.get()), KeepName));
198 if (Error E = Reader->initialize(std::move(Buffer))) {
199 return std::move(E);
200 }
201 return std::move(Reader);
202}
203
205 auto BufferOr = MemoryBuffer::getFileOrSTDIN(Path);
206 if (!BufferOr)
207 return false;
208
209 std::unique_ptr<MemoryBuffer> Buffer(BufferOr.get().release());
210 return hasFormat(*Buffer);
211}
212
214 if (Buffer.getBufferSize() < sizeof(uint64_t))
215 return false;
216 // Aligned read to sanity check that the buffer was allocated with at least 8b
217 // alignment.
218 const uint64_t Magic = alignedRead(Buffer.getBufferStart());
219 return Magic == MEMPROF_RAW_MAGIC_64;
220}
221
223 uint64_t NumAllocFunctions = 0, NumMibInfo = 0;
224 for (const auto &KV : FunctionProfileData) {
225 const size_t NumAllocSites = KV.second.AllocSites.size();
226 if (NumAllocSites > 0) {
227 NumAllocFunctions++;
228 NumMibInfo += NumAllocSites;
229 }
230 }
231
232 OS << "MemprofProfile:\n";
233 OS << " Summary:\n";
234 OS << " Version: " << MEMPROF_RAW_VERSION << "\n";
235 OS << " NumSegments: " << SegmentInfo.size() << "\n";
236 OS << " NumMibInfo: " << NumMibInfo << "\n";
237 OS << " NumAllocFunctions: " << NumAllocFunctions << "\n";
238 OS << " NumStackOffsets: " << StackMap.size() << "\n";
239 // Print out the segment information.
240 OS << " Segments:\n";
241 for (const auto &Entry : SegmentInfo) {
242 OS << " -\n";
243 OS << " BuildId: " << getBuildIdString(Entry) << "\n";
244 OS << " Start: 0x" << llvm::utohexstr(Entry.Start) << "\n";
245 OS << " End: 0x" << llvm::utohexstr(Entry.End) << "\n";
246 OS << " Offset: 0x" << llvm::utohexstr(Entry.Offset) << "\n";
247 }
248 // Print out the merged contents of the profiles.
249 OS << " Records:\n";
250 for (const auto &Entry : *this) {
251 OS << " -\n";
252 OS << " FunctionGUID: " << Entry.first << "\n";
253 Entry.second.print(OS);
254 }
255}
256
257Error RawMemProfReader::initialize(std::unique_ptr<MemoryBuffer> DataBuffer) {
258 const StringRef FileName = Binary.getBinary()->getFileName();
259
260 auto *ElfObject = dyn_cast<object::ELFObjectFileBase>(Binary.getBinary());
261 if (!ElfObject) {
262 return report(make_error<StringError>(Twine("Not an ELF file: "),
264 FileName);
265 }
266
267 // Check whether the profiled binary was built with position independent code
268 // (PIC). For now we provide a error message until symbolization support
269 // is added for pic.
270 auto* Elf64LEObject = llvm::cast<llvm::object::ELF64LEObjectFile>(ElfObject);
271 const llvm::object::ELF64LEFile& ElfFile = Elf64LEObject->getELFFile();
272 auto PHdrsOr = ElfFile.program_headers();
273 if(!PHdrsOr)
274 return report(make_error<StringError>(Twine("Could not read program headers: "),
276 FileName);
277 auto FirstLoadHeader = PHdrsOr->begin();
278 while (FirstLoadHeader->p_type != llvm::ELF::PT_LOAD)
279 ++FirstLoadHeader;
280 if(FirstLoadHeader->p_vaddr == 0)
281 return report(make_error<StringError>(Twine("Unsupported position independent code"),
283 FileName);
284
285 auto Triple = ElfObject->makeTriple();
286 if (!Triple.isX86())
287 return report(make_error<StringError>(Twine("Unsupported target: ") +
290 FileName);
291
292 auto *Object = cast<object::ObjectFile>(Binary.getBinary());
293 std::unique_ptr<DIContext> Context = DWARFContext::create(
295
297 Object, std::move(Context), /*UntagAddresses=*/false);
298 if (!SOFOr)
299 return report(SOFOr.takeError(), FileName);
300 Symbolizer = std::move(SOFOr.get());
301
302 if (Error E = readRawProfile(std::move(DataBuffer)))
303 return E;
304
305 if (Error E = symbolizeAndFilterStackFrames())
306 return E;
307
308 return mapRawProfileToRecords();
309}
310
311Error RawMemProfReader::mapRawProfileToRecords() {
312 // Hold a mapping from function to each callsite location we encounter within
313 // it that is part of some dynamic allocation context. The location is stored
314 // as a pointer to a symbolized list of inline frames.
315 using LocationPtr = const llvm::SmallVector<FrameId> *;
317 PerFunctionCallSites;
318
319 // Convert the raw profile callstack data into memprof records. While doing so
320 // keep track of related contexts so that we can fill these in later.
321 for (const auto &Entry : CallstackProfileData) {
322 const uint64_t StackId = Entry.first;
323
324 auto It = StackMap.find(StackId);
325 if (It == StackMap.end())
326 return make_error<InstrProfError>(
328 "memprof callstack record does not contain id: " + Twine(StackId));
329
330 // Construct the symbolized callstack.
332 Callstack.reserve(It->getSecond().size());
333
334 llvm::ArrayRef<uint64_t> Addresses = It->getSecond();
335 for (size_t I = 0; I < Addresses.size(); I++) {
336 const uint64_t Address = Addresses[I];
337 assert(SymbolizedFrame.count(Address) > 0 &&
338 "Address not found in SymbolizedFrame map");
339 const SmallVector<FrameId> &Frames = SymbolizedFrame[Address];
340
341 assert(!idToFrame(Frames.back()).IsInlineFrame &&
342 "The last frame should not be inlined");
343
344 // Record the callsites for each function. Skip the first frame of the
345 // first address since it is the allocation site itself that is recorded
346 // as an alloc site.
347 for (size_t J = 0; J < Frames.size(); J++) {
348 if (I == 0 && J == 0)
349 continue;
350 // We attach the entire bottom-up frame here for the callsite even
351 // though we only need the frames up to and including the frame for
352 // Frames[J].Function. This will enable better deduplication for
353 // compression in the future.
354 const GlobalValue::GUID Guid = idToFrame(Frames[J]).Function;
355 PerFunctionCallSites[Guid].insert(&Frames);
356 }
357
358 // Add all the frames to the current allocation callstack.
359 Callstack.append(Frames.begin(), Frames.end());
360 }
361
362 // We attach the memprof record to each function bottom-up including the
363 // first non-inline frame.
364 for (size_t I = 0; /*Break out using the condition below*/; I++) {
365 const Frame &F = idToFrame(Callstack[I]);
366 auto Result =
367 FunctionProfileData.insert({F.Function, IndexedMemProfRecord()});
368 IndexedMemProfRecord &Record = Result.first->second;
369 Record.AllocSites.emplace_back(Callstack, Entry.second);
370
371 if (!F.IsInlineFrame)
372 break;
373 }
374 }
375
376 // Fill in the related callsites per function.
377 for (const auto &[Id, Locs] : PerFunctionCallSites) {
378 // Some functions may have only callsite data and no allocation data. Here
379 // we insert a new entry for callsite data if we need to.
380 auto Result = FunctionProfileData.insert({Id, IndexedMemProfRecord()});
381 IndexedMemProfRecord &Record = Result.first->second;
382 for (LocationPtr Loc : Locs) {
383 Record.CallSites.push_back(*Loc);
384 }
385 }
386
387 return Error::success();
388}
389
390Error RawMemProfReader::symbolizeAndFilterStackFrames() {
391 // The specifier to use when symbolization is requested.
392 const DILineInfoSpecifier Specifier(
393 DILineInfoSpecifier::FileLineInfoKind::RawValue,
394 DILineInfoSpecifier::FunctionNameKind::LinkageName);
395
396 // For entries where all PCs in the callstack are discarded, we erase the
397 // entry from the stack map.
398 llvm::SmallVector<uint64_t> EntriesToErase;
399 // We keep track of all prior discarded entries so that we can avoid invoking
400 // the symbolizer for such entries.
401 llvm::DenseSet<uint64_t> AllVAddrsToDiscard;
402 for (auto &Entry : StackMap) {
403 for (const uint64_t VAddr : Entry.getSecond()) {
404 // Check if we have already symbolized and cached the result or if we
405 // don't want to attempt symbolization since we know this address is bad.
406 // In this case the address is also removed from the current callstack.
407 if (SymbolizedFrame.count(VAddr) > 0 ||
408 AllVAddrsToDiscard.contains(VAddr))
409 continue;
410
411 Expected<DIInliningInfo> DIOr = Symbolizer->symbolizeInlinedCode(
412 getModuleOffset(VAddr), Specifier, /*UseSymbolTable=*/false);
413 if (!DIOr)
414 return DIOr.takeError();
415 DIInliningInfo DI = DIOr.get();
416
417 // Drop frames which we can't symbolize or if they belong to the runtime.
418 if (DI.getFrame(0).FunctionName == DILineInfo::BadString ||
419 isRuntimePath(DI.getFrame(0).FileName)) {
420 AllVAddrsToDiscard.insert(VAddr);
421 continue;
422 }
423
424 for (size_t I = 0, NumFrames = DI.getNumberOfFrames(); I < NumFrames;
425 I++) {
426 const auto &DIFrame = DI.getFrame(I);
427 const uint64_t Guid =
428 IndexedMemProfRecord::getGUID(DIFrame.FunctionName);
429 const Frame F(Guid, DIFrame.Line - DIFrame.StartLine, DIFrame.Column,
430 // Only the last entry is not an inlined location.
431 I != NumFrames - 1);
432 // Here we retain a mapping from the GUID to symbol name instead of
433 // adding it to the frame object directly to reduce memory overhead.
434 // This is because there can be many unique frames, particularly for
435 // callsite frames.
436 if (KeepSymbolName)
437 GuidToSymbolName.insert({Guid, DIFrame.FunctionName});
438
439 const FrameId Hash = F.hash();
440 IdToFrame.insert({Hash, F});
441 SymbolizedFrame[VAddr].push_back(Hash);
442 }
443 }
444
445 auto &CallStack = Entry.getSecond();
446 llvm::erase_if(CallStack, [&AllVAddrsToDiscard](const uint64_t A) {
447 return AllVAddrsToDiscard.contains(A);
448 });
449 if (CallStack.empty())
450 EntriesToErase.push_back(Entry.getFirst());
451 }
452
453 // Drop the entries where the callstack is empty.
454 for (const uint64_t Id : EntriesToErase) {
455 StackMap.erase(Id);
456 CallstackProfileData.erase(Id);
457 }
458
459 if (StackMap.empty())
460 return make_error<InstrProfError>(
462 "no entries in callstack map after symbolization");
463
464 return Error::success();
465}
466
467Error RawMemProfReader::readRawProfile(
468 std::unique_ptr<MemoryBuffer> DataBuffer) {
469 const char *Next = DataBuffer->getBufferStart();
470
471 while (Next < DataBuffer->getBufferEnd()) {
472 auto *Header = reinterpret_cast<const memprof::Header *>(Next);
473
474 // Read in the segment information, check whether its the same across all
475 // profiles in this binary file.
476 const llvm::SmallVector<SegmentEntry> Entries =
477 readSegmentEntries(Next + Header->SegmentOffset);
478 if (!SegmentInfo.empty() && SegmentInfo != Entries) {
479 // We do not expect segment information to change when deserializing from
480 // the same binary profile file. This can happen if dynamic libraries are
481 // loaded/unloaded between profile dumping.
482 return make_error<InstrProfError>(
484 "memprof raw profile has different segment information");
485 }
486 SegmentInfo.assign(Entries.begin(), Entries.end());
487
488 // Read in the MemInfoBlocks. Merge them based on stack id - we assume that
489 // raw profiles in the same binary file are from the same process so the
490 // stackdepot ids are the same.
491 for (const auto &Value : readMemInfoBlocks(Next + Header->MIBOffset)) {
492 if (CallstackProfileData.count(Value.first)) {
493 CallstackProfileData[Value.first].Merge(Value.second);
494 } else {
495 CallstackProfileData[Value.first] = Value.second;
496 }
497 }
498
499 // Read in the callstack for each ids. For multiple raw profiles in the same
500 // file, we expect that the callstack is the same for a unique id.
501 const CallStackMap CSM = readStackInfo(Next + Header->StackOffset);
502 if (StackMap.empty()) {
503 StackMap = CSM;
504 } else {
505 if (mergeStackMap(CSM, StackMap))
506 return make_error<InstrProfError>(
508 "memprof raw profile got different call stack for same id");
509 }
510
511 Next += Header->TotalSize;
512 }
513
514 return Error::success();
515}
516
517object::SectionedAddress
518RawMemProfReader::getModuleOffset(const uint64_t VirtualAddress) {
519 LLVM_DEBUG({
520 SegmentEntry *ContainingSegment = nullptr;
521 for (auto &SE : SegmentInfo) {
522 if (VirtualAddress > SE.Start && VirtualAddress <= SE.End) {
523 ContainingSegment = &SE;
524 }
525 }
526
527 // Ensure that the virtual address is valid.
528 assert(ContainingSegment && "Could not find a segment entry");
529 });
530
531 // TODO: Compute the file offset based on the maps and program headers. For
532 // now this only works for non PIE binaries.
533 return object::SectionedAddress{VirtualAddress};
534}
535
537 if (FunctionProfileData.empty())
538 return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
539
540 if (Iter == FunctionProfileData.end())
541 return make_error<InstrProfError>(instrprof_error::eof);
542
543 auto IdToFrameCallback = [this](const FrameId Id) {
544 Frame F = this->idToFrame(Id);
545 if (!this->KeepSymbolName)
546 return F;
547 auto Iter = this->GuidToSymbolName.find(F.Function);
548 assert(Iter != this->GuidToSymbolName.end());
549 F.SymbolName = Iter->getSecond();
550 return F;
551 };
552
553 const IndexedMemProfRecord &IndexedRecord = Iter->second;
554 GuidRecord = {Iter->first, MemProfRecord(IndexedRecord, IdToFrameCallback)};
555 Iter++;
556 return Error::success();
557}
558} // namespace memprof
559} // namespace llvm
BlockVerifier::State From
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DEBUG(X)
Definition: Debug.h:101
This file defines the DenseMap class.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#define H(x, y, z)
Definition: MD5.cpp:57
LLVMContext & Context
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:163
static std::unique_ptr< DWARFContext > create(const object::ObjectFile &Obj, ProcessDebugRelocations RelocAction=ProcessDebugRelocations::Process, const LoadedObjectInfo *L=nullptr, std::string DWPName="", std::function< void(Error)> RecoverableErrorHandler=WithColor::defaultErrorHandler, std::function< void(Error)> WarningHandler=WithColor::defaultWarningHandler)
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
unsigned size() const
Definition: DenseMap.h:99
iterator end()
Definition: DenseMap.h:84
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:220
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
Definition: GlobalValue.h:583
This class implements a map that also provides access to all stored values in a deterministic order.
Definition: MapVector.h:37
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: MapVector.h:118
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:51
size_t getBufferSize() const
Definition: MemoryBuffer.h:68
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
const char * getBufferStart() const
Definition: MemoryBuffer.h:66
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
void assign(size_type NumElts, ValueParamT Elt)
Definition: SmallVector.h:708
void reserve(size_type N)
Definition: SmallVector.h:667
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:687
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
bool isX86() const
Tests whether the target is x86 (32- or 64-bit).
Definition: Triple.h:939
StringRef getArchName() const
Get the architecture (first) component of the triple.
Definition: Triple.cpp:1151
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition: DenseSet.h:185
std::pair< GlobalValue::GUID, MemProfRecord > GuidMemProfRecordPair
static Expected< std::unique_ptr< RawMemProfReader > > create(const Twine &Path, const StringRef ProfiledBinary, bool KeepName=false)
Error readNextRecord(GuidMemProfRecordPair &GuidRecord)
static bool hasFormat(const MemoryBuffer &DataBuffer)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
static Expected< std::unique_ptr< SymbolizableObjectFile > > create(const object::ObjectFile *Obj, std::unique_ptr< DIContext > DICtx, bool UntagAddresses)
@ PT_LOAD
Definition: ELF.h:1382
uint64_t FrameId
Definition: MemProf.h:138
llvm::DenseMap< uint64_t, llvm::SmallVector< uint64_t > > CallStackMap
Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
Definition: Binary.cpp:45
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:577
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::error_code make_error_code(BitcodeError E)
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:79
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1246
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:427
FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)
format_hex_no_prefix - Output N as a fixed width hexadecimal.
Definition: Format.h:199
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition: STLExtras.h:2076
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:92
static constexpr const char *const BadString
Definition: DIContext.h:34
GlobalValue::GUID Function
Definition: MemProf.h:145
static GlobalValue::GUID getGUID(const StringRef FunctionName)
Definition: MemProf.cpp:73