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