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 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