OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [x86-64-linux-tdep.c] - Rev 1773

Go to most recent revision | Compare with Previous | Blame | View Log

/* Target-dependent code for GNU/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 "gdb_string.h"
#include "regcache.h"
#include "x86-64-tdep.h"
#include "dwarf2cfi.h"
 
#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;
}
 
#define LINUX_SIGINFO_SIZE 128
 
/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>.  */
#define LINUX_UCONTEXT_SIGCONTEXT_OFFSET (36)
 
/* Assuming FRAME is for a GNU/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 + LINUX_SIGINFO_SIZE +
	  LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
 
 
      /* This is the top frame. */
      return read_register (SP_REGNUM) + LINUX_SIGINFO_SIZE +
	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 GNU/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);
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.