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