From cf57f6bcdb5c928b8adf4fbe7c9bdea74b8b764c Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Sat, 24 Apr 2010 11:29:38 -0400 Subject: [PATCH] [vxworks] remote-wtxapi: The WTX API abstraction layer. This provides an API torwards for the WTX protocol which is stable across versions of WTX. The implementation is a thin binding over the wtx API provided by WindRiver. 2010-04-24 Joel Brobecker * remote-wtxapi.h, remote-wtxapi.c: New files. --- gdb/remote-wtxapi.c | 2957 +++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/remote-wtxapi.h | 1221 +++++++++++++++++++++ 2 files changed, 4178 insertions(+), 0 deletions(-) create mode 100644 gdb/remote-wtxapi.c create mode 100644 gdb/remote-wtxapi.h diff --git a/gdb/remote-wtxapi.c b/gdb/remote-wtxapi.c new file mode 100644 index 0000000..2a3d464 --- /dev/null +++ b/gdb/remote-wtxapi.c @@ -0,0 +1,2957 @@ +/* Thin binding for the WTX protocol, for GDB. + + Copyright 2004, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "command.h" +#include "gdbcmd.h" +#include "gdb_string.h" +#include "remote-wtxapi.h" +#include "gdb_assert.h" +#include "remote-wtx-utils.h" +#include "remote-wtx-opt.h" + +/* This layer is only implemented and tested on WTX 2.0, 3.0 and 4.0. */ + +#if WTX_PROT_VERSION != 2 && WTX_PROT_VERSION != 3 && WTX_PROT_VERSION != 4 +#error +#endif + +/* In WTX 4.0, the context-related functions take a WTX_CONTEXT * as + parameter; In previous versions, it was a WTX_CONTEXT_ID_T and a + WTX_CONTEXT_TYPE. The following macros are a klugde to fix that. + FIXME: The good method is probably to change the specs of the + corresponding functions in remote-wtxapi. */ +static void initialize_context (WTX_CONTEXT * context, + WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id); + +#if WTX_PROT_VERSION > 3 +#define MARSHALL_WTX_CONTEXT_PARAM(context) &context +#else +#define MARSHALL_WTX_CONTEXT_PARAM(context) \ + context.contextType, context.contextId +#endif + +#if WTX_PROT_VERSION != 2 +typedef WTX_EVTPT_LIST wtx_evtpt_list; +#else +typedef WTX_EVTPT_LIST_2 wtx_evtpt_list; +#endif + +#if WTX_PROT_VERSION != 2 +typedef WTX_MODULE_INFO wtx_module_info; +#else +typedef WTX_LD_M_FILE_DESC wtx_module_info; +#endif + +static STATUS (*wtx_initialize) (); +static STATUS (*wtx_terminate) (); +static WTX_DESC_Q *(*wtx_info_q) (); +static STATUS (*wtx_tool_attach) (); +static int (*wtx_tool_connected) (); +static STATUS (*wtx_tool_detach) (); +static STATUS (*wtx_err_clear) (); +static WTX_ERROR_T (*wtx_err_get) (); +static WTX_HANDLER_T (*wtx_err_handler_add) (); +static STATUS (*wtx_err_handler_remove) (); +static char * (*wtx_err_msg_get) (); +static WTX_AGENT_MODE_TYPE (*wtx_agent_mode_get) (); +static STATUS (*wtx_agent_mode_set) (); +static evtpt_id_t (*wtx_breakpoint_add) (); +static evtpt_id_t (*wtx_eventpoint_add) (); +static STATUS (*wtx_eventpoint_delete) (); +static WTX_EVENT_DESC * (*wtx_event_get) (); +static WTX_CONTEXT_STATUS (*wtx_context_status_get) (); +static STATUS (*wtx_context_cont) (); +static WTX_CONTEXT_ID_T (*wtx_context_create) (); +static STATUS (*wtx_context_resume) (); +static evtpt_id_t (*wtx_context_exit_notify_add) (); +static STATUS (*wtx_context_kill) (); +static STATUS (*wtx_context_step) (); +static STATUS (*wtx_context_suspend) (); +static STATUS (*wtx_context_stop) (); +static wtx_evtpt_list * (*wtx_eventpoint_list_get) (); +static STATUS (*wtx_result_free) (); +static WTX_GOPHER_TAPE * (*wtx_gopher_eval) (); +static WTX_MEM_INFO * (*wtx_mem_info_get) (); +static wtxapi_tgt_addr_t (*wtx_mem_alloc) (); +static int (*wtx_mem_checksum) (); +static STATUS (*wtx_mem_move) (); +static STATUS (*wtx_mem_free) (); +static int (*wtx_mem_read) (); +static int (*wtx_mem_width_read) (); +static int (*wtx_mem_write) (); +static int (*wtx_mem_width_write) (); +static int (*wtx_mem_set) (); +static STATUS (*wtx_mem_add_to_pool) (); +static wtxapi_tgt_addr_t (*wtx_mem_realloc) (); +static wtxapi_tgt_addr_t (*wtx_mem_align) (); +static STATUS (*wtx_mem_scan) (); +static STATUS (*wtx_obj_module_checksum) (); +static module_id_t (*wtx_obj_module_find_id) (); +static char * (*wtx_obj_module_find_name) (); +static WTX_MODULE_INFO * (*wtx_obj_module_info_get) (); +static wtx_module_info * (*wtx_obj_module_load) (); +static STATUS (*wtx_obj_module_unload) (); +static STATUS (*wtx_obj_module_by_name_unload) (); +static STATUS (*wtx_register_for_event) (); +static STATUS (*wtx_regs_get) (); +static STATUS (*wtx_regs_set) (); +static wtxapi_tgt_addr_t (*wtx_str_to_tgt_addr) (); +static WTX_CONTEXT_ID_T (*wtx_str_to_context_id) (); +static WTX_CONTEXT_TYPE (*wtx_str_to_context_type) (); +static int (*wtx_str_to_int32) (); +static WTX_EVENT_TYPE (*wtx_str_to_event_type) (); +static STATUS (*wtx_sym_add) (); +static WTX_SYMBOL * (*wtx_sym_find) (); +static WTX_SYM_LIST * (*wtx_sym_list_get) (); +static WTX_SYM_LIST * (*wtx_sym_list_by_module_id_get) (); +static WTX_SYM_LIST * (*wtx_sym_list_by_module_name_get) (); +static STATUS (*wtx_sym_remove) (); +static WTX_SYM_TBL_INFO * (*wtx_sym_tbl_info_get) (); +static STATUS (*wtx_target_reset) (); +static char * (*wtx_ts_name_get) (); +static int (*wtx_target_cpu_type_get) (); +static int (*wtx_target_has_fpp_get) (); +static WTX_ENDIAN_T (*wtx_target_endian_get) (); +static char * (*wtx_target_bootline_get) (); +static char * (*wtx_tool_name_get) (); +static char * (*wtx_ts_version_get) (); +static STATUS (*wtx_unregister_for_event) (); +static STATUS (*wtx_direct_call) (); +static WTX_TS_INFO * (*wtx_ts_info_get) (); +static STATUS (*wtx_target_attach) (); +static STATUS (*wtx_probe) (); +static STATUS (*wtx_timeout_set) (); +static STATUS (*wtx_timeout_get) (); + +#if WTX_PROT_VERSION != 2 +static WTX_MODULE_LIST * (*wtx_obj_module_list_get) (); +static pd_id_t (*wtx_pd_create) (); +static pd_id_t (*wtx_pd_kernel_get) (); +static pd_id_t (*wtx_pd_current_get) (); +static STATUS (*wtx_pd_current_set) (); +static WTX_PD_DESC_Q * (*wtx_pd_info_q_get) (); +#else +static WTX_MODULE_LIST * (*wtx_obj_module_list) (); +#endif + +/* Conversion from an to a BOOL32. */ + +#define TO_BOOL(b) (b ? TRUE : FALSE) + +#ifndef WTX_PD_CURRENT +const wtxapi_tgt_addr_t WTX_PD_CURRENT; +#endif + +#ifndef WTX_PD_ALL +const wtxapi_tgt_addr_t WTX_PD_ALL = -1; +#endif + +#ifndef WTX_MOD_FIND_IN_ALL_PD +const wtxapi_tgt_addr_t WTX_MOD_FIND_IN_ALL_PD = -1; +#endif + +#ifndef WTX_SYM_FIND_IN_ALL_PD +const int WTX_SYM_FIND_IN_ALL_PD = -1; +#endif + +#if WTX_PROT_VERSION == 2 +const WTX_CONTEXT_TYPE WTX_CONTEXT_PD = WTX_CONTEXT_ANY_TASK; +const int WTX_ERR_PD_INVALID_PD = WTX_ERROR; +#endif + +#if WTX_PROT_VERSION > 3 +const WTX_ACTION_TYPE WTX_ACTION_STOP_ALL = WTX_ACTION_ALL_STOP; +#endif + +const int wtxapi_symbol_copy_none = 0; +const int wtxapi_symbol_copy_name = 1 << 0; +const int wtxapi_symbol_copy_module_name = 1 << 1; + +const pd_id_t invalid_pd_id = WTX_ERROR; +const evtpt_id_t invalid_module_id = WTX_ERROR; +const evtpt_id_t invalid_evtpt_id = WTX_ERROR; +const WTX_CONTEXT_ID_T invalid_context_id = WTX_ERROR; +const WTX_AGENT_MODE_TYPE invalid_agent_mode = WTX_ERROR; +const WTX_CONTEXT_STATUS invalid_context_status = WTX_ERROR; + +/* Only one PD is allowed in WTX 2.0; NULL_PD is the value of this PD + ID. */ + +const pd_id_t NULL_PD = 0; + +/* Symbol list: complete declaration. Based on WTX_SYMBOL and + WTX_SYMBOL_LIST. */ + +struct wtxapi_symbol_list +{ + /* First element of the list. */ + WTX_SYMBOL *first; + + /* Current element (when going through the list with the iterator). */ + WTX_SYMBOL *current; + + /* Pointer to the result of the WTX operation used to get the symbol + list. It is used at deallocation time. */ + void *wtx_result_to_cleanup; +}; + +/* Current WTX handle. */ + +static HWTX current_wtx_handle = 0; + +/* Allocate a new wtxapi_symbol_list and initialize it with + WTX_SYM. WTX_SYM should not be deallocated directly by the caller, + it will be deallocated by free_wtxapi_symbol_list. */ + +static struct wtxapi_symbol_list + *new_wtxapi_symbol_list (WTX_SYM_LIST *wtx_sym); + + +static struct wtxapi_symbol_list + *new_wtxapi_symbol_list_from_symbol (WTX_SYMBOL *wtx_sym); + + +/* Allocate a new wtxapi_module_info, and initialize it with + WTX_MINFO. The caller can deallocate WTX_MINFO, as it is fully + copied. It does not initialize wtx_minfo->undef_list; it should + be handled separatly if needed. */ + +static struct wtxapi_module_info + *new_wtxapi_module_info (WTX_MODULE_INFO * wtx_minfo); + +static void +initialize_context (WTX_CONTEXT *context, + WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id) +{ + context->contextType = context_type; + context->contextId = context_id; +#if WTX_PROT_VERSION > 3 + context->contextSubId = 0; +#endif +} + +/* Build and initialize a WTX client handle. This handle can then be + used to connect to a target server. */ + +int +wtxapi_initialize () +{ + return wtx_initialize (¤t_wtx_handle) != WTX_ERROR; +} + +/* Return the current WTX handle. */ + +HWTX +wtxapi_get_current_wtx_handle () +{ + return current_wtx_handle; +} + +/* Terminate use of WTX client handle. */ + +int +wtxapi_terminate () +{ + return wtx_terminate (current_wtx_handle) != WTX_ERROR; +} + +/* Return list of registred services. NAME_PAT is the reg expression + to match svc name. TYPE_PAT is the reg expression to match svc + type. KEY_PAT is the reg expression to match svc key. */ + +WTX_DESC_Q * +wtxapi_info_q (const char *name_pat, const char *type_pat, + const char *key_pat) +{ + return wtx_info_q (current_wtx_handle, name_pat, type_pat, key_pat); +} + +/* Connect client to the target server. */ + +int +wtxapi_tool_attach (const char *target_name, const char *tool_name) +{ + return wtx_tool_attach (current_wtx_handle, target_name, + tool_name) != WTX_ERROR; +} + +/* Check tool connection to the server. */ + +int +wtxapi_tool_connected () +{ + return wtx_tool_connected (current_wtx_handle) == TRUE; +} + +/* Detach from the target server. */ + +int +wtxapi_tool_detach () +{ + return wtx_tool_detach (current_wtx_handle) != WTX_ERROR; +} + +/* Clear any error for the tool. */ + +int +wtxapi_err_clear () +{ + return wtx_err_clear (current_wtx_handle) != WTX_ERROR; +} + +/* Return the last error for a handle. */ + +WTX_ERROR_T +wtxapi_err_get () +{ + return wtx_err_get (current_wtx_handle); +} + +/* Add an error handler. */ + +WTX_HANDLER_T +wtxapi_err_handler_add (WTX_HANDLER_FUNC p_func, void *p_client_data) +{ + return wtx_err_handler_add (current_wtx_handle, p_func, p_client_data); +} + +/* Remove error handler for WTX handle. */ + +int +wtxapi_err_handler_remove (WTX_HANDLER_T p_handler) +{ + return wtx_err_handler_remove (current_wtx_handle, p_handler) != WTX_ERROR; +} + +/* Fetch last WTX API error string. */ + +const char * +wtxapi_err_msg_get () +{ + if (current_wtx_handle == 0) + return "Invalid WTX handle"; + else + return wtx_err_msg_get (current_wtx_handle); +} + +/* Get agent mode. */ + +WTX_AGENT_MODE_TYPE +wtxapi_agent_mode_get () +{ + return wtx_agent_mode_get (current_wtx_handle); +} + +/* Set the mode of the target agent. */ + +int +wtxapi_agent_mode_set (WTX_AGENT_MODE_TYPE agent_mode) +{ + return wtx_agent_mode_set (current_wtx_handle, agent_mode) != WTX_ERROR; +} + +/* Create a new breakpoint. */ + +evtpt_id_t +wtxapi_breakpoint_add (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id, wtxapi_tgt_addr_t tgt_addr) +{ + WTX_CONTEXT context; + initialize_context (&context, context_type, context_id); + return wtx_breakpoint_add (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context), tgt_addr); +} + +/* Create a new event point. */ + +evtpt_id_t +wtxapi_eventpoint_add (struct wtxapi_evtpt *p_evtpt) +{ +#if WTX_PROT_VERSION != 2 + WTX_EVTPT wtx_evtpt; +#else + WTX_EVTPT_2 wtx_evtpt; +#endif + memset (&wtx_evtpt, 0, sizeof (wtx_evtpt)); + wtx_evtpt.event.eventType = p_evtpt->event.event_type; + wtx_evtpt.event.numArgs = p_evtpt->event.num_args; + wtx_evtpt.event.args = p_evtpt->event.args; + wtx_evtpt.context.contextType = p_evtpt->context.context_type; + + /* In WTX 4.1, WTX_CONTEXT_ANY_TASK does not work if the context ID + is not null; in the previous versions, it is simply ignored; so + unconditionally set the context ID to zero in the "any task" + case. */ + if (p_evtpt->context.context_type == WTX_CONTEXT_ANY_TASK) + wtx_evtpt.context.contextId = 0; + else + wtx_evtpt.context.contextId = p_evtpt->context.context_id; + + wtx_evtpt.action.actionType = p_evtpt->action.action_type; + wtx_evtpt.action.actionArg = p_evtpt->action.action_arg; + wtx_evtpt.action.callRtn = p_evtpt->action.call_rtn; + wtx_evtpt.action.callArg = p_evtpt->action.call_arg; + return wtx_eventpoint_add (current_wtx_handle, &wtx_evtpt); +} + +/* Delete eventpoint from the target. */ + +int +wtxapi_eventpoint_delete (evtpt_id_t evtpt_id) +{ + return wtx_eventpoint_delete (current_wtx_handle, evtpt_id) != WTX_ERROR; +} + +/* Parse a CTX_EXIT event string, and return the associated EVENT. */ + +static void +wtxapi_parse_ctx_exit_event (char *event_str, + struct wtxapi_ctx_exit_event *event) +{ + char *context_id_str = NULL; + char *context_type_str = NULL; + char *exit_code_str = NULL; + + if (WTX_PROT_VERSION > 3) + { + /* Format: "Context_Type Context_ID xxx Exit_Code..." + (where "xxx" is a field that we can ignore). */ + event_str = get_space_delimited_token (event_str, &context_type_str); + event_str = get_space_delimited_token (event_str, &context_id_str); + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &exit_code_str); + } + else + { + /* Format: "Context_Type Context_ID Exit_Code". */ + event_str = get_space_delimited_token (event_str, &context_type_str); + event_str = get_space_delimited_token (event_str, &context_id_str); + event_str = get_space_delimited_token (event_str, &exit_code_str); + } + + event->context_id = wtxapi_str_to_context_id (context_id_str); + event->context_type = wtxapi_str_to_context_type (context_type_str); + event->exit_code = wtxapi_str_to_int32 (exit_code_str); + + wtx_opt_events_debug (1, "CTX_EXIT: " + "context_id = \"%s\" 0x%lx, " + "context_type = \"%s\" %d, " + "exit_code = \"%s\" %d", + context_id_str, event->context_id, + context_type_str, event->context_type, + exit_code_str, event->exit_code); + xfree (context_id_str); + xfree (context_type_str); + xfree (exit_code_str); + +} + +/* Parse a DATA_ACCESS event string, and return the associated EVENT. */ + +static void +wtxapi_parse_data_access_event (char *event_str, + struct wtxapi_data_access_event *event) +{ + char *task_id_str = NULL; + char *context_id_str = NULL; + char *context_type_str = NULL; + char *data_addr_str = NULL; + + /* The formatting of the DATA_ACCESS event depends on the WTX + protocol version. Extract each of the appropriate field + and discard the others. */ + + if (WTX_PROT_VERSION == 2) + { + /* Format: "Task_ID/Context_ID Context_Type xxx xxx xxx Data_Addr..." + (where "xxx" is a field that we can ignore, and the Task_ID and + Context_ID are identical). */ + event_str = get_space_delimited_token (event_str, &task_id_str); + event_str = get_space_delimited_token (event_str, &context_type_str); + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &data_addr_str); + context_id_str = xstrdup (task_id_str); + } + else if (WTX_PROT_VERSION == 3) + { + /* Format: "Context_ID Context_Type xxx xxx xxx Data_Addr Task_ID ..." + (where "xxx" is a field that we can ignore). */ + event_str = get_space_delimited_token (event_str, &context_id_str); + event_str = get_space_delimited_token (event_str, &context_type_str); + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &data_addr_str); + event_str = get_space_delimited_token (event_str, &task_id_str); + } + else + { + /* Format: "xxx Context_Type Context_ID xxx xxx Task_ID xxx + xxx xxx xxx Data_Addr" + (where "xxx" is a field that we can ignore). */ + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &context_type_str); + event_str = get_space_delimited_token (event_str, &context_id_str); + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &task_id_str); + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &data_addr_str); + } + + event->task_id = wtxapi_str_to_context_id (task_id_str); + event->context_id = wtxapi_str_to_context_id (context_id_str); + event->context_type = wtxapi_str_to_context_type (context_type_str); + event->data_addr = wtxapi_str_to_tgt_addr (data_addr_str); + + wtx_opt_events_debug (1, "DATA_ACCESS: " + "task_id = \"%s\" 0x%lx, " + "context_id = \"%s\" 0x%lx, " + "context_type = \"%s\" %d, " + "data_addr = \"%s\" 0x%s", + task_id_str, event->task_id, + context_id_str, event->context_id, + context_type_str, event->context_type, + data_addr_str, + paddress (target_gdbarch, event->data_addr)); + xfree (task_id_str); + xfree (context_id_str); + xfree (context_type_str); + xfree (data_addr_str); +} + +/* Parse an EXCEPTION event string, and return the associated EVENT. */ + +static void +wtxapi_parse_exception_event (char *event_str, + struct wtxapi_exception_event *event) +{ + char *context_id_str = NULL; + char *context_type_str = NULL; + char *exception_value_str = NULL; + + /* The formatting of the EXCEPTION event depends on the WTX + protocol version. Extract each of the appropriate field + and discard the others. */ + + if (WTX_PROT_VERSION < 4) + { + /* Format: "Context_Type Context_ID ...". */ + event_str = get_space_delimited_token (event_str, &context_type_str); + event_str = get_space_delimited_token (event_str, &context_id_str); + event_str = get_space_delimited_token (event_str, &exception_value_str); + } + else + { + /* Format: "xxx xxx xxx xxx Context_Type Context_ID xxx Data_Addr ..." + (where "xxx" are fields we can ignore). */ + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &context_type_str); + event_str = get_space_delimited_token (event_str, &context_id_str); + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &exception_value_str); + } + + event->context_id = wtxapi_str_to_context_id (context_id_str); + event->context_type = wtxapi_str_to_context_type (context_type_str); + event->exception_value = wtxapi_str_to_tgt_addr (exception_value_str); + + wtx_opt_events_debug (1, "EXCEPTION: " + "context_id = \"%s\" 0x%lx, " + "context_type = \"%s\" %d, " + "exception_value = \"%s\" %s", + context_id_str, event->context_id, + context_type_str, event->context_type, + exception_value_str, + hex_string (event->exception_value)); + xfree (context_id_str); + xfree (context_type_str); +} + +/* Parse an OBJ_LOADED event string, and return the associated EVENT. */ + +static void +wtxapi_parse_obj_loaded_event (char *event_str, + struct wtxapi_obj_loaded_event *event) +{ + char *module_id_str = NULL; + + /* Format: "Module_Id Module_Name [...]", but we only need + the module ID. */ + event_str = get_space_delimited_token (event_str, &module_id_str); + event->module_id = wtxapi_str_to_int32 (module_id_str); + + wtx_opt_events_debug (1, "OBJ_LOADED: module_id_str = \"%s\" 0x%x", + module_id_str, event->module_id); + + xfree (module_id_str); +} + +/* Parse an OBJ_UNLOADED event string, and return the associated EVENT. */ + +static void +wtxapi_parse_obj_unloaded_event (char *event_str, + struct wtxapi_obj_unloaded_event *event) +{ + /* Format: "Module_Id Module_Name [...]", but we only need + the module filename. */ + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &event->module_filename); + + wtx_opt_events_debug (1, "OBJ_LOADED: module_filename = \"%s\"", + event->module_filename); +} + +/* Parse a TEXT_ACCESS event string, and return the associated EVENT. */ + +static void +wtxapi_parse_text_access_event (char *event_str, + struct wtxapi_text_access_event *event) +{ + char *task_id_str = NULL; + char *context_id_str = NULL; + char *context_type_str = NULL; + char *text_addr_str = NULL; + + /* The formatting of the TEXT_ACCESS event depends on the WTX + protocol version. Extract each of the appropriate field + and discard the others. */ + + if (WTX_PROT_VERSION == 2) + { + /* Format: "Task_ID/Context_ID Context_Type Text_Addr ..." + (the Task_ID and Context_ID are equal). */ + event_str = get_space_delimited_token (event_str, &task_id_str); + event_str = get_space_delimited_token (event_str, &context_type_str); + event_str = get_space_delimited_token (event_str, &text_addr_str); + context_id_str = xstrdup (task_id_str); + } + else if (WTX_PROT_VERSION == 3) + { + /* Format: "Context_ID Context_Type Text_Addr xxx xxx Task_ID ..." + (where "xxx" is a field that we can ignore). */ + event_str = get_space_delimited_token (event_str, &context_id_str); + event_str = get_space_delimited_token (event_str, &context_type_str); + event_str = get_space_delimited_token (event_str, &text_addr_str); + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &task_id_str); + } + else + { + /* Format: "xxx Context_Type Context_ID xxx xxx Task_ID xxx Text_Addr..." + (where "xxx" is a field that we can ignore). */ + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &context_type_str); + event_str = get_space_delimited_token (event_str, &context_id_str); + event_str = skip_space_delimited_token (event_str); + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &task_id_str); + event_str = skip_space_delimited_token (event_str); + event_str = get_space_delimited_token (event_str, &text_addr_str); + } + + /* With WTX version 3 and later and when in system mode, the task ID + in the event string is apparently not the ID we are looking for. + Get the current task ID differently. */ + /* brobecker/2007-08-31: Not sure what the wrong task ID could be. + So, for now, do nothing special; enhance later if we find some + evidence that it is necessary. */ + + event->task_id = wtxapi_str_to_context_id (task_id_str); + event->context_id = wtxapi_str_to_context_id (context_id_str); + event->context_type = wtxapi_str_to_context_type (context_type_str); + event->text_addr = wtxapi_str_to_tgt_addr (text_addr_str); + + wtx_opt_events_debug (1, "TEXT_ACCESS: " + "task_id = \"%s\" 0x%lx, " + "context_id = \"%s\" 0x%lx, " + "context_type = \"%s\" %d, " + "text_addr = \"%s\" 0x%s", + task_id_str, event->task_id, + context_id_str, event->context_id, + context_type_str, event->context_type, + text_addr_str, + paddress (target_gdbarch, event->text_addr)); + + xfree (task_id_str); + xfree (context_id_str); + xfree (context_type_str); + xfree (text_addr_str); +} + +/* Parse a VIO_WRITE event string, the given DATA and its associated + DATA_LEN, and return the corresponding EVENT. */ + +static void +wtxapi_parse_vio_write_event (char *event_str, char *data, int data_len, + struct wtxapi_vio_write_event *event) +{ + char *channel_id_str = NULL; + + /* Format: "Channel_Id". The rest of the information is + inside the additional_data. */ + event_str = get_space_delimited_token (event_str, &channel_id_str); + + event->channel_id = atoi (event_str); + + event->data = xmalloc ((data_len + 1) * sizeof (char)); + strncpy (event->data, data, data_len); + event->data[data_len] = '\0'; + + wtx_opt_events_debug (1, "VIO_WRITE: " + "channel_id = \"%s\" %d, " + "data = \"%s\"", + channel_id_str, event->channel_id, + event->data); + + xfree (channel_id_str); +} + + +/* Get the next event from the event queue if one is available. + Return NULL otherwise. + + The new event must be deallocated after use. */ + +struct wtxapi_event_desc * +wtxapi_event_get (void) +{ + WTX_EVENT_DESC *event_desc = wtx_event_get (current_wtx_handle); + char *event_str; + char *token = NULL; + struct wtxapi_event_desc *result; + + if (event_desc == NULL) + return NULL; + if (event_desc->event == NULL) + { + /* That's kind of dumb, but it actually happens. */ + wtx_result_free (current_wtx_handle, event_desc); + return NULL; + } + + wtx_opt_events_debug (2, "wtxapi_event_get: \"%s\"", event_desc->event); + + result = xmalloc (sizeof (struct wtxapi_event_desc)); + + /* Get the event type from the first token in the event string. */ + event_str = event_desc->event; + event_str = get_space_delimited_token (event_str, &token); + result->event_type = wtxapi_str_to_event_type (token); + xfree (token); + + switch (result->event_type) + { + case WTX_EVENT_CTX_EXIT: + wtxapi_parse_ctx_exit_event (event_str, &result->desc.ctx_exit); + break; + + case WTX_EVENT_DATA_ACCESS: + wtxapi_parse_data_access_event (event_str, &result->desc.data_access); + break; + + case WTX_EVENT_EXCEPTION: + wtxapi_parse_exception_event (event_str, &result->desc.exception); + break; + + case WTX_EVENT_OBJ_LOADED: + wtxapi_parse_obj_loaded_event (event_str, &result->desc.obj_loaded); + break; + + case WTX_EVENT_OBJ_UNLOADED: + wtxapi_parse_obj_unloaded_event (event_str, + &result->desc.obj_unloaded); + break; + + case WTX_EVENT_TEXT_ACCESS: + wtxapi_parse_text_access_event (event_str, &result->desc.text_access); + break; + + case WTX_EVENT_VIO_WRITE: + wtxapi_parse_vio_write_event (event_str, + event_desc->addlData, + event_desc->addlDataLen, + &result->desc.vio_write); + break; + + case WTX_EVENT_EVTPT_ADDED: + case WTX_EVENT_EVTPT_DELETED: + /* We do not handle eventpoints added/removed by other tools. + So ignore these events by falling back to the "default" case. */ + default: + /* Ignore this event. */ + xfree (result); + result = NULL; + break; + } + + wtx_result_free (current_wtx_handle, event_desc); + return result; +} + +WTX_CONTEXT_STATUS +wtxapi_context_status_get (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id) +{ + WTX_CONTEXT context; + initialize_context (&context, context_type, context_id); + return wtx_context_status_get (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context)); +} + + +/* Continue execution of target context. */ + +int +wtxapi_context_cont (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id) +{ + WTX_CONTEXT context; + initialize_context (&context, context_type, context_id); + return wtx_context_cont (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context)) != WTX_ERROR; +} + +/* Create a context on target. */ + +WTX_CONTEXT_ID_T +wtxapi_context_create (struct wtxapi_context_desc *p_context_desc) +{ + int ix; + WTX_CONTEXT_DESC context_desc; + memset (&context_desc, 0, sizeof (context_desc)); +#if WTX_PROT_VERSION != 2 + context_desc.wtxContextType = p_context_desc->context_type; + + if (p_context_desc->context_type == WTX_CONTEXT_PD) + { + context_desc.wtxContextDef.wtxPdContextDef.name = + p_context_desc->wtx_context_def.pd_context.name; + context_desc.wtxContextDef.wtxPdContextDef.options = + p_context_desc->wtx_context_def.pd_context.options; + context_desc.wtxContextDef.wtxPdContextDef.heapSize = + p_context_desc->wtx_context_def.pd_context.heap_size; + context_desc.wtxContextDef.wtxPdContextDef.lowPriority = + p_context_desc->wtx_context_def.pd_context.low_priority; + context_desc.wtxContextDef.wtxPdContextDef.highPriority = + p_context_desc->wtx_context_def.pd_context.high_priority; + context_desc.wtxContextDef.wtxPdContextDef.pagePoolList = + p_context_desc->wtx_context_def.pd_context.page_pool_list; + context_desc.wtxContextDef.wtxPdContextDef.destroyRtn = + p_context_desc->wtx_context_def.pd_context.destroy_rtn; + context_desc.wtxContextDef.wtxPdContextDef.linkPath = + p_context_desc->wtx_context_def.pd_context.link_path; + context_desc.wtxContextDef.wtxPdContextDef.redirIn = + p_context_desc->wtx_context_def.pd_context.redir_in; + context_desc.wtxContextDef.wtxPdContextDef.redirOut = + p_context_desc->wtx_context_def.pd_context.redir_out; + context_desc.wtxContextDef.wtxPdContextDef.redirErr = + p_context_desc->wtx_context_def.pd_context.redir_err; + context_desc.wtxContextDef.wtxPdContextDef.argc = + p_context_desc->wtx_context_def.pd_context.argc; + context_desc.wtxContextDef.wtxPdContextDef.argv = + p_context_desc->wtx_context_def.pd_context.argv; + } + else + { + context_desc.wtxContextDef.wtxTaskContextDef.pdId = + p_context_desc->wtx_context_def.task_context.pd_id; + context_desc.wtxContextDef.wtxTaskContextDef.returnType = + p_context_desc->wtx_context_def.task_context.return_type; + context_desc.wtxContextDef.wtxTaskContextDef.name = + p_context_desc->wtx_context_def.task_context.name; + context_desc.wtxContextDef.wtxTaskContextDef.priority = + p_context_desc->wtx_context_def.task_context.priority; + context_desc.wtxContextDef.wtxTaskContextDef.options = + p_context_desc->wtx_context_def.task_context.options; + context_desc.wtxContextDef.wtxTaskContextDef.stackBase = + p_context_desc->wtx_context_def.task_context.stack_base; + context_desc.wtxContextDef.wtxTaskContextDef.stackSize = + p_context_desc->wtx_context_def.task_context.stack_size; + context_desc.wtxContextDef.wtxTaskContextDef.entry = + p_context_desc->wtx_context_def.task_context.entry; + context_desc.wtxContextDef.wtxTaskContextDef.redirIn = + p_context_desc->wtx_context_def.task_context.redir_in; + context_desc.wtxContextDef.wtxTaskContextDef.redirOut = + p_context_desc->wtx_context_def.task_context.redir_out; + context_desc.wtxContextDef.wtxTaskContextDef.redirErr = + p_context_desc->wtx_context_def.task_context.redir_err; + context_desc.wtxContextDef.wtxTaskContextDef.argc = + p_context_desc->wtx_context_def.task_context.argc; + context_desc.wtxContextDef.wtxTaskContextDef.argv = + p_context_desc->wtx_context_def.task_context.argv; + } + +#else + + /* In WTX 2.0, we cannot create a new PD. */ + + if (p_context_desc->context_type == WTX_CONTEXT_PD) + return invalid_context_id; + + context_desc.contextType = p_context_desc->context_type; + context_desc.returnType = + p_context_desc->wtx_context_def.task_context.return_type; + context_desc.name = p_context_desc->wtx_context_def.task_context.name; + context_desc.priority = + p_context_desc->wtx_context_def.task_context.priority; + context_desc.options = p_context_desc->wtx_context_def.task_context.options; + context_desc.stackBase = + p_context_desc->wtx_context_def.task_context.stack_base; + context_desc.stackSize = + p_context_desc->wtx_context_def.task_context.stack_size; + context_desc.entry = p_context_desc->wtx_context_def.task_context.entry; + context_desc.redirIn = p_context_desc->wtx_context_def.task_context.redir_in; + context_desc.redirOut = + p_context_desc->wtx_context_def.task_context.redir_out; + for (ix = 0; ix < WTX_MAX_ARG_CNT; ix++) + if (ix < p_context_desc->wtx_context_def.task_context.argc) + context_desc.args[ix] = + p_context_desc->wtx_context_def.task_context.argv[ix]; + else + context_desc.args[ix] = NULL_PD; +#endif + return wtx_context_create (current_wtx_handle, &context_desc); +} + +/* Resume execution of a target context. */ + +int +wtxapi_context_resume (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id) +{ + WTX_CONTEXT context; + initialize_context (&context, context_type, context_id); + return wtx_context_resume (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context)) + != WTX_ERROR; +} + +/* Add exit evpt notification. */ + +evtpt_id_t +wtxapi_context_exit_notify_add (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id) +{ + WTX_CONTEXT context; + initialize_context (&context, context_type, context_id); + return wtx_context_exit_notify_add (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context)); +} + +/* Kill a target context. */ + +int +wtxapi_context_kill (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id) +{ + WTX_CONTEXT context; + initialize_context (&context, context_type, context_id); +#if WTX_PROT_VERSION != 2 + return wtx_context_kill (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context), + WTX_PD_DELETE_OPTION_NONE) != WTX_ERROR; +#else + return wtx_context_kill (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context)) != WTX_ERROR; +#endif +} + +/* Single step exec of target context. */ + +int +wtxapi_context_step (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id, wtxapi_tgt_addr_t step_start, + wtxapi_tgt_addr_t step_end) +{ + WTX_CONTEXT context; + initialize_context (&context, context_type, context_id); + return wtx_context_step (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context), + step_start, step_end) != WTX_ERROR; +} + +/* Suspend a target context. */ + +int +wtxapi_context_suspend (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id) +{ + WTX_CONTEXT context; + initialize_context (&context, context_type, context_id); + return wtx_context_suspend (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context)) + != WTX_ERROR; +} + +int +wtxapi_context_stop (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id) +{ + WTX_CONTEXT context; + initialize_context (&context, context_type, context_id); + +#if WTX_PROT_VERSION != 2 + return wtx_context_stop (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context)) != WTX_ERROR; +#else + /* FIXME : wtxContextStop does not exist on WTX 2.0. For now, use + wtxContextSuspend as a workaround. */ + + return wtx_context_suspend (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context)) + != WTX_ERROR; +#endif +} + +/* List event points on TS. */ + +struct wtxapi_evtpt_list * +wtxapi_eventpoint_list_get () +{ + int ix; + struct wtxapi_evtpt_list *evtpt_list; + wtx_evtpt_list *wtx_list; + wtx_list = wtx_eventpoint_list_get (current_wtx_handle); + + if (!wtx_list) + return NULL; + + evtpt_list = (struct wtxapi_evtpt_list *) + xmalloc (sizeof (struct wtxapi_evtpt_list)); + evtpt_list->n_evtpt = wtx_list->nEvtpt; + evtpt_list->p_evtpt_info = (struct wtxapi_evtpt_info *) + xmalloc (sizeof (struct wtxapi_evtpt_info) * wtx_list->nEvtpt); + for (ix = 0; ix < wtx_list->nEvtpt; ix++) + { + evtpt_list->p_evtpt_info[ix].wtx_evtpt.event.event_type = + wtx_list->pEvtptInfo[ix].wtxEvtpt.event.eventType; + evtpt_list->p_evtpt_info[ix].wtx_evtpt.event.num_args = + wtx_list->pEvtptInfo[ix].wtxEvtpt.event.numArgs; + evtpt_list->p_evtpt_info[ix].wtx_evtpt.event.args = (wtxapi_tgt_arg_t *) + xmalloc (wtx_list->pEvtptInfo[ix].wtxEvtpt.event.numArgs * + sizeof (wtxapi_tgt_arg_t)); + memcpy (evtpt_list->p_evtpt_info[ix].wtx_evtpt.event.args, + wtx_list->pEvtptInfo[ix].wtxEvtpt.event.args, + wtx_list->pEvtptInfo[ix].wtxEvtpt.event.numArgs * + sizeof (wtxapi_tgt_arg_t)); + evtpt_list->p_evtpt_info[ix].wtx_evtpt.context.context_type = + wtx_list->pEvtptInfo[ix].wtxEvtpt.context.contextType; + evtpt_list->p_evtpt_info[ix].wtx_evtpt.context.context_id = + wtx_list->pEvtptInfo[ix].wtxEvtpt.context.contextId; + evtpt_list->p_evtpt_info[ix].wtx_evtpt.action.action_type = + wtx_list->pEvtptInfo[ix].wtxEvtpt.action.actionType; + evtpt_list->p_evtpt_info[ix].wtx_evtpt.action.action_arg = + wtx_list->pEvtptInfo[ix].wtxEvtpt.action.actionArg; + evtpt_list->p_evtpt_info[ix].wtx_evtpt.action.call_rtn = + wtx_list->pEvtptInfo[ix].wtxEvtpt.action.callRtn; + evtpt_list->p_evtpt_info[ix].wtx_evtpt.action.call_arg = + wtx_list->pEvtptInfo[ix].wtxEvtpt.action.callArg; + evtpt_list->p_evtpt_info[ix].tool_id = wtx_list->pEvtptInfo[ix].toolId; + evtpt_list->p_evtpt_info[ix].evtpt_num = + wtx_list->pEvtptInfo[ix].evtptNum; + } + + wtx_result_free (current_wtx_handle, wtx_list); + return evtpt_list; +} + +/* Free mem allocated by WTX API call. */ + +int +wtxapi_result_free (void *p_result) +{ + return wtx_result_free (current_wtx_handle, p_result) != WTX_ERROR; +} + +/* Evaluate Gopher string on target. */ + +WTX_GOPHER_TAPE * +wtxapi_gopher_eval (pd_id_t pd_id, const char *input_string) +{ +#if WTX_PROT_VERSION != 2 + return wtx_gopher_eval (current_wtx_handle, pd_id, input_string); +#else + return wtx_gopher_eval (current_wtx_handle, input_string); +#endif +} + +/* Get info about memory pool. */ + +WTX_MEM_INFO * +wtxapi_mem_info_get (pd_id_t pd_id) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_info_get (current_wtx_handle, pd_id); +#else + return wtx_mem_info_get (current_wtx_handle); +#endif +} + +/* Alloc blocks in memory pool. */ + +wtxapi_tgt_addr_t +wtxapi_mem_alloc (pd_id_t pd_id, int num_bytes) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_alloc (current_wtx_handle, pd_id, num_bytes); +#else + return wtx_mem_alloc (current_wtx_handle, num_bytes); +#endif +} + +/* Perform checksum on target memory. */ + +int +wtxapi_mem_checksum (pd_id_t pd_id, wtxapi_tgt_addr_t start_addr, + int num_bytes) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_checksum (current_wtx_handle, pd_id, start_addr, num_bytes); +#else + return wtx_mem_checksum (current_wtx_handle, start_addr, num_bytes); +#endif +} + +/* Move a block of target memory. */ + +int +wtxapi_mem_move (pd_id_t src_pd_id, wtxapi_tgt_addr_t src_addr, + pd_id_t dst_pd_id, wtxapi_tgt_addr_t dest_addr, int num_bytes) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_move (current_wtx_handle, src_pd_id, src_addr, dst_pd_id, + dest_addr, num_bytes) != WTX_ERROR; +#else + return wtx_mem_move (current_wtx_handle, src_addr, dest_addr, + num_bytes) != WTX_ERROR; +#endif +} + +/* Free a block of target memory. */ + +int +wtxapi_mem_free (pd_id_t pd_id, wtxapi_tgt_addr_t address) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_free (current_wtx_handle, pd_id, address) != WTX_ERROR; +#else + return wtx_mem_free (current_wtx_handle, address) != WTX_ERROR; +#endif +} + +/* Read memory from the target. */ + +int +wtxapi_mem_read (pd_id_t pd_id, wtxapi_tgt_addr_t from_addr, + void *to_addr, int num_bytes) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_read (current_wtx_handle, pd_id, from_addr, to_addr, + num_bytes, 0); +#else + return wtx_mem_read (current_wtx_handle, from_addr, to_addr, num_bytes); +#endif +} + +/* Read memory on WIDTH bytes. */ + +int +wtxapi_mem_width_read (pd_id_t pd_id, wtxapi_tgt_addr_t from_addr, + void *to_addr, int num_bytes, int width) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_width_read (current_wtx_handle, pd_id, from_addr, to_addr, + num_bytes, width, 0); +#else + return wtx_mem_width_read (current_wtx_handle, from_addr, to_addr, num_bytes, + width); +#endif +} + +/* Write memory on the target. */ + +int +wtxapi_mem_write (pd_id_t pd_id, void *from_addr, + wtxapi_tgt_addr_t to_addr, int num_bytes) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_write (current_wtx_handle, pd_id, from_addr, to_addr, + num_bytes, 0); +#else + return wtx_mem_write (current_wtx_handle, from_addr, to_addr, num_bytes); +#endif +} + +/* Write memory on the target on WIDTH bytes large. */ + +int +wtxapi_mem_width_write (pd_id_t pd_id, void *from_addr, + wtxapi_tgt_addr_t to_addr, int num_bytes, int width) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_width_write (current_wtx_handle, pd_id, from_addr, to_addr, + num_bytes, width, 0); +#else + return wtx_mem_width_write (current_wtx_handle, from_addr, to_addr, + num_bytes, width); +#endif +} + +/* Set target memory to given value. */ + +int +wtxapi_mem_set (pd_id_t pd_id, wtxapi_tgt_addr_t addr, int num_bytes, int val) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_set (current_wtx_handle, pd_id, addr, num_bytes, val); +#else + return wtx_mem_set (current_wtx_handle, addr, num_bytes, val); +#endif +} + +/* Add memory to the agent pool. */ + +int +wtxapi_mem_add_to_pool (pd_id_t pd_id, wtxapi_tgt_addr_t address, int size) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_add_to_pool (current_wtx_handle, pd_id, address, + size) != WTX_ERROR; +#else + return wtx_mem_add_to_pool (current_wtx_handle, address, size) != WTX_ERROR; +#endif +} + +/* Reallocate a block of target mem. */ + +wtxapi_tgt_addr_t +wtxapi_mem_realloc (pd_id_t pd_id, wtxapi_tgt_addr_t address, int num_bytes) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_realloc (current_wtx_handle, pd_id, address, num_bytes); +#else + return wtx_mem_realloc (current_wtx_handle, address, num_bytes); +#endif +} + +/* Allocate aligned target memory. */ + +wtxapi_tgt_addr_t +wtxapi_mem_align (pd_id_t pd_id, wtxapi_tgt_addr_t alignment, int num_bytes) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_align (current_wtx_handle, pd_id, alignment, num_bytes); +#else + return wtx_mem_align (current_wtx_handle, alignment, num_bytes); +#endif +} + +/* Scan target memory for pattern. */ + +int +wtxapi_mem_scan (pd_id_t pd_id, int match, wtxapi_tgt_addr_t start_addr, + wtxapi_tgt_addr_t end_addr, int num_bytes, void *pattern, + wtxapi_tgt_addr_t * p_result) +{ +#if WTX_PROT_VERSION != 2 + return wtx_mem_scan (current_wtx_handle, pd_id, TO_BOOL (match), start_addr, + end_addr, num_bytes, pattern, p_result) != WTX_ERROR; +#else + return wtx_mem_scan (current_wtx_handle, TO_BOOL (match), start_addr, + end_addr, num_bytes, pattern, p_result) != WTX_ERROR; +#endif +} + +/* Checks validity of target memory. */ + +int +wtxapi_obj_module_checksum (pd_id_t pd_id, module_id_t module_id, + char *module_name) +{ +#if WTX_PROT_VERSION != 2 + return wtx_obj_module_checksum (current_wtx_handle, pd_id, module_id, + module_name) != WTX_ERROR; +#else + return wtx_obj_module_checksum (current_wtx_handle, module_id, + module_name) != WTX_ERROR; +#endif +} + +/* Find obj module ID from name. */ + +module_id_t +wtxapi_obj_module_find_id (pd_id_t pd_id, const char *module_name) +{ + module_id_t module_id; +#if WTX_PROT_VERSION != 2 + module_id = wtx_obj_module_find_id (current_wtx_handle, pd_id, module_name); +#else + module_id = wtx_obj_module_find_id (current_wtx_handle, module_name); +#endif + return module_id; +} + +module_id_t +wtxapi_obj_module_in_system_find_id (const char *module_name) +{ +#if WTX_PROT_VERSION != 2 + const pd_id_t current_pd = wtxapi_pd_current_get (current_wtx_handle); + module_id_t module_id; + + module_id = wtx_obj_module_find_id (current_wtx_handle, current_pd, module_name); + if (module_id != WTX_ERROR) + return module_id; + + return wtx_obj_module_find_id (current_wtx_handle, WTX_PD_ALL, module_name); +#else + return wtx_obj_module_find_id (current_wtx_handle, module_name); +#endif +} + +/* Find module name given its ID. */ + +const char * +wtxapi_obj_module_find_name (pd_id_t pd_id, module_id_t module_id) +{ +#if WTX_PROT_VERSION != 2 + return wtx_obj_module_find_name (current_wtx_handle, pd_id, module_id); +#else + return wtx_obj_module_find_name (current_wtx_handle, module_id); +#endif +} + +/* Allocate a new wtxapi_module_info. */ + +static struct wtxapi_module_info * +new_wtxapi_module_info (WTX_MODULE_INFO *wtx_minfo) +{ + int i; + struct wtxapi_module_info *module_info; + + if (!wtx_minfo) + return NULL; + + module_info = (struct wtxapi_module_info *) + xzalloc (sizeof (struct wtxapi_module_info)); +#if WTX_PROT_VERSION != 2 + module_info->pd_id = wtx_minfo->pdId; + module_info->section_addrs = alloc_section_addr_info (wtx_minfo->nSections); + for (i = 0; i < wtx_minfo->nSections; i++) + { + struct other_sections *other = module_info->section_addrs->other + i; + + other->name = xstrdup (wtx_minfo->section[i].name); + other->addr = wtx_minfo->section[i].baseAddr; + /* brobecker/2007-05-14: The sectindex should really be set to + the same index as the BFD section index. But accessing the BFD + data at this point is not easy, so I am making a bet instead + that the BFD index is the same as the WTX section index. If + this assertion turns out to be false, then we'll have to add + some fixup code in remote-wtx.c that recomputes all section + indexes from BFD. */ + other->sectindex = i; + } + module_info->segments = NULL; +#else + /* On Tornado 2, the system does not give us access to the section + addresses, but 3 segment base addresses instead, from which we + need to compute the actual section addresses. Ideally, it would + have been nice to compute these addresses at this point, to make + the behavior of this function independent of the Tornado version, + but the implementation is too awkward (one of the problems we + are facing is trying to locate the object file on the host file + system, which is something we already do, but sometime later in + another part of the code, and using the result from this function). + So we just return the segment addresses for now, and let the client + deal with the conversion at a more appropriate moment. */ + gdb_assert (wtx_minfo->nSegments == 3); + + module_info->pd_id = NULL_PD; + module_info->section_addrs = NULL; + module_info->segments = + (struct segment_addresses *) xmalloc (sizeof (struct segment_addresses)); + module_info->segments->text_addr = wtx_minfo->segment[0].addr; + module_info->segments->data_addr = wtx_minfo->segment[1].addr; + module_info->segments->bss_addr = wtx_minfo->segment[2].addr; +#endif + module_info->module_id = wtx_minfo->moduleId; + if (wtx_minfo->moduleName) + module_info->module_name = xstrdup (wtx_minfo->moduleName); + module_info->load_flag = wtx_minfo->loadFlag; + module_info->undef_list = NULL; + return module_info; +} + +/* Give info on obj module. */ + +struct wtxapi_module_info * +wtxapi_obj_module_info_get (pd_id_t pd_id, module_id_t module_id) +{ + struct wtxapi_module_info *module_info; + WTX_MODULE_INFO *wtx_minfo; +#if WTX_PROT_VERSION != 2 + wtx_minfo = wtx_obj_module_info_get (current_wtx_handle, pd_id, module_id); +#else + wtx_minfo = wtx_obj_module_info_get (current_wtx_handle, module_id); +#endif + if (!wtx_minfo) + return NULL; + + module_info = new_wtxapi_module_info (wtx_minfo); + wtx_result_free (current_wtx_handle, wtx_minfo); + return module_info; +} + +/* List loaded obj modules. */ + +struct wtxapi_module_list * +wtxapi_obj_module_list_get (pd_id_t pd_id) +{ + WTX_MODULE_LIST *wtx_mlist; + struct wtxapi_module_list *list; + int ix = 0; +#if WTX_PROT_VERSION != 2 + WTX_MOD_FIND_CRITERIA criteria; + WTX_MODULE *current; + + memset (&criteria, 0, sizeof (criteria)); + criteria.options = WTX_MOD_FIND_ALL; + criteria.pdId = pd_id; + criteria.moduleId = 0; + criteria.moduleName = NULL; + criteria.ref = 0; + + wtx_mlist = wtx_obj_module_list_get (current_wtx_handle, &criteria); + + if (!wtx_mlist) + return NULL; + + list = (struct wtxapi_module_list *) + xmalloc (sizeof (struct wtxapi_module_list)); + + /* Note: as the module list is expected to have, say, less than 10 + elements, the full copy should not take much time. */ + + list->num_obj_mod = 0; + for (current = wtx_mlist->pModule; current; current = current->next) + list->num_obj_mod++; + + list->mod_id_array = (int *) xmalloc (list->num_obj_mod * sizeof (int)); + list->pd_id_array = (pd_id_t *) + xmalloc (list->num_obj_mod * sizeof (pd_id_t)); + for (current = wtx_mlist->pModule; current; current = current->next) + { + list->mod_id_array[ix] = current->moduleId; + list->pd_id_array[ix] = current->pdId; + ix++; + } + +#else + wtx_mlist = wtx_obj_module_list (current_wtx_handle); + + if (!wtx_mlist) + return NULL; + + list = (struct wtxapi_module_list *) + xmalloc (sizeof (struct wtxapi_module_list)); + list->num_obj_mod = wtx_mlist->numObjMod; + list->mod_id_array = (int *) xmalloc (list->num_obj_mod * sizeof (int)); + list->pd_id_array = (pd_id_t *) + xmalloc (list->num_obj_mod * sizeof (pd_id_t)); + for (ix = 0; ix < list->num_obj_mod; ix++) + list->mod_id_array[ix] = wtx_mlist->modIdList[ix]; + memset (list->pd_id_array, 0, list->num_obj_mod * sizeof (pd_id_t)); +#endif + wtx_result_free (current_wtx_handle, wtx_mlist); + return list; +} + +/* Load a new object module. */ + +struct wtxapi_module_info * +wtxapi_obj_module_load (pd_id_t pd_id, char *filename, int load_flags) +{ + struct wtxapi_module_info *minfo; + wtx_module_info * wtx_minfo; + +#if WTX_PROT_VERSION != 2 + WTX_MODULE_FILE_DESC wtx_fdesc; + + memset (&wtx_fdesc, 0, sizeof (wtx_fdesc)); + wtx_fdesc.filename = filename; + wtx_fdesc.loadFlag = load_flags; + + wtx_minfo = wtx_obj_module_load (current_wtx_handle, pd_id, &wtx_fdesc, + WTX_LOAD_FROM_TOOL); + + if (!wtx_minfo) + return NULL; + + minfo = new_wtxapi_module_info (wtx_minfo); + minfo->undef_list = + new_wtxapi_symbol_list_from_symbol (wtx_minfo->undefSymList.pSymbol); + if (minfo->undef_list) + minfo->undef_list->wtx_result_to_cleanup = (void *) wtx_minfo; +#else + WTX_LD_M_FILE_DESC wtx_fdesc; + + memset (&wtx_fdesc, 0, sizeof (wtx_fdesc)); + wtx_fdesc.filename = filename; + wtx_fdesc.loadFlag = load_flags; + + wtx_minfo = wtx_obj_module_load (current_wtx_handle, &wtx_fdesc); + + if (!wtx_minfo) + return NULL; + minfo = wtxapi_obj_module_info_get (wtxapi_pd_current_get (), + wtx_minfo->moduleId); + if (minfo->undef_list) + minfo->undef_list->wtx_result_to_cleanup = (void *) wtx_minfo; +#endif + return minfo; +} + +/* The same as wtxapi_obj_module_load except that it temporary changes + the WTX timeout value to the given TIMEOUT. + + Basically, this function changes the WTX timeout to TIMEOUT, + calls wtxapi_obj_module_load, and then restores the old timeout. */ + +struct wtxapi_module_info * +wtxapi_module_load (pd_id_t pd_id, char *filename, int load_flag, int timeout) +{ + int saved_timeout; + struct wtxapi_module_info *module_info; + + wtxapi_timeout_get (&saved_timeout); + wtxapi_timeout_set (timeout); + module_info = wtxapi_obj_module_load (pd_id, filename, load_flag); + wtxapi_timeout_set (saved_timeout); + + return module_info; +} + +/* Unload an obj module from target. */ + +int +wtxapi_obj_module_unload (pd_id_t pd_id, module_id_t mod_id) +{ +#if WTX_PROT_VERSION != 2 + return wtx_obj_module_unload (current_wtx_handle, pd_id, 0, + mod_id) != WTX_ERROR; +#else + return wtx_obj_module_unload (current_wtx_handle, mod_id) != WTX_ERROR; +#endif +} + +/* Unload an obj. module from target. */ + +int +wtxapi_obj_module_by_name_unload (pd_id_t pd_id, char *name) +{ +#if WTX_PROT_VERSION != 2 + return wtx_obj_module_by_name_unload (current_wtx_handle, pd_id, 0, + name) != WTX_ERROR; +#else + return wtx_obj_module_by_name_unload (current_wtx_handle, name) != WTX_ERROR; +#endif +} + +/* Send events matching expression. */ + +int +wtxapi_register_for_event (const char *reg_exp) +{ + return wtx_register_for_event (current_wtx_handle, reg_exp) != WTX_ERROR; +} + +/* Read register data from the target. */ + +int +wtxapi_regs_get (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id, WTX_REG_SET_TYPE reg_set, + int first_byte, int num_bytes, void *reg_memory) +{ + WTX_CONTEXT context; + initialize_context (&context, context_type, context_id); + return wtx_regs_get (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context), reg_set, + first_byte, num_bytes, reg_memory) != WTX_ERROR; +} + +/* Write to registers on the target. */ + +int +wtxapi_regs_set (WTX_CONTEXT_TYPE context_type, WTX_CONTEXT_ID_T context_id, + WTX_REG_SET_TYPE reg_set, int first_byte, int num_bytes, + void *reg_memory) +{ + WTX_CONTEXT context; + initialize_context (&context, context_type, context_id); + return wtx_regs_set (current_wtx_handle, + MARSHALL_WTX_CONTEXT_PARAM (context), reg_set, + first_byte, num_bytes, reg_memory) != WTX_ERROR; +} + +/* Convert str to a wtxapi_tgt_addr_t. */ + +wtxapi_tgt_addr_t +wtxapi_str_to_tgt_addr (const char *str) +{ + return wtx_str_to_tgt_addr (current_wtx_handle, str); +} + +/* Convert str to context ID. */ + +WTX_CONTEXT_ID_T +wtxapi_str_to_context_id (const char *str) +{ + return wtx_str_to_context_id (current_wtx_handle, str); +} + +/* Convert str ton context type. */ + +WTX_CONTEXT_TYPE +wtxapi_str_to_context_type (const char *str) +{ + return wtx_str_to_context_type (current_wtx_handle, str); +} + +/* Convert str to an int. */ + +int +wtxapi_str_to_int32 (const char *str) +{ + return wtx_str_to_int32 (current_wtx_handle, str); +} + +/* Convert string to event type. */ + +WTX_EVENT_TYPE +wtxapi_str_to_event_type (const char *str) +{ + return wtx_str_to_event_type (current_wtx_handle, str); +} + +/* Add symbol with given params. */ + +int +wtxapi_sym_add (pd_id_t pd_id, const char *sym_name, + wtxapi_tgt_addr_t sym_value, int sym_type) +{ +#if WTX_PROT_VERSION != 2 + return wtx_sym_add (current_wtx_handle, pd_id, sym_name, sym_value, + sym_type) != WTX_ERROR; +#else + return wtx_sym_add (current_wtx_handle, sym_name, sym_value, + (UINT8) sym_type) != WTX_ERROR; +#endif +} + +static struct wtxapi_symbol_list * +new_wtxapi_symbol_list (WTX_SYM_LIST *wtx_sym) +{ + struct wtxapi_symbol_list *sym_list; + + if (!wtx_sym) + return NULL; + + sym_list = (struct wtxapi_symbol_list *) + xmalloc (sizeof (struct wtxapi_symbol_list)); + sym_list->wtx_result_to_cleanup = (void *) wtx_sym; + sym_list->first = wtx_sym->pSymbol; + sym_list->current = sym_list->first; + return sym_list; +} + +static struct wtxapi_symbol_list * +new_wtxapi_symbol_list_from_symbol (WTX_SYMBOL *wtx_sym) +{ + struct wtxapi_symbol_list *sym_list; + + if (!wtx_sym) + return NULL; + + sym_list = (struct wtxapi_symbol_list *) + xmalloc (sizeof (struct wtxapi_symbol_list)); + sym_list->wtx_result_to_cleanup = (void *) wtx_sym; + sym_list->first = wtx_sym; + sym_list->current = wtx_sym; + return sym_list; +} + +/* Find info on symbol. Based on wtxSymFind WTX 2.0, with two differences: + _ one additional parameter: the protection domain ID (PD_ID); + _ no filter on the type. */ + +struct wtxapi_symbol_list * +wtxapi_sym_find (pd_id_t pd_id, char *sym_name, + wtxapi_tgt_addr_t sym_value, int exact_name) +{ +#if WTX_PROT_VERSION != 2 + WTX_SYM_FIND_CRITERIA criteria; + memset (&criteria, 0, sizeof (criteria)); + criteria.pdId = pd_id; + criteria.type = 0; + criteria.nSymbols = 1; + criteria.ref = 0; + criteria.moduleId = 0; + criteria.moduleName = NULL; + + if (sym_name) + { + criteria.findName = sym_name; + criteria.findValue = 0; + criteria.options |= WTX_SYM_FIND_BY_NAME; + + if (exact_name) + criteria.options |= WTX_SYM_FIND_BY_EXACT_NAME; + } + else + { + criteria.findName = NULL; + criteria.findValue = sym_value; + criteria.options |= WTX_SYM_FIND_BY_VALUE; + + if (exact_name) + criteria.options |= WTX_SYM_FIND_BY_EXACT_VALUE; + } + + return new_wtxapi_symbol_list_from_symbol (wtx_sym_find (current_wtx_handle, + &criteria)); +#else + return new_wtxapi_symbol_list_from_symbol (wtx_sym_find (current_wtx_handle, + sym_name, + sym_value, + exact_name, 0, 0)); +#endif +} + +/* Get list of symbols. Based on wtxSymListGet WTX 2.0, with three differences: + - one additional parameter: the protection domain ID (PD_ID); + - no filter on the unknown symbols; + - no filter on the module name/id. */ + +struct wtxapi_symbol_list * +wtxapi_sym_list_get (pd_id_t pd_id, char *substring, wtxapi_tgt_addr_t value) +{ + struct wtxapi_symbol_list *sym_list; + WTX_SYM_LIST *wtx_sym_list; +#if WTX_PROT_VERSION != 2 + WTX_SYM_FIND_CRITERIA criteria; + memset (&criteria, 0, sizeof (criteria)); + criteria.pdId = pd_id; + criteria.type = 0; + criteria.nSymbols = 0; + criteria.ref = 0; + criteria.moduleId = 0; + criteria.moduleName = NULL; + + if (substring) + { + criteria.findName = substring; + criteria.findValue = 0; + criteria.options |= WTX_SYM_FIND_BY_NAME; + } + else + { + criteria.findName = NULL; + criteria.findValue = value; + criteria.options |= WTX_SYM_FIND_BY_VALUE; + } + + wtx_sym_list = wtx_sym_list_get (current_wtx_handle, &criteria); +#else + wtx_sym_list = + wtx_sym_list_get (current_wtx_handle, substring, NULL, value, FALSE); +#endif + sym_list = new_wtxapi_symbol_list (wtx_sym_list); + return sym_list; +} + +/* Get list of symbols. */ + +struct wtxapi_symbol_list * +wtxapi_sym_list_by_module_id_get (pd_id_t pd_id, const char *string, + module_id_t module_id, + wtxapi_tgt_addr_t value, + int list_unknown) +{ +#if WTX_PROT_VERSION != 2 + return new_wtxapi_symbol_list + (wtx_sym_list_by_module_id_get (current_wtx_handle, pd_id, string, + module_id, value, TO_BOOL (list_unknown))); +#else + return new_wtxapi_symbol_list + (wtx_sym_list_by_module_id_get (current_wtx_handle, string, module_id, + value, TO_BOOL (list_unknown))); +#endif +} + +/* Get list of symbols. */ + +struct wtxapi_symbol_list * +wtxapi_sym_list_by_module_name_get (pd_id_t pd_id, const char *string, + const char *module_name, + wtxapi_tgt_addr_t value, + int list_unknown) +{ +#if WTX_PROT_VERSION != 2 + return new_wtxapi_symbol_list + (wtx_sym_list_by_module_name_get (current_wtx_handle, pd_id, string, + module_name, value, + TO_BOOL (list_unknown))); +#else + return new_wtxapi_symbol_list + (wtx_sym_list_by_module_name_get (current_wtx_handle, string, + module_name, value, + TO_BOOL (list_unknown))); +#endif +} + +/* Remove a symbol from sym table. */ + +int +wtxapi_sym_remove (pd_id_t pd_id, const char *sym_name, int sym_type) +{ +#if WTX_PROT_VERSION != 2 + return wtx_sym_remove (current_wtx_handle, pd_id, sym_name, + sym_type) != WTX_ERROR; +#else + return wtx_sym_remove (current_wtx_handle, sym_name, sym_type) != WTX_ERROR; +#endif +} + +/* Return sym table info. */ + +struct wtxapi_sym_tbl_info * +wtxapi_sym_tbl_info_get (pd_id_t pd_id) +{ + WTX_SYM_TBL_INFO *wtx_tbl_info; + struct wtxapi_sym_tbl_info *tbl_info; + pd_id_t current_pd_id; +#if WTX_PROT_VERSION != 2 + wtx_tbl_info = wtx_sym_tbl_info_get (current_wtx_handle, pd_id); + current_pd_id = wtx_tbl_info->pdId; +#else + wtx_tbl_info = wtx_sym_tbl_info_get (current_wtx_handle); + current_pd_id = NULL_PD; +#endif + + if (!wtx_tbl_info) + return NULL; + + tbl_info = (struct wtxapi_sym_tbl_info *) + xmalloc (sizeof (struct wtxapi_sym_tbl_info)); + tbl_info->pd_id = current_pd_id; + tbl_info->sym_num = wtx_tbl_info->symNum; + tbl_info->same_name_ok = (wtx_tbl_info->sameNameOk == TRUE); + wtx_result_free (current_wtx_handle, wtx_tbl_info); + return tbl_info; +} + +/* Reset the target. */ + +int +wtxapi_target_reset () +{ + return wtx_target_reset (current_wtx_handle) != WTX_ERROR; +} + +/* Get target server name. */ + +const char * +wtxapi_ts_name_get () +{ + return wtx_ts_name_get (current_wtx_handle); +} + +/* Get the target CPU type code. */ + +int +wtxapi_target_cpu_type_get () +{ + return wtx_target_cpu_type_get (current_wtx_handle); +} + +/* Check for floating point processor. */ + +int +wtxapi_target_has_fpp_get () +{ + return wtx_target_has_fpp_get (current_wtx_handle); +} + +/* Get edianness of target. */ + +WTX_ENDIAN_T +wtxapi_target_endian_get () +{ + return wtx_target_endian_get (current_wtx_handle); +} + +/* Get target boot line info (or NULL on error). + + The string returned is a pointer to temporary memory, and should + be duplicated if it is to be stored. */ + +const char * +wtxapi_target_bootline_get () +{ + return wtx_target_bootline_get (current_wtx_handle); +} + +/* Return name of current tool. */ + +const char * +wtxapi_tool_name_get () +{ + return wtx_tool_name_get (current_wtx_handle); +} + +/* Return the Tornado version. */ + +const char * +wtxapi_ts_version_get () +{ + return wtx_ts_version_get (current_wtx_handle); +} + +/* Return the version of WTX. */ +int +wtxapi_version_get () +{ + return WTX_PROT_VERSION; +} + +/* Unregister for some events. */ + +int +wtxapi_unregister_for_event (char *reg_exp) +{ + return wtx_unregister_for_event (current_wtx_handle, reg_exp) != WTX_ERROR; +} + +/* Call func on target within agent. */ + +int +wtxapi_direct_call (wtxapi_tgt_addr_t entry, void *p_ret_val, + wtxapi_tgt_arg_t arg0, wtxapi_tgt_arg_t arg1, + wtxapi_tgt_arg_t arg2, wtxapi_tgt_arg_t arg3, + wtxapi_tgt_arg_t arg4, wtxapi_tgt_arg_t arg5, + wtxapi_tgt_arg_t arg6, wtxapi_tgt_arg_t arg7, + wtxapi_tgt_arg_t arg8, wtxapi_tgt_arg_t arg9) +{ +#if WTX_PROT_VERSION != 2 + return wtx_direct_call (current_wtx_handle, entry, p_ret_val, 10, arg0, arg1, + arg2, arg3, arg4, arg5, arg6, arg7, arg8, + arg9) != WTX_ERROR; +#else + return wtx_direct_call (current_wtx_handle, entry, p_ret_val, arg0, arg1, + arg2, arg3, arg4, arg5, arg6, arg7, arg8, + arg9) != WTX_ERROR; +#endif +} + +/* Get info about target and server. */ + +struct wtxapi_ts_info * +wtxapi_ts_info_get () +{ + static const char vxworks_prefix[] = "VxWorks"; + WTX_TS_INFO *wtx_tsinfo = wtx_ts_info_get (current_wtx_handle); + struct wtxapi_ts_info *ts_info; + char *version; + if (!wtx_tsinfo) + return NULL; + + ts_info = (struct wtxapi_ts_info *) + xmalloc (sizeof (struct wtxapi_ts_info)); + memset (ts_info, 0, sizeof (struct wtxapi_ts_info)); + ts_info->tgt_link_desc = wtx_tsinfo->tgtLinkDesc; + +#if WTX_PROT_VERSION != 2 + if (wtx_tsinfo->tgtInfo.rtInfo.rtName) + ts_info->tgt_info.rt_info.rt_name = + xstrdup (wtx_tsinfo->tgtInfo.rtInfo.rtName); + if (wtx_tsinfo->tgtInfo.rtInfo.rtVersion) + ts_info->tgt_info.rt_info.rt_version = + xstrdup (wtx_tsinfo->tgtInfo.rtInfo.rtVersion); +#else + /* On VxWorks 5, the runtime name is not included into the rt info; + instead, the version information is prefixed by "vxWorks". + Strip it the prefix, move it to rt_name. */ + version = wtx_tsinfo->tgtInfo.rtInfo.rtVersion; + if (version) + { + if (strncmp (vxworks_prefix, version, strlen (vxworks_prefix)) == 0) + version += strlen (vxworks_prefix); + ts_info->tgt_info.rt_info.rt_version = xstrdup (version); + } + ts_info->tgt_info.rt_info.rt_name = xstrdup (vxworks_prefix); +#endif + ts_info->tgt_info.rt_info.cpu_type = + wtx_tsinfo->tgtInfo.rtInfo.cpuType; + +#if WTX_PROT_VERSION > 3 + if (wtx_tsinfo->tgtInfo.rtInfo.cpuVariant) + ts_info->tgt_info.rt_info.cpu_variant = + xstrdup (wtx_tsinfo->tgtInfo.rtInfo.cpuVariant); +#endif + + ts_info->tgt_info.rt_info.has_write_protect = + wtx_tsinfo->tgtInfo.rtInfo.hasWriteProtect; + ts_info->tgt_info.rt_info.page_size = + wtx_tsinfo->tgtInfo.rtInfo.pageSize; + ts_info->tgt_info.rt_info.endian = + wtx_tsinfo->tgtInfo.rtInfo.endian; + if (wtx_tsinfo->tgtInfo.rtInfo.bspName) + ts_info->tgt_info.rt_info.bsp_name = + xstrdup (wtx_tsinfo->tgtInfo.rtInfo.bspName); + if (wtx_tsinfo->tgtInfo.rtInfo.bootline) + ts_info->tgt_info.rt_info.boot_line = + xstrdup (wtx_tsinfo->tgtInfo.rtInfo.bootline); + ts_info->tgt_info.rt_info.mem_base = + wtx_tsinfo->tgtInfo.rtInfo.memBase; + ts_info->tgt_info.rt_info.mem_size = + wtx_tsinfo->tgtInfo.rtInfo.memSize; + ts_info->tgt_info.rt_info.num_regions = + wtx_tsinfo->tgtInfo.rtInfo.numRegions; + ts_info->tgt_info.rt_info.host_pool_base = + wtx_tsinfo->tgtInfo.rtInfo.hostPoolBase; + ts_info->tgt_info.rt_info.host_pool_size = + wtx_tsinfo->tgtInfo.rtInfo.hostPoolSize; + ts_info->tgt_info.agent_info.agent_version = + wtx_tsinfo->tgtInfo.agentInfo.agentVersion; + ts_info->tgt_info.agent_info.mtu = + wtx_tsinfo->tgtInfo.agentInfo.mtu; + ts_info->tgt_info.agent_info.mode = + wtx_tsinfo->tgtInfo.agentInfo.mode; + + if (wtx_tsinfo->version) + ts_info->version = xstrdup (wtx_tsinfo->version); + if (wtx_tsinfo->userName) + ts_info->user_name = xstrdup (wtx_tsinfo->userName); + if (wtx_tsinfo->lockMsg) + ts_info->lock_msg = xstrdup (wtx_tsinfo->lockMsg); +#if WTX_PROT_VERSION != 2 + ts_info->pd_initialized = (wtx_tsinfo->pdInitialized == TRUE); +#else + ts_info->pd_initialized = 1; +#endif + return ts_info; +} + +/* Reattach to the target. */ + +int +wtxapi_target_attach () +{ + return wtx_target_attach (current_wtx_handle) != WTX_ERROR; +} + +/* Probe to see if registry is running. */ + +int +wtxapi_probe () +{ + return wtx_probe (current_wtx_handle) != WTX_ERROR; +} + +/* Set WTX timeout. */ + +int +wtxapi_timeout_set (int msec) +{ + return wtx_timeout_set (current_wtx_handle, msec) != WTX_ERROR; +} + +/* Get the current timeout. */ + +int +wtxapi_timeout_get (int *p_msec) +{ + UINT32 wtx_timeout; + int result = wtx_timeout_get (current_wtx_handle, &wtx_timeout) != WTX_ERROR; + *p_msec = wtx_timeout; + return result; +} + +/* Create a new protection domain. */ + +pd_id_t +wtxapi_pd_create (const char *name, int options, int heap_size, + int low_priority, int high_priority, + wtxapi_tgt_addr_t page_pool_list, const char *link_path) +{ +#if WTX_PROT_VERSION != 2 + return wtx_pd_create (current_wtx_handle, name, options, heap_size, + low_priority, high_priority, page_pool_list, + link_path); +#else + return NULL_PD; +#endif +} + +/* Get kernel Protection Domain ID. */ + +pd_id_t +wtxapi_pd_kernel_get () +{ +#if WTX_PROT_VERSION != 2 + return wtx_pd_kernel_get (current_wtx_handle); +#else + return NULL_PD; +#endif +} + +/* Get the current Protection Domain. */ + +pd_id_t +wtxapi_pd_current_get () +{ +#if WTX_PROT_VERSION != 2 + return wtx_pd_current_get (current_wtx_handle); +#else + return NULL_PD; +#endif +} + +/* Set the current Protection Domain. */ + +int +wtxapi_pd_current_set (pd_id_t pd_id) +{ +#if WTX_PROT_VERSION != 2 + return wtx_pd_current_set (current_wtx_handle, pd_id) != WTX_ERROR; +#else + return pd_id == NULL_PD; +#endif +} + +/* Get the list of allocated PDs. */ + +/* NOTE: it performs a full copy of the PD description list. It should + not be a problem, we should not expect to many PDs. If there are + some speed issues, the solution would be to have the same kind of + model we use for wtxapi_symbol_list. To be investigated. */ + +struct wtxapi_pd_desc_q * +wtxapi_pd_info_q_get () +{ + struct wtxapi_pd_desc_q *pd_desc_list; +#if WTX_PROT_VERSION != 2 + WTX_PD_DESC_Q *wtx_pd_desc_q = wtx_pd_info_q_get (current_wtx_handle); + WTX_PD_DESC_Q *current_wtx_desc = wtx_pd_desc_q; + struct wtxapi_pd_desc_q *current_desc; + int ix; + + if (wtx_pd_desc_q == NULL) + return NULL; + + pd_desc_list = (struct wtxapi_pd_desc_q *) + xmalloc (sizeof (struct wtxapi_pd_desc_q)); + current_desc = pd_desc_list; + + for (current_wtx_desc = wtx_pd_desc_q; + current_wtx_desc != NULL; + current_wtx_desc = current_wtx_desc->pNext) + { + current_desc->pd_desc.pd_id = current_wtx_desc->wtxPdDesc.pdId; + if (current_wtx_desc->wtxPdDesc.pdName) + current_desc->pd_desc.pd_name = + xstrdup (current_wtx_desc->wtxPdDesc.pdName); + current_desc->pd_desc.pd_flags = current_wtx_desc->wtxPdDesc.pdFlags; + if (current_wtx_desc->wtxPdDesc.pdLinkPathStr) + current_desc->pd_desc.pd_link_path_str = + xstrdup (current_wtx_desc->wtxPdDesc.pdLinkPathStr); + current_desc->pd_desc.pd_link_path_count = + current_wtx_desc->wtxPdDesc.pdLinkPathCount; + if (current_wtx_desc->wtxPdDesc.pdLinkPathCount) + { + current_desc->pd_desc.pd_link_path = (pd_id_t *) + xmalloc (current_wtx_desc->wtxPdDesc.pdLinkPathCount + * sizeof (pd_id_t)); + for (ix = 0; ix < current_wtx_desc->wtxPdDesc.pdLinkPathCount; ix++) + current_desc->pd_desc.pd_link_path[ix] + = current_wtx_desc->wtxPdDesc.pdLinkPath[ix]; + + } + else + { + current_desc->pd_desc.pd_link_path = NULL; + } + if (current_wtx_desc->wtxPdDesc.pdAttachToCount) + { + current_desc->pd_desc.pd_attach_to_count = + current_wtx_desc->wtxPdDesc.pdAttachToCount; + current_desc->pd_desc.pd_attach_to = (pd_id_t *) + xmalloc (current_wtx_desc->wtxPdDesc.pdAttachToCount + * sizeof (pd_id_t)); + for (ix = 0; ix < current_wtx_desc->wtxPdDesc.pdAttachToCount; ix++) + current_desc->pd_desc.pd_attach_to[ix] + = current_wtx_desc->wtxPdDesc.pdAttachTo[ix]; + } + else + { + current_desc->pd_desc.pd_attach_to = NULL; + } + + if (current_wtx_desc->pNext != NULL) + { + current_desc->next = (struct wtxapi_pd_desc_q *) + xmalloc (sizeof (struct wtxapi_pd_desc_q)); + current_desc = current_desc->next; + } + else + current_desc->next = NULL; + } + wtx_result_free (current_wtx_handle, wtx_pd_desc_q); +#else + pd_desc_list = (struct wtxapi_pd_desc_q *) + xmalloc (sizeof (struct wtxapi_pd_desc_q)); + memset (&pd_desc_list, 0, sizeof (pd_desc_list)); + pd_desc_list->pd_desc.pd_name = xstrdup ("kernel"); + pd_desc_list->pd_desc.pd_link_path_str = xstrdup (""); +#endif + return pd_desc_list; +} + +/* Return non-zero if the given module has been fully linked, + or, in other words, relocation has already been performed. */ + +int +wtxapi_load_fully_linked (const struct wtxapi_module_info *module_info) +{ + /* The WTX_LOAD_FULLY_LINKED macro has been introduced *after* Vxworks 5.x. + For Vxworks 5.x targets, we simply define it ourselves. */ +#ifndef WTX_LOAD_FULLY_LINKED +#define WTX_LOAD_FULLY_LINKED 0x20 +#endif + + return module_info->load_flag & WTX_LOAD_FULLY_LINKED; +} + +/* Test target server availability. */ + +int +wtxapi_target_server_available_p () +{ + WTX_TS_INFO *ts_info = wtx_ts_info_get (current_wtx_handle); + return ts_info != NULL; +} + + +/* Symbol list handling. */ + +struct wtxapi_symbol * +get_current_wtxapi_symbol (struct wtxapi_symbol_list *list) +{ + struct wtxapi_symbol *sym; + if (!list || !list->current) + return NULL; + + sym = (struct wtxapi_symbol *) xmalloc (sizeof (struct wtxapi_symbol)); + copy_current_wtxapi_symbol (list, sym, wtxapi_symbol_copy_full); + return sym; +} + +void +copy_current_wtxapi_symbol (struct wtxapi_symbol_list *list, + struct wtxapi_symbol *to, int options) +{ + if (!to || !list || !list->current) + return; + + to->status = list->current->status; +#if WTX_PROT_VERSION != 2 + to->pd_id = list->current->pdId; +#else + to->pd_id = NULL_PD; +#endif + if (options != wtxapi_symbol_copy_dont_copy_name + && options != wtxapi_symbol_copy_dont_copy_strings + && list->current->name) + to->name = xstrdup (list->current->name); + else + to->name = NULL; + + if (options != wtxapi_symbol_copy_dont_copy_module_name + && options != wtxapi_symbol_copy_dont_copy_strings + && list->current->moduleName) + to->module_name = xstrdup (list->current->moduleName); + else + to->module_name = NULL; + + to->exact_name = (list->current->exactName == TRUE); + to->value = list->current->value; + to->type = list->current->type; + to->type_mask = list->current->typeMask; +} + +char * +current_wtxapi_symbol_name (struct wtxapi_symbol_list *list) +{ + return xstrdup (list->current->name); +} + +int +go_to_first_element_in_wtxapi_sym_list (struct wtxapi_symbol_list *list) +{ + if (!list || !list->first) + return 0; + + list->current = list->first; + return 1; +} + +int +go_to_next_element_in_wtxapi_sym_list (struct wtxapi_symbol_list *list) +{ + if (!list->current || !list->current->next) + return 0; + + list->current = list->current->next; + return 1; +} + +/* Deallocation functions. */ + +void +free_wtxapi_evtpt_list (struct wtxapi_evtpt_list *to_free) +{ + int ix; + for (ix = 0; ix < to_free->n_evtpt; ix++) + { + xfree (to_free->p_evtpt_info[ix].wtx_evtpt.event.args); + } + xfree (to_free->p_evtpt_info); + xfree (to_free); +} + +void +free_wtxapi_module_list (struct wtxapi_module_list *to_free) +{ + xfree (to_free->mod_id_array); + xfree (to_free->pd_id_array); + xfree (to_free); +} + +void +free_wtxapi_pd_desc_q (struct wtxapi_pd_desc_q *to_free) +{ + struct wtxapi_pd_desc_q *current; + struct wtxapi_pd_desc_q *element_to_deallocate = NULL; + + for (current = to_free; current != NULL; current = current->next) + { + if (element_to_deallocate) + xfree (element_to_deallocate); + if (current->pd_desc.pd_name) + xfree (current->pd_desc.pd_name); + if (current->pd_desc.pd_link_path_str) + xfree (current->pd_desc.pd_link_path_str); + if (current->pd_desc.pd_link_path) + xfree (current->pd_desc.pd_link_path); + if (current->pd_desc.pd_attach_to) + xfree (current->pd_desc.pd_attach_to); + element_to_deallocate = current; + } +} + +void +free_wtxapi_symbol (struct wtxapi_symbol *to_free) +{ + if (to_free->name) + xfree (to_free->name); + + if (to_free->module_name) + xfree (to_free->module_name); + + xfree (to_free); +} + +void +free_wtxapi_symbol_list (struct wtxapi_symbol_list *to_free) +{ + if (to_free->wtx_result_to_cleanup != NULL) + wtx_result_free (current_wtx_handle, to_free->wtx_result_to_cleanup); + + xfree (to_free); +} + +void +free_wtxapi_module_info (struct wtxapi_module_info *to_free) +{ + xfree (to_free->module_name); + if (to_free->section_addrs != NULL) + free_section_addr_info (to_free->section_addrs); + if (to_free->segments != NULL) + xfree (to_free->segments); + if (to_free->undef_list) + free_wtxapi_symbol_list (to_free->undef_list); + xfree (to_free); +} + +void +free_wtxapi_ts_info (struct wtxapi_ts_info *to_free) +{ + if (to_free->tgt_info.rt_info.rt_name) + xfree (to_free->tgt_info.rt_info.rt_name); + + if (to_free->tgt_info.rt_info.cpu_variant) + xfree (to_free->tgt_info.rt_info.cpu_variant); + + if (to_free->tgt_info.rt_info.rt_version) + xfree (to_free->tgt_info.rt_info.rt_version); + + if (to_free->tgt_info.rt_info.bsp_name) + xfree (to_free->tgt_info.rt_info.bsp_name); + + if (to_free->tgt_info.rt_info.boot_line) + xfree (to_free->tgt_info.rt_info.boot_line); + + if (to_free->version) + xfree (to_free->version); + + if (to_free->user_name) + xfree (to_free->user_name); + + if (to_free->lock_msg) + xfree (to_free->lock_msg); + + xfree (to_free); +} + +void +free_wtxapi_event_desc (struct wtxapi_event_desc *to_free) +{ + switch (to_free->event_type) + { + case WTX_EVENT_OBJ_UNLOADED: + xfree (to_free->desc.obj_unloaded.module_filename); + break; + case WTX_EVENT_VIO_WRITE: + xfree (to_free->desc.vio_write.data); + break; + } + + xfree (to_free); +} + + +/* cleanup functions. */ + +void +cleanup_wtxapi_evtpt_list (void *to_free) +{ + free_wtxapi_evtpt_list ((struct wtxapi_evtpt_list *) to_free); +} + +void +cleanup_wtxapi_module_list (void *to_free) +{ + free_wtxapi_module_list ((struct wtxapi_module_list *) to_free); +} + +void +cleanup_wtxapi_pd_desc_q (void *to_free) +{ + free_wtxapi_pd_desc_q ((struct wtxapi_pd_desc_q *) to_free); +} + +void +cleanup_wtxapi_symbol (void *to_free) +{ + free_wtxapi_symbol ((struct wtxapi_symbol *) to_free); +} + +void +cleanup_wtxapi_symbol_list (void *to_free) +{ + free_wtxapi_symbol_list ((struct wtxapi_symbol_list *) to_free); +} + +void +cleanup_wtxapi_module_info (void *to_free) +{ + free_wtxapi_module_info ((struct wtxapi_module_info *) to_free); +} + +void +cleanup_wtxapi_ts_info (void *to_free) +{ + free_wtxapi_ts_info ((struct wtxapi_ts_info *) to_free); +} + +void +cleanup_wtxapi_result_free (void *to_free) +{ + wtxapi_result_free (to_free); +} + + +/* Implements simple symbol lookup. */ + +int +remote_wtxapi_get_symbol_address (char *symbol_name, CORE_ADDR *symbol_addr) +{ + struct wtxapi_symbol_list *symbol_list; + struct wtxapi_symbol *symbol_info; + + symbol_list = wtxapi_sym_find (wtxapi_pd_current_get (), symbol_name, 0, 1); + symbol_info = get_current_wtxapi_symbol (symbol_list); + + if (symbol_info != NULL) + { + *symbol_addr = symbol_info->value; + + free_wtxapi_symbol (symbol_info); + free_wtxapi_symbol_list (symbol_list); + return 0; + } + else + { + *symbol_addr = 0; + return -1; + } +} + +/* Return non-zero if BoDA support (Breakpoint on Data Access) is available + on the system we're connected to. This routine assumes that we are + connected to the target server. */ + +int +wtxapi_target_has_BoDA (void) +{ + /* Will be set to 1 as soon as we've checked whether the system + we're running on provides BoDA or not. This is used to determine + whether BoDA_supported_p has been set yet, or not. */ + static int BoDA_support_checked_p = 0; + + /* Set to non-zero if BoDA is supported on the system. Set iff + BoDA_support_checked_p is non-zero. + + We're checking the support for BoDA in a lazy fashion, because + it's a tiny bit expensive (need to do a symbol lookup), and because + we need to be connected to the system before we do so. We could + be doing that check after connecting with the target server, but + that would be useless during the sessions when watchpoints are + not actually used. So we wait until we need to have this info + before we actually do the check. */ + static int BoDA_supported_p = 0; + + if (!BoDA_support_checked_p) + { + /* BoDA is supported by the target iff the symbol wdbEventClassHwBpVa + is defined in the Core OS partition. Instead of trying to find + the PD ID of the Core OS partition, we just seach the symbol + in all partitions. It's unlikely that any other partition + would define a symbol using that name, so accept that risk. */ + struct wtxapi_symbol_list *symbol_list; + + symbol_list = wtxapi_sym_find (WTX_SYM_FIND_IN_ALL_PD, + "wdbEventClassHwBpVa", 0, 1); + + if (symbol_list != NULL) + { + BoDA_supported_p = 1; + free_wtxapi_symbol_list (symbol_list); + } + + BoDA_support_checked_p = 1; + } + + return BoDA_supported_p; +} + +/* Free the memory allocated by the given THREADS list. */ + +void +free_wtxapi_thread_info (struct wtxapi_thread_info *threads) +{ + struct wtxapi_thread_info *this = threads; + struct wtxapi_thread_info *next; + + while (this != NULL) + { + next = this->next; + xfree (this->name); + xfree (this); + this = next; + } +} + +/* Routines implemented using the support of external modules. */ + +static struct wtxapi_support_ops *support_ops = NULL; + +/* Setup the current wtx_support_ops vector to OPS. */ + +void +wtxapi_set_support_ops (struct wtxapi_support_ops *ops) +{ + support_ops = ops; +} + +/* Call the wtx_connection_established_callback method of + the support_ops vector. */ + +void +wtxapi_notify_connection_established (void) +{ + /* If the support_ops structure hasn't been set, then simply + do nothing. */ + if (support_ops == NULL) + return; + gdb_assert (support_ops->wtx_connection_established_callback != NULL); + + support_ops->wtx_connection_established_callback (current_wtx_handle); +} + +/* Return the list of threads currently running on the target. + + This routine is dependent on the support_ops vector being set, + or else NULL will be returned. */ + +struct wtxapi_thread_info * +wtxapi_get_thread_list (void) +{ + /* If the support_ops structure has not be set, then return NULL. */ + if (support_ops == NULL) + return NULL; + gdb_assert (support_ops->get_thread_list != NULL); + + return support_ops->get_thread_list (); +} + +/* If TASK_ID is a valid task ID, then save its PD inside TASK_PD, + and return non-zero. In case of failure, return zero, and the value + of TASK_PD is undefined. + + This function is dependent on the support_ops vector being set, + or else zero will be returned. */ + +int +wtxapi_get_task_pd (int task_id, pd_id_t *task_pd) +{ + /* If the support_ops structure has not be set, then return 0. */ + if (support_ops == NULL) + return 0; + gdb_assert (support_ops->get_task_pd != NULL); + + return support_ops->get_task_pd (task_id, task_pd); +} + +/* Execute the system_mode_support_p method of the wtxapi_support_ops + vector. + + This function is dependent on the support_ops vector being set, + or else zero will be returned. */ + +int +wtxapi_system_mode_support_p (void) +{ + if (support_ops == NULL) + return 0; + gdb_assert (support_ops->system_mode_support_p != NULL); + + return support_ops->system_mode_support_p (); +} + +/* Execute the system_mode_get_current_context_id method of the + wtxapi_support_ops vector. + + This function is dependent on the support_ops vector being set, + or else the SYSTEM_CID will be returned. */ + +WTX_CONTEXT_ID_T +wtxapi_system_mode_get_current_context_id (void) +{ + /* If the support_ops structure has not be set, then return 0. */ + if (support_ops == NULL) + return SYSTEM_CID; + gdb_assert (support_ops->system_mode_get_current_context_id != NULL); + + return support_ops->system_mode_get_current_context_id (); +} + +/* Return the value of VX_FP_TASK for the current target. The value of + this option depends on the VxWorks version. */ + +int +wtxapi_vx_fp_task () +{ + struct wtxapi_ts_info *ts_info = wtxapi_ts_info_get (); + struct cleanup *old_cleanup = make_cleanup (cleanup_wtxapi_ts_info, ts_info); + char vx6_pattern[] = "6."; + + if (strncmp (vx6_pattern, ts_info->tgt_info.rt_info.rt_version, + strlen (vx6_pattern)) == 0) + return 0x1000000; + else + return 0x8; + do_cleanups (old_cleanup); +} + +/* Ask WTX which variant is the target CPU, and compare it against + VARIANT. If they match, return 1; otherwise, return 0. */ + +int +wtxapi_has_target_variant (const char *variant) +{ + int result; + struct wtxapi_ts_info *ts_info = wtxapi_ts_info_get (); + struct cleanup *old_cleanup = make_cleanup (cleanup_wtxapi_ts_info, ts_info); + + if (ts_info->tgt_info.rt_info.cpu_variant + && strcmp (ts_info->tgt_info.rt_info.cpu_variant, variant) == 0) + result = 1; + else + result = 0; + + do_cleanups (old_cleanup); + return result; +} + +static struct cmd_list_element *info_wtx_list = NULL; + +static void +info_wtx_version_command (char *args, int from_tty) +{ + printf_filtered (_("WTX protocol version %d\n"), wtxapi_version_get ()); +} + +/* Print the version of VxWorks running on the target. */ + +static void +info_wtx_vxworks_version () +{ + struct wtxapi_ts_info *ts_info; + struct cleanup *old_cleanup = NULL; + char *name; + char *version; + + if (current_wtx_handle == NULL + || !(ts_info = wtxapi_ts_info_get ())) + printf_filtered (_("Not connected to a VxWorks target.\n")); + else + { + old_cleanup = make_cleanup (cleanup_wtxapi_ts_info, ts_info); + name = ts_info->tgt_info.rt_info.rt_name; + version = ts_info->tgt_info.rt_info.rt_version; + printf_filtered (_("%s version %s\n"), name, version); + } + + if (old_cleanup) + do_cleanups (old_cleanup); +} + +static void +info_wtx_threads_command (char *args, int from_tty) +{ + struct wtxapi_thread_info *threads = wtxapi_get_thread_list (); + struct wtxapi_thread_info *current_thread = threads; + + if (threads == NULL) + { + printf_filtered ("No threads.\n"); + return; + } + + while (current_thread != NULL) + { + printf_filtered ("0x%lx\t%s\n", current_thread->id, + current_thread->name); + current_thread = current_thread->next; + } + free_wtxapi_thread_info (threads); +} + +static void +info_wtx_command (char *args, int from_tty) +{ + /* brobecker/2007-12-17: Ideally, the "info wtx" command should + only be a prefix command. But we have been using it to get + the WTX protocol version for the past few years. So keep this + command as an alias of "info wtx version" for now. Eventually, + when all the GDB versions that didn't support "info wtx version" + are no longer supported, we can remove this compatibility hack. */ + info_wtx_version_command (NULL, from_tty); +} + +/* Load the WTX shared libraries and initialize the pointers to WTX + functions. */ + +static void +load_wtx_libraries () +{ + void *wtx_lib = NULL; + + if (WTX_PROT_VERSION == 4) + { + wtx_lib = load_shared_lib ("wtxapi41"); + + if (!wtx_lib) + wtx_lib = load_shared_lib ("wtxapi40"); + } + else if (WTX_PROT_VERSION == 3) + { + wtx_lib = load_shared_lib ("wtxapi30"); + } + else if (WTX_PROT_VERSION == 2) + { + wtx_lib = load_shared_lib ("wtxapi"); + } + + if (!wtx_lib) + error ("WTX library not found."); + +#define resolve(sym, name) \ + if (!(sym = get_symbol_from_shared_lib (wtx_lib, name))) \ + error ("%s not found in WTX library", name); + + resolve (wtx_initialize, "wtxInitialize"); + resolve (wtx_terminate, "wtxTerminate"); + resolve (wtx_info_q, "wtxInfoQ"); + resolve (wtx_tool_attach, "wtxToolAttach"); + resolve (wtx_tool_connected, "wtxToolConnected"); + resolve (wtx_tool_detach, "wtxToolDetach"); + resolve (wtx_err_clear, "wtxErrClear"); + resolve (wtx_err_get, "wtxErrGet"); + resolve (wtx_err_handler_add, "wtxErrHandlerAdd"); + resolve (wtx_err_handler_remove, "wtxErrHandlerRemove"); + resolve (wtx_err_msg_get, "wtxErrMsgGet"); + resolve (wtx_agent_mode_get, "wtxAgentModeGet"); + resolve (wtx_agent_mode_set, "wtxAgentModeSet"); + resolve (wtx_breakpoint_add, "wtxBreakpointAdd"); + resolve (wtx_eventpoint_add, "wtxEventpointAdd"); + resolve (wtx_eventpoint_delete, "wtxEventpointDelete"); + resolve (wtx_event_get, "wtxEventGet"); + resolve (wtx_context_status_get, "wtxContextStatusGet"); + resolve (wtx_context_cont, "wtxContextCont"); + resolve (wtx_context_create, "wtxContextCreate"); + resolve (wtx_context_resume, "wtxContextResume"); + resolve (wtx_context_exit_notify_add, "wtxContextExitNotifyAdd"); + resolve (wtx_context_kill, "wtxContextKill"); + resolve (wtx_context_step, "wtxContextStep"); + resolve (wtx_context_suspend, "wtxContextSuspend"); + resolve (wtx_eventpoint_list_get, "wtxEventpointListGet"); + resolve (wtx_result_free, "wtxResultFree"); + resolve (wtx_gopher_eval, "wtxGopherEval"); + resolve (wtx_mem_info_get, "wtxMemInfoGet"); + resolve (wtx_mem_alloc, "wtxMemAlloc"); + resolve (wtx_mem_checksum, "wtxMemChecksum"); + resolve (wtx_mem_move, "wtxMemMove"); + resolve (wtx_mem_free, "wtxMemFree"); + resolve (wtx_mem_read, "wtxMemRead"); + resolve (wtx_mem_width_read, "wtxMemWidthRead"); + resolve (wtx_mem_write, "wtxMemWrite"); + resolve (wtx_mem_width_write, "wtxMemWidthWrite"); + resolve (wtx_mem_set, "wtxMemSet"); + resolve (wtx_mem_add_to_pool, "wtxMemAddToPool"); + resolve (wtx_mem_realloc, "wtxMemRealloc"); + resolve (wtx_mem_align, "wtxMemAlign"); + resolve (wtx_mem_scan, "wtxMemScan"); + resolve (wtx_obj_module_checksum, "wtxObjModuleChecksum"); + resolve (wtx_obj_module_find_id, "wtxObjModuleFindId"); + resolve (wtx_obj_module_find_name, "wtxObjModuleFindName"); + resolve (wtx_obj_module_info_get, "wtxObjModuleInfoGet"); + resolve (wtx_obj_module_load, "wtxObjModuleLoad"); + resolve (wtx_obj_module_unload, "wtxObjModuleUnload"); + resolve (wtx_obj_module_by_name_unload, "wtxObjModuleByNameUnload"); + resolve (wtx_register_for_event, "wtxRegisterForEvent"); + resolve (wtx_regs_get, "wtxRegsGet"); + resolve (wtx_regs_set, "wtxRegsSet"); + resolve (wtx_str_to_tgt_addr, "wtxStrToTgtAddr"); + resolve (wtx_str_to_context_id, "wtxStrToContextId"); + resolve (wtx_str_to_context_type, "wtxStrToContextType"); + resolve (wtx_str_to_int32, "wtxStrToInt32"); + resolve (wtx_str_to_event_type, "wtxStrToEventType"); + resolve (wtx_sym_add, "wtxSymAdd"); + resolve (wtx_sym_find, "wtxSymFind"); + resolve (wtx_sym_list_get, "wtxSymListGet"); + resolve (wtx_sym_list_by_module_id_get, "wtxSymListByModuleIdGet"); + resolve (wtx_sym_list_by_module_name_get, "wtxSymListByModuleNameGet"); + resolve (wtx_sym_remove, "wtxSymRemove"); + resolve (wtx_sym_tbl_info_get, "wtxSymTblInfoGet"); + resolve (wtx_target_reset, "wtxTargetReset"); + resolve (wtx_ts_name_get, "wtxTsNameGet"); + resolve (wtx_target_cpu_type_get, "wtxTargetCpuTypeGet"); + resolve (wtx_target_has_fpp_get, "wtxTargetHasFppGet"); + resolve (wtx_target_endian_get, "wtxTargetEndianGet"); + resolve (wtx_target_bootline_get, "wtxTargetBootlineGet"); + resolve (wtx_tool_name_get, "wtxToolNameGet"); + resolve (wtx_ts_version_get, "wtxTsVersionGet"); + resolve (wtx_unregister_for_event, "wtxUnregisterForEvent"); + resolve (wtx_direct_call, "wtxDirectCall"); + resolve (wtx_ts_info_get, "wtxTsInfoGet"); + resolve (wtx_target_attach, "wtxTargetAttach"); + resolve (wtx_probe, "wtxProbe"); + resolve (wtx_timeout_set, "wtxTimeoutSet"); + resolve (wtx_timeout_get, "wtxTimeoutGet"); + +#if WTX_PROT_VERSION != 2 + resolve (wtx_obj_module_list_get, "wtxObjModuleListGet"); + resolve (wtx_context_stop, "wtxContextStop"); + resolve (wtx_pd_create, "wtxPdCreate"); + resolve (wtx_pd_kernel_get, "wtxPdKernelGet"); + resolve (wtx_pd_current_get, "wtxPdCurrentGet"); + resolve (wtx_pd_current_set, "wtxPdCurrentSet"); + resolve (wtx_pd_info_q_get, "wtxPdInfoQGet"); +#else + resolve (wtx_obj_module_list, "wtxObjModuleList"); +#endif + +} + +void +_initialize_remote_wtxapi () +{ + load_wtx_libraries (); + + add_prefix_cmd ("wtx", no_class, info_wtx_command, + _("Display version of WTX protocol for which gdb is built."), + &info_wtx_list, "info wtx ", 0, &infolist); + + add_cmd ("threads", class_info, info_wtx_threads_command, + _("Display the list of threads running on the target."), + &info_wtx_list); + + add_cmd ("version", class_info, info_wtx_version_command, + _("Display version of WTX protocol for which gdb is built."), + &info_wtx_list); + + add_cmd ("vxworks-version", class_info, info_wtx_vxworks_version, + _("Display version of VxWorks for the target."), + &info_wtx_list); +} diff --git a/gdb/remote-wtxapi.h b/gdb/remote-wtxapi.h new file mode 100644 index 0000000..fa05061 --- /dev/null +++ b/gdb/remote-wtxapi.h @@ -0,0 +1,1221 @@ +/* Thin binding for the WTX protocol, for GDB. + + Copyright 2004, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef REMOTE_WTXAPI_H +#define REMOTE_WTXAPI_H + +/* For wtx.h : GDB is run on the host. */ +#define HOST + +#include "wtx.h" +#include "symfile.h" + +/* When in system-mode, the context ID to use is -1. */ + +#define SYSTEM_CID (-1) + +#ifndef WTX_PROT_VERSION +#define WTX_PROT_VERSION 2 +#endif + +#if WTX_PROT_VERSION == 4 +typedef WTX_TGT_ADDR_T wtxapi_tgt_addr_t; +typedef WTX_TGT_ARG_T wtxapi_tgt_arg_t; +#else +typedef TGT_ADDR_T wtxapi_tgt_addr_t; +typedef TGT_ARG_T wtxapi_tgt_arg_t; +#endif + +/* Some macros are not defined in WTX 2.0. Define them as constant when + possible. */ + +#ifndef WTX_PD_CURRENT +extern const wtxapi_tgt_arg_t WTX_PD_CURRENT; +#endif + +#ifndef WTX_PD_ALL +extern const wtxapi_tgt_addr_t WTX_PD_ALL; +#endif + +#ifndef WTX_MOD_FIND_IN_ALL_PD +extern const wtxapi_tgt_addr_t WTX_MOD_FIND_IN_ALL_PD; +#endif + +#ifndef WTX_SYM_FIND_IN_ALL_PD +extern const int WTX_SYM_FIND_IN_ALL_PD; +#endif + +/* On WTX 3.0, some additional values has been added in the enums to + deal with the protection domains. Emulate these value in WTX 2.0. */ + +#if WTX_PROT_VERSION == 2 +extern const WTX_CONTEXT_TYPE WTX_CONTEXT_PD; +extern const int WTX_ERR_PD_INVALID_PD; +#endif + +#ifndef WTX_LOAD_GLOBAL_SYMBOLS +#define WTX_LOAD_GLOBAL_SYMBOLS 0x4 +#endif + +/* On WTX 4.0, some variables have been renamed. */ + +#if WTX_PROT_VERSION == 4 +extern const WTX_ACTION_TYPE WTX_ACTION_STOP_ALL; +#endif + +/* The structures defined below are used to resolve differences + between version of the WTX protocol. + + Note those differences: + - When the WTX structure contains a BOOL32, the WTX API structure uses an + int; if it is FALSE in the WTX structure, it is 0 in the WTX API structure; + - When the WTX structure contains a UINT32, the WTX API uses an int; the + conversion is straightforward. */ + +/* Protection domain ID. */ + +typedef wtxapi_tgt_addr_t pd_id_t; + +/* Module ID. */ + +typedef UINT32 module_id_t; + +/* Event point id. */ + +typedef UINT32 evtpt_id_t; + + +/* Invalid identifiers. Equivalent to WTX_ERROR. */ + +extern const pd_id_t invalid_pd_id; +extern const evtpt_id_t invalid_module_id; +extern const evtpt_id_t invalid_evtpt_id; +extern const WTX_CONTEXT_ID_T invalid_context_id; +extern const WTX_AGENT_MODE_TYPE invalid_agent_mode; +extern const WTX_CONTEXT_STATUS invalid_context_status; + +/* Event. Same as WTX_EVENT in WTX 3.0, and WTX_EVENT_2 in WTX 2.0. */ + +struct wtxapi_event +{ + WTX_EVENT_TYPE event_type; + int num_args; + wtxapi_tgt_arg_t *args; +}; + +/* Action. Based on WTX_ACTION. */ + +struct wtxapi_action +{ + /* Action type to perform. */ + WTX_ACTION_TYPE action_type; + /* Action dependent argument. */ + int action_arg; + /* Function to ACTION_CALL. */ + wtxapi_tgt_addr_t call_rtn; + /* Function argument. */ + wtxapi_tgt_arg_t call_arg; +}; + +/* Context. Same as WTX_CONTEXT */ + +struct wtxapi_context +{ + WTX_CONTEXT_TYPE context_type; + WTX_CONTEXT_ID_T context_id; + + /* WTX 4.0-specific field. */ + WTX_CONTEXT_ID_T context_sub_id; +}; + +/* Eventpoint desc. Same as WTX_EVTPT in WTX 3.0, and WTX_EVTPT_2 + in WTX 2.0. */ + +struct wtxapi_evtpt +{ + struct wtxapi_event event; + struct wtxapi_context context; + struct wtxapi_action action; +}; + +/* Eventpoint info. Same as WTX_EVTPT_INFO. */ + +struct wtxapi_evtpt_info +{ + /* Eventpoint descriptor. */ + struct wtxapi_evtpt wtx_evtpt; + /* Tool identifier. */ + int tool_id; + /* Eventpoint identifier. */ + evtpt_id_t evtpt_num; +}; + + +/* Eventpoint list message. Same as WTX_EVTPT_LIST in WTX 3.0, + and WTX_EVTPT_LIST_2 in WTX 2.0. */ + +struct wtxapi_evtpt_list +{ + int n_evtpt; + struct wtxapi_evtpt_info *p_evtpt_info; +}; + +/* Section descriptor. Based on WTX_SECTION_DESC (WTX 3.0) + and LD_M_SECTION (WTX 2.0). */ + +struct wtxapi_section_desc +{ + /* Name of the section. */ + char *name; + /* Section flags. */ + int flags; + /* Section base address. */ + wtxapi_tgt_addr_t base_addr; + /* Section length. */ + int length; +}; + +/* Symbol description. Based on WTX_SYMBOL. */ + +struct wtxapi_symbol +{ + /* Returned value for find request. */ + int status; + /* Protection domain ID. */ + pd_id_t pd_id; + /* Symbol name. */ + char *name; + /* 0 iff symbol name prefixed by an underscore. */ + int exact_name; + /* Symbol value. */ + wtxapi_tgt_addr_t value; + /* symbol type. */ + int type; + /* symbol type mask for lookup. */ + int type_mask; + /* Module name. */ + char *module_name; +}; + +/* Symbol copy options for copy_current_symbol. */ + +extern const int wtxapi_symbol_copy_none; +extern const int wtxapi_symbol_copy_name; +extern const int wtxapi_symbol_copy_module_name; +#define wtxapi_symbol_copy_all (wtxapi_symbol_copy_module_name \ + | wtxapi_symbol_copy_name) + +enum wtxapi_symbol_copy_options +{ + wtxapi_symbol_copy_full = 1, + wtxapi_symbol_copy_dont_copy_name = 2, + wtxapi_symbol_copy_dont_copy_module_name = 3, + wtxapi_symbol_copy_dont_copy_strings = 4 +}; + +/* Symbol list. Based on WTX_SYMBOL and WTX_SYMBOL_LIST. */ + +struct wtxapi_symbol_list; + +struct segment_addresses +{ + CORE_ADDR text_addr; + CORE_ADDR data_addr; + CORE_ADDR bss_addr; +}; + +/* Object module information. Based on WTX_MODULE_INFO. */ + +struct wtxapi_module_info +{ + /* Protection domain ID. */ + pd_id_t pd_id; + /* Module ID. */ + module_id_t module_id; + /* Module name (with path). */ + char *module_name; + /* Flags used to load module. */ + int load_flag; + /* Section description. */ + struct section_addr_info *section_addrs; + /* On older systems (Tornado 2), the system does not provide + the section addresses, but rather 3 segment addresses. + The following field stores these segment addresses to allow + us later to compute each section address. + + On targets where the system does provide us with the section + addresses, this field should be unused. */ + struct segment_addresses *segments; + /* List of undefined symbols. Only initialized after a 'load' operation. */ + struct wtxapi_symbol_list *undef_list; +}; + +/* Module ID list. Based on WTX_MODULE_LIST (WTX 2.0). */ + +struct wtxapi_module_list +{ + /* Number of module in list. */ + int num_obj_mod; + /* Arrays of object module id and pd id. For one index, you have a + couple (module id, pd id). */ + module_id_t *mod_id_array; + pd_id_t *pd_id_array; +}; + +/* task context descriptor. Same as WTX_TASK_CONTEXT_DEF (WTX 3.0) and + equivalent to WTX_CONTEXT_DESC (WTX 2.0). */ + +struct wtxapi_task_context_desc +{ + /* Context PD ID. */ + pd_id_t pd_id; + /* Integer or double. */ + WTX_RETURN_TYPE return_type; + /* Task name. */ + char *name; + /* Priority. */ + int priority; + /* Options. */ + int options; + /* Base of stack. */ + wtxapi_tgt_addr_t stack_base; + /* Stack size. */ + int stack_size; + /* Context entry point. */ + wtxapi_tgt_addr_t entry; + /* Redirection in file or NULL. */ + INT32 redir_in; + /* Redirection out file or NULL. */ + INT32 redir_out; + /* Redirection error file or NULL. */ + INT32 redir_err; + /* Arguments. */ + int argc; + wtxapi_tgt_arg_t *argv; +}; + +/* PD context descriptor. Same on WTX_PD_CONTEXT_DEF (WTX 3.0) and + equivalent to WTX_CONTEXT_DESC (WTX 2.0). */ + +struct wtxapi_pd_context_desc +{ + /* PD name. */ + char *name; + /* Options. */ + int options; + /* Size of the PD's heap. */ + int heap_size; + /* Lowest task's priority. */ + int low_priority; + /* Highest task's priority. */ + int high_priority; + /* Page pool list name to use. */ + wtxapi_tgt_addr_t page_pool_list; + /* Return address to call on deletion. */ + wtxapi_tgt_addr_t destroy_rtn; + /* Initial link path for this PD. */ + char *link_path; + /* Redirection in file or NULL. */ + INT32 redir_in; + /* Redirection out file or NULL. */ + INT32 redir_out; + /* Redirection error file or NULL. */ + INT32 redir_err; + /* Extra argument count (in argv). */ + int argc; + /* Extra argument array. */ + wtxapi_tgt_arg_t *argv; +}; + +/* Context descriptor. Based on WTX_CONTEXT_DESC (WTX 3.0). Different + from WTX_CONTEXT_DESC in WTX 2.0. */ + +struct wtxapi_context_desc +{ + /* Type of context. */ + WTX_CONTEXT_TYPE context_type; + + union _wtx_context_def + { + /* Task context definition. */ + struct wtxapi_task_context_desc task_context; + /* PD context definition. */ + struct wtxapi_pd_context_desc pd_context; + } wtx_context_def; +}; + +/* Some macro to access the fields of a wtxapi_context_desc */ + +#define TASK_CONTEXT_ARGV(context_desc, i) \ + (context_desc.wtx_context_def.task_context.argv[i]) +#define TASK_CONTEXT_ENTRY(context_desc) \ + (context_desc.wtx_context_def.task_context.entry) +#define TASK_CONTEXT_NAME(context_desc) \ + (context_desc.wtx_context_def.task_context.name) +#define TASK_CONTEXT_CONTEXT_TYPE(context_desc) \ + (context_desc.context_type) +#define TASK_CONTEXT_STACK_SIZE(context_desc) \ + (context_desc.wtx_context_def.task_context.stack_size) +#define TASK_CONTEXT_PRIORITY(context_desc) \ + (context_desc.wtx_context_def.task_context.priority) +#define TASK_CONTEXT_OPTIONS(context_desc) \ + (context_desc.wtx_context_def.task_context.options) +#define TASK_CONTEXT_ARGC(context_desc) \ + (context_desc.wtx_context_def.task_context.argc) +#define TASK_CONTEXT_PDID(context_desc) \ + (context_desc.wtx_context_def.task_context.pd_id) + +/* PD descriptor. Same as WTX_PD_DESC (WTX 3.0). */ + +struct wtxapi_pd_desc +{ + /* Protection domain ID. */ + pd_id_t pd_id; + /* Protection domain name. */ + char *pd_name; + /* Protection domain flags. */ + int pd_flags; + /* Link path string. */ + char *pd_link_path_str; + /* Nb of PD in linkpath. */ + int pd_link_path_count; + /* PD ids of the linkpath. */ + pd_id_t *pd_link_path; + int pd_attach_to_count; + pd_id_t *pd_attach_to; +}; + +/* PD descriptor list. Same as WTX_PD_DESC_Q (WTX 3.0). */ + +struct wtxapi_pd_desc_q +{ + struct wtxapi_pd_desc pd_desc; + struct wtxapi_pd_desc_q *next; +}; + +/* Symbol table info. Same as WTX_SYM_TBL_INFO (WTX 3.0). */ + +struct wtxapi_sym_tbl_info +{ + /* Protection domain ID. */ + pd_id_t pd_id; + /* Number of symbols. */ + int sym_num; + /* Name clash policy. */ + int same_name_ok; +}; + +/* Target agent info. Based on WTX_AGENT_INFO. */ + +struct wtxapi_agent_info +{ + /* WDB agent version. */ + char *agent_version; + /* Max transfer size (bytes). */ + int mtu; + /* Available agent modes. */ + int mode; +}; + +/* Target runtime information. Based on WTX_RT_INFO. */ + +struct wtxapi_rt_info +{ + /* Runtime name. */ + char *rt_name; + /* Runtime version. */ + char *rt_version; + /* Target processor type. */ + int cpu_type; + /* Target cpu variant. */ + char *cpu_variant; + /* Text write protect available. */ + int has_write_protect; + /* Size of a page. */ + int page_size; + /* Endianness (LITTLE or BIG). */ + int endian; + /* Board support package name. */ + char *bsp_name; + /* Boot file name. */ + char *boot_line; + /* Target main memory base address. */ + wtxapi_tgt_addr_t mem_base; + /* Target main memory size. */ + int mem_size; + /* Number of memory regions. */ + int num_regions; + /* Target server memory pool base. */ + int host_pool_base; + /* Target server memory pool size. */ + int host_pool_size; +}; + +/* Target information. Based on WTX_TGT_INFO. */ +struct wtxapi_tgt_info +{ + struct wtxapi_agent_info agent_info; + struct wtxapi_rt_info rt_info; +}; + +/* Target server information message. Based on WTX_TS_INFO. */ + +struct wtxapi_ts_info +{ + /* Target link descriptor. */ + WTX_TGT_LINK_DESC tgt_link_desc; + /* Info obtained from Target. */ + struct wtxapi_tgt_info tgt_info; + /* Target Server version. */ + char *version; + /* Target server user name. */ + char *user_name; + /* Lock/authorization message. */ + char *lock_msg; + /* 0 iff the PDs are not initialized. */ + int pd_initialized; +}; + +/* The data from a context-exit event. */ + +struct wtxapi_ctx_exit_event +{ + WTX_CONTEXT_ID_T context_id; + WTX_CONTEXT_TYPE context_type; + int exit_code; +}; + +/* The data from a data-access (watchpoint) event. */ + +struct wtxapi_data_access_event +{ + WTX_CONTEXT_ID_T task_id; + WTX_CONTEXT_ID_T context_id; + WTX_CONTEXT_TYPE context_type; + + /* The address being watched that triggered the DATA_ACCESS event. */ + CORE_ADDR data_addr; +}; + +/* The data from an exception event. */ + +struct wtxapi_exception_event +{ + WTX_CONTEXT_ID_T context_id; + WTX_CONTEXT_TYPE context_type; + int exception_value; +}; + +/* The data from an obj-loaded event. */ + +struct wtxapi_obj_loaded_event +{ + module_id_t module_id; +}; + +/* The data from an obj-unloaded event. */ + +struct wtxapi_obj_unloaded_event +{ + char *module_filename; +}; + +/* The data from a text-access (breakpoint) event. */ + +struct wtxapi_text_access_event +{ + WTX_CONTEXT_ID_T task_id; + WTX_CONTEXT_ID_T context_id; + WTX_CONTEXT_TYPE context_type; + + /* The address of the breakpoint that triggered this event. */ + CORE_ADDR text_addr; +}; + +/* The data from the vio-write event. */ + +struct wtxapi_vio_write_event +{ + int channel_id; + char *data; /* The contents printed on the virtual IO channel. */ +}; + +/* A structure representing the contents of an event received from + the target server. */ + +struct wtxapi_event_desc +{ + WTX_EVENT_TYPE event_type; + + union + { + struct wtxapi_ctx_exit_event ctx_exit; + struct wtxapi_data_access_event data_access; + struct wtxapi_exception_event exception; + struct wtxapi_obj_loaded_event obj_loaded; + struct wtxapi_obj_unloaded_event obj_unloaded; + struct wtxapi_text_access_event text_access; + struct wtxapi_vio_write_event vio_write; + } desc; +}; + +/* The following function are simple wrappers used to resolve the + differences between the WTX versions. Unless specified in the + comments, the WTX lib C documentation applies. If the return type + is a WTX type, it should be deallocated using wtxapi_result_free. + If it is a type defined in remote-wtxapi.h, it should be deallocate + using one of the deallocation function provided in this file. + + Note those differences: + + - when the return type of the WTX function is a STATUS, the wrapper + returns an int; in this case, iff the WTX function returns + WTX_ERROR, the wrapper returns 0; + + - when the return type of the WTX function is a BOOL32, the wrapper + returns an int; in this case, iff the WTX function returns FALSE, + the wrapper returns 0. */ + +/* Initialize the global WTX client handle. Only one WTX connection is + allowed. */ + +extern int wtxapi_initialize (); + +/* Return the WTX handle of the current WTX connection. + Valid only after a successful call to wtxapi_initialize. */ + +extern HWTX wtxapi_get_current_wtx_handle (); + +/* Return list of registred services. NAME_PAT is the reg expression + to match svc name. TYPE_PAT is the reg expression to match svc + type. KEY_PAT is the reg expression to match svc key. */ + +extern WTX_DESC_Q *wtxapi_info_q (const char *name_pat, const char *type_pat, + const char *key_pat); + +/* Terminate the use of the global WTX client handle. */ + +extern int wtxapi_terminate (); + +/* Connect the client to the target server. */ + +extern int wtxapi_tool_attach (const char *target_name, + const char *tool_name); + +/* Check tool connection to the server. */ + +extern int wtxapi_tool_connected (); + +/* Detach from the target server. */ + +extern int wtxapi_tool_detach (); + +/* Clear any error for the tool. */ + +extern int wtxapi_err_clear (); + +/* Return the version of WTX. */ + +extern int wtxapi_version_get (); + +/* Return the last error for a handle. */ + +extern WTX_ERROR_T wtxapi_err_get (); + +/* Add an error handler. */ + +extern WTX_HANDLER_T wtxapi_err_handler_add (WTX_HANDLER_FUNC p_func, + void *p_client_data); + +/* Remove an error handler for WTX handle. */ + +extern int wtxapi_err_handler_remove (WTX_HANDLER_T p_handler); + +/* Fetch the last WTX API error string. */ + +extern const char *wtxapi_err_msg_get (); + +/* Get the agent mode. Return invalid_agent_mode if an error occurs. */ + +extern WTX_AGENT_MODE_TYPE wtxapi_agent_mode_get (); + +/* Set the mode of the target agent. */ + +extern int wtxapi_agent_mode_set (WTX_AGENT_MODE_TYPE agent_mode); + +/* Create a new breakpoint. */ + +extern evtpt_id_t wtxapi_breakpoint_add (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id, + wtxapi_tgt_addr_t tgt_addr); + +/* Create a new event point. */ + +extern evtpt_id_t wtxapi_eventpoint_add (struct wtxapi_evtpt *p_evtpt); + +/* Delete eventpoint from the target. */ + +extern int wtxapi_eventpoint_delete (evtpt_id_t evtpt_id); + +/* Get the next event in the event queue. */ + +extern struct wtxapi_event_desc * wtxapi_event_get (void); + +/* Get status of a context. Return invalid_context_status if the operation + fails. */ + +extern WTX_CONTEXT_STATUS wtxapi_context_status_get + (WTX_CONTEXT_TYPE context_type, WTX_CONTEXT_ID_T context_id); + +/* Continue execution of target context. */ + +extern int wtxapi_context_cont (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id); + +/* Create a context on target. + - if P_CONTEXT_DESC is invalid, generates WTX_ERR_API_INVALID_ARG; + - if another unidentified error occurs, return invalid_context_id; + e.g if the operation is not permitted by the kernel. */ + +extern WTX_CONTEXT_ID_T wtxapi_context_create + (struct wtxapi_context_desc *p_context_desc); + +/* Resume execution of a target context. */ + +extern int wtxapi_context_resume (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id); + +/* Add exit evpt notification. */ + +extern evtpt_id_t wtxapi_context_exit_notify_add + (WTX_CONTEXT_TYPE context_type, WTX_CONTEXT_ID_T context_id); + +/* Kill a target context. */ + +extern int wtxapi_context_kill (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id); + +/* Single step exec of target context. */ + +extern int wtxapi_context_step (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id, + wtxapi_tgt_addr_t step_start, + wtxapi_tgt_addr_t step_end); + +/* Suspend a target context. */ + +extern int wtxapi_context_suspend (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id); + +/* Stop (on WTX 3.0) or suspend (on WTX 2.0) a target context. */ + +extern int wtxapi_context_stop (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id); + +/* List event points on TS. */ + +extern struct wtxapi_evtpt_list *wtxapi_eventpoint_list_get (); + +/* Free mem allocated by WTX API call. */ + +extern int wtxapi_result_free (void *p_result); + +/* Evaluate Gopher string on target. */ + +extern WTX_GOPHER_TAPE *wtxapi_gopher_eval (pd_id_t pd_id, + const char *input_string); + +/* Get info about memory pool. */ + +extern WTX_MEM_INFO *wtxapi_mem_info_get (pd_id_t pd_id); + +/* Alloc blocks in memory pool. */ + +extern wtxapi_tgt_addr_t wtxapi_mem_alloc (pd_id_t pd_id, int num_bytes); + +/* Perform checksum on target memory. */ + +extern int wtxapi_mem_checksum (pd_id_t pd_id, wtxapi_tgt_addr_t start_addr, + int num_bytes); + +/* Move a block of target memory. */ + +extern int wtxapi_mem_move (pd_id_t src_pd_id, wtxapi_tgt_addr_t src_addr, + pd_id_t dst_pd_id, wtxapi_tgt_addr_t dest_addr, + int num_bytes); + +/* Free a block of target memory. */ + +extern int wtxapi_mem_free (pd_id_t pd_id, wtxapi_tgt_addr_t address); + +/* Read memory from the target. */ + +extern int wtxapi_mem_read (pd_id_t pd_id, wtxapi_tgt_addr_t from_addr, + void *to_addr, int num_bytes); + +/* Read memory on WIDTH bytes. */ + +extern int wtxapi_mem_width_read (pd_id_t pd_id, wtxapi_tgt_addr_t from_addr, + void *to_addr, int num_bytes, int width); + +/* Write memory on the target. */ + +extern int wtxapi_mem_write (pd_id_t pd_id, void *from_addr, + wtxapi_tgt_addr_t to_addr, int num_bytes); + +/* Write memory on the target, on WIDTH bytes large. */ + +extern int wtxapi_mem_width_write (pd_id_t pd_id, void *from_addr, + wtxapi_tgt_addr_t to_addr, int num_bytes, + int width); + +/* Set target memory to given value. */ + +extern int wtxapi_mem_set (pd_id_t pd_id, wtxapi_tgt_addr_t addr, + int num_bytes, int val); + +/* Add memory to the agent pool. */ + +extern int wtxapi_mem_add_to_pool (pd_id_t pd_id, wtxapi_tgt_addr_t address, + int size); + +/* Reallocate a block of target mem. */ + +extern wtxapi_tgt_addr_t wtxapi_mem_realloc (pd_id_t pd_id, + wtxapi_tgt_addr_t address, + int num_bytes); + +/* Allocate aligned target memory. */ + +extern wtxapi_tgt_addr_t wtxapi_mem_align (pd_id_t pd_id, + wtxapi_tgt_addr_t alignment, + int num_bytes); + +/* Scan target memory for pattern. */ + +extern int wtxapi_mem_scan (pd_id_t pd_id, int match, + wtxapi_tgt_addr_t start_addr, + wtxapi_tgt_addr_t end_addr, + int num_bytes, void *pattern, + wtxapi_tgt_addr_t * p_result); + +/* Checks validity of target memory. */ + +extern int wtxapi_obj_module_checksum (pd_id_t pd_id, module_id_t module_id, + char *module_name); + +/* Find obj module ID from name. */ + +extern module_id_t wtxapi_obj_module_find_id (pd_id_t pd_id, + const char *module_name); + +/* Return the ID of the module which basename is equal to MODULE_NAME. + Search the current PD first, before extending the search to all PDs. */ + +extern module_id_t wtxapi_obj_module_in_system_find_id + (const char *module_name); + +/* Find module name given its ID. */ + +extern const char *wtxapi_obj_module_find_name (pd_id_t pd_id, + module_id_t module_id); + +/* Give info on obj module. */ + +extern struct wtxapi_module_info + *wtxapi_obj_module_info_get (pd_id_t pd_id, module_id_t module_id); + +/* List loaded obj modules (wrapper around wtxObjModuleList (WTX 2.0) + or wtxObjModuleListGet (WTX 3.0)). To search on every PD, pd_id + should be set to WTX_MOD_FIND_IN_ALL_PD. */ + +extern struct wtxapi_module_list *wtxapi_obj_module_list_get (pd_id_t pd_id); + +/* Load a new object module. */ + +extern struct wtxapi_module_info + *wtxapi_obj_module_load (pd_id_t pd_id, char *filename, int load_flag); + +extern struct wtxapi_module_info *wtxapi_module_load (pd_id_t pd_id, + char *filename, + int load_flag, + int timeout); + +/* Unload an obj module from target. */ + +extern int wtxapi_obj_module_unload (pd_id_t pd_id, module_id_t mod_id); + +extern int wtxapi_obj_module_by_name_unload (pd_id_t pd_id, char *name); + +/* Send events matching expression. */ + +extern int wtxapi_register_for_event (const char *reg_exp); + +/* Read register data from the target. */ + +extern int wtxapi_regs_get (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id, + WTX_REG_SET_TYPE reg_set, + int first_byte, int num_bytes, void *reg_memory); + +/* Write to registers on the target. */ + +extern int wtxapi_regs_set (WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id, + WTX_REG_SET_TYPE reg_set, + int first_byte, int num_bytes, void *reg_memory); + +/* Convert str to a wtxapi_tgt_addr_t. */ + +extern wtxapi_tgt_addr_t wtxapi_str_to_tgt_addr (const char *str); + +/* Convert str to context ID. */ + +extern WTX_CONTEXT_ID_T wtxapi_str_to_context_id (const char *str); + +/* Convert str ton context type. */ + +extern WTX_CONTEXT_TYPE wtxapi_str_to_context_type (const char *str); + +/* Convert str to an INT32. */ + +extern int wtxapi_str_to_int32 (const char *str); + +/* Convert string to event type. */ + +extern WTX_EVENT_TYPE wtxapi_str_to_event_type (const char *str); + +/* Add symbol with given params. */ + +extern int wtxapi_sym_add (pd_id_t pd_id, const char *sym_name, + wtxapi_tgt_addr_t sym_value, int sym_type); + +/* Find info on symbol. Based on wtxSymFind WTX 2.0, with two differences: + _ one additional parameter: the protection domain ID (PD_ID); + _ no filter on the type. */ + +extern struct wtxapi_symbol_list *wtxapi_sym_find (pd_id_t pd_id, + char *sym_name, + wtxapi_tgt_addr_t sym_value, + int exact_name); + +/* Get list of symbols. Based on wtxSymListGet WTX 2.0, with three differences: + - one additional parameter: the protection domain ID (PD_ID); + - no filter on the unknown symbols; + - no filter on the module name/id. */ + +extern struct wtxapi_symbol_list + *wtxapi_sym_list_get (pd_id_t pd_id, char *substring, + wtxapi_tgt_addr_t value); + +/* Get list of symbols. */ + +extern struct wtxapi_symbol_list + *wtxapi_sym_list_by_module_id_get (pd_id_t pd_id, const char *string, + module_id_t module_id, + wtxapi_tgt_addr_t value, + int list_unknown); + +/* Get list of symbols. */ + +extern struct wtxapi_symbol_list + *wtxapi_sym_list_by_module_name_get (pd_id_t pd_id, + const char *string, + const char *module_name, + wtxapi_tgt_addr_t value, + int list_unknown); + +/* Remove a symbol from sym table. */ + +extern int wtxapi_sym_remove (pd_id_t pd_id, const char *sym_name, + int sym_type); + +/* Get the symbol table info. */ + +extern struct wtxapi_sym_tbl_info *wtxapi_sym_tbl_info_get (pd_id_t pd_id); + +/* Reset the target. */ + +extern int wtxapi_target_reset (); + +/* Get target server name. */ + +extern const char *wtxapi_ts_name_get (); + +/* Get target-runtime version. */ + +extern const char *wtxapi_target_rt_version_get (); + +/* Get the target CPU type code. */ + +extern int wtxapi_target_cpu_type_get (); + +/* Check for floating point processor. */ + +extern int wtxapi_target_has_fpp_get (); + +/* Get edianness of target. */ + +extern WTX_ENDIAN_T wtxapi_target_endian_get (); + +/* Get target boot line info. */ + +extern const char *wtxapi_target_bootline_get (); + +/* Return name of current tool. */ + +extern const char *wtxapi_tool_name_get (); + +/* Return the Tornado version. */ + +extern const char *wtxapi_ts_version_get (); + +/* Unregister for some events. */ + +extern int wtxapi_unregister_for_event (char *reg_exp); + +/* Call func on target within agent. */ + +extern int wtxapi_direct_call (wtxapi_tgt_addr_t entry, void *p_ret_val, + wtxapi_tgt_arg_t arg0, wtxapi_tgt_arg_t arg1, + wtxapi_tgt_arg_t arg2, wtxapi_tgt_arg_t arg3, + wtxapi_tgt_arg_t arg4, wtxapi_tgt_arg_t arg5, + wtxapi_tgt_arg_t arg6, wtxapi_tgt_arg_t arg7, + wtxapi_tgt_arg_t arg8, wtxapi_tgt_arg_t arg9); + +/* Get info about target and server. */ + +extern struct wtxapi_ts_info *wtxapi_ts_info_get (); + +/* Reattach to the target. */ + +extern int wtxapi_target_attach (); + +/* Probe to see if registry is running. */ + +extern int wtxapi_probe (); + +/* Set WTX timeout. */ + +extern int wtxapi_timeout_set (int msec); + +/* Get the current timeout. */ + +extern int wtxapi_timeout_get (int *p_msec); + +/* Create a new protection domain. */ + +extern wtxapi_tgt_addr_t wtxapi_pd_create (const char *name, int options, + int heap_size, int low_priority, + int high_priority, + wtxapi_tgt_addr_t page_pool_list, + const char *link_path); + +/* Get kernel Protection Domain ID. */ + +extern pd_id_t wtxapi_pd_kernel_get (); + +/* Get the current Protection Domain. */ + +extern pd_id_t wtxapi_pd_current_get (); + +/* Set the current Protection Domain. */ + +extern int wtxapi_pd_current_set (pd_id_t pd_id); + +/* Get the list of allocated PDs. */ + +extern struct wtxapi_pd_desc_q *wtxapi_pd_info_q_get (); + +/* Check whether the module has been fully linked or not. */ + +extern int wtxapi_load_fully_linked (const struct wtxapi_module_info + *module_info); + +/* Simple additional functions. */ + +/* Test target server availability. */ + +extern int wtxapi_target_server_available_p (); + +/* Symbol list handling. The symbol list contain a 'current symbol'. + This current symbol is used to go through the list. */ + +/* Get a copy of the current symbol. */ + +extern struct wtxapi_symbol + *get_current_wtxapi_symbol (struct wtxapi_symbol_list *list); + + +/* Copy current symbol of LIST into TO. + + OPTIONS is used to avoid uneeded dynamic allocation. + + If OPTIONS is set to wtxapi_symbol_copy_full, the fields name and + module_name of TO are null pointers, these string fields of TO are + allocated and fully copied from the current symbol, and should be + deallocated by the caller. + + If OPTIONS is set to wtxapi_symbol_copy_name (resp. + wtxapi_symbol_copy_module_name), the field name (resp. the + module_name) of TO is copied. If not, it is is set to NULL. + + If OPTIONS is set to wtxapi_symbol_copy_none, the field name and + module_name of TO are not copied and are set to NULL. In this case + and only in this case no dynamic allocation is performed by this + function. */ + +extern void copy_current_wtxapi_symbol (struct wtxapi_symbol_list *list, + struct wtxapi_symbol *to, + int options); + +/* Return the name of the current symbol inside LIST. + The result must be deallocated after use. */ + +extern char *current_wtxapi_symbol_name (struct wtxapi_symbol_list *list); + +/* Change the current symbol to the first element of the list.If there + is no next element, return 0. */ + +int go_to_first_element_in_wtxapi_sym_list (struct wtxapi_symbol_list *list); + +/* Change the current symbol to the next element of the list. If there + is no next element, return 0. */ + +int go_to_next_element_in_wtxapi_sym_list (struct wtxapi_symbol_list *list); + +/* Deallocation functions for the structures,lists returned by the + function defined in this file. It frees "everything", i.e. it go + through every element of the list and deallocate it, and also + deallocate strings and arrays referenced by a field. */ + +extern void free_wtxapi_evtpt_list (struct wtxapi_evtpt_list *to_free); + +extern void free_wtxapi_module_list (struct wtxapi_module_list *to_free); + +extern void free_wtxapi_pd_desc_q (struct wtxapi_pd_desc_q *to_free); + +extern void free_wtxapi_symbol (struct wtxapi_symbol *to_free); + +extern void free_wtxapi_symbol_list (struct wtxapi_symbol_list *to_free); + +extern void free_wtxapi_module_info (struct wtxapi_module_info *to_free); + +extern void free_wtxapi_ts_info (struct wtxapi_ts_info *to_free); + +extern void free_wtxapi_event_desc (struct wtxapi_event_desc *to_free); + +/* Stubs for GDB cleanup functions. */ + +extern void cleanup_wtxapi_evtpt_list (void *to_free); + +extern void cleanup_wtxapi_module_list (void *to_free); + +extern void cleanup_wtxapi_pd_desc_q (void *to_free); + +extern void cleanup_wtxapi_symbol (void *to_free); + +extern void cleanup_wtxapi_symbol_list (void *to_free); + +extern void cleanup_wtxapi_module_info (void *to_free); + +extern void cleanup_wtxapi_ts_info (void *to_free); + +extern void cleanup_wtxapi_result_free (void *to_free); + +/* Helpers. */ + +int remote_wtxapi_get_symbol_address (char *symbol_name, + CORE_ADDR *symbol_addr); + +int wtxapi_target_has_BoDA (void); + +/* A list of threads running on the target system. */ + +struct wtxapi_thread_info +{ + struct wtxapi_thread_info *next; + WTX_CONTEXT_ID_T id; + char *name; + + /* The address where the task GP registers are stored when the task + is not being executed. This is necessary to retrieve the registers + of this task when in system mode, because wtxapi_regs_get/set + will only get/set the registers of the current task (ie the + task currently being scheduled by the system). */ + CORE_ADDR regs_addr; + + /* Similarly, we need to store the address where the FP registers + are stored. Computing this address requires support from the system, + and thus may not be available - in this case, this address should + be set to zero. */ + CORE_ADDR fp_regs_addr; +}; + +extern void free_wtxapi_thread_info (struct wtxapi_thread_info *threads); + +/* The WTX protocol does not have all the necessary features needed + to implement a remote backend. So this module relies on other + modules provided by the target system (typically a TCL interpreter, + or a DFW server). Unfortunately, which module to use is dependent + on the target. So we maintain a vector with pointers to functions + that provide the missing features of WTX. */ + +struct wtxapi_support_ops +{ + /* Perform all necessary actions following the establishing of + the given WTX connection. */ + void (*wtx_connection_established_callback) (HWTX wtx_handle); + + /* Get the list of threads currently running on the target system. */ + struct wtxapi_thread_info * (*get_thread_list) (void); + + /* Find the Partition ID of the given task ID. + If successful, then set TASK_PD with the result, and return non-zero. + Otherwise, return zero and leave the value of TASK_PD undefined. */ + int (*get_task_pd) (int task_id, pd_id_t *task_pd); + + /* Return 1 if system-mode is supported, 0 otherwise. Warn if + some features are unsupported. */ + int (*system_mode_support_p) (void); + + /* Find the context id of the task currently being executed + by the system. This function assumes that the target is + currently running in system mode. */ + WTX_CONTEXT_ID_T (*system_mode_get_current_context_id) (void); +}; + +extern void wtxapi_set_support_ops (struct wtxapi_support_ops *ops); + +extern void wtxapi_notify_connection_established (void); + +extern struct wtxapi_thread_info *wtxapi_get_thread_list (void); + +extern int wtxapi_get_task_pd (int task_id, pd_id_t *task_pd); + +extern int wtxapi_system_mode_support_p (void); + +extern WTX_CONTEXT_ID_T wtxapi_system_mode_get_current_context_id (void); + +extern int wtxapi_vx_fp_task (); + +extern int wtxapi_has_target_variant (const char *variant); +#endif -- 1.6.3.3