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