llvm-project/lldb/source/API/SBInstructionList.cpp
Walter Erquinigo ad7bcda940 [trace] Add a flag to the decoder to output the instruction type
To build complex binding upon instruction trace, additional metadata 'instruction type' is needed.

This diff has followings:
 - Add a flag -k  / --kind for instruction dump
 - Remove SetGranularity and SetIgnoreErros from Trace cursor

Sample output:

```
(lldb) thread trace dump instruction -k
thread #1: tid = 3198805
  libc.so.6`_IO_puts + 356
    2107: 0x00007ffff7163594 (    return)     retq
    2106: 0x00007ffff7163592 (     other)     popq   %r13
    2105: 0x00007ffff7163590 (     other)     popq   %r12
    2104: 0x00007ffff716358f (     other)     popq   %rbp
    2103: 0x00007ffff716358e (     other)     popq   %rbx
    2102: 0x00007ffff716358c (     other)     movl   %ebx, %eax
    2101: 0x00007ffff7163588 (     other)     addq   $0x8, %rsp
    2100: 0x00007ffff7163570 ( cond jump)     je     0x89588                   ; <+344>
    2099: 0x00007ffff716356e (     other)     decl   (%rdx)
    2098: 0x00007ffff7163565 ( cond jump)     je     0x8956e                   ; <+318>
    2097: 0x00007ffff716355e (     other)     cmpl   $0x0, 0x33c02b(%rip)      ; __libc_multiple_threads
    2096: 0x00007ffff7163556 (     other)     movq   $0x0, 0x8(%rdx)
    2095: 0x00007ffff7163554 ( cond jump)     jne    0x89588                   ; <+344>
    2094: 0x00007ffff7163550 (     other)     subl   $0x1, 0x4(%rdx)
    2093: 0x00007ffff7163549 (     other)     movq   0x88(%rbp), %rdx
    2092: 0x00007ffff7163547 ( cond jump)     jne    0x89588                   ; <+344>
    2091: 0x00007ffff7163540 (     other)     testl  $0x8000, (%rbp)           ; imm = 0x8000
    2090: 0x00007ffff716353c (     other)     cmovaq %rax, %rbx
    2089: 0x00007ffff7163535 (     other)     cmpq   $0x7fffffff, %rbx         ; imm = 0x7FFFFFFF
    2088: 0x00007ffff7163530 (     other)     movl   $0x7fffffff, %eax         ; imm = 0x7FFFFFFF
```

Reviewed By: wallace

Differential Revision: https://reviews.llvm.org/D128477
2022-07-12 16:23:03 -07:00

191 lines
5.3 KiB
C++

//===-- SBInstructionList.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/API/SBInstructionList.h"
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBFile.h"
#include "lldb/API/SBInstruction.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Utility/Instrumentation.h"
#include "lldb/Utility/Stream.h"
using namespace lldb;
using namespace lldb_private;
SBInstructionList::SBInstructionList() { LLDB_INSTRUMENT_VA(this); }
SBInstructionList::SBInstructionList(const SBInstructionList &rhs)
: m_opaque_sp(rhs.m_opaque_sp) {
LLDB_INSTRUMENT_VA(this, rhs);
}
const SBInstructionList &SBInstructionList::
operator=(const SBInstructionList &rhs) {
LLDB_INSTRUMENT_VA(this, rhs);
if (this != &rhs)
m_opaque_sp = rhs.m_opaque_sp;
return *this;
}
SBInstructionList::~SBInstructionList() = default;
bool SBInstructionList::IsValid() const {
LLDB_INSTRUMENT_VA(this);
return this->operator bool();
}
SBInstructionList::operator bool() const {
LLDB_INSTRUMENT_VA(this);
return m_opaque_sp.get() != nullptr;
}
size_t SBInstructionList::GetSize() {
LLDB_INSTRUMENT_VA(this);
if (m_opaque_sp)
return m_opaque_sp->GetInstructionList().GetSize();
return 0;
}
SBInstruction SBInstructionList::GetInstructionAtIndex(uint32_t idx) {
LLDB_INSTRUMENT_VA(this, idx);
SBInstruction inst;
if (m_opaque_sp && idx < m_opaque_sp->GetInstructionList().GetSize())
inst.SetOpaque(
m_opaque_sp,
m_opaque_sp->GetInstructionList().GetInstructionAtIndex(idx));
return inst;
}
size_t SBInstructionList::GetInstructionsCount(const SBAddress &start,
const SBAddress &end,
bool canSetBreakpoint) {
LLDB_INSTRUMENT_VA(this, start, end, canSetBreakpoint);
size_t num_instructions = GetSize();
size_t i = 0;
SBAddress addr;
size_t lower_index = 0;
size_t upper_index = 0;
size_t instructions_to_skip = 0;
for (i = 0; i < num_instructions; ++i) {
addr = GetInstructionAtIndex(i).GetAddress();
if (start == addr)
lower_index = i;
if (end == addr)
upper_index = i;
}
if (canSetBreakpoint)
for (i = lower_index; i <= upper_index; ++i) {
SBInstruction insn = GetInstructionAtIndex(i);
if (!insn.CanSetBreakpoint())
++instructions_to_skip;
}
return upper_index - lower_index - instructions_to_skip;
}
void SBInstructionList::Clear() {
LLDB_INSTRUMENT_VA(this);
m_opaque_sp.reset();
}
void SBInstructionList::AppendInstruction(SBInstruction insn) {
LLDB_INSTRUMENT_VA(this, insn);
}
void SBInstructionList::SetDisassembler(const lldb::DisassemblerSP &opaque_sp) {
m_opaque_sp = opaque_sp;
}
void SBInstructionList::Print(FILE *out) {
LLDB_INSTRUMENT_VA(this, out);
if (out == nullptr)
return;
StreamFile stream(out, false);
GetDescription(stream);
}
void SBInstructionList::Print(SBFile out) {
LLDB_INSTRUMENT_VA(this, out);
if (!out.IsValid())
return;
StreamFile stream(out.m_opaque_sp);
GetDescription(stream);
}
void SBInstructionList::Print(FileSP out_sp) {
LLDB_INSTRUMENT_VA(this, out_sp);
if (!out_sp || !out_sp->IsValid())
return;
StreamFile stream(out_sp);
GetDescription(stream);
}
bool SBInstructionList::GetDescription(lldb::SBStream &stream) {
LLDB_INSTRUMENT_VA(this, stream);
return GetDescription(stream.ref());
}
bool SBInstructionList::GetDescription(Stream &sref) {
if (m_opaque_sp) {
size_t num_instructions = GetSize();
if (num_instructions) {
// Call the ref() to make sure a stream is created if one deesn't exist
// already inside description...
const uint32_t max_opcode_byte_size =
m_opaque_sp->GetInstructionList().GetMaxOpcocdeByteSize();
FormatEntity::Entry format;
FormatEntity::Parse("${addr}: ", format);
SymbolContext sc;
SymbolContext prev_sc;
for (size_t i = 0; i < num_instructions; ++i) {
Instruction *inst =
m_opaque_sp->GetInstructionList().GetInstructionAtIndex(i).get();
if (inst == nullptr)
break;
const Address &addr = inst->GetAddress();
prev_sc = sc;
ModuleSP module_sp(addr.GetModule());
if (module_sp) {
module_sp->ResolveSymbolContextForAddress(
addr, eSymbolContextEverything, sc);
}
inst->Dump(&sref, max_opcode_byte_size, true, false,
/*show_control_flow_kind=*/false, nullptr, &sc, &prev_sc,
&format, 0);
sref.EOL();
}
return true;
}
}
return false;
}
bool SBInstructionList::DumpEmulationForAllInstructions(const char *triple) {
LLDB_INSTRUMENT_VA(this, triple);
if (m_opaque_sp) {
size_t len = GetSize();
for (size_t i = 0; i < len; ++i) {
if (!GetInstructionAtIndex((uint32_t)i).DumpEmulation(triple))
return false;
}
}
return true;
}