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]

[RFA] New qRelocInsn RSP packet, docs and NEWS.


This extracts the new qRelocInsn packet from this larger patch:

 [GDBserver fast tracepoints support]
 http://sourceware.org/ml/gdb-patches/2010-05/msg00149.html

It also extends the documentation a bit compared to that other
patch, and also adds a NEWS entry.

Okay?

-- 
Pedro Alves

gdb/
2010-05-24  Pedro Alves  <pedro@codesourcery.com>

	* NEWS: Mention the `qRelocInsn' feature.
	* gdbarch.sh (relocate_instruction): New.
	* amd64-tdep.c (rip_relative_offset): New.
	(append_insns): New.
	(amd64_relocate_instruction): New.
	(amd64_init_abi): Install it.
	* i386-tdep.c (append_insns): New.
	(i386_relocate_instruction): New.
	(i386_gdbarch_init): Install it.
	* remote.c (remote_get_noisy_reply): Handle qRelocInsn requests.
	* gdbarch.h, gdbarch.c: Regenerate.

gdb/doc/
2010-05-24  Pedro Alves  <pedro@codesourcery.com>

	* gdb.texinfo (General Query Packets) <qSupported>: Describe the
	`qRelocInsn' feature.
	(Relocate instruction reply packet): New subsection
	of `Tracepoint Packets'.
	(Tracepoint Packets): Mention that packets QTDP and QTStart
	support the qRelocInsn request, and add cross reference to new
	subsection.

---
 gdb/NEWS            |    9 +++
 gdb/amd64-tdep.c    |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/doc/gdb.texinfo |   53 ++++++++++++++++++++++-
 gdb/gdbarch.c       |   35 +++++++++++++++
 gdb/gdbarch.h       |   18 +++++++
 gdb/gdbarch.sh      |   13 +++++
 gdb/i386-tdep.c     |   82 +++++++++++++++++++++++++++++++++++
 gdb/remote.c        |   62 ++++++++++++++++++++++++---
 8 files changed, 382 insertions(+), 9 deletions(-)

Index: src/gdb/NEWS
===================================================================
--- src.orig/gdb/NEWS	2010-05-24 14:22:02.000000000 +0100
+++ src/gdb/NEWS	2010-05-24 14:29:38.000000000 +0100
@@ -18,6 +18,15 @@ qGetTIBAddr
 
   Return the address of the Windows Thread Information Block of a given thread.
 
+qRelocInsn
+
+  In response to several of the tracepoint packets, the target may now
+  also respond with a number of intermediate `qRelocInsn' request
+  packets before the final result packet, to have GDB handle
+  relocatating an instruction to execute at a different address.  This
+  is particularly useful for stubs that support fast tracepoints.  GDB
+  reports support for this feature in the qSupported packet.
+
 * The source command now accepts a -s option to force searching for the
   script in the source search path even if the script name specifies
   a directory.
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo	2010-05-24 12:28:55.000000000 +0100
+++ src/gdb/doc/gdb.texinfo	2010-05-24 14:21:56.000000000 +0100
@@ -31408,6 +31408,11 @@ This feature indicates that @value{GDBN}
 description.  If the stub sees @samp{xmlRegisters=} with target
 specific strings separated by a comma, it will report register
 description.
+
+@item qRelocInsn
+This feature indicates whether @value{GDBN} supports the
+@samp{qRelocInsn} packet (@pxref{Tracepoint Packets,,Relocate
+instruction reply packet}).
 @end table
 
 Stubs should ignore any unknown values for
@@ -32016,6 +32021,8 @@ Replies:
 @table @samp
 @item OK
 The packet was understood and carried out.
+@item qRelocInsn
+@xref{Tracepoint Packets,,Relocate instruction reply packet}.
 @item 
 The packet was not recognized.
 @end table
@@ -32080,6 +32087,8 @@ Replies:
 @table @samp
 @item OK
 The packet was understood and carried out.
+@item qRelocInsn
+@xref{Tracepoint Packets,,Relocate instruction reply packet}.
 @item 
 The packet was not recognized.
 @end table
@@ -32171,8 +32180,10 @@ Like @samp{QTFrame:range:@var{start}:@va
 frame @emph{outside} the given range of addresses (exclusive).
 
 @item QTStart
-Begin the tracepoint experiment.  Begin collecting data from tracepoint
-hits in the trace frame buffer.
+Begin the tracepoint experiment.  Begin collecting data from
+tracepoint hits in the trace frame buffer.  This packet supports the
+@samp{qRelocInsn} reply (@pxref{Tracepoint Packets,,Relocate
+instruction reply packet}).
 
 @item QTStop
 End the tracepoint experiment.  Stop collecting trace frames.
@@ -32333,6 +32344,44 @@ This packet directs the target to use a 
 
 @end table
 
+@subsection Relocate instruction reply packet
+When installing fast tracepoints in memory, the target may need to
+relocate the instruction currently at the tracepoint address to a
+different address in memory.  For most instructions, a simple copy is
+enough, but, for example, call instructions that implicitly push the
+return address on the stack, and relative branches or other
+PC-relative instructions require offset adjustment, so that the effect
+of executing the instruction at a different address is the same as if
+it had executed in the original location.
+
+In response to several of the tracepoint packets, the target may also
+respond with a number of intermediate @samp{qRelocInsn} request
+packets before the final result packet, to have @value{GDBN} handle
+this relocation operation.  If a packet supports this mechanism, its
+documentation will explicitly say so.  See for example the above
+descriptions for the @samp{QTStart} and @samp{QTDP} packets.  The
+format of the request is:
+
+@table @samp
+@item qRelocInsn:@var{from};@var{to}
+
+This requests @value{GDBN} to copy instruction at address @var{from}
+to address @var{to}, possibly adjusted so that executing the
+instruction at @var{to} has the same effect as executing it at
+@var{from}.  @value{GDBN} writes the adjusted instruction to target
+memory starting at @var{to}.
+@end table
+
+Replies:
+@table @samp
+@item qRelocInsn:@var{adjusted_size}
+Informs the stub the relocation is complete.  @var{adjusted_size} is
+the length in bytes of resulting relocated instruction sequence.
+@item E @var{NN}
+A badly formed request was detected, or an error was encountered while
+relocating the instruction.
+@end table
+
 @node Host I/O Packets
 @section Host I/O Packets
 @cindex Host I/O, remote protocol
Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c	2010-05-24 12:28:42.000000000 +0100
+++ src/gdb/remote.c	2010-05-24 13:14:56.000000000 +0100
@@ -242,6 +242,8 @@ static void remote_terminal_ours (void);
 
 static int remote_read_description_p (struct target_ops *target);
 
+char *unpack_varlen_hex (char *buff, ULONGEST *result);
+
 /* The non-stop remote protocol provisions for one pending stop reply.
    This is where we keep it until it is acknowledged.  */
 
@@ -433,6 +435,55 @@ remote_get_noisy_reply (char **buf_p,
       buf = *buf_p;
       if (buf[0] == 'E')
 	trace_error (buf);
+      else if (strncmp (buf, "qRelocInsn:", strlen ("qRelocInsn:")) == 0)
+	{
+	  ULONGEST ul;
+	  CORE_ADDR from, to, org_to;
+	  char *p, *pp;
+	  int adjusted_size = 0;
+	  volatile struct gdb_exception ex;
+
+	  p = buf + strlen ("qRelocInsn:");
+	  pp = unpack_varlen_hex (p, &ul);
+	  if (*pp != ';')
+	    error (_("invalid qRelocInsn packet: %s\n"), buf);
+	  from = ul;
+
+	  p = pp + 1;
+	  pp = unpack_varlen_hex (p, &ul);
+	  to = ul;
+
+	  org_to = to;
+
+	  TRY_CATCH (ex, RETURN_MASK_ALL)
+	    {
+	      gdbarch_relocate_instruction (target_gdbarch, &to, from);
+	    }
+	  if (ex.reason >= 0)
+	    {
+	      adjusted_size = to - org_to;
+
+	      sprintf (buf, "qRelocInsn:%x", adjusted_size);
+	      putpkt (buf);
+	    }
+	  else if (ex.reason < 0 && ex.error == MEMORY_ERROR)
+	    {
+	      /* Propagate memory errors silently back to the target.
+		 The stub may have limited the range of addresses we
+		 can write to, for example.  */
+	      putpkt ("E01");
+	    }
+	  else
+	    {
+	      /* Something unexpectedly bad happened.  Be verbose so
+		 we can tell what, and propagate the error back to the
+		 stub, so it doesn't get stuck waiting for a
+		 response.  */
+	      exception_fprintf (gdb_stderr, ex,
+				 _("warning: relocating instruction: "));
+	      putpkt ("E01");
+	    }
+	}
       else if (buf[0] == 'O' && buf[1] != 'K')
 	remote_console_output (buf + 1);	/* 'O' message from stub */
       else
@@ -3584,13 +3635,10 @@ remote_query_supported (void)
       if (remote_support_xml)
 	q = remote_query_supported_append (q, remote_support_xml);
 
-      if (q)
-	{
-	  q = reconcat (q, "qSupported:", q, (char *) NULL);
-	  putpkt (q);
-	}
-      else
-	putpkt ("qSupported");
+      q = remote_query_supported_append (q, "qRelocInsn+");
+
+      q = reconcat (q, "qSupported:", q, (char *) NULL);
+      putpkt (q);
 
       do_cleanups (old_chain);
 
Index: src/gdb/amd64-tdep.c
===================================================================
--- src.orig/gdb/amd64-tdep.c	2010-05-24 13:00:23.000000000 +0100
+++ src/gdb/amd64-tdep.c	2010-05-24 14:14:21.000000000 +0100
@@ -1507,6 +1507,123 @@ amd64_displaced_step_fixup (struct gdbar
 			    paddress (gdbarch, retaddr));
     }
 }
+
+/* If the instruction INSN uses RIP-relative addressing, return the
+   offset into the raw INSN where the displacement to be adjusted is
+   found.  Returns 0 if the instruction doesn't use RIP-relative
+   addressing.  */
+
+static int
+rip_relative_offset (struct amd64_insn *insn)
+{
+  if (insn->modrm_offset != -1)
+    {
+      gdb_byte modrm = insn->raw_insn[insn->modrm_offset];
+
+      if ((modrm & 0xc7) == 0x05)
+	{
+	  /* The displacement is found right after the ModRM byte.  */
+	  return insn->modrm_offset + 1;
+	}
+    }
+
+  return 0;
+}
+
+static void
+append_insns (CORE_ADDR *to, ULONGEST len, const gdb_byte *buf)
+{
+  target_write_memory (*to, buf, len);
+  *to += len;
+}
+
+void
+amd64_relocate_instruction (struct gdbarch *gdbarch,
+			    CORE_ADDR *to, CORE_ADDR oldloc)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int len = gdbarch_max_insn_length (gdbarch);
+  /* Extra space for sentinels.  */
+  int fixup_sentinel_space = len;
+  gdb_byte *buf = xmalloc (len + fixup_sentinel_space);
+  struct amd64_insn insn_details;
+  int offset = 0;
+  LONGEST rel32, newrel;
+  gdb_byte *insn;
+  int insn_length;
+
+  read_memory (oldloc, buf, len);
+
+  /* Set up the sentinel space so we don't have to worry about running
+     off the end of the buffer.  An excessive number of leading prefixes
+     could otherwise cause this.  */
+  memset (buf + len, 0, fixup_sentinel_space);
+
+  insn = buf;
+  amd64_get_insn_details (insn, &insn_details);
+
+  insn_length = gdb_buffered_insn_length (gdbarch, insn, len, oldloc);
+
+  /* Skip legacy instruction prefixes.  */
+  insn = amd64_skip_prefixes (insn);
+
+  /* Adjust calls with 32-bit relative addresses as push/jump, with
+     the address pushed being the location where the original call in
+     the user program would return to.  */
+  if (insn[0] == 0xe8)
+    {
+      gdb_byte push_buf[16];
+      unsigned int ret_addr;
+
+      /* Where "ret" in the original code will return to.  */
+      ret_addr = oldloc + insn_length;
+      push_buf[0] = 0x68; /* pushq $... */
+      memcpy (&push_buf[1], &ret_addr, 4);
+      /* Push the push.  */
+      append_insns (to, 5, push_buf);
+
+      /* Convert the relative call to a relative jump.  */
+      insn[0] = 0xe9;
+
+      /* Adjust the destination offset.  */
+      rel32 = extract_signed_integer (insn + 1, 4, byte_order);
+      newrel = (oldloc - *to) + rel32;
+      store_signed_integer (insn + 1, 4, newrel, byte_order);
+
+      /* Write the adjusted jump into its displaced location.  */
+      append_insns (to, 5, insn);
+      return;
+    }
+
+  offset = rip_relative_offset (&insn_details);
+  if (!offset)
+    {
+      /* Adjust jumps with 32-bit relative addresses.  Calls are
+	 already handled above.  */
+      if (insn[0] == 0xe9)
+	offset = 1;
+      /* Adjust conditional jumps.  */
+      else if (insn[0] == 0x0f && (insn[1] & 0xf0) == 0x80)
+	offset = 2;
+    }
+
+  if (offset)
+    {
+      rel32 = extract_signed_integer (insn + offset, 4, byte_order);
+      newrel = (oldloc - *to) + rel32;
+      store_signed_integer (insn + offset, 4, newrel, byte_order);
+      if (debug_displaced)
+	fprintf_unfiltered (gdb_stdlog,
+			    "Adjusted insn rel32=0x%s at 0x%s to"
+			    " rel32=0x%s at 0x%s\n",
+			    hex_string (rel32), paddress (gdbarch, oldloc),
+			    hex_string (newrel), paddress (gdbarch, *to));
+    }
+
+  /* Write the adjusted instruction into its displaced location.  */
+  append_insns (to, insn_length, buf);
+}
+
 
 /* The maximum number of saved registers.  This should include %rip.  */
 #define AMD64_NUM_SAVED_REGS	AMD64_NUM_GREGS
@@ -2363,6 +2480,8 @@ amd64_init_abi (struct gdbarch_info info
 					  amd64_regset_from_core_section);
 
   set_gdbarch_get_longjmp_target (gdbarch, amd64_get_longjmp_target);
+
+  set_gdbarch_relocate_instruction (gdbarch, amd64_relocate_instruction);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
Index: src/gdb/gdbarch.c
===================================================================
--- src.orig/gdb/gdbarch.c	2010-05-24 13:00:42.000000000 +0100
+++ src/gdb/gdbarch.c	2010-05-24 14:14:44.000000000 +0100
@@ -245,6 +245,7 @@ struct gdbarch
   gdbarch_displaced_step_fixup_ftype *displaced_step_fixup;
   gdbarch_displaced_step_free_closure_ftype *displaced_step_free_closure;
   gdbarch_displaced_step_location_ftype *displaced_step_location;
+  gdbarch_relocate_instruction_ftype *relocate_instruction;
   gdbarch_overlay_update_ftype *overlay_update;
   gdbarch_core_read_description_ftype *core_read_description;
   gdbarch_static_transform_name_ftype *static_transform_name;
@@ -392,6 +393,7 @@ struct gdbarch startup_gdbarch =
   0,  /* displaced_step_fixup */
   NULL,  /* displaced_step_free_closure */
   NULL,  /* displaced_step_location */
+  0,  /* relocate_instruction */
   0,  /* overlay_update */
   0,  /* core_read_description */
   0,  /* static_transform_name */
@@ -493,6 +495,7 @@ gdbarch_alloc (const struct gdbarch_info
   gdbarch->displaced_step_fixup = NULL;
   gdbarch->displaced_step_free_closure = NULL;
   gdbarch->displaced_step_location = NULL;
+  gdbarch->relocate_instruction = NULL;
   gdbarch->target_signal_from_host = default_target_signal_from_host;
   gdbarch->target_signal_to_host = default_target_signal_to_host;
   gdbarch->has_shared_address_space = default_has_shared_address_space;
@@ -667,6 +670,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
     fprintf_unfiltered (log, "\n\tdisplaced_step_free_closure");
   if ((! gdbarch->displaced_step_location) != (! gdbarch->displaced_step_copy_insn))
     fprintf_unfiltered (log, "\n\tdisplaced_step_location");
+  /* Skip verify of relocate_instruction, has predicate */
   /* Skip verify of overlay_update, has predicate */
   /* Skip verify of core_read_description, has predicate */
   /* Skip verify of static_transform_name, has predicate */
@@ -1105,6 +1109,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s
                       "gdbarch_dump: regset_from_core_section = <%s>\n",
                       host_address_to_string (gdbarch->regset_from_core_section));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_relocate_instruction_p() = %d\n",
+                      gdbarch_relocate_instruction_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: relocate_instruction = <%s>\n",
+                      host_address_to_string (gdbarch->relocate_instruction));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: remote_breakpoint_from_pc = <%s>\n",
                       host_address_to_string (gdbarch->remote_breakpoint_from_pc));
   fprintf_unfiltered (file,
@@ -3303,6 +3313,31 @@ set_gdbarch_displaced_step_location (str
 }
 
 int
+gdbarch_relocate_instruction_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->relocate_instruction != NULL;
+}
+
+void
+gdbarch_relocate_instruction (struct gdbarch *gdbarch, CORE_ADDR *to, CORE_ADDR from)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->relocate_instruction != NULL);
+  /* Do not check predicate: gdbarch->relocate_instruction != NULL, allow call.  */
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_relocate_instruction called\n");
+  gdbarch->relocate_instruction (gdbarch, to, from);
+}
+
+void
+set_gdbarch_relocate_instruction (struct gdbarch *gdbarch,
+                                  gdbarch_relocate_instruction_ftype relocate_instruction)
+{
+  gdbarch->relocate_instruction = relocate_instruction;
+}
+
+int
 gdbarch_overlay_update_p (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
Index: src/gdb/gdbarch.h
===================================================================
--- src.orig/gdb/gdbarch.h	2010-05-24 13:00:42.000000000 +0100
+++ src/gdb/gdbarch.h	2010-05-24 14:14:43.000000000 +0100
@@ -806,6 +806,24 @@ typedef CORE_ADDR (gdbarch_displaced_ste
 extern CORE_ADDR gdbarch_displaced_step_location (struct gdbarch *gdbarch);
 extern void set_gdbarch_displaced_step_location (struct gdbarch *gdbarch, gdbarch_displaced_step_location_ftype *displaced_step_location);
 
+/* Relocate an instruction to execute at a different address.  OLDLOC
+   is the address in the inferior memory where the instruction to
+   relocate is currently at.  On input, TO points to the destination
+   where we want the instruction to be copied (and possibly adjusted)
+   to.  On output, it points to one past the end of the resulting
+   instruction(s).  The effect of executing the instruction at TO shall
+   be the same as if executing it at FROM.  For example, call
+   instructions that implicitly push the return address on the stack
+   should be adjusted to return to the instruction after OLDLOC;
+   relative branches, and other PC-relative instructions need the
+   offset adjusted; etc. */
+
+extern int gdbarch_relocate_instruction_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_relocate_instruction_ftype) (struct gdbarch *gdbarch, CORE_ADDR *to, CORE_ADDR from);
+extern void gdbarch_relocate_instruction (struct gdbarch *gdbarch, CORE_ADDR *to, CORE_ADDR from);
+extern void set_gdbarch_relocate_instruction (struct gdbarch *gdbarch, gdbarch_relocate_instruction_ftype *relocate_instruction);
+
 /* Refresh overlay mapped state for section OSECT. */
 
 extern int gdbarch_overlay_update_p (struct gdbarch *gdbarch);
Index: src/gdb/gdbarch.sh
===================================================================
--- src.orig/gdb/gdbarch.sh	2010-05-24 13:00:42.000000000 +0100
+++ src/gdb/gdbarch.sh	2010-05-24 14:14:47.000000000 +0100
@@ -708,6 +708,19 @@ m:void:displaced_step_free_closure:struc
 # see the comments in infrun.c.
 m:CORE_ADDR:displaced_step_location:void:::NULL::(! gdbarch->displaced_step_location) != (! gdbarch->displaced_step_copy_insn)
 
+# Relocate an instruction to execute at a different address.  OLDLOC
+# is the address in the inferior memory where the instruction to
+# relocate is currently at.  On input, TO points to the destination
+# where we want the instruction to be copied (and possibly adjusted)
+# to.  On output, it points to one past the end of the resulting
+# instruction(s).  The effect of executing the instruction at TO shall
+# be the same as if executing it at FROM.  For example, call
+# instructions that implicitly push the return address on the stack
+# should be adjusted to return to the instruction after OLDLOC;
+# relative branches, and other PC-relative instructions need the
+# offset adjusted; etc.
+M:void:relocate_instruction:CORE_ADDR *to, CORE_ADDR from:to, from::NULL
+
 # Refresh overlay mapped state for section OSECT.
 F:void:overlay_update:struct obj_section *osect:osect
 
Index: src/gdb/i386-tdep.c
===================================================================
--- src.orig/gdb/i386-tdep.c	2010-05-24 12:58:48.000000000 +0100
+++ src/gdb/i386-tdep.c	2010-05-24 14:14:36.000000000 +0100
@@ -658,6 +658,86 @@ i386_displaced_step_fixup (struct gdbarc
                             paddress (gdbarch, retaddr));
     }
 }
+
+static void
+append_insns (CORE_ADDR *to, ULONGEST len, const gdb_byte *buf)
+{
+  target_write_memory (*to, buf, len);
+  *to += len;
+}
+
+static void
+i386_relocate_instruction (struct gdbarch *gdbarch,
+			   CORE_ADDR *to, CORE_ADDR oldloc)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte buf[I386_MAX_INSN_LEN];
+  int offset = 0, rel32, newrel;
+  int insn_length;
+  gdb_byte *insn = buf;
+
+  read_memory (oldloc, buf, I386_MAX_INSN_LEN);
+
+  insn_length = gdb_buffered_insn_length (gdbarch, insn,
+					  I386_MAX_INSN_LEN, oldloc);
+
+  /* Get past the prefixes.  */
+  insn = i386_skip_prefixes (insn, I386_MAX_INSN_LEN);
+
+  /* Adjust calls with 32-bit relative addresses as push/jump, with
+     the address pushed being the location where the original call in
+     the user program would return to.  */
+  if (insn[0] == 0xe8)
+    {
+      gdb_byte push_buf[16];
+      unsigned int ret_addr;
+
+      /* Where "ret" in the original code will return to.  */
+      ret_addr = oldloc + insn_length;
+      push_buf[0] = 0x68; /* pushq $... */
+      memcpy (&push_buf[1], &ret_addr, 4);
+      /* Push the push.  */
+      append_insns (to, 5, push_buf);
+
+      /* Convert the relative call to a relative jump.  */
+      insn[0] = 0xe9;
+
+      /* Adjust the destination offset.  */
+      rel32 = extract_signed_integer (insn + 1, 4, byte_order);
+      newrel = (oldloc - *to) + rel32;
+      store_signed_integer (insn + 1, 4, newrel, byte_order);
+
+      /* Write the adjusted jump into its displaced location.  */
+      append_insns (to, 5, insn);
+      return;
+    }
+
+  /* Adjust jumps with 32-bit relative addresses.  Calls are already
+     handled above.  */
+  if (insn[0] == 0xe9)
+    offset = 1;
+  /* Adjust conditional jumps.  */
+  else if (insn[0] == 0x0f && (insn[1] & 0xf0) == 0x80)
+    offset = 2;
+
+  if (offset)
+    {
+      rel32 = extract_signed_integer (insn + offset, 4, byte_order);
+      newrel = (oldloc - *to) + rel32;
+      store_signed_integer (insn + offset, 4, newrel, byte_order);
+      if (debug_displaced)
+	fprintf_unfiltered (gdb_stdlog,
+			    "Adjusted insn rel32=0x%s at 0x%s to"
+			    " rel32=0x%s at 0x%s\n",
+			    hex_string (rel32), paddress (gdbarch, oldloc),
+			    hex_string (newrel), paddress (gdbarch, *to));
+    }
+
+  /* Write the adjusted instructions into their displaced
+     location.  */
+  append_insns (to, insn_length, buf);
+}
+
 
 #ifdef I386_REGNO_TO_SYMMETRY
 #error "The Sequent Symmetry is no longer supported."
@@ -6909,6 +6989,8 @@ i386_gdbarch_init (struct gdbarch_info i
 
   tdesc_data = tdesc_data_alloc ();
 
+  set_gdbarch_relocate_instruction (gdbarch, i386_relocate_instruction);
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
   info.tdep_info = (void *) tdesc_data;
   gdbarch_init_osabi (info, gdbarch);


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