1ac7ddfbfSEd Maste //===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===// 2ac7ddfbfSEd Maste // 3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure 4ac7ddfbfSEd Maste // 5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source 6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details. 7ac7ddfbfSEd Maste // 8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===// 9ac7ddfbfSEd Maste 10ac7ddfbfSEd Maste #include "lldb/lldb-python.h" 11ac7ddfbfSEd Maste 12ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlan.h" 13ac7ddfbfSEd Maste 14ac7ddfbfSEd Maste // C Includes 15ac7ddfbfSEd Maste #include <string.h> 16ac7ddfbfSEd Maste // C++ Includes 17ac7ddfbfSEd Maste // Other libraries and framework includes 18ac7ddfbfSEd Maste // Project includes 19ac7ddfbfSEd Maste #include "lldb/Core/ArchSpec.h" 20ac7ddfbfSEd Maste #include "lldb/Core/DataBufferHeap.h" 21ac7ddfbfSEd Maste #include "lldb/Core/Debugger.h" 22ac7ddfbfSEd Maste #include "lldb/Core/Disassembler.h" 23ac7ddfbfSEd Maste #include "lldb/Core/Log.h" 24ac7ddfbfSEd Maste #include "lldb/Core/Module.h" 25ac7ddfbfSEd Maste #include "lldb/Core/State.h" 2612b93ac6SEd Maste #include "lldb/Core/StreamFile.h" 27ac7ddfbfSEd Maste #include "lldb/Core/Value.h" 28ac7ddfbfSEd Maste #include "lldb/Symbol/TypeList.h" 29ac7ddfbfSEd Maste #include "lldb/Target/RegisterContext.h" 30ac7ddfbfSEd Maste #include "lldb/Target/Thread.h" 31ac7ddfbfSEd Maste #include "lldb/Target/Process.h" 3212b93ac6SEd Maste #include "lldb/Target/SectionLoadList.h" 33ac7ddfbfSEd Maste #include "lldb/Target/Target.h" 34ac7ddfbfSEd Maste 35ac7ddfbfSEd Maste using namespace lldb; 36ac7ddfbfSEd Maste using namespace lldb_private; 37ac7ddfbfSEd Maste 38ac7ddfbfSEd Maste #pragma mark ThreadPlanTracer 39ac7ddfbfSEd Maste 40ac7ddfbfSEd Maste ThreadPlanTracer::ThreadPlanTracer (Thread &thread, lldb::StreamSP &stream_sp) : 41ac7ddfbfSEd Maste m_thread (thread), 42ac7ddfbfSEd Maste m_single_step(true), 43ac7ddfbfSEd Maste m_enabled (false), 44ac7ddfbfSEd Maste m_stream_sp (stream_sp) 45ac7ddfbfSEd Maste { 46ac7ddfbfSEd Maste } 47ac7ddfbfSEd Maste 48ac7ddfbfSEd Maste ThreadPlanTracer::ThreadPlanTracer (Thread &thread) : 49ac7ddfbfSEd Maste m_thread (thread), 50ac7ddfbfSEd Maste m_single_step(true), 51ac7ddfbfSEd Maste m_enabled (false), 52ac7ddfbfSEd Maste m_stream_sp () 53ac7ddfbfSEd Maste { 54ac7ddfbfSEd Maste } 55ac7ddfbfSEd Maste 56ac7ddfbfSEd Maste Stream * 57ac7ddfbfSEd Maste ThreadPlanTracer::GetLogStream () 58ac7ddfbfSEd Maste { 59ac7ddfbfSEd Maste 60ac7ddfbfSEd Maste if (m_stream_sp.get()) 61ac7ddfbfSEd Maste return m_stream_sp.get(); 62ac7ddfbfSEd Maste else 63ac7ddfbfSEd Maste { 64ac7ddfbfSEd Maste TargetSP target_sp (m_thread.CalculateTarget()); 65ac7ddfbfSEd Maste if (target_sp) 6612b93ac6SEd Maste return target_sp->GetDebugger().GetOutputFile().get(); 67ac7ddfbfSEd Maste } 68ac7ddfbfSEd Maste return NULL; 69ac7ddfbfSEd Maste } 70ac7ddfbfSEd Maste 71ac7ddfbfSEd Maste void 72ac7ddfbfSEd Maste ThreadPlanTracer::Log() 73ac7ddfbfSEd Maste { 74ac7ddfbfSEd Maste SymbolContext sc; 75ac7ddfbfSEd Maste bool show_frame_index = false; 76ac7ddfbfSEd Maste bool show_fullpaths = false; 77ac7ddfbfSEd Maste 78ac7ddfbfSEd Maste Stream *stream = GetLogStream(); 79ac7ddfbfSEd Maste if (stream) 80ac7ddfbfSEd Maste { 81ac7ddfbfSEd Maste m_thread.GetStackFrameAtIndex(0)->Dump (stream, show_frame_index, show_fullpaths); 82ac7ddfbfSEd Maste stream->Printf("\n"); 83ac7ddfbfSEd Maste stream->Flush(); 84ac7ddfbfSEd Maste } 85ac7ddfbfSEd Maste 86ac7ddfbfSEd Maste } 87ac7ddfbfSEd Maste 88ac7ddfbfSEd Maste bool 89ac7ddfbfSEd Maste ThreadPlanTracer::TracerExplainsStop () 90ac7ddfbfSEd Maste { 91ac7ddfbfSEd Maste if (m_enabled && m_single_step) 92ac7ddfbfSEd Maste { 93ac7ddfbfSEd Maste lldb::StopInfoSP stop_info = m_thread.GetStopInfo(); 94ac7ddfbfSEd Maste if (stop_info->GetStopReason() == eStopReasonTrace) 95ac7ddfbfSEd Maste return true; 96ac7ddfbfSEd Maste else 97ac7ddfbfSEd Maste return false; 98ac7ddfbfSEd Maste } 99ac7ddfbfSEd Maste else 100ac7ddfbfSEd Maste return false; 101ac7ddfbfSEd Maste } 102ac7ddfbfSEd Maste 103ac7ddfbfSEd Maste #pragma mark ThreadPlanAssemblyTracer 104ac7ddfbfSEd Maste 105ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp) : 106ac7ddfbfSEd Maste ThreadPlanTracer (thread, stream_sp), 107ac7ddfbfSEd Maste m_disassembler_sp (), 108ac7ddfbfSEd Maste m_intptr_type (), 109ac7ddfbfSEd Maste m_register_values () 110ac7ddfbfSEd Maste { 111ac7ddfbfSEd Maste } 112ac7ddfbfSEd Maste 113ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread) : 114ac7ddfbfSEd Maste ThreadPlanTracer (thread), 115ac7ddfbfSEd Maste m_disassembler_sp (), 116ac7ddfbfSEd Maste m_intptr_type (), 117ac7ddfbfSEd Maste m_register_values () 118ac7ddfbfSEd Maste { 119ac7ddfbfSEd Maste } 120ac7ddfbfSEd Maste 121ac7ddfbfSEd Maste Disassembler * 122ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::GetDisassembler () 123ac7ddfbfSEd Maste { 124ac7ddfbfSEd Maste if (m_disassembler_sp.get() == NULL) 125ac7ddfbfSEd Maste m_disassembler_sp = Disassembler::FindPlugin(m_thread.GetProcess()->GetTarget().GetArchitecture(), NULL, NULL); 126ac7ddfbfSEd Maste return m_disassembler_sp.get(); 127ac7ddfbfSEd Maste } 128ac7ddfbfSEd Maste 129ac7ddfbfSEd Maste TypeFromUser 130ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::GetIntPointerType() 131ac7ddfbfSEd Maste { 132ac7ddfbfSEd Maste if (!m_intptr_type.IsValid ()) 133ac7ddfbfSEd Maste { 134ac7ddfbfSEd Maste TargetSP target_sp (m_thread.CalculateTarget()); 135ac7ddfbfSEd Maste if (target_sp) 136ac7ddfbfSEd Maste { 137ac7ddfbfSEd Maste Module *exe_module = target_sp->GetExecutableModulePointer(); 138ac7ddfbfSEd Maste 139ac7ddfbfSEd Maste if (exe_module) 140ac7ddfbfSEd Maste { 141ac7ddfbfSEd Maste m_intptr_type = TypeFromUser(exe_module->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, target_sp->GetArchitecture().GetAddressByteSize() * 8)); 142ac7ddfbfSEd Maste } 143ac7ddfbfSEd Maste } 144ac7ddfbfSEd Maste } 145ac7ddfbfSEd Maste return m_intptr_type; 146ac7ddfbfSEd Maste } 147ac7ddfbfSEd Maste 148ac7ddfbfSEd Maste 149ac7ddfbfSEd Maste 150ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer() 151ac7ddfbfSEd Maste { 152ac7ddfbfSEd Maste } 153ac7ddfbfSEd Maste 154ac7ddfbfSEd Maste void 155ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::TracingStarted () 156ac7ddfbfSEd Maste { 157ac7ddfbfSEd Maste RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 158ac7ddfbfSEd Maste 159ac7ddfbfSEd Maste if (m_register_values.size() == 0) 160ac7ddfbfSEd Maste m_register_values.resize (reg_ctx->GetRegisterCount()); 161ac7ddfbfSEd Maste } 162ac7ddfbfSEd Maste 163ac7ddfbfSEd Maste void 164ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::TracingEnded () 165ac7ddfbfSEd Maste { 166ac7ddfbfSEd Maste m_register_values.clear(); 167ac7ddfbfSEd Maste } 168ac7ddfbfSEd Maste 169ac7ddfbfSEd Maste void 170ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::Log () 171ac7ddfbfSEd Maste { 172ac7ddfbfSEd Maste Stream *stream = GetLogStream (); 173ac7ddfbfSEd Maste 174ac7ddfbfSEd Maste if (!stream) 175ac7ddfbfSEd Maste return; 176ac7ddfbfSEd Maste 177ac7ddfbfSEd Maste RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 178ac7ddfbfSEd Maste 179ac7ddfbfSEd Maste lldb::addr_t pc = reg_ctx->GetPC(); 180ac7ddfbfSEd Maste ProcessSP process_sp (m_thread.GetProcess()); 181ac7ddfbfSEd Maste Address pc_addr; 182ac7ddfbfSEd Maste bool addr_valid = false; 183ac7ddfbfSEd Maste uint8_t buffer[16] = {0}; // Must be big enough for any single instruction 184ac7ddfbfSEd Maste addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr); 185ac7ddfbfSEd Maste 186ac7ddfbfSEd Maste pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress); 187ac7ddfbfSEd Maste stream->PutCString (" "); 188ac7ddfbfSEd Maste 189ac7ddfbfSEd Maste Disassembler *disassembler = GetDisassembler(); 190ac7ddfbfSEd Maste if (disassembler) 191ac7ddfbfSEd Maste { 192ac7ddfbfSEd Maste Error err; 193ac7ddfbfSEd Maste process_sp->ReadMemory(pc, buffer, sizeof(buffer), err); 194ac7ddfbfSEd Maste 195ac7ddfbfSEd Maste if (err.Success()) 196ac7ddfbfSEd Maste { 197ac7ddfbfSEd Maste DataExtractor extractor(buffer, sizeof(buffer), 198ac7ddfbfSEd Maste process_sp->GetByteOrder(), 199ac7ddfbfSEd Maste process_sp->GetAddressByteSize()); 200ac7ddfbfSEd Maste 201ac7ddfbfSEd Maste bool data_from_file = false; 202ac7ddfbfSEd Maste if (addr_valid) 203ac7ddfbfSEd Maste disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false, data_from_file); 204ac7ddfbfSEd Maste else 205ac7ddfbfSEd Maste disassembler->DecodeInstructions (Address (pc), extractor, 0, 1, false, data_from_file); 206ac7ddfbfSEd Maste 207ac7ddfbfSEd Maste InstructionList &instruction_list = disassembler->GetInstructionList(); 208ac7ddfbfSEd Maste const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); 209ac7ddfbfSEd Maste 210ac7ddfbfSEd Maste if (instruction_list.GetSize()) 211ac7ddfbfSEd Maste { 212ac7ddfbfSEd Maste const bool show_bytes = true; 213ac7ddfbfSEd Maste const bool show_address = true; 214ac7ddfbfSEd Maste Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get(); 2157aa51b79SEd Maste const char *disassemble_format = "${addr-file-or-load}: "; 216ac7ddfbfSEd Maste instruction->Dump (stream, 217ac7ddfbfSEd Maste max_opcode_byte_size, 218ac7ddfbfSEd Maste show_address, 219ac7ddfbfSEd Maste show_bytes, 2207aa51b79SEd Maste NULL, 2217aa51b79SEd Maste NULL, 2227aa51b79SEd Maste NULL, 2237aa51b79SEd Maste disassemble_format); 224ac7ddfbfSEd Maste } 225ac7ddfbfSEd Maste } 226ac7ddfbfSEd Maste } 227ac7ddfbfSEd Maste 228ac7ddfbfSEd Maste const ABI *abi = process_sp->GetABI().get(); 229ac7ddfbfSEd Maste TypeFromUser intptr_type = GetIntPointerType(); 230ac7ddfbfSEd Maste 231ac7ddfbfSEd Maste if (abi && intptr_type.IsValid()) 232ac7ddfbfSEd Maste { 233ac7ddfbfSEd Maste ValueList value_list; 234ac7ddfbfSEd Maste const int num_args = 1; 235ac7ddfbfSEd Maste 236ac7ddfbfSEd Maste for (int arg_index = 0; arg_index < num_args; ++arg_index) 237ac7ddfbfSEd Maste { 238ac7ddfbfSEd Maste Value value; 239ac7ddfbfSEd Maste value.SetValueType (Value::eValueTypeScalar); 240ac7ddfbfSEd Maste // value.SetContext (Value::eContextTypeClangType, intptr_type.GetOpaqueQualType()); 241ac7ddfbfSEd Maste value.SetClangType (intptr_type); 242ac7ddfbfSEd Maste value_list.PushValue (value); 243ac7ddfbfSEd Maste } 244ac7ddfbfSEd Maste 245ac7ddfbfSEd Maste if (abi->GetArgumentValues (m_thread, value_list)) 246ac7ddfbfSEd Maste { 247ac7ddfbfSEd Maste for (int arg_index = 0; arg_index < num_args; ++arg_index) 248ac7ddfbfSEd Maste { 249ac7ddfbfSEd Maste stream->Printf("\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong()); 250ac7ddfbfSEd Maste 251ac7ddfbfSEd Maste if (arg_index + 1 < num_args) 252ac7ddfbfSEd Maste stream->PutCString (", "); 253ac7ddfbfSEd Maste } 254ac7ddfbfSEd Maste } 255ac7ddfbfSEd Maste } 256ac7ddfbfSEd Maste 257ac7ddfbfSEd Maste 258ac7ddfbfSEd Maste RegisterValue reg_value; 259ac7ddfbfSEd Maste for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount(); 260ac7ddfbfSEd Maste reg_num < num_registers; 261ac7ddfbfSEd Maste ++reg_num) 262ac7ddfbfSEd Maste { 263ac7ddfbfSEd Maste const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); 264ac7ddfbfSEd Maste if (reg_ctx->ReadRegister (reg_info, reg_value)) 265ac7ddfbfSEd Maste { 266ac7ddfbfSEd Maste assert (reg_num < m_register_values.size()); 267ac7ddfbfSEd Maste if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid || 268ac7ddfbfSEd Maste reg_value != m_register_values[reg_num]) 269ac7ddfbfSEd Maste { 270ac7ddfbfSEd Maste if (reg_value.GetType() != RegisterValue::eTypeInvalid) 271ac7ddfbfSEd Maste { 272ac7ddfbfSEd Maste stream->PutCString ("\n\t"); 273ac7ddfbfSEd Maste reg_value.Dump(stream, reg_info, true, false, eFormatDefault); 274ac7ddfbfSEd Maste } 275ac7ddfbfSEd Maste } 276ac7ddfbfSEd Maste m_register_values[reg_num] = reg_value; 277ac7ddfbfSEd Maste } 278ac7ddfbfSEd Maste } 279ac7ddfbfSEd Maste stream->EOL(); 280ac7ddfbfSEd Maste stream->Flush(); 281ac7ddfbfSEd Maste } 282