130fdc8d8SChris Lattner //===-- StackFrame.cpp ------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1093a64300SDaniel Malea #include "lldb/lldb-python.h" 1193a64300SDaniel Malea 12*f23bf743SJason Molenda #include "lldb/Target/Frame.h" 1330fdc8d8SChris Lattner #include "lldb/Target/StackFrame.h" 1430fdc8d8SChris Lattner 1530fdc8d8SChris Lattner // C Includes 1630fdc8d8SChris Lattner // C++ Includes 1730fdc8d8SChris Lattner // Other libraries and framework includes 1830fdc8d8SChris Lattner // Project includes 1930fdc8d8SChris Lattner #include "lldb/Core/Module.h" 200603aa9dSGreg Clayton #include "lldb/Core/Debugger.h" 2130fdc8d8SChris Lattner #include "lldb/Core/Disassembler.h" 2230fdc8d8SChris Lattner #include "lldb/Core/Value.h" 23288bdf9cSGreg Clayton #include "lldb/Core/ValueObjectVariable.h" 2454979cddSGreg Clayton #include "lldb/Core/ValueObjectConstResult.h" 251f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 2630fdc8d8SChris Lattner #include "lldb/Symbol/Function.h" 271f746071SGreg Clayton #include "lldb/Symbol/Symbol.h" 281f746071SGreg Clayton #include "lldb/Symbol/SymbolContextScope.h" 29288bdf9cSGreg Clayton #include "lldb/Symbol/VariableList.h" 3030fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h" 3130fdc8d8SChris Lattner #include "lldb/Target/Process.h" 3230fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 3330fdc8d8SChris Lattner #include "lldb/Target/Target.h" 3430fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 3530fdc8d8SChris Lattner 3630fdc8d8SChris Lattner using namespace lldb; 3730fdc8d8SChris Lattner using namespace lldb_private; 3830fdc8d8SChris Lattner 3930fdc8d8SChris Lattner // The first bits in the flags are reserved for the SymbolContext::Scope bits 4030fdc8d8SChris Lattner // so we know if we have tried to look up information in our internal symbol 4130fdc8d8SChris Lattner // context (m_sc) already. 4259e8fc1cSGreg Clayton #define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextEverything + 1)) 436dadd508SGreg Clayton #define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1) 4459e8fc1cSGreg Clayton #define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1) 4559e8fc1cSGreg Clayton #define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1) 467c0962dcSSean Callanan #define RESOLVED_GLOBAL_VARIABLES (RESOLVED_VARIABLES << 1) 4730fdc8d8SChris Lattner 48d9e416c0SGreg Clayton StackFrame::StackFrame (const ThreadSP &thread_sp, 49d9e416c0SGreg Clayton user_id_t frame_idx, 504d122c40SGreg Clayton user_id_t unwind_frame_index, 514d122c40SGreg Clayton addr_t cfa, 524d122c40SGreg Clayton addr_t pc, 538f7180b1SGreg Clayton const SymbolContext *sc_ptr) : 54d9e416c0SGreg Clayton m_thread_wp (thread_sp), 551b72fcb7SGreg Clayton m_frame_index (frame_idx), 565ccbd294SGreg Clayton m_concrete_frame_index (unwind_frame_index), 5730fdc8d8SChris Lattner m_reg_context_sp (), 586dadd508SGreg Clayton m_id (pc, cfa, NULL), 59e72dfb32SGreg Clayton m_frame_code_addr (pc), 6030fdc8d8SChris Lattner m_sc (), 6130fdc8d8SChris Lattner m_flags (), 6230fdc8d8SChris Lattner m_frame_base (), 6330fdc8d8SChris Lattner m_frame_base_error (), 6430fdc8d8SChris Lattner m_variable_list_sp (), 651a65ae11SGreg Clayton m_variable_list_value_objects (), 661a65ae11SGreg Clayton m_disassembly () 6730fdc8d8SChris Lattner { 6830fdc8d8SChris Lattner if (sc_ptr != NULL) 691b72fcb7SGreg Clayton { 7030fdc8d8SChris Lattner m_sc = *sc_ptr; 711b72fcb7SGreg Clayton m_flags.Set(m_sc.GetResolvedMask ()); 721b72fcb7SGreg Clayton } 7330fdc8d8SChris Lattner } 7430fdc8d8SChris Lattner 75d9e416c0SGreg Clayton StackFrame::StackFrame (const ThreadSP &thread_sp, 76d9e416c0SGreg Clayton user_id_t frame_idx, 774d122c40SGreg Clayton user_id_t unwind_frame_index, 781b72fcb7SGreg Clayton const RegisterContextSP ®_context_sp, 794d122c40SGreg Clayton addr_t cfa, 804d122c40SGreg Clayton addr_t pc, 818f7180b1SGreg Clayton const SymbolContext *sc_ptr) : 82d9e416c0SGreg Clayton m_thread_wp (thread_sp), 831b72fcb7SGreg Clayton m_frame_index (frame_idx), 845ccbd294SGreg Clayton m_concrete_frame_index (unwind_frame_index), 8530fdc8d8SChris Lattner m_reg_context_sp (reg_context_sp), 866dadd508SGreg Clayton m_id (pc, cfa, NULL), 87e72dfb32SGreg Clayton m_frame_code_addr (pc), 8830fdc8d8SChris Lattner m_sc (), 8930fdc8d8SChris Lattner m_flags (), 9030fdc8d8SChris Lattner m_frame_base (), 9130fdc8d8SChris Lattner m_frame_base_error (), 9230fdc8d8SChris Lattner m_variable_list_sp (), 931a65ae11SGreg Clayton m_variable_list_value_objects (), 941a65ae11SGreg Clayton m_disassembly () 9530fdc8d8SChris Lattner { 9630fdc8d8SChris Lattner if (sc_ptr != NULL) 971b72fcb7SGreg Clayton { 9830fdc8d8SChris Lattner m_sc = *sc_ptr; 991b72fcb7SGreg Clayton m_flags.Set(m_sc.GetResolvedMask ()); 1001b72fcb7SGreg Clayton } 1011b72fcb7SGreg Clayton 1021b72fcb7SGreg Clayton if (reg_context_sp && !m_sc.target_sp) 1031b72fcb7SGreg Clayton { 104d9e416c0SGreg Clayton m_sc.target_sp = reg_context_sp->CalculateTarget(); 105d9e416c0SGreg Clayton if (m_sc.target_sp) 1061b72fcb7SGreg Clayton m_flags.Set (eSymbolContextTarget); 1071b72fcb7SGreg Clayton } 1081b72fcb7SGreg Clayton } 1091b72fcb7SGreg Clayton 110d9e416c0SGreg Clayton StackFrame::StackFrame (const ThreadSP &thread_sp, 111d9e416c0SGreg Clayton user_id_t frame_idx, 1124d122c40SGreg Clayton user_id_t unwind_frame_index, 1131b72fcb7SGreg Clayton const RegisterContextSP ®_context_sp, 1144d122c40SGreg Clayton addr_t cfa, 1151b72fcb7SGreg Clayton const Address& pc_addr, 1168f7180b1SGreg Clayton const SymbolContext *sc_ptr) : 117d9e416c0SGreg Clayton m_thread_wp (thread_sp), 1181b72fcb7SGreg Clayton m_frame_index (frame_idx), 1195ccbd294SGreg Clayton m_concrete_frame_index (unwind_frame_index), 1201b72fcb7SGreg Clayton m_reg_context_sp (reg_context_sp), 1211ac04c30SGreg Clayton m_id (pc_addr.GetLoadAddress (thread_sp->CalculateTarget().get()), cfa, NULL), 12212fc3e0fSGreg Clayton m_frame_code_addr (pc_addr), 1231b72fcb7SGreg Clayton m_sc (), 1241b72fcb7SGreg Clayton m_flags (), 1251b72fcb7SGreg Clayton m_frame_base (), 1261b72fcb7SGreg Clayton m_frame_base_error (), 1271b72fcb7SGreg Clayton m_variable_list_sp (), 1281a65ae11SGreg Clayton m_variable_list_value_objects (), 1291a65ae11SGreg Clayton m_disassembly () 1301b72fcb7SGreg Clayton { 1311b72fcb7SGreg Clayton if (sc_ptr != NULL) 1321b72fcb7SGreg Clayton { 1331b72fcb7SGreg Clayton m_sc = *sc_ptr; 1341b72fcb7SGreg Clayton m_flags.Set(m_sc.GetResolvedMask ()); 1351b72fcb7SGreg Clayton } 1361b72fcb7SGreg Clayton 1371b72fcb7SGreg Clayton if (m_sc.target_sp.get() == NULL && reg_context_sp) 1381b72fcb7SGreg Clayton { 139d9e416c0SGreg Clayton m_sc.target_sp = reg_context_sp->CalculateTarget(); 140d9e416c0SGreg Clayton if (m_sc.target_sp) 1411b72fcb7SGreg Clayton m_flags.Set (eSymbolContextTarget); 1421b72fcb7SGreg Clayton } 1431b72fcb7SGreg Clayton 144e72dfb32SGreg Clayton ModuleSP pc_module_sp (pc_addr.GetModule()); 145e72dfb32SGreg Clayton if (!m_sc.module_sp || m_sc.module_sp != pc_module_sp) 1461b72fcb7SGreg Clayton { 147e72dfb32SGreg Clayton if (pc_module_sp) 1481b72fcb7SGreg Clayton { 149e72dfb32SGreg Clayton m_sc.module_sp = pc_module_sp; 1501b72fcb7SGreg Clayton m_flags.Set (eSymbolContextModule); 1511b72fcb7SGreg Clayton } 152ffc1d667SGreg Clayton else 153ffc1d667SGreg Clayton { 154ffc1d667SGreg Clayton m_sc.module_sp.reset(); 155ffc1d667SGreg Clayton } 1561b72fcb7SGreg Clayton } 15730fdc8d8SChris Lattner } 15830fdc8d8SChris Lattner 15930fdc8d8SChris Lattner 16030fdc8d8SChris Lattner //---------------------------------------------------------------------- 16130fdc8d8SChris Lattner // Destructor 16230fdc8d8SChris Lattner //---------------------------------------------------------------------- 16330fdc8d8SChris Lattner StackFrame::~StackFrame() 16430fdc8d8SChris Lattner { 16530fdc8d8SChris Lattner } 16630fdc8d8SChris Lattner 16730fdc8d8SChris Lattner StackID& 16830fdc8d8SChris Lattner StackFrame::GetStackID() 16930fdc8d8SChris Lattner { 1706dadd508SGreg Clayton // Make sure we have resolved the StackID object's symbol context scope if 1716dadd508SGreg Clayton // we already haven't looked it up. 17259e8fc1cSGreg Clayton 17359e8fc1cSGreg Clayton if (m_flags.IsClear (RESOLVED_FRAME_ID_SYMBOL_SCOPE)) 17459e8fc1cSGreg Clayton { 1752cad65a5SGreg Clayton if (m_id.GetSymbolContextScope ()) 17659e8fc1cSGreg Clayton { 17795897c6aSGreg Clayton // We already have a symbol context scope, we just don't have our 17895897c6aSGreg Clayton // flag bit set. 17959e8fc1cSGreg Clayton m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE); 18059e8fc1cSGreg Clayton } 18159e8fc1cSGreg Clayton else 18259e8fc1cSGreg Clayton { 18395897c6aSGreg Clayton // Calculate the frame block and use this for the stack ID symbol 18495897c6aSGreg Clayton // context scope if we have one. 18595897c6aSGreg Clayton SymbolContextScope *scope = GetFrameBlock (); 18695897c6aSGreg Clayton if (scope == NULL) 18759e8fc1cSGreg Clayton { 18895897c6aSGreg Clayton // We don't have a block, so use the symbol 18995897c6aSGreg Clayton if (m_flags.IsClear (eSymbolContextSymbol)) 19059e8fc1cSGreg Clayton GetSymbolContext (eSymbolContextSymbol); 19195897c6aSGreg Clayton 19295897c6aSGreg Clayton // It is ok if m_sc.symbol is NULL here 19395897c6aSGreg Clayton scope = m_sc.symbol; 19459e8fc1cSGreg Clayton } 19595897c6aSGreg Clayton // Set the symbol context scope (the accessor will set the 19695897c6aSGreg Clayton // RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags). 19795897c6aSGreg Clayton SetSymbolContextScope (scope); 19859e8fc1cSGreg Clayton } 19959e8fc1cSGreg Clayton } 20030fdc8d8SChris Lattner return m_id; 20130fdc8d8SChris Lattner } 20230fdc8d8SChris Lattner 203513c6bb8SJim Ingham uint32_t 204513c6bb8SJim Ingham StackFrame::GetFrameIndex () const 205513c6bb8SJim Ingham { 206513c6bb8SJim Ingham ThreadSP thread_sp = GetThread(); 207513c6bb8SJim Ingham if (thread_sp) 208*f23bf743SJason Molenda return thread_sp->GetStackFrameList()->GetVisibleFrameIndex(m_frame_index); 209513c6bb8SJim Ingham else 210513c6bb8SJim Ingham return m_frame_index; 211513c6bb8SJim Ingham } 212513c6bb8SJim Ingham 21359e8fc1cSGreg Clayton void 21459e8fc1cSGreg Clayton StackFrame::SetSymbolContextScope (SymbolContextScope *symbol_scope) 21559e8fc1cSGreg Clayton { 21659e8fc1cSGreg Clayton m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE); 21759e8fc1cSGreg Clayton m_id.SetSymbolContextScope (symbol_scope); 21859e8fc1cSGreg Clayton } 21959e8fc1cSGreg Clayton 22034132754SGreg Clayton const Address& 2219da7bd07SGreg Clayton StackFrame::GetFrameCodeAddress() 22230fdc8d8SChris Lattner { 22359e8fc1cSGreg Clayton if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && !m_frame_code_addr.IsSectionOffset()) 22430fdc8d8SChris Lattner { 22559e8fc1cSGreg Clayton m_flags.Set (RESOLVED_FRAME_CODE_ADDR); 22630fdc8d8SChris Lattner 22730fdc8d8SChris Lattner // Resolve the PC into a temporary address because if ResolveLoadAddress 22830fdc8d8SChris Lattner // fails to resolve the address, it will clear the address object... 229d9e416c0SGreg Clayton ThreadSP thread_sp (GetThread()); 230d9e416c0SGreg Clayton if (thread_sp) 231d9e416c0SGreg Clayton { 232d9e416c0SGreg Clayton TargetSP target_sp (thread_sp->CalculateTarget()); 233d9e416c0SGreg Clayton if (target_sp) 234d9e416c0SGreg Clayton { 235d9e416c0SGreg Clayton if (m_frame_code_addr.SetOpcodeLoadAddress (m_frame_code_addr.GetOffset(), target_sp.get())) 23630fdc8d8SChris Lattner { 237e72dfb32SGreg Clayton ModuleSP module_sp (m_frame_code_addr.GetModule()); 238e72dfb32SGreg Clayton if (module_sp) 23930fdc8d8SChris Lattner { 240e72dfb32SGreg Clayton m_sc.module_sp = module_sp; 24130fdc8d8SChris Lattner m_flags.Set(eSymbolContextModule); 24230fdc8d8SChris Lattner } 24330fdc8d8SChris Lattner } 24430fdc8d8SChris Lattner } 24530fdc8d8SChris Lattner } 246d9e416c0SGreg Clayton } 24712fc3e0fSGreg Clayton return m_frame_code_addr; 24830fdc8d8SChris Lattner } 24930fdc8d8SChris Lattner 250*f23bf743SJason Molenda bool 25130fdc8d8SChris Lattner StackFrame::ChangePC (addr_t pc) 25230fdc8d8SChris Lattner { 253e72dfb32SGreg Clayton m_frame_code_addr.SetRawAddress(pc); 25472310355SGreg Clayton m_sc.Clear(false); 25573b472d4SGreg Clayton m_flags.Reset(0); 256d9e416c0SGreg Clayton ThreadSP thread_sp (GetThread()); 257d9e416c0SGreg Clayton if (thread_sp) 258d9e416c0SGreg Clayton thread_sp->ClearStackFrames (); 259*f23bf743SJason Molenda return true; 26030fdc8d8SChris Lattner } 26130fdc8d8SChris Lattner 26230fdc8d8SChris Lattner const char * 26330fdc8d8SChris Lattner StackFrame::Disassemble () 26430fdc8d8SChris Lattner { 26530fdc8d8SChris Lattner if (m_disassembly.GetSize() == 0) 26630fdc8d8SChris Lattner { 267d9e416c0SGreg Clayton ExecutionContext exe_ctx (shared_from_this()); 268d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 269d9e416c0SGreg Clayton if (target) 270d9e416c0SGreg Clayton { 2710f063ba6SJim Ingham const char *plugin_name = NULL; 2720f063ba6SJim Ingham const char *flavor = NULL; 273d9e416c0SGreg Clayton Disassembler::Disassemble (target->GetDebugger(), 274d9e416c0SGreg Clayton target->GetArchitecture(), 2750f063ba6SJim Ingham plugin_name, 2760f063ba6SJim Ingham flavor, 27730fdc8d8SChris Lattner exe_ctx, 27830fdc8d8SChris Lattner 0, 27937023b06SJim Ingham 0, 2801da6f9d7SGreg Clayton 0, 28130fdc8d8SChris Lattner m_disassembly); 282d9e416c0SGreg Clayton } 28330fdc8d8SChris Lattner if (m_disassembly.GetSize() == 0) 28430fdc8d8SChris Lattner return NULL; 28530fdc8d8SChris Lattner } 28630fdc8d8SChris Lattner return m_disassembly.GetData(); 28730fdc8d8SChris Lattner } 28830fdc8d8SChris Lattner 28995897c6aSGreg Clayton Block * 29095897c6aSGreg Clayton StackFrame::GetFrameBlock () 29195897c6aSGreg Clayton { 29295897c6aSGreg Clayton if (m_sc.block == NULL && m_flags.IsClear (eSymbolContextBlock)) 29395897c6aSGreg Clayton GetSymbolContext (eSymbolContextBlock); 29495897c6aSGreg Clayton 29595897c6aSGreg Clayton if (m_sc.block) 29695897c6aSGreg Clayton { 29795897c6aSGreg Clayton Block *inline_block = m_sc.block->GetContainingInlinedBlock(); 29895897c6aSGreg Clayton if (inline_block) 29995897c6aSGreg Clayton { 30095897c6aSGreg Clayton // Use the block with the inlined function info 30195897c6aSGreg Clayton // as the frame block we want this frame to have only the variables 30295897c6aSGreg Clayton // for the inlined function and its non-inlined block child blocks. 30395897c6aSGreg Clayton return inline_block; 30495897c6aSGreg Clayton } 30595897c6aSGreg Clayton else 30695897c6aSGreg Clayton { 30795897c6aSGreg Clayton // This block is not contained withing any inlined function blocks 30895897c6aSGreg Clayton // with so we want to use the top most function block. 30995897c6aSGreg Clayton return &m_sc.function->GetBlock (false); 31095897c6aSGreg Clayton } 31195897c6aSGreg Clayton } 31295897c6aSGreg Clayton return NULL; 31395897c6aSGreg Clayton } 31495897c6aSGreg Clayton 31530fdc8d8SChris Lattner //---------------------------------------------------------------------- 31630fdc8d8SChris Lattner // Get the symbol context if we already haven't done so by resolving the 31730fdc8d8SChris Lattner // PC address as much as possible. This way when we pass around a 31830fdc8d8SChris Lattner // StackFrame object, everyone will have as much information as 31930fdc8d8SChris Lattner // possible and no one will ever have to look things up manually. 32030fdc8d8SChris Lattner //---------------------------------------------------------------------- 32130fdc8d8SChris Lattner const SymbolContext& 32230fdc8d8SChris Lattner StackFrame::GetSymbolContext (uint32_t resolve_scope) 32330fdc8d8SChris Lattner { 32430fdc8d8SChris Lattner // Copy our internal symbol context into "sc". 32573b472d4SGreg Clayton if ((m_flags.Get() & resolve_scope) != resolve_scope) 32630fdc8d8SChris Lattner { 32775a0333bSGreg Clayton uint32_t resolved = 0; 32875a0333bSGreg Clayton 32975a0333bSGreg Clayton // If the target was requested add that: 33075a0333bSGreg Clayton if (!m_sc.target_sp) 33175a0333bSGreg Clayton { 33275a0333bSGreg Clayton m_sc.target_sp = CalculateTarget(); 33375a0333bSGreg Clayton if (m_sc.target_sp) 33475a0333bSGreg Clayton resolved |= eSymbolContextTarget; 33575a0333bSGreg Clayton } 33675a0333bSGreg Clayton 33775a0333bSGreg Clayton 33830fdc8d8SChris Lattner // Resolve our PC to section offset if we haven't alreday done so 33930fdc8d8SChris Lattner // and if we don't have a module. The resolved address section will 34030fdc8d8SChris Lattner // contain the module to which it belongs 34159e8fc1cSGreg Clayton if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR)) 3429da7bd07SGreg Clayton GetFrameCodeAddress(); 34330fdc8d8SChris Lattner 34430fdc8d8SChris Lattner // If this is not frame zero, then we need to subtract 1 from the PC 34530fdc8d8SChris Lattner // value when doing address lookups since the PC will be on the 34630fdc8d8SChris Lattner // instruction following the function call instruction... 34730fdc8d8SChris Lattner 3489da7bd07SGreg Clayton Address lookup_addr(GetFrameCodeAddress()); 3491b72fcb7SGreg Clayton if (m_frame_index > 0 && lookup_addr.IsValid()) 35030fdc8d8SChris Lattner { 35130fdc8d8SChris Lattner addr_t offset = lookup_addr.GetOffset(); 35230fdc8d8SChris Lattner if (offset > 0) 35330fdc8d8SChris Lattner lookup_addr.SetOffset(offset - 1); 35430fdc8d8SChris Lattner } 35530fdc8d8SChris Lattner 3569da7bd07SGreg Clayton 35730fdc8d8SChris Lattner if (m_sc.module_sp) 35830fdc8d8SChris Lattner { 35930fdc8d8SChris Lattner // We have something in our stack frame symbol context, lets check 36030fdc8d8SChris Lattner // if we haven't already tried to lookup one of those things. If we 36130fdc8d8SChris Lattner // haven't then we will do the query. 3621b72fcb7SGreg Clayton 3631b72fcb7SGreg Clayton uint32_t actual_resolve_scope = 0; 3641b72fcb7SGreg Clayton 3651b72fcb7SGreg Clayton if (resolve_scope & eSymbolContextCompUnit) 3661b72fcb7SGreg Clayton { 3671b72fcb7SGreg Clayton if (m_flags.IsClear (eSymbolContextCompUnit)) 3681b72fcb7SGreg Clayton { 3691b72fcb7SGreg Clayton if (m_sc.comp_unit) 3709da7bd07SGreg Clayton resolved |= eSymbolContextCompUnit; 3711b72fcb7SGreg Clayton else 3721b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextCompUnit; 3731b72fcb7SGreg Clayton } 3741b72fcb7SGreg Clayton } 3751b72fcb7SGreg Clayton 3761b72fcb7SGreg Clayton if (resolve_scope & eSymbolContextFunction) 3771b72fcb7SGreg Clayton { 3781b72fcb7SGreg Clayton if (m_flags.IsClear (eSymbolContextFunction)) 3791b72fcb7SGreg Clayton { 3801b72fcb7SGreg Clayton if (m_sc.function) 3819da7bd07SGreg Clayton resolved |= eSymbolContextFunction; 3821b72fcb7SGreg Clayton else 3831b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextFunction; 3841b72fcb7SGreg Clayton } 3851b72fcb7SGreg Clayton } 3861b72fcb7SGreg Clayton 3871b72fcb7SGreg Clayton if (resolve_scope & eSymbolContextBlock) 3881b72fcb7SGreg Clayton { 3891b72fcb7SGreg Clayton if (m_flags.IsClear (eSymbolContextBlock)) 3901b72fcb7SGreg Clayton { 3911b72fcb7SGreg Clayton if (m_sc.block) 3929da7bd07SGreg Clayton resolved |= eSymbolContextBlock; 3931b72fcb7SGreg Clayton else 3941b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextBlock; 3951b72fcb7SGreg Clayton } 3961b72fcb7SGreg Clayton } 3971b72fcb7SGreg Clayton 3981b72fcb7SGreg Clayton if (resolve_scope & eSymbolContextSymbol) 3991b72fcb7SGreg Clayton { 4001b72fcb7SGreg Clayton if (m_flags.IsClear (eSymbolContextSymbol)) 4011b72fcb7SGreg Clayton { 4021b72fcb7SGreg Clayton if (m_sc.symbol) 4039da7bd07SGreg Clayton resolved |= eSymbolContextSymbol; 4041b72fcb7SGreg Clayton else 4051b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextSymbol; 4061b72fcb7SGreg Clayton } 4071b72fcb7SGreg Clayton } 4081b72fcb7SGreg Clayton 4091b72fcb7SGreg Clayton if (resolve_scope & eSymbolContextLineEntry) 4101b72fcb7SGreg Clayton { 4111b72fcb7SGreg Clayton if (m_flags.IsClear (eSymbolContextLineEntry)) 4121b72fcb7SGreg Clayton { 4131b72fcb7SGreg Clayton if (m_sc.line_entry.IsValid()) 4149da7bd07SGreg Clayton resolved |= eSymbolContextLineEntry; 4151b72fcb7SGreg Clayton else 4161b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextLineEntry; 4171b72fcb7SGreg Clayton } 4181b72fcb7SGreg Clayton } 4191b72fcb7SGreg Clayton 4201b72fcb7SGreg Clayton if (actual_resolve_scope) 42130fdc8d8SChris Lattner { 42230fdc8d8SChris Lattner // We might be resolving less information than what is already 42330fdc8d8SChris Lattner // in our current symbol context so resolve into a temporary 42430fdc8d8SChris Lattner // symbol context "sc" so we don't clear out data we have 42530fdc8d8SChris Lattner // already found in "m_sc" 42630fdc8d8SChris Lattner SymbolContext sc; 42730fdc8d8SChris Lattner // Set flags that indicate what we have tried to resolve 4289da7bd07SGreg Clayton resolved |= m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, actual_resolve_scope, sc); 4291b72fcb7SGreg Clayton // Only replace what we didn't already have as we may have 4301b72fcb7SGreg Clayton // information for an inlined function scope that won't match 4311b72fcb7SGreg Clayton // what a standard lookup by address would match 4329da7bd07SGreg Clayton if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == NULL) 4339da7bd07SGreg Clayton m_sc.comp_unit = sc.comp_unit; 4349da7bd07SGreg Clayton if ((resolved & eSymbolContextFunction) && m_sc.function == NULL) 4359da7bd07SGreg Clayton m_sc.function = sc.function; 4369da7bd07SGreg Clayton if ((resolved & eSymbolContextBlock) && m_sc.block == NULL) 4379da7bd07SGreg Clayton m_sc.block = sc.block; 4389da7bd07SGreg Clayton if ((resolved & eSymbolContextSymbol) && m_sc.symbol == NULL) 4399da7bd07SGreg Clayton m_sc.symbol = sc.symbol; 4409da7bd07SGreg Clayton if ((resolved & eSymbolContextLineEntry) && !m_sc.line_entry.IsValid()) 44175a0333bSGreg Clayton { 4429da7bd07SGreg Clayton m_sc.line_entry = sc.line_entry; 44375a0333bSGreg Clayton if (m_sc.target_sp) 44475a0333bSGreg Clayton { 44575a0333bSGreg Clayton // Be sure to apply and file remappings to our file and line 44675a0333bSGreg Clayton // entries when handing out a line entry 44775a0333bSGreg Clayton FileSpec new_file_spec; 44875a0333bSGreg Clayton if (m_sc.target_sp->GetSourcePathMap().FindFile (m_sc.line_entry.file, new_file_spec)) 44975a0333bSGreg Clayton m_sc.line_entry.file = new_file_spec; 45075a0333bSGreg Clayton } 45175a0333bSGreg Clayton } 45230fdc8d8SChris Lattner } 45330fdc8d8SChris Lattner } 45430fdc8d8SChris Lattner else 45530fdc8d8SChris Lattner { 45630fdc8d8SChris Lattner // If we don't have a module, then we can't have the compile unit, 45730fdc8d8SChris Lattner // function, block, line entry or symbol, so we can safely call 45830fdc8d8SChris Lattner // ResolveSymbolContextForAddress with our symbol context member m_sc. 4599da7bd07SGreg Clayton if (m_sc.target_sp) 460f4be227dSSean Callanan { 46175a0333bSGreg Clayton resolved |= m_sc.target_sp->GetImages().ResolveSymbolContextForAddress (lookup_addr, resolve_scope, m_sc); 462f4be227dSSean Callanan } 4639da7bd07SGreg Clayton } 46430fdc8d8SChris Lattner 46530fdc8d8SChris Lattner // Update our internal flags so we remember what we have tried to locate so 46630fdc8d8SChris Lattner // we don't have to keep trying when more calls to this function are made. 4679da7bd07SGreg Clayton // We might have dug up more information that was requested (for example 4689da7bd07SGreg Clayton // if we were asked to only get the block, we will have gotten the 4699da7bd07SGreg Clayton // compile unit, and function) so set any additional bits that we resolved 4709da7bd07SGreg Clayton m_flags.Set (resolve_scope | resolved); 47130fdc8d8SChris Lattner } 47230fdc8d8SChris Lattner 47330fdc8d8SChris Lattner // Return the symbol context with everything that was possible to resolve 47430fdc8d8SChris Lattner // resolved. 47530fdc8d8SChris Lattner return m_sc; 47630fdc8d8SChris Lattner } 47730fdc8d8SChris Lattner 47830fdc8d8SChris Lattner 47930fdc8d8SChris Lattner VariableList * 480288bdf9cSGreg Clayton StackFrame::GetVariableList (bool get_file_globals) 48130fdc8d8SChris Lattner { 48230fdc8d8SChris Lattner if (m_flags.IsClear(RESOLVED_VARIABLES)) 48330fdc8d8SChris Lattner { 48430fdc8d8SChris Lattner m_flags.Set(RESOLVED_VARIABLES); 48530fdc8d8SChris Lattner 48695897c6aSGreg Clayton Block *frame_block = GetFrameBlock(); 487288bdf9cSGreg Clayton 48895897c6aSGreg Clayton if (frame_block) 48930fdc8d8SChris Lattner { 49095897c6aSGreg Clayton const bool get_child_variables = true; 49195897c6aSGreg Clayton const bool can_create = true; 492c662ec8bSGreg Clayton const bool stop_if_child_block_is_inlined_function = true; 493c662ec8bSGreg Clayton m_variable_list_sp.reset(new VariableList()); 494c662ec8bSGreg Clayton frame_block->AppendBlockVariables(can_create, get_child_variables, stop_if_child_block_is_inlined_function, m_variable_list_sp.get()); 49530fdc8d8SChris Lattner } 4967c0962dcSSean Callanan } 497288bdf9cSGreg Clayton 4987c0962dcSSean Callanan if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) && 4997c0962dcSSean Callanan get_file_globals) 50095897c6aSGreg Clayton { 5017c0962dcSSean Callanan m_flags.Set(RESOLVED_GLOBAL_VARIABLES); 5027c0962dcSSean Callanan 50395897c6aSGreg Clayton if (m_flags.IsClear (eSymbolContextCompUnit)) 50495897c6aSGreg Clayton GetSymbolContext (eSymbolContextCompUnit); 50595897c6aSGreg Clayton 50695897c6aSGreg Clayton if (m_sc.comp_unit) 507288bdf9cSGreg Clayton { 508288bdf9cSGreg Clayton VariableListSP global_variable_list_sp (m_sc.comp_unit->GetVariableList(true)); 509288bdf9cSGreg Clayton if (m_variable_list_sp) 510288bdf9cSGreg Clayton m_variable_list_sp->AddVariables (global_variable_list_sp.get()); 511288bdf9cSGreg Clayton else 512288bdf9cSGreg Clayton m_variable_list_sp = global_variable_list_sp; 513288bdf9cSGreg Clayton } 51430fdc8d8SChris Lattner } 5157c0962dcSSean Callanan 51630fdc8d8SChris Lattner return m_variable_list_sp.get(); 51730fdc8d8SChris Lattner } 51830fdc8d8SChris Lattner 519d41f032aSGreg Clayton VariableListSP 520d41f032aSGreg Clayton StackFrame::GetInScopeVariableList (bool get_file_globals) 521d41f032aSGreg Clayton { 522d41f032aSGreg Clayton VariableListSP var_list_sp(new VariableList); 523d41f032aSGreg Clayton GetSymbolContext (eSymbolContextCompUnit | eSymbolContextBlock); 524d41f032aSGreg Clayton 525d41f032aSGreg Clayton if (m_sc.block) 526d41f032aSGreg Clayton { 527d41f032aSGreg Clayton const bool can_create = true; 528d41f032aSGreg Clayton const bool get_parent_variables = true; 529d41f032aSGreg Clayton const bool stop_if_block_is_inlined_function = true; 530d41f032aSGreg Clayton m_sc.block->AppendVariables (can_create, 531d41f032aSGreg Clayton get_parent_variables, 532d41f032aSGreg Clayton stop_if_block_is_inlined_function, 533d41f032aSGreg Clayton var_list_sp.get()); 534d41f032aSGreg Clayton } 535d41f032aSGreg Clayton 536d41f032aSGreg Clayton if (m_sc.comp_unit) 537d41f032aSGreg Clayton { 538d41f032aSGreg Clayton VariableListSP global_variable_list_sp (m_sc.comp_unit->GetVariableList(true)); 539d41f032aSGreg Clayton if (global_variable_list_sp) 540d41f032aSGreg Clayton var_list_sp->AddVariables (global_variable_list_sp.get()); 541d41f032aSGreg Clayton } 542d41f032aSGreg Clayton 543d41f032aSGreg Clayton return var_list_sp; 544d41f032aSGreg Clayton } 545d41f032aSGreg Clayton 546d41f032aSGreg Clayton 5478b2fe6dcSGreg Clayton ValueObjectSP 5482837b766SJim Ingham StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, 5494d122c40SGreg Clayton DynamicValueType use_dynamic, 5502837b766SJim Ingham uint32_t options, 5514d122c40SGreg Clayton VariableSP &var_sp, 5522837b766SJim Ingham Error &error) 5538b2fe6dcSGreg Clayton { 55454979cddSGreg Clayton 55554979cddSGreg Clayton if (var_expr_cstr && var_expr_cstr[0]) 55654979cddSGreg Clayton { 5576d5e68eaSGreg Clayton const bool check_ptr_vs_member = (options & eExpressionPathOptionCheckPtrVsMember) != 0; 5586d5e68eaSGreg Clayton const bool no_fragile_ivar = (options & eExpressionPathOptionsNoFragileObjcIvar) != 0; 55927b625e1SEnrico Granata const bool no_synth_child = (options & eExpressionPathOptionsNoSyntheticChildren) != 0; 56058ad3344SEnrico Granata //const bool no_synth_array = (options & eExpressionPathOptionsNoSyntheticArrayRange) != 0; 56154979cddSGreg Clayton error.Clear(); 5628b2fe6dcSGreg Clayton bool deref = false; 5638b2fe6dcSGreg Clayton bool address_of = false; 5648b2fe6dcSGreg Clayton ValueObjectSP valobj_sp; 5658b2fe6dcSGreg Clayton const bool get_file_globals = true; 566d41f032aSGreg Clayton // When looking up a variable for an expression, we need only consider the 567d41f032aSGreg Clayton // variables that are in scope. 568d41f032aSGreg Clayton VariableListSP var_list_sp (GetInScopeVariableList (get_file_globals)); 569d41f032aSGreg Clayton VariableList *variable_list = var_list_sp.get(); 5708b2fe6dcSGreg Clayton 5718b2fe6dcSGreg Clayton if (variable_list) 5728b2fe6dcSGreg Clayton { 5738b2fe6dcSGreg Clayton // If first character is a '*', then show pointer contents 57454979cddSGreg Clayton const char *var_expr = var_expr_cstr; 5758b2fe6dcSGreg Clayton if (var_expr[0] == '*') 5768b2fe6dcSGreg Clayton { 5778b2fe6dcSGreg Clayton deref = true; 5788b2fe6dcSGreg Clayton var_expr++; // Skip the '*' 5798b2fe6dcSGreg Clayton } 5808b2fe6dcSGreg Clayton else if (var_expr[0] == '&') 5818b2fe6dcSGreg Clayton { 5828b2fe6dcSGreg Clayton address_of = true; 5838b2fe6dcSGreg Clayton var_expr++; // Skip the '&' 5848b2fe6dcSGreg Clayton } 5858b2fe6dcSGreg Clayton 5868b2fe6dcSGreg Clayton std::string var_path (var_expr); 58754979cddSGreg Clayton size_t separator_idx = var_path.find_first_of(".-[=+~|&^%#@!/?,<>{}"); 58854979cddSGreg Clayton StreamString var_expr_path_strm; 5898b2fe6dcSGreg Clayton 5908b2fe6dcSGreg Clayton ConstString name_const_string; 5918b2fe6dcSGreg Clayton if (separator_idx == std::string::npos) 5928b2fe6dcSGreg Clayton name_const_string.SetCString (var_path.c_str()); 5938b2fe6dcSGreg Clayton else 5948b2fe6dcSGreg Clayton name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx); 5958b2fe6dcSGreg Clayton 5962837b766SJim Ingham var_sp = variable_list->FindVariable(name_const_string); 597685c88c5SGreg Clayton 598685c88c5SGreg Clayton bool synthetically_added_instance_object = false; 599685c88c5SGreg Clayton 600685c88c5SGreg Clayton if (var_sp) 601685c88c5SGreg Clayton { 602685c88c5SGreg Clayton var_path.erase (0, name_const_string.GetLength ()); 603685c88c5SGreg Clayton } 604685c88c5SGreg Clayton else if (options & eExpressionPathOptionsAllowDirectIVarAccess) 605685c88c5SGreg Clayton { 606685c88c5SGreg Clayton // Check for direct ivars access which helps us with implicit 607685c88c5SGreg Clayton // access to ivars with the "this->" or "self->" 608685c88c5SGreg Clayton GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock); 609685c88c5SGreg Clayton lldb::LanguageType method_language = eLanguageTypeUnknown; 610685c88c5SGreg Clayton bool is_instance_method = false; 611685c88c5SGreg Clayton ConstString method_object_name; 612685c88c5SGreg Clayton if (m_sc.GetFunctionMethodInfo (method_language, is_instance_method, method_object_name)) 613685c88c5SGreg Clayton { 614685c88c5SGreg Clayton if (is_instance_method && method_object_name) 615685c88c5SGreg Clayton { 616685c88c5SGreg Clayton var_sp = variable_list->FindVariable(method_object_name); 617685c88c5SGreg Clayton if (var_sp) 618685c88c5SGreg Clayton { 619685c88c5SGreg Clayton separator_idx = 0; 620685c88c5SGreg Clayton var_path.insert(0, "->"); 621685c88c5SGreg Clayton synthetically_added_instance_object = true; 622685c88c5SGreg Clayton } 623685c88c5SGreg Clayton } 624685c88c5SGreg Clayton } 625685c88c5SGreg Clayton } 626685c88c5SGreg Clayton 6278b2fe6dcSGreg Clayton if (var_sp) 6288b2fe6dcSGreg Clayton { 6292837b766SJim Ingham valobj_sp = GetValueObjectForFrameVariable (var_sp, use_dynamic); 63078a685aaSJim Ingham if (!valobj_sp) 63178a685aaSJim Ingham return valobj_sp; 6328b2fe6dcSGreg Clayton 6338b2fe6dcSGreg Clayton // We are dumping at least one child 6348b2fe6dcSGreg Clayton while (separator_idx != std::string::npos) 6358b2fe6dcSGreg Clayton { 6368b2fe6dcSGreg Clayton // Calculate the next separator index ahead of time 6378b2fe6dcSGreg Clayton ValueObjectSP child_valobj_sp; 6388b2fe6dcSGreg Clayton const char separator_type = var_path[0]; 6398b2fe6dcSGreg Clayton switch (separator_type) 6408b2fe6dcSGreg Clayton { 6418b2fe6dcSGreg Clayton 6428b2fe6dcSGreg Clayton case '-': 6438b2fe6dcSGreg Clayton if (var_path.size() >= 2 && var_path[1] != '>') 6448b2fe6dcSGreg Clayton return ValueObjectSP(); 6458b2fe6dcSGreg Clayton 6466d5e68eaSGreg Clayton if (no_fragile_ivar) 6476d5e68eaSGreg Clayton { 6486d5e68eaSGreg Clayton // Make sure we aren't trying to deref an objective 6496d5e68eaSGreg Clayton // C ivar if this is not allowed 65057ee3067SGreg Clayton const uint32_t pointer_type_flags = valobj_sp->GetClangType().GetTypeInfo (NULL); 65157ee3067SGreg Clayton if ((pointer_type_flags & ClangASTType::eTypeIsObjC) && 65257ee3067SGreg Clayton (pointer_type_flags & ClangASTType::eTypeIsPointer)) 6536d5e68eaSGreg Clayton { 6546d5e68eaSGreg Clayton // This was an objective C object pointer and 6556d5e68eaSGreg Clayton // it was requested we skip any fragile ivars 6566d5e68eaSGreg Clayton // so return nothing here 6576d5e68eaSGreg Clayton return ValueObjectSP(); 6586d5e68eaSGreg Clayton } 6596d5e68eaSGreg Clayton } 6608b2fe6dcSGreg Clayton var_path.erase (0, 1); // Remove the '-' 6618b2fe6dcSGreg Clayton // Fall through 6628b2fe6dcSGreg Clayton case '.': 6638b2fe6dcSGreg Clayton { 66454979cddSGreg Clayton const bool expr_is_ptr = var_path[0] == '>'; 6658b2fe6dcSGreg Clayton 6668b2fe6dcSGreg Clayton var_path.erase (0, 1); // Remove the '.' or '>' 6678b2fe6dcSGreg Clayton separator_idx = var_path.find_first_of(".-["); 6688b2fe6dcSGreg Clayton ConstString child_name; 6698b2fe6dcSGreg Clayton if (separator_idx == std::string::npos) 6708b2fe6dcSGreg Clayton child_name.SetCString (var_path.c_str()); 6718b2fe6dcSGreg Clayton else 6728b2fe6dcSGreg Clayton child_name.SetCStringWithLength(var_path.c_str(), separator_idx); 6738b2fe6dcSGreg Clayton 67454979cddSGreg Clayton if (check_ptr_vs_member) 67554979cddSGreg Clayton { 67654979cddSGreg Clayton // We either have a pointer type and need to verify 67754979cddSGreg Clayton // valobj_sp is a pointer, or we have a member of a 67854979cddSGreg Clayton // class/union/struct being accessed with the . syntax 67954979cddSGreg Clayton // and need to verify we don't have a pointer. 68054979cddSGreg Clayton const bool actual_is_ptr = valobj_sp->IsPointerType (); 68154979cddSGreg Clayton 68254979cddSGreg Clayton if (actual_is_ptr != expr_is_ptr) 68354979cddSGreg Clayton { 68454979cddSGreg Clayton // Incorrect use of "." with a pointer, or "->" with 68554979cddSGreg Clayton // a class/union/struct instance or reference. 6866beaaa68SGreg Clayton valobj_sp->GetExpressionPath (var_expr_path_strm, false); 68754979cddSGreg Clayton if (actual_is_ptr) 68854979cddSGreg Clayton error.SetErrorStringWithFormat ("\"%s\" is a pointer and . was used to attempt to access \"%s\". Did you mean \"%s->%s\"?", 68954979cddSGreg Clayton var_expr_path_strm.GetString().c_str(), 69054979cddSGreg Clayton child_name.GetCString(), 69154979cddSGreg Clayton var_expr_path_strm.GetString().c_str(), 69254979cddSGreg Clayton var_path.c_str()); 69354979cddSGreg Clayton else 69454979cddSGreg Clayton error.SetErrorStringWithFormat ("\"%s\" is not a pointer and -> was used to attempt to access \"%s\". Did you mean \"%s.%s\"?", 69554979cddSGreg Clayton var_expr_path_strm.GetString().c_str(), 69654979cddSGreg Clayton child_name.GetCString(), 69754979cddSGreg Clayton var_expr_path_strm.GetString().c_str(), 69854979cddSGreg Clayton var_path.c_str()); 69954979cddSGreg Clayton return ValueObjectSP(); 70054979cddSGreg Clayton } 70154979cddSGreg Clayton } 7028b2fe6dcSGreg Clayton child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true); 7038b2fe6dcSGreg Clayton if (!child_valobj_sp) 7048b2fe6dcSGreg Clayton { 7058c9d3560SEnrico Granata if (no_synth_child == false) 70686cc9829SEnrico Granata { 70786cc9829SEnrico Granata child_valobj_sp = valobj_sp->GetSyntheticValue(); 70886cc9829SEnrico Granata if (child_valobj_sp) 70986cc9829SEnrico Granata child_valobj_sp = child_valobj_sp->GetChildMemberWithName (child_name, true); 71086cc9829SEnrico Granata } 7118c9d3560SEnrico Granata 7128c9d3560SEnrico Granata if (no_synth_child || !child_valobj_sp) 7138c9d3560SEnrico Granata { 7148b2fe6dcSGreg Clayton // No child member with name "child_name" 715685c88c5SGreg Clayton if (synthetically_added_instance_object) 716685c88c5SGreg Clayton { 717685c88c5SGreg Clayton // We added a "this->" or "self->" to the beginning of the expression 718685c88c5SGreg Clayton // and this is the first pointer ivar access, so just return the normal 719685c88c5SGreg Clayton // error 720685c88c5SGreg Clayton error.SetErrorStringWithFormat("no variable or instance variable named '%s' found in this frame", 721685c88c5SGreg Clayton name_const_string.GetCString()); 722685c88c5SGreg Clayton } 723685c88c5SGreg Clayton else 724685c88c5SGreg Clayton { 7256beaaa68SGreg Clayton valobj_sp->GetExpressionPath (var_expr_path_strm, false); 72654979cddSGreg Clayton if (child_name) 72754979cddSGreg Clayton { 72854979cddSGreg Clayton error.SetErrorStringWithFormat ("\"%s\" is not a member of \"(%s) %s\"", 72954979cddSGreg Clayton child_name.GetCString(), 73054979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 73154979cddSGreg Clayton var_expr_path_strm.GetString().c_str()); 73254979cddSGreg Clayton } 73354979cddSGreg Clayton else 73454979cddSGreg Clayton { 73554979cddSGreg Clayton error.SetErrorStringWithFormat ("incomplete expression path after \"%s\" in \"%s\"", 73654979cddSGreg Clayton var_expr_path_strm.GetString().c_str(), 73754979cddSGreg Clayton var_expr_cstr); 73854979cddSGreg Clayton } 739685c88c5SGreg Clayton } 7408b2fe6dcSGreg Clayton return ValueObjectSP(); 7418b2fe6dcSGreg Clayton } 7428c9d3560SEnrico Granata } 743685c88c5SGreg Clayton synthetically_added_instance_object = false; 7448b2fe6dcSGreg Clayton // Remove the child name from the path 7458b2fe6dcSGreg Clayton var_path.erase(0, child_name.GetLength()); 7464d122c40SGreg Clayton if (use_dynamic != eNoDynamicValues) 74778a685aaSJim Ingham { 7482837b766SJim Ingham ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic)); 74978a685aaSJim Ingham if (dynamic_value_sp) 75078a685aaSJim Ingham child_valobj_sp = dynamic_value_sp; 75178a685aaSJim Ingham } 7528b2fe6dcSGreg Clayton } 7538b2fe6dcSGreg Clayton break; 7548b2fe6dcSGreg Clayton 7558b2fe6dcSGreg Clayton case '[': 7568b2fe6dcSGreg Clayton // Array member access, or treating pointer as an array 7578b2fe6dcSGreg Clayton if (var_path.size() > 2) // Need at least two brackets and a number 7588b2fe6dcSGreg Clayton { 7598b2fe6dcSGreg Clayton char *end = NULL; 7601a65ae11SGreg Clayton long child_index = ::strtol (&var_path[1], &end, 0); 7619fc1944eSEnrico Granata if (end && *end == ']' 7629fc1944eSEnrico Granata && *(end-1) != '[') // this code forces an error in the case of arr[]. as bitfield[] is not a good syntax we're good to go 7638b2fe6dcSGreg Clayton { 76457ee3067SGreg Clayton if (valobj_sp->GetClangType().IsPointerToScalarType() && deref) 7659fc1944eSEnrico Granata { 7669fc1944eSEnrico Granata // what we have is *ptr[low]. the most similar C++ syntax is to deref ptr 7679fc1944eSEnrico Granata // and extract bit low out of it. reading array item low 7689fc1944eSEnrico Granata // would be done by saying ptr[low], without a deref * sign 7699fc1944eSEnrico Granata Error error; 7709fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->Dereference(error)); 7719fc1944eSEnrico Granata if (error.Fail()) 7729fc1944eSEnrico Granata { 7739fc1944eSEnrico Granata valobj_sp->GetExpressionPath (var_expr_path_strm, false); 7749fc1944eSEnrico Granata error.SetErrorStringWithFormat ("could not dereference \"(%s) %s\"", 7759fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 7769fc1944eSEnrico Granata var_expr_path_strm.GetString().c_str()); 7779fc1944eSEnrico Granata return ValueObjectSP(); 7789fc1944eSEnrico Granata } 7799fc1944eSEnrico Granata valobj_sp = temp; 7809fc1944eSEnrico Granata deref = false; 7819fc1944eSEnrico Granata } 78257ee3067SGreg Clayton else if (valobj_sp->GetClangType().IsArrayOfScalarType() && deref) 7839fc1944eSEnrico Granata { 7849fc1944eSEnrico Granata // what we have is *arr[low]. the most similar C++ syntax is to get arr[0] 7859fc1944eSEnrico Granata // (an operation that is equivalent to deref-ing arr) 7869fc1944eSEnrico Granata // and extract bit low out of it. reading array item low 7879fc1944eSEnrico Granata // would be done by saying arr[low], without a deref * sign 7889fc1944eSEnrico Granata Error error; 7899fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->GetChildAtIndex (0, true)); 7909fc1944eSEnrico Granata if (error.Fail()) 7919fc1944eSEnrico Granata { 7929fc1944eSEnrico Granata valobj_sp->GetExpressionPath (var_expr_path_strm, false); 7939fc1944eSEnrico Granata error.SetErrorStringWithFormat ("could not get item 0 for \"(%s) %s\"", 7949fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 7959fc1944eSEnrico Granata var_expr_path_strm.GetString().c_str()); 7969fc1944eSEnrico Granata return ValueObjectSP(); 7979fc1944eSEnrico Granata } 7989fc1944eSEnrico Granata valobj_sp = temp; 7999fc1944eSEnrico Granata deref = false; 8009fc1944eSEnrico Granata } 8018b2fe6dcSGreg Clayton 8024ef877f5SGreg Clayton bool is_incomplete_array = false; 8038b2fe6dcSGreg Clayton if (valobj_sp->IsPointerType ()) 8048b2fe6dcSGreg Clayton { 805226b70c1SSean Callanan bool is_objc_pointer = true; 806226b70c1SSean Callanan 80757ee3067SGreg Clayton if (valobj_sp->GetClangType().GetMinimumLanguage() != eLanguageTypeObjC) 808226b70c1SSean Callanan is_objc_pointer = false; 80957ee3067SGreg Clayton else if (!valobj_sp->GetClangType().IsPointerType()) 810226b70c1SSean Callanan is_objc_pointer = false; 811226b70c1SSean Callanan 812226b70c1SSean Callanan if (no_synth_child && is_objc_pointer) 813226b70c1SSean Callanan { 814226b70c1SSean Callanan error.SetErrorStringWithFormat("\"(%s) %s\" is an Objective-C pointer, and cannot be subscripted", 815226b70c1SSean Callanan valobj_sp->GetTypeName().AsCString("<invalid type>"), 816226b70c1SSean Callanan var_expr_path_strm.GetString().c_str()); 817226b70c1SSean Callanan 818226b70c1SSean Callanan return ValueObjectSP(); 819226b70c1SSean Callanan } 820226b70c1SSean Callanan else if (is_objc_pointer) 82127b625e1SEnrico Granata { 82227b625e1SEnrico Granata // dereferencing ObjC variables is not valid.. so let's try and recur to synthetic children 82386cc9829SEnrico Granata ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); 82427b625e1SEnrico Granata if (synthetic.get() == NULL /* no synthetic */ 82527b625e1SEnrico Granata || synthetic == valobj_sp) /* synthetic is the same as the original object */ 82627b625e1SEnrico Granata { 82727b625e1SEnrico Granata valobj_sp->GetExpressionPath (var_expr_path_strm, false); 82827b625e1SEnrico Granata error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type", 82927b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 83027b625e1SEnrico Granata var_expr_path_strm.GetString().c_str()); 83127b625e1SEnrico Granata } 83227b625e1SEnrico Granata else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */) 83327b625e1SEnrico Granata { 83427b625e1SEnrico Granata valobj_sp->GetExpressionPath (var_expr_path_strm, false); 8357e589a60SJason Molenda error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"", 83627b625e1SEnrico Granata child_index, 83727b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 83827b625e1SEnrico Granata var_expr_path_strm.GetString().c_str()); 83927b625e1SEnrico Granata } 84027b625e1SEnrico Granata else 84127b625e1SEnrico Granata { 84227b625e1SEnrico Granata child_valobj_sp = synthetic->GetChildAtIndex(child_index, true); 84327b625e1SEnrico Granata if (!child_valobj_sp) 84427b625e1SEnrico Granata { 84527b625e1SEnrico Granata valobj_sp->GetExpressionPath (var_expr_path_strm, false); 8467e589a60SJason Molenda error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"", 84727b625e1SEnrico Granata child_index, 84827b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 84927b625e1SEnrico Granata var_expr_path_strm.GetString().c_str()); 85027b625e1SEnrico Granata } 85127b625e1SEnrico Granata } 85227b625e1SEnrico Granata } 85327b625e1SEnrico Granata else 85427b625e1SEnrico Granata { 8558b2fe6dcSGreg Clayton child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true); 85654979cddSGreg Clayton if (!child_valobj_sp) 85754979cddSGreg Clayton { 8586beaaa68SGreg Clayton valobj_sp->GetExpressionPath (var_expr_path_strm, false); 8597e589a60SJason Molenda error.SetErrorStringWithFormat ("failed to use pointer as array for index %ld for \"(%s) %s\"", 86054979cddSGreg Clayton child_index, 86154979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 86254979cddSGreg Clayton var_expr_path_strm.GetString().c_str()); 86354979cddSGreg Clayton } 86454979cddSGreg Clayton } 86527b625e1SEnrico Granata } 86657ee3067SGreg Clayton else if (valobj_sp->GetClangType().IsArrayType (NULL, NULL, &is_incomplete_array)) 86754979cddSGreg Clayton { 86878a685aaSJim Ingham // Pass false to dynamic_value here so we can tell the difference between 86978a685aaSJim Ingham // no dynamic value and no member of this type... 87054979cddSGreg Clayton child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true); 8714ef877f5SGreg Clayton if (!child_valobj_sp && (is_incomplete_array || no_synth_child == false)) 8724ef877f5SGreg Clayton child_valobj_sp = valobj_sp->GetSyntheticArrayMember (child_index, true); 8734ef877f5SGreg Clayton 87454979cddSGreg Clayton if (!child_valobj_sp) 87554979cddSGreg Clayton { 8766beaaa68SGreg Clayton valobj_sp->GetExpressionPath (var_expr_path_strm, false); 8777e589a60SJason Molenda error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"", 87854979cddSGreg Clayton child_index, 87954979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 88054979cddSGreg Clayton var_expr_path_strm.GetString().c_str()); 88154979cddSGreg Clayton } 8828b2fe6dcSGreg Clayton } 88357ee3067SGreg Clayton else if (valobj_sp->GetClangType().IsScalarType()) 8849fc1944eSEnrico Granata { 8859fc1944eSEnrico Granata // this is a bitfield asking to display just one bit 8869fc1944eSEnrico Granata child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, child_index, true); 8879fc1944eSEnrico Granata if (!child_valobj_sp) 8889fc1944eSEnrico Granata { 8899fc1944eSEnrico Granata valobj_sp->GetExpressionPath (var_expr_path_strm, false); 8907e589a60SJason Molenda error.SetErrorStringWithFormat ("bitfield range %ld-%ld is not valid for \"(%s) %s\"", 8919fc1944eSEnrico Granata child_index, child_index, 8929fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 8939fc1944eSEnrico Granata var_expr_path_strm.GetString().c_str()); 8949fc1944eSEnrico Granata } 8959fc1944eSEnrico Granata } 8968b2fe6dcSGreg Clayton else 8978b2fe6dcSGreg Clayton { 89886cc9829SEnrico Granata ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); 89927b625e1SEnrico Granata if (no_synth_child /* synthetic is forbidden */ || 90027b625e1SEnrico Granata synthetic.get() == NULL /* no synthetic */ 90127b625e1SEnrico Granata || synthetic == valobj_sp) /* synthetic is the same as the original object */ 90227b625e1SEnrico Granata { 9036beaaa68SGreg Clayton valobj_sp->GetExpressionPath (var_expr_path_strm, false); 90454979cddSGreg Clayton error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type", 90554979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 90654979cddSGreg Clayton var_expr_path_strm.GetString().c_str()); 9078b2fe6dcSGreg Clayton } 90827b625e1SEnrico Granata else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */) 90927b625e1SEnrico Granata { 91027b625e1SEnrico Granata valobj_sp->GetExpressionPath (var_expr_path_strm, false); 9117e589a60SJason Molenda error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"", 91227b625e1SEnrico Granata child_index, 91327b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 91427b625e1SEnrico Granata var_expr_path_strm.GetString().c_str()); 91527b625e1SEnrico Granata } 91627b625e1SEnrico Granata else 91727b625e1SEnrico Granata { 91827b625e1SEnrico Granata child_valobj_sp = synthetic->GetChildAtIndex(child_index, true); 91927b625e1SEnrico Granata if (!child_valobj_sp) 92027b625e1SEnrico Granata { 92127b625e1SEnrico Granata valobj_sp->GetExpressionPath (var_expr_path_strm, false); 9227e589a60SJason Molenda error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"", 92327b625e1SEnrico Granata child_index, 92427b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 92527b625e1SEnrico Granata var_expr_path_strm.GetString().c_str()); 92627b625e1SEnrico Granata } 92727b625e1SEnrico Granata } 92827b625e1SEnrico Granata } 9298b2fe6dcSGreg Clayton 9308b2fe6dcSGreg Clayton if (!child_valobj_sp) 9318b2fe6dcSGreg Clayton { 9328b2fe6dcSGreg Clayton // Invalid array index... 9338b2fe6dcSGreg Clayton return ValueObjectSP(); 9348b2fe6dcSGreg Clayton } 9358b2fe6dcSGreg Clayton 9368b2fe6dcSGreg Clayton // Erase the array member specification '[%i]' where 9378b2fe6dcSGreg Clayton // %i is the array index 9388b2fe6dcSGreg Clayton var_path.erase(0, (end - var_path.c_str()) + 1); 9398b2fe6dcSGreg Clayton separator_idx = var_path.find_first_of(".-["); 9404d122c40SGreg Clayton if (use_dynamic != eNoDynamicValues) 94178a685aaSJim Ingham { 9422837b766SJim Ingham ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic)); 94378a685aaSJim Ingham if (dynamic_value_sp) 94478a685aaSJim Ingham child_valobj_sp = dynamic_value_sp; 94578a685aaSJim Ingham } 9468b2fe6dcSGreg Clayton // Break out early from the switch since we were 9478b2fe6dcSGreg Clayton // able to find the child member 9488b2fe6dcSGreg Clayton break; 9498b2fe6dcSGreg Clayton } 9509fc1944eSEnrico Granata else if (end && *end == '-') 9519fc1944eSEnrico Granata { 9529fc1944eSEnrico Granata // this is most probably a BitField, let's take a look 9539fc1944eSEnrico Granata char *real_end = NULL; 9549fc1944eSEnrico Granata long final_index = ::strtol (end+1, &real_end, 0); 955d64d0bc0SEnrico Granata bool expand_bitfield = true; 9569fc1944eSEnrico Granata if (real_end && *real_end == ']') 9579fc1944eSEnrico Granata { 9589fc1944eSEnrico Granata // if the format given is [high-low], swap range 9599fc1944eSEnrico Granata if (child_index > final_index) 9609fc1944eSEnrico Granata { 9619fc1944eSEnrico Granata long temp = child_index; 9629fc1944eSEnrico Granata child_index = final_index; 9639fc1944eSEnrico Granata final_index = temp; 9649fc1944eSEnrico Granata } 9659fc1944eSEnrico Granata 96657ee3067SGreg Clayton if (valobj_sp->GetClangType().IsPointerToScalarType() && deref) 9679fc1944eSEnrico Granata { 9689fc1944eSEnrico Granata // what we have is *ptr[low-high]. the most similar C++ syntax is to deref ptr 9699fc1944eSEnrico Granata // and extract bits low thru high out of it. reading array items low thru high 9709fc1944eSEnrico Granata // would be done by saying ptr[low-high], without a deref * sign 9719fc1944eSEnrico Granata Error error; 9729fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->Dereference(error)); 9739fc1944eSEnrico Granata if (error.Fail()) 9749fc1944eSEnrico Granata { 9759fc1944eSEnrico Granata valobj_sp->GetExpressionPath (var_expr_path_strm, false); 9769fc1944eSEnrico Granata error.SetErrorStringWithFormat ("could not dereference \"(%s) %s\"", 9779fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 9789fc1944eSEnrico Granata var_expr_path_strm.GetString().c_str()); 9799fc1944eSEnrico Granata return ValueObjectSP(); 9809fc1944eSEnrico Granata } 9819fc1944eSEnrico Granata valobj_sp = temp; 9829fc1944eSEnrico Granata deref = false; 9839fc1944eSEnrico Granata } 98457ee3067SGreg Clayton else if (valobj_sp->GetClangType().IsArrayOfScalarType() && deref) 9859fc1944eSEnrico Granata { 9869fc1944eSEnrico Granata // what we have is *arr[low-high]. the most similar C++ syntax is to get arr[0] 9879fc1944eSEnrico Granata // (an operation that is equivalent to deref-ing arr) 9889fc1944eSEnrico Granata // and extract bits low thru high out of it. reading array items low thru high 9899fc1944eSEnrico Granata // would be done by saying arr[low-high], without a deref * sign 9909fc1944eSEnrico Granata Error error; 9919fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->GetChildAtIndex (0, true)); 9929fc1944eSEnrico Granata if (error.Fail()) 9939fc1944eSEnrico Granata { 9949fc1944eSEnrico Granata valobj_sp->GetExpressionPath (var_expr_path_strm, false); 9959fc1944eSEnrico Granata error.SetErrorStringWithFormat ("could not get item 0 for \"(%s) %s\"", 9969fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 9979fc1944eSEnrico Granata var_expr_path_strm.GetString().c_str()); 9989fc1944eSEnrico Granata return ValueObjectSP(); 9999fc1944eSEnrico Granata } 10009fc1944eSEnrico Granata valobj_sp = temp; 10019fc1944eSEnrico Granata deref = false; 10029fc1944eSEnrico Granata } 1003d64d0bc0SEnrico Granata /*else if (valobj_sp->IsArrayType() || valobj_sp->IsPointerType()) 1004d64d0bc0SEnrico Granata { 1005d64d0bc0SEnrico Granata child_valobj_sp = valobj_sp->GetSyntheticArrayRangeChild(child_index, final_index, true); 1006d64d0bc0SEnrico Granata expand_bitfield = false; 1007d64d0bc0SEnrico Granata if (!child_valobj_sp) 1008d64d0bc0SEnrico Granata { 1009d64d0bc0SEnrico Granata valobj_sp->GetExpressionPath (var_expr_path_strm, false); 1010d64d0bc0SEnrico Granata error.SetErrorStringWithFormat ("array range %i-%i is not valid for \"(%s) %s\"", 1011d64d0bc0SEnrico Granata child_index, final_index, 1012d64d0bc0SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 1013d64d0bc0SEnrico Granata var_expr_path_strm.GetString().c_str()); 1014d64d0bc0SEnrico Granata } 1015d64d0bc0SEnrico Granata }*/ 10169fc1944eSEnrico Granata 1017d64d0bc0SEnrico Granata if (expand_bitfield) 1018d64d0bc0SEnrico Granata { 10199fc1944eSEnrico Granata child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true); 10209fc1944eSEnrico Granata if (!child_valobj_sp) 10219fc1944eSEnrico Granata { 10229fc1944eSEnrico Granata valobj_sp->GetExpressionPath (var_expr_path_strm, false); 10237e589a60SJason Molenda error.SetErrorStringWithFormat ("bitfield range %ld-%ld is not valid for \"(%s) %s\"", 10249fc1944eSEnrico Granata child_index, final_index, 10259fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 10269fc1944eSEnrico Granata var_expr_path_strm.GetString().c_str()); 10279fc1944eSEnrico Granata } 10289fc1944eSEnrico Granata } 1029d64d0bc0SEnrico Granata } 10309fc1944eSEnrico Granata 10319fc1944eSEnrico Granata if (!child_valobj_sp) 10329fc1944eSEnrico Granata { 10339fc1944eSEnrico Granata // Invalid bitfield range... 10349fc1944eSEnrico Granata return ValueObjectSP(); 10359fc1944eSEnrico Granata } 10369fc1944eSEnrico Granata 10379fc1944eSEnrico Granata // Erase the bitfield member specification '[%i-%i]' where 10389fc1944eSEnrico Granata // %i is the index 10399fc1944eSEnrico Granata var_path.erase(0, (real_end - var_path.c_str()) + 1); 10409fc1944eSEnrico Granata separator_idx = var_path.find_first_of(".-["); 10414d122c40SGreg Clayton if (use_dynamic != eNoDynamicValues) 10429fc1944eSEnrico Granata { 10439fc1944eSEnrico Granata ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic)); 10449fc1944eSEnrico Granata if (dynamic_value_sp) 10459fc1944eSEnrico Granata child_valobj_sp = dynamic_value_sp; 10469fc1944eSEnrico Granata } 10479fc1944eSEnrico Granata // Break out early from the switch since we were 10489fc1944eSEnrico Granata // able to find the child member 10499fc1944eSEnrico Granata break; 10509fc1944eSEnrico Granata 10519fc1944eSEnrico Granata } 10529fc1944eSEnrico Granata } 10539fc1944eSEnrico Granata else 10549fc1944eSEnrico Granata { 10559fc1944eSEnrico Granata error.SetErrorStringWithFormat("invalid square bracket encountered after \"%s\" in \"%s\"", 10569fc1944eSEnrico Granata var_expr_path_strm.GetString().c_str(), 10579fc1944eSEnrico Granata var_path.c_str()); 10588b2fe6dcSGreg Clayton } 10598b2fe6dcSGreg Clayton return ValueObjectSP(); 10608b2fe6dcSGreg Clayton 10618b2fe6dcSGreg Clayton default: 10628b2fe6dcSGreg Clayton // Failure... 106354979cddSGreg Clayton { 10646beaaa68SGreg Clayton valobj_sp->GetExpressionPath (var_expr_path_strm, false); 106554979cddSGreg Clayton error.SetErrorStringWithFormat ("unexpected char '%c' encountered after \"%s\" in \"%s\"", 106654979cddSGreg Clayton separator_type, 106754979cddSGreg Clayton var_expr_path_strm.GetString().c_str(), 106854979cddSGreg Clayton var_path.c_str()); 106954979cddSGreg Clayton 10708b2fe6dcSGreg Clayton return ValueObjectSP(); 10718b2fe6dcSGreg Clayton } 107254979cddSGreg Clayton } 10738b2fe6dcSGreg Clayton 10748b2fe6dcSGreg Clayton if (child_valobj_sp) 10758b2fe6dcSGreg Clayton valobj_sp = child_valobj_sp; 10768b2fe6dcSGreg Clayton 10778b2fe6dcSGreg Clayton if (var_path.empty()) 10788b2fe6dcSGreg Clayton break; 10798b2fe6dcSGreg Clayton 10808b2fe6dcSGreg Clayton } 10818b2fe6dcSGreg Clayton if (valobj_sp) 10828b2fe6dcSGreg Clayton { 10838b2fe6dcSGreg Clayton if (deref) 10848b2fe6dcSGreg Clayton { 1085af67cecdSGreg Clayton ValueObjectSP deref_valobj_sp (valobj_sp->Dereference(error)); 10868b2fe6dcSGreg Clayton valobj_sp = deref_valobj_sp; 10878b2fe6dcSGreg Clayton } 10888b2fe6dcSGreg Clayton else if (address_of) 10898b2fe6dcSGreg Clayton { 109054979cddSGreg Clayton ValueObjectSP address_of_valobj_sp (valobj_sp->AddressOf(error)); 10918b2fe6dcSGreg Clayton valobj_sp = address_of_valobj_sp; 10928b2fe6dcSGreg Clayton } 10938b2fe6dcSGreg Clayton } 10948b2fe6dcSGreg Clayton return valobj_sp; 10958b2fe6dcSGreg Clayton } 109654979cddSGreg Clayton else 109754979cddSGreg Clayton { 10982837b766SJim Ingham error.SetErrorStringWithFormat("no variable named '%s' found in this frame", 10992837b766SJim Ingham name_const_string.GetCString()); 110054979cddSGreg Clayton } 110154979cddSGreg Clayton } 110254979cddSGreg Clayton } 110354979cddSGreg Clayton else 110454979cddSGreg Clayton { 110554979cddSGreg Clayton error.SetErrorStringWithFormat("invalid variable path '%s'", var_expr_cstr); 11068b2fe6dcSGreg Clayton } 11078b2fe6dcSGreg Clayton return ValueObjectSP(); 11088b2fe6dcSGreg Clayton } 110930fdc8d8SChris Lattner 111030fdc8d8SChris Lattner bool 111130fdc8d8SChris Lattner StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr) 111230fdc8d8SChris Lattner { 111330fdc8d8SChris Lattner if (m_flags.IsClear(GOT_FRAME_BASE)) 111430fdc8d8SChris Lattner { 111530fdc8d8SChris Lattner if (m_sc.function) 111630fdc8d8SChris Lattner { 111730fdc8d8SChris Lattner m_frame_base.Clear(); 111830fdc8d8SChris Lattner m_frame_base_error.Clear(); 111930fdc8d8SChris Lattner 112030fdc8d8SChris Lattner m_flags.Set(GOT_FRAME_BASE); 1121d9e416c0SGreg Clayton ExecutionContext exe_ctx (shared_from_this()); 112230fdc8d8SChris Lattner Value expr_value; 1123016a95ebSGreg Clayton addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; 1124016a95ebSGreg Clayton if (m_sc.function->GetFrameBaseExpression().IsLocationList()) 1125d9e416c0SGreg Clayton loclist_base_addr = m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (exe_ctx.GetTargetPtr()); 1126016a95ebSGreg Clayton 112757ee3067SGreg Clayton if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, NULL, NULL, loclist_base_addr, NULL, expr_value, &m_frame_base_error) == false) 112830fdc8d8SChris Lattner { 112930fdc8d8SChris Lattner // We should really have an error if evaluate returns, but in case 113030fdc8d8SChris Lattner // we don't, lets set the error to something at least. 113130fdc8d8SChris Lattner if (m_frame_base_error.Success()) 113230fdc8d8SChris Lattner m_frame_base_error.SetErrorString("Evaluation of the frame base expression failed."); 113330fdc8d8SChris Lattner } 113430fdc8d8SChris Lattner else 113530fdc8d8SChris Lattner { 113657ee3067SGreg Clayton m_frame_base = expr_value.ResolveValue(&exe_ctx); 113730fdc8d8SChris Lattner } 113830fdc8d8SChris Lattner } 113930fdc8d8SChris Lattner else 114030fdc8d8SChris Lattner { 114130fdc8d8SChris Lattner m_frame_base_error.SetErrorString ("No function in symbol context."); 114230fdc8d8SChris Lattner } 114330fdc8d8SChris Lattner } 114430fdc8d8SChris Lattner 114530fdc8d8SChris Lattner if (m_frame_base_error.Success()) 114630fdc8d8SChris Lattner frame_base = m_frame_base; 114730fdc8d8SChris Lattner 114830fdc8d8SChris Lattner if (error_ptr) 114930fdc8d8SChris Lattner *error_ptr = m_frame_base_error; 115030fdc8d8SChris Lattner return m_frame_base_error.Success(); 115130fdc8d8SChris Lattner } 115230fdc8d8SChris Lattner 11535ccbd294SGreg Clayton RegisterContextSP 115430fdc8d8SChris Lattner StackFrame::GetRegisterContext () 115530fdc8d8SChris Lattner { 11565ccbd294SGreg Clayton if (!m_reg_context_sp) 1157d9e416c0SGreg Clayton { 1158d9e416c0SGreg Clayton ThreadSP thread_sp (GetThread()); 1159d9e416c0SGreg Clayton if (thread_sp) 1160d9e416c0SGreg Clayton m_reg_context_sp = thread_sp->CreateRegisterContextForFrame (this); 1161d9e416c0SGreg Clayton } 11625ccbd294SGreg Clayton return m_reg_context_sp; 116330fdc8d8SChris Lattner } 116430fdc8d8SChris Lattner 116530fdc8d8SChris Lattner bool 116630fdc8d8SChris Lattner StackFrame::HasDebugInformation () 116730fdc8d8SChris Lattner { 116830fdc8d8SChris Lattner GetSymbolContext (eSymbolContextLineEntry); 116930fdc8d8SChris Lattner return m_sc.line_entry.IsValid(); 117030fdc8d8SChris Lattner } 117130fdc8d8SChris Lattner 1172288bdf9cSGreg Clayton 1173288bdf9cSGreg Clayton ValueObjectSP 11744d122c40SGreg Clayton StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic) 117530fdc8d8SChris Lattner { 1176288bdf9cSGreg Clayton ValueObjectSP valobj_sp; 1177288bdf9cSGreg Clayton VariableList *var_list = GetVariableList (true); 1178288bdf9cSGreg Clayton if (var_list) 1179288bdf9cSGreg Clayton { 1180288bdf9cSGreg Clayton // Make sure the variable is a frame variable 1181288bdf9cSGreg Clayton const uint32_t var_idx = var_list->FindIndexForVariable (variable_sp.get()); 1182288bdf9cSGreg Clayton const uint32_t num_variables = var_list->GetSize(); 1183288bdf9cSGreg Clayton if (var_idx < num_variables) 1184288bdf9cSGreg Clayton { 1185288bdf9cSGreg Clayton valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex (var_idx); 1186288bdf9cSGreg Clayton if (valobj_sp.get() == NULL) 1187288bdf9cSGreg Clayton { 1188288bdf9cSGreg Clayton if (m_variable_list_value_objects.GetSize() < num_variables) 1189288bdf9cSGreg Clayton m_variable_list_value_objects.Resize(num_variables); 119058b59f95SJim Ingham valobj_sp = ValueObjectVariable::Create (this, variable_sp); 1191288bdf9cSGreg Clayton m_variable_list_value_objects.SetValueObjectAtIndex (var_idx, valobj_sp); 1192288bdf9cSGreg Clayton } 1193288bdf9cSGreg Clayton } 1194288bdf9cSGreg Clayton } 11954d122c40SGreg Clayton if (use_dynamic != eNoDynamicValues && valobj_sp) 119678a685aaSJim Ingham { 11972837b766SJim Ingham ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue (use_dynamic); 119878a685aaSJim Ingham if (dynamic_sp) 119978a685aaSJim Ingham return dynamic_sp; 120078a685aaSJim Ingham } 1201288bdf9cSGreg Clayton return valobj_sp; 1202288bdf9cSGreg Clayton } 1203288bdf9cSGreg Clayton 1204288bdf9cSGreg Clayton ValueObjectSP 12054d122c40SGreg Clayton StackFrame::TrackGlobalVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic) 1206288bdf9cSGreg Clayton { 1207288bdf9cSGreg Clayton // Check to make sure we aren't already tracking this variable? 120878a685aaSJim Ingham ValueObjectSP valobj_sp (GetValueObjectForFrameVariable (variable_sp, use_dynamic)); 1209288bdf9cSGreg Clayton if (!valobj_sp) 1210288bdf9cSGreg Clayton { 1211288bdf9cSGreg Clayton // We aren't already tracking this global 1212288bdf9cSGreg Clayton VariableList *var_list = GetVariableList (true); 1213288bdf9cSGreg Clayton // If this frame has no variables, create a new list 1214288bdf9cSGreg Clayton if (var_list == NULL) 1215288bdf9cSGreg Clayton m_variable_list_sp.reset (new VariableList()); 1216288bdf9cSGreg Clayton 1217288bdf9cSGreg Clayton // Add the global/static variable to this frame 1218288bdf9cSGreg Clayton m_variable_list_sp->AddVariable (variable_sp); 1219288bdf9cSGreg Clayton 1220288bdf9cSGreg Clayton // Now make a value object for it so we can track its changes 122178a685aaSJim Ingham valobj_sp = GetValueObjectForFrameVariable (variable_sp, use_dynamic); 1222288bdf9cSGreg Clayton } 1223288bdf9cSGreg Clayton return valobj_sp; 122430fdc8d8SChris Lattner } 122530fdc8d8SChris Lattner 12266b8379c4SJim Ingham bool 12276b8379c4SJim Ingham StackFrame::IsInlined () 12286b8379c4SJim Ingham { 122959e8fc1cSGreg Clayton if (m_sc.block == NULL) 123059e8fc1cSGreg Clayton GetSymbolContext (eSymbolContextBlock); 123159e8fc1cSGreg Clayton if (m_sc.block) 123259e8fc1cSGreg Clayton return m_sc.block->GetContainingInlinedBlock() != NULL; 123359e8fc1cSGreg Clayton return false; 12346b8379c4SJim Ingham } 12356b8379c4SJim Ingham 1236d9e416c0SGreg Clayton TargetSP 123730fdc8d8SChris Lattner StackFrame::CalculateTarget () 123830fdc8d8SChris Lattner { 1239d9e416c0SGreg Clayton TargetSP target_sp; 1240d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 1241d9e416c0SGreg Clayton if (thread_sp) 1242d9e416c0SGreg Clayton { 1243d9e416c0SGreg Clayton ProcessSP process_sp (thread_sp->CalculateProcess()); 1244d9e416c0SGreg Clayton if (process_sp) 1245d9e416c0SGreg Clayton target_sp = process_sp->CalculateTarget(); 1246d9e416c0SGreg Clayton } 1247d9e416c0SGreg Clayton return target_sp; 124830fdc8d8SChris Lattner } 124930fdc8d8SChris Lattner 1250d9e416c0SGreg Clayton ProcessSP 125130fdc8d8SChris Lattner StackFrame::CalculateProcess () 125230fdc8d8SChris Lattner { 1253d9e416c0SGreg Clayton ProcessSP process_sp; 1254d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 1255d9e416c0SGreg Clayton if (thread_sp) 1256d9e416c0SGreg Clayton process_sp = thread_sp->CalculateProcess(); 1257d9e416c0SGreg Clayton return process_sp; 125830fdc8d8SChris Lattner } 125930fdc8d8SChris Lattner 1260d9e416c0SGreg Clayton ThreadSP 126130fdc8d8SChris Lattner StackFrame::CalculateThread () 126230fdc8d8SChris Lattner { 1263d9e416c0SGreg Clayton return GetThread(); 126430fdc8d8SChris Lattner } 126530fdc8d8SChris Lattner 1266*f23bf743SJason Molenda FrameSP 1267*f23bf743SJason Molenda StackFrame::CalculateFrame () 126830fdc8d8SChris Lattner { 1269d9e416c0SGreg Clayton return shared_from_this(); 127030fdc8d8SChris Lattner } 127130fdc8d8SChris Lattner 127230fdc8d8SChris Lattner 127330fdc8d8SChris Lattner void 12740603aa9dSGreg Clayton StackFrame::CalculateExecutionContext (ExecutionContext &exe_ctx) 127530fdc8d8SChris Lattner { 1276d9e416c0SGreg Clayton exe_ctx.SetContext (shared_from_this()); 127730fdc8d8SChris Lattner } 127830fdc8d8SChris Lattner 127930fdc8d8SChris Lattner void 12808ec10efcSJim Ingham StackFrame::DumpUsingSettingsFormat (Stream *strm, const char *frame_marker) 12810603aa9dSGreg Clayton { 12820603aa9dSGreg Clayton if (strm == NULL) 12830603aa9dSGreg Clayton return; 12840603aa9dSGreg Clayton 12850603aa9dSGreg Clayton GetSymbolContext(eSymbolContextEverything); 1286d9e416c0SGreg Clayton ExecutionContext exe_ctx (shared_from_this()); 12870603aa9dSGreg Clayton StreamString s; 12888ec10efcSJim Ingham 12898ec10efcSJim Ingham if (frame_marker) 12908ec10efcSJim Ingham s.PutCString(frame_marker); 12918ec10efcSJim Ingham 1292d9e416c0SGreg Clayton const char *frame_format = NULL; 1293d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 1294d9e416c0SGreg Clayton if (target) 1295d9e416c0SGreg Clayton frame_format = target->GetDebugger().GetFrameFormat(); 1296c3ce7f27SMichael Sartain if (frame_format && Debugger::FormatPrompt (frame_format, &m_sc, &exe_ctx, NULL, s)) 12970603aa9dSGreg Clayton { 12980603aa9dSGreg Clayton strm->Write(s.GetData(), s.GetSize()); 12990603aa9dSGreg Clayton } 13000603aa9dSGreg Clayton else 13010603aa9dSGreg Clayton { 13020603aa9dSGreg Clayton Dump (strm, true, false); 13030603aa9dSGreg Clayton strm->EOL(); 13040603aa9dSGreg Clayton } 13050603aa9dSGreg Clayton } 13060603aa9dSGreg Clayton 13070603aa9dSGreg Clayton void 13086dadd508SGreg Clayton StackFrame::Dump (Stream *strm, bool show_frame_index, bool show_fullpaths) 130930fdc8d8SChris Lattner { 131030fdc8d8SChris Lattner if (strm == NULL) 131130fdc8d8SChris Lattner return; 131230fdc8d8SChris Lattner 131330fdc8d8SChris Lattner if (show_frame_index) 13141b72fcb7SGreg Clayton strm->Printf("frame #%u: ", m_frame_index); 1315d9e416c0SGreg Clayton ExecutionContext exe_ctx (shared_from_this()); 1316d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 1317d01b2953SDaniel Malea strm->Printf("0x%0*" PRIx64 " ", 1318d9e416c0SGreg Clayton target ? (target->GetArchitecture().GetAddressByteSize() * 2) : 16, 1319d9e416c0SGreg Clayton GetFrameCodeAddress().GetLoadAddress(target)); 13209da7bd07SGreg Clayton GetSymbolContext(eSymbolContextEverything); 13211b72fcb7SGreg Clayton const bool show_module = true; 13221b72fcb7SGreg Clayton const bool show_inline = true; 1323d9e416c0SGreg Clayton m_sc.DumpStopContext (strm, 1324d9e416c0SGreg Clayton exe_ctx.GetBestExecutionContextScope(), 1325d9e416c0SGreg Clayton GetFrameCodeAddress(), 1326d9e416c0SGreg Clayton show_fullpaths, 1327d9e416c0SGreg Clayton show_module, 1328d9e416c0SGreg Clayton show_inline); 132930fdc8d8SChris Lattner } 133030fdc8d8SChris Lattner 13315082c5fdSGreg Clayton void 1332*f23bf743SJason Molenda StackFrame::UpdateCurrentFrameFromPreviousFrame (Frame &prev_frame) 13335082c5fdSGreg Clayton { 133459e8fc1cSGreg Clayton assert (GetStackID() == prev_frame.GetStackID()); // TODO: remove this after some testing 1335*f23bf743SJason Molenda if (strcmp (prev_frame.GetFrameType(), "StackFrame") == 0) 1336*f23bf743SJason Molenda { 1337*f23bf743SJason Molenda StackFrame &prev_stackframe = *static_cast<StackFrame*>(&prev_frame); 1338*f23bf743SJason Molenda m_variable_list_sp = prev_stackframe.m_variable_list_sp; 1339*f23bf743SJason Molenda m_variable_list_value_objects.Swap (prev_stackframe.m_variable_list_value_objects); 134068275d5eSGreg Clayton if (!m_disassembly.GetString().empty()) 134168275d5eSGreg Clayton m_disassembly.GetString().swap (m_disassembly.GetString()); 13425082c5fdSGreg Clayton } 1343*f23bf743SJason Molenda } 134468275d5eSGreg Clayton 134568275d5eSGreg Clayton 134659e8fc1cSGreg Clayton void 1347*f23bf743SJason Molenda StackFrame::UpdatePreviousFrameFromCurrentFrame (Frame &curr_frame) 134859e8fc1cSGreg Clayton { 134959e8fc1cSGreg Clayton assert (GetStackID() == curr_frame.GetStackID()); // TODO: remove this after some testing 1350*f23bf743SJason Molenda if (strcmp (curr_frame.GetFrameType(), "StackFrame") == 0) 1351*f23bf743SJason Molenda { 1352*f23bf743SJason Molenda StackFrame &curr_stackframe = *static_cast<StackFrame*>(&curr_frame); 1353*f23bf743SJason Molenda m_id.SetPC (curr_stackframe.m_id.GetPC()); // Update the Stack ID PC value 1354*f23bf743SJason Molenda assert (GetThread() == curr_stackframe.GetThread()); 1355*f23bf743SJason Molenda m_frame_index = curr_stackframe.m_frame_index; 1356*f23bf743SJason Molenda m_concrete_frame_index = curr_stackframe.m_concrete_frame_index; 1357*f23bf743SJason Molenda m_reg_context_sp = curr_stackframe.m_reg_context_sp; 1358*f23bf743SJason Molenda m_frame_code_addr = curr_stackframe.m_frame_code_addr; 1359*f23bf743SJason Molenda assert (m_sc.target_sp.get() == NULL || curr_stackframe.m_sc.target_sp.get() == NULL || m_sc.target_sp.get() == curr_stackframe.m_sc.target_sp.get()); 1360*f23bf743SJason Molenda assert (m_sc.module_sp.get() == NULL || curr_stackframe.m_sc.module_sp.get() == NULL || m_sc.module_sp.get() == curr_stackframe.m_sc.module_sp.get()); 1361*f23bf743SJason Molenda assert (m_sc.comp_unit == NULL || curr_stackframe.m_sc.comp_unit == NULL || m_sc.comp_unit == curr_stackframe.m_sc.comp_unit); 1362*f23bf743SJason Molenda assert (m_sc.function == NULL || curr_stackframe.m_sc.function == NULL || m_sc.function == curr_stackframe.m_sc.function); 1363*f23bf743SJason Molenda m_sc = curr_stackframe.m_sc; 136459e8fc1cSGreg Clayton m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything); 136559e8fc1cSGreg Clayton m_flags.Set (m_sc.GetResolvedMask()); 136659e8fc1cSGreg Clayton m_frame_base.Clear(); 136759e8fc1cSGreg Clayton m_frame_base_error.Clear(); 136859e8fc1cSGreg Clayton } 13692cad65a5SGreg Clayton } 1370e4284b71SJim Ingham 1371*f23bf743SJason Molenda 13727260f620SGreg Clayton bool 13737260f620SGreg Clayton StackFrame::GetStatus (Stream& strm, 13747260f620SGreg Clayton bool show_frame_info, 13758ec10efcSJim Ingham bool show_source, 13768ec10efcSJim Ingham const char *frame_marker) 13777260f620SGreg Clayton { 137853eb7ad2SGreg Clayton 13797260f620SGreg Clayton if (show_frame_info) 13807260f620SGreg Clayton { 13817260f620SGreg Clayton strm.Indent(); 13828ec10efcSJim Ingham DumpUsingSettingsFormat (&strm, frame_marker); 13837260f620SGreg Clayton } 13847260f620SGreg Clayton 13857260f620SGreg Clayton if (show_source) 13867260f620SGreg Clayton { 1387d9e416c0SGreg Clayton ExecutionContext exe_ctx (shared_from_this()); 1388e372b98dSGreg Clayton bool have_source = false; 138967cc0636SGreg Clayton Debugger::StopDisassemblyType disasm_display = Debugger::eStopDisassemblyTypeNever; 1390d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 139153eb7ad2SGreg Clayton if (target) 139253eb7ad2SGreg Clayton { 139353eb7ad2SGreg Clayton Debugger &debugger = target->GetDebugger(); 139453eb7ad2SGreg Clayton const uint32_t source_lines_before = debugger.GetStopSourceLineCount(true); 139553eb7ad2SGreg Clayton const uint32_t source_lines_after = debugger.GetStopSourceLineCount(false); 139653eb7ad2SGreg Clayton disasm_display = debugger.GetStopDisassemblyDisplay (); 139753eb7ad2SGreg Clayton 139853eb7ad2SGreg Clayton if (source_lines_before > 0 || source_lines_after > 0) 1399e372b98dSGreg Clayton { 14007260f620SGreg Clayton GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry); 14017260f620SGreg Clayton 14027260f620SGreg Clayton if (m_sc.comp_unit && m_sc.line_entry.IsValid()) 14037260f620SGreg Clayton { 14047cd81c55SJason Molenda have_source = true; 14057cd81c55SJason Molenda target->GetSourceManager().DisplaySourceLinesWithLineNumbers (m_sc.line_entry.file, 14067260f620SGreg Clayton m_sc.line_entry.line, 1407d9e416c0SGreg Clayton source_lines_before, 1408d9e416c0SGreg Clayton source_lines_after, 14097260f620SGreg Clayton "->", 14107cd81c55SJason Molenda &strm); 1411e372b98dSGreg Clayton } 1412e372b98dSGreg Clayton } 1413e372b98dSGreg Clayton switch (disasm_display) 1414e372b98dSGreg Clayton { 141567cc0636SGreg Clayton case Debugger::eStopDisassemblyTypeNever: 1416e372b98dSGreg Clayton break; 1417e372b98dSGreg Clayton 141867cc0636SGreg Clayton case Debugger::eStopDisassemblyTypeNoSource: 1419e372b98dSGreg Clayton if (have_source) 1420e372b98dSGreg Clayton break; 1421e372b98dSGreg Clayton // Fall through to next case 142267cc0636SGreg Clayton case Debugger::eStopDisassemblyTypeAlways: 1423d9e416c0SGreg Clayton if (target) 1424e372b98dSGreg Clayton { 142553eb7ad2SGreg Clayton const uint32_t disasm_lines = debugger.GetDisassemblyLineCount(); 1426e372b98dSGreg Clayton if (disasm_lines > 0) 1427e372b98dSGreg Clayton { 1428d9e416c0SGreg Clayton const ArchSpec &target_arch = target->GetArchitecture(); 1429e372b98dSGreg Clayton AddressRange pc_range; 1430e372b98dSGreg Clayton pc_range.GetBaseAddress() = GetFrameCodeAddress(); 1431e372b98dSGreg Clayton pc_range.SetByteSize(disasm_lines * target_arch.GetMaximumOpcodeByteSize()); 14320f063ba6SJim Ingham const char *plugin_name = NULL; 14330f063ba6SJim Ingham const char *flavor = NULL; 1434d9e416c0SGreg Clayton Disassembler::Disassemble (target->GetDebugger(), 1435e372b98dSGreg Clayton target_arch, 14360f063ba6SJim Ingham plugin_name, 14370f063ba6SJim Ingham flavor, 1438e372b98dSGreg Clayton exe_ctx, 1439e372b98dSGreg Clayton pc_range, 1440e372b98dSGreg Clayton disasm_lines, 1441e372b98dSGreg Clayton 0, 1442e372b98dSGreg Clayton Disassembler::eOptionMarkPCAddress, 1443e372b98dSGreg Clayton strm); 1444e372b98dSGreg Clayton } 1445e372b98dSGreg Clayton } 1446e372b98dSGreg Clayton break; 14477260f620SGreg Clayton } 14487260f620SGreg Clayton } 144953eb7ad2SGreg Clayton } 14507260f620SGreg Clayton return true; 14517260f620SGreg Clayton } 14527260f620SGreg Clayton 1453