/* Tracepoint code for remote server for GDB.
- Copyright (C) 2009-2013 Free Software Foundation, Inc.
+ Copyright (C) 2009-2015 Free Software Foundation, Inc.
This file is part of GDB.
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "server.h"
+#include "tracepoint.h"
#include "gdbthread.h"
#include "agent.h"
+#include "rsp-low.h"
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
-#include <sys/time.h>
-#include <stddef.h>
+#include "gdb_sys_time.h"
#include <inttypes.h>
-#include <stdint.h>
-
#include "ax.h"
#include "tdesc.h"
*/
+#ifdef IN_PROCESS_AGENT
+
static void trace_vdebug (const char *, ...) ATTRIBUTE_PRINTF (1, 2);
static void
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 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 IPA_SYM_EXPORTED_NAME (gdb_collect)
+# 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 IPA_SYM_EXPORTED_NAME (get_raw_reg)
# define get_trace_state_variable_value \
- gdb_agent_get_trace_state_variable_value
+ IPA_SYM_EXPORTED_NAME (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
+ IPA_SYM_EXPORTED_NAME (set_trace_state_variable_value)
+# 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)
#endif
#ifndef IN_PROCESS_AGENT
{
const char *name;
int offset;
- int required;
} symbol_list[] = {
IPA_SYM(gdb_tp_heap_buffer),
IPA_SYM(gdb_jump_pad_buffer),
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;
}
}
# 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. */
#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;
-static enum eval_result_type expr_eval_result = expr_eval_no_error;
+/* The first error that occurred during expression evaluation. */
+
+/* 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 */
/* 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
{
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
} ATTR_PACKED;
+/* 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)
+
/* 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. */
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
#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)
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. */
/* 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
/* The global that controls tracing overall. */
-IP_AGENT_EXPORT int tracing;
+IP_AGENT_EXPORT_VAR int tracing;
#ifndef IN_PROCESS_AGENT
static void
init_trace_buffer (LONGEST bufsize)
{
+ size_t alloc_size;
+
trace_buffer_size = bufsize;
- /* If we already have a trace buffer, try realloc'ing. */
- trace_buffer_lo = xrealloc (trace_buffer_lo, 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 = xrealloc (trace_buffer_lo, alloc_size);
- trace_buffer_hi = trace_buffer_lo + bufsize;
+ 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
(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:
return tsv;
}
-IP_AGENT_EXPORT LONGEST
+IP_AGENT_EXPORT_FUNC LONGEST
get_trace_state_variable_value (int num)
{
struct trace_state_variable *tsv;
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;
{
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;
struct tracepoint *prev_stpoint;
pause_all (1);
- cancel_breakpoints ();
prev_stpoint = NULL;
packet = unpack_varlen_hex (packet, &slen);
++packet; /* skip a colon */
src = xmalloc (slen + 1);
- nbytes = unhexify (src, packet, strlen (packet) / 2);
+ nbytes = hex2bin (packet, (gdb_byte *) src, strlen (packet) / 2);
src[nbytes] = '\0';
newlast = xmalloc (sizeof (struct source_string));
nbytes = strlen (packet) / 2;
varname = xmalloc (nbytes + 1);
- nbytes = unhexify (varname, packet, nbytes);
+ nbytes = hex2bin (packet, (gdb_byte *) varname, nbytes);
varname[nbytes] = '\0';
tsv = create_trace_state_variable (num, 1);
{
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;
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");
}
}
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)
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);
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);
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. */
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 ();
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);
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);
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);
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
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);
/* 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;
p = stop_reason_rsp = 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. */
"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);
}
len = strlen (src->str);
buf = alloca (len * 2 + 1);
- convert_int_to_ascii ((gdb_byte *) src->str, buf, len);
+ bin2hex ((gdb_byte *) src->str, buf, len);
sprintf (packet, "Z%x:%s:%s:%x:%x:%s",
tpoint->number, paddress (tpoint->address),
{
namelen = strlen (tsv->name);
buf = alloca (namelen * 2 + 1);
- convert_int_to_ascii ((gdb_byte *) tsv->name, buf, namelen);
+ bin2hex ((gdb_byte *) tsv->name, buf, namelen);
}
sprintf (packet, "%x:%s:%x:%s", tsv->number, phex_nz (tsv->initial_value, 0),
run_inferior_command (packet, strlen (packet) + 1);
}
+/* Helper for gdb_agent_about_to_close.
+ Return non-zero if thread ENTRY is in the same process in DATA. */
+
+static int
+same_process_p (struct inferior_list_entry *entry, void *data)
+{
+ int *pid = data;
+
+ return ptid_get_pid (entry->id) == *pid;
+}
+
/* Sent the agent a command to close it. */
void
if (!maybe_write_ipa_not_loaded (buf))
{
- struct thread_info *save_inferior;
- struct inferior_list_entry *inf = all_threads.head;
-
- save_inferior = current_inferior;
+ struct thread_info *saved_thread;
- /* Find a certain thread which belongs to process PID. */
- while (inf != NULL)
- {
- if (ptid_get_pid (inf->id) == pid)
- break;
- inf = inf->next;
- }
+ saved_thread = current_thread;
- current_inferior = (struct thread_info *) inf;
+ /* Find any thread which belongs to process PID. */
+ current_thread = (struct thread_info *)
+ find_inferior (&all_threads, same_process_p, &pid);
strcpy (buf, "close");
run_inferior_command (buf, strlen (buf) + 1);
- current_inferior = save_inferior;
+ current_thread = saved_thread;
}
}
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");
if (num >= (PBUFSIZ - 16) / 2 )
num = (PBUFSIZ - 16) / 2;
- convert_int_to_ascii (tbp, own_buf, num);
+ bin2hex (tbp, own_buf, num);
}
static void
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);
+ 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);
+ 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);
+ nbytes = hex2bin (saved, (gdb_byte *) stopnote, nbytes);
stopnote[nbytes] = '\0';
++packet; /* skip the semicolon */
trace_debug ("tstop note is '%s'", stopnote);
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;
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 ("QTBuffer:size:", packet, strlen ("QTBuffer:size:")) == 0)
+ else if (startswith (packet, "QTBuffer:size:"))
{
cmd_bigqtbuffer_size (packet);
return 1;
}
- else if (strncmp ("QTNotes:", packet, strlen ("QTNotes:")) == 0)
+ else if (startswith (packet, "QTNotes:"))
{
cmd_qtnotes (packet);
return 1;
cmd_qtstatus (packet);
return 1;
}
- else if (strncmp ("qTP:", packet, strlen ("qTP:")) == 0)
+ else if (startswith (packet, "qTP:"))
{
cmd_qtp (packet);
return 1;
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;
cmd_qtsstm (packet);
return 1;
}
- else if (strncmp ("qTSTMat:", packet, strlen ("qTSTMat:")) == 0)
+ else if (startswith (packet, "qTSTMat:"))
{
cmd_qtstmat (packet);
return 1;
break;
}
case 'V':
+ {
+ int vnum;
+
+ memcpy (&vnum, dataptr, sizeof (vnum));
+ buffer_xml_printf (buffer, "<tvar id=\"%d\"/>\n", vnum);
+ break;
+ }
case 'R':
case 'S':
{
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)
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;
/* 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;
if (ipa_action != 0)
write_inferior_data_ptr
- (actions_array + i * sizeof (sizeof (*tpoint->actions)),
+ (actions_array + i * sizeof (*tpoint->actions),
ipa_action);
}
}
if (ret)
return ret;
- if (strncmp (buf, "OK", 2) != 0)
+ if (!startswith (buf, "OK"))
return 1;
/* The value of tracepoint's target address is stored in BUF. */
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
name_addr);
}
- if (tsv->getter != NULL)
- {
- fatal ("what to do with these?");
- }
+ gdb_assert (tsv->getter == NULL);
}
if (prev_ptr != 0)
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... */
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;
#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
/* 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)
{
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;
}
#endif /* HAVE_UST */
#include <sys/syscall.h>
-#include <stdlib.h>
static void
gdb_agent_remove_socket (void)
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));
if (cmd_buf[0])
{
- if (strncmp ("close", cmd_buf, 5) == 0)
+ if (startswith (cmd_buf, "close"))
{
stop_loop = 1;
}
{
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);
}
/* Sleep endlessly to wait the whole inferior stops. This
thread can not exit because GDB or GDBserver may still need
- 'current_inferior' (representing this thread) to access
+ 'current_thread' (representing this thread) to access
inferior memory. Otherwise, this thread exits earlier than
- other threads, and 'current_inferior' is set to NULL. */
+ other threads, and 'current_thread' is set to NULL. */
while (1)
sleep (10);
}
#include <signal.h>
#include <pthread.h>
-IP_AGENT_EXPORT int gdb_agent_capability = AGENT_CAPA_STATIC_TRACE;
+EXTERN_C_PUSH
+IP_AGENT_EXPORT_VAR int gdb_agent_capability = AGENT_CAPA_STATIC_TRACE;
+EXTERN_C_POP
static void
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,
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);
#include <sys/mman.h>
#include <fcntl.h>
-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
pagesize = sysconf (_SC_PAGE_SIZE);
if (pagesize == -1)
- fatal ("sysconf");
+ perror_with_name ("sysconf");
gdb_tp_heap_buffer = xmalloc (5 * 1024 * 1024);
}
if (addr == 0)
- fatal ("\
-initialize_tracepoint: mmap'ing jump pad buffer failed with %s",
- strerror (errno));
+ perror_with_name ("mmap");
gdb_jump_pad_buffer_end = gdb_jump_pad_buffer + pagesize * SCRATCH_BUFFER_NPAGES;
}