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