blob: 88564271ff56790c0e12f1f54b3f882d801e81de [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) :
Stephen Wilsondbeb3e12011-04-11 19:41:40 +000036 m_thread (thread),
Jim Ingham745ac7a2010-11-11 19:26:09 +000037 m_single_step(true),
38 m_enabled (false),
Jim Ingham745ac7a2010-11-11 19:26:09 +000039 m_stream_sp (stream_sp)
40{
41}
42
43ThreadPlanTracer::ThreadPlanTracer (Thread &thread) :
Stephen Wilsondbeb3e12011-04-11 19:41:40 +000044 m_thread (thread),
Jim Ingham745ac7a2010-11-11 19:26:09 +000045 m_single_step(true),
46 m_enabled (false),
Jim Ingham745ac7a2010-11-11 19:26:09 +000047 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
Jim Ingham41ae8122011-06-22 18:23:52 +000058 return &m_thread.GetProcess().GetTarget().GetDebugger().GetOutputStream();
Jim Ingham745ac7a2010-11-11 19:26:09 +000059}
60
61void
62ThreadPlanTracer::Log()
63{
64 SymbolContext sc;
65 bool show_frame_index = false;
66 bool show_fullpaths = false;
67
Caroline Tice2b5e4e62011-06-15 19:35:17 +000068 Stream *stream = GetLogStream();
69 m_thread.GetStackFrameAtIndex(0)->Dump (stream, show_frame_index, show_fullpaths);
70 stream->Printf("\n");
71 stream->Flush();
72
Jim Ingham745ac7a2010-11-11 19:26:09 +000073}
74
75bool
76ThreadPlanTracer::TracerExplainsStop ()
77{
78 if (m_enabled && m_single_step)
79 {
80 lldb::StopInfoSP stop_info = m_thread.GetStopInfo();
81 if (stop_info->GetStopReason() == eStopReasonTrace)
82 return true;
83 else
84 return false;
85 }
86 else
87 return false;
88}
Sean Callanan5b0228a2010-11-12 03:22:21 +000089
90#pragma mark ThreadPlanAssemblyTracer
91
92ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp) :
93 ThreadPlanTracer (thread, stream_sp),
94 m_process(thread.GetProcess()),
95 m_target(thread.GetProcess().GetTarget())
96{
Jim Inghamae7862a2010-11-17 20:19:50 +000097 InitializeTracer ();
98}
99
100ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread) :
101 ThreadPlanTracer (thread),
102 m_process(thread.GetProcess()),
103 m_target(thread.GetProcess().GetTarget())
104{
105 InitializeTracer ();
106}
107
108void
109ThreadPlanAssemblyTracer::InitializeTracer()
110{
111 Process &process = m_thread.GetProcess();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000112 Target &target = process.GetTarget();
113
114 ArchSpec arch(target.GetArchitecture());
115
Greg Clayton149731c2011-03-25 18:03:16 +0000116 m_disassembler = Disassembler::FindPlugin(arch, NULL);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000117
Greg Clayton75906e42011-05-11 18:39:18 +0000118 m_abi = process.GetABI().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000119
Greg Claytonb01000f2011-01-17 03:46:26 +0000120 ModuleSP exe_module_sp (target.GetExecutableModule());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000121
Greg Claytonb01000f2011-01-17 03:46:26 +0000122 if (exe_module_sp)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000123 {
Greg Claytonb01000f2011-01-17 03:46:26 +0000124 m_intptr_type = TypeFromUser(exe_module_sp->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, arch.GetAddressByteSize() * 8),
125 exe_module_sp->GetClangASTContext().getASTContext());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000126 }
127
128 const unsigned int buf_size = 32;
129
130 m_buffer_sp.reset(new DataBufferHeap(buf_size, 0));
131}
132
133ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer()
134{
135}
136
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000137void
138ThreadPlanAssemblyTracer::TracingStarted ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000139{
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000140 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000141
142 if (m_register_values.size() == 0)
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000143 m_register_values.resize (reg_ctx->GetRegisterCount());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000144}
145
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000146void
147ThreadPlanAssemblyTracer::TracingEnded ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000148{
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000149 m_register_values.clear();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000150}
151
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000152static void
153PadOutTo (StreamString &stream, int target)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000154{
155 stream.Flush();
156
157 int length = stream.GetString().length();
158
159 if (length + 1 < target)
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000160 stream.Printf("%*s", target - (length + 1) + 1, "");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000161}
162
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000163void
164ThreadPlanAssemblyTracer::Log ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000165{
166 Stream *stream = GetLogStream ();
167
168 if (!stream)
169 return;
170
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000171 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000172
173 lldb::addr_t pc = reg_ctx->GetPC();
174 Address pc_addr;
175 bool addr_valid = false;
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000176
Sean Callanan5b0228a2010-11-12 03:22:21 +0000177 addr_valid = m_process.GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
178
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000179 pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
Jim Inghamb5867672011-06-22 21:13:28 +0000180 stream->PutCString (" ");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000181
182 if (m_disassembler)
183 {
Greg Claytonddff7cc2011-02-04 21:13:05 +0000184 ::memset(m_buffer_sp->GetBytes(), 0, m_buffer_sp->GetByteSize());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000185
186 Error err;
187 m_process.ReadMemory(pc, m_buffer_sp->GetBytes(), m_buffer_sp->GetByteSize(), err);
188
189 if (err.Success())
190 {
191 DataExtractor extractor(m_buffer_sp,
192 m_process.GetByteOrder(),
193 m_process.GetAddressByteSize());
194
195 if (addr_valid)
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000196 m_disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000197 else
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000198 m_disassembler->DecodeInstructions (Address (NULL, pc), extractor, 0, 1, false);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000199
200 InstructionList &instruction_list = m_disassembler->GetInstructionList();
Greg Clayton889fbd02011-03-26 19:14:58 +0000201 const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
202
Sean Callanan5b0228a2010-11-12 03:22:21 +0000203 if (instruction_list.GetSize())
204 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000205 const bool show_bytes = true;
206 const bool show_address = true;
Sean Callanan5b0228a2010-11-12 03:22:21 +0000207 Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000208 instruction->Dump (stream,
Greg Clayton889fbd02011-03-26 19:14:58 +0000209 max_opcode_byte_size,
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000210 show_address,
211 show_bytes,
Sean Callanan5b0228a2010-11-12 03:22:21 +0000212 NULL,
213 true);
214 }
215 }
Sean Callanan5b0228a2010-11-12 03:22:21 +0000216 }
217
218 if (m_abi && m_intptr_type.GetOpaqueQualType())
219 {
220 ValueList value_list;
221 const int num_args = 1;
222
223 for (int arg_index = 0; arg_index < num_args; ++arg_index)
224 {
225 Value value;
226 value.SetValueType (Value::eValueTypeScalar);
Greg Clayton6916e352010-11-13 03:52:47 +0000227 value.SetContext (Value::eContextTypeClangType, m_intptr_type.GetOpaqueQualType());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000228 value_list.PushValue (value);
229 }
230
231 if (m_abi->GetArgumentValues (m_thread, value_list))
232 {
233 for (int arg_index = 0; arg_index < num_args; ++arg_index)
234 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000235 stream->Printf("\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000236
237 if (arg_index + 1 < num_args)
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000238 stream->PutCString (", ");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000239 }
240 }
241 }
242
Sean Callanan5b0228a2010-11-12 03:22:21 +0000243
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000244 RegisterValue reg_value;
245 for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount();
246 reg_num < num_registers;
247 ++reg_num)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000248 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000249 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
250 if (reg_ctx->ReadRegister (reg_info, reg_value))
Sean Callanan5b0228a2010-11-12 03:22:21 +0000251 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000252 assert (reg_num < m_register_values.size());
253 if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid ||
254 reg_value != m_register_values[reg_num])
255 {
256 if (reg_value.GetType() != RegisterValue::eTypeInvalid)
257 {
258 stream->PutCString ("\n\t");
259 reg_value.Dump(stream, reg_info, true, false, eFormatDefault);
260 }
261 }
262 m_register_values[reg_num] = reg_value;
Sean Callanan5b0228a2010-11-12 03:22:21 +0000263 }
264 }
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000265 stream->EOL();
Caroline Tice2b5e4e62011-06-15 19:35:17 +0000266 stream->Flush();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000267}