This is the mail archive of the gdb-patches@sourceware.cygnus.com 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]

[PATCH RFA] TARGET_ADJUST_BREAKPOINT_ADDRESS...


I request approval for committing the changes below.

The patches below add a new gdbarch operation called
TARGET_ADJUST_BREAKPOINT_ADDRESS.  It is intended to be used by
targets which have architectural constraints on the addresses at which
a breakpoint may be placed.

E.g, a VLIW or EPIC architecture may have rules about where in the
instruction word a breakpoint may be placed.  On such architectures,
an instruction consists of several sub-instructions all of which are
executed in parallel.  The compiler could emit code which causes
portions of two source language statements to share the same
instruction.  The debugging info could then indicate that a particular
statement starts at an address at which it is not acceptable to place
a breakpoint.

For such a target, one would define a TARGET_ADJUST_BREAKPOINT_ADDRESS
operation which, given an address, would return a (possibly adjusted)
address at which it is acceptable to place a breakoint.

A RISC architecture could define this operation to make sure that a
breakpoint address is aligned on a word boundary.  And the IA-64
architecture could use this operation to ensure that the user
specified a valid slot address (changing the address to something
reasonable if incorrect).

If a breakpoint address is adjusted, there's some new code in
breakpoint.c which'll print out a warning.  Such a warning might
look something like this...

	(gdb) b foo
	warning: Breakpoint address moved from 0x06200090 to 0x0620008c.
	Breakpoint 1 at 0x0620008c: file bar.c, line 21.

I will submit a separate documentation patch once the patches below
are accepted.

	* gdbarch.sh (TARGET_ADJUST_BREAKPOINT_ADDRESS): New entry.
	* gdbarch.h, gdbarch.c: Regenerated from gdbarch.sh.

	* arch-utils.c, arch-utils.h 
	(default_target_adjust_breakpoint_address): New function.

	* breakpoint.c (adjust_breakpoint_address): New function.
	(set_raw_breakpoint, set_longjmp_resume_breakpoint,
	watch_command_1, breakpoint_re_set_one):  When setting the
	breakpoint's address, call adjust_breakpoint_address() to
	account for architectural constraints on locations where a
	breakpoint may be placed.

Index: arch-utils.c
===================================================================
RCS file: /cvs/src/src/gdb/arch-utils.c,v
retrieving revision 1.10
diff -u -p -r1.10 arch-utils.c
--- arch-utils.c	2000/06/10 05:37:47	1.10
+++ arch-utils.c	2000/06/21 02:19:27
@@ -95,6 +95,21 @@ legacy_breakpoint_from_pc (CORE_ADDR * p
   return NULL;
 }
 
+/* Some architectures have constraints about where a breakpoint may be
+   placed.  TARGET_ADJUST_BREAKPOINT_ADDRESS is given an address that is
+   adjusted (and returned) to conform to the constraints imposed by
+   the architecture.
+   
+   Targets which have no architectural constraints on breakpoint placement
+   should use default_target_adjust_breakpoint_address which merely returns
+   the breakpoint address unadjusted */
+
+CORE_ADDR
+default_target_adjust_breakpoint_address (CORE_ADDR bpaddr)
+{
+  return bpaddr;
+}
+
 int
 generic_frameless_function_invocation_not (struct frame_info *fi)
 {
Index: arch-utils.h
===================================================================
RCS file: /cvs/src/src/gdb/arch-utils.h,v
retrieving revision 1.7
diff -u -p -r1.7 arch-utils.h
--- arch-utils.h	2000/06/07 04:38:02	1.7
+++ arch-utils.h	2000/06/21 02:19:28
@@ -36,6 +36,11 @@ extern gdbarch_frame_num_args_ftype fram
    targets that don't yet implement their own breakpoint_from_pc(). */
 extern gdbarch_breakpoint_from_pc_ftype legacy_breakpoint_from_pc;
 
+/* Identity function for targets which don't have architectural constraints
+   on placement of breakpoints. */
+extern gdbarch_target_adjust_breakpoint_address_ftype
+  default_target_adjust_breakpoint_address;
+
 /* Frameless functions not identifable. */
 extern gdbarch_frameless_function_invocation_ftype generic_frameless_function_invocation_not;
 
Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.13
diff -u -p -r1.13 breakpoint.c
--- breakpoint.c	2000/06/12 21:17:21	1.13
+++ breakpoint.c	2000/06/21 02:19:36
@@ -96,6 +96,8 @@ struct breakpoint *set_raw_breakpoint (s
 
 static void check_duplicates (CORE_ADDR, asection *);
 
+static CORE_ADDR adjust_breakpoint_address (CORE_ADDR bpaddr);
+
 static void describe_other_breakpoints (CORE_ADDR, asection *);
 
 static void breakpoints_info (char *, int);
@@ -3827,6 +3829,30 @@ check_duplicates (address, section)
     }
 }
 
+/* Call TARGET_ADJUST_BREAKPOINT_ADDRESS and print warning if an address
+   adjustment was made.  Returns the adjusted address. */
+
+static CORE_ADDR
+adjust_breakpoint_address (CORE_ADDR bpaddr)
+{
+  CORE_ADDR adjusted_bpaddr;
+
+  adjusted_bpaddr = TARGET_ADJUST_BREAKPOINT_ADDRESS (bpaddr);
+
+  if (adjusted_bpaddr != bpaddr)
+    {
+      char astr1[50];
+      char astr2[50];
+      strcpy (astr1, local_hex_string_custom ((unsigned long) bpaddr, "08l"));
+      strcpy (astr2,
+	      local_hex_string_custom ((unsigned long) adjusted_bpaddr,
+				       "08l"));
+      warning ("Breakpoint address moved from %s to %s.", astr1, astr2);
+    }
+
+  return adjusted_bpaddr;
+}
+
 /* Low level routine to set a breakpoint.
    Takes as args the three things that every breakpoint must have.
    Returns the breakpoint object so caller can set other things.
@@ -3845,7 +3871,7 @@ set_raw_breakpoint (sal)
 
   b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
   memset (b, 0, sizeof (*b));
-  b->address = sal.pc;
+  b->address = adjust_breakpoint_address (sal.pc);
   if (sal.symtab == NULL)
     b->source_file = NULL;
   else
@@ -4327,7 +4353,7 @@ set_longjmp_resume_breakpoint (pc, frame
   ALL_BREAKPOINTS (b)
     if (b->type == bp_longjmp_resume)
     {
-      b->address = pc;
+      b->address = adjust_breakpoint_address (pc);
       b->enable = enabled;
       if (frame != NULL)
 	b->frame = frame->frame;
@@ -5506,7 +5532,8 @@ watch_command_1 (arg, accessflag, from_t
 	  scope_breakpoint->frame = prev_frame->frame;
 
 	  /* Set the address at which we will stop.  */
-	  scope_breakpoint->address = get_frame_pc (prev_frame);
+	  scope_breakpoint->address = 
+	    adjust_breakpoint_address (get_frame_pc (prev_frame));
 
 	  /* The scope breakpoint is related to the watchpoint.  We
 	     will need to act on them together.  */
@@ -7162,7 +7189,7 @@ breakpoint_re_set_one (bint)
 		  savestring (sals.sals[i].symtab->filename,
 			      strlen (sals.sals[i].symtab->filename));
 	      b->line_number = sals.sals[i].line;
-	      b->address = sals.sals[i].pc;
+	      b->address = adjust_breakpoint_address (sals.sals[i].pc);
 
 	      /* Used to check for duplicates here, but that can
 	         cause trouble, as it doesn't check for disable
Index: gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.29
diff -u -p -r1.29 gdbarch.c
--- gdbarch.c	2000/06/12 00:35:33	1.29
+++ gdbarch.c	2000/06/21 02:19:39
@@ -205,6 +205,7 @@ struct gdbarch
   gdbarch_prologue_frameless_p_ftype *prologue_frameless_p;
   gdbarch_inner_than_ftype *inner_than;
   gdbarch_breakpoint_from_pc_ftype *breakpoint_from_pc;
+  gdbarch_target_adjust_breakpoint_address_ftype *target_adjust_breakpoint_address;
   gdbarch_memory_insert_breakpoint_ftype *memory_insert_breakpoint;
   gdbarch_memory_remove_breakpoint_ftype *memory_remove_breakpoint;
   CORE_ADDR decr_pc_after_break;
@@ -340,6 +341,7 @@ struct gdbarch startup_gdbarch =
   0,
   0,
   0,
+  0,
   /* startup_gdbarch() */
 };
 
@@ -391,6 +393,7 @@ gdbarch_alloc (const struct gdbarch_info
   gdbarch->return_value_on_stack = generic_return_value_on_stack_not;
   gdbarch->prologue_frameless_p = generic_prologue_frameless_p;
   gdbarch->breakpoint_from_pc = legacy_breakpoint_from_pc;
+  gdbarch->target_adjust_breakpoint_address = default_target_adjust_breakpoint_address;
   gdbarch->memory_insert_breakpoint = default_memory_insert_breakpoint;
   gdbarch->memory_remove_breakpoint = default_memory_remove_breakpoint;
   gdbarch->decr_pc_after_break = -1;
@@ -611,6 +614,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
       && (gdbarch->inner_than == 0))
     internal_error ("gdbarch: verify_gdbarch: inner_than invalid");
   /* Skip verify of breakpoint_from_pc, invalid_p == 0 */
+  /* Skip verify of target_adjust_breakpoint_address, invalid_p == 0 */
   /* Skip verify of memory_insert_breakpoint, invalid_p == 0 */
   /* Skip verify of memory_remove_breakpoint, invalid_p == 0 */
   if ((GDB_MULTI_ARCH >= 2)
@@ -1124,6 +1128,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s
                       "BREAKPOINT_FROM_PC(pcptr, lenptr)",
                       XSTRING (BREAKPOINT_FROM_PC (pcptr, lenptr)));
 #endif
+#ifdef TARGET_ADJUST_BREAKPOINT_ADDRESS
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: %s # %s\n",
+                      "TARGET_ADJUST_BREAKPOINT_ADDRESS(bpaddr)",
+                      XSTRING (TARGET_ADJUST_BREAKPOINT_ADDRESS (bpaddr)));
+#endif
 #ifdef MEMORY_INSERT_BREAKPOINT
   fprintf_unfiltered (file,
                       "gdbarch_dump: %s # %s\n",
@@ -1724,6 +1734,13 @@ gdbarch_dump (struct gdbarch *gdbarch, s
                         (long) current_gdbarch->breakpoint_from_pc
                         /*BREAKPOINT_FROM_PC ()*/);
 #endif
+#ifdef TARGET_ADJUST_BREAKPOINT_ADDRESS
+  if (GDB_MULTI_ARCH)
+    fprintf_unfiltered (file,
+                        "gdbarch_dump: TARGET_ADJUST_BREAKPOINT_ADDRESS = 0x%08lx\n",
+                        (long) current_gdbarch->target_adjust_breakpoint_address
+                        /*TARGET_ADJUST_BREAKPOINT_ADDRESS ()*/);
+#endif
 #ifdef MEMORY_INSERT_BREAKPOINT
   if (GDB_MULTI_ARCH)
     fprintf_unfiltered (file,
@@ -3177,6 +3194,23 @@ set_gdbarch_breakpoint_from_pc (struct g
                                 gdbarch_breakpoint_from_pc_ftype breakpoint_from_pc)
 {
   gdbarch->breakpoint_from_pc = breakpoint_from_pc;
+}
+
+CORE_ADDR
+gdbarch_target_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
+{
+  if (gdbarch->target_adjust_breakpoint_address == 0)
+    internal_error ("gdbarch: gdbarch_target_adjust_breakpoint_address invalid");
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_target_adjust_breakpoint_address called\n");
+  return gdbarch->target_adjust_breakpoint_address (bpaddr);
+}
+
+void
+set_gdbarch_target_adjust_breakpoint_address (struct gdbarch *gdbarch,
+                                              gdbarch_target_adjust_breakpoint_address_ftype target_adjust_breakpoint_address)
+{
+  gdbarch->target_adjust_breakpoint_address = target_adjust_breakpoint_address;
 }
 
 int
Index: gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.23
diff -u -p -r1.23 gdbarch.h
--- gdbarch.h	2000/06/10 05:37:47	1.23
+++ gdbarch.h	2000/06/21 02:19:41
@@ -862,6 +862,20 @@ extern void set_gdbarch_breakpoint_from_
 #endif
 
 /* Default (function) for non- multi-arch platforms. */
+#if (GDB_MULTI_ARCH == 0) && !defined (TARGET_ADJUST_BREAKPOINT_ADDRESS)
+#define TARGET_ADJUST_BREAKPOINT_ADDRESS(bpaddr) (default_target_adjust_breakpoint_address (bpaddr))
+#endif
+
+typedef CORE_ADDR (gdbarch_target_adjust_breakpoint_address_ftype) (CORE_ADDR bpaddr);
+extern CORE_ADDR gdbarch_target_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr);
+extern void set_gdbarch_target_adjust_breakpoint_address (struct gdbarch *gdbarch, gdbarch_target_adjust_breakpoint_address_ftype *target_adjust_breakpoint_address);
+#if GDB_MULTI_ARCH
+#if (GDB_MULTI_ARCH > 1) || !defined (TARGET_ADJUST_BREAKPOINT_ADDRESS)
+#define TARGET_ADJUST_BREAKPOINT_ADDRESS(bpaddr) (gdbarch_target_adjust_breakpoint_address (current_gdbarch, bpaddr))
+#endif
+#endif
+
+/* Default (function) for non- multi-arch platforms. */
 #if (GDB_MULTI_ARCH == 0) && !defined (MEMORY_INSERT_BREAKPOINT)
 #define MEMORY_INSERT_BREAKPOINT(addr, contents_cache) (default_memory_insert_breakpoint (addr, contents_cache))
 #endif
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.29
diff -u -p -r1.29 gdbarch.sh
--- gdbarch.sh	2000/06/12 00:35:34	1.29
+++ gdbarch.sh	2000/06/21 02:19:43
@@ -364,6 +364,7 @@ f:2:SKIP_PROLOGUE:CORE_ADDR:skip_prologu
 f:2:PROLOGUE_FRAMELESS_P:int:prologue_frameless_p:CORE_ADDR ip:ip::0:generic_prologue_frameless_p::0
 f:2:INNER_THAN:int:inner_than:CORE_ADDR lhs, CORE_ADDR rhs:lhs, rhs::0:0
 f:2:BREAKPOINT_FROM_PC:unsigned char *:breakpoint_from_pc:CORE_ADDR *pcptr, int *lenptr:pcptr, lenptr:::legacy_breakpoint_from_pc::0
+f:2:TARGET_ADJUST_BREAKPOINT_ADDRESS:CORE_ADDR:target_adjust_breakpoint_address:CORE_ADDR bpaddr:bpaddr:::default_target_adjust_breakpoint_address::0
 f:2:MEMORY_INSERT_BREAKPOINT:int:memory_insert_breakpoint:CORE_ADDR addr, char *contents_cache:addr, contents_cache::0:default_memory_insert_breakpoint::0
 f:2:MEMORY_REMOVE_BREAKPOINT:int:memory_remove_breakpoint:CORE_ADDR addr, char *contents_cache:addr, contents_cache::0:default_memory_remove_breakpoint::0
 v:2:DECR_PC_AFTER_BREAK:CORE_ADDR:decr_pc_after_break::::0:-1


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