X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgdbserver%2Ftracepoint.c;h=5fb8a5134ba3d5fa46e4328fb7ea19426e90571e;hb=be6d4f74c77c6f521afc873d226480e001cb99c2;hp=f5f506a29833b11d9dec54dea63b5a4de8817a13;hpb=2fa291aca43cb851ba4e108cb64c7844a257df4f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c index f5f506a298..5fb8a5134b 100644 --- a/gdb/gdbserver/tracepoint.c +++ b/gdb/gdbserver/tracepoint.c @@ -1,5 +1,5 @@ /* Tracepoint code for remote server for GDB. - Copyright (C) 2009-2012 Free Software Foundation, Inc. + Copyright (C) 2009-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -17,17 +17,22 @@ along with this program. If not, see . */ #include "server.h" -#include "agent.h" +#include "tracepoint.h" +#include "gdbthread.h" +#include "rsp-low.h" #include #include #include -#include -#include -#if HAVE_STDINT_H -#include -#endif +#include +#include #include "ax.h" +#include "tdesc.h" + +#define IPA_SYM_STRUCT_NAME ipa_sym_addresses +#include "agent.h" + +#define DEFAULT_TRACE_BUFFER_SIZE 5242880 /* 5*1024*1024 */ /* This file is built for both GDBserver, and the in-process agent (IPA), a shared library that includes a tracing agent that is @@ -56,7 +61,9 @@ */ -static void trace_vdebug (const char *, ...) ATTR_FORMAT (printf, 1, 2); +#ifdef IN_PROCESS_AGENT + +static void trace_vdebug (const char *, ...) ATTRIBUTE_PRINTF (1, 2); static void trace_vdebug (const char *fmt, ...) @@ -76,73 +83,60 @@ trace_vdebug (const char *fmt, ...) trace_vdebug ((fmt), ##args); \ } while (0) -#define trace_debug(FMT, args...) \ - trace_debug_1 (1, FMT, ##args) - -#if defined(__GNUC__) -# define ATTR_USED __attribute__((used)) -# define ATTR_NOINLINE __attribute__((noinline)) -# define ATTR_CONSTRUCTOR __attribute__ ((constructor)) #else -# define ATTR_USED -# define ATTR_NOINLINE -# define ATTR_CONSTRUCTOR -#endif -/* Make sure the functions the IPA needs to export (symbols GDBserver - needs to query GDB about) are exported. */ +#define trace_debug_1(level, fmt, args...) \ + do { \ + if (level <= debug_threads) \ + { \ + debug_printf ((fmt), ##args); \ + debug_printf ("\n"); \ + } \ + } while (0) -#ifdef IN_PROCESS_AGENT -# if defined _WIN32 || defined __CYGWIN__ -# define IP_AGENT_EXPORT __declspec(dllexport) ATTR_USED -# else -# if __GNUC__ >= 4 -# define IP_AGENT_EXPORT \ - __attribute__ ((visibility("default"))) ATTR_USED -# else -# define IP_AGENT_EXPORT ATTR_USED -# endif -# endif -#else -# define IP_AGENT_EXPORT #endif +#define trace_debug(FMT, args...) \ + trace_debug_1 (1, FMT, ##args) + /* Prefix exported symbols, for good citizenship. All the symbols - that need exporting are defined in this module. */ + that need exporting are defined in this module. Note that all + these symbols must be tagged with IP_AGENT_EXPORT_*. */ #ifdef IN_PROCESS_AGENT -# 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 -# define flush_trace_buffer gdb_agent_flush_trace_buffer -# define about_to_request_buffer_space gdb_agent_about_to_request_buffer_space -# define trace_buffer_is_full gdb_agent_trace_buffer_is_full -# define stopping_tracepoint gdb_agent_stopping_tracepoint -# define expr_eval_result gdb_agent_expr_eval_result -# define error_tracepoint gdb_agent_error_tracepoint -# define tracepoints gdb_agent_tracepoints -# define tracing gdb_agent_tracing -# define trace_buffer_ctrl gdb_agent_trace_buffer_ctrl -# define trace_buffer_ctrl_curr gdb_agent_trace_buffer_ctrl_curr -# define trace_buffer_lo gdb_agent_trace_buffer_lo -# define trace_buffer_hi gdb_agent_trace_buffer_hi -# define traceframe_read_count gdb_agent_traceframe_read_count -# define traceframe_write_count gdb_agent_traceframe_write_count -# define traceframes_created gdb_agent_traceframes_created -# define trace_state_variables gdb_agent_trace_state_variables -# define get_raw_reg gdb_agent_get_raw_reg -# define get_trace_state_variable_value \ - gdb_agent_get_trace_state_variable_value -# define set_trace_state_variable_value \ - gdb_agent_set_trace_state_variable_value -# define ust_loaded gdb_agent_ust_loaded -# define helper_thread_id gdb_agent_helper_thread_id -# define cmd_buf gdb_agent_cmd_buf +# define gdb_tp_heap_buffer IPA_SYM_EXPORTED_NAME (gdb_tp_heap_buffer) +# define gdb_jump_pad_buffer IPA_SYM_EXPORTED_NAME (gdb_jump_pad_buffer) +# define gdb_jump_pad_buffer_end IPA_SYM_EXPORTED_NAME (gdb_jump_pad_buffer_end) +# define gdb_trampoline_buffer IPA_SYM_EXPORTED_NAME (gdb_trampoline_buffer) +# define gdb_trampoline_buffer_end IPA_SYM_EXPORTED_NAME (gdb_trampoline_buffer_end) +# define gdb_trampoline_buffer_error IPA_SYM_EXPORTED_NAME (gdb_trampoline_buffer_error) +# define collecting IPA_SYM_EXPORTED_NAME (collecting) +# define gdb_collect_ptr IPA_SYM_EXPORTED_NAME (gdb_collect_ptr) +# define stop_tracing IPA_SYM_EXPORTED_NAME (stop_tracing) +# define flush_trace_buffer IPA_SYM_EXPORTED_NAME (flush_trace_buffer) +# define about_to_request_buffer_space IPA_SYM_EXPORTED_NAME (about_to_request_buffer_space) +# define trace_buffer_is_full IPA_SYM_EXPORTED_NAME (trace_buffer_is_full) +# define stopping_tracepoint IPA_SYM_EXPORTED_NAME (stopping_tracepoint) +# define expr_eval_result IPA_SYM_EXPORTED_NAME (expr_eval_result) +# define error_tracepoint IPA_SYM_EXPORTED_NAME (error_tracepoint) +# define tracepoints IPA_SYM_EXPORTED_NAME (tracepoints) +# define tracing IPA_SYM_EXPORTED_NAME (tracing) +# define trace_buffer_ctrl IPA_SYM_EXPORTED_NAME (trace_buffer_ctrl) +# define trace_buffer_ctrl_curr IPA_SYM_EXPORTED_NAME (trace_buffer_ctrl_curr) +# define trace_buffer_lo IPA_SYM_EXPORTED_NAME (trace_buffer_lo) +# define trace_buffer_hi IPA_SYM_EXPORTED_NAME (trace_buffer_hi) +# define traceframe_read_count IPA_SYM_EXPORTED_NAME (traceframe_read_count) +# define traceframe_write_count IPA_SYM_EXPORTED_NAME (traceframe_write_count) +# define traceframes_created IPA_SYM_EXPORTED_NAME (traceframes_created) +# define trace_state_variables IPA_SYM_EXPORTED_NAME (trace_state_variables) +# define get_raw_reg_ptr IPA_SYM_EXPORTED_NAME (get_raw_reg_ptr) +# define get_trace_state_variable_value_ptr \ + IPA_SYM_EXPORTED_NAME (get_trace_state_variable_value_ptr) +# define set_trace_state_variable_value_ptr \ + IPA_SYM_EXPORTED_NAME (set_trace_state_variable_value_ptr) +# define ust_loaded IPA_SYM_EXPORTED_NAME (ust_loaded) +# define helper_thread_id IPA_SYM_EXPORTED_NAME (helper_thread_id) +# define cmd_buf IPA_SYM_EXPORTED_NAME (cmd_buf) +# define ipa_tdesc_idx IPA_SYM_EXPORTED_NAME (ipa_tdesc_idx) #endif #ifndef IN_PROCESS_AGENT @@ -158,7 +152,7 @@ struct ipa_sym_addresses 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_gdb_collect_ptr; CORE_ADDR addr_stop_tracing; CORE_ADDR addr_flush_trace_buffer; CORE_ADDR addr_about_to_request_buffer_space; @@ -176,17 +170,17 @@ struct ipa_sym_addresses CORE_ADDR addr_traceframe_write_count; CORE_ADDR addr_traceframes_created; CORE_ADDR addr_trace_state_variables; - CORE_ADDR addr_get_raw_reg; - CORE_ADDR addr_get_trace_state_variable_value; - CORE_ADDR addr_set_trace_state_variable_value; + CORE_ADDR addr_get_raw_reg_ptr; + CORE_ADDR addr_get_trace_state_variable_value_ptr; + CORE_ADDR addr_set_trace_state_variable_value_ptr; CORE_ADDR addr_ust_loaded; + CORE_ADDR addr_ipa_tdesc_idx; }; static struct { const char *name; int offset; - int required; } symbol_list[] = { IPA_SYM(gdb_tp_heap_buffer), IPA_SYM(gdb_jump_pad_buffer), @@ -195,7 +189,7 @@ static struct IPA_SYM(gdb_trampoline_buffer_end), IPA_SYM(gdb_trampoline_buffer_error), IPA_SYM(collecting), - IPA_SYM(gdb_collect), + IPA_SYM(gdb_collect_ptr), IPA_SYM(stop_tracing), IPA_SYM(flush_trace_buffer), IPA_SYM(about_to_request_buffer_space), @@ -213,45 +207,46 @@ static struct IPA_SYM(traceframe_write_count), IPA_SYM(traceframes_created), IPA_SYM(trace_state_variables), - IPA_SYM(get_raw_reg), - IPA_SYM(get_trace_state_variable_value), - IPA_SYM(set_trace_state_variable_value), + IPA_SYM(get_raw_reg_ptr), + IPA_SYM(get_trace_state_variable_value_ptr), + IPA_SYM(set_trace_state_variable_value_ptr), IPA_SYM(ust_loaded), + IPA_SYM(ipa_tdesc_idx), }; static struct ipa_sym_addresses ipa_sym_addrs; -int all_tracepoint_symbols_looked_up; - -int -in_process_agent_loaded (void) -{ - return all_tracepoint_symbols_looked_up; -} - static int read_inferior_integer (CORE_ADDR symaddr, int *val); /* Returns true if both the in-process agent library and the static - tracepoints libraries are loaded in the inferior. */ + tracepoints libraries are loaded in the inferior, and agent has + capability on static tracepoints. */ static int -in_process_agent_loaded_ust (void) +in_process_agent_supports_ust (void) { int loaded = 0; - if (!in_process_agent_loaded ()) + if (!agent_loaded_p ()) { warning ("In-process agent not loaded"); return 0; } - if (read_inferior_integer (ipa_sym_addrs.addr_ust_loaded, &loaded)) + if (agent_capability_check (AGENT_CAPA_STATIC_TRACE)) { - warning ("Error reading ust_loaded in lib"); - return 0; - } + /* Agent understands static tracepoint, then check whether UST is in + fact loaded in the inferior. */ + if (read_inferior_integer (ipa_sym_addrs.addr_ust_loaded, &loaded)) + { + warning ("Error reading ust_loaded in lib"); + return 0; + } - return loaded; + return loaded; + } + else + return 0; } static void @@ -283,7 +278,7 @@ write_e_ust_not_loaded (char *buffer) static int maybe_write_ipa_not_loaded (char *buffer) { - if (!in_process_agent_loaded ()) + if (!agent_loaded_p ()) { write_e_ipa_not_loaded (buffer); return 1; @@ -298,12 +293,12 @@ maybe_write_ipa_not_loaded (char *buffer) static int maybe_write_ipa_ust_not_loaded (char *buffer) { - if (!in_process_agent_loaded ()) + if (!agent_loaded_p ()) { write_e_ipa_not_loaded (buffer); return 1; } - else if (!in_process_agent_loaded_ust ()) + else if (!in_process_agent_supports_ust ()) { write_e_ust_not_loaded (buffer); return 1; @@ -322,7 +317,7 @@ tracepoint_look_up_symbols (void) { int i; - if (all_tracepoint_symbols_looked_up) + if (agent_loaded_p ()) return; for (i = 0; i < sizeof (symbol_list) / sizeof (symbol_list[0]); i++) @@ -333,15 +328,12 @@ tracepoint_look_up_symbols (void) if (look_up_one_symbol (symbol_list[i].name, addrp, 1) == 0) { if (debug_threads) - fprintf (stderr, "symbol `%s' not found\n", symbol_list[i].name); + debug_printf ("symbol `%s' not found\n", symbol_list[i].name); return; } } - if (agent_look_up_symbols () != 0) - return; - - all_tracepoint_symbols_looked_up = 1; + agent_look_up_symbols (NULL); } #endif @@ -378,14 +370,14 @@ read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) # define UNKNOWN_SIDE_EFFECTS() do {} while (0) #endif -IP_AGENT_EXPORT void ATTR_USED ATTR_NOINLINE +IP_AGENT_EXPORT_FUNC void stop_tracing (void) { /* GDBserver places breakpoint here. */ UNKNOWN_SIDE_EFFECTS(); } -IP_AGENT_EXPORT void ATTR_USED ATTR_NOINLINE +IP_AGENT_EXPORT_FUNC void flush_trace_buffer (void) { /* GDBserver places breakpoint here. */ @@ -411,11 +403,10 @@ static int stop_tracing_handler (CORE_ADDR); struct breakpoint *flush_trace_buffer_bkpt; static int flush_trace_buffer_handler (CORE_ADDR); -static void download_tracepoints (void); static void download_trace_state_variables (void); static void upload_fast_traceframes (void); -static int run_inferior_command (char *cmd); +static int run_inferior_command (char *cmd, int len); static int read_inferior_integer (CORE_ADDR symaddr, int *val) @@ -424,6 +415,9 @@ read_inferior_integer (CORE_ADDR symaddr, int *val) sizeof (*val)); } +struct tracepoint; +static int tracepoint_send_agent (struct tracepoint *tpoint); + static int read_inferior_uinteger (CORE_ADDR symaddr, unsigned int *val) { @@ -456,12 +450,26 @@ write_inferior_integer (CORE_ADDR symaddr, int val) return write_inferior_memory (symaddr, (unsigned char *) &val, sizeof (val)); } +static int +write_inferior_int8 (CORE_ADDR symaddr, int8_t val) +{ + return write_inferior_memory (symaddr, (unsigned char *) &val, sizeof (val)); +} + static int write_inferior_uinteger (CORE_ADDR symaddr, unsigned int val) { return write_inferior_memory (symaddr, (unsigned char *) &val, sizeof (val)); } +static CORE_ADDR target_malloc (ULONGEST size); + +#define COPY_FIELD_TO_BUF(BUF, OBJ, FIELD) \ + do { \ + memcpy (BUF, &(OBJ)->FIELD, sizeof ((OBJ)->FIELD)); \ + BUF += sizeof ((OBJ)->FIELD); \ + } while (0) + #endif /* Base action. Concrete actions inherit this. */ @@ -478,7 +486,7 @@ struct collect_memory_action ULONGEST addr; ULONGEST len; - int basereg; + int32_t basereg; }; /* An 'R' (collect registers) action. */ @@ -503,6 +511,150 @@ struct collect_static_trace_data_action struct tracepoint_action base; }; +#ifndef IN_PROCESS_AGENT +static CORE_ADDR +m_tracepoint_action_download (const struct tracepoint_action *action) +{ + CORE_ADDR ipa_action = target_malloc (sizeof (struct collect_memory_action)); + + write_inferior_memory (ipa_action, (unsigned char *) action, + sizeof (struct collect_memory_action)); + + return ipa_action; +} +static char * +m_tracepoint_action_send (char *buffer, const struct tracepoint_action *action) +{ + struct collect_memory_action *maction + = (struct collect_memory_action *) action; + + COPY_FIELD_TO_BUF (buffer, maction, addr); + COPY_FIELD_TO_BUF (buffer, maction, len); + COPY_FIELD_TO_BUF (buffer, maction, basereg); + + return buffer; +} + +static CORE_ADDR +r_tracepoint_action_download (const struct tracepoint_action *action) +{ + CORE_ADDR ipa_action = target_malloc (sizeof (struct collect_registers_action)); + + write_inferior_memory (ipa_action, (unsigned char *) action, + sizeof (struct collect_registers_action)); + + return ipa_action; +} + +static char * +r_tracepoint_action_send (char *buffer, const struct tracepoint_action *action) +{ + return buffer; +} + +static CORE_ADDR download_agent_expr (struct agent_expr *expr); + +static CORE_ADDR +x_tracepoint_action_download (const struct tracepoint_action *action) +{ + CORE_ADDR ipa_action = target_malloc (sizeof (struct eval_expr_action)); + CORE_ADDR expr; + + write_inferior_memory (ipa_action, (unsigned char *) action, + sizeof (struct eval_expr_action)); + expr = download_agent_expr (((struct eval_expr_action *) action)->expr); + write_inferior_data_pointer (ipa_action + + offsetof (struct eval_expr_action, expr), + expr); + + return ipa_action; +} + +/* Copy agent expression AEXPR to buffer pointed by P. If AEXPR is NULL, + copy 0 to P. Return updated header of buffer. */ + +static char * +agent_expr_send (char *p, const struct agent_expr *aexpr) +{ + /* Copy the length of condition first, and then copy its + content. */ + if (aexpr == NULL) + { + memset (p, 0, 4); + p += 4; + } + else + { + memcpy (p, &aexpr->length, 4); + p +=4; + + memcpy (p, aexpr->bytes, aexpr->length); + p += aexpr->length; + } + return p; +} + +static char * +x_tracepoint_action_send ( char *buffer, const struct tracepoint_action *action) +{ + struct eval_expr_action *eaction = (struct eval_expr_action *) action; + + return agent_expr_send (buffer, eaction->expr); +} + +static CORE_ADDR +l_tracepoint_action_download (const struct tracepoint_action *action) +{ + CORE_ADDR ipa_action + = target_malloc (sizeof (struct collect_static_trace_data_action)); + + write_inferior_memory (ipa_action, (unsigned char *) action, + sizeof (struct collect_static_trace_data_action)); + + return ipa_action; +} + +static char * +l_tracepoint_action_send (char *buffer, const struct tracepoint_action *action) +{ + return buffer; +} + +static char * +tracepoint_action_send (char *buffer, const struct tracepoint_action *action) +{ + switch (action->type) + { + case 'M': + return m_tracepoint_action_send (buffer, action); + case 'R': + return r_tracepoint_action_send (buffer, action); + case 'X': + return x_tracepoint_action_send (buffer, action); + case 'L': + return l_tracepoint_action_send (buffer, action); + } + error ("Unknown trace action '%c'.", action->type); +} + +static CORE_ADDR +tracepoint_action_download (const struct tracepoint_action *action) +{ + switch (action->type) + { + case 'M': + return m_tracepoint_action_download (action); + case 'R': + return r_tracepoint_action_download (action); + case 'X': + return x_tracepoint_action_download (action); + case 'L': + return l_tracepoint_action_download (action); + } + error ("Unknown trace action '%c'.", action->type); +} +#endif + /* This structure describes a piece of the source-level definition of the tracepoint. The contents are not interpreted by the target, but preserved verbatim for uploading upon reconnection. */ @@ -538,7 +690,7 @@ enum tracepoint_type struct tracepoint_hit_ctx; -typedef enum eval_result_type (*condfn) (struct tracepoint_hit_ctx *, +typedef enum eval_result_type (*condfn) (unsigned char *, ULONGEST *); /* The definition of a tracepoint. */ @@ -557,7 +709,7 @@ struct tracepoint { /* The number of the tracepoint, as specified by GDB. Several tracepoint objects here may share a number. */ - int number; + uint32_t number; /* Address at which the tracepoint is supposed to trigger. Several tracepoints may share an address. */ @@ -567,30 +719,30 @@ struct tracepoint enum tracepoint_type type; /* True if the tracepoint is currently enabled. */ - int enabled; + int8_t enabled; /* The number of single steps that will be performed after each tracepoint hit. */ - long step_count; + uint64_t step_count; /* The number of times the tracepoint may be hit before it will terminate the entire tracing run. */ - long pass_count; + uint64_t pass_count; /* Pointer to the agent expression that is the tracepoint's conditional, or NULL if the tracepoint is unconditional. */ struct agent_expr *cond; /* The list of actions to take when the tracepoint triggers. */ - int numactions; + uint32_t numactions; struct tracepoint_action **actions; /* Count of the times we've hit this tracepoint during the run. Note that while-stepping steps are not counted as "hits". */ - long hit_count; + uint64_t hit_count; /* Cached sum of the sizes of traceframes created by this point. */ - long traceframe_usage; + uint64_t traceframe_usage; CORE_ADDR compiled_cond; @@ -610,7 +762,7 @@ struct tracepoint /* The number of bytes displaced by fast tracepoints. It may subsume multiple instructions, for multi-byte fast tracepoints. This field is only valid for fast tracepoints. */ - int orig_size; + uint32_t orig_size; /* Only for fast tracepoints. */ CORE_ADDR obj_addr_on_target; @@ -674,31 +826,37 @@ struct wstep_state #endif +EXTERN_C_PUSH + /* The linked list of all tracepoints. Marked explicitly as used as the in-process library doesn't use it for the fast tracepoints support. */ -IP_AGENT_EXPORT struct tracepoint *tracepoints ATTR_USED; - -#ifndef IN_PROCESS_AGENT - -/* Pointer to the last tracepoint in the list, new tracepoints are - linked in at the end. */ - -static struct tracepoint *last_tracepoint; -#endif +IP_AGENT_EXPORT_VAR struct tracepoint *tracepoints; /* The first tracepoint to exceed its pass count. */ -IP_AGENT_EXPORT struct tracepoint *stopping_tracepoint; +IP_AGENT_EXPORT_VAR struct tracepoint *stopping_tracepoint; /* True if the trace buffer is full or otherwise no longer usable. */ -IP_AGENT_EXPORT int trace_buffer_is_full; +IP_AGENT_EXPORT_VAR int trace_buffer_is_full; + +/* The first error that occurred during expression evaluation. */ -static enum eval_result_type expr_eval_result = expr_eval_no_error; +/* Stored as an int to avoid the IPA ABI being dependent on whatever + the compiler decides to use for the enum's underlying type. Holds + enum eval_result_type values. */ +IP_AGENT_EXPORT_VAR int expr_eval_result = expr_eval_no_error; + +EXTERN_C_POP #ifndef IN_PROCESS_AGENT +/* Pointer to the last tracepoint in the list, new tracepoints are + linked in at the end. */ + +static struct tracepoint *last_tracepoint; + static const char *eval_result_names[] = { "terror:in the attic", /* this should never be reported */ @@ -715,7 +873,9 @@ static const char *eval_result_names[] = /* The tracepoint in which the error occurred. */ -static struct tracepoint *error_tracepoint; +EXTERN_C_PUSH +IP_AGENT_EXPORT_VAR struct tracepoint *error_tracepoint; +EXTERN_C_POP struct trace_state_variable { @@ -749,7 +909,7 @@ struct trace_state_variable struct trace_state_variable *alloced_trace_state_variables; #endif -IP_AGENT_EXPORT struct trace_state_variable *trace_state_variables; +IP_AGENT_EXPORT_VAR struct trace_state_variable *trace_state_variables; /* The results of tracing go into a fixed-size space known as the "trace buffer". Because usage follows a limited number of @@ -811,10 +971,9 @@ struct traceframe } ATTR_PACKED; -/* The traceframe to be used as the source of data to send back to - GDB. A value of -1 means to get data from the live program. */ - -int current_traceframe = -1; +/* The size of the EOB marker, in bytes. A traceframe with zeroed + fields (and no data) marks the end of trace data. */ +#define TRACEFRAME_EOB_MARKER_SIZE offsetof (struct traceframe, data) /* This flag is true if the trace buffer is circular, meaning that when it fills, the oldest trace frames are discarded in order to @@ -824,14 +983,22 @@ int current_traceframe = -1; static int circular_trace_buffer; #endif +/* Size of the trace buffer. */ + +static LONGEST trace_buffer_size; + +EXTERN_C_PUSH + /* Pointer to the block of memory that traceframes all go into. */ -static unsigned char *trace_buffer_lo; +IP_AGENT_EXPORT_VAR unsigned char *trace_buffer_lo; /* Pointer to the end of the trace buffer, more precisely to the byte after the end of the buffer. */ -static unsigned char *trace_buffer_hi; +IP_AGENT_EXPORT_VAR unsigned char *trace_buffer_hi; + +EXTERN_C_POP /* Control structure holding the read/write/etc. pointers into the trace buffer. We need more than one of these to implement a @@ -985,8 +1152,8 @@ A GDBserver update of `trace_buffer_ctrl_curr' does: #define GDBSERVER_UPDATED_FLUSH_COUNT_BIT 0x80000000 #ifdef IN_PROCESS_AGENT -IP_AGENT_EXPORT struct trace_buffer_control trace_buffer_ctrl[3]; -IP_AGENT_EXPORT unsigned int trace_buffer_ctrl_curr; +IP_AGENT_EXPORT_VAR struct trace_buffer_control trace_buffer_ctrl[3]; +IP_AGENT_EXPORT_VAR unsigned int trace_buffer_ctrl_curr; # define TRACE_BUFFER_CTRL_CURR \ (trace_buffer_ctrl_curr & ~GDBSERVER_FLUSH_COUNT_MASK) @@ -1031,8 +1198,8 @@ struct trace_buffer_control trace_buffer_ctrl[1]; of complete traceframes present in the trace buffer. The IP agent writes to the write count, GDBserver writes to read count. */ -IP_AGENT_EXPORT unsigned int traceframe_write_count; -IP_AGENT_EXPORT unsigned int traceframe_read_count; +IP_AGENT_EXPORT_VAR unsigned int traceframe_write_count; +IP_AGENT_EXPORT_VAR unsigned int traceframe_read_count; /* Convenience macro. */ @@ -1042,7 +1209,7 @@ IP_AGENT_EXPORT unsigned int traceframe_read_count; /* The count of all traceframes created in the current run, including ones that were discarded to make room. */ -IP_AGENT_EXPORT int traceframes_created; +IP_AGENT_EXPORT_VAR int traceframes_created; #ifndef IN_PROCESS_AGENT @@ -1072,7 +1239,7 @@ static struct readonly_region *readonly_regions; /* The global that controls tracing overall. */ -IP_AGENT_EXPORT int tracing; +IP_AGENT_EXPORT_VAR int tracing; #ifndef IN_PROCESS_AGENT @@ -1178,12 +1345,6 @@ struct trap_tracepoint_ctx #endif -static enum eval_result_type -eval_tracepoint_agent_expr (struct tracepoint_hit_ctx *ctx, - struct traceframe *tframe, - struct agent_expr *aexpr, - ULONGEST *rslt); - #ifndef IN_PROCESS_AGENT static CORE_ADDR traceframe_get_pc (struct traceframe *tframe); static int traceframe_read_tsv (int num, LONGEST *val); @@ -1219,6 +1380,8 @@ static struct tracepoint *fast_tracepoint_from_ipa_tpoint_address (CORE_ADDR); static void install_tracepoint (struct tracepoint *, char *own_buf); static void download_tracepoint (struct tracepoint *); static int install_fast_tracepoint (struct tracepoint *, char *errbuf); +static void clone_fast_tracepoint (struct tracepoint *to, + const struct tracepoint *from); #endif static LONGEST get_timestamp (void); @@ -1314,17 +1477,26 @@ clear_inferior_trace_buffer (void) #endif static void -init_trace_buffer (unsigned char *buf, int bufsize) +init_trace_buffer (LONGEST bufsize) { - trace_buffer_lo = buf; - trace_buffer_hi = trace_buffer_lo + bufsize; + size_t alloc_size; + + trace_buffer_size = bufsize; + + /* Make sure to internally allocate at least space for the EOB + marker. */ + alloc_size = (bufsize < TRACEFRAME_EOB_MARKER_SIZE + ? TRACEFRAME_EOB_MARKER_SIZE : bufsize); + trace_buffer_lo = (unsigned char *) xrealloc (trace_buffer_lo, alloc_size); + + trace_buffer_hi = trace_buffer_lo + trace_buffer_size; clear_trace_buffer (); } #ifdef IN_PROCESS_AGENT -IP_AGENT_EXPORT void ATTR_USED ATTR_NOINLINE +IP_AGENT_EXPORT_FUNC void about_to_request_buffer_space (void) { /* GDBserver places breakpoint here while it goes about to flush @@ -1357,7 +1529,7 @@ trace_buffer_alloc (size_t amt) (long) amt, (long) sizeof (struct traceframe)); /* Account for the EOB marker. */ - amt += sizeof (struct traceframe); + amt += TRACEFRAME_EOB_MARKER_SIZE; #ifdef IN_PROCESS_AGENT again: @@ -1621,7 +1793,7 @@ add_tracepoint (int num, CORE_ADDR addr) { struct tracepoint *tpoint, **tp_next; - tpoint = xmalloc (sizeof (struct tracepoint)); + tpoint = XNEW (struct tracepoint); tpoint->number = num; tpoint->address = addr; tpoint->numactions = 0; @@ -1687,6 +1859,28 @@ find_tracepoint (int id, CORE_ADDR addr) return NULL; } +/* Remove TPOINT from global list. */ + +static void +remove_tracepoint (struct tracepoint *tpoint) +{ + struct tracepoint *tp, *tp_prev; + + for (tp = tracepoints, tp_prev = NULL; tp && tp != tpoint; + tp_prev = tp, tp = tp->next) + ; + + if (tp) + { + if (tp_prev) + tp_prev->next = tp->next; + else + tracepoints = tp->next; + + xfree (tp); + } +} + /* There may be several tracepoints with the same number (because they are "locations", in GDB parlance); return the next one after the given tracepoint, or search from the beginning of the list if the @@ -1710,24 +1904,12 @@ find_next_tracepoint_by_number (struct tracepoint *prev_tp, int num) #endif -static char * -save_string (const char *str, size_t len) -{ - char *s; - - s = xmalloc (len + 1); - memcpy (s, str, len); - s[len] = '\0'; - - return s; -} - /* Append another action to perform when the tracepoint triggers. */ static void -add_tracepoint_action (struct tracepoint *tpoint, char *packet) +add_tracepoint_action (struct tracepoint *tpoint, const char *packet) { - char *act; + const char *act; if (*packet == 'S') { @@ -1739,18 +1921,18 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet) while (*act) { - char *act_start = act; + const char *act_start = act; struct tracepoint_action *action = NULL; switch (*act) { case 'M': { - struct collect_memory_action *maction; + struct collect_memory_action *maction = + XNEW (struct collect_memory_action); ULONGEST basereg; int is_neg; - maction = xmalloc (sizeof *maction); maction->base.type = *act; action = &maction->base; @@ -1773,9 +1955,9 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet) } case 'R': { - struct collect_registers_action *raction; + struct collect_registers_action *raction = + XNEW (struct collect_registers_action); - raction = xmalloc (sizeof *raction); raction->base.type = *act; action = &raction->base; @@ -1788,9 +1970,9 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet) } case 'L': { - struct collect_static_trace_data_action *raction; + struct collect_static_trace_data_action *raction = + XNEW (struct collect_static_trace_data_action); - raction = xmalloc (sizeof *raction); raction->base.type = *act; action = &raction->base; @@ -1804,9 +1986,8 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet) break; case 'X': { - struct eval_expr_action *xaction; + struct eval_expr_action *xaction = XNEW (struct eval_expr_action); - xaction = xmalloc (sizeof (*xaction)); xaction->base.type = *act; action = &xaction->base; @@ -1829,29 +2010,26 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet) tpoint->num_step_actions++; tpoint->step_actions - = xrealloc (tpoint->step_actions, - (sizeof (*tpoint->step_actions) - * tpoint->num_step_actions)); + = XRESIZEVEC (struct tracepoint_action *, tpoint->step_actions, + tpoint->num_step_actions); tpoint->step_actions_str - = xrealloc (tpoint->step_actions_str, - (sizeof (*tpoint->step_actions_str) - * tpoint->num_step_actions)); + = XRESIZEVEC (char *, tpoint->step_actions_str, + tpoint->num_step_actions); tpoint->step_actions[tpoint->num_step_actions - 1] = action; tpoint->step_actions_str[tpoint->num_step_actions - 1] - = save_string (act_start, act - act_start); + = savestring (act_start, act - act_start); } else { tpoint->numactions++; tpoint->actions - = xrealloc (tpoint->actions, - sizeof (*tpoint->actions) * tpoint->numactions); + = XRESIZEVEC (struct tracepoint_action *, tpoint->actions, + tpoint->numactions); tpoint->actions_str - = xrealloc (tpoint->actions_str, - sizeof (*tpoint->actions_str) * tpoint->numactions); + = XRESIZEVEC (char *, tpoint->actions_str, tpoint->numactions); tpoint->actions[tpoint->numactions - 1] = action; tpoint->actions_str[tpoint->numactions - 1] - = save_string (act_start, act - act_start); + = savestring (act_start, act - act_start); } } } @@ -1892,7 +2070,7 @@ create_trace_state_variable (int num, int gdb) return tsv; /* Create a new variable. */ - tsv = xmalloc (sizeof (struct trace_state_variable)); + tsv = XNEW (struct trace_state_variable); tsv->number = num; tsv->initial_value = 0; tsv->value = 0; @@ -1913,7 +2091,7 @@ create_trace_state_variable (int num, int gdb) return tsv; } -IP_AGENT_EXPORT LONGEST +IP_AGENT_EXPORT_FUNC LONGEST get_trace_state_variable_value (int num) { struct trace_state_variable *tsv; @@ -1939,7 +2117,7 @@ get_trace_state_variable_value (int num) return tsv->value; } -IP_AGENT_EXPORT void +IP_AGENT_EXPORT_FUNC void set_trace_state_variable_value (int num, LONGEST val) { struct trace_state_variable *tsv; @@ -2006,7 +2184,8 @@ add_traceframe (struct tracepoint *tpoint) { struct traceframe *tframe; - tframe = trace_buffer_alloc (sizeof (struct traceframe)); + tframe + = (struct traceframe *) trace_buffer_alloc (sizeof (struct traceframe)); if (tframe == NULL) return NULL; @@ -2020,19 +2199,23 @@ add_traceframe (struct tracepoint *tpoint) /* Add a block to the traceframe currently being worked on. */ static unsigned char * -add_traceframe_block (struct traceframe *tframe, int amt) +add_traceframe_block (struct traceframe *tframe, + struct tracepoint *tpoint, int amt) { unsigned char *block; if (!tframe) return NULL; - block = trace_buffer_alloc (amt); + block = (unsigned char *) trace_buffer_alloc (amt); if (!block) return NULL; + gdb_assert (tframe->tpnum == tpoint->number); + tframe->data_size += amt; + tpoint->traceframe_usage += amt; return block; } @@ -2093,10 +2276,11 @@ static struct traceframe * find_next_traceframe_in_range (CORE_ADDR lo, CORE_ADDR hi, int inside_p, int *tfnump) { + client_state &cs = get_client_state (); struct traceframe *tframe; CORE_ADDR tfaddr; - *tfnump = current_traceframe + 1; + *tfnump = cs.current_traceframe + 1; tframe = find_traceframe (*tfnump); /* The search is not supposed to wrap around. */ if (!tframe) @@ -2126,9 +2310,10 @@ find_next_traceframe_in_range (CORE_ADDR lo, CORE_ADDR hi, int inside_p, static struct traceframe * find_next_traceframe_by_tracepoint (int num, int *tfnump) { + client_state &cs = get_client_state (); struct traceframe *tframe; - *tfnump = current_traceframe + 1; + *tfnump = cs.current_traceframe + 1; tframe = find_traceframe (*tfnump); /* The search is not supposed to wrap around. */ if (!tframe) @@ -2157,10 +2342,20 @@ find_next_traceframe_by_tracepoint (int num, int *tfnump) static void cmd_qtinit (char *packet) { + client_state &cs = get_client_state (); struct trace_state_variable *tsv, *prev, *next; + /* Can't do this command without a pid attached. */ + if (current_thread == NULL) + { + write_enn (packet); + return; + } + /* Make sure we don't try to read from a trace frame. */ - current_traceframe = -1; + cs.current_traceframe = -1; + + stop_tracing (); trace_debug ("Initializing the trace"); @@ -2209,7 +2404,7 @@ unprobe_marker_at (CORE_ADDR address) char cmd[IPA_CMD_BUF_SIZE]; sprintf (cmd, "unprobe_marker_at:%s", paddress (address)); - run_inferior_command (cmd); + run_inferior_command (cmd, strlen (cmd) + 1); } /* Restore the program to its pre-tracing state. This routine may be called @@ -2223,7 +2418,6 @@ clear_installed_tracepoints (void) struct tracepoint *prev_stpoint; pause_all (1); - cancel_breakpoints (); prev_stpoint = NULL; @@ -2243,10 +2437,20 @@ clear_installed_tracepoints (void) switch (tpoint->type) { case trap_tracepoint: - delete_breakpoint (tpoint->handle); + { + struct breakpoint *bp + = (struct breakpoint *) tpoint->handle; + + delete_breakpoint (bp); + } break; case fast_tracepoint: - delete_fast_tracepoint_jump (tpoint->handle); + { + struct fast_tracepoint_jump *jump + = (struct fast_tracepoint_jump *) tpoint->handle; + + delete_fast_tracepoint_jump (jump); + } break; case static_tracepoint: if (prev_stpoint != NULL @@ -2281,8 +2485,7 @@ cmd_qtdp (char *own_buf) ULONGEST addr; ULONGEST count; struct tracepoint *tpoint; - char *actparm; - char *packet = own_buf; + const char *packet = own_buf; packet += strlen ("QTDP:"); @@ -2342,9 +2545,7 @@ cmd_qtdp (char *own_buf) } else if (*packet == 'X') { - actparm = (char *) packet; - tpoint->cond = gdb_parse_agent_expr (&actparm); - packet = actparm; + tpoint->cond = gdb_parse_agent_expr (&packet); } else if (*packet == '-') break; @@ -2360,7 +2561,7 @@ cmd_qtdp (char *own_buf) } trace_debug ("Defined %stracepoint %d at 0x%s, " - "enabled %d step %ld pass %ld", + "enabled %d step %" PRIu64 " pass %" PRIu64, tpoint->type == fast_tracepoint ? "fast " : tpoint->type == static_tracepoint ? "static " : "", tpoint->number, paddress (tpoint->address), tpoint->enabled, @@ -2382,6 +2583,8 @@ cmd_qtdp (char *own_buf) trailing hyphen in QTDP packet. */ if (tracing && !trail_hyphen) { + struct tracepoint *tp = NULL; + /* Pause all threads temporarily while we patch tracepoints. */ pause_all (0); @@ -2392,8 +2595,52 @@ cmd_qtdp (char *own_buf) /* Freeze threads. */ pause_all (1); - download_tracepoint (tpoint); - install_tracepoint (tpoint, own_buf); + + if (tpoint->type != trap_tracepoint) + { + /* Find another fast or static tracepoint at the same address. */ + for (tp = tracepoints; tp; tp = tp->next) + { + if (tp->address == tpoint->address && tp->type == tpoint->type + && tp->number != tpoint->number) + break; + } + + /* TPOINT is installed at the same address as TP. */ + if (tp) + { + if (tpoint->type == fast_tracepoint) + clone_fast_tracepoint (tpoint, tp); + else if (tpoint->type == static_tracepoint) + tpoint->handle = (void *) -1; + } + } + + if (use_agent && tpoint->type == fast_tracepoint + && agent_capability_check (AGENT_CAPA_FAST_TRACE)) + { + /* Download and install fast tracepoint by agent. */ + if (tracepoint_send_agent (tpoint) == 0) + write_ok (own_buf); + else + { + write_enn (own_buf); + remove_tracepoint (tpoint); + } + } + else + { + download_tracepoint (tpoint); + + if (tpoint->type == trap_tracepoint || tp == NULL) + { + install_tracepoint (tpoint, own_buf); + if (strcmp (own_buf, "OK") != 0) + remove_tracepoint (tpoint); + } + else + write_ok (own_buf); + } unpause_all (1); return; @@ -2407,8 +2654,9 @@ cmd_qtdpsrc (char *own_buf) { ULONGEST num, addr, start, slen; struct tracepoint *tpoint; - char *packet = own_buf; - char *saved, *srctype, *src; + const char *packet = own_buf; + const char *saved; + char *srctype, *src; size_t nbytes; struct source_string *last, *newlast; @@ -2432,7 +2680,7 @@ cmd_qtdpsrc (char *own_buf) saved = packet; packet = strchr (packet, ':'); - srctype = xmalloc (packet - saved + 1); + srctype = (char *) xmalloc (packet - saved + 1); memcpy (srctype, saved, packet - saved); srctype[packet - saved] = '\0'; ++packet; @@ -2440,11 +2688,11 @@ cmd_qtdpsrc (char *own_buf) ++packet; /* skip a colon */ packet = unpack_varlen_hex (packet, &slen); ++packet; /* skip a colon */ - src = xmalloc (slen + 1); - nbytes = unhexify (src, packet, strlen (packet) / 2); + src = (char *) xmalloc (slen + 1); + nbytes = hex2bin (packet, (gdb_byte *) src, strlen (packet) / 2); src[nbytes] = '\0'; - newlast = xmalloc (sizeof (struct source_string)); + newlast = XNEW (struct source_string); newlast->type = srctype; newlast->str = src; newlast->next = NULL; @@ -2470,7 +2718,7 @@ cmd_qtdv (char *own_buf) char *varname; size_t nbytes; struct trace_state_variable *tsv; - char *packet = own_buf; + const char *packet = own_buf; packet += strlen ("QTDV:"); @@ -2482,8 +2730,8 @@ cmd_qtdv (char *own_buf) ++packet; /* skip a colon */ nbytes = strlen (packet) / 2; - varname = xmalloc (nbytes + 1); - nbytes = unhexify (varname, packet, nbytes); + varname = (char *) xmalloc (nbytes + 1); + nbytes = hex2bin (packet, (gdb_byte *) varname, nbytes); varname[nbytes] = '\0'; tsv = create_trace_state_variable (num, 1); @@ -2498,7 +2746,7 @@ cmd_qtdv (char *own_buf) static void cmd_qtenable_disable (char *own_buf, int enable) { - char *packet = own_buf; + const char *packet = own_buf; ULONGEST num, addr; struct tracepoint *tp; @@ -2539,8 +2787,8 @@ cmd_qtenable_disable (char *own_buf, int enable) write_enn (own_buf); return; } - - ret = write_inferior_integer (obj_addr, enable); + + ret = write_inferior_int8 (obj_addr, enable); done_accessing_memory (); if (ret) @@ -2565,15 +2813,16 @@ cmd_qtenable_disable (char *own_buf, int enable) static void cmd_qtv (char *own_buf) { + client_state &cs = get_client_state (); ULONGEST num; - LONGEST val; + LONGEST val = 0; int err; char *packet = own_buf; packet += strlen ("qTV:"); unpack_varlen_hex (packet, &num); - if (current_traceframe >= 0) + if (cs.current_traceframe >= 0) { err = traceframe_read_tsv ((int) num, &val); if (err) @@ -2620,7 +2869,7 @@ cmd_qtro (char *own_buf) { ULONGEST start, end; struct readonly_region *roreg; - char *packet = own_buf; + const char *packet = own_buf; trace_debug ("Want to mark readonly regions"); @@ -2634,7 +2883,8 @@ cmd_qtro (char *own_buf) packet = unpack_varlen_hex (packet, &start); ++packet; /* skip a comma */ packet = unpack_varlen_hex (packet, &end); - roreg = xmalloc (sizeof (struct readonly_region)); + + roreg = XNEW (struct readonly_region); roreg->start = start; roreg->end = end; roreg->next = readonly_regions; @@ -2662,9 +2912,6 @@ in_readonly_region (CORE_ADDR addr, ULONGEST length) return 0; } -/* The maximum size of a jump pad entry. */ -static const int max_jump_pad_size = 0x100; - static CORE_ADDR gdb_jump_pad_head; /* Return the address of the next free jump space. */ @@ -2676,7 +2923,10 @@ get_jump_space_head (void) { if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_jump_pad_buffer, &gdb_jump_pad_head)) - fatal ("error extracting jump_pad_buffer"); + { + internal_error (__FILE__, __LINE__, + "error extracting jump_pad_buffer"); + } } return gdb_jump_pad_head; @@ -2707,15 +2957,15 @@ claim_trampoline_space (ULONGEST used, CORE_ADDR *trampoline) if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer, &trampoline_buffer_tail)) { - fatal ("error extracting trampoline_buffer"); - return 0; + internal_error (__FILE__, __LINE__, + "error extracting trampoline_buffer"); } if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_end, &trampoline_buffer_head)) { - fatal ("error extracting trampoline_buffer_end"); - return 0; + internal_error (__FILE__, __LINE__, + "error extracting trampoline_buffer_end"); } } @@ -2750,8 +3000,8 @@ have_fast_tracepoint_trampoline_buffer (char *buf) if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_end, &trampoline_end)) { - fatal ("error extracting trampoline_buffer_end"); - return 0; + internal_error (__FILE__, __LINE__, + "error extracting trampoline_buffer_end"); } if (buf) @@ -2761,8 +3011,8 @@ have_fast_tracepoint_trampoline_buffer (char *buf) if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_error, &errbuf)) { - fatal ("error extracting errbuf"); - return 0; + internal_error (__FILE__, __LINE__, + "error extracting errbuf"); } read_inferior_memory (errbuf, (unsigned char *) buf, 100); @@ -2784,7 +3034,7 @@ probe_marker_at (CORE_ADDR address, char *errout) int err; sprintf (cmd, "probe_marker_at:%s", paddress (address)); - err = run_inferior_command (cmd); + err = run_inferior_command (cmd, strlen (cmd) + 1); if (err == 0) { @@ -2823,6 +3073,7 @@ install_fast_tracepoint (struct tracepoint *tpoint, char *errbuf) { CORE_ADDR jentry, jump_entry; CORE_ADDR trampoline; + CORE_ADDR collect; ULONGEST trampoline_size; int err = 0; /* The jump to the jump pad of the last fast tracepoint @@ -2837,6 +3088,13 @@ install_fast_tracepoint (struct tracepoint *tpoint, char *errbuf) return 0; } + if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_collect_ptr, + &collect)) + { + error ("error extracting gdb_collect_ptr"); + return 1; + } + jentry = jump_entry = get_jump_space_head (); trampoline = 0; @@ -2845,7 +3103,7 @@ install_fast_tracepoint (struct tracepoint *tpoint, char *errbuf) /* Install the jump pad. */ err = install_fast_tracepoint_jump_pad (tpoint->obj_addr_on_target, tpoint->address, - ipa_sym_addrs.addr_gdb_collect, + collect, ipa_sym_addrs.addr_collecting, tpoint->orig_size, &jentry, @@ -2897,9 +3155,7 @@ install_tracepoint (struct tracepoint *tpoint, char *own_buf) } else if (tpoint->type == fast_tracepoint || tpoint->type == static_tracepoint) { - struct tracepoint *tp; - - if (!in_process_agent_loaded ()) + if (!agent_loaded_p ()) { trace_debug ("Requested a %s tracepoint, but fast " "tracepoints aren't supported.", @@ -2907,7 +3163,8 @@ install_tracepoint (struct tracepoint *tpoint, char *own_buf) write_e_ipa_not_loaded (own_buf); return; } - if (tpoint->type == static_tracepoint && !in_process_agent_loaded_ust ()) + if (tpoint->type == static_tracepoint + && !in_process_agent_supports_ust ()) { trace_debug ("Requested a static tracepoint, but static " "tracepoints are not supported."); @@ -2915,30 +3172,12 @@ install_tracepoint (struct tracepoint *tpoint, char *own_buf) return; } - /* Find another fast or static tracepoint at the same address. */ - for (tp = tracepoints; tp; tp = tp->next) - { - if (tp->address == tpoint->address && tp->type == tpoint->type - && tp->number != tpoint->number) - break; - } - if (tpoint->type == fast_tracepoint) - { - if (tp) /* TPOINT is installed at the same address as TP. */ - clone_fast_tracepoint (tpoint, tp); - else - install_fast_tracepoint (tpoint, own_buf); - } + install_fast_tracepoint (tpoint, own_buf); else { - if (tp) + if (probe_marker_at (tpoint->address, own_buf) == 0) tpoint->handle = (void *) -1; - else - { - if (probe_marker_at (tpoint->address, own_buf) == 0) - tpoint->handle = (void *) -1; - } } } @@ -2954,10 +3193,13 @@ install_tracepoint (struct tracepoint *tpoint, char *own_buf) write_ok (own_buf); } +static void download_tracepoint_1 (struct tracepoint *tpoint); + static void cmd_qtstart (char *packet) { struct tracepoint *tpoint, *prev_ftpoint, *prev_stpoint; + CORE_ADDR tpptr = 0, prev_tpptr = 0; trace_debug ("Starting the trace"); @@ -2974,11 +3216,8 @@ cmd_qtstart (char *packet) pause_all (1); /* Sync the fast tracepoints list in the inferior ftlib. */ - if (in_process_agent_loaded ()) - { - download_tracepoints (); - download_trace_state_variables (); - } + if (agent_loaded_p ()) + download_trace_state_variables (); /* No previous fast tpoint yet. */ prev_ftpoint = NULL; @@ -2988,7 +3227,19 @@ cmd_qtstart (char *packet) *packet = '\0'; - /* Install tracepoints. */ + if (agent_loaded_p ()) + { + /* Tell IPA about the correct tdesc. */ + if (write_inferior_integer (ipa_sym_addrs.addr_ipa_tdesc_idx, + target_get_ipa_tdesc_idx ())) + error ("Error setting ipa_tdesc_idx variable in lib"); + } + + /* Start out empty. */ + if (agent_loaded_p ()) + write_inferior_data_pointer (ipa_sym_addrs.addr_tracepoints, 0); + + /* Download and install tracepoints. */ for (tpoint = tracepoints; tpoint; tpoint = tpoint->next) { /* Ensure all the hit counts start at zero. */ @@ -3004,48 +3255,89 @@ cmd_qtstart (char *packet) tpoint->handle = set_breakpoint_at (tpoint->address, tracepoint_handler); } - else if (tpoint->type == fast_tracepoint) + else if (tpoint->type == fast_tracepoint + || tpoint->type == static_tracepoint) { if (maybe_write_ipa_not_loaded (packet)) { - trace_debug ("Requested a fast tracepoint, but fast " - "tracepoints aren't supported."); + trace_debug ("Requested a %s tracepoint, but fast " + "tracepoints aren't supported.", + tpoint->type == static_tracepoint + ? "static" : "fast"); break; } - if (prev_ftpoint != NULL && prev_ftpoint->address == tpoint->address) - clone_fast_tracepoint (tpoint, prev_ftpoint); - else - { - if (install_fast_tracepoint (tpoint, packet) == 0) - prev_ftpoint = tpoint; - } - } - else if (tpoint->type == static_tracepoint) - { - if (maybe_write_ipa_ust_not_loaded (packet)) + if (tpoint->type == fast_tracepoint) { - trace_debug ("Requested a static tracepoint, but static " - "tracepoints are not supported."); - break; - } + int use_agent_p + = use_agent && agent_capability_check (AGENT_CAPA_FAST_TRACE); - /* Can only probe a given marker once. */ - if (prev_stpoint != NULL && prev_stpoint->address == tpoint->address) - { - tpoint->handle = (void *) -1; + if (prev_ftpoint != NULL + && prev_ftpoint->address == tpoint->address) + { + if (use_agent_p) + tracepoint_send_agent (tpoint); + else + download_tracepoint_1 (tpoint); + + clone_fast_tracepoint (tpoint, prev_ftpoint); + } + else + { + /* Tracepoint is installed successfully? */ + int installed = 0; + + /* Download and install fast tracepoint by agent. */ + if (use_agent_p) + installed = !tracepoint_send_agent (tpoint); + else + { + download_tracepoint_1 (tpoint); + installed = !install_fast_tracepoint (tpoint, packet); + } + + if (installed) + prev_ftpoint = tpoint; + } } else { - if (probe_marker_at (tpoint->address, packet) == 0) + if (!in_process_agent_supports_ust ()) { - tpoint->handle = (void *) -1; + trace_debug ("Requested a static tracepoint, but static " + "tracepoints are not supported."); + break; + } - /* So that we can handle multiple static tracepoints - at the same address easily. */ - prev_stpoint = tpoint; + download_tracepoint_1 (tpoint); + /* Can only probe a given marker once. */ + if (prev_stpoint != NULL + && prev_stpoint->address == tpoint->address) + tpoint->handle = (void *) -1; + else + { + if (probe_marker_at (tpoint->address, packet) == 0) + { + tpoint->handle = (void *) -1; + + /* So that we can handle multiple static tracepoints + at the same address easily. */ + prev_stpoint = tpoint; + } } } + + prev_tpptr = tpptr; + tpptr = tpoint->obj_addr_on_target; + + if (tpoint == tracepoints) + /* First object in list, set the head pointer in the + inferior. */ + write_inferior_data_pointer (ipa_sym_addrs.addr_tracepoints, tpptr); + else + write_inferior_data_pointer (prev_tpptr + + offsetof (struct tracepoint, next), + tpptr); } /* Any failure in the inner loop is sufficient cause to give @@ -3075,17 +3367,28 @@ cmd_qtstart (char *packet) /* Tracing is now active, hits will now start being logged. */ tracing = 1; - if (in_process_agent_loaded ()) + if (agent_loaded_p ()) { if (write_inferior_integer (ipa_sym_addrs.addr_tracing, 1)) - fatal ("Error setting tracing variable in lib"); + { + internal_error (__FILE__, __LINE__, + "Error setting tracing variable in lib"); + } if (write_inferior_data_pointer (ipa_sym_addrs.addr_stopping_tracepoint, 0)) - fatal ("Error clearing stopping_tracepoint variable in lib"); + { + internal_error (__FILE__, __LINE__, + "Error clearing stopping_tracepoint variable" + " in lib"); + } if (write_inferior_integer (ipa_sym_addrs.addr_trace_buffer_is_full, 0)) - fatal ("Error clearing trace_buffer_is_full variable in lib"); + { + internal_error (__FILE__, __LINE__, + "Error clearing trace_buffer_is_full variable" + " in lib"); + } stop_tracing_bkpt = set_breakpoint_at (ipa_sym_addrs.addr_stop_tracing, stop_tracing_handler); @@ -3127,17 +3430,17 @@ stop_tracing (void) We can't now, since we may be getting here due to the inferior agent calling us. */ pause_all (1); - /* Since we're removing breakpoints, cancel breakpoint hits, - possibly related to the breakpoints we're about to delete. */ - cancel_breakpoints (); /* Stop logging. Tracepoints can still be hit, but they will not be recorded. */ tracing = 0; - if (in_process_agent_loaded ()) + if (agent_loaded_p ()) { if (write_inferior_integer (ipa_sym_addrs.addr_tracing, 0)) - fatal ("Error clearing tracing variable in lib"); + { + internal_error (__FILE__, __LINE__, + "Error clearing tracing variable in lib"); + } } tracing_stop_time = get_timestamp (); @@ -3146,7 +3449,7 @@ stop_tracing (void) if (stopping_tracepoint) { trace_debug ("Stopping the trace because " - "tracepoint %d was hit %ld times", + "tracepoint %d was hit %" PRIu64 " times", stopping_tracepoint->number, stopping_tracepoint->pass_count); tracing_stop_reason = "tpasscount"; @@ -3182,7 +3485,7 @@ stop_tracing (void) /* Clear out the tracepoints. */ clear_installed_tracepoints (); - if (in_process_agent_loaded ()) + if (agent_loaded_p ()) { /* Pull in fast tracepoint trace frames from the inferior lib buffer into our buffer, even if our buffer is already full, @@ -3250,21 +3553,22 @@ cmd_qtdisconnected (char *own_buf) static void cmd_qtframe (char *own_buf) { + client_state &cs = get_client_state (); ULONGEST frame, pc, lo, hi, num; int tfnum, tpnum; struct traceframe *tframe; - char *packet = own_buf; + const char *packet = own_buf; packet += strlen ("QTFrame:"); - if (strncmp (packet, "pc:", strlen ("pc:")) == 0) + if (startswith (packet, "pc:")) { packet += strlen ("pc:"); unpack_varlen_hex (packet, &pc); trace_debug ("Want to find next traceframe at pc=0x%s", paddress (pc)); tframe = find_next_traceframe_in_range (pc, pc, 1, &tfnum); } - else if (strncmp (packet, "range:", strlen ("range:")) == 0) + else if (startswith (packet, "range:")) { packet += strlen ("range:"); packet = unpack_varlen_hex (packet, &lo); @@ -3274,7 +3578,7 @@ cmd_qtframe (char *own_buf) paddress (lo), paddress (hi)); tframe = find_next_traceframe_in_range (lo, hi, 1, &tfnum); } - else if (strncmp (packet, "outside:", strlen ("outside:")) == 0) + else if (startswith (packet, "outside:")) { packet += strlen ("outside:"); packet = unpack_varlen_hex (packet, &lo); @@ -3285,7 +3589,7 @@ cmd_qtframe (char *own_buf) paddress (lo), paddress (hi)); tframe = find_next_traceframe_in_range (lo, hi, 0, &tfnum); } - else if (strncmp (packet, "tdp:", strlen ("tdp:")) == 0) + else if (startswith (packet, "tdp:")) { packet += strlen ("tdp:"); unpack_varlen_hex (packet, &num); @@ -3300,7 +3604,7 @@ cmd_qtframe (char *own_buf) if (tfnum == -1) { trace_debug ("Want to stop looking at traceframes"); - current_traceframe = -1; + cs.current_traceframe = -1; write_ok (own_buf); return; } @@ -3310,7 +3614,7 @@ cmd_qtframe (char *own_buf) if (tframe) { - current_traceframe = tfnum; + cs.current_traceframe = tfnum; sprintf (own_buf, "F%xT%x", tfnum, tframe->tpnum); } else @@ -3321,7 +3625,8 @@ static void cmd_qtstatus (char *packet) { char *stop_reason_rsp = NULL; - char *buf1, *buf2, *buf3, *str; + char *buf1, *buf2, *buf3; + const char *str; int slen; /* Translate the plain text of the notes back into hex for @@ -3330,22 +3635,22 @@ cmd_qtstatus (char *packet) str = (tracing_user_name ? tracing_user_name : ""); slen = strlen (str); buf1 = (char *) alloca (slen * 2 + 1); - hexify (buf1, str, slen); + bin2hex ((gdb_byte *) str, buf1, slen); str = (tracing_notes ? tracing_notes : ""); slen = strlen (str); buf2 = (char *) alloca (slen * 2 + 1); - hexify (buf2, str, slen); + bin2hex ((gdb_byte *) str, buf2, slen); str = (tracing_stop_note ? tracing_stop_note : ""); slen = strlen (str); buf3 = (char *) alloca (slen * 2 + 1); - hexify (buf3, str, slen); + bin2hex ((gdb_byte *) str, buf3, slen); trace_debug ("Returning trace status as %d, stop reason %s", tracing, tracing_stop_reason); - if (in_process_agent_loaded ()) + if (agent_loaded_p ()) { pause_all (1); @@ -3359,7 +3664,7 @@ cmd_qtstatus (char *packet) /* The user visible error string in terror needs to be hex encoded. We leave it as plain string in `tracing_stop_reason' to ease debugging. */ - if (strncmp (stop_reason_rsp, "terror:", strlen ("terror:")) == 0) + if (startswith (stop_reason_rsp, "terror:")) { const char *result_name; int hexstr_len; @@ -3367,16 +3672,17 @@ cmd_qtstatus (char *packet) result_name = stop_reason_rsp + strlen ("terror:"); hexstr_len = strlen (result_name) * 2; - p = stop_reason_rsp = alloca (strlen ("terror:") + hexstr_len + 1); + p = stop_reason_rsp + = (char *) alloca (strlen ("terror:") + hexstr_len + 1); strcpy (p, "terror:"); p += strlen (p); - convert_int_to_ascii ((gdb_byte *) result_name, p, strlen (result_name)); + bin2hex ((gdb_byte *) result_name, p, strlen (result_name)); } /* If this was a forced stop, include any stop note that was supplied. */ if (strcmp (stop_reason_rsp, "tstop") == 0) { - stop_reason_rsp = alloca (strlen ("tstop:") + strlen (buf3) + 1); + stop_reason_rsp = (char *) alloca (strlen ("tstop:") + strlen (buf3) + 1); strcpy (stop_reason_rsp, "tstop:"); strcat (stop_reason_rsp, buf3); } @@ -3389,14 +3695,15 @@ cmd_qtstatus (char *packet) "circular:%d;" "disconn:%d;" "starttime:%s;stoptime:%s;" - "username:%s:;notes:%s:", + "username:%s;notes:%s:", tracing ? 1 : 0, stop_reason_rsp, tracing_stop_tpnum, traceframe_count, traceframes_created, free_space (), phex_nz (trace_buffer_hi - trace_buffer_lo, 0), circular_trace_buffer, disconnected_tracing, - plongest (tracing_start_time), plongest (tracing_stop_time), + phex_nz (tracing_start_time, sizeof (tracing_start_time)), + phex_nz (tracing_stop_time, sizeof (tracing_stop_time)), buf1, buf2); } @@ -3405,7 +3712,7 @@ cmd_qtp (char *own_buf) { ULONGEST num, addr; struct tracepoint *tpoint; - char *packet = own_buf; + const char *packet = own_buf; packet += strlen ("qTP:"); @@ -3424,13 +3731,14 @@ cmd_qtp (char *own_buf) return; } - sprintf (own_buf, "V%lx:%lx", tpoint->hit_count, tpoint->traceframe_usage); + sprintf (own_buf, "V%" PRIu64 ":%" PRIu64 "", tpoint->hit_count, + tpoint->traceframe_usage); } /* State variables to help return all the tracepoint bits. */ static struct tracepoint *cur_tpoint; -static int cur_action; -static int cur_step_action; +static unsigned int cur_action; +static unsigned int cur_step_action; static struct source_string *cur_source_string; static struct trace_state_variable *cur_tsv; @@ -3442,7 +3750,7 @@ response_tracepoint (char *packet, struct tracepoint *tpoint) { char *buf; - sprintf (packet, "T%x:%s:%c:%lx:%lx", tpoint->number, + sprintf (packet, "T%x:%s:%c:%" PRIx64 ":%" PRIx64, tpoint->number, paddress (tpoint->address), (tpoint->enabled ? 'E' : 'D'), tpoint->step_count, tpoint->pass_count); @@ -3486,8 +3794,8 @@ response_source (char *packet, int len; len = strlen (src->str); - buf = alloca (len * 2 + 1); - convert_int_to_ascii ((gdb_byte *) src->str, buf, len); + buf = (char *) alloca (len * 2 + 1); + bin2hex ((gdb_byte *) src->str, buf, len); sprintf (packet, "Z%x:%s:%s:%x:%x:%s", tpoint->number, paddress (tpoint->address), @@ -3504,7 +3812,7 @@ cmd_qtfp (char *packet) trace_debug ("Returning first tracepoint definition piece"); cur_tpoint = tracepoints; - cur_action = cur_step_action = -1; + cur_action = cur_step_action = 0; cur_source_string = NULL; if (cur_tpoint) @@ -3529,17 +3837,17 @@ cmd_qtsp (char *packet) GDB misbehavior. */ strcpy (packet, "l"); } - else if (cur_action < cur_tpoint->numactions - 1) + else if (cur_action < cur_tpoint->numactions) { - ++cur_action; response_action (packet, cur_tpoint, cur_tpoint->actions_str[cur_action], 0); + ++cur_action; } - else if (cur_step_action < cur_tpoint->num_step_actions - 1) + else if (cur_step_action < cur_tpoint->num_step_actions) { - ++cur_step_action; response_action (packet, cur_tpoint, cur_tpoint->step_actions_str[cur_step_action], 1); + ++cur_step_action; } else if ((cur_source_string ? cur_source_string->next @@ -3554,7 +3862,7 @@ cmd_qtsp (char *packet) else { cur_tpoint = cur_tpoint->next; - cur_action = cur_step_action = -1; + cur_action = cur_step_action = 0; cur_source_string = NULL; if (cur_tpoint) response_tracepoint (packet, cur_tpoint); @@ -3575,8 +3883,8 @@ response_tsv (char *packet, struct trace_state_variable *tsv) if (tsv->name) { namelen = strlen (tsv->name); - buf = alloca (namelen * 2 + 1); - convert_int_to_ascii ((gdb_byte *) tsv->name, buf, namelen); + buf = (char *) alloca (namelen * 2 + 1); + bin2hex ((gdb_byte *) tsv->name, buf, namelen); } sprintf (packet, "%x:%s:%x:%s", tsv->number, phex_nz (tsv->initial_value, 0), @@ -3604,15 +3912,9 @@ cmd_qtfv (char *packet) static void cmd_qtsv (char *packet) { - trace_debug ("Returning first trace state variable definition"); + trace_debug ("Returning additional trace state variable definition"); - if (!cur_tpoint) - { - /* This case would normally never occur, but be prepared for - GDB misbehavior. */ - strcpy (packet, "l"); - } - else if (cur_tsv) + if (cur_tsv) { cur_tsv = cur_tsv->next; if (cur_tsv) @@ -3632,7 +3934,7 @@ static void cmd_qtfstm (char *packet) { if (!maybe_write_ipa_ust_not_loaded (packet)) - run_inferior_command (packet); + run_inferior_command (packet, strlen (packet) + 1); } /* Return additional static tracepoints markers. */ @@ -3641,7 +3943,7 @@ static void cmd_qtsstm (char *packet) { if (!maybe_write_ipa_ust_not_loaded (packet)) - run_inferior_command (packet); + run_inferior_command (packet, strlen (packet) + 1); } /* Return the definition of the static tracepoint at a given address. @@ -3651,7 +3953,31 @@ static void cmd_qtstmat (char *packet) { if (!maybe_write_ipa_ust_not_loaded (packet)) - run_inferior_command (packet); + run_inferior_command (packet, strlen (packet) + 1); +} + +/* Sent the agent a command to close it. */ + +void +gdb_agent_about_to_close (int pid) +{ + char buf[IPA_CMD_BUF_SIZE]; + + if (!maybe_write_ipa_not_loaded (buf)) + { + struct thread_info *saved_thread; + + saved_thread = current_thread; + + /* Find any thread which belongs to process PID. */ + current_thread = find_any_thread_of_pid (pid); + + strcpy (buf, "close"); + + run_inferior_command (buf, strlen (buf) + 1); + + current_thread = saved_thread; + } } /* Return the minimum instruction size needed for fast tracepoints as a @@ -3660,7 +3986,7 @@ cmd_qtstmat (char *packet) static void cmd_qtminftpilen (char *packet) { - if (current_inferior == NULL) + if (current_thread == NULL) { /* Indicate that the minimum length is currently unknown. */ strcpy (packet, "0"); @@ -3679,7 +4005,7 @@ cmd_qtbuffer (char *own_buf) { ULONGEST offset, num, tot; unsigned char *tbp; - char *packet = own_buf; + const char *packet = own_buf; packet += strlen ("qTBuffer:"); @@ -3688,7 +4014,7 @@ cmd_qtbuffer (char *own_buf) unpack_varlen_hex (packet, &num); trace_debug ("Want to get trace buffer, %d bytes at offset 0x%s", - (int) num, pulongest (offset)); + (int) num, phex_nz (offset, 0)); tot = (trace_buffer_hi - trace_buffer_lo) - free_space (); @@ -3720,8 +4046,7 @@ cmd_qtbuffer (char *own_buf) if (num >= (PBUFSIZ - 16) / 2 ) num = (PBUFSIZ - 16) / 2; - convert_int_to_ascii (tbp, own_buf, num); - own_buf[num] = '\0'; + bin2hex (tbp, own_buf, num); } static void @@ -3739,6 +4064,37 @@ cmd_bigqtbuffer_circular (char *own_buf) write_ok (own_buf); } +static void +cmd_bigqtbuffer_size (char *own_buf) +{ + ULONGEST val; + LONGEST sval; + char *packet = own_buf; + + /* Can't change the size during a tracing run. */ + if (tracing) + { + write_enn (own_buf); + return; + } + + packet += strlen ("QTBuffer:size:"); + + /* -1 is sent as literal "-1". */ + if (strcmp (packet, "-1") == 0) + sval = DEFAULT_TRACE_BUFFER_SIZE; + else + { + unpack_varlen_hex (packet, &val); + sval = (LONGEST) val; + } + + init_trace_buffer (sval); + trace_debug ("Trace buffer is now %s bytes", + plongest (trace_buffer_size)); + write_ok (own_buf); +} + static void cmd_qtnotes (char *own_buf) { @@ -3750,43 +4106,46 @@ cmd_qtnotes (char *own_buf) while (*packet) { - if (strncmp ("user:", packet, strlen ("user:")) == 0) + if (startswith (packet, "user:")) { packet += strlen ("user:"); saved = packet; packet = strchr (packet, ';'); nbytes = (packet - saved) / 2; - user = xmalloc (nbytes + 1); - nbytes = unhexify (user, saved, nbytes); + user = (char *) xmalloc (nbytes + 1); + nbytes = hex2bin (saved, (gdb_byte *) user, nbytes); user[nbytes] = '\0'; ++packet; /* skip the semicolon */ trace_debug ("User is '%s'", user); + xfree (tracing_user_name); tracing_user_name = user; } - else if (strncmp ("notes:", packet, strlen ("notes:")) == 0) + else if (startswith (packet, "notes:")) { packet += strlen ("notes:"); saved = packet; packet = strchr (packet, ';'); nbytes = (packet - saved) / 2; - notes = xmalloc (nbytes + 1); - nbytes = unhexify (notes, saved, nbytes); + notes = (char *) xmalloc (nbytes + 1); + nbytes = hex2bin (saved, (gdb_byte *) notes, nbytes); notes[nbytes] = '\0'; ++packet; /* skip the semicolon */ trace_debug ("Notes is '%s'", notes); + xfree (tracing_notes); tracing_notes = notes; } - else if (strncmp ("tstop:", packet, strlen ("tstop:")) == 0) + else if (startswith (packet, "tstop:")) { packet += strlen ("tstop:"); saved = packet; packet = strchr (packet, ';'); nbytes = (packet - saved) / 2; - stopnote = xmalloc (nbytes + 1); - nbytes = unhexify (stopnote, saved, nbytes); + stopnote = (char *) xmalloc (nbytes + 1); + nbytes = hex2bin (saved, (gdb_byte *) stopnote, nbytes); stopnote[nbytes] = '\0'; ++packet; /* skip the semicolon */ trace_debug ("tstop note is '%s'", stopnote); + xfree (tracing_stop_note); tracing_stop_note = stopnote; } else @@ -3804,32 +4163,32 @@ handle_tracepoint_general_set (char *packet) cmd_qtinit (packet); return 1; } - else if (strncmp ("QTDP:", packet, strlen ("QTDP:")) == 0) + else if (startswith (packet, "QTDP:")) { cmd_qtdp (packet); return 1; } - else if (strncmp ("QTDPsrc:", packet, strlen ("QTDPsrc:")) == 0) + else if (startswith (packet, "QTDPsrc:")) { cmd_qtdpsrc (packet); return 1; } - else if (strncmp ("QTEnable:", packet, strlen ("QTEnable:")) == 0) + else if (startswith (packet, "QTEnable:")) { cmd_qtenable_disable (packet, 1); return 1; } - else if (strncmp ("QTDisable:", packet, strlen ("QTDisable:")) == 0) + else if (startswith (packet, "QTDisable:")) { cmd_qtenable_disable (packet, 0); return 1; } - else if (strncmp ("QTDV:", packet, strlen ("QTDV:")) == 0) + else if (startswith (packet, "QTDV:")) { cmd_qtdv (packet); return 1; } - else if (strncmp ("QTro:", packet, strlen ("QTro:")) == 0) + else if (startswith (packet, "QTro:")) { cmd_qtro (packet); return 1; @@ -3844,23 +4203,27 @@ handle_tracepoint_general_set (char *packet) cmd_qtstop (packet); return 1; } - else if (strncmp ("QTDisconnected:", packet, - strlen ("QTDisconnected:")) == 0) + else if (startswith (packet, "QTDisconnected:")) { cmd_qtdisconnected (packet); return 1; } - else if (strncmp ("QTFrame:", packet, strlen ("QTFrame:")) == 0) + else if (startswith (packet, "QTFrame:")) { cmd_qtframe (packet); return 1; } - else if (strncmp ("QTBuffer:circular:", packet, strlen ("QTBuffer:circular:")) == 0) + else if (startswith (packet, "QTBuffer:circular:")) { cmd_bigqtbuffer_circular (packet); return 1; } - else if (strncmp ("QTNotes:", packet, strlen ("QTNotes:")) == 0) + else if (startswith (packet, "QTBuffer:size:")) + { + cmd_bigqtbuffer_size (packet); + return 1; + } + else if (startswith (packet, "QTNotes:")) { cmd_qtnotes (packet); return 1; @@ -3877,7 +4240,7 @@ handle_tracepoint_query (char *packet) cmd_qtstatus (packet); return 1; } - else if (strncmp ("qTP:", packet, strlen ("qTP:")) == 0) + else if (startswith (packet, "qTP:")) { cmd_qtp (packet); return 1; @@ -3902,12 +4265,12 @@ handle_tracepoint_query (char *packet) cmd_qtsv (packet); return 1; } - else if (strncmp ("qTV:", packet, strlen ("qTV:")) == 0) + else if (startswith (packet, "qTV:")) { cmd_qtv (packet); return 1; } - else if (strncmp ("qTBuffer:", packet, strlen ("qTBuffer:")) == 0) + else if (startswith (packet, "qTBuffer:")) { cmd_qtbuffer (packet); return 1; @@ -3922,7 +4285,7 @@ handle_tracepoint_query (char *packet) cmd_qtsstm (packet); return 1; } - else if (strncmp ("qTSTMat:", packet, strlen ("qTSTMat:")) == 0) + else if (startswith (packet, "qTSTMat:")) { cmd_qtstmat (packet); return 1; @@ -3962,9 +4325,8 @@ static void add_while_stepping_state (struct thread_info *tinfo, int tp_number, CORE_ADDR tp_address) { - struct wstep_state *wstep; + struct wstep_state *wstep = XNEW (struct wstep_state); - wstep = xmalloc (sizeof (*wstep)); wstep->next = tinfo->while_stepping; wstep->tp_number = tp_number; @@ -4013,7 +4375,7 @@ tracepoint_finished_step (struct thread_info *tinfo, CORE_ADDR stop_pc) /* Pull in fast tracepoint trace frames from the inferior lib buffer into our buffer. */ - if (in_process_agent_loaded ()) + if (agent_loaded_p ()) upload_fast_traceframes (); /* Check if we were indeed collecting data for one of more @@ -4036,7 +4398,7 @@ tracepoint_finished_step (struct thread_info *tinfo, CORE_ADDR stop_pc) wstep_link = &tinfo->while_stepping; trace_debug ("Thread %s finished a single-step for tracepoint %d at 0x%s", - target_pid_to_str (tinfo->entry.id), + target_pid_to_str (tinfo->id), wstep->tp_number, paddress (wstep->tp_address)); ctx.base.type = trap_tracepoint; @@ -4049,7 +4411,7 @@ tracepoint_finished_step (struct thread_info *tinfo, CORE_ADDR stop_pc) { trace_debug ("NO TRACEPOINT %d at 0x%s FOR THREAD %s!", wstep->tp_number, paddress (wstep->tp_address), - target_pid_to_str (tinfo->entry.id)); + target_pid_to_str (tinfo->id)); /* Unlink. */ *wstep_link = wstep->next; @@ -4069,7 +4431,7 @@ tracepoint_finished_step (struct thread_info *tinfo, CORE_ADDR stop_pc) { /* The requested numbers of steps have occurred. */ trace_debug ("Thread %s done stepping for tracepoint %d at 0x%s", - target_pid_to_str (tinfo->entry.id), + target_pid_to_str (tinfo->id), wstep->tp_number, paddress (wstep->tp_address)); /* Unlink the wstep. */ @@ -4114,7 +4476,7 @@ handle_tracepoint_bkpts (struct thread_info *tinfo, CORE_ADDR stop_pc) /* Pull in fast tracepoint trace frames from the inferior in-process agent's buffer into our buffer. */ - if (!in_process_agent_loaded ()) + if (!agent_loaded_p ()) return 0; upload_fast_traceframes (); @@ -4160,7 +4522,7 @@ handle_tracepoint_bkpts (struct thread_info *tinfo, CORE_ADDR stop_pc) trace_debug ("lib stopped due to full buffer."); if (ipa_stopping_tracepoint) trace_debug ("lib stopped due to tpoint"); - if (ipa_stopping_tracepoint) + if (ipa_error_tracepoint) trace_debug ("lib stopped due to error"); } @@ -4216,7 +4578,7 @@ tracepoint_was_hit (struct thread_info *tinfo, CORE_ADDR stop_pc) && tpoint->type != static_tracepoint) { trace_debug ("Thread %s at address of tracepoint %d at 0x%s", - target_pid_to_str (tinfo->entry.id), + target_pid_to_str (tinfo->id), tpoint->number, paddress (tpoint->address)); /* Test the condition if present, and collect if true. */ @@ -4279,7 +4641,7 @@ collect_data_at_tracepoint (struct tracepoint_hit_ctx *ctx, CORE_ADDR stop_pc, && stopping_tracepoint == NULL) stopping_tracepoint = tpoint; - trace_debug ("Making new traceframe for tracepoint %d at 0x%s, hit %ld", + trace_debug ("Making new traceframe for tracepoint %d at 0x%s, hit %" PRIu64, tpoint->number, paddress (tpoint->address), tpoint->hit_count); tframe = add_traceframe (tpoint); @@ -4316,7 +4678,7 @@ collect_data_at_step (struct tracepoint_hit_ctx *ctx, int acti; trace_debug ("Making new step traceframe for " - "tracepoint %d at 0x%s, step %d of %ld, hit %ld", + "tracepoint %d at 0x%s, step %d of %" PRIu64 ", hit %" PRIu64, tpoint->number, paddress (tpoint->address), current_step, tpoint->step_count, tpoint->hit_count); @@ -4344,19 +4706,28 @@ collect_data_at_step (struct tracepoint_hit_ctx *ctx, #endif +#ifdef IN_PROCESS_AGENT +/* The target description index for IPA. Passed from gdbserver, used + to select ipa_tdesc. */ +EXTERN_C_PUSH +IP_AGENT_EXPORT_VAR int ipa_tdesc_idx; +EXTERN_C_POP +#endif + static struct regcache * get_context_regcache (struct tracepoint_hit_ctx *ctx) { struct regcache *regcache = NULL; - #ifdef IN_PROCESS_AGENT + const struct target_desc *ipa_tdesc = get_ipa_tdesc (ipa_tdesc_idx); + if (ctx->type == fast_tracepoint) { struct fast_tracepoint_ctx *fctx = (struct fast_tracepoint_ctx *) ctx; if (!fctx->regcache_initted) { fctx->regcache_initted = 1; - init_register_cache (&fctx->regcache, fctx->regspace); + init_register_cache (&fctx->regcache, ipa_tdesc, fctx->regspace); supply_regblock (&fctx->regcache, NULL); supply_fast_tracepoint_registers (&fctx->regcache, fctx->regs); } @@ -4371,7 +4742,7 @@ get_context_regcache (struct tracepoint_hit_ctx *ctx) if (!sctx->regcache_initted) { sctx->regcache_initted = 1; - init_register_cache (&sctx->regcache, sctx->regspace); + init_register_cache (&sctx->regcache, ipa_tdesc, sctx->regspace); supply_regblock (&sctx->regcache, NULL); /* Pass down the tracepoint address, because REGS doesn't include the PC, but we know what it must have been. */ @@ -4410,15 +4781,19 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx, case 'M': { struct collect_memory_action *maction; + struct eval_agent_expr_context ax_ctx; maction = (struct collect_memory_action *) taction; + ax_ctx.regcache = NULL; + ax_ctx.tframe = tframe; + ax_ctx.tpoint = tpoint; trace_debug ("Want to collect %s bytes at 0x%s (basereg %d)", pulongest (maction->len), paddress (maction->addr), maction->basereg); /* (should use basereg) */ - agent_mem_read (tframe, NULL, - (CORE_ADDR) maction->addr, maction->len); + agent_mem_read (&ax_ctx, NULL, (CORE_ADDR) maction->addr, + maction->len); break; } case 'R': @@ -4426,13 +4801,15 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx, unsigned char *regspace; struct regcache tregcache; struct regcache *context_regcache; - + int regcache_size; trace_debug ("Want to collect registers"); + context_regcache = get_context_regcache (ctx); + regcache_size = register_cache_size (context_regcache->tdesc); + /* Collect all registers for now. */ - regspace = add_traceframe_block (tframe, - 1 + register_cache_size ()); + regspace = add_traceframe_block (tframe, tpoint, 1 + regcache_size); if (regspace == NULL) { trace_debug ("Trace buffer block allocation failed, skipping"); @@ -4441,11 +4818,10 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx, /* Identify a register block. */ *regspace = 'R'; - context_regcache = get_context_regcache (ctx); - /* Wrap the regblock in a register cache (in the stack, we don't want to malloc here). */ - init_register_cache (&tregcache, regspace + 1); + init_register_cache (&tregcache, context_regcache->tdesc, + regspace + 1); /* Copy the register data to the regblock. */ regcache_cpy (&tregcache, context_regcache); @@ -4473,12 +4849,16 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx, case 'X': { struct eval_expr_action *eaction; + struct eval_agent_expr_context ax_ctx; eaction = (struct eval_expr_action *) taction; + ax_ctx.regcache = get_context_regcache (ctx); + ax_ctx.tframe = tframe; + ax_ctx.tpoint = tpoint; trace_debug ("Want to evaluate expression"); - err = eval_tracepoint_agent_expr (ctx, tframe, eaction->expr, NULL); + err = gdb_eval_agent_expr (&ax_ctx, eaction->expr, NULL); if (err != expr_eval_no_error) { @@ -4527,11 +4907,21 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx, used. */ #ifdef IN_PROCESS_AGENT if (tpoint->compiled_cond) - err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value); + { + struct fast_tracepoint_ctx *fctx = (struct fast_tracepoint_ctx *) ctx; + err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (fctx->regs, &value); + } else #endif - err = eval_tracepoint_agent_expr (ctx, NULL, tpoint->cond, &value); + { + struct eval_agent_expr_context ax_ctx; + ax_ctx.regcache = get_context_regcache (ctx); + ax_ctx.tframe = NULL; + ax_ctx.tpoint = tpoint; + + err = gdb_eval_agent_expr (&ax_ctx, tpoint->cond, &value); + } if (err != expr_eval_no_error) { record_tracepoint_error (tpoint, "condition", err); @@ -4545,27 +4935,11 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx, return (value ? 1 : 0); } -/* Evaluates a tracepoint agent expression with context CTX, - traceframe TFRAME, agent expression AEXPR and store the - result in RSLT. */ - -static enum eval_result_type -eval_tracepoint_agent_expr (struct tracepoint_hit_ctx *ctx, - struct traceframe *tframe, - struct agent_expr *aexpr, - ULONGEST *rslt) -{ - struct regcache *regcache; - regcache = get_context_regcache (ctx); - - return gdb_eval_agent_expr (regcache, tframe, aexpr, rslt); -} - /* Do memory copies for bytecodes. */ /* Do the recording of memory blocks for actions and bytecodes. */ int -agent_mem_read (struct traceframe *tframe, +agent_mem_read (struct eval_agent_expr_context *ctx, unsigned char *to, CORE_ADDR from, ULONGEST len) { unsigned char *mspace; @@ -4586,7 +4960,7 @@ agent_mem_read (struct traceframe *tframe, blocklen = (remaining > 65535 ? 65535 : remaining); sp = 1 + sizeof (from) + sizeof (blocklen) + blocklen; - mspace = add_traceframe_block (tframe, sp); + mspace = add_traceframe_block (ctx->tframe, ctx->tpoint, sp); if (mspace == NULL) return 1; /* Identify block as a memory block. */ @@ -4607,7 +4981,7 @@ agent_mem_read (struct traceframe *tframe, } int -agent_mem_read_string (struct traceframe *tframe, +agent_mem_read_string (struct eval_agent_expr_context *ctx, unsigned char *to, CORE_ADDR from, ULONGEST len) { unsigned char *buf, *mspace; @@ -4643,7 +5017,7 @@ agent_mem_read_string (struct traceframe *tframe, } } sp = 1 + sizeof (from) + sizeof (blocklen) + blocklen; - mspace = add_traceframe_block (tframe, sp); + mspace = add_traceframe_block (ctx->tframe, ctx->tpoint, sp); if (mspace == NULL) { xfree (buf); @@ -4669,12 +5043,12 @@ agent_mem_read_string (struct traceframe *tframe, /* Record the value of a trace state variable. */ int -agent_tsv_read (struct traceframe *tframe, int n) +agent_tsv_read (struct eval_agent_expr_context *ctx, int n) { unsigned char *vspace; LONGEST val; - vspace = add_traceframe_block (tframe, + vspace = add_traceframe_block (ctx->tframe, ctx->tpoint, 1 + sizeof (n) + sizeof (LONGEST)); if (vspace == NULL) return 1; @@ -4696,7 +5070,7 @@ agent_tsv_read (struct traceframe *tframe, int n) static int match_blocktype (char blocktype, unsigned char *dataptr, void *data) { - char *wantedp = data; + char *wantedp = (char *) data; if (*wantedp == blocktype) return 1; @@ -4753,7 +5127,7 @@ traceframe_walk_blocks (unsigned char *database, unsigned int datasize, { case 'R': /* Skip over the registers block. */ - dataptr += register_cache_size (); + dataptr += current_target_desc ()->registers_size; break; case 'M': /* Skip over the memory block. */ @@ -4848,12 +5222,13 @@ traceframe_get_pc (struct traceframe *tframe) { struct regcache regcache; unsigned char *dataptr; + const struct target_desc *tdesc = current_target_desc (); dataptr = traceframe_find_regblock (tframe, -1); if (dataptr == NULL) return 0; - init_register_cache (®cache, dataptr); + init_register_cache (®cache, tdesc, dataptr); return regcache_read_pc (®cache); } @@ -4924,15 +5299,17 @@ traceframe_read_mem (int tfnum, CORE_ADDR addr, static int traceframe_read_tsv (int tsvnum, LONGEST *val) { + client_state &cs = get_client_state (); int tfnum; struct traceframe *tframe; unsigned char *database, *dataptr; unsigned int datasize; int vnum; + int found = 0; trace_debug ("traceframe_read_tsv"); - tfnum = current_traceframe; + tfnum = cs.current_traceframe; if (tfnum < 0) { @@ -4951,7 +5328,8 @@ traceframe_read_tsv (int tsvnum, LONGEST *val) datasize = tframe->data_size; database = dataptr = &tframe->data[0]; - /* Iterate through a traceframe's blocks, looking for the tsv. */ + /* Iterate through a traceframe's blocks, looking for the last + matched tsv. */ while ((dataptr = traceframe_find_block_type (dataptr, datasize - (dataptr - database), @@ -4966,16 +5344,17 @@ traceframe_read_tsv (int tsvnum, LONGEST *val) if (tsvnum == vnum) { memcpy (val, dataptr, sizeof (*val)); - return 0; + found = 1; } /* Skip over this block. */ dataptr += sizeof (LONGEST); } - trace_debug ("traceframe %d has no data for variable %d", - tfnum, tsvnum); - return 1; + if (!found) + trace_debug ("traceframe %d has no data for variable %d", + tfnum, tsvnum); + return !found; } /* Read a requested block of static tracepoint data from a trace @@ -5038,7 +5417,7 @@ traceframe_read_sdata (int tfnum, ULONGEST offset, static int build_traceframe_info_xml (char blocktype, unsigned char *dataptr, void *data) { - struct buffer *buffer = data; + struct buffer *buffer = (struct buffer *) data; switch (blocktype) { @@ -5057,6 +5436,13 @@ build_traceframe_info_xml (char blocktype, unsigned char *dataptr, void *data) break; } case 'V': + { + int vnum; + + memcpy (&vnum, dataptr, sizeof (vnum)); + buffer_xml_printf (buffer, "\n", vnum); + break; + } case 'R': case 'S': { @@ -5184,7 +5570,7 @@ force_unlock_trace_buffer (void) case, if we want to move the thread out of the jump pad, we need to single-step it until this function returns 0. */ -int +fast_tpoint_collect_result fast_tracepoint_collecting (CORE_ADDR thread_area, CORE_ADDR stop_pc, struct fast_tpoint_collect_status *status) @@ -5226,17 +5612,29 @@ fast_tracepoint_collecting (CORE_ADDR thread_area, if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_jump_pad_buffer, &ipa_gdb_jump_pad_buffer)) - fatal ("error extracting `gdb_jump_pad_buffer'"); + { + internal_error (__FILE__, __LINE__, + "error extracting `gdb_jump_pad_buffer'"); + } if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_jump_pad_buffer_end, &ipa_gdb_jump_pad_buffer_end)) - fatal ("error extracting `gdb_jump_pad_buffer_end'"); + { + internal_error (__FILE__, __LINE__, + "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'"); + { + internal_error (__FILE__, __LINE__, + "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'"); + { + internal_error (__FILE__, __LINE__, + "error extracting `gdb_trampoline_buffer_end'"); + } if (ipa_gdb_jump_pad_buffer <= stop_pc && stop_pc < ipa_gdb_jump_pad_buffer_end) @@ -5247,7 +5645,7 @@ fast_tracepoint_collecting (CORE_ADDR thread_area, if (tpoint == NULL) { warning ("in jump pad, but no matching tpoint?"); - return 0; + return fast_tpoint_collect_result::not_collecting; } else { @@ -5275,7 +5673,7 @@ fast_tracepoint_collecting (CORE_ADDR thread_area, if (tpoint == NULL) { warning ("in trampoline, but no matching tpoint?"); - return 0; + return fast_tpoint_collect_result::not_collecting; } else { @@ -5303,14 +5701,14 @@ fast_tracepoint_collecting (CORE_ADDR thread_area, { trace_debug ("fast_tracepoint_collecting:" " failed reading 'collecting' in the inferior"); - return 0; + return fast_tpoint_collect_result::not_collecting; } if (!ipa_collecting) { trace_debug ("fast_tracepoint_collecting: not collecting" " (and nobody is)."); - return 0; + return fast_tpoint_collect_result::not_collecting; } /* Some thread is collecting. Check which. */ @@ -5323,7 +5721,7 @@ fast_tracepoint_collecting (CORE_ADDR thread_area, { trace_debug ("fast_tracepoint_collecting: not collecting " "(another thread is)"); - return 0; + return fast_tpoint_collect_result::not_collecting; } tpoint @@ -5333,7 +5731,7 @@ fast_tracepoint_collecting (CORE_ADDR thread_area, warning ("fast_tracepoint_collecting: collecting, " "but tpoint %s not found?", paddress ((CORE_ADDR) ipa_collecting_obj.tpoint)); - return 0; + return fast_tpoint_collect_result::not_collecting; } /* The thread is within `gdb_collect', skip over the rest of @@ -5360,7 +5758,7 @@ fast_tracepoint_collecting (CORE_ADDR thread_area, fast_tracepoint_collecting, returning continue-until-break at %s", paddress (tpoint->adjusted_insn_addr)); - return 1; /* continue */ + return fast_tpoint_collect_result::before_insn; /* continue */ } else { @@ -5371,7 +5769,7 @@ fast_tracepoint_collecting, returning continue-until-break at %s", paddress (tpoint->adjusted_insn_addr), paddress (tpoint->adjusted_insn_addr_end)); - return 2; /* single-step */ + return fast_tpoint_collect_result::at_insn; /* single-step */ } } @@ -5384,27 +5782,31 @@ fast_tracepoint_collecting, returning continue-until-break at %s", NULL if it isn't locked. Note that this lock *must* be set while executing any *function other than the jump pad. See fast_tracepoint_collecting. */ -static collecting_t * ATTR_USED collecting; +EXTERN_C_PUSH +IP_AGENT_EXPORT_VAR collecting_t *collecting; +EXTERN_C_POP /* This routine, called from the jump pad (in asm) is designed to be called from the jump pads of fast tracepoints, thus it is on the critical path. */ -IP_AGENT_EXPORT void ATTR_USED +IP_AGENT_EXPORT_FUNC void gdb_collect (struct tracepoint *tpoint, unsigned char *regs) { struct fast_tracepoint_ctx ctx; + const struct target_desc *ipa_tdesc; /* Don't do anything until the trace run is completely set up. */ if (!tracing) return; + ipa_tdesc = get_ipa_tdesc (ipa_tdesc_idx); ctx.base.type = fast_tracepoint; ctx.regs = regs; ctx.regcache_initted = 0; /* Wrap the regblock in a register cache (in the stack, we don't want to malloc here). */ - ctx.regspace = alloca (register_cache_size ()); + ctx.regspace = (unsigned char *) alloca (ipa_tdesc->registers_size); if (ctx.regspace == NULL) { trace_debug ("Trace buffer block allocation failed, skipping"); @@ -5457,6 +5859,25 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs) } } +/* These global variables points to the corresponding functions. This is + necessary on powerpc64, where asking for function symbol address from gdb + results in returning the actual code pointer, instead of the descriptor + pointer. */ + +typedef void (*gdb_collect_ptr_type) (struct tracepoint *, unsigned char *); +typedef ULONGEST (*get_raw_reg_ptr_type) (const unsigned char *, int); +typedef LONGEST (*get_trace_state_variable_value_ptr_type) (int); +typedef void (*set_trace_state_variable_value_ptr_type) (int, LONGEST); + +EXTERN_C_PUSH +IP_AGENT_EXPORT_VAR gdb_collect_ptr_type gdb_collect_ptr = gdb_collect; +IP_AGENT_EXPORT_VAR get_raw_reg_ptr_type get_raw_reg_ptr = get_raw_reg; +IP_AGENT_EXPORT_VAR get_trace_state_variable_value_ptr_type + get_trace_state_variable_value_ptr = get_trace_state_variable_value; +IP_AGENT_EXPORT_VAR set_trace_state_variable_value_ptr_type + set_trace_state_variable_value_ptr = set_trace_state_variable_value; +EXTERN_C_POP + #endif #ifndef IN_PROCESS_AGENT @@ -5464,19 +5885,39 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs) CORE_ADDR get_raw_reg_func_addr (void) { - return ipa_sym_addrs.addr_get_raw_reg; + CORE_ADDR res; + if (read_inferior_data_pointer (ipa_sym_addrs.addr_get_raw_reg_ptr, &res)) + { + error ("error extracting get_raw_reg_ptr"); + return 0; + } + return res; } CORE_ADDR get_get_tsv_func_addr (void) { - return ipa_sym_addrs.addr_get_trace_state_variable_value; + CORE_ADDR res; + if (read_inferior_data_pointer ( + ipa_sym_addrs.addr_get_trace_state_variable_value_ptr, &res)) + { + error ("error extracting get_trace_state_variable_value_ptr"); + return 0; + } + return res; } CORE_ADDR get_set_tsv_func_addr (void) { - return ipa_sym_addrs.addr_set_trace_state_variable_value; + CORE_ADDR res; + if (read_inferior_data_pointer ( + ipa_sym_addrs.addr_set_trace_state_variable_value_ptr, &res)) + { + error ("error extracting set_trace_state_variable_value_ptr"); + return 0; + } + return res; } static void @@ -5526,16 +5967,6 @@ compile_tracepoint_condition (struct tracepoint *tpoint, *jump_entry += 16; } -/* We'll need to adjust these when we consider bi-arch setups, and big - endian machines. */ - -static int -write_inferior_data_ptr (CORE_ADDR where, CORE_ADDR ptr) -{ - return write_inferior_memory (where, - (unsigned char *) &ptr, sizeof (void *)); -} - /* The base pointer of the IPA's heap. This is the only memory the IPA is allowed to use. The IPA should _not_ call the inferior's `malloc' during operation. That'd be slow, and, most importantly, @@ -5556,7 +5987,10 @@ target_malloc (ULONGEST size) /* We have the pointer *address*, need what it points to. */ if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_tp_heap_buffer, &target_tp_heap)) - fatal ("could get target heap head pointer"); + { + internal_error (__FILE__, __LINE__, + "couldn't get target heap head pointer"); + } } ptr = target_tp_heap; @@ -5578,8 +6012,8 @@ download_agent_expr (struct agent_expr *expr) write_inferior_memory (expr_addr, (unsigned char *) expr, sizeof (*expr)); expr_bytes = target_malloc (expr->length); - write_inferior_data_ptr (expr_addr + offsetof (struct agent_expr, bytes), - expr_bytes); + write_inferior_data_pointer (expr_addr + offsetof (struct agent_expr, bytes), + expr_bytes); write_inferior_memory (expr_bytes, expr->bytes, expr->length); return expr_addr; @@ -5637,9 +6071,9 @@ download_tracepoint_1 (struct tracepoint *tpoint) sizeof (target_tracepoint)); if (tpoint->cond) - write_inferior_data_ptr (tpptr + offsetof (struct tracepoint, - cond), - download_agent_expr (tpoint->cond)); + write_inferior_data_pointer (tpptr + + offsetof (struct tracepoint, cond), + download_agent_expr (tpoint->cond)); if (tpoint->numactions) { @@ -5649,71 +6083,109 @@ download_tracepoint_1 (struct tracepoint *tpoint) /* The pointers array. */ actions_array = target_malloc (sizeof (*tpoint->actions) * tpoint->numactions); - write_inferior_data_ptr (tpptr + offsetof (struct tracepoint, - actions), - actions_array); + write_inferior_data_pointer (tpptr + offsetof (struct tracepoint, + actions), + actions_array); /* Now for each pointer, download the action. */ for (i = 0; i < tpoint->numactions; i++) { - CORE_ADDR ipa_action = 0; struct tracepoint_action *action = tpoint->actions[i]; - - switch (action->type) - { - case 'M': - ipa_action - = target_malloc (sizeof (struct collect_memory_action)); - write_inferior_memory (ipa_action, - (unsigned char *) action, - sizeof (struct collect_memory_action)); - break; - case 'R': - ipa_action - = target_malloc (sizeof (struct collect_registers_action)); - write_inferior_memory (ipa_action, - (unsigned char *) action, - sizeof (struct collect_registers_action)); - break; - case 'X': - { - CORE_ADDR expr; - struct eval_expr_action *eaction - = (struct eval_expr_action *) action; - - ipa_action = target_malloc (sizeof (*eaction)); - write_inferior_memory (ipa_action, - (unsigned char *) eaction, - sizeof (*eaction)); - - expr = download_agent_expr (eaction->expr); - write_inferior_data_ptr - (ipa_action + offsetof (struct eval_expr_action, expr), - expr); - break; - } - case 'L': - ipa_action = target_malloc - (sizeof (struct collect_static_trace_data_action)); - write_inferior_memory - (ipa_action, - (unsigned char *) action, - sizeof (struct collect_static_trace_data_action)); - break; - default: - trace_debug ("unknown trace action '%c', ignoring", - action->type); - break; - } + CORE_ADDR ipa_action = tracepoint_action_download (action); if (ipa_action != 0) - write_inferior_data_ptr - (actions_array + i * sizeof (sizeof (*tpoint->actions)), - ipa_action); + write_inferior_data_pointer (actions_array + + i * sizeof (*tpoint->actions), + ipa_action); } } } +#define IPA_PROTO_FAST_TRACE_FLAG 0 +#define IPA_PROTO_FAST_TRACE_ADDR_ON_TARGET 2 +#define IPA_PROTO_FAST_TRACE_JUMP_PAD 10 +#define IPA_PROTO_FAST_TRACE_FJUMP_SIZE 18 +#define IPA_PROTO_FAST_TRACE_FJUMP_INSN 22 + +/* Send a command to agent to download and install tracepoint TPOINT. */ + +static int +tracepoint_send_agent (struct tracepoint *tpoint) +{ + char buf[IPA_CMD_BUF_SIZE]; + char *p; + int i, ret; + + p = buf; + strcpy (p, "FastTrace:"); + p += 10; + + COPY_FIELD_TO_BUF (p, tpoint, number); + COPY_FIELD_TO_BUF (p, tpoint, address); + COPY_FIELD_TO_BUF (p, tpoint, type); + COPY_FIELD_TO_BUF (p, tpoint, enabled); + COPY_FIELD_TO_BUF (p, tpoint, step_count); + COPY_FIELD_TO_BUF (p, tpoint, pass_count); + COPY_FIELD_TO_BUF (p, tpoint, numactions); + COPY_FIELD_TO_BUF (p, tpoint, hit_count); + COPY_FIELD_TO_BUF (p, tpoint, traceframe_usage); + COPY_FIELD_TO_BUF (p, tpoint, compiled_cond); + COPY_FIELD_TO_BUF (p, tpoint, orig_size); + + /* condition */ + p = agent_expr_send (p, tpoint->cond); + + /* tracepoint_action */ + for (i = 0; i < tpoint->numactions; i++) + { + struct tracepoint_action *action = tpoint->actions[i]; + + p[0] = action->type; + p = tracepoint_action_send (&p[1], action); + } + + get_jump_space_head (); + /* Copy the value of GDB_JUMP_PAD_HEAD to command buffer, so that + agent can use jump pad from it. */ + if (tpoint->type == fast_tracepoint) + { + memcpy (p, &gdb_jump_pad_head, 8); + p += 8; + } + + ret = run_inferior_command (buf, (int) (ptrdiff_t) (p - buf)); + if (ret) + return ret; + + if (!startswith (buf, "OK")) + return 1; + + /* The value of tracepoint's target address is stored in BUF. */ + memcpy (&tpoint->obj_addr_on_target, + &buf[IPA_PROTO_FAST_TRACE_ADDR_ON_TARGET], 8); + + if (tpoint->type == fast_tracepoint) + { + unsigned char *insn + = (unsigned char *) &buf[IPA_PROTO_FAST_TRACE_FJUMP_INSN]; + int fjump_size; + + trace_debug ("agent: read from cmd_buf 0x%x 0x%x\n", + (unsigned int) tpoint->obj_addr_on_target, + (unsigned int) gdb_jump_pad_head); + + memcpy (&gdb_jump_pad_head, &buf[IPA_PROTO_FAST_TRACE_JUMP_PAD], 8); + + /* This has been done in agent. We should also set up record for it. */ + memcpy (&fjump_size, &buf[IPA_PROTO_FAST_TRACE_FJUMP_SIZE], 4); + /* Wire it in. */ + tpoint->handle + = set_fast_tracepoint_jump (tpoint->address, insn, fjump_size); + } + + return 0; +} + static void download_tracepoint (struct tracepoint *tpoint) { @@ -5742,61 +6214,28 @@ download_tracepoint (struct tracepoint *tpoint) if (read_inferior_data_pointer (tp_prev->obj_addr_on_target + offsetof (struct tracepoint, next), &tp_prev_target_next_addr)) - fatal ("error reading `tp_prev->next'"); + { + internal_error (__FILE__, __LINE__, + "error reading `tp_prev->next'"); + } /* tpoint->next = tp_prev->next */ - write_inferior_data_ptr (tpoint->obj_addr_on_target - + offsetof (struct tracepoint, next), - tp_prev_target_next_addr); + write_inferior_data_pointer (tpoint->obj_addr_on_target + + offsetof (struct tracepoint, next), + tp_prev_target_next_addr); /* tp_prev->next = tpoint */ - write_inferior_data_ptr (tp_prev->obj_addr_on_target - + offsetof (struct tracepoint, next), - tpoint->obj_addr_on_target); + write_inferior_data_pointer (tp_prev->obj_addr_on_target + + offsetof (struct tracepoint, next), + tpoint->obj_addr_on_target); } else /* First object in list, set the head pointer in the inferior. */ - write_inferior_data_ptr (ipa_sym_addrs.addr_tracepoints, - tpoint->obj_addr_on_target); + write_inferior_data_pointer (ipa_sym_addrs.addr_tracepoints, + tpoint->obj_addr_on_target); } -static void -download_tracepoints (void) -{ - CORE_ADDR tpptr = 0, prev_tpptr = 0; - struct tracepoint *tpoint; - - /* Start out empty. */ - write_inferior_data_ptr (ipa_sym_addrs.addr_tracepoints, 0); - - for (tpoint = tracepoints; tpoint; tpoint = tpoint->next) - { - if (tpoint->type != fast_tracepoint - && tpoint->type != static_tracepoint) - continue; - - prev_tpptr = tpptr; - - download_tracepoint_1 (tpoint); - - tpptr = tpoint->obj_addr_on_target; - - if (tpoint == tracepoints) - { - /* First object in list, set the head pointer in the - inferior. */ - write_inferior_data_ptr (ipa_sym_addrs.addr_tracepoints, tpptr); - } - else - { - write_inferior_data_ptr (prev_tpptr + offsetof (struct tracepoint, - next), - tpptr); - } - } -} - static void download_trace_state_variables (void) { @@ -5804,7 +6243,7 @@ download_trace_state_variables (void) struct trace_state_variable *tsv; /* Start out empty. */ - write_inferior_data_ptr (ipa_sym_addrs.addr_trace_state_variables, 0); + write_inferior_data_pointer (ipa_sym_addrs.addr_trace_state_variables, 0); for (tsv = trace_state_variables; tsv != NULL; tsv = tsv->next) { @@ -5825,15 +6264,15 @@ download_trace_state_variables (void) /* First object in list, set the head pointer in the inferior. */ - write_inferior_data_ptr (ipa_sym_addrs.addr_trace_state_variables, - ptr); + write_inferior_data_pointer (ipa_sym_addrs.addr_trace_state_variables, + ptr); } else { - write_inferior_data_ptr (prev_ptr - + offsetof (struct trace_state_variable, - next), - ptr); + write_inferior_data_pointer (prev_ptr + + offsetof (struct trace_state_variable, + next), + ptr); } /* Write the whole object. We'll fix up its pointers in a bit. @@ -5849,24 +6288,21 @@ download_trace_state_variables (void) CORE_ADDR name_addr = target_malloc (size); write_inferior_memory (name_addr, (unsigned char *) tsv->name, size); - write_inferior_data_ptr (ptr - + offsetof (struct trace_state_variable, - name), - name_addr); + write_inferior_data_pointer (ptr + + offsetof (struct trace_state_variable, + name), + name_addr); } - if (tsv->getter != NULL) - { - fatal ("what to do with these?"); - } + gdb_assert (tsv->getter == NULL); } if (prev_ptr != 0) { /* Fixup the next pointer in the last item in the list. */ - write_inferior_data_ptr (prev_ptr - + offsetof (struct trace_state_variable, - next), 0); + write_inferior_data_pointer (prev_ptr + + offsetof (struct trace_state_variable, + next), 0); } } @@ -6031,9 +6467,13 @@ upload_fast_traceframes (void) error ("Uploading: couldn't read traceframe at %s\n", paddress (tf)); if (ipa_tframe.tpnum == 0) - fatal ("Uploading: No (more) fast traceframes, but " - "ipa_traceframe_count == %u??\n", - ipa_traceframe_write_count - ipa_traceframe_read_count); + { + internal_error (__FILE__, __LINE__, + "Uploading: No (more) fast traceframes, but" + " ipa_traceframe_count == %u??\n", + ipa_traceframe_write_count + - ipa_traceframe_read_count); + } /* Note that this will be incorrect for multi-location tracepoints... */ @@ -6049,7 +6489,8 @@ upload_fast_traceframes (void) { /* Copy the whole set of blocks in one go for now. FIXME: split this in smaller blocks. */ - block = add_traceframe_block (tframe, ipa_tframe.data_size); + block = add_traceframe_block (tframe, tpoint, + ipa_tframe.data_size); if (block != NULL) { if (read_inferior_memory (tf @@ -6118,7 +6559,6 @@ upload_fast_traceframes (void) trace_debug ("Done uploading traceframes [%d]\n", curr_tbctrl_idx); pause_all (1); - cancel_breakpoints (); delete_breakpoint (about_to_request_buffer_space_bkpt); about_to_request_buffer_space_bkpt = NULL; @@ -6132,8 +6572,8 @@ upload_fast_traceframes (void) #ifdef IN_PROCESS_AGENT -IP_AGENT_EXPORT int ust_loaded; -IP_AGENT_EXPORT char cmd_buf[IPA_CMD_BUF_SIZE]; +IP_AGENT_EXPORT_VAR int ust_loaded; +IP_AGENT_EXPORT_VAR char cmd_buf[IPA_CMD_BUF_SIZE]; #ifdef HAVE_UST @@ -6245,6 +6685,7 @@ gdb_probe (const struct marker *mdata, void *probe_private, { struct tracepoint *tpoint; struct static_tracepoint_ctx ctx; + const struct target_desc *ipa_tdesc; /* Don't do anything until the trace run is completely set up. */ if (!tracing) @@ -6253,6 +6694,7 @@ gdb_probe (const struct marker *mdata, void *probe_private, return; } + ipa_tdesc = get_ipa_tdesc (ipa_tdesc_idx); ctx.base.type = static_tracepoint; ctx.regcache_initted = 0; ctx.regs = regs; @@ -6261,7 +6703,7 @@ gdb_probe (const struct marker *mdata, void *probe_private, /* Wrap the regblock in a register cache (in the stack, we don't want to malloc here). */ - ctx.regspace = alloca (register_cache_size ()); + ctx.regspace = alloca (ipa_tdesc->registers_size); if (ctx.regspace == NULL) { trace_debug ("Trace buffer block allocation failed, skipping"); @@ -6348,7 +6790,7 @@ collect_ust_data_at_tracepoint (struct tracepoint_hit_ctx *ctx, trace_debug ("Want to collect ust data"); /* 'S' + size + string */ - bufspace = add_traceframe_block (tframe, + bufspace = add_traceframe_block (tframe, umd->tpoint, 1 + sizeof (blocklen) + size + 1); if (bufspace == NULL) { @@ -6392,17 +6834,17 @@ static struct ltt_available_probe gdb_ust_probe = synchronization. */ static int -run_inferior_command (char *cmd) +run_inferior_command (char *cmd, int len) { int err = -1; - int pid = ptid_get_pid (current_inferior->entry.id); + int pid = current_ptid.pid (); trace_debug ("run_inferior_command: running: %s", cmd); pause_all (0); uninsert_all_breakpoints (); - err = agent_run_command (pid, (const char *) cmd); + err = agent_run_command (pid, (const char *) cmd, len); reinsert_all_breakpoints (); unpause_all (0); @@ -6424,7 +6866,9 @@ run_inferior_command (char *cmd) /* Thread ID of the helper thread. GDBserver reads this to know which is the help thread. This is an LWP id on Linux. */ -int helper_thread_id; +EXTERN_C_PUSH +IP_AGENT_EXPORT_VAR int helper_thread_id; +EXTERN_C_POP static int init_named_socket (const char *name) @@ -6477,13 +6921,14 @@ init_named_socket (const char *name) return fd; } +static char agent_socket_name[UNIX_PATH_MAX]; + static int gdb_agent_socket_init (void) { int result, fd; - char name[UNIX_PATH_MAX]; - result = xsnprintf (name, UNIX_PATH_MAX, "%s/gdb_ust%d", + result = xsnprintf (agent_socket_name, UNIX_PATH_MAX, "%s/gdb_ust%d", SOCK_DIR, getpid ()); if (result >= UNIX_PATH_MAX) { @@ -6491,11 +6936,11 @@ gdb_agent_socket_init (void) return -1; } - fd = init_named_socket (name); + fd = init_named_socket (agent_socket_name); if (fd < 0) warning ("Error initializing named socket (%s) for communication with the " "ust helper thread. Check that directory exists and that it " - "is writable.", name); + "is writable.", agent_socket_name); return fd; } @@ -6548,7 +6993,7 @@ cstr_to_hexstr (const char *str) { int len = strlen (str); char *hexstr = xmalloc (len * 2 + 1); - convert_int_to_ascii ((gdb_byte *) str, hexstr, len); + bin2hex ((gdb_byte *) str, hexstr, len); return hexstr; } @@ -6725,6 +7170,12 @@ gdb_ust_init (void) #include +static void +gdb_agent_remove_socket (void) +{ + unlink (agent_socket_name); +} + /* Helper thread of agent. */ static void * @@ -6732,6 +7183,8 @@ gdb_agent_helper_thread (void *arg) { int listen_fd; + atexit (gdb_agent_remove_socket); + while (1) { listen_fd = gdb_agent_socket_init (); @@ -6752,12 +7205,13 @@ gdb_agent_helper_thread (void *arg) int fd; char buf[1]; int ret; + int stop_loop = 0; tmp = sizeof (sockaddr); do { - fd = accept (listen_fd, &sockaddr, &tmp); + fd = accept (listen_fd, (struct sockaddr *) &sockaddr, &tmp); } /* It seems an ERESTARTSYS can escape out of accept. */ while (fd == -512 || (fd == -1 && errno == EINTR)); @@ -6784,8 +7238,12 @@ gdb_agent_helper_thread (void *arg) if (cmd_buf[0]) { + if (startswith (cmd_buf, "close")) + { + stop_loop = 1; + } #ifdef HAVE_UST - if (strcmp ("qTfSTM", cmd_buf) == 0) + else if (strcmp ("qTfSTM", cmd_buf) == 0) { cmd_qtfstm (cmd_buf); } @@ -6793,21 +7251,15 @@ gdb_agent_helper_thread (void *arg) { cmd_qtsstm (cmd_buf); } - else if (strncmp ("unprobe_marker_at:", - cmd_buf, - sizeof ("unprobe_marker_at:") - 1) == 0) + else if (startswith (cmd_buf, "unprobe_marker_at:")) { unprobe_marker_at (cmd_buf); } - else if (strncmp ("probe_marker_at:", - cmd_buf, - sizeof ("probe_marker_at:") - 1) == 0) + else if (startswith (cmd_buf, "probe_marker_at:")) { probe_marker_at (cmd_buf); } - else if (strncmp ("qTSTMat:", - cmd_buf, - sizeof ("qTSTMat:") - 1) == 0) + else if (startswith (cmd_buf, "qTSTMat:")) { cmd_qtstmat (cmd_buf); } @@ -6817,6 +7269,20 @@ gdb_agent_helper_thread (void *arg) /* Fix compiler's warning: ignoring return value of 'write'. */ ret = write (fd, buf, 1); close (fd); + + if (stop_loop) + { + close (listen_fd); + unlink (agent_socket_name); + + /* Sleep endlessly to wait the whole inferior stops. This + thread can not exit because GDB or GDBserver may still need + 'current_thread' (representing this thread) to access + inferior memory. Otherwise, this thread exits earlier than + other threads, and 'current_thread' is set to NULL. */ + while (1) + sleep (10); + } } } @@ -6826,6 +7292,10 @@ gdb_agent_helper_thread (void *arg) #include #include +EXTERN_C_PUSH +IP_AGENT_EXPORT_VAR int gdb_agent_capability = AGENT_CAPA_STATIC_TRACE; +EXTERN_C_POP + static void gdb_agent_init (void) { @@ -6840,7 +7310,7 @@ gdb_agent_init (void) sigfillset (&new_mask); res = pthread_sigmask (SIG_SETMASK, &new_mask, &orig_mask); if (res) - fatal ("pthread_sigmask (1) failed: %s", strerror (res)); + perror_with_name ("pthread_sigmask (1)"); res = pthread_create (&thread, NULL, @@ -6849,7 +7319,7 @@ gdb_agent_init (void) res = pthread_sigmask (SIG_SETMASK, &orig_mask, NULL); if (res) - fatal ("pthread_sigmask (2) failed: %s", strerror (res)); + perror_with_name ("pthread_sigmask (2)"); while (helper_thread_id == 0) usleep (1); @@ -6860,14 +7330,13 @@ gdb_agent_init (void) } #include -#include -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; +IP_AGENT_EXPORT_VAR char *gdb_tp_heap_buffer; +IP_AGENT_EXPORT_VAR char *gdb_jump_pad_buffer; +IP_AGENT_EXPORT_VAR char *gdb_jump_pad_buffer_end; +IP_AGENT_EXPORT_VAR char *gdb_trampoline_buffer; +IP_AGENT_EXPORT_VAR char *gdb_trampoline_buffer_end; +IP_AGENT_EXPORT_VAR 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 @@ -6892,6 +7361,34 @@ initialize_tracepoint_ftlib (void) gdb_agent_init (); } +#ifndef HAVE_GETAUXVAL +/* Retrieve the value of TYPE from the auxiliary vector. If TYPE is not + found, 0 is returned. This function is provided if glibc is too old. */ + +unsigned long +getauxval (unsigned long type) +{ + unsigned long data[2]; + FILE *f = fopen ("/proc/self/auxv", "r"); + unsigned long value = 0; + + if (f == NULL) + return 0; + + while (fread (data, sizeof (data), 1, f) > 0) + { + if (data[0] == type) + { + value = data[1]; + break; + } + } + + fclose (f); + return value; +} +#endif + #endif /* IN_PROCESS_AGENT */ /* Return a timestamp, expressed as microseconds of the usual Unix @@ -6901,21 +7398,17 @@ initialize_tracepoint_ftlib (void) static LONGEST get_timestamp (void) { - struct timeval tv; + using namespace std::chrono; - if (gettimeofday (&tv, 0) != 0) - return -1; - else - return (LONGEST) tv.tv_sec * 1000000 + tv.tv_usec; + steady_clock::time_point now = steady_clock::now (); + return duration_cast (now.time_since_epoch ()).count (); } void initialize_tracepoint (void) { - /* There currently no way to change the buffer size. */ - const int sizeOfBuffer = 5 * 1024 * 1024; - unsigned char *buf = xmalloc (sizeOfBuffer); - init_trace_buffer (buf, sizeOfBuffer); + /* Start with the default size. */ + init_trace_buffer (DEFAULT_TRACE_BUFFER_SIZE); /* Wire trace state variable 1 to be the timestamp. This will be uploaded to GDB upon connection and become one of its trace state @@ -6927,35 +7420,22 @@ initialize_tracepoint (void) #ifdef IN_PROCESS_AGENT { - uintptr_t addr; int pagesize; + size_t jump_pad_size; pagesize = sysconf (_SC_PAGE_SIZE); if (pagesize == -1) - fatal ("sysconf"); - - gdb_tp_heap_buffer = xmalloc (5 * 1024 * 1024); + perror_with_name ("sysconf"); #define SCRATCH_BUFFER_NPAGES 20 - /* Allocate scratch buffer aligned on a page boundary, at a low - address (close to the main executable's code). */ - for (addr = pagesize; addr != 0; addr += pagesize) - { - gdb_jump_pad_buffer = mmap ((void *) addr, pagesize * SCRATCH_BUFFER_NPAGES, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, - -1, 0); - if (gdb_jump_pad_buffer != MAP_FAILED) - break; - } - - if (addr == 0) - fatal ("\ -initialize_tracepoint: mmap'ing jump pad buffer failed with %s", - strerror (errno)); + jump_pad_size = pagesize * SCRATCH_BUFFER_NPAGES; - gdb_jump_pad_buffer_end = gdb_jump_pad_buffer + pagesize * SCRATCH_BUFFER_NPAGES; + gdb_tp_heap_buffer = (char *) xmalloc (5 * 1024 * 1024); + gdb_jump_pad_buffer = (char *) alloc_jump_pad_buffer (jump_pad_size); + if (gdb_jump_pad_buffer == NULL) + perror_with_name ("mmap"); + gdb_jump_pad_buffer_end = gdb_jump_pad_buffer + jump_pad_size; } gdb_trampoline_buffer = gdb_trampoline_buffer_end = 0; @@ -6964,7 +7444,7 @@ initialize_tracepoint: mmap'ing jump pad buffer failed with %s", 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 when the problem occurs. */ - gdb_trampoline_buffer_error = xmalloc (IPA_BUFSIZ); + gdb_trampoline_buffer_error = (char *) xmalloc (IPA_BUFSIZ); strcpy (gdb_trampoline_buffer_error, "No errors reported");