14f06d46fSCarlos Alberto Enciso //===-- LVBinaryReader.cpp ------------------------------------------------===// 24f06d46fSCarlos Alberto Enciso // 34f06d46fSCarlos Alberto Enciso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 44f06d46fSCarlos Alberto Enciso // See https://llvm.org/LICENSE.txt for license information. 54f06d46fSCarlos Alberto Enciso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 64f06d46fSCarlos Alberto Enciso // 74f06d46fSCarlos Alberto Enciso //===----------------------------------------------------------------------===// 84f06d46fSCarlos Alberto Enciso // 94f06d46fSCarlos Alberto Enciso // This implements the LVBinaryReader class. 104f06d46fSCarlos Alberto Enciso // 114f06d46fSCarlos Alberto Enciso //===----------------------------------------------------------------------===// 124f06d46fSCarlos Alberto Enciso 134f06d46fSCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h" 144f06d46fSCarlos Alberto Enciso #include "llvm/Support/Errc.h" 154f06d46fSCarlos Alberto Enciso #include "llvm/Support/FormatAdapters.h" 164f06d46fSCarlos Alberto Enciso #include "llvm/Support/FormatVariadic.h" 174f06d46fSCarlos Alberto Enciso 184f06d46fSCarlos Alberto Enciso using namespace llvm; 194f06d46fSCarlos Alberto Enciso using namespace llvm::logicalview; 204f06d46fSCarlos Alberto Enciso 214f06d46fSCarlos Alberto Enciso #define DEBUG_TYPE "BinaryReader" 224f06d46fSCarlos Alberto Enciso 234f06d46fSCarlos Alberto Enciso // Function names extracted from the object symbol table. 244f06d46fSCarlos Alberto Enciso void LVSymbolTable::add(StringRef Name, LVScope *Function, 254f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex) { 264f06d46fSCarlos Alberto Enciso std::string SymbolName(Name); 274f06d46fSCarlos Alberto Enciso if (SymbolNames.find(SymbolName) == SymbolNames.end()) { 284f06d46fSCarlos Alberto Enciso SymbolNames.emplace( 294f06d46fSCarlos Alberto Enciso std::piecewise_construct, std::forward_as_tuple(SymbolName), 304f06d46fSCarlos Alberto Enciso std::forward_as_tuple(Function, 0, SectionIndex, false)); 314f06d46fSCarlos Alberto Enciso } else { 324f06d46fSCarlos Alberto Enciso // Update a recorded entry with its logical scope and section index. 334f06d46fSCarlos Alberto Enciso SymbolNames[SymbolName].Scope = Function; 344f06d46fSCarlos Alberto Enciso if (SectionIndex) 354f06d46fSCarlos Alberto Enciso SymbolNames[SymbolName].SectionIndex = SectionIndex; 364f06d46fSCarlos Alberto Enciso } 374f06d46fSCarlos Alberto Enciso 384f06d46fSCarlos Alberto Enciso if (Function && SymbolNames[SymbolName].IsComdat) 394f06d46fSCarlos Alberto Enciso Function->setIsComdat(); 404f06d46fSCarlos Alberto Enciso 414f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ print(dbgs()); }); 424f06d46fSCarlos Alberto Enciso } 434f06d46fSCarlos Alberto Enciso 444f06d46fSCarlos Alberto Enciso void LVSymbolTable::add(StringRef Name, LVAddress Address, 454f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex, bool IsComdat) { 464f06d46fSCarlos Alberto Enciso std::string SymbolName(Name); 474f06d46fSCarlos Alberto Enciso if (SymbolNames.find(SymbolName) == SymbolNames.end()) 484f06d46fSCarlos Alberto Enciso SymbolNames.emplace( 494f06d46fSCarlos Alberto Enciso std::piecewise_construct, std::forward_as_tuple(SymbolName), 504f06d46fSCarlos Alberto Enciso std::forward_as_tuple(nullptr, Address, SectionIndex, IsComdat)); 514f06d46fSCarlos Alberto Enciso else 524f06d46fSCarlos Alberto Enciso // Update a recorded symbol name with its logical scope. 534f06d46fSCarlos Alberto Enciso SymbolNames[SymbolName].Address = Address; 544f06d46fSCarlos Alberto Enciso 554f06d46fSCarlos Alberto Enciso LVScope *Function = SymbolNames[SymbolName].Scope; 564f06d46fSCarlos Alberto Enciso if (Function && IsComdat) 574f06d46fSCarlos Alberto Enciso Function->setIsComdat(); 584f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ print(dbgs()); }); 594f06d46fSCarlos Alberto Enciso } 604f06d46fSCarlos Alberto Enciso 614f06d46fSCarlos Alberto Enciso LVSectionIndex LVSymbolTable::update(LVScope *Function) { 624f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex = getReader().getDotTextSectionIndex(); 634f06d46fSCarlos Alberto Enciso StringRef Name = Function->getLinkageName(); 644f06d46fSCarlos Alberto Enciso if (Name.empty()) 654f06d46fSCarlos Alberto Enciso Name = Function->getName(); 664f06d46fSCarlos Alberto Enciso std::string SymbolName(Name); 674f06d46fSCarlos Alberto Enciso 684f06d46fSCarlos Alberto Enciso if (SymbolName.empty() || (SymbolNames.find(SymbolName) == SymbolNames.end())) 694f06d46fSCarlos Alberto Enciso return SectionIndex; 704f06d46fSCarlos Alberto Enciso 714f06d46fSCarlos Alberto Enciso // Update a recorded entry with its logical scope, only if the scope has 724f06d46fSCarlos Alberto Enciso // ranges. That is the case when in DWARF there are 2 DIEs connected via 734f06d46fSCarlos Alberto Enciso // the DW_AT_specification. 744f06d46fSCarlos Alberto Enciso if (Function->getHasRanges()) { 754f06d46fSCarlos Alberto Enciso SymbolNames[SymbolName].Scope = Function; 764f06d46fSCarlos Alberto Enciso SectionIndex = SymbolNames[SymbolName].SectionIndex; 774f06d46fSCarlos Alberto Enciso } else { 784f06d46fSCarlos Alberto Enciso SectionIndex = UndefinedSectionIndex; 794f06d46fSCarlos Alberto Enciso } 804f06d46fSCarlos Alberto Enciso 814f06d46fSCarlos Alberto Enciso if (SymbolNames[SymbolName].IsComdat) 824f06d46fSCarlos Alberto Enciso Function->setIsComdat(); 834f06d46fSCarlos Alberto Enciso 844f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ print(dbgs()); }); 854f06d46fSCarlos Alberto Enciso return SectionIndex; 864f06d46fSCarlos Alberto Enciso } 874f06d46fSCarlos Alberto Enciso 884f06d46fSCarlos Alberto Enciso const LVSymbolTableEntry &LVSymbolTable::getEntry(StringRef Name) { 894f06d46fSCarlos Alberto Enciso static LVSymbolTableEntry Empty = LVSymbolTableEntry(); 90*5c9c281cSKazu Hirata LVSymbolNames::iterator Iter = SymbolNames.find(Name); 914f06d46fSCarlos Alberto Enciso return Iter != SymbolNames.end() ? Iter->second : Empty; 924f06d46fSCarlos Alberto Enciso } 934f06d46fSCarlos Alberto Enciso LVAddress LVSymbolTable::getAddress(StringRef Name) { 94*5c9c281cSKazu Hirata LVSymbolNames::iterator Iter = SymbolNames.find(Name); 954f06d46fSCarlos Alberto Enciso return Iter != SymbolNames.end() ? Iter->second.Address : 0; 964f06d46fSCarlos Alberto Enciso } 974f06d46fSCarlos Alberto Enciso LVSectionIndex LVSymbolTable::getIndex(StringRef Name) { 98*5c9c281cSKazu Hirata LVSymbolNames::iterator Iter = SymbolNames.find(Name); 994f06d46fSCarlos Alberto Enciso return Iter != SymbolNames.end() ? Iter->second.SectionIndex 1004f06d46fSCarlos Alberto Enciso : getReader().getDotTextSectionIndex(); 1014f06d46fSCarlos Alberto Enciso } 1024f06d46fSCarlos Alberto Enciso bool LVSymbolTable::getIsComdat(StringRef Name) { 103*5c9c281cSKazu Hirata LVSymbolNames::iterator Iter = SymbolNames.find(Name); 1044f06d46fSCarlos Alberto Enciso return Iter != SymbolNames.end() ? Iter->second.IsComdat : false; 1054f06d46fSCarlos Alberto Enciso } 1064f06d46fSCarlos Alberto Enciso 1074f06d46fSCarlos Alberto Enciso void LVSymbolTable::print(raw_ostream &OS) { 1084f06d46fSCarlos Alberto Enciso OS << "Symbol Table\n"; 1094f06d46fSCarlos Alberto Enciso for (LVSymbolNames::reference Entry : SymbolNames) { 1104f06d46fSCarlos Alberto Enciso LVSymbolTableEntry &SymbolName = Entry.second; 1114f06d46fSCarlos Alberto Enciso LVScope *Scope = SymbolName.Scope; 1124f06d46fSCarlos Alberto Enciso LVOffset Offset = Scope ? Scope->getOffset() : 0; 1134f06d46fSCarlos Alberto Enciso OS << "Index: " << hexValue(SymbolName.SectionIndex, 5) 1144f06d46fSCarlos Alberto Enciso << " Comdat: " << (SymbolName.IsComdat ? "Y" : "N") 1154f06d46fSCarlos Alberto Enciso << " Scope: " << hexValue(Offset) 1164f06d46fSCarlos Alberto Enciso << " Address: " << hexValue(SymbolName.Address) 1174f06d46fSCarlos Alberto Enciso << " Name: " << Entry.first << "\n"; 1184f06d46fSCarlos Alberto Enciso } 1194f06d46fSCarlos Alberto Enciso } 1204f06d46fSCarlos Alberto Enciso 1214f06d46fSCarlos Alberto Enciso void LVBinaryReader::addToSymbolTable(StringRef Name, LVScope *Function, 1224f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex) { 1234f06d46fSCarlos Alberto Enciso SymbolTable.add(Name, Function, SectionIndex); 1244f06d46fSCarlos Alberto Enciso } 1254f06d46fSCarlos Alberto Enciso void LVBinaryReader::addToSymbolTable(StringRef Name, LVAddress Address, 1264f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex, 1274f06d46fSCarlos Alberto Enciso bool IsComdat) { 1284f06d46fSCarlos Alberto Enciso SymbolTable.add(Name, Address, SectionIndex, IsComdat); 1294f06d46fSCarlos Alberto Enciso } 1304f06d46fSCarlos Alberto Enciso LVSectionIndex LVBinaryReader::updateSymbolTable(LVScope *Function) { 1314f06d46fSCarlos Alberto Enciso return SymbolTable.update(Function); 1324f06d46fSCarlos Alberto Enciso } 1334f06d46fSCarlos Alberto Enciso 1344f06d46fSCarlos Alberto Enciso const LVSymbolTableEntry &LVBinaryReader::getSymbolTableEntry(StringRef Name) { 1354f06d46fSCarlos Alberto Enciso return SymbolTable.getEntry(Name); 1364f06d46fSCarlos Alberto Enciso } 1374f06d46fSCarlos Alberto Enciso LVAddress LVBinaryReader::getSymbolTableAddress(StringRef Name) { 1384f06d46fSCarlos Alberto Enciso return SymbolTable.getAddress(Name); 1394f06d46fSCarlos Alberto Enciso } 1404f06d46fSCarlos Alberto Enciso LVSectionIndex LVBinaryReader::getSymbolTableIndex(StringRef Name) { 1414f06d46fSCarlos Alberto Enciso return SymbolTable.getIndex(Name); 1424f06d46fSCarlos Alberto Enciso } 1434f06d46fSCarlos Alberto Enciso bool LVBinaryReader::getSymbolTableIsComdat(StringRef Name) { 1444f06d46fSCarlos Alberto Enciso return SymbolTable.getIsComdat(Name); 1454f06d46fSCarlos Alberto Enciso } 1464f06d46fSCarlos Alberto Enciso 1474f06d46fSCarlos Alberto Enciso void LVBinaryReader::mapVirtualAddress(const object::ObjectFile &Obj) { 1484f06d46fSCarlos Alberto Enciso for (const object::SectionRef &Section : Obj.sections()) { 149b19cfb91SCarlos Alberto Enciso LLVM_DEBUG({ 150b19cfb91SCarlos Alberto Enciso Expected<StringRef> SectionNameOrErr = Section.getName(); 151b19cfb91SCarlos Alberto Enciso StringRef Name; 152b19cfb91SCarlos Alberto Enciso if (!SectionNameOrErr) 153b19cfb91SCarlos Alberto Enciso consumeError(SectionNameOrErr.takeError()); 154b19cfb91SCarlos Alberto Enciso else 155b19cfb91SCarlos Alberto Enciso Name = *SectionNameOrErr; 156b19cfb91SCarlos Alberto Enciso dbgs() << "Index: " << format_decimal(Section.getIndex(), 3) << ", " 157b19cfb91SCarlos Alberto Enciso << "Address: " << hexValue(Section.getAddress()) << ", " 158b19cfb91SCarlos Alberto Enciso << "Size: " << hexValue(Section.getSize()) << ", " 159b19cfb91SCarlos Alberto Enciso << "Name: " << Name << "\n"; 160b19cfb91SCarlos Alberto Enciso dbgs() << "isCompressed: " << Section.isCompressed() << ", " 161b19cfb91SCarlos Alberto Enciso << "isText: " << Section.isText() << ", " 162b19cfb91SCarlos Alberto Enciso << "isData: " << Section.isData() << ", " 163b19cfb91SCarlos Alberto Enciso << "isBSS: " << Section.isBSS() << ", " 164b19cfb91SCarlos Alberto Enciso << "isVirtual: " << Section.isVirtual() << "\n"; 165b19cfb91SCarlos Alberto Enciso dbgs() << "isBitcode: " << Section.isBitcode() << ", " 166b19cfb91SCarlos Alberto Enciso << "isStripped: " << Section.isStripped() << ", " 167b19cfb91SCarlos Alberto Enciso << "isBerkeleyText: " << Section.isBerkeleyText() << ", " 168b19cfb91SCarlos Alberto Enciso << "isBerkeleyData: " << Section.isBerkeleyData() << ", " 169b19cfb91SCarlos Alberto Enciso << "isDebugSection: " << Section.isDebugSection() << "\n"; 170b19cfb91SCarlos Alberto Enciso dbgs() << "\n"; 171b19cfb91SCarlos Alberto Enciso }); 172b19cfb91SCarlos Alberto Enciso 1734f06d46fSCarlos Alberto Enciso if (!Section.isText() || Section.isVirtual() || !Section.getSize()) 1744f06d46fSCarlos Alberto Enciso continue; 1754f06d46fSCarlos Alberto Enciso 1764f06d46fSCarlos Alberto Enciso // Record section information required for symbol resolution. 1774f06d46fSCarlos Alberto Enciso // Note: The section index returned by 'getIndex()' is one based. 1784f06d46fSCarlos Alberto Enciso Sections.emplace(Section.getIndex(), Section); 1794f06d46fSCarlos Alberto Enciso addSectionAddress(Section); 1804f06d46fSCarlos Alberto Enciso 1814f06d46fSCarlos Alberto Enciso // Identify the ".text" section. 1824f06d46fSCarlos Alberto Enciso Expected<StringRef> SectionNameOrErr = Section.getName(); 1834f06d46fSCarlos Alberto Enciso if (!SectionNameOrErr) { 1844f06d46fSCarlos Alberto Enciso consumeError(SectionNameOrErr.takeError()); 1854f06d46fSCarlos Alberto Enciso continue; 1864f06d46fSCarlos Alberto Enciso } 187026a29e8SKazu Hirata if (*SectionNameOrErr == ".text" || *SectionNameOrErr == "CODE" || 188026a29e8SKazu Hirata *SectionNameOrErr == ".code") { 1894f06d46fSCarlos Alberto Enciso DotTextSectionIndex = Section.getIndex(); 190b19cfb91SCarlos Alberto Enciso // If the object is WebAssembly, update the address offset that 191b19cfb91SCarlos Alberto Enciso // will be added to DWARF DW_AT_* attributes. 192b19cfb91SCarlos Alberto Enciso if (Obj.isWasm()) 193b19cfb91SCarlos Alberto Enciso WasmCodeSectionOffset = Section.getAddress(); 194b19cfb91SCarlos Alberto Enciso } 1954f06d46fSCarlos Alberto Enciso } 1964f06d46fSCarlos Alberto Enciso 1974f06d46fSCarlos Alberto Enciso // Process the symbol table. 1984f06d46fSCarlos Alberto Enciso mapRangeAddress(Obj); 1994f06d46fSCarlos Alberto Enciso 2004f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 2014f06d46fSCarlos Alberto Enciso dbgs() << "\nSections Information:\n"; 2024f06d46fSCarlos Alberto Enciso for (LVSections::reference Entry : Sections) { 2034f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex = Entry.first; 2044f06d46fSCarlos Alberto Enciso const object::SectionRef Section = Entry.second; 2054f06d46fSCarlos Alberto Enciso Expected<StringRef> SectionNameOrErr = Section.getName(); 2064f06d46fSCarlos Alberto Enciso if (!SectionNameOrErr) 2074f06d46fSCarlos Alberto Enciso consumeError(SectionNameOrErr.takeError()); 2084f06d46fSCarlos Alberto Enciso dbgs() << "\nIndex: " << format_decimal(SectionIndex, 3) 2094f06d46fSCarlos Alberto Enciso << " Name: " << *SectionNameOrErr << "\n" 2104f06d46fSCarlos Alberto Enciso << "Size: " << hexValue(Section.getSize()) << "\n" 2114f06d46fSCarlos Alberto Enciso << "VirtualAddress: " << hexValue(VirtualAddress) << "\n" 2124f06d46fSCarlos Alberto Enciso << "SectionAddress: " << hexValue(Section.getAddress()) << "\n"; 2134f06d46fSCarlos Alberto Enciso } 2144f06d46fSCarlos Alberto Enciso dbgs() << "\nObject Section Information:\n"; 2154f06d46fSCarlos Alberto Enciso for (LVSectionAddresses::const_reference Entry : SectionAddresses) 2164f06d46fSCarlos Alberto Enciso dbgs() << "[" << hexValue(Entry.first) << ":" 2174f06d46fSCarlos Alberto Enciso << hexValue(Entry.first + Entry.second.getSize()) 2184f06d46fSCarlos Alberto Enciso << "] Size: " << hexValue(Entry.second.getSize()) << "\n"; 2194f06d46fSCarlos Alberto Enciso }); 2204f06d46fSCarlos Alberto Enciso } 2214f06d46fSCarlos Alberto Enciso 222e7950fceSCarlos Alberto Enciso void LVBinaryReader::mapVirtualAddress(const object::COFFObjectFile &COFFObj) { 223e7950fceSCarlos Alberto Enciso ErrorOr<uint64_t> ImageBase = COFFObj.getImageBase(); 224e7950fceSCarlos Alberto Enciso if (ImageBase) 225e7950fceSCarlos Alberto Enciso ImageBaseAddress = ImageBase.get(); 226e7950fceSCarlos Alberto Enciso 227e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 228e7950fceSCarlos Alberto Enciso dbgs() << "ImageBaseAddress: " << hexValue(ImageBaseAddress) << "\n"; 229e7950fceSCarlos Alberto Enciso }); 230e7950fceSCarlos Alberto Enciso 231e7950fceSCarlos Alberto Enciso uint32_t Flags = COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_LNK_COMDAT; 232e7950fceSCarlos Alberto Enciso 233e7950fceSCarlos Alberto Enciso for (const object::SectionRef &Section : COFFObj.sections()) { 234e7950fceSCarlos Alberto Enciso if (!Section.isText() || Section.isVirtual() || !Section.getSize()) 235e7950fceSCarlos Alberto Enciso continue; 236e7950fceSCarlos Alberto Enciso 237e7950fceSCarlos Alberto Enciso const object::coff_section *COFFSection = COFFObj.getCOFFSection(Section); 238e7950fceSCarlos Alberto Enciso VirtualAddress = COFFSection->VirtualAddress; 239e7950fceSCarlos Alberto Enciso bool IsComdat = (COFFSection->Characteristics & Flags) == Flags; 240e7950fceSCarlos Alberto Enciso 241e7950fceSCarlos Alberto Enciso // Record section information required for symbol resolution. 242e7950fceSCarlos Alberto Enciso // Note: The section index returned by 'getIndex()' is zero based. 243e7950fceSCarlos Alberto Enciso Sections.emplace(Section.getIndex() + 1, Section); 244e7950fceSCarlos Alberto Enciso addSectionAddress(Section); 245e7950fceSCarlos Alberto Enciso 246e7950fceSCarlos Alberto Enciso // Additional initialization on the specific object format. 247e7950fceSCarlos Alberto Enciso mapRangeAddress(COFFObj, Section, IsComdat); 248e7950fceSCarlos Alberto Enciso } 249e7950fceSCarlos Alberto Enciso 250e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 251e7950fceSCarlos Alberto Enciso dbgs() << "\nSections Information:\n"; 252e7950fceSCarlos Alberto Enciso for (LVSections::reference Entry : Sections) { 253e7950fceSCarlos Alberto Enciso LVSectionIndex SectionIndex = Entry.first; 254e7950fceSCarlos Alberto Enciso const object::SectionRef Section = Entry.second; 255e7950fceSCarlos Alberto Enciso const object::coff_section *COFFSection = COFFObj.getCOFFSection(Section); 256e7950fceSCarlos Alberto Enciso Expected<StringRef> SectionNameOrErr = Section.getName(); 257e7950fceSCarlos Alberto Enciso if (!SectionNameOrErr) 258e7950fceSCarlos Alberto Enciso consumeError(SectionNameOrErr.takeError()); 259e7950fceSCarlos Alberto Enciso dbgs() << "\nIndex: " << format_decimal(SectionIndex, 3) 260e7950fceSCarlos Alberto Enciso << " Name: " << *SectionNameOrErr << "\n" 261e7950fceSCarlos Alberto Enciso << "Size: " << hexValue(Section.getSize()) << "\n" 262e7950fceSCarlos Alberto Enciso << "VirtualAddress: " << hexValue(VirtualAddress) << "\n" 263e7950fceSCarlos Alberto Enciso << "SectionAddress: " << hexValue(Section.getAddress()) << "\n" 264e7950fceSCarlos Alberto Enciso << "PointerToRawData: " << hexValue(COFFSection->PointerToRawData) 265e7950fceSCarlos Alberto Enciso << "\n" 266e7950fceSCarlos Alberto Enciso << "SizeOfRawData: " << hexValue(COFFSection->SizeOfRawData) 267e7950fceSCarlos Alberto Enciso << "\n"; 268e7950fceSCarlos Alberto Enciso } 269e7950fceSCarlos Alberto Enciso dbgs() << "\nObject Section Information:\n"; 270e7950fceSCarlos Alberto Enciso for (LVSectionAddresses::const_reference Entry : SectionAddresses) 271e7950fceSCarlos Alberto Enciso dbgs() << "[" << hexValue(Entry.first) << ":" 272e7950fceSCarlos Alberto Enciso << hexValue(Entry.first + Entry.second.getSize()) 273e7950fceSCarlos Alberto Enciso << "] Size: " << hexValue(Entry.second.getSize()) << "\n"; 274e7950fceSCarlos Alberto Enciso }); 275e7950fceSCarlos Alberto Enciso } 276e7950fceSCarlos Alberto Enciso 2774f06d46fSCarlos Alberto Enciso Error LVBinaryReader::loadGenericTargetInfo(StringRef TheTriple, 2784f06d46fSCarlos Alberto Enciso StringRef TheFeatures) { 2794f06d46fSCarlos Alberto Enciso std::string TargetLookupError; 2804f06d46fSCarlos Alberto Enciso const Target *TheTarget = 2814f06d46fSCarlos Alberto Enciso TargetRegistry::lookupTarget(std::string(TheTriple), TargetLookupError); 2824f06d46fSCarlos Alberto Enciso if (!TheTarget) 2834f06d46fSCarlos Alberto Enciso return createStringError(errc::invalid_argument, TargetLookupError.c_str()); 2844f06d46fSCarlos Alberto Enciso 2854f06d46fSCarlos Alberto Enciso // Register information. 2864f06d46fSCarlos Alberto Enciso MCRegisterInfo *RegisterInfo = TheTarget->createMCRegInfo(TheTriple); 2874f06d46fSCarlos Alberto Enciso if (!RegisterInfo) 2884f06d46fSCarlos Alberto Enciso return createStringError(errc::invalid_argument, 2894f06d46fSCarlos Alberto Enciso "no register info for target " + TheTriple); 2904f06d46fSCarlos Alberto Enciso MRI.reset(RegisterInfo); 2914f06d46fSCarlos Alberto Enciso 2924f06d46fSCarlos Alberto Enciso // Assembler properties and features. 2934f06d46fSCarlos Alberto Enciso MCTargetOptions MCOptions; 2944f06d46fSCarlos Alberto Enciso MCAsmInfo *AsmInfo(TheTarget->createMCAsmInfo(*MRI, TheTriple, MCOptions)); 2954f06d46fSCarlos Alberto Enciso if (!AsmInfo) 2964f06d46fSCarlos Alberto Enciso return createStringError(errc::invalid_argument, 2974f06d46fSCarlos Alberto Enciso "no assembly info for target " + TheTriple); 2984f06d46fSCarlos Alberto Enciso MAI.reset(AsmInfo); 2994f06d46fSCarlos Alberto Enciso 3004f06d46fSCarlos Alberto Enciso // Target subtargets. 3014f06d46fSCarlos Alberto Enciso StringRef CPU; 3024f06d46fSCarlos Alberto Enciso MCSubtargetInfo *SubtargetInfo( 3034f06d46fSCarlos Alberto Enciso TheTarget->createMCSubtargetInfo(TheTriple, CPU, TheFeatures)); 3044f06d46fSCarlos Alberto Enciso if (!SubtargetInfo) 3054f06d46fSCarlos Alberto Enciso return createStringError(errc::invalid_argument, 3064f06d46fSCarlos Alberto Enciso "no subtarget info for target " + TheTriple); 3074f06d46fSCarlos Alberto Enciso STI.reset(SubtargetInfo); 3084f06d46fSCarlos Alberto Enciso 3094f06d46fSCarlos Alberto Enciso // Instructions Info. 3104f06d46fSCarlos Alberto Enciso MCInstrInfo *InstructionInfo(TheTarget->createMCInstrInfo()); 3114f06d46fSCarlos Alberto Enciso if (!InstructionInfo) 3124f06d46fSCarlos Alberto Enciso return createStringError(errc::invalid_argument, 3134f06d46fSCarlos Alberto Enciso "no instruction info for target " + TheTriple); 3144f06d46fSCarlos Alberto Enciso MII.reset(InstructionInfo); 3154f06d46fSCarlos Alberto Enciso 3164f06d46fSCarlos Alberto Enciso MC = std::make_unique<MCContext>(Triple(TheTriple), MAI.get(), MRI.get(), 3174f06d46fSCarlos Alberto Enciso STI.get()); 3184f06d46fSCarlos Alberto Enciso 3194f06d46fSCarlos Alberto Enciso // Assembler. 3204f06d46fSCarlos Alberto Enciso MCDisassembler *DisAsm(TheTarget->createMCDisassembler(*STI, *MC)); 3214f06d46fSCarlos Alberto Enciso if (!DisAsm) 3224f06d46fSCarlos Alberto Enciso return createStringError(errc::invalid_argument, 3234f06d46fSCarlos Alberto Enciso "no disassembler for target " + TheTriple); 3244f06d46fSCarlos Alberto Enciso MD.reset(DisAsm); 3254f06d46fSCarlos Alberto Enciso 3264f06d46fSCarlos Alberto Enciso MCInstPrinter *InstructionPrinter(TheTarget->createMCInstPrinter( 3274f06d46fSCarlos Alberto Enciso Triple(TheTriple), AsmInfo->getAssemblerDialect(), *MAI, *MII, *MRI)); 3284f06d46fSCarlos Alberto Enciso if (!InstructionPrinter) 3294f06d46fSCarlos Alberto Enciso return createStringError(errc::invalid_argument, 3304f06d46fSCarlos Alberto Enciso "no target assembly language printer for target " + 3314f06d46fSCarlos Alberto Enciso TheTriple); 3324f06d46fSCarlos Alberto Enciso MIP.reset(InstructionPrinter); 3334f06d46fSCarlos Alberto Enciso InstructionPrinter->setPrintImmHex(true); 3344f06d46fSCarlos Alberto Enciso 3354f06d46fSCarlos Alberto Enciso return Error::success(); 3364f06d46fSCarlos Alberto Enciso } 3374f06d46fSCarlos Alberto Enciso 3384f06d46fSCarlos Alberto Enciso Expected<std::pair<uint64_t, object::SectionRef>> 3394f06d46fSCarlos Alberto Enciso LVBinaryReader::getSection(LVScope *Scope, LVAddress Address, 3404f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex) { 3414f06d46fSCarlos Alberto Enciso // Return the 'text' section with the code for this logical scope. 3424f06d46fSCarlos Alberto Enciso // COFF: SectionIndex is zero. Use 'SectionAddresses' data. 3434f06d46fSCarlos Alberto Enciso // ELF: SectionIndex is the section index in the file. 3444f06d46fSCarlos Alberto Enciso if (SectionIndex) { 3454f06d46fSCarlos Alberto Enciso LVSections::iterator Iter = Sections.find(SectionIndex); 3464f06d46fSCarlos Alberto Enciso if (Iter == Sections.end()) { 3474f06d46fSCarlos Alberto Enciso return createStringError(errc::invalid_argument, 3484f06d46fSCarlos Alberto Enciso "invalid section index for: '%s'", 3494f06d46fSCarlos Alberto Enciso Scope->getName().str().c_str()); 3504f06d46fSCarlos Alberto Enciso } 3514f06d46fSCarlos Alberto Enciso const object::SectionRef Section = Iter->second; 3524f06d46fSCarlos Alberto Enciso return std::make_pair(Section.getAddress(), Section); 3534f06d46fSCarlos Alberto Enciso } 3544f06d46fSCarlos Alberto Enciso 3554f06d46fSCarlos Alberto Enciso // Ensure a valid starting address for the public names. 3564f06d46fSCarlos Alberto Enciso LVSectionAddresses::const_iterator Iter = 3574f06d46fSCarlos Alberto Enciso SectionAddresses.upper_bound(Address); 3584f06d46fSCarlos Alberto Enciso if (Iter == SectionAddresses.begin()) 3594f06d46fSCarlos Alberto Enciso return createStringError(errc::invalid_argument, 3604f06d46fSCarlos Alberto Enciso "invalid section address for: '%s'", 3614f06d46fSCarlos Alberto Enciso Scope->getName().str().c_str()); 3624f06d46fSCarlos Alberto Enciso 3634f06d46fSCarlos Alberto Enciso // Get section that contains the code for this function. 3644f06d46fSCarlos Alberto Enciso Iter = SectionAddresses.lower_bound(Address); 3654f06d46fSCarlos Alberto Enciso if (Iter != SectionAddresses.begin()) 3664f06d46fSCarlos Alberto Enciso --Iter; 3674f06d46fSCarlos Alberto Enciso return std::make_pair(Iter->first, Iter->second); 3684f06d46fSCarlos Alberto Enciso } 3694f06d46fSCarlos Alberto Enciso 3704f06d46fSCarlos Alberto Enciso void LVBinaryReader::addSectionRange(LVSectionIndex SectionIndex, 3714f06d46fSCarlos Alberto Enciso LVScope *Scope) { 3724f06d46fSCarlos Alberto Enciso LVRange *ScopesWithRanges = getSectionRanges(SectionIndex); 3734f06d46fSCarlos Alberto Enciso ScopesWithRanges->addEntry(Scope); 3744f06d46fSCarlos Alberto Enciso } 3754f06d46fSCarlos Alberto Enciso 3764f06d46fSCarlos Alberto Enciso void LVBinaryReader::addSectionRange(LVSectionIndex SectionIndex, 3774f06d46fSCarlos Alberto Enciso LVScope *Scope, LVAddress LowerAddress, 3784f06d46fSCarlos Alberto Enciso LVAddress UpperAddress) { 3794f06d46fSCarlos Alberto Enciso LVRange *ScopesWithRanges = getSectionRanges(SectionIndex); 3804f06d46fSCarlos Alberto Enciso ScopesWithRanges->addEntry(Scope, LowerAddress, UpperAddress); 3814f06d46fSCarlos Alberto Enciso } 3824f06d46fSCarlos Alberto Enciso 3834f06d46fSCarlos Alberto Enciso LVRange *LVBinaryReader::getSectionRanges(LVSectionIndex SectionIndex) { 3844f06d46fSCarlos Alberto Enciso // Check if we already have a mapping for this section index. 3854f06d46fSCarlos Alberto Enciso LVSectionRanges::iterator IterSection = SectionRanges.find(SectionIndex); 3867fbcc244SCarlos Alberto Enciso if (IterSection == SectionRanges.end()) 3877fbcc244SCarlos Alberto Enciso IterSection = 3887fbcc244SCarlos Alberto Enciso SectionRanges.emplace(SectionIndex, std::make_unique<LVRange>()).first; 3897fbcc244SCarlos Alberto Enciso LVRange *Range = IterSection->second.get(); 3904f06d46fSCarlos Alberto Enciso assert(Range && "Range is null."); 3914f06d46fSCarlos Alberto Enciso return Range; 3924f06d46fSCarlos Alberto Enciso } 3934f06d46fSCarlos Alberto Enciso 3944f06d46fSCarlos Alberto Enciso Error LVBinaryReader::createInstructions(LVScope *Scope, 3954f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex, 3964f06d46fSCarlos Alberto Enciso const LVNameInfo &NameInfo) { 3974f06d46fSCarlos Alberto Enciso assert(Scope && "Scope is null."); 3984f06d46fSCarlos Alberto Enciso 3994f06d46fSCarlos Alberto Enciso // Skip stripped functions. 4004f06d46fSCarlos Alberto Enciso if (Scope->getIsDiscarded()) 4014f06d46fSCarlos Alberto Enciso return Error::success(); 4024f06d46fSCarlos Alberto Enciso 4034f06d46fSCarlos Alberto Enciso // Find associated address and size for the given function entry point. 4044f06d46fSCarlos Alberto Enciso LVAddress Address = NameInfo.first; 4054f06d46fSCarlos Alberto Enciso uint64_t Size = NameInfo.second; 4064f06d46fSCarlos Alberto Enciso 4074f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 4084f06d46fSCarlos Alberto Enciso dbgs() << "\nPublic Name instructions: '" << Scope->getName() << "' / '" 4094f06d46fSCarlos Alberto Enciso << Scope->getLinkageName() << "'\n" 4104f06d46fSCarlos Alberto Enciso << "DIE Offset: " << hexValue(Scope->getOffset()) << " Range: [" 4114f06d46fSCarlos Alberto Enciso << hexValue(Address) << ":" << hexValue(Address + Size) << "]\n"; 4124f06d46fSCarlos Alberto Enciso }); 4134f06d46fSCarlos Alberto Enciso 4144f06d46fSCarlos Alberto Enciso Expected<std::pair<uint64_t, const object::SectionRef>> SectionOrErr = 4154f06d46fSCarlos Alberto Enciso getSection(Scope, Address, SectionIndex); 4164f06d46fSCarlos Alberto Enciso if (!SectionOrErr) 4174f06d46fSCarlos Alberto Enciso return SectionOrErr.takeError(); 4184f06d46fSCarlos Alberto Enciso const object::SectionRef Section = (*SectionOrErr).second; 4194f06d46fSCarlos Alberto Enciso uint64_t SectionAddress = (*SectionOrErr).first; 4204f06d46fSCarlos Alberto Enciso 4214f06d46fSCarlos Alberto Enciso Expected<StringRef> SectionContentsOrErr = Section.getContents(); 4224f06d46fSCarlos Alberto Enciso if (!SectionContentsOrErr) 4234f06d46fSCarlos Alberto Enciso return SectionOrErr.takeError(); 4244f06d46fSCarlos Alberto Enciso 4254f06d46fSCarlos Alberto Enciso // There are cases where the section size is smaller than the [LowPC,HighPC] 4264f06d46fSCarlos Alberto Enciso // range; it causes us to decode invalid addresses. The recorded size in the 4274f06d46fSCarlos Alberto Enciso // logical scope is one less than the real size. 4284f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 4294f06d46fSCarlos Alberto Enciso dbgs() << " Size: " << hexValue(Size) 4304f06d46fSCarlos Alberto Enciso << ", Section Size: " << hexValue(Section.getSize()) << "\n"; 4314f06d46fSCarlos Alberto Enciso }); 4324f06d46fSCarlos Alberto Enciso Size = std::min(Size + 1, Section.getSize()); 4334f06d46fSCarlos Alberto Enciso 4344f06d46fSCarlos Alberto Enciso ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(*SectionContentsOrErr); 4354f06d46fSCarlos Alberto Enciso uint64_t Offset = Address - SectionAddress; 4364f06d46fSCarlos Alberto Enciso uint8_t const *Begin = Bytes.data() + Offset; 4374f06d46fSCarlos Alberto Enciso uint8_t const *End = Bytes.data() + Offset + Size; 4384f06d46fSCarlos Alberto Enciso 4394f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 4404f06d46fSCarlos Alberto Enciso Expected<StringRef> SectionNameOrErr = Section.getName(); 4414f06d46fSCarlos Alberto Enciso if (!SectionNameOrErr) 4424f06d46fSCarlos Alberto Enciso consumeError(SectionNameOrErr.takeError()); 4434f06d46fSCarlos Alberto Enciso else 4444f06d46fSCarlos Alberto Enciso dbgs() << "Section Index: " << hexValue(Section.getIndex()) << " [" 4454f06d46fSCarlos Alberto Enciso << hexValue((uint64_t)Section.getAddress()) << ":" 4464f06d46fSCarlos Alberto Enciso << hexValue((uint64_t)Section.getAddress() + Section.getSize(), 10) 4474f06d46fSCarlos Alberto Enciso << "] Name: '" << *SectionNameOrErr << "'\n" 4484f06d46fSCarlos Alberto Enciso << "Begin: " << hexValue((uint64_t)Begin) 4494f06d46fSCarlos Alberto Enciso << ", End: " << hexValue((uint64_t)End) << "\n"; 4504f06d46fSCarlos Alberto Enciso }); 4514f06d46fSCarlos Alberto Enciso 4524f06d46fSCarlos Alberto Enciso // Address for first instruction line. 4534f06d46fSCarlos Alberto Enciso LVAddress FirstAddress = Address; 4547fbcc244SCarlos Alberto Enciso auto InstructionsSP = std::make_unique<LVLines>(); 4557fbcc244SCarlos Alberto Enciso LVLines &Instructions = *InstructionsSP; 4567fbcc244SCarlos Alberto Enciso DiscoveredLines.emplace_back(std::move(InstructionsSP)); 4574f06d46fSCarlos Alberto Enciso 4584f06d46fSCarlos Alberto Enciso while (Begin < End) { 4594f06d46fSCarlos Alberto Enciso MCInst Instruction; 4604f06d46fSCarlos Alberto Enciso uint64_t BytesConsumed = 0; 4614f06d46fSCarlos Alberto Enciso SmallVector<char, 64> InsnStr; 4624f06d46fSCarlos Alberto Enciso raw_svector_ostream Annotations(InsnStr); 4634f06d46fSCarlos Alberto Enciso MCDisassembler::DecodeStatus const S = 4644f06d46fSCarlos Alberto Enciso MD->getInstruction(Instruction, BytesConsumed, 4654f06d46fSCarlos Alberto Enciso ArrayRef<uint8_t>(Begin, End), Address, outs()); 4664f06d46fSCarlos Alberto Enciso switch (S) { 4674f06d46fSCarlos Alberto Enciso case MCDisassembler::Fail: 4684f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ dbgs() << "Invalid instruction\n"; }); 4694f06d46fSCarlos Alberto Enciso if (BytesConsumed == 0) 4704f06d46fSCarlos Alberto Enciso // Skip invalid bytes 4714f06d46fSCarlos Alberto Enciso BytesConsumed = 1; 4724f06d46fSCarlos Alberto Enciso break; 4734f06d46fSCarlos Alberto Enciso case MCDisassembler::SoftFail: 4744f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ dbgs() << "Potentially undefined instruction:"; }); 4756006d43eSCraig Topper [[fallthrough]]; 4764f06d46fSCarlos Alberto Enciso case MCDisassembler::Success: { 4774f06d46fSCarlos Alberto Enciso std::string Buffer; 4784f06d46fSCarlos Alberto Enciso raw_string_ostream Stream(Buffer); 4794f06d46fSCarlos Alberto Enciso StringRef AnnotationsStr = Annotations.str(); 480d22f050eSGregory Alfonso MIP->printInst(&Instruction, Address, AnnotationsStr, *STI, Stream); 4814f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 4824f06d46fSCarlos Alberto Enciso std::string BufferCodes; 4834f06d46fSCarlos Alberto Enciso raw_string_ostream StreamCodes(BufferCodes); 4844f06d46fSCarlos Alberto Enciso StreamCodes << format_bytes( 48511011599SKazu Hirata ArrayRef<uint8_t>(Begin, Begin + BytesConsumed), std::nullopt, 16, 48611011599SKazu Hirata 16); 4874f06d46fSCarlos Alberto Enciso dbgs() << "[" << hexValue((uint64_t)Begin) << "] " 4884f06d46fSCarlos Alberto Enciso << "Size: " << format_decimal(BytesConsumed, 2) << " (" 4894f06d46fSCarlos Alberto Enciso << formatv("{0}", 4904f06d46fSCarlos Alberto Enciso fmt_align(StreamCodes.str(), AlignStyle::Left, 32)) 4914f06d46fSCarlos Alberto Enciso << ") " << hexValue((uint64_t)Address) << ": " << Stream.str() 4924f06d46fSCarlos Alberto Enciso << "\n"; 4934f06d46fSCarlos Alberto Enciso }); 4944f06d46fSCarlos Alberto Enciso // Here we add logical lines to the Instructions. Later on, 4954f06d46fSCarlos Alberto Enciso // the 'processLines()' function will move each created logical line 4964f06d46fSCarlos Alberto Enciso // to its enclosing logical scope, using the debug ranges information 4974f06d46fSCarlos Alberto Enciso // and they will be released when its scope parent is deleted. 4987fbcc244SCarlos Alberto Enciso LVLineAssembler *Line = createLineAssembler(); 4994f06d46fSCarlos Alberto Enciso Line->setAddress(Address); 5004f06d46fSCarlos Alberto Enciso Line->setName(StringRef(Stream.str()).trim()); 5017fbcc244SCarlos Alberto Enciso Instructions.push_back(Line); 5024f06d46fSCarlos Alberto Enciso break; 5034f06d46fSCarlos Alberto Enciso } 5044f06d46fSCarlos Alberto Enciso } 5054f06d46fSCarlos Alberto Enciso Address += BytesConsumed; 5064f06d46fSCarlos Alberto Enciso Begin += BytesConsumed; 5074f06d46fSCarlos Alberto Enciso } 5084f06d46fSCarlos Alberto Enciso 5094f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 5104f06d46fSCarlos Alberto Enciso size_t Index = 0; 5114f06d46fSCarlos Alberto Enciso dbgs() << "\nSectionIndex: " << format_decimal(SectionIndex, 3) 5124f06d46fSCarlos Alberto Enciso << " Scope DIE: " << hexValue(Scope->getOffset()) << "\n" 5134f06d46fSCarlos Alberto Enciso << "Address: " << hexValue(FirstAddress) 5144f06d46fSCarlos Alberto Enciso << format(" - Collected instructions lines: %d\n", 5157fbcc244SCarlos Alberto Enciso Instructions.size()); 5167fbcc244SCarlos Alberto Enciso for (const LVLine *Line : Instructions) 5174f06d46fSCarlos Alberto Enciso dbgs() << format_decimal(++Index, 5) << ": " 5184f06d46fSCarlos Alberto Enciso << hexValue(Line->getOffset()) << ", (" << Line->getName() 5194f06d46fSCarlos Alberto Enciso << ")\n"; 5204f06d46fSCarlos Alberto Enciso }); 5214f06d46fSCarlos Alberto Enciso 5224f06d46fSCarlos Alberto Enciso // The scope in the assembler names is linked to its own instructions. 5237fbcc244SCarlos Alberto Enciso ScopeInstructions.add(SectionIndex, Scope, &Instructions); 5244f06d46fSCarlos Alberto Enciso AssemblerMappings.add(SectionIndex, FirstAddress, Scope); 5254f06d46fSCarlos Alberto Enciso 5264f06d46fSCarlos Alberto Enciso return Error::success(); 5274f06d46fSCarlos Alberto Enciso } 5284f06d46fSCarlos Alberto Enciso 5294f06d46fSCarlos Alberto Enciso Error LVBinaryReader::createInstructions(LVScope *Function, 5304f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex) { 5314f06d46fSCarlos Alberto Enciso if (!options().getPrintInstructions()) 5324f06d46fSCarlos Alberto Enciso return Error::success(); 5334f06d46fSCarlos Alberto Enciso 5344f06d46fSCarlos Alberto Enciso LVNameInfo Name = CompileUnit->findPublicName(Function); 5354f06d46fSCarlos Alberto Enciso if (Name.first != LVAddress(UINT64_MAX)) 5364f06d46fSCarlos Alberto Enciso return createInstructions(Function, SectionIndex, Name); 5374f06d46fSCarlos Alberto Enciso 5384f06d46fSCarlos Alberto Enciso return Error::success(); 5394f06d46fSCarlos Alberto Enciso } 5404f06d46fSCarlos Alberto Enciso 5414f06d46fSCarlos Alberto Enciso Error LVBinaryReader::createInstructions() { 5424f06d46fSCarlos Alberto Enciso if (!options().getPrintInstructions()) 5434f06d46fSCarlos Alberto Enciso return Error::success(); 5444f06d46fSCarlos Alberto Enciso 5454f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 5464f06d46fSCarlos Alberto Enciso size_t Index = 1; 5474f06d46fSCarlos Alberto Enciso dbgs() << "\nPublic Names (Scope):\n"; 5484f06d46fSCarlos Alberto Enciso for (LVPublicNames::const_reference Name : CompileUnit->getPublicNames()) { 5494f06d46fSCarlos Alberto Enciso LVScope *Scope = Name.first; 5504f06d46fSCarlos Alberto Enciso const LVNameInfo &NameInfo = Name.second; 5514f06d46fSCarlos Alberto Enciso LVAddress Address = NameInfo.first; 5524f06d46fSCarlos Alberto Enciso uint64_t Size = NameInfo.second; 5534f06d46fSCarlos Alberto Enciso dbgs() << format_decimal(Index++, 5) << ": " 5544f06d46fSCarlos Alberto Enciso << "DIE Offset: " << hexValue(Scope->getOffset()) << " Range: [" 5554f06d46fSCarlos Alberto Enciso << hexValue(Address) << ":" << hexValue(Address + Size) << "] " 5564f06d46fSCarlos Alberto Enciso << "Name: '" << Scope->getName() << "' / '" 5574f06d46fSCarlos Alberto Enciso << Scope->getLinkageName() << "'\n"; 5584f06d46fSCarlos Alberto Enciso } 5594f06d46fSCarlos Alberto Enciso }); 5604f06d46fSCarlos Alberto Enciso 5614f06d46fSCarlos Alberto Enciso // For each public name in the current compile unit, create the line 5624f06d46fSCarlos Alberto Enciso // records that represent the executable instructions. 5634f06d46fSCarlos Alberto Enciso for (LVPublicNames::const_reference Name : CompileUnit->getPublicNames()) { 5644f06d46fSCarlos Alberto Enciso LVScope *Scope = Name.first; 5654f06d46fSCarlos Alberto Enciso // The symbol table extracted from the object file always contains a 5664f06d46fSCarlos Alberto Enciso // non-empty name (linkage name). However, the logical scope does not 5674f06d46fSCarlos Alberto Enciso // guarantee to have a name for the linkage name (main is one case). 5684f06d46fSCarlos Alberto Enciso // For those cases, set the linkage name the same as the name. 5694f06d46fSCarlos Alberto Enciso if (!Scope->getLinkageNameIndex()) 5704f06d46fSCarlos Alberto Enciso Scope->setLinkageName(Scope->getName()); 5714f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex = getSymbolTableIndex(Scope->getLinkageName()); 5724f06d46fSCarlos Alberto Enciso if (Error Err = createInstructions(Scope, SectionIndex, Name.second)) 5734f06d46fSCarlos Alberto Enciso return Err; 5744f06d46fSCarlos Alberto Enciso } 5754f06d46fSCarlos Alberto Enciso 5764f06d46fSCarlos Alberto Enciso return Error::success(); 5774f06d46fSCarlos Alberto Enciso } 5784f06d46fSCarlos Alberto Enciso 5794f06d46fSCarlos Alberto Enciso // During the traversal of the debug information sections, we created the 5804f06d46fSCarlos Alberto Enciso // logical lines representing the disassembled instructions from the text 5814f06d46fSCarlos Alberto Enciso // section and the logical lines representing the line records from the 5824f06d46fSCarlos Alberto Enciso // debug line section. Using the ranges associated with the logical scopes, 5834f06d46fSCarlos Alberto Enciso // we will allocate those logical lines to their logical scopes. 5844f06d46fSCarlos Alberto Enciso void LVBinaryReader::processLines(LVLines *DebugLines, 5854f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex, 5864f06d46fSCarlos Alberto Enciso LVScope *Function) { 5874f06d46fSCarlos Alberto Enciso assert(DebugLines && "DebugLines is null."); 5884f06d46fSCarlos Alberto Enciso 5894f06d46fSCarlos Alberto Enciso // Just return if this compilation unit does not have any line records 5904f06d46fSCarlos Alberto Enciso // and no instruction lines were created. 5914f06d46fSCarlos Alberto Enciso if (DebugLines->empty() && !options().getPrintInstructions()) 5924f06d46fSCarlos Alberto Enciso return; 5934f06d46fSCarlos Alberto Enciso 5944f06d46fSCarlos Alberto Enciso // Merge the debug lines and instruction lines using their text address; 5954f06d46fSCarlos Alberto Enciso // the logical line representing the debug line record is followed by the 5964f06d46fSCarlos Alberto Enciso // line(s) representing the disassembled instructions, whose addresses are 5974f06d46fSCarlos Alberto Enciso // equal or greater that the line address and less than the address of the 5984f06d46fSCarlos Alberto Enciso // next debug line record. 5994f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 6004f06d46fSCarlos Alberto Enciso size_t Index = 1; 6014f06d46fSCarlos Alberto Enciso size_t PerLine = 4; 6024f06d46fSCarlos Alberto Enciso dbgs() << format("\nProcess debug lines: %d\n", DebugLines->size()); 6034f06d46fSCarlos Alberto Enciso for (const LVLine *Line : *DebugLines) { 6044f06d46fSCarlos Alberto Enciso dbgs() << format_decimal(Index, 5) << ": " << hexValue(Line->getOffset()) 6054f06d46fSCarlos Alberto Enciso << ", (" << Line->getLineNumber() << ")" 6064f06d46fSCarlos Alberto Enciso << ((Index % PerLine) ? " " : "\n"); 6074f06d46fSCarlos Alberto Enciso ++Index; 6084f06d46fSCarlos Alberto Enciso } 6094f06d46fSCarlos Alberto Enciso dbgs() << ((Index % PerLine) ? "\n" : ""); 6104f06d46fSCarlos Alberto Enciso }); 6114f06d46fSCarlos Alberto Enciso 6124f06d46fSCarlos Alberto Enciso bool TraverseLines = true; 6134f06d46fSCarlos Alberto Enciso LVLines::iterator Iter = DebugLines->begin(); 6144f06d46fSCarlos Alberto Enciso while (TraverseLines && Iter != DebugLines->end()) { 6154f06d46fSCarlos Alberto Enciso uint64_t DebugAddress = (*Iter)->getAddress(); 6164f06d46fSCarlos Alberto Enciso 6174f06d46fSCarlos Alberto Enciso // Get the function with an entry point that matches this line and 6184f06d46fSCarlos Alberto Enciso // its associated assembler entries. In the case of COMDAT, the input 6194f06d46fSCarlos Alberto Enciso // 'Function' is not null. Use it to find its address ranges. 6204f06d46fSCarlos Alberto Enciso LVScope *Scope = Function; 6214f06d46fSCarlos Alberto Enciso if (!Function) { 6224f06d46fSCarlos Alberto Enciso Scope = AssemblerMappings.find(SectionIndex, DebugAddress); 6234f06d46fSCarlos Alberto Enciso if (!Scope) { 6244f06d46fSCarlos Alberto Enciso ++Iter; 6254f06d46fSCarlos Alberto Enciso continue; 6264f06d46fSCarlos Alberto Enciso } 6274f06d46fSCarlos Alberto Enciso } 6284f06d46fSCarlos Alberto Enciso 6294f06d46fSCarlos Alberto Enciso // Get the associated instructions for the found 'Scope'. 6304f06d46fSCarlos Alberto Enciso LVLines InstructionLines; 6314f06d46fSCarlos Alberto Enciso LVLines *Lines = ScopeInstructions.find(SectionIndex, Scope); 6324f06d46fSCarlos Alberto Enciso if (Lines) 6334f06d46fSCarlos Alberto Enciso InstructionLines = std::move(*Lines); 6344f06d46fSCarlos Alberto Enciso 6354f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 6364f06d46fSCarlos Alberto Enciso size_t Index = 0; 6374f06d46fSCarlos Alberto Enciso dbgs() << "\nSectionIndex: " << format_decimal(SectionIndex, 3) 6384f06d46fSCarlos Alberto Enciso << " Scope DIE: " << hexValue(Scope->getOffset()) << "\n" 6399d56d9a9SCarlos Alberto Enciso << format("Process instruction lines: %d\n", 6404f06d46fSCarlos Alberto Enciso InstructionLines.size()); 6414f06d46fSCarlos Alberto Enciso for (const LVLine *Line : InstructionLines) 6424f06d46fSCarlos Alberto Enciso dbgs() << format_decimal(++Index, 5) << ": " 6434f06d46fSCarlos Alberto Enciso << hexValue(Line->getOffset()) << ", (" << Line->getName() 6444f06d46fSCarlos Alberto Enciso << ")\n"; 6454f06d46fSCarlos Alberto Enciso }); 6464f06d46fSCarlos Alberto Enciso 6474f06d46fSCarlos Alberto Enciso // Continue with next debug line if there are not instructions lines. 6484f06d46fSCarlos Alberto Enciso if (InstructionLines.empty()) { 6494f06d46fSCarlos Alberto Enciso ++Iter; 6504f06d46fSCarlos Alberto Enciso continue; 6514f06d46fSCarlos Alberto Enciso } 6524f06d46fSCarlos Alberto Enciso 6534f06d46fSCarlos Alberto Enciso for (LVLine *InstructionLine : InstructionLines) { 6544f06d46fSCarlos Alberto Enciso uint64_t InstructionAddress = InstructionLine->getAddress(); 6554f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 6564f06d46fSCarlos Alberto Enciso dbgs() << "Instruction address: " << hexValue(InstructionAddress) 6574f06d46fSCarlos Alberto Enciso << "\n"; 6584f06d46fSCarlos Alberto Enciso }); 6594f06d46fSCarlos Alberto Enciso if (TraverseLines) { 6604f06d46fSCarlos Alberto Enciso while (Iter != DebugLines->end()) { 6614f06d46fSCarlos Alberto Enciso DebugAddress = (*Iter)->getAddress(); 6624f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 6634f06d46fSCarlos Alberto Enciso bool IsDebug = (*Iter)->getIsLineDebug(); 6644f06d46fSCarlos Alberto Enciso dbgs() << "Line " << (IsDebug ? "dbg:" : "ins:") << " [" 6654f06d46fSCarlos Alberto Enciso << hexValue(DebugAddress) << "]"; 6664f06d46fSCarlos Alberto Enciso if (IsDebug) 6674f06d46fSCarlos Alberto Enciso dbgs() << format(" %d", (*Iter)->getLineNumber()); 6684f06d46fSCarlos Alberto Enciso dbgs() << "\n"; 6694f06d46fSCarlos Alberto Enciso }); 6704f06d46fSCarlos Alberto Enciso // Instruction address before debug line. 6714f06d46fSCarlos Alberto Enciso if (InstructionAddress < DebugAddress) { 6724f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 6734f06d46fSCarlos Alberto Enciso dbgs() << "Inserted instruction address: " 6744f06d46fSCarlos Alberto Enciso << hexValue(InstructionAddress) << " before line: " 6754f06d46fSCarlos Alberto Enciso << format("%d", (*Iter)->getLineNumber()) << " [" 6764f06d46fSCarlos Alberto Enciso << hexValue(DebugAddress) << "]\n"; 6774f06d46fSCarlos Alberto Enciso }); 6784f06d46fSCarlos Alberto Enciso Iter = DebugLines->insert(Iter, InstructionLine); 6794f06d46fSCarlos Alberto Enciso // The returned iterator points to the inserted instruction. 6804f06d46fSCarlos Alberto Enciso // Skip it and point to the line acting as reference. 6814f06d46fSCarlos Alberto Enciso ++Iter; 6824f06d46fSCarlos Alberto Enciso break; 6834f06d46fSCarlos Alberto Enciso } 6844f06d46fSCarlos Alberto Enciso ++Iter; 6854f06d46fSCarlos Alberto Enciso } 6864f06d46fSCarlos Alberto Enciso if (Iter == DebugLines->end()) { 6874f06d46fSCarlos Alberto Enciso // We have reached the end of the source lines and the current 6884f06d46fSCarlos Alberto Enciso // instruction line address is greater than the last source line. 6894f06d46fSCarlos Alberto Enciso TraverseLines = false; 6904f06d46fSCarlos Alberto Enciso DebugLines->push_back(InstructionLine); 6914f06d46fSCarlos Alberto Enciso } 6924f06d46fSCarlos Alberto Enciso } else { 6934f06d46fSCarlos Alberto Enciso DebugLines->push_back(InstructionLine); 6944f06d46fSCarlos Alberto Enciso } 6954f06d46fSCarlos Alberto Enciso } 6964f06d46fSCarlos Alberto Enciso } 6974f06d46fSCarlos Alberto Enciso 6984f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 6994f06d46fSCarlos Alberto Enciso dbgs() << format("Lines after merge: %d\n", DebugLines->size()); 7004f06d46fSCarlos Alberto Enciso size_t Index = 0; 7014f06d46fSCarlos Alberto Enciso for (const LVLine *Line : *DebugLines) { 7024f06d46fSCarlos Alberto Enciso dbgs() << format_decimal(++Index, 5) << ": " 7034f06d46fSCarlos Alberto Enciso << hexValue(Line->getOffset()) << ", (" 7044f06d46fSCarlos Alberto Enciso << ((Line->getIsLineDebug()) 7054f06d46fSCarlos Alberto Enciso ? Line->lineNumberAsStringStripped(/*ShowZero=*/true) 7064f06d46fSCarlos Alberto Enciso : Line->getName()) 7074f06d46fSCarlos Alberto Enciso << ")\n"; 7084f06d46fSCarlos Alberto Enciso } 7094f06d46fSCarlos Alberto Enciso }); 7104f06d46fSCarlos Alberto Enciso 7114f06d46fSCarlos Alberto Enciso // If this compilation unit does not have line records, traverse its scopes 7124f06d46fSCarlos Alberto Enciso // and take any collected instruction lines as the working set in order 7134f06d46fSCarlos Alberto Enciso // to move them to their associated scope. 7144f06d46fSCarlos Alberto Enciso if (DebugLines->empty()) { 7154f06d46fSCarlos Alberto Enciso if (const LVScopes *Scopes = CompileUnit->getScopes()) 7164f06d46fSCarlos Alberto Enciso for (LVScope *Scope : *Scopes) { 7174f06d46fSCarlos Alberto Enciso LVLines *Lines = ScopeInstructions.find(Scope); 7184f06d46fSCarlos Alberto Enciso if (Lines) { 7194f06d46fSCarlos Alberto Enciso 7204f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 7214f06d46fSCarlos Alberto Enciso size_t Index = 0; 7224f06d46fSCarlos Alberto Enciso dbgs() << "\nSectionIndex: " << format_decimal(SectionIndex, 3) 7234f06d46fSCarlos Alberto Enciso << " Scope DIE: " << hexValue(Scope->getOffset()) << "\n" 7249d56d9a9SCarlos Alberto Enciso << format("Instruction lines: %d\n", Lines->size()); 7254f06d46fSCarlos Alberto Enciso for (const LVLine *Line : *Lines) 7264f06d46fSCarlos Alberto Enciso dbgs() << format_decimal(++Index, 5) << ": " 7274f06d46fSCarlos Alberto Enciso << hexValue(Line->getOffset()) << ", (" << Line->getName() 7284f06d46fSCarlos Alberto Enciso << ")\n"; 7294f06d46fSCarlos Alberto Enciso }); 7304f06d46fSCarlos Alberto Enciso 7319d56d9a9SCarlos Alberto Enciso if (Scope->getIsArtificial()) { 7329d56d9a9SCarlos Alberto Enciso // Add the instruction lines to their artificial scope. 7339d56d9a9SCarlos Alberto Enciso for (LVLine *Line : *Lines) 7349d56d9a9SCarlos Alberto Enciso Scope->addElement(Line); 7359d56d9a9SCarlos Alberto Enciso } else { 7364f06d46fSCarlos Alberto Enciso DebugLines->append(*Lines); 7379d56d9a9SCarlos Alberto Enciso } 7384f06d46fSCarlos Alberto Enciso Lines->clear(); 7394f06d46fSCarlos Alberto Enciso } 7404f06d46fSCarlos Alberto Enciso } 7414f06d46fSCarlos Alberto Enciso } 7424f06d46fSCarlos Alberto Enciso 7434f06d46fSCarlos Alberto Enciso LVRange *ScopesWithRanges = getSectionRanges(SectionIndex); 7444f06d46fSCarlos Alberto Enciso ScopesWithRanges->startSearch(); 7454f06d46fSCarlos Alberto Enciso 7464f06d46fSCarlos Alberto Enciso // Process collected lines. 7474f06d46fSCarlos Alberto Enciso LVScope *Scope; 7484f06d46fSCarlos Alberto Enciso for (LVLine *Line : *DebugLines) { 7494f06d46fSCarlos Alberto Enciso // Using the current line address, get its associated lexical scope and 7504f06d46fSCarlos Alberto Enciso // add the line information to it. 7514f06d46fSCarlos Alberto Enciso Scope = ScopesWithRanges->getEntry(Line->getAddress()); 7524f06d46fSCarlos Alberto Enciso if (!Scope) { 7534f06d46fSCarlos Alberto Enciso // If missing scope, use the compile unit. 7544f06d46fSCarlos Alberto Enciso Scope = CompileUnit; 7554f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 7564f06d46fSCarlos Alberto Enciso dbgs() << "Adding line to CU: " << hexValue(Line->getOffset()) << ", (" 7574f06d46fSCarlos Alberto Enciso << ((Line->getIsLineDebug()) 7584f06d46fSCarlos Alberto Enciso ? Line->lineNumberAsStringStripped(/*ShowZero=*/true) 7594f06d46fSCarlos Alberto Enciso : Line->getName()) 7604f06d46fSCarlos Alberto Enciso << ")\n"; 7614f06d46fSCarlos Alberto Enciso }); 7624f06d46fSCarlos Alberto Enciso } 7634f06d46fSCarlos Alberto Enciso 7644f06d46fSCarlos Alberto Enciso // Add line object to scope. 7654f06d46fSCarlos Alberto Enciso Scope->addElement(Line); 7664f06d46fSCarlos Alberto Enciso 7674f06d46fSCarlos Alberto Enciso // Report any line zero. 7684f06d46fSCarlos Alberto Enciso if (options().getWarningLines() && Line->getIsLineDebug() && 7694f06d46fSCarlos Alberto Enciso !Line->getLineNumber()) 7704f06d46fSCarlos Alberto Enciso CompileUnit->addLineZero(Line); 7714f06d46fSCarlos Alberto Enciso 7724f06d46fSCarlos Alberto Enciso // Some compilers generate ranges in the compile unit; other compilers 7734f06d46fSCarlos Alberto Enciso // only DW_AT_low_pc/DW_AT_high_pc. In order to correctly map global 7744f06d46fSCarlos Alberto Enciso // variables, we need to generate the map ranges for the compile unit. 7754f06d46fSCarlos Alberto Enciso // If we use the ranges stored at the scope level, there are cases where 7764f06d46fSCarlos Alberto Enciso // the address referenced by a symbol location, is not in the enclosing 7774f06d46fSCarlos Alberto Enciso // scope, but in an outer one. By using the ranges stored in the compile 7784f06d46fSCarlos Alberto Enciso // unit, we can catch all those addresses. 7794f06d46fSCarlos Alberto Enciso if (Line->getIsLineDebug()) 7804f06d46fSCarlos Alberto Enciso CompileUnit->addMapping(Line, SectionIndex); 7814f06d46fSCarlos Alberto Enciso 7824f06d46fSCarlos Alberto Enciso // Resolve any given pattern. 7834f06d46fSCarlos Alberto Enciso patterns().resolvePatternMatch(Line); 7844f06d46fSCarlos Alberto Enciso } 7854f06d46fSCarlos Alberto Enciso 7864f06d46fSCarlos Alberto Enciso ScopesWithRanges->endSearch(); 7874f06d46fSCarlos Alberto Enciso } 7884f06d46fSCarlos Alberto Enciso 7894f06d46fSCarlos Alberto Enciso void LVBinaryReader::processLines(LVLines *DebugLines, 7904f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex) { 7914f06d46fSCarlos Alberto Enciso assert(DebugLines && "DebugLines is null."); 7924f06d46fSCarlos Alberto Enciso if (DebugLines->empty() && !ScopeInstructions.findMap(SectionIndex)) 7934f06d46fSCarlos Alberto Enciso return; 7944f06d46fSCarlos Alberto Enciso 7954f06d46fSCarlos Alberto Enciso // If the Compile Unit does not contain comdat functions, use the whole 7964f06d46fSCarlos Alberto Enciso // set of debug lines, as the addresses don't have conflicts. 7974f06d46fSCarlos Alberto Enciso if (!CompileUnit->getHasComdatScopes()) { 7984f06d46fSCarlos Alberto Enciso processLines(DebugLines, SectionIndex, nullptr); 7994f06d46fSCarlos Alberto Enciso return; 8004f06d46fSCarlos Alberto Enciso } 8014f06d46fSCarlos Alberto Enciso 8024f06d46fSCarlos Alberto Enciso // Find the indexes for the lines whose address is zero. 8034f06d46fSCarlos Alberto Enciso std::vector<size_t> AddressZero; 8044f06d46fSCarlos Alberto Enciso LVLines::iterator It = 8054f06d46fSCarlos Alberto Enciso std::find_if(std::begin(*DebugLines), std::end(*DebugLines), 8064f06d46fSCarlos Alberto Enciso [](LVLine *Line) { return !Line->getAddress(); }); 8074f06d46fSCarlos Alberto Enciso while (It != std::end(*DebugLines)) { 8084f06d46fSCarlos Alberto Enciso AddressZero.emplace_back(std::distance(std::begin(*DebugLines), It)); 8094f06d46fSCarlos Alberto Enciso It = std::find_if(std::next(It), std::end(*DebugLines), 8104f06d46fSCarlos Alberto Enciso [](LVLine *Line) { return !Line->getAddress(); }); 8114f06d46fSCarlos Alberto Enciso } 8124f06d46fSCarlos Alberto Enciso 8134f06d46fSCarlos Alberto Enciso // If the set of debug lines does not contain any line with address zero, 8144f06d46fSCarlos Alberto Enciso // use the whole set. It means we are dealing with an initialization 8154f06d46fSCarlos Alberto Enciso // section from a fully linked binary. 8164f06d46fSCarlos Alberto Enciso if (AddressZero.empty()) { 8174f06d46fSCarlos Alberto Enciso processLines(DebugLines, SectionIndex, nullptr); 8184f06d46fSCarlos Alberto Enciso return; 8194f06d46fSCarlos Alberto Enciso } 8204f06d46fSCarlos Alberto Enciso 8214f06d46fSCarlos Alberto Enciso // The Compile unit contains comdat functions. Traverse the collected 8224f06d46fSCarlos Alberto Enciso // debug lines and identify logical groups based on their start and 8234f06d46fSCarlos Alberto Enciso // address. Each group starts with a zero address. 8244f06d46fSCarlos Alberto Enciso // Begin, End, Address, IsDone. 8254f06d46fSCarlos Alberto Enciso using LVBucket = std::tuple<size_t, size_t, LVAddress, bool>; 8264f06d46fSCarlos Alberto Enciso std::vector<LVBucket> Buckets; 8274f06d46fSCarlos Alberto Enciso 8284f06d46fSCarlos Alberto Enciso LVAddress Address; 8294f06d46fSCarlos Alberto Enciso size_t Begin = 0; 8304f06d46fSCarlos Alberto Enciso size_t End = 0; 8314f06d46fSCarlos Alberto Enciso size_t Index = 0; 8324f06d46fSCarlos Alberto Enciso for (Index = 0; Index < AddressZero.size() - 1; ++Index) { 8334f06d46fSCarlos Alberto Enciso Begin = AddressZero[Index]; 8344f06d46fSCarlos Alberto Enciso End = AddressZero[Index + 1] - 1; 8354f06d46fSCarlos Alberto Enciso Address = (*DebugLines)[End]->getAddress(); 8364f06d46fSCarlos Alberto Enciso Buckets.emplace_back(Begin, End, Address, false); 8374f06d46fSCarlos Alberto Enciso } 8384f06d46fSCarlos Alberto Enciso 8394f06d46fSCarlos Alberto Enciso // Add the last bucket. 8404f06d46fSCarlos Alberto Enciso if (Index) { 8414f06d46fSCarlos Alberto Enciso Begin = AddressZero[Index]; 8424f06d46fSCarlos Alberto Enciso End = DebugLines->size() - 1; 8434f06d46fSCarlos Alberto Enciso Address = (*DebugLines)[End]->getAddress(); 8444f06d46fSCarlos Alberto Enciso Buckets.emplace_back(Begin, End, Address, false); 8454f06d46fSCarlos Alberto Enciso } 8464f06d46fSCarlos Alberto Enciso 8474f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 8484f06d46fSCarlos Alberto Enciso dbgs() << "\nDebug Lines buckets: " << Buckets.size() << "\n"; 8494f06d46fSCarlos Alberto Enciso for (LVBucket &Bucket : Buckets) { 8504f06d46fSCarlos Alberto Enciso dbgs() << "Begin: " << format_decimal(std::get<0>(Bucket), 5) << ", " 8514f06d46fSCarlos Alberto Enciso << "End: " << format_decimal(std::get<1>(Bucket), 5) << ", " 8524f06d46fSCarlos Alberto Enciso << "Address: " << hexValue(std::get<2>(Bucket)) << "\n"; 8534f06d46fSCarlos Alberto Enciso } 8544f06d46fSCarlos Alberto Enciso }); 8554f06d46fSCarlos Alberto Enciso 8564f06d46fSCarlos Alberto Enciso // Traverse the sections and buckets looking for matches on the section 8574f06d46fSCarlos Alberto Enciso // sizes. In the unlikely event of different buckets with the same size 8584f06d46fSCarlos Alberto Enciso // process them in order and mark them as done. 8594f06d46fSCarlos Alberto Enciso LVLines Group; 8604f06d46fSCarlos Alberto Enciso for (LVSections::reference Entry : Sections) { 8614f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex = Entry.first; 8624f06d46fSCarlos Alberto Enciso const object::SectionRef Section = Entry.second; 8634f06d46fSCarlos Alberto Enciso uint64_t Size = Section.getSize(); 8644f06d46fSCarlos Alberto Enciso LLVM_DEBUG({ 8654f06d46fSCarlos Alberto Enciso dbgs() << "\nSection Index: " << format_decimal(SectionIndex, 3) 8664f06d46fSCarlos Alberto Enciso << " , Section Size: " << hexValue(Section.getSize()) 8674f06d46fSCarlos Alberto Enciso << " , Section Address: " << hexValue(Section.getAddress()) 8684f06d46fSCarlos Alberto Enciso << "\n"; 8694f06d46fSCarlos Alberto Enciso }); 8704f06d46fSCarlos Alberto Enciso 8714f06d46fSCarlos Alberto Enciso for (LVBucket &Bucket : Buckets) { 8724f06d46fSCarlos Alberto Enciso if (std::get<3>(Bucket)) 8734f06d46fSCarlos Alberto Enciso // Already done for previous section. 8744f06d46fSCarlos Alberto Enciso continue; 8754f06d46fSCarlos Alberto Enciso if (Size == std::get<2>(Bucket)) { 8764f06d46fSCarlos Alberto Enciso // We have a match on the section size. 8774f06d46fSCarlos Alberto Enciso Group.clear(); 8784f06d46fSCarlos Alberto Enciso LVLines::iterator IterStart = DebugLines->begin() + std::get<0>(Bucket); 8794f06d46fSCarlos Alberto Enciso LVLines::iterator IterEnd = 8804f06d46fSCarlos Alberto Enciso DebugLines->begin() + std::get<1>(Bucket) + 1; 8814f06d46fSCarlos Alberto Enciso for (LVLines::iterator Iter = IterStart; Iter < IterEnd; ++Iter) 8824f06d46fSCarlos Alberto Enciso Group.push_back(*Iter); 8834f06d46fSCarlos Alberto Enciso processLines(&Group, SectionIndex, /*Function=*/nullptr); 8844f06d46fSCarlos Alberto Enciso std::get<3>(Bucket) = true; 8854f06d46fSCarlos Alberto Enciso break; 8864f06d46fSCarlos Alberto Enciso } 8874f06d46fSCarlos Alberto Enciso } 8884f06d46fSCarlos Alberto Enciso } 8894f06d46fSCarlos Alberto Enciso } 8904f06d46fSCarlos Alberto Enciso 891e7950fceSCarlos Alberto Enciso // Traverse the scopes for the given 'Function' looking for any inlined 892e7950fceSCarlos Alberto Enciso // scopes with inlined lines, which are found in 'CUInlineeLines'. 893e7950fceSCarlos Alberto Enciso void LVBinaryReader::includeInlineeLines(LVSectionIndex SectionIndex, 894e7950fceSCarlos Alberto Enciso LVScope *Function) { 895e7950fceSCarlos Alberto Enciso SmallVector<LVInlineeLine::iterator> InlineeIters; 896e7950fceSCarlos Alberto Enciso std::function<void(LVScope * Parent)> FindInlinedScopes = 897e7950fceSCarlos Alberto Enciso [&](LVScope *Parent) { 898e7950fceSCarlos Alberto Enciso if (const LVScopes *Scopes = Parent->getScopes()) 899e7950fceSCarlos Alberto Enciso for (LVScope *Scope : *Scopes) { 900e7950fceSCarlos Alberto Enciso LVInlineeLine::iterator Iter = CUInlineeLines.find(Scope); 901e7950fceSCarlos Alberto Enciso if (Iter != CUInlineeLines.end()) 902e7950fceSCarlos Alberto Enciso InlineeIters.push_back(Iter); 903e7950fceSCarlos Alberto Enciso FindInlinedScopes(Scope); 904e7950fceSCarlos Alberto Enciso } 905e7950fceSCarlos Alberto Enciso }; 906e7950fceSCarlos Alberto Enciso 907e7950fceSCarlos Alberto Enciso // Find all inlined scopes for the given 'Function'. 908e7950fceSCarlos Alberto Enciso FindInlinedScopes(Function); 909e7950fceSCarlos Alberto Enciso for (LVInlineeLine::iterator InlineeIter : InlineeIters) { 910e7950fceSCarlos Alberto Enciso LVScope *Scope = InlineeIter->first; 911e7950fceSCarlos Alberto Enciso addToSymbolTable(Scope->getLinkageName(), Scope, SectionIndex); 912e7950fceSCarlos Alberto Enciso 913e7950fceSCarlos Alberto Enciso // TODO: Convert this into a reference. 914e7950fceSCarlos Alberto Enciso LVLines *InlineeLines = InlineeIter->second.get(); 915e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 916e7950fceSCarlos Alberto Enciso dbgs() << "Inlined lines for: " << Scope->getName() << "\n"; 917e7950fceSCarlos Alberto Enciso for (const LVLine *Line : *InlineeLines) 918e7950fceSCarlos Alberto Enciso dbgs() << "[" << hexValue(Line->getAddress()) << "] " 919e7950fceSCarlos Alberto Enciso << Line->getLineNumber() << "\n"; 920e7950fceSCarlos Alberto Enciso dbgs() << format("Debug lines: %d\n", CULines.size()); 921e7950fceSCarlos Alberto Enciso for (const LVLine *Line : CULines) 922e7950fceSCarlos Alberto Enciso dbgs() << "Line address: " << hexValue(Line->getOffset()) << ", (" 923e7950fceSCarlos Alberto Enciso << Line->getLineNumber() << ")\n"; 924e7950fceSCarlos Alberto Enciso ; 925e7950fceSCarlos Alberto Enciso }); 926e7950fceSCarlos Alberto Enciso 927e7950fceSCarlos Alberto Enciso // The inlined lines must be merged using its address, in order to keep 928e7950fceSCarlos Alberto Enciso // the real order of the instructions. The inlined lines are mixed with 929e7950fceSCarlos Alberto Enciso // the other non-inlined lines. 930e7950fceSCarlos Alberto Enciso if (InlineeLines->size()) { 931e7950fceSCarlos Alberto Enciso // First address of inlinee code. 932e7950fceSCarlos Alberto Enciso uint64_t InlineeStart = (InlineeLines->front())->getAddress(); 933e7950fceSCarlos Alberto Enciso LVLines::iterator Iter = std::find_if( 934e7950fceSCarlos Alberto Enciso CULines.begin(), CULines.end(), [&](LVLine *Item) -> bool { 935e7950fceSCarlos Alberto Enciso return Item->getAddress() == InlineeStart; 936e7950fceSCarlos Alberto Enciso }); 937e7950fceSCarlos Alberto Enciso if (Iter != CULines.end()) { 938e7950fceSCarlos Alberto Enciso // 'Iter' points to the line where the inlined function is called. 939e7950fceSCarlos Alberto Enciso // Emulate the DW_AT_call_line attribute. 940e7950fceSCarlos Alberto Enciso Scope->setCallLineNumber((*Iter)->getLineNumber()); 941e7950fceSCarlos Alberto Enciso // Mark the referenced line as the start of the inlined function. 942e7950fceSCarlos Alberto Enciso // Skip the first line during the insertion, as the address and 943e7950fceSCarlos Alberto Enciso // line number as the same. Otherwise we have to erase and insert. 944e7950fceSCarlos Alberto Enciso (*Iter)->setLineNumber((*InlineeLines->begin())->getLineNumber()); 945e7950fceSCarlos Alberto Enciso ++Iter; 946e7950fceSCarlos Alberto Enciso CULines.insert(Iter, InlineeLines->begin() + 1, InlineeLines->end()); 947e7950fceSCarlos Alberto Enciso } 948e7950fceSCarlos Alberto Enciso } 949e7950fceSCarlos Alberto Enciso 950e7950fceSCarlos Alberto Enciso // Remove this set of lines from the container; each inlined function 951e7950fceSCarlos Alberto Enciso // creates an unique set of lines. Remove only the created container. 952e7950fceSCarlos Alberto Enciso CUInlineeLines.erase(InlineeIter); 953e7950fceSCarlos Alberto Enciso InlineeLines->clear(); 954e7950fceSCarlos Alberto Enciso } 955e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 956e7950fceSCarlos Alberto Enciso dbgs() << "Merged Inlined lines for: " << Function->getName() << "\n"; 957e7950fceSCarlos Alberto Enciso dbgs() << format("Debug lines: %d\n", CULines.size()); 958e7950fceSCarlos Alberto Enciso for (const LVLine *Line : CULines) 959e7950fceSCarlos Alberto Enciso dbgs() << "Line address: " << hexValue(Line->getOffset()) << ", (" 960e7950fceSCarlos Alberto Enciso << Line->getLineNumber() << ")\n"; 961e7950fceSCarlos Alberto Enciso ; 962e7950fceSCarlos Alberto Enciso }); 963e7950fceSCarlos Alberto Enciso } 964e7950fceSCarlos Alberto Enciso 9654f06d46fSCarlos Alberto Enciso void LVBinaryReader::print(raw_ostream &OS) const { 9664f06d46fSCarlos Alberto Enciso OS << "LVBinaryReader\n"; 9674f06d46fSCarlos Alberto Enciso LLVM_DEBUG(dbgs() << "PrintReader\n"); 9684f06d46fSCarlos Alberto Enciso } 969