ThreadPlanTracer.cpp revision 344779
11638Srgrimes//===-- ThreadPlanTracer.cpp ------------------------------------*- C++ -*-===// 21638Srgrimes// 31638Srgrimes// The LLVM Compiler Infrastructure 41638Srgrimes// 51638Srgrimes// This file is distributed under the University of Illinois Open Source 61638Srgrimes// License. See LICENSE.TXT for details. 71638Srgrimes// 81638Srgrimes//===----------------------------------------------------------------------===// 91638Srgrimes 101638Srgrimes#include <cstring> 111638Srgrimes 121638Srgrimes#include "lldb/Core/Debugger.h" 131638Srgrimes#include "lldb/Core/Disassembler.h" 141638Srgrimes#include "lldb/Core/DumpRegisterValue.h" 151638Srgrimes#include "lldb/Core/Module.h" 161638Srgrimes#include "lldb/Core/StreamFile.h" 171638Srgrimes#include "lldb/Core/Value.h" 181638Srgrimes#include "lldb/Symbol/TypeList.h" 191638Srgrimes#include "lldb/Symbol/TypeSystem.h" 201638Srgrimes#include "lldb/Target/ABI.h" 211638Srgrimes#include "lldb/Target/Process.h" 221638Srgrimes#include "lldb/Target/RegisterContext.h" 231638Srgrimes#include "lldb/Target/SectionLoadList.h" 241638Srgrimes#include "lldb/Target/Target.h" 251638Srgrimes#include "lldb/Target/Thread.h" 261638Srgrimes#include "lldb/Target/ThreadPlan.h" 271638Srgrimes#include "lldb/Utility/DataBufferHeap.h" 281638Srgrimes#include "lldb/Utility/DataExtractor.h" 291638Srgrimes#include "lldb/Utility/Log.h" 301638Srgrimes#include "lldb/Utility/State.h" 311638Srgrimes 321638Srgrimesusing namespace lldb; 3350476Speterusing namespace lldb_private; 341638Srgrimes 351638Srgrimes#pragma mark ThreadPlanTracer 361638Srgrimes 371638SrgrimesThreadPlanTracer::ThreadPlanTracer(Thread &thread, lldb::StreamSP &stream_sp) 381638Srgrimes : m_thread(thread), m_single_step(true), m_enabled(false), 391638Srgrimes m_stream_sp(stream_sp) {} 401638Srgrimes 411638SrgrimesThreadPlanTracer::ThreadPlanTracer(Thread &thread) 421638Srgrimes : m_thread(thread), m_single_step(true), m_enabled(false), m_stream_sp() {} 431638Srgrimes 441638SrgrimesStream *ThreadPlanTracer::GetLogStream() { 451638Srgrimes if (m_stream_sp) 461638Srgrimes return m_stream_sp.get(); 471638Srgrimes else { 481638Srgrimes TargetSP target_sp(m_thread.CalculateTarget()); 491638Srgrimes if (target_sp) 501638Srgrimes return target_sp->GetDebugger().GetOutputFile().get(); 511638Srgrimes } 521638Srgrimes return nullptr; 531638Srgrimes} 541638Srgrimes 551638Srgrimesvoid ThreadPlanTracer::Log() { 561638Srgrimes SymbolContext sc; 571638Srgrimes bool show_frame_index = false; 581638Srgrimes bool show_fullpaths = false; 591638Srgrimes 601638Srgrimes Stream *stream = GetLogStream(); 611638Srgrimes if (stream) { 621638Srgrimes m_thread.GetStackFrameAtIndex(0)->Dump(stream, show_frame_index, 631638Srgrimes show_fullpaths); 641638Srgrimes stream->Printf("\n"); 651638Srgrimes stream->Flush(); 661638Srgrimes } 671638Srgrimes} 681638Srgrimes 691638Srgrimesbool ThreadPlanTracer::TracerExplainsStop() { 701638Srgrimes if (m_enabled && m_single_step) { 711638Srgrimes lldb::StopInfoSP stop_info = m_thread.GetStopInfo(); 721638Srgrimes return (stop_info->GetStopReason() == eStopReasonTrace); 731638Srgrimes } else 741638Srgrimes return false; 751638Srgrimes} 761638Srgrimes 771638Srgrimes#pragma mark ThreadPlanAssemblyTracer 781638Srgrimes 791638SrgrimesThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer(Thread &thread, 801638Srgrimes lldb::StreamSP &stream_sp) 811638Srgrimes : ThreadPlanTracer(thread, stream_sp), m_disassembler_sp(), m_intptr_type(), 821638Srgrimes m_register_values() {} 831638Srgrimes 841638SrgrimesThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer(Thread &thread) 851638Srgrimes : ThreadPlanTracer(thread), m_disassembler_sp(), m_intptr_type(), 861638Srgrimes m_register_values() {} 871638Srgrimes 881638SrgrimesDisassembler *ThreadPlanAssemblyTracer::GetDisassembler() { 891638Srgrimes if (!m_disassembler_sp) 901638Srgrimes m_disassembler_sp = Disassembler::FindPlugin( 911638Srgrimes m_thread.GetProcess()->GetTarget().GetArchitecture(), nullptr, nullptr); 921638Srgrimes return m_disassembler_sp.get(); 931638Srgrimes} 941638Srgrimes 951638SrgrimesTypeFromUser ThreadPlanAssemblyTracer::GetIntPointerType() { 961638Srgrimes if (!m_intptr_type.IsValid()) { 971638Srgrimes TargetSP target_sp(m_thread.CalculateTarget()); 981638Srgrimes if (target_sp) { 991638Srgrimes TypeSystem *type_system = 1001638Srgrimes target_sp->GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC); 1011638Srgrimes if (type_system) 1021638Srgrimes m_intptr_type = 1031638Srgrimes TypeFromUser(type_system->GetBuiltinTypeForEncodingAndBitSize( 1041638Srgrimes eEncodingUint, 1051638Srgrimes target_sp->GetArchitecture().GetAddressByteSize() * 8)); 1061638Srgrimes } 1071638Srgrimes } 1081638Srgrimes return m_intptr_type; 1091638Srgrimes} 1101638Srgrimes 1111638SrgrimesThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer() = default; 1121638Srgrimes 1131638Srgrimesvoid ThreadPlanAssemblyTracer::TracingStarted() { 1141638Srgrimes RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 1151638Srgrimes 1161638Srgrimes if (m_register_values.empty()) 1171638Srgrimes m_register_values.resize(reg_ctx->GetRegisterCount()); 1181638Srgrimes} 1191638Srgrimes 1201638Srgrimesvoid ThreadPlanAssemblyTracer::TracingEnded() { m_register_values.clear(); } 1211638Srgrimes 1221638Srgrimesvoid ThreadPlanAssemblyTracer::Log() { 1231638Srgrimes Stream *stream = GetLogStream(); 1241638Srgrimes 1251638Srgrimes if (!stream) 1261638Srgrimes return; 1271638Srgrimes 1281638Srgrimes RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 1291638Srgrimes 1301638Srgrimes lldb::addr_t pc = reg_ctx->GetPC(); 1311638Srgrimes ProcessSP process_sp(m_thread.GetProcess()); 1321638Srgrimes Address pc_addr; 1331638Srgrimes bool addr_valid = false; 1341638Srgrimes uint8_t buffer[16] = {0}; // Must be big enough for any single instruction 1351638Srgrimes addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress( 1361638Srgrimes pc, pc_addr); 1371638Srgrimes 1381638Srgrimes pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, 1391638Srgrimes Address::DumpStyleModuleWithFileAddress); 1401638Srgrimes stream->PutCString(" "); 1411638Srgrimes 1421638Srgrimes Disassembler *disassembler = GetDisassembler(); 1431638Srgrimes if (disassembler) { 1441638Srgrimes Status err; 1451638Srgrimes process_sp->ReadMemory(pc, buffer, sizeof(buffer), err); 1461638Srgrimes 1471638Srgrimes if (err.Success()) { 1481638Srgrimes DataExtractor extractor(buffer, sizeof(buffer), 1491638Srgrimes process_sp->GetByteOrder(), 1501638Srgrimes process_sp->GetAddressByteSize()); 1511638Srgrimes 15222188Sache bool data_from_file = false; 1531638Srgrimes if (addr_valid) 1541638Srgrimes disassembler->DecodeInstructions(pc_addr, extractor, 0, 1, false, 1551638Srgrimes data_from_file); 1561638Srgrimes else 1571638Srgrimes disassembler->DecodeInstructions(Address(pc), extractor, 0, 1, false, 1581638Srgrimes data_from_file); 1591638Srgrimes 1601638Srgrimes InstructionList &instruction_list = disassembler->GetInstructionList(); 1611638Srgrimes const uint32_t max_opcode_byte_size = 1621638Srgrimes instruction_list.GetMaxOpcocdeByteSize(); 1631638Srgrimes 1641638Srgrimes if (instruction_list.GetSize()) { 1651638Srgrimes const bool show_bytes = true; 1661638Srgrimes const bool show_address = true; 16722188Sache Instruction *instruction = 1681638Srgrimes instruction_list.GetInstructionAtIndex(0).get(); 1691638Srgrimes const FormatEntity::Entry *disassemble_format = 1701638Srgrimes m_thread.GetProcess() 1711638Srgrimes ->GetTarget() 1721638Srgrimes .GetDebugger() 1731638Srgrimes .GetDisassemblyFormat(); 1741638Srgrimes instruction->Dump(stream, max_opcode_byte_size, show_address, 1751638Srgrimes show_bytes, nullptr, nullptr, nullptr, 1761638Srgrimes disassemble_format, 0); 1771638Srgrimes } 1781638Srgrimes } 1791638Srgrimes } 1801638Srgrimes 1811638Srgrimes const ABI *abi = process_sp->GetABI().get(); 18222188Sache TypeFromUser intptr_type = GetIntPointerType(); 1831638Srgrimes 1841638Srgrimes if (abi && intptr_type.IsValid()) { 1851638Srgrimes ValueList value_list; 1861638Srgrimes const int num_args = 1; 1871638Srgrimes 1881638Srgrimes for (int arg_index = 0; arg_index < num_args; ++arg_index) { 1891638Srgrimes Value value; 1901638Srgrimes value.SetValueType(Value::eValueTypeScalar); 1911638Srgrimes // value.SetContext (Value::eContextTypeClangType, 1921638Srgrimes // intptr_type.GetOpaqueQualType()); 1931638Srgrimes value.SetCompilerType(intptr_type); 1941638Srgrimes value_list.PushValue(value); 1951638Srgrimes } 1961638Srgrimes 1971638Srgrimes if (abi->GetArgumentValues(m_thread, value_list)) { 1981638Srgrimes for (int arg_index = 0; arg_index < num_args; ++arg_index) { 1991638Srgrimes stream->Printf( 2001638Srgrimes "\n\targ[%d]=%llx", arg_index, 2011638Srgrimes value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong()); 20222188Sache 2031638Srgrimes if (arg_index + 1 < num_args) 2041638Srgrimes stream->PutCString(", "); 2051638Srgrimes } 2061638Srgrimes } 2071638Srgrimes } 2081638Srgrimes 2091638Srgrimes RegisterValue reg_value; 2101638Srgrimes for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount(); 2111638Srgrimes reg_num < num_registers; ++reg_num) { 2121638Srgrimes const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); 2131638Srgrimes if (reg_ctx->ReadRegister(reg_info, reg_value)) { 2141638Srgrimes assert(reg_num < m_register_values.size()); 2151638Srgrimes if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid || 2161638Srgrimes reg_value != m_register_values[reg_num]) { 21722188Sache if (reg_value.GetType() != RegisterValue::eTypeInvalid) { 2181638Srgrimes stream->PutCString("\n\t"); 2191638Srgrimes DumpRegisterValue(reg_value, stream, reg_info, true, false, 2201638Srgrimes eFormatDefault); 2211638Srgrimes } 2221638Srgrimes } 2231638Srgrimes m_register_values[reg_num] = reg_value; 2241638Srgrimes } 2251638Srgrimes } 2261638Srgrimes stream->EOL(); 2271638Srgrimes stream->Flush(); 2281638Srgrimes} 2291638Srgrimes