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 
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 
38 Block::~Block ()
39 {
40 }
41 
42 void
43 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
73 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.8x}", 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 *
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
154 Block::CalculateSymbolContext (SymbolContext* sc)
155 {
156     if (m_parent_scope)
157         m_parent_scope->CalculateSymbolContext(sc);
158     sc->block = this;
159 }
160 
161 Module *
162 Block::CalculateSymbolContextModule ()
163 {
164     if (m_parent_scope)
165         return m_parent_scope->CalculateSymbolContextModule ();
166     return NULL;
167 }
168 
169 CompileUnit *
170 Block::CalculateSymbolContextCompileUnit ()
171 {
172     if (m_parent_scope)
173         return m_parent_scope->CalculateSymbolContextCompileUnit ();
174     return NULL;
175 }
176 
177 Function *
178 Block::CalculateSymbolContextFunction ()
179 {
180     if (m_parent_scope)
181         return m_parent_scope->CalculateSymbolContextFunction ();
182     return NULL;
183 }
184 
185 Block *
186 Block::CalculateSymbolContextBlock ()
187 {
188     return this;
189 }
190 
191 void
192 Block::DumpSymbolContext(Stream *s)
193 {
194     Function *function = CalculateSymbolContextFunction();
195     if (function)
196         function->DumpSymbolContext(s);
197     s->Printf(", Block{0x%8.8x}", GetID());
198 }
199 
200 void
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
215 Block::Contains (addr_t range_offset) const
216 {
217     return m_ranges.FindEntryThatContains(range_offset) != NULL;
218 }
219 
220 bool
221 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
239 Block::Contains (const Range& range) const
240 {
241     return m_ranges.FindEntryThatContains (range) != NULL;
242 }
243 
244 Block *
245 Block::GetParent () const
246 {
247     if (m_parent_scope)
248         return m_parent_scope->CalculateSymbolContextBlock();
249     return NULL;
250 }
251 
252 Block *
253 Block::GetContainingInlinedBlock ()
254 {
255     if (GetInlinedFunctionInfo())
256         return this;
257     return GetInlinedParent ();
258 }
259 
260 Block *
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
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
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 uint32_t
321 Block::GetRangeIndexContainingAddress (const Address& addr)
322 {
323     Function *function = CalculateSymbolContextFunction();
324     if (function)
325     {
326         const AddressRange &func_range = function->GetAddressRange();
327         if (addr.GetSection() == func_range.GetBaseAddress().GetSection())
328         {
329             const addr_t addr_offset = addr.GetOffset();
330             const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
331             if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize())
332             {
333                 addr_t offset = addr_offset - func_offset;
334                 return m_ranges.FindEntryIndexThatContains (offset);
335             }
336         }
337     }
338     return UINT32_MAX;
339 }
340 
341 bool
342 Block::GetRangeAtIndex (uint32_t range_idx, AddressRange &range)
343 {
344     if (range_idx < m_ranges.GetSize())
345     {
346         Function *function = CalculateSymbolContextFunction();
347         if (function)
348         {
349             const Range &vm_range = m_ranges.GetEntryRef(range_idx);
350             range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();
351             range.GetBaseAddress().Slide(vm_range.GetRangeBase ());
352             range.SetByteSize (vm_range.GetByteSize());
353             return true;
354         }
355     }
356     return false;
357 }
358 
359 bool
360 Block::GetStartAddress (Address &addr)
361 {
362     if (m_ranges.IsEmpty())
363         return false;
364 
365     Function *function = CalculateSymbolContextFunction();
366     if (function)
367     {
368         addr = function->GetAddressRange().GetBaseAddress();
369         addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase ());
370         return true;
371     }
372     return false;
373 }
374 
375 void
376 Block::FinalizeRanges ()
377 {
378     m_ranges.Sort();
379     m_ranges.CombineConsecutiveRanges ();
380 }
381 
382 void
383 Block::AddRange (const Range& range)
384 {
385     Block *parent_block = GetParent ();
386     if (parent_block && !parent_block->Contains(range))
387     {
388         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
389         if (log)
390         {
391             Module *module = m_parent_scope->CalculateSymbolContextModule();
392             Function *function = m_parent_scope->CalculateSymbolContextFunction();
393             const addr_t function_file_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
394             const addr_t block_start_addr = function_file_addr + range.GetRangeBase ();
395             const addr_t block_end_addr = function_file_addr + range.GetRangeEnd ();
396             Type *func_type = function->GetType();
397 
398             const Declaration &func_decl = func_type->GetDeclaration();
399             if (func_decl.GetLine())
400             {
401                 log->Printf ("warning: %s/%s:%u block {0x%8.8x} has range[%u] [0x%llx - 0x%llx) which is not contained in parent block {0x%8.8x} in function {0x%8.8x} from %s/%s",
402                              func_decl.GetFile().GetDirectory().GetCString(),
403                              func_decl.GetFile().GetFilename().GetCString(),
404                              func_decl.GetLine(),
405                              GetID(),
406                              (uint32_t)m_ranges.GetSize(),
407                              block_start_addr,
408                              block_end_addr,
409                              parent_block->GetID(),
410                              function->GetID(),
411                              module->GetFileSpec().GetDirectory().GetCString(),
412                              module->GetFileSpec().GetFilename().GetCString());
413             }
414             else
415             {
416                 log->Printf ("warning: block {0x%8.8x} has range[%u] [0x%llx - 0x%llx) which is not contained in parent block {0x%8.8x} in function {0x%8.8x} from %s/%s",
417                              GetID(),
418                              (uint32_t)m_ranges.GetSize(),
419                              block_start_addr,
420                              block_end_addr,
421                              parent_block->GetID(),
422                              function->GetID(),
423                              module->GetFileSpec().GetDirectory().GetCString(),
424                              module->GetFileSpec().GetFilename().GetCString());
425             }
426         }
427         parent_block->AddRange (range);
428     }
429     m_ranges.Append(range);
430 }
431 
432 // Return the current number of bytes that this object occupies in memory
433 size_t
434 Block::MemorySize() const
435 {
436     size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range);
437     if (m_inlineInfoSP.get())
438         mem_size += m_inlineInfoSP->MemorySize();
439     if (m_variable_list_sp.get())
440         mem_size += m_variable_list_sp->MemorySize();
441     return mem_size;
442 
443 }
444 
445 void
446 Block::AddChild(const BlockSP &child_block_sp)
447 {
448     if (child_block_sp)
449     {
450         child_block_sp->SetParentScope (this);
451         m_children.push_back (child_block_sp);
452     }
453 }
454 
455 void
456 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
457 {
458     m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
459 }
460 
461 
462 
463 VariableListSP
464 Block::GetBlockVariableList (bool can_create)
465 {
466     if (m_parsed_block_variables == false)
467     {
468         if (m_variable_list_sp.get() == NULL && can_create)
469         {
470             m_parsed_block_variables = true;
471             SymbolContext sc;
472             CalculateSymbolContext(&sc);
473             assert(sc.module_sp);
474             sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
475         }
476     }
477     return m_variable_list_sp;
478 }
479 
480 uint32_t
481 Block::AppendBlockVariables (bool can_create,
482                              bool get_child_block_variables,
483                              bool stop_if_child_block_is_inlined_function,
484                              VariableList *variable_list)
485 {
486     uint32_t num_variables_added = 0;
487     VariableList *block_var_list = GetBlockVariableList (can_create).get();
488     if (block_var_list)
489     {
490         num_variables_added += block_var_list->GetSize();
491         variable_list->AddVariables (block_var_list);
492     }
493 
494     if (get_child_block_variables)
495     {
496         collection::const_iterator pos, end = m_children.end();
497         for (pos = m_children.begin(); pos != end; ++pos)
498         {
499             Block *child_block = pos->get();
500             if (stop_if_child_block_is_inlined_function == false ||
501                 child_block->GetInlinedFunctionInfo() == NULL)
502             {
503                 num_variables_added += child_block->AppendBlockVariables (can_create,
504                                                                           get_child_block_variables,
505                                                                           stop_if_child_block_is_inlined_function,
506                                                                           variable_list);
507             }
508         }
509     }
510     return num_variables_added;
511 }
512 
513 uint32_t
514 Block::AppendVariables
515 (
516     bool can_create,
517     bool get_parent_variables,
518     bool stop_if_block_is_inlined_function,
519     VariableList *variable_list
520 )
521 {
522     uint32_t num_variables_added = 0;
523     VariableListSP variable_list_sp(GetBlockVariableList(can_create));
524 
525     bool is_inlined_function = GetInlinedFunctionInfo() != NULL;
526     if (variable_list_sp.get())
527     {
528         num_variables_added = variable_list_sp->GetSize();
529         variable_list->AddVariables(variable_list_sp.get());
530     }
531 
532     if (get_parent_variables)
533     {
534         if (stop_if_block_is_inlined_function && is_inlined_function)
535             return num_variables_added;
536 
537         Block* parent_block = GetParent();
538         if (parent_block)
539             num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list);
540     }
541     return num_variables_added;
542 }
543 
544 clang::DeclContext *
545 Block::GetClangDeclContextForInlinedFunction()
546 {
547     SymbolContext sc;
548 
549     CalculateSymbolContext (&sc);
550 
551     if (!sc.module_sp)
552         return NULL;
553 
554     SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
555 
556     if (!sym_vendor)
557         return NULL;
558 
559     SymbolFile *sym_file = sym_vendor->GetSymbolFile();
560 
561     if (!sym_file)
562         return NULL;
563 
564     return sym_file->GetClangDeclContextForTypeUID (sc, m_uid);
565 }
566 
567 void
568 Block::SetBlockInfoHasBeenParsed (bool b, bool set_children)
569 {
570     m_parsed_block_info = b;
571     if (set_children)
572     {
573         m_parsed_child_blocks = true;
574         collection::const_iterator pos, end = m_children.end();
575         for (pos = m_children.begin(); pos != end; ++pos)
576             (*pos)->SetBlockInfoHasBeenParsed (b, true);
577     }
578 }
579 
580 void
581 Block::SetDidParseVariables (bool b, bool set_children)
582 {
583     m_parsed_block_variables = b;
584     if (set_children)
585     {
586         collection::const_iterator pos, end = m_children.end();
587         for (pos = m_children.begin(); pos != end; ++pos)
588             (*pos)->SetDidParseVariables (b, true);
589     }
590 }
591 
592 
593 Block *
594 Block::GetSibling() const
595 {
596     if (m_parent_scope)
597     {
598         Block *parent_block = GetParent();
599         if (parent_block)
600             return parent_block->GetSiblingForChild (this);
601     }
602     return NULL;
603 }
604 // A parent of child blocks can be asked to find a sibling block given
605 // one of its child blocks
606 Block *
607 Block::GetSiblingForChild (const Block *child_block) const
608 {
609     if (!m_children.empty())
610     {
611         collection::const_iterator pos, end = m_children.end();
612         for (pos = m_children.begin(); pos != end; ++pos)
613         {
614             if (pos->get() == child_block)
615             {
616                 if (++pos != end)
617                     return pos->get();
618                 break;
619             }
620         }
621     }
622     return NULL;
623 }
624 
625