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