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