a4e0d8eae43c49b34ec3bcc24089c30ceed3a859
[oota-llvm.git] / lib / DebugInfo / DWARFContext.cpp
1 //===-- DWARFContext.cpp --------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "DWARFContext.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/Support/Dwarf.h"
13 #include "llvm/Support/Format.h"
14 #include "llvm/Support/Path.h"
15 #include "llvm/Support/raw_ostream.h"
16 #include <algorithm>
17 using namespace llvm;
18 using namespace dwarf;
19
20 void DWARFContext::dump(raw_ostream &OS) {
21   OS << ".debug_abbrev contents:\n";
22   getDebugAbbrev()->dump(OS);
23
24   OS << "\n.debug_info contents:\n";
25   for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i)
26     getCompileUnitAtIndex(i)->dump(OS);
27
28   OS << "\n.debug_aranges contents:\n";
29   DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
30   uint32_t offset = 0;
31   DWARFDebugArangeSet set;
32   while (set.extract(arangesData, &offset))
33     set.dump(OS);
34
35   OS << "\n.debug_lines contents:\n";
36   for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) {
37     DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
38     unsigned stmtOffset =
39       cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
40                                                            -1U);
41     if (stmtOffset != -1U) {
42       DataExtractor lineData(getLineSection(), isLittleEndian(),
43                              cu->getAddressByteSize());
44       DWARFDebugLine::DumpingState state(OS);
45       DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state);
46     }
47   }
48
49   OS << "\n.debug_str contents:\n";
50   DataExtractor strData(getStringSection(), isLittleEndian(), 0);
51   offset = 0;
52   uint32_t lastOffset = 0;
53   while (const char *s = strData.getCStr(&offset)) {
54     OS << format("0x%8.8x: \"%s\"\n", lastOffset, s);
55     lastOffset = offset;
56   }
57 }
58
59 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
60   if (Abbrev)
61     return Abbrev.get();
62
63   DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0);
64
65   Abbrev.reset(new DWARFDebugAbbrev());
66   Abbrev->parse(abbrData);
67   return Abbrev.get();
68 }
69
70 const DWARFDebugAranges *DWARFContext::getDebugAranges() {
71   if (Aranges)
72     return Aranges.get();
73
74   DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
75
76   Aranges.reset(new DWARFDebugAranges());
77   Aranges->extract(arangesData);
78   if (Aranges->isEmpty()) // No aranges in file, generate them from the DIEs.
79     Aranges->generate(this);
80   return Aranges.get();
81 }
82
83 const DWARFDebugLine::LineTable *
84 DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
85   if (!Line)
86     Line.reset(new DWARFDebugLine());
87
88   unsigned stmtOffset =
89     cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
90                                                          -1U);
91   if (stmtOffset == -1U)
92     return 0; // No line table for this compile unit.
93
94   // See if the line table is cached.
95   if (const DWARFDebugLine::LineTable *lt = Line->getLineTable(stmtOffset))
96     return lt;
97
98   // We have to parse it first.
99   DataExtractor lineData(getLineSection(), isLittleEndian(),
100                          cu->getAddressByteSize());
101   return Line->getOrParseLineTable(lineData, stmtOffset);
102 }
103
104 void DWARFContext::parseCompileUnits() {
105   uint32_t offset = 0;
106   const DataExtractor &debug_info_data = DataExtractor(getInfoSection(),
107                                                        isLittleEndian(), 0);
108   while (debug_info_data.isValidOffset(offset)) {
109     CUs.push_back(DWARFCompileUnit(*this));
110     if (!CUs.back().extract(debug_info_data, &offset)) {
111       CUs.pop_back();
112       break;
113     }
114
115     offset = CUs.back().getNextCompileUnitOffset();
116   }
117 }
118
119 namespace {
120   struct OffsetComparator {
121     bool operator()(const DWARFCompileUnit &LHS,
122                     const DWARFCompileUnit &RHS) const {
123       return LHS.getOffset() < RHS.getOffset();
124     }
125     bool operator()(const DWARFCompileUnit &LHS, uint32_t RHS) const {
126       return LHS.getOffset() < RHS;
127     }
128     bool operator()(uint32_t LHS, const DWARFCompileUnit &RHS) const {
129       return LHS < RHS.getOffset();
130     }
131   };
132 }
133
134 DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t offset) {
135   if (CUs.empty())
136     parseCompileUnits();
137
138   DWARFCompileUnit *i = std::lower_bound(CUs.begin(), CUs.end(), offset,
139                                          OffsetComparator());
140   if (i != CUs.end())
141     return &*i;
142   return 0;
143 }
144
145 DILineInfo DWARFContext::getLineInfoForAddress(uint64_t address,
146     DILineInfoSpecifier specifier) {
147   // First, get the offset of the compile unit.
148   uint32_t cuOffset = getDebugAranges()->findAddress(address);
149   // Retrieve the compile unit.
150   DWARFCompileUnit *cu = getCompileUnitForOffset(cuOffset);
151   if (!cu)
152     return DILineInfo();
153   SmallString<16> fileName("<invalid>");
154   SmallString<16> functionName("<invalid>");
155   uint32_t line = 0;
156   uint32_t column = 0;
157   if (specifier.needs(DILineInfoSpecifier::FunctionName)) {
158     const DWARFDebugInfoEntryMinimal *function_die =
159         cu->getFunctionDIEForAddress(address);
160     if (function_die) {
161       if (const char *name = function_die->getSubprogramName(cu))
162         functionName = name;
163     }
164   }
165   if (specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
166     // Get the line table for this compile unit.
167     const DWARFDebugLine::LineTable *lineTable = getLineTableForCompileUnit(cu);
168     if (lineTable) {
169       // Get the index of the row we're looking for in the line table.
170       uint64_t hiPC = cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(
171           cu, DW_AT_high_pc, -1ULL);
172       uint32_t rowIndex = lineTable->lookupAddress(address, hiPC);
173       if (rowIndex != -1U) {
174         const DWARFDebugLine::Row &row = lineTable->Rows[rowIndex];
175         // Take file/line info from the line table.
176         const DWARFDebugLine::FileNameEntry &fileNameEntry =
177             lineTable->Prologue.FileNames[row.File - 1];
178         fileName = fileNameEntry.Name;
179         if (specifier.needs(DILineInfoSpecifier::AbsoluteFilePath) &&
180             sys::path::is_relative(fileName.str())) {
181           // Append include directory of file (if it is present in line table)
182           // and compilation directory of compile unit to make path absolute.
183           const char *includeDir = 0;
184           if (uint64_t includeDirIndex = fileNameEntry.DirIdx) {
185             includeDir = lineTable->Prologue
186                          .IncludeDirectories[includeDirIndex - 1];
187           }
188           SmallString<16> absFileName;
189           if (includeDir == 0 || sys::path::is_relative(includeDir)) {
190             if (const char *compilationDir = cu->getCompilationDir())
191               sys::path::append(absFileName, compilationDir);
192           }
193           if (includeDir) {
194             sys::path::append(absFileName, includeDir);
195           }
196           sys::path::append(absFileName, fileName.str());
197           fileName = absFileName;
198         }
199         line = row.Line;
200         column = row.Column;
201       }
202     }
203   }
204   return DILineInfo(fileName, functionName, line, column);
205 }
206
207 void DWARFContextInMemory::anchor() { }