xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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