blob: 87e5e1964fb51140f1c17b727e540415bc058ae5 [file] [log] [blame]
Jim Ingham745ac7a2010-11-11 19:26:09 +00001//===-- 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
Sean Callanan5b0228a2010-11-12 03:22:21 +000013#include <string.h>
Jim Ingham745ac7a2010-11-11 19:26:09 +000014// C++ Includes
15// Other libraries and framework includes
16// Project includes
Sean Callanan5b0228a2010-11-12 03:22:21 +000017#include "lldb/Core/ArchSpec.h"
18#include "lldb/Core/DataBufferHeap.h"
Jim Ingham745ac7a2010-11-11 19:26:09 +000019#include "lldb/Core/Debugger.h"
Sean Callanan5b0228a2010-11-12 03:22:21 +000020#include "lldb/Core/Disassembler.h"
Jim Ingham745ac7a2010-11-11 19:26:09 +000021#include "lldb/Core/Log.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000022#include "lldb/Core/Module.h"
Jim Ingham745ac7a2010-11-11 19:26:09 +000023#include "lldb/Core/State.h"
Sean Callanan5b0228a2010-11-12 03:22:21 +000024#include "lldb/Core/Value.h"
25#include "lldb/Symbol/TypeList.h"
Jim Ingham745ac7a2010-11-11 19:26:09 +000026#include "lldb/Target/RegisterContext.h"
27#include "lldb/Target/Thread.h"
28#include "lldb/Target/Process.h"
29#include "lldb/Target/Target.h"
30
31using namespace lldb;
32using namespace lldb_private;
33
Sean Callanan5b0228a2010-11-12 03:22:21 +000034#pragma mark ThreadPlanTracer
35
Jim Ingham745ac7a2010-11-11 19:26:09 +000036ThreadPlanTracer::ThreadPlanTracer (Thread &thread, lldb::StreamSP &stream_sp) :
Stephen Wilsondbeb3e12011-04-11 19:41:40 +000037 m_thread (thread),
Jim Ingham745ac7a2010-11-11 19:26:09 +000038 m_single_step(true),
39 m_enabled (false),
Jim Ingham745ac7a2010-11-11 19:26:09 +000040 m_stream_sp (stream_sp)
41{
42}
43
44ThreadPlanTracer::ThreadPlanTracer (Thread &thread) :
Stephen Wilsondbeb3e12011-04-11 19:41:40 +000045 m_thread (thread),
Jim Ingham745ac7a2010-11-11 19:26:09 +000046 m_single_step(true),
47 m_enabled (false),
Jim Ingham745ac7a2010-11-11 19:26:09 +000048 m_stream_sp ()
49{
50}
51
52Stream *
53ThreadPlanTracer::GetLogStream ()
54{
55
56 if (m_stream_sp.get())
57 return m_stream_sp.get();
58 else
Greg Claytonf4124de2012-02-21 00:09:25 +000059 {
60 TargetSP target_sp (m_thread.CalculateTarget());
61 if (target_sp)
62 return &target_sp->GetDebugger().GetOutputStream();
63 }
64 return NULL;
Jim Ingham745ac7a2010-11-11 19:26:09 +000065}
66
67void
68ThreadPlanTracer::Log()
69{
70 SymbolContext sc;
71 bool show_frame_index = false;
72 bool show_fullpaths = false;
73
Caroline Tice2b5e4e62011-06-15 19:35:17 +000074 Stream *stream = GetLogStream();
75 m_thread.GetStackFrameAtIndex(0)->Dump (stream, show_frame_index, show_fullpaths);
76 stream->Printf("\n");
77 stream->Flush();
78
Jim Ingham745ac7a2010-11-11 19:26:09 +000079}
80
81bool
82ThreadPlanTracer::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}
Sean Callanan5b0228a2010-11-12 03:22:21 +000095
96#pragma mark ThreadPlanAssemblyTracer
97
98ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp) :
99 ThreadPlanTracer (thread, stream_sp),
Sean Callanan4f28c312012-08-01 18:50:59 +0000100 m_disassembler_sp (),
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000101 m_intptr_type (),
102 m_register_values ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000103{
Jim Inghamae7862a2010-11-17 20:19:50 +0000104}
105
106ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread) :
107 ThreadPlanTracer (thread),
Sean Callanan4f28c312012-08-01 18:50:59 +0000108 m_disassembler_sp (),
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000109 m_intptr_type (),
110 m_register_values ()
Jim Inghamae7862a2010-11-17 20:19:50 +0000111{
Jim Inghamae7862a2010-11-17 20:19:50 +0000112}
113
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000114Disassembler *
115ThreadPlanAssemblyTracer::GetDisassembler ()
Jim Inghamae7862a2010-11-17 20:19:50 +0000116{
Sean Callanan4f28c312012-08-01 18:50:59 +0000117 if (m_disassembler_sp.get() == NULL)
118 m_disassembler_sp = Disassembler::FindPlugin(m_thread.GetProcess()->GetTarget().GetArchitecture(), NULL);
119 return m_disassembler_sp.get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000120}
121
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000122TypeFromUser
123ThreadPlanAssemblyTracer::GetIntPointerType()
124{
125 if (!m_intptr_type.IsValid ())
126 {
Greg Claytonf4124de2012-02-21 00:09:25 +0000127 TargetSP target_sp (m_thread.CalculateTarget());
128 if (target_sp)
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000129 {
Greg Claytonf4124de2012-02-21 00:09:25 +0000130 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 }
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000137 }
138 }
139 return m_intptr_type;
140}
141
142
143
Sean Callanan5b0228a2010-11-12 03:22:21 +0000144ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer()
145{
146}
147
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000148void
149ThreadPlanAssemblyTracer::TracingStarted ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000150{
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000151 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000152
153 if (m_register_values.size() == 0)
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000154 m_register_values.resize (reg_ctx->GetRegisterCount());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000155}
156
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000157void
158ThreadPlanAssemblyTracer::TracingEnded ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000159{
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000160 m_register_values.clear();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000161}
162
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000163static void
164PadOutTo (StreamString &stream, int target)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000165{
166 stream.Flush();
167
168 int length = stream.GetString().length();
169
170 if (length + 1 < target)
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000171 stream.Printf("%*s", target - (length + 1) + 1, "");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000172}
173
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000174void
175ThreadPlanAssemblyTracer::Log ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000176{
177 Stream *stream = GetLogStream ();
178
179 if (!stream)
180 return;
181
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000182 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000183
184 lldb::addr_t pc = reg_ctx->GetPC();
Greg Claytonf4124de2012-02-21 00:09:25 +0000185 ProcessSP process_sp (m_thread.GetProcess());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000186 Address pc_addr;
187 bool addr_valid = false;
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000188 uint8_t buffer[16] = {0}; // Must be big enough for any single instruction
Greg Claytonf4124de2012-02-21 00:09:25 +0000189 addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000190
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000191 pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
Jim Inghamb5867672011-06-22 21:13:28 +0000192 stream->PutCString (" ");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000193
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000194 Disassembler *disassembler = GetDisassembler();
195 if (disassembler)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000196 {
Sean Callanan5b0228a2010-11-12 03:22:21 +0000197 Error err;
Greg Claytonf4124de2012-02-21 00:09:25 +0000198 process_sp->ReadMemory(pc, buffer, sizeof(buffer), err);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000199
200 if (err.Success())
201 {
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000202 DataExtractor extractor(buffer, sizeof(buffer),
Greg Claytonf4124de2012-02-21 00:09:25 +0000203 process_sp->GetByteOrder(),
204 process_sp->GetAddressByteSize());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000205
206 if (addr_valid)
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000207 disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000208 else
Greg Clayton3508c382012-02-24 01:59:29 +0000209 disassembler->DecodeInstructions (Address (pc), extractor, 0, 1, false);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000210
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000211 InstructionList &instruction_list = disassembler->GetInstructionList();
Greg Clayton889fbd02011-03-26 19:14:58 +0000212 const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
213
Sean Callanan5b0228a2010-11-12 03:22:21 +0000214 if (instruction_list.GetSize())
215 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000216 const bool show_bytes = true;
217 const bool show_address = true;
Sean Callanan5b0228a2010-11-12 03:22:21 +0000218 Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000219 instruction->Dump (stream,
Greg Clayton889fbd02011-03-26 19:14:58 +0000220 max_opcode_byte_size,
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000221 show_address,
222 show_bytes,
Greg Clayton0fef9682012-05-10 02:52:23 +0000223 NULL);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000224 }
225 }
Sean Callanan5b0228a2010-11-12 03:22:21 +0000226 }
227
Greg Claytonf4124de2012-02-21 00:09:25 +0000228 const ABI *abi = process_sp->GetABI().get();
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000229 TypeFromUser intptr_type = GetIntPointerType();
230
231 if (abi && intptr_type.IsValid())
Sean Callanan5b0228a2010-11-12 03:22:21 +0000232 {
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);
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000240 value.SetContext (Value::eContextTypeClangType, intptr_type.GetOpaqueQualType());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000241 value_list.PushValue (value);
242 }
243
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000244 if (abi->GetArgumentValues (m_thread, value_list))
Sean Callanan5b0228a2010-11-12 03:22:21 +0000245 {
246 for (int arg_index = 0; arg_index < num_args; ++arg_index)
247 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000248 stream->Printf("\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000249
250 if (arg_index + 1 < num_args)
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000251 stream->PutCString (", ");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000252 }
253 }
254 }
255
Sean Callanan5b0228a2010-11-12 03:22:21 +0000256
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000257 RegisterValue reg_value;
258 for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount();
259 reg_num < num_registers;
260 ++reg_num)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000261 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000262 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
263 if (reg_ctx->ReadRegister (reg_info, reg_value))
Sean Callanan5b0228a2010-11-12 03:22:21 +0000264 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000265 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;
Sean Callanan5b0228a2010-11-12 03:22:21 +0000276 }
277 }
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000278 stream->EOL();
Caroline Tice2b5e4e62011-06-15 19:35:17 +0000279 stream->Flush();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000280}