blob: b8b7627201a956a7abe59dda0b2cfd39ed955b54 [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"
22#include "lldb/Core/State.h"
Sean Callanan5b0228a2010-11-12 03:22:21 +000023#include "lldb/Core/Value.h"
24#include "lldb/Symbol/TypeList.h"
Jim Ingham745ac7a2010-11-11 19:26:09 +000025#include "lldb/Target/RegisterContext.h"
26#include "lldb/Target/Thread.h"
27#include "lldb/Target/Process.h"
28#include "lldb/Target/Target.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
Sean Callanan5b0228a2010-11-12 03:22:21 +000033#pragma mark ThreadPlanTracer
34
Jim Ingham745ac7a2010-11-11 19:26:09 +000035ThreadPlanTracer::ThreadPlanTracer (Thread &thread, lldb::StreamSP &stream_sp) :
36 m_single_step(true),
37 m_enabled (false),
38 m_thread (thread),
39 m_stream_sp (stream_sp)
40{
41}
42
43ThreadPlanTracer::ThreadPlanTracer (Thread &thread) :
44 m_single_step(true),
45 m_enabled (false),
46 m_thread (thread),
47 m_stream_sp ()
48{
49}
50
51Stream *
52ThreadPlanTracer::GetLogStream ()
53{
54
55 if (m_stream_sp.get())
56 return m_stream_sp.get();
57 else
58 return &(m_thread.GetProcess().GetTarget().GetDebugger().GetOutputStream());
59}
60
61void
62ThreadPlanTracer::Log()
63{
64 SymbolContext sc;
65 bool show_frame_index = false;
66 bool show_fullpaths = false;
67
68 m_thread.GetStackFrameAtIndex(0)->Dump (GetLogStream(), show_frame_index, show_fullpaths);
69 GetLogStream()->Printf("\n");
70}
71
72bool
73ThreadPlanTracer::TracerExplainsStop ()
74{
75 if (m_enabled && m_single_step)
76 {
77 lldb::StopInfoSP stop_info = m_thread.GetStopInfo();
78 if (stop_info->GetStopReason() == eStopReasonTrace)
79 return true;
80 else
81 return false;
82 }
83 else
84 return false;
85}
Sean Callanan5b0228a2010-11-12 03:22:21 +000086
87#pragma mark ThreadPlanAssemblyTracer
88
89ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp) :
90 ThreadPlanTracer (thread, stream_sp),
91 m_process(thread.GetProcess()),
92 m_target(thread.GetProcess().GetTarget())
93{
Jim Inghamae7862a2010-11-17 20:19:50 +000094 InitializeTracer ();
95}
96
97ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread) :
98 ThreadPlanTracer (thread),
99 m_process(thread.GetProcess()),
100 m_target(thread.GetProcess().GetTarget())
101{
102 InitializeTracer ();
103}
104
105void
106ThreadPlanAssemblyTracer::InitializeTracer()
107{
108 Process &process = m_thread.GetProcess();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000109 Target &target = process.GetTarget();
110
111 ArchSpec arch(target.GetArchitecture());
112
113 m_disassembler = Disassembler::FindPlugin(arch);
114
115 m_abi = process.GetABI();
116
Greg Claytonb01000f2011-01-17 03:46:26 +0000117 ModuleSP exe_module_sp (target.GetExecutableModule());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000118
Greg Claytonb01000f2011-01-17 03:46:26 +0000119 if (exe_module_sp)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000120 {
Greg Claytonb01000f2011-01-17 03:46:26 +0000121 m_intptr_type = TypeFromUser(exe_module_sp->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, arch.GetAddressByteSize() * 8),
122 exe_module_sp->GetClangASTContext().getASTContext());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000123 }
124
125 const unsigned int buf_size = 32;
126
127 m_buffer_sp.reset(new DataBufferHeap(buf_size, 0));
128}
129
130ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer()
131{
132}
133
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000134void
135ThreadPlanAssemblyTracer::TracingStarted ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000136{
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000137 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000138
139 if (m_register_values.size() == 0)
140 {
141 for (uint32_t reg_index = 0, num_registers = reg_ctx->GetRegisterCount();
142 reg_index < num_registers;
143 ++reg_index)
144 m_register_values.push_back(0);
145 }
146}
147
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000148void
149ThreadPlanAssemblyTracer::TracingEnded ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000150{
151 for (uint32_t reg_index = 0, num_registers = m_register_values.size();
152 reg_index < num_registers;
153 ++reg_index)
154 m_register_values[reg_index] = 0;
155}
156
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000157static void
158PadOutTo (StreamString &stream, int target)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000159{
160 stream.Flush();
161
162 int length = stream.GetString().length();
163
164 if (length + 1 < target)
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000165 stream.Printf("%*s", target - (length + 1) + 1, "");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000166}
167
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000168void
169ThreadPlanAssemblyTracer::Log ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000170{
171 Stream *stream = GetLogStream ();
172
173 if (!stream)
174 return;
175
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000176 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000177
178 lldb::addr_t pc = reg_ctx->GetPC();
179 Address pc_addr;
180 bool addr_valid = false;
181
182 StreamString desc;
183
184 int desired_width = 0;
185
186 addr_valid = m_process.GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
187
188 pc_addr.Dump(&desc, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
189
190 desired_width += 64;
191 PadOutTo(desc, desired_width);
192
193 if (m_disassembler)
194 {
Greg Claytonddff7cc2011-02-04 21:13:05 +0000195 ::memset(m_buffer_sp->GetBytes(), 0, m_buffer_sp->GetByteSize());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000196
197 Error err;
198 m_process.ReadMemory(pc, m_buffer_sp->GetBytes(), m_buffer_sp->GetByteSize(), err);
199
200 if (err.Success())
201 {
202 DataExtractor extractor(m_buffer_sp,
203 m_process.GetByteOrder(),
204 m_process.GetAddressByteSize());
205
206 if (addr_valid)
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000207 m_disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000208 else
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000209 m_disassembler->DecodeInstructions (Address (NULL, pc), extractor, 0, 1, false);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000210
211 InstructionList &instruction_list = m_disassembler->GetInstructionList();
212
213 if (instruction_list.GetSize())
214 {
215 Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
216 instruction->Dump (&desc,
217 false,
218 NULL,
219 0,
220 NULL,
221 true);
222 }
223 }
224
225 desired_width += 32;
226 PadOutTo(desc, desired_width);
227 }
228
229 if (m_abi && m_intptr_type.GetOpaqueQualType())
230 {
231 ValueList value_list;
232 const int num_args = 1;
233
234 for (int arg_index = 0; arg_index < num_args; ++arg_index)
235 {
236 Value value;
237 value.SetValueType (Value::eValueTypeScalar);
Greg Clayton6916e352010-11-13 03:52:47 +0000238 value.SetContext (Value::eContextTypeClangType, m_intptr_type.GetOpaqueQualType());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000239 value_list.PushValue (value);
240 }
241
242 if (m_abi->GetArgumentValues (m_thread, value_list))
243 {
244 for (int arg_index = 0; arg_index < num_args; ++arg_index)
245 {
246 desc.Printf("arg[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
247
248 if (arg_index + 1 < num_args)
249 desc.Printf(", ");
250 }
251 }
252 }
253
254 desired_width += 20;
255 PadOutTo(desc, desired_width);
256
257 for (uint32_t reg_index = 0, num_registers = reg_ctx->GetRegisterCount();
258 reg_index < num_registers;
259 ++reg_index)
260 {
261 uint64_t reg_value = reg_ctx->ReadRegisterAsUnsigned(reg_index, 0x0);
262
263 if (reg_value != m_register_values[reg_index])
264 {
265 desc.Printf ("%s:0x%llx->0x%llx ", reg_ctx->GetRegisterName(reg_index), m_register_values[reg_index], reg_value);
266
267 m_register_values[reg_index] = reg_value;
268 }
269 }
270
Jim Inghamc7836602010-11-17 20:40:29 +0000271 stream->Printf ("Single-step: %s\n", desc.GetString().c_str());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000272}