[Lldb-commits] [lldb] r118879 - in /lldb/trunk: include/lldb/Target/ThreadPlanTracer.h source/Target/ThreadPlanTracer.cpp
Sean Callanan
scallanan at apple.com
Thu Nov 11 19:22:22 PST 2010
Author: spyffe
Date: Thu Nov 11 21:22:21 2010
New Revision: 118879
URL: http://llvm.org/viewvc/llvm-project?rev=118879&view=rev
Log:
Added a thread plan tracer that prints lines of
assembly as well as registers that changed.
Modified:
lldb/trunk/include/lldb/Target/ThreadPlanTracer.h
lldb/trunk/source/Target/ThreadPlanTracer.cpp
Modified: lldb/trunk/include/lldb/Target/ThreadPlanTracer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanTracer.h?rev=118879&r1=118878&r2=118879&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanTracer.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanTracer.h Thu Nov 11 21:22:21 2010
@@ -15,6 +15,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
+#include "lldb/Symbol/TaggedASTType.h"
#include "lldb/Target/Thread.h"
namespace lldb_private {
@@ -98,6 +99,24 @@
bool m_enabled;
lldb::StreamSP m_stream_sp;
};
+
+class ThreadPlanAssemblyTracer : public ThreadPlanTracer
+{
+public:
+ ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp);
+ virtual ~ThreadPlanAssemblyTracer ();
+ virtual void TracingStarted ();
+ virtual void TracingEnded ();
+ virtual void Log();
+private:
+ Process &m_process;
+ Target &m_target;
+ Disassembler *m_disassembler;
+ const ABI *m_abi;
+ TypeFromUser m_intptr_type;
+ std::vector<uint64_t> m_register_values;
+ lldb::DataBufferSP m_buffer_sp;
+};
} // namespace lldb_private
Modified: lldb/trunk/source/Target/ThreadPlanTracer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanTracer.cpp?rev=118879&r1=118878&r2=118879&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanTracer.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanTracer.cpp Thu Nov 11 21:22:21 2010
@@ -10,12 +10,18 @@
#include "lldb/Target/ThreadPlan.h"
// C Includes
+#include <string.h>
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/Process.h"
@@ -24,6 +30,8 @@
using namespace lldb;
using namespace lldb_private;
+#pragma mark ThreadPlanTracer
+
ThreadPlanTracer::ThreadPlanTracer (Thread &thread, lldb::StreamSP &stream_sp) :
m_single_step(true),
m_enabled (false),
@@ -75,3 +83,200 @@
else
return false;
}
+
+#pragma mark ThreadPlanAssemblyTracer
+
+ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp) :
+ ThreadPlanTracer (thread, stream_sp),
+ m_process(thread.GetProcess()),
+ m_target(thread.GetProcess().GetTarget())
+{
+ Process &process = thread.GetProcess();
+ Target &target = process.GetTarget();
+
+ ArchSpec arch(target.GetArchitecture());
+
+ m_disassembler = Disassembler::FindPlugin(arch);
+
+ m_abi = process.GetABI();
+
+ ModuleSP executableModuleSP (target.GetExecutableModule());
+ TypeList *type_list = executableModuleSP->GetTypeList();
+
+ if (type_list)
+ {
+ m_intptr_type = TypeFromUser(type_list->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, arch.GetAddressByteSize() * 8),
+ type_list->GetClangASTContext().getASTContext());
+ }
+
+ const unsigned int buf_size = 32;
+
+ m_buffer_sp.reset(new DataBufferHeap(buf_size, 0));
+}
+
+ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer()
+{
+}
+
+void ThreadPlanAssemblyTracer::TracingStarted ()
+{
+ RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+
+ if (m_register_values.size() == 0)
+ {
+ for (uint32_t reg_index = 0, num_registers = reg_ctx->GetRegisterCount();
+ reg_index < num_registers;
+ ++reg_index)
+ m_register_values.push_back(0);
+ }
+}
+
+void ThreadPlanAssemblyTracer::TracingEnded ()
+{
+ for (uint32_t reg_index = 0, num_registers = m_register_values.size();
+ reg_index < num_registers;
+ ++reg_index)
+ m_register_values[reg_index] = 0;
+}
+
+static const char *Padding(int length)
+{
+ const int padding_size = 256;
+
+ static char* padding = NULL;
+ static int prev_length = 256;
+
+ if (!padding) {
+ padding = new char[padding_size];
+ memset(padding, ' ', padding_size);
+ }
+
+ if (length > 255)
+ length = 255;
+
+ if (prev_length < 256)
+ padding[prev_length] = ' ';
+
+ padding[length] = '\0';
+
+ prev_length = length;
+
+ return padding;
+}
+
+static void PadOutTo(StreamString &stream, int target)
+{
+ stream.Flush();
+
+ int length = stream.GetString().length();
+
+ if (length + 1 < target)
+ stream.PutCString(Padding(target - (length + 1)));
+
+ stream.PutCString(" ");
+}
+
+void ThreadPlanAssemblyTracer::Log ()
+{
+ Stream *stream = GetLogStream ();
+
+ if (!stream)
+ return;
+
+ RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+
+ lldb::addr_t pc = reg_ctx->GetPC();
+ Address pc_addr;
+ bool addr_valid = false;
+
+ StreamString desc;
+
+ int desired_width = 0;
+
+ addr_valid = m_process.GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
+
+ pc_addr.Dump(&desc, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
+
+ desired_width += 64;
+ PadOutTo(desc, desired_width);
+
+ if (m_disassembler)
+ {
+ bzero(m_buffer_sp->GetBytes(), m_buffer_sp->GetByteSize());
+
+ Error err;
+ m_process.ReadMemory(pc, m_buffer_sp->GetBytes(), m_buffer_sp->GetByteSize(), err);
+
+ if (err.Success())
+ {
+ DataExtractor extractor(m_buffer_sp,
+ m_process.GetByteOrder(),
+ m_process.GetAddressByteSize());
+
+ if (addr_valid)
+ m_disassembler->DecodeInstructions (pc_addr, extractor, 0, 1);
+ else
+ m_disassembler->DecodeInstructions (Address (NULL, pc), extractor, 0, 1);
+
+ InstructionList &instruction_list = m_disassembler->GetInstructionList();
+
+ if (instruction_list.GetSize())
+ {
+ Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
+ instruction->Dump (&desc,
+ false,
+ NULL,
+ 0,
+ NULL,
+ true);
+ }
+ }
+
+ desired_width += 32;
+ PadOutTo(desc, desired_width);
+ }
+
+ if (m_abi && m_intptr_type.GetOpaqueQualType())
+ {
+ ValueList value_list;
+ const int num_args = 1;
+
+ for (int arg_index = 0; arg_index < num_args; ++arg_index)
+ {
+ Value value;
+ value.SetValueType (Value::eValueTypeScalar);
+ value.SetContext (Value::eContextTypeOpaqueClangQualType, m_intptr_type.GetOpaqueQualType());
+ value_list.PushValue (value);
+ }
+
+ if (m_abi->GetArgumentValues (m_thread, value_list))
+ {
+ for (int arg_index = 0; arg_index < num_args; ++arg_index)
+ {
+ desc.Printf("arg[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
+
+ if (arg_index + 1 < num_args)
+ desc.Printf(", ");
+ }
+ }
+ }
+
+ desired_width += 20;
+ PadOutTo(desc, desired_width);
+
+ for (uint32_t reg_index = 0, num_registers = reg_ctx->GetRegisterCount();
+ reg_index < num_registers;
+ ++reg_index)
+ {
+ uint64_t reg_value = reg_ctx->ReadRegisterAsUnsigned(reg_index, 0x0);
+
+ if (reg_value != m_register_values[reg_index])
+ {
+ desc.Printf ("%s:0x%llx->0x%llx ", reg_ctx->GetRegisterName(reg_index), m_register_values[reg_index], reg_value);
+
+ m_register_values[reg_index] = reg_value;
+ }
+ }
+
+ stream->Printf ("Single-step: %s", desc.GetString().c_str());
+}
More information about the lldb-commits
mailing list