aboutsummaryrefslogtreecommitdiff
path: root/gdb/python
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2024-04-24 10:03:08 -0600
committerTom Tromey <tromey@adacore.com>2024-05-10 12:09:32 -0600
commita2f972b330b1575f49ea7a02103085378e7937c7 (patch)
treee250a35a426847182b6256ff947ba35e3a39b2ac /gdb/python
parent400d4e3290b2012f9c44dff21cf6af9bb557e8de (diff)
downloadgdb-a2f972b330b1575f49ea7a02103085378e7937c7.zip
gdb-a2f972b330b1575f49ea7a02103085378e7937c7.tar.gz
gdb-a2f972b330b1575f49ea7a02103085378e7937c7.tar.bz2
Add symbol, line, and location to DAP disassemble result
The DAP spec allows a number of attributes on the resulting instructions that gdb currently does not emit. A user requested some of these, so this patch adds the 'symbol', 'line', and 'location' attributes. While the spec lets the implementation omit 'location' in some cases, it was simpler in the code to just always emit it, as then no extra tracking was needed.
Diffstat (limited to 'gdb/python')
-rw-r--r--gdb/python/lib/gdb/dap/disassemble.py59
1 files changed, 52 insertions, 7 deletions
diff --git a/gdb/python/lib/gdb/dap/disassemble.py b/gdb/python/lib/gdb/dap/disassemble.py
index 65bf3d4..d65790a 100644
--- a/gdb/python/lib/gdb/dap/disassemble.py
+++ b/gdb/python/lib/gdb/dap/disassemble.py
@@ -16,6 +16,50 @@
import gdb
from .server import capability, request
+from .sources import make_source
+
+
+# This tracks labels associated with a disassembly request and helps
+# with updating individual instructions.
+class _BlockTracker:
+ def __init__(self):
+ # Map from PC to symbol names. A given PC is assumed to have
+ # just one label -- DAP wouldn't let us return multiple labels
+ # anyway.
+ self.labels = {}
+ # List of blocks that have already been handled. Note that
+ # blocks aren't hashable so a set is not used.
+ self.blocks = []
+
+ # Add a gdb.Block and its superblocks, ignoring the static and
+ # global block. BLOCK can also be None, which is ignored.
+ def add_block(self, block):
+ while block is not None:
+ if block.is_static or block.is_global or block in self.blocks:
+ return
+ self.blocks.append(block)
+ if block.function is not None:
+ self.labels[block.start] = block.function.name
+ for sym in block:
+ if sym.addr_class == gdb.SYMBOL_LOC_LABEL:
+ self.labels[int(sym.value())] = sym.name
+ block = block.superblock
+
+ # Add PC to this tracker. Update RESULT as appropriate with
+ # information about the source and any label.
+ def add_pc(self, pc, result):
+ self.add_block(gdb.block_for_pc(pc))
+ if pc in self.labels:
+ result["symbol"] = self.labels[pc]
+ sal = gdb.find_pc_line(pc)
+ if sal.symtab is not None:
+ if sal.line != 0:
+ result["line"] = sal.line
+ if sal.symtab.filename is not None:
+ # The spec says this can be omitted in some
+ # situations, but it's a little simpler to just always
+ # supply it.
+ result["location"] = make_source(sal.symtab.filename)
@request("disassemble")
@@ -35,17 +79,18 @@ def disassemble(
except gdb.error:
# Maybe there was no frame.
arch = inf.architecture()
+ tracker = _BlockTracker()
result = []
total_count = instructionOffset + instructionCount
for elt in arch.disassemble(pc, count=total_count)[instructionOffset:]:
mem = inf.read_memory(elt["addr"], elt["length"])
- result.append(
- {
- "address": hex(elt["addr"]),
- "instruction": elt["asm"],
- "instructionBytes": mem.hex(),
- }
- )
+ insn = {
+ "address": hex(elt["addr"]),
+ "instruction": elt["asm"],
+ "instructionBytes": mem.hex(),
+ }
+ tracker.add_pc(elt["addr"], insn)
+ result.append(insn)
return {
"instructions": result,
}