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