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 35 using namespace lldb; 36 using namespace lldb_private; 37 38 #pragma mark ThreadPlanTracer 39 40 ThreadPlanTracer::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 48 ThreadPlanTracer::ThreadPlanTracer (Thread &thread) : 49 m_thread (thread), 50 m_single_step(true), 51 m_enabled (false), 52 m_stream_sp () 53 { 54 } 55 56 Stream * 57 ThreadPlanTracer::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 71 void 72 ThreadPlanTracer::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 88 bool 89 ThreadPlanTracer::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 105 ThreadPlanAssemblyTracer::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 113 ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread) : 114 ThreadPlanTracer (thread), 115 m_disassembler_sp (), 116 m_intptr_type (), 117 m_register_values () 118 { 119 } 120 121 Disassembler * 122 ThreadPlanAssemblyTracer::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 129 TypeFromUser 130 ThreadPlanAssemblyTracer::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 150 ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer() 151 { 152 } 153 154 void 155 ThreadPlanAssemblyTracer::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 163 void 164 ThreadPlanAssemblyTracer::TracingEnded () 165 { 166 m_register_values.clear(); 167 } 168 169 static void 170 PadOutTo (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 180 void 181 ThreadPlanAssemblyTracer::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