summaryrefslogtreecommitdiff
path: root/lib/DebugInfo/DWARFDebugAbbrev.cpp
blob: 6e6c37e309454158568ace3c6b68819db4bba619 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//===-- DWARFDebugAbbrev.cpp ----------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "DWARFDebugAbbrev.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

bool DWARFAbbreviationDeclarationSet::extract(DataExtractor data,
                                              uint32_t* offset_ptr) {
  const uint32_t beginOffset = *offset_ptr;
  Offset = beginOffset;
  clear();
  DWARFAbbreviationDeclaration abbrevDeclaration;
  uint32_t prevAbbrAode = 0;
  while (abbrevDeclaration.extract(data, offset_ptr)) {
    Decls.push_back(abbrevDeclaration);
    if (IdxOffset == 0) {
      IdxOffset = abbrevDeclaration.getCode();
    } else {
      if (prevAbbrAode + 1 != abbrevDeclaration.getCode())
        IdxOffset = UINT32_MAX;// Out of order indexes, we can't do O(1) lookups
    }
    prevAbbrAode = abbrevDeclaration.getCode();
  }
  return beginOffset != *offset_ptr;
}

void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
  for (unsigned i = 0, e = Decls.size(); i != e; ++i)
    Decls[i].dump(OS);
}

const DWARFAbbreviationDeclaration*
DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(uint32_t abbrCode)
  const {
  if (IdxOffset == UINT32_MAX) {
    DWARFAbbreviationDeclarationCollConstIter pos;
    DWARFAbbreviationDeclarationCollConstIter end = Decls.end();
    for (pos = Decls.begin(); pos != end; ++pos) {
      if (pos->getCode() == abbrCode)
        return &(*pos);
    }
  } else {
    uint32_t idx = abbrCode - IdxOffset;
    if (idx < Decls.size())
      return &Decls[idx];
  }
  return NULL;
}

DWARFDebugAbbrev::DWARFDebugAbbrev() :
  AbbrevCollMap(),
  PrevAbbrOffsetPos(AbbrevCollMap.end()) {}


void DWARFDebugAbbrev::parse(DataExtractor data) {
  uint32_t offset = 0;

  while (data.isValidOffset(offset)) {
    uint32_t initial_cu_offset = offset;
    DWARFAbbreviationDeclarationSet abbrevDeclSet;

    if (abbrevDeclSet.extract(data, &offset))
      AbbrevCollMap[initial_cu_offset] = abbrevDeclSet;
    else
      break;
  }
  PrevAbbrOffsetPos = AbbrevCollMap.end();
}

void DWARFDebugAbbrev::dump(raw_ostream &OS) const {
  if (AbbrevCollMap.empty()) {
    OS << "< EMPTY >\n";
    return;
  }

  DWARFAbbreviationDeclarationCollMapConstIter pos;
  for (pos = AbbrevCollMap.begin(); pos != AbbrevCollMap.end(); ++pos) {
    OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", pos->first);
    pos->second.dump(OS);
  }
}

const DWARFAbbreviationDeclarationSet*
DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const {
  DWARFAbbreviationDeclarationCollMapConstIter end = AbbrevCollMap.end();
  DWARFAbbreviationDeclarationCollMapConstIter pos;
  if (PrevAbbrOffsetPos != end &&
      PrevAbbrOffsetPos->first == cu_abbr_offset) {
    return &(PrevAbbrOffsetPos->second);
  } else {
    pos = AbbrevCollMap.find(cu_abbr_offset);
    PrevAbbrOffsetPos = pos;
  }

  if (pos != AbbrevCollMap.end())
    return &(pos->second);
  return NULL;
}