This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH/tilegx] tilegx bug fixes & improvements


Hi All,

attachments fix several bugs on tilegx exposed by dejagnu and improve tilegx gdb's info register output.

after these patches, the dejagnu test result improved from:

=== gdb Summary ===

# of expected passes            19030
# of unexpected failures        116

to:
                === gdb Summary ===

# of expected passes            19100
# of unexpected failures        61


these patches are against the latest commit:


   commit 2cca06a0bf0f859e20276e5c614db7b325753a8d
   Author: Joel Brobecker <brobecker@gnat.com>
   Date:   Thu Dec 6 04:57:06 2012 +0000

aix-thread: Fix getthrds declaration and call.


please review, thanks


--
Regards,
Jiong. Wang
Tilera Corporation

>From 85696377fc2c76ea51463c5896f63c96a5ace92e Mon Sep 17 00:00:00 2001
From: Jiong Wang <jiwang@tilera.com>
Date: Thu, 6 Dec 2012 12:13:03 +0800
Subject: [PATCH 1/5]     * tilegx-tdep.c (tilegx_push_dummy_call): stack
 alignment should be 64bit

      for tilegx, when push args on stack, the alignment should be 64bit
---
 gdb/tilegx-tdep.c |   32 ++++++++------------------------
 1 file changed, 8 insertions(+), 24 deletions(-)

diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c
index 627a470..2f7f253 100644
--- a/gdb/tilegx-tdep.c
+++ b/gdb/tilegx-tdep.c
@@ -292,7 +292,7 @@ tilegx_push_dummy_call (struct gdbarch *gdbarch,
   int argreg = TILEGX_R0_REGNUM;
   int i, j;
   int typelen, slacklen, alignlen;
-  static const gdb_byte two_zero_words[8] = { 0 };
+  static const gdb_byte four_zero_words[16] = { 0 };
 
   /* If struct_return is 1, then the struct return address will
      consume one argument-passing register.  */
@@ -324,44 +324,28 @@ tilegx_push_dummy_call (struct gdbarch *gdbarch,
     }
 
   /* Align SP.  */
-  stack_dest = tilegx_frame_align (gdbarch, stack_dest);
-
-  /* Loop backwards through arguments to determine stack alignment.  */
-  alignlen = 0;
-
-  for (j = nargs - 1; j >= i; j--)
-    {
-      typelen = TYPE_LENGTH (value_enclosing_type (args[j]));
-      alignlen += (typelen + 3) & (~3);
-    }
-
-  if (alignlen & 0x4)
-    stack_dest -= 4;
+  stack_dest = (stack_dest + 7) & ~0x7;
 
   /* Loop backwards through remaining arguments and push them on
      the stack, word aligned.  */
   for (j = nargs - 1; j >= i; j--)
     {
       gdb_byte *val;
-      struct cleanup *back_to;
-      const gdb_byte *contents = value_contents (args[j]);
 
       typelen = TYPE_LENGTH (value_enclosing_type (args[j]));
-      slacklen = ((typelen + 3) & (~3)) - typelen;
-      val = xmalloc (typelen + slacklen);
-      back_to = make_cleanup (xfree, val);
-      memcpy (val, contents, typelen);
+      slacklen = ((typelen + 7) & (~7)) - typelen;
+      val = alloca (typelen + slacklen);
+      memcpy (val, value_contents (args[j]), typelen);
       memset (val + typelen, 0, slacklen);
 
       /* Now write data to the stack.  The stack grows downwards.  */
       stack_dest -= typelen + slacklen;
       write_memory (stack_dest, val, typelen + slacklen);
-      do_cleanups (back_to);
     }
 
-  /* Add 2 words for linkage space to the stack.  */
-  stack_dest = stack_dest - 8;
-  write_memory (stack_dest, two_zero_words, 8);
+  /* Add 2 double words for linkage space to the stack.  */
+  stack_dest = stack_dest - 16;
+  write_memory (stack_dest, four_zero_words, 16);
 
   /* Update stack pointer.  */
   regcache_cooked_write_unsigned (regcache, TILEGX_SP_REGNUM, stack_dest);
-- 
1.7.10.4

>From 028cafa74fe2601ebf13e9a64e6de90e891cbed8 Mon Sep 17 00:00:00 2001
From: Jiong Wang <jiwang@tilera.com>
Date: Thu, 6 Dec 2012 12:15:32 +0800
Subject: [PATCH 2/5]     * tilegx-tdep.c (tilegx_analyze_prologue): fix
 prologue analysis overflow bug

        when setting breakpoint by function name, if that function
      is in .so and that .so is not loaded yet, then gdb will do
      partial name match, which will match the corresponding plt
      stub entry. We should take this situation into account when
      doing prologue analysis.
---
 gdb/tilegx-tdep.c |   18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c
index 2f7f253..93969c9 100644
--- a/gdb/tilegx-tdep.c
+++ b/gdb/tilegx-tdep.c
@@ -432,8 +432,22 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch,
 
 	  status = safe_frame_unwind_memory (next_frame, instbuf_start,
 					     instbuf, instbuf_size);
-	  if (status == 0)
-	    memory_error (status, next_addr);
+	  if (status == 0) {
+            /* fix gdb.base/gdb1250
+             * breakpoint is set before dynamic library loaded, thus gdb
+             * does a partial symbol name finding and sets the breakpoint
+             * in the plt stub. our 32-bundle prefetch window is too large
+             * for this situation to cause a memory access error.
+             * For plt stub, we just need to return directly.
+             *
+             * x86 does not have this problem, because the first instruction
+             * in their plt stub is jump, which ends the analysis also.
+             */
+            if (strcmp(find_pc_section(instbuf_start)->the_bfd_section->name,
+                 ".plt") == 0)
+              return instbuf_start;
+            memory_error (status, next_addr);
+          }
 	}
 
       reverse_frame_valid = 0;
-- 
1.7.10.4

>From 2ecf3fa49f1c2e5031762e0558b1f0c8f37103b4 Mon Sep 17 00:00:00 2001
From: Jiong Wang <jiwang@tilera.com>
Date: Thu, 6 Dec 2012 12:16:15 +0800
Subject: [PATCH 3/5]     * tilegx-tdep.c (tilegx_write_pc): prevent kernel
 from restarting syscall for gdb hand call

        if we just interrupted a system call, the kernel might
      try to restart it when we resume the inferior, such as
      nanosleep.

        for gdb, we may resume the inferior because of a hand call.
      in this situation, we should prevent kernel from restarting
      syscall at $pc - 8, which is no longer the original place
      where syscall occured.
---
 gdb/tilegx-linux-nat.c  |    2 +-
 gdb/tilegx-linux-tdep.c |    6 ++++--
 gdb/tilegx-tdep.c       |   32 ++++++++++++++++++++++++++++++--
 gdb/tilegx-tdep.h       |    4 ++--
 4 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/gdb/tilegx-linux-nat.c b/gdb/tilegx-linux-nat.c
index 23acba5..51dbf5e 100644
--- a/gdb/tilegx-linux-nat.c
+++ b/gdb/tilegx-linux-nat.c
@@ -65,7 +65,7 @@ static const int regmap[] =
   40, 41, 42, 43, 44, 45, 46, 47,
   48, 49, 50, 51, 52, 53, 54, 55,
   -1, -1, -1, -1, -1, -1, -1, -1,
-  56
+  56, 58
 };
 
 /* Transfering the general-purpose registers between GDB, inferiors
diff --git a/gdb/tilegx-linux-tdep.c b/gdb/tilegx-linux-tdep.c
index c5e0e80..19ad297 100644
--- a/gdb/tilegx-linux-tdep.c
+++ b/gdb/tilegx-linux-tdep.c
@@ -85,9 +85,11 @@ tilegx_linux_supply_regset (const struct regset *regset,
   int i;
 
   /* This logic must match that of struct pt_regs in "ptrace.h".  */
-  for (i = 0; i < TILEGX_NUM_EASY_REGS + 1; i++, ptr += tilegx_reg_size)
+  for (i = 0; i < TILEGX_NUM_EASY_REGS + 2; i++, ptr += tilegx_reg_size)
     {
-      int gri = (i < TILEGX_NUM_EASY_REGS) ? i : TILEGX_PC_REGNUM;
+      int gri = (i < TILEGX_NUM_EASY_REGS)
+                 ? i : (i == TILEGX_NUM_EASY_REGS)
+                        ? TILEGX_PC_REGNUM : TILEGX_FAULTNUM_REGNUM;
 
       if (regnum == gri || regnum == -1)
 	regcache_raw_supply (regcache, gri, ptr);
diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c
index 93969c9..bc8cd35 100644
--- a/gdb/tilegx-tdep.c
+++ b/gdb/tilegx-tdep.c
@@ -155,7 +155,7 @@ tilegx_register_name (struct gdbarch *gdbarch, int regnum)
       "r40",  "r41",  "r42",  "r43",  "r44",  "r45",  "r46",  "r47",
       "r48",  "r49",  "r50",  "r51",  "r52",  "tp",   "sp",   "lr",
       "sn",   "idn0", "idn1", "udn0", "udn1", "udn2", "udn3", "zero",
-      "pc"
+      "pc",   "faultnum",
     };
 
   if (regnum < 0 || regnum >= TILEGX_NUM_REGS)
@@ -782,6 +782,32 @@ tilegx_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
   return 0;
 }
 
+#define INT_SWINT_1_SIGRETURN (~0)
+static void
+tilegx_write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  regcache_cooked_write_unsigned (regcache, TILEGX_PC_REGNUM, pc);
+
+  /* We must be careful with modifying the program counter.  If we
+     just interrupted a system call, the kernel might try to restart
+     it when we resume the inferior.  On restarting the system call,
+     the kernel will try backing up the program counter even though it
+     no longer points at the system call.  This typically results in a
+     SIGSEGV or SIGILL.  We can prevent this by writing INT_SWINT_1_SIGRETURN
+     in the "faultnum" pseudo-register.
+
+     Note that "faultnum" is saved when setting up a dummy call frame.
+     This means that it is properly restored when that frame is
+     popped, and that the interrupted system call will be restarted
+     when we resume the inferior on return from a function call from
+     within GDB.  In all other cases the system call will not be
+     restarted.  */
+  regcache_cooked_write_unsigned (regcache, TILEGX_FAULTNUM_REGNUM,
+                                  INT_SWINT_1_SIGRETURN);
+}
+
+
+
 /* This is the implementation of gdbarch method breakpoint_from_pc.  */
 
 static const unsigned char *
@@ -913,7 +939,8 @@ tilegx_cannot_reference_register (struct gdbarch *gdbarch, int regno)
 {
   if (regno >= 0 && regno < TILEGX_NUM_EASY_REGS)
     return 0;
-  else if (regno == TILEGX_PC_REGNUM)
+  else if (regno == TILEGX_PC_REGNUM
+           || regno == TILEGX_FAULTNUM_REGNUM)
     return 0;
   else
     return 1;
@@ -996,6 +1023,7 @@ tilegx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* These values and methods are used when gdb calls a target function.  */
   set_gdbarch_push_dummy_call (gdbarch, tilegx_push_dummy_call);
+  set_gdbarch_write_pc (gdbarch, tilegx_write_pc);
   set_gdbarch_breakpoint_from_pc (gdbarch, tilegx_breakpoint_from_pc);
   set_gdbarch_return_value (gdbarch, tilegx_return_value);
 
diff --git a/gdb/tilegx-tdep.h b/gdb/tilegx-tdep.h
index 3ac18a5..5f99fd9 100644
--- a/gdb/tilegx-tdep.h
+++ b/gdb/tilegx-tdep.h
@@ -100,8 +100,8 @@ enum tilegx_regnum
 
     TILEGX_PC_REGNUM,
     TILEGX_NUM_PHYS_REGS = TILEGX_PC_REGNUM, /* 64 */
-
-    TILEGX_NUM_REGS /* 65 */
+    TILEGX_FAULTNUM_REGNUM,
+    TILEGX_NUM_REGS, /* 66 */
   };
 
 enum { tilegx_reg_size = 8 };
-- 
1.7.10.4

>From 42a5f9a8d1caffda706d1371f1cfa5b2490bef03 Mon Sep 17 00:00:00 2001
From: Jiong Wang <jiwang@tilera.com>
Date: Thu, 6 Dec 2012 14:11:08 +0800
Subject: [PATCH 4/5]     * tilegx-tdep.c (tilegx_skip_prologue): use
 skip_prologue_using_sal instead of find_pc_line

---
 gdb/tilegx-tdep.c |   18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c
index bc8cd35..1e967fe 100644
--- a/gdb/tilegx-tdep.c
+++ b/gdb/tilegx-tdep.c
@@ -741,24 +741,24 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch,
 /* This is the implementation of gdbarch method skip_prologue.  */
 
 static CORE_ADDR
-tilegx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+tilegx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
 {
-  struct symtab_and_line sal;
-  CORE_ADDR func_start, func_end;
+  CORE_ADDR func_start;
 
   /* This is the preferred method, find the end of the prologue by
      using the debugging information.  */
-  if (find_pc_partial_function (pc, NULL, &func_start, &func_end))
+  if (find_pc_partial_function (start_pc, NULL, &func_start, NULL))
     {
-	sal = find_pc_line (func_start, 0);
-
-	if (sal.end < func_end && pc <= sal.end)
-	  return sal.end;
+      CORE_ADDR post_prologue_pc
+        = skip_prologue_using_sal (gdbarch, func_start);
+      if (post_prologue_pc != 0)
+        return max (start_pc, post_prologue_pc);
     }
 
   /* Otherwise, try to skip prologue the hard way.  */
   return tilegx_analyze_prologue (gdbarch,
-				  pc, pc + 8 * TILEGX_BUNDLE_SIZE_IN_BYTES,
+                                  start_pc,
+                                  start_pc + 8 * TILEGX_BUNDLE_SIZE_IN_BYTES,
 				  NULL, NULL);
 }
 
-- 
1.7.10.4

>From d6ea11561793c96cf1eb9f3f013089724c9c923d Mon Sep 17 00:00:00 2001
From: Jiong Wang <jiwang@tilera.com>
Date: Thu, 6 Dec 2012 14:15:54 +0800
Subject: [PATCH 5/5]     * tilegx-tdep.c (tilera_print_registers_info): new

        support tilegx private register info hook to show
      registers in columns.
---
 gdb/tilegx-tdep.c |   63 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c
index 1e967fe..bf00983 100644
--- a/gdb/tilegx-tdep.c
+++ b/gdb/tilegx-tdep.c
@@ -946,6 +946,66 @@ tilegx_cannot_reference_register (struct gdbarch *gdbarch, int regno)
     return 1;
 }
 
+
+/* Tilera private register printer.  */
+#define MAX_COLUMNS 3
+static void
+tilera_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
+                             struct frame_info *frame,
+                             int regnum, int print_all)
+{
+  int i;
+  int j;
+  int k;
+  gdb_byte buffer[MAX_REGISTER_SIZE];
+
+  if (regnum != -1)
+    {
+      default_print_registers_info (gdbarch, file, frame, regnum, print_all);
+      return;
+    }
+
+  for (i = 0; i < TILEGX_NUM_EASY_REGS / MAX_COLUMNS + 1; ++i)
+    {
+      for (j = i;
+           j < TILEGX_NUM_EASY_REGS + 1;
+           j += TILEGX_NUM_EASY_REGS / MAX_COLUMNS + 1)
+        {
+	  /* Some registers are never available. Skip them and print PC.  */
+	  if (j > TILEGX_LR_REGNUM)
+	    j = TILEGX_PC_REGNUM;
+
+	  if (j > i)
+	    fprintf_filtered (file, "    ");
+
+	  fputs_filtered (gdbarch_register_name (gdbarch, j), file);
+	  print_spaces_filtered (5 - strlen (gdbarch_register_name
+					     (gdbarch, j)), file);
+
+	  /* Get the data in raw format.  */
+	  if (! deprecated_frame_register_read (frame, j, buffer))
+	    {
+	      fprintf_filtered (file, " *** no value *** ");
+	    }
+	  else
+	    {
+	      fprintf_filtered (file, "0x");
+	      for (k = 0; k < tilegx_reg_size; k++)
+		{
+		  int idx;
+		  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+		    idx = k;
+		  else
+		    idx = tilegx_reg_size - 1 - k;
+		  fprintf_filtered (file, "%02x", (unsigned char) buffer[idx]);
+		}
+	    }
+        }
+
+      fprintf_filtered (file, "\n");
+    }
+}
+
 static struct gdbarch *
 tilegx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
@@ -1006,6 +1066,9 @@ tilegx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Stack grows down.  */
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
+  /* Tilera private register printer */
+  set_gdbarch_print_registers_info (gdbarch, tilera_print_registers_info);
+
   /* Frame Info.  */
   set_gdbarch_unwind_sp (gdbarch, tilegx_unwind_sp);
   set_gdbarch_unwind_pc (gdbarch, tilegx_unwind_pc);
-- 
1.7.10.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]