Add return address collection for tracepoints.

* tracepoint.c (encode_actions_1): Add case for $_ret.
	(validate_actionline): Check for $_ret.
	(trace_dump_actions): Ditto.
	* ax-gdb.h (gen_trace_for_return_address): Declare.
	* ax-gdb.c: Include arch-utils.h.
	(gen_trace_for_return_address): New function.
	(agent_command): Add return address special case.
	* amd64-tdep.c: Include ax.h and ax-gdb.h.
	(amd64_gen_return_address): New function.
	(amd64_init_abi): Call it.
	* i386-tdep.c: Include ax.h and ax-gdb.h.
	(i386_gen_return_address): New function.
	(i386_init_abi): Call it.
	* arch-utils.h (default_gen_return_address): Declare.
	* arch-utils.c (default_gen_return_address): New function.
	* gdbarch.sh (gen_return_address): New method.
	* gdbarch.h, gdbarch.c: Regenerate.

	* gdb.texinfo (Tracepoint Action Lists): Document $_ret.

	* gdb.trace/collection.exp: Test collection of $_ret.
This commit is contained in:
Stan Shebs 2011-09-27 13:09:37 +00:00
parent 21eb9156ec
commit 6710bf39b7
15 changed files with 250 additions and 4 deletions

View File

@ -1,3 +1,24 @@
2011-09-27 Stan Shebs <stan@codesourcery.com>
Add return address collection for tracepoints.
* tracepoint.c (encode_actions_1): Add case for $_ret.
(validate_actionline): Check for $_ret.
(trace_dump_actions): Ditto.
* ax-gdb.h (gen_trace_for_return_address): Declare.
* ax-gdb.c: Include arch-utils.h.
(gen_trace_for_return_address): New function.
(agent_command): Add return address special case.
* amd64-tdep.c: Include ax.h and ax-gdb.h.
(amd64_gen_return_address): New function.
(amd64_init_abi): Call it.
* i386-tdep.c: Include ax.h and ax-gdb.h.
(i386_gen_return_address): New function.
(i386_init_abi): Call it.
* arch-utils.h (default_gen_return_address): Declare.
* arch-utils.c (default_gen_return_address): New function.
* gdbarch.sh (gen_return_address): New method.
* gdbarch.h, gdbarch.c: Regenerate.
2011-09-23 Joseph Myers <joseph@codesourcery.com>
PR gdb/13079

View File

@ -45,6 +45,9 @@
#include "features/i386/amd64.c"
#include "features/i386/amd64-avx.c"
#include "ax.h"
#include "ax-gdb.h"
/* Note that the AMD64 architecture was previously known as x86-64.
The latter is (forever) engraved into the canonical system name as
returned by config.guess, and used as the name for the AMD64 port
@ -2165,6 +2168,22 @@ static const struct frame_unwind amd64_frame_unwind =
default_frame_sniffer
};
/* Generate a bytecode expression to get the value of the saved PC. */
static void
amd64_gen_return_address (struct gdbarch *gdbarch,
struct agent_expr *ax, struct axs_value *value,
CORE_ADDR scope)
{
/* The following sequence assumes the traditional use of the base
register. */
ax_reg (ax, AMD64_RBP_REGNUM);
ax_const_l (ax, 8);
ax_simple (ax, aop_add);
value->type = register_type (gdbarch, AMD64_RIP_REGNUM);
value->kind = axs_lvalue_memory;
}
/* Signal trampolines. */
@ -2669,6 +2688,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_get_longjmp_target (gdbarch, amd64_get_longjmp_target);
set_gdbarch_relocate_instruction (gdbarch, amd64_relocate_instruction);
set_gdbarch_gen_return_address (gdbarch, amd64_gen_return_address);
}
/* Provide a prototype to silence -Wmissing-prototypes. */

View File

@ -786,6 +786,14 @@ default_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
gdbarch_breakpoint_from_pc (gdbarch, pcptr, kindptr);
}
void
default_gen_return_address (struct gdbarch *gdbarch,
struct agent_expr *ax, struct axs_value *value,
CORE_ADDR scope)
{
error (_("This architecture has no method to collect a return address."));
}
/* */
/* -Wmissing-prototypes */

View File

@ -164,6 +164,11 @@ extern int default_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
extern void default_remote_breakpoint_from_pc (struct gdbarch *,
CORE_ADDR *pcptr, int *kindptr);
extern void default_gen_return_address (struct gdbarch *gdbarch,
struct agent_expr *ax,
struct axs_value *value,
CORE_ADDR scope);
extern const char *default_auto_charset (void);
extern const char *default_auto_wide_charset (void);

View File

@ -40,6 +40,7 @@
#include "breakpoint.h"
#include "tracepoint.h"
#include "cp-support.h"
#include "arch-utils.h"
/* To make sense of this file, you should read doc/agentexpr.texi.
Then look at the types and enums in ax-gdb.h. For the code itself,
@ -2444,6 +2445,32 @@ gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
return ax;
}
struct agent_expr *
gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch)
{
struct cleanup *old_chain = 0;
struct agent_expr *ax = new_agent_expr (gdbarch, scope);
struct axs_value value;
old_chain = make_cleanup_free_agent_expr (ax);
trace_kludge = 1;
gdbarch_gen_return_address (gdbarch, ax, &value, scope);
/* Make sure we record the final object, and get rid of it. */
gen_traced_pop (gdbarch, ax, &value);
/* Oh, and terminate. */
ax_simple (ax, aop_end);
/* We have successfully built the agent expr, so cancel the cleanup
request. If we add more cleanups that we always want done, this
will have to get more complicated. */
discard_cleanups (old_chain);
return ax;
}
static void
agent_command (char *exp, int from_tty)
{
@ -2462,10 +2489,22 @@ agent_command (char *exp, int from_tty)
if (exp == 0)
error_no_arg (_("expression to translate"));
expr = parse_expression (exp);
old_chain = make_cleanup (free_current_contents, &expr);
agent = gen_trace_for_expr (get_frame_pc (fi), expr);
make_cleanup_free_agent_expr (agent);
/* Recognize the return address collection directive specially. Note
that it is not really an expression of any sort. */
if (strcmp (exp, "$_ret") == 0)
{
agent = gen_trace_for_return_address (get_frame_pc (fi),
get_current_arch ());
old_chain = make_cleanup_free_agent_expr (agent);
}
else
{
expr = parse_expression (exp);
old_chain = make_cleanup (free_current_contents, &expr);
agent = gen_trace_for_expr (get_frame_pc (fi), expr);
make_cleanup_free_agent_expr (agent);
}
ax_reqs (agent);
ax_print (gdb_stdout, agent);

View File

@ -106,6 +106,9 @@ extern struct agent_expr *gen_trace_for_expr (CORE_ADDR, struct expression *);
extern struct agent_expr *gen_trace_for_var (CORE_ADDR, struct gdbarch *,
struct symbol *);
extern struct agent_expr *gen_trace_for_return_address (CORE_ADDR,
struct gdbarch *);
extern struct agent_expr *gen_eval_for_expr (CORE_ADDR, struct expression *);
extern int trace_kludge;

View File

@ -1,3 +1,7 @@
2011-09-27 Stan Shebs <stan@codesourcery.com>
* gdb.texinfo (Tracepoint Action Lists): Document $_ret.
2011-09-16 Hui Zhu <teawater@gmail.com>
* gdb.texinfo (Tracepoint Restrictions): Change *$esp@300

View File

@ -10284,6 +10284,10 @@ Collect all function arguments.
@item $locals
Collect all local variables.
@item $_ret
Collect the return address. This is helpful if you want to see more
of a backtrace.
@item $_sdata
@vindex $_sdata@r{, collect}
Collect static tracepoint marker specific data. Only available for

View File

@ -270,6 +270,7 @@ struct gdbarch
gdbarch_auto_wide_charset_ftype *auto_wide_charset;
const char * solib_symbols_extension;
int has_dos_based_file_system;
gdbarch_gen_return_address_ftype *gen_return_address;
};
@ -423,6 +424,7 @@ struct gdbarch startup_gdbarch =
default_auto_wide_charset, /* auto_wide_charset */
0, /* solib_symbols_extension */
0, /* has_dos_based_file_system */
default_gen_return_address, /* gen_return_address */
/* startup_gdbarch() */
};
@ -513,6 +515,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
gdbarch->fast_tracepoint_valid_at = default_fast_tracepoint_valid_at;
gdbarch->auto_charset = default_auto_charset;
gdbarch->auto_wide_charset = default_auto_wide_charset;
gdbarch->gen_return_address = default_gen_return_address;
/* gdbarch_alloc() */
return gdbarch;
@ -707,6 +710,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of auto_charset, invalid_p == 0 */
/* Skip verify of auto_wide_charset, invalid_p == 0 */
/* Skip verify of has_dos_based_file_system, invalid_p == 0 */
/* Skip verify of gen_return_address, invalid_p == 0 */
buf = ui_file_xstrdup (log, &length);
make_cleanup (xfree, buf);
if (length > 0)
@ -946,6 +950,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
fprintf_unfiltered (file,
"gdbarch_dump: gcore_bfd_target = %s\n",
gdbarch->gcore_bfd_target);
fprintf_unfiltered (file,
"gdbarch_dump: gen_return_address = <%s>\n",
host_address_to_string (gdbarch->gen_return_address));
fprintf_unfiltered (file,
"gdbarch_dump: gdbarch_get_longjmp_target_p() = %d\n",
gdbarch_get_longjmp_target_p (gdbarch));
@ -3863,6 +3870,23 @@ set_gdbarch_has_dos_based_file_system (struct gdbarch *gdbarch,
gdbarch->has_dos_based_file_system = has_dos_based_file_system;
}
void
gdbarch_gen_return_address (struct gdbarch *gdbarch, struct agent_expr *ax, struct axs_value *value, CORE_ADDR scope)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->gen_return_address != NULL);
if (gdbarch_debug >= 2)
fprintf_unfiltered (gdb_stdlog, "gdbarch_gen_return_address called\n");
gdbarch->gen_return_address (gdbarch, ax, value, scope);
}
void
set_gdbarch_gen_return_address (struct gdbarch *gdbarch,
gdbarch_gen_return_address_ftype gen_return_address)
{
gdbarch->gen_return_address = gen_return_address;
}
/* Keep a registry of per-architecture data-pointers required by GDB
modules. */

View File

@ -54,6 +54,7 @@ struct displaced_step_closure;
struct core_regset_section;
struct syscall;
struct agent_expr;
struct axs_value;
/* The architecture associated with the connection to the target.
@ -1014,6 +1015,16 @@ extern void set_gdbarch_solib_symbols_extension (struct gdbarch *gdbarch, const
extern int gdbarch_has_dos_based_file_system (struct gdbarch *gdbarch);
extern void set_gdbarch_has_dos_based_file_system (struct gdbarch *gdbarch, int has_dos_based_file_system);
/* Generate bytecodes to collect the return address in a frame.
Since the bytecodes run on the target, possibly with GDB not even
connected, the full unwinding machinery is not available, and
typically this function will issue bytecodes for one or more likely
places that the return address may be found. */
typedef void (gdbarch_gen_return_address_ftype) (struct gdbarch *gdbarch, struct agent_expr *ax, struct axs_value *value, CORE_ADDR scope);
extern void gdbarch_gen_return_address (struct gdbarch *gdbarch, struct agent_expr *ax, struct axs_value *value, CORE_ADDR scope);
extern void set_gdbarch_gen_return_address (struct gdbarch *gdbarch, gdbarch_gen_return_address_ftype *gen_return_address);
/* Definition for an unknown syscall, used basically in error-cases. */
#define UNKNOWN_SYSCALL (-1)

View File

@ -820,6 +820,14 @@ v:const char *:solib_symbols_extension:::::::pstring (gdbarch->solib_symbols_ext
# is, absolute paths include a drive name, and the backslash is
# considered a directory separator.
v:int:has_dos_based_file_system:::0:0::0
# Generate bytecodes to collect the return address in a frame.
# Since the bytecodes run on the target, possibly with GDB not even
# connected, the full unwinding machinery is not available, and
# typically this function will issue bytecodes for one or more likely
# places that the return address may be found.
m:void:gen_return_address:struct agent_expr *ax, struct axs_value *value, CORE_ADDR scope:ax, value, scope::default_gen_return_address::0
EOF
}
@ -934,6 +942,7 @@ struct displaced_step_closure;
struct core_regset_section;
struct syscall;
struct agent_expr;
struct axs_value;
/* The architecture associated with the connection to the target.

View File

@ -60,6 +60,9 @@
#include "features/i386/i386-avx.c"
#include "features/i386/i386-mmx.c"
#include "ax.h"
#include "ax-gdb.h"
/* Register names. */
static const char *i386_register_names[] =
@ -2074,6 +2077,22 @@ static const struct frame_unwind i386_stack_tramp_frame_unwind =
i386_stack_tramp_frame_sniffer
};
/* Generate a bytecode expression to get the value of the saved PC. */
static void
i386_gen_return_address (struct gdbarch *gdbarch,
struct agent_expr *ax, struct axs_value *value,
CORE_ADDR scope)
{
/* The following sequence assumes the traditional use of the base
register. */
ax_reg (ax, I386_EBP_REGNUM);
ax_const_l (ax, 4);
ax_simple (ax, aop_add);
value->type = register_type (gdbarch, I386_EIP_REGNUM);
value->kind = axs_lvalue_memory;
}
/* Signal trampolines. */
@ -7410,6 +7429,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_relocate_instruction (gdbarch, i386_relocate_instruction);
set_gdbarch_gen_return_address (gdbarch, i386_gen_return_address);
/* Hook in ABI-specific overrides, if they have been registered. */
info.tdep_info = (void *) tdesc_data;
gdbarch_init_osabi (info, gdbarch);

View File

@ -1,3 +1,7 @@
2011-09-27 Stan Shebs <stan@codesourcery.com>
* gdb.trace/collection.exp: Test collection of $_ret.
2011-09-22 Andreas Tobler <andreast@fgznet.ch>
* lib/gdb.exp (gdb_compile): Set rpath and remove -ldl from the

View File

@ -588,6 +588,37 @@ proc gdb_collect_global_in_pieces_test { } {
"collect global in pieces: cease trace debugging"
}
proc gdb_collect_return_test { } {
prepare_for_trace_test
# We'll simply re-use the args_test_function for this test
gdb_test "trace args_test_func" \
"Tracepoint \[0-9\]+ at .*" \
"collect \$_ret: set tracepoint"
gdb_trace_setactions "collect \$_ret: define actions" \
"" \
"collect \$_ret" "^$"
# Begin the test.
run_trace_experiment \$_ret args_test_func
# Since we can't guarantee that $_ret will give us the caller,
# pass either way, but giving different messages.
gdb_test_multiple "backtrace" "" {
-re ".*#1 .* in main .*" {
pass "collect \$_ret: backtrace lists main"
}
-re ".*#1 .* in ?? .*" {
pass "collect \$_ret: backtrace not listing main"
}
}
gdb_test "tfind none" \
"#0 end .*" \
"collect \$_ret: cease trace debugging"
}
proc gdb_trace_collection_test {} {
global fpreg
global spreg
@ -696,6 +727,7 @@ proc gdb_trace_collection_test {} {
gdb_collect_expression_test globals_test_func \
"globalarr\[\(l6, l7\)\]" "7" "a\[\(b, c\)\]"
gdb_collect_return_test
}
clean_restart $executable

View File

@ -667,6 +667,7 @@ validate_actionline (char **line, struct breakpoint *b)
if (0 == strncasecmp ("reg", p + 1, 3)
|| 0 == strncasecmp ("arg", p + 1, 3)
|| 0 == strncasecmp ("loc", p + 1, 3)
|| 0 == strncasecmp ("_ret", p + 1, 4)
|| 0 == strncasecmp ("_sdata", p + 1, 6))
{
p = strchr (p, ',');
@ -1344,6 +1345,43 @@ encode_actions_1 (struct command_line *action,
'L');
action_exp = strchr (action_exp, ','); /* more? */
}
else if (0 == strncasecmp ("$_ret", action_exp, 5))
{
struct cleanup *old_chain1 = NULL;
aexpr = gen_trace_for_return_address (tloc->address,
t->gdbarch);
old_chain1 = make_cleanup_free_agent_expr (aexpr);
ax_reqs (aexpr);
report_agent_reqs_errors (aexpr);
discard_cleanups (old_chain1);
add_aexpr (collect, aexpr);
/* take care of the registers */
if (aexpr->reg_mask_len > 0)
{
int ndx1, ndx2;
for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
{
QUIT; /* allow user to bail out with ^C */
if (aexpr->reg_mask[ndx1] != 0)
{
/* assume chars have 8 bits */
for (ndx2 = 0; ndx2 < 8; ndx2++)
if (aexpr->reg_mask[ndx1] & (1 << ndx2))
/* it's used -- record it */
add_register (collect,
ndx1 * 8 + ndx2);
}
}
}
action_exp = strchr (action_exp, ','); /* more? */
}
else if (0 == strncasecmp ("$_sdata", action_exp, 7))
{
add_static_trace_data (collect);
@ -2555,6 +2593,8 @@ trace_dump_actions (struct command_line *action,
if (0 == strncasecmp (action_exp, "$reg", 4))
registers_info (NULL, from_tty);
else if (0 == strncasecmp (action_exp, "$_ret", 5))
;
else if (0 == strncasecmp (action_exp, "$loc", 4))
locals_info (NULL, from_tty);
else if (0 == strncasecmp (action_exp, "$arg", 4))