1 //===-- ProfiledBinary.cpp - Binary decoder ---------------------*- 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 #include "ProfiledBinary.h"
10 #include "ErrorHandling.h"
11 #include "ProfileGenerator.h"
12 #include "llvm/ADT/Triple.h"
13 #include "llvm/Demangle/Demangle.h"
14 #include "llvm/IR/DebugInfoMetadata.h"
15 #include "llvm/Support/CommandLine.h"
16 #include "llvm/Support/Format.h"
17 #include "llvm/Support/TargetRegistry.h"
18 #include "llvm/Support/TargetSelect.h"
19 
20 #define DEBUG_TYPE "load-binary"
21 
22 using namespace llvm;
23 using namespace sampleprof;
24 
25 cl::opt<bool> ShowDisassemblyOnly("show-disassembly-only", cl::ReallyHidden,
26                                   cl::init(false), cl::ZeroOrMore,
27                                   cl::desc("Print disassembled code."));
28 
29 cl::opt<bool> ShowSourceLocations("show-source-locations", cl::ReallyHidden,
30                                   cl::init(false), cl::ZeroOrMore,
31                                   cl::desc("Print source locations."));
32 
33 cl::opt<bool> ShowCanonicalFnName("show-canonical-fname", cl::ReallyHidden,
34                                   cl::init(false), cl::ZeroOrMore,
35                                   cl::desc("Print canonical function name."));
36 
37 cl::opt<bool> ShowPseudoProbe(
38     "show-pseudo-probe", cl::ReallyHidden, cl::init(false), cl::ZeroOrMore,
39     cl::desc("Print pseudo probe section and disassembled info."));
40 
41 namespace llvm {
42 namespace sampleprof {
43 
44 static const Target *getTarget(const ObjectFile *Obj) {
45   Triple TheTriple = Obj->makeTriple();
46   std::string Error;
47   std::string ArchName;
48   const Target *TheTarget =
49       TargetRegistry::lookupTarget(ArchName, TheTriple, Error);
50   if (!TheTarget)
51     exitWithError(Error, Obj->getFileName());
52   return TheTarget;
53 }
54 
55 void BinarySizeContextTracker::addInstructionForContext(
56     const SampleContextFrameVector &Context, uint32_t InstrSize) {
57   ContextTrieNode *CurNode = &RootContext;
58   bool IsLeaf = true;
59   for (const auto &Callsite : reverse(Context)) {
60     StringRef CallerName = Callsite.CallerName;
61     LineLocation CallsiteLoc = IsLeaf ? LineLocation(0, 0) : Callsite.Callsite;
62     CurNode = CurNode->getOrCreateChildContext(CallsiteLoc, CallerName);
63     IsLeaf = false;
64   }
65 
66   CurNode->addFunctionSize(InstrSize);
67 }
68 
69 uint32_t
70 BinarySizeContextTracker::getFuncSizeForContext(const SampleContext &Context) {
71   ContextTrieNode *CurrNode = &RootContext;
72   ContextTrieNode *PrevNode = nullptr;
73   SampleContextFrames Frames = Context.getContextFrames();
74   int32_t I = Frames.size() - 1;
75   Optional<uint32_t> Size;
76 
77   // Start from top-level context-less function, traverse down the reverse
78   // context trie to find the best/longest match for given context, then
79   // retrieve the size.
80 
81   while (CurrNode && I >= 0) {
82     // Process from leaf function to callers (added to context).
83     const auto &ChildFrame = Frames[I--];
84     PrevNode = CurrNode;
85     CurrNode =
86         CurrNode->getChildContext(ChildFrame.Callsite, ChildFrame.CallerName);
87     if (CurrNode && CurrNode->getFunctionSize().hasValue())
88       Size = CurrNode->getFunctionSize().getValue();
89   }
90 
91   // If we traversed all nodes along the path of the context and haven't
92   // found a size yet, pivot to look for size from sibling nodes, i.e size
93   // of inlinee under different context.
94   if (!Size.hasValue()) {
95     if (!CurrNode)
96       CurrNode = PrevNode;
97     while (!Size.hasValue() && CurrNode &&
98            !CurrNode->getAllChildContext().empty()) {
99       CurrNode = &CurrNode->getAllChildContext().begin()->second;
100       if (CurrNode->getFunctionSize().hasValue())
101         Size = CurrNode->getFunctionSize().getValue();
102     }
103   }
104 
105   assert(Size.hasValue() && "We should at least find one context size.");
106   return Size.getValue();
107 }
108 
109 void BinarySizeContextTracker::trackInlineesOptimizedAway(
110     MCPseudoProbeDecoder &ProbeDecoder) {
111   ProbeFrameStack ProbeContext;
112   for (const auto &Child : ProbeDecoder.getDummyInlineRoot().getChildren())
113     trackInlineesOptimizedAway(ProbeDecoder, *Child.second.get(), ProbeContext);
114 }
115 
116 void BinarySizeContextTracker::trackInlineesOptimizedAway(
117     MCPseudoProbeDecoder &ProbeDecoder,
118     MCDecodedPseudoProbeInlineTree &ProbeNode, ProbeFrameStack &ProbeContext) {
119   StringRef FuncName =
120       ProbeDecoder.getFuncDescForGUID(ProbeNode.Guid)->FuncName;
121   ProbeContext.emplace_back(FuncName, 0);
122 
123   // This ProbeContext has a probe, so it has code before inlining and
124   // optimization. Make sure we mark its size as known.
125   if (!ProbeNode.getProbes().empty()) {
126     ContextTrieNode *SizeContext = &RootContext;
127     for (auto &ProbeFrame : reverse(ProbeContext)) {
128       StringRef CallerName = ProbeFrame.first;
129       LineLocation CallsiteLoc(ProbeFrame.second, 0);
130       SizeContext =
131           SizeContext->getOrCreateChildContext(CallsiteLoc, CallerName);
132     }
133     // Add 0 size to make known.
134     SizeContext->addFunctionSize(0);
135   }
136 
137   // DFS down the probe inline tree
138   for (const auto &ChildNode : ProbeNode.getChildren()) {
139     InlineSite Location = ChildNode.first;
140     ProbeContext.back().second = std::get<1>(Location);
141     trackInlineesOptimizedAway(ProbeDecoder, *ChildNode.second.get(), ProbeContext);
142   }
143 
144   ProbeContext.pop_back();
145 }
146 
147 void ProfiledBinary::load() {
148   // Attempt to open the binary.
149   OwningBinary<Binary> OBinary = unwrapOrError(createBinary(Path), Path);
150   Binary &Binary = *OBinary.getBinary();
151 
152   auto *Obj = dyn_cast<ELFObjectFileBase>(&Binary);
153   if (!Obj)
154     exitWithError("not a valid Elf image", Path);
155 
156   TheTriple = Obj->makeTriple();
157   // Current only support X86
158   if (!TheTriple.isX86())
159     exitWithError("unsupported target", TheTriple.getTriple());
160   LLVM_DEBUG(dbgs() << "Loading " << Path << "\n");
161 
162   // Find the preferred load address for text sections.
163   setPreferredTextSegmentAddresses(Obj);
164 
165   // Decode pseudo probe related section
166   decodePseudoProbe(Obj);
167 
168   // Disassemble the text sections.
169   disassemble(Obj);
170 
171   // Track size for optimized inlinees when probe is available
172   if (UsePseudoProbes && TrackFuncContextSize)
173     FuncSizeTracker.trackInlineesOptimizedAway(ProbeDecoder);
174 
175   // Use function start and return address to infer prolog and epilog
176   ProEpilogTracker.inferPrologOffsets(FuncStartAddrMap);
177   ProEpilogTracker.inferEpilogOffsets(RetAddrs);
178 
179   // TODO: decode other sections.
180 }
181 
182 bool ProfiledBinary::inlineContextEqual(uint64_t Address1,
183                                         uint64_t Address2) const {
184   uint64_t Offset1 = virtualAddrToOffset(Address1);
185   uint64_t Offset2 = virtualAddrToOffset(Address2);
186   const SampleContextFrameVector &Context1 = getFrameLocationStack(Offset1);
187   const SampleContextFrameVector &Context2 = getFrameLocationStack(Offset2);
188   if (Context1.size() != Context2.size())
189     return false;
190   if (Context1.empty())
191     return false;
192   // The leaf frame contains location within the leaf, and it
193   // needs to be remove that as it's not part of the calling context
194   return std::equal(Context1.begin(), Context1.begin() + Context1.size() - 1,
195                     Context2.begin(), Context2.begin() + Context2.size() - 1);
196 }
197 
198 SampleContextFrameVector
199 ProfiledBinary::getExpandedContext(const SmallVectorImpl<uint64_t> &Stack,
200                                    bool &WasLeafInlined) const {
201   SampleContextFrameVector ContextVec;
202   // Process from frame root to leaf
203   for (auto Address : Stack) {
204     uint64_t Offset = virtualAddrToOffset(Address);
205     const SampleContextFrameVector &ExpandedContext =
206         getFrameLocationStack(Offset);
207     // An instruction without a valid debug line will be ignored by sample
208     // processing
209     if (ExpandedContext.empty())
210       return SampleContextFrameVector();
211     // Set WasLeafInlined to the size of inlined frame count for the last
212     // address which is leaf
213     WasLeafInlined = (ExpandedContext.size() > 1);
214     ContextVec.append(ExpandedContext);
215   }
216 
217   // Compress the context string except for the leaf frame
218   auto LeafFrame = ContextVec.back();
219   LeafFrame.Callsite = LineLocation(0, 0);
220   ContextVec.pop_back();
221   assert(ContextVec.size() && "Context length should be at least 1");
222   CSProfileGenerator::compressRecursionContext(ContextVec);
223   CSProfileGenerator::trimContext(ContextVec);
224   ContextVec.push_back(LeafFrame);
225   return ContextVec;
226 }
227 
228 template <class ELFT>
229 void ProfiledBinary::setPreferredTextSegmentAddresses(const ELFFile<ELFT> &Obj, StringRef FileName) {
230   const auto &PhdrRange = unwrapOrError(Obj.program_headers(), FileName);
231   for (const typename ELFT::Phdr &Phdr : PhdrRange) {
232     if ((Phdr.p_type == ELF::PT_LOAD) && (Phdr.p_flags & ELF::PF_X)) {
233         // Segments will always be loaded at a page boundary.
234         PreferredTextSegmentAddresses.push_back(Phdr.p_vaddr & ~(Phdr.p_align - 1U));
235         TextSegmentOffsets.push_back(Phdr.p_offset & ~(Phdr.p_align - 1U));
236       }
237   }
238 
239   if (PreferredTextSegmentAddresses.empty())
240     exitWithError("no executable segment found", FileName);
241 }
242 
243 void ProfiledBinary::setPreferredTextSegmentAddresses(const ELFObjectFileBase *Obj) {
244   if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
245     setPreferredTextSegmentAddresses(ELFObj->getELFFile(), Obj->getFileName());
246   else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
247     setPreferredTextSegmentAddresses(ELFObj->getELFFile(), Obj->getFileName());
248   else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
249     setPreferredTextSegmentAddresses(ELFObj->getELFFile(), Obj->getFileName());
250   else if (const auto *ELFObj = cast<ELF64BEObjectFile>(Obj))
251     setPreferredTextSegmentAddresses(ELFObj->getELFFile(), Obj->getFileName());
252   else
253     llvm_unreachable("invalid ELF object format");
254 }
255 
256 void ProfiledBinary::decodePseudoProbe(const ELFObjectFileBase *Obj) {
257   StringRef FileName = Obj->getFileName();
258   for (section_iterator SI = Obj->section_begin(), SE = Obj->section_end();
259        SI != SE; ++SI) {
260     const SectionRef &Section = *SI;
261     StringRef SectionName = unwrapOrError(Section.getName(), FileName);
262 
263     if (SectionName == ".pseudo_probe_desc") {
264       StringRef Contents = unwrapOrError(Section.getContents(), FileName);
265       if (!ProbeDecoder.buildGUID2FuncDescMap(
266               reinterpret_cast<const uint8_t *>(Contents.data()),
267               Contents.size()))
268         exitWithError("Pseudo Probe decoder fail in .pseudo_probe_desc section");
269     } else if (SectionName == ".pseudo_probe") {
270       StringRef Contents = unwrapOrError(Section.getContents(), FileName);
271       if (!ProbeDecoder.buildAddress2ProbeMap(
272               reinterpret_cast<const uint8_t *>(Contents.data()),
273               Contents.size()))
274         exitWithError("Pseudo Probe decoder fail in .pseudo_probe section");
275       // set UsePseudoProbes flag, used for PerfReader
276       UsePseudoProbes = true;
277     }
278   }
279 
280   if (ShowPseudoProbe)
281     ProbeDecoder.printGUID2FuncDescMap(outs());
282 }
283 
284 bool ProfiledBinary::dissassembleSymbol(std::size_t SI, ArrayRef<uint8_t> Bytes,
285                                         SectionSymbolsTy &Symbols,
286                                         const SectionRef &Section) {
287   std::size_t SE = Symbols.size();
288   uint64_t SectionOffset = Section.getAddress() - getPreferredBaseAddress();
289   uint64_t SectSize = Section.getSize();
290   uint64_t StartOffset = Symbols[SI].Addr - getPreferredBaseAddress();
291   uint64_t EndOffset = (SI + 1 < SE)
292                            ? Symbols[SI + 1].Addr - getPreferredBaseAddress()
293                            : SectionOffset + SectSize;
294   if (StartOffset >= EndOffset)
295     return true;
296 
297   StringRef SymbolName =
298       ShowCanonicalFnName
299           ? FunctionSamples::getCanonicalFnName(Symbols[SI].Name)
300           : Symbols[SI].Name;
301   if (ShowDisassemblyOnly)
302     outs() << '<' << SymbolName << ">:\n";
303 
304   auto WarnInvalidInsts = [](uint64_t Start, uint64_t End) {
305     WithColor::warning() << "Invalid instructions at "
306                          << format("%8" PRIx64, Start) << " - "
307                          << format("%8" PRIx64, End) << "\n";
308   };
309 
310   uint64_t Offset = StartOffset;
311   // Size of a consecutive invalid instruction range starting from Offset -1
312   // backwards.
313   uint64_t InvalidInstLength = 0;
314   while (Offset < EndOffset) {
315     MCInst Inst;
316     uint64_t Size;
317     // Disassemble an instruction.
318     bool Disassembled =
319         DisAsm->getInstruction(Inst, Size, Bytes.slice(Offset - SectionOffset),
320                                Offset + getPreferredBaseAddress(), nulls());
321     if (Size == 0)
322       Size = 1;
323 
324     if (ShowDisassemblyOnly) {
325       if (ShowPseudoProbe) {
326         ProbeDecoder.printProbeForAddress(outs(),
327                                           Offset + getPreferredBaseAddress());
328       }
329       outs() << format("%8" PRIx64 ":", Offset + getPreferredBaseAddress());
330       size_t Start = outs().tell();
331       if (Disassembled)
332         IPrinter->printInst(&Inst, Offset + Size, "", *STI.get(), outs());
333       else
334         outs() << "\t<unknown>";
335       if (ShowSourceLocations) {
336         unsigned Cur = outs().tell() - Start;
337         if (Cur < 40)
338           outs().indent(40 - Cur);
339         InstructionPointer IP(this, Offset);
340         outs() << getReversedLocWithContext(
341             symbolize(IP, ShowCanonicalFnName, ShowPseudoProbe));
342       }
343       outs() << "\n";
344     }
345 
346     if (Disassembled) {
347       const MCInstrDesc &MCDesc = MII->get(Inst.getOpcode());
348       // Populate a vector of the symbolized callsite at this location
349       // We don't need symbolized info for probe-based profile, just use an
350       // empty stack as an entry to indicate a valid binary offset
351       SampleContextFrameVector SymbolizedCallStack;
352       if (!UsePseudoProbes || TrackFuncContextSize) {
353         InstructionPointer IP(this, Offset);
354         // TODO: reallocation of Offset2LocStackMap will lead to dangling
355         // strings We need ProfiledBinary to owned these string.
356         Offset2LocStackMap[Offset] = symbolize(IP, true, UsePseudoProbes);
357         SampleContextFrameVector &SymbolizedCallStack =
358             Offset2LocStackMap[Offset];
359         // Record instruction size for the corresponding context
360         if (TrackFuncContextSize && !SymbolizedCallStack.empty())
361           FuncSizeTracker.addInstructionForContext(Offset2LocStackMap[Offset],
362                                                    Size);
363       } else {
364         Offset2LocStackMap[Offset] = SampleContextFrameVector();
365       }
366 
367       // Populate address maps.
368       CodeAddrs.push_back(Offset);
369       if (MCDesc.isCall())
370         CallAddrs.insert(Offset);
371       else if (MCDesc.isReturn())
372         RetAddrs.insert(Offset);
373 
374       if (InvalidInstLength) {
375         WarnInvalidInsts(Offset - InvalidInstLength, Offset - 1);
376         InvalidInstLength = 0;
377       }
378     } else {
379       InvalidInstLength += Size;
380     }
381 
382     Offset += Size;
383   }
384 
385   if (InvalidInstLength)
386     WarnInvalidInsts(Offset - InvalidInstLength, Offset - 1);
387 
388   if (ShowDisassemblyOnly)
389     outs() << "\n";
390 
391   FuncStartAddrMap[StartOffset] = Symbols[SI].Name.str();
392   return true;
393 }
394 
395 void ProfiledBinary::setUpDisassembler(const ELFObjectFileBase *Obj) {
396   const Target *TheTarget = getTarget(Obj);
397   std::string TripleName = TheTriple.getTriple();
398   StringRef FileName = Obj->getFileName();
399 
400   MRI.reset(TheTarget->createMCRegInfo(TripleName));
401   if (!MRI)
402     exitWithError("no register info for target " + TripleName, FileName);
403 
404   MCTargetOptions MCOptions;
405   AsmInfo.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
406   if (!AsmInfo)
407     exitWithError("no assembly info for target " + TripleName, FileName);
408 
409   SubtargetFeatures Features = Obj->getFeatures();
410   STI.reset(
411       TheTarget->createMCSubtargetInfo(TripleName, "", Features.getString()));
412   if (!STI)
413     exitWithError("no subtarget info for target " + TripleName, FileName);
414 
415   MII.reset(TheTarget->createMCInstrInfo());
416   if (!MII)
417     exitWithError("no instruction info for target " + TripleName, FileName);
418 
419   MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
420   std::unique_ptr<MCObjectFileInfo> MOFI(
421       TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false));
422   Ctx.setObjectFileInfo(MOFI.get());
423   DisAsm.reset(TheTarget->createMCDisassembler(*STI, Ctx));
424   if (!DisAsm)
425     exitWithError("no disassembler for target " + TripleName, FileName);
426 
427   MIA.reset(TheTarget->createMCInstrAnalysis(MII.get()));
428 
429   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
430   IPrinter.reset(TheTarget->createMCInstPrinter(
431       Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI));
432   IPrinter->setPrintBranchImmAsAddress(true);
433 }
434 
435 void ProfiledBinary::disassemble(const ELFObjectFileBase *Obj) {
436   // Set up disassembler and related components.
437   setUpDisassembler(Obj);
438 
439   // Create a mapping from virtual address to symbol name. The symbols in text
440   // sections are the candidates to dissassemble.
441   std::map<SectionRef, SectionSymbolsTy> AllSymbols;
442   StringRef FileName = Obj->getFileName();
443   for (const SymbolRef &Symbol : Obj->symbols()) {
444     const uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName);
445     const StringRef Name = unwrapOrError(Symbol.getName(), FileName);
446     section_iterator SecI = unwrapOrError(Symbol.getSection(), FileName);
447     if (SecI != Obj->section_end())
448       AllSymbols[*SecI].push_back(SymbolInfoTy(Addr, Name, ELF::STT_NOTYPE));
449   }
450 
451   // Sort all the symbols. Use a stable sort to stabilize the output.
452   for (std::pair<const SectionRef, SectionSymbolsTy> &SecSyms : AllSymbols)
453     stable_sort(SecSyms.second);
454 
455   if (ShowDisassemblyOnly)
456     outs() << "\nDisassembly of " << FileName << ":\n";
457 
458   // Dissassemble a text section.
459   for (section_iterator SI = Obj->section_begin(), SE = Obj->section_end();
460        SI != SE; ++SI) {
461     const SectionRef &Section = *SI;
462     if (!Section.isText())
463       continue;
464 
465     uint64_t ImageLoadAddr = getPreferredBaseAddress();
466     uint64_t SectionOffset = Section.getAddress() - ImageLoadAddr;
467     uint64_t SectSize = Section.getSize();
468     if (!SectSize)
469       continue;
470 
471     // Register the text section.
472     TextSections.insert({SectionOffset, SectSize});
473 
474     if (ShowDisassemblyOnly) {
475       StringRef SectionName = unwrapOrError(Section.getName(), FileName);
476       outs() << "\nDisassembly of section " << SectionName;
477       outs() << " [" << format("0x%" PRIx64, Section.getAddress()) << ", "
478              << format("0x%" PRIx64, Section.getAddress() + SectSize)
479              << "]:\n\n";
480     }
481 
482     // Get the section data.
483     ArrayRef<uint8_t> Bytes =
484         arrayRefFromStringRef(unwrapOrError(Section.getContents(), FileName));
485 
486     // Get the list of all the symbols in this section.
487     SectionSymbolsTy &Symbols = AllSymbols[Section];
488 
489     // Disassemble symbol by symbol.
490     for (std::size_t SI = 0, SE = Symbols.size(); SI != SE; ++SI) {
491       if (!dissassembleSymbol(SI, Bytes, Symbols, Section))
492         exitWithError("disassembling error", FileName);
493     }
494   }
495 }
496 
497 void ProfiledBinary::setupSymbolizer() {
498   symbolize::LLVMSymbolizer::Options SymbolizerOpts;
499   SymbolizerOpts.PrintFunctions =
500       DILineInfoSpecifier::FunctionNameKind::LinkageName;
501   SymbolizerOpts.Demangle = false;
502   SymbolizerOpts.DefaultArch = TheTriple.getArchName().str();
503   SymbolizerOpts.UseSymbolTable = false;
504   SymbolizerOpts.RelativeAddresses = false;
505   Symbolizer = std::make_unique<symbolize::LLVMSymbolizer>(SymbolizerOpts);
506 }
507 
508 SampleContextFrameVector ProfiledBinary::symbolize(const InstructionPointer &IP,
509                                                    bool UseCanonicalFnName,
510                                                    bool UseProbeDiscriminator) {
511   assert(this == IP.Binary &&
512          "Binary should only symbolize its own instruction");
513   auto Addr = object::SectionedAddress{IP.Offset + getPreferredBaseAddress(),
514                                        object::SectionedAddress::UndefSection};
515   DIInliningInfo InlineStack =
516       unwrapOrError(Symbolizer->symbolizeInlinedCode(Path, Addr), getName());
517 
518   SampleContextFrameVector CallStack;
519   for (int32_t I = InlineStack.getNumberOfFrames() - 1; I >= 0; I--) {
520     const auto &CallerFrame = InlineStack.getFrame(I);
521     if (CallerFrame.FunctionName == "<invalid>")
522       break;
523 
524     StringRef FunctionName(CallerFrame.FunctionName);
525     if (UseCanonicalFnName)
526       FunctionName = FunctionSamples::getCanonicalFnName(FunctionName);
527 
528     uint32_t Discriminator = CallerFrame.Discriminator;
529     uint32_t LineOffset = CallerFrame.Line - CallerFrame.StartLine;
530     if (UseProbeDiscriminator) {
531       LineOffset =
532           PseudoProbeDwarfDiscriminator::extractProbeIndex(Discriminator);
533       Discriminator = 0;
534     } else {
535       Discriminator = DILocation::getBaseDiscriminatorFromDiscriminator(
536           CallerFrame.Discriminator,
537           /* IsFSDiscriminator */ false);
538     }
539 
540     LineLocation Line(LineOffset, Discriminator);
541     auto It = NameStrings.insert(FunctionName.str());
542     CallStack.emplace_back(*It.first, Line);
543   }
544 
545   return CallStack;
546 }
547 
548 InstructionPointer::InstructionPointer(const ProfiledBinary *Binary,
549                                        uint64_t Address, bool RoundToNext)
550     : Binary(Binary), Address(Address) {
551   Index = Binary->getIndexForAddr(Address);
552   if (RoundToNext) {
553     // we might get address which is not the code
554     // it should round to the next valid address
555     this->Address = Binary->getAddressforIndex(Index);
556   }
557 }
558 
559 void InstructionPointer::advance() {
560   Index++;
561   Address = Binary->getAddressforIndex(Index);
562 }
563 
564 void InstructionPointer::backward() {
565   Index--;
566   Address = Binary->getAddressforIndex(Index);
567 }
568 
569 void InstructionPointer::update(uint64_t Addr) {
570   Address = Addr;
571   Index = Binary->getIndexForAddr(Address);
572 }
573 
574 } // end namespace sampleprof
575 } // end namespace llvm
576