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