blob: 0ca2d1778000cd12d71e2235a16c3787829dd588 [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
135void ThreadPlanAssemblyTracer::TracingStarted ()
136{
137 RegisterContext *reg_ctx = m_thread.GetRegisterContext();
138
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
148void ThreadPlanAssemblyTracer::TracingEnded ()
149{
150 for (uint32_t reg_index = 0, num_registers = m_register_values.size();
151 reg_index < num_registers;
152 ++reg_index)
153 m_register_values[reg_index] = 0;
154}
155
156static const char *Padding(int length)
157{
158 const int padding_size = 256;
159
160 static char* padding = NULL;
161 static int prev_length = 256;
162
163 if (!padding) {
164 padding = new char[padding_size];
165 memset(padding, ' ', padding_size);
166 }
167
168 if (length > 255)
169 length = 255;
170
171 if (prev_length < 256)
172 padding[prev_length] = ' ';
173
174 padding[length] = '\0';
175
176 prev_length = length;
177
178 return padding;
179}
180
181static void PadOutTo(StreamString &stream, int target)
182{
183 stream.Flush();
184
185 int length = stream.GetString().length();
186
187 if (length + 1 < target)
188 stream.PutCString(Padding(target - (length + 1)));
189
190 stream.PutCString(" ");
191}
192
193void ThreadPlanAssemblyTracer::Log ()
194{
195 Stream *stream = GetLogStream ();
196
197 if (!stream)
198 return;
199
200 RegisterContext *reg_ctx = m_thread.GetRegisterContext();
201
202 lldb::addr_t pc = reg_ctx->GetPC();
203 Address pc_addr;
204 bool addr_valid = false;
205
206 StreamString desc;
207
208 int desired_width = 0;
209
210 addr_valid = m_process.GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
211
212 pc_addr.Dump(&desc, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
213
214 desired_width += 64;
215 PadOutTo(desc, desired_width);
216
217 if (m_disassembler)
218 {
219 bzero(m_buffer_sp->GetBytes(), m_buffer_sp->GetByteSize());
220
221 Error err;
222 m_process.ReadMemory(pc, m_buffer_sp->GetBytes(), m_buffer_sp->GetByteSize(), err);
223
224 if (err.Success())
225 {
226 DataExtractor extractor(m_buffer_sp,
227 m_process.GetByteOrder(),
228 m_process.GetAddressByteSize());
229
230 if (addr_valid)
231 m_disassembler->DecodeInstructions (pc_addr, extractor, 0, 1);
232 else
233 m_disassembler->DecodeInstructions (Address (NULL, pc), extractor, 0, 1);
234
235 InstructionList &instruction_list = m_disassembler->GetInstructionList();
236
237 if (instruction_list.GetSize())
238 {
239 Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
240 instruction->Dump (&desc,
241 false,
242 NULL,
243 0,
244 NULL,
245 true);
246 }
247 }
248
249 desired_width += 32;
250 PadOutTo(desc, desired_width);
251 }
252
253 if (m_abi && m_intptr_type.GetOpaqueQualType())
254 {
255 ValueList value_list;
256 const int num_args = 1;
257
258 for (int arg_index = 0; arg_index < num_args; ++arg_index)
259 {
260 Value value;
261 value.SetValueType (Value::eValueTypeScalar);
Greg Clayton6916e352010-11-13 03:52:47 +0000262 value.SetContext (Value::eContextTypeClangType, m_intptr_type.GetOpaqueQualType());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000263 value_list.PushValue (value);
264 }
265
266 if (m_abi->GetArgumentValues (m_thread, value_list))
267 {
268 for (int arg_index = 0; arg_index < num_args; ++arg_index)
269 {
270 desc.Printf("arg[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
271
272 if (arg_index + 1 < num_args)
273 desc.Printf(", ");
274 }
275 }
276 }
277
278 desired_width += 20;
279 PadOutTo(desc, desired_width);
280
281 for (uint32_t reg_index = 0, num_registers = reg_ctx->GetRegisterCount();
282 reg_index < num_registers;
283 ++reg_index)
284 {
285 uint64_t reg_value = reg_ctx->ReadRegisterAsUnsigned(reg_index, 0x0);
286
287 if (reg_value != m_register_values[reg_index])
288 {
289 desc.Printf ("%s:0x%llx->0x%llx ", reg_ctx->GetRegisterName(reg_index), m_register_values[reg_index], reg_value);
290
291 m_register_values[reg_index] = reg_value;
292 }
293 }
294
Jim Inghamc7836602010-11-17 20:40:29 +0000295 stream->Printf ("Single-step: %s\n", desc.GetString().c_str());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000296}