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