blob: bf0235390027a6f6cc01dcc3311ae216dca86c49 [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);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000180
181 if (m_disassembler)
182 {
Greg Claytonddff7cc2011-02-04 21:13:05 +0000183 ::memset(m_buffer_sp->GetBytes(), 0, m_buffer_sp->GetByteSize());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000184
185 Error err;
186 m_process.ReadMemory(pc, m_buffer_sp->GetBytes(), m_buffer_sp->GetByteSize(), err);
187
188 if (err.Success())
189 {
190 DataExtractor extractor(m_buffer_sp,
191 m_process.GetByteOrder(),
192 m_process.GetAddressByteSize());
193
194 if (addr_valid)
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000195 m_disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000196 else
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000197 m_disassembler->DecodeInstructions (Address (NULL, pc), extractor, 0, 1, false);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000198
199 InstructionList &instruction_list = m_disassembler->GetInstructionList();
Greg Clayton889fbd02011-03-26 19:14:58 +0000200 const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
201
Sean Callanan5b0228a2010-11-12 03:22:21 +0000202 if (instruction_list.GetSize())
203 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000204 const bool show_bytes = true;
205 const bool show_address = true;
Sean Callanan5b0228a2010-11-12 03:22:21 +0000206 Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000207 instruction->Dump (stream,
Greg Clayton889fbd02011-03-26 19:14:58 +0000208 max_opcode_byte_size,
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000209 show_address,
210 show_bytes,
Sean Callanan5b0228a2010-11-12 03:22:21 +0000211 NULL,
212 true);
213 }
214 }
Sean Callanan5b0228a2010-11-12 03:22:21 +0000215 }
216
217 if (m_abi && m_intptr_type.GetOpaqueQualType())
218 {
219 ValueList value_list;
220 const int num_args = 1;
221
222 for (int arg_index = 0; arg_index < num_args; ++arg_index)
223 {
224 Value value;
225 value.SetValueType (Value::eValueTypeScalar);
Greg Clayton6916e352010-11-13 03:52:47 +0000226 value.SetContext (Value::eContextTypeClangType, m_intptr_type.GetOpaqueQualType());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000227 value_list.PushValue (value);
228 }
229
230 if (m_abi->GetArgumentValues (m_thread, value_list))
231 {
232 for (int arg_index = 0; arg_index < num_args; ++arg_index)
233 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000234 stream->Printf("\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000235
236 if (arg_index + 1 < num_args)
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000237 stream->PutCString (", ");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000238 }
239 }
240 }
241
Sean Callanan5b0228a2010-11-12 03:22:21 +0000242
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000243 RegisterValue reg_value;
244 for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount();
245 reg_num < num_registers;
246 ++reg_num)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000247 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000248 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
249 if (reg_ctx->ReadRegister (reg_info, reg_value))
Sean Callanan5b0228a2010-11-12 03:22:21 +0000250 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000251 assert (reg_num < m_register_values.size());
252 if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid ||
253 reg_value != m_register_values[reg_num])
254 {
255 if (reg_value.GetType() != RegisterValue::eTypeInvalid)
256 {
257 stream->PutCString ("\n\t");
258 reg_value.Dump(stream, reg_info, true, false, eFormatDefault);
259 }
260 }
261 m_register_values[reg_num] = reg_value;
Sean Callanan5b0228a2010-11-12 03:22:21 +0000262 }
263 }
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000264 stream->EOL();
Caroline Tice2b5e4e62011-06-15 19:35:17 +0000265 stream->Flush();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000266}