blob: a1de78a1f3089d6fedaf7e56f049f5016fcd2256 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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
17using namespace lldb;
18using namespace lldb_private;
19
Greg Clayton75ccf502010-08-21 02:22:51 +000020Block::Block(lldb::user_id_t uid) :
Chris Lattner24943d22010-06-08 16:52:24 +000021 UserID(uid),
Greg Clayton75ccf502010-08-21 02:22:51 +000022 m_parent_scope (NULL),
23 m_sibling (NULL),
24 m_children (),
25 m_ranges (),
26 m_inlineInfoSP (),
Greg Claytonb04e7a82010-08-24 21:05:24 +000027 m_variable_list_sp (),
Greg Clayton75ccf502010-08-21 02:22:51 +000028 m_parsed_block_info (false),
29 m_parsed_block_variables (false),
30 m_parsed_child_blocks (false)
Chris Lattner24943d22010-06-08 16:52:24 +000031{
32}
33
Chris Lattner24943d22010-06-08 16:52:24 +000034Block::~Block ()
35{
36}
37
38void
Greg Clayton75ccf502010-08-21 02:22:51 +000039Block::GetDescription(Stream *s, Function *function, lldb::DescriptionLevel level, Process *process) const
Greg Clayton12bec712010-06-28 21:30:43 +000040{
41 size_t num_ranges = m_ranges.size();
42 if (num_ranges)
43 {
44
45 addr_t base_addr = LLDB_INVALID_ADDRESS;
46 if (process)
Greg Clayton75ccf502010-08-21 02:22:51 +000047 base_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(process);
Greg Clayton12bec712010-06-28 21:30:43 +000048 if (base_addr == LLDB_INVALID_ADDRESS)
Greg Clayton75ccf502010-08-21 02:22:51 +000049 base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
Greg Clayton12bec712010-06-28 21:30:43 +000050
51 s->Printf("range%s = ", num_ranges > 1 ? "s" : "");
52 std::vector<VMRange>::const_iterator pos, end = m_ranges.end();
53 for (pos = m_ranges.begin(); pos != end; ++pos)
54 pos->Dump(s, base_addr, 4);
55 }
56 *s << ", id = " << ((const UserID&)*this);
57
58 if (m_inlineInfoSP.get() != NULL)
59 m_inlineInfoSP->Dump(s);
60}
61
62void
Chris Lattner24943d22010-06-08 16:52:24 +000063Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
64{
65 if (depth < 0)
66 {
Greg Clayton75ccf502010-08-21 02:22:51 +000067 Block *parent = GetParent();
68 if (parent)
69 {
70 // We have a depth that is less than zero, print our parent blocks
71 // first
72 parent->Dump(s, base_addr, depth + 1, show_context);
73 }
Chris Lattner24943d22010-06-08 16:52:24 +000074 }
75
76 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
77 s->Indent();
78 *s << "Block" << ((const UserID&)*this);
Greg Clayton12bec712010-06-28 21:30:43 +000079 const Block* parent_block = GetParent();
80 if (parent_block)
Chris Lattner24943d22010-06-08 16:52:24 +000081 {
Greg Clayton12bec712010-06-28 21:30:43 +000082 s->Printf(", parent = {0x%8.8x}", parent_block->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +000083 }
84 if (m_inlineInfoSP.get() != NULL)
85 m_inlineInfoSP->Dump(s);
86
87 if (!m_ranges.empty())
88 {
89 *s << ", ranges =";
90 std::vector<VMRange>::const_iterator pos;
91 std::vector<VMRange>::const_iterator end = m_ranges.end();
92 for (pos = m_ranges.begin(); pos != end; ++pos)
93 {
94 if (parent_block != NULL && parent_block->Contains(*pos) == false)
95 *s << '!';
96 else
97 *s << ' ';
98 pos->Dump(s, base_addr);
99 }
100 }
101 s->EOL();
102
103 if (depth > 0)
104 {
105 s->IndentMore();
106
Greg Claytonb04e7a82010-08-24 21:05:24 +0000107 if (m_variable_list_sp.get())
Chris Lattner24943d22010-06-08 16:52:24 +0000108 {
Greg Claytonb04e7a82010-08-24 21:05:24 +0000109 m_variable_list_sp->Dump(s, show_context);
Chris Lattner24943d22010-06-08 16:52:24 +0000110 }
111
Greg Clayton75ccf502010-08-21 02:22:51 +0000112 for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling())
Chris Lattner24943d22010-06-08 16:52:24 +0000113 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000114 child_block->Dump(s, base_addr, depth - 1, show_context);
Chris Lattner24943d22010-06-08 16:52:24 +0000115 }
116
117 s->IndentLess();
118 }
119
120}
121
122
Greg Clayton75ccf502010-08-21 02:22:51 +0000123Block *
124Block::FindBlockByID (user_id_t block_id)
125{
126 if (block_id == GetID())
127 return this;
128
129 Block *matching_block = NULL;
130 for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling())
131 {
132 matching_block = child_block->FindBlockByID (block_id);
133 if (matching_block)
134 break;
135 }
136 return matching_block;
137}
138
Chris Lattner24943d22010-06-08 16:52:24 +0000139void
Greg Claytonb04e7a82010-08-24 21:05:24 +0000140Block::CalculateSymbolContext (SymbolContext* sc)
Chris Lattner24943d22010-06-08 16:52:24 +0000141{
Greg Clayton75ccf502010-08-21 02:22:51 +0000142 if (m_parent_scope)
143 m_parent_scope->CalculateSymbolContext(sc);
Chris Lattner24943d22010-06-08 16:52:24 +0000144 sc->block = this;
Chris Lattner24943d22010-06-08 16:52:24 +0000145}
146
147void
Greg Clayton69aa5d92010-09-07 04:20:48 +0000148Block::DumpStopContext
149(
150 Stream *s,
151 const SymbolContext *sc_ptr,
152 const Declaration *child_inline_call_site,
153 bool show_fullpaths,
154 bool show_inline_blocks)
Chris Lattner24943d22010-06-08 16:52:24 +0000155{
Greg Clayton12bec712010-06-28 21:30:43 +0000156 Block* parent_block = GetParent();
Chris Lattner24943d22010-06-08 16:52:24 +0000157
Greg Clayton69aa5d92010-09-07 04:20:48 +0000158 const InlineFunctionInfo* inline_info = GetInlinedFunctionInfo ();
159 const Declaration *inline_call_site = child_inline_call_site;
Chris Lattner24943d22010-06-08 16:52:24 +0000160 if (inline_info)
161 {
Greg Clayton69aa5d92010-09-07 04:20:48 +0000162 inline_call_site = &inline_info->GetCallSite();
163 if (sc_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000164 {
Greg Clayton69aa5d92010-09-07 04:20:48 +0000165 // First frame in a frame with inlined functions
Chris Lattner24943d22010-06-08 16:52:24 +0000166 s->PutCString (" [inlined]");
167 }
Greg Clayton69aa5d92010-09-07 04:20:48 +0000168 if (show_inline_blocks)
169 s->EOL();
170 else
171 s->PutChar(' ');
172
173 s->PutCString(inline_info->GetName ().AsCString());
174
175 if (child_inline_call_site && child_inline_call_site->IsValid())
Chris Lattner24943d22010-06-08 16:52:24 +0000176 {
Greg Clayton69aa5d92010-09-07 04:20:48 +0000177 s->PutCString(" at ");
178 child_inline_call_site->DumpStopContext (s, show_fullpaths);
Chris Lattner24943d22010-06-08 16:52:24 +0000179 }
180 }
181
Greg Clayton69aa5d92010-09-07 04:20:48 +0000182 if (sc_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000183 {
184 // If we have any inlined functions, this will be the deepest most
185 // inlined location
Greg Clayton69aa5d92010-09-07 04:20:48 +0000186 if (sc_ptr->line_entry.IsValid())
Chris Lattner24943d22010-06-08 16:52:24 +0000187 {
188 s->PutCString(" at ");
Greg Clayton69aa5d92010-09-07 04:20:48 +0000189 sc_ptr->line_entry.DumpStopContext (s, show_fullpaths);
Chris Lattner24943d22010-06-08 16:52:24 +0000190 }
191 }
Greg Clayton69aa5d92010-09-07 04:20:48 +0000192
193 if (show_inline_blocks)
194 {
195 if (parent_block)
196 {
197 parent_block->Block::DumpStopContext (s,
198 NULL,
199 inline_call_site,
200 show_fullpaths,
201 show_inline_blocks);
202 }
203 else if (child_inline_call_site)
204 {
205 SymbolContext sc;
206 CalculateSymbolContext(&sc);
207 if (sc.function)
208 {
209 s->EOL();
210 s->Indent (sc.function->GetMangled().GetName().AsCString());
211 if (child_inline_call_site && child_inline_call_site->IsValid())
212 {
213 s->PutCString(" at ");
214 child_inline_call_site->DumpStopContext (s, show_fullpaths);
215 }
216 }
217 }
218 }
Chris Lattner24943d22010-06-08 16:52:24 +0000219}
220
221
222void
223Block::DumpSymbolContext(Stream *s)
224{
Greg Clayton75ccf502010-08-21 02:22:51 +0000225 SymbolContext sc;
226 CalculateSymbolContext(&sc);
227 if (sc.function)
228 sc.function->DumpSymbolContext(s);
Chris Lattner24943d22010-06-08 16:52:24 +0000229 s->Printf(", Block{0x%8.8x}", GetID());
230}
231
232bool
233Block::Contains (addr_t range_offset) const
234{
235 return VMRange::ContainsValue(m_ranges, range_offset);
236}
237
238bool
Greg Clayton72b71582010-09-02 21:44:10 +0000239Block::Contains (const Block *block) const
240{
241 // Block objects can't contain themselves...
242 if (this == block)
243 return false;
244
245 const Block *block_parent;
246 for (block_parent = block->GetParent();
247 block_parent != NULL;
248 block_parent = block_parent->GetParent())
249 {
250 if (block_parent == block)
251 return true;
252 }
253 return false;
254}
255
256bool
Chris Lattner24943d22010-06-08 16:52:24 +0000257Block::Contains (const VMRange& range) const
258{
259 return VMRange::ContainsRange(m_ranges, range);
260}
261
Greg Clayton75ccf502010-08-21 02:22:51 +0000262Block *
263Block::GetParent () const
Chris Lattner24943d22010-06-08 16:52:24 +0000264{
Greg Clayton75ccf502010-08-21 02:22:51 +0000265 if (m_parent_scope)
Chris Lattner24943d22010-06-08 16:52:24 +0000266 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000267 SymbolContext sc;
268 m_parent_scope->CalculateSymbolContext(&sc);
269 if (sc.block)
270 return sc.block;
Chris Lattner24943d22010-06-08 16:52:24 +0000271 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000272 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000273}
274
Greg Clayton33ed1702010-08-24 00:45:41 +0000275Block *
Greg Claytonb04e7a82010-08-24 21:05:24 +0000276Block::GetContainingInlinedBlock ()
277{
Greg Clayton69aa5d92010-09-07 04:20:48 +0000278 if (GetInlinedFunctionInfo())
Greg Claytonb04e7a82010-08-24 21:05:24 +0000279 return this;
280 return GetInlinedParent ();
281}
282
283Block *
284Block::GetInlinedParent ()
Greg Clayton33ed1702010-08-24 00:45:41 +0000285{
286 Block *parent_block = GetParent ();
287 if (parent_block)
288 {
Greg Clayton69aa5d92010-09-07 04:20:48 +0000289 if (parent_block->GetInlinedFunctionInfo())
Greg Clayton33ed1702010-08-24 00:45:41 +0000290 return parent_block;
291 else
292 return parent_block->GetInlinedParent();
293 }
294 return NULL;
295}
296
297
298bool
Greg Claytonb04e7a82010-08-24 21:05:24 +0000299Block::GetRangeContainingOffset (const addr_t offset, VMRange &range)
300{
301 uint32_t range_idx = VMRange::FindRangeIndexThatContainsValue (m_ranges, offset);
302 if (range_idx < m_ranges.size())
303 {
304 range = m_ranges[range_idx];
305 return true;
306 }
307 range.Clear();
308 return false;
309}
310
311
312bool
Greg Clayton33ed1702010-08-24 00:45:41 +0000313Block::GetRangeContainingAddress (const Address& addr, AddressRange &range)
314{
315 SymbolContext sc;
316 CalculateSymbolContext(&sc);
317 if (sc.function)
318 {
319 const AddressRange &func_range = sc.function->GetAddressRange();
320 if (addr.GetSection() == func_range.GetBaseAddress().GetSection())
321 {
322 const addr_t addr_offset = addr.GetOffset();
323 const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
324 if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize())
325 {
326 addr_t offset = addr_offset - func_offset;
327
328 uint32_t range_idx = VMRange::FindRangeIndexThatContainsValue (m_ranges, offset);
329 if (range_idx < m_ranges.size())
330 {
331 range.GetBaseAddress() = func_range.GetBaseAddress();
332 range.GetBaseAddress().SetOffset(func_offset + m_ranges[range_idx].GetBaseAddress());
333 range.SetByteSize(m_ranges[range_idx].GetByteSize());
334 return true;
335 }
336 }
337 }
338 }
339 range.Clear();
340 return false;
341}
342
Chris Lattner24943d22010-06-08 16:52:24 +0000343void
344Block::AddRange(addr_t start_offset, addr_t end_offset)
345{
346 m_ranges.resize(m_ranges.size()+1);
347 m_ranges.back().Reset(start_offset, end_offset);
348}
349
Chris Lattner24943d22010-06-08 16:52:24 +0000350// Return the current number of bytes that this object occupies in memory
351size_t
352Block::MemorySize() const
353{
354 size_t mem_size = sizeof(Block) + m_ranges.size() * sizeof(VMRange);
355 if (m_inlineInfoSP.get())
356 mem_size += m_inlineInfoSP->MemorySize();
Greg Claytonb04e7a82010-08-24 21:05:24 +0000357 if (m_variable_list_sp.get())
358 mem_size += m_variable_list_sp->MemorySize();
Chris Lattner24943d22010-06-08 16:52:24 +0000359 return mem_size;
360
361}
362
Greg Clayton75ccf502010-08-21 02:22:51 +0000363void
364Block::AddChild(const BlockSP &child_block_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000365{
Greg Clayton75ccf502010-08-21 02:22:51 +0000366 if (child_block_sp)
367 {
368 Block *block_needs_sibling = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000369
Greg Clayton75ccf502010-08-21 02:22:51 +0000370 if (!m_children.empty())
371 block_needs_sibling = m_children.back().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000372
Greg Clayton75ccf502010-08-21 02:22:51 +0000373 child_block_sp->SetParentScope (this);
374 m_children.push_back (child_block_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000375
Greg Clayton75ccf502010-08-21 02:22:51 +0000376 if (block_needs_sibling)
377 block_needs_sibling->SetSibling (child_block_sp.get());
378 }
Chris Lattner24943d22010-06-08 16:52:24 +0000379}
380
381void
382Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
383{
384 m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
385}
386
Jim Ingham7382a532010-08-18 19:29:16 +0000387
388
389VariableListSP
390Block::GetVariableList (bool get_child_variables, bool can_create)
391{
392 VariableListSP variable_list_sp;
Greg Clayton75ccf502010-08-21 02:22:51 +0000393 if (m_parsed_block_variables == false)
Jim Ingham7382a532010-08-18 19:29:16 +0000394 {
Greg Claytonb04e7a82010-08-24 21:05:24 +0000395 if (m_variable_list_sp.get() == NULL && can_create)
Greg Clayton75ccf502010-08-21 02:22:51 +0000396 {
397 m_parsed_block_variables = true;
398 SymbolContext sc;
399 CalculateSymbolContext(&sc);
400 assert(sc.module_sp);
401 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
402 }
Jim Ingham7382a532010-08-18 19:29:16 +0000403 }
404
Greg Claytonb04e7a82010-08-24 21:05:24 +0000405 if (m_variable_list_sp.get())
Jim Ingham7382a532010-08-18 19:29:16 +0000406 {
407 variable_list_sp.reset(new VariableList());
408 if (variable_list_sp.get())
Greg Claytonb04e7a82010-08-24 21:05:24 +0000409 variable_list_sp->AddVariables(m_variable_list_sp.get());
Jim Ingham7382a532010-08-18 19:29:16 +0000410
411 if (get_child_variables)
412 {
Greg Clayton69aa5d92010-09-07 04:20:48 +0000413 for (Block *child_block = GetFirstChild();
414 child_block != NULL;
415 child_block = child_block->GetSibling())
416 {
417 if (child_block->GetInlinedFunctionInfo() == NULL)
418 {
419 VariableListSP child_block_variable_list(child_block->GetVariableList(get_child_variables, can_create));
420 if (child_block_variable_list.get())
421 variable_list_sp->AddVariables(child_block_variable_list.get());
422 }
423
Jim Ingham7382a532010-08-18 19:29:16 +0000424 }
425 }
426 }
427
428 return variable_list_sp;
429}
430
431uint32_t
Greg Clayton33ed1702010-08-24 00:45:41 +0000432Block::AppendVariables
433(
434 bool can_create,
435 bool get_parent_variables,
436 bool stop_if_block_is_inlined_function,
437 VariableList *variable_list
438)
Jim Ingham7382a532010-08-18 19:29:16 +0000439{
440 uint32_t num_variables_added = 0;
441 VariableListSP variable_list_sp(GetVariableList(false, can_create));
442
Greg Clayton69aa5d92010-09-07 04:20:48 +0000443 bool is_inlined_function = GetInlinedFunctionInfo() != NULL;
Jim Ingham7382a532010-08-18 19:29:16 +0000444 if (variable_list_sp.get())
445 {
446 num_variables_added = variable_list_sp->GetSize();
447 variable_list->AddVariables(variable_list_sp.get());
448 }
Greg Clayton33ed1702010-08-24 00:45:41 +0000449
Jim Ingham7382a532010-08-18 19:29:16 +0000450 if (get_parent_variables)
451 {
Greg Clayton33ed1702010-08-24 00:45:41 +0000452 if (stop_if_block_is_inlined_function && is_inlined_function)
453 return num_variables_added;
454
Jim Ingham7382a532010-08-18 19:29:16 +0000455 Block* parent_block = GetParent();
456 if (parent_block)
Greg Clayton33ed1702010-08-24 00:45:41 +0000457 num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list);
Jim Ingham7382a532010-08-18 19:29:16 +0000458 }
459 return num_variables_added;
460}
461
Chris Lattner24943d22010-06-08 16:52:24 +0000462void
Greg Clayton75ccf502010-08-21 02:22:51 +0000463Block::SetBlockInfoHasBeenParsed (bool b, bool set_children)
Chris Lattner24943d22010-06-08 16:52:24 +0000464{
Greg Clayton75ccf502010-08-21 02:22:51 +0000465 m_parsed_block_info = b;
466 if (set_children)
Chris Lattner24943d22010-06-08 16:52:24 +0000467 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000468 m_parsed_child_blocks = true;
469 for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling())
470 child_block->SetBlockInfoHasBeenParsed (b, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000471 }
Chris Lattner24943d22010-06-08 16:52:24 +0000472}