1435933ddSDimitry Andric //===-- ThreadPlanTracer.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 // C Includes 11ac7ddfbfSEd Maste // C++ Includes 129f2f44ceSEd Maste #include <cstring> 139f2f44ceSEd Maste 14ac7ddfbfSEd Maste // Other libraries and framework includes 15ac7ddfbfSEd Maste // Project includes 16ac7ddfbfSEd Maste #include "lldb/Core/ArchSpec.h" 17ac7ddfbfSEd Maste #include "lldb/Core/DataBufferHeap.h" 181c3bbb01SEd Maste #include "lldb/Core/DataExtractor.h" 19ac7ddfbfSEd Maste #include "lldb/Core/Debugger.h" 20ac7ddfbfSEd Maste #include "lldb/Core/Disassembler.h" 21ac7ddfbfSEd Maste #include "lldb/Core/Log.h" 22ac7ddfbfSEd Maste #include "lldb/Core/Module.h" 23ac7ddfbfSEd Maste #include "lldb/Core/State.h" 2412b93ac6SEd Maste #include "lldb/Core/StreamFile.h" 25ac7ddfbfSEd Maste #include "lldb/Core/Value.h" 26ac7ddfbfSEd Maste #include "lldb/Symbol/TypeList.h" 279f2f44ceSEd Maste #include "lldb/Symbol/TypeSystem.h" 281c3bbb01SEd Maste #include "lldb/Target/ABI.h" 29ac7ddfbfSEd Maste #include "lldb/Target/Process.h" 30435933ddSDimitry Andric #include "lldb/Target/RegisterContext.h" 3112b93ac6SEd Maste #include "lldb/Target/SectionLoadList.h" 32ac7ddfbfSEd Maste #include "lldb/Target/Target.h" 33435933ddSDimitry Andric #include "lldb/Target/Thread.h" 34435933ddSDimitry Andric #include "lldb/Target/ThreadPlan.h" 35ac7ddfbfSEd Maste 36ac7ddfbfSEd Maste using namespace lldb; 37ac7ddfbfSEd Maste using namespace lldb_private; 38ac7ddfbfSEd Maste 39ac7ddfbfSEd Maste #pragma mark ThreadPlanTracer 40ac7ddfbfSEd Maste 41435933ddSDimitry Andric ThreadPlanTracer::ThreadPlanTracer(Thread &thread, lldb::StreamSP &stream_sp) 42435933ddSDimitry Andric : m_thread(thread), m_single_step(true), m_enabled(false), 43435933ddSDimitry Andric m_stream_sp(stream_sp) {} 44ac7ddfbfSEd Maste 45435933ddSDimitry Andric ThreadPlanTracer::ThreadPlanTracer(Thread &thread) 46435933ddSDimitry Andric : m_thread(thread), m_single_step(true), m_enabled(false), m_stream_sp() {} 47ac7ddfbfSEd Maste 48435933ddSDimitry Andric Stream *ThreadPlanTracer::GetLogStream() { 499f2f44ceSEd Maste if (m_stream_sp) 50ac7ddfbfSEd Maste return m_stream_sp.get(); 51435933ddSDimitry Andric else { 52ac7ddfbfSEd Maste TargetSP target_sp(m_thread.CalculateTarget()); 53ac7ddfbfSEd Maste if (target_sp) 5412b93ac6SEd Maste return target_sp->GetDebugger().GetOutputFile().get(); 55ac7ddfbfSEd Maste } 569f2f44ceSEd Maste return nullptr; 57ac7ddfbfSEd Maste } 58ac7ddfbfSEd Maste 59435933ddSDimitry Andric void ThreadPlanTracer::Log() { 60ac7ddfbfSEd Maste SymbolContext sc; 61ac7ddfbfSEd Maste bool show_frame_index = false; 62ac7ddfbfSEd Maste bool show_fullpaths = false; 63ac7ddfbfSEd Maste 64ac7ddfbfSEd Maste Stream *stream = GetLogStream(); 65435933ddSDimitry Andric if (stream) { 66435933ddSDimitry Andric m_thread.GetStackFrameAtIndex(0)->Dump(stream, show_frame_index, 67435933ddSDimitry Andric show_fullpaths); 68ac7ddfbfSEd Maste stream->Printf("\n"); 69ac7ddfbfSEd Maste stream->Flush(); 70ac7ddfbfSEd Maste } 71ac7ddfbfSEd Maste } 72ac7ddfbfSEd Maste 73435933ddSDimitry Andric bool ThreadPlanTracer::TracerExplainsStop() { 74435933ddSDimitry Andric if (m_enabled && m_single_step) { 75ac7ddfbfSEd Maste lldb::StopInfoSP stop_info = m_thread.GetStopInfo(); 769f2f44ceSEd Maste return (stop_info->GetStopReason() == eStopReasonTrace); 77435933ddSDimitry Andric } else 78ac7ddfbfSEd Maste return false; 79ac7ddfbfSEd Maste } 80ac7ddfbfSEd Maste 81ac7ddfbfSEd Maste #pragma mark ThreadPlanAssemblyTracer 82ac7ddfbfSEd Maste 83435933ddSDimitry Andric ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer(Thread &thread, 84435933ddSDimitry Andric lldb::StreamSP &stream_sp) 85435933ddSDimitry Andric : ThreadPlanTracer(thread, stream_sp), m_disassembler_sp(), m_intptr_type(), 86435933ddSDimitry Andric m_register_values() {} 87ac7ddfbfSEd Maste 88435933ddSDimitry Andric ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer(Thread &thread) 89435933ddSDimitry Andric : ThreadPlanTracer(thread), m_disassembler_sp(), m_intptr_type(), 90435933ddSDimitry Andric m_register_values() {} 91ac7ddfbfSEd Maste 92435933ddSDimitry Andric Disassembler *ThreadPlanAssemblyTracer::GetDisassembler() { 939f2f44ceSEd Maste if (!m_disassembler_sp) 94435933ddSDimitry Andric m_disassembler_sp = Disassembler::FindPlugin( 95435933ddSDimitry Andric m_thread.GetProcess()->GetTarget().GetArchitecture(), nullptr, nullptr); 96ac7ddfbfSEd Maste return m_disassembler_sp.get(); 97ac7ddfbfSEd Maste } 98ac7ddfbfSEd Maste 99435933ddSDimitry Andric TypeFromUser ThreadPlanAssemblyTracer::GetIntPointerType() { 100435933ddSDimitry Andric if (!m_intptr_type.IsValid()) { 101ac7ddfbfSEd Maste TargetSP target_sp(m_thread.CalculateTarget()); 102435933ddSDimitry Andric if (target_sp) { 103435933ddSDimitry Andric TypeSystem *type_system = 104435933ddSDimitry Andric target_sp->GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC); 1059f2f44ceSEd Maste if (type_system) 106435933ddSDimitry Andric m_intptr_type = 107435933ddSDimitry Andric TypeFromUser(type_system->GetBuiltinTypeForEncodingAndBitSize( 108435933ddSDimitry Andric eEncodingUint, 109435933ddSDimitry Andric target_sp->GetArchitecture().GetAddressByteSize() * 8)); 110ac7ddfbfSEd Maste } 111ac7ddfbfSEd Maste } 112ac7ddfbfSEd Maste return m_intptr_type; 113ac7ddfbfSEd Maste } 114ac7ddfbfSEd Maste 1159f2f44ceSEd Maste ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer() = default; 116ac7ddfbfSEd Maste 117435933ddSDimitry Andric void ThreadPlanAssemblyTracer::TracingStarted() { 118ac7ddfbfSEd Maste RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 119ac7ddfbfSEd Maste 1209f2f44ceSEd Maste if (m_register_values.empty()) 121ac7ddfbfSEd Maste m_register_values.resize(reg_ctx->GetRegisterCount()); 122ac7ddfbfSEd Maste } 123ac7ddfbfSEd Maste 124435933ddSDimitry Andric void ThreadPlanAssemblyTracer::TracingEnded() { m_register_values.clear(); } 125ac7ddfbfSEd Maste 126435933ddSDimitry Andric void ThreadPlanAssemblyTracer::Log() { 127ac7ddfbfSEd Maste Stream *stream = GetLogStream(); 128ac7ddfbfSEd Maste 129ac7ddfbfSEd Maste if (!stream) 130ac7ddfbfSEd Maste return; 131ac7ddfbfSEd Maste 132ac7ddfbfSEd Maste RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 133ac7ddfbfSEd Maste 134ac7ddfbfSEd Maste lldb::addr_t pc = reg_ctx->GetPC(); 135ac7ddfbfSEd Maste ProcessSP process_sp(m_thread.GetProcess()); 136ac7ddfbfSEd Maste Address pc_addr; 137ac7ddfbfSEd Maste bool addr_valid = false; 138ac7ddfbfSEd Maste uint8_t buffer[16] = {0}; // Must be big enough for any single instruction 139435933ddSDimitry Andric addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress( 140435933ddSDimitry Andric pc, pc_addr); 141ac7ddfbfSEd Maste 142435933ddSDimitry Andric pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, 143435933ddSDimitry Andric Address::DumpStyleModuleWithFileAddress); 144ac7ddfbfSEd Maste stream->PutCString(" "); 145ac7ddfbfSEd Maste 146ac7ddfbfSEd Maste Disassembler *disassembler = GetDisassembler(); 147435933ddSDimitry Andric if (disassembler) { 148ac7ddfbfSEd Maste Error err; 149ac7ddfbfSEd Maste process_sp->ReadMemory(pc, buffer, sizeof(buffer), err); 150ac7ddfbfSEd Maste 151435933ddSDimitry Andric if (err.Success()) { 152ac7ddfbfSEd Maste DataExtractor extractor(buffer, sizeof(buffer), 153ac7ddfbfSEd Maste process_sp->GetByteOrder(), 154ac7ddfbfSEd Maste process_sp->GetAddressByteSize()); 155ac7ddfbfSEd Maste 156ac7ddfbfSEd Maste bool data_from_file = false; 157ac7ddfbfSEd Maste if (addr_valid) 158435933ddSDimitry Andric disassembler->DecodeInstructions(pc_addr, extractor, 0, 1, false, 159435933ddSDimitry Andric data_from_file); 160ac7ddfbfSEd Maste else 161435933ddSDimitry Andric disassembler->DecodeInstructions(Address(pc), extractor, 0, 1, false, 162435933ddSDimitry Andric data_from_file); 163ac7ddfbfSEd Maste 164ac7ddfbfSEd Maste InstructionList &instruction_list = disassembler->GetInstructionList(); 165435933ddSDimitry Andric const uint32_t max_opcode_byte_size = 166435933ddSDimitry Andric instruction_list.GetMaxOpcocdeByteSize(); 167ac7ddfbfSEd Maste 168435933ddSDimitry Andric if (instruction_list.GetSize()) { 169ac7ddfbfSEd Maste const bool show_bytes = true; 170ac7ddfbfSEd Maste const bool show_address = true; 171435933ddSDimitry Andric Instruction *instruction = 172435933ddSDimitry Andric instruction_list.GetInstructionAtIndex(0).get(); 173435933ddSDimitry Andric const FormatEntity::Entry *disassemble_format = 174435933ddSDimitry Andric m_thread.GetProcess() 175435933ddSDimitry Andric ->GetTarget() 176435933ddSDimitry Andric .GetDebugger() 177435933ddSDimitry Andric .GetDisassemblyFormat(); 178435933ddSDimitry Andric instruction->Dump(stream, max_opcode_byte_size, show_address, 179435933ddSDimitry Andric show_bytes, nullptr, nullptr, nullptr, 180435933ddSDimitry Andric disassemble_format, 0); 181ac7ddfbfSEd Maste } 182ac7ddfbfSEd Maste } 183ac7ddfbfSEd Maste } 184ac7ddfbfSEd Maste 185ac7ddfbfSEd Maste const ABI *abi = process_sp->GetABI().get(); 186ac7ddfbfSEd Maste TypeFromUser intptr_type = GetIntPointerType(); 187ac7ddfbfSEd Maste 188435933ddSDimitry Andric if (abi && intptr_type.IsValid()) { 189ac7ddfbfSEd Maste ValueList value_list; 190ac7ddfbfSEd Maste const int num_args = 1; 191ac7ddfbfSEd Maste 192435933ddSDimitry Andric for (int arg_index = 0; arg_index < num_args; ++arg_index) { 193ac7ddfbfSEd Maste Value value; 194ac7ddfbfSEd Maste value.SetValueType(Value::eValueTypeScalar); 195435933ddSDimitry Andric // value.SetContext (Value::eContextTypeClangType, 196435933ddSDimitry Andric // intptr_type.GetOpaqueQualType()); 1979f2f44ceSEd Maste value.SetCompilerType(intptr_type); 198ac7ddfbfSEd Maste value_list.PushValue(value); 199ac7ddfbfSEd Maste } 200ac7ddfbfSEd Maste 201435933ddSDimitry Andric if (abi->GetArgumentValues(m_thread, value_list)) { 202435933ddSDimitry Andric for (int arg_index = 0; arg_index < num_args; ++arg_index) { 203435933ddSDimitry Andric stream->Printf( 204435933ddSDimitry Andric "\n\targ[%d]=%llx", arg_index, 205435933ddSDimitry Andric value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong()); 206ac7ddfbfSEd Maste 207ac7ddfbfSEd Maste if (arg_index + 1 < num_args) 208ac7ddfbfSEd Maste stream->PutCString(", "); 209ac7ddfbfSEd Maste } 210ac7ddfbfSEd Maste } 211ac7ddfbfSEd Maste } 212ac7ddfbfSEd Maste 213ac7ddfbfSEd Maste RegisterValue reg_value; 214ac7ddfbfSEd Maste for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount(); 215435933ddSDimitry Andric reg_num < num_registers; ++reg_num) { 216ac7ddfbfSEd Maste const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); 217435933ddSDimitry Andric if (reg_ctx->ReadRegister(reg_info, reg_value)) { 218ac7ddfbfSEd Maste assert(reg_num < m_register_values.size()); 219ac7ddfbfSEd Maste if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid || 220435933ddSDimitry Andric reg_value != m_register_values[reg_num]) { 221435933ddSDimitry Andric if (reg_value.GetType() != RegisterValue::eTypeInvalid) { 222ac7ddfbfSEd Maste stream->PutCString("\n\t"); 223ac7ddfbfSEd Maste reg_value.Dump(stream, reg_info, true, false, eFormatDefault); 224ac7ddfbfSEd Maste } 225ac7ddfbfSEd Maste } 226ac7ddfbfSEd Maste m_register_values[reg_num] = reg_value; 227ac7ddfbfSEd Maste } 228ac7ddfbfSEd Maste } 229ac7ddfbfSEd Maste stream->EOL(); 230ac7ddfbfSEd Maste stream->Flush(); 231ac7ddfbfSEd Maste } 232