10b57cec5SDimitry Andric //===- DWARFDebugAbbrev.cpp -----------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 100b57cec5SDimitry Andric #include "llvm/Support/Format.h" 110b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 120b57cec5SDimitry Andric #include <algorithm> 130b57cec5SDimitry Andric #include <cinttypes> 140b57cec5SDimitry Andric #include <cstdint> 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric using namespace llvm; 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() { 190b57cec5SDimitry Andric clear(); 200b57cec5SDimitry Andric } 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric void DWARFAbbreviationDeclarationSet::clear() { 230b57cec5SDimitry Andric Offset = 0; 240b57cec5SDimitry Andric FirstAbbrCode = 0; 250b57cec5SDimitry Andric Decls.clear(); 260b57cec5SDimitry Andric } 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data, 298bcb0991SDimitry Andric uint64_t *OffsetPtr) { 300b57cec5SDimitry Andric clear(); 318bcb0991SDimitry Andric const uint64_t BeginOffset = *OffsetPtr; 320b57cec5SDimitry Andric Offset = BeginOffset; 330b57cec5SDimitry Andric DWARFAbbreviationDeclaration AbbrDecl; 340b57cec5SDimitry Andric uint32_t PrevAbbrCode = 0; 350b57cec5SDimitry Andric while (AbbrDecl.extract(Data, OffsetPtr)) { 360b57cec5SDimitry Andric if (FirstAbbrCode == 0) { 370b57cec5SDimitry Andric FirstAbbrCode = AbbrDecl.getCode(); 380b57cec5SDimitry Andric } else { 390b57cec5SDimitry Andric if (PrevAbbrCode + 1 != AbbrDecl.getCode()) { 400b57cec5SDimitry Andric // Codes are not consecutive, can't do O(1) lookups. 410b57cec5SDimitry Andric FirstAbbrCode = UINT32_MAX; 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric } 440b57cec5SDimitry Andric PrevAbbrCode = AbbrDecl.getCode(); 450b57cec5SDimitry Andric Decls.push_back(std::move(AbbrDecl)); 460b57cec5SDimitry Andric } 470b57cec5SDimitry Andric return BeginOffset != *OffsetPtr; 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const { 510b57cec5SDimitry Andric for (const auto &Decl : Decls) 520b57cec5SDimitry Andric Decl.dump(OS); 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric const DWARFAbbreviationDeclaration * 560b57cec5SDimitry Andric DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration( 570b57cec5SDimitry Andric uint32_t AbbrCode) const { 580b57cec5SDimitry Andric if (FirstAbbrCode == UINT32_MAX) { 590b57cec5SDimitry Andric for (const auto &Decl : Decls) { 600b57cec5SDimitry Andric if (Decl.getCode() == AbbrCode) 610b57cec5SDimitry Andric return &Decl; 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric return nullptr; 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size()) 660b57cec5SDimitry Andric return nullptr; 670b57cec5SDimitry Andric return &Decls[AbbrCode - FirstAbbrCode]; 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 70*fe6060f1SDimitry Andric std::string DWARFAbbreviationDeclarationSet::getCodeRange() const { 71*fe6060f1SDimitry Andric // Create a sorted list of all abbrev codes. 72*fe6060f1SDimitry Andric std::vector<uint32_t> Codes; 73*fe6060f1SDimitry Andric Codes.reserve(Decls.size()); 74*fe6060f1SDimitry Andric for (const auto &Decl : Decls) 75*fe6060f1SDimitry Andric Codes.push_back(Decl.getCode()); 76*fe6060f1SDimitry Andric 77*fe6060f1SDimitry Andric std::string Buffer = ""; 78*fe6060f1SDimitry Andric raw_string_ostream Stream(Buffer); 79*fe6060f1SDimitry Andric // Each iteration through this loop represents a single contiguous range in 80*fe6060f1SDimitry Andric // the set of codes. 81*fe6060f1SDimitry Andric for (auto Current = Codes.begin(), End = Codes.end(); Current != End;) { 82*fe6060f1SDimitry Andric uint32_t RangeStart = *Current; 83*fe6060f1SDimitry Andric // Add the current range start. 84*fe6060f1SDimitry Andric Stream << *Current; 85*fe6060f1SDimitry Andric uint32_t RangeEnd = RangeStart; 86*fe6060f1SDimitry Andric // Find the end of the current range. 87*fe6060f1SDimitry Andric while (++Current != End && *Current == RangeEnd + 1) 88*fe6060f1SDimitry Andric ++RangeEnd; 89*fe6060f1SDimitry Andric // If there is more than one value in the range, add the range end too. 90*fe6060f1SDimitry Andric if (RangeStart != RangeEnd) 91*fe6060f1SDimitry Andric Stream << "-" << RangeEnd; 92*fe6060f1SDimitry Andric // If there is at least one more range, add a separator. 93*fe6060f1SDimitry Andric if (Current != End) 94*fe6060f1SDimitry Andric Stream << ", "; 95*fe6060f1SDimitry Andric } 96*fe6060f1SDimitry Andric return Buffer; 97*fe6060f1SDimitry Andric } 98*fe6060f1SDimitry Andric 990b57cec5SDimitry Andric DWARFDebugAbbrev::DWARFDebugAbbrev() { clear(); } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric void DWARFDebugAbbrev::clear() { 1020b57cec5SDimitry Andric AbbrDeclSets.clear(); 1030b57cec5SDimitry Andric PrevAbbrOffsetPos = AbbrDeclSets.end(); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric void DWARFDebugAbbrev::extract(DataExtractor Data) { 1070b57cec5SDimitry Andric clear(); 1080b57cec5SDimitry Andric this->Data = Data; 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric void DWARFDebugAbbrev::parse() const { 1120b57cec5SDimitry Andric if (!Data) 1130b57cec5SDimitry Andric return; 1148bcb0991SDimitry Andric uint64_t Offset = 0; 1150b57cec5SDimitry Andric auto I = AbbrDeclSets.begin(); 1160b57cec5SDimitry Andric while (Data->isValidOffset(Offset)) { 1170b57cec5SDimitry Andric while (I != AbbrDeclSets.end() && I->first < Offset) 1180b57cec5SDimitry Andric ++I; 1198bcb0991SDimitry Andric uint64_t CUAbbrOffset = Offset; 1200b57cec5SDimitry Andric DWARFAbbreviationDeclarationSet AbbrDecls; 1210b57cec5SDimitry Andric if (!AbbrDecls.extract(*Data, &Offset)) 1220b57cec5SDimitry Andric break; 1230b57cec5SDimitry Andric AbbrDeclSets.insert(I, std::make_pair(CUAbbrOffset, std::move(AbbrDecls))); 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric Data = None; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric void DWARFDebugAbbrev::dump(raw_ostream &OS) const { 1290b57cec5SDimitry Andric parse(); 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric if (AbbrDeclSets.empty()) { 1320b57cec5SDimitry Andric OS << "< EMPTY >\n"; 1330b57cec5SDimitry Andric return; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric for (const auto &I : AbbrDeclSets) { 1370b57cec5SDimitry Andric OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", I.first); 1380b57cec5SDimitry Andric I.second.dump(OS); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric const DWARFAbbreviationDeclarationSet* 1430b57cec5SDimitry Andric DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const { 1440b57cec5SDimitry Andric const auto End = AbbrDeclSets.end(); 1450b57cec5SDimitry Andric if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) { 1460b57cec5SDimitry Andric return &(PrevAbbrOffsetPos->second); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric const auto Pos = AbbrDeclSets.find(CUAbbrOffset); 1500b57cec5SDimitry Andric if (Pos != End) { 1510b57cec5SDimitry Andric PrevAbbrOffsetPos = Pos; 1520b57cec5SDimitry Andric return &(Pos->second); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric if (Data && CUAbbrOffset < Data->getData().size()) { 1568bcb0991SDimitry Andric uint64_t Offset = CUAbbrOffset; 1570b57cec5SDimitry Andric DWARFAbbreviationDeclarationSet AbbrDecls; 1580b57cec5SDimitry Andric if (!AbbrDecls.extract(*Data, &Offset)) 1590b57cec5SDimitry Andric return nullptr; 1600b57cec5SDimitry Andric PrevAbbrOffsetPos = 1610b57cec5SDimitry Andric AbbrDeclSets.insert(std::make_pair(CUAbbrOffset, std::move(AbbrDecls))) 1620b57cec5SDimitry Andric .first; 1630b57cec5SDimitry Andric return &PrevAbbrOffsetPos->second; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric return nullptr; 1670b57cec5SDimitry Andric } 168