ThreadPlanTracer.cpp revision dbeb3e1e038a75f00fd565203839020e1d00a7c6
1//===-- 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
13#include <string.h>
14// C++ Includes
15// Other libraries and framework includes
16// Project includes
17#include "lldb/Core/ArchSpec.h"
18#include "lldb/Core/DataBufferHeap.h"
19#include "lldb/Core/Debugger.h"
20#include "lldb/Core/Disassembler.h"
21#include "lldb/Core/Log.h"
22#include "lldb/Core/State.h"
23#include "lldb/Core/Value.h"
24#include "lldb/Symbol/TypeList.h"
25#include "lldb/Target/RegisterContext.h"
26#include "lldb/Target/Thread.h"
27#include "lldb/Target/Process.h"
28#include "lldb/Target/Target.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
33#pragma mark ThreadPlanTracer
34
35ThreadPlanTracer::ThreadPlanTracer (Thread &thread, lldb::StreamSP &stream_sp) :
36    m_thread (thread),
37    m_single_step(true),
38    m_enabled (false),
39    m_stream_sp (stream_sp)
40{
41}
42
43ThreadPlanTracer::ThreadPlanTracer (Thread &thread) :
44    m_thread (thread),
45    m_single_step(true),
46    m_enabled (false),
47    m_stream_sp ()
48{
49}
50
51Stream *
52ThreadPlanTracer::GetLogStream ()
53{
54
55    if (m_stream_sp.get())
56        return m_stream_sp.get();
57    else
58        return &(m_thread.GetProcess().GetTarget().GetDebugger().GetOutputStream());
59}
60
61void
62ThreadPlanTracer::Log()
63{
64    SymbolContext sc;
65    bool show_frame_index = false;
66    bool show_fullpaths = false;
67
68    m_thread.GetStackFrameAtIndex(0)->Dump (GetLogStream(), show_frame_index, show_fullpaths);
69    GetLogStream()->Printf("\n");
70}
71
72bool
73ThreadPlanTracer::TracerExplainsStop ()
74{
75    if (m_enabled && m_single_step)
76    {
77        lldb::StopInfoSP stop_info = m_thread.GetStopInfo();
78        if (stop_info->GetStopReason() == eStopReasonTrace)
79            return true;
80        else
81            return false;
82    }
83    else
84        return false;
85}
86
87#pragma mark ThreadPlanAssemblyTracer
88
89ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp) :
90    ThreadPlanTracer (thread, stream_sp),
91    m_process(thread.GetProcess()),
92    m_target(thread.GetProcess().GetTarget())
93{
94    InitializeTracer ();
95}
96
97ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread) :
98    ThreadPlanTracer (thread),
99    m_process(thread.GetProcess()),
100    m_target(thread.GetProcess().GetTarget())
101{
102    InitializeTracer ();
103}
104
105void
106ThreadPlanAssemblyTracer::InitializeTracer()
107{
108    Process &process = m_thread.GetProcess();
109    Target &target = process.GetTarget();
110
111    ArchSpec arch(target.GetArchitecture());
112
113    m_disassembler = Disassembler::FindPlugin(arch, NULL);
114
115    m_abi = process.GetABI();
116
117    ModuleSP exe_module_sp (target.GetExecutableModule());
118
119    if (exe_module_sp)
120    {
121        m_intptr_type = TypeFromUser(exe_module_sp->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, arch.GetAddressByteSize() * 8),
122                                     exe_module_sp->GetClangASTContext().getASTContext());
123    }
124
125    const unsigned int buf_size = 32;
126
127    m_buffer_sp.reset(new DataBufferHeap(buf_size, 0));
128}
129
130ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer()
131{
132}
133
134void
135ThreadPlanAssemblyTracer::TracingStarted ()
136{
137    RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
138
139    if (m_register_values.size() == 0)
140    {
141        for (uint32_t reg_index = 0, num_registers = reg_ctx->GetRegisterCount();
142             reg_index < num_registers;
143             ++reg_index)
144            m_register_values.push_back(0);
145    }
146}
147
148void
149ThreadPlanAssemblyTracer::TracingEnded ()
150{
151    for (uint32_t reg_index = 0, num_registers = m_register_values.size();
152         reg_index < num_registers;
153         ++reg_index)
154        m_register_values[reg_index] = 0;
155}
156
157static void
158PadOutTo (StreamString &stream, int target)
159{
160    stream.Flush();
161
162    int length = stream.GetString().length();
163
164    if (length + 1 < target)
165        stream.Printf("%*s", target - (length + 1) + 1, "");
166}
167
168void
169ThreadPlanAssemblyTracer::Log ()
170{
171    Stream *stream = GetLogStream ();
172
173    if (!stream)
174        return;
175
176    RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
177
178    lldb::addr_t pc = reg_ctx->GetPC();
179    Address pc_addr;
180    bool addr_valid = false;
181
182    StreamString desc;
183
184    int desired_width = 0;
185
186    addr_valid = m_process.GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
187
188    pc_addr.Dump(&desc, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
189
190    desired_width += 64;
191    PadOutTo(desc, desired_width);
192
193    if (m_disassembler)
194    {
195        ::memset(m_buffer_sp->GetBytes(), 0, m_buffer_sp->GetByteSize());
196
197        Error err;
198        m_process.ReadMemory(pc, m_buffer_sp->GetBytes(), m_buffer_sp->GetByteSize(), err);
199
200        if (err.Success())
201        {
202            DataExtractor extractor(m_buffer_sp,
203                                    m_process.GetByteOrder(),
204                                    m_process.GetAddressByteSize());
205
206            if (addr_valid)
207                m_disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false);
208            else
209                m_disassembler->DecodeInstructions (Address (NULL, pc), extractor, 0, 1, false);
210
211            InstructionList &instruction_list = m_disassembler->GetInstructionList();
212            const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
213
214            if (instruction_list.GetSize())
215            {
216                Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
217                instruction->Dump (&desc,
218                                   max_opcode_byte_size,
219                                   false,
220                                   false,
221                                   NULL,
222                                   true);
223            }
224        }
225
226        desired_width += 32;
227        PadOutTo(desc, desired_width);
228    }
229
230    if (m_abi && m_intptr_type.GetOpaqueQualType())
231    {
232        ValueList value_list;
233        const int num_args = 1;
234
235        for (int arg_index = 0; arg_index < num_args; ++arg_index)
236        {
237            Value value;
238            value.SetValueType (Value::eValueTypeScalar);
239            value.SetContext (Value::eContextTypeClangType, m_intptr_type.GetOpaqueQualType());
240            value_list.PushValue (value);
241        }
242
243        if (m_abi->GetArgumentValues (m_thread, value_list))
244        {
245            for (int arg_index = 0; arg_index < num_args; ++arg_index)
246            {
247                desc.Printf("arg[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
248
249                if (arg_index + 1 < num_args)
250                    desc.Printf(", ");
251            }
252        }
253    }
254
255    desired_width += 20;
256    PadOutTo(desc, desired_width);
257
258    for (uint32_t reg_index = 0, num_registers = reg_ctx->GetRegisterCount();
259         reg_index < num_registers;
260         ++reg_index)
261    {
262        uint64_t reg_value = reg_ctx->ReadRegisterAsUnsigned(reg_index, 0x0);
263
264        if (reg_value != m_register_values[reg_index])
265        {
266            desc.Printf ("%s:0x%llx->0x%llx ", reg_ctx->GetRegisterName(reg_index), m_register_values[reg_index], reg_value);
267
268            m_register_values[reg_index] = reg_value;
269        }
270    }
271
272    stream->Printf ("Single-step: %s\n", desc.GetString().c_str());
273}
274