diff options
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/i386-tdep.c | 144 |
2 files changed, 118 insertions, 35 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 50503bf..88f9749 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +Sun Feb 27 21:39:48 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * config/i386/tm-i386v4.h (I386V4_SIGTRAMP_SAVED_PC, IN_SIGTRAMP, + FRAME_CHAIN, FRAMELESS_FUNCTION_INVOCATION, FRAME_SAVED_PC): + Define to make backtracing through the various sigtramp handlers + work. + * i386-tdep.c (i386v4_sigtramp_saved_pc): New routine to fetch + the saved pc from ucontext on the stack for SVR4 signal handling. + Fri Feb 25 09:41:11 1994 Jim Kingdon (kingdon@deneb.cygnus.com) * remote.c, remote-mon.c, remote-utils.c, remote-utils.h, diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index d6d20b0..e6ee9ce 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -1,5 +1,5 @@ /* Intel 386 target-dependent stuff. - Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc. + Copyright (C) 1988, 1989, 1991, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "inferior.h" #include "gdbcore.h" #include "target.h" +#include "symtab.h" static long i386_get_frame_setup PARAMS ((int)); @@ -115,42 +116,48 @@ codestream_read (buf, count) static void i386_follow_jump () { - int long_delta; - short short_delta; - char byte_delta; + unsigned char buf[4]; + long delta; + int data16; - int pos; - + CORE_ADDR pos; + pos = codestream_tell (); - + data16 = 0; if (codestream_peek () == 0x66) { codestream_get (); data16 = 1; } - + switch (codestream_get ()) { case 0xe9: /* relative jump: if data16 == 0, disp32, else disp16 */ if (data16) { - codestream_read ((unsigned char *)&short_delta, 2); + codestream_read (buf, 2); + delta = extract_signed_integer (buf, 2); /* include size of jmp inst (including the 0x66 prefix). */ - pos += short_delta + 4; + pos += delta + 4; } else { - codestream_read ((unsigned char *)&long_delta, 4); - pos += long_delta + 5; + codestream_read (buf, 4); + delta = extract_signed_integer (buf, 4); + + pos += delta + 5; } break; case 0xeb: /* relative jump, disp8 (ignore data16) */ - codestream_read ((unsigned char *)&byte_delta, 1); - pos += byte_delta + 2; + codestream_read (buf, 1); + /* Sign-extend it. */ + delta = extract_signed_integer (buf, 1); + + pos += delta + 2; break; } codestream_seek (pos); @@ -169,13 +176,13 @@ i386_get_frame_setup (pc) int pc; { unsigned char op; - + codestream_seek (pc); - + i386_follow_jump (); - + op = codestream_get (); - + if (op == 0x58) /* popl %eax */ { /* @@ -202,11 +209,11 @@ i386_get_frame_setup (pc) pos += 3; else if (memcmp (buf, proto2, 4) == 0) pos += 4; - + codestream_seek (pos); op = codestream_get (); /* update next opcode */ } - + if (op == 0x55) /* pushl %ebp */ { /* check for movl %esp, %ebp - can be written two ways */ @@ -441,6 +448,10 @@ i386_skip_prologue (pc) { unsigned char op; int i; + static unsigned char pic_pat[6] = { 0xe8, 0, 0, 0, 0, /* call 0x0 */ + 0x5b, /* popl %ebx */ + }; + CORE_ADDR pos; if (i386_get_frame_setup (pc) < 0) return (pc); @@ -458,6 +469,54 @@ i386_skip_prologue (pc) break; codestream_get (); } + + /* The native cc on SVR4 in -K PIC mode inserts the following code to get + the address of the global offset table (GOT) into register %ebx. + call 0x0 + popl %ebx + movl %ebx,x(%ebp) (optional) + addl y,%ebx + This code is with the rest of the prologue (at the end of the + function), so we have to skip it to get to the first real + instruction at the start of the function. */ + + pos = codestream_tell (); + for (i = 0; i < 6; i++) + { + op = codestream_get (); + if (pic_pat [i] != op) + break; + } + if (i == 6) + { + unsigned char buf[4]; + long delta = 6; + + op = codestream_get (); + if (op == 0x89) /* movl %ebx, x(%ebp) */ + { + op = codestream_get (); + if (op == 0x5d) /* one byte offset from %ebp */ + { + delta += 3; + codestream_read (buf, 1); + } + else if (op == 0x9d) /* four byte offset from %ebp */ + { + delta += 6; + codestream_read (buf, 4); + } + else /* unexpected instruction */ + delta = -1; + op = codestream_get (); + } + /* addl y,%ebx */ + if (delta > 0 && op == 0x81 && codestream_get () == 0xc3) + { + pos += delta + 6; + } + } + codestream_seek (pos); i386_follow_jump (); @@ -565,21 +624,7 @@ i386_extract_return_value(type, regbuf, valbuf) ieee_extended_to_double (&ext_format_i387, ®buf[REGISTER_BYTE(FP0_REGNUM)], &d); - switch (TYPE_LENGTH(type)) - { - case 4: /* float */ - { - float f = (float) d; - memcpy (valbuf, &f, 4); - break; - } - case 8: /* double */ - memcpy (valbuf, &d, 8); - break; - default: - error("Unknown floating point size"); - break; - } + store_floating (valbuf, TYPE_LENGTH (type), d); } else { @@ -587,3 +632,32 @@ i386_extract_return_value(type, regbuf, valbuf) } } #endif /* I386_AIX_TARGET */ + +#ifdef I386V4_SIGTRAMP_SAVED_PC +/* Get saved user PC for sigtramp from the pushed ucontext on the stack + for all three variants of SVR4 sigtramps. */ + +CORE_ADDR +i386v4_sigtramp_saved_pc (frame) + FRAME frame; +{ + CORE_ADDR saved_pc_offset = 4; + char *name = NULL; + + find_pc_partial_function (frame->pc, &name, + (CORE_ADDR *)NULL,(CORE_ADDR *)NULL); + if (name) + { + if (STREQ (name, "_sigreturn")) + saved_pc_offset = 132 + 14 * 4; + if (STREQ (name, "_sigacthandler")) + saved_pc_offset = 80 + 14 * 4; + if (STREQ (name, "sigvechandler")) + saved_pc_offset = 120 + 14 * 4; + } + + if (frame->next) + return read_memory_integer (frame->next->frame + saved_pc_offset, 4); + return read_memory_integer (read_register (SP_REGNUM) + saved_pc_offset, 4); +} +#endif /* I386V4_SIGTRAMP_SAVED_PC */ |