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