This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA/mips(commit?)] Unwinding from noreturn function


Hello,

I'm starting to work on bringing mips-irix back to life. One of the issues
I've noticed is that unwinding is generally broken, particularly from
noreturn functions. I normally have commit priviledges for mips, but
in this case I wouldn't mind an extra opinion on the first issue I found.
Since I don't have access to a mips16 machine, I can't test the change
there...

Consider the following example:

        procedure A is
        begin
           raise Constraint_Error;
        end A;

Compile it with the following command:

        % gnatmake -g a

Then try the following:

        % gdb a
        (gdb) start
        (gdb) b __gnat_debug_raise_exception 
        Breakpoint 2 at 0x9947160: file s-except.adb, line 44.
        (gdb) cont
        Continuing.
        
        Breakpoint 2, <__gnat_debug_raise_exception> (e=0x9a33168)
        [...]
        (gdb) bt
        #0  <__gnat_debug_raise_exception> (e=0x9a33168) at s-except.adb:44
        #1  0x097b82e8 in <__gnat_raise_nodefer_with_msg> (e=0x9a33168)
            at a-except.adb:830
        #2  0x097b82e8 in <__gnat_raise_nodefer_with_msg> (e=0x9a33168)
            at a-except.adb:830
        Backtrace stopped: previous frame identical to this frame (corrupt stack?)

I actually found two issues:

  1. One major: mips_pc_is_mips16 that returns non-zero if bit 0
     of the address it is given is set.

        /* If bit 0 of the address is set, assume this is a MIPS16 address. */
        if (is_mips16_addr (memaddr))
          return 1;

     However, this doesn't work very well in our case, especially
     in this situation:

        static const struct frame_unwind *
        mips_insn16_frame_sniffer (struct frame_info *next_frame)
        {
          CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
          if (mips_pc_is_mips16 (pc))
            return &mips_insn16_frame_unwind;
          return NULL;
        }

     In this case, frame_unwind_address_in_block will return the
     frame return address *minus one*, thus accidently triggering
     the check above.

     As a consequence, we ended up using the mips16 unwinder instead
     of the mips32 one.

     It seems to me that the above check is only an optimization,
     and I've spotted at least one instance where I cannot see an
     obvious guaranty that the address has not been decremented
     by one of the _in_block functions... So the decision I made
     was to remove that check.

  2. One minor: There was a confusion in the unwinder between
     the return address and the address of the instruction calling us.
     So I replaced frame_pc_unwind calls by their associated
     frame_unwind_address_in_block.

With the two fixes above, I managed to get the full backtrace:

        (gdb) bt
        #0  <__gnat_debug_raise_exception> (e=0x9a33168) at s-except.adb:44
        #1  0x097b82e8 in <__gnat_raise_nodefer_with_msg> (e=0x9a33168)
            at a-except.adb:830
        #2  0x097b8990 in ada.exceptions.raise_with_location_and_msg (
            e=0x9a33168, f=(system.address) 0xf, l=1717986919, 
            m=(system.address) 0x31) at a-except.adb:995
        #3  0x097b82a0 in <__gnat_raise_constraint_error_msg> (
            file=(system.address) 0x9a33168, line=161761434, 
            msg=(system.address) 0x31) at a-except.adb:795
        #4  0x097b8b58 in <__gnat_rcheck_04> (
            file=(system.address) 0x9a3b240, line=15) at a-except.adb:1043
        #5  0x100027f0 in a () at a.adb:3

2007-03-07  Joel Brobecker  <brobecker@adacore.com>

        * mips-tdep.c (mips_pc_is_mips16): Remove check for bit zero of
        the given address.
        (mips_insn16_frame_cache): Use the proper function to get the
        address of the caller instruction.
        (mips_insn32_frame_cache): Likewise.

Tested on mips-irix. Fixes many many many tests (about 500 or so).
OK to apply?

Thanks,
-- 
Joel

Attachment: mips16.diff
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]