gdb/
2010-05-26 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-26 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.
This commit is contained in:
parent
0a5b531f15
commit
dde08ee109
@ -1,3 +1,17 @@
|
|||||||
|
2010-05-26 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.
|
||||||
|
|
||||||
2010-05-26 Tom Tromey <tromey@redhat.com>
|
2010-05-26 Tom Tromey <tromey@redhat.com>
|
||||||
|
|
||||||
* dwarf2loc.h (struct dwarf2_locexpr_baton) <data>: Now const.
|
* dwarf2loc.h (struct dwarf2_locexpr_baton) <data>: Now const.
|
||||||
|
9
gdb/NEWS
9
gdb/NEWS
@ -18,6 +18,15 @@ qGetTIBAddr
|
|||||||
|
|
||||||
Return the address of the Windows Thread Information Block of a given thread.
|
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
|
||||||
|
relocating 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
|
* 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
|
script in the source search path even if the script name specifies
|
||||||
a directory.
|
a directory.
|
||||||
|
119
gdb/amd64-tdep.c
119
gdb/amd64-tdep.c
@ -1507,6 +1507,123 @@ amd64_displaced_step_fixup (struct gdbarch *gdbarch,
|
|||||||
paddress (gdbarch, retaddr));
|
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. */
|
/* The maximum number of saved registers. This should include %rip. */
|
||||||
#define AMD64_NUM_SAVED_REGS AMD64_NUM_GREGS
|
#define AMD64_NUM_SAVED_REGS AMD64_NUM_GREGS
|
||||||
@ -2363,6 +2480,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|||||||
amd64_regset_from_core_section);
|
amd64_regset_from_core_section);
|
||||||
|
|
||||||
set_gdbarch_get_longjmp_target (gdbarch, amd64_get_longjmp_target);
|
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. */
|
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
2010-05-26 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.
|
||||||
|
|
||||||
2010-05-25 Doug Evans <dje@google.com>
|
2010-05-25 Doug Evans <dje@google.com>
|
||||||
|
|
||||||
* gdb.texinfo (Exception Handling): Document gdb.GdbError.
|
* gdb.texinfo (Exception Handling): Document gdb.GdbError.
|
||||||
|
@ -31446,6 +31446,11 @@ This feature indicates that @value{GDBN} supports the XML target
|
|||||||
description. If the stub sees @samp{xmlRegisters=} with target
|
description. If the stub sees @samp{xmlRegisters=} with target
|
||||||
specific strings separated by a comma, it will report register
|
specific strings separated by a comma, it will report register
|
||||||
description.
|
description.
|
||||||
|
|
||||||
|
@item qRelocInsn
|
||||||
|
This feature indicates whether @value{GDBN} supports the
|
||||||
|
@samp{qRelocInsn} packet (@pxref{Tracepoint Packets,,Relocate
|
||||||
|
instruction reply packet}).
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
Stubs should ignore any unknown values for
|
Stubs should ignore any unknown values for
|
||||||
@ -32054,6 +32059,8 @@ Replies:
|
|||||||
@table @samp
|
@table @samp
|
||||||
@item OK
|
@item OK
|
||||||
The packet was understood and carried out.
|
The packet was understood and carried out.
|
||||||
|
@item qRelocInsn
|
||||||
|
@xref{Tracepoint Packets,,Relocate instruction reply packet}.
|
||||||
@item
|
@item
|
||||||
The packet was not recognized.
|
The packet was not recognized.
|
||||||
@end table
|
@end table
|
||||||
@ -32118,6 +32125,8 @@ Replies:
|
|||||||
@table @samp
|
@table @samp
|
||||||
@item OK
|
@item OK
|
||||||
The packet was understood and carried out.
|
The packet was understood and carried out.
|
||||||
|
@item qRelocInsn
|
||||||
|
@xref{Tracepoint Packets,,Relocate instruction reply packet}.
|
||||||
@item
|
@item
|
||||||
The packet was not recognized.
|
The packet was not recognized.
|
||||||
@end table
|
@end table
|
||||||
@ -32209,8 +32218,10 @@ Like @samp{QTFrame:range:@var{start}:@var{end}}, but select the first
|
|||||||
frame @emph{outside} the given range of addresses (exclusive).
|
frame @emph{outside} the given range of addresses (exclusive).
|
||||||
|
|
||||||
@item QTStart
|
@item QTStart
|
||||||
Begin the tracepoint experiment. Begin collecting data from tracepoint
|
Begin the tracepoint experiment. Begin collecting data from
|
||||||
hits in the trace frame buffer.
|
tracepoint hits in the trace frame buffer. This packet supports the
|
||||||
|
@samp{qRelocInsn} reply (@pxref{Tracepoint Packets,,Relocate
|
||||||
|
instruction reply packet}).
|
||||||
|
|
||||||
@item QTStop
|
@item QTStop
|
||||||
End the tracepoint experiment. Stop collecting trace frames.
|
End the tracepoint experiment. Stop collecting trace frames.
|
||||||
@ -32371,6 +32382,44 @@ This packet directs the target to use a circular trace buffer if
|
|||||||
|
|
||||||
@end table
|
@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
|
@node Host I/O Packets
|
||||||
@section Host I/O Packets
|
@section Host I/O Packets
|
||||||
@cindex Host I/O, remote protocol
|
@cindex Host I/O, remote protocol
|
||||||
|
@ -245,6 +245,7 @@ struct gdbarch
|
|||||||
gdbarch_displaced_step_fixup_ftype *displaced_step_fixup;
|
gdbarch_displaced_step_fixup_ftype *displaced_step_fixup;
|
||||||
gdbarch_displaced_step_free_closure_ftype *displaced_step_free_closure;
|
gdbarch_displaced_step_free_closure_ftype *displaced_step_free_closure;
|
||||||
gdbarch_displaced_step_location_ftype *displaced_step_location;
|
gdbarch_displaced_step_location_ftype *displaced_step_location;
|
||||||
|
gdbarch_relocate_instruction_ftype *relocate_instruction;
|
||||||
gdbarch_overlay_update_ftype *overlay_update;
|
gdbarch_overlay_update_ftype *overlay_update;
|
||||||
gdbarch_core_read_description_ftype *core_read_description;
|
gdbarch_core_read_description_ftype *core_read_description;
|
||||||
gdbarch_static_transform_name_ftype *static_transform_name;
|
gdbarch_static_transform_name_ftype *static_transform_name;
|
||||||
@ -392,6 +393,7 @@ struct gdbarch startup_gdbarch =
|
|||||||
0, /* displaced_step_fixup */
|
0, /* displaced_step_fixup */
|
||||||
NULL, /* displaced_step_free_closure */
|
NULL, /* displaced_step_free_closure */
|
||||||
NULL, /* displaced_step_location */
|
NULL, /* displaced_step_location */
|
||||||
|
0, /* relocate_instruction */
|
||||||
0, /* overlay_update */
|
0, /* overlay_update */
|
||||||
0, /* core_read_description */
|
0, /* core_read_description */
|
||||||
0, /* static_transform_name */
|
0, /* static_transform_name */
|
||||||
@ -493,6 +495,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
|
|||||||
gdbarch->displaced_step_fixup = NULL;
|
gdbarch->displaced_step_fixup = NULL;
|
||||||
gdbarch->displaced_step_free_closure = NULL;
|
gdbarch->displaced_step_free_closure = NULL;
|
||||||
gdbarch->displaced_step_location = NULL;
|
gdbarch->displaced_step_location = NULL;
|
||||||
|
gdbarch->relocate_instruction = NULL;
|
||||||
gdbarch->target_signal_from_host = default_target_signal_from_host;
|
gdbarch->target_signal_from_host = default_target_signal_from_host;
|
||||||
gdbarch->target_signal_to_host = default_target_signal_to_host;
|
gdbarch->target_signal_to_host = default_target_signal_to_host;
|
||||||
gdbarch->has_shared_address_space = default_has_shared_address_space;
|
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");
|
fprintf_unfiltered (log, "\n\tdisplaced_step_free_closure");
|
||||||
if ((! gdbarch->displaced_step_location) != (! gdbarch->displaced_step_copy_insn))
|
if ((! gdbarch->displaced_step_location) != (! gdbarch->displaced_step_copy_insn))
|
||||||
fprintf_unfiltered (log, "\n\tdisplaced_step_location");
|
fprintf_unfiltered (log, "\n\tdisplaced_step_location");
|
||||||
|
/* Skip verify of relocate_instruction, has predicate */
|
||||||
/* Skip verify of overlay_update, has predicate */
|
/* Skip verify of overlay_update, has predicate */
|
||||||
/* Skip verify of core_read_description, has predicate */
|
/* Skip verify of core_read_description, has predicate */
|
||||||
/* Skip verify of static_transform_name, has predicate */
|
/* Skip verify of static_transform_name, has predicate */
|
||||||
@ -1104,6 +1108,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
|||||||
fprintf_unfiltered (file,
|
fprintf_unfiltered (file,
|
||||||
"gdbarch_dump: regset_from_core_section = <%s>\n",
|
"gdbarch_dump: regset_from_core_section = <%s>\n",
|
||||||
host_address_to_string (gdbarch->regset_from_core_section));
|
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,
|
fprintf_unfiltered (file,
|
||||||
"gdbarch_dump: remote_breakpoint_from_pc = <%s>\n",
|
"gdbarch_dump: remote_breakpoint_from_pc = <%s>\n",
|
||||||
host_address_to_string (gdbarch->remote_breakpoint_from_pc));
|
host_address_to_string (gdbarch->remote_breakpoint_from_pc));
|
||||||
@ -3302,6 +3312,31 @@ set_gdbarch_displaced_step_location (struct gdbarch *gdbarch,
|
|||||||
gdbarch->displaced_step_location = displaced_step_location;
|
gdbarch->displaced_step_location = displaced_step_location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
int
|
||||||
gdbarch_overlay_update_p (struct gdbarch *gdbarch)
|
gdbarch_overlay_update_p (struct gdbarch *gdbarch)
|
||||||
{
|
{
|
||||||
|
@ -806,6 +806,24 @@ typedef CORE_ADDR (gdbarch_displaced_step_location_ftype) (struct gdbarch *gdbar
|
|||||||
extern CORE_ADDR gdbarch_displaced_step_location (struct gdbarch *gdbarch);
|
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);
|
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. */
|
/* Refresh overlay mapped state for section OSECT. */
|
||||||
|
|
||||||
extern int gdbarch_overlay_update_p (struct gdbarch *gdbarch);
|
extern int gdbarch_overlay_update_p (struct gdbarch *gdbarch);
|
||||||
|
@ -708,6 +708,19 @@ m:void:displaced_step_free_closure:struct displaced_step_closure *closure:closur
|
|||||||
# see the comments in infrun.c.
|
# see the comments in infrun.c.
|
||||||
m:CORE_ADDR:displaced_step_location:void:::NULL::(! gdbarch->displaced_step_location) != (! gdbarch->displaced_step_copy_insn)
|
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.
|
# Refresh overlay mapped state for section OSECT.
|
||||||
F:void:overlay_update:struct obj_section *osect:osect
|
F:void:overlay_update:struct obj_section *osect:osect
|
||||||
|
|
||||||
|
@ -658,6 +658,86 @@ i386_displaced_step_fixup (struct gdbarch *gdbarch,
|
|||||||
paddress (gdbarch, retaddr));
|
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
|
#ifdef I386_REGNO_TO_SYMMETRY
|
||||||
#error "The Sequent Symmetry is no longer supported."
|
#error "The Sequent Symmetry is no longer supported."
|
||||||
@ -6909,6 +6989,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||||||
|
|
||||||
tdesc_data = tdesc_data_alloc ();
|
tdesc_data = tdesc_data_alloc ();
|
||||||
|
|
||||||
|
set_gdbarch_relocate_instruction (gdbarch, i386_relocate_instruction);
|
||||||
|
|
||||||
/* Hook in ABI-specific overrides, if they have been registered. */
|
/* Hook in ABI-specific overrides, if they have been registered. */
|
||||||
info.tdep_info = (void *) tdesc_data;
|
info.tdep_info = (void *) tdesc_data;
|
||||||
gdbarch_init_osabi (info, gdbarch);
|
gdbarch_init_osabi (info, gdbarch);
|
||||||
|
58
gdb/remote.c
58
gdb/remote.c
@ -242,6 +242,8 @@ static void remote_terminal_ours (void);
|
|||||||
|
|
||||||
static int remote_read_description_p (struct target_ops *target);
|
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.
|
/* The non-stop remote protocol provisions for one pending stop reply.
|
||||||
This is where we keep it until it is acknowledged. */
|
This is where we keep it until it is acknowledged. */
|
||||||
|
|
||||||
@ -433,6 +435,55 @@ remote_get_noisy_reply (char **buf_p,
|
|||||||
buf = *buf_p;
|
buf = *buf_p;
|
||||||
if (buf[0] == 'E')
|
if (buf[0] == 'E')
|
||||||
trace_error (buf);
|
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')
|
else if (buf[0] == 'O' && buf[1] != 'K')
|
||||||
remote_console_output (buf + 1); /* 'O' message from stub */
|
remote_console_output (buf + 1); /* 'O' message from stub */
|
||||||
else
|
else
|
||||||
@ -3584,13 +3635,10 @@ remote_query_supported (void)
|
|||||||
if (remote_support_xml)
|
if (remote_support_xml)
|
||||||
q = remote_query_supported_append (q, remote_support_xml);
|
q = remote_query_supported_append (q, remote_support_xml);
|
||||||
|
|
||||||
if (q)
|
q = remote_query_supported_append (q, "qRelocInsn+");
|
||||||
{
|
|
||||||
q = reconcat (q, "qSupported:", q, (char *) NULL);
|
q = reconcat (q, "qSupported:", q, (char *) NULL);
|
||||||
putpkt (q);
|
putpkt (q);
|
||||||
}
|
|
||||||
else
|
|
||||||
putpkt ("qSupported");
|
|
||||||
|
|
||||||
do_cleanups (old_chain);
|
do_cleanups (old_chain);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user