* [PATCH] Shorter fast tracepoints
@ 2011-10-29 1:55 Stan Shebs
2011-10-29 10:09 ` Eli Zaretskii
0 siblings, 1 reply; 2+ messages in thread
From: Stan Shebs @ 2011-10-29 1:55 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 4934 bytes --]
One of the downsides of fast tracepoints is that because they are
typically implemented with multi-byte jump instructions (so as to avoid
expensive trap handlers and context switches), they can't be inserted
anywhere that you might like. On the x86, this is especially
troublesome because the general jump is five bytes long, and
well-optimized code isn't even going to have that many 5-byte
instructions. The x86 does offer a jump with a 2-byte address, although
it needs a prefix and so ends up being four bytes in all. This patch,
then, does the work of making that possible for 32-bit x86 Linux.
The ugly part is that the 2-byte address is in the low 64K of memory,
which may or may not be available - GDB has to check
/proc/sys/vm/mmap_min_addr. Fortunately users can tweak it manually
(via sysctl) if the preset is to block out all of low memory.
This brings up two troublesome points about this patch as it stands.
First, documentation. As it stands, the patch to the manual says
nothing about fooling with the kernel's mmap_min_addr. Should it? It's
very system-specific, and the user would only need to do anything
special if mmap_min_addr were set to 64K or higher, otherwise everything
quietly works as desired.
Second, this is hard to write a test case for. Certainly asm hackery to
available to create the 4-byte instruction, but if mmap_min_addr is too
high, the necessary sysctl-ing requires a sudo, and I don't think we
normally allow sudo's in the testsuite. In any case, this patch is not
causing any regressions in the current tests.
(Many thanks to Kwok for doing the real work, I'm just massaging it a bit.)
Stan
2011-10-28 Stan Shebs <stan@codesourcery.com>
Kwok Cheung Yeung <kcy@codesourcery.com>
* NEWS: Document new qTMinFTPILen packet.
* i386-tdep.c (i386_fast_tracepoint_valid_at): Query target for
the minimum instruction size for fast tracepoints.
* target.h (struct target_ops): Add new method
to_get_min_fast_tracepoint_insn_len.
(target_get_min_fast_tracepoint_insn_len): New.
* target.c (update_current_target): Set up new target operation.
* remote.c (remote_write_bytes_aux): Fix typo.
(remote_download_tracepoint): Revert to regular tracepoint if a
fast tracepoint is placed on an instruction that is too short.
(remote_get_min_fast_tracepoint_insn_len): New.
(init_remote_ops): Initialize new field.
[gdb/gdbserver]
* linux-x86-low.c (small_jump_insn): New.
(i386_install_fast_tracepoint_jump_pad): Add arguments for
trampoline and error message, build a trampoline and issue a small
jump instruction to it.
(x86_install_fast_tracepoint_jump_pad): Add arguments for
trampoline and error message.
(x86_get_min_fast_tracepoint_insn_len): New.
(the_low_target): Add call to x86_get_min_fast_tracepoint_insn_len.
* linux-low.h (struct linux_target_ops): Add arguments to
install_fast_tracepoint_jump_pad operation, add new operation.
* linux-low.c (linux_install_fast_tracepoint_jump_pad): Add
arguments.
(linux_get_min_fast_tracepoint_insn_len): New function.
(linux_target_op): Add new operation.
* tracepoint.c (gdb_trampoline_buffer): New IPA variable.
(gdb_trampoline_buffer_end): Ditto.
(gdb_trampoline_buffer_error): Ditto.
(struct ipa_sym_addresses): Add fields for new IPA variables.
(symbol_list): Add entries for new IPA variables.
(struct tracepoint): Add fields to hold the address range of the
trampoline used by the tracepoint.
(trampoline_buffer_head): New static variable.
(trampoline_buffer_tail): Ditto.
(claim_trampoline_space): New function.
(have_fast_tracepoint_trampoline_buffer): New function.
(cmd_qtstart): Return errors in packet reply, fill in trampoline
fields of tracepoint structure.
(cmd_qtminftpilen): New function.
(handle_tracepoint_query): Add response to qTMinFTPILen packet.
(fast_tracepoint_from_trampoline_address): New function.
(fast_tracepoint_collecting): Handle trampoline as part of jump
pad space.
(set_trampoline_buffer_space): New function.
(initialize_tracepoint): Initialize new IPA variables.
* target.h (struct target_ops): Add arguments to
install_fast_tracepoint_jump_pad operation, add new
get_min_fast_tracepoint_insn_len operation.
(target_get_min_fast_tracepoint_insn_len): New.
(install_fast_tracepoint_jump_pad): Add arguments.
* linux-i386-ipa.c: Include extra header files.
(initialize_fast_tracepoint_trampoline_buffer): New function.
(initialize_low_tracepoint): Call it.
* server.h (set_trampoline_buffer_space): Declare.
(claim_trampoline_space): Ditto.
(have_fast_tracepoint_trampoline_buffer): Ditto.
[gdb/doc]
* gdb.texinfo (Tracepoint Packets): Document new qTMinFTPILen packet.
[-- Attachment #2: tshort-patch-1 --]
[-- Type: text/plain, Size: 44085 bytes --]
Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.462
diff -p -r1.462 NEWS
*** NEWS 28 Oct 2011 14:48:36 -0000 1.462
--- NEWS 29 Oct 2011 00:37:56 -0000
***************
*** 13,18 ****
--- 13,23 ----
watchpoints are slower than real hardware watchpoints but are
significantly faster than gdb software watchpoints.
+ qTMinFTPILen
+
+ Query the minimum length of instruction at which a fast tracepoint may
+ be placed.
+
* Python scripting
** The register_pretty_printer function in module gdb.printing now takes
Index: i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.339
diff -p -r1.339 i386-tdep.c
*** i386-tdep.c 11 Oct 2011 19:08:58 -0000 1.339
--- i386-tdep.c 29 Oct 2011 00:37:56 -0000
*************** static const int i386_record_regmap[] =
*** 7109,7118 ****
};
/* Check that the given address appears suitable for a fast
! tracepoint, which on x86 means that we need an instruction of at
least 5 bytes, so that we can overwrite it with a 4-byte-offset
jump and not have to worry about program jumps to an address in the
! middle of the tracepoint jump. Returns 1 if OK, and writes a size
of instruction to replace, and 0 if not, plus an explanatory
string. */
--- 7109,7120 ----
};
/* Check that the given address appears suitable for a fast
! tracepoint, which on x86-64 means that we need an instruction of at
least 5 bytes, so that we can overwrite it with a 4-byte-offset
jump and not have to worry about program jumps to an address in the
! middle of the tracepoint jump. On x86, it may be possible to use
! 4-byte jumps with a 2-byte offset to a trampoline located in the
! bottom 64 KiB of memory. Returns 1 if OK, and writes a size
of instruction to replace, and 0 if not, plus an explanatory
string. */
*************** i386_fast_tracepoint_valid_at (struct gd
*** 7123,7132 ****
int len, jumplen;
static struct ui_file *gdb_null = NULL;
! /* This is based on the target agent using a 4-byte relative jump.
! Alternate future possibilities include 8-byte offset for x86-84,
! or 3-byte jumps if the program has trampoline space close by. */
! jumplen = 5;
/* Dummy file descriptor for the disassembler. */
if (!gdb_null)
--- 7125,7150 ----
int len, jumplen;
static struct ui_file *gdb_null = NULL;
! /* Ask the target for the minimum instruction length supported. */
! jumplen = target_get_min_fast_tracepoint_insn_len ();
!
! if (jumplen < 0)
! {
! /* If the target does not support the get_min_fast_tracepoint_insn_len
! operation, assume that fast tracepoints will always be implemented
! using 4-byte relative jumps on both x86 and x86-64. */
! jumplen = 5;
! }
! else if (jumplen == 0)
! {
! /* If the target does support get_min_fast_tracepoint_insn_len but
! returns zero, then the IPA has not loaded yet. In this case,
! we optimistically assume that truncated 2-byte relative jumps
! will be available on x86, and compensate later if this assumption
! turns out to be incorrect. On x86-64 architectures, 4-byte relative
! jumps will always be used. */
! jumplen = (register_size (gdbarch, 0) == 8) ? 5 : 4;
! }
/* Dummy file descriptor for the disassembler. */
if (!gdb_null)
*************** i386_fast_tracepoint_valid_at (struct gd
*** 7134,7139 ****
--- 7152,7160 ----
/* Check for fit. */
len = gdb_print_insn (gdbarch, addr, gdb_null, NULL);
+ if (isize)
+ *isize = len;
+
if (len < jumplen)
{
/* Return a bit of target-specific detail to add to the caller's
*************** i386_fast_tracepoint_valid_at (struct gd
*** 7144,7155 ****
len, jumplen);
return 0;
}
!
! if (isize)
! *isize = len;
! if (msg)
! *msg = NULL;
! return 1;
}
static int
--- 7165,7176 ----
len, jumplen);
return 0;
}
! else
! {
! if (msg)
! *msg = NULL;
! return 1;
! }
}
static int
Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.465
diff -p -r1.465 remote.c
*** remote.c 13 Oct 2011 13:15:16 -0000 1.465
--- remote.c 29 Oct 2011 00:37:56 -0000
*************** remote_write_bytes_aux (const char *head
*** 6338,6344 ****
if (todo <= 0)
internal_error (__FILE__, __LINE__,
! _("minumum packet size too small to write data"));
/* If we already need another packet, then try to align the end
of this packet to a useful boundary. */
--- 6338,6344 ----
if (todo <= 0)
internal_error (__FILE__, __LINE__,
! _("minimum packet size too small to write data"));
/* If we already need another packet, then try to align the end
of this packet to a useful boundary. */
*************** remote_download_tracepoint (struct break
*** 9859,9869 ****
tpaddr, &isize, NULL))
sprintf (buf + strlen (buf), ":F%x", isize);
else
! /* If it passed validation at definition but fails now,
! something is very wrong. */
! internal_error (__FILE__, __LINE__,
! _("Fast tracepoint not "
! "valid during download"));
}
else
/* Fast tracepoints are functionally identical to regular
--- 9859,9868 ----
tpaddr, &isize, NULL))
sprintf (buf + strlen (buf), ":F%x", isize);
else
! warning (_("Target does not support fast tracepoints at "
! "%d-byte long instructions, downloading %d as "
! "regular tracepoint."),
! isize, b->number);
}
else
/* Fast tracepoints are functionally identical to regular
*************** remote_traceframe_info (void)
*** 10390,10395 ****
--- 10389,10419 ----
return NULL;
}
+ /* Handle the qTMinFTPILen packet. Returns the minimum length of instruction
+ on which a fast tracepoint may be placed. Returns -1 if the packet is not
+ supported, and 0 if the minimum instruction length is unknown. */
+
+ static int
+ remote_get_min_fast_tracepoint_insn_len (void)
+ {
+ struct remote_state *rs = get_remote_state ();
+ char *reply;
+
+ sprintf (rs->buf, "qTMinFTPILen");
+ putpkt (rs->buf);
+ reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (*reply == '\0')
+ return -1;
+ else
+ {
+ ULONGEST min_insn_len;
+
+ unpack_varlen_hex (reply, &min_insn_len);
+
+ return (int) min_insn_len;
+ }
+ }
+
static void
init_remote_ops (void)
{
*************** Specify the serial device it is connecte
*** 10477,10482 ****
--- 10501,10507 ----
remote_ops.to_upload_trace_state_variables
= remote_upload_trace_state_variables;
remote_ops.to_get_raw_trace_data = remote_get_raw_trace_data;
+ remote_ops.to_get_min_fast_tracepoint_insn_len = remote_get_min_fast_tracepoint_insn_len;
remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing;
remote_ops.to_set_circular_trace_buffer = remote_set_circular_trace_buffer;
remote_ops.to_core_of_thread = remote_core_of_thread;
Index: target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.286
diff -p -r1.286 target.c
*** target.c 7 Oct 2011 12:06:46 -0000 1.286
--- target.c 29 Oct 2011 00:37:56 -0000
*************** update_current_target (void)
*** 687,692 ****
--- 687,693 ----
INHERIT (to_upload_tracepoints, t);
INHERIT (to_upload_trace_state_variables, t);
INHERIT (to_get_raw_trace_data, t);
+ INHERIT (to_get_min_fast_tracepoint_insn_len, t);
INHERIT (to_set_disconnected_tracing, t);
INHERIT (to_set_circular_trace_buffer, t);
INHERIT (to_get_tib_address, t);
*************** update_current_target (void)
*** 885,890 ****
--- 886,894 ----
de_fault (to_get_raw_trace_data,
(LONGEST (*) (gdb_byte *, ULONGEST, LONGEST))
tcomplain);
+ de_fault (to_get_min_fast_tracepoint_insn_len,
+ (int (*) (void))
+ return_minus_one);
de_fault (to_set_disconnected_tracing,
(void (*) (int))
target_ignore);
Index: target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.214
diff -p -r1.214 target.h
*** target.h 28 Oct 2011 18:29:59 -0000 1.214
--- target.h 29 Oct 2011 00:37:56 -0000
*************** struct target_ops
*** 731,736 ****
--- 731,742 ----
LONGEST (*to_get_raw_trace_data) (gdb_byte *buf,
ULONGEST offset, LONGEST len);
+ /* Get the minimum length of instruction on which a fast tracepoint
+ may be set on the target. If this operation is unsupported,
+ return -1. If for some reason the minimum length cannot be
+ determined, return 0. */
+ int (*to_get_min_fast_tracepoint_insn_len) (void);
+
/* Set the target's tracing behavior in response to unexpected
disconnection - set VAL to 1 to keep tracing, 0 to stop. */
void (*to_set_disconnected_tracing) (int val);
*************** extern int target_search_memory (CORE_AD
*** 1510,1515 ****
--- 1516,1524 ----
#define target_get_raw_trace_data(buf,offset,len) \
(*current_target.to_get_raw_trace_data) ((buf), (offset), (len))
+ #define target_get_min_fast_tracepoint_insn_len() \
+ (*current_target.to_get_min_fast_tracepoint_insn_len) ()
+
#define target_set_disconnected_tracing(val) \
(*current_target.to_set_disconnected_tracing) (val)
Index: gdbserver/linux-i386-ipa.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-i386-ipa.c,v
retrieving revision 1.5
diff -p -r1.5 linux-i386-ipa.c
*** gdbserver/linux-i386-ipa.c 16 May 2011 15:59:45 -0000 1.5
--- gdbserver/linux-i386-ipa.c 29 Oct 2011 00:37:56 -0000
***************
*** 19,24 ****
--- 19,26 ----
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "server.h"
+ #include <stdint.h>
+ #include <sys/mman.h>
/* GDB register numbers. */
*************** supply_static_tracepoint_registers (stru
*** 191,198 ****
--- 193,247 ----
may use it proper at some point. */
const char *gdbserver_xmltarget;
+ /* Attempt to allocate memory for trampolines in the first 64 KiB of
+ memory to enable smaller jump patches. */
+
+ static void
+ initialize_fast_tracepoint_trampoline_buffer (void)
+ {
+ const CORE_ADDR buffer_end = 64 * 1024;
+ char buf[100];
+ CORE_ADDR mmap_min_addr = buffer_end + 1;
+ ULONGEST buffer_size;
+ FILE *f = fopen ("/proc/sys/vm/mmap_min_addr", "r");
+
+ if (!f)
+ {
+ snprintf (buf, sizeof (buf), "mmap_min_addr open failed: %s",
+ strerror (errno));
+ set_trampoline_buffer_space (0, 0, buf);
+ return;
+ }
+
+ if (fgets (buf, 100, f))
+ sscanf (buf, "%llu", &mmap_min_addr);
+
+ fclose (f);
+
+ buffer_size = buffer_end - mmap_min_addr;
+
+ /* Ensure that the buffer will be at least 1 KiB in size (i.e. enough
+ space for over 200 fast tracepoints). */
+ if (buffer_size >= 1024)
+ {
+ if (mmap ((void *) (uintptr_t) mmap_min_addr, buffer_size,
+ PROT_READ | PROT_EXEC | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0)
+ != MAP_FAILED)
+ set_trampoline_buffer_space (mmap_min_addr, buffer_end, NULL);
+ else
+ {
+ snprintf (buf, 99, "low-64K-buffer mmap() failed: %s",
+ strerror (errno));
+ set_trampoline_buffer_space (0, 0, buf);
+ }
+ }
+ }
+
void
initialize_low_tracepoint (void)
{
init_registers_i386_linux ();
+ initialize_fast_tracepoint_trampoline_buffer ();
}
Index: gdbserver/linux-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.c,v
retrieving revision 1.178
diff -p -r1.178 linux-low.c
*** gdbserver/linux-low.c 7 Oct 2011 12:06:48 -0000 1.178
--- gdbserver/linux-low.c 29 Oct 2011 00:37:57 -0000
*************** linux_install_fast_tracepoint_jump_pad (
*** 4933,4947 ****
CORE_ADDR lockaddr,
ULONGEST orig_size,
CORE_ADDR *jump_entry,
unsigned char *jjump_pad_insn,
ULONGEST *jjump_pad_insn_size,
CORE_ADDR *adjusted_insn_addr,
! CORE_ADDR *adjusted_insn_addr_end)
{
return (*the_low_target.install_fast_tracepoint_jump_pad)
(tpoint, tpaddr, collector, lockaddr, orig_size,
! jump_entry, jjump_pad_insn, jjump_pad_insn_size,
! adjusted_insn_addr, adjusted_insn_addr_end);
}
static struct emit_ops *
--- 4933,4952 ----
CORE_ADDR lockaddr,
ULONGEST orig_size,
CORE_ADDR *jump_entry,
+ CORE_ADDR *trampoline,
+ ULONGEST *trampoline_size,
unsigned char *jjump_pad_insn,
ULONGEST *jjump_pad_insn_size,
CORE_ADDR *adjusted_insn_addr,
! CORE_ADDR *adjusted_insn_addr_end,
! char *err)
{
return (*the_low_target.install_fast_tracepoint_jump_pad)
(tpoint, tpaddr, collector, lockaddr, orig_size,
! jump_entry, trampoline, trampoline_size,
! jjump_pad_insn, jjump_pad_insn_size,
! adjusted_insn_addr, adjusted_insn_addr_end,
! err);
}
static struct emit_ops *
*************** linux_emit_ops (void)
*** 4953,4958 ****
--- 4958,4969 ----
return NULL;
}
+ static int
+ linux_get_min_fast_tracepoint_insn_len (void)
+ {
+ return (*the_low_target.get_min_fast_tracepoint_insn_len) ();
+ }
+
static struct target_ops linux_target_ops = {
linux_create_inferior,
linux_attach,
*************** static struct target_ops linux_target_op
*** 5014,5019 ****
--- 5025,5031 ----
linux_install_fast_tracepoint_jump_pad,
linux_emit_ops,
linux_supports_disable_randomization,
+ linux_get_min_fast_tracepoint_insn_len,
};
static void
Index: gdbserver/linux-low.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.h,v
retrieving revision 1.47
diff -p -r1.47 linux-low.h
*** gdbserver/linux-low.h 1 Jan 2011 15:33:24 -0000 1.47
--- gdbserver/linux-low.h 29 Oct 2011 00:37:57 -0000
*************** struct linux_target_ops
*** 132,145 ****
CORE_ADDR lockaddr,
ULONGEST orig_size,
CORE_ADDR *jump_entry,
unsigned char *jjump_pad_insn,
ULONGEST *jjump_pad_insn_size,
CORE_ADDR *adjusted_insn_addr,
! CORE_ADDR *adjusted_insn_addr_end);
/* Return the bytecode operations vector for the current inferior.
Returns NULL if bytecode compilation is not supported. */
struct emit_ops *(*emit_ops) (void);
};
extern struct linux_target_ops the_low_target;
--- 132,153 ----
CORE_ADDR lockaddr,
ULONGEST orig_size,
CORE_ADDR *jump_entry,
+ CORE_ADDR *trampoline,
+ ULONGEST *trampoline_size,
unsigned char *jjump_pad_insn,
ULONGEST *jjump_pad_insn_size,
CORE_ADDR *adjusted_insn_addr,
! CORE_ADDR *adjusted_insn_addr_end,
! char *err);
/* Return the bytecode operations vector for the current inferior.
Returns NULL if bytecode compilation is not supported. */
struct emit_ops *(*emit_ops) (void);
+
+ /* Return the minimum length of an instruction that can be safely overwritten
+ for use as a fast tracepoint. */
+ int (*get_min_fast_tracepoint_insn_len) (void);
+
};
extern struct linux_target_ops the_low_target;
Index: gdbserver/linux-x86-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-x86-low.c,v
retrieving revision 1.30
diff -p -r1.30 linux-x86-low.c
*** gdbserver/linux-x86-low.c 15 Sep 2011 22:54:12 -0000 1.30
--- gdbserver/linux-x86-low.c 29 Oct 2011 00:37:57 -0000
*************** void init_registers_amd64_avx_linux (voi
*** 42,47 ****
--- 42,48 ----
void init_registers_i386_mmx_linux (void);
static unsigned char jump_insn[] = { 0xe9, 0, 0, 0, 0 };
+ static unsigned char small_jump_insn[] = { 0x66, 0xe9, 0, 0 };
/* Backward compatibility for gdb without XML support. */
*************** amd64_install_fast_tracepoint_jump_pad (
*** 1182,1191 ****
CORE_ADDR lockaddr,
ULONGEST orig_size,
CORE_ADDR *jump_entry,
unsigned char *jjump_pad_insn,
ULONGEST *jjump_pad_insn_size,
CORE_ADDR *adjusted_insn_addr,
! CORE_ADDR *adjusted_insn_addr_end)
{
unsigned char buf[40];
int i, offset;
--- 1183,1195 ----
CORE_ADDR lockaddr,
ULONGEST orig_size,
CORE_ADDR *jump_entry,
+ CORE_ADDR *trampoline,
+ ULONGEST *trampoline_size,
unsigned char *jjump_pad_insn,
ULONGEST *jjump_pad_insn_size,
CORE_ADDR *adjusted_insn_addr,
! CORE_ADDR *adjusted_insn_addr_end,
! char *err)
{
unsigned char buf[40];
int i, offset;
*************** i386_install_fast_tracepoint_jump_pad (C
*** 1346,1355 ****
CORE_ADDR lockaddr,
ULONGEST orig_size,
CORE_ADDR *jump_entry,
unsigned char *jjump_pad_insn,
ULONGEST *jjump_pad_insn_size,
CORE_ADDR *adjusted_insn_addr,
! CORE_ADDR *adjusted_insn_addr_end)
{
unsigned char buf[0x100];
int i, offset;
--- 1350,1362 ----
CORE_ADDR lockaddr,
ULONGEST orig_size,
CORE_ADDR *jump_entry,
+ CORE_ADDR *trampoline,
+ ULONGEST *trampoline_size,
unsigned char *jjump_pad_insn,
ULONGEST *jjump_pad_insn_size,
CORE_ADDR *adjusted_insn_addr,
! CORE_ADDR *adjusted_insn_addr_end,
! char *err)
{
unsigned char buf[0x100];
int i, offset;
*************** i386_install_fast_tracepoint_jump_pad (C
*** 1455,1461 ****
buf[i++] = 0x0f; /* pop %fs */
buf[i++] = 0xa1;
buf[i++] = 0x07; /* pop %es */
! buf[i++] = 0x1f; /* pop %de */
buf[i++] = 0x9d; /* popf */
buf[i++] = 0x83; /* add $0x4,%esp (pop of tpaddr aka $pc) */
buf[i++] = 0xc4;
--- 1462,1468 ----
buf[i++] = 0x0f; /* pop %fs */
buf[i++] = 0xa1;
buf[i++] = 0x07; /* pop %es */
! buf[i++] = 0x1f; /* pop %ds */
buf[i++] = 0x9d; /* popf */
buf[i++] = 0x83; /* add $0x4,%esp (pop of tpaddr aka $pc) */
buf[i++] = 0xc4;
*************** i386_install_fast_tracepoint_jump_pad (C
*** 1479,1489 ****
is always done last (by our caller actually), so that we can
install fast tracepoints with threads running. This relies on
the agent's atomic write support. */
! offset = *jump_entry - (tpaddr + sizeof (jump_insn));
! memcpy (buf, jump_insn, sizeof (jump_insn));
! memcpy (buf + 1, &offset, 4);
! memcpy (jjump_pad_insn, buf, sizeof (jump_insn));
! *jjump_pad_insn_size = sizeof (jump_insn);
/* Return the end address of our pad. */
*jump_entry = buildaddr;
--- 1486,1525 ----
is always done last (by our caller actually), so that we can
install fast tracepoints with threads running. This relies on
the agent's atomic write support. */
! if (orig_size == 4)
! {
! /* Create a trampoline. */
! *trampoline_size = sizeof (jump_insn);
! if (!claim_trampoline_space (*trampoline_size, trampoline))
! {
! /* No trampoline space available. */
! strcpy (err,
! "E.Cannot allocate trampoline space needed for fast "
! "tracepoints on 4-byte instructions.");
! return 1;
! }
!
! offset = *jump_entry - (*trampoline + sizeof (jump_insn));
! memcpy (buf, jump_insn, sizeof (jump_insn));
! memcpy (buf + 1, &offset, 4);
! write_inferior_memory (*trampoline, buf, sizeof (jump_insn));
!
! /* Use a 16-bit relative jump instruction to jump to the trampoline. */
! offset = (*trampoline - (tpaddr + sizeof (small_jump_insn))) & 0xffff;
! memcpy (buf, small_jump_insn, sizeof (small_jump_insn));
! memcpy (buf + 2, &offset, 2);
! memcpy (jjump_pad_insn, buf, sizeof (small_jump_insn));
! *jjump_pad_insn_size = sizeof (small_jump_insn);
! }
! else
! {
! /* Else use a 32-bit relative jump instruction. */
! offset = *jump_entry - (tpaddr + sizeof (jump_insn));
! memcpy (buf, jump_insn, sizeof (jump_insn));
! memcpy (buf + 1, &offset, 4);
! memcpy (jjump_pad_insn, buf, sizeof (jump_insn));
! *jjump_pad_insn_size = sizeof (jump_insn);
! }
/* Return the end address of our pad. */
*jump_entry = buildaddr;
*************** x86_install_fast_tracepoint_jump_pad (CO
*** 1497,1525 ****
CORE_ADDR lockaddr,
ULONGEST orig_size,
CORE_ADDR *jump_entry,
unsigned char *jjump_pad_insn,
ULONGEST *jjump_pad_insn_size,
CORE_ADDR *adjusted_insn_addr,
! CORE_ADDR *adjusted_insn_addr_end)
{
#ifdef __x86_64__
if (register_size (0) == 8)
return amd64_install_fast_tracepoint_jump_pad (tpoint, tpaddr,
collector, lockaddr,
orig_size, jump_entry,
jjump_pad_insn,
jjump_pad_insn_size,
adjusted_insn_addr,
! adjusted_insn_addr_end);
#endif
return i386_install_fast_tracepoint_jump_pad (tpoint, tpaddr,
collector, lockaddr,
orig_size, jump_entry,
jjump_pad_insn,
jjump_pad_insn_size,
adjusted_insn_addr,
! adjusted_insn_addr_end);
}
static void
--- 1533,1610 ----
CORE_ADDR lockaddr,
ULONGEST orig_size,
CORE_ADDR *jump_entry,
+ CORE_ADDR *trampoline,
+ ULONGEST *trampoline_size,
unsigned char *jjump_pad_insn,
ULONGEST *jjump_pad_insn_size,
CORE_ADDR *adjusted_insn_addr,
! CORE_ADDR *adjusted_insn_addr_end,
! char *err)
{
#ifdef __x86_64__
if (register_size (0) == 8)
return amd64_install_fast_tracepoint_jump_pad (tpoint, tpaddr,
collector, lockaddr,
orig_size, jump_entry,
+ trampoline, trampoline_size,
jjump_pad_insn,
jjump_pad_insn_size,
adjusted_insn_addr,
! adjusted_insn_addr_end,
! err);
#endif
return i386_install_fast_tracepoint_jump_pad (tpoint, tpaddr,
collector, lockaddr,
orig_size, jump_entry,
+ trampoline, trampoline_size,
jjump_pad_insn,
jjump_pad_insn_size,
adjusted_insn_addr,
! adjusted_insn_addr_end,
! err);
! }
!
! /* Return the minimum instruction length for fast tracepoints on x86/x86-64
! architectures. */
!
! static int
! x86_get_min_fast_tracepoint_insn_len (void)
! {
! static int warned_about_fast_tracepoints = 0;
!
! #ifdef __x86_64__
! /* On x86-64, 5-byte jump instructions with a 4-byte offset are always
! used for fast tracepoints. */
! if (register_size (0) == 8)
! return 5;
! #endif
!
! if (in_process_agent_loaded ())
! {
! char mybuf[100];
!
! /* On x86, if trampolines are available, then 4-byte jump instructions
! with a 2-byte offset may be used, otherwise 5-byte jump instructions
! with a 4-byte offset are used instead. */
! if (have_fast_tracepoint_trampoline_buffer (mybuf))
! return 4;
! else
! {
! if (!warned_about_fast_tracepoints)
! {
! warning ("4-byte fast tracepoints not available; %s\n", mybuf);
! warned_about_fast_tracepoints = 1;
! }
! return 5;
! }
! }
! else
! {
! /* Indicate that the minimum length is currently unknown since the IPA
! has not loaded yet. */
! return 0;
! }
}
static void
*************** struct linux_target_ops the_low_target =
*** 2873,2877 ****
x86_supports_tracepoints,
x86_get_thread_area,
x86_install_fast_tracepoint_jump_pad,
! x86_emit_ops
};
--- 2958,2963 ----
x86_supports_tracepoints,
x86_get_thread_area,
x86_install_fast_tracepoint_jump_pad,
! x86_emit_ops,
! x86_get_min_fast_tracepoint_insn_len,
};
Index: gdbserver/server.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.h,v
retrieving revision 1.87
diff -p -r1.87 server.h
*** gdbserver/server.h 7 Oct 2011 12:06:48 -0000 1.87
--- gdbserver/server.h 29 Oct 2011 00:37:57 -0000
*************** void supply_fast_tracepoint_registers (s
*** 494,501 ****
--- 494,506 ----
void supply_static_tracepoint_registers (struct regcache *regcache,
const unsigned char *regs,
CORE_ADDR pc);
+ void set_trampoline_buffer_space (CORE_ADDR begin, CORE_ADDR end,
+ char *errmsg);
#else
void stop_tracing (void);
+
+ int claim_trampoline_space (ULONGEST used, CORE_ADDR *trampoline);
+ int have_fast_tracepoint_trampoline_buffer (char *msgbuf);
#endif
/* Bytecode compilation function vector. */
Index: gdbserver/target.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/target.h,v
retrieving revision 1.57
diff -p -r1.57 target.h
*** gdbserver/target.h 7 Oct 2011 12:06:48 -0000 1.57
--- gdbserver/target.h 29 Oct 2011 00:37:57 -0000
*************** struct target_ops
*** 359,378 ****
pad lock object. ORIG_SIZE is the size in bytes of the
instruction at TPADDR. JUMP_ENTRY points to the address of the
jump pad entry, and on return holds the address past the end of
! the created jump pad. JJUMP_PAD_INSN is a buffer containing a
! copy of the instruction at TPADDR. ADJUST_INSN_ADDR and
! ADJUST_INSN_ADDR_END are output parameters that return the
! address range where the instruction at TPADDR was relocated
! to. */
int (*install_fast_tracepoint_jump_pad) (CORE_ADDR tpoint, CORE_ADDR tpaddr,
CORE_ADDR collector,
CORE_ADDR lockaddr,
ULONGEST orig_size,
CORE_ADDR *jump_entry,
unsigned char *jjump_pad_insn,
ULONGEST *jjump_pad_insn_size,
CORE_ADDR *adjusted_insn_addr,
! CORE_ADDR *adjusted_insn_addr_end);
/* Return the bytecode operations vector for the current inferior.
Returns NULL if bytecode compilation is not supported. */
--- 359,384 ----
pad lock object. ORIG_SIZE is the size in bytes of the
instruction at TPADDR. JUMP_ENTRY points to the address of the
jump pad entry, and on return holds the address past the end of
! the created jump pad. If a trampoline is created by the function,
! then TRAMPOLINE and TRAMPOLINE_SIZE return the address and size of
! the trampoline, else they remain unchanged. JJUMP_PAD_INSN is a
! buffer containing a copy of the instruction at TPADDR.
! ADJUST_INSN_ADDR and ADJUST_INSN_ADDR_END are output parameters that
! return the address range where the instruction at TPADDR was relocated
! to. If an error occurs, the ERR may be used to pass on an error
! message. */
int (*install_fast_tracepoint_jump_pad) (CORE_ADDR tpoint, CORE_ADDR tpaddr,
CORE_ADDR collector,
CORE_ADDR lockaddr,
ULONGEST orig_size,
CORE_ADDR *jump_entry,
+ CORE_ADDR *trampoline,
+ ULONGEST *trampoline_size,
unsigned char *jjump_pad_insn,
ULONGEST *jjump_pad_insn_size,
CORE_ADDR *adjusted_insn_addr,
! CORE_ADDR *adjusted_insn_addr_end,
! char *err);
/* Return the bytecode operations vector for the current inferior.
Returns NULL if bytecode compilation is not supported. */
*************** struct target_ops
*** 380,385 ****
--- 386,395 ----
/* Returns true if the target supports disabling randomization. */
int (*supports_disable_randomization) (void);
+
+ /* Return the minimum length of an instruction that can be safely overwritten
+ for use as a fast tracepoint. */
+ int (*get_min_fast_tracepoint_insn_len) (void);
};
extern struct target_ops *the_target;
*************** void set_target_ops (struct target_ops *
*** 437,442 ****
--- 447,456 ----
#define target_supports_fast_tracepoints() \
(the_target->install_fast_tracepoint_jump_pad != NULL)
+ #define target_get_min_fast_tracepoint_insn_len() \
+ (the_target->get_min_fast_tracepoint_insn_len \
+ ? (*the_target->get_min_fast_tracepoint_insn_len) () : 0)
+
#define thread_stopped(thread) \
(*the_target->thread_stopped) (thread)
*************** void set_target_ops (struct target_ops *
*** 471,487 ****
#define install_fast_tracepoint_jump_pad(tpoint, tpaddr, \
collector, lockaddr, \
orig_size, \
! jump_entry, jjump_pad_insn, \
jjump_pad_insn_size, \
adjusted_insn_addr, \
! adjusted_insn_addr_end) \
(*the_target->install_fast_tracepoint_jump_pad) (tpoint, tpaddr, \
collector,lockaddr, \
orig_size, jump_entry, \
jjump_pad_insn, \
jjump_pad_insn_size, \
adjusted_insn_addr, \
! adjusted_insn_addr_end)
#define target_emit_ops() \
(the_target->emit_ops ? (*the_target->emit_ops) () : NULL)
--- 485,507 ----
#define install_fast_tracepoint_jump_pad(tpoint, tpaddr, \
collector, lockaddr, \
orig_size, \
! jump_entry, \
! trampoline, trampoline_size, \
! jjump_pad_insn, \
jjump_pad_insn_size, \
adjusted_insn_addr, \
! adjusted_insn_addr_end, \
! err) \
(*the_target->install_fast_tracepoint_jump_pad) (tpoint, tpaddr, \
collector,lockaddr, \
orig_size, jump_entry, \
+ trampoline, \
+ trampoline_size, \
jjump_pad_insn, \
jjump_pad_insn_size, \
adjusted_insn_addr, \
! adjusted_insn_addr_end, \
! err)
#define target_emit_ops() \
(the_target->emit_ops ? (*the_target->emit_ops) () : NULL)
Index: gdbserver/tracepoint.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/tracepoint.c,v
retrieving revision 1.27
diff -p -r1.27 tracepoint.c
*** gdbserver/tracepoint.c 15 Sep 2011 22:54:13 -0000 1.27
--- gdbserver/tracepoint.c 29 Oct 2011 00:37:57 -0000
*************** trace_vdebug (const char *fmt, ...)
*** 110,115 ****
--- 110,118 ----
# define gdb_tp_heap_buffer gdb_agent_gdb_tp_heap_buffer
# define gdb_jump_pad_buffer gdb_agent_gdb_jump_pad_buffer
# define gdb_jump_pad_buffer_end gdb_agent_gdb_jump_pad_buffer_end
+ # define gdb_trampoline_buffer gdb_agent_gdb_trampoline_buffer
+ # define gdb_trampoline_buffer_end gdb_agent_gdb_trampoline_buffer_end
+ # define gdb_trampoline_buffer_error gdb_agent_gdb_trampoline_buffer_error
# define collecting gdb_agent_collecting
# define gdb_collect gdb_agent_gdb_collect
# define stop_tracing gdb_agent_stop_tracing
*************** struct ipa_sym_addresses
*** 148,153 ****
--- 151,159 ----
CORE_ADDR addr_gdb_tp_heap_buffer;
CORE_ADDR addr_gdb_jump_pad_buffer;
CORE_ADDR addr_gdb_jump_pad_buffer_end;
+ CORE_ADDR addr_gdb_trampoline_buffer;
+ CORE_ADDR addr_gdb_trampoline_buffer_end;
+ CORE_ADDR addr_gdb_trampoline_buffer_error;
CORE_ADDR addr_collecting;
CORE_ADDR addr_gdb_collect;
CORE_ADDR addr_stop_tracing;
*************** static struct
*** 192,197 ****
--- 198,206 ----
IPA_SYM(gdb_tp_heap_buffer),
IPA_SYM(gdb_jump_pad_buffer),
IPA_SYM(gdb_jump_pad_buffer_end),
+ IPA_SYM(gdb_trampoline_buffer),
+ IPA_SYM(gdb_trampoline_buffer_end),
+ IPA_SYM(gdb_trampoline_buffer_error),
IPA_SYM(collecting),
IPA_SYM(gdb_collect),
IPA_SYM(stop_tracing),
*************** struct tracepoint
*** 658,663 ****
--- 667,678 ----
CORE_ADDR jump_pad;
CORE_ADDR jump_pad_end;
+ /* The address range of the piece of the trampoline buffer that was
+ assigned to this fast tracepoint. (_end is actually one byte
+ past the end). */
+ CORE_ADDR trampoline;
+ CORE_ADDR trampoline_end;
+
/* The list of actions to take while in a stepping loop. These
fields are only valid for patch-based tracepoints. */
int num_step_actions;
*************** claim_jump_space (ULONGEST used)
*** 2654,2659 ****
--- 2669,2746 ----
gdb_jump_pad_head += used;
}
+ static CORE_ADDR trampoline_buffer_head = 0;
+ static CORE_ADDR trampoline_buffer_tail;
+
+ /* Reserve USED bytes from the trampoline buffer and return the
+ address of the start of the reserved space in TRAMPOLINE. Returns
+ non-zero if the space is successfully claimed. */
+
+ int
+ claim_trampoline_space (ULONGEST used, CORE_ADDR *trampoline)
+ {
+ if (!trampoline_buffer_head)
+ {
+ if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer,
+ &trampoline_buffer_tail))
+ {
+ fatal ("error extracting trampoline_buffer");
+ return 0;
+ }
+
+ if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_end,
+ &trampoline_buffer_head))
+ {
+ fatal ("error extracting trampoline_buffer_end");
+ return 0;
+ }
+ }
+
+ /* Start claiming space from the top of the trampoline space. If
+ the space is located at the bottom of the virtual address space,
+ this reduces the possibility that corruption will occur if a null
+ pointer is used to write to memory. */
+ if (trampoline_buffer_head - trampoline_buffer_tail < used)
+ {
+ trace_debug ("claim_trampoline_space failed to reserve %s bytes",
+ pulongest (used));
+ return 0;
+ }
+
+ trampoline_buffer_head -= used;
+
+ trace_debug ("claim_trampoline_space reserves %s bytes at %s",
+ pulongest (used), paddress (trampoline_buffer_head));
+
+ *trampoline = trampoline_buffer_head;
+ return 1;
+ }
+
+ /* Returns non-zero if there is space allocated for use in trampolines
+ for fast tracepoints. */
+
+ int
+ have_fast_tracepoint_trampoline_buffer (char *buf)
+ {
+ CORE_ADDR trampoline_end, errbuf;
+
+ if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_end,
+ &trampoline_end))
+ fatal ("error extracting trampoline_buffer_end");
+
+ if (buf)
+ {
+ buf[0] = '\0';
+ if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_error,
+ &errbuf))
+ fatal ("error extracting errbuf");
+
+ read_inferior_memory (errbuf, (unsigned char *) buf, 100);
+ }
+
+ return trampoline_end != 0;
+ }
+
/* Sort tracepoints by PC, using a bubble sort. */
static void
*************** cmd_qtstart (char *packet)
*** 2818,2835 ****
fjump_size);
tpoint->jump_pad = prev_ftpoint->jump_pad;
tpoint->jump_pad_end = prev_ftpoint->jump_pad_end;
tpoint->adjusted_insn_addr = prev_ftpoint->adjusted_insn_addr;
tpoint->adjusted_insn_addr_end
= prev_ftpoint->adjusted_insn_addr_end;
}
else
{
! CORE_ADDR jentry;
int err = 0;
prev_ftpoint = NULL;
jentry = jump_entry = get_jump_space_head ();
/* Install the jump pad. */
err = install_fast_tracepoint_jump_pad
--- 2905,2934 ----
fjump_size);
tpoint->jump_pad = prev_ftpoint->jump_pad;
tpoint->jump_pad_end = prev_ftpoint->jump_pad_end;
+ tpoint->trampoline = prev_ftpoint->trampoline;
+ tpoint->trampoline_end = prev_ftpoint->trampoline_end;
tpoint->adjusted_insn_addr = prev_ftpoint->adjusted_insn_addr;
tpoint->adjusted_insn_addr_end
= prev_ftpoint->adjusted_insn_addr_end;
}
else
{
! CORE_ADDR jentry, trampoline;
! ULONGEST trampoline_size;
int err = 0;
+ if (tpoint->orig_size < target_get_min_fast_tracepoint_insn_len ())
+ {
+ trace_debug ("Requested a fast tracepoint on an instruction "
+ "that is of less than the minimum length.");
+ break;
+ }
+
prev_ftpoint = NULL;
jentry = jump_entry = get_jump_space_head ();
+ trampoline = 0;
+ trampoline_size = 0;
/* Install the jump pad. */
err = install_fast_tracepoint_jump_pad
*************** cmd_qtstart (char *packet)
*** 2839,2847 ****
ipa_sym_addrs.addr_collecting,
tpoint->orig_size,
&jentry,
fjump, &fjump_size,
&tpoint->adjusted_insn_addr,
! &tpoint->adjusted_insn_addr_end);
/* Wire it in. */
if (!err)
--- 2938,2948 ----
ipa_sym_addrs.addr_collecting,
tpoint->orig_size,
&jentry,
+ &trampoline, &trampoline_size,
fjump, &fjump_size,
&tpoint->adjusted_insn_addr,
! &tpoint->adjusted_insn_addr_end,
! packet);
/* Wire it in. */
if (!err)
*************** cmd_qtstart (char *packet)
*** 2852,2857 ****
--- 2953,2960 ----
{
tpoint->jump_pad = jump_entry;
tpoint->jump_pad_end = jentry;
+ tpoint->trampoline = trampoline;
+ tpoint->trampoline_end = trampoline + trampoline_size;
/* Pad to 8-byte alignment. */
jentry = ((jentry + 7) & ~0x7);
*************** cmd_qtstmat (char *packet)
*** 3435,3440 ****
--- 3538,3552 ----
run_inferior_command (packet);
}
+ /* Return the minimum instruction size needed for fast tracepoints as a
+ hexadecimal number. */
+
+ static void
+ cmd_qtminftpilen (char *packet)
+ {
+ sprintf (packet, "%x", target_get_min_fast_tracepoint_insn_len ());
+ }
+
/* Respond to qTBuffer packet with a block of raw data from the trace
buffer. GDB may ask for a lot, but we are allowed to reply with
only as much as will fit within packet limits or whatever. */
*************** handle_tracepoint_query (char *packet)
*** 3631,3636 ****
--- 3743,3753 ----
cmd_qtstmat (packet);
return 1;
}
+ else if (strcmp ("qTMinFTPILen", packet) == 0)
+ {
+ cmd_qtminftpilen (packet);
+ return 1;
+ }
return 0;
}
*************** fast_tracepoint_from_jump_pad_address (C
*** 5180,5185 ****
--- 5297,5319 ----
return NULL;
}
+ /* Return the first fast tracepoint whose trampoline contains PC. */
+
+ static struct tracepoint *
+ fast_tracepoint_from_trampoline_address (CORE_ADDR pc)
+ {
+ struct tracepoint *tpoint;
+
+ for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
+ {
+ if (tpoint->type == fast_tracepoint
+ && tpoint->trampoline <= pc && pc < tpoint->trampoline_end)
+ return tpoint;
+ }
+
+ return NULL;
+ }
+
/* Return GDBserver's tracepoint that matches the IP Agent's
tracepoint object that lives at IPA_TPOINT_OBJ in the IP Agent's
address space. */
*************** fast_tracepoint_collecting (CORE_ADDR th
*** 5242,5247 ****
--- 5376,5383 ----
{
CORE_ADDR ipa_collecting;
CORE_ADDR ipa_gdb_jump_pad_buffer, ipa_gdb_jump_pad_buffer_end;
+ CORE_ADDR ipa_gdb_trampoline_buffer;
+ CORE_ADDR ipa_gdb_trampoline_buffer_end;
struct tracepoint *tpoint;
int needs_breakpoint;
*************** fast_tracepoint_collecting (CORE_ADDR th
*** 5280,5285 ****
--- 5416,5428 ----
&ipa_gdb_jump_pad_buffer_end))
fatal ("error extracting `gdb_jump_pad_buffer_end'");
+ if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer,
+ &ipa_gdb_trampoline_buffer))
+ fatal ("error extracting `gdb_trampoline_buffer'");
+ if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_end,
+ &ipa_gdb_trampoline_buffer_end))
+ fatal ("error extracting `gdb_trampoline_buffer_end'");
+
if (ipa_gdb_jump_pad_buffer <= stop_pc
&& stop_pc < ipa_gdb_jump_pad_buffer_end)
{
*************** fast_tracepoint_collecting (CORE_ADDR th
*** 5308,5313 ****
--- 5451,5480 ----
&& stop_pc < tpoint->adjusted_insn_addr)
needs_breakpoint = 1;
}
+ else if (ipa_gdb_trampoline_buffer <= stop_pc
+ && stop_pc < ipa_gdb_trampoline_buffer_end)
+ {
+ /* We can tell which tracepoint(s) the thread is collecting by
+ matching the trampoline address back to the tracepoint. */
+ tpoint = fast_tracepoint_from_trampoline_address (stop_pc);
+ if (tpoint == NULL)
+ {
+ warning ("in trampoline, but no matching tpoint?");
+ return 0;
+ }
+ else
+ {
+ trace_debug ("in trampoline of tpoint (%d, %s); trampoline(%s, %s)",
+ tpoint->number, paddress (tpoint->address),
+ paddress (tpoint->trampoline),
+ paddress (tpoint->trampoline_end));
+ }
+
+ /* Have not reached jump pad yet, but treat the trampoline as a
+ part of the jump pad that is before the adjusted original
+ instruction. */
+ needs_breakpoint = 1;
+ }
else
{
collecting_t ipa_collecting_obj;
*************** gdb_ust_init (void)
*** 7621,7626 ****
--- 7788,7809 ----
IP_AGENT_EXPORT char *gdb_tp_heap_buffer;
IP_AGENT_EXPORT char *gdb_jump_pad_buffer;
IP_AGENT_EXPORT char *gdb_jump_pad_buffer_end;
+ IP_AGENT_EXPORT char *gdb_trampoline_buffer;
+ IP_AGENT_EXPORT char *gdb_trampoline_buffer_end;
+ IP_AGENT_EXPORT char *gdb_trampoline_buffer_error;
+
+ /* Record the result of getting buffer space for fast tracepoint
+ trampolines. Any error message is copied, since caller may not be
+ using persistent storage. */
+
+ void
+ set_trampoline_buffer_space (CORE_ADDR begin, CORE_ADDR end, char *errmsg)
+ {
+ gdb_trampoline_buffer = (char *) (uintptr_t) begin;
+ gdb_trampoline_buffer_end = (char *) (uintptr_t) end;
+ if (errmsg)
+ strncpy (gdb_trampoline_buffer_error, errmsg, 99);
+ }
static void __attribute__ ((constructor))
initialize_tracepoint_ftlib (void)
*************** initialize_tracepoint: mprotect(%p, %d,
*** 7682,7687 ****
--- 7865,7878 ----
gdb_jump_pad_buffer, pagesize * 20, strerror (errno));
}
+ gdb_trampoline_buffer = gdb_trampoline_buffer_end = 0;
+
+ /* It's not a fatal error for something to go wrong with trampoline
+ buffer setup, but it can be mysterious, so create a channel to
+ report back on what went wrong, using a fixed size since we may
+ not be able to allocate space later. */
+ gdb_trampoline_buffer_error = xmalloc (100);
+
initialize_low_tracepoint ();
#endif
}
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.884
diff -p -r1.884 gdb.texinfo
*** doc/gdb.texinfo 28 Oct 2011 14:48:59 -0000 1.884
--- doc/gdb.texinfo 29 Oct 2011 00:37:58 -0000
*************** encoded). @value{GDBN} will continue to
*** 34774,34779 ****
--- 34774,34781 ----
@itemx qTfP
@itemx qTfV
@itemx QTFrame
+ @itemx qTMinFTPILen
+
@xref{Tracepoint Packets}.
@item qThreadExtraInfo,@var{thread-id}
*************** numbers.
*** 35297,35302 ****
--- 35299,35323 ----
Like @samp{QTFrame:range:@var{start}:@var{end}}, but select the first
frame @emph{outside} the given range of addresses (exclusive).
+ @item qTMinFTPILen
+ This packet requests the minimum length of instruction at which a fast
+ tracepoint may be placed.
+
+ Replies:
+
+ @table @samp
+ @item 0
+ The minimum instruction length is currently unknown.
+ @item @var{length}
+ The minimum instruction length is @var{length}, where @var{length} is greater
+ or equal to 1. @var{length} is a hexadecimal number. A reply of 1 means
+ that a fast tracepoint may be placed on any instruction regardless of size.
+ @item E
+ An error has occurred.
+ @item
+ An empty reply indicates that the request is not supported by the stub.
+ @end table
+
@item QTStart
Begin the tracepoint experiment. Begin collecting data from
tracepoint hits in the trace frame buffer. This packet supports the
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH] Shorter fast tracepoints
2011-10-29 1:55 [PATCH] Shorter fast tracepoints Stan Shebs
@ 2011-10-29 10:09 ` Eli Zaretskii
0 siblings, 0 replies; 2+ messages in thread
From: Eli Zaretskii @ 2011-10-29 10:09 UTC (permalink / raw)
To: Stan Shebs; +Cc: gdb-patches
> Date: Fri, 28 Oct 2011 18:30:36 -0700
> From: Stan Shebs <stanshebs@earthlink.net>
>
> The ugly part is that the 2-byte address is in the low 64K of memory,
> which may or may not be available - GDB has to check
> /proc/sys/vm/mmap_min_addr. Fortunately users can tweak it manually
> (via sysctl) if the preset is to block out all of low memory.
>
> This brings up two troublesome points about this patch as it stands.
> First, documentation. As it stands, the patch to the manual says
> nothing about fooling with the kernel's mmap_min_addr.
In fact, it says nothing at all about the potential problems you
described in this mail that this patch and the packet you introduced
attempts to solve. Readers might wonder why the packet is even
needed.
> Should it? It's very system-specific, and the user would only need
> to do anything special if mmap_min_addr were set to 64K or higher,
> otherwise everything quietly works as desired.
If users of tracepoints need to know about this detail, then yes, the
manual should mention it. We can always qualify any specific info by
its being system-specific, but having the information there for
specific systems, especially popular ones, is a Good Thing.
I have no other comments for the documentation parts of your patch,
they are fine with me. Thanks.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2011-10-29 9:21 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-29 1:55 [PATCH] Shorter fast tracepoints Stan Shebs
2011-10-29 10:09 ` Eli Zaretskii
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox