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 (lldb::user_id_t frame_idx, Thread &thread, lldb::addr_t cfa, lldb::addr_t pc, const SymbolContext *sc_ptr) :
39     UserID (frame_idx),
40     m_thread (thread),
41     m_reg_context_sp(),
42     m_id(cfa),
43     m_pc(NULL, pc),
44     m_sc(),
45     m_flags(),
46     m_frame_base(),
47     m_frame_base_error(),
48     m_variable_list_sp (),
49     m_value_object_list ()
50 {
51     if (sc_ptr != NULL)
52         m_sc = *sc_ptr;
53 }
54 
55 StackFrame::StackFrame (lldb::user_id_t frame_idx, Thread &thread, RegisterContextSP &reg_context_sp, lldb::addr_t cfa, lldb::addr_t pc, const SymbolContext *sc_ptr) :
56     UserID (frame_idx),
57     m_thread (thread),
58     m_reg_context_sp(reg_context_sp),
59     m_id(cfa),
60     m_pc(NULL, pc),
61     m_sc(),
62     m_flags(),
63     m_frame_base(),
64     m_frame_base_error(),
65     m_variable_list_sp (),
66     m_value_object_list ()
67 {
68     if (sc_ptr != NULL)
69         m_sc = *sc_ptr;
70 }
71 
72 
73 //----------------------------------------------------------------------
74 // Destructor
75 //----------------------------------------------------------------------
76 StackFrame::~StackFrame()
77 {
78 }
79 
80 StackID&
81 StackFrame::GetStackID()
82 {
83     // Make sure we have resolved our stack ID's address range before we give
84     // it out to any external clients
85     if (m_id.GetStartAddress().IsValid() == 0 && m_flags.IsClear(RESOLVED_FRAME_ID))
86     {
87         m_flags.Set (RESOLVED_FRAME_ID);
88 
89         // Resolve our PC to section offset if we haven't alreday done so
90         // and if we don't have a module. The resolved address section will
91         // contain the module to which it belongs.
92         if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_PC_SO_ADDR))
93             GetPC();
94 
95         const uint32_t resolve_scope = eSymbolContextModule |
96                                        eSymbolContextCompUnit |
97                                        eSymbolContextFunction;
98 
99         if (m_sc.module_sp)
100         {
101             if (m_sc.module_sp->ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextFunction)
102             {
103                 assert (m_sc.function);
104                 m_id.SetStartAddress(m_sc.function->GetAddressRange().GetBaseAddress());
105             }
106             else if (m_sc.module_sp->ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextSymbol)
107             {
108                 assert (m_sc.symbol);
109                 AddressRange *symbol_range_ptr = m_sc.symbol->GetAddressRangePtr();
110                 if (symbol_range_ptr)
111                     m_id.SetStartAddress(symbol_range_ptr->GetBaseAddress());
112             }
113         }
114 //      else if (m_sc.target != NULL)
115 //      {
116 //          if (m_sc.target->GetImages().ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextFunction)
117 //          {
118 //              assert (m_sc.function);
119 //              m_id.GetAddressRange() = m_sc.function->GetAddressRange();
120 //          }
121 //          else if (m_sc.target->GetImages().ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextSymbol)
122 //          {
123 //              assert (m_sc.symbol);
124 //              AddressRange *symbol_range_ptr = m_sc.symbol->GetAddressRange();
125 //              if (symbol_range_ptr)
126 //                  m_id.GetAddressRange() = *symbol_range_ptr;
127 //          }
128 //      }
129     }
130     return m_id;
131 }
132 
133 Address&
134 StackFrame::GetPC()
135 {
136     if (m_flags.IsClear(RESOLVED_PC_SO_ADDR) && !m_pc.IsSectionOffset())
137     {
138         m_flags.Set (RESOLVED_PC_SO_ADDR);
139 
140         // Resolve the PC into a temporary address because if ResolveLoadAddress
141         // fails to resolve the address, it will clear the address object...
142         Address resolved_pc;
143         if (m_thread.GetProcess().ResolveLoadAddress(m_pc.GetOffset(), resolved_pc))
144         {
145             m_pc = resolved_pc;
146             const Section *section = m_pc.GetSection();
147             if (section)
148             {
149                 Module *module = section->GetModule();
150                 if (module)
151                 {
152                     m_sc.module_sp = module->GetSP();
153                     if (m_sc.module_sp)
154                         m_flags.Set(eSymbolContextModule);
155                 }
156             }
157         }
158     }
159     return m_pc;
160 }
161 
162 void
163 StackFrame::ChangePC (addr_t pc)
164 {
165     m_pc.SetOffset(pc);
166     m_pc.SetSection(NULL);
167     m_sc.Clear();
168     m_flags.SetAllFlagBits(0);
169     m_thread.ClearStackFrames ();
170 }
171 
172 const char *
173 StackFrame::Disassemble ()
174 {
175     if (m_disassembly.GetSize() == 0)
176     {
177         ExecutionContext exe_ctx;
178         Calculate(exe_ctx);
179         Target &target = m_thread.GetProcess().GetTarget();
180         Disassembler::Disassemble (target.GetDebugger(),
181                                    target.GetArchitecture(),
182                                    exe_ctx,
183                                    0,
184                                    false,
185                                    m_disassembly);
186         if (m_disassembly.GetSize() == 0)
187             return NULL;
188     }
189     return m_disassembly.GetData();
190 }
191 
192 //----------------------------------------------------------------------
193 // Get the symbol context if we already haven't done so by resolving the
194 // PC address as much as possible. This way when we pass around a
195 // StackFrame object, everyone will have as much information as
196 // possible and no one will ever have to look things up manually.
197 //----------------------------------------------------------------------
198 const SymbolContext&
199 StackFrame::GetSymbolContext (uint32_t resolve_scope)
200 {
201     // Copy our internal symbol context into "sc".
202 
203     if ((m_flags.GetAllFlagBits() & resolve_scope) != resolve_scope)
204     {
205         // Resolve our PC to section offset if we haven't alreday done so
206         // and if we don't have a module. The resolved address section will
207         // contain the module to which it belongs
208         if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_PC_SO_ADDR))
209             GetPC();
210 
211         // If this is not frame zero, then we need to subtract 1 from the PC
212         // value when doing address lookups since the PC will be on the
213         // instruction following the function call instruction...
214 
215         Address lookup_addr(GetPC());
216         if (GetID() > 0 && lookup_addr.IsValid())
217         {
218             addr_t offset = lookup_addr.GetOffset();
219             if (offset > 0)
220                 lookup_addr.SetOffset(offset - 1);
221         }
222 
223         if (m_sc.module_sp)
224         {
225             // We have something in our stack frame symbol context, lets check
226             // if we haven't already tried to lookup one of those things. If we
227             // haven't then we will do the query.
228             if ((m_sc.comp_unit == NULL     && (resolve_scope & eSymbolContextCompUnit ) && m_flags.IsClear(eSymbolContextCompUnit   )) ||
229                 (m_sc.function  == NULL     && (resolve_scope & eSymbolContextFunction ) && m_flags.IsClear(eSymbolContextFunction   )) ||
230                 (m_sc.block     == NULL     && (resolve_scope & eSymbolContextBlock    ) && m_flags.IsClear(eSymbolContextBlock      )) ||
231                 (m_sc.symbol    == NULL     && (resolve_scope & eSymbolContextSymbol   ) && m_flags.IsClear(eSymbolContextSymbol     )) ||
232                 (!m_sc.line_entry.IsValid() && (resolve_scope & eSymbolContextLineEntry) && m_flags.IsClear(eSymbolContextLineEntry  )))
233             {
234                 // We might be resolving less information than what is already
235                 // in our current symbol context so resolve into a temporary
236                 // symbol context "sc" so we don't clear out data we have
237                 // already found in "m_sc"
238                 SymbolContext sc;
239                 // Set flags that indicate what we have tried to resolve
240                 const uint32_t resolved = m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, resolve_scope, sc);
241                 if (resolved & eSymbolContextCompUnit)  m_sc.comp_unit  = sc.comp_unit;
242                 if (resolved & eSymbolContextFunction)  m_sc.function   = sc.function;
243                 if (resolved & eSymbolContextBlock)     m_sc.block      = sc.block;
244                 if (resolved & eSymbolContextSymbol)    m_sc.symbol     = sc.symbol;
245                 if (resolved & eSymbolContextLineEntry) m_sc.line_entry = sc.line_entry;
246             }
247         }
248         else
249         {
250             // If we don't have a module, then we can't have the compile unit,
251             // function, block, line entry or symbol, so we can safely call
252             // ResolveSymbolContextForAddress with our symbol context member m_sc.
253             m_thread.GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (lookup_addr, resolve_scope, m_sc);
254         }
255 
256         // If the target was requested add that:
257         if (m_sc.target_sp.get() == NULL)
258             m_sc.target_sp = CalculateProcess()->GetTarget().GetSP();
259 
260         // Update our internal flags so we remember what we have tried to locate so
261         // we don't have to keep trying when more calls to this function are made.
262         m_flags.Set(resolve_scope);
263     }
264 
265     // Return the symbol context with everything that was possible to resolve
266     // resolved.
267     return m_sc;
268 }
269 
270 
271 VariableList *
272 StackFrame::GetVariableList ()
273 {
274     if (m_flags.IsClear(RESOLVED_VARIABLES))
275     {
276         m_flags.Set(RESOLVED_VARIABLES);
277 
278         GetSymbolContext(eSymbolContextFunction);
279         if (m_sc.function)
280         {
281             bool get_child_variables = true;
282             bool can_create = true;
283             m_variable_list_sp = m_sc.function->GetBlocks(can_create).GetVariableList (Block::RootID, get_child_variables, can_create);
284         }
285     }
286     return m_variable_list_sp.get();
287 }
288 
289 
290 bool
291 StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
292 {
293     if (m_flags.IsClear(GOT_FRAME_BASE))
294     {
295         if (m_sc.function)
296         {
297             m_frame_base.Clear();
298             m_frame_base_error.Clear();
299 
300             m_flags.Set(GOT_FRAME_BASE);
301             ExecutionContext exe_ctx (&m_thread.GetProcess(), &m_thread, this);
302             Value expr_value;
303             if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, NULL, expr_value, &m_frame_base_error) < 0)
304             {
305                 // We should really have an error if evaluate returns, but in case
306                 // we don't, lets set the error to something at least.
307                 if (m_frame_base_error.Success())
308                     m_frame_base_error.SetErrorString("Evaluation of the frame base expression failed.");
309             }
310             else
311             {
312                 m_frame_base = expr_value.ResolveValue(&exe_ctx, NULL);
313             }
314         }
315         else
316         {
317             m_frame_base_error.SetErrorString ("No function in symbol context.");
318         }
319     }
320 
321     if (m_frame_base_error.Success())
322         frame_base = m_frame_base;
323 
324     if (error_ptr)
325         *error_ptr = m_frame_base_error;
326     return m_frame_base_error.Success();
327 }
328 
329 RegisterContext *
330 StackFrame::GetRegisterContext ()
331 {
332     if (m_reg_context_sp.get() == NULL)
333         m_reg_context_sp.reset (m_thread.CreateRegisterContextForFrame (this));
334     return m_reg_context_sp.get();
335 }
336 
337 bool
338 StackFrame::HasDebugInformation ()
339 {
340     GetSymbolContext(eSymbolContextLineEntry);
341     return m_sc.line_entry.IsValid();
342 }
343 
344 ValueObjectList &
345 StackFrame::GetValueObjectList()
346 {
347     return m_value_object_list;
348 }
349 
350 
351 Target *
352 StackFrame::CalculateTarget ()
353 {
354     return m_thread.CalculateTarget();
355 }
356 
357 Process *
358 StackFrame::CalculateProcess ()
359 {
360     return m_thread.CalculateProcess();
361 }
362 
363 Thread *
364 StackFrame::CalculateThread ()
365 {
366     return &m_thread;
367 }
368 
369 StackFrame *
370 StackFrame::CalculateStackFrame ()
371 {
372     return this;
373 }
374 
375 
376 void
377 StackFrame::Calculate (ExecutionContext &exe_ctx)
378 {
379     m_thread.Calculate (exe_ctx);
380     exe_ctx.frame = this;
381 }
382 
383 void
384 StackFrame::Dump (Stream *strm, bool show_frame_index)
385 {
386     if (strm == NULL)
387         return;
388 
389     if (show_frame_index)
390         strm->Printf("frame #%u: ", GetID());
391     strm->Printf("pc = 0x%0*llx", m_thread.GetProcess().GetAddressByteSize() * 2, GetRegisterContext()->GetPC());
392     SymbolContext sc (GetSymbolContext(eSymbolContextEverything));
393     strm->PutCString(", where = ");
394     sc.DumpStopContext(strm, &m_thread.GetProcess(), GetPC());
395 }
396 
397