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.size();
48     if (num_ranges)
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         std::vector<VMRange>::const_iterator pos, end = m_ranges.end();
59         for (pos = m_ranges.begin(); pos != end; ++pos)
60             pos->Dump(s, base_addr, 4);
61     }
62 
63     if (m_inlineInfoSP.get() != NULL)
64     {
65         bool show_fullpaths = (level == eDescriptionLevelVerbose);
66         m_inlineInfoSP->Dump(s, show_fullpaths);
67     }
68 }
69 
70 void
71 Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
72 {
73     if (depth < 0)
74     {
75         Block *parent = GetParent();
76         if (parent)
77         {
78             // We have a depth that is less than zero, print our parent blocks
79             // first
80             parent->Dump(s, base_addr, depth + 1, show_context);
81         }
82     }
83 
84     s->Printf("%p: ", this);
85     s->Indent();
86     *s << "Block" << ((const UserID&)*this);
87     const Block* parent_block = GetParent();
88     if (parent_block)
89     {
90         s->Printf(", parent = {0x%8.8x}", parent_block->GetID());
91     }
92     if (m_inlineInfoSP.get() != NULL)
93     {
94         bool show_fullpaths = false;
95         m_inlineInfoSP->Dump(s, show_fullpaths);
96     }
97 
98     if (!m_ranges.empty())
99     {
100         *s << ", ranges =";
101         std::vector<VMRange>::const_iterator pos;
102         std::vector<VMRange>::const_iterator end = m_ranges.end();
103         for (pos = m_ranges.begin(); pos != end; ++pos)
104         {
105             if (parent_block != NULL && parent_block->Contains(*pos) == false)
106                 *s << '!';
107             else
108                 *s << ' ';
109             pos->Dump(s, base_addr);
110         }
111     }
112     s->EOL();
113 
114     if (depth > 0)
115     {
116         s->IndentMore();
117 
118         if (m_variable_list_sp.get())
119         {
120             m_variable_list_sp->Dump(s, show_context);
121         }
122 
123         collection::const_iterator pos, end = m_children.end();
124         for (pos = m_children.begin(); pos != end; ++pos)
125             (*pos)->Dump(s, base_addr, depth - 1, show_context);
126 
127         s->IndentLess();
128     }
129 
130 }
131 
132 
133 Block *
134 Block::FindBlockByID (user_id_t block_id)
135 {
136     if (block_id == GetID())
137         return this;
138 
139     Block *matching_block = NULL;
140     collection::const_iterator pos, end = m_children.end();
141     for (pos = m_children.begin(); pos != end; ++pos)
142     {
143         matching_block = (*pos)->FindBlockByID (block_id);
144         if (matching_block)
145             break;
146     }
147     return matching_block;
148 }
149 
150 void
151 Block::CalculateSymbolContext (SymbolContext* sc)
152 {
153     if (m_parent_scope)
154         m_parent_scope->CalculateSymbolContext(sc);
155     sc->block = this;
156 }
157 
158 Module *
159 Block::CalculateSymbolContextModule ()
160 {
161     if (m_parent_scope)
162         return m_parent_scope->CalculateSymbolContextModule ();
163     return NULL;
164 }
165 
166 CompileUnit *
167 Block::CalculateSymbolContextCompileUnit ()
168 {
169     if (m_parent_scope)
170         return m_parent_scope->CalculateSymbolContextCompileUnit ();
171     return NULL;
172 }
173 
174 Function *
175 Block::CalculateSymbolContextFunction ()
176 {
177     if (m_parent_scope)
178         return m_parent_scope->CalculateSymbolContextFunction ();
179     return NULL;
180 }
181 
182 Block *
183 Block::CalculateSymbolContextBlock ()
184 {
185     return this;
186 }
187 
188 void
189 Block::DumpSymbolContext(Stream *s)
190 {
191     Function *function = CalculateSymbolContextFunction();
192     if (function)
193         function->DumpSymbolContext(s);
194     s->Printf(", Block{0x%8.8x}", GetID());
195 }
196 
197 void
198 Block::DumpAddressRanges (Stream *s, lldb::addr_t base_addr)
199 {
200     if (!m_ranges.empty())
201     {
202         std::vector<VMRange>::const_iterator pos, end = m_ranges.end();
203         for (pos = m_ranges.begin(); pos != end; ++pos)
204             pos->Dump (s, base_addr);
205     }
206 }
207 
208 bool
209 Block::Contains (addr_t range_offset) const
210 {
211     return VMRange::ContainsValue(m_ranges, range_offset);
212 }
213 
214 bool
215 Block::Contains (const Block *block) const
216 {
217     if (this == block)
218         return false; // This block doesn't contain itself...
219 
220     // Walk the parent chain for "block" and see if any if them match this block
221     const Block *block_parent;
222     for (block_parent = block->GetParent();
223          block_parent != NULL;
224          block_parent = block_parent->GetParent())
225     {
226         if (this == block_parent)
227             return true; // One of the parents of "block" is this object!
228     }
229     return false;
230 }
231 
232 bool
233 Block::Contains (const VMRange& range) const
234 {
235     return VMRange::ContainsRange(m_ranges, range);
236 }
237 
238 Block *
239 Block::GetParent () const
240 {
241     if (m_parent_scope)
242         return m_parent_scope->CalculateSymbolContextBlock();
243     return NULL;
244 }
245 
246 Block *
247 Block::GetContainingInlinedBlock ()
248 {
249     if (GetInlinedFunctionInfo())
250         return this;
251     return GetInlinedParent ();
252 }
253 
254 Block *
255 Block::GetInlinedParent ()
256 {
257     Block *parent_block = GetParent ();
258     if (parent_block)
259     {
260         if (parent_block->GetInlinedFunctionInfo())
261             return parent_block;
262         else
263             return parent_block->GetInlinedParent();
264     }
265     return NULL;
266 }
267 
268 
269 bool
270 Block::GetRangeContainingOffset (const addr_t offset, VMRange &range)
271 {
272     uint32_t range_idx = VMRange::FindRangeIndexThatContainsValue (m_ranges, offset);
273     if (range_idx < m_ranges.size())
274     {
275         range = m_ranges[range_idx];
276         return true;
277     }
278     range.Clear();
279     return false;
280 }
281 
282 
283 bool
284 Block::GetRangeContainingAddress (const Address& addr, AddressRange &range, uint32_t *range_idx_ptr)
285 {
286     Function *function = CalculateSymbolContextFunction();
287     if (function)
288     {
289         const AddressRange &func_range = function->GetAddressRange();
290         if (addr.GetSection() == func_range.GetBaseAddress().GetSection())
291         {
292             const addr_t addr_offset = addr.GetOffset();
293             const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
294             if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize())
295             {
296                 addr_t offset = addr_offset - func_offset;
297 
298                 uint32_t range_idx = VMRange::FindRangeIndexThatContainsValue (m_ranges, offset);
299                 if (range_idx < m_ranges.size())
300                 {
301                     range.GetBaseAddress() = func_range.GetBaseAddress();
302                     range.GetBaseAddress().SetOffset(func_offset + m_ranges[range_idx].GetBaseAddress());
303                     range.SetByteSize(m_ranges[range_idx].GetByteSize());
304                     if (range_idx_ptr)
305                         *range_idx_ptr = range_idx;
306                     return true;
307                 }
308             }
309         }
310     }
311     if (range_idx_ptr)
312         *range_idx_ptr = UINT32_MAX;
313     range.Clear();
314     return false;
315 }
316 
317 bool
318 Block::GetRangeAtIndex (uint32_t range_idx, AddressRange &range)
319 {
320     if (range_idx < m_ranges.size())
321     {
322         Function *function = CalculateSymbolContextFunction();
323         if (function)
324         {
325             range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();
326             range.GetBaseAddress().Slide(m_ranges[range_idx].GetBaseAddress ());
327             range.SetByteSize (m_ranges[range_idx].GetByteSize());
328             return true;
329         }
330     }
331     return false;
332 }
333 
334 bool
335 Block::GetStartAddress (Address &addr)
336 {
337     if (m_ranges.empty())
338         return false;
339 
340     Function *function = CalculateSymbolContextFunction();
341     if (function)
342     {
343         addr = function->GetAddressRange().GetBaseAddress();
344         addr.Slide(m_ranges.front().GetBaseAddress ());
345         return true;
346     }
347     return false;
348 }
349 
350 void
351 Block::AddRange (const VMRange& new_range)
352 {
353     Block *parent_block = GetParent ();
354     if (parent_block && !parent_block->Contains(new_range))
355     {
356         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
357         if (log)
358         {
359             Module *module = m_parent_scope->CalculateSymbolContextModule();
360             Function *function = m_parent_scope->CalculateSymbolContextFunction();
361             const addr_t function_file_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
362             const addr_t block_start_addr = function_file_addr + new_range.GetBaseAddress ();
363             const addr_t block_end_addr = function_file_addr + new_range.GetEndAddress ();
364             Type *func_type = function->GetType();
365 
366             const Declaration &func_decl = func_type->GetDeclaration();
367             if (func_decl.GetLine())
368             {
369                 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",
370                              func_decl.GetFile().GetDirectory().GetCString(),
371                              func_decl.GetFile().GetFilename().GetCString(),
372                              func_decl.GetLine(),
373                              GetID(),
374                              (uint32_t)m_ranges.size(),
375                              block_start_addr,
376                              block_end_addr,
377                              parent_block->GetID(),
378                              function->GetID(),
379                              module->GetFileSpec().GetDirectory().GetCString(),
380                              module->GetFileSpec().GetFilename().GetCString());
381             }
382             else
383             {
384                 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",
385                              GetID(),
386                              (uint32_t)m_ranges.size(),
387                              block_start_addr,
388                              block_end_addr,
389                              parent_block->GetID(),
390                              function->GetID(),
391                              module->GetFileSpec().GetDirectory().GetCString(),
392                              module->GetFileSpec().GetFilename().GetCString());
393             }
394         }
395         parent_block->AddRange (new_range);
396     }
397     m_ranges.push_back(new_range);
398 }
399 
400 // Return the current number of bytes that this object occupies in memory
401 size_t
402 Block::MemorySize() const
403 {
404     size_t mem_size = sizeof(Block) + m_ranges.size() * sizeof(VMRange);
405     if (m_inlineInfoSP.get())
406         mem_size += m_inlineInfoSP->MemorySize();
407     if (m_variable_list_sp.get())
408         mem_size += m_variable_list_sp->MemorySize();
409     return mem_size;
410 
411 }
412 
413 void
414 Block::AddChild(const BlockSP &child_block_sp)
415 {
416     if (child_block_sp)
417     {
418         child_block_sp->SetParentScope (this);
419         m_children.push_back (child_block_sp);
420     }
421 }
422 
423 void
424 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
425 {
426     m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
427 }
428 
429 
430 
431 VariableListSP
432 Block::GetBlockVariableList (bool can_create)
433 {
434     if (m_parsed_block_variables == false)
435     {
436         if (m_variable_list_sp.get() == NULL && can_create)
437         {
438             m_parsed_block_variables = true;
439             SymbolContext sc;
440             CalculateSymbolContext(&sc);
441             assert(sc.module_sp);
442             sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
443         }
444     }
445     return m_variable_list_sp;
446 }
447 
448 uint32_t
449 Block::AppendBlockVariables (bool can_create,
450                              bool get_child_block_variables,
451                              bool stop_if_child_block_is_inlined_function,
452                              VariableList *variable_list)
453 {
454     uint32_t num_variables_added = 0;
455     VariableList *block_var_list = GetBlockVariableList (can_create).get();
456     if (block_var_list)
457     {
458         num_variables_added += block_var_list->GetSize();
459         variable_list->AddVariables (block_var_list);
460     }
461 
462     if (get_child_block_variables)
463     {
464         collection::const_iterator pos, end = m_children.end();
465         for (pos = m_children.begin(); pos != end; ++pos)
466         {
467             Block *child_block = pos->get();
468             if (stop_if_child_block_is_inlined_function == false ||
469                 child_block->GetInlinedFunctionInfo() == NULL)
470             {
471                 num_variables_added += child_block->AppendBlockVariables (can_create,
472                                                                           get_child_block_variables,
473                                                                           stop_if_child_block_is_inlined_function,
474                                                                           variable_list);
475             }
476         }
477     }
478     return num_variables_added;
479 }
480 
481 uint32_t
482 Block::AppendVariables
483 (
484     bool can_create,
485     bool get_parent_variables,
486     bool stop_if_block_is_inlined_function,
487     VariableList *variable_list
488 )
489 {
490     uint32_t num_variables_added = 0;
491     VariableListSP variable_list_sp(GetBlockVariableList(can_create));
492 
493     bool is_inlined_function = GetInlinedFunctionInfo() != NULL;
494     if (variable_list_sp.get())
495     {
496         num_variables_added = variable_list_sp->GetSize();
497         variable_list->AddVariables(variable_list_sp.get());
498     }
499 
500     if (get_parent_variables)
501     {
502         if (stop_if_block_is_inlined_function && is_inlined_function)
503             return num_variables_added;
504 
505         Block* parent_block = GetParent();
506         if (parent_block)
507             num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list);
508     }
509     return num_variables_added;
510 }
511 
512 clang::DeclContext *
513 Block::GetClangDeclContextForInlinedFunction()
514 {
515     SymbolContext sc;
516 
517     CalculateSymbolContext (&sc);
518 
519     if (!sc.module_sp)
520         return NULL;
521 
522     SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
523 
524     if (!sym_vendor)
525         return NULL;
526 
527     SymbolFile *sym_file = sym_vendor->GetSymbolFile();
528 
529     if (!sym_file)
530         return NULL;
531 
532     return sym_file->GetClangDeclContextForTypeUID (sc, m_uid);
533 }
534 
535 void
536 Block::SetBlockInfoHasBeenParsed (bool b, bool set_children)
537 {
538     m_parsed_block_info = b;
539     if (set_children)
540     {
541         m_parsed_child_blocks = true;
542         collection::const_iterator pos, end = m_children.end();
543         for (pos = m_children.begin(); pos != end; ++pos)
544             (*pos)->SetBlockInfoHasBeenParsed (b, true);
545     }
546 }
547 
548 void
549 Block::SetDidParseVariables (bool b, bool set_children)
550 {
551     m_parsed_block_variables = b;
552     if (set_children)
553     {
554         collection::const_iterator pos, end = m_children.end();
555         for (pos = m_children.begin(); pos != end; ++pos)
556             (*pos)->SetDidParseVariables (b, true);
557     }
558 }
559 
560 
561 Block *
562 Block::GetSibling() const
563 {
564     if (m_parent_scope)
565     {
566         Block *parent_block = GetParent();
567         if (parent_block)
568             return parent_block->GetSiblingForChild (this);
569     }
570     return NULL;
571 }
572 // A parent of child blocks can be asked to find a sibling block given
573 // one of its child blocks
574 Block *
575 Block::GetSiblingForChild (const Block *child_block) const
576 {
577     if (!m_children.empty())
578     {
579         collection::const_iterator pos, end = m_children.end();
580         for (pos = m_children.begin(); pos != end; ++pos)
581         {
582             if (pos->get() == child_block)
583             {
584                 if (++pos != end)
585                     return pos->get();
586                 break;
587             }
588         }
589     }
590     return NULL;
591 }
592 
593