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 // C Includes 11ac7ddfbfSEd Maste // C++ Includes 129f2f44ceSEd Maste #include <cstring> 139f2f44ceSEd Maste 14ac7ddfbfSEd Maste // Other libraries and framework includes 15ac7ddfbfSEd Maste // Project includes 169f2f44ceSEd Maste #include "lldb/Target/ThreadPlan.h" 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" 27ac7ddfbfSEd Maste #include "lldb/Symbol/TypeList.h" 289f2f44ceSEd Maste #include "lldb/Symbol/TypeSystem.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 { 609f2f44ceSEd Maste if (m_stream_sp) 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 } 689f2f44ceSEd Maste return nullptr; 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 bool 88ac7ddfbfSEd Maste ThreadPlanTracer::TracerExplainsStop () 89ac7ddfbfSEd Maste { 90ac7ddfbfSEd Maste if (m_enabled && m_single_step) 91ac7ddfbfSEd Maste { 92ac7ddfbfSEd Maste lldb::StopInfoSP stop_info = m_thread.GetStopInfo(); 939f2f44ceSEd Maste return (stop_info->GetStopReason() == eStopReasonTrace); 94ac7ddfbfSEd Maste } 95ac7ddfbfSEd Maste else 96ac7ddfbfSEd Maste return false; 97ac7ddfbfSEd Maste } 98ac7ddfbfSEd Maste 99ac7ddfbfSEd Maste #pragma mark ThreadPlanAssemblyTracer 100ac7ddfbfSEd Maste 101ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp) : 102ac7ddfbfSEd Maste ThreadPlanTracer (thread, stream_sp), 103ac7ddfbfSEd Maste m_disassembler_sp (), 104ac7ddfbfSEd Maste m_intptr_type (), 105ac7ddfbfSEd Maste m_register_values () 106ac7ddfbfSEd Maste { 107ac7ddfbfSEd Maste } 108ac7ddfbfSEd Maste 109ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread) : 110ac7ddfbfSEd Maste ThreadPlanTracer (thread), 111ac7ddfbfSEd Maste m_disassembler_sp (), 112ac7ddfbfSEd Maste m_intptr_type (), 113ac7ddfbfSEd Maste m_register_values () 114ac7ddfbfSEd Maste { 115ac7ddfbfSEd Maste } 116ac7ddfbfSEd Maste 117ac7ddfbfSEd Maste Disassembler * 118ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::GetDisassembler () 119ac7ddfbfSEd Maste { 1209f2f44ceSEd Maste if (!m_disassembler_sp) 1219f2f44ceSEd Maste m_disassembler_sp = Disassembler::FindPlugin(m_thread.GetProcess()->GetTarget().GetArchitecture(), nullptr, nullptr); 122ac7ddfbfSEd Maste return m_disassembler_sp.get(); 123ac7ddfbfSEd Maste } 124ac7ddfbfSEd Maste 125ac7ddfbfSEd Maste TypeFromUser 126ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::GetIntPointerType() 127ac7ddfbfSEd Maste { 128ac7ddfbfSEd Maste if (!m_intptr_type.IsValid ()) 129ac7ddfbfSEd Maste { 130ac7ddfbfSEd Maste TargetSP target_sp (m_thread.CalculateTarget()); 131ac7ddfbfSEd Maste if (target_sp) 132ac7ddfbfSEd Maste { 1339f2f44ceSEd Maste TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC); 1349f2f44ceSEd Maste if (type_system) 1359f2f44ceSEd Maste m_intptr_type = TypeFromUser(type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, target_sp->GetArchitecture().GetAddressByteSize() * 8)); 136ac7ddfbfSEd Maste } 137ac7ddfbfSEd Maste } 138ac7ddfbfSEd Maste return m_intptr_type; 139ac7ddfbfSEd Maste } 140ac7ddfbfSEd Maste 1419f2f44ceSEd Maste ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer() = default; 142ac7ddfbfSEd Maste 143ac7ddfbfSEd Maste void 144ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::TracingStarted () 145ac7ddfbfSEd Maste { 146ac7ddfbfSEd Maste RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 147ac7ddfbfSEd Maste 1489f2f44ceSEd Maste if (m_register_values.empty()) 149ac7ddfbfSEd Maste m_register_values.resize (reg_ctx->GetRegisterCount()); 150ac7ddfbfSEd Maste } 151ac7ddfbfSEd Maste 152ac7ddfbfSEd Maste void 153ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::TracingEnded () 154ac7ddfbfSEd Maste { 155ac7ddfbfSEd Maste m_register_values.clear(); 156ac7ddfbfSEd Maste } 157ac7ddfbfSEd Maste 158ac7ddfbfSEd Maste void 159ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::Log () 160ac7ddfbfSEd Maste { 161ac7ddfbfSEd Maste Stream *stream = GetLogStream (); 162ac7ddfbfSEd Maste 163ac7ddfbfSEd Maste if (!stream) 164ac7ddfbfSEd Maste return; 165ac7ddfbfSEd Maste 166ac7ddfbfSEd Maste RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 167ac7ddfbfSEd Maste 168ac7ddfbfSEd Maste lldb::addr_t pc = reg_ctx->GetPC(); 169ac7ddfbfSEd Maste ProcessSP process_sp (m_thread.GetProcess()); 170ac7ddfbfSEd Maste Address pc_addr; 171ac7ddfbfSEd Maste bool addr_valid = false; 172ac7ddfbfSEd Maste uint8_t buffer[16] = {0}; // Must be big enough for any single instruction 173ac7ddfbfSEd Maste addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr); 174ac7ddfbfSEd Maste 175ac7ddfbfSEd Maste pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress); 176ac7ddfbfSEd Maste stream->PutCString (" "); 177ac7ddfbfSEd Maste 178ac7ddfbfSEd Maste Disassembler *disassembler = GetDisassembler(); 179ac7ddfbfSEd Maste if (disassembler) 180ac7ddfbfSEd Maste { 181ac7ddfbfSEd Maste Error err; 182ac7ddfbfSEd Maste process_sp->ReadMemory(pc, buffer, sizeof(buffer), err); 183ac7ddfbfSEd Maste 184ac7ddfbfSEd Maste if (err.Success()) 185ac7ddfbfSEd Maste { 186ac7ddfbfSEd Maste DataExtractor extractor(buffer, sizeof(buffer), 187ac7ddfbfSEd Maste process_sp->GetByteOrder(), 188ac7ddfbfSEd Maste process_sp->GetAddressByteSize()); 189ac7ddfbfSEd Maste 190ac7ddfbfSEd Maste bool data_from_file = false; 191ac7ddfbfSEd Maste if (addr_valid) 192ac7ddfbfSEd Maste disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false, data_from_file); 193ac7ddfbfSEd Maste else 194ac7ddfbfSEd Maste disassembler->DecodeInstructions (Address (pc), extractor, 0, 1, false, data_from_file); 195ac7ddfbfSEd Maste 196ac7ddfbfSEd Maste InstructionList &instruction_list = disassembler->GetInstructionList(); 197ac7ddfbfSEd Maste const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); 198ac7ddfbfSEd Maste 199ac7ddfbfSEd Maste if (instruction_list.GetSize()) 200ac7ddfbfSEd Maste { 201ac7ddfbfSEd Maste const bool show_bytes = true; 202ac7ddfbfSEd Maste const bool show_address = true; 203ac7ddfbfSEd Maste Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get(); 2041c3bbb01SEd Maste const FormatEntity::Entry *disassemble_format = m_thread.GetProcess()->GetTarget().GetDebugger().GetDisassemblyFormat(); 205ac7ddfbfSEd Maste instruction->Dump(stream, 206ac7ddfbfSEd Maste max_opcode_byte_size, 207ac7ddfbfSEd Maste show_address, 208ac7ddfbfSEd Maste show_bytes, 2099f2f44ceSEd Maste nullptr, 2109f2f44ceSEd Maste nullptr, 2119f2f44ceSEd Maste nullptr, 2121c3bbb01SEd Maste disassemble_format, 2131c3bbb01SEd Maste 0); 214ac7ddfbfSEd Maste } 215ac7ddfbfSEd Maste } 216ac7ddfbfSEd Maste } 217ac7ddfbfSEd Maste 218ac7ddfbfSEd Maste const ABI *abi = process_sp->GetABI().get(); 219ac7ddfbfSEd Maste TypeFromUser intptr_type = GetIntPointerType(); 220ac7ddfbfSEd Maste 221ac7ddfbfSEd Maste if (abi && intptr_type.IsValid()) 222ac7ddfbfSEd Maste { 223ac7ddfbfSEd Maste ValueList value_list; 224ac7ddfbfSEd Maste const int num_args = 1; 225ac7ddfbfSEd Maste 226ac7ddfbfSEd Maste for (int arg_index = 0; arg_index < num_args; ++arg_index) 227ac7ddfbfSEd Maste { 228ac7ddfbfSEd Maste Value value; 229ac7ddfbfSEd Maste value.SetValueType (Value::eValueTypeScalar); 230ac7ddfbfSEd Maste // value.SetContext (Value::eContextTypeClangType, intptr_type.GetOpaqueQualType()); 2319f2f44ceSEd Maste value.SetCompilerType (intptr_type); 232ac7ddfbfSEd Maste value_list.PushValue (value); 233ac7ddfbfSEd Maste } 234ac7ddfbfSEd Maste 235ac7ddfbfSEd Maste if (abi->GetArgumentValues (m_thread, value_list)) 236ac7ddfbfSEd Maste { 237ac7ddfbfSEd Maste for (int arg_index = 0; arg_index < num_args; ++arg_index) 238ac7ddfbfSEd Maste { 239ac7ddfbfSEd Maste stream->Printf("\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong()); 240ac7ddfbfSEd Maste 241ac7ddfbfSEd Maste if (arg_index + 1 < num_args) 242ac7ddfbfSEd Maste stream->PutCString (", "); 243ac7ddfbfSEd Maste } 244ac7ddfbfSEd Maste } 245ac7ddfbfSEd Maste } 246ac7ddfbfSEd Maste 247ac7ddfbfSEd Maste RegisterValue reg_value; 248ac7ddfbfSEd Maste for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount(); 249ac7ddfbfSEd Maste reg_num < num_registers; 250ac7ddfbfSEd Maste ++reg_num) 251ac7ddfbfSEd Maste { 252ac7ddfbfSEd Maste const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); 253ac7ddfbfSEd Maste if (reg_ctx->ReadRegister (reg_info, reg_value)) 254ac7ddfbfSEd Maste { 255ac7ddfbfSEd Maste assert (reg_num < m_register_values.size()); 256ac7ddfbfSEd Maste if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid || 257ac7ddfbfSEd Maste reg_value != m_register_values[reg_num]) 258ac7ddfbfSEd Maste { 259ac7ddfbfSEd Maste if (reg_value.GetType() != RegisterValue::eTypeInvalid) 260ac7ddfbfSEd Maste { 261ac7ddfbfSEd Maste stream->PutCString ("\n\t"); 262ac7ddfbfSEd Maste reg_value.Dump(stream, reg_info, true, false, eFormatDefault); 263ac7ddfbfSEd Maste } 264ac7ddfbfSEd Maste } 265ac7ddfbfSEd Maste m_register_values[reg_num] = reg_value; 266ac7ddfbfSEd Maste } 267ac7ddfbfSEd Maste } 268ac7ddfbfSEd Maste stream->EOL(); 269ac7ddfbfSEd Maste stream->Flush(); 270ac7ddfbfSEd Maste } 271