1ac7ddfbfSEd Maste //===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlan.h"
11ac7ddfbfSEd Maste 
12ac7ddfbfSEd Maste // C Includes
13ac7ddfbfSEd Maste #include <string.h>
14ac7ddfbfSEd Maste // C++ Includes
15ac7ddfbfSEd Maste // Other libraries and framework includes
16ac7ddfbfSEd Maste // Project includes
17ac7ddfbfSEd Maste #include "lldb/Core/ArchSpec.h"
18ac7ddfbfSEd Maste #include "lldb/Core/DataBufferHeap.h"
191c3bbb01SEd Maste #include "lldb/Core/DataExtractor.h"
20ac7ddfbfSEd Maste #include "lldb/Core/Debugger.h"
21ac7ddfbfSEd Maste #include "lldb/Core/Disassembler.h"
22ac7ddfbfSEd Maste #include "lldb/Core/Log.h"
23ac7ddfbfSEd Maste #include "lldb/Core/Module.h"
24ac7ddfbfSEd Maste #include "lldb/Core/State.h"
2512b93ac6SEd Maste #include "lldb/Core/StreamFile.h"
26ac7ddfbfSEd Maste #include "lldb/Core/Value.h"
271c3bbb01SEd Maste #include "lldb/Symbol/ClangASTContext.h"
28ac7ddfbfSEd Maste #include "lldb/Symbol/TypeList.h"
291c3bbb01SEd Maste #include "lldb/Target/ABI.h"
30ac7ddfbfSEd Maste #include "lldb/Target/RegisterContext.h"
31ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
32ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
3312b93ac6SEd Maste #include "lldb/Target/SectionLoadList.h"
34ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
35ac7ddfbfSEd Maste 
36ac7ddfbfSEd Maste using namespace lldb;
37ac7ddfbfSEd Maste using namespace lldb_private;
38ac7ddfbfSEd Maste 
39ac7ddfbfSEd Maste #pragma mark ThreadPlanTracer
40ac7ddfbfSEd Maste 
41ac7ddfbfSEd Maste ThreadPlanTracer::ThreadPlanTracer (Thread &thread, lldb::StreamSP &stream_sp) :
42ac7ddfbfSEd Maste     m_thread (thread),
43ac7ddfbfSEd Maste     m_single_step(true),
44ac7ddfbfSEd Maste     m_enabled (false),
45ac7ddfbfSEd Maste     m_stream_sp (stream_sp)
46ac7ddfbfSEd Maste {
47ac7ddfbfSEd Maste }
48ac7ddfbfSEd Maste 
49ac7ddfbfSEd Maste ThreadPlanTracer::ThreadPlanTracer (Thread &thread) :
50ac7ddfbfSEd Maste     m_thread (thread),
51ac7ddfbfSEd Maste     m_single_step(true),
52ac7ddfbfSEd Maste     m_enabled (false),
53ac7ddfbfSEd Maste     m_stream_sp ()
54ac7ddfbfSEd Maste {
55ac7ddfbfSEd Maste }
56ac7ddfbfSEd Maste 
57ac7ddfbfSEd Maste Stream *
58ac7ddfbfSEd Maste ThreadPlanTracer::GetLogStream ()
59ac7ddfbfSEd Maste {
60ac7ddfbfSEd Maste 
61ac7ddfbfSEd Maste     if (m_stream_sp.get())
62ac7ddfbfSEd Maste         return m_stream_sp.get();
63ac7ddfbfSEd Maste     else
64ac7ddfbfSEd Maste     {
65ac7ddfbfSEd Maste         TargetSP target_sp (m_thread.CalculateTarget());
66ac7ddfbfSEd Maste         if (target_sp)
6712b93ac6SEd Maste             return target_sp->GetDebugger().GetOutputFile().get();
68ac7ddfbfSEd Maste     }
69ac7ddfbfSEd Maste     return NULL;
70ac7ddfbfSEd Maste }
71ac7ddfbfSEd Maste 
72ac7ddfbfSEd Maste void
73ac7ddfbfSEd Maste ThreadPlanTracer::Log()
74ac7ddfbfSEd Maste {
75ac7ddfbfSEd Maste     SymbolContext sc;
76ac7ddfbfSEd Maste     bool show_frame_index = false;
77ac7ddfbfSEd Maste     bool show_fullpaths = false;
78ac7ddfbfSEd Maste 
79ac7ddfbfSEd Maste     Stream *stream = GetLogStream();
80ac7ddfbfSEd Maste     if (stream)
81ac7ddfbfSEd Maste     {
82ac7ddfbfSEd Maste         m_thread.GetStackFrameAtIndex(0)->Dump (stream, show_frame_index, show_fullpaths);
83ac7ddfbfSEd Maste         stream->Printf("\n");
84ac7ddfbfSEd Maste         stream->Flush();
85ac7ddfbfSEd Maste     }
86ac7ddfbfSEd Maste 
87ac7ddfbfSEd Maste }
88ac7ddfbfSEd Maste 
89ac7ddfbfSEd Maste bool
90ac7ddfbfSEd Maste ThreadPlanTracer::TracerExplainsStop ()
91ac7ddfbfSEd Maste {
92ac7ddfbfSEd Maste     if (m_enabled && m_single_step)
93ac7ddfbfSEd Maste     {
94ac7ddfbfSEd Maste         lldb::StopInfoSP stop_info = m_thread.GetStopInfo();
95ac7ddfbfSEd Maste         if (stop_info->GetStopReason() == eStopReasonTrace)
96ac7ddfbfSEd Maste             return true;
97ac7ddfbfSEd Maste         else
98ac7ddfbfSEd Maste             return false;
99ac7ddfbfSEd Maste     }
100ac7ddfbfSEd Maste     else
101ac7ddfbfSEd Maste         return false;
102ac7ddfbfSEd Maste }
103ac7ddfbfSEd Maste 
104ac7ddfbfSEd Maste #pragma mark ThreadPlanAssemblyTracer
105ac7ddfbfSEd Maste 
106ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp) :
107ac7ddfbfSEd Maste     ThreadPlanTracer (thread, stream_sp),
108ac7ddfbfSEd Maste     m_disassembler_sp (),
109ac7ddfbfSEd Maste     m_intptr_type (),
110ac7ddfbfSEd Maste     m_register_values ()
111ac7ddfbfSEd Maste {
112ac7ddfbfSEd Maste }
113ac7ddfbfSEd Maste 
114ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread) :
115ac7ddfbfSEd Maste     ThreadPlanTracer (thread),
116ac7ddfbfSEd Maste     m_disassembler_sp (),
117ac7ddfbfSEd Maste     m_intptr_type (),
118ac7ddfbfSEd Maste     m_register_values ()
119ac7ddfbfSEd Maste {
120ac7ddfbfSEd Maste }
121ac7ddfbfSEd Maste 
122ac7ddfbfSEd Maste Disassembler *
123ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::GetDisassembler ()
124ac7ddfbfSEd Maste {
125ac7ddfbfSEd Maste     if (m_disassembler_sp.get() == NULL)
126ac7ddfbfSEd Maste         m_disassembler_sp = Disassembler::FindPlugin(m_thread.GetProcess()->GetTarget().GetArchitecture(), NULL, NULL);
127ac7ddfbfSEd Maste     return m_disassembler_sp.get();
128ac7ddfbfSEd Maste }
129ac7ddfbfSEd Maste 
130ac7ddfbfSEd Maste TypeFromUser
131ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::GetIntPointerType()
132ac7ddfbfSEd Maste {
133ac7ddfbfSEd Maste     if (!m_intptr_type.IsValid ())
134ac7ddfbfSEd Maste     {
135ac7ddfbfSEd Maste         TargetSP target_sp (m_thread.CalculateTarget());
136ac7ddfbfSEd Maste         if (target_sp)
137ac7ddfbfSEd Maste         {
138ac7ddfbfSEd Maste             Module *exe_module = target_sp->GetExecutableModulePointer();
139ac7ddfbfSEd Maste 
140ac7ddfbfSEd Maste             if (exe_module)
141ac7ddfbfSEd Maste             {
142ac7ddfbfSEd Maste                 m_intptr_type = TypeFromUser(exe_module->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, target_sp->GetArchitecture().GetAddressByteSize() * 8));
143ac7ddfbfSEd Maste             }
144ac7ddfbfSEd Maste         }
145ac7ddfbfSEd Maste     }
146ac7ddfbfSEd Maste     return m_intptr_type;
147ac7ddfbfSEd Maste }
148ac7ddfbfSEd Maste 
149ac7ddfbfSEd Maste 
150ac7ddfbfSEd Maste 
151ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer()
152ac7ddfbfSEd Maste {
153ac7ddfbfSEd Maste }
154ac7ddfbfSEd Maste 
155ac7ddfbfSEd Maste void
156ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::TracingStarted ()
157ac7ddfbfSEd Maste {
158ac7ddfbfSEd Maste     RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
159ac7ddfbfSEd Maste 
160ac7ddfbfSEd Maste     if (m_register_values.size() == 0)
161ac7ddfbfSEd Maste         m_register_values.resize (reg_ctx->GetRegisterCount());
162ac7ddfbfSEd Maste }
163ac7ddfbfSEd Maste 
164ac7ddfbfSEd Maste void
165ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::TracingEnded ()
166ac7ddfbfSEd Maste {
167ac7ddfbfSEd Maste     m_register_values.clear();
168ac7ddfbfSEd Maste }
169ac7ddfbfSEd Maste 
170ac7ddfbfSEd Maste void
171ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::Log ()
172ac7ddfbfSEd Maste {
173ac7ddfbfSEd Maste     Stream *stream = GetLogStream ();
174ac7ddfbfSEd Maste 
175ac7ddfbfSEd Maste     if (!stream)
176ac7ddfbfSEd Maste         return;
177ac7ddfbfSEd Maste 
178ac7ddfbfSEd Maste     RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
179ac7ddfbfSEd Maste 
180ac7ddfbfSEd Maste     lldb::addr_t pc = reg_ctx->GetPC();
181ac7ddfbfSEd Maste     ProcessSP process_sp (m_thread.GetProcess());
182ac7ddfbfSEd Maste     Address pc_addr;
183ac7ddfbfSEd Maste     bool addr_valid = false;
184ac7ddfbfSEd Maste     uint8_t buffer[16] = {0}; // Must be big enough for any single instruction
185ac7ddfbfSEd Maste     addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
186ac7ddfbfSEd Maste 
187ac7ddfbfSEd Maste     pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
188ac7ddfbfSEd Maste     stream->PutCString (" ");
189ac7ddfbfSEd Maste 
190ac7ddfbfSEd Maste     Disassembler *disassembler = GetDisassembler();
191ac7ddfbfSEd Maste     if (disassembler)
192ac7ddfbfSEd Maste     {
193ac7ddfbfSEd Maste         Error err;
194ac7ddfbfSEd Maste         process_sp->ReadMemory(pc, buffer, sizeof(buffer), err);
195ac7ddfbfSEd Maste 
196ac7ddfbfSEd Maste         if (err.Success())
197ac7ddfbfSEd Maste         {
198ac7ddfbfSEd Maste             DataExtractor extractor(buffer, sizeof(buffer),
199ac7ddfbfSEd Maste                                     process_sp->GetByteOrder(),
200ac7ddfbfSEd Maste                                     process_sp->GetAddressByteSize());
201ac7ddfbfSEd Maste 
202ac7ddfbfSEd Maste 			bool data_from_file = false;
203ac7ddfbfSEd Maste             if (addr_valid)
204ac7ddfbfSEd Maste                 disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false, data_from_file);
205ac7ddfbfSEd Maste             else
206ac7ddfbfSEd Maste                 disassembler->DecodeInstructions (Address (pc), extractor, 0, 1, false, data_from_file);
207ac7ddfbfSEd Maste 
208ac7ddfbfSEd Maste             InstructionList &instruction_list = disassembler->GetInstructionList();
209ac7ddfbfSEd Maste             const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
210ac7ddfbfSEd Maste 
211ac7ddfbfSEd Maste             if (instruction_list.GetSize())
212ac7ddfbfSEd Maste             {
213ac7ddfbfSEd Maste                 const bool show_bytes = true;
214ac7ddfbfSEd Maste                 const bool show_address = true;
215ac7ddfbfSEd Maste                 Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
2161c3bbb01SEd Maste                 const FormatEntity::Entry *disassemble_format = m_thread.GetProcess()->GetTarget().GetDebugger().GetDisassemblyFormat();
217ac7ddfbfSEd Maste                 instruction->Dump (stream,
218ac7ddfbfSEd Maste                                    max_opcode_byte_size,
219ac7ddfbfSEd Maste                                    show_address,
220ac7ddfbfSEd Maste                                    show_bytes,
2217aa51b79SEd Maste                                    NULL,
2227aa51b79SEd Maste                                    NULL,
2237aa51b79SEd Maste                                    NULL,
2241c3bbb01SEd Maste                                    disassemble_format,
2251c3bbb01SEd Maste                                    0);
226ac7ddfbfSEd Maste             }
227ac7ddfbfSEd Maste         }
228ac7ddfbfSEd Maste     }
229ac7ddfbfSEd Maste 
230ac7ddfbfSEd Maste     const ABI *abi = process_sp->GetABI().get();
231ac7ddfbfSEd Maste     TypeFromUser intptr_type = GetIntPointerType();
232ac7ddfbfSEd Maste 
233ac7ddfbfSEd Maste     if (abi && intptr_type.IsValid())
234ac7ddfbfSEd Maste     {
235ac7ddfbfSEd Maste         ValueList value_list;
236ac7ddfbfSEd Maste         const int num_args = 1;
237ac7ddfbfSEd Maste 
238ac7ddfbfSEd Maste         for (int arg_index = 0; arg_index < num_args; ++arg_index)
239ac7ddfbfSEd Maste         {
240ac7ddfbfSEd Maste             Value value;
241ac7ddfbfSEd Maste             value.SetValueType (Value::eValueTypeScalar);
242ac7ddfbfSEd Maste //            value.SetContext (Value::eContextTypeClangType, intptr_type.GetOpaqueQualType());
243ac7ddfbfSEd Maste             value.SetClangType (intptr_type);
244ac7ddfbfSEd Maste             value_list.PushValue (value);
245ac7ddfbfSEd Maste         }
246ac7ddfbfSEd Maste 
247ac7ddfbfSEd Maste         if (abi->GetArgumentValues (m_thread, value_list))
248ac7ddfbfSEd Maste         {
249ac7ddfbfSEd Maste             for (int arg_index = 0; arg_index < num_args; ++arg_index)
250ac7ddfbfSEd Maste             {
251ac7ddfbfSEd Maste                 stream->Printf("\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
252ac7ddfbfSEd Maste 
253ac7ddfbfSEd Maste                 if (arg_index + 1 < num_args)
254ac7ddfbfSEd Maste                     stream->PutCString (", ");
255ac7ddfbfSEd Maste             }
256ac7ddfbfSEd Maste         }
257ac7ddfbfSEd Maste     }
258ac7ddfbfSEd Maste 
259ac7ddfbfSEd Maste 
260ac7ddfbfSEd Maste     RegisterValue reg_value;
261ac7ddfbfSEd Maste     for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount();
262ac7ddfbfSEd Maste          reg_num < num_registers;
263ac7ddfbfSEd Maste          ++reg_num)
264ac7ddfbfSEd Maste     {
265ac7ddfbfSEd Maste         const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
266ac7ddfbfSEd Maste         if (reg_ctx->ReadRegister (reg_info, reg_value))
267ac7ddfbfSEd Maste         {
268ac7ddfbfSEd Maste             assert (reg_num < m_register_values.size());
269ac7ddfbfSEd Maste             if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid ||
270ac7ddfbfSEd Maste                 reg_value != m_register_values[reg_num])
271ac7ddfbfSEd Maste             {
272ac7ddfbfSEd Maste                 if (reg_value.GetType() != RegisterValue::eTypeInvalid)
273ac7ddfbfSEd Maste                 {
274ac7ddfbfSEd Maste                     stream->PutCString ("\n\t");
275ac7ddfbfSEd Maste                     reg_value.Dump(stream, reg_info, true, false, eFormatDefault);
276ac7ddfbfSEd Maste                 }
277ac7ddfbfSEd Maste             }
278ac7ddfbfSEd Maste             m_register_values[reg_num] = reg_value;
279ac7ddfbfSEd Maste         }
280ac7ddfbfSEd Maste     }
281ac7ddfbfSEd Maste     stream->EOL();
282ac7ddfbfSEd Maste     stream->Flush();
283ac7ddfbfSEd Maste }
284