-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[lldb-dap] Show load addresses in disassembly #136755
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-lldb Author: Ely Ronnen (eronnen) ChangesImproves the lldb-dap disassembly by showing load addresses in disassembly, same as in a regular LLDB Before: After: Full diff: https://github.com/llvm/llvm-project/pull/136755.diff 4 Files Affected:
diff --git a/lldb/include/lldb/API/SBFrame.h b/lldb/include/lldb/API/SBFrame.h
index 3635ee5a537ad..66db059d531a8 100644
--- a/lldb/include/lldb/API/SBFrame.h
+++ b/lldb/include/lldb/API/SBFrame.h
@@ -221,6 +221,7 @@ class LLDB_API SBFrame {
friend class SBBlock;
friend class SBExecutionContext;
friend class SBInstruction;
+ friend class SBInstructionList;
friend class SBThread;
friend class SBValue;
diff --git a/lldb/include/lldb/API/SBInstructionList.h b/lldb/include/lldb/API/SBInstructionList.h
index 4c26ec9a294e0..b337c91721653 100644
--- a/lldb/include/lldb/API/SBInstructionList.h
+++ b/lldb/include/lldb/API/SBInstructionList.h
@@ -54,6 +54,10 @@ class LLDB_API SBInstructionList {
bool GetDescription(lldb::SBStream &description);
+ // Writes assembly instructions to `description` with load addresses using
+ // `frame`.
+ bool GetDescription(lldb::SBStream &description, lldb::SBFrame &frame);
+
bool DumpEmulationForAllInstructions(const char *triple);
protected:
@@ -62,8 +66,7 @@ class LLDB_API SBInstructionList {
friend class SBTarget;
void SetDisassembler(const lldb::DisassemblerSP &opaque_sp);
- bool GetDescription(lldb_private::Stream &description);
-
+ bool GetDescription(lldb_private::Stream &description, lldb::SBFrame *frame);
private:
lldb::DisassemblerSP m_opaque_sp;
diff --git a/lldb/source/API/SBInstructionList.cpp b/lldb/source/API/SBInstructionList.cpp
index c18204375dff1..79432e8c6c91a 100644
--- a/lldb/source/API/SBInstructionList.cpp
+++ b/lldb/source/API/SBInstructionList.cpp
@@ -15,8 +15,10 @@
#include "lldb/Core/Module.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/Instrumentation.h"
#include "lldb/Utility/Stream.h"
+#include <memory>
using namespace lldb;
using namespace lldb_private;
@@ -114,7 +116,7 @@ void SBInstructionList::Print(FILE *out) {
if (out == nullptr)
return;
StreamFile stream(out, false);
- GetDescription(stream);
+ GetDescription(stream, nullptr);
}
void SBInstructionList::Print(SBFile out) {
@@ -122,7 +124,7 @@ void SBInstructionList::Print(SBFile out) {
if (!out.IsValid())
return;
StreamFile stream(out.m_opaque_sp);
- GetDescription(stream);
+ GetDescription(stream, nullptr);
}
void SBInstructionList::Print(FileSP out_sp) {
@@ -130,15 +132,21 @@ void SBInstructionList::Print(FileSP out_sp) {
if (!out_sp || !out_sp->IsValid())
return;
StreamFile stream(out_sp);
- GetDescription(stream);
+ GetDescription(stream, nullptr);
}
bool SBInstructionList::GetDescription(lldb::SBStream &stream) {
LLDB_INSTRUMENT_VA(this, stream);
- return GetDescription(stream.ref());
+ return GetDescription(stream.ref(), nullptr);
}
-bool SBInstructionList::GetDescription(Stream &sref) {
+bool SBInstructionList::GetDescription(lldb::SBStream &stream,
+ lldb::SBFrame &frame) {
+ LLDB_INSTRUMENT_VA(this, stream);
+ return GetDescription(stream.ref(), &frame);
+}
+
+bool SBInstructionList::GetDescription(Stream &sref, lldb::SBFrame *frame) {
if (m_opaque_sp) {
size_t num_instructions = GetSize();
@@ -148,10 +156,15 @@ bool SBInstructionList::GetDescription(Stream &sref) {
const uint32_t max_opcode_byte_size =
m_opaque_sp->GetInstructionList().GetMaxOpcocdeByteSize();
FormatEntity::Entry format;
- FormatEntity::Parse("${addr}: ", format);
+ FormatEntity::Parse("${addr-file-or-load}: ", format);
SymbolContext sc;
SymbolContext prev_sc;
+ std::shared_ptr<ExecutionContext> exec_ctx;
+ if (nullptr != frame) {
+ exec_ctx = std::make_shared<ExecutionContext>(frame->GetFrameSP());
+ }
+
// Expected address of the next instruction. Used to print an empty line
// for non-contiguous blocks of insns.
std::optional<Address> next_addr;
@@ -172,8 +185,8 @@ bool SBInstructionList::GetDescription(Stream &sref) {
if (next_addr && *next_addr != addr)
sref.EOL();
inst->Dump(&sref, max_opcode_byte_size, true, false,
- /*show_control_flow_kind=*/false, nullptr, &sc, &prev_sc,
- &format, 0);
+ /*show_control_flow_kind=*/false, exec_ctx.get(), &sc,
+ &prev_sc, &format, 0);
sref.EOL();
next_addr = addr;
next_addr->Slide(inst->GetOpcode().GetByteSize());
diff --git a/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp
index 1a7a13d9f267a..bd4fc981475f4 100644
--- a/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp
@@ -43,7 +43,7 @@ SourceRequestHandler::Run(const protocol::SourceArguments &args) const {
lldb::SBInstructionList insts = frame.GetSymbol().GetInstructions(dap.target);
lldb::SBStream stream;
- insts.GetDescription(stream);
+ insts.GetDescription(stream, frame);
return protocol::SourceResponseBody{/*content=*/stream.GetData(),
/*mimeType=*/"text/x-lldb.disassembly"};
|
@@ -54,6 +54,10 @@ class LLDB_API SBInstructionList { | |||
|
|||
bool GetDescription(lldb::SBStream &description); | |||
|
|||
// Writes assembly instructions to `description` with load addresses using | |||
// `frame`. | |||
bool GetDescription(lldb::SBStream &description, lldb::SBFrame &frame); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd want this API to be as generic as possible. Since you only need the execution context, that means this should take an SBExecutionContext, which you can create from a frame or thread or process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
@@ -62,8 +66,7 @@ class LLDB_API SBInstructionList { | |||
friend class SBTarget; | |||
|
|||
void SetDisassembler(const lldb::DisassemblerSP &opaque_sp); | |||
bool GetDescription(lldb_private::Stream &description); | |||
|
|||
bool GetDescription(lldb_private::Stream &description, lldb::SBFrame *frame); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's give this a default argument so you don't need to pass nullptr
everywhere.
bool GetDescription(lldb_private::Stream &description, lldb::SBFrame *frame); | |
bool GetDescription(lldb_private::Stream &description, lldb::SBExecutionContext *exe_ctx = nullptr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
@JDevlieghere Thanks for the review! updated the API to receive |
} | ||
|
||
bool SBInstructionList::GetDescription(Stream &sref, | ||
lldb::SBExecutionContext *exe_ctx) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could take the private type (e.g. ExecutionContext*
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
bool GetDescription(lldb_private::Stream &description); | ||
|
||
bool GetDescription(lldb_private::Stream &description, | ||
lldb::SBExecutionContext *exe_ctx = nullptr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this can now take the private type (i.e. ExecutionContext*
). All the SB API objects are PIMPL objects so it feels a bit weird to take their address.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
std::shared_ptr<ExecutionContext> exe_ctx_ptr; | ||
if (nullptr != exe_ctx) { | ||
exe_ctx_ptr = std::make_shared<ExecutionContext>(exe_ctx->get()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few nits:
- No braces around single-line ifs.
- Do we actually need to wrap this in a shared pointer? The underlying object will already live long enough, right? Anyway the current code doesn't look safe unless the underlying object inherits from
enable_shared_from_this
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
@JDevlieghere Nice catch, now that the internal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
@JDevlieghere I don't have write access, fee free to merge this PR if possible (I don't know how the procedures of LLVM work in order to merge) |
Improves the lldb-dap disassembly by showing load addresses in disassembly, same as in a regular LLDB `disassemble` command by default. Before:  After: 
Improves the lldb-dap disassembly by showing load addresses in disassembly, same as in a regular LLDB `disassemble` command by default. Before:  After: 
Improves the lldb-dap disassembly by showing load addresses in disassembly, same as in a regular LLDB `disassemble` command by default. Before:  After: 
Improves the lldb-dap disassembly by showing load addresses in disassembly, same as in a regular LLDB `disassemble` command by default. Before:  After: 
Improves the lldb-dap disassembly by showing load addresses in disassembly, same as in a regular LLDB
disassemble
command by default.Before:
After: