ThreadPlanTracer.cpp revision 344779
11638Srgrimes//===-- ThreadPlanTracer.cpp ------------------------------------*- C++ -*-===//
21638Srgrimes//
31638Srgrimes//                     The LLVM Compiler Infrastructure
41638Srgrimes//
51638Srgrimes// This file is distributed under the University of Illinois Open Source
61638Srgrimes// License. See LICENSE.TXT for details.
71638Srgrimes//
81638Srgrimes//===----------------------------------------------------------------------===//
91638Srgrimes
101638Srgrimes#include <cstring>
111638Srgrimes
121638Srgrimes#include "lldb/Core/Debugger.h"
131638Srgrimes#include "lldb/Core/Disassembler.h"
141638Srgrimes#include "lldb/Core/DumpRegisterValue.h"
151638Srgrimes#include "lldb/Core/Module.h"
161638Srgrimes#include "lldb/Core/StreamFile.h"
171638Srgrimes#include "lldb/Core/Value.h"
181638Srgrimes#include "lldb/Symbol/TypeList.h"
191638Srgrimes#include "lldb/Symbol/TypeSystem.h"
201638Srgrimes#include "lldb/Target/ABI.h"
211638Srgrimes#include "lldb/Target/Process.h"
221638Srgrimes#include "lldb/Target/RegisterContext.h"
231638Srgrimes#include "lldb/Target/SectionLoadList.h"
241638Srgrimes#include "lldb/Target/Target.h"
251638Srgrimes#include "lldb/Target/Thread.h"
261638Srgrimes#include "lldb/Target/ThreadPlan.h"
271638Srgrimes#include "lldb/Utility/DataBufferHeap.h"
281638Srgrimes#include "lldb/Utility/DataExtractor.h"
291638Srgrimes#include "lldb/Utility/Log.h"
301638Srgrimes#include "lldb/Utility/State.h"
311638Srgrimes
321638Srgrimesusing namespace lldb;
3350476Speterusing namespace lldb_private;
341638Srgrimes
351638Srgrimes#pragma mark ThreadPlanTracer
361638Srgrimes
371638SrgrimesThreadPlanTracer::ThreadPlanTracer(Thread &thread, lldb::StreamSP &stream_sp)
381638Srgrimes    : m_thread(thread), m_single_step(true), m_enabled(false),
391638Srgrimes      m_stream_sp(stream_sp) {}
401638Srgrimes
411638SrgrimesThreadPlanTracer::ThreadPlanTracer(Thread &thread)
421638Srgrimes    : m_thread(thread), m_single_step(true), m_enabled(false), m_stream_sp() {}
431638Srgrimes
441638SrgrimesStream *ThreadPlanTracer::GetLogStream() {
451638Srgrimes  if (m_stream_sp)
461638Srgrimes    return m_stream_sp.get();
471638Srgrimes  else {
481638Srgrimes    TargetSP target_sp(m_thread.CalculateTarget());
491638Srgrimes    if (target_sp)
501638Srgrimes      return target_sp->GetDebugger().GetOutputFile().get();
511638Srgrimes  }
521638Srgrimes  return nullptr;
531638Srgrimes}
541638Srgrimes
551638Srgrimesvoid ThreadPlanTracer::Log() {
561638Srgrimes  SymbolContext sc;
571638Srgrimes  bool show_frame_index = false;
581638Srgrimes  bool show_fullpaths = false;
591638Srgrimes
601638Srgrimes  Stream *stream = GetLogStream();
611638Srgrimes  if (stream) {
621638Srgrimes    m_thread.GetStackFrameAtIndex(0)->Dump(stream, show_frame_index,
631638Srgrimes                                           show_fullpaths);
641638Srgrimes    stream->Printf("\n");
651638Srgrimes    stream->Flush();
661638Srgrimes  }
671638Srgrimes}
681638Srgrimes
691638Srgrimesbool ThreadPlanTracer::TracerExplainsStop() {
701638Srgrimes  if (m_enabled && m_single_step) {
711638Srgrimes    lldb::StopInfoSP stop_info = m_thread.GetStopInfo();
721638Srgrimes    return (stop_info->GetStopReason() == eStopReasonTrace);
731638Srgrimes  } else
741638Srgrimes    return false;
751638Srgrimes}
761638Srgrimes
771638Srgrimes#pragma mark ThreadPlanAssemblyTracer
781638Srgrimes
791638SrgrimesThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer(Thread &thread,
801638Srgrimes                                                   lldb::StreamSP &stream_sp)
811638Srgrimes    : ThreadPlanTracer(thread, stream_sp), m_disassembler_sp(), m_intptr_type(),
821638Srgrimes      m_register_values() {}
831638Srgrimes
841638SrgrimesThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer(Thread &thread)
851638Srgrimes    : ThreadPlanTracer(thread), m_disassembler_sp(), m_intptr_type(),
861638Srgrimes      m_register_values() {}
871638Srgrimes
881638SrgrimesDisassembler *ThreadPlanAssemblyTracer::GetDisassembler() {
891638Srgrimes  if (!m_disassembler_sp)
901638Srgrimes    m_disassembler_sp = Disassembler::FindPlugin(
911638Srgrimes        m_thread.GetProcess()->GetTarget().GetArchitecture(), nullptr, nullptr);
921638Srgrimes  return m_disassembler_sp.get();
931638Srgrimes}
941638Srgrimes
951638SrgrimesTypeFromUser ThreadPlanAssemblyTracer::GetIntPointerType() {
961638Srgrimes  if (!m_intptr_type.IsValid()) {
971638Srgrimes    TargetSP target_sp(m_thread.CalculateTarget());
981638Srgrimes    if (target_sp) {
991638Srgrimes      TypeSystem *type_system =
1001638Srgrimes          target_sp->GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC);
1011638Srgrimes      if (type_system)
1021638Srgrimes        m_intptr_type =
1031638Srgrimes            TypeFromUser(type_system->GetBuiltinTypeForEncodingAndBitSize(
1041638Srgrimes                eEncodingUint,
1051638Srgrimes                target_sp->GetArchitecture().GetAddressByteSize() * 8));
1061638Srgrimes    }
1071638Srgrimes  }
1081638Srgrimes  return m_intptr_type;
1091638Srgrimes}
1101638Srgrimes
1111638SrgrimesThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer() = default;
1121638Srgrimes
1131638Srgrimesvoid ThreadPlanAssemblyTracer::TracingStarted() {
1141638Srgrimes  RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
1151638Srgrimes
1161638Srgrimes  if (m_register_values.empty())
1171638Srgrimes    m_register_values.resize(reg_ctx->GetRegisterCount());
1181638Srgrimes}
1191638Srgrimes
1201638Srgrimesvoid ThreadPlanAssemblyTracer::TracingEnded() { m_register_values.clear(); }
1211638Srgrimes
1221638Srgrimesvoid ThreadPlanAssemblyTracer::Log() {
1231638Srgrimes  Stream *stream = GetLogStream();
1241638Srgrimes
1251638Srgrimes  if (!stream)
1261638Srgrimes    return;
1271638Srgrimes
1281638Srgrimes  RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
1291638Srgrimes
1301638Srgrimes  lldb::addr_t pc = reg_ctx->GetPC();
1311638Srgrimes  ProcessSP process_sp(m_thread.GetProcess());
1321638Srgrimes  Address pc_addr;
1331638Srgrimes  bool addr_valid = false;
1341638Srgrimes  uint8_t buffer[16] = {0}; // Must be big enough for any single instruction
1351638Srgrimes  addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress(
1361638Srgrimes      pc, pc_addr);
1371638Srgrimes
1381638Srgrimes  pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription,
1391638Srgrimes               Address::DumpStyleModuleWithFileAddress);
1401638Srgrimes  stream->PutCString(" ");
1411638Srgrimes
1421638Srgrimes  Disassembler *disassembler = GetDisassembler();
1431638Srgrimes  if (disassembler) {
1441638Srgrimes    Status err;
1451638Srgrimes    process_sp->ReadMemory(pc, buffer, sizeof(buffer), err);
1461638Srgrimes
1471638Srgrimes    if (err.Success()) {
1481638Srgrimes      DataExtractor extractor(buffer, sizeof(buffer),
1491638Srgrimes                              process_sp->GetByteOrder(),
1501638Srgrimes                              process_sp->GetAddressByteSize());
1511638Srgrimes
15222188Sache      bool data_from_file = false;
1531638Srgrimes      if (addr_valid)
1541638Srgrimes        disassembler->DecodeInstructions(pc_addr, extractor, 0, 1, false,
1551638Srgrimes                                         data_from_file);
1561638Srgrimes      else
1571638Srgrimes        disassembler->DecodeInstructions(Address(pc), extractor, 0, 1, false,
1581638Srgrimes                                         data_from_file);
1591638Srgrimes
1601638Srgrimes      InstructionList &instruction_list = disassembler->GetInstructionList();
1611638Srgrimes      const uint32_t max_opcode_byte_size =
1621638Srgrimes          instruction_list.GetMaxOpcocdeByteSize();
1631638Srgrimes
1641638Srgrimes      if (instruction_list.GetSize()) {
1651638Srgrimes        const bool show_bytes = true;
1661638Srgrimes        const bool show_address = true;
16722188Sache        Instruction *instruction =
1681638Srgrimes            instruction_list.GetInstructionAtIndex(0).get();
1691638Srgrimes        const FormatEntity::Entry *disassemble_format =
1701638Srgrimes            m_thread.GetProcess()
1711638Srgrimes                ->GetTarget()
1721638Srgrimes                .GetDebugger()
1731638Srgrimes                .GetDisassemblyFormat();
1741638Srgrimes        instruction->Dump(stream, max_opcode_byte_size, show_address,
1751638Srgrimes                          show_bytes, nullptr, nullptr, nullptr,
1761638Srgrimes                          disassemble_format, 0);
1771638Srgrimes      }
1781638Srgrimes    }
1791638Srgrimes  }
1801638Srgrimes
1811638Srgrimes  const ABI *abi = process_sp->GetABI().get();
18222188Sache  TypeFromUser intptr_type = GetIntPointerType();
1831638Srgrimes
1841638Srgrimes  if (abi && intptr_type.IsValid()) {
1851638Srgrimes    ValueList value_list;
1861638Srgrimes    const int num_args = 1;
1871638Srgrimes
1881638Srgrimes    for (int arg_index = 0; arg_index < num_args; ++arg_index) {
1891638Srgrimes      Value value;
1901638Srgrimes      value.SetValueType(Value::eValueTypeScalar);
1911638Srgrimes      //            value.SetContext (Value::eContextTypeClangType,
1921638Srgrimes      //            intptr_type.GetOpaqueQualType());
1931638Srgrimes      value.SetCompilerType(intptr_type);
1941638Srgrimes      value_list.PushValue(value);
1951638Srgrimes    }
1961638Srgrimes
1971638Srgrimes    if (abi->GetArgumentValues(m_thread, value_list)) {
1981638Srgrimes      for (int arg_index = 0; arg_index < num_args; ++arg_index) {
1991638Srgrimes        stream->Printf(
2001638Srgrimes            "\n\targ[%d]=%llx", arg_index,
2011638Srgrimes            value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
20222188Sache
2031638Srgrimes        if (arg_index + 1 < num_args)
2041638Srgrimes          stream->PutCString(", ");
2051638Srgrimes      }
2061638Srgrimes    }
2071638Srgrimes  }
2081638Srgrimes
2091638Srgrimes  RegisterValue reg_value;
2101638Srgrimes  for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount();
2111638Srgrimes       reg_num < num_registers; ++reg_num) {
2121638Srgrimes    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
2131638Srgrimes    if (reg_ctx->ReadRegister(reg_info, reg_value)) {
2141638Srgrimes      assert(reg_num < m_register_values.size());
2151638Srgrimes      if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid ||
2161638Srgrimes          reg_value != m_register_values[reg_num]) {
21722188Sache        if (reg_value.GetType() != RegisterValue::eTypeInvalid) {
2181638Srgrimes          stream->PutCString("\n\t");
2191638Srgrimes          DumpRegisterValue(reg_value, stream, reg_info, true, false,
2201638Srgrimes                            eFormatDefault);
2211638Srgrimes        }
2221638Srgrimes      }
2231638Srgrimes      m_register_values[reg_num] = reg_value;
2241638Srgrimes    }
2251638Srgrimes  }
2261638Srgrimes  stream->EOL();
2271638Srgrimes  stream->Flush();
2281638Srgrimes}
2291638Srgrimes