]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
Upgrade LDNS to 1.7.0.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / SymbolFile / DWARF / DWARFDebugInfo.cpp
1 //===-- DWARFDebugInfo.cpp --------------------------------------*- C++ -*-===//
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 "SymbolFileDWARF.h"
11
12 #include <algorithm>
13 #include <set>
14
15 #include "lldb/Host/PosixApi.h"
16 #include "lldb/Symbol/ObjectFile.h"
17 #include "lldb/Utility/RegularExpression.h"
18 #include "lldb/Utility/Stream.h"
19
20 #include "DWARFCompileUnit.h"
21 #include "DWARFDebugAranges.h"
22 #include "DWARFDebugAranges.h"
23 #include "DWARFDebugInfo.h"
24 #include "DWARFDebugInfoEntry.h"
25 #include "DWARFFormValue.h"
26 #include "LogChannelDWARF.h"
27
28 using namespace lldb;
29 using namespace lldb_private;
30 using namespace std;
31
32 //----------------------------------------------------------------------
33 // Constructor
34 //----------------------------------------------------------------------
35 DWARFDebugInfo::DWARFDebugInfo()
36     : m_dwarf2Data(NULL), m_compile_units(), m_cu_aranges_ap() {}
37
38 //----------------------------------------------------------------------
39 // SetDwarfData
40 //----------------------------------------------------------------------
41 void DWARFDebugInfo::SetDwarfData(SymbolFileDWARF *dwarf2Data) {
42   m_dwarf2Data = dwarf2Data;
43   m_compile_units.clear();
44 }
45
46 DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() {
47   if (m_cu_aranges_ap.get() == NULL && m_dwarf2Data) {
48     Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
49
50     m_cu_aranges_ap.reset(new DWARFDebugAranges());
51     const DWARFDataExtractor &debug_aranges_data =
52         m_dwarf2Data->get_debug_aranges_data();
53     if (debug_aranges_data.GetByteSize() > 0) {
54       if (log)
55         log->Printf(
56             "DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" from "
57             ".debug_aranges",
58             m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
59       m_cu_aranges_ap->Extract(debug_aranges_data);
60     }
61
62     // Make a list of all CUs represented by the arange data in the file.
63     std::set<dw_offset_t> cus_with_data;
64     for (size_t n = 0; n < m_cu_aranges_ap.get()->GetNumRanges(); n++) {
65       dw_offset_t offset = m_cu_aranges_ap.get()->OffsetAtIndex(n);
66       if (offset != DW_INVALID_OFFSET)
67         cus_with_data.insert(offset);
68     }
69
70     // Manually build arange data for everything that wasn't in the
71     // .debug_aranges table.
72     bool printed = false;
73     const size_t num_compile_units = GetNumCompileUnits();
74     for (size_t idx = 0; idx < num_compile_units; ++idx) {
75       DWARFCompileUnit *cu = GetCompileUnitAtIndex(idx);
76
77       dw_offset_t offset = cu->GetOffset();
78       if (cus_with_data.find(offset) == cus_with_data.end()) {
79         if (log) {
80           if (!printed)
81             log->Printf(
82                 "DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing",
83                 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
84           printed = true;
85         }
86         cu->BuildAddressRangeTable(m_dwarf2Data, m_cu_aranges_ap.get());
87       }
88     }
89
90     const bool minimize = true;
91     m_cu_aranges_ap->Sort(minimize);
92   }
93   return *m_cu_aranges_ap.get();
94 }
95
96 void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() {
97   if (m_compile_units.empty()) {
98     if (m_dwarf2Data != NULL) {
99       lldb::offset_t offset = 0;
100       DWARFCompileUnitSP cu_sp;
101       while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, &offset))) {
102         m_compile_units.push_back(cu_sp);
103
104         offset = cu_sp->GetNextCompileUnitOffset();
105       }
106     }
107   }
108 }
109
110 size_t DWARFDebugInfo::GetNumCompileUnits() {
111   ParseCompileUnitHeadersIfNeeded();
112   return m_compile_units.size();
113 }
114
115 DWARFCompileUnit *DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) {
116   DWARFCompileUnit *cu = NULL;
117   if (idx < GetNumCompileUnits())
118     cu = m_compile_units[idx].get();
119   return cu;
120 }
121
122 bool DWARFDebugInfo::ContainsCompileUnit(const DWARFCompileUnit *cu) const {
123   // Not a verify efficient function, but it is handy for use in assertions
124   // to make sure that a compile unit comes from a debug information file.
125   CompileUnitColl::const_iterator end_pos = m_compile_units.end();
126   CompileUnitColl::const_iterator pos;
127
128   for (pos = m_compile_units.begin(); pos != end_pos; ++pos) {
129     if (pos->get() == cu)
130       return true;
131   }
132   return false;
133 }
134
135 bool DWARFDebugInfo::OffsetLessThanCompileUnitOffset(
136     dw_offset_t offset, const DWARFCompileUnitSP &cu_sp) {
137   return offset < cu_sp->GetOffset();
138 }
139
140 DWARFCompileUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset,
141                                                  uint32_t *idx_ptr) {
142   DWARFCompileUnitSP cu_sp;
143   uint32_t cu_idx = DW_INVALID_INDEX;
144   if (cu_offset != DW_INVALID_OFFSET) {
145     ParseCompileUnitHeadersIfNeeded();
146
147     // Watch out for single compile unit executable as they are pretty common
148     const size_t num_cus = m_compile_units.size();
149     if (num_cus == 1) {
150       if (m_compile_units[0]->GetOffset() == cu_offset) {
151         cu_sp = m_compile_units[0];
152         cu_idx = 0;
153       }
154     } else if (num_cus) {
155       CompileUnitColl::const_iterator end_pos = m_compile_units.end();
156       CompileUnitColl::const_iterator begin_pos = m_compile_units.begin();
157       CompileUnitColl::const_iterator pos = std::upper_bound(
158           begin_pos, end_pos, cu_offset, OffsetLessThanCompileUnitOffset);
159       if (pos != begin_pos) {
160         --pos;
161         if ((*pos)->GetOffset() == cu_offset) {
162           cu_sp = *pos;
163           cu_idx = std::distance(begin_pos, pos);
164         }
165       }
166     }
167   }
168   if (idx_ptr)
169     *idx_ptr = cu_idx;
170   return cu_sp.get();
171 }
172
173 DWARFCompileUnit *DWARFDebugInfo::GetCompileUnit(const DIERef &die_ref) {
174   if (die_ref.cu_offset == DW_INVALID_OFFSET)
175     return GetCompileUnitContainingDIEOffset(die_ref.die_offset);
176   else
177     return GetCompileUnit(die_ref.cu_offset);
178 }
179
180 DWARFCompileUnit *
181 DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset) {
182   ParseCompileUnitHeadersIfNeeded();
183
184   DWARFCompileUnitSP cu_sp;
185
186   // Watch out for single compile unit executable as they are pretty common
187   const size_t num_cus = m_compile_units.size();
188   if (num_cus == 1) {
189     if (m_compile_units[0]->ContainsDIEOffset(die_offset))
190       return m_compile_units[0].get();
191   } else if (num_cus) {
192     CompileUnitColl::const_iterator end_pos = m_compile_units.end();
193     CompileUnitColl::const_iterator begin_pos = m_compile_units.begin();
194     CompileUnitColl::const_iterator pos = std::upper_bound(
195         begin_pos, end_pos, die_offset, OffsetLessThanCompileUnitOffset);
196     if (pos != begin_pos) {
197       --pos;
198       if ((*pos)->ContainsDIEOffset(die_offset))
199         return (*pos).get();
200     }
201   }
202
203   return nullptr;
204 }
205
206 DWARFDIE
207 DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset) {
208   DWARFCompileUnit *cu = GetCompileUnitContainingDIEOffset(die_offset);
209   if (cu)
210     return cu->GetDIE(die_offset);
211   return DWARFDIE();
212 }
213
214 //----------------------------------------------------------------------
215 // GetDIE()
216 //
217 // Get the DIE (Debug Information Entry) with the specified offset.
218 //----------------------------------------------------------------------
219 DWARFDIE
220 DWARFDebugInfo::GetDIE(const DIERef &die_ref) {
221   DWARFCompileUnit *cu = GetCompileUnit(die_ref);
222   if (cu)
223     return cu->GetDIE(die_ref.die_offset);
224   return DWARFDIE(); // Not found
225 }
226
227 //----------------------------------------------------------------------
228 // Parse
229 //
230 // Parses the .debug_info section and uses the .debug_abbrev section
231 // and various other sections in the SymbolFileDWARF class and calls the
232 // supplied callback function each time a compile unit header, or debug
233 // information entry is successfully parsed. This function can be used
234 // for different tasks such as parsing the file contents into a
235 // structured data, dumping, verifying and much more.
236 //----------------------------------------------------------------------
237 void DWARFDebugInfo::Parse(SymbolFileDWARF *dwarf2Data, Callback callback,
238                            void *userData) {
239   if (dwarf2Data) {
240     lldb::offset_t offset = 0;
241     uint32_t depth = 0;
242     DWARFDebugInfoEntry die;
243
244     DWARFCompileUnitSP cu;
245     while ((cu = DWARFCompileUnit::Extract(dwarf2Data, &offset))) {
246       const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset();
247
248       depth = 0;
249       // Call the callback function with no DIE pointer for the compile unit
250       // and get the offset that we are to continue to parse from
251       offset = callback(dwarf2Data, cu.get(), NULL, offset, depth, userData);
252
253       // Make sure we are within our compile unit
254       if (offset < next_cu_offset) {
255         // We are in our compile unit, parse starting at the offset
256         // we were told to parse
257         bool done = false;
258         while (!done && die.Extract(dwarf2Data, cu.get(), &offset)) {
259           // Call the callback function with DIE pointer that falls within the
260           // compile unit
261           offset =
262               callback(dwarf2Data, cu.get(), &die, offset, depth, userData);
263
264           if (die.IsNULL()) {
265             if (depth)
266               --depth;
267             else
268               done = true; // We are done with this compile unit!
269           } else if (die.HasChildren())
270             ++depth;
271         }
272       }
273
274       // Make sure the offset returned is valid, and if not stop parsing.
275       // Returning DW_INVALID_OFFSET from this callback is a good way to end
276       // all parsing
277       if (!dwarf2Data->get_debug_info_data().ValidOffset(offset))
278         break;
279
280       // Make sure we start on a proper
281       offset = next_cu_offset;
282     }
283   }
284 }
285
286 typedef struct DumpInfo {
287   DumpInfo(Stream *init_strm, uint32_t off, uint32_t depth)
288       : strm(init_strm), die_offset(off), recurse_depth(depth),
289         found_depth(UINT32_MAX), found_die(false), ancestors() {}
290   Stream *strm;
291   const uint32_t die_offset;
292   const uint32_t recurse_depth;
293   uint32_t found_depth;
294   bool found_die;
295   std::vector<DWARFDebugInfoEntry> ancestors;
296
297   DISALLOW_COPY_AND_ASSIGN(DumpInfo);
298 } DumpInfo;
299
300 //----------------------------------------------------------------------
301 // DumpCallback
302 //
303 // A callback function for the static DWARFDebugInfo::Parse() function
304 // that gets called each time a compile unit header or debug information
305 // entry is successfully parsed.
306 //
307 // This function dump DWARF information and obey recurse depth and
308 // whether a single DIE is to be dumped (or all of the data).
309 //----------------------------------------------------------------------
310 static dw_offset_t DumpCallback(SymbolFileDWARF *dwarf2Data,
311                                 DWARFCompileUnit *cu, DWARFDebugInfoEntry *die,
312                                 const dw_offset_t next_offset,
313                                 const uint32_t curr_depth, void *userData) {
314   DumpInfo *dumpInfo = (DumpInfo *)userData;
315   Stream *s = dumpInfo->strm;
316   bool show_parents =
317       s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors);
318
319   if (die) {
320     // Are we dumping everything?
321     if (dumpInfo->die_offset == DW_INVALID_OFFSET) {
322       // Yes we are dumping everything. Obey our recurse level though
323       if (curr_depth < dumpInfo->recurse_depth)
324         die->Dump(dwarf2Data, cu, *s, 0);
325     } else {
326       // We are dumping a specific DIE entry by offset
327       if (dumpInfo->die_offset == die->GetOffset()) {
328         // We found the DIE we were looking for, dump it!
329         if (show_parents) {
330           s->SetIndentLevel(0);
331           const uint32_t num_ancestors = dumpInfo->ancestors.size();
332           if (num_ancestors > 0) {
333             for (uint32_t i = 0; i < num_ancestors - 1; ++i) {
334               dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0);
335               s->IndentMore();
336             }
337           }
338         }
339
340         dumpInfo->found_depth = curr_depth;
341
342         die->Dump(dwarf2Data, cu, *s, 0);
343
344         // Note that we found the DIE we were looking for
345         dumpInfo->found_die = true;
346
347         // Since we are dumping a single DIE, if there are no children we are
348         // done!
349         if (!die->HasChildren() || dumpInfo->recurse_depth == 0)
350           return DW_INVALID_OFFSET; // Return an invalid address to end parsing
351       } else if (dumpInfo->found_die) {
352         // Are we done with all the children?
353         if (curr_depth <= dumpInfo->found_depth)
354           return DW_INVALID_OFFSET;
355
356         // We have already found our DIE and are printing it's children. Obey
357         // our recurse depth and return an invalid offset if we get done
358         // dumping all of the children
359         if (dumpInfo->recurse_depth == UINT32_MAX ||
360             curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth)
361           die->Dump(dwarf2Data, cu, *s, 0);
362       } else if (dumpInfo->die_offset > die->GetOffset()) {
363         if (show_parents)
364           dumpInfo->ancestors.back() = *die;
365       }
366     }
367
368     // Keep up with our indent level
369     if (die->IsNULL()) {
370       if (show_parents)
371         dumpInfo->ancestors.pop_back();
372
373       if (curr_depth <= 1)
374         return cu->GetNextCompileUnitOffset();
375       else
376         s->IndentLess();
377     } else if (die->HasChildren()) {
378       if (show_parents) {
379         DWARFDebugInfoEntry null_die;
380         dumpInfo->ancestors.push_back(null_die);
381       }
382       s->IndentMore();
383     }
384   } else {
385     if (cu == NULL)
386       s->PutCString("NULL - cu");
387     // We have a compile unit, reset our indent level to zero just in case
388     s->SetIndentLevel(0);
389
390     // See if we are dumping everything?
391     if (dumpInfo->die_offset == DW_INVALID_OFFSET) {
392       // We are dumping everything
393       if (cu) {
394         cu->Dump(s);
395         return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this
396                                         // Compile Unit
397       } else {
398         return DW_INVALID_OFFSET;
399       }
400     } else {
401       if (show_parents) {
402         dumpInfo->ancestors.clear();
403         dumpInfo->ancestors.resize(1);
404       }
405
406       // We are dumping only a single DIE possibly with it's children and
407       // we must find it's compile unit before we can dump it properly
408       if (cu && dumpInfo->die_offset < cu->GetFirstDIEOffset()) {
409         // Not found, maybe the DIE offset provided wasn't correct?
410         //  *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << "
411         //  was not found." << endl;
412         return DW_INVALID_OFFSET;
413       } else {
414         // See if the DIE is in this compile unit?
415         if (cu && dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) {
416           return next_offset;
417           //  // We found our compile unit that contains our DIE, just skip to
418           //  dumping the requested DIE...
419           //  return dumpInfo->die_offset;
420         } else {
421           // Skip to the next compile unit as the DIE isn't in the current one!
422           if (cu) {
423             return cu->GetNextCompileUnitOffset();
424           } else {
425             return DW_INVALID_OFFSET;
426           }
427         }
428       }
429     }
430   }
431
432   // Just return the current offset to parse the next CU or DIE entry
433   return next_offset;
434 }
435
436 //----------------------------------------------------------------------
437 // Dump
438 //
439 // Dump the information in the .debug_info section to the specified
440 // ostream. If die_offset is valid, a single DIE will be dumped. If the
441 // die_offset is invalid, all the DWARF information will be dumped. Both
442 // cases will obey a "recurse_depth" or how deep to traverse into the
443 // children of each DIE entry. A recurse_depth of zero will dump all
444 // compile unit headers. A recurse_depth of 1 will dump all compile unit
445 // headers and the DW_TAG_compile unit tags. A depth of 2 will also
446 // dump all types and functions.
447 //----------------------------------------------------------------------
448 void DWARFDebugInfo::Dump(Stream *s, SymbolFileDWARF *dwarf2Data,
449                           const uint32_t die_offset,
450                           const uint32_t recurse_depth) {
451   DumpInfo dumpInfo(s, die_offset, recurse_depth);
452   s->PutCString(".debug_info contents");
453   if (dwarf2Data->get_debug_info_data().GetByteSize() > 0) {
454     if (die_offset == DW_INVALID_OFFSET)
455       s->PutCString(":\n");
456     else {
457       s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset);
458       if (recurse_depth != UINT32_MAX)
459         s->Printf(" recursing %u levels deep.", recurse_depth);
460       s->EOL();
461     }
462   } else {
463     s->PutCString(": < EMPTY >\n");
464     return;
465   }
466   DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo);
467 }
468
469 //----------------------------------------------------------------------
470 // Dump
471 //
472 // Dump the contents of this DWARFDebugInfo object as has been parsed
473 // and/or modified after it has been parsed.
474 //----------------------------------------------------------------------
475 void DWARFDebugInfo::Dump(Stream *s, const uint32_t die_offset,
476                           const uint32_t recurse_depth) {
477   DumpInfo dumpInfo(s, die_offset, recurse_depth);
478
479   s->PutCString("Dumping .debug_info section from internal representation\n");
480
481   CompileUnitColl::const_iterator pos;
482   uint32_t curr_depth = 0;
483   ParseCompileUnitHeadersIfNeeded();
484   for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos) {
485     DWARFCompileUnit *cu = pos->get();
486     DumpCallback(m_dwarf2Data, cu, NULL, 0, curr_depth, &dumpInfo);
487
488     const DWARFDIE die = cu->DIE();
489     if (die)
490       die.Dump(s, recurse_depth);
491   }
492 }