1 //===-- StackFrame.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/Target/StackFrame.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/Disassembler.h"
18 #include "lldb/Core/Value.h"
19 #include "lldb/Symbol/Function.h"
20 #include "lldb/Target/ExecutionContext.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/RegisterContext.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/Thread.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 // The first bits in the flags are reserved for the SymbolContext::Scope bits
30 // so we know if we have tried to look up information in our internal symbol
31 // context (m_sc) already.
32 #define RESOLVED_PC_SO_ADDR (uint32_t(eSymbolContextEverything + 1))
33 #define RESOLVED_FRAME_ID   (RESOLVED_PC_SO_ADDR << 1)
34 #define GOT_FRAME_BASE      (RESOLVED_FRAME_ID << 1)
35 #define FRAME_IS_OBSOLETE   (GOT_FRAME_BASE << 1)
36 #define RESOLVED_VARIABLES  (FRAME_IS_OBSOLETE << 1)
37 
38 StackFrame::StackFrame
39 (
40     lldb::user_id_t frame_idx,
41     lldb::user_id_t concrete_frame_index,
42     Thread &thread,
43     lldb::addr_t cfa,
44     uint32_t inline_height,
45     lldb::addr_t pc,
46     const SymbolContext *sc_ptr
47 ) :
48     m_frame_index (frame_idx),
49     m_concrete_frame_index (concrete_frame_index),
50     m_thread (thread),
51     m_reg_context_sp (),
52     m_id (cfa, inline_height),
53     m_pc (NULL, pc),
54     m_sc (),
55     m_flags (),
56     m_frame_base (),
57     m_frame_base_error (),
58     m_variable_list_sp (),
59     m_value_object_list ()
60 {
61     if (sc_ptr != NULL)
62     {
63         m_sc = *sc_ptr;
64         m_flags.Set(m_sc.GetResolvedMask ());
65     }
66 }
67 
68 StackFrame::StackFrame
69 (
70     lldb::user_id_t frame_idx,
71     lldb::user_id_t concrete_frame_index,
72     Thread &thread,
73     const RegisterContextSP &reg_context_sp,
74     lldb::addr_t cfa,
75     uint32_t inline_height,
76     lldb::addr_t pc,
77     const SymbolContext *sc_ptr
78 ) :
79     m_frame_index (frame_idx),
80     m_concrete_frame_index (concrete_frame_index),
81     m_thread (thread),
82     m_reg_context_sp (reg_context_sp),
83     m_id (cfa, inline_height),
84     m_pc (NULL, pc),
85     m_sc (),
86     m_flags (),
87     m_frame_base (),
88     m_frame_base_error (),
89     m_variable_list_sp (),
90     m_value_object_list ()
91 {
92     if (sc_ptr != NULL)
93     {
94         m_sc = *sc_ptr;
95         m_flags.Set(m_sc.GetResolvedMask ());
96     }
97 
98     if (reg_context_sp && !m_sc.target_sp)
99     {
100         m_sc.target_sp = reg_context_sp->GetThread().GetProcess().GetTarget().GetSP();
101         m_flags.Set (eSymbolContextTarget);
102     }
103 }
104 
105 StackFrame::StackFrame
106 (
107     lldb::user_id_t frame_idx,
108     lldb::user_id_t concrete_frame_index,
109     Thread &thread,
110     const RegisterContextSP &reg_context_sp,
111     lldb::addr_t cfa,
112     uint32_t inline_height,
113     const Address& pc_addr,
114     const SymbolContext *sc_ptr
115 ) :
116     m_frame_index (frame_idx),
117     m_concrete_frame_index (concrete_frame_index),
118     m_thread (thread),
119     m_reg_context_sp (reg_context_sp),
120     m_id (cfa, inline_height),
121     m_pc (pc_addr),
122     m_sc (),
123     m_flags (),
124     m_frame_base (),
125     m_frame_base_error (),
126     m_variable_list_sp (),
127     m_value_object_list ()
128 {
129     if (sc_ptr != NULL)
130     {
131         m_sc = *sc_ptr;
132         m_flags.Set(m_sc.GetResolvedMask ());
133     }
134 
135     if (m_sc.target_sp.get() == NULL && reg_context_sp)
136     {
137         m_sc.target_sp = reg_context_sp->GetThread().GetProcess().GetTarget().GetSP();
138         m_flags.Set (eSymbolContextTarget);
139     }
140 
141     if (m_sc.module_sp.get() == NULL && pc_addr.GetSection())
142     {
143         Module *pc_module = pc_addr.GetSection()->GetModule();
144         if (pc_module)
145         {
146             m_sc.module_sp = pc_module->GetSP();
147             m_flags.Set (eSymbolContextModule);
148         }
149     }
150 }
151 
152 
153 //----------------------------------------------------------------------
154 // Destructor
155 //----------------------------------------------------------------------
156 StackFrame::~StackFrame()
157 {
158 }
159 
160 StackID&
161 StackFrame::GetStackID()
162 {
163     // Make sure we have resolved our stack ID's address range before we give
164     // it out to any external clients
165     if (m_id.GetStartAddress().IsValid() == 0 && m_flags.IsClear(RESOLVED_FRAME_ID))
166     {
167         m_flags.Set (RESOLVED_FRAME_ID);
168 
169         // Resolve our PC to section offset if we haven't alreday done so
170         // and if we don't have a module. The resolved address section will
171         // contain the module to which it belongs.
172         if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_PC_SO_ADDR))
173             GetPC();
174 
175         const uint32_t resolve_scope = eSymbolContextModule |
176                                        eSymbolContextCompUnit |
177                                        eSymbolContextFunction;
178 
179         if (m_sc.module_sp)
180         {
181             if (m_sc.module_sp->ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextFunction)
182             {
183                 assert (m_sc.function);
184                 m_id.SetStartAddress(m_sc.function->GetAddressRange().GetBaseAddress());
185             }
186             else if (m_sc.module_sp->ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextSymbol)
187             {
188                 assert (m_sc.symbol);
189                 AddressRange *symbol_range_ptr = m_sc.symbol->GetAddressRangePtr();
190                 if (symbol_range_ptr)
191                     m_id.SetStartAddress(symbol_range_ptr->GetBaseAddress());
192             }
193         }
194 //      else if (m_sc.target != NULL)
195 //      {
196 //          if (m_sc.target->GetImages().ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextFunction)
197 //          {
198 //              assert (m_sc.function);
199 //              m_id.GetAddressRange() = m_sc.function->GetAddressRange();
200 //          }
201 //          else if (m_sc.target->GetImages().ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextSymbol)
202 //          {
203 //              assert (m_sc.symbol);
204 //              AddressRange *symbol_range_ptr = m_sc.symbol->GetAddressRange();
205 //              if (symbol_range_ptr)
206 //                  m_id.GetAddressRange() = *symbol_range_ptr;
207 //          }
208 //      }
209     }
210     return m_id;
211 }
212 
213 Address&
214 StackFrame::GetPC()
215 {
216     if (m_flags.IsClear(RESOLVED_PC_SO_ADDR) && !m_pc.IsSectionOffset())
217     {
218         m_flags.Set (RESOLVED_PC_SO_ADDR);
219 
220         // Resolve the PC into a temporary address because if ResolveLoadAddress
221         // fails to resolve the address, it will clear the address object...
222         Address resolved_pc;
223         if (m_thread.GetProcess().ResolveLoadAddress(m_pc.GetOffset(), resolved_pc))
224         {
225             m_pc = resolved_pc;
226             const Section *section = m_pc.GetSection();
227             if (section)
228             {
229                 Module *module = section->GetModule();
230                 if (module)
231                 {
232                     m_sc.module_sp = module->GetSP();
233                     if (m_sc.module_sp)
234                         m_flags.Set(eSymbolContextModule);
235                 }
236             }
237         }
238     }
239     return m_pc;
240 }
241 
242 void
243 StackFrame::ChangePC (addr_t pc)
244 {
245     m_pc.SetOffset(pc);
246     m_pc.SetSection(NULL);
247     m_sc.Clear();
248     m_flags.SetAllFlagBits(0);
249     m_thread.ClearStackFrames ();
250 }
251 
252 const char *
253 StackFrame::Disassemble ()
254 {
255     if (m_disassembly.GetSize() == 0)
256     {
257         ExecutionContext exe_ctx;
258         Calculate(exe_ctx);
259         Target &target = m_thread.GetProcess().GetTarget();
260         Disassembler::Disassemble (target.GetDebugger(),
261                                    target.GetArchitecture(),
262                                    exe_ctx,
263                                    0,
264                                    false,
265                                    m_disassembly);
266         if (m_disassembly.GetSize() == 0)
267             return NULL;
268     }
269     return m_disassembly.GetData();
270 }
271 
272 //----------------------------------------------------------------------
273 // Get the symbol context if we already haven't done so by resolving the
274 // PC address as much as possible. This way when we pass around a
275 // StackFrame object, everyone will have as much information as
276 // possible and no one will ever have to look things up manually.
277 //----------------------------------------------------------------------
278 const SymbolContext&
279 StackFrame::GetSymbolContext (uint32_t resolve_scope)
280 {
281     // Copy our internal symbol context into "sc".
282 
283     if ((m_flags.GetAllFlagBits() & resolve_scope) != resolve_scope)
284     {
285         // Resolve our PC to section offset if we haven't alreday done so
286         // and if we don't have a module. The resolved address section will
287         // contain the module to which it belongs
288         if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_PC_SO_ADDR))
289             GetPC();
290 
291         // If this is not frame zero, then we need to subtract 1 from the PC
292         // value when doing address lookups since the PC will be on the
293         // instruction following the function call instruction...
294 
295         Address lookup_addr(GetPC());
296         if (m_frame_index > 0 && lookup_addr.IsValid())
297         {
298             addr_t offset = lookup_addr.GetOffset();
299             if (offset > 0)
300                 lookup_addr.SetOffset(offset - 1);
301         }
302 
303         if (m_sc.module_sp)
304         {
305             // We have something in our stack frame symbol context, lets check
306             // if we haven't already tried to lookup one of those things. If we
307             // haven't then we will do the query.
308 
309             uint32_t actual_resolve_scope = 0;
310 
311             if (resolve_scope & eSymbolContextCompUnit)
312             {
313                 if (m_flags.IsClear (eSymbolContextCompUnit))
314                 {
315                     if (m_sc.comp_unit)
316                         m_flags.Set (eSymbolContextCompUnit);
317                     else
318                         actual_resolve_scope |= eSymbolContextCompUnit;
319                 }
320             }
321 
322             if (resolve_scope & eSymbolContextFunction)
323             {
324                 if (m_flags.IsClear (eSymbolContextFunction))
325                 {
326                     if (m_sc.function)
327                         m_flags.Set (eSymbolContextFunction);
328                     else
329                         actual_resolve_scope |= eSymbolContextFunction;
330                 }
331             }
332 
333             if (resolve_scope & eSymbolContextBlock)
334             {
335                 if (m_flags.IsClear (eSymbolContextBlock))
336                 {
337                     if (m_sc.block)
338                         m_flags.Set (eSymbolContextBlock);
339                     else
340                         actual_resolve_scope |= eSymbolContextBlock;
341                 }
342             }
343 
344             if (resolve_scope & eSymbolContextSymbol)
345             {
346                 if (m_flags.IsClear (eSymbolContextSymbol))
347                 {
348                     if (m_sc.symbol)
349                         m_flags.Set (eSymbolContextSymbol);
350                     else
351                         actual_resolve_scope |= eSymbolContextSymbol;
352                 }
353             }
354 
355             if (resolve_scope & eSymbolContextLineEntry)
356             {
357                 if (m_flags.IsClear (eSymbolContextLineEntry))
358                 {
359                     if (m_sc.line_entry.IsValid())
360                         m_flags.Set (eSymbolContextLineEntry);
361                     else
362                         actual_resolve_scope |= eSymbolContextLineEntry;
363                 }
364             }
365 
366             if (actual_resolve_scope)
367             {
368                 // We might be resolving less information than what is already
369                 // in our current symbol context so resolve into a temporary
370                 // symbol context "sc" so we don't clear out data we have
371                 // already found in "m_sc"
372                 SymbolContext sc;
373                 // Set flags that indicate what we have tried to resolve
374                 const uint32_t resolved = m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, actual_resolve_scope, sc);
375                 // Only replace what we didn't already have as we may have
376                 // information for an inlined function scope that won't match
377                 // what a standard lookup by address would match
378                 if (resolved & eSymbolContextCompUnit)  m_sc.comp_unit  = sc.comp_unit;
379                 if (resolved & eSymbolContextFunction)  m_sc.function   = sc.function;
380                 if (resolved & eSymbolContextBlock)     m_sc.block      = sc.block;
381                 if (resolved & eSymbolContextSymbol)    m_sc.symbol     = sc.symbol;
382                 if (resolved & eSymbolContextLineEntry) m_sc.line_entry = sc.line_entry;
383             }
384         }
385         else
386         {
387             // If we don't have a module, then we can't have the compile unit,
388             // function, block, line entry or symbol, so we can safely call
389             // ResolveSymbolContextForAddress with our symbol context member m_sc.
390             m_thread.GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (lookup_addr, resolve_scope, m_sc);
391         }
392 
393         // If the target was requested add that:
394         if (m_sc.target_sp.get() == NULL)
395             m_sc.target_sp = CalculateProcess()->GetTarget().GetSP();
396 
397         // Update our internal flags so we remember what we have tried to locate so
398         // we don't have to keep trying when more calls to this function are made.
399         m_flags.Set(resolve_scope);
400     }
401 
402     // Return the symbol context with everything that was possible to resolve
403     // resolved.
404     return m_sc;
405 }
406 
407 
408 VariableList *
409 StackFrame::GetVariableList ()
410 {
411     if (m_flags.IsClear(RESOLVED_VARIABLES))
412     {
413         m_flags.Set(RESOLVED_VARIABLES);
414 
415         GetSymbolContext(eSymbolContextFunction);
416         if (m_sc.function)
417         {
418             bool get_child_variables = true;
419             bool can_create = true;
420             m_variable_list_sp = m_sc.function->GetBlock (can_create).GetVariableList (get_child_variables, can_create);
421         }
422     }
423     return m_variable_list_sp.get();
424 }
425 
426 
427 bool
428 StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
429 {
430     if (m_flags.IsClear(GOT_FRAME_BASE))
431     {
432         if (m_sc.function)
433         {
434             m_frame_base.Clear();
435             m_frame_base_error.Clear();
436 
437             m_flags.Set(GOT_FRAME_BASE);
438             ExecutionContext exe_ctx (&m_thread.GetProcess(), &m_thread, this);
439             Value expr_value;
440             if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, NULL, expr_value, &m_frame_base_error) < 0)
441             {
442                 // We should really have an error if evaluate returns, but in case
443                 // we don't, lets set the error to something at least.
444                 if (m_frame_base_error.Success())
445                     m_frame_base_error.SetErrorString("Evaluation of the frame base expression failed.");
446             }
447             else
448             {
449                 m_frame_base = expr_value.ResolveValue(&exe_ctx, NULL);
450             }
451         }
452         else
453         {
454             m_frame_base_error.SetErrorString ("No function in symbol context.");
455         }
456     }
457 
458     if (m_frame_base_error.Success())
459         frame_base = m_frame_base;
460 
461     if (error_ptr)
462         *error_ptr = m_frame_base_error;
463     return m_frame_base_error.Success();
464 }
465 
466 RegisterContext *
467 StackFrame::GetRegisterContext ()
468 {
469     if (m_reg_context_sp.get() == NULL)
470         m_reg_context_sp.reset (m_thread.CreateRegisterContextForFrame (this));
471     return m_reg_context_sp.get();
472 }
473 
474 bool
475 StackFrame::HasDebugInformation ()
476 {
477     GetSymbolContext(eSymbolContextLineEntry);
478     return m_sc.line_entry.IsValid();
479 }
480 
481 ValueObjectList &
482 StackFrame::GetValueObjectList()
483 {
484     return m_value_object_list;
485 }
486 
487 
488 Target *
489 StackFrame::CalculateTarget ()
490 {
491     return m_thread.CalculateTarget();
492 }
493 
494 Process *
495 StackFrame::CalculateProcess ()
496 {
497     return m_thread.CalculateProcess();
498 }
499 
500 Thread *
501 StackFrame::CalculateThread ()
502 {
503     return &m_thread;
504 }
505 
506 StackFrame *
507 StackFrame::CalculateStackFrame ()
508 {
509     return this;
510 }
511 
512 
513 void
514 StackFrame::Calculate (ExecutionContext &exe_ctx)
515 {
516     m_thread.Calculate (exe_ctx);
517     exe_ctx.frame = this;
518 }
519 
520 void
521 StackFrame::Dump (Stream *strm, bool show_frame_index)
522 {
523     if (strm == NULL)
524         return;
525 
526     if (show_frame_index)
527         strm->Printf("frame #%u: ", m_frame_index);
528     strm->Printf("pc = 0x%0*llx", m_thread.GetProcess().GetAddressByteSize() * 2, GetRegisterContext()->GetPC());
529     SymbolContext sc (GetSymbolContext(eSymbolContextEverything));
530     strm->PutCString(", where = ");
531     // TODO: need to get the
532     const bool show_module = true;
533     const bool show_inline = true;
534     sc.DumpStopContext(strm, &m_thread.GetProcess(), GetPC(), show_module, show_inline);
535 }
536 
537