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