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