Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Joel Brobecker <brobecker@adacore.com>
To: gdb-patches@sourceware.org
Subject: Re: [PATCH 7/8] ia64-hpux: unwinding bsp value from system call
Date: Fri, 31 Dec 2010 18:15:00 -0000	[thread overview]
Message-ID: <20101231063258.GK2396@adacore.com> (raw)
In-Reply-To: <201012291042.14627.pedro@codesourcery.com>

[-- Attachment #1: Type: text/plain, Size: 206 bytes --]

Following Pedro's suggestion, here is a new revised version of this
patch that defines a new TARGET_OBJECT_HPUX_UREGS target object to
get to the __reason pseudo-register...

Thanks again, Pedro.

-- 
Joel

[-- Attachment #2: uregs.diff --]
[-- Type: text/x-diff, Size: 9335 bytes --]

commit e246563d5cc60890c2ceba3d5b85d30e3f1ce5b2
Author: Joel Brobecker <brobecker@adacore.com>
Date:   Tue Dec 21 07:04:13 2010 -0500

    [ia64-hpux] unwinding bsp value from system call
    
    This fixes unwinding from a thread that is stopped inside a system call.
    This can be seen when switching to a thread that is stopped doing a
    pthread_cond_wait, for instance...
    
    The comments inside the code should explain what is happening in our
    case (the HP-UX exception in the case of system calls): Under certain
    circumstances (program stopped inside syscall), the offset to apply to
    the current BSP in order to compute the previous BSP is not the usual
    CFM & 0x7f.
    
    We parts in this patch:
    
      1. Figuring out that we are stopped inside a syscal: This requires
         a TT_LWP_RUREGS ttrace call, which is not directly possible from
         ia64-tdep.c.  So use defined a new TARGET_OBJECT_HPUX_UREGS object
         to request it from the -nat side.
    
      2. Add a gdbarch_tdep method that allows us to change the default
         behavior on ia64-hpux, permitting us to have a different "size of
         register frame" in that one particular case.
    
    gdb/ChangeLog:
    
            * target.h (enum target_object): Add TARGET_OBJECT_HPUX_UREGS.
            * ia64-tdep.h (struct frame_info): forward declaration.
            (struct gdbarch_tdep): Add field size_of_register_frame.
            * ia64-tdep.c (ia64_access_reg): Use tdep->size_of_register_frame
            to determine the size of the register frame.
            (ia64_size_of_register_frame): New function.
            (ia64_gdbarch_init): Set tdep->size_of_register_frame.
            * ia64-hpux-tdep.c: Include "target.h" and "frame.h".
            (IA64_HPUX_UREG_REASON): New macro.
            (ia64_hpux_stopped_in_syscall, ia64_hpux_size_of_register_frame):
            New functions.
            (ia64_hpux_init_abi): Set tdep->size_of_register_frame.
            * ia64-hpux-nat.c (ia64_hpux_xfer_uregs): New function.
            (ia64_hpux_xfer_partial): Add handling of TARGET_OBJECT_HPUX_UREGS
            objects.

diff --git a/gdb/ia64-hpux-nat.c b/gdb/ia64-hpux-nat.c
index 53941a7..80f7d99 100644
--- a/gdb/ia64-hpux-nat.c
+++ b/gdb/ia64-hpux-nat.c
@@ -567,6 +567,28 @@ ia64_hpux_xfer_memory (struct target_ops *ops, const char *annex,
   return len;
 }
 
+/* Handle the transfer of TARGET_OBJECT_HPUX_UREGS objects on ia64-hpux.
+   ANNEX is currently ignored.
+
+   The current implementation does not support write transfers (because
+   we do not currently do not need these transfers), and will raise
+   a failed assertion if WRITEBUF is not NULL.  */
+
+static LONGEST
+ia64_hpux_xfer_uregs (struct target_ops *ops, const char *annex,
+		      gdb_byte *readbuf, const gdb_byte *writebuf,
+		      ULONGEST offset, LONGEST len)
+{
+  int status;
+
+  gdb_assert (writebuf == NULL);
+
+  status = ia64_hpux_read_register_from_save_state_t (offset, readbuf, len);
+  if (status < 0)
+    return -1;
+  return len;
+}
+
 /* The "to_xfer_partial" target_ops routine for ia64-hpux.  */
 
 static LONGEST
@@ -578,6 +600,8 @@ ia64_hpux_xfer_partial (struct target_ops *ops, enum target_object object,
 
   if (object == TARGET_OBJECT_MEMORY)
     val = ia64_hpux_xfer_memory (ops, annex, readbuf, writebuf, offset, len);
+  else if (object == TARGET_OBJECT_HPUX_UREGS)
+    val = ia64_hpux_xfer_uregs (ops, annex, readbuf, writebuf, offset, len);
   else
     val = super_xfer_partial (ops, object, annex, readbuf, writebuf, offset,
 			      len);
diff --git a/gdb/ia64-hpux-tdep.c b/gdb/ia64-hpux-tdep.c
index 139ff83..a4d2fa7 100644
--- a/gdb/ia64-hpux-tdep.c
+++ b/gdb/ia64-hpux-tdep.c
@@ -23,6 +23,17 @@
 #include "osabi.h"
 #include "gdbtypes.h"
 #include "solib.h"
+#include "target.h"
+#include "frame.h"
+
+/* The offset to be used in order to get the __reason pseudo-register
+   when using one of the *UREGS ttrace requests (see system header file
+   /usr/include/ia64/sys/uregs.h for more details).
+
+   The documentation for this pseudo-register says that a nonzero value
+   indicates that the thread stopped due to a fault, trap, or interrupt.
+   A null value indicates a stop inside a syscall.  */
+#define IA64_HPUX_UREG_REASON 0x00070000
 
 /* Return nonzero if the value of the register identified by REGNUM
    can be modified.  */
@@ -74,6 +85,47 @@ ia64_hpux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
   return 0;
 }
 
+/* Return nonzero if the inferior is stopped inside a system call.  */
+
+static int
+ia64_hpux_stopped_in_syscall (struct gdbarch *gdbarch)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  struct target_ops *ops = &current_target;
+  gdb_byte buf[8];
+  int len;
+
+  len = target_read (ops, TARGET_OBJECT_HPUX_UREGS, NULL,
+		     buf, IA64_HPUX_UREG_REASON, sizeof (buf));
+  if (len == -1)
+    /* The target wasn't able to tell us.  Assume we are not stopped
+       in a system call, which is the normal situation.  */
+    return 0;
+  gdb_assert (len == 8);
+
+  return (extract_unsigned_integer (buf, len, byte_order) == 0);
+}
+
+/* The "size_of_register_frame" gdbarch_tdep routine for ia64-hpux.  */
+
+static int
+ia64_hpux_size_of_register_frame (struct frame_info *this_frame,
+				  ULONGEST cfm)
+{
+  int sof;
+
+  if (frame_relative_level (this_frame) == 0
+      && ia64_hpux_stopped_in_syscall (get_frame_arch (this_frame)))
+    /* If the inferior stopped in a system call, the base address
+       of the register frame is at BSP - SOL instead of BSP - SOF.
+       This is an HP-UX exception.  */
+    sof = (cfm & 0x3f80) >> 7;
+  else
+    sof = (cfm & 0x7f);
+
+  return sof;
+}
+
 /* Should be set to non-NULL if the ia64-hpux solib module is linked in.
    This may not be the case because the shared library support code can
    only be compiled on ia64-hpux.  */
@@ -83,6 +135,10 @@ struct target_so_ops *ia64_hpux_so_ops = NULL;
 static void
 ia64_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  tdep->size_of_register_frame = ia64_hpux_size_of_register_frame;
+
   set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
   set_gdbarch_cannot_store_register (gdbarch, ia64_hpux_cannot_store_register);
 
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index 1cd6a38..1cfffc7 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -2423,7 +2423,7 @@ ia64_is_fpreg (int uw_regnum)
 {
   return unw_is_fpreg (uw_regnum);
 }
-  
+
 /* Libunwind callback accessor function for general registers.  */
 static int
 ia64_access_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_word_t *val, 
@@ -2460,7 +2460,7 @@ ia64_access_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_word_t *val,
 	bsp = extract_unsigned_integer (buf, 8, byte_order);
 	get_frame_register (this_frame, IA64_CFM_REGNUM, buf);
 	cfm = extract_unsigned_integer (buf, 8, byte_order);
-	sof = (cfm & 0x7f);
+	sof = gdbarch_tdep (gdbarch)->size_of_register_frame (this_frame, cfm);
 	*val = ia64_rse_skip_regs (bsp, -sof);
 	break;
 
@@ -3812,6 +3812,14 @@ ia64_print_insn (bfd_vma memaddr, struct disassemble_info *info)
   return print_insn_ia64 (memaddr, info);
 }
 
+/* The default "size_of_register_frame" gdbarch_tdep routine for ia64.  */
+
+static int
+ia64_size_of_register_frame (struct frame_info *this_frame, ULONGEST cfm)
+{
+  return (cfm & 0x7f);
+}
+
 static struct gdbarch *
 ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
@@ -3826,6 +3834,8 @@ ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep = xzalloc (sizeof (struct gdbarch_tdep));
   gdbarch = gdbarch_alloc (&info, tdep);
 
+  tdep->size_of_register_frame = ia64_size_of_register_frame;
+
   /* According to the ia64 specs, instructions that store long double
      floats in memory use a long-double format different than that
      used in the floating registers.  The memory format matches the
diff --git a/gdb/ia64-tdep.h b/gdb/ia64-tdep.h
index b7a8eaf..b88031e 100644
--- a/gdb/ia64-tdep.h
+++ b/gdb/ia64-tdep.h
@@ -195,11 +195,20 @@
 #define IA64_NAT32_REGNUM	(IA64_NAT0_REGNUM + 32)
 #define IA64_NAT127_REGNUM	(IA64_NAT0_REGNUM + 127)
 
+struct frame_info;
+
 struct gdbarch_tdep
 {
   CORE_ADDR (*sigcontext_register_address) (struct gdbarch *, CORE_ADDR, int);
   int (*pc_in_sigtramp) (CORE_ADDR);
 
+  /* Return the total size of THIS_FRAME's register frame.
+     CFM is THIS_FRAME's cfm register value.
+
+     Normally, the size of the register frame is always obtained by
+     extracting the lowest 7 bits ("cfm & 0x7f").  */
+  int (*size_of_register_frame) (struct frame_info *this_frame, ULONGEST cfm);
+
   /* ISA-specific data types.  */
   struct type *ia64_ext_type;
 };
diff --git a/gdb/target.h b/gdb/target.h
index 7290d90..24221ce 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -265,6 +265,9 @@ enum target_object
   TARGET_OBJECT_THREADS,
   /* Collected static trace data.  */
   TARGET_OBJECT_STATIC_TRACE_DATA,
+  /* The HP-UX registers (those that can be obtained or modified by using
+     the TT_LWP_RUREGS/TT_LWP_WUREGS ttrace requests).  */
+  TARGET_OBJECT_HPUX_UREGS,
   /* Possible future objects: TARGET_OBJECT_FILE, ... */
 };
 

  parent reply	other threads:[~2010-12-31  6:33 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-28  4:43 Porting GDB to ia64-hpux Joel Brobecker
2010-12-28  4:43 ` [PATCH 2/8] small integral parameters and return values Joel Brobecker
2010-12-28  4:43 ` [PATCH 4/8] libunwind-frame.c: handle functions with no minimal symbol/debug info Joel Brobecker
2010-12-28  4:43 ` [PATCH 1/8] Add a big-endian version of the ia64-ext floatformat Joel Brobecker
2010-12-28  4:44 ` [PATCH 6/8] port GDB to ia64-hpux (native) Joel Brobecker
2011-01-11 23:26   ` Steve Ellcey
2011-01-12  1:26     ` Joel Brobecker
2011-01-12 16:57       ` Steve Ellcey
2011-01-12 20:11         ` Joel Brobecker
2011-01-13  1:01     ` Joel Brobecker
2011-01-13  5:13       ` Steve Ellcey
     [not found]       ` <1299014508.30497.20.camel@hpsje.cup.hp.com>
     [not found]         ` <20110302044549.GU2513@adacore.com>
     [not found]           ` <1299171098.30497.88.camel@hpsje.cup.hp.com>
     [not found]             ` <20110303172717.GJ2513@adacore.com>
     [not found]               ` <1299173882.30497.114.camel@hpsje.cup.hp.com>
2011-06-17 16:30                 ` Joel Brobecker
2011-01-13 18:07   ` Joel Brobecker
2010-12-28  4:44 ` [PATCH 3/8] Make sure __LITTLE_ENDIAN/__BIG_ENDIAN are defined in libunwind-frame.c Joel Brobecker
2010-12-28  4:44 ` [PATCH 5/8] inf-ttrace: Determine attached process LWP immediately after attaching Joel Brobecker
2010-12-28 11:04   ` Pedro Alves
2010-12-28 11:26     ` Joel Brobecker
2010-12-28  4:54 ` [PATCH 7/8] ia64-hpux: unwinding bsp value from system call Joel Brobecker
2010-12-28 11:35   ` Pedro Alves
2010-12-28 12:01     ` Joel Brobecker
2010-12-28 16:17       ` Pedro Alves
2010-12-29  5:49         ` Joel Brobecker
2010-12-29 12:05           ` Pedro Alves
2010-12-29 13:16             ` Joel Brobecker
2010-12-31 18:15             ` Joel Brobecker [this message]
2010-12-28 15:29     ` [RFA/commit] Add documentation for TARGET_OBJECT_OSDATA Joel Brobecker
2010-12-28 15:46       ` Pedro Alves
2010-12-29  3:29       ` Joel Brobecker
2010-12-28  5:00 ` [PATCH 8/8] [ia64-hpux] inferior function call support Joel Brobecker
2010-12-31 19:18   ` Joel Brobecker
2011-01-13 16:53 ` Porting GDB to ia64-hpux Joel Brobecker

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20101231063258.GK2396@adacore.com \
    --to=brobecker@adacore.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox