]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Symbol/Block.cpp
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Symbol / Block.cpp
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/Module.h"
13 #include "lldb/Core/Section.h"
14 #include "lldb/Symbol/Function.h"
15 #include "lldb/Symbol/SymbolFile.h"
16 #include "lldb/Symbol/SymbolVendor.h"
17 #include "lldb/Symbol/VariableList.h"
18 #include "lldb/Utility/Log.h"
19
20 using namespace lldb;
21 using namespace lldb_private;
22
23 Block::Block(lldb::user_id_t uid)
24     : UserID(uid), m_parent_scope(nullptr), m_children(), m_ranges(),
25       m_inlineInfoSP(), m_variable_list_sp(), m_parsed_block_info(false),
26       m_parsed_block_variables(false), m_parsed_child_blocks(false) {}
27
28 Block::~Block() {}
29
30 void Block::GetDescription(Stream *s, Function *function,
31                            lldb::DescriptionLevel level, Target *target) const {
32   *s << "id = " << ((const UserID &)*this);
33
34   size_t num_ranges = m_ranges.GetSize();
35   if (num_ranges > 0) {
36
37     addr_t base_addr = LLDB_INVALID_ADDRESS;
38     if (target)
39       base_addr =
40           function->GetAddressRange().GetBaseAddress().GetLoadAddress(target);
41     if (base_addr == LLDB_INVALID_ADDRESS)
42       base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
43
44     s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");
45     for (size_t i = 0; i < num_ranges; ++i) {
46       const Range &range = m_ranges.GetEntryRef(i);
47       s->AddressRange(base_addr + range.GetRangeBase(),
48                       base_addr + range.GetRangeEnd(), 4);
49     }
50   }
51
52   if (m_inlineInfoSP.get() != nullptr) {
53     bool show_fullpaths = (level == eDescriptionLevelVerbose);
54     m_inlineInfoSP->Dump(s, show_fullpaths);
55   }
56 }
57
58 void Block::Dump(Stream *s, addr_t base_addr, int32_t depth,
59                  bool show_context) const {
60   if (depth < 0) {
61     Block *parent = GetParent();
62     if (parent) {
63       // We have a depth that is less than zero, print our parent blocks first
64       parent->Dump(s, base_addr, depth + 1, show_context);
65     }
66   }
67
68   s->Printf("%p: ", static_cast<const void *>(this));
69   s->Indent();
70   *s << "Block" << static_cast<const UserID &>(*this);
71   const Block *parent_block = GetParent();
72   if (parent_block) {
73     s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID());
74   }
75   if (m_inlineInfoSP.get() != nullptr) {
76     bool show_fullpaths = false;
77     m_inlineInfoSP->Dump(s, show_fullpaths);
78   }
79
80   if (!m_ranges.IsEmpty()) {
81     *s << ", ranges =";
82
83     size_t num_ranges = m_ranges.GetSize();
84     for (size_t i = 0; i < num_ranges; ++i) {
85       const Range &range = m_ranges.GetEntryRef(i);
86       if (parent_block != nullptr && !parent_block->Contains(range))
87         *s << '!';
88       else
89         *s << ' ';
90       s->AddressRange(base_addr + range.GetRangeBase(),
91                       base_addr + range.GetRangeEnd(), 4);
92     }
93   }
94   s->EOL();
95
96   if (depth > 0) {
97     s->IndentMore();
98
99     if (m_variable_list_sp.get()) {
100       m_variable_list_sp->Dump(s, show_context);
101     }
102
103     collection::const_iterator pos, end = m_children.end();
104     for (pos = m_children.begin(); pos != end; ++pos)
105       (*pos)->Dump(s, base_addr, depth - 1, show_context);
106
107     s->IndentLess();
108   }
109 }
110
111 Block *Block::FindBlockByID(user_id_t block_id) {
112   if (block_id == GetID())
113     return this;
114
115   Block *matching_block = nullptr;
116   collection::const_iterator pos, end = m_children.end();
117   for (pos = m_children.begin(); pos != end; ++pos) {
118     matching_block = (*pos)->FindBlockByID(block_id);
119     if (matching_block)
120       break;
121   }
122   return matching_block;
123 }
124
125 void Block::CalculateSymbolContext(SymbolContext *sc) {
126   if (m_parent_scope)
127     m_parent_scope->CalculateSymbolContext(sc);
128   sc->block = this;
129 }
130
131 lldb::ModuleSP Block::CalculateSymbolContextModule() {
132   if (m_parent_scope)
133     return m_parent_scope->CalculateSymbolContextModule();
134   return lldb::ModuleSP();
135 }
136
137 CompileUnit *Block::CalculateSymbolContextCompileUnit() {
138   if (m_parent_scope)
139     return m_parent_scope->CalculateSymbolContextCompileUnit();
140   return nullptr;
141 }
142
143 Function *Block::CalculateSymbolContextFunction() {
144   if (m_parent_scope)
145     return m_parent_scope->CalculateSymbolContextFunction();
146   return nullptr;
147 }
148
149 Block *Block::CalculateSymbolContextBlock() { return this; }
150
151 void Block::DumpSymbolContext(Stream *s) {
152   Function *function = CalculateSymbolContextFunction();
153   if (function)
154     function->DumpSymbolContext(s);
155   s->Printf(", Block{0x%8.8" PRIx64 "}", GetID());
156 }
157
158 void Block::DumpAddressRanges(Stream *s, lldb::addr_t base_addr) {
159   if (!m_ranges.IsEmpty()) {
160     size_t num_ranges = m_ranges.GetSize();
161     for (size_t i = 0; i < num_ranges; ++i) {
162       const Range &range = m_ranges.GetEntryRef(i);
163       s->AddressRange(base_addr + range.GetRangeBase(),
164                       base_addr + range.GetRangeEnd(), 4);
165     }
166   }
167 }
168
169 bool Block::Contains(addr_t range_offset) const {
170   return m_ranges.FindEntryThatContains(range_offset) != nullptr;
171 }
172
173 bool Block::Contains(const Block *block) const {
174   if (this == block)
175     return false; // This block doesn't contain itself...
176
177   // Walk the parent chain for "block" and see if any if them match this block
178   const Block *block_parent;
179   for (block_parent = block->GetParent(); block_parent != nullptr;
180        block_parent = block_parent->GetParent()) {
181     if (this == block_parent)
182       return true; // One of the parents of "block" is this object!
183   }
184   return false;
185 }
186
187 bool Block::Contains(const Range &range) const {
188   return m_ranges.FindEntryThatContains(range) != nullptr;
189 }
190
191 Block *Block::GetParent() const {
192   if (m_parent_scope)
193     return m_parent_scope->CalculateSymbolContextBlock();
194   return nullptr;
195 }
196
197 Block *Block::GetContainingInlinedBlock() {
198   if (GetInlinedFunctionInfo())
199     return this;
200   return GetInlinedParent();
201 }
202
203 Block *Block::GetInlinedParent() {
204   Block *parent_block = GetParent();
205   if (parent_block) {
206     if (parent_block->GetInlinedFunctionInfo())
207       return parent_block;
208     else
209       return parent_block->GetInlinedParent();
210   }
211   return nullptr;
212 }
213
214 bool Block::GetRangeContainingOffset(const addr_t offset, Range &range) {
215   const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
216   if (range_ptr) {
217     range = *range_ptr;
218     return true;
219   }
220   range.Clear();
221   return false;
222 }
223
224 bool Block::GetRangeContainingAddress(const Address &addr,
225                                       AddressRange &range) {
226   Function *function = CalculateSymbolContextFunction();
227   if (function) {
228     const AddressRange &func_range = function->GetAddressRange();
229     if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
230       const addr_t addr_offset = addr.GetOffset();
231       const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
232       if (addr_offset >= func_offset &&
233           addr_offset < func_offset + func_range.GetByteSize()) {
234         addr_t offset = addr_offset - func_offset;
235
236         const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
237
238         if (range_ptr) {
239           range.GetBaseAddress() = func_range.GetBaseAddress();
240           range.GetBaseAddress().SetOffset(func_offset +
241                                            range_ptr->GetRangeBase());
242           range.SetByteSize(range_ptr->GetByteSize());
243           return true;
244         }
245       }
246     }
247   }
248   range.Clear();
249   return false;
250 }
251
252 bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr,
253                                           Target &target, AddressRange &range) {
254   Address load_address;
255   load_address.SetLoadAddress(load_addr, &target);
256   AddressRange containing_range;
257   return GetRangeContainingAddress(load_address, containing_range);
258 }
259
260 uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) {
261   Function *function = CalculateSymbolContextFunction();
262   if (function) {
263     const AddressRange &func_range = function->GetAddressRange();
264     if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
265       const addr_t addr_offset = addr.GetOffset();
266       const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
267       if (addr_offset >= func_offset &&
268           addr_offset < func_offset + func_range.GetByteSize()) {
269         addr_t offset = addr_offset - func_offset;
270         return m_ranges.FindEntryIndexThatContains(offset);
271       }
272     }
273   }
274   return UINT32_MAX;
275 }
276
277 bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {
278   if (range_idx < m_ranges.GetSize()) {
279     Function *function = CalculateSymbolContextFunction();
280     if (function) {
281       const Range &vm_range = m_ranges.GetEntryRef(range_idx);
282       range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();
283       range.GetBaseAddress().Slide(vm_range.GetRangeBase());
284       range.SetByteSize(vm_range.GetByteSize());
285       return true;
286     }
287   }
288   return false;
289 }
290
291 bool Block::GetStartAddress(Address &addr) {
292   if (m_ranges.IsEmpty())
293     return false;
294
295   Function *function = CalculateSymbolContextFunction();
296   if (function) {
297     addr = function->GetAddressRange().GetBaseAddress();
298     addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase());
299     return true;
300   }
301   return false;
302 }
303
304 void Block::FinalizeRanges() {
305   m_ranges.Sort();
306   m_ranges.CombineConsecutiveRanges();
307 }
308
309 void Block::AddRange(const Range &range) {
310   Block *parent_block = GetParent();
311   if (parent_block && !parent_block->Contains(range)) {
312     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS));
313     if (log) {
314       ModuleSP module_sp(m_parent_scope->CalculateSymbolContextModule());
315       Function *function = m_parent_scope->CalculateSymbolContextFunction();
316       const addr_t function_file_addr =
317           function->GetAddressRange().GetBaseAddress().GetFileAddress();
318       const addr_t block_start_addr = function_file_addr + range.GetRangeBase();
319       const addr_t block_end_addr = function_file_addr + range.GetRangeEnd();
320       Type *func_type = function->GetType();
321
322       const Declaration &func_decl = func_type->GetDeclaration();
323       if (func_decl.GetLine()) {
324         log->Printf("warning: %s:%u block {0x%8.8" PRIx64
325                     "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64
326                     ") which is not contained in parent block {0x%8.8" PRIx64
327                     "} in function {0x%8.8" PRIx64 "} from %s",
328                     func_decl.GetFile().GetPath().c_str(), func_decl.GetLine(),
329                     GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,
330                     block_end_addr, parent_block->GetID(), function->GetID(),
331                     module_sp->GetFileSpec().GetPath().c_str());
332       } else {
333         log->Printf("warning: block {0x%8.8" PRIx64
334                     "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64
335                     ") which is not contained in parent block {0x%8.8" PRIx64
336                     "} in function {0x%8.8" PRIx64 "} from %s",
337                     GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,
338                     block_end_addr, parent_block->GetID(), function->GetID(),
339                     module_sp->GetFileSpec().GetPath().c_str());
340       }
341     }
342     parent_block->AddRange(range);
343   }
344   m_ranges.Append(range);
345 }
346
347 // Return the current number of bytes that this object occupies in memory
348 size_t Block::MemorySize() const {
349   size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range);
350   if (m_inlineInfoSP.get())
351     mem_size += m_inlineInfoSP->MemorySize();
352   if (m_variable_list_sp.get())
353     mem_size += m_variable_list_sp->MemorySize();
354   return mem_size;
355 }
356
357 void Block::AddChild(const BlockSP &child_block_sp) {
358   if (child_block_sp) {
359     child_block_sp->SetParentScope(this);
360     m_children.push_back(child_block_sp);
361   }
362 }
363
364 void Block::SetInlinedFunctionInfo(const char *name, const char *mangled,
365                                    const Declaration *decl_ptr,
366                                    const Declaration *call_decl_ptr) {
367   m_inlineInfoSP.reset(
368       new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
369 }
370
371 VariableListSP Block::GetBlockVariableList(bool can_create) {
372   if (!m_parsed_block_variables) {
373     if (m_variable_list_sp.get() == nullptr && can_create) {
374       m_parsed_block_variables = true;
375       SymbolContext sc;
376       CalculateSymbolContext(&sc);
377       assert(sc.module_sp);
378       sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
379     }
380   }
381   return m_variable_list_sp;
382 }
383
384 uint32_t
385 Block::AppendBlockVariables(bool can_create, bool get_child_block_variables,
386                             bool stop_if_child_block_is_inlined_function,
387                             const std::function<bool(Variable *)> &filter,
388                             VariableList *variable_list) {
389   uint32_t num_variables_added = 0;
390   VariableList *block_var_list = GetBlockVariableList(can_create).get();
391   if (block_var_list) {
392     for (size_t i = 0; i < block_var_list->GetSize(); ++i) {
393       VariableSP variable = block_var_list->GetVariableAtIndex(i);
394       if (filter(variable.get())) {
395         num_variables_added++;
396         variable_list->AddVariable(variable);
397       }
398     }
399   }
400
401   if (get_child_block_variables) {
402     collection::const_iterator pos, end = m_children.end();
403     for (pos = m_children.begin(); pos != end; ++pos) {
404       Block *child_block = pos->get();
405       if (!stop_if_child_block_is_inlined_function ||
406           child_block->GetInlinedFunctionInfo() == nullptr) {
407         num_variables_added += child_block->AppendBlockVariables(
408             can_create, get_child_block_variables,
409             stop_if_child_block_is_inlined_function, filter, variable_list);
410       }
411     }
412   }
413   return num_variables_added;
414 }
415
416 uint32_t Block::AppendVariables(bool can_create, bool get_parent_variables,
417                                 bool stop_if_block_is_inlined_function,
418                                 const std::function<bool(Variable *)> &filter,
419                                 VariableList *variable_list) {
420   uint32_t num_variables_added = 0;
421   VariableListSP variable_list_sp(GetBlockVariableList(can_create));
422
423   bool is_inlined_function = GetInlinedFunctionInfo() != nullptr;
424   if (variable_list_sp) {
425     for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) {
426       VariableSP variable = variable_list_sp->GetVariableAtIndex(i);
427       if (filter(variable.get())) {
428         num_variables_added++;
429         variable_list->AddVariable(variable);
430       }
431     }
432   }
433
434   if (get_parent_variables) {
435     if (stop_if_block_is_inlined_function && is_inlined_function)
436       return num_variables_added;
437
438     Block *parent_block = GetParent();
439     if (parent_block)
440       num_variables_added += parent_block->AppendVariables(
441           can_create, get_parent_variables, stop_if_block_is_inlined_function,
442           filter, variable_list);
443   }
444   return num_variables_added;
445 }
446
447 SymbolFile *Block::GetSymbolFile() {
448   if (ModuleSP module_sp = CalculateSymbolContextModule())
449     if (SymbolVendor *sym_vendor = module_sp->GetSymbolVendor())
450       return sym_vendor->GetSymbolFile();
451   return nullptr;
452 }
453
454 CompilerDeclContext Block::GetDeclContext() {
455   if (SymbolFile *sym_file = GetSymbolFile())
456     return sym_file->GetDeclContextForUID(GetID());
457   return CompilerDeclContext();
458 }
459
460 void Block::SetBlockInfoHasBeenParsed(bool b, bool set_children) {
461   m_parsed_block_info = b;
462   if (set_children) {
463     m_parsed_child_blocks = true;
464     collection::const_iterator pos, end = m_children.end();
465     for (pos = m_children.begin(); pos != end; ++pos)
466       (*pos)->SetBlockInfoHasBeenParsed(b, true);
467   }
468 }
469
470 void Block::SetDidParseVariables(bool b, bool set_children) {
471   m_parsed_block_variables = b;
472   if (set_children) {
473     collection::const_iterator pos, end = m_children.end();
474     for (pos = m_children.begin(); pos != end; ++pos)
475       (*pos)->SetDidParseVariables(b, true);
476   }
477 }
478
479 Block *Block::GetSibling() const {
480   if (m_parent_scope) {
481     Block *parent_block = GetParent();
482     if (parent_block)
483       return parent_block->GetSiblingForChild(this);
484   }
485   return nullptr;
486 }
487 // A parent of child blocks can be asked to find a sibling block given
488 // one of its child blocks
489 Block *Block::GetSiblingForChild(const Block *child_block) const {
490   if (!m_children.empty()) {
491     collection::const_iterator pos, end = m_children.end();
492     for (pos = m_children.begin(); pos != end; ++pos) {
493       if (pos->get() == child_block) {
494         if (++pos != end)
495           return pos->get();
496         break;
497       }
498     }
499   }
500   return nullptr;
501 }