]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Symbol/Block.cpp
Merge content currently under test from ^/vendor/NetBSD/tests/dist/@r312123
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Symbol / Block.cpp
1 //===-- Block.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 "lldb/Symbol/Block.h"
11
12 #include "lldb/Core/Log.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/Section.h"
15 #include "lldb/Symbol/Function.h"
16 #include "lldb/Symbol/SymbolFile.h"
17 #include "lldb/Symbol/SymbolVendor.h"
18 #include "lldb/Symbol/VariableList.h"
19
20 using namespace lldb;
21 using namespace lldb_private;
22
23 Block::Block(lldb::user_id_t uid) :
24     UserID(uid),
25     m_parent_scope (nullptr),
26     m_children (),
27     m_ranges (),
28     m_inlineInfoSP (),
29     m_variable_list_sp (),
30     m_parsed_block_info (false),
31     m_parsed_block_variables (false),
32     m_parsed_child_blocks (false)
33 {
34 }
35
36 Block::~Block ()
37 {
38 }
39
40 void
41 Block::GetDescription(Stream *s, Function *function, lldb::DescriptionLevel level, Target *target) const
42 {
43     *s << "id = " << ((const UserID&)*this);
44
45     size_t num_ranges = m_ranges.GetSize();
46     if (num_ranges > 0)
47     {
48         
49         addr_t base_addr = LLDB_INVALID_ADDRESS;
50         if (target)
51             base_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(target);
52         if (base_addr == LLDB_INVALID_ADDRESS)
53             base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
54
55         s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");
56         for (size_t i=0; i<num_ranges; ++i)
57         {
58             const Range &range = m_ranges.GetEntryRef(i);
59             s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4);
60         }
61     }
62
63     if (m_inlineInfoSP.get() != nullptr)
64     {
65         bool show_fullpaths = (level == eDescriptionLevelVerbose);
66         m_inlineInfoSP->Dump(s, show_fullpaths);
67     }
68 }
69
70 void
71 Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
72 {
73     if (depth < 0)
74     {
75         Block *parent = GetParent();
76         if (parent)
77         {
78             // We have a depth that is less than zero, print our parent blocks
79             // first
80             parent->Dump(s, base_addr, depth + 1, show_context);
81         }
82     }
83
84     s->Printf("%p: ", static_cast<const void*>(this));
85     s->Indent();
86     *s << "Block" << static_cast<const UserID&>(*this);
87     const Block* parent_block = GetParent();
88     if (parent_block)
89     {
90         s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID());
91     }
92     if (m_inlineInfoSP.get() != nullptr)
93     {
94         bool show_fullpaths = false;
95         m_inlineInfoSP->Dump(s, show_fullpaths);
96     }
97
98     if (!m_ranges.IsEmpty())
99     {
100         *s << ", ranges =";
101
102         size_t num_ranges = m_ranges.GetSize();
103         for (size_t i=0; i<num_ranges; ++i)
104         {
105             const Range &range = m_ranges.GetEntryRef(i);
106             if (parent_block != nullptr && parent_block->Contains(range) == false)
107                 *s << '!';
108             else
109                 *s << ' ';
110             s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4);
111         }
112     }
113     s->EOL();
114
115     if (depth > 0)
116     {
117         s->IndentMore();
118
119         if (m_variable_list_sp.get())
120         {
121             m_variable_list_sp->Dump(s, show_context);
122         }
123
124         collection::const_iterator pos, end = m_children.end();
125         for (pos = m_children.begin(); pos != end; ++pos)
126             (*pos)->Dump(s, base_addr, depth - 1, show_context);
127
128         s->IndentLess();
129     }
130
131 }
132
133
134 Block *
135 Block::FindBlockByID (user_id_t block_id)
136 {
137     if (block_id == GetID())
138         return this;
139
140     Block *matching_block = nullptr;
141     collection::const_iterator pos, end = m_children.end();
142     for (pos = m_children.begin(); pos != end; ++pos)
143     {
144         matching_block = (*pos)->FindBlockByID (block_id);
145         if (matching_block)
146             break;
147     }
148     return matching_block;
149 }
150
151 void
152 Block::CalculateSymbolContext (SymbolContext* sc)
153 {
154     if (m_parent_scope)
155         m_parent_scope->CalculateSymbolContext(sc);
156     sc->block = this;
157 }
158
159 lldb::ModuleSP
160 Block::CalculateSymbolContextModule ()
161 {
162     if (m_parent_scope)
163         return m_parent_scope->CalculateSymbolContextModule ();
164     return lldb::ModuleSP();
165 }
166
167 CompileUnit *
168 Block::CalculateSymbolContextCompileUnit ()
169 {
170     if (m_parent_scope)
171         return m_parent_scope->CalculateSymbolContextCompileUnit ();
172     return nullptr;
173 }
174
175 Function *
176 Block::CalculateSymbolContextFunction ()
177 {
178     if (m_parent_scope)
179         return m_parent_scope->CalculateSymbolContextFunction ();
180     return nullptr;
181 }
182
183 Block *
184 Block::CalculateSymbolContextBlock ()
185 {
186     return this;
187 }
188
189 void
190 Block::DumpSymbolContext(Stream *s)
191 {
192     Function *function = CalculateSymbolContextFunction();
193     if (function)
194         function->DumpSymbolContext(s);
195     s->Printf(", Block{0x%8.8" PRIx64 "}", GetID());
196 }
197
198 void
199 Block::DumpAddressRanges (Stream *s, lldb::addr_t base_addr)
200 {
201     if (!m_ranges.IsEmpty())
202     {
203         size_t num_ranges = m_ranges.GetSize();
204         for (size_t i=0; i<num_ranges; ++i)
205         {
206             const Range &range = m_ranges.GetEntryRef(i);
207             s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4);
208         }
209     }
210 }
211
212 bool
213 Block::Contains (addr_t range_offset) const
214 {
215     return m_ranges.FindEntryThatContains(range_offset) != nullptr;
216 }
217
218 bool
219 Block::Contains (const Block *block) const
220 {
221     if (this == block)
222         return false; // This block doesn't contain itself...
223     
224     // Walk the parent chain for "block" and see if any if them match this block
225     const Block *block_parent;
226     for (block_parent = block->GetParent();
227          block_parent != nullptr;
228          block_parent = block_parent->GetParent())
229     {
230         if (this == block_parent)
231             return true; // One of the parents of "block" is this object!
232     }
233     return false;
234 }
235
236 bool
237 Block::Contains (const Range& range) const
238 {
239     return m_ranges.FindEntryThatContains (range) != nullptr;
240 }
241
242 Block *
243 Block::GetParent () const
244 {
245     if (m_parent_scope)
246         return m_parent_scope->CalculateSymbolContextBlock();
247     return nullptr;
248 }
249
250 Block *
251 Block::GetContainingInlinedBlock ()
252 {
253     if (GetInlinedFunctionInfo())
254         return this;
255     return GetInlinedParent ();
256 }
257
258 Block *
259 Block::GetInlinedParent ()
260 {
261     Block *parent_block = GetParent ();
262     if (parent_block)
263     {
264         if (parent_block->GetInlinedFunctionInfo())
265             return parent_block;
266         else
267             return parent_block->GetInlinedParent();
268     }
269     return nullptr;
270 }
271
272
273 bool
274 Block::GetRangeContainingOffset (const addr_t offset, Range &range)
275 {
276     const Range *range_ptr = m_ranges.FindEntryThatContains (offset);
277     if (range_ptr)
278     {
279         range = *range_ptr;
280         return true;
281     }
282     range.Clear();
283     return false;
284 }
285
286
287 bool
288 Block::GetRangeContainingAddress (const Address& addr, AddressRange &range)
289 {
290     Function *function = CalculateSymbolContextFunction();
291     if (function)
292     {
293         const AddressRange &func_range = function->GetAddressRange();
294         if (addr.GetSection() == func_range.GetBaseAddress().GetSection())
295         {
296             const addr_t addr_offset = addr.GetOffset();
297             const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
298             if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize())
299             {
300                 addr_t offset = addr_offset - func_offset;
301                 
302                 const Range *range_ptr = m_ranges.FindEntryThatContains (offset);
303
304                 if (range_ptr)
305                 {
306                     range.GetBaseAddress() = func_range.GetBaseAddress();
307                     range.GetBaseAddress().SetOffset(func_offset + range_ptr->GetRangeBase());
308                     range.SetByteSize(range_ptr->GetByteSize());
309                     return true;
310                 }
311             }
312         }
313     }
314     range.Clear();
315     return false;
316 }
317
318 bool
319 Block::GetRangeContainingLoadAddress (lldb::addr_t load_addr, Target &target, AddressRange &range)
320 {
321     Address load_address;
322     load_address.SetLoadAddress(load_addr, &target);
323     AddressRange containing_range;
324     return GetRangeContainingAddress(load_address, containing_range);
325 }
326
327
328 uint32_t
329 Block::GetRangeIndexContainingAddress (const Address& addr)
330 {
331     Function *function = CalculateSymbolContextFunction();
332     if (function)
333     {
334         const AddressRange &func_range = function->GetAddressRange();
335         if (addr.GetSection() == func_range.GetBaseAddress().GetSection())
336         {
337             const addr_t addr_offset = addr.GetOffset();
338             const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
339             if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize())
340             {
341                 addr_t offset = addr_offset - func_offset;
342                 return m_ranges.FindEntryIndexThatContains (offset);
343             }
344         }
345     }
346     return UINT32_MAX;
347 }
348
349 bool
350 Block::GetRangeAtIndex (uint32_t range_idx, AddressRange &range)
351 {
352     if (range_idx < m_ranges.GetSize())
353     {
354         Function *function = CalculateSymbolContextFunction();
355         if (function)
356         {
357             const Range &vm_range = m_ranges.GetEntryRef(range_idx);
358             range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();
359             range.GetBaseAddress().Slide(vm_range.GetRangeBase ());
360             range.SetByteSize (vm_range.GetByteSize());
361             return true;
362         }
363     }
364     return false;
365 }
366
367 bool
368 Block::GetStartAddress (Address &addr)
369 {
370     if (m_ranges.IsEmpty())
371         return false;
372
373     Function *function = CalculateSymbolContextFunction();
374     if (function)
375     {
376         addr = function->GetAddressRange().GetBaseAddress();
377         addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase ());
378         return true;
379     }
380     return false;
381 }
382
383 void
384 Block::FinalizeRanges ()
385 {
386     m_ranges.Sort();
387     m_ranges.CombineConsecutiveRanges ();
388 }
389
390 void
391 Block::AddRange (const Range& range)
392 {
393     Block *parent_block = GetParent ();
394     if (parent_block && !parent_block->Contains(range))
395     {
396         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
397         if (log)
398         {
399             ModuleSP module_sp (m_parent_scope->CalculateSymbolContextModule());
400             Function *function = m_parent_scope->CalculateSymbolContextFunction();
401             const addr_t function_file_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
402             const addr_t block_start_addr = function_file_addr + range.GetRangeBase ();
403             const addr_t block_end_addr = function_file_addr + range.GetRangeEnd ();
404             Type *func_type = function->GetType();
405             
406             const Declaration &func_decl = func_type->GetDeclaration();
407             if (func_decl.GetLine())
408             {
409                 log->Printf ("warning: %s:%u block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 ") which is not contained in parent block {0x%8.8" PRIx64 "} in function {0x%8.8" PRIx64 "} from %s",
410                              func_decl.GetFile().GetPath().c_str(),
411                              func_decl.GetLine(),
412                              GetID(),
413                              (uint32_t)m_ranges.GetSize(),
414                              block_start_addr,
415                              block_end_addr,
416                              parent_block->GetID(),
417                              function->GetID(),
418                              module_sp->GetFileSpec().GetPath().c_str());
419             }
420             else
421             {
422                 log->Printf ("warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 ") which is not contained in parent block {0x%8.8" PRIx64 "} in function {0x%8.8" PRIx64 "} from %s",
423                              GetID(),
424                              (uint32_t)m_ranges.GetSize(),
425                              block_start_addr,
426                              block_end_addr,
427                              parent_block->GetID(),
428                              function->GetID(),
429                              module_sp->GetFileSpec().GetPath().c_str());
430             }
431         }
432         parent_block->AddRange (range);
433     }
434     m_ranges.Append(range);
435 }
436
437 // Return the current number of bytes that this object occupies in memory
438 size_t
439 Block::MemorySize() const
440 {
441     size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range);
442     if (m_inlineInfoSP.get())
443         mem_size += m_inlineInfoSP->MemorySize();
444     if (m_variable_list_sp.get())
445         mem_size += m_variable_list_sp->MemorySize();
446     return mem_size;
447
448 }
449
450 void
451 Block::AddChild(const BlockSP &child_block_sp)
452 {
453     if (child_block_sp)
454     {
455         child_block_sp->SetParentScope (this);
456         m_children.push_back (child_block_sp);
457     }
458 }
459
460 void
461 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
462 {
463     m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
464 }
465
466
467
468 VariableListSP
469 Block::GetBlockVariableList (bool can_create)
470 {
471     if (m_parsed_block_variables == false)
472     {
473         if (m_variable_list_sp.get() == nullptr && can_create)
474         {
475             m_parsed_block_variables = true;
476             SymbolContext sc;
477             CalculateSymbolContext(&sc);
478             assert(sc.module_sp);
479             sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
480         }
481     }
482     return m_variable_list_sp;
483 }
484
485 uint32_t
486 Block::AppendBlockVariables (bool can_create,
487                              bool get_child_block_variables,
488                              bool stop_if_child_block_is_inlined_function,
489                              const std::function<bool(Variable*)>& filter,
490                              VariableList *variable_list)
491 {
492     uint32_t num_variables_added = 0;
493     VariableList *block_var_list = GetBlockVariableList (can_create).get();
494     if (block_var_list)
495     {
496         for (size_t i = 0; i < block_var_list->GetSize(); ++i)
497         {
498             VariableSP variable = block_var_list->GetVariableAtIndex(i);
499             if (filter(variable.get()))
500             {
501                 num_variables_added++;
502                 variable_list->AddVariable(variable);
503             }
504         }
505     }
506
507     if (get_child_block_variables)
508     {
509         collection::const_iterator pos, end = m_children.end();
510         for (pos = m_children.begin(); pos != end; ++pos)
511         {
512             Block *child_block = pos->get();
513             if (stop_if_child_block_is_inlined_function == false || 
514                 child_block->GetInlinedFunctionInfo() == nullptr)
515             {
516                 num_variables_added += child_block->AppendBlockVariables (can_create,
517                                                                           get_child_block_variables,
518                                                                           stop_if_child_block_is_inlined_function,
519                                                                           filter,
520                                                                           variable_list);
521             }
522         }
523     }
524     return num_variables_added;
525 }
526
527 uint32_t
528 Block::AppendVariables 
529 (
530     bool can_create, 
531     bool get_parent_variables, 
532     bool stop_if_block_is_inlined_function,
533     const std::function<bool(Variable*)>& filter,
534     VariableList *variable_list
535 )
536 {
537     uint32_t num_variables_added = 0;
538     VariableListSP variable_list_sp(GetBlockVariableList(can_create));
539
540     bool is_inlined_function = GetInlinedFunctionInfo() != nullptr;
541     if (variable_list_sp)
542     {
543         for (size_t i = 0; i < variable_list_sp->GetSize(); ++i)
544         {
545             VariableSP variable = variable_list_sp->GetVariableAtIndex(i);
546             if (filter(variable.get()))
547             {
548                 num_variables_added++;
549                 variable_list->AddVariable(variable);
550             }
551         }
552     }
553
554     if (get_parent_variables)
555     {
556         if (stop_if_block_is_inlined_function && is_inlined_function)
557             return num_variables_added;
558             
559         Block* parent_block = GetParent();
560         if (parent_block)
561             num_variables_added += parent_block->AppendVariables(can_create,
562                                                                  get_parent_variables,
563                                                                  stop_if_block_is_inlined_function,
564                                                                  filter,
565                                                                  variable_list);
566     }
567     return num_variables_added;
568 }
569
570 CompilerDeclContext
571 Block::GetDeclContext()
572 {
573     ModuleSP module_sp = CalculateSymbolContextModule ();
574
575     if (module_sp)
576     {
577         SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
578     
579         if (sym_vendor)
580         {
581             SymbolFile *sym_file = sym_vendor->GetSymbolFile();
582     
583             if (sym_file)
584                 return sym_file->GetDeclContextForUID (GetID());
585         }
586     }
587     return CompilerDeclContext();
588 }
589
590 void
591 Block::SetBlockInfoHasBeenParsed (bool b, bool set_children)
592 {
593     m_parsed_block_info = b;
594     if (set_children)
595     {
596         m_parsed_child_blocks = true;
597         collection::const_iterator pos, end = m_children.end();
598         for (pos = m_children.begin(); pos != end; ++pos)
599             (*pos)->SetBlockInfoHasBeenParsed (b, true);
600     }
601 }
602
603 void
604 Block::SetDidParseVariables (bool b, bool set_children)
605 {
606     m_parsed_block_variables = b;
607     if (set_children)
608     {
609         collection::const_iterator pos, end = m_children.end();
610         for (pos = m_children.begin(); pos != end; ++pos)
611             (*pos)->SetDidParseVariables (b, true);
612     }
613 }
614
615
616 Block *
617 Block::GetSibling() const
618 {
619     if (m_parent_scope)
620     {
621         Block *parent_block = GetParent();
622         if (parent_block)
623             return parent_block->GetSiblingForChild (this);
624     }
625     return nullptr;
626 }
627 // A parent of child blocks can be asked to find a sibling block given
628 // one of its child blocks
629 Block *
630 Block::GetSiblingForChild (const Block *child_block) const
631 {
632     if (!m_children.empty())
633     {
634         collection::const_iterator pos, end = m_children.end();
635         for (pos = m_children.begin(); pos != end; ++pos)
636         {
637             if (pos->get() == child_block)
638             {
639                 if (++pos != end)
640                     return pos->get();
641                 break;
642             }
643         }
644     }
645     return nullptr;
646 }
647