blob: 8256aa7e19909bb4c083552f95cac99528fe3959 [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 (),
27 m_variables (),
28 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
107 if (m_variables.get())
108 {
109 m_variables->Dump(s, show_context);
110 }
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
140Block::CalculateSymbolContext(SymbolContext* sc)
141{
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
148Block::DumpStopContext (Stream *s, const SymbolContext *sc)
149{
Greg Clayton12bec712010-06-28 21:30:43 +0000150 Block* parent_block = GetParent();
Chris Lattner24943d22010-06-08 16:52:24 +0000151
152 InlineFunctionInfo* inline_info = InlinedFunctionInfo ();
153 if (inline_info)
154 {
155 const Declaration &call_site = inline_info->GetCallSite();
156 if (sc)
157 {
158 // First frame, dump the first inline call site
159// if (call_site.IsValid())
160// {
161// s->PutCString(" at ");
162// call_site.DumpStopContext (s);
163// }
164 s->PutCString (" [inlined]");
165 }
166 s->EOL();
167 inline_info->DumpStopContext (s);
168 if (sc == NULL)
169 {
170 if (call_site.IsValid())
171 {
172 s->PutCString(" at ");
173 call_site.DumpStopContext (s);
174 }
175 }
176 }
177
178 if (sc)
179 {
180 // If we have any inlined functions, this will be the deepest most
181 // inlined location
182 if (sc->line_entry.IsValid())
183 {
184 s->PutCString(" at ");
185 sc->line_entry.DumpStopContext (s);
186 }
187 }
188 if (parent_block)
189 parent_block->Block::DumpStopContext (s, NULL);
190}
191
192
193void
194Block::DumpSymbolContext(Stream *s)
195{
Greg Clayton75ccf502010-08-21 02:22:51 +0000196 SymbolContext sc;
197 CalculateSymbolContext(&sc);
198 if (sc.function)
199 sc.function->DumpSymbolContext(s);
Chris Lattner24943d22010-06-08 16:52:24 +0000200 s->Printf(", Block{0x%8.8x}", GetID());
201}
202
203bool
204Block::Contains (addr_t range_offset) const
205{
206 return VMRange::ContainsValue(m_ranges, range_offset);
207}
208
209bool
210Block::Contains (const VMRange& range) const
211{
212 return VMRange::ContainsRange(m_ranges, range);
213}
214
Greg Clayton75ccf502010-08-21 02:22:51 +0000215Block *
216Block::GetParent () const
Chris Lattner24943d22010-06-08 16:52:24 +0000217{
Greg Clayton75ccf502010-08-21 02:22:51 +0000218 if (m_parent_scope)
Chris Lattner24943d22010-06-08 16:52:24 +0000219 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000220 SymbolContext sc;
221 m_parent_scope->CalculateSymbolContext(&sc);
222 if (sc.block)
223 return sc.block;
Chris Lattner24943d22010-06-08 16:52:24 +0000224 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000225 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000226}
227
Greg Clayton33ed1702010-08-24 00:45:41 +0000228Block *
229Block::GetInlinedParent () const
230{
231 Block *parent_block = GetParent ();
232 if (parent_block)
233 {
234 if (parent_block->InlinedFunctionInfo())
235 return parent_block;
236 else
237 return parent_block->GetInlinedParent();
238 }
239 return NULL;
240}
241
242
243bool
244Block::GetRangeContainingAddress (const Address& addr, AddressRange &range)
245{
246 SymbolContext sc;
247 CalculateSymbolContext(&sc);
248 if (sc.function)
249 {
250 const AddressRange &func_range = sc.function->GetAddressRange();
251 if (addr.GetSection() == func_range.GetBaseAddress().GetSection())
252 {
253 const addr_t addr_offset = addr.GetOffset();
254 const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
255 if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize())
256 {
257 addr_t offset = addr_offset - func_offset;
258
259 uint32_t range_idx = VMRange::FindRangeIndexThatContainsValue (m_ranges, offset);
260 if (range_idx < m_ranges.size())
261 {
262 range.GetBaseAddress() = func_range.GetBaseAddress();
263 range.GetBaseAddress().SetOffset(func_offset + m_ranges[range_idx].GetBaseAddress());
264 range.SetByteSize(m_ranges[range_idx].GetByteSize());
265 return true;
266 }
267 }
268 }
269 }
270 range.Clear();
271 return false;
272}
273
Chris Lattner24943d22010-06-08 16:52:24 +0000274void
275Block::AddRange(addr_t start_offset, addr_t end_offset)
276{
277 m_ranges.resize(m_ranges.size()+1);
278 m_ranges.back().Reset(start_offset, end_offset);
279}
280
281InlineFunctionInfo*
282Block::InlinedFunctionInfo ()
283{
284 return m_inlineInfoSP.get();
285}
286
287const InlineFunctionInfo*
288Block::InlinedFunctionInfo () const
289{
290 return m_inlineInfoSP.get();
291}
292
293// Return the current number of bytes that this object occupies in memory
294size_t
295Block::MemorySize() const
296{
297 size_t mem_size = sizeof(Block) + m_ranges.size() * sizeof(VMRange);
298 if (m_inlineInfoSP.get())
299 mem_size += m_inlineInfoSP->MemorySize();
300 if (m_variables.get())
301 mem_size += m_variables->MemorySize();
302 return mem_size;
303
304}
305
Greg Clayton12bec712010-06-28 21:30:43 +0000306Block *
Greg Clayton12bec712010-06-28 21:30:43 +0000307Block::GetFirstChild () const
308{
Greg Clayton75ccf502010-08-21 02:22:51 +0000309 if (m_children.empty())
310 return NULL;
311 return m_children.front().get();
Greg Clayton12bec712010-06-28 21:30:43 +0000312}
313
Greg Clayton75ccf502010-08-21 02:22:51 +0000314void
315Block::AddChild(const BlockSP &child_block_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000316{
Greg Clayton75ccf502010-08-21 02:22:51 +0000317 if (child_block_sp)
318 {
319 Block *block_needs_sibling = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000320
Greg Clayton75ccf502010-08-21 02:22:51 +0000321 if (!m_children.empty())
322 block_needs_sibling = m_children.back().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000323
Greg Clayton75ccf502010-08-21 02:22:51 +0000324 child_block_sp->SetParentScope (this);
325 m_children.push_back (child_block_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000326
Greg Clayton75ccf502010-08-21 02:22:51 +0000327 if (block_needs_sibling)
328 block_needs_sibling->SetSibling (child_block_sp.get());
329 }
Chris Lattner24943d22010-06-08 16:52:24 +0000330}
331
332void
333Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
334{
335 m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
336}
337
Jim Ingham7382a532010-08-18 19:29:16 +0000338
339
340VariableListSP
341Block::GetVariableList (bool get_child_variables, bool can_create)
342{
343 VariableListSP variable_list_sp;
Greg Clayton75ccf502010-08-21 02:22:51 +0000344 if (m_parsed_block_variables == false)
Jim Ingham7382a532010-08-18 19:29:16 +0000345 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000346 if (m_variables.get() == NULL && can_create)
347 {
348 m_parsed_block_variables = true;
349 SymbolContext sc;
350 CalculateSymbolContext(&sc);
351 assert(sc.module_sp);
352 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
353 }
Jim Ingham7382a532010-08-18 19:29:16 +0000354 }
355
356 if (m_variables.get())
357 {
358 variable_list_sp.reset(new VariableList());
359 if (variable_list_sp.get())
360 variable_list_sp->AddVariables(m_variables.get());
361
362 if (get_child_variables)
363 {
364 Block *child_block = GetFirstChild();
365 while (child_block)
366 {
367 VariableListSP child_block_variable_list(child_block->GetVariableList(get_child_variables, can_create));
368 if (child_block_variable_list.get())
369 variable_list_sp->AddVariables(child_block_variable_list.get());
370 child_block = child_block->GetSibling();
371 }
372 }
373 }
374
375 return variable_list_sp;
376}
377
378uint32_t
Greg Clayton33ed1702010-08-24 00:45:41 +0000379Block::AppendVariables
380(
381 bool can_create,
382 bool get_parent_variables,
383 bool stop_if_block_is_inlined_function,
384 VariableList *variable_list
385)
Jim Ingham7382a532010-08-18 19:29:16 +0000386{
387 uint32_t num_variables_added = 0;
388 VariableListSP variable_list_sp(GetVariableList(false, can_create));
389
Greg Clayton33ed1702010-08-24 00:45:41 +0000390 bool is_inlined_function = InlinedFunctionInfo() != NULL;
Jim Ingham7382a532010-08-18 19:29:16 +0000391 if (variable_list_sp.get())
392 {
393 num_variables_added = variable_list_sp->GetSize();
394 variable_list->AddVariables(variable_list_sp.get());
395 }
Greg Clayton33ed1702010-08-24 00:45:41 +0000396
Jim Ingham7382a532010-08-18 19:29:16 +0000397 if (get_parent_variables)
398 {
Greg Clayton33ed1702010-08-24 00:45:41 +0000399 if (stop_if_block_is_inlined_function && is_inlined_function)
400 return num_variables_added;
401
Jim Ingham7382a532010-08-18 19:29:16 +0000402 Block* parent_block = GetParent();
403 if (parent_block)
Greg Clayton33ed1702010-08-24 00:45:41 +0000404 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 +0000405 }
406 return num_variables_added;
407}
408
409
410void
411Block::SetVariableList(VariableListSP& variables)
412{
413 m_variables = variables;
414}
415
Chris Lattner24943d22010-06-08 16:52:24 +0000416void
Greg Clayton75ccf502010-08-21 02:22:51 +0000417Block::SetBlockInfoHasBeenParsed (bool b, bool set_children)
Chris Lattner24943d22010-06-08 16:52:24 +0000418{
Greg Clayton75ccf502010-08-21 02:22:51 +0000419 m_parsed_block_info = b;
420 if (set_children)
Chris Lattner24943d22010-06-08 16:52:24 +0000421 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000422 m_parsed_child_blocks = true;
423 for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling())
424 child_block->SetBlockInfoHasBeenParsed (b, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000425 }
Chris Lattner24943d22010-06-08 16:52:24 +0000426}