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