blob: f77d0fac1976ae93e0e5209e3064c8771c46d686 [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{
94 Process &process = thread.GetProcess();
95 Target &target = process.GetTarget();
96
97 ArchSpec arch(target.GetArchitecture());
98
99 m_disassembler = Disassembler::FindPlugin(arch);
100
101 m_abi = process.GetABI();
102
103 ModuleSP executableModuleSP (target.GetExecutableModule());
104 TypeList *type_list = executableModuleSP->GetTypeList();
105
106 if (type_list)
107 {
108 m_intptr_type = TypeFromUser(type_list->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, arch.GetAddressByteSize() * 8),
109 type_list->GetClangASTContext().getASTContext());
110 }
111
112 const unsigned int buf_size = 32;
113
114 m_buffer_sp.reset(new DataBufferHeap(buf_size, 0));
115}
116
117ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer()
118{
119}
120
121void ThreadPlanAssemblyTracer::TracingStarted ()
122{
123 RegisterContext *reg_ctx = m_thread.GetRegisterContext();
124
125 if (m_register_values.size() == 0)
126 {
127 for (uint32_t reg_index = 0, num_registers = reg_ctx->GetRegisterCount();
128 reg_index < num_registers;
129 ++reg_index)
130 m_register_values.push_back(0);
131 }
132}
133
134void ThreadPlanAssemblyTracer::TracingEnded ()
135{
136 for (uint32_t reg_index = 0, num_registers = m_register_values.size();
137 reg_index < num_registers;
138 ++reg_index)
139 m_register_values[reg_index] = 0;
140}
141
142static const char *Padding(int length)
143{
144 const int padding_size = 256;
145
146 static char* padding = NULL;
147 static int prev_length = 256;
148
149 if (!padding) {
150 padding = new char[padding_size];
151 memset(padding, ' ', padding_size);
152 }
153
154 if (length > 255)
155 length = 255;
156
157 if (prev_length < 256)
158 padding[prev_length] = ' ';
159
160 padding[length] = '\0';
161
162 prev_length = length;
163
164 return padding;
165}
166
167static void PadOutTo(StreamString &stream, int target)
168{
169 stream.Flush();
170
171 int length = stream.GetString().length();
172
173 if (length + 1 < target)
174 stream.PutCString(Padding(target - (length + 1)));
175
176 stream.PutCString(" ");
177}
178
179void ThreadPlanAssemblyTracer::Log ()
180{
181 Stream *stream = GetLogStream ();
182
183 if (!stream)
184 return;
185
186 RegisterContext *reg_ctx = m_thread.GetRegisterContext();
187
188 lldb::addr_t pc = reg_ctx->GetPC();
189 Address pc_addr;
190 bool addr_valid = false;
191
192 StreamString desc;
193
194 int desired_width = 0;
195
196 addr_valid = m_process.GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
197
198 pc_addr.Dump(&desc, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
199
200 desired_width += 64;
201 PadOutTo(desc, desired_width);
202
203 if (m_disassembler)
204 {
205 bzero(m_buffer_sp->GetBytes(), m_buffer_sp->GetByteSize());
206
207 Error err;
208 m_process.ReadMemory(pc, m_buffer_sp->GetBytes(), m_buffer_sp->GetByteSize(), err);
209
210 if (err.Success())
211 {
212 DataExtractor extractor(m_buffer_sp,
213 m_process.GetByteOrder(),
214 m_process.GetAddressByteSize());
215
216 if (addr_valid)
217 m_disassembler->DecodeInstructions (pc_addr, extractor, 0, 1);
218 else
219 m_disassembler->DecodeInstructions (Address (NULL, pc), extractor, 0, 1);
220
221 InstructionList &instruction_list = m_disassembler->GetInstructionList();
222
223 if (instruction_list.GetSize())
224 {
225 Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
226 instruction->Dump (&desc,
227 false,
228 NULL,
229 0,
230 NULL,
231 true);
232 }
233 }
234
235 desired_width += 32;
236 PadOutTo(desc, desired_width);
237 }
238
239 if (m_abi && m_intptr_type.GetOpaqueQualType())
240 {
241 ValueList value_list;
242 const int num_args = 1;
243
244 for (int arg_index = 0; arg_index < num_args; ++arg_index)
245 {
246 Value value;
247 value.SetValueType (Value::eValueTypeScalar);
248 value.SetContext (Value::eContextTypeOpaqueClangQualType, m_intptr_type.GetOpaqueQualType());
249 value_list.PushValue (value);
250 }
251
252 if (m_abi->GetArgumentValues (m_thread, value_list))
253 {
254 for (int arg_index = 0; arg_index < num_args; ++arg_index)
255 {
256 desc.Printf("arg[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
257
258 if (arg_index + 1 < num_args)
259 desc.Printf(", ");
260 }
261 }
262 }
263
264 desired_width += 20;
265 PadOutTo(desc, desired_width);
266
267 for (uint32_t reg_index = 0, num_registers = reg_ctx->GetRegisterCount();
268 reg_index < num_registers;
269 ++reg_index)
270 {
271 uint64_t reg_value = reg_ctx->ReadRegisterAsUnsigned(reg_index, 0x0);
272
273 if (reg_value != m_register_values[reg_index])
274 {
275 desc.Printf ("%s:0x%llx->0x%llx ", reg_ctx->GetRegisterName(reg_index), m_register_values[reg_index], reg_value);
276
277 m_register_values[reg_index] = reg_value;
278 }
279 }
280
281 stream->Printf ("Single-step: %s", desc.GetString().c_str());
282}