blob: a6e7f8f7e9acddc97cb0938e8ca93f4b875f28bf [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{
Greg Claytonc67b7d12010-09-10 01:30:46 +000041 *s << "id = " << ((const UserID&)*this);
42
Greg Clayton12bec712010-06-28 21:30:43 +000043 size_t num_ranges = m_ranges.size();
44 if (num_ranges)
45 {
46
47 addr_t base_addr = LLDB_INVALID_ADDRESS;
48 if (process)
Greg Clayton75ccf502010-08-21 02:22:51 +000049 base_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(process);
Greg Clayton12bec712010-06-28 21:30:43 +000050 if (base_addr == LLDB_INVALID_ADDRESS)
Greg Clayton75ccf502010-08-21 02:22:51 +000051 base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
Greg Clayton12bec712010-06-28 21:30:43 +000052
Greg Claytonc67b7d12010-09-10 01:30:46 +000053 s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");
Greg Clayton12bec712010-06-28 21:30:43 +000054 std::vector<VMRange>::const_iterator pos, end = m_ranges.end();
55 for (pos = m_ranges.begin(); pos != end; ++pos)
56 pos->Dump(s, base_addr, 4);
57 }
Greg Clayton12bec712010-06-28 21:30:43 +000058
59 if (m_inlineInfoSP.get() != NULL)
60 m_inlineInfoSP->Dump(s);
61}
62
63void
Chris Lattner24943d22010-06-08 16:52:24 +000064Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
65{
66 if (depth < 0)
67 {
Greg Clayton75ccf502010-08-21 02:22:51 +000068 Block *parent = GetParent();
69 if (parent)
70 {
71 // We have a depth that is less than zero, print our parent blocks
72 // first
73 parent->Dump(s, base_addr, depth + 1, show_context);
74 }
Chris Lattner24943d22010-06-08 16:52:24 +000075 }
76
77 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
78 s->Indent();
79 *s << "Block" << ((const UserID&)*this);
Greg Clayton12bec712010-06-28 21:30:43 +000080 const Block* parent_block = GetParent();
81 if (parent_block)
Chris Lattner24943d22010-06-08 16:52:24 +000082 {
Greg Clayton12bec712010-06-28 21:30:43 +000083 s->Printf(", parent = {0x%8.8x}", parent_block->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +000084 }
85 if (m_inlineInfoSP.get() != NULL)
86 m_inlineInfoSP->Dump(s);
87
88 if (!m_ranges.empty())
89 {
90 *s << ", ranges =";
91 std::vector<VMRange>::const_iterator pos;
92 std::vector<VMRange>::const_iterator end = m_ranges.end();
93 for (pos = m_ranges.begin(); pos != end; ++pos)
94 {
95 if (parent_block != NULL && parent_block->Contains(*pos) == false)
96 *s << '!';
97 else
98 *s << ' ';
99 pos->Dump(s, base_addr);
100 }
101 }
102 s->EOL();
103
104 if (depth > 0)
105 {
106 s->IndentMore();
107
Greg Claytonb04e7a82010-08-24 21:05:24 +0000108 if (m_variable_list_sp.get())
Chris Lattner24943d22010-06-08 16:52:24 +0000109 {
Greg Claytonb04e7a82010-08-24 21:05:24 +0000110 m_variable_list_sp->Dump(s, show_context);
Chris Lattner24943d22010-06-08 16:52:24 +0000111 }
112
Greg Clayton75ccf502010-08-21 02:22:51 +0000113 for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling())
Chris Lattner24943d22010-06-08 16:52:24 +0000114 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000115 child_block->Dump(s, base_addr, depth - 1, show_context);
Chris Lattner24943d22010-06-08 16:52:24 +0000116 }
117
118 s->IndentLess();
119 }
120
121}
122
123
Greg Clayton75ccf502010-08-21 02:22:51 +0000124Block *
125Block::FindBlockByID (user_id_t block_id)
126{
127 if (block_id == GetID())
128 return this;
129
130 Block *matching_block = NULL;
131 for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling())
132 {
133 matching_block = child_block->FindBlockByID (block_id);
134 if (matching_block)
135 break;
136 }
137 return matching_block;
138}
139
Chris Lattner24943d22010-06-08 16:52:24 +0000140void
Greg Claytonb04e7a82010-08-24 21:05:24 +0000141Block::CalculateSymbolContext (SymbolContext* sc)
Chris Lattner24943d22010-06-08 16:52:24 +0000142{
Greg Clayton75ccf502010-08-21 02:22:51 +0000143 if (m_parent_scope)
144 m_parent_scope->CalculateSymbolContext(sc);
Chris Lattner24943d22010-06-08 16:52:24 +0000145 sc->block = this;
Chris Lattner24943d22010-06-08 16:52:24 +0000146}
147
148void
Greg Clayton69aa5d92010-09-07 04:20:48 +0000149Block::DumpStopContext
150(
151 Stream *s,
152 const SymbolContext *sc_ptr,
153 const Declaration *child_inline_call_site,
154 bool show_fullpaths,
155 bool show_inline_blocks)
Chris Lattner24943d22010-06-08 16:52:24 +0000156{
Greg Clayton12bec712010-06-28 21:30:43 +0000157 Block* parent_block = GetParent();
Chris Lattner24943d22010-06-08 16:52:24 +0000158
Greg Clayton69aa5d92010-09-07 04:20:48 +0000159 const InlineFunctionInfo* inline_info = GetInlinedFunctionInfo ();
160 const Declaration *inline_call_site = child_inline_call_site;
Chris Lattner24943d22010-06-08 16:52:24 +0000161 if (inline_info)
162 {
Greg Clayton69aa5d92010-09-07 04:20:48 +0000163 inline_call_site = &inline_info->GetCallSite();
164 if (sc_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000165 {
Greg Clayton69aa5d92010-09-07 04:20:48 +0000166 // First frame in a frame with inlined functions
Chris Lattner24943d22010-06-08 16:52:24 +0000167 s->PutCString (" [inlined]");
168 }
Greg Clayton69aa5d92010-09-07 04:20:48 +0000169 if (show_inline_blocks)
170 s->EOL();
171 else
172 s->PutChar(' ');
173
174 s->PutCString(inline_info->GetName ().AsCString());
175
176 if (child_inline_call_site && child_inline_call_site->IsValid())
Chris Lattner24943d22010-06-08 16:52:24 +0000177 {
Greg Clayton69aa5d92010-09-07 04:20:48 +0000178 s->PutCString(" at ");
179 child_inline_call_site->DumpStopContext (s, show_fullpaths);
Chris Lattner24943d22010-06-08 16:52:24 +0000180 }
181 }
182
Greg Clayton69aa5d92010-09-07 04:20:48 +0000183 if (sc_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000184 {
185 // If we have any inlined functions, this will be the deepest most
186 // inlined location
Greg Clayton69aa5d92010-09-07 04:20:48 +0000187 if (sc_ptr->line_entry.IsValid())
Chris Lattner24943d22010-06-08 16:52:24 +0000188 {
189 s->PutCString(" at ");
Greg Clayton69aa5d92010-09-07 04:20:48 +0000190 sc_ptr->line_entry.DumpStopContext (s, show_fullpaths);
Chris Lattner24943d22010-06-08 16:52:24 +0000191 }
192 }
Greg Clayton69aa5d92010-09-07 04:20:48 +0000193
194 if (show_inline_blocks)
195 {
196 if (parent_block)
197 {
198 parent_block->Block::DumpStopContext (s,
199 NULL,
200 inline_call_site,
201 show_fullpaths,
202 show_inline_blocks);
203 }
204 else if (child_inline_call_site)
205 {
206 SymbolContext sc;
207 CalculateSymbolContext(&sc);
208 if (sc.function)
209 {
210 s->EOL();
211 s->Indent (sc.function->GetMangled().GetName().AsCString());
212 if (child_inline_call_site && child_inline_call_site->IsValid())
213 {
214 s->PutCString(" at ");
215 child_inline_call_site->DumpStopContext (s, show_fullpaths);
216 }
217 }
218 }
219 }
Chris Lattner24943d22010-06-08 16:52:24 +0000220}
221
222
223void
224Block::DumpSymbolContext(Stream *s)
225{
Greg Clayton75ccf502010-08-21 02:22:51 +0000226 SymbolContext sc;
227 CalculateSymbolContext(&sc);
228 if (sc.function)
229 sc.function->DumpSymbolContext(s);
Chris Lattner24943d22010-06-08 16:52:24 +0000230 s->Printf(", Block{0x%8.8x}", GetID());
231}
232
233bool
234Block::Contains (addr_t range_offset) const
235{
236 return VMRange::ContainsValue(m_ranges, range_offset);
237}
238
239bool
Greg Clayton72b71582010-09-02 21:44:10 +0000240Block::Contains (const Block *block) const
241{
242 // Block objects can't contain themselves...
243 if (this == block)
244 return false;
245
246 const Block *block_parent;
247 for (block_parent = block->GetParent();
248 block_parent != NULL;
249 block_parent = block_parent->GetParent())
250 {
251 if (block_parent == block)
252 return true;
253 }
254 return false;
255}
256
257bool
Chris Lattner24943d22010-06-08 16:52:24 +0000258Block::Contains (const VMRange& range) const
259{
260 return VMRange::ContainsRange(m_ranges, range);
261}
262
Greg Clayton75ccf502010-08-21 02:22:51 +0000263Block *
264Block::GetParent () const
Chris Lattner24943d22010-06-08 16:52:24 +0000265{
Greg Clayton75ccf502010-08-21 02:22:51 +0000266 if (m_parent_scope)
Chris Lattner24943d22010-06-08 16:52:24 +0000267 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000268 SymbolContext sc;
269 m_parent_scope->CalculateSymbolContext(&sc);
270 if (sc.block)
271 return sc.block;
Chris Lattner24943d22010-06-08 16:52:24 +0000272 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000273 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000274}
275
Greg Clayton33ed1702010-08-24 00:45:41 +0000276Block *
Greg Claytonb04e7a82010-08-24 21:05:24 +0000277Block::GetContainingInlinedBlock ()
278{
Greg Clayton69aa5d92010-09-07 04:20:48 +0000279 if (GetInlinedFunctionInfo())
Greg Claytonb04e7a82010-08-24 21:05:24 +0000280 return this;
281 return GetInlinedParent ();
282}
283
284Block *
285Block::GetInlinedParent ()
Greg Clayton33ed1702010-08-24 00:45:41 +0000286{
287 Block *parent_block = GetParent ();
288 if (parent_block)
289 {
Greg Clayton69aa5d92010-09-07 04:20:48 +0000290 if (parent_block->GetInlinedFunctionInfo())
Greg Clayton33ed1702010-08-24 00:45:41 +0000291 return parent_block;
292 else
293 return parent_block->GetInlinedParent();
294 }
295 return NULL;
296}
297
298
299bool
Greg Claytonb04e7a82010-08-24 21:05:24 +0000300Block::GetRangeContainingOffset (const addr_t offset, VMRange &range)
301{
302 uint32_t range_idx = VMRange::FindRangeIndexThatContainsValue (m_ranges, offset);
303 if (range_idx < m_ranges.size())
304 {
305 range = m_ranges[range_idx];
306 return true;
307 }
308 range.Clear();
309 return false;
310}
311
312
313bool
Greg Clayton33ed1702010-08-24 00:45:41 +0000314Block::GetRangeContainingAddress (const Address& addr, AddressRange &range)
315{
316 SymbolContext sc;
317 CalculateSymbolContext(&sc);
318 if (sc.function)
319 {
320 const AddressRange &func_range = sc.function->GetAddressRange();
321 if (addr.GetSection() == func_range.GetBaseAddress().GetSection())
322 {
323 const addr_t addr_offset = addr.GetOffset();
324 const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
325 if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize())
326 {
327 addr_t offset = addr_offset - func_offset;
328
329 uint32_t range_idx = VMRange::FindRangeIndexThatContainsValue (m_ranges, offset);
330 if (range_idx < m_ranges.size())
331 {
332 range.GetBaseAddress() = func_range.GetBaseAddress();
333 range.GetBaseAddress().SetOffset(func_offset + m_ranges[range_idx].GetBaseAddress());
334 range.SetByteSize(m_ranges[range_idx].GetByteSize());
335 return true;
336 }
337 }
338 }
339 }
340 range.Clear();
341 return false;
342}
343
Chris Lattner24943d22010-06-08 16:52:24 +0000344void
345Block::AddRange(addr_t start_offset, addr_t end_offset)
346{
347 m_ranges.resize(m_ranges.size()+1);
348 m_ranges.back().Reset(start_offset, end_offset);
349}
350
Chris Lattner24943d22010-06-08 16:52:24 +0000351// Return the current number of bytes that this object occupies in memory
352size_t
353Block::MemorySize() const
354{
355 size_t mem_size = sizeof(Block) + m_ranges.size() * sizeof(VMRange);
356 if (m_inlineInfoSP.get())
357 mem_size += m_inlineInfoSP->MemorySize();
Greg Claytonb04e7a82010-08-24 21:05:24 +0000358 if (m_variable_list_sp.get())
359 mem_size += m_variable_list_sp->MemorySize();
Chris Lattner24943d22010-06-08 16:52:24 +0000360 return mem_size;
361
362}
363
Greg Clayton75ccf502010-08-21 02:22:51 +0000364void
365Block::AddChild(const BlockSP &child_block_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000366{
Greg Clayton75ccf502010-08-21 02:22:51 +0000367 if (child_block_sp)
368 {
369 Block *block_needs_sibling = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000370
Greg Clayton75ccf502010-08-21 02:22:51 +0000371 if (!m_children.empty())
372 block_needs_sibling = m_children.back().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000373
Greg Clayton75ccf502010-08-21 02:22:51 +0000374 child_block_sp->SetParentScope (this);
375 m_children.push_back (child_block_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000376
Greg Clayton75ccf502010-08-21 02:22:51 +0000377 if (block_needs_sibling)
378 block_needs_sibling->SetSibling (child_block_sp.get());
379 }
Chris Lattner24943d22010-06-08 16:52:24 +0000380}
381
382void
383Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
384{
385 m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
386}
387
Jim Ingham7382a532010-08-18 19:29:16 +0000388
389
390VariableListSP
391Block::GetVariableList (bool get_child_variables, bool can_create)
392{
393 VariableListSP variable_list_sp;
Greg Clayton75ccf502010-08-21 02:22:51 +0000394 if (m_parsed_block_variables == false)
Jim Ingham7382a532010-08-18 19:29:16 +0000395 {
Greg Claytonb04e7a82010-08-24 21:05:24 +0000396 if (m_variable_list_sp.get() == NULL && can_create)
Greg Clayton75ccf502010-08-21 02:22:51 +0000397 {
398 m_parsed_block_variables = true;
399 SymbolContext sc;
400 CalculateSymbolContext(&sc);
401 assert(sc.module_sp);
402 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
403 }
Jim Ingham7382a532010-08-18 19:29:16 +0000404 }
405
Greg Claytonb04e7a82010-08-24 21:05:24 +0000406 if (m_variable_list_sp.get())
Jim Ingham7382a532010-08-18 19:29:16 +0000407 {
408 variable_list_sp.reset(new VariableList());
409 if (variable_list_sp.get())
Greg Claytonb04e7a82010-08-24 21:05:24 +0000410 variable_list_sp->AddVariables(m_variable_list_sp.get());
Jim Ingham7382a532010-08-18 19:29:16 +0000411
412 if (get_child_variables)
413 {
Greg Clayton69aa5d92010-09-07 04:20:48 +0000414 for (Block *child_block = GetFirstChild();
415 child_block != NULL;
416 child_block = child_block->GetSibling())
417 {
418 if (child_block->GetInlinedFunctionInfo() == NULL)
419 {
420 VariableListSP child_block_variable_list(child_block->GetVariableList(get_child_variables, can_create));
421 if (child_block_variable_list.get())
422 variable_list_sp->AddVariables(child_block_variable_list.get());
423 }
424
Jim Ingham7382a532010-08-18 19:29:16 +0000425 }
426 }
427 }
428
429 return variable_list_sp;
430}
431
432uint32_t
Greg Clayton33ed1702010-08-24 00:45:41 +0000433Block::AppendVariables
434(
435 bool can_create,
436 bool get_parent_variables,
437 bool stop_if_block_is_inlined_function,
438 VariableList *variable_list
439)
Jim Ingham7382a532010-08-18 19:29:16 +0000440{
441 uint32_t num_variables_added = 0;
442 VariableListSP variable_list_sp(GetVariableList(false, can_create));
443
Greg Clayton69aa5d92010-09-07 04:20:48 +0000444 bool is_inlined_function = GetInlinedFunctionInfo() != NULL;
Jim Ingham7382a532010-08-18 19:29:16 +0000445 if (variable_list_sp.get())
446 {
447 num_variables_added = variable_list_sp->GetSize();
448 variable_list->AddVariables(variable_list_sp.get());
449 }
Greg Clayton33ed1702010-08-24 00:45:41 +0000450
Jim Ingham7382a532010-08-18 19:29:16 +0000451 if (get_parent_variables)
452 {
Greg Clayton33ed1702010-08-24 00:45:41 +0000453 if (stop_if_block_is_inlined_function && is_inlined_function)
454 return num_variables_added;
455
Jim Ingham7382a532010-08-18 19:29:16 +0000456 Block* parent_block = GetParent();
457 if (parent_block)
Greg Clayton33ed1702010-08-24 00:45:41 +0000458 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 +0000459 }
460 return num_variables_added;
461}
462
Chris Lattner24943d22010-06-08 16:52:24 +0000463void
Greg Clayton75ccf502010-08-21 02:22:51 +0000464Block::SetBlockInfoHasBeenParsed (bool b, bool set_children)
Chris Lattner24943d22010-06-08 16:52:24 +0000465{
Greg Clayton75ccf502010-08-21 02:22:51 +0000466 m_parsed_block_info = b;
467 if (set_children)
Chris Lattner24943d22010-06-08 16:52:24 +0000468 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000469 m_parsed_child_blocks = true;
470 for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling())
471 child_block->SetBlockInfoHasBeenParsed (b, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000472 }
Chris Lattner24943d22010-06-08 16:52:24 +0000473}