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 void
156 Block::DumpStopContext
157 (
158     Stream *s,
159     const SymbolContext *sc_ptr,
160     const Declaration *child_inline_call_site,
161     bool show_fullpaths,
162     bool show_inline_blocks)
163 {
164     const InlineFunctionInfo* inline_info = NULL;
165     Block* inlined_block;
166     if (sc_ptr)
167         inlined_block = GetContainingInlinedBlock ();
168     else
169         inlined_block = GetInlinedParent();
170 
171     if (inlined_block)
172         inline_info = inlined_block->GetInlinedFunctionInfo();
173     const Declaration *inline_call_site = child_inline_call_site;
174     if (inline_info)
175     {
176         inline_call_site = &inline_info->GetCallSite();
177         if (sc_ptr)
178         {
179             // First frame in a frame with inlined functions
180             s->PutCString (" [inlined]");
181         }
182         if (show_inline_blocks && child_inline_call_site)
183             s->EOL();
184         else
185             s->PutChar(' ');
186 
187         if (sc_ptr == NULL)
188             s->Indent();
189 
190         s->PutCString(inline_info->GetName ().AsCString());
191 
192         if (child_inline_call_site && child_inline_call_site->IsValid())
193         {
194             s->PutCString(" at ");
195             child_inline_call_site->DumpStopContext (s, show_fullpaths);
196         }
197     }
198 
199     // The first call to this function from something that has a symbol
200     // context will pass in a valid sc_ptr. Subsequent calls to this function
201     // from this function for inline purposes will NULL out sc_ptr. So on the
202     // first time through we dump the line table entry (which is always at the
203     // deepest inline code block). And subsequent calls to this function we
204     // will use hte inline call site information to print line numbers.
205     if (sc_ptr)
206     {
207         // If we have any inlined functions, this will be the deepest most
208         // inlined location
209         if (sc_ptr->line_entry.IsValid())
210         {
211             s->PutCString(" at ");
212             sc_ptr->line_entry.DumpStopContext (s, show_fullpaths);
213         }
214     }
215 
216     if (show_inline_blocks)
217     {
218         if (inlined_block)
219         {
220             inlined_block->Block::DumpStopContext (s,
221                                                    NULL,
222                                                    inline_call_site,
223                                                    show_fullpaths,
224                                                    show_inline_blocks);
225         }
226         else if (child_inline_call_site)
227         {
228             SymbolContext sc;
229             CalculateSymbolContext(&sc);
230             if (sc.function)
231             {
232                 s->EOL();
233                 s->Indent (sc.function->GetMangled().GetName().AsCString());
234                 if (child_inline_call_site && child_inline_call_site->IsValid())
235                 {
236                     s->PutCString(" at ");
237                     child_inline_call_site->DumpStopContext (s, show_fullpaths);
238                 }
239             }
240         }
241     }
242 }
243 
244 
245 void
246 Block::DumpSymbolContext(Stream *s)
247 {
248     SymbolContext sc;
249     CalculateSymbolContext(&sc);
250     if (sc.function)
251         sc.function->DumpSymbolContext(s);
252     s->Printf(", Block{0x%8.8x}", GetID());
253 }
254 
255 void
256 Block::DumpAddressRanges (Stream *s, lldb::addr_t base_addr)
257 {
258     if (!m_ranges.empty())
259     {
260         std::vector<VMRange>::const_iterator pos, end = m_ranges.end();
261         for (pos = m_ranges.begin(); pos != end; ++pos)
262             pos->Dump (s, base_addr);
263     }
264 }
265 
266 bool
267 Block::Contains (addr_t range_offset) const
268 {
269     return VMRange::ContainsValue(m_ranges, range_offset);
270 }
271 
272 bool
273 Block::Contains (const Block *block) const
274 {
275     if (this == block)
276         return false; // This block doesn't contain itself...
277 
278     // Walk the parent chain for "block" and see if any if them match this block
279     const Block *block_parent;
280     for (block_parent = block->GetParent();
281          block_parent != NULL;
282          block_parent = block_parent->GetParent())
283     {
284         if (this == block_parent)
285             return true; // One of the parents of "block" is this object!
286     }
287     return false;
288 }
289 
290 bool
291 Block::Contains (const VMRange& range) const
292 {
293     return VMRange::ContainsRange(m_ranges, range);
294 }
295 
296 Block *
297 Block::GetParent () const
298 {
299     if (m_parent_scope)
300     {
301         SymbolContext sc;
302         m_parent_scope->CalculateSymbolContext(&sc);
303         if (sc.block)
304             return sc.block;
305     }
306     return NULL;
307 }
308 
309 Block *
310 Block::GetContainingInlinedBlock ()
311 {
312     if (GetInlinedFunctionInfo())
313         return this;
314     return GetInlinedParent ();
315 }
316 
317 Block *
318 Block::GetInlinedParent ()
319 {
320     Block *parent_block = GetParent ();
321     if (parent_block)
322     {
323         if (parent_block->GetInlinedFunctionInfo())
324             return parent_block;
325         else
326             return parent_block->GetInlinedParent();
327     }
328     return NULL;
329 }
330 
331 
332 bool
333 Block::GetRangeContainingOffset (const addr_t offset, VMRange &range)
334 {
335     uint32_t range_idx = VMRange::FindRangeIndexThatContainsValue (m_ranges, offset);
336     if (range_idx < m_ranges.size())
337     {
338         range = m_ranges[range_idx];
339         return true;
340     }
341     range.Clear();
342     return false;
343 }
344 
345 
346 bool
347 Block::GetRangeContainingAddress (const Address& addr, AddressRange &range)
348 {
349     SymbolContext sc;
350     CalculateSymbolContext(&sc);
351     if (sc.function)
352     {
353         const AddressRange &func_range = sc.function->GetAddressRange();
354         if (addr.GetSection() == func_range.GetBaseAddress().GetSection())
355         {
356             const addr_t addr_offset = addr.GetOffset();
357             const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
358             if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize())
359             {
360                 addr_t offset = addr_offset - func_offset;
361 
362                 uint32_t range_idx = VMRange::FindRangeIndexThatContainsValue (m_ranges, offset);
363                 if (range_idx < m_ranges.size())
364                 {
365                     range.GetBaseAddress() = func_range.GetBaseAddress();
366                     range.GetBaseAddress().SetOffset(func_offset + m_ranges[range_idx].GetBaseAddress());
367                     range.SetByteSize(m_ranges[range_idx].GetByteSize());
368                     return true;
369                 }
370             }
371         }
372     }
373     range.Clear();
374     return false;
375 }
376 
377 bool
378 Block::GetRangeAtIndex (uint32_t range_idx, AddressRange &range)
379 {
380     if (range_idx < m_ranges.size())
381     {
382         SymbolContext sc;
383         CalculateSymbolContext(&sc);
384         if (sc.function)
385         {
386             range.GetBaseAddress() = sc.function->GetAddressRange().GetBaseAddress();
387             range.GetBaseAddress().Slide(m_ranges[range_idx].GetBaseAddress ());
388             range.SetByteSize (m_ranges[range_idx].GetByteSize());
389             return true;
390         }
391     }
392     return false;
393 }
394 
395 bool
396 Block::GetStartAddress (Address &addr)
397 {
398     if (m_ranges.empty())
399         return false;
400 
401     SymbolContext sc;
402     CalculateSymbolContext(&sc);
403     if (sc.function)
404     {
405         addr = sc.function->GetAddressRange().GetBaseAddress();
406         addr.Slide(m_ranges.front().GetBaseAddress ());
407         return true;
408     }
409     return false;
410 }
411 
412 void
413 Block::AddRange(addr_t start_offset, addr_t end_offset)
414 {
415     m_ranges.resize(m_ranges.size()+1);
416     m_ranges.back().Reset(start_offset, end_offset);
417 }
418 
419 // Return the current number of bytes that this object occupies in memory
420 size_t
421 Block::MemorySize() const
422 {
423     size_t mem_size = sizeof(Block) + m_ranges.size() * sizeof(VMRange);
424     if (m_inlineInfoSP.get())
425         mem_size += m_inlineInfoSP->MemorySize();
426     if (m_variable_list_sp.get())
427         mem_size += m_variable_list_sp->MemorySize();
428     return mem_size;
429 
430 }
431 
432 void
433 Block::AddChild(const BlockSP &child_block_sp)
434 {
435     if (child_block_sp)
436     {
437         Block *block_needs_sibling = NULL;
438 
439         if (!m_children.empty())
440             block_needs_sibling = m_children.back().get();
441 
442         child_block_sp->SetParentScope (this);
443         m_children.push_back (child_block_sp);
444 
445         if (block_needs_sibling)
446             block_needs_sibling->SetSibling (child_block_sp.get());
447     }
448 }
449 
450 void
451 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
452 {
453     m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
454 }
455 
456 
457 
458 VariableListSP
459 Block::GetBlockVariableList (bool can_create)
460 {
461     if (m_parsed_block_variables == false)
462     {
463         if (m_variable_list_sp.get() == NULL && can_create)
464         {
465             m_parsed_block_variables = true;
466             SymbolContext sc;
467             CalculateSymbolContext(&sc);
468             assert(sc.module_sp);
469             sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
470         }
471     }
472     return m_variable_list_sp;
473 }
474 
475 uint32_t
476 Block::AppendBlockVariables (bool can_create,
477                              bool get_child_block_variables,
478                              bool stop_if_child_block_is_inlined_function,
479                              VariableList *variable_list)
480 {
481     uint32_t num_variables_added = 0;
482     VariableList *block_var_list = GetBlockVariableList (can_create).get();
483     if (block_var_list)
484     {
485         num_variables_added += block_var_list->GetSize();
486         variable_list->AddVariables (block_var_list);
487     }
488 
489     if (get_child_block_variables)
490     {
491         for (Block *child_block = GetFirstChild();
492              child_block != NULL;
493              child_block = child_block->GetSibling())
494         {
495             if (stop_if_child_block_is_inlined_function == false ||
496                 child_block->GetInlinedFunctionInfo() == NULL)
497             {
498                 num_variables_added += child_block->AppendBlockVariables (can_create,
499                                                                           get_child_block_variables,
500                                                                           stop_if_child_block_is_inlined_function,
501                                                                           variable_list);
502             }
503         }
504     }
505     return num_variables_added;
506 }
507 
508 uint32_t
509 Block::AppendVariables
510 (
511     bool can_create,
512     bool get_parent_variables,
513     bool stop_if_block_is_inlined_function,
514     VariableList *variable_list
515 )
516 {
517     uint32_t num_variables_added = 0;
518     VariableListSP variable_list_sp(GetBlockVariableList(can_create));
519 
520     bool is_inlined_function = GetInlinedFunctionInfo() != NULL;
521     if (variable_list_sp.get())
522     {
523         num_variables_added = variable_list_sp->GetSize();
524         variable_list->AddVariables(variable_list_sp.get());
525     }
526 
527     if (get_parent_variables)
528     {
529         if (stop_if_block_is_inlined_function && is_inlined_function)
530             return num_variables_added;
531 
532         Block* parent_block = GetParent();
533         if (parent_block)
534             num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list);
535     }
536     return num_variables_added;
537 }
538 
539 clang::DeclContext *
540 Block::GetClangDeclContextForInlinedFunction()
541 {
542     SymbolContext sc;
543 
544     CalculateSymbolContext (&sc);
545 
546     if (!sc.module_sp)
547         return NULL;
548 
549     SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
550 
551     if (!sym_vendor)
552         return NULL;
553 
554     SymbolFile *sym_file = sym_vendor->GetSymbolFile();
555 
556     if (!sym_file)
557         return NULL;
558 
559     return sym_file->GetClangDeclContextForTypeUID (sc, m_uid);
560 }
561 
562 void
563 Block::SetBlockInfoHasBeenParsed (bool b, bool set_children)
564 {
565     m_parsed_block_info = b;
566     if (set_children)
567     {
568         m_parsed_child_blocks = true;
569         for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling())
570             child_block->SetBlockInfoHasBeenParsed (b, true);
571     }
572 }
573 
574 void
575 Block::SetDidParseVariables (bool b, bool set_children)
576 {
577     m_parsed_block_variables = b;
578     if (set_children)
579     {
580         for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling())
581             child_block->SetDidParseVariables (b, true);
582     }
583 }
584 
585