blob: f957b804681ad7664331cacbea13abfbc0a828a4 [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
117 ModuleSP executableModuleSP (target.GetExecutableModule());
118 TypeList *type_list = executableModuleSP->GetTypeList();
119
120 if (type_list)
121 {
122 m_intptr_type = TypeFromUser(type_list->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, arch.GetAddressByteSize() * 8),
123 type_list->GetClangASTContext().getASTContext());
124 }
125
126 const unsigned int buf_size = 32;
127
128 m_buffer_sp.reset(new DataBufferHeap(buf_size, 0));
129}
130
131ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer()
132{
133}
134
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000135void
136ThreadPlanAssemblyTracer::TracingStarted ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000137{
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000138 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000139
140 if (m_register_values.size() == 0)
141 {
142 for (uint32_t reg_index = 0, num_registers = reg_ctx->GetRegisterCount();
143 reg_index < num_registers;
144 ++reg_index)
145 m_register_values.push_back(0);
146 }
147}
148
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000149void
150ThreadPlanAssemblyTracer::TracingEnded ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000151{
152 for (uint32_t reg_index = 0, num_registers = m_register_values.size();
153 reg_index < num_registers;
154 ++reg_index)
155 m_register_values[reg_index] = 0;
156}
157
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000158static void
159PadOutTo (StreamString &stream, int target)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000160{
161 stream.Flush();
162
163 int length = stream.GetString().length();
164
165 if (length + 1 < target)
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000166 stream.Printf("%*s", target - (length + 1) + 1, "");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000167}
168
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000169void
170ThreadPlanAssemblyTracer::Log ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000171{
172 Stream *stream = GetLogStream ();
173
174 if (!stream)
175 return;
176
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000177 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000178
179 lldb::addr_t pc = reg_ctx->GetPC();
180 Address pc_addr;
181 bool addr_valid = false;
182
183 StreamString desc;
184
185 int desired_width = 0;
186
187 addr_valid = m_process.GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
188
189 pc_addr.Dump(&desc, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
190
191 desired_width += 64;
192 PadOutTo(desc, desired_width);
193
194 if (m_disassembler)
195 {
196 bzero(m_buffer_sp->GetBytes(), m_buffer_sp->GetByteSize());
197
198 Error err;
199 m_process.ReadMemory(pc, m_buffer_sp->GetBytes(), m_buffer_sp->GetByteSize(), err);
200
201 if (err.Success())
202 {
203 DataExtractor extractor(m_buffer_sp,
204 m_process.GetByteOrder(),
205 m_process.GetAddressByteSize());
206
207 if (addr_valid)
208 m_disassembler->DecodeInstructions (pc_addr, extractor, 0, 1);
209 else
210 m_disassembler->DecodeInstructions (Address (NULL, pc), extractor, 0, 1);
211
212 InstructionList &instruction_list = m_disassembler->GetInstructionList();
213
214 if (instruction_list.GetSize())
215 {
216 Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
217 instruction->Dump (&desc,
218 false,
219 NULL,
220 0,
221 NULL,
222 true);
223 }
224 }
225
226 desired_width += 32;
227 PadOutTo(desc, desired_width);
228 }
229
230 if (m_abi && m_intptr_type.GetOpaqueQualType())
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);
Greg Clayton6916e352010-11-13 03:52:47 +0000239 value.SetContext (Value::eContextTypeClangType, m_intptr_type.GetOpaqueQualType());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000240 value_list.PushValue (value);
241 }
242
243 if (m_abi->GetArgumentValues (m_thread, value_list))
244 {
245 for (int arg_index = 0; arg_index < num_args; ++arg_index)
246 {
247 desc.Printf("arg[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
248
249 if (arg_index + 1 < num_args)
250 desc.Printf(", ");
251 }
252 }
253 }
254
255 desired_width += 20;
256 PadOutTo(desc, desired_width);
257
258 for (uint32_t reg_index = 0, num_registers = reg_ctx->GetRegisterCount();
259 reg_index < num_registers;
260 ++reg_index)
261 {
262 uint64_t reg_value = reg_ctx->ReadRegisterAsUnsigned(reg_index, 0x0);
263
264 if (reg_value != m_register_values[reg_index])
265 {
266 desc.Printf ("%s:0x%llx->0x%llx ", reg_ctx->GetRegisterName(reg_index), m_register_values[reg_index], reg_value);
267
268 m_register_values[reg_index] = reg_value;
269 }
270 }
271
Jim Inghamc7836602010-11-17 20:40:29 +0000272 stream->Printf ("Single-step: %s\n", desc.GetString().c_str());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000273}