----- Original Message -----
Hi Dave,
Current I am trying to make crash support display out function param
and local value while backtracing.
The idea for this patch is to mimic core dump support in gdb,
teaching the crash to supply the regset to the gdb, so that gdb
could have full knowledge what is going on in the panic point.
A few progress has been made, the first two frames could display out
correctly, but while it is going on to display out the third frame,
it report fail as “Cannot access memory” to the stack address.
While I use the rd command to access this range, and could correct pc
value there.
With further check, I find it failed at value_fetch_lazy at gdb code.
Do you have any idea why gdb side couldn’t read the stack content?
The generated log as:
crash> bt
PID: 886 TASK: c54991a0 CPU: 0 COMMAND: "sh"
#0 sysrq_handle_crash (key=99) at drivers/tty/sysrq.c:132
No locals.
#1 0xc02da6dc in __handle_sysrq (key=99, check_mask=false) at drivers/tty/sysrq.c:522
op_p = 0xc06dbeb8
orig_log_level = 7
i = -1066549576
flags = 1610612755
Cannot access memory at address 0xd29d5f34
bt: display local fail at c02da1c0
crash> rd 0xd29d5f34 1
d29d5f34: c02da7cc ..-.
crash> sym c02da7cc
c02da7cc (t) write_sysrq_trigger+40 /kernel/drivers/tty/sysrq.c: 873
Thanks,
Lei
Hello Lei,
When the embedded gdb needs to read kernel memory, its code path typically
ends up calling target_read_memory() in gdb-7.3.1/gdb/target.c, which has
been patched to redirect the read back up into the crash source code:
int
target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
{
#ifdef CRASH_MERGE
extern int gdb_readmem_callback(unsigned long, void *, int, int);
if (gdb_readmem_callback(memaddr, (void *)myaddr, len, 0))
return 0;
else
return EIO;
#endif
/* Dispatch to the topmost target, not the flattened current_target.
Memory accesses check target->to_has_(all_)memory, and the
flattened target doesn't inherit those. */
if (target_read (current_target.beneath, TARGET_OBJECT_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
return EIO;
}
The gdb_readmem_callback() function is in the crash source file gdb_interface.c.
But since the read is failing, I'm guessing that it's trying to access the
memory from a different path, probably like this:
value_fetch_lazy()
read_value_memory()
and read_value_memory() looks like this:
void
read_value_memory (struct value *val, int embedded_offset,
int stack, CORE_ADDR memaddr,
gdb_byte *buffer, size_t length)
{
if (length)
{
VEC(mem_range_s) *available_memory;
if (get_traceframe_number () < 0
|| !traceframe_available_memory (&available_memory, memaddr, length))
{
if (stack)
read_stack (memaddr, buffer, length); <== this path has never been
used
else
read_memory (memaddr, buffer, length);
}
If read_memory() were called, then it would call the patched target_read_memory()
function above, and the read would work OK. But if read_stack() is called, it takes
a different path:
read_stack()
target_read_stack()
and target_read_stack() does not call target_read_memory(), but rather it
calls the similar function target_read_stack().
And it appears that target_read_stack() can be modified in the same way
that target_read_memory() has been, since they are essentially the same:
int
target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
{
/* Dispatch to the topmost target, not the flattened current_target.
Memory accesses check target->to_has_(all_)memory, and the
flattened target doesn't inherit those. */
if (target_read (current_target.beneath, TARGET_OBJECT_STACK_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
return EIO;
}
So just try cut-and-pasting the same #ifdef CRASH_MERGE section into target_read_stack().
Dave