[Crash-utility] [RFC] display function param and local value for backtrace

Dave Anderson anderson at redhat.com
Tue Oct 16 13:27:56 UTC 2012



----- 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




More information about the Crash-utility mailing list