blob: c8fef6504f295e9d5c2054d2b559628b6aea0ff9 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- SymbolFileDWARF.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// Other libraries and framework includes
13#include "clang/AST/ASTConsumer.h"
14#include "clang/AST/ASTContext.h"
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclGroup.h"
17#include "clang/Basic/Builtins.h"
18#include "clang/Basic/IdentifierTable.h"
19#include "clang/Basic/LangOptions.h"
20#include "clang/Basic/SourceManager.h"
21#include "clang/Basic/TargetInfo.h"
22#include "clang/Basic/Specifiers.h"
23
24#include "lldb/Core/Module.h"
25#include "lldb/Core/PluginManager.h"
26#include "lldb/Core/RegularExpression.h"
27#include "lldb/Core/Scalar.h"
28#include "lldb/Core/Section.h"
29#include "lldb/Core/Timer.h"
30#include "lldb/Core/Value.h"
31
32#include "lldb/Symbol/Block.h"
33#include "lldb/Symbol/CompileUnit.h"
34#include "lldb/Symbol/LineTable.h"
35#include "lldb/Symbol/ObjectFile.h"
36#include "lldb/Symbol/SymbolVendor.h"
37#include "lldb/Symbol/VariableList.h"
38
39#include "DWARFCompileUnit.h"
40#include "DWARFDebugAbbrev.h"
41#include "DWARFDebugAranges.h"
42#include "DWARFDebugInfo.h"
43#include "DWARFDebugInfoEntry.h"
44#include "DWARFDebugLine.h"
45#include "DWARFDebugPubnames.h"
46#include "DWARFDebugRanges.h"
47#include "DWARFDIECollection.h"
48#include "DWARFFormValue.h"
49#include "DWARFLocationList.h"
50#include "LogChannelDWARF.h"
51
52#include <map>
53
54#define DIE_IS_BEING_PARSED ((void*)1)
55
56using namespace lldb;
57using namespace lldb_private;
58
59
Sean Callanan70a4f922010-08-06 00:32:49 +000060static AccessType
Greg Clayton84f80752010-07-22 18:30:50 +000061DW_ACCESS_to_AccessType (uint32_t dwarf_accessibility)
Chris Lattner24943d22010-06-08 16:52:24 +000062{
63 switch (dwarf_accessibility)
64 {
Sean Callanan70a4f922010-08-06 00:32:49 +000065 case DW_ACCESS_public: return eAccessPublic;
66 case DW_ACCESS_private: return eAccessPrivate;
67 case DW_ACCESS_protected: return eAccessProtected;
Greg Clayton84f80752010-07-22 18:30:50 +000068 default: break;
Chris Lattner24943d22010-06-08 16:52:24 +000069 }
Sean Callanan70a4f922010-08-06 00:32:49 +000070 return eAccessNone;
Chris Lattner24943d22010-06-08 16:52:24 +000071}
72
73void
74SymbolFileDWARF::Initialize()
75{
76 LogChannelDWARF::Initialize();
77 PluginManager::RegisterPlugin (GetPluginNameStatic(),
78 GetPluginDescriptionStatic(),
79 CreateInstance);
80}
81
82void
83SymbolFileDWARF::Terminate()
84{
85 PluginManager::UnregisterPlugin (CreateInstance);
86 LogChannelDWARF::Initialize();
87}
88
89
90const char *
91SymbolFileDWARF::GetPluginNameStatic()
92{
93 return "symbol-file.dwarf2";
94}
95
96const char *
97SymbolFileDWARF::GetPluginDescriptionStatic()
98{
99 return "DWARF and DWARF3 debug symbol file reader.";
100}
101
102
103SymbolFile*
104SymbolFileDWARF::CreateInstance (ObjectFile* obj_file)
105{
106 return new SymbolFileDWARF(obj_file);
107}
108
109//----------------------------------------------------------------------
110// Gets the first parent that is a lexical block, function or inlined
111// subroutine, or compile unit.
112//----------------------------------------------------------------------
113static const DWARFDebugInfoEntry *
114GetParentSymbolContextDIE(const DWARFDebugInfoEntry *child_die)
115{
116 const DWARFDebugInfoEntry *die;
117 for (die = child_die->GetParent(); die != NULL; die = die->GetParent())
118 {
119 dw_tag_t tag = die->Tag();
120
121 switch (tag)
122 {
123 case DW_TAG_compile_unit:
124 case DW_TAG_subprogram:
125 case DW_TAG_inlined_subroutine:
126 case DW_TAG_lexical_block:
127 return die;
128 }
129 }
130 return NULL;
131}
132
133
134SymbolFileDWARF::SymbolFileDWARF(ObjectFile* ofile) :
135 SymbolFile(ofile),
136 m_flags(),
137 m_data_debug_abbrev(),
138 m_data_debug_aranges(),
139 m_data_debug_frame(),
140 m_data_debug_info(),
141 m_data_debug_line(),
142 m_data_debug_loc(),
143 m_data_debug_macinfo(),
144 m_data_debug_pubnames(),
145 m_data_debug_pubtypes(),
146 m_data_debug_ranges(),
147 m_data_debug_str(),
148 m_abbr(),
149 m_aranges(),
150 m_info(),
151 m_line(),
Greg Clayton12bec712010-06-28 21:30:43 +0000152 m_base_name_to_function_die(),
153 m_full_name_to_function_die(),
154 m_method_name_to_function_die(),
155 m_selector_name_to_function_die(),
Chris Lattner24943d22010-06-08 16:52:24 +0000156 m_name_to_global_die(),
157 m_name_to_type_die(),
158 m_indexed(false),
159// m_pubnames(),
Chris Lattner24943d22010-06-08 16:52:24 +0000160// m_pubbasetypes(),
Greg Clayton960d6a42010-08-03 00:35:52 +0000161 m_pubtypes(),
Chris Lattner24943d22010-06-08 16:52:24 +0000162 m_ranges()//,
163// m_type_fixups(),
164// m_indirect_fixups()
165{
166}
167
168SymbolFileDWARF::~SymbolFileDWARF()
169{
170}
171
172bool
173SymbolFileDWARF::SupportedVersion(uint16_t version)
174{
175 return version == 2 || version == 3;
176}
177
178uint32_t
179SymbolFileDWARF::GetAbilities ()
180{
181 uint32_t abilities = 0;
182 if (m_obj_file != NULL)
183 {
184 const Section* section = NULL;
185 const SectionList *section_list = m_obj_file->GetSectionList();
186 if (section_list == NULL)
187 return 0;
188
189 uint64_t debug_abbrev_file_size = 0;
190 uint64_t debug_aranges_file_size = 0;
191 uint64_t debug_frame_file_size = 0;
192 uint64_t debug_info_file_size = 0;
193 uint64_t debug_line_file_size = 0;
194 uint64_t debug_loc_file_size = 0;
195 uint64_t debug_macinfo_file_size = 0;
196 uint64_t debug_pubnames_file_size = 0;
197 uint64_t debug_pubtypes_file_size = 0;
198 uint64_t debug_ranges_file_size = 0;
199 uint64_t debug_str_file_size = 0;
200
201 static ConstString g_dwarf_section_name ("__DWARF");
202
203 section = section_list->FindSectionByName(g_dwarf_section_name).get();
204
205 if (section)
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000206 {
Chris Lattner24943d22010-06-08 16:52:24 +0000207 section->MemoryMapSectionDataFromObjectFile(m_obj_file, m_dwarf_data);
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000208 section_list = &section->GetChildren ();
209 }
Chris Lattner24943d22010-06-08 16:52:24 +0000210
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000211 section = section_list->FindSectionByType (eSectionTypeDWARFDebugInfo, true).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000212 if (section != NULL)
213 {
214 debug_info_file_size = section->GetByteSize();
215
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000216 section = section_list->FindSectionByType (eSectionTypeDWARFDebugAbbrev, true).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000217 if (section)
218 debug_abbrev_file_size = section->GetByteSize();
219 else
220 m_flags.Set (flagsGotDebugAbbrevData);
221
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000222 section = section_list->FindSectionByType (eSectionTypeDWARFDebugAranges, true).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000223 if (section)
224 debug_aranges_file_size = section->GetByteSize();
225 else
226 m_flags.Set (flagsGotDebugArangesData);
227
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000228 section = section_list->FindSectionByType (eSectionTypeDWARFDebugFrame, true).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000229 if (section)
230 debug_frame_file_size = section->GetByteSize();
231 else
232 m_flags.Set (flagsGotDebugFrameData);
233
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000234 section = section_list->FindSectionByType (eSectionTypeDWARFDebugLine, true).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000235 if (section)
236 debug_line_file_size = section->GetByteSize();
237 else
238 m_flags.Set (flagsGotDebugLineData);
239
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000240 section = section_list->FindSectionByType (eSectionTypeDWARFDebugLoc, true).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000241 if (section)
242 debug_loc_file_size = section->GetByteSize();
243 else
244 m_flags.Set (flagsGotDebugLocData);
245
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000246 section = section_list->FindSectionByType (eSectionTypeDWARFDebugMacInfo, true).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000247 if (section)
248 debug_macinfo_file_size = section->GetByteSize();
249 else
250 m_flags.Set (flagsGotDebugMacInfoData);
251
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000252 section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubNames, true).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000253 if (section)
254 debug_pubnames_file_size = section->GetByteSize();
255 else
256 m_flags.Set (flagsGotDebugPubNamesData);
257
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000258 section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubTypes, true).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000259 if (section)
260 debug_pubtypes_file_size = section->GetByteSize();
261 else
262 m_flags.Set (flagsGotDebugPubTypesData);
263
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000264 section = section_list->FindSectionByType (eSectionTypeDWARFDebugRanges, true).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000265 if (section)
266 debug_ranges_file_size = section->GetByteSize();
267 else
268 m_flags.Set (flagsGotDebugRangesData);
269
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000270 section = section_list->FindSectionByType (eSectionTypeDWARFDebugStr, true).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000271 if (section)
272 debug_str_file_size = section->GetByteSize();
273 else
274 m_flags.Set (flagsGotDebugStrData);
275 }
276
277 if (debug_abbrev_file_size > 0 && debug_info_file_size > 0)
278 abilities |= CompileUnits | Functions | Blocks | GlobalVariables | LocalVariables | VariableTypes;
279
280 if (debug_line_file_size > 0)
281 abilities |= LineTables;
282
283 if (debug_aranges_file_size > 0)
284 abilities |= AddressAcceleratorTable;
285
286 if (debug_pubnames_file_size > 0)
287 abilities |= FunctionAcceleratorTable;
288
289 if (debug_pubtypes_file_size > 0)
290 abilities |= TypeAcceleratorTable;
291
292 if (debug_macinfo_file_size > 0)
293 abilities |= MacroInformation;
294
295 if (debug_frame_file_size > 0)
296 abilities |= CallFrameInformation;
297 }
298 return abilities;
299}
300
301const DataExtractor&
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000302SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type, DataExtractor &data)
Chris Lattner24943d22010-06-08 16:52:24 +0000303{
304 if (m_flags.IsClear (got_flag))
305 {
306 m_flags.Set (got_flag);
307 const SectionList *section_list = m_obj_file->GetSectionList();
308 if (section_list)
309 {
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000310 Section *section = section_list->FindSectionByType(sect_type, true).get();
311 if (section)
Chris Lattner24943d22010-06-08 16:52:24 +0000312 {
313 // See if we memory mapped the DWARF segment?
314 if (m_dwarf_data.GetByteSize())
315 {
316 data.SetData(m_dwarf_data, section->GetOffset (), section->GetByteSize());
317 }
318 else
319 {
320 if (section->ReadSectionDataFromObjectFile(m_obj_file, data) == 0)
321 data.Clear();
322 }
323 }
324 }
325 }
326 return data;
327}
328
329const DataExtractor&
330SymbolFileDWARF::get_debug_abbrev_data()
331{
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000332 return GetCachedSectionData (flagsGotDebugAbbrevData, eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev);
Chris Lattner24943d22010-06-08 16:52:24 +0000333}
334
335const DataExtractor&
336SymbolFileDWARF::get_debug_aranges_data()
337{
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000338 return GetCachedSectionData (flagsGotDebugArangesData, eSectionTypeDWARFDebugAranges, m_data_debug_aranges);
Chris Lattner24943d22010-06-08 16:52:24 +0000339}
340
341const DataExtractor&
342SymbolFileDWARF::get_debug_frame_data()
343{
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000344 return GetCachedSectionData (flagsGotDebugFrameData, eSectionTypeDWARFDebugFrame, m_data_debug_frame);
Chris Lattner24943d22010-06-08 16:52:24 +0000345}
346
347const DataExtractor&
348SymbolFileDWARF::get_debug_info_data()
349{
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000350 return GetCachedSectionData (flagsGotDebugInfoData, eSectionTypeDWARFDebugInfo, m_data_debug_info);
Chris Lattner24943d22010-06-08 16:52:24 +0000351}
352
353const DataExtractor&
354SymbolFileDWARF::get_debug_line_data()
355{
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000356 return GetCachedSectionData (flagsGotDebugLineData, eSectionTypeDWARFDebugLine, m_data_debug_line);
Chris Lattner24943d22010-06-08 16:52:24 +0000357}
358
359const DataExtractor&
360SymbolFileDWARF::get_debug_loc_data()
361{
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000362 return GetCachedSectionData (flagsGotDebugLocData, eSectionTypeDWARFDebugLoc, m_data_debug_loc);
Chris Lattner24943d22010-06-08 16:52:24 +0000363}
364
365const DataExtractor&
366SymbolFileDWARF::get_debug_macinfo_data()
367{
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000368 return GetCachedSectionData (flagsGotDebugMacInfoData, eSectionTypeDWARFDebugMacInfo, m_data_debug_macinfo);
Chris Lattner24943d22010-06-08 16:52:24 +0000369}
370
371const DataExtractor&
372SymbolFileDWARF::get_debug_pubnames_data()
373{
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000374 return GetCachedSectionData (flagsGotDebugPubNamesData, eSectionTypeDWARFDebugPubNames, m_data_debug_pubnames);
Chris Lattner24943d22010-06-08 16:52:24 +0000375}
376
377const DataExtractor&
378SymbolFileDWARF::get_debug_pubtypes_data()
379{
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000380 return GetCachedSectionData (flagsGotDebugPubTypesData, eSectionTypeDWARFDebugPubTypes, m_data_debug_pubtypes);
Chris Lattner24943d22010-06-08 16:52:24 +0000381}
382
383const DataExtractor&
384SymbolFileDWARF::get_debug_ranges_data()
385{
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000386 return GetCachedSectionData (flagsGotDebugRangesData, eSectionTypeDWARFDebugRanges, m_data_debug_ranges);
Chris Lattner24943d22010-06-08 16:52:24 +0000387}
388
389const DataExtractor&
390SymbolFileDWARF::get_debug_str_data()
391{
Greg Clayton32a8c7e2010-07-21 22:54:26 +0000392 return GetCachedSectionData (flagsGotDebugStrData, eSectionTypeDWARFDebugStr, m_data_debug_str);
Chris Lattner24943d22010-06-08 16:52:24 +0000393}
394
395
396DWARFDebugAbbrev*
397SymbolFileDWARF::DebugAbbrev()
398{
399 if (m_abbr.get() == NULL)
400 {
401 const DataExtractor &debug_abbrev_data = get_debug_abbrev_data();
402 if (debug_abbrev_data.GetByteSize() > 0)
403 {
404 m_abbr.reset(new DWARFDebugAbbrev());
405 if (m_abbr.get())
406 m_abbr->Parse(debug_abbrev_data);
407 }
408 }
409 return m_abbr.get();
410}
411
412const DWARFDebugAbbrev*
413SymbolFileDWARF::DebugAbbrev() const
414{
415 return m_abbr.get();
416}
417
418DWARFDebugAranges*
419SymbolFileDWARF::DebugAranges()
420{
421 if (m_aranges.get() == NULL)
422 {
423 Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
424 m_aranges.reset(new DWARFDebugAranges());
425 if (m_aranges.get())
426 {
427 const DataExtractor &debug_aranges_data = get_debug_aranges_data();
428 if (debug_aranges_data.GetByteSize() > 0)
429 m_aranges->Extract(debug_aranges_data);
430 else
431 m_aranges->Generate(this);
432 }
433 }
434 return m_aranges.get();
435}
436
437const DWARFDebugAranges*
438SymbolFileDWARF::DebugAranges() const
439{
440 return m_aranges.get();
441}
442
443
444DWARFDebugInfo*
445SymbolFileDWARF::DebugInfo()
446{
447 if (m_info.get() == NULL)
448 {
449 Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
450 if (get_debug_info_data().GetByteSize() > 0)
451 {
452 m_info.reset(new DWARFDebugInfo());
453 if (m_info.get())
454 {
455 m_info->SetDwarfData(this);
456 }
457 }
458 }
459 return m_info.get();
460}
461
462const DWARFDebugInfo*
463SymbolFileDWARF::DebugInfo() const
464{
465 return m_info.get();
466}
467
468//DWARFDebugLine*
469//SymbolFileDWARF::DebugLine()
470//{
471// if (m_line.get() == NULL)
472// {
473// Timer scoped_timer(__PRETTY_FUNCTION__);
474// const DataExtractor &debug_line_data = debug_line();
475// if (debug_line_data.GetByteSize() > 0)
476// {
477// m_line.reset(new DWARFDebugLine());
478// if (m_line.get())
479// m_line->Parse(debug_line_data);
480// }
481// }
482// return m_line.get();
483//}
484//
485//const DWARFDebugLine*
486//SymbolFileDWARF::DebugLine() const
487//{
488// return m_line.get();
489//}
490
491
492DWARFCompileUnit*
493SymbolFileDWARF::GetDWARFCompileUnitForUID(lldb::user_id_t cu_uid)
494{
495 DWARFDebugInfo* info = DebugInfo();
496 if (info)
497 return info->GetCompileUnit(cu_uid).get();
498 return NULL;
499}
500
501//DWARFCompileUnit*
502//SymbolFileDWARF::GetNextUnparsedDWARFCompileUnit(DWARFCompileUnit* prev_cu)
503//{
504// DWARFCompileUnit* cu = NULL;
505// DWARFDebugInfo* info = DebugInfo();
506// if (info)
507// {
508// uint32_t cu_idx = 0;
509// if (prev_cu != NULL)
510// {
511// // Find the index of the previus DWARF compile unit if one was provided
512// while ((cu = info->GetCompileUnitAtIndex(cu_idx)) != NULL)
513// {
514// ++cu_idx;
515// if (cu == prev_cu)
516// break;
517// }
518// }
519//
520// // Now find the next unparsed DWARF compile unit. We do this by checking the
521// // user data in the DWARFCompileUnit class that starts as NULL, and eventually
522// // holds a pointer to the CompileUnit that was created for it after it has
523// // been parsed.
524// while ((cu = info->GetCompileUnitAtIndex(cu_idx)) != NULL)
525// {
526// if (cu->GetUserData() == NULL)
527// break;
528// }
529// }
530// return cu;
531//}
532
533DWARFDebugRanges*
534SymbolFileDWARF::DebugRanges()
535{
536 if (m_ranges.get() == NULL)
537 {
538 Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
539 if (get_debug_ranges_data().GetByteSize() > 0)
540 {
541 m_ranges.reset(new DWARFDebugRanges());
542 if (m_ranges.get())
543 m_ranges->Extract(this);
544 }
545 }
546 return m_ranges.get();
547}
548
549const DWARFDebugRanges*
550SymbolFileDWARF::DebugRanges() const
551{
552 return m_ranges.get();
553}
554//
555//DWARFDebugPubnames*
556//SymbolFileDWARF::DebugPubnames()
557//{
558// if (m_pubnames.get() == NULL)
559// {
560// Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
561// const DataExtractor &debug_pubnames_data = get_debug_pubnames_data();
562// if (debug_pubnames_data.GetByteSize() > 0)
563// {
564// // Pass false to indicate this is a pubnames section
565// m_pubnames.reset(new DWARFDebugPubnames());
566// if (m_pubnames.get())
567// {
568// // "m_pubnames->GeneratePubnames" is costly, but needed for global variables
569// m_pubnames->GeneratePubnames(this);
570//
571//#if 0
572// StreamFile s(stdout);
573// s.Printf (".debug_pubnames for %s/%s:\n",
574// m_obj_file->GetModule()->GetFileSpec().GetDirectory().AsCString(),
575// m_obj_file->GetModule()->GetFileSpec().GetFilename().AsCString());
576// m_pubnames->Dump (&s);
577//#endif
578// // "m_pubnames->Extract" is quicker, but the pubnames don't always contain what we need.
579// //m_pubnames->Extract(debug_pubnames_data);
580// }
581// }
582// }
583// return m_pubnames.get();
584//}
585//
586//const DWARFDebugPubnames*
587//SymbolFileDWARF::DebugPubnames() const
588//{
589// return m_pubnames.get();
590//}
591
592//DWARFDebugPubnames*
593//SymbolFileDWARF::DebugPubBaseTypes()
594//{
595// if (m_pubbasetypes.get() == NULL)
596// {
597// Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
598// // Pass false to indicate this is a pubnames section
599// m_pubbasetypes.reset(new DWARFDebugPubnames());
600// if (m_pubbasetypes.get())
601// m_pubbasetypes->GeneratePubBaseTypes(this);
602// }
603// return m_pubbasetypes.get();
604//}
605//
606//const DWARFDebugPubnames*
607//SymbolFileDWARF::DebugPubBaseTypes() const
608//{
609// return m_pubbasetypes.get();
610//}
611//
612//const DWARFDebugPubnames*
613//SymbolFileDWARF::DebugPubtypes() const
614//{
615// return m_pubtypes.get();
616//}
617//
Greg Clayton960d6a42010-08-03 00:35:52 +0000618DWARFDebugPubnames*
619SymbolFileDWARF::DebugPubtypes()
620{
621 if (m_pubtypes.get() == NULL)
622 {
623 Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
624 const DataExtractor &debug_pubtypes_data = get_debug_pubtypes_data();
625 if (debug_pubtypes_data.GetByteSize() > 0)
626 {
627 // Pass false to indicate this is a pubnames section
628 m_pubtypes.reset(new DWARFDebugPubnames());
629 if (m_pubtypes.get())
630 m_pubtypes->Extract(debug_pubtypes_data);
631 }
632 }
633 return m_pubtypes.get();
634}
635
Chris Lattner24943d22010-06-08 16:52:24 +0000636
637bool
638SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit* cu, CompUnitSP& compile_unit_sp)
639{
640 if (cu != NULL)
641 {
642 const DWARFDebugInfoEntry * cu_die = cu->GetCompileUnitDIEOnly ();
643 if (cu_die)
644 {
645 const char * cu_die_name = cu_die->GetName(this, cu);
646 const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, cu, DW_AT_comp_dir, NULL);
Greg Clayton9488b742010-07-28 02:04:09 +0000647 LanguageType class_language = (LanguageType)cu_die->GetAttributeValueAsUnsigned(this, cu, DW_AT_language, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000648 if (cu_die_name)
649 {
650 if (cu_die_name[0] == '/' || cu_comp_dir == NULL && cu_comp_dir[0])
651 {
Greg Clayton9488b742010-07-28 02:04:09 +0000652 compile_unit_sp.reset(new CompileUnit(m_obj_file->GetModule(), cu, cu_die_name, cu->GetOffset(), class_language));
Chris Lattner24943d22010-06-08 16:52:24 +0000653 }
654 else
655 {
656 std::string fullpath(cu_comp_dir);
657 if (*fullpath.rbegin() != '/')
658 fullpath += '/';
659 fullpath += cu_die_name;
660
Greg Clayton9488b742010-07-28 02:04:09 +0000661 compile_unit_sp.reset(new CompileUnit(m_obj_file->GetModule(), cu, fullpath.c_str(), cu->GetOffset(), class_language));
Chris Lattner24943d22010-06-08 16:52:24 +0000662 }
663
664 if (compile_unit_sp.get())
665 {
666 cu->SetUserData(compile_unit_sp.get());
667 return true;
668 }
669 }
670 }
671 }
672 return false;
673}
674
675#if defined LLDB_SYMBOL_FILE_DWARF_SHRINK_TEST
676
677void
678SymbolFileDWARF::ShrinkDSYM(CompileUnit *dc_cu, DWARFCompileUnit *dw_cu, const FileSpec& cu_fspec, const FileSpec& base_types_fspec, FSToDIES& fs_to_dies, const DWARFDebugInfoEntry *die)
679{
680 while (die != NULL)
681 {
682 dw_tag_t tag = die->Tag();
683
684 switch (tag)
685 {
686 case DW_TAG_base_type:
687 // Put all base types into the base type compile unit
688 fs_to_dies[base_types_fspec].Insert(die);
689 break;
690
691 default:
692 {
693 uint32_t decl_file = die->GetAttributeValueAsUnsigned(this, dw_cu, DW_AT_decl_file, 0);
694 if (decl_file)
695 {
696 fs_to_dies[dc_cu->GetSupportFiles().GetFileSpecAtIndex(decl_file)].Insert(die);
697 }
698 else
699 {
700 // add this to the current compile unit
701 fs_to_dies[cu_fspec].Insert(die);
702 }
703 }
704 break;
705 }
706
707 die = die->GetSibling();
708 }
709}
710
711
712
713#endif
714
715uint32_t
716SymbolFileDWARF::GetNumCompileUnits()
717{
718 DWARFDebugInfo* info = DebugInfo();
719 if (info)
720 {
721#if defined LLDB_SYMBOL_FILE_DWARF_SHRINK_TEST
722 uint32_t cu_idx;
723 FSToDIES fs_to_dies;
724
725 FileSpec base_type_fspec("DW_TAG_base_type");
726 const uint32_t num_comp_units = info->GetNumCompileUnits();
727
728 for (cu_idx=0; cu_idx < num_comp_units; ++cu_idx)
729 {
730 DWARFCompileUnit* cu = info->GetCompileUnitAtIndex(cu_idx);
731 if (cu != NULL)
732 {
733 const DWARFDebugInfoEntry *cu_die = cu->DIE();
734 if (cu_die)
735 {
736 CompUnitSP dc_cu_sp;
737 ParseCompileUnit(cu, dc_cu_sp);
738 if (dc_cu_sp.get())
739 {
740 FileSpec cu_fspec(*dc_cu_sp.get());
741
742 ShrinkDSYM(dc_cu_sp.get(), cu, cu_fspec, base_type_fspec, fs_to_dies, cu->DIE()->GetFirstChild());
743 }
744 }
745 }
746 }
747
748 Stream strm(stdout);
749 FSToDIES::const_iterator pos, end = fs_to_dies.end();
750 for (pos = fs_to_dies.begin(); pos != end; ++pos)
751 {
752 strm << "\n\nMinimal Compile Unit: " << pos->first << ":\n";
753 const DWARFDIECollection& dies = pos->second;
754 dies.Dump(strm, NULL);
755 }
756 return num_comp_units;
757#else
758 return info->GetNumCompileUnits();
759#endif
760 }
761 return 0;
762}
763
764CompUnitSP
765SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx)
766{
767 CompUnitSP comp_unit;
768 DWARFDebugInfo* info = DebugInfo();
769 if (info)
770 {
771 DWARFCompileUnit* cu = info->GetCompileUnitAtIndex(cu_idx);
772 if (cu != NULL)
773 {
774 // Our symbol vendor shouldn't be asking us to add a compile unit that
775 // has already been added to it, which this DWARF plug-in knows as it
776 // stores the lldb compile unit (CompileUnit) pointer in each
777 // DWARFCompileUnit object when it gets added.
778 assert(cu->GetUserData() == NULL);
779 ParseCompileUnit(cu, comp_unit);
780 }
781 }
782 return comp_unit;
783}
784
785static void
786AddRangesToBlock
787(
Greg Clayton75ccf502010-08-21 02:22:51 +0000788 Block& block,
Chris Lattner24943d22010-06-08 16:52:24 +0000789 DWARFDebugRanges::RangeList& ranges,
790 addr_t block_base_addr
791)
792{
793 ranges.SubtractOffset (block_base_addr);
794 size_t range_idx = 0;
795 const DWARFDebugRanges::Range *debug_range;
796 for (range_idx = 0; (debug_range = ranges.RangeAtIndex(range_idx)) != NULL; range_idx++)
797 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000798 block.AddRange(debug_range->begin_offset, debug_range->end_offset);
Chris Lattner24943d22010-06-08 16:52:24 +0000799 }
800}
801
802
803Function *
804SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die)
805{
806 DWARFDebugRanges::RangeList func_ranges;
807 const char *name = NULL;
808 const char *mangled = NULL;
809 int decl_file = 0;
810 int decl_line = 0;
811 int decl_column = 0;
812 int call_file = 0;
813 int call_line = 0;
814 int call_column = 0;
815 DWARFExpression frame_base;
816
817 // Parse the function prototype as a type that can then be added to concrete function instance
818 ParseTypes (sc, dwarf_cu, die, false, false);
819 //FixupTypes();
820
821 if (die->GetDIENamesAndRanges(this, dwarf_cu, name, mangled, func_ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column, &frame_base))
822 {
823 // Union of all ranges in the function DIE (if the function is discontiguous)
824 AddressRange func_range;
825 lldb::addr_t lowest_func_addr = func_ranges.LowestAddress(0);
826 lldb::addr_t highest_func_addr = func_ranges.HighestAddress(0);
827 if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr)
828 {
829 func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, m_obj_file->GetSectionList());
830 if (func_range.GetBaseAddress().IsValid())
831 func_range.SetByteSize(highest_func_addr - lowest_func_addr);
832 }
833
834 if (func_range.GetBaseAddress().IsValid())
835 {
836 Mangled func_name;
837 if (mangled)
838 func_name.SetValue(mangled, true);
839 else if (name)
840 func_name.SetValue(name, false);
841
842 FunctionSP func_sp;
843 std::auto_ptr<Declaration> decl_ap;
844 if (decl_file != 0 || decl_line != 0 || decl_column != 0)
845 decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), decl_line, decl_column));
846
847 Type *func_type = NULL;
848
849 if (die->GetUserData() != DIE_IS_BEING_PARSED)
850 func_type = (Type*)die->GetUserData();
851
852 assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
853
854 func_range.GetBaseAddress().ResolveLinkedAddress();
855
856 func_sp.reset(new Function (sc.comp_unit,
857 die->GetOffset(), // UserID is the DIE offset
858 die->GetOffset(),
859 func_name,
860 func_type,
861 func_range)); // first address range
862
863 if (func_sp.get() != NULL)
864 {
865 func_sp->GetFrameBaseExpression() = frame_base;
866 sc.comp_unit->AddFunction(func_sp);
867 return func_sp.get();
868 }
869 }
870 }
871 return NULL;
872}
873
874size_t
875SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc)
876{
877 assert (sc.comp_unit);
878 size_t functions_added = 0;
879 const DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
880 if (dwarf_cu)
881 {
882 DWARFDIECollection function_dies;
883 const size_t num_funtions = dwarf_cu->AppendDIEsWithTag (DW_TAG_subprogram, function_dies);
884 size_t func_idx;
885 for (func_idx = 0; func_idx < num_funtions; ++func_idx)
886 {
887 const DWARFDebugInfoEntry *die = function_dies.GetDIEPtrAtIndex(func_idx);
888 if (sc.comp_unit->FindFunctionByUID (die->GetOffset()).get() == NULL)
889 {
890 if (ParseCompileUnitFunction(sc, dwarf_cu, die))
891 ++functions_added;
892 }
893 }
894 //FixupTypes();
895 }
896 return functions_added;
897}
898
899bool
900SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files)
901{
902 assert (sc.comp_unit);
903 DWARFCompileUnit* cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
904 assert (cu);
905 const DWARFDebugInfoEntry * cu_die = cu->GetCompileUnitDIEOnly();
906
907 if (cu_die)
908 {
909 const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, cu, DW_AT_comp_dir, NULL);
910 dw_offset_t stmt_list = cu_die->GetAttributeValueAsUnsigned(this, cu, DW_AT_stmt_list, DW_INVALID_OFFSET);
911
912 // All file indexes in DWARF are one based and a file of index zero is
913 // supposed to be the compile unit itself.
914 support_files.Append (*sc.comp_unit);
915
916 return DWARFDebugLine::ParseSupportFiles(get_debug_line_data(), cu_comp_dir, stmt_list, support_files);
917 }
918 return false;
919}
920
921struct ParseDWARFLineTableCallbackInfo
922{
923 LineTable* line_table;
924 const SectionList *section_list;
925 lldb::addr_t prev_sect_file_base_addr;
926 lldb::addr_t curr_sect_file_base_addr;
927 bool is_oso_for_debug_map;
928 bool prev_in_final_executable;
929 DWARFDebugLine::Row prev_row;
930 SectionSP prev_section_sp;
931 SectionSP curr_section_sp;
932};
933
934//----------------------------------------------------------------------
935// ParseStatementTableCallback
936//----------------------------------------------------------------------
937static void
938ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& state, void* userData)
939{
940 LineTable* line_table = ((ParseDWARFLineTableCallbackInfo*)userData)->line_table;
941 if (state.row == DWARFDebugLine::State::StartParsingLineTable)
942 {
943 // Just started parsing the line table
944 }
945 else if (state.row == DWARFDebugLine::State::DoneParsingLineTable)
946 {
947 // Done parsing line table, nothing to do for the cleanup
948 }
949 else
950 {
951 ParseDWARFLineTableCallbackInfo* info = (ParseDWARFLineTableCallbackInfo*)userData;
952 // We have a new row, lets append it
953
954 if (info->curr_section_sp.get() == NULL || info->curr_section_sp->ContainsFileAddress(state.address) == false)
955 {
956 info->prev_section_sp = info->curr_section_sp;
957 info->prev_sect_file_base_addr = info->curr_sect_file_base_addr;
958 // If this is an end sequence entry, then we subtract one from the
959 // address to make sure we get an address that is not the end of
960 // a section.
961 if (state.end_sequence && state.address != 0)
962 info->curr_section_sp = info->section_list->FindSectionContainingFileAddress (state.address - 1);
963 else
964 info->curr_section_sp = info->section_list->FindSectionContainingFileAddress (state.address);
965
966 if (info->curr_section_sp.get())
967 info->curr_sect_file_base_addr = info->curr_section_sp->GetFileAddress ();
968 else
969 info->curr_sect_file_base_addr = 0;
970 }
971 if (info->curr_section_sp.get())
972 {
973 lldb::addr_t curr_line_section_offset = state.address - info->curr_sect_file_base_addr;
974 // Check for the fancy section magic to determine if we
975
976 if (info->is_oso_for_debug_map)
977 {
978 // When this is a debug map object file that contains DWARF
979 // (referenced from an N_OSO debug map nlist entry) we will have
980 // a file address in the file range for our section from the
981 // original .o file, and a load address in the executable that
982 // contains the debug map.
983 //
984 // If the sections for the file range and load range are
985 // different, we have a remapped section for the function and
986 // this address is resolved. If they are the same, then the
987 // function for this address didn't make it into the final
988 // executable.
989 bool curr_in_final_executable = info->curr_section_sp->GetLinkedSection () != NULL;
990
991 // If we are doing DWARF with debug map, then we need to carefully
992 // add each line table entry as there may be gaps as functions
993 // get moved around or removed.
994 if (!info->prev_row.end_sequence && info->prev_section_sp.get())
995 {
996 if (info->prev_in_final_executable)
997 {
998 bool terminate_previous_entry = false;
999 if (!curr_in_final_executable)
1000 {
1001 // Check for the case where the previous line entry
1002 // in a function made it into the final executable,
1003 // yet the current line entry falls in a function
1004 // that didn't. The line table used to be contiguous
1005 // through this address range but now it isn't. We
1006 // need to terminate the previous line entry so
1007 // that we can reconstruct the line range correctly
1008 // for it and to keep the line table correct.
1009 terminate_previous_entry = true;
1010 }
1011 else if (info->curr_section_sp.get() != info->prev_section_sp.get())
1012 {
1013 // Check for cases where the line entries used to be
1014 // contiguous address ranges, but now they aren't.
1015 // This can happen when order files specify the
1016 // ordering of the functions.
1017 lldb::addr_t prev_line_section_offset = info->prev_row.address - info->prev_sect_file_base_addr;
1018 Section *curr_sect = info->curr_section_sp.get();
1019 Section *prev_sect = info->prev_section_sp.get();
1020 assert (curr_sect->GetLinkedSection());
1021 assert (prev_sect->GetLinkedSection());
1022 lldb::addr_t object_file_addr_delta = state.address - info->prev_row.address;
1023 lldb::addr_t curr_linked_file_addr = curr_sect->GetLinkedFileAddress() + curr_line_section_offset;
1024 lldb::addr_t prev_linked_file_addr = prev_sect->GetLinkedFileAddress() + prev_line_section_offset;
1025 lldb::addr_t linked_file_addr_delta = curr_linked_file_addr - prev_linked_file_addr;
1026 if (object_file_addr_delta != linked_file_addr_delta)
1027 terminate_previous_entry = true;
1028 }
1029
1030 if (terminate_previous_entry)
1031 {
1032 line_table->InsertLineEntry (info->prev_section_sp,
1033 state.address - info->prev_sect_file_base_addr,
1034 info->prev_row.line,
1035 info->prev_row.column,
1036 info->prev_row.file,
1037 false, // is_stmt
1038 false, // basic_block
1039 false, // state.prologue_end
1040 false, // state.epilogue_begin
1041 true); // end_sequence);
1042 }
1043 }
1044 }
1045
1046 if (curr_in_final_executable)
1047 {
1048 line_table->InsertLineEntry (info->curr_section_sp,
1049 curr_line_section_offset,
1050 state.line,
1051 state.column,
1052 state.file,
1053 state.is_stmt,
1054 state.basic_block,
1055 state.prologue_end,
1056 state.epilogue_begin,
1057 state.end_sequence);
1058 info->prev_section_sp = info->curr_section_sp;
1059 }
1060 else
1061 {
1062 // If the current address didn't make it into the final
1063 // executable, the current section will be the __text
1064 // segment in the .o file, so we need to clear this so
1065 // we can catch the next function that did make it into
1066 // the final executable.
1067 info->prev_section_sp.reset();
1068 info->curr_section_sp.reset();
1069 }
1070
1071 info->prev_in_final_executable = curr_in_final_executable;
1072 }
1073 else
1074 {
1075 // We are not in an object file that contains DWARF for an
1076 // N_OSO, this is just a normal DWARF file. The DWARF spec
1077 // guarantees that the addresses will be in increasing order
1078 // so, since we store line tables in file address order, we
1079 // can always just append the line entry without needing to
1080 // search for the correct insertion point (we don't need to
1081 // use LineEntry::InsertLineEntry()).
1082 line_table->AppendLineEntry (info->curr_section_sp,
1083 curr_line_section_offset,
1084 state.line,
1085 state.column,
1086 state.file,
1087 state.is_stmt,
1088 state.basic_block,
1089 state.prologue_end,
1090 state.epilogue_begin,
1091 state.end_sequence);
1092 }
1093 }
1094
1095 info->prev_row = state;
1096 }
1097}
1098
1099bool
1100SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)
1101{
1102 assert (sc.comp_unit);
1103 if (sc.comp_unit->GetLineTable() != NULL)
1104 return true;
1105
1106 DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
1107 if (dwarf_cu)
1108 {
1109 const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
1110 const dw_offset_t cu_line_offset = dwarf_cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET);
1111 if (cu_line_offset != DW_INVALID_OFFSET)
1112 {
1113 std::auto_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit));
1114 if (line_table_ap.get())
1115 {
1116 ParseDWARFLineTableCallbackInfo info = { line_table_ap.get(), m_obj_file->GetSectionList(), 0, 0, m_flags.IsSet (flagsDWARFIsOSOForDebugMap), false};
1117 uint32_t offset = cu_line_offset;
1118 DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, &info);
1119 sc.comp_unit->SetLineTable(line_table_ap.release());
1120 return true;
1121 }
1122 }
1123 }
1124 return false;
1125}
1126
1127size_t
1128SymbolFileDWARF::ParseFunctionBlocks
1129(
1130 const SymbolContext& sc,
Greg Clayton75ccf502010-08-21 02:22:51 +00001131 Block *parent_block,
Chris Lattner24943d22010-06-08 16:52:24 +00001132 const DWARFCompileUnit* dwarf_cu,
1133 const DWARFDebugInfoEntry *die,
1134 addr_t subprogram_low_pc,
1135 bool parse_siblings,
1136 bool parse_children
1137)
1138{
1139 size_t blocks_added = 0;
1140 while (die != NULL)
1141 {
1142 dw_tag_t tag = die->Tag();
1143
1144 switch (tag)
1145 {
Chris Lattner24943d22010-06-08 16:52:24 +00001146 case DW_TAG_inlined_subroutine:
Jim Ingham0007dff2010-08-12 01:20:14 +00001147 case DW_TAG_subprogram:
Chris Lattner24943d22010-06-08 16:52:24 +00001148 case DW_TAG_lexical_block:
1149 {
1150 DWARFDebugRanges::RangeList ranges;
1151 const char *name = NULL;
1152 const char *mangled_name = NULL;
Greg Clayton75ccf502010-08-21 02:22:51 +00001153 Block *block = NULL;
1154 if (tag != DW_TAG_subprogram)
1155 {
1156 BlockSP block_sp(new Block (die->GetOffset()));
1157 parent_block->AddChild(block_sp);
1158 block = block_sp.get();
1159 }
1160 else
1161 {
1162 block = parent_block;
1163 }
Chris Lattner24943d22010-06-08 16:52:24 +00001164
Chris Lattner24943d22010-06-08 16:52:24 +00001165 int decl_file = 0;
1166 int decl_line = 0;
1167 int decl_column = 0;
1168 int call_file = 0;
1169 int call_line = 0;
1170 int call_column = 0;
Greg Clayton75ccf502010-08-21 02:22:51 +00001171 if (die->GetDIENamesAndRanges (this,
1172 dwarf_cu,
1173 name,
1174 mangled_name,
1175 ranges,
1176 decl_file, decl_line, decl_column,
1177 call_file, call_line, call_column))
Chris Lattner24943d22010-06-08 16:52:24 +00001178 {
1179 if (tag == DW_TAG_subprogram)
1180 {
1181 assert (subprogram_low_pc == LLDB_INVALID_ADDRESS);
1182 subprogram_low_pc = ranges.LowestAddress(0);
1183 }
Jim Ingham0007dff2010-08-12 01:20:14 +00001184 else if (tag == DW_TAG_inlined_subroutine)
1185 {
1186 // We get called here for inlined subroutines in two ways.
1187 // The first time is when we are making the Function object
1188 // for this inlined concrete instance. Since we're creating a top level block at
1189 // here, the subprogram_low_pc will be LLDB_INVALID_ADDRESS. So we need to
1190 // adjust the containing address.
1191 // The second time is when we are parsing the blocks inside the function that contains
1192 // the inlined concrete instance. Since these will be blocks inside the containing "real"
1193 // function the offset will be for that function.
1194 if (subprogram_low_pc == LLDB_INVALID_ADDRESS)
1195 {
1196 subprogram_low_pc = ranges.LowestAddress(0);
1197 }
1198 }
1199
Greg Clayton75ccf502010-08-21 02:22:51 +00001200 AddRangesToBlock (*block, ranges, subprogram_low_pc);
Chris Lattner24943d22010-06-08 16:52:24 +00001201
1202 if (tag != DW_TAG_subprogram && (name != NULL || mangled_name != NULL))
1203 {
1204 std::auto_ptr<Declaration> decl_ap;
1205 if (decl_file != 0 || decl_line != 0 || decl_column != 0)
Jim Ingham0007dff2010-08-12 01:20:14 +00001206 decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
1207 decl_line, decl_column));
Chris Lattner24943d22010-06-08 16:52:24 +00001208
1209 std::auto_ptr<Declaration> call_ap;
1210 if (call_file != 0 || call_line != 0 || call_column != 0)
Jim Ingham0007dff2010-08-12 01:20:14 +00001211 call_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(call_file),
1212 call_line, call_column));
Chris Lattner24943d22010-06-08 16:52:24 +00001213
Greg Clayton75ccf502010-08-21 02:22:51 +00001214 block->SetInlinedFunctionInfo (name, mangled_name, decl_ap.get(), call_ap.get());
Chris Lattner24943d22010-06-08 16:52:24 +00001215 }
1216
1217 ++blocks_added;
1218
1219 if (parse_children && die->HasChildren())
1220 {
Greg Clayton75ccf502010-08-21 02:22:51 +00001221 blocks_added += ParseFunctionBlocks (sc,
1222 block,
1223 dwarf_cu,
1224 die->GetFirstChild(),
1225 subprogram_low_pc,
1226 true,
1227 true);
Chris Lattner24943d22010-06-08 16:52:24 +00001228 }
1229 }
1230 }
1231 break;
1232 default:
1233 break;
1234 }
1235
1236 if (parse_siblings)
1237 die = die->GetSibling();
1238 else
1239 die = NULL;
1240 }
1241 return blocks_added;
1242}
1243
1244size_t
1245SymbolFileDWARF::ParseChildMembers
1246(
1247 const SymbolContext& sc,
1248 TypeSP& type_sp,
1249 const DWARFCompileUnit* dwarf_cu,
1250 const DWARFDebugInfoEntry *parent_die,
Greg Clayton9488b742010-07-28 02:04:09 +00001251 void *class_clang_type,
1252 const LanguageType class_language,
Chris Lattner24943d22010-06-08 16:52:24 +00001253 std::vector<clang::CXXBaseSpecifier *>& base_classes,
1254 std::vector<int>& member_accessibilities,
Sean Callanan70a4f922010-08-06 00:32:49 +00001255 AccessType& default_accessibility,
Chris Lattner24943d22010-06-08 16:52:24 +00001256 bool &is_a_class
1257)
1258{
1259 if (parent_die == NULL)
1260 return 0;
1261
1262 TypeList* type_list = m_obj_file->GetModule()->GetTypeList();
1263
1264 size_t count = 0;
1265 const DWARFDebugInfoEntry *die;
1266 for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
1267 {
1268 dw_tag_t tag = die->Tag();
1269
1270 switch (tag)
1271 {
1272 case DW_TAG_member:
1273 {
1274 DWARFDebugInfoEntry::Attributes attributes;
1275 const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
1276 if (num_attributes > 0)
1277 {
1278 Declaration decl;
1279 DWARFExpression location;
1280 const char *name = NULL;
1281 lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
Sean Callanan70a4f922010-08-06 00:32:49 +00001282 AccessType accessibility = eAccessNone;
Chris Lattner24943d22010-06-08 16:52:24 +00001283 off_t member_offset = 0;
1284 size_t byte_size = 0;
1285 size_t bit_offset = 0;
1286 size_t bit_size = 0;
1287 uint32_t i;
1288 for (i=0; i<num_attributes; ++i)
1289 {
1290 const dw_attr_t attr = attributes.AttributeAtIndex(i);
1291 DWARFFormValue form_value;
1292 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
1293 {
1294 switch (attr)
1295 {
1296 case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
1297 case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
1298 case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
1299 case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
1300 case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break;
1301 case DW_AT_bit_offset: bit_offset = form_value.Unsigned(); break;
1302 case DW_AT_bit_size: bit_size = form_value.Unsigned(); break;
1303 case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
1304 case DW_AT_data_member_location:
1305 if (form_value.BlockData())
1306 {
1307 Value initialValue(0);
1308 Value memberOffset(0);
1309 const DataExtractor& debug_info_data = get_debug_info_data();
1310 uint32_t block_length = form_value.Unsigned();
1311 uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
1312 if (DWARFExpression::Evaluate(NULL, NULL, debug_info_data, NULL, NULL, block_offset, block_length, eRegisterKindDWARF, &initialValue, memberOffset, NULL))
1313 {
1314 member_offset = memberOffset.ResolveValue(NULL, NULL).UInt();
1315 }
1316 }
1317 break;
1318
Greg Clayton84f80752010-07-22 18:30:50 +00001319 case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType (form_value.Unsigned()); break;
Chris Lattner24943d22010-06-08 16:52:24 +00001320 case DW_AT_declaration:
1321 case DW_AT_description:
1322 case DW_AT_mutable:
1323 case DW_AT_visibility:
1324 default:
1325 case DW_AT_sibling:
1326 break;
1327 }
1328 }
1329 }
1330
1331 Type *member_type = ResolveTypeUID(encoding_uid);
1332 assert(member_type);
Sean Callanan70a4f922010-08-06 00:32:49 +00001333 if (accessibility == eAccessNone)
Chris Lattner24943d22010-06-08 16:52:24 +00001334 accessibility = default_accessibility;
1335 member_accessibilities.push_back(accessibility);
1336
1337 type_list->GetClangASTContext().AddFieldToRecordType (type_sp->GetOpaqueClangQualType(), name, member_type->GetOpaqueClangQualType(), accessibility, bit_size);
1338 }
1339 }
1340 break;
1341
1342 case DW_TAG_subprogram:
1343 {
1344 is_a_class = true;
Sean Callanan70a4f922010-08-06 00:32:49 +00001345 if (default_accessibility == eAccessNone)
1346 default_accessibility = eAccessPrivate;
Chris Lattner24943d22010-06-08 16:52:24 +00001347 // TODO: implement DW_TAG_subprogram type parsing
1348// UserDefTypeChildInfo method_info(die->GetOffset());
1349//
1350// FunctionSP func_sp (sc.comp_unit->FindFunctionByUID (die->GetOffset()));
1351// if (func_sp.get() == NULL)
1352// ParseCompileUnitFunction(sc, dwarf_cu, die);
1353//
1354// method_info.SetEncodingTypeUID(die->GetOffset());
1355// struct_udt->AddMethod(method_info);
1356 }
1357 break;
1358
1359 case DW_TAG_inheritance:
1360 {
1361 is_a_class = true;
Sean Callanan70a4f922010-08-06 00:32:49 +00001362 if (default_accessibility == eAccessNone)
1363 default_accessibility = eAccessPrivate;
Chris Lattner24943d22010-06-08 16:52:24 +00001364 // TODO: implement DW_TAG_inheritance type parsing
1365 DWARFDebugInfoEntry::Attributes attributes;
1366 const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
1367 if (num_attributes > 0)
1368 {
1369 Declaration decl;
1370 DWARFExpression location;
1371 lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
Sean Callanan70a4f922010-08-06 00:32:49 +00001372 AccessType accessibility = default_accessibility;
Chris Lattner24943d22010-06-08 16:52:24 +00001373 bool is_virtual = false;
1374 bool is_base_of_class = true;
1375 off_t member_offset = 0;
1376 uint32_t i;
1377 for (i=0; i<num_attributes; ++i)
1378 {
1379 const dw_attr_t attr = attributes.AttributeAtIndex(i);
1380 DWARFFormValue form_value;
1381 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
1382 {
1383 switch (attr)
1384 {
1385 case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
1386 case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
1387 case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
1388 case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break;
1389 case DW_AT_data_member_location:
1390 if (form_value.BlockData())
1391 {
1392 Value initialValue(0);
1393 Value memberOffset(0);
1394 const DataExtractor& debug_info_data = get_debug_info_data();
1395 uint32_t block_length = form_value.Unsigned();
1396 uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
1397 if (DWARFExpression::Evaluate(NULL, NULL, debug_info_data, NULL, NULL, block_offset, block_length, eRegisterKindDWARF, &initialValue, memberOffset, NULL))
1398 {
1399 member_offset = memberOffset.ResolveValue(NULL, NULL).UInt();
1400 }
1401 }
1402 break;
1403
1404 case DW_AT_accessibility:
Greg Clayton84f80752010-07-22 18:30:50 +00001405 accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
Chris Lattner24943d22010-06-08 16:52:24 +00001406 break;
1407
1408 case DW_AT_virtuality: is_virtual = form_value.Unsigned() != 0; break;
1409 default:
1410 case DW_AT_sibling:
1411 break;
1412 }
1413 }
1414 }
1415
1416 Type *base_class_dctype = ResolveTypeUID(encoding_uid);
1417 assert(base_class_dctype);
Greg Clayton9488b742010-07-28 02:04:09 +00001418
1419 if (class_language == eLanguageTypeObjC)
1420 {
1421 type_list->GetClangASTContext().SetObjCSuperClass(class_clang_type, base_class_dctype->GetOpaqueClangQualType());
1422 }
1423 else
1424 {
1425 base_classes.push_back (type_list->GetClangASTContext().CreateBaseClassSpecifier (base_class_dctype->GetOpaqueClangQualType(), accessibility, is_virtual, is_base_of_class));
1426 assert(base_classes.back());
1427 }
Chris Lattner24943d22010-06-08 16:52:24 +00001428 }
1429 }
1430 break;
1431
1432 default:
1433 break;
1434 }
1435 }
1436 return count;
1437}
1438
1439
1440clang::DeclContext*
1441SymbolFileDWARF::GetClangDeclContextForTypeUID (lldb::user_id_t type_uid)
1442{
1443 DWARFDebugInfo* debug_info = DebugInfo();
1444 if (debug_info)
1445 {
1446 DWARFCompileUnitSP cu_sp;
1447 const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(type_uid, &cu_sp);
1448 if (die)
1449 return GetClangDeclContextForDIE (cu_sp.get(), die);
1450 }
1451 return NULL;
1452}
1453
1454Type*
1455SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid)
1456{
1457 DWARFDebugInfo* debug_info = DebugInfo();
1458 if (debug_info)
1459 {
1460 const DWARFDebugInfoEntry* type_die = debug_info->GetDIEPtr(type_uid, NULL);
1461 if (type_die != NULL)
1462 {
1463 void *type = type_die->GetUserData();
1464 if (type == NULL)
1465 {
1466 DWARFCompileUnitSP cu_sp;
1467 const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(type_uid, &cu_sp);
1468 if (die != NULL)
1469 {
1470 TypeSP owning_type_sp;
1471 TypeSP type_sp(GetTypeForDIE(cu_sp.get(), die, owning_type_sp, 0, 0));
1472 }
1473 type = type_die->GetUserData();
1474 }
1475 if (type != DIE_IS_BEING_PARSED)
1476 return (Type *)type;
1477 }
1478 }
1479 return NULL;
1480}
1481
1482CompileUnit*
1483SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit* cu, uint32_t cu_idx)
1484{
1485 // Check if the symbol vendor already knows about this compile unit?
1486 if (cu->GetUserData() == NULL)
1487 {
1488 // The symbol vendor doesn't know about this compile unit, we
1489 // need to parse and add it to the symbol vendor object.
1490 CompUnitSP dc_cu;
1491 ParseCompileUnit(cu, dc_cu);
1492 if (dc_cu.get())
1493 {
1494 // Figure out the compile unit index if we weren't given one
1495 if (cu_idx == UINT_MAX)
1496 DebugInfo()->GetCompileUnit(cu->GetOffset(), &cu_idx);
1497
1498 m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(dc_cu, cu_idx);
1499 }
1500 }
1501 return (CompileUnit*)cu->GetUserData();
1502}
1503
1504bool
1505SymbolFileDWARF::GetFunction (DWARFCompileUnit* cu, const DWARFDebugInfoEntry* func_die, SymbolContext& sc)
1506{
1507 sc.Clear();
1508 // Check if the symbol vendor already knows about this compile unit?
1509 sc.module_sp = m_obj_file->GetModule()->GetSP();
1510 sc.comp_unit = GetCompUnitForDWARFCompUnit(cu, UINT_MAX);
1511
1512 sc.function = sc.comp_unit->FindFunctionByUID (func_die->GetOffset()).get();
1513 if (sc.function == NULL)
1514 sc.function = ParseCompileUnitFunction(sc, cu, func_die);
1515
1516 return sc.function != NULL;
1517}
1518
1519uint32_t
1520SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
1521{
1522 Timer scoped_timer(__PRETTY_FUNCTION__,
1523 "SymbolFileDWARF::ResolveSymbolContext (so_addr = { section = %p, offset = 0x%llx }, resolve_scope = 0x%8.8x)",
1524 so_addr.GetSection(),
1525 so_addr.GetOffset(),
1526 resolve_scope);
1527 uint32_t resolved = 0;
1528 if (resolve_scope & ( eSymbolContextCompUnit |
1529 eSymbolContextFunction |
1530 eSymbolContextBlock |
1531 eSymbolContextLineEntry))
1532 {
1533 lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
1534
1535 DWARFDebugAranges* debug_aranges = DebugAranges();
1536 DWARFDebugInfo* debug_info = DebugInfo();
1537 if (debug_aranges)
1538 {
1539 dw_offset_t cu_offset = debug_aranges->FindAddress(file_vm_addr);
1540 if (cu_offset != DW_INVALID_OFFSET)
1541 {
1542 uint32_t cu_idx;
1543 DWARFCompileUnit* cu = debug_info->GetCompileUnit(cu_offset, &cu_idx).get();
1544 if (cu)
1545 {
1546 sc.comp_unit = GetCompUnitForDWARFCompUnit(cu, cu_idx);
1547 assert(sc.comp_unit != NULL);
1548 resolved |= eSymbolContextCompUnit;
1549
1550 if (resolve_scope & eSymbolContextLineEntry)
1551 {
1552 LineTable *line_table = sc.comp_unit->GetLineTable();
1553 if (line_table == NULL)
1554 {
1555 if (ParseCompileUnitLineTable(sc))
1556 line_table = sc.comp_unit->GetLineTable();
1557 }
1558 if (line_table != NULL)
1559 {
1560 if (so_addr.IsLinkedAddress())
1561 {
1562 Address linked_addr (so_addr);
1563 linked_addr.ResolveLinkedAddress();
1564 if (line_table->FindLineEntryByAddress (linked_addr, sc.line_entry))
1565 {
1566 resolved |= eSymbolContextLineEntry;
1567 }
1568 }
1569 else if (line_table->FindLineEntryByAddress (so_addr, sc.line_entry))
1570 {
1571 resolved |= eSymbolContextLineEntry;
1572 }
1573 }
1574 }
1575
1576 if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock))
1577 {
1578 DWARFDebugInfoEntry *function_die = NULL;
1579 DWARFDebugInfoEntry *block_die = NULL;
1580 if (resolve_scope & eSymbolContextBlock)
1581 {
1582 cu->LookupAddress(file_vm_addr, &function_die, &block_die);
1583 }
1584 else
1585 {
1586 cu->LookupAddress(file_vm_addr, &function_die, NULL);
1587 }
1588
1589 if (function_die != NULL)
1590 {
1591 sc.function = sc.comp_unit->FindFunctionByUID (function_die->GetOffset()).get();
1592 if (sc.function == NULL)
1593 sc.function = ParseCompileUnitFunction(sc, cu, function_die);
1594 }
1595
1596 if (sc.function != NULL)
1597 {
1598 resolved |= eSymbolContextFunction;
1599
1600 if (resolve_scope & eSymbolContextBlock)
1601 {
Greg Clayton75ccf502010-08-21 02:22:51 +00001602 Block& block = sc.function->GetBlock (true);
Chris Lattner24943d22010-06-08 16:52:24 +00001603
1604 if (block_die != NULL)
Greg Clayton75ccf502010-08-21 02:22:51 +00001605 sc.block = block.FindBlockByID (block_die->GetOffset());
Chris Lattner24943d22010-06-08 16:52:24 +00001606 else
Greg Clayton75ccf502010-08-21 02:22:51 +00001607 sc.block = block.FindBlockByID (function_die->GetOffset());
Chris Lattner24943d22010-06-08 16:52:24 +00001608 if (sc.block)
1609 resolved |= eSymbolContextBlock;
1610 }
1611 }
1612 }
1613 }
1614 }
1615 }
1616 }
1617 return resolved;
1618}
1619
1620
1621
1622uint32_t
1623SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
1624{
1625 const uint32_t prev_size = sc_list.GetSize();
1626 if (resolve_scope & eSymbolContextCompUnit)
1627 {
1628 DWARFDebugInfo* debug_info = DebugInfo();
1629 if (debug_info)
1630 {
1631 uint32_t cu_idx;
1632 DWARFCompileUnit* cu = NULL;
1633
1634 for (cu_idx = 0; (cu = debug_info->GetCompileUnitAtIndex(cu_idx)) != NULL; ++cu_idx)
1635 {
1636 CompileUnit *dc_cu = GetCompUnitForDWARFCompUnit(cu, cu_idx);
1637 bool file_spec_matches_cu_file_spec = dc_cu != NULL && FileSpec::Compare(file_spec, *dc_cu, false) == 0;
1638 if (check_inlines || file_spec_matches_cu_file_spec)
1639 {
1640 SymbolContext sc (m_obj_file->GetModule());
1641 sc.comp_unit = GetCompUnitForDWARFCompUnit(cu, cu_idx);
1642 assert(sc.comp_unit != NULL);
1643
1644 uint32_t file_idx = UINT32_MAX;
1645
1646 // If we are looking for inline functions only and we don't
1647 // find it in the support files, we are done.
1648 if (check_inlines)
1649 {
1650 file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec);
1651 if (file_idx == UINT32_MAX)
1652 continue;
1653 }
1654
1655 if (line != 0)
1656 {
1657 LineTable *line_table = sc.comp_unit->GetLineTable();
1658
1659 if (line_table != NULL && line != 0)
1660 {
1661 // We will have already looked up the file index if
1662 // we are searching for inline entries.
1663 if (!check_inlines)
1664 file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec);
1665
1666 if (file_idx != UINT32_MAX)
1667 {
1668 uint32_t found_line;
1669 uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_idx, line, false, &sc.line_entry);
1670 found_line = sc.line_entry.line;
1671
1672 while (line_idx != UINT_MAX)
1673 {
1674 sc.function = NULL;
1675 sc.block = NULL;
1676 if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock))
1677 {
1678 const lldb::addr_t file_vm_addr = sc.line_entry.range.GetBaseAddress().GetFileAddress();
1679 if (file_vm_addr != LLDB_INVALID_ADDRESS)
1680 {
1681 DWARFDebugInfoEntry *function_die = NULL;
1682 DWARFDebugInfoEntry *block_die = NULL;
1683 cu->LookupAddress(file_vm_addr, &function_die, resolve_scope & eSymbolContextBlock ? &block_die : NULL);
1684
1685 if (function_die != NULL)
1686 {
1687 sc.function = sc.comp_unit->FindFunctionByUID (function_die->GetOffset()).get();
1688 if (sc.function == NULL)
1689 sc.function = ParseCompileUnitFunction(sc, cu, function_die);
1690 }
1691
1692 if (sc.function != NULL)
1693 {
Greg Clayton75ccf502010-08-21 02:22:51 +00001694 Block& block = sc.function->GetBlock (true);
Chris Lattner24943d22010-06-08 16:52:24 +00001695
1696 if (block_die != NULL)
Greg Clayton75ccf502010-08-21 02:22:51 +00001697 sc.block = block.FindBlockByID (block_die->GetOffset());
Chris Lattner24943d22010-06-08 16:52:24 +00001698 else
Greg Clayton75ccf502010-08-21 02:22:51 +00001699 sc.block = block.FindBlockByID (function_die->GetOffset());
Chris Lattner24943d22010-06-08 16:52:24 +00001700 }
1701 }
1702 }
1703
1704 sc_list.Append(sc);
1705 line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_idx, found_line, true, &sc.line_entry);
1706 }
1707 }
1708 }
1709 else if (file_spec_matches_cu_file_spec && !check_inlines)
1710 {
1711 // only append the context if we aren't looking for inline call sites
1712 // by file and line and if the file spec matches that of the compile unit
1713 sc_list.Append(sc);
1714 }
1715 }
1716 else if (file_spec_matches_cu_file_spec && !check_inlines)
1717 {
1718 // only append the context if we aren't looking for inline call sites
1719 // by file and line and if the file spec matches that of the compile unit
1720 sc_list.Append(sc);
1721 }
1722
1723 if (!check_inlines)
1724 break;
1725 }
1726 }
1727 }
1728 }
1729 return sc_list.GetSize() - prev_size;
1730}
1731
1732void
1733SymbolFileDWARF::Index ()
1734{
1735 if (m_indexed)
1736 return;
1737 m_indexed = true;
1738 Timer scoped_timer (__PRETTY_FUNCTION__,
1739 "SymbolFileDWARF::Index (%s)",
1740 GetObjectFile()->GetFileSpec().GetFilename().AsCString());
1741
1742 DWARFDebugInfo* debug_info = DebugInfo();
1743 if (debug_info)
1744 {
1745 uint32_t cu_idx = 0;
1746 const uint32_t num_compile_units = GetNumCompileUnits();
1747 for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
1748 {
1749 DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
1750
1751 bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1;
1752
Greg Clayton12bec712010-06-28 21:30:43 +00001753 cu->Index (m_base_name_to_function_die,
1754 m_full_name_to_function_die,
1755 m_method_name_to_function_die,
1756 m_selector_name_to_function_die,
Chris Lattner24943d22010-06-08 16:52:24 +00001757 m_name_to_global_die,
1758 m_name_to_type_die);
1759
1760 // Keep memory down by clearing DIEs if this generate function
1761 // caused them to be parsed
1762 if (clear_dies)
1763 cu->ClearDIEs (true);
1764 }
1765
Greg Clayton12bec712010-06-28 21:30:43 +00001766 m_base_name_to_function_die.Sort();
1767 m_full_name_to_function_die.Sort();
1768 m_method_name_to_function_die.Sort();
1769 m_selector_name_to_function_die.Sort();
Chris Lattner24943d22010-06-08 16:52:24 +00001770 m_name_to_global_die.Sort();
1771 m_name_to_type_die.Sort();
1772 }
1773}
1774
1775uint32_t
1776SymbolFileDWARF::FindGlobalVariables (const ConstString &name, bool append, uint32_t max_matches, VariableList& variables)
1777{
1778 std::vector<dw_offset_t> die_offsets;
1779
1780 // If we aren't appending the results to this list, then clear the list
1781 if (!append)
1782 variables.Clear();
1783
1784 // Remember how many variables are in the list before we search in case
1785 // we are appending the results to a variable list.
1786 const uint32_t original_size = variables.GetSize();
1787
1788 // Index the DWARF if we haven't already
1789 if (!m_indexed)
1790 Index ();
1791
1792 const UniqueCStringMap<dw_offset_t>::Entry *entry;
1793
1794 for (entry = m_name_to_global_die.FindFirstValueForName (name.AsCString());
1795 entry != NULL;
1796 entry = m_name_to_global_die.FindNextValueForName (name.AsCString(), entry))
1797 {
1798 DWARFCompileUnitSP cu_sp;
1799 const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr (entry->value, &cu_sp);
1800 DWARFCompileUnit* cu = cu_sp.get();
1801 if (die)
1802 {
1803 SymbolContext sc;
1804 sc.module_sp = m_obj_file->GetModule()->GetSP();
1805 assert (sc.module_sp);
1806
1807 sc.comp_unit = GetCompUnitForDWARFCompUnit(cu, UINT_MAX);
1808 assert(sc.comp_unit != NULL);
1809
1810 ParseVariables(sc, cu_sp.get(), die, false, false, &variables);
1811
1812 if (variables.GetSize() - original_size >= max_matches)
1813 break;
1814 }
1815 }
1816
1817 // Return the number of variable that were appended to the list
1818 return variables.GetSize() - original_size;
1819}
1820
1821uint32_t
1822SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
1823{
1824 std::vector<dw_offset_t> die_offsets;
1825
1826 // If we aren't appending the results to this list, then clear the list
1827 if (!append)
1828 variables.Clear();
1829
1830 // Remember how many variables are in the list before we search in case
1831 // we are appending the results to a variable list.
1832 const uint32_t original_size = variables.GetSize();
1833
1834 // Index the DWARF if we haven't already
1835 if (!m_indexed)
1836 Index ();
1837
1838 // Create the pubnames information so we can quickly lookup external symbols by name
1839 const size_t num_entries = m_name_to_global_die.GetSize();
1840 for (size_t i=0; i<num_entries; i++)
1841 {
1842 if (!regex.Execute(m_name_to_global_die.GetCStringAtIndex (i)))
1843 continue;
1844
1845 const dw_offset_t die_offset = *m_name_to_global_die.GetValueAtIndex (i);
1846
1847 DWARFCompileUnitSP cu_sp;
1848 const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr (die_offset, &cu_sp);
1849 DWARFCompileUnit* cu = cu_sp.get();
1850 if (die)
1851 {
1852 SymbolContext sc;
1853 sc.module_sp = m_obj_file->GetModule()->GetSP();
1854 assert (sc.module_sp);
1855
1856
1857 sc.comp_unit = GetCompUnitForDWARFCompUnit(cu, UINT_MAX);
1858 assert(sc.comp_unit != NULL);
1859
1860 ParseVariables(sc, cu_sp.get(), die, false, false, &variables);
1861
1862 if (variables.GetSize() - original_size >= max_matches)
1863 break;
1864 }
1865 }
1866
1867 // Return the number of variable that were appended to the list
1868 return variables.GetSize() - original_size;
1869}
1870
1871
Greg Clayton12bec712010-06-28 21:30:43 +00001872void
1873SymbolFileDWARF::FindFunctions
1874(
1875 const ConstString &name,
1876 UniqueCStringMap<dw_offset_t> &name_to_die,
1877 SymbolContextList& sc_list
1878)
Chris Lattner24943d22010-06-08 16:52:24 +00001879{
Chris Lattner24943d22010-06-08 16:52:24 +00001880 const UniqueCStringMap<dw_offset_t>::Entry *entry;
1881
1882 SymbolContext sc;
Greg Clayton12bec712010-06-28 21:30:43 +00001883 for (entry = name_to_die.FindFirstValueForName (name.AsCString());
Chris Lattner24943d22010-06-08 16:52:24 +00001884 entry != NULL;
Greg Clayton12bec712010-06-28 21:30:43 +00001885 entry = name_to_die.FindNextValueForName (name.AsCString(), entry))
Chris Lattner24943d22010-06-08 16:52:24 +00001886 {
1887 DWARFCompileUnitSP cu_sp;
1888 const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr (entry->value, &cu_sp);
1889 if (die)
1890 {
1891 if (GetFunction (cu_sp.get(), die, sc))
1892 {
1893 // We found the function, so we should find the line table
1894 // and line table entry as well
1895 LineTable *line_table = sc.comp_unit->GetLineTable();
1896 if (line_table == NULL)
1897 {
1898 if (ParseCompileUnitLineTable(sc))
1899 line_table = sc.comp_unit->GetLineTable();
1900 }
1901 if (line_table != NULL)
1902 line_table->FindLineEntryByAddress (sc.function->GetAddressRange().GetBaseAddress(), sc.line_entry);
1903
1904 sc_list.Append(sc);
1905 }
1906 }
1907 }
1908
Greg Clayton12bec712010-06-28 21:30:43 +00001909}
1910
1911uint32_t
1912SymbolFileDWARF::FindFunctions
1913(
1914 const ConstString &name,
1915 uint32_t name_type_mask,
1916 bool append,
1917 SymbolContextList& sc_list
1918)
1919{
1920 Timer scoped_timer (__PRETTY_FUNCTION__,
1921 "SymbolFileDWARF::FindFunctions (name = '%s')",
1922 name.AsCString());
1923
1924 std::vector<dw_offset_t> die_offsets;
1925
1926 // If we aren't appending the results to this list, then clear the list
1927 if (!append)
1928 sc_list.Clear();
1929
1930 // Remember how many sc_list are in the list before we search in case
1931 // we are appending the results to a variable list.
1932 uint32_t original_size = sc_list.GetSize();
1933
1934 // Index the DWARF if we haven't already
1935 if (!m_indexed)
1936 Index ();
1937
1938 if (name_type_mask & eFunctionNameTypeBase)
1939 FindFunctions (name, m_base_name_to_function_die, sc_list);
1940
1941 if (name_type_mask & eFunctionNameTypeFull)
1942 FindFunctions (name, m_full_name_to_function_die, sc_list);
1943
1944 if (name_type_mask & eFunctionNameTypeMethod)
1945 FindFunctions (name, m_method_name_to_function_die, sc_list);
1946
1947 if (name_type_mask & eFunctionNameTypeSelector)
1948 FindFunctions (name, m_selector_name_to_function_die, sc_list);
1949
Chris Lattner24943d22010-06-08 16:52:24 +00001950 // Return the number of variable that were appended to the list
1951 return sc_list.GetSize() - original_size;
1952}
1953
1954
1955uint32_t
1956SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool append, SymbolContextList& sc_list)
1957{
1958 Timer scoped_timer (__PRETTY_FUNCTION__,
1959 "SymbolFileDWARF::FindFunctions (regex = '%s')",
1960 regex.GetText());
1961
1962 std::vector<dw_offset_t> die_offsets;
1963
1964 // If we aren't appending the results to this list, then clear the list
1965 if (!append)
1966 sc_list.Clear();
1967
1968 // Remember how many sc_list are in the list before we search in case
1969 // we are appending the results to a variable list.
1970 uint32_t original_size = sc_list.GetSize();
1971
1972 // Index the DWARF if we haven't already
1973 if (!m_indexed)
1974 Index ();
1975
1976 // Create the pubnames information so we can quickly lookup external symbols by name
1977 // Create the pubnames information so we can quickly lookup external symbols by name
Greg Clayton12bec712010-06-28 21:30:43 +00001978 const size_t num_entries = m_full_name_to_function_die.GetSize();
Chris Lattner24943d22010-06-08 16:52:24 +00001979 SymbolContext sc;
1980 for (size_t i=0; i<num_entries; i++)
1981 {
Greg Clayton12bec712010-06-28 21:30:43 +00001982 if (!regex.Execute(m_full_name_to_function_die.GetCStringAtIndex (i)))
Chris Lattner24943d22010-06-08 16:52:24 +00001983 continue;
1984
Greg Clayton12bec712010-06-28 21:30:43 +00001985 const dw_offset_t die_offset = *m_full_name_to_function_die.GetValueAtIndex (i);
Chris Lattner24943d22010-06-08 16:52:24 +00001986
1987 DWARFCompileUnitSP cu_sp;
1988 const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr (die_offset, &cu_sp);
1989 if (die)
1990 {
1991 if (GetFunction (cu_sp.get(), die, sc))
1992 {
1993 // We found the function, so we should find the line table
1994 // and line table entry as well
1995 LineTable *line_table = sc.comp_unit->GetLineTable();
Jim Ingham35729d62010-08-20 01:13:58 +00001996
Chris Lattner24943d22010-06-08 16:52:24 +00001997 if (line_table != NULL)
1998 line_table->FindLineEntryByAddress (sc.function->GetAddressRange().GetBaseAddress(), sc.line_entry);
1999
2000
2001 sc_list.Append(sc);
2002 }
2003 }
2004 }
2005
2006 // Return the number of variable that were appended to the list
2007 return sc_list.GetSize() - original_size;
2008}
2009
Chris Lattner24943d22010-06-08 16:52:24 +00002010uint32_t
Greg Clayton960d6a42010-08-03 00:35:52 +00002011SymbolFileDWARF::FindTypes(const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types)
Chris Lattner24943d22010-06-08 16:52:24 +00002012{
2013 // If we aren't appending the results to this list, then clear the list
2014 if (!append)
2015 types.Clear();
2016
2017 // Create the pubnames information so we can quickly lookup external symbols by name
2018 DWARFDebugPubnames* pubtypes = DebugPubtypes();
Greg Clayton960d6a42010-08-03 00:35:52 +00002019
Chris Lattner24943d22010-06-08 16:52:24 +00002020 if (pubtypes)
2021 {
2022 std::vector<dw_offset_t> die_offsets;
2023 if (!pubtypes->Find(name.AsCString(), false, die_offsets))
2024 {
Greg Clayton960d6a42010-08-03 00:35:52 +00002025// DWARFDebugPubnames* pub_base_types = DebugPubBaseTypes();
2026// if (pub_base_types && !pub_base_types->Find(name.AsCString(), false, die_offsets))
Chris Lattner24943d22010-06-08 16:52:24 +00002027 return 0;
2028 }
Greg Clayton960d6a42010-08-03 00:35:52 +00002029 return FindTypes(die_offsets, max_matches, types);
Chris Lattner24943d22010-06-08 16:52:24 +00002030 }
2031 return 0;
2032}
2033
2034
Greg Clayton960d6a42010-08-03 00:35:52 +00002035//uint32_t
2036//SymbolFileDWARF::FindTypes(const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types)
2037//{
2038// // If we aren't appending the results to this list, then clear the list
2039// if (!append)
2040// types.Clear();
2041//
2042// // Create the pubnames information so we can quickly lookup external symbols by name
2043// DWARFDebugPubnames* pubtypes = DebugPubtypes();
2044// if (pubtypes)
2045// {
2046// std::vector<dw_offset_t> die_offsets;
2047// if (!pubtypes->Find(regex, die_offsets))
2048// {
2049// DWARFDebugPubnames* pub_base_types = DebugPubBaseTypes();
2050// if (pub_base_types && !pub_base_types->Find(regex, die_offsets))
2051// return 0;
2052// }
2053//
2054// return FindTypes(die_offsets, max_matches, encoding, udt_uid, types);
2055// }
2056//
2057// return 0;
2058//}
2059//
Chris Lattner24943d22010-06-08 16:52:24 +00002060
2061
2062uint32_t
Greg Clayton960d6a42010-08-03 00:35:52 +00002063SymbolFileDWARF::FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, TypeList& types)
Chris Lattner24943d22010-06-08 16:52:24 +00002064{
2065 // Remember how many sc_list are in the list before we search in case
2066 // we are appending the results to a variable list.
Greg Clayton960d6a42010-08-03 00:35:52 +00002067 uint32_t original_size = types.GetSize();
Chris Lattner24943d22010-06-08 16:52:24 +00002068
2069 const uint32_t num_die_offsets = die_offsets.size();
2070 // Parse all of the types we found from the pubtypes matches
2071 uint32_t i;
2072 uint32_t num_matches = 0;
2073 for (i = 0; i < num_die_offsets; ++i)
2074 {
Greg Clayton960d6a42010-08-03 00:35:52 +00002075 Type *matching_type = ResolveTypeUID (die_offsets[i]);
2076 if (matching_type)
Chris Lattner24943d22010-06-08 16:52:24 +00002077 {
Greg Clayton960d6a42010-08-03 00:35:52 +00002078 // We found a type pointer, now find the shared pointer form our type list
2079 TypeSP type_sp (m_obj_file->GetModule()->GetTypeList()->FindType(matching_type->GetID()));
2080 assert (type_sp.get() != NULL);
2081 types.InsertUnique (type_sp);
2082 ++num_matches;
2083 if (num_matches >= max_matches)
2084 break;
Chris Lattner24943d22010-06-08 16:52:24 +00002085 }
2086 }
2087
2088 // Return the number of variable that were appended to the list
Greg Clayton960d6a42010-08-03 00:35:52 +00002089 return types.GetSize() - original_size;
Chris Lattner24943d22010-06-08 16:52:24 +00002090}
2091
Chris Lattner24943d22010-06-08 16:52:24 +00002092
2093size_t
2094SymbolFileDWARF::ParseChildParameters
2095(
2096 const SymbolContext& sc,
2097 TypeSP& type_sp,
2098 const DWARFCompileUnit* dwarf_cu,
2099 const DWARFDebugInfoEntry *parent_die,
2100 TypeList* type_list,
2101 std::vector<void *>& function_param_types,
2102 std::vector<clang::ParmVarDecl*>& function_param_decls
2103)
2104{
2105 if (parent_die == NULL)
2106 return 0;
2107
2108 size_t count = 0;
2109 const DWARFDebugInfoEntry *die;
2110 for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
2111 {
2112 dw_tag_t tag = die->Tag();
2113 switch (tag)
2114 {
2115 case DW_TAG_formal_parameter:
2116 {
2117 DWARFDebugInfoEntry::Attributes attributes;
2118 const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
2119 if (num_attributes > 0)
2120 {
2121 const char *name = NULL;
2122 Declaration decl;
2123 dw_offset_t param_type_die_offset = DW_INVALID_OFFSET;
2124 // one of None, Auto, Register, Extern, Static, PrivateExtern
2125
2126 clang::VarDecl::StorageClass storage = clang::VarDecl::None;
2127 uint32_t i;
2128 for (i=0; i<num_attributes; ++i)
2129 {
2130 const dw_attr_t attr = attributes.AttributeAtIndex(i);
2131 DWARFFormValue form_value;
2132 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
2133 {
2134 switch (attr)
2135 {
2136 case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
2137 case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
2138 case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
2139 case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
2140 case DW_AT_type: param_type_die_offset = form_value.Reference(dwarf_cu); break;
2141 case DW_AT_location:
2142 // if (form_value.BlockData())
2143 // {
2144 // const DataExtractor& debug_info_data = debug_info();
2145 // uint32_t block_length = form_value.Unsigned();
2146 // DataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length);
2147 // }
2148 // else
2149 // {
2150 // }
2151 // break;
2152 case DW_AT_artificial:
2153 case DW_AT_const_value:
2154 case DW_AT_default_value:
2155 case DW_AT_description:
2156 case DW_AT_endianity:
2157 case DW_AT_is_optional:
2158 case DW_AT_segment:
2159 case DW_AT_variable_parameter:
2160 default:
2161 case DW_AT_abstract_origin:
2162 case DW_AT_sibling:
2163 break;
2164 }
2165 }
2166 }
2167 Type *dc_type = ResolveTypeUID(param_type_die_offset);
2168 if (dc_type)
2169 {
2170 function_param_types.push_back (dc_type->GetOpaqueClangQualType());
2171
2172 clang::ParmVarDecl *param_var_decl = type_list->GetClangASTContext().CreateParmeterDeclaration (name, dc_type->GetOpaqueClangQualType(), storage);
2173 assert(param_var_decl);
2174 function_param_decls.push_back(param_var_decl);
2175 }
2176 }
2177 }
2178 break;
2179
2180 default:
2181 break;
2182 }
2183 }
2184 return count;
2185}
2186
2187size_t
2188SymbolFileDWARF::ParseChildEnumerators
2189(
2190 const SymbolContext& sc,
2191 TypeSP& type_sp,
2192 void * enumerator_qual_type,
2193 uint32_t enumerator_byte_size,
2194 const DWARFCompileUnit* dwarf_cu,
2195 const DWARFDebugInfoEntry *parent_die
2196)
2197{
2198 if (parent_die == NULL)
2199 return 0;
2200
2201 size_t enumerators_added = 0;
2202 const DWARFDebugInfoEntry *die;
2203 for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
2204 {
2205 const dw_tag_t tag = die->Tag();
2206 if (tag == DW_TAG_enumerator)
2207 {
2208 DWARFDebugInfoEntry::Attributes attributes;
2209 const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, attributes);
2210 if (num_child_attributes > 0)
2211 {
2212 const char *name = NULL;
2213 bool got_value = false;
2214 int64_t enum_value = 0;
2215 Declaration decl;
2216
2217 uint32_t i;
2218 for (i=0; i<num_child_attributes; ++i)
2219 {
2220 const dw_attr_t attr = attributes.AttributeAtIndex(i);
2221 DWARFFormValue form_value;
2222 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
2223 {
2224 switch (attr)
2225 {
2226 case DW_AT_const_value:
2227 got_value = true;
2228 enum_value = form_value.Unsigned();
2229 break;
2230
2231 case DW_AT_name:
2232 name = form_value.AsCString(&get_debug_str_data());
2233 break;
2234
2235 case DW_AT_description:
2236 default:
2237 case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
2238 case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
2239 case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
2240 case DW_AT_sibling:
2241 break;
2242 }
2243 }
2244 }
2245
2246 if (name && name[0] && got_value)
2247 {
2248 TypeList* type_list = m_obj_file->GetModule()->GetTypeList();
2249 type_list->GetClangASTContext().AddEnumerationValueToEnumerationType (type_sp->GetOpaqueClangQualType(), enumerator_qual_type, decl, name, enum_value, enumerator_byte_size * 8);
2250 ++enumerators_added;
2251 }
2252 }
2253 }
2254 }
2255 return enumerators_added;
2256}
2257
2258void
2259SymbolFileDWARF::ParseChildArrayInfo
2260(
2261 const SymbolContext& sc,
2262 const DWARFCompileUnit* dwarf_cu,
2263 const DWARFDebugInfoEntry *parent_die,
2264 int64_t& first_index,
2265 std::vector<uint64_t>& element_orders,
2266 uint32_t& byte_stride,
2267 uint32_t& bit_stride
2268)
2269{
2270 if (parent_die == NULL)
2271 return;
2272
2273 const DWARFDebugInfoEntry *die;
2274 for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
2275 {
2276 const dw_tag_t tag = die->Tag();
2277 switch (tag)
2278 {
2279 case DW_TAG_enumerator:
2280 {
2281 DWARFDebugInfoEntry::Attributes attributes;
2282 const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, attributes);
2283 if (num_child_attributes > 0)
2284 {
2285 const char *name = NULL;
2286 bool got_value = false;
2287 int64_t enum_value = 0;
2288
2289 uint32_t i;
2290 for (i=0; i<num_child_attributes; ++i)
2291 {
2292 const dw_attr_t attr = attributes.AttributeAtIndex(i);
2293 DWARFFormValue form_value;
2294 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
2295 {
2296 switch (attr)
2297 {
2298 case DW_AT_const_value:
2299 got_value = true;
2300 enum_value = form_value.Unsigned();
2301 break;
2302
2303 case DW_AT_name:
2304 name = form_value.AsCString(&get_debug_str_data());
2305 break;
2306
2307 case DW_AT_description:
2308 default:
2309 case DW_AT_decl_file:
2310 case DW_AT_decl_line:
2311 case DW_AT_decl_column:
2312 case DW_AT_sibling:
2313 break;
2314 }
2315 }
2316 }
2317 }
2318 }
2319 break;
2320
2321 case DW_TAG_subrange_type:
2322 {
2323 DWARFDebugInfoEntry::Attributes attributes;
2324 const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, attributes);
2325 if (num_child_attributes > 0)
2326 {
2327 const char *name = NULL;
2328 bool got_value = false;
2329 uint64_t byte_size = 0;
2330 int64_t enum_value = 0;
2331 uint64_t num_elements = 0;
2332 uint64_t lower_bound = 0;
2333 uint64_t upper_bound = 0;
2334 uint32_t i;
2335 for (i=0; i<num_child_attributes; ++i)
2336 {
2337 const dw_attr_t attr = attributes.AttributeAtIndex(i);
2338 DWARFFormValue form_value;
2339 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
2340 {
2341 switch (attr)
2342 {
2343 case DW_AT_const_value:
2344 got_value = true;
2345 enum_value = form_value.Unsigned();
2346 break;
2347
2348 case DW_AT_name:
2349 name = form_value.AsCString(&get_debug_str_data());
2350 break;
2351
2352 case DW_AT_count:
2353 num_elements = form_value.Unsigned();
2354 break;
2355
2356 case DW_AT_bit_stride:
2357 bit_stride = form_value.Unsigned();
2358 break;
2359
2360 case DW_AT_byte_stride:
2361 byte_stride = form_value.Unsigned();
2362 break;
2363
2364 case DW_AT_byte_size:
2365 byte_size = form_value.Unsigned();
2366 break;
2367
2368 case DW_AT_lower_bound:
2369 lower_bound = form_value.Unsigned();
2370 break;
2371
2372 case DW_AT_upper_bound:
2373 upper_bound = form_value.Unsigned();
2374 break;
2375
2376 default:
2377 //printf("0x%8.8x: %-30s skipping attribute at 0x%8.8x: %s\n", die->GetOffset(), DW_TAG_value_to_name(tag), attributes.die_offsets[i], DW_AT_value_to_name(attr)); // remove this, debug only
2378
2379 case DW_AT_abstract_origin:
2380 case DW_AT_accessibility:
2381 case DW_AT_allocated:
2382 case DW_AT_associated:
2383 case DW_AT_data_location:
2384 case DW_AT_declaration:
2385 case DW_AT_description:
2386 case DW_AT_sibling:
2387 case DW_AT_threads_scaled:
2388 case DW_AT_type:
2389 case DW_AT_visibility:
2390 break;
2391 }
2392 }
2393 }
2394
2395 if (upper_bound > lower_bound)
2396 num_elements = upper_bound - lower_bound + 1;
2397
2398 if (num_elements > 0)
2399 element_orders.push_back (num_elements);
2400 }
2401 }
2402 break;
2403 }
2404 }
2405}
2406
2407Type*
2408SymbolFileDWARF::GetUniquedTypeForDIEOffset(dw_offset_t type_die_offset, TypeSP& owning_type_sp, int32_t child_type, uint32_t idx, bool safe)
2409{
2410 if (type_die_offset != DW_INVALID_OFFSET)
2411 {
2412 DWARFCompileUnitSP cu_sp;
2413 const DWARFDebugInfoEntry* type_die = DebugInfo()->GetDIEPtr(type_die_offset, &cu_sp);
2414 assert(type_die != NULL);
2415 GetTypeForDIE(cu_sp.get(), type_die, owning_type_sp, child_type, idx);
2416 // Return the uniqued type if there is one
2417 Type* type = (Type*)type_die->GetUserData();
2418 if (type == DIE_IS_BEING_PARSED && safe)
2419 return NULL;
2420 return type;
2421 }
2422 return NULL;
2423}
2424
2425TypeSP
2426SymbolFileDWARF::GetTypeForDIE(DWARFCompileUnit *cu, const DWARFDebugInfoEntry* die, TypeSP& owning_type_sp, int32_t child_type, uint32_t idx)
2427{
2428 TypeSP type_sp;
2429 if (die != NULL)
2430 {
2431 assert(cu != NULL);
2432 Type *type_ptr = (Type *)die->GetUserData();
2433 if (type_ptr == NULL)
2434 {
2435 SymbolContext sc(GetCompUnitForDWARFCompUnit(cu));
2436 bool type_is_new = false;
2437 type_sp = ParseType(sc, cu, die, type_is_new);
2438 type_ptr = (Type *)die->GetUserData();
2439 if (owning_type_sp.get() == NULL)
2440 owning_type_sp = type_sp;
2441 }
2442 else if (type_ptr != DIE_IS_BEING_PARSED)
2443 {
2444 // Grab the existing type from the master types lists
2445 type_sp = m_obj_file->GetModule()->GetTypeList()->FindType(type_ptr->GetID());
2446 }
2447
2448 }
2449 return type_sp;
2450}
2451
2452clang::DeclContext *
2453SymbolFileDWARF::GetClangDeclContextForDIEOffset (dw_offset_t die_offset)
2454{
2455 if (die_offset != DW_INVALID_OFFSET)
2456 {
2457 DWARFCompileUnitSP cu_sp;
2458 const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr(die_offset, &cu_sp);
2459 return GetClangDeclContextForDIE (cu_sp.get(), die);
2460 }
2461 return NULL;
2462}
2463
2464
2465
2466clang::DeclContext *
2467SymbolFileDWARF::GetClangDeclContextForDIE (const DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
2468{
2469 DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die);
2470 if (pos != m_die_to_decl_ctx.end())
2471 return pos->second;
2472
2473 while (die != NULL)
2474 {
2475 switch (die->Tag())
2476 {
2477 case DW_TAG_namespace:
2478 {
2479 const char *namespace_name = die->GetAttributeValueAsString(this, cu, DW_AT_name, NULL);
2480 if (namespace_name)
2481 {
2482 TypeList* type_list = m_obj_file->GetModule()->GetTypeList();
2483 assert(type_list);
2484 Declaration decl; // TODO: fill in the decl object
2485 clang::NamespaceDecl *namespace_decl = type_list->GetClangASTContext().GetUniqueNamespaceDeclaration (namespace_name, decl, GetClangDeclContextForDIE (cu, die->GetParent()));
2486 if (namespace_decl)
2487 m_die_to_decl_ctx[die] = (clang::DeclContext*)namespace_decl;
2488 return namespace_decl;
2489 }
2490 }
2491 break;
2492
2493 default:
2494 break;
2495 }
2496 clang::DeclContext *decl_ctx;
2497 decl_ctx = GetClangDeclContextForDIEOffset (die->GetAttributeValueAsUnsigned(this, cu, DW_AT_specification, DW_INVALID_OFFSET));
2498 if (decl_ctx)
2499 return decl_ctx;
2500
2501 decl_ctx = GetClangDeclContextForDIEOffset (die->GetAttributeValueAsUnsigned(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET));
2502 if (decl_ctx)
2503 return decl_ctx;
2504
2505 die = die->GetParent();
2506 }
2507 return NULL;
2508}
2509
2510TypeSP
2511SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool &type_is_new)
2512{
2513 TypeSP type_sp;
2514
Sean Callanan70a4f922010-08-06 00:32:49 +00002515 AccessType accessibility = eAccessNone;
Chris Lattner24943d22010-06-08 16:52:24 +00002516 if (die != NULL)
2517 {
2518 dw_tag_t tag = die->Tag();
2519 if (die->GetUserData() == NULL)
2520 {
2521 type_is_new = true;
2522
2523 bool is_forward_declaration = false;
2524 DWARFDebugInfoEntry::Attributes attributes;
2525 const char *type_name_cstr = NULL;
2526 ConstString type_name_dbstr;
2527 Type::EncodingUIDType encoding_uid_type = Type::eIsTypeWithUID;
2528 void *clang_type = NULL;
2529
2530 TypeList* type_list = m_obj_file->GetModule()->GetTypeList();
2531 dw_attr_t attr;
2532
2533 switch (tag)
2534 {
2535 case DW_TAG_base_type:
2536 case DW_TAG_pointer_type:
2537 case DW_TAG_reference_type:
2538 case DW_TAG_typedef:
2539 case DW_TAG_const_type:
2540 case DW_TAG_restrict_type:
2541 case DW_TAG_volatile_type:
2542 {
2543 //printf("0x%8.8x: %s (ParesTypes)\n", die->GetOffset(), DW_TAG_value_to_name(tag));
2544 // Set a bit that lets us know that we are currently parsing this
2545 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED);
2546
2547 const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
2548 Declaration decl;
2549 uint32_t encoding = 0;
2550 size_t byte_size = 0;
2551 lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
2552
2553 if (num_attributes > 0)
2554 {
2555 uint32_t i;
2556 for (i=0; i<num_attributes; ++i)
2557 {
2558 attr = attributes.AttributeAtIndex(i);
2559 DWARFFormValue form_value;
2560 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
2561 {
2562 switch (attr)
2563 {
2564 case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
2565 case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
2566 case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
2567 case DW_AT_name:
2568 type_name_cstr = form_value.AsCString(&get_debug_str_data());
2569 type_name_dbstr.SetCString(type_name_cstr);
2570 break;
2571 case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
2572 case DW_AT_encoding: encoding = form_value.Unsigned(); break;
2573 case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break;
2574 default:
2575 case DW_AT_sibling:
2576 break;
2577 }
2578 }
2579 }
2580 }
2581
2582 switch (tag)
2583 {
2584 default:
2585 case DW_TAG_base_type:
2586 clang_type = type_list->GetClangASTContext().GetBuiltinTypeForDWARFEncodingAndBitSize (type_name_cstr, encoding, byte_size * 8);
2587 break;
2588
2589 case DW_TAG_pointer_type:
2590 // The encoding_uid will be embedded into the
2591 // Type object and will be looked up when the Type::GetOpaqueClangQualType()
2592 encoding_uid_type = Type::ePointerToTypeWithUID;
2593 break;
2594
2595 case DW_TAG_reference_type:
2596 // The encoding_uid will be embedded into the
2597 // Type object and will be looked up when the Type::GetOpaqueClangQualType()
2598 encoding_uid_type = Type::eLValueReferenceToTypeWithUID;
2599 break;
2600
2601 case DW_TAG_typedef:
2602 // The encoding_uid will be embedded into the
2603 // Type object and will be looked up when the Type::GetOpaqueClangQualType()
2604 encoding_uid_type = Type::eTypedefToTypeWithUID;
2605 break;
2606
2607 case DW_TAG_const_type:
2608 // The encoding_uid will be embedded into the
2609 // Type object and will be looked up when the Type::GetOpaqueClangQualType()
2610 encoding_uid_type = Type::eIsConstTypeWithUID; //ClangASTContext::AddConstModifier (clang_type);
2611 break;
2612
2613 case DW_TAG_restrict_type:
2614 // The encoding_uid will be embedded into the
2615 // Type object and will be looked up when the Type::GetOpaqueClangQualType()
2616 encoding_uid_type = Type::eIsRestrictTypeWithUID; //ClangASTContext::AddRestrictModifier (clang_type);
2617 break;
2618
2619 case DW_TAG_volatile_type:
2620 // The encoding_uid will be embedded into the
2621 // Type object and will be looked up when the Type::GetOpaqueClangQualType()
2622 encoding_uid_type = Type::eIsVolatileTypeWithUID; //ClangASTContext::AddVolatileModifier (clang_type);
2623 break;
2624 }
2625
Greg Clayton960d6a42010-08-03 00:35:52 +00002626 if (type_name_cstr != NULL && sc.comp_unit != NULL &&
2627 (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus))
2628 {
2629 static ConstString g_objc_type_name_id("id");
2630 static ConstString g_objc_type_name_Class("Class");
2631 static ConstString g_objc_type_name_selector("SEL");
2632
2633 if (type_name_dbstr == g_objc_type_name_id)
2634 {
2635 clang_type = type_list->GetClangASTContext().GetBuiltInType_objc_id();
Greg Clayton960d6a42010-08-03 00:35:52 +00002636 }
2637 else if (type_name_dbstr == g_objc_type_name_Class)
2638 {
2639 clang_type = type_list->GetClangASTContext().GetBuiltInType_objc_Class();
Greg Clayton960d6a42010-08-03 00:35:52 +00002640 }
2641 else if (type_name_dbstr == g_objc_type_name_selector)
2642 {
2643 clang_type = type_list->GetClangASTContext().GetBuiltInType_objc_selector();
Greg Clayton960d6a42010-08-03 00:35:52 +00002644 }
2645 }
2646
Chris Lattner24943d22010-06-08 16:52:24 +00002647 type_sp.reset( new Type(die->GetOffset(), this, type_name_dbstr, byte_size, NULL, encoding_uid, encoding_uid_type, &decl, clang_type));
2648
2649 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
2650
2651
2652// Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false);
2653// if (encoding_type != NULL)
2654// {
2655// if (encoding_type != DIE_IS_BEING_PARSED)
2656// type_sp->SetEncodingType(encoding_type);
2657// else
2658// m_indirect_fixups.push_back(type_sp.get());
2659// }
2660 }
2661 break;
2662
2663 case DW_TAG_structure_type:
2664 case DW_TAG_union_type:
2665 case DW_TAG_class_type:
2666 {
2667 //printf("0x%8.8x: %s (ParesTypes)\n", die->GetOffset(), DW_TAG_value_to_name(tag));
2668 // Set a bit that lets us know that we are currently parsing this
2669 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED);
2670
2671 size_t byte_size = 0;
Greg Clayton9488b742010-07-28 02:04:09 +00002672 LanguageType class_language = eLanguageTypeUnknown;
Chris Lattner24943d22010-06-08 16:52:24 +00002673 //bool struct_is_class = false;
2674 Declaration decl;
2675 const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
2676 if (num_attributes > 0)
2677 {
2678 uint32_t i;
2679 for (i=0; i<num_attributes; ++i)
2680 {
2681 attr = attributes.AttributeAtIndex(i);
2682 DWARFFormValue form_value;
2683 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
2684 {
2685 switch (attr)
2686 {
Greg Clayton9488b742010-07-28 02:04:09 +00002687 case DW_AT_decl_file:
2688 decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned()));
2689 break;
2690
2691 case DW_AT_decl_line:
2692 decl.SetLine(form_value.Unsigned());
2693 break;
2694
2695 case DW_AT_decl_column:
2696 decl.SetColumn(form_value.Unsigned());
2697 break;
2698
Chris Lattner24943d22010-06-08 16:52:24 +00002699 case DW_AT_name:
2700 type_name_cstr = form_value.AsCString(&get_debug_str_data());
2701 type_name_dbstr.SetCString(type_name_cstr);
2702 break;
Greg Clayton9488b742010-07-28 02:04:09 +00002703
2704 case DW_AT_byte_size:
2705 byte_size = form_value.Unsigned();
2706 break;
2707
2708 case DW_AT_accessibility:
2709 accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
2710 break;
2711
2712 case DW_AT_declaration:
2713 is_forward_declaration = form_value.Unsigned() != 0;
2714 break;
2715
2716 case DW_AT_APPLE_runtime_class:
2717 class_language = (LanguageType)form_value.Signed();
2718 break;
2719
Chris Lattner24943d22010-06-08 16:52:24 +00002720 case DW_AT_allocated:
2721 case DW_AT_associated:
2722 case DW_AT_data_location:
2723 case DW_AT_description:
2724 case DW_AT_start_scope:
2725 case DW_AT_visibility:
2726 default:
2727 case DW_AT_sibling:
2728 break;
2729 }
2730 }
2731 }
2732 }
2733
2734 int tag_decl_kind = -1;
Sean Callanan70a4f922010-08-06 00:32:49 +00002735 AccessType default_accessibility = eAccessNone;
Chris Lattner24943d22010-06-08 16:52:24 +00002736 if (tag == DW_TAG_structure_type)
2737 {
2738 tag_decl_kind = clang::TTK_Struct;
Sean Callanan70a4f922010-08-06 00:32:49 +00002739 default_accessibility = eAccessPublic;
Chris Lattner24943d22010-06-08 16:52:24 +00002740 }
2741 else if (tag == DW_TAG_union_type)
2742 {
2743 tag_decl_kind = clang::TTK_Union;
Sean Callanan70a4f922010-08-06 00:32:49 +00002744 default_accessibility = eAccessPublic;
Chris Lattner24943d22010-06-08 16:52:24 +00002745 }
2746 else if (tag == DW_TAG_class_type)
2747 {
2748 tag_decl_kind = clang::TTK_Class;
Sean Callanan70a4f922010-08-06 00:32:49 +00002749 default_accessibility = eAccessPrivate;
Chris Lattner24943d22010-06-08 16:52:24 +00002750 }
2751
2752 assert (tag_decl_kind != -1);
Greg Clayton9488b742010-07-28 02:04:09 +00002753 clang_type = type_list->GetClangASTContext().CreateRecordType (type_name_cstr, tag_decl_kind, GetClangDeclContextForDIE (dwarf_cu, die), class_language);
Chris Lattner24943d22010-06-08 16:52:24 +00002754
2755 m_die_to_decl_ctx[die] = ClangASTContext::GetDeclContextForType (clang_type);
2756 type_sp.reset( new Type(die->GetOffset(), this, type_name_dbstr, byte_size, NULL, LLDB_INVALID_UID, Type::eIsTypeWithUID, &decl, clang_type));
2757
2758 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
2759
2760// assert(type_sp.get());
2761// if (accessibility)
2762// type_sp->SetAccess(accessibility);
2763//
2764 type_list->GetClangASTContext().StartTagDeclarationDefinition (clang_type);
2765 if (die->HasChildren())
2766 {
2767 std::vector<clang::CXXBaseSpecifier *> base_classes;
2768 std::vector<int> member_accessibilities;
2769 bool is_a_class = false;
Greg Clayton9488b742010-07-28 02:04:09 +00002770 ParseChildMembers (sc,
2771 type_sp,
2772 dwarf_cu,
2773 die,
2774 clang_type,
2775 class_language,
2776 base_classes,
2777 member_accessibilities,
2778 default_accessibility,
2779 is_a_class);
2780
Chris Lattner24943d22010-06-08 16:52:24 +00002781 // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
2782 // need to tell the clang type it is actually a class.
Greg Clayton9488b742010-07-28 02:04:09 +00002783 if (class_language != eLanguageTypeObjC)
2784 {
2785 if (is_a_class && tag_decl_kind != clang::TTK_Class)
2786 type_list->GetClangASTContext().SetTagTypeKind (clang_type, clang::TTK_Class);
2787 }
Chris Lattner24943d22010-06-08 16:52:24 +00002788
2789 // Since DW_TAG_structure_type gets used for both classes
2790 // and structures, we may need to set any DW_TAG_member
2791 // fields to have a "private" access if none was specified.
2792 // When we parsed the child members we tracked that actual
2793 // accessibility value for each DW_TAG_member in the
2794 // "member_accessibilities" array. If the value for the
2795 // member is zero, then it was set to the "default_accessibility"
2796 // which for structs was "public". Below we correct this
2797 // by setting any fields to "private" that weren't correctly
2798 // set.
2799 if (is_a_class && !member_accessibilities.empty())
2800 {
2801 // This is a class and all members that didn't have
2802 // their access specified are private.
Sean Callanan70a4f922010-08-06 00:32:49 +00002803 type_list->GetClangASTContext().SetDefaultAccessForRecordFields (clang_type, eAccessPrivate, &member_accessibilities.front(), member_accessibilities.size());
Chris Lattner24943d22010-06-08 16:52:24 +00002804 }
2805
2806 if (!base_classes.empty())
2807 {
Greg Clayton53d68e72010-07-20 22:52:08 +00002808 type_list->GetClangASTContext().SetBaseClassesForClassType (clang_type, &base_classes.front(), base_classes.size());
2809
2810 // Clang will copy each CXXBaseSpecifier in "base_classes"
2811 // so we have to free them all.
2812 ClangASTContext::DeleteBaseClassSpecifiers (&base_classes.front(), base_classes.size());
Chris Lattner24943d22010-06-08 16:52:24 +00002813 }
Greg Claytone9d0df42010-07-02 01:29:13 +00002814
Chris Lattner24943d22010-06-08 16:52:24 +00002815 }
2816 type_list->GetClangASTContext().CompleteTagDeclarationDefinition (clang_type);
2817 }
2818 break;
2819
2820 case DW_TAG_enumeration_type:
2821 {
2822 //printf("0x%8.8x: %s (ParesTypes)\n", die->GetOffset(), DW_TAG_value_to_name(tag));
2823 // Set a bit that lets us know that we are currently parsing this
2824 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED);
2825
2826 size_t byte_size = 0;
2827 lldb::user_id_t encoding_uid = DW_INVALID_OFFSET;
2828 Declaration decl;
2829
2830 const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
2831 if (num_attributes > 0)
2832 {
2833 uint32_t i;
2834
2835 for (i=0; i<num_attributes; ++i)
2836 {
2837 attr = attributes.AttributeAtIndex(i);
2838 DWARFFormValue form_value;
2839 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
2840 {
2841 switch (attr)
2842 {
2843 case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
2844 case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
2845 case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
2846 case DW_AT_name:
2847 type_name_cstr = form_value.AsCString(&get_debug_str_data());
2848 type_name_dbstr.SetCString(type_name_cstr);
2849 break;
2850 case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break;
2851 case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
Greg Clayton84f80752010-07-22 18:30:50 +00002852 case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
Chris Lattner24943d22010-06-08 16:52:24 +00002853 case DW_AT_declaration: is_forward_declaration = form_value.Unsigned() != 0; break;
2854 case DW_AT_allocated:
2855 case DW_AT_associated:
2856 case DW_AT_bit_stride:
2857 case DW_AT_byte_stride:
2858 case DW_AT_data_location:
2859 case DW_AT_description:
2860 case DW_AT_start_scope:
2861 case DW_AT_visibility:
2862 case DW_AT_specification:
2863 case DW_AT_abstract_origin:
2864 case DW_AT_sibling:
2865 break;
2866 }
2867 }
2868 }
Greg Claytone37f23c2010-09-12 23:17:56 +00002869
2870 void *enumerator_qual_type = type_list->GetClangASTContext().GetBuiltinTypeForDWARFEncodingAndBitSize (NULL, DW_ATE_signed, byte_size * 8);
Chris Lattner24943d22010-06-08 16:52:24 +00002871
Greg Claytone37f23c2010-09-12 23:17:56 +00002872 clang_type = type_list->GetClangASTContext().CreateEnumerationType(decl, type_name_cstr, enumerator_qual_type);
Chris Lattner24943d22010-06-08 16:52:24 +00002873 m_die_to_decl_ctx[die] = ClangASTContext::GetDeclContextForType (clang_type);
2874 type_sp.reset( new Type(die->GetOffset(), this, type_name_dbstr, byte_size, NULL, encoding_uid, Type::eIsTypeWithUID, &decl, clang_type));
2875
2876 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
2877
2878 if (die->HasChildren())
2879 {
2880 type_list->GetClangASTContext().StartTagDeclarationDefinition (clang_type);
Chris Lattner24943d22010-06-08 16:52:24 +00002881 ParseChildEnumerators(sc, type_sp, enumerator_qual_type, byte_size, dwarf_cu, die);
2882 type_list->GetClangASTContext().CompleteTagDeclarationDefinition (clang_type);
2883 }
2884 }
2885 }
2886 break;
2887
Jim Ingham0007dff2010-08-12 01:20:14 +00002888 case DW_TAG_inlined_subroutine:
Chris Lattner24943d22010-06-08 16:52:24 +00002889 case DW_TAG_subprogram:
2890 case DW_TAG_subroutine_type:
2891 {
2892 //printf("0x%8.8x: %s (ParesTypes)\n", die->GetOffset(), DW_TAG_value_to_name(tag));
2893 // Set a bit that lets us know that we are currently parsing this
2894 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED);
2895
2896 const char *mangled = NULL;
2897 dw_offset_t type_die_offset = DW_INVALID_OFFSET;
2898 Declaration decl;
2899 bool isVariadic = false;
2900 bool is_inline = false;
2901 unsigned type_quals = 0;
2902 clang::FunctionDecl::StorageClass storage = clang::FunctionDecl::None;//, Extern, Static, PrivateExtern
2903
2904
2905 const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
2906 if (num_attributes > 0)
2907 {
2908 uint32_t i;
2909 for (i=0; i<num_attributes; ++i)
2910 {
2911 attr = attributes.AttributeAtIndex(i);
2912 DWARFFormValue form_value;
2913 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
2914 {
2915 switch (attr)
2916 {
2917 case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
2918 case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
2919 case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
2920 case DW_AT_name:
2921 type_name_cstr = form_value.AsCString(&get_debug_str_data());
2922 type_name_dbstr.SetCString(type_name_cstr);
2923 break;
2924
2925 case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break;
2926 case DW_AT_type: type_die_offset = form_value.Reference(dwarf_cu); break;
Greg Clayton84f80752010-07-22 18:30:50 +00002927 case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
Chris Lattner24943d22010-06-08 16:52:24 +00002928 case DW_AT_declaration: is_forward_declaration = form_value.Unsigned() != 0; break;
2929 case DW_AT_external:
2930 if (form_value.Unsigned())
2931 {
2932 if (storage == clang::FunctionDecl::None)
2933 storage = clang::FunctionDecl::Extern;
2934 else
2935 storage = clang::FunctionDecl::PrivateExtern;
2936 }
2937 break;
2938 case DW_AT_inline:
2939 is_inline = form_value.Unsigned() != 0;
2940 break;
2941
2942 case DW_AT_allocated:
2943 case DW_AT_associated:
2944 case DW_AT_address_class:
2945 case DW_AT_artificial:
2946 case DW_AT_calling_convention:
2947 case DW_AT_data_location:
2948 case DW_AT_elemental:
2949 case DW_AT_entry_pc:
2950 case DW_AT_explicit:
2951 case DW_AT_frame_base:
2952 case DW_AT_high_pc:
2953 case DW_AT_low_pc:
2954 case DW_AT_object_pointer:
2955 case DW_AT_prototyped:
2956 case DW_AT_pure:
2957 case DW_AT_ranges:
2958 case DW_AT_recursive:
2959 case DW_AT_return_addr:
2960 case DW_AT_segment:
2961 case DW_AT_specification:
2962 case DW_AT_start_scope:
2963 case DW_AT_static_link:
2964 case DW_AT_trampoline:
2965 case DW_AT_visibility:
2966 case DW_AT_virtuality:
2967 case DW_AT_vtable_elem_location:
2968 case DW_AT_abstract_origin:
2969 case DW_AT_description:
2970 case DW_AT_sibling:
2971 break;
2972 }
2973 }
2974 }
2975
2976 void *return_clang_type = NULL;
2977 Type *func_type = ResolveTypeUID(type_die_offset);
2978 if (func_type)
2979 return_clang_type = func_type->GetOpaqueClangQualType();
2980 else
Greg Clayton960d6a42010-08-03 00:35:52 +00002981 return_clang_type = type_list->GetClangASTContext().GetBuiltInType_void();
Chris Lattner24943d22010-06-08 16:52:24 +00002982
2983 std::vector<void *> function_param_types;
2984 std::vector<clang::ParmVarDecl*> function_param_decls;
2985
2986 // Parse the function children for the parameters
2987 ParseChildParameters(sc, type_sp, dwarf_cu, die, type_list, function_param_types, function_param_decls);
2988
2989 clang_type = type_list->GetClangASTContext().CreateFunctionType (return_clang_type, &function_param_types[0], function_param_types.size(), isVariadic, type_quals);
2990 if (type_name_cstr)
2991 {
2992 clang::FunctionDecl *function_decl = type_list->GetClangASTContext().CreateFunctionDeclaration (type_name_cstr, clang_type, storage, is_inline);
2993 // Add the decl to our DIE to decl context map
2994 assert (function_decl);
2995 m_die_to_decl_ctx[die] = function_decl;
2996 if (!function_param_decls.empty())
Greg Clayton53d68e72010-07-20 22:52:08 +00002997 type_list->GetClangASTContext().SetFunctionParameters (function_decl, &function_param_decls.front(), function_param_decls.size());
Chris Lattner24943d22010-06-08 16:52:24 +00002998 }
2999 type_sp.reset( new Type(die->GetOffset(), this, type_name_dbstr, 0, NULL, LLDB_INVALID_UID, Type::eIsTypeWithUID, &decl, clang_type));
3000
3001 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
3002 assert(type_sp.get());
3003 }
3004 }
3005 break;
3006
3007 case DW_TAG_array_type:
3008 {
3009 //printf("0x%8.8x: %s (ParesTypes)\n", die->GetOffset(), DW_TAG_value_to_name(tag));
3010 // Set a bit that lets us know that we are currently parsing this
3011 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED);
3012
3013 size_t byte_size = 0;
3014 lldb::user_id_t type_die_offset = DW_INVALID_OFFSET;
3015 Declaration decl;
3016 int64_t first_index = 0;
3017 uint32_t byte_stride = 0;
3018 uint32_t bit_stride = 0;
3019 const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
3020
3021 if (num_attributes > 0)
3022 {
3023 uint32_t i;
3024 for (i=0; i<num_attributes; ++i)
3025 {
3026 attr = attributes.AttributeAtIndex(i);
3027 DWARFFormValue form_value;
3028 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
3029 {
3030 switch (attr)
3031 {
3032 case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
3033 case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
3034 case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
3035 case DW_AT_name:
3036 type_name_cstr = form_value.AsCString(&get_debug_str_data());
3037 type_name_dbstr.SetCString(type_name_cstr);
3038 break;
3039
3040 case DW_AT_type: type_die_offset = form_value.Reference(dwarf_cu); break;
3041 case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
3042 case DW_AT_byte_stride: byte_stride = form_value.Unsigned(); break;
3043 case DW_AT_bit_stride: bit_stride = form_value.Unsigned(); break;
Greg Clayton84f80752010-07-22 18:30:50 +00003044 case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
Chris Lattner24943d22010-06-08 16:52:24 +00003045 case DW_AT_declaration: is_forward_declaration = form_value.Unsigned() != 0; break;
3046 case DW_AT_allocated:
3047 case DW_AT_associated:
3048 case DW_AT_data_location:
3049 case DW_AT_description:
3050 case DW_AT_ordering:
3051 case DW_AT_start_scope:
3052 case DW_AT_visibility:
3053 case DW_AT_specification:
3054 case DW_AT_abstract_origin:
3055 case DW_AT_sibling:
3056 break;
3057 }
3058 }
3059 }
3060
3061 Type *element_type = ResolveTypeUID(type_die_offset);
3062
3063 if (element_type)
3064 {
3065 std::vector<uint64_t> element_orders;
3066 ParseChildArrayInfo(sc, dwarf_cu, die, first_index, element_orders, byte_stride, bit_stride);
Greg Claytonaed58812010-09-13 02:37:44 +00003067 // We have an array that claims to have no members, lets give it at least one member...
3068 if (element_orders.empty())
3069 element_orders.push_back (1);
Chris Lattner24943d22010-06-08 16:52:24 +00003070 if (byte_stride == 0 && bit_stride == 0)
3071 byte_stride = element_type->GetByteSize();
3072 void *array_element_type = element_type->GetOpaqueClangQualType();
3073 uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride;
3074 uint64_t num_elements = 0;
3075 std::vector<uint64_t>::const_reverse_iterator pos;
3076 std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend();
3077 for (pos = element_orders.rbegin(); pos != end; ++pos)
3078 {
3079 num_elements = *pos;
3080 clang_type = type_list->GetClangASTContext().CreateArrayType (array_element_type, num_elements, num_elements * array_element_bit_stride);
3081 array_element_type = clang_type;
3082 array_element_bit_stride = array_element_bit_stride * num_elements;
3083 }
3084 ConstString empty_name;
3085 type_sp.reset( new Type(die->GetOffset(), this, empty_name, array_element_bit_stride / 8, NULL, LLDB_INVALID_UID, Type::eIsTypeWithUID, &decl, clang_type));
3086 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
3087 }
3088 }
3089 }
3090 break;
3091
Greg Claytonfa970692010-06-12 01:20:30 +00003092 case DW_TAG_ptr_to_member_type:
3093 {
3094 dw_offset_t type_die_offset = DW_INVALID_OFFSET;
3095 dw_offset_t containing_type_die_offset = DW_INVALID_OFFSET;
3096
3097 const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
3098
3099 if (num_attributes > 0) {
3100 uint32_t i;
3101 for (i=0; i<num_attributes; ++i)
3102 {
3103 attr = attributes.AttributeAtIndex(i);
3104 DWARFFormValue form_value;
3105 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
3106 {
3107 switch (attr)
3108 {
3109 case DW_AT_type:
3110 type_die_offset = form_value.Reference(dwarf_cu); break;
3111 case DW_AT_containing_type:
3112 containing_type_die_offset = form_value.Reference(dwarf_cu); break;
3113 }
3114 }
3115 }
3116
3117 Type *pointee_type = ResolveTypeUID(type_die_offset);
3118 Type *class_type = ResolveTypeUID(containing_type_die_offset);
3119
3120 void *pointee_clang_type = pointee_type->GetOpaqueClangQualType();
Greg Claytonf6e509a2010-06-12 15:33:14 +00003121 void *class_clang_type = class_type->GetOpaqueClangQualType();
Greg Claytonfa970692010-06-12 01:20:30 +00003122
Greg Claytonbef15832010-07-14 00:18:15 +00003123 clang_type = type_list->GetClangASTContext().CreateMemberPointerType(pointee_clang_type, class_clang_type);
Greg Claytonfa970692010-06-12 01:20:30 +00003124
Greg Clayton960d6a42010-08-03 00:35:52 +00003125 size_t byte_size = ClangASTType::GetClangTypeBitWidth (type_list->GetClangASTContext().getASTContext(), clang_type) / 8;
Greg Claytonfa970692010-06-12 01:20:30 +00003126
3127 type_sp.reset( new Type(die->GetOffset(), this, type_name_dbstr, byte_size, NULL, LLDB_INVALID_UID, Type::eIsTypeWithUID, NULL, clang_type));
3128 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
3129 }
3130
3131 break;
3132 }
Chris Lattner24943d22010-06-08 16:52:24 +00003133 default:
Greg Claytonfa970692010-06-12 01:20:30 +00003134 assert(false && "Unhandled type tag!");
Chris Lattner24943d22010-06-08 16:52:24 +00003135 break;
3136 }
3137
3138 if (type_sp.get())
3139 {
3140 const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
3141 dw_tag_t sc_parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
3142
3143 SymbolContextScope * symbol_context_scope = NULL;
3144 if (sc_parent_tag == DW_TAG_compile_unit)
3145 {
3146 symbol_context_scope = sc.comp_unit;
3147 }
3148 else if (sc.function != NULL)
3149 {
Greg Clayton75ccf502010-08-21 02:22:51 +00003150 symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die->GetOffset());
Chris Lattner24943d22010-06-08 16:52:24 +00003151 if (symbol_context_scope == NULL)
3152 symbol_context_scope = sc.function;
3153 }
3154
3155 if (symbol_context_scope != NULL)
3156 {
3157 type_sp->SetSymbolContextScope(symbol_context_scope);
3158 }
3159
3160// if (udt_sp.get())
3161// {
3162// if (is_forward_declaration)
3163// udt_sp->GetFlags().Set(UserDefType::flagIsForwardDefinition);
3164// type_sp->SetUserDefinedType(udt_sp);
3165// }
3166
3167 if (type_sp.unique())
3168 {
3169 // We are ready to put this type into the uniqued list up at the module level
3170 TypeSP uniqued_type_sp(m_obj_file->GetModule()->GetTypeList()->InsertUnique(type_sp));
3171
3172 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(uniqued_type_sp.get());
3173
3174 type_sp = uniqued_type_sp;
3175 }
3176 }
3177 }
3178 else
3179 {
3180 switch (tag)
3181 {
3182 case DW_TAG_base_type:
3183 case DW_TAG_pointer_type:
3184 case DW_TAG_reference_type:
3185 case DW_TAG_typedef:
3186 case DW_TAG_const_type:
3187 case DW_TAG_restrict_type:
3188 case DW_TAG_volatile_type:
3189 case DW_TAG_structure_type:
3190 case DW_TAG_union_type:
3191 case DW_TAG_class_type:
3192 case DW_TAG_enumeration_type:
3193 case DW_TAG_subprogram:
3194 case DW_TAG_subroutine_type:
3195 case DW_TAG_array_type:
3196 {
3197 Type *existing_type = (Type*)die->GetUserData();
3198 if (existing_type != DIE_IS_BEING_PARSED)
3199 {
3200 type_sp = m_obj_file->GetModule()->GetTypeList()->FindType(existing_type->GetID());
3201 }
3202 }
3203 break;
3204 default:
3205 //assert(!"invalid type tag...");
3206 break;
3207 }
3208 }
3209 }
3210 return type_sp;
3211}
3212
3213size_t
3214SymbolFileDWARF::ParseTypes (const SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children)
3215{
3216 size_t types_added = 0;
3217 while (die != NULL)
3218 {
3219 bool type_is_new = false;
3220 if (ParseType(sc, dwarf_cu, die, type_is_new).get())
3221 {
3222 if (type_is_new)
3223 ++types_added;
3224 }
3225
3226 if (parse_children && die->HasChildren())
3227 {
3228 if (die->Tag() == DW_TAG_subprogram)
3229 {
3230 SymbolContext child_sc(sc);
3231 child_sc.function = sc.comp_unit->FindFunctionByUID(die->GetOffset()).get();
3232 types_added += ParseTypes(child_sc, dwarf_cu, die->GetFirstChild(), true, true);
3233 }
3234 else
3235 types_added += ParseTypes(sc, dwarf_cu, die->GetFirstChild(), true, true);
3236 }
3237
3238 if (parse_siblings)
3239 die = die->GetSibling();
3240 else
3241 die = NULL;
3242 }
3243 return types_added;
3244}
3245
3246
3247size_t
3248SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext &sc)
3249{
3250 assert(sc.comp_unit && sc.function);
3251 size_t functions_added = 0;
3252 DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
3253 if (dwarf_cu)
3254 {
3255 dw_offset_t function_die_offset = sc.function->GetID();
3256 const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(function_die_offset);
3257 if (function_die)
3258 {
Greg Clayton75ccf502010-08-21 02:22:51 +00003259 ParseFunctionBlocks(sc, &sc.function->GetBlock (false), dwarf_cu, function_die, LLDB_INVALID_ADDRESS, false, true);
Chris Lattner24943d22010-06-08 16:52:24 +00003260 }
3261 }
3262
3263 return functions_added;
3264}
3265
3266
3267size_t
3268SymbolFileDWARF::ParseTypes (const SymbolContext &sc)
3269{
3270 // At least a compile unit must be valid
3271 assert(sc.comp_unit);
3272 size_t types_added = 0;
3273 DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
3274 if (dwarf_cu)
3275 {
3276 if (sc.function)
3277 {
3278 dw_offset_t function_die_offset = sc.function->GetID();
3279 const DWARFDebugInfoEntry *func_die = dwarf_cu->GetDIEPtr(function_die_offset);
3280 if (func_die && func_die->HasChildren())
3281 {
3282 types_added = ParseTypes(sc, dwarf_cu, func_die->GetFirstChild(), true, true);
3283 }
3284 }
3285 else
3286 {
3287 const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->DIE();
3288 if (dwarf_cu_die && dwarf_cu_die->HasChildren())
3289 {
3290 types_added = ParseTypes(sc, dwarf_cu, dwarf_cu_die->GetFirstChild(), true, true);
3291 }
3292 }
3293 }
3294
3295 return types_added;
3296}
3297
3298size_t
3299SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
3300{
3301 if (sc.comp_unit != NULL)
3302 {
3303 DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
3304
3305 if (dwarf_cu == NULL)
3306 return 0;
3307
3308 if (sc.function)
3309 {
3310 const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(sc.function->GetID());
3311 return ParseVariables(sc, dwarf_cu, function_die->GetFirstChild(), true, true);
3312 }
3313 else if (sc.comp_unit)
3314 {
3315 uint32_t vars_added = 0;
3316 VariableListSP variables (sc.comp_unit->GetVariableList(false));
3317
3318 if (variables.get() == NULL)
3319 {
3320 variables.reset(new VariableList());
3321 sc.comp_unit->SetVariableList(variables);
3322
3323 // Index if we already haven't to make sure the compile units
3324 // get indexed and make their global DIE index list
3325 if (!m_indexed)
3326 Index ();
3327
3328 const size_t num_globals = dwarf_cu->GetNumGlobals();
3329 for (size_t idx=0; idx<num_globals; ++idx)
3330 {
3331 VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, dwarf_cu->GetGlobalDIEAtIndex (idx)));
3332 if (var_sp)
3333 {
3334 variables->AddVariable(var_sp);
3335 ++vars_added;
3336 }
3337 }
3338 }
3339 return vars_added;
3340 }
3341 }
3342 return 0;
3343}
3344
3345
3346VariableSP
3347SymbolFileDWARF::ParseVariableDIE
3348(
3349 const SymbolContext& sc,
3350 const DWARFCompileUnit* dwarf_cu,
3351 const DWARFDebugInfoEntry *die
3352)
3353{
3354
3355 VariableSP var_sp;
3356
3357 const dw_tag_t tag = die->Tag();
3358 DWARFDebugInfoEntry::Attributes attributes;
3359 const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
3360 if (num_attributes > 0)
3361 {
3362 const char *name = NULL;
Greg Claytonaed58812010-09-13 02:37:44 +00003363 const char *mangled = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +00003364 Declaration decl;
3365 uint32_t i;
3366 TypeSP type_sp;
3367 Type *var_type = NULL;
3368 DWARFExpression location;
3369 bool is_external = false;
3370 bool is_artificial = false;
Sean Callanan70a4f922010-08-06 00:32:49 +00003371 AccessType accessibility = eAccessNone;
Chris Lattner24943d22010-06-08 16:52:24 +00003372
3373 for (i=0; i<num_attributes; ++i)
3374 {
3375 dw_attr_t attr = attributes.AttributeAtIndex(i);
3376 DWARFFormValue form_value;
3377 if (attributes.ExtractFormValueAtIndex(this, i, form_value))
3378 {
3379 switch (attr)
3380 {
3381 case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
3382 case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
3383 case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
3384 case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
Greg Claytonaed58812010-09-13 02:37:44 +00003385 case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break;
Chris Lattner24943d22010-06-08 16:52:24 +00003386 case DW_AT_type: var_type = GetUniquedTypeForDIEOffset(form_value.Reference(dwarf_cu), type_sp, 0, 0, false); break;
3387 case DW_AT_external: is_external = form_value.Unsigned() != 0; break;
3388 case DW_AT_location:
3389 {
3390 if (form_value.BlockData())
3391 {
3392 const DataExtractor& debug_info_data = get_debug_info_data();
3393
3394 uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
3395 uint32_t block_length = form_value.Unsigned();
3396 location.SetOpcodeData(get_debug_info_data(), block_offset, block_length, NULL);
3397 }
3398 else
3399 {
3400 const DataExtractor& debug_loc_data = get_debug_loc_data();
3401 const dw_offset_t debug_loc_offset = form_value.Unsigned();
3402
3403 size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
3404 if (loc_list_length > 0)
3405 {
3406 Address base_address(dwarf_cu->GetBaseAddress(), m_obj_file->GetSectionList());
3407 location.SetOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length, &base_address);
3408 }
3409 }
3410 }
3411 break;
3412
3413 case DW_AT_artificial: is_artificial = form_value.Unsigned() != 0; break;
Greg Clayton84f80752010-07-22 18:30:50 +00003414 case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
Chris Lattner24943d22010-06-08 16:52:24 +00003415 case DW_AT_const_value:
3416 case DW_AT_declaration:
3417 case DW_AT_description:
3418 case DW_AT_endianity:
3419 case DW_AT_segment:
3420 case DW_AT_start_scope:
3421 case DW_AT_visibility:
3422 default:
3423 case DW_AT_abstract_origin:
3424 case DW_AT_sibling:
3425 case DW_AT_specification:
3426 break;
3427 }
3428 }
3429 }
3430
3431 if (location.IsValid())
3432 {
3433 assert(var_type != DIE_IS_BEING_PARSED);
3434
Greg Claytonaed58812010-09-13 02:37:44 +00003435 ConstString var_name;
3436 if (mangled)
3437 {
3438 Mangled mangled_var_name (mangled, true);
3439 var_name = mangled_var_name.GetDemangledName();
3440 }
3441
3442 if (!var_name && name)
3443 {
3444 var_name.SetCString(name);
3445 }
Chris Lattner24943d22010-06-08 16:52:24 +00003446
3447 ValueType scope = eValueTypeInvalid;
3448
3449 const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
3450 dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
3451
3452 if (tag == DW_TAG_formal_parameter)
3453 scope = eValueTypeVariableArgument;
3454 else if (is_external || parent_tag == DW_TAG_compile_unit)
3455 scope = eValueTypeVariableGlobal;
3456 else
3457 scope = eValueTypeVariableLocal;
3458
3459 SymbolContextScope * symbol_context_scope = NULL;
3460 if (parent_tag == DW_TAG_compile_unit)
3461 {
3462 symbol_context_scope = sc.comp_unit;
3463 }
3464 else if (sc.function != NULL)
3465 {
Greg Clayton75ccf502010-08-21 02:22:51 +00003466 symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die->GetOffset());
Chris Lattner24943d22010-06-08 16:52:24 +00003467 if (symbol_context_scope == NULL)
3468 symbol_context_scope = sc.function;
3469 }
3470
3471 assert(symbol_context_scope != NULL);
3472 var_sp.reset (new Variable(die->GetOffset(),
3473 var_name,
3474 var_type,
3475 scope,
3476 symbol_context_scope,
3477 &decl,
3478 location,
3479 is_external,
3480 is_artificial));
3481 const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(var_sp.get());
3482 }
3483 }
3484 return var_sp;
3485}
3486
3487size_t
3488SymbolFileDWARF::ParseVariables
3489(
3490 const SymbolContext& sc,
3491 const DWARFCompileUnit* dwarf_cu,
3492 const DWARFDebugInfoEntry *orig_die,
3493 bool parse_siblings,
3494 bool parse_children,
3495 VariableList* cc_variable_list
3496)
3497{
3498 if (orig_die == NULL)
3499 return 0;
3500
3501 size_t vars_added = 0;
3502 const DWARFDebugInfoEntry *die = orig_die;
3503 const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(orig_die);
3504 dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
3505 VariableListSP variables;
3506 switch (parent_tag)
3507 {
3508 case DW_TAG_compile_unit:
3509 if (sc.comp_unit != NULL)
3510 {
3511 variables = sc.comp_unit->GetVariableList(false);
3512 if (variables.get() == NULL)
3513 {
3514 variables.reset(new VariableList());
3515 sc.comp_unit->SetVariableList(variables);
3516 }
3517 }
3518 else
3519 {
3520 assert(!"Parent DIE was a compile unit, yet we don't have a valid compile unit in the symbol context...");
3521 vars_added = 0;
3522 }
3523 break;
3524
3525 case DW_TAG_subprogram:
3526 case DW_TAG_inlined_subroutine:
3527 case DW_TAG_lexical_block:
3528 if (sc.function != NULL)
3529 {
3530 // Check to see if we already have parsed the variables for the given scope
Greg Clayton75ccf502010-08-21 02:22:51 +00003531
3532 Block *block = sc.function->GetBlock(true).FindBlockByID(sc_parent_die->GetOffset());
3533 assert (block != NULL);
3534 variables = block->GetVariableList(false, true);
Chris Lattner24943d22010-06-08 16:52:24 +00003535 if (variables.get() == NULL)
3536 {
3537 variables.reset(new VariableList());
Greg Clayton75ccf502010-08-21 02:22:51 +00003538 block->SetVariableList(variables);
Chris Lattner24943d22010-06-08 16:52:24 +00003539 }
3540 }
3541 else
3542 {
3543 assert(!"Parent DIE was a function or block, yet we don't have a function in the symbol context...");
3544 vars_added = 0;
3545 }
3546 break;
3547
3548 default:
3549 assert(!"Didn't find appropriate parent DIE for variable list...");
3550 break;
3551 }
3552
3553 // We need to have a variable list at this point that we can add variables to
3554 assert(variables.get());
3555
3556 while (die != NULL)
3557 {
3558 dw_tag_t tag = die->Tag();
3559
3560 // Check to see if we have already parsed this variable or constant?
3561 if (die->GetUserData() == NULL)
3562 {
3563 // We haven't already parsed it, lets do that now.
3564 if ((tag == DW_TAG_variable) ||
3565 (tag == DW_TAG_constant) ||
3566 (tag == DW_TAG_formal_parameter && sc.function))
3567 {
3568 VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die));
3569 if (var_sp)
3570 {
3571 variables->AddVariable(var_sp);
3572 ++vars_added;
3573 }
3574 }
3575 }
3576
3577 bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram);
3578
3579 if (!skip_children && parse_children && die->HasChildren())
3580 {
3581 vars_added += ParseVariables(sc, dwarf_cu, die->GetFirstChild(), true, true);
3582 //vars_added += ParseVariables(sc, dwarf_cu, die->GetFirstChild(), parse_siblings, parse_children);
3583 }
3584
3585 if (parse_siblings)
3586 die = die->GetSibling();
3587 else
3588 die = NULL;
3589 }
3590
3591 if (cc_variable_list)
3592 {
3593 cc_variable_list->AddVariables(variables.get());
3594 }
3595
3596 return vars_added;
3597}
3598
3599//------------------------------------------------------------------
3600// PluginInterface protocol
3601//------------------------------------------------------------------
3602const char *
3603SymbolFileDWARF::GetPluginName()
3604{
3605 return "SymbolFileDWARF";
3606}
3607
3608const char *
3609SymbolFileDWARF::GetShortPluginName()
3610{
3611 return GetPluginNameStatic();
3612}
3613
3614uint32_t
3615SymbolFileDWARF::GetPluginVersion()
3616{
3617 return 1;
3618}
3619
3620void
3621SymbolFileDWARF::GetPluginCommandHelp (const char *command, Stream *strm)
3622{
3623}
3624
3625Error
3626SymbolFileDWARF::ExecutePluginCommand (Args &command, Stream *strm)
3627{
3628 Error error;
3629 error.SetErrorString("No plug-in command are currently supported.");
3630 return error;
3631}
3632
3633Log *
3634SymbolFileDWARF::EnablePluginLogging (Stream *strm, Args &command)
3635{
3636 return NULL;
3637}
3638