[PATCH] Delegate to target_ops->beneath to read cache lines

Yao Qi
2013-11-27T12:22:25Z

GDB on x86_64-linux is unable to disassemble on core-file target.

$ ./gdb ./testsuite/gdb.base/corefile
(gdb) core-file ./testsuite/gdb.base/corefile.core
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000400976 <+0>: Cannot access memory at address 0x400976

However, it works if we turn code-cache off.

(gdb) set code-cache off
(gdb) disassemble main,+4
Dump of assembler code from 0x400976 to 0x40097a:
0x0000000000400976 <main+0>: push %rbp
0x0000000000400977 <main+1>: mov %rsp,%rbp
End of assembler dump.

When code-cache is off, GDB will iterate target_ops from top and call
to_xfer_partial. When current_target is "core", it will call
to_xfer_partial of target "exec", which reads the contents for
disassemble. However, dcache doesn't have such mechanism, and that is
the cause for the error.

This patch adds something similar in dcache_read_line to go through
target_ops from top to bottom, and call to_xfer_partial.
The original code uses TARGET_OBJECT_RAW_MEMORY, which is replaced
by TARGET_OBJECT_MEMORY in target_xfer_partial,

enum target_object raw_object = object;

/* If this is a raw memory transfer, request the normal
memory object from other layers. */
if (raw_object == TARGET_OBJECT_RAW_MEMORY)
raw_object = TARGET_OBJECT_MEMORY;

so we can use TARGET_OBJECT_MEMORY here. Regression tested on
x86_64-linux.

gdb:

2013-11-27 Yao Qi <yao@codesourcery.com>

* dcache.c (dcache_read_line): Don't call target_read. Use
beneath->to_xfer_partial in a loop.
---
gdb/dcache.c | 23 +++++++++++++++++++----
1 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/gdb/dcache.c b/gdb/dcache.c
index ea2b732..f52fc17 100644
--- a/gdb/dcache.c
+++ b/gdb/dcache.c
@@ -313,6 +313,7 @@ dcache_read_line (DCACHE *dcache, struct dcache_block *db)
int res;
int reg_len;
struct mem_region *region;
+ struct target_ops *ops = current_target.beneath;

len = dcache->line_size;
memaddr = db->addr;
@@ -336,10 +337,24 @@ dcache_read_line (DCACHE *dcache, struct dcache_block *db)
len -= reg_len;
continue;
}
-
- res = target_read (&current_target, TARGET_OBJECT_RAW_MEMORY,
- NULL, myaddr, memaddr, reg_len);
- if (res < reg_len)
+
+ do
+ {
+ res = ops->to_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
+ myaddr, NULL, memaddr, reg_len);
+ if (res > 0)
+ break;
+
+ /* We want to continue past core files to executables, but not
+ past a running target's memory. */
+ if (ops->to_has_all_memory (ops))
+ break;
+
+ ops = ops->beneath;
+ }
+ while (ops != NULL);
+
+ if (res <= 0)
return 0;

memaddr += res;
--
1.7.7.6