aboutsummaryrefslogtreecommitdiff
path: root/gdb/x86-64-linux-tdep.c
diff options
context:
space:
mode:
authorJiri Smid <smid@suse.cz>2001-09-21 12:19:15 +0000
committerJiri Smid <smid@suse.cz>2001-09-21 12:19:15 +0000
commit53e95fcfec25913398c95486c2c80afdf06f0eb0 (patch)
tree7d5483c2f216808e7da48d9e280e5c3ab29705ab /gdb/x86-64-linux-tdep.c
parent9a82579f3d1ba4b133844af18ec0a7fb0074dad9 (diff)
downloadfsf-binutils-gdb-53e95fcfec25913398c95486c2c80afdf06f0eb0.zip
fsf-binutils-gdb-53e95fcfec25913398c95486c2c80afdf06f0eb0.tar.gz
fsf-binutils-gdb-53e95fcfec25913398c95486c2c80afdf06f0eb0.tar.bz2
* config/i386/x86-64linux.mh: New file.
* config/i386/x86-64linux.mt: New file. * config/i386/nm-x86_64.h: New file. * x86-64-linux-tdep.c: New file. * x86-64-linux-nat.c: New file. * x86-64-tdep.c: New file. * x86-64-tdep.h: New file. * config/djgpp/fnchange.lst: Add entries for x86_64-linux-tdep.c and x86_64-linux-nat.c * Makefile.in: Add x86_64-linux-tdep.o, x86_64-tdep.o, x86_64-linux-tdep.o, x86_64-nat.o, update dependencies.
Diffstat (limited to 'gdb/x86-64-linux-tdep.c')
-rw-r--r--gdb/x86-64-linux-tdep.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/gdb/x86-64-linux-tdep.c b/gdb/x86-64-linux-tdep.c
new file mode 100644
index 0000000..7a1a045
--- /dev/null
+++ b/gdb/x86-64-linux-tdep.c
@@ -0,0 +1,136 @@
+/* Target-dependent code for Linux running on x86-64, for GDB.
+ Copyright 2001
+ Free Software Foundation, Inc.
+ Contributed by Jiri Smid, SuSE Labs.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "regcache.h"
+#include "x86-64-tdep.h"
+#include "dwarf2cfi.h"
+
+#define STRUCT_OFFSET(struct_type, member) \
+ ((long) ((char*) &((struct_type*) 0)->member))
+
+#define LINUX_SIGTRAMP_INSN0 (0x48) /* mov $NNNNNNNN,%rax */
+#define LINUX_SIGTRAMP_OFFSET0 (0)
+#define LINUX_SIGTRAMP_INSN1 (0x0f) /* syscall */
+#define LINUX_SIGTRAMP_OFFSET1 (7)
+
+static const unsigned char linux_sigtramp_code[] = {
+ LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x89, 0x00, 0x00, 0x00, /* mov $0x89,%rax */
+ LINUX_SIGTRAMP_INSN1, 0x05 /* syscall */
+};
+
+#define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
+
+/* If PC is in a sigtramp routine, return the address of the start of
+ the routine. Otherwise, return 0. */
+
+static CORE_ADDR
+x86_64_linux_sigtramp_start (CORE_ADDR pc)
+{
+ unsigned char buf[LINUX_SIGTRAMP_LEN];
+ if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
+ return 0;
+
+ if (buf[0] != LINUX_SIGTRAMP_INSN0)
+ {
+ if (buf[0] != LINUX_SIGTRAMP_INSN1)
+ return 0;
+
+ pc -= LINUX_SIGTRAMP_OFFSET1;
+
+ if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
+ return 0;
+ }
+
+ if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
+ return 0;
+
+ return pc;
+}
+
+/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */
+#define LINUX_UCONTEXT_SIGCONTEXT_OFFSET (36)
+
+/* Assuming FRAME is for a Linux sigtramp routine, return the address
+ of the associated sigcontext structure. */
+CORE_ADDR
+x86_64_linux_sigcontext_addr (struct frame_info *frame)
+{
+ CORE_ADDR pc;
+
+ pc = x86_64_linux_sigtramp_start (frame->pc);
+ if (pc)
+ {
+ if (frame->next)
+ /* If this isn't the top frame, the next frame must be for the
+ signal handler itself. The sigcontext structure is part of
+ the user context. */
+ return frame->next->frame + sizeof (struct siginfo) +
+ LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
+
+
+ /* This is the top frame. */
+ return read_register (SP_REGNUM) + sizeof (struct siginfo) +
+ LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
+
+ }
+
+ error ("Couldn't recognize signal trampoline.");
+ return 0;
+}
+
+/* Offset to saved PC in sigcontext, from <asm/sigcontext.h>. */
+#define LINUX_SIGCONTEXT_PC_OFFSET (136)
+
+/* Assuming FRAME is for a Linux sigtramp routine, return the saved
+ program counter. */
+
+CORE_ADDR
+x86_64_linux_sigtramp_saved_pc (struct frame_info *frame)
+{
+ CORE_ADDR addr;
+
+ addr = x86_64_linux_sigcontext_addr (frame);
+ return read_memory_integer (addr + LINUX_SIGCONTEXT_PC_OFFSET, 8);
+}
+
+/* Immediately after a function call, return the saved pc. */
+
+CORE_ADDR
+x86_64_linux_saved_pc_after_call (struct frame_info *frame)
+{
+ if (frame->signal_handler_caller)
+ return x86_64_linux_sigtramp_saved_pc (frame);
+
+ return read_memory_integer (read_register (SP_REGNUM), 8);
+}
+
+/* Saved Pc. Get it from sigcontext if within sigtramp. */
+CORE_ADDR
+x86_64_linux_frame_saved_pc (struct frame_info *frame)
+{
+ if (frame->signal_handler_caller)
+ return x86_64_linux_sigtramp_saved_pc (frame);
+ return cfi_get_ra (frame);
+}