21#define DEBUG_TYPE "BinaryReader"
26 std::string SymbolName(
Name);
27 if (SymbolNames.find(SymbolName) == SymbolNames.end()) {
29 std::piecewise_construct, std::forward_as_tuple(SymbolName),
30 std::forward_as_tuple(
Function, 0, SectionIndex,
false));
33 SymbolNames[SymbolName].Scope =
Function;
35 SymbolNames[SymbolName].SectionIndex = SectionIndex;
38 if (
Function && SymbolNames[SymbolName].IsComdat)
46 std::string SymbolName(
Name);
47 if (SymbolNames.find(SymbolName) == SymbolNames.end())
49 std::piecewise_construct, std::forward_as_tuple(SymbolName),
50 std::forward_as_tuple(
nullptr,
Address, SectionIndex, IsComdat));
53 SymbolNames[SymbolName].Address =
Address;
66 std::string SymbolName(
Name);
68 if (SymbolName.empty() || (SymbolNames.find(SymbolName) == SymbolNames.end()))
75 SymbolNames[SymbolName].Scope =
Function;
76 SectionIndex = SymbolNames[SymbolName].SectionIndex;
81 if (SymbolNames[SymbolName].IsComdat)
90 LVSymbolNames::iterator Iter = SymbolNames.find(std::string(
Name));
91 return Iter != SymbolNames.end() ? Iter->second :
Empty;
94 LVSymbolNames::iterator Iter = SymbolNames.find(std::string(
Name));
95 return Iter != SymbolNames.end() ? Iter->second.Address : 0;
98 LVSymbolNames::iterator Iter = SymbolNames.find(std::string(
Name));
99 return Iter != SymbolNames.end() ? Iter->second.SectionIndex
103 LVSymbolNames::iterator Iter = SymbolNames.find(std::string(
Name));
104 return Iter != SymbolNames.end() ? Iter->second.IsComdat :
false;
108 OS <<
"Symbol Table\n";
109 for (LVSymbolNames::reference Entry : SymbolNames) {
111 LVScope *Scope = SymbolName.Scope;
113 OS <<
"Index: " <<
hexValue(SymbolName.SectionIndex, 5)
114 <<
" Comdat: " << (SymbolName.IsComdat ?
"Y" :
"N")
116 <<
" Address: " <<
hexValue(SymbolName.Address)
117 <<
" Name: " << Entry.first <<
"\n";
149 if (!Section.isText() || Section.isVirtual() || !Section.getSize())
154 Sections.emplace(Section.getIndex(), Section);
155 addSectionAddress(Section);
159 if (!SectionNameOrErr) {
163 if ((*SectionNameOrErr).equals(
".text") ||
164 (*SectionNameOrErr).equals(
".code"))
172 dbgs() <<
"\nSections Information:\n";
173 for (LVSections::reference Entry : Sections) {
177 if (!SectionNameOrErr)
180 <<
" Name: " << *SectionNameOrErr <<
"\n"
181 <<
"Size: " <<
hexValue(Section.getSize()) <<
"\n"
182 <<
"VirtualAddress: " <<
hexValue(VirtualAddress) <<
"\n"
183 <<
"SectionAddress: " <<
hexValue(Section.getAddress()) <<
"\n";
185 dbgs() <<
"\nObject Section Information:\n";
186 for (LVSectionAddresses::const_reference Entry : SectionAddresses)
188 <<
hexValue(Entry.first + Entry.second.getSize())
189 <<
"] Size: " <<
hexValue(Entry.second.getSize()) <<
"\n";
196 ImageBaseAddress = ImageBase.
get();
199 dbgs() <<
"ImageBaseAddress: " <<
hexValue(ImageBaseAddress) <<
"\n";
205 if (!Section.isText() || Section.isVirtual() || !Section.getSize())
214 Sections.emplace(Section.getIndex() + 1, Section);
215 addSectionAddress(Section);
222 dbgs() <<
"\nSections Information:\n";
223 for (LVSections::reference Entry : Sections) {
228 if (!SectionNameOrErr)
231 <<
" Name: " << *SectionNameOrErr <<
"\n"
232 <<
"Size: " <<
hexValue(Section.getSize()) <<
"\n"
233 <<
"VirtualAddress: " <<
hexValue(VirtualAddress) <<
"\n"
234 <<
"SectionAddress: " <<
hexValue(Section.getAddress()) <<
"\n"
240 dbgs() <<
"\nObject Section Information:\n";
241 for (LVSectionAddresses::const_reference Entry : SectionAddresses)
243 <<
hexValue(Entry.first + Entry.second.getSize())
244 <<
"] Size: " <<
hexValue(Entry.second.getSize()) <<
"\n";
250 std::string TargetLookupError;
260 "no register info for target " + TheTriple);
261 MRI.reset(RegisterInfo);
268 "no assembly info for target " + TheTriple);
277 "no subtarget info for target " + TheTriple);
278 STI.reset(SubtargetInfo);
282 if (!InstructionInfo)
284 "no instruction info for target " + TheTriple);
285 MII.reset(InstructionInfo);
287 MC = std::make_unique<MCContext>(
Triple(TheTriple),
MAI.get(),
MRI.get(),
294 "no disassembler for target " + TheTriple);
299 if (!InstructionPrinter)
301 "no target assembly language printer for target " +
303 MIP.reset(InstructionPrinter);
316 LVSections::iterator Iter = Sections.find(SectionIndex);
317 if (Iter == Sections.end()) {
319 "invalid section index for: '%s'",
320 Scope->getName().str().c_str());
323 return std::make_pair(Section.getAddress(), Section);
327 LVSectionAddresses::const_iterator Iter =
328 SectionAddresses.upper_bound(
Address);
329 if (Iter == SectionAddresses.begin())
331 "invalid section address for: '%s'",
332 Scope->getName().str().c_str());
335 Iter = SectionAddresses.lower_bound(
Address);
336 if (Iter != SectionAddresses.begin())
338 return std::make_pair(Iter->first, Iter->second);
351 ScopesWithRanges->
addEntry(Scope, LowerAddress, UpperAddress);
356 LVSectionRanges::iterator IterSection = SectionRanges.find(SectionIndex);
357 if (IterSection == SectionRanges.end())
359 SectionRanges.emplace(SectionIndex, std::make_unique<LVRange>()).first;
368 assert(Scope &&
"Scope is null.");
371 if (Scope->getIsDiscarded())
379 dbgs() <<
"\nPublic Name instructions: '" << Scope->getName() <<
"' / '"
380 << Scope->getLinkageName() <<
"'\n"
381 <<
"DIE Offset: " <<
hexValue(Scope->getOffset()) <<
" Range: ["
388 return SectionOrErr.takeError();
390 uint64_t SectionAddress = (*SectionOrErr).first;
393 if (!SectionContentsOrErr)
394 return SectionOrErr.takeError();
401 <<
", Section Size: " <<
hexValue(Section.getSize()) <<
"\n";
403 Size = std::min(
Size + 1, Section.getSize());
412 if (!SectionNameOrErr)
415 dbgs() <<
"Section Index: " <<
hexValue(Section.getIndex()) <<
" ["
418 <<
"] Name: '" << *SectionNameOrErr <<
"'\n"
425 auto InstructionsSP = std::make_unique<LVLines>();
427 DiscoveredLines.emplace_back(std::move(InstructionsSP));
429 while (Begin <
End) {
440 if (BytesConsumed == 0)
453 std::string BufferCodes;
477 Begin += BytesConsumed;
483 <<
" Scope DIE: " <<
hexValue(Scope->getOffset()) <<
"\n"
484 <<
"Address: " <<
hexValue(FirstAddress)
485 <<
format(
" - Collected instructions lines: %d\n",
494 ScopeInstructions.add(SectionIndex, Scope, &
Instructions);
495 AssemblerMappings.add(SectionIndex, FirstAddress, Scope);
502 if (!
options().getPrintInstructions())
513 if (!
options().getPrintInstructions())
518 dbgs() <<
"\nPublic Names (Scope):\n";
519 for (LVPublicNames::const_reference
Name :
CompileUnit->getPublicNames()) {
525 <<
"DIE Offset: " <<
hexValue(Scope->getOffset()) <<
" Range: ["
527 <<
"Name: '" << Scope->getName() <<
"' / '"
528 << Scope->getLinkageName() <<
"'\n";
534 for (LVPublicNames::const_reference
Name :
CompileUnit->getPublicNames()) {
540 if (!Scope->getLinkageNameIndex())
541 Scope->setLinkageName(Scope->getName());
558 assert(DebugLines &&
"DebugLines is null.");
562 if (DebugLines->
empty() && !
options().getPrintInstructions())
573 dbgs() <<
format(
"\nProcess debug lines: %d\n", DebugLines->
size());
576 <<
", (" <<
Line->getLineNumber() <<
")"
577 << ((
Index % PerLine) ?
" " :
"\n");
580 dbgs() << ((
Index % PerLine) ?
"\n" :
"");
583 bool TraverseLines =
true;
585 while (TraverseLines && Iter != DebugLines->
end()) {
586 uint64_t DebugAddress = (*Iter)->getAddress();
593 Scope = AssemblerMappings.find(SectionIndex, DebugAddress);
602 LVLines *
Lines = ScopeInstructions.find(SectionIndex, Scope);
604 InstructionLines = std::move(*
Lines);
609 <<
" Scope DIE: " <<
hexValue(Scope->getOffset()) <<
"\n"
610 <<
format(
"Process instruction lines: %d\n",
611 InstructionLines.
size());
619 if (InstructionLines.
empty()) {
624 for (
LVLine *InstructionLine : InstructionLines) {
625 uint64_t InstructionAddress = InstructionLine->getAddress();
627 dbgs() <<
"Instruction address: " <<
hexValue(InstructionAddress)
631 while (Iter != DebugLines->
end()) {
632 DebugAddress = (*Iter)->getAddress();
634 bool IsDebug = (*Iter)->getIsLineDebug();
635 dbgs() <<
"Line " << (IsDebug ?
"dbg:" :
"ins:") <<
" ["
638 dbgs() <<
format(
" %d", (*Iter)->getLineNumber());
642 if (InstructionAddress < DebugAddress) {
644 dbgs() <<
"Inserted instruction address: "
645 <<
hexValue(InstructionAddress) <<
" before line: "
646 <<
format(
"%d", (*Iter)->getLineNumber()) <<
" ["
649 Iter = DebugLines->
insert(Iter, InstructionLine);
657 if (Iter == DebugLines->
end()) {
660 TraverseLines =
false;
675 << ((
Line->getIsLineDebug())
676 ?
Line->lineNumberAsStringStripped(
true)
685 if (DebugLines->
empty()) {
694 <<
" Scope DIE: " <<
hexValue(Scope->getOffset()) <<
"\n"
695 <<
format(
"Instruction lines: %d\n",
Lines->size());
702 if (Scope->getIsArtificial()) {
705 Scope->addElement(
Line);
728 << ((
Line->getIsLineDebug())
729 ?
Line->lineNumberAsStringStripped(
true)
736 Scope->addElement(
Line);
739 if (
options().getWarningLines() &&
Line->getIsLineDebug() &&
740 !
Line->getLineNumber())
750 if (
Line->getIsLineDebug())
762 assert(DebugLines &&
"DebugLines is null.");
763 if (DebugLines->
empty() && !ScopeInstructions.findMap(SectionIndex))
774 std::vector<size_t> AddressZero;
776 std::find_if(std::begin(*DebugLines), std::end(*DebugLines),
778 while (It != std::end(*DebugLines)) {
779 AddressZero.emplace_back(std::distance(std::begin(*DebugLines), It));
780 It = std::find_if(std::next(It), std::end(*DebugLines),
787 if (AddressZero.empty()) {
796 using LVBucket = std::tuple<size_t, size_t, LVAddress, bool>;
797 std::vector<LVBucket> Buckets;
804 Begin = AddressZero[
Index];
807 Buckets.emplace_back(Begin,
End,
Address,
false);
812 Begin = AddressZero[
Index];
815 Buckets.emplace_back(Begin,
End,
Address,
false);
819 dbgs() <<
"\nDebug Lines buckets: " << Buckets.size() <<
"\n";
820 for (LVBucket &Bucket : Buckets) {
823 <<
"Address: " <<
hexValue(std::get<2>(Bucket)) <<
"\n";
831 for (LVSections::reference Entry : Sections) {
837 <<
" , Section Size: " <<
hexValue(Section.getSize())
838 <<
" , Section Address: " <<
hexValue(Section.getAddress())
842 for (LVBucket &Bucket : Buckets) {
843 if (std::get<3>(Bucket))
846 if (
Size == std::get<2>(Bucket)) {
851 DebugLines->
begin() + std::get<1>(Bucket) + 1;
853 Group.push_back(*Iter);
855 std::get<3>(Bucket) =
true;
867 std::function<void(
LVScope * Parent)> FindInlinedScopes =
871 LVInlineeLine::iterator Iter = CUInlineeLines.find(Scope);
872 if (Iter != CUInlineeLines.end())
874 FindInlinedScopes(Scope);
880 for (LVInlineeLine::iterator InlineeIter : InlineeIters) {
881 LVScope *Scope = InlineeIter->first;
887 dbgs() <<
"Inlined lines for: " << Scope->getName() <<
"\n";
890 <<
Line->getLineNumber() <<
"\n";
894 <<
Line->getLineNumber() <<
")\n";
906 return Item->getAddress() == InlineeStart;
911 Scope->setCallLineNumber((*Iter)->getLineNumber());
915 (*Iter)->setLineNumber((*
InlineeLines->begin())->getLineNumber());
923 CUInlineeLines.erase(InlineeIter);
931 <<
Line->getLineNumber() <<
")\n";
937 OS <<
"LVBinaryReader\n";
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Annotations lets you mark points and ranges inside source code, for tests:
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Stores all information relating to a compile unit, be it in its original instance in the object file ...
Represents either an error or a value T.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
This class is intended to be used as a base class for asm properties and features specific to the tar...
unsigned getAssemblerDialect() const
Superclass for all disassemblers.
DecodeStatus
Ternary decode status.
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
void setPrintImmHex(bool Value)
Instances of this class represent a single low-level machine instruction.
Interface to description of machine instruction set.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Generic base class for all target subtargets.
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
Target - Wrapper for Target specific information.
MCSubtargetInfo * createMCSubtargetInfo(StringRef TheTriple, StringRef CPU, StringRef Features) const
createMCSubtargetInfo - Create a MCSubtargetInfo implementation.
MCRegisterInfo * createMCRegInfo(StringRef TT) const
createMCRegInfo - Create a MCRegisterInfo implementation.
MCDisassembler * createMCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) const
MCAsmInfo * createMCAsmInfo(const MCRegisterInfo &MRI, StringRef TheTriple, const MCTargetOptions &Options) const
createMCAsmInfo - Create a MCAsmInfo implementation for the specified target triple.
MCInstPrinter * createMCInstPrinter(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI) const
MCInstrInfo * createMCInstrInfo() const
createMCInstrInfo - Create a MCInstrInfo implementation.
Triple - Helper class for working with autoconf configuration names.
StringRef getName() const
Return a constant reference to the value's name.
const LVSymbolTableEntry & getSymbolTableEntry(StringRef Name)
LVSectionIndex updateSymbolTable(LVScope *Function)
Expected< std::pair< LVSectionIndex, object::SectionRef > > getSection(LVScope *Scope, LVAddress Address, LVSectionIndex SectionIndex)
std::unique_ptr< MCContext > MC
void includeInlineeLines(LVSectionIndex SectionIndex, LVScope *Function)
std::unique_ptr< const MCInstrInfo > MII
LVAddress getSymbolTableAddress(StringRef Name)
void print(raw_ostream &OS) const
std::unique_ptr< const MCSubtargetInfo > STI
void addToSymbolTable(StringRef Name, LVScope *Function, LVSectionIndex SectionIndex=0)
virtual void mapRangeAddress(const object::ObjectFile &Obj)
void processLines(LVLines *DebugLines, LVSectionIndex SectionIndex)
void mapVirtualAddress(const object::ObjectFile &Obj)
std::unique_ptr< const MCAsmInfo > MAI
LVSectionIndex getSymbolTableIndex(StringRef Name)
bool getSymbolTableIsComdat(StringRef Name)
std::unique_ptr< const MCRegisterInfo > MRI
std::unique_ptr< const MCDisassembler > MD
LVRange * getSectionRanges(LVSectionIndex SectionIndex)
Error loadGenericTargetInfo(StringRef TheTriple, StringRef TheFeatures)
void addSectionRange(LVSectionIndex SectionIndex, LVScope *Scope)
Error createInstructions()
std::unique_ptr< MCInstPrinter > MIP
void resolvePatternMatch(LVLine *Line)
LVScope * getEntry(LVAddress Address) const
void addEntry(LVScope *Scope, LVAddress LowerAddress, LVAddress UpperAddress)
LVSectionIndex getDotTextSectionIndex() const
LVScopeCompileUnit * CompileUnit
LVSectionIndex DotTextSectionIndex
const LVScopes * getScopes() const
LVSectionIndex getIndex(StringRef Name)
bool getIsComdat(StringRef Name)
void print(raw_ostream &OS)
LVAddress getAddress(StringRef Name)
void add(StringRef Name, LVScope *Function, LVSectionIndex SectionIndex=0)
LVSectionIndex update(LVScope *Function)
const LVSymbolTableEntry & getEntry(StringRef Name)
uint64_t getImageBase() const
const coff_section * getCOFFSection(const SectionRef &Section) const
This class is the base class for all object file types.
section_iterator_range sections() const
This is a value type class that represents a single section in the list of sections in the object fil...
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
A raw_ostream that writes to an SmallVector or SmallString.
FormattedNumber hexValue(uint64_t N, unsigned Width=HEX_WIDTH, bool Upper=false)
std::pair< LVAddress, uint64_t > LVNameInfo
constexpr LVSectionIndex UndefinedSectionIndex
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
FormattedNumber format_decimal(int64_t N, unsigned Width)
format_decimal - Output N as a right justified, fixed-width decimal.
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
detail::AlignAdapter< T > fmt_align(T &&Item, AlignStyle Where, size_t Amount, char Fill=' ')
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
void consumeError(Error Err)
Consume a Error without doing anything.
FormattedBytes format_bytes(ArrayRef< uint8_t > Bytes, std::optional< uint64_t > FirstByteOffset=std::nullopt, uint32_t NumPerLine=16, uint8_t ByteGroupSize=4, uint32_t IndentLevel=0, bool Upper=false)
static const Target * lookupTarget(StringRef Triple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
support::ulittle32_t PointerToRawData
support::ulittle32_t Characteristics
support::ulittle32_t SizeOfRawData
support::ulittle32_t VirtualAddress