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_FRAME_ADDR (uint32_t(eSymbolContextEverything + 1))
33 #define RESOLVED_FRAME_ID   (RESOLVED_FRAME_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_FRAME_ADDR))
173             GetFrameCodeAddress();
174 
175         if (GetSymbolContext (eSymbolContextFunction).function)
176         {
177             m_id.SetStartAddress (m_sc.function->GetAddressRange().GetBaseAddress());
178         }
179         else if (GetSymbolContext (eSymbolContextSymbol).symbol)
180         {
181             AddressRange *symbol_range_ptr = m_sc.symbol->GetAddressRangePtr();
182             if (symbol_range_ptr)
183                 m_id.SetStartAddress(symbol_range_ptr->GetBaseAddress());
184         }
185     }
186     return m_id;
187 }
188 
189 Address&
190 StackFrame::GetFrameCodeAddress()
191 {
192     if (m_flags.IsClear(RESOLVED_FRAME_ADDR) && !m_pc.IsSectionOffset())
193     {
194         m_flags.Set (RESOLVED_FRAME_ADDR);
195 
196         // Resolve the PC into a temporary address because if ResolveLoadAddress
197         // fails to resolve the address, it will clear the address object...
198         Address resolved_pc;
199         if (m_thread.GetProcess().ResolveLoadAddress(m_pc.GetOffset(), resolved_pc))
200         {
201             m_pc = resolved_pc;
202             const Section *section = m_pc.GetSection();
203             if (section)
204             {
205                 Module *module = section->GetModule();
206                 if (module)
207                 {
208                     m_sc.module_sp = module->GetSP();
209                     if (m_sc.module_sp)
210                         m_flags.Set(eSymbolContextModule);
211                 }
212             }
213         }
214     }
215     return m_pc;
216 }
217 
218 void
219 StackFrame::ChangePC (addr_t pc)
220 {
221     m_pc.SetOffset(pc);
222     m_pc.SetSection(NULL);
223     m_sc.Clear();
224     m_flags.SetAllFlagBits(0);
225     m_thread.ClearStackFrames ();
226 }
227 
228 const char *
229 StackFrame::Disassemble ()
230 {
231     if (m_disassembly.GetSize() == 0)
232     {
233         ExecutionContext exe_ctx;
234         Calculate(exe_ctx);
235         Target &target = m_thread.GetProcess().GetTarget();
236         Disassembler::Disassemble (target.GetDebugger(),
237                                    target.GetArchitecture(),
238                                    exe_ctx,
239                                    0,
240                                    false,
241                                    m_disassembly);
242         if (m_disassembly.GetSize() == 0)
243             return NULL;
244     }
245     return m_disassembly.GetData();
246 }
247 
248 //----------------------------------------------------------------------
249 // Get the symbol context if we already haven't done so by resolving the
250 // PC address as much as possible. This way when we pass around a
251 // StackFrame object, everyone will have as much information as
252 // possible and no one will ever have to look things up manually.
253 //----------------------------------------------------------------------
254 const SymbolContext&
255 StackFrame::GetSymbolContext (uint32_t resolve_scope)
256 {
257     // Copy our internal symbol context into "sc".
258     if ((m_flags.GetAllFlagBits() & resolve_scope) != resolve_scope)
259     {
260         // Resolve our PC to section offset if we haven't alreday done so
261         // and if we don't have a module. The resolved address section will
262         // contain the module to which it belongs
263         if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_ADDR))
264             GetFrameCodeAddress();
265 
266         // If this is not frame zero, then we need to subtract 1 from the PC
267         // value when doing address lookups since the PC will be on the
268         // instruction following the function call instruction...
269 
270         Address lookup_addr(GetFrameCodeAddress());
271         if (m_frame_index > 0 && lookup_addr.IsValid())
272         {
273             addr_t offset = lookup_addr.GetOffset();
274             if (offset > 0)
275                 lookup_addr.SetOffset(offset - 1);
276         }
277 
278 
279         uint32_t resolved = 0;
280         if (m_sc.module_sp)
281         {
282             // We have something in our stack frame symbol context, lets check
283             // if we haven't already tried to lookup one of those things. If we
284             // haven't then we will do the query.
285 
286             uint32_t actual_resolve_scope = 0;
287 
288             if (resolve_scope & eSymbolContextCompUnit)
289             {
290                 if (m_flags.IsClear (eSymbolContextCompUnit))
291                 {
292                     if (m_sc.comp_unit)
293                         resolved |= eSymbolContextCompUnit;
294                     else
295                         actual_resolve_scope |= eSymbolContextCompUnit;
296                 }
297             }
298 
299             if (resolve_scope & eSymbolContextFunction)
300             {
301                 if (m_flags.IsClear (eSymbolContextFunction))
302                 {
303                     if (m_sc.function)
304                         resolved |= eSymbolContextFunction;
305                     else
306                         actual_resolve_scope |= eSymbolContextFunction;
307                 }
308             }
309 
310             if (resolve_scope & eSymbolContextBlock)
311             {
312                 if (m_flags.IsClear (eSymbolContextBlock))
313                 {
314                     if (m_sc.block)
315                         resolved |= eSymbolContextBlock;
316                     else
317                         actual_resolve_scope |= eSymbolContextBlock;
318                 }
319             }
320 
321             if (resolve_scope & eSymbolContextSymbol)
322             {
323                 if (m_flags.IsClear (eSymbolContextSymbol))
324                 {
325                     if (m_sc.symbol)
326                         resolved |= eSymbolContextSymbol;
327                     else
328                         actual_resolve_scope |= eSymbolContextSymbol;
329                 }
330             }
331 
332             if (resolve_scope & eSymbolContextLineEntry)
333             {
334                 if (m_flags.IsClear (eSymbolContextLineEntry))
335                 {
336                     if (m_sc.line_entry.IsValid())
337                         resolved |= eSymbolContextLineEntry;
338                     else
339                         actual_resolve_scope |= eSymbolContextLineEntry;
340                 }
341             }
342 
343             if (actual_resolve_scope)
344             {
345                 // We might be resolving less information than what is already
346                 // in our current symbol context so resolve into a temporary
347                 // symbol context "sc" so we don't clear out data we have
348                 // already found in "m_sc"
349                 SymbolContext sc;
350                 // Set flags that indicate what we have tried to resolve
351                 resolved |= m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, actual_resolve_scope, sc);
352                 // Only replace what we didn't already have as we may have
353                 // information for an inlined function scope that won't match
354                 // what a standard lookup by address would match
355                 if ((resolved & eSymbolContextCompUnit)  && m_sc.comp_unit == NULL)
356                     m_sc.comp_unit = sc.comp_unit;
357                 if ((resolved & eSymbolContextFunction)  && m_sc.function == NULL)
358                     m_sc.function = sc.function;
359                 if ((resolved & eSymbolContextBlock)     && m_sc.block == NULL)
360                     m_sc.block = sc.block;
361                 if ((resolved & eSymbolContextSymbol)    && m_sc.symbol == NULL)
362                     m_sc.symbol = sc.symbol;
363                 if ((resolved & eSymbolContextLineEntry) && !m_sc.line_entry.IsValid())
364                     m_sc.line_entry = sc.line_entry;
365 
366             }
367         }
368         else
369         {
370             // If we don't have a module, then we can't have the compile unit,
371             // function, block, line entry or symbol, so we can safely call
372             // ResolveSymbolContextForAddress with our symbol context member m_sc.
373             resolved |= m_thread.GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (lookup_addr, resolve_scope, m_sc);
374         }
375 
376         // If the target was requested add that:
377         if (m_sc.target_sp.get() == NULL)
378         {
379             m_sc.target_sp = CalculateProcess()->GetTarget().GetSP();
380             if (m_sc.target_sp)
381                 resolved |= eSymbolContextTarget;
382         }
383 
384         // Update our internal flags so we remember what we have tried to locate so
385         // we don't have to keep trying when more calls to this function are made.
386         // We might have dug up more information that was requested (for example
387         // if we were asked to only get the block, we will have gotten the
388         // compile unit, and function) so set any additional bits that we resolved
389         m_flags.Set (resolve_scope | resolved);
390     }
391 
392     // Return the symbol context with everything that was possible to resolve
393     // resolved.
394     return m_sc;
395 }
396 
397 
398 VariableList *
399 StackFrame::GetVariableList ()
400 {
401     if (m_flags.IsClear(RESOLVED_VARIABLES))
402     {
403         m_flags.Set(RESOLVED_VARIABLES);
404 
405         if (GetSymbolContext (eSymbolContextFunction).function)
406         {
407             bool get_child_variables = true;
408             bool can_create = true;
409             m_variable_list_sp = m_sc.function->GetBlock (can_create).GetVariableList (get_child_variables, can_create);
410         }
411     }
412     return m_variable_list_sp.get();
413 }
414 
415 
416 bool
417 StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
418 {
419     if (m_flags.IsClear(GOT_FRAME_BASE))
420     {
421         if (m_sc.function)
422         {
423             m_frame_base.Clear();
424             m_frame_base_error.Clear();
425 
426             m_flags.Set(GOT_FRAME_BASE);
427             ExecutionContext exe_ctx (&m_thread.GetProcess(), &m_thread, this);
428             Value expr_value;
429             if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, NULL, expr_value, &m_frame_base_error) < 0)
430             {
431                 // We should really have an error if evaluate returns, but in case
432                 // we don't, lets set the error to something at least.
433                 if (m_frame_base_error.Success())
434                     m_frame_base_error.SetErrorString("Evaluation of the frame base expression failed.");
435             }
436             else
437             {
438                 m_frame_base = expr_value.ResolveValue(&exe_ctx, NULL);
439             }
440         }
441         else
442         {
443             m_frame_base_error.SetErrorString ("No function in symbol context.");
444         }
445     }
446 
447     if (m_frame_base_error.Success())
448         frame_base = m_frame_base;
449 
450     if (error_ptr)
451         *error_ptr = m_frame_base_error;
452     return m_frame_base_error.Success();
453 }
454 
455 RegisterContext *
456 StackFrame::GetRegisterContext ()
457 {
458     if (m_reg_context_sp.get() == NULL)
459         m_reg_context_sp.reset (m_thread.CreateRegisterContextForFrame (this));
460     return m_reg_context_sp.get();
461 }
462 
463 bool
464 StackFrame::HasDebugInformation ()
465 {
466     GetSymbolContext (eSymbolContextLineEntry);
467     return m_sc.line_entry.IsValid();
468 }
469 
470 ValueObjectList &
471 StackFrame::GetValueObjectList()
472 {
473     return m_value_object_list;
474 }
475 
476 
477 Target *
478 StackFrame::CalculateTarget ()
479 {
480     return m_thread.CalculateTarget();
481 }
482 
483 Process *
484 StackFrame::CalculateProcess ()
485 {
486     return m_thread.CalculateProcess();
487 }
488 
489 Thread *
490 StackFrame::CalculateThread ()
491 {
492     return &m_thread;
493 }
494 
495 StackFrame *
496 StackFrame::CalculateStackFrame ()
497 {
498     return this;
499 }
500 
501 
502 void
503 StackFrame::Calculate (ExecutionContext &exe_ctx)
504 {
505     m_thread.Calculate (exe_ctx);
506     exe_ctx.frame = this;
507 }
508 
509 void
510 StackFrame::Dump (Stream *strm, bool show_frame_index)
511 {
512     if (strm == NULL)
513         return;
514 
515     if (show_frame_index)
516         strm->Printf("frame #%u: ", m_frame_index);
517     strm->Printf("0x%0*llx", m_thread.GetProcess().GetAddressByteSize() * 2, GetFrameCodeAddress().GetLoadAddress(&m_thread.GetProcess()));
518     GetSymbolContext(eSymbolContextEverything);
519     strm->PutCString(", where = ");
520     // TODO: need to get the
521     const bool show_module = true;
522     const bool show_inline = true;
523     m_sc.DumpStopContext(strm, &m_thread.GetProcess(), GetFrameCodeAddress(), show_module, show_inline);
524 }
525 
526