blob: eca278e0ac89eb13f848f9785c04aee85c65040a [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- SymbolContext.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/SymbolContext.h"
Greg Clayton12bec712010-06-28 21:30:43 +000011
Chris Lattner24943d22010-06-08 16:52:24 +000012#include "lldb/Core/Module.h"
Greg Clayton12bec712010-06-28 21:30:43 +000013#include "lldb/Symbol/CompileUnit.h"
Chris Lattner24943d22010-06-08 16:52:24 +000014#include "lldb/Symbol/ObjectFile.h"
15#include "lldb/Symbol/Symbol.h"
Chris Lattner24943d22010-06-08 16:52:24 +000016#include "lldb/Symbol/SymbolVendor.h"
Greg Clayton12bec712010-06-28 21:30:43 +000017#include "lldb/Target/Target.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018
19using namespace lldb;
20using namespace lldb_private;
21
22SymbolContext::SymbolContext() :
23 target_sp (),
24 module_sp (),
25 comp_unit (NULL),
26 function (NULL),
27 block (NULL),
28 line_entry (),
29 symbol (NULL)
30{
31}
32
33SymbolContext::SymbolContext(const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
34 target_sp (),
35 module_sp (m),
36 comp_unit (cu),
37 function (f),
38 block (b),
39 line_entry (),
40 symbol (s)
41{
42 if (le)
43 line_entry = *le;
44}
45
46SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
47 target_sp (t),
48 module_sp (m),
49 comp_unit (cu),
50 function (f),
51 block (b),
52 line_entry (),
53 symbol (s)
54{
55 if (le)
56 line_entry = *le;
57}
58
59SymbolContext::SymbolContext(const SymbolContext& rhs) :
60 target_sp (rhs.target_sp),
61 module_sp (rhs.module_sp),
62 comp_unit (rhs.comp_unit),
63 function (rhs.function),
64 block (rhs.block),
65 line_entry (rhs.line_entry),
66 symbol (rhs.symbol)
67{
68}
69
70
71SymbolContext::SymbolContext (SymbolContextScope *sc_scope) :
72 target_sp (),
73 module_sp (),
74 comp_unit (NULL),
75 function (NULL),
76 block (NULL),
77 line_entry (),
78 symbol (NULL)
79{
80 sc_scope->CalculateSymbolContext (this);
81}
82
83const SymbolContext&
84SymbolContext::operator= (const SymbolContext& rhs)
85{
86 if (this != &rhs)
87 {
88 target_sp = rhs.target_sp;
89 module_sp = rhs.module_sp;
90 comp_unit = rhs.comp_unit;
91 function = rhs.function;
92 block = rhs.block;
93 line_entry = rhs.line_entry;
94 symbol = rhs.symbol;
95 }
96 return *this;
97}
98
99void
100SymbolContext::Clear()
101{
102 target_sp.reset();
103 module_sp.reset();
104 comp_unit = NULL;
105 function = NULL;
106 block = NULL;
107 line_entry.Clear();
108 symbol = NULL;
109}
110
111void
112SymbolContext::DumpStopContext
113(
114 Stream *s,
115 ExecutionContextScope *exe_scope,
116 const Address &addr,
117 bool show_module
118) const
119{
120 Process *process = NULL;
121 if (exe_scope)
122 process = exe_scope->CalculateProcess();
123 addr_t load_addr = addr.GetLoadAddress (process);
124
125 if (show_module && module_sp)
126 {
127 *s << module_sp->GetFileSpec().GetFilename() << '`';
128 }
129
130 if (function != NULL)
131 {
132 if (function->GetMangled().GetName())
133 function->GetMangled().GetName().Dump(s);
134
135 const addr_t func_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(process);
136 if (load_addr > func_load_addr)
137 s->Printf(" + %llu", load_addr - func_load_addr);
138
139 if (block != NULL)
140 {
141 s->IndentMore();
142 block->DumpStopContext(s, this);
143 s->IndentLess();
144 }
145 else
146 {
147 if (line_entry.IsValid())
148 {
149 s->PutCString(" at ");
150 if (line_entry.DumpStopContext(s))
151 return;
152 }
153 }
154 }
155 else if (symbol != NULL)
156 {
157 symbol->GetMangled().GetName().Dump(s);
158
159 if (symbol->GetAddressRangePtr())
160 {
161 const addr_t sym_load_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetLoadAddress(process);
162 if (load_addr > sym_load_addr)
163 s->Printf(" + %llu", load_addr - sym_load_addr);
164 }
165 }
166 else
167 {
168 addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress);
169 }
170}
171
172void
Greg Clayton12bec712010-06-28 21:30:43 +0000173SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Process *process) const
174{
175 if (module_sp)
176 {
177 s->Indent(" Module: \"");
178 module_sp->GetFileSpec().Dump(s);
179 s->PutChar('"');
180 s->EOL();
181 }
182
183 if (comp_unit != NULL)
184 {
185 s->Indent("CompileUnit: ");
186 comp_unit->GetDescription (s, level);
187 s->EOL();
188 }
189
190 if (function != NULL)
191 {
192 s->Indent(" Function: ");
193 function->GetDescription (s, level, process);
194 s->EOL();
195
196 Type *func_type = function->GetType();
197 if (func_type)
198 {
199 s->Indent(" FuncType: ");
200 func_type->GetDescription (s, level, false);
201 s->EOL();
202 }
203 }
204
205 if (block != NULL)
206 {
207 std::vector<Block *> blocks;
208 blocks.push_back (block);
209 Block *parent_block = block->GetParent();
210
211 while (parent_block)
212 {
213 blocks.push_back (parent_block);
214 parent_block = parent_block->GetParent();
215 }
216 std::vector<Block *>::reverse_iterator pos;
217 std::vector<Block *>::reverse_iterator begin = blocks.rbegin();
218 std::vector<Block *>::reverse_iterator end = blocks.rend();
219 for (pos = begin; pos != end; ++pos)
220 {
221 if (pos == begin)
222 s->Indent(" Blocks: ");
223 else
224 s->Indent(" ");
225 (*pos)->GetDescription(s, level, process);
226 s->EOL();
227 }
228 }
229
230 if (line_entry.IsValid())
231 {
232 s->Indent(" LineEntry: ");
233 line_entry.GetDescription (s, level, comp_unit, process, false);
234 s->EOL();
235 }
236
237 if (symbol != NULL)
238 {
239 s->Indent(" Symbol: ");
240 symbol->GetDescription(s, level, process);
241 s->EOL();
242 }
243}
244
245
246
247void
Chris Lattner24943d22010-06-08 16:52:24 +0000248SymbolContext::Dump(Stream *s, Process *process) const
249{
250 *s << (void *)this << ": ";
251 s->Indent();
252 s->PutCString("SymbolContext");
253 s->IndentMore();
254 s->EOL();
255 s->IndentMore();
256 s->Indent();
Greg Clayton12bec712010-06-28 21:30:43 +0000257 *s << "Module = " << (void *)module_sp.get() << ' ';
Chris Lattner24943d22010-06-08 16:52:24 +0000258 if (module_sp)
259 module_sp->GetFileSpec().Dump(s);
260 s->EOL();
261 s->Indent();
262 *s << "CompileUnit = " << (void *)comp_unit;
263 if (comp_unit != NULL)
Greg Clayton12bec712010-06-28 21:30:43 +0000264 *s << " {0x" << comp_unit->GetID() << "} " << *(dynamic_cast<FileSpec*> (comp_unit));
Chris Lattner24943d22010-06-08 16:52:24 +0000265 s->EOL();
266 s->Indent();
Greg Clayton12bec712010-06-28 21:30:43 +0000267 *s << "Function = " << (void *)function;
Chris Lattner24943d22010-06-08 16:52:24 +0000268 if (function != NULL)
269 {
Greg Clayton12bec712010-06-28 21:30:43 +0000270 *s << " {0x" << function->GetID() << "} " << function->GetType()->GetName() << ", address-range = ";
271 function->GetAddressRange().Dump(s, process, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
272 s->EOL();
273 s->Indent();
274 Type* func_type = function->GetType();
275 if (func_type)
276 {
277 *s << " Type = ";
278 func_type->Dump (s, false);
279 }
Chris Lattner24943d22010-06-08 16:52:24 +0000280 }
281 s->EOL();
282 s->Indent();
Greg Clayton12bec712010-06-28 21:30:43 +0000283 *s << "Block = " << (void *)block;
Chris Lattner24943d22010-06-08 16:52:24 +0000284 if (block != NULL)
Greg Clayton12bec712010-06-28 21:30:43 +0000285 *s << " {0x" << block->GetID() << '}';
Chris Lattner24943d22010-06-08 16:52:24 +0000286 // Dump the block and pass it a negative depth to we print all the parent blocks
287 //if (block != NULL)
288 // block->Dump(s, function->GetFileAddress(), INT_MIN);
289 s->EOL();
290 s->Indent();
Greg Clayton12bec712010-06-28 21:30:43 +0000291 *s << "LineEntry = ";
Chris Lattner24943d22010-06-08 16:52:24 +0000292 line_entry.Dump (s, process, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true);
293 s->EOL();
294 s->Indent();
Greg Clayton12bec712010-06-28 21:30:43 +0000295 *s << "Symbol = " << (void *)symbol;
Chris Lattner24943d22010-06-08 16:52:24 +0000296 if (symbol != NULL && symbol->GetMangled())
297 *s << ' ' << symbol->GetMangled().GetName().AsCString();
298 s->EOL();
299 s->IndentLess();
300 s->IndentLess();
301}
302
303bool
304lldb_private::operator== (const SymbolContext& lhs, const SymbolContext& rhs)
305{
306 return lhs.target_sp.get() == rhs.target_sp.get() &&
307 lhs.module_sp.get() == rhs.module_sp.get() &&
308 lhs.comp_unit == rhs.comp_unit &&
309 lhs.function == rhs.function &&
310 LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0 &&
311 lhs.symbol == rhs.symbol;
312}
313
314bool
315lldb_private::operator!= (const SymbolContext& lhs, const SymbolContext& rhs)
316{
317 return lhs.target_sp.get() != rhs.target_sp.get() ||
318 lhs.module_sp.get() != rhs.module_sp.get() ||
319 lhs.comp_unit != rhs.comp_unit ||
320 lhs.function != rhs.function ||
321 LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0 ||
322 lhs.symbol != rhs.symbol;
323}
324
325bool
326SymbolContext::GetAddressRange (uint32_t scope, AddressRange &range) const
327{
328 if ((scope & eSymbolContextLineEntry) && line_entry.IsValid())
329 {
330 range = line_entry.range;
331 return true;
332 }
333 else if ((scope & eSymbolContextFunction) && function != NULL)
334 {
335 range = function->GetAddressRange();
336 return true;
337 }
338 else if ((scope & eSymbolContextSymbol) && symbol != NULL && symbol->GetAddressRangePtr())
339 {
340 range = *symbol->GetAddressRangePtr();
341
342 if (range.GetByteSize() == 0)
343 {
344 if (module_sp)
345 {
346 ObjectFile *objfile = module_sp->GetObjectFile();
347 if (objfile)
348 {
349 Symtab *symtab = objfile->GetSymtab();
350 if (symtab)
351 range.SetByteSize(symtab->CalculateSymbolSize (symbol));
352 }
353 }
354 }
355 return true;
356 }
357 range.Clear();
358 return false;
359}
360
361
362Function *
363SymbolContext::FindFunctionByName (const char *name) const
364{
365 ConstString name_const_str (name);
366 if (function != NULL)
367 {
368 // FIXME: Look in the class of the current function, if it exists,
369 // for methods matching name.
370 }
371
372 //
373 if (comp_unit != NULL)
374 {
375 // Make sure we've read in all the functions. We should be able to check and see
376 // if there's one by this name present before we do this...
377 module_sp->GetSymbolVendor()->ParseCompileUnitFunctions(*this);
378 uint32_t func_idx;
379 lldb::FunctionSP func_sp;
380 for (func_idx = 0; (func_sp = comp_unit->GetFunctionAtIndex(func_idx)) != NULL; ++func_idx)
381 {
382 if (func_sp->GetMangled().GetName() == name_const_str)
383 return func_sp.get();
384 }
385 }
386 if (module_sp != NULL)
387 {
388 SymbolContextList sc_matches;
Greg Clayton12bec712010-06-28 21:30:43 +0000389 if (module_sp->FindFunctions (name_const_str, eFunctionNameTypeBase | eFunctionNameTypeFull, false, sc_matches) > 0)
Chris Lattner24943d22010-06-08 16:52:24 +0000390 {
391 SymbolContext sc;
392 sc_matches.GetContextAtIndex (0, sc);
393 return sc.function;
394 }
395 }
396
397 if (target_sp)
398 {
399 SymbolContextList sc_matches;
Greg Clayton12bec712010-06-28 21:30:43 +0000400 if (target_sp->GetImages().FindFunctions (name_const_str, eFunctionNameTypeBase | eFunctionNameTypeFull, sc_matches) > 0)
Chris Lattner24943d22010-06-08 16:52:24 +0000401 {
402 SymbolContext sc;
403 sc_matches.GetContextAtIndex (0, sc);
404 return sc.function;
405 }
406 }
407
408 return NULL;
409}
410
411lldb::VariableSP
412SymbolContext::FindVariableByName (const char *name) const
413{
414 lldb::VariableSP return_value;
415 return return_value;
416}
417
418lldb::TypeSP
419SymbolContext::FindTypeByName (const char *name) const
420{
421 lldb::TypeSP return_value;
422 return return_value;
423}
424
425//----------------------------------------------------------------------
426//
427// SymbolContextList
428//
429//----------------------------------------------------------------------
430
431
432SymbolContextList::SymbolContextList() :
433 m_symbol_contexts()
434{
435}
436
437SymbolContextList::~SymbolContextList()
438{
439}
440
441void
442SymbolContextList::Append(const SymbolContext& sc)
443{
444 m_symbol_contexts.push_back(sc);
445}
446
447void
448SymbolContextList::Clear()
449{
450 m_symbol_contexts.clear();
451}
452
453void
454SymbolContextList::Dump(Stream *s, Process *process) const
455{
456
457 *s << (void *)this << ": ";
458 s->Indent();
459 s->PutCString("SymbolContextList");
460 s->EOL();
461 s->IndentMore();
462
463 collection::const_iterator pos, end = m_symbol_contexts.end();
464 for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
465 {
466 pos->Dump(s, process);
467 }
468 s->IndentLess();
469}
470
471bool
472SymbolContextList::GetContextAtIndex(uint32_t idx, SymbolContext& sc) const
473{
474 if (idx < m_symbol_contexts.size())
475 {
476 sc = m_symbol_contexts[idx];
477 return true;
478 }
479 return false;
480}
481
482bool
483SymbolContextList::RemoveContextAtIndex (uint32_t idx)
484{
485 if (idx < m_symbol_contexts.size())
486 {
487 m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
488 return true;
489 }
490 return false;
491}
492
493uint32_t
494SymbolContextList::GetSize() const
495{
496 return m_symbol_contexts.size();
497}