blob: 1a3f0d4242d20ea7bfe057436cb0a3ff4eb3b26b [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),
Greg Claytonc51ffbf2011-08-12 21:40:01 +000094 m_disassembler_ap (),
95 m_intptr_type (),
96 m_register_values ()
Sean Callanan5b0228a2010-11-12 03:22:21 +000097{
Jim Inghamae7862a2010-11-17 20:19:50 +000098}
99
100ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread) :
101 ThreadPlanTracer (thread),
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000102 m_disassembler_ap (),
103 m_intptr_type (),
104 m_register_values ()
Jim Inghamae7862a2010-11-17 20:19:50 +0000105{
Jim Inghamae7862a2010-11-17 20:19:50 +0000106}
107
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000108Disassembler *
109ThreadPlanAssemblyTracer::GetDisassembler ()
Jim Inghamae7862a2010-11-17 20:19:50 +0000110{
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000111 if (m_disassembler_ap.get() == NULL)
112 m_disassembler_ap.reset(Disassembler::FindPlugin(m_thread.GetProcess().GetTarget().GetArchitecture(), NULL));
113 return m_disassembler_ap.get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000114}
115
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000116TypeFromUser
117ThreadPlanAssemblyTracer::GetIntPointerType()
118{
119 if (!m_intptr_type.IsValid ())
120 {
121 Target &target = m_thread.GetProcess().GetTarget();
122 Module *exe_module = target.GetExecutableModulePointer();
123
124 if (exe_module)
125 {
126 m_intptr_type = TypeFromUser(exe_module->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, m_thread.GetProcess().GetAddressByteSize() * 8),
127 exe_module->GetClangASTContext().getASTContext());
128 }
129 }
130 return m_intptr_type;
131}
132
133
134
Sean Callanan5b0228a2010-11-12 03:22:21 +0000135ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer()
136{
137}
138
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000139void
140ThreadPlanAssemblyTracer::TracingStarted ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000141{
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000142 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000143
144 if (m_register_values.size() == 0)
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000145 m_register_values.resize (reg_ctx->GetRegisterCount());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000146}
147
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000148void
149ThreadPlanAssemblyTracer::TracingEnded ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000150{
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000151 m_register_values.clear();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000152}
153
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000154static void
155PadOutTo (StreamString &stream, int target)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000156{
157 stream.Flush();
158
159 int length = stream.GetString().length();
160
161 if (length + 1 < target)
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000162 stream.Printf("%*s", target - (length + 1) + 1, "");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000163}
164
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000165void
166ThreadPlanAssemblyTracer::Log ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000167{
168 Stream *stream = GetLogStream ();
169
170 if (!stream)
171 return;
172
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000173 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000174
175 lldb::addr_t pc = reg_ctx->GetPC();
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000176 Process &process = m_thread.GetProcess();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000177 Address pc_addr;
178 bool addr_valid = false;
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000179 uint8_t buffer[16] = {0}; // Must be big enough for any single instruction
180 addr_valid = process.GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000181
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000182 pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
Jim Inghamb5867672011-06-22 21:13:28 +0000183 stream->PutCString (" ");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000184
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000185 Disassembler *disassembler = GetDisassembler();
186 if (disassembler)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000187 {
Sean Callanan5b0228a2010-11-12 03:22:21 +0000188 Error err;
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000189 process.ReadMemory(pc, buffer, sizeof(buffer), err);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000190
191 if (err.Success())
192 {
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000193 DataExtractor extractor(buffer, sizeof(buffer),
194 process.GetByteOrder(),
195 process.GetAddressByteSize());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000196
197 if (addr_valid)
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000198 disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000199 else
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000200 disassembler->DecodeInstructions (Address (NULL, pc), extractor, 0, 1, false);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000201
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000202 InstructionList &instruction_list = disassembler->GetInstructionList();
Greg Clayton889fbd02011-03-26 19:14:58 +0000203 const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
204
Sean Callanan5b0228a2010-11-12 03:22:21 +0000205 if (instruction_list.GetSize())
206 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000207 const bool show_bytes = true;
208 const bool show_address = true;
Sean Callanan5b0228a2010-11-12 03:22:21 +0000209 Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000210 instruction->Dump (stream,
Greg Clayton889fbd02011-03-26 19:14:58 +0000211 max_opcode_byte_size,
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000212 show_address,
213 show_bytes,
Sean Callanan5b0228a2010-11-12 03:22:21 +0000214 NULL,
215 true);
216 }
217 }
Sean Callanan5b0228a2010-11-12 03:22:21 +0000218 }
219
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000220 const ABI *abi = process.GetABI().get();
221 TypeFromUser intptr_type = GetIntPointerType();
222
223 if (abi && intptr_type.IsValid())
Sean Callanan5b0228a2010-11-12 03:22:21 +0000224 {
225 ValueList value_list;
226 const int num_args = 1;
227
228 for (int arg_index = 0; arg_index < num_args; ++arg_index)
229 {
230 Value value;
231 value.SetValueType (Value::eValueTypeScalar);
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000232 value.SetContext (Value::eContextTypeClangType, intptr_type.GetOpaqueQualType());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000233 value_list.PushValue (value);
234 }
235
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000236 if (abi->GetArgumentValues (m_thread, value_list))
Sean Callanan5b0228a2010-11-12 03:22:21 +0000237 {
238 for (int arg_index = 0; arg_index < num_args; ++arg_index)
239 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000240 stream->Printf("\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000241
242 if (arg_index + 1 < num_args)
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000243 stream->PutCString (", ");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000244 }
245 }
246 }
247
Sean Callanan5b0228a2010-11-12 03:22:21 +0000248
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000249 RegisterValue reg_value;
250 for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount();
251 reg_num < num_registers;
252 ++reg_num)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000253 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000254 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
255 if (reg_ctx->ReadRegister (reg_info, reg_value))
Sean Callanan5b0228a2010-11-12 03:22:21 +0000256 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000257 assert (reg_num < m_register_values.size());
258 if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid ||
259 reg_value != m_register_values[reg_num])
260 {
261 if (reg_value.GetType() != RegisterValue::eTypeInvalid)
262 {
263 stream->PutCString ("\n\t");
264 reg_value.Dump(stream, reg_info, true, false, eFormatDefault);
265 }
266 }
267 m_register_values[reg_num] = reg_value;
Sean Callanan5b0228a2010-11-12 03:22:21 +0000268 }
269 }
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000270 stream->EOL();
Caroline Tice2b5e4e62011-06-15 19:35:17 +0000271 stream->Flush();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000272}