aboutsummaryrefslogtreecommitdiff
path: root/gdb/i386-tdep.c
diff options
context:
space:
mode:
authorPeter Schauer <Peter.Schauer@mytum.de>1994-02-27 21:24:16 +0000
committerPeter Schauer <Peter.Schauer@mytum.de>1994-02-27 21:24:16 +0000
commit28ee4b428911fb8c5df3b4af30ab39f3963a8f23 (patch)
treec3e1d0a2001cf1ad3a40c45f00ef6bd86be2beda /gdb/i386-tdep.c
parente08b9ad7a1dac15ca593a1c6aa8cac7000c19045 (diff)
downloadfsf-binutils-gdb-28ee4b428911fb8c5df3b4af30ab39f3963a8f23.zip
fsf-binutils-gdb-28ee4b428911fb8c5df3b4af30ab39f3963a8f23.tar.gz
fsf-binutils-gdb-28ee4b428911fb8c5df3b4af30ab39f3963a8f23.tar.bz2
* 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.
Diffstat (limited to 'gdb/i386-tdep.c')
-rw-r--r--gdb/i386-tdep.c144
1 files changed, 109 insertions, 35 deletions
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,
&regbuf[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 */