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