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 // C Includes
11ac7ddfbfSEd Maste // C++ Includes
129f2f44ceSEd Maste #include <cstring>
139f2f44ceSEd Maste 
14ac7ddfbfSEd Maste // Other libraries and framework includes
15ac7ddfbfSEd Maste // Project includes
169f2f44ceSEd Maste #include "lldb/Target/ThreadPlan.h"
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"
27ac7ddfbfSEd Maste #include "lldb/Symbol/TypeList.h"
289f2f44ceSEd Maste #include "lldb/Symbol/TypeSystem.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 {
609f2f44ceSEd Maste     if (m_stream_sp)
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     }
689f2f44ceSEd Maste     return nullptr;
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 bool
88ac7ddfbfSEd Maste ThreadPlanTracer::TracerExplainsStop ()
89ac7ddfbfSEd Maste {
90ac7ddfbfSEd Maste     if (m_enabled && m_single_step)
91ac7ddfbfSEd Maste     {
92ac7ddfbfSEd Maste         lldb::StopInfoSP stop_info = m_thread.GetStopInfo();
939f2f44ceSEd Maste         return (stop_info->GetStopReason() == eStopReasonTrace);
94ac7ddfbfSEd Maste     }
95ac7ddfbfSEd Maste     else
96ac7ddfbfSEd Maste         return false;
97ac7ddfbfSEd Maste }
98ac7ddfbfSEd Maste 
99ac7ddfbfSEd Maste #pragma mark ThreadPlanAssemblyTracer
100ac7ddfbfSEd Maste 
101ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp) :
102ac7ddfbfSEd Maste     ThreadPlanTracer (thread, stream_sp),
103ac7ddfbfSEd Maste     m_disassembler_sp (),
104ac7ddfbfSEd Maste     m_intptr_type (),
105ac7ddfbfSEd Maste     m_register_values ()
106ac7ddfbfSEd Maste {
107ac7ddfbfSEd Maste }
108ac7ddfbfSEd Maste 
109ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread) :
110ac7ddfbfSEd Maste     ThreadPlanTracer (thread),
111ac7ddfbfSEd Maste     m_disassembler_sp (),
112ac7ddfbfSEd Maste     m_intptr_type (),
113ac7ddfbfSEd Maste     m_register_values ()
114ac7ddfbfSEd Maste {
115ac7ddfbfSEd Maste }
116ac7ddfbfSEd Maste 
117ac7ddfbfSEd Maste Disassembler *
118ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::GetDisassembler ()
119ac7ddfbfSEd Maste {
1209f2f44ceSEd Maste     if (!m_disassembler_sp)
1219f2f44ceSEd Maste         m_disassembler_sp = Disassembler::FindPlugin(m_thread.GetProcess()->GetTarget().GetArchitecture(), nullptr, nullptr);
122ac7ddfbfSEd Maste     return m_disassembler_sp.get();
123ac7ddfbfSEd Maste }
124ac7ddfbfSEd Maste 
125ac7ddfbfSEd Maste TypeFromUser
126ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::GetIntPointerType()
127ac7ddfbfSEd Maste {
128ac7ddfbfSEd Maste     if (!m_intptr_type.IsValid ())
129ac7ddfbfSEd Maste     {
130ac7ddfbfSEd Maste         TargetSP target_sp (m_thread.CalculateTarget());
131ac7ddfbfSEd Maste         if (target_sp)
132ac7ddfbfSEd Maste         {
1339f2f44ceSEd Maste             TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC);
1349f2f44ceSEd Maste             if (type_system)
1359f2f44ceSEd Maste                 m_intptr_type = TypeFromUser(type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, target_sp->GetArchitecture().GetAddressByteSize() * 8));
136ac7ddfbfSEd Maste         }
137ac7ddfbfSEd Maste     }
138ac7ddfbfSEd Maste     return m_intptr_type;
139ac7ddfbfSEd Maste }
140ac7ddfbfSEd Maste 
1419f2f44ceSEd Maste ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer() = default;
142ac7ddfbfSEd Maste 
143ac7ddfbfSEd Maste void
144ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::TracingStarted ()
145ac7ddfbfSEd Maste {
146ac7ddfbfSEd Maste     RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
147ac7ddfbfSEd Maste 
1489f2f44ceSEd Maste     if (m_register_values.empty())
149ac7ddfbfSEd Maste         m_register_values.resize (reg_ctx->GetRegisterCount());
150ac7ddfbfSEd Maste }
151ac7ddfbfSEd Maste 
152ac7ddfbfSEd Maste void
153ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::TracingEnded ()
154ac7ddfbfSEd Maste {
155ac7ddfbfSEd Maste     m_register_values.clear();
156ac7ddfbfSEd Maste }
157ac7ddfbfSEd Maste 
158ac7ddfbfSEd Maste void
159ac7ddfbfSEd Maste ThreadPlanAssemblyTracer::Log ()
160ac7ddfbfSEd Maste {
161ac7ddfbfSEd Maste     Stream *stream = GetLogStream ();
162ac7ddfbfSEd Maste 
163ac7ddfbfSEd Maste     if (!stream)
164ac7ddfbfSEd Maste         return;
165ac7ddfbfSEd Maste 
166ac7ddfbfSEd Maste     RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
167ac7ddfbfSEd Maste 
168ac7ddfbfSEd Maste     lldb::addr_t pc = reg_ctx->GetPC();
169ac7ddfbfSEd Maste     ProcessSP process_sp (m_thread.GetProcess());
170ac7ddfbfSEd Maste     Address pc_addr;
171ac7ddfbfSEd Maste     bool addr_valid = false;
172ac7ddfbfSEd Maste     uint8_t buffer[16] = {0}; // Must be big enough for any single instruction
173ac7ddfbfSEd Maste     addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
174ac7ddfbfSEd Maste 
175ac7ddfbfSEd Maste     pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
176ac7ddfbfSEd Maste     stream->PutCString (" ");
177ac7ddfbfSEd Maste 
178ac7ddfbfSEd Maste     Disassembler *disassembler = GetDisassembler();
179ac7ddfbfSEd Maste     if (disassembler)
180ac7ddfbfSEd Maste     {
181ac7ddfbfSEd Maste         Error err;
182ac7ddfbfSEd Maste         process_sp->ReadMemory(pc, buffer, sizeof(buffer), err);
183ac7ddfbfSEd Maste 
184ac7ddfbfSEd Maste         if (err.Success())
185ac7ddfbfSEd Maste         {
186ac7ddfbfSEd Maste             DataExtractor extractor(buffer, sizeof(buffer),
187ac7ddfbfSEd Maste                                     process_sp->GetByteOrder(),
188ac7ddfbfSEd Maste                                     process_sp->GetAddressByteSize());
189ac7ddfbfSEd Maste 
190ac7ddfbfSEd Maste 			bool data_from_file = false;
191ac7ddfbfSEd Maste             if (addr_valid)
192ac7ddfbfSEd Maste                 disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false, data_from_file);
193ac7ddfbfSEd Maste             else
194ac7ddfbfSEd Maste                 disassembler->DecodeInstructions (Address (pc), extractor, 0, 1, false, data_from_file);
195ac7ddfbfSEd Maste 
196ac7ddfbfSEd Maste             InstructionList &instruction_list = disassembler->GetInstructionList();
197ac7ddfbfSEd Maste             const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
198ac7ddfbfSEd Maste 
199ac7ddfbfSEd Maste             if (instruction_list.GetSize())
200ac7ddfbfSEd Maste             {
201ac7ddfbfSEd Maste                 const bool show_bytes = true;
202ac7ddfbfSEd Maste                 const bool show_address = true;
203ac7ddfbfSEd Maste                 Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
2041c3bbb01SEd Maste                 const FormatEntity::Entry *disassemble_format = m_thread.GetProcess()->GetTarget().GetDebugger().GetDisassemblyFormat();
205ac7ddfbfSEd Maste                 instruction->Dump(stream,
206ac7ddfbfSEd Maste                                   max_opcode_byte_size,
207ac7ddfbfSEd Maste                                   show_address,
208ac7ddfbfSEd Maste                                   show_bytes,
2099f2f44ceSEd Maste                                   nullptr,
2109f2f44ceSEd Maste                                   nullptr,
2119f2f44ceSEd Maste                                   nullptr,
2121c3bbb01SEd Maste                                   disassemble_format,
2131c3bbb01SEd Maste                                   0);
214ac7ddfbfSEd Maste             }
215ac7ddfbfSEd Maste         }
216ac7ddfbfSEd Maste     }
217ac7ddfbfSEd Maste 
218ac7ddfbfSEd Maste     const ABI *abi = process_sp->GetABI().get();
219ac7ddfbfSEd Maste     TypeFromUser intptr_type = GetIntPointerType();
220ac7ddfbfSEd Maste 
221ac7ddfbfSEd Maste     if (abi && intptr_type.IsValid())
222ac7ddfbfSEd Maste     {
223ac7ddfbfSEd Maste         ValueList value_list;
224ac7ddfbfSEd Maste         const int num_args = 1;
225ac7ddfbfSEd Maste 
226ac7ddfbfSEd Maste         for (int arg_index = 0; arg_index < num_args; ++arg_index)
227ac7ddfbfSEd Maste         {
228ac7ddfbfSEd Maste             Value value;
229ac7ddfbfSEd Maste             value.SetValueType (Value::eValueTypeScalar);
230ac7ddfbfSEd Maste //            value.SetContext (Value::eContextTypeClangType, intptr_type.GetOpaqueQualType());
2319f2f44ceSEd Maste             value.SetCompilerType (intptr_type);
232ac7ddfbfSEd Maste             value_list.PushValue (value);
233ac7ddfbfSEd Maste         }
234ac7ddfbfSEd Maste 
235ac7ddfbfSEd Maste         if (abi->GetArgumentValues (m_thread, value_list))
236ac7ddfbfSEd Maste         {
237ac7ddfbfSEd Maste             for (int arg_index = 0; arg_index < num_args; ++arg_index)
238ac7ddfbfSEd Maste             {
239ac7ddfbfSEd Maste                 stream->Printf("\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
240ac7ddfbfSEd Maste 
241ac7ddfbfSEd Maste                 if (arg_index + 1 < num_args)
242ac7ddfbfSEd Maste                     stream->PutCString (", ");
243ac7ddfbfSEd Maste             }
244ac7ddfbfSEd Maste         }
245ac7ddfbfSEd Maste     }
246ac7ddfbfSEd Maste 
247ac7ddfbfSEd Maste     RegisterValue reg_value;
248ac7ddfbfSEd Maste     for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount();
249ac7ddfbfSEd Maste          reg_num < num_registers;
250ac7ddfbfSEd Maste          ++reg_num)
251ac7ddfbfSEd Maste     {
252ac7ddfbfSEd Maste         const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
253ac7ddfbfSEd Maste         if (reg_ctx->ReadRegister (reg_info, reg_value))
254ac7ddfbfSEd Maste         {
255ac7ddfbfSEd Maste             assert (reg_num < m_register_values.size());
256ac7ddfbfSEd Maste             if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid ||
257ac7ddfbfSEd Maste                 reg_value != m_register_values[reg_num])
258ac7ddfbfSEd Maste             {
259ac7ddfbfSEd Maste                 if (reg_value.GetType() != RegisterValue::eTypeInvalid)
260ac7ddfbfSEd Maste                 {
261ac7ddfbfSEd Maste                     stream->PutCString ("\n\t");
262ac7ddfbfSEd Maste                     reg_value.Dump(stream, reg_info, true, false, eFormatDefault);
263ac7ddfbfSEd Maste                 }
264ac7ddfbfSEd Maste             }
265ac7ddfbfSEd Maste             m_register_values[reg_num] = reg_value;
266ac7ddfbfSEd Maste         }
267ac7ddfbfSEd Maste     }
268ac7ddfbfSEd Maste     stream->EOL();
269ac7ddfbfSEd Maste     stream->Flush();
270ac7ddfbfSEd Maste }
271