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         Disassembler::Disassemble (m_thread.GetProcess().GetTarget().GetArchitecture(),
180                                    exe_ctx,
181                                    0,
182                                    m_disassembly);
183         if (m_disassembly.GetSize() == 0)
184             return NULL;
185     }
186     return m_disassembly.GetData();
187 }
188 
189 //----------------------------------------------------------------------
190 // Get the symbol context if we already haven't done so by resolving the
191 // PC address as much as possible. This way when we pass around a
192 // StackFrame object, everyone will have as much information as
193 // possible and no one will ever have to look things up manually.
194 //----------------------------------------------------------------------
195 const SymbolContext&
196 StackFrame::GetSymbolContext (uint32_t resolve_scope)
197 {
198     // Copy our internal symbol context into "sc".
199 
200     if ((m_flags.GetAllFlagBits() & resolve_scope) != resolve_scope)
201     {
202         // Resolve our PC to section offset if we haven't alreday done so
203         // and if we don't have a module. The resolved address section will
204         // contain the module to which it belongs
205         if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_PC_SO_ADDR))
206             GetPC();
207 
208         // If this is not frame zero, then we need to subtract 1 from the PC
209         // value when doing address lookups since the PC will be on the
210         // instruction following the function call instruction...
211 
212         Address lookup_addr(GetPC());
213         if (GetID() > 0 && lookup_addr.IsValid())
214         {
215             addr_t offset = lookup_addr.GetOffset();
216             if (offset > 0)
217                 lookup_addr.SetOffset(offset - 1);
218         }
219 
220         if (m_sc.module_sp)
221         {
222             // We have something in our stack frame symbol context, lets check
223             // if we haven't already tried to lookup one of those things. If we
224             // haven't then we will do the query.
225             if ((m_sc.comp_unit == NULL     && (resolve_scope & eSymbolContextCompUnit ) && m_flags.IsClear(eSymbolContextCompUnit   )) ||
226                 (m_sc.function  == NULL     && (resolve_scope & eSymbolContextFunction ) && m_flags.IsClear(eSymbolContextFunction   )) ||
227                 (m_sc.block     == NULL     && (resolve_scope & eSymbolContextBlock    ) && m_flags.IsClear(eSymbolContextBlock      )) ||
228                 (m_sc.symbol    == NULL     && (resolve_scope & eSymbolContextSymbol   ) && m_flags.IsClear(eSymbolContextSymbol     )) ||
229                 (!m_sc.line_entry.IsValid() && (resolve_scope & eSymbolContextLineEntry) && m_flags.IsClear(eSymbolContextLineEntry  )))
230             {
231                 // We might be resolving less information than what is already
232                 // in our current symbol context so resolve into a temporary
233                 // symbol context "sc" so we don't clear out data we have
234                 // already found in "m_sc"
235                 SymbolContext sc;
236                 // Set flags that indicate what we have tried to resolve
237                 const uint32_t resolved = m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, resolve_scope, sc);
238                 if (resolved & eSymbolContextCompUnit)  m_sc.comp_unit  = sc.comp_unit;
239                 if (resolved & eSymbolContextFunction)  m_sc.function   = sc.function;
240                 if (resolved & eSymbolContextBlock)     m_sc.block      = sc.block;
241                 if (resolved & eSymbolContextSymbol)    m_sc.symbol     = sc.symbol;
242                 if (resolved & eSymbolContextLineEntry) m_sc.line_entry = sc.line_entry;
243             }
244         }
245         else
246         {
247             // If we don't have a module, then we can't have the compile unit,
248             // function, block, line entry or symbol, so we can safely call
249             // ResolveSymbolContextForAddress with our symbol context member m_sc.
250             m_thread.GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (lookup_addr, resolve_scope, m_sc);
251         }
252 
253         // If the target was requested add that:
254         if (m_sc.target_sp.get() == NULL)
255             m_sc.target_sp = CalculateProcess()->GetTarget().GetSP();
256 
257         // Update our internal flags so we remember what we have tried to locate so
258         // we don't have to keep trying when more calls to this function are made.
259         m_flags.Set(resolve_scope);
260     }
261 
262     // Return the symbol context with everything that was possible to resolve
263     // resolved.
264     return m_sc;
265 }
266 
267 
268 VariableList *
269 StackFrame::GetVariableList ()
270 {
271     if (m_flags.IsClear(RESOLVED_VARIABLES))
272     {
273         m_flags.Set(RESOLVED_VARIABLES);
274 
275         GetSymbolContext(eSymbolContextFunction);
276         if (m_sc.function)
277         {
278             bool get_child_variables = true;
279             bool can_create = true;
280             m_variable_list_sp = m_sc.function->GetBlocks(can_create).GetVariableList (Block::RootID, get_child_variables, can_create);
281         }
282     }
283     return m_variable_list_sp.get();
284 }
285 
286 
287 bool
288 StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
289 {
290     if (m_flags.IsClear(GOT_FRAME_BASE))
291     {
292         if (m_sc.function)
293         {
294             m_frame_base.Clear();
295             m_frame_base_error.Clear();
296 
297             m_flags.Set(GOT_FRAME_BASE);
298             ExecutionContext exe_ctx (&m_thread.GetProcess(), &m_thread, this);
299             Value expr_value;
300             if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, NULL, expr_value, &m_frame_base_error) < 0)
301             {
302                 // We should really have an error if evaluate returns, but in case
303                 // we don't, lets set the error to something at least.
304                 if (m_frame_base_error.Success())
305                     m_frame_base_error.SetErrorString("Evaluation of the frame base expression failed.");
306             }
307             else
308             {
309                 m_frame_base = expr_value.ResolveValue(&exe_ctx, NULL);
310             }
311         }
312         else
313         {
314             m_frame_base_error.SetErrorString ("No function in symbol context.");
315         }
316     }
317 
318     if (m_frame_base_error.Success())
319         frame_base = m_frame_base;
320 
321     if (error_ptr)
322         *error_ptr = m_frame_base_error;
323     return m_frame_base_error.Success();
324 }
325 
326 RegisterContext *
327 StackFrame::GetRegisterContext ()
328 {
329     if (m_reg_context_sp.get() == NULL)
330         m_reg_context_sp.reset (m_thread.CreateRegisterContextForFrame (this));
331     return m_reg_context_sp.get();
332 }
333 
334 bool
335 StackFrame::HasDebugInformation ()
336 {
337     GetSymbolContext(eSymbolContextLineEntry);
338     return m_sc.line_entry.IsValid();
339 }
340 
341 ValueObjectList &
342 StackFrame::GetValueObjectList()
343 {
344     return m_value_object_list;
345 }
346 
347 
348 Target *
349 StackFrame::CalculateTarget ()
350 {
351     return m_thread.CalculateTarget();
352 }
353 
354 Process *
355 StackFrame::CalculateProcess ()
356 {
357     return m_thread.CalculateProcess();
358 }
359 
360 Thread *
361 StackFrame::CalculateThread ()
362 {
363     return &m_thread;
364 }
365 
366 StackFrame *
367 StackFrame::CalculateStackFrame ()
368 {
369     return this;
370 }
371 
372 
373 void
374 StackFrame::Calculate (ExecutionContext &exe_ctx)
375 {
376     m_thread.Calculate (exe_ctx);
377     exe_ctx.frame = this;
378 }
379 
380 void
381 StackFrame::Dump (Stream *strm, bool show_frame_index)
382 {
383     if (strm == NULL)
384         return;
385 
386     if (show_frame_index)
387         strm->Printf("frame #%u: ", GetID());
388     strm->Printf("pc = 0x%0*llx", m_thread.GetProcess().GetAddressByteSize() * 2, GetRegisterContext()->GetPC());
389     SymbolContext sc (GetSymbolContext(eSymbolContextEverything));
390     strm->PutCString(", where = ");
391     sc.DumpStopContext(strm, &m_thread.GetProcess(), GetPC());
392 }
393 
394