blob: ab61c3c763909b69b7e746efaa05ba29743f72bd [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"
Greg Clayton49ce8962012-08-29 21:13:06 +000022#include "lldb/Core/Module.h"
Jim Ingham745ac7a2010-11-11 19:26:09 +000023#include "lldb/Core/State.h"
Sean Callanan5b0228a2010-11-12 03:22:21 +000024#include "lldb/Core/Value.h"
25#include "lldb/Symbol/TypeList.h"
Jim Ingham745ac7a2010-11-11 19:26:09 +000026#include "lldb/Target/RegisterContext.h"
27#include "lldb/Target/Thread.h"
28#include "lldb/Target/Process.h"
29#include "lldb/Target/Target.h"
30
31using namespace lldb;
32using namespace lldb_private;
33
Sean Callanan5b0228a2010-11-12 03:22:21 +000034#pragma mark ThreadPlanTracer
35
Jim Ingham745ac7a2010-11-11 19:26:09 +000036ThreadPlanTracer::ThreadPlanTracer (Thread &thread, lldb::StreamSP &stream_sp) :
Stephen Wilsondbeb3e12011-04-11 19:41:40 +000037 m_thread (thread),
Jim Ingham745ac7a2010-11-11 19:26:09 +000038 m_single_step(true),
39 m_enabled (false),
Jim Ingham745ac7a2010-11-11 19:26:09 +000040 m_stream_sp (stream_sp)
41{
42}
43
44ThreadPlanTracer::ThreadPlanTracer (Thread &thread) :
Stephen Wilsondbeb3e12011-04-11 19:41:40 +000045 m_thread (thread),
Jim Ingham745ac7a2010-11-11 19:26:09 +000046 m_single_step(true),
47 m_enabled (false),
Jim Ingham745ac7a2010-11-11 19:26:09 +000048 m_stream_sp ()
49{
50}
51
52Stream *
53ThreadPlanTracer::GetLogStream ()
54{
55
56 if (m_stream_sp.get())
57 return m_stream_sp.get();
58 else
Greg Claytonf4124de2012-02-21 00:09:25 +000059 {
60 TargetSP target_sp (m_thread.CalculateTarget());
61 if (target_sp)
62 return &target_sp->GetDebugger().GetOutputStream();
63 }
64 return NULL;
Jim Ingham745ac7a2010-11-11 19:26:09 +000065}
66
67void
68ThreadPlanTracer::Log()
69{
70 SymbolContext sc;
71 bool show_frame_index = false;
72 bool show_fullpaths = false;
73
Caroline Tice2b5e4e62011-06-15 19:35:17 +000074 Stream *stream = GetLogStream();
Jim Ingham6f01c932012-10-12 17:34:26 +000075 if (stream)
76 {
77 m_thread.GetStackFrameAtIndex(0)->Dump (stream, show_frame_index, show_fullpaths);
78 stream->Printf("\n");
79 stream->Flush();
80 }
Caroline Tice2b5e4e62011-06-15 19:35:17 +000081
Jim Ingham745ac7a2010-11-11 19:26:09 +000082}
83
84bool
85ThreadPlanTracer::TracerExplainsStop ()
86{
87 if (m_enabled && m_single_step)
88 {
89 lldb::StopInfoSP stop_info = m_thread.GetStopInfo();
90 if (stop_info->GetStopReason() == eStopReasonTrace)
91 return true;
92 else
93 return false;
94 }
95 else
96 return false;
97}
Sean Callanan5b0228a2010-11-12 03:22:21 +000098
99#pragma mark ThreadPlanAssemblyTracer
100
101ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp) :
102 ThreadPlanTracer (thread, stream_sp),
Sean Callanan4f28c312012-08-01 18:50:59 +0000103 m_disassembler_sp (),
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000104 m_intptr_type (),
105 m_register_values ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000106{
Jim Inghamae7862a2010-11-17 20:19:50 +0000107}
108
109ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread) :
110 ThreadPlanTracer (thread),
Sean Callanan4f28c312012-08-01 18:50:59 +0000111 m_disassembler_sp (),
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000112 m_intptr_type (),
113 m_register_values ()
Jim Inghamae7862a2010-11-17 20:19:50 +0000114{
Jim Inghamae7862a2010-11-17 20:19:50 +0000115}
116
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000117Disassembler *
118ThreadPlanAssemblyTracer::GetDisassembler ()
Jim Inghamae7862a2010-11-17 20:19:50 +0000119{
Sean Callanan4f28c312012-08-01 18:50:59 +0000120 if (m_disassembler_sp.get() == NULL)
121 m_disassembler_sp = Disassembler::FindPlugin(m_thread.GetProcess()->GetTarget().GetArchitecture(), NULL);
122 return m_disassembler_sp.get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000123}
124
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000125TypeFromUser
126ThreadPlanAssemblyTracer::GetIntPointerType()
127{
128 if (!m_intptr_type.IsValid ())
129 {
Greg Claytonf4124de2012-02-21 00:09:25 +0000130 TargetSP target_sp (m_thread.CalculateTarget());
131 if (target_sp)
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000132 {
Greg Claytonf4124de2012-02-21 00:09:25 +0000133 Module *exe_module = target_sp->GetExecutableModulePointer();
134
135 if (exe_module)
136 {
137 m_intptr_type = TypeFromUser(exe_module->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, target_sp->GetArchitecture().GetAddressByteSize() * 8),
138 exe_module->GetClangASTContext().getASTContext());
139 }
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000140 }
141 }
142 return m_intptr_type;
143}
144
145
146
Sean Callanan5b0228a2010-11-12 03:22:21 +0000147ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer()
148{
149}
150
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000151void
152ThreadPlanAssemblyTracer::TracingStarted ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000153{
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000154 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000155
156 if (m_register_values.size() == 0)
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000157 m_register_values.resize (reg_ctx->GetRegisterCount());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000158}
159
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000160void
161ThreadPlanAssemblyTracer::TracingEnded ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000162{
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000163 m_register_values.clear();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000164}
165
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000166static void
167PadOutTo (StreamString &stream, int target)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000168{
169 stream.Flush();
170
171 int length = stream.GetString().length();
172
173 if (length + 1 < target)
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000174 stream.Printf("%*s", target - (length + 1) + 1, "");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000175}
176
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000177void
178ThreadPlanAssemblyTracer::Log ()
Sean Callanan5b0228a2010-11-12 03:22:21 +0000179{
180 Stream *stream = GetLogStream ();
181
182 if (!stream)
183 return;
184
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000185 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000186
187 lldb::addr_t pc = reg_ctx->GetPC();
Greg Claytonf4124de2012-02-21 00:09:25 +0000188 ProcessSP process_sp (m_thread.GetProcess());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000189 Address pc_addr;
190 bool addr_valid = false;
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000191 uint8_t buffer[16] = {0}; // Must be big enough for any single instruction
Greg Claytonf4124de2012-02-21 00:09:25 +0000192 addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000193
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000194 pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
Jim Inghamb5867672011-06-22 21:13:28 +0000195 stream->PutCString (" ");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000196
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000197 Disassembler *disassembler = GetDisassembler();
198 if (disassembler)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000199 {
Sean Callanan5b0228a2010-11-12 03:22:21 +0000200 Error err;
Greg Claytonf4124de2012-02-21 00:09:25 +0000201 process_sp->ReadMemory(pc, buffer, sizeof(buffer), err);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000202
203 if (err.Success())
204 {
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000205 DataExtractor extractor(buffer, sizeof(buffer),
Greg Claytonf4124de2012-02-21 00:09:25 +0000206 process_sp->GetByteOrder(),
207 process_sp->GetAddressByteSize());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000208
209 if (addr_valid)
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000210 disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000211 else
Greg Clayton3508c382012-02-24 01:59:29 +0000212 disassembler->DecodeInstructions (Address (pc), extractor, 0, 1, false);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000213
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000214 InstructionList &instruction_list = disassembler->GetInstructionList();
Greg Clayton889fbd02011-03-26 19:14:58 +0000215 const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
216
Sean Callanan5b0228a2010-11-12 03:22:21 +0000217 if (instruction_list.GetSize())
218 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000219 const bool show_bytes = true;
220 const bool show_address = true;
Sean Callanan5b0228a2010-11-12 03:22:21 +0000221 Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000222 instruction->Dump (stream,
Greg Clayton889fbd02011-03-26 19:14:58 +0000223 max_opcode_byte_size,
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000224 show_address,
225 show_bytes,
Greg Clayton0fef9682012-05-10 02:52:23 +0000226 NULL);
Sean Callanan5b0228a2010-11-12 03:22:21 +0000227 }
228 }
Sean Callanan5b0228a2010-11-12 03:22:21 +0000229 }
230
Greg Claytonf4124de2012-02-21 00:09:25 +0000231 const ABI *abi = process_sp->GetABI().get();
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000232 TypeFromUser intptr_type = GetIntPointerType();
233
234 if (abi && intptr_type.IsValid())
Sean Callanan5b0228a2010-11-12 03:22:21 +0000235 {
236 ValueList value_list;
237 const int num_args = 1;
238
239 for (int arg_index = 0; arg_index < num_args; ++arg_index)
240 {
241 Value value;
242 value.SetValueType (Value::eValueTypeScalar);
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000243 value.SetContext (Value::eContextTypeClangType, intptr_type.GetOpaqueQualType());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000244 value_list.PushValue (value);
245 }
246
Greg Claytonc51ffbf2011-08-12 21:40:01 +0000247 if (abi->GetArgumentValues (m_thread, value_list))
Sean Callanan5b0228a2010-11-12 03:22:21 +0000248 {
249 for (int arg_index = 0; arg_index < num_args; ++arg_index)
250 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000251 stream->Printf("\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
Sean Callanan5b0228a2010-11-12 03:22:21 +0000252
253 if (arg_index + 1 < num_args)
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000254 stream->PutCString (", ");
Sean Callanan5b0228a2010-11-12 03:22:21 +0000255 }
256 }
257 }
258
Sean Callanan5b0228a2010-11-12 03:22:21 +0000259
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000260 RegisterValue reg_value;
261 for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount();
262 reg_num < num_registers;
263 ++reg_num)
Sean Callanan5b0228a2010-11-12 03:22:21 +0000264 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000265 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
266 if (reg_ctx->ReadRegister (reg_info, reg_value))
Sean Callanan5b0228a2010-11-12 03:22:21 +0000267 {
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000268 assert (reg_num < m_register_values.size());
269 if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid ||
270 reg_value != m_register_values[reg_num])
271 {
272 if (reg_value.GetType() != RegisterValue::eTypeInvalid)
273 {
274 stream->PutCString ("\n\t");
275 reg_value.Dump(stream, reg_info, true, false, eFormatDefault);
276 }
277 }
278 m_register_values[reg_num] = reg_value;
Sean Callanan5b0228a2010-11-12 03:22:21 +0000279 }
280 }
Greg Claytonb9e8f6e2011-05-18 01:58:14 +0000281 stream->EOL();
Caroline Tice2b5e4e62011-06-15 19:35:17 +0000282 stream->Flush();
Sean Callanan5b0228a2010-11-12 03:22:21 +0000283}