ThreadPlanTracer.cpp revision 269024
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 169static void 170PadOutTo (StreamString &stream, int target) 171{ 172 stream.Flush(); 173 174 int length = stream.GetString().length(); 175 176 if (length + 1 < target) 177 stream.Printf("%*s", target - (length + 1) + 1, ""); 178} 179 180void 181ThreadPlanAssemblyTracer::Log () 182{ 183 Stream *stream = GetLogStream (); 184 185 if (!stream) 186 return; 187 188 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 189 190 lldb::addr_t pc = reg_ctx->GetPC(); 191 ProcessSP process_sp (m_thread.GetProcess()); 192 Address pc_addr; 193 bool addr_valid = false; 194 uint8_t buffer[16] = {0}; // Must be big enough for any single instruction 195 addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr); 196 197 pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress); 198 stream->PutCString (" "); 199 200 Disassembler *disassembler = GetDisassembler(); 201 if (disassembler) 202 { 203 Error err; 204 process_sp->ReadMemory(pc, buffer, sizeof(buffer), err); 205 206 if (err.Success()) 207 { 208 DataExtractor extractor(buffer, sizeof(buffer), 209 process_sp->GetByteOrder(), 210 process_sp->GetAddressByteSize()); 211 212 bool data_from_file = false; 213 if (addr_valid) 214 disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false, data_from_file); 215 else 216 disassembler->DecodeInstructions (Address (pc), extractor, 0, 1, false, data_from_file); 217 218 InstructionList &instruction_list = disassembler->GetInstructionList(); 219 const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); 220 221 if (instruction_list.GetSize()) 222 { 223 const bool show_bytes = true; 224 const bool show_address = true; 225 Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get(); 226 instruction->Dump (stream, 227 max_opcode_byte_size, 228 show_address, 229 show_bytes, 230 NULL); 231 } 232 } 233 } 234 235 const ABI *abi = process_sp->GetABI().get(); 236 TypeFromUser intptr_type = GetIntPointerType(); 237 238 if (abi && intptr_type.IsValid()) 239 { 240 ValueList value_list; 241 const int num_args = 1; 242 243 for (int arg_index = 0; arg_index < num_args; ++arg_index) 244 { 245 Value value; 246 value.SetValueType (Value::eValueTypeScalar); 247// value.SetContext (Value::eContextTypeClangType, intptr_type.GetOpaqueQualType()); 248 value.SetClangType (intptr_type); 249 value_list.PushValue (value); 250 } 251 252 if (abi->GetArgumentValues (m_thread, value_list)) 253 { 254 for (int arg_index = 0; arg_index < num_args; ++arg_index) 255 { 256 stream->Printf("\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong()); 257 258 if (arg_index + 1 < num_args) 259 stream->PutCString (", "); 260 } 261 } 262 } 263 264 265 RegisterValue reg_value; 266 for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount(); 267 reg_num < num_registers; 268 ++reg_num) 269 { 270 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); 271 if (reg_ctx->ReadRegister (reg_info, reg_value)) 272 { 273 assert (reg_num < m_register_values.size()); 274 if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid || 275 reg_value != m_register_values[reg_num]) 276 { 277 if (reg_value.GetType() != RegisterValue::eTypeInvalid) 278 { 279 stream->PutCString ("\n\t"); 280 reg_value.Dump(stream, reg_info, true, false, eFormatDefault); 281 } 282 } 283 m_register_values[reg_num] = reg_value; 284 } 285 } 286 stream->EOL(); 287 stream->Flush(); 288} 289