1130812Smarcel/* Memory-access and commands for remote VxWorks processes, for GDB. 2130812Smarcel 3130812Smarcel Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1997, 1998, 1999, 4130812Smarcel 2000, 2001, 2002 Free Software Foundation, Inc. 5130812Smarcel 6130812Smarcel Contributed by Wind River Systems and Cygnus Support. 7130812Smarcel 8130812Smarcel This file is part of GDB. 9130812Smarcel 10130812Smarcel This program is free software; you can redistribute it and/or modify 11130812Smarcel it under the terms of the GNU General Public License as published by 12130812Smarcel the Free Software Foundation; either version 2 of the License, or 13130812Smarcel (at your option) any later version. 14130812Smarcel 15130812Smarcel This program is distributed in the hope that it will be useful, 16130812Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 17130812Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18130812Smarcel GNU General Public License for more details. 19130812Smarcel 20130812Smarcel You should have received a copy of the GNU General Public License 21130812Smarcel along with this program; if not, write to the Free Software 22130812Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 23130812Smarcel Boston, MA 02111-1307, USA. */ 24130812Smarcel 25130812Smarcel#include "defs.h" 26130812Smarcel#include "frame.h" 27130812Smarcel#include "inferior.h" 28130812Smarcel#include "target.h" 29130812Smarcel#include "gdbcore.h" 30130812Smarcel#include "command.h" 31130812Smarcel#include "symtab.h" 32130812Smarcel#include "complaints.h" 33130812Smarcel#include "gdbcmd.h" 34130812Smarcel#include "bfd.h" /* Required by objfiles.h. */ 35130812Smarcel#include "symfile.h" 36130812Smarcel#include "objfiles.h" 37130812Smarcel#include "gdb-stabs.h" 38130812Smarcel#include "regcache.h" 39130812Smarcel 40130812Smarcel#include "gdb_string.h" 41130812Smarcel#include <errno.h> 42130812Smarcel#include <signal.h> 43130812Smarcel#include <fcntl.h> 44130812Smarcel#include <sys/types.h> 45130812Smarcel#include <sys/socket.h> 46130812Smarcel#define malloc bogon_malloc /* Sun claims "char *malloc()" not void * */ 47130812Smarcel#define free bogon_free /* Sun claims "int free()" not void */ 48130812Smarcel#define realloc bogon_realloc /* Sun claims "char *realloc()", not void * */ 49130812Smarcel#include <rpc/rpc.h> 50130812Smarcel#undef malloc 51130812Smarcel#undef free 52130812Smarcel#undef realloc 53130812Smarcel#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */ 54130812Smarcel#include <netdb.h> 55130812Smarcel#include "vx-share/ptrace.h" 56130812Smarcel#include "vx-share/xdr_ptrace.h" 57130812Smarcel#include "vx-share/xdr_ld.h" 58130812Smarcel#include "vx-share/xdr_rdb.h" 59130812Smarcel#include "vx-share/dbgRpcLib.h" 60130812Smarcel 61130812Smarcel#include <symtab.h> 62130812Smarcel 63130812Smarcel/* Maximum number of bytes to transfer in a single 64130812Smarcel PTRACE_{READ,WRITE}DATA request. */ 65130812Smarcel#define VX_MEMXFER_MAX 4096 66130812Smarcel 67130812Smarcelextern void vx_read_register (); 68130812Smarcelextern void vx_write_register (); 69130812Smarcelextern void symbol_file_command (); 70130812Smarcelextern enum stop_kind stop_soon; /* for wait_for_inferior */ 71130812Smarcel 72130812Smarcelstatic int net_step (); 73130812Smarcelstatic int net_ptrace_clnt_call (); /* Forward decl */ 74130812Smarcelstatic enum clnt_stat net_clnt_call (); /* Forward decl */ 75130812Smarcel 76130812Smarcel/* Target ops structure for accessing memory and such over the net */ 77130812Smarcel 78130812Smarcelstatic struct target_ops vx_ops; 79130812Smarcel 80130812Smarcel/* Target ops structure for accessing VxWorks child processes over the net */ 81130812Smarcel 82130812Smarcelstatic struct target_ops vx_run_ops; 83130812Smarcel 84130812Smarcel/* Saved name of target host and called function for "info files". 85130812Smarcel Both malloc'd. */ 86130812Smarcel 87130812Smarcelstatic char *vx_host; 88130812Smarcelstatic char *vx_running; /* Called function */ 89130812Smarcel 90130812Smarcel/* Nonzero means target that is being debugged remotely has a floating 91130812Smarcel point processor. */ 92130812Smarcel 93130812Smarcelint target_has_fp; 94130812Smarcel 95130812Smarcel/* Default error message when the network is forking up. */ 96130812Smarcel 97130812Smarcelstatic const char rpcerr[] = "network target debugging: rpc error"; 98130812Smarcel 99130812SmarcelCLIENT *pClient; /* client used in net debugging */ 100130812Smarcelstatic int ptraceSock = RPC_ANYSOCK; 101130812Smarcel 102130812Smarcelenum clnt_stat net_clnt_call (); 103130812Smarcelstatic void parse_args (); 104130812Smarcel 105130812Smarcelstatic struct timeval rpcTimeout = 106130812Smarcel{10, 0}; 107130812Smarcel 108130812Smarcelstatic char *skip_white_space (); 109130812Smarcelstatic char *find_white_space (); 110130812Smarcel 111130812Smarcel/* Tell the VxWorks target system to download a file. 112130812Smarcel The load addresses of the text, data, and bss segments are 113130812Smarcel stored in *pTextAddr, *pDataAddr, and *pBssAddr (respectively). 114130812Smarcel Returns 0 for success, -1 for failure. */ 115130812Smarcel 116130812Smarcelstatic int 117130812Smarcelnet_load (char *filename, CORE_ADDR *pTextAddr, CORE_ADDR *pDataAddr, 118130812Smarcel CORE_ADDR *pBssAddr) 119130812Smarcel{ 120130812Smarcel enum clnt_stat status; 121130812Smarcel struct ldfile ldstruct; 122130812Smarcel struct timeval load_timeout; 123130812Smarcel 124130812Smarcel memset ((char *) &ldstruct, '\0', sizeof (ldstruct)); 125130812Smarcel 126130812Smarcel /* We invoke clnt_call () here directly, instead of through 127130812Smarcel net_clnt_call (), because we need to set a large timeout value. 128130812Smarcel The load on the target side can take quite a while, easily 129130812Smarcel more than 10 seconds. The user can kill this call by typing 130130812Smarcel CTRL-C if there really is a problem with the load. 131130812Smarcel 132130812Smarcel Do not change the tv_sec value without checking -- select() imposes 133130812Smarcel a limit of 10**8 on it for no good reason that I can see... */ 134130812Smarcel 135130812Smarcel load_timeout.tv_sec = 99999999; /* A large number, effectively inf. */ 136130812Smarcel load_timeout.tv_usec = 0; 137130812Smarcel 138130812Smarcel status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile, 139130812Smarcel &ldstruct, load_timeout); 140130812Smarcel 141130812Smarcel if (status == RPC_SUCCESS) 142130812Smarcel { 143130812Smarcel if (*ldstruct.name == 0) /* load failed on VxWorks side */ 144130812Smarcel return -1; 145130812Smarcel *pTextAddr = ldstruct.txt_addr; 146130812Smarcel *pDataAddr = ldstruct.data_addr; 147130812Smarcel *pBssAddr = ldstruct.bss_addr; 148130812Smarcel return 0; 149130812Smarcel } 150130812Smarcel else 151130812Smarcel return -1; 152130812Smarcel} 153130812Smarcel 154130812Smarcel/* returns 0 if successful, errno if RPC failed or VxWorks complains. */ 155130812Smarcel 156130812Smarcelstatic int 157130812Smarcelnet_break (int addr, u_long procnum) 158130812Smarcel{ 159130812Smarcel enum clnt_stat status; 160130812Smarcel int break_status; 161130812Smarcel Rptrace ptrace_in; /* XXX This is stupid. It doesn't need to be a ptrace 162130812Smarcel structure. How about something smaller? */ 163130812Smarcel 164130812Smarcel memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in)); 165130812Smarcel break_status = 0; 166130812Smarcel 167130812Smarcel ptrace_in.addr = addr; 168130812Smarcel ptrace_in.pid = PIDGET (inferior_ptid); 169130812Smarcel 170130812Smarcel status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int, 171130812Smarcel &break_status); 172130812Smarcel 173130812Smarcel if (status != RPC_SUCCESS) 174130812Smarcel return errno; 175130812Smarcel 176130812Smarcel if (break_status == -1) 177130812Smarcel return ENOMEM; 178130812Smarcel return break_status; /* probably (FIXME) zero */ 179130812Smarcel} 180130812Smarcel 181130812Smarcel/* returns 0 if successful, errno otherwise */ 182130812Smarcel 183130812Smarcelstatic int 184130812Smarcelvx_insert_breakpoint (int addr) 185130812Smarcel{ 186130812Smarcel return net_break (addr, VX_BREAK_ADD); 187130812Smarcel} 188130812Smarcel 189130812Smarcel/* returns 0 if successful, errno otherwise */ 190130812Smarcel 191130812Smarcelstatic int 192130812Smarcelvx_remove_breakpoint (int addr) 193130812Smarcel{ 194130812Smarcel return net_break (addr, VX_BREAK_DELETE); 195130812Smarcel} 196130812Smarcel 197130812Smarcel/* Start an inferior process and sets inferior_ptid to its pid. 198130812Smarcel EXEC_FILE is the file to run. 199130812Smarcel ALLARGS is a string containing the arguments to the program. 200130812Smarcel ENV is the environment vector to pass. 201130812Smarcel Returns process id. Errors reported with error(). 202130812Smarcel On VxWorks, we ignore exec_file. */ 203130812Smarcel 204130812Smarcelstatic void 205130812Smarcelvx_create_inferior (char *exec_file, char *args, char **env) 206130812Smarcel{ 207130812Smarcel enum clnt_stat status; 208130812Smarcel arg_array passArgs; 209130812Smarcel TASK_START taskStart; 210130812Smarcel 211130812Smarcel memset ((char *) &passArgs, '\0', sizeof (passArgs)); 212130812Smarcel memset ((char *) &taskStart, '\0', sizeof (taskStart)); 213130812Smarcel 214130812Smarcel /* parse arguments, put them in passArgs */ 215130812Smarcel 216130812Smarcel parse_args (args, &passArgs); 217130812Smarcel 218130812Smarcel if (passArgs.arg_array_len == 0) 219130812Smarcel error ("You must specify a function name to run, and arguments if any"); 220130812Smarcel 221130812Smarcel status = net_clnt_call (PROCESS_START, xdr_arg_array, &passArgs, 222130812Smarcel xdr_TASK_START, &taskStart); 223130812Smarcel 224130812Smarcel if ((status != RPC_SUCCESS) || (taskStart.status == -1)) 225130812Smarcel error ("Can't create process on remote target machine"); 226130812Smarcel 227130812Smarcel /* Save the name of the running function */ 228130812Smarcel vx_running = savestring (passArgs.arg_array_val[0], 229130812Smarcel strlen (passArgs.arg_array_val[0])); 230130812Smarcel 231130812Smarcel push_target (&vx_run_ops); 232130812Smarcel inferior_ptid = pid_to_ptid (taskStart.pid); 233130812Smarcel 234130812Smarcel /* We will get a trace trap after one instruction. 235130812Smarcel Insert breakpoints and continue. */ 236130812Smarcel 237130812Smarcel init_wait_for_inferior (); 238130812Smarcel 239130812Smarcel /* Set up the "saved terminal modes" of the inferior 240130812Smarcel based on what modes we are starting it with. */ 241130812Smarcel target_terminal_init (); 242130812Smarcel 243130812Smarcel /* Install inferior's terminal modes. */ 244130812Smarcel target_terminal_inferior (); 245130812Smarcel 246130812Smarcel stop_soon = STOP_QUIETLY; 247130812Smarcel wait_for_inferior (); /* Get the task spawn event */ 248130812Smarcel stop_soon = NO_STOP_QUIETLY; 249130812Smarcel 250130812Smarcel /* insert_step_breakpoint (); FIXME, do we need this? */ 251130812Smarcel proceed (-1, TARGET_SIGNAL_DEFAULT, 0); 252130812Smarcel} 253130812Smarcel 254130812Smarcel/* Fill ARGSTRUCT in argc/argv form with the arguments from the 255130812Smarcel argument string ARGSTRING. */ 256130812Smarcel 257130812Smarcelstatic void 258130812Smarcelparse_args (char *arg_string, arg_array *arg_struct) 259130812Smarcel{ 260130812Smarcel int arg_count = 0; /* number of arguments */ 261130812Smarcel int arg_index = 0; 262130812Smarcel char *p0; 263130812Smarcel 264130812Smarcel memset ((char *) arg_struct, '\0', sizeof (arg_array)); 265130812Smarcel 266130812Smarcel /* first count how many arguments there are */ 267130812Smarcel 268130812Smarcel p0 = arg_string; 269130812Smarcel while (*p0 != '\0') 270130812Smarcel { 271130812Smarcel if (*(p0 = skip_white_space (p0)) == '\0') 272130812Smarcel break; 273130812Smarcel p0 = find_white_space (p0); 274130812Smarcel arg_count++; 275130812Smarcel } 276130812Smarcel 277130812Smarcel arg_struct->arg_array_len = arg_count; 278130812Smarcel arg_struct->arg_array_val = (char **) xmalloc ((arg_count + 1) 279130812Smarcel * sizeof (char *)); 280130812Smarcel 281130812Smarcel /* now copy argument strings into arg_struct. */ 282130812Smarcel 283130812Smarcel while (*(arg_string = skip_white_space (arg_string))) 284130812Smarcel { 285130812Smarcel p0 = find_white_space (arg_string); 286130812Smarcel arg_struct->arg_array_val[arg_index++] = savestring (arg_string, 287130812Smarcel p0 - arg_string); 288130812Smarcel arg_string = p0; 289130812Smarcel } 290130812Smarcel 291130812Smarcel arg_struct->arg_array_val[arg_count] = NULL; 292130812Smarcel} 293130812Smarcel 294130812Smarcel/* Advance a string pointer across whitespace and return a pointer 295130812Smarcel to the first non-white character. */ 296130812Smarcel 297130812Smarcelstatic char * 298130812Smarcelskip_white_space (char *p) 299130812Smarcel{ 300130812Smarcel while (*p == ' ' || *p == '\t') 301130812Smarcel p++; 302130812Smarcel return p; 303130812Smarcel} 304130812Smarcel 305130812Smarcel/* Search for the first unquoted whitespace character in a string. 306130812Smarcel Returns a pointer to the character, or to the null terminator 307130812Smarcel if no whitespace is found. */ 308130812Smarcel 309130812Smarcelstatic char * 310130812Smarcelfind_white_space (char *p) 311130812Smarcel{ 312130812Smarcel int c; 313130812Smarcel 314130812Smarcel while ((c = *p) != ' ' && c != '\t' && c) 315130812Smarcel { 316130812Smarcel if (c == '\'' || c == '"') 317130812Smarcel { 318130812Smarcel while (*++p != c && *p) 319130812Smarcel { 320130812Smarcel if (*p == '\\') 321130812Smarcel p++; 322130812Smarcel } 323130812Smarcel if (!*p) 324130812Smarcel break; 325130812Smarcel } 326130812Smarcel p++; 327130812Smarcel } 328130812Smarcel return p; 329130812Smarcel} 330130812Smarcel 331130812Smarcel/* Poll the VxWorks target system for an event related 332130812Smarcel to the debugged task. 333130812Smarcel Returns -1 if remote wait failed, task status otherwise. */ 334130812Smarcel 335130812Smarcelstatic int 336130812Smarcelnet_wait (RDB_EVENT *pEvent) 337130812Smarcel{ 338130812Smarcel int pid; 339130812Smarcel enum clnt_stat status; 340130812Smarcel 341130812Smarcel memset ((char *) pEvent, '\0', sizeof (RDB_EVENT)); 342130812Smarcel 343130812Smarcel pid = PIDGET (inferior_ptid); 344130812Smarcel status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT, 345130812Smarcel pEvent); 346130812Smarcel 347130812Smarcel /* return (status == RPC_SUCCESS)? pEvent->status: -1; */ 348130812Smarcel if (status == RPC_SUCCESS) 349130812Smarcel return ((pEvent->status) ? 1 : 0); 350130812Smarcel else if (status == RPC_TIMEDOUT) 351130812Smarcel return (1); 352130812Smarcel else 353130812Smarcel return (-1); 354130812Smarcel} 355130812Smarcel 356130812Smarcel/* Suspend the remote task. 357130812Smarcel Returns -1 if suspend fails on target system, 0 otherwise. */ 358130812Smarcel 359130812Smarcelstatic int 360130812Smarcelnet_quit (void) 361130812Smarcel{ 362130812Smarcel int pid; 363130812Smarcel int quit_status; 364130812Smarcel enum clnt_stat status; 365130812Smarcel 366130812Smarcel quit_status = 0; 367130812Smarcel 368130812Smarcel /* don't let rdbTask suspend itself by passing a pid of 0 */ 369130812Smarcel 370130812Smarcel if ((pid = PIDGET (inferior_ptid)) == 0) 371130812Smarcel return -1; 372130812Smarcel 373130812Smarcel status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int, 374130812Smarcel &quit_status); 375130812Smarcel 376130812Smarcel return (status == RPC_SUCCESS) ? quit_status : -1; 377130812Smarcel} 378130812Smarcel 379130812Smarcel/* Read a register or registers from the remote system. */ 380130812Smarcel 381130812Smarcelvoid 382130812Smarcelnet_read_registers (char *reg_buf, int len, u_long procnum) 383130812Smarcel{ 384130812Smarcel int status; 385130812Smarcel Rptrace ptrace_in; 386130812Smarcel Ptrace_return ptrace_out; 387130812Smarcel C_bytes out_data; 388130812Smarcel char message[100]; 389130812Smarcel 390130812Smarcel memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in)); 391130812Smarcel memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out)); 392130812Smarcel 393130812Smarcel /* Initialize RPC input argument structure. */ 394130812Smarcel 395130812Smarcel ptrace_in.pid = PIDGET (inferior_ptid); 396130812Smarcel ptrace_in.info.ttype = NOINFO; 397130812Smarcel 398130812Smarcel /* Initialize RPC return value structure. */ 399130812Smarcel 400130812Smarcel out_data.bytes = reg_buf; 401130812Smarcel out_data.len = len; 402130812Smarcel ptrace_out.info.more_data = (caddr_t) & out_data; 403130812Smarcel 404130812Smarcel /* Call RPC; take an error exit if appropriate. */ 405130812Smarcel 406130812Smarcel status = net_ptrace_clnt_call (procnum, &ptrace_in, &ptrace_out); 407130812Smarcel if (status) 408130812Smarcel error (rpcerr); 409130812Smarcel if (ptrace_out.status == -1) 410130812Smarcel { 411130812Smarcel errno = ptrace_out.errno_num; 412130812Smarcel sprintf (message, "reading %s registers", (procnum == PTRACE_GETREGS) 413130812Smarcel ? "general-purpose" 414130812Smarcel : "floating-point"); 415130812Smarcel perror_with_name (message); 416130812Smarcel } 417130812Smarcel} 418130812Smarcel 419130812Smarcel/* Write register values to a VxWorks target. REG_BUF points to a buffer 420130812Smarcel containing the raw register values, LEN is the length of REG_BUF in 421130812Smarcel bytes, and PROCNUM is the RPC procedure number (PTRACE_SETREGS or 422130812Smarcel PTRACE_SETFPREGS). An error exit is taken if the RPC call fails or 423130812Smarcel if an error status is returned by the remote debug server. This is 424130812Smarcel a utility routine used by vx_write_register (). */ 425130812Smarcel 426130812Smarcelvoid 427130812Smarcelnet_write_registers (char *reg_buf, int len, u_long procnum) 428130812Smarcel{ 429130812Smarcel int status; 430130812Smarcel Rptrace ptrace_in; 431130812Smarcel Ptrace_return ptrace_out; 432130812Smarcel C_bytes in_data; 433130812Smarcel char message[100]; 434130812Smarcel 435130812Smarcel memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in)); 436130812Smarcel memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out)); 437130812Smarcel 438130812Smarcel /* Initialize RPC input argument structure. */ 439130812Smarcel 440130812Smarcel in_data.bytes = reg_buf; 441130812Smarcel in_data.len = len; 442130812Smarcel 443130812Smarcel ptrace_in.pid = PIDGET (inferior_ptid); 444130812Smarcel ptrace_in.info.ttype = DATA; 445130812Smarcel ptrace_in.info.more_data = (caddr_t) & in_data; 446130812Smarcel 447130812Smarcel /* Call RPC; take an error exit if appropriate. */ 448130812Smarcel 449130812Smarcel status = net_ptrace_clnt_call (procnum, &ptrace_in, &ptrace_out); 450130812Smarcel if (status) 451130812Smarcel error (rpcerr); 452130812Smarcel if (ptrace_out.status == -1) 453130812Smarcel { 454130812Smarcel errno = ptrace_out.errno_num; 455130812Smarcel sprintf (message, "writing %s registers", (procnum == PTRACE_SETREGS) 456130812Smarcel ? "general-purpose" 457130812Smarcel : "floating-point"); 458130812Smarcel perror_with_name (message); 459130812Smarcel } 460130812Smarcel} 461130812Smarcel 462130812Smarcel/* Prepare to store registers. Since we will store all of them, 463130812Smarcel read out their current values now. */ 464130812Smarcel 465130812Smarcelstatic void 466130812Smarcelvx_prepare_to_store (void) 467130812Smarcel{ 468130812Smarcel /* Fetch all registers, if any of them are not yet fetched. */ 469130812Smarcel deprecated_read_register_bytes (0, NULL, DEPRECATED_REGISTER_BYTES); 470130812Smarcel} 471130812Smarcel 472130812Smarcel/* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR 473130812Smarcel to debugger memory starting at MYADDR. WRITE is true if writing to the 474130812Smarcel inferior. TARGET is unused. 475130812Smarcel Result is the number of bytes written or read (zero if error). The 476130812Smarcel protocol allows us to return a negative count, indicating that we can't 477130812Smarcel handle the current address but can handle one N bytes further, but 478130812Smarcel vxworks doesn't give us that information. */ 479130812Smarcel 480130812Smarcelstatic int 481130812Smarcelvx_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, 482130812Smarcel struct mem_attrib *attrib, struct target_ops *target) 483130812Smarcel{ 484130812Smarcel int status; 485130812Smarcel Rptrace ptrace_in; 486130812Smarcel Ptrace_return ptrace_out; 487130812Smarcel C_bytes data; 488130812Smarcel enum ptracereq request; 489130812Smarcel int nleft, nxfer; 490130812Smarcel 491130812Smarcel memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in)); 492130812Smarcel memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out)); 493130812Smarcel 494130812Smarcel ptrace_in.pid = PIDGET (inferior_ptid); /* XXX pid unnecessary for READDATA */ 495130812Smarcel ptrace_in.addr = (int) memaddr; /* Where from */ 496130812Smarcel ptrace_in.data = len; /* How many bytes */ 497130812Smarcel 498130812Smarcel if (write) 499130812Smarcel { 500130812Smarcel ptrace_in.info.ttype = DATA; 501130812Smarcel ptrace_in.info.more_data = (caddr_t) & data; 502130812Smarcel 503130812Smarcel data.bytes = (caddr_t) myaddr; /* Where from */ 504130812Smarcel data.len = len; /* How many bytes (again, for XDR) */ 505130812Smarcel request = PTRACE_WRITEDATA; 506130812Smarcel } 507130812Smarcel else 508130812Smarcel { 509130812Smarcel ptrace_out.info.more_data = (caddr_t) & data; 510130812Smarcel request = PTRACE_READDATA; 511130812Smarcel } 512130812Smarcel /* Loop until the entire request has been satisfied, transferring 513130812Smarcel at most VX_MEMXFER_MAX bytes per iteration. Break from the loop 514130812Smarcel if an error status is returned by the remote debug server. */ 515130812Smarcel 516130812Smarcel nleft = len; 517130812Smarcel status = 0; 518130812Smarcel 519130812Smarcel while (nleft > 0 && status == 0) 520130812Smarcel { 521130812Smarcel nxfer = min (nleft, VX_MEMXFER_MAX); 522130812Smarcel 523130812Smarcel ptrace_in.addr = (int) memaddr; 524130812Smarcel ptrace_in.data = nxfer; 525130812Smarcel data.bytes = (caddr_t) myaddr; 526130812Smarcel data.len = nxfer; 527130812Smarcel 528130812Smarcel /* Request a block from the remote debug server; if RPC fails, 529130812Smarcel report an error and return to debugger command level. */ 530130812Smarcel 531130812Smarcel if (net_ptrace_clnt_call (request, &ptrace_in, &ptrace_out)) 532130812Smarcel error (rpcerr); 533130812Smarcel 534130812Smarcel status = ptrace_out.status; 535130812Smarcel if (status == 0) 536130812Smarcel { 537130812Smarcel memaddr += nxfer; 538130812Smarcel myaddr += nxfer; 539130812Smarcel nleft -= nxfer; 540130812Smarcel } 541130812Smarcel else 542130812Smarcel { 543130812Smarcel /* A target-side error has ocurred. Set errno to the error 544130812Smarcel code chosen by the target so that a later perror () will 545130812Smarcel say something meaningful. */ 546130812Smarcel 547130812Smarcel errno = ptrace_out.errno_num; 548130812Smarcel } 549130812Smarcel } 550130812Smarcel 551130812Smarcel /* Return the number of bytes transferred. */ 552130812Smarcel 553130812Smarcel return (len - nleft); 554130812Smarcel} 555130812Smarcel 556130812Smarcelstatic void 557130812Smarcelvx_files_info (void) 558130812Smarcel{ 559130812Smarcel printf_unfiltered ("\tAttached to host `%s'", vx_host); 560130812Smarcel printf_unfiltered (", which has %sfloating point", target_has_fp ? "" : "no "); 561130812Smarcel printf_unfiltered (".\n"); 562130812Smarcel} 563130812Smarcel 564130812Smarcelstatic void 565130812Smarcelvx_run_files_info (void) 566130812Smarcel{ 567130812Smarcel printf_unfiltered ("\tRunning %s VxWorks process %s", 568130812Smarcel vx_running ? "child" : "attached", 569130812Smarcel local_hex_string (PIDGET (inferior_ptid))); 570130812Smarcel if (vx_running) 571130812Smarcel printf_unfiltered (", function `%s'", vx_running); 572130812Smarcel printf_unfiltered (".\n"); 573130812Smarcel} 574130812Smarcel 575130812Smarcelstatic void 576130812Smarcelvx_resume (ptid_t ptid, int step, enum target_signal siggnal) 577130812Smarcel{ 578130812Smarcel int status; 579130812Smarcel Rptrace ptrace_in; 580130812Smarcel Ptrace_return ptrace_out; 581130812Smarcel CORE_ADDR cont_addr; 582130812Smarcel 583130812Smarcel if (ptid_equal (ptid, minus_one_ptid)) 584130812Smarcel ptid = inferior_ptid; 585130812Smarcel 586130812Smarcel if (siggnal != 0 && siggnal != stop_signal) 587130812Smarcel error ("Cannot send signals to VxWorks processes"); 588130812Smarcel 589130812Smarcel /* Set CONT_ADDR to the address at which we are continuing, 590130812Smarcel or to 1 if we are continuing from where the program stopped. 591130812Smarcel This conforms to traditional ptrace () usage, but at the same 592130812Smarcel time has special meaning for the VxWorks remote debug server. 593130812Smarcel If the address is not 1, the server knows that the target 594130812Smarcel program is jumping to a new address, which requires special 595130812Smarcel handling if there is a breakpoint at the new address. */ 596130812Smarcel 597130812Smarcel cont_addr = read_register (PC_REGNUM); 598130812Smarcel if (cont_addr == stop_pc) 599130812Smarcel cont_addr = 1; 600130812Smarcel 601130812Smarcel memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in)); 602130812Smarcel memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out)); 603130812Smarcel 604130812Smarcel ptrace_in.pid = PIDGET (ptid); 605130812Smarcel ptrace_in.addr = cont_addr; /* Target side insists on this, or it panics. */ 606130812Smarcel 607130812Smarcel if (step) 608130812Smarcel status = net_step (); 609130812Smarcel else 610130812Smarcel status = net_ptrace_clnt_call (PTRACE_CONT, &ptrace_in, &ptrace_out); 611130812Smarcel 612130812Smarcel if (status) 613130812Smarcel error (rpcerr); 614130812Smarcel if (ptrace_out.status == -1) 615130812Smarcel { 616130812Smarcel errno = ptrace_out.errno_num; 617130812Smarcel perror_with_name ("Resuming remote process"); 618130812Smarcel } 619130812Smarcel} 620130812Smarcel 621130812Smarcelstatic void 622130812Smarcelvx_mourn_inferior (void) 623130812Smarcel{ 624130812Smarcel pop_target (); /* Pop back to no-child state */ 625130812Smarcel generic_mourn_inferior (); 626130812Smarcel} 627130812Smarcel 628130812Smarcel 629130812Smarcelstatic void vx_add_symbols (char *, int, CORE_ADDR, CORE_ADDR, CORE_ADDR); 630130812Smarcel 631130812Smarcelstruct find_sect_args 632130812Smarcel { 633130812Smarcel CORE_ADDR text_start; 634130812Smarcel CORE_ADDR data_start; 635130812Smarcel CORE_ADDR bss_start; 636130812Smarcel }; 637130812Smarcel 638130812Smarcelstatic void find_sect (bfd *, asection *, void *); 639130812Smarcel 640130812Smarcelstatic void 641130812Smarcelfind_sect (bfd *abfd, asection *sect, void *obj) 642130812Smarcel{ 643130812Smarcel struct find_sect_args *args = (struct find_sect_args *) obj; 644130812Smarcel 645130812Smarcel if (bfd_get_section_flags (abfd, sect) & (SEC_CODE & SEC_READONLY)) 646130812Smarcel args->text_start = bfd_get_section_vma (abfd, sect); 647130812Smarcel else if (bfd_get_section_flags (abfd, sect) & SEC_ALLOC) 648130812Smarcel { 649130812Smarcel if (bfd_get_section_flags (abfd, sect) & SEC_LOAD) 650130812Smarcel { 651130812Smarcel /* Exclude .ctor and .dtor sections which have SEC_CODE set but not 652130812Smarcel SEC_DATA. */ 653130812Smarcel if (bfd_get_section_flags (abfd, sect) & SEC_DATA) 654130812Smarcel args->data_start = bfd_get_section_vma (abfd, sect); 655130812Smarcel } 656130812Smarcel else 657130812Smarcel args->bss_start = bfd_get_section_vma (abfd, sect); 658130812Smarcel } 659130812Smarcel} 660130812Smarcel 661130812Smarcelstatic void 662130812Smarcelvx_add_symbols (char *name, int from_tty, CORE_ADDR text_addr, 663130812Smarcel CORE_ADDR data_addr, CORE_ADDR bss_addr) 664130812Smarcel{ 665130812Smarcel struct section_offsets *offs; 666130812Smarcel struct objfile *objfile; 667130812Smarcel struct find_sect_args ss; 668130812Smarcel 669130812Smarcel /* It might be nice to suppress the breakpoint_re_set which happens here 670130812Smarcel because we are going to do one again after the objfile_relocate. */ 671130812Smarcel objfile = symbol_file_add (name, from_tty, NULL, 0, 0); 672130812Smarcel 673130812Smarcel /* This is a (slightly cheesy) way of superceding the old symbols. A less 674130812Smarcel cheesy way would be to find the objfile with the same name and 675130812Smarcel free_objfile it. */ 676130812Smarcel objfile_to_front (objfile); 677130812Smarcel 678130812Smarcel offs = 679130812Smarcel (struct section_offsets *) 680130812Smarcel alloca (SIZEOF_N_SECTION_OFFSETS (objfile->num_sections)); 681130812Smarcel memcpy (offs, objfile->section_offsets, 682130812Smarcel SIZEOF_N_SECTION_OFFSETS (objfile->num_sections)); 683130812Smarcel 684130812Smarcel ss.text_start = 0; 685130812Smarcel ss.data_start = 0; 686130812Smarcel ss.bss_start = 0; 687130812Smarcel bfd_map_over_sections (objfile->obfd, find_sect, &ss); 688130812Smarcel 689130812Smarcel /* Both COFF and b.out frontends use these SECT_OFF_* values. */ 690130812Smarcel offs->offsets[SECT_OFF_TEXT (objfile)] = text_addr - ss.text_start; 691130812Smarcel offs->offsets[SECT_OFF_DATA (objfile)] = data_addr - ss.data_start; 692130812Smarcel offs->offsets[SECT_OFF_BSS (objfile)] = bss_addr - ss.bss_start; 693130812Smarcel objfile_relocate (objfile, offs); 694130812Smarcel} 695130812Smarcel 696130812Smarcel/* This function allows the addition of incrementally linked object files. */ 697130812Smarcel 698130812Smarcelstatic void 699130812Smarcelvx_load_command (char *arg_string, int from_tty) 700130812Smarcel{ 701130812Smarcel CORE_ADDR text_addr; 702130812Smarcel CORE_ADDR data_addr; 703130812Smarcel CORE_ADDR bss_addr; 704130812Smarcel 705130812Smarcel if (arg_string == 0) 706130812Smarcel error ("The load command takes a file name"); 707130812Smarcel 708130812Smarcel arg_string = tilde_expand (arg_string); 709130812Smarcel make_cleanup (xfree, arg_string); 710130812Smarcel 711130812Smarcel dont_repeat (); 712130812Smarcel 713130812Smarcel /* Refuse to load the module if a debugged task is running. Doing so 714130812Smarcel can have a number of unpleasant consequences to the running task. */ 715130812Smarcel 716130812Smarcel if (PIDGET (inferior_ptid) != 0 && target_has_execution) 717130812Smarcel { 718130812Smarcel if (query ("You may not load a module while the target task is running.\n\ 719130812SmarcelKill the target task? ")) 720130812Smarcel target_kill (); 721130812Smarcel else 722130812Smarcel error ("Load canceled."); 723130812Smarcel } 724130812Smarcel 725130812Smarcel QUIT; 726130812Smarcel immediate_quit++; 727130812Smarcel if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1) 728130812Smarcel error ("Load failed on target machine"); 729130812Smarcel immediate_quit--; 730130812Smarcel 731130812Smarcel vx_add_symbols (arg_string, from_tty, text_addr, data_addr, bss_addr); 732130812Smarcel 733130812Smarcel /* Getting new symbols may change our opinion about what is 734130812Smarcel frameless. */ 735130812Smarcel reinit_frame_cache (); 736130812Smarcel} 737130812Smarcel 738130812Smarcel/* Single step the target program at the source or machine level. 739130812Smarcel Takes an error exit if rpc fails. 740130812Smarcel Returns -1 if remote single-step operation fails, else 0. */ 741130812Smarcel 742130812Smarcelstatic int 743130812Smarcelnet_step (void) 744130812Smarcel{ 745130812Smarcel enum clnt_stat status; 746130812Smarcel int step_status; 747130812Smarcel SOURCE_STEP source_step; 748130812Smarcel 749130812Smarcel source_step.taskId = PIDGET (inferior_ptid); 750130812Smarcel 751130812Smarcel if (step_range_end) 752130812Smarcel { 753130812Smarcel source_step.startAddr = step_range_start; 754130812Smarcel source_step.endAddr = step_range_end; 755130812Smarcel } 756130812Smarcel else 757130812Smarcel { 758130812Smarcel source_step.startAddr = 0; 759130812Smarcel source_step.endAddr = 0; 760130812Smarcel } 761130812Smarcel 762130812Smarcel status = net_clnt_call (VX_SOURCE_STEP, xdr_SOURCE_STEP, &source_step, 763130812Smarcel xdr_int, &step_status); 764130812Smarcel 765130812Smarcel if (status == RPC_SUCCESS) 766130812Smarcel return step_status; 767130812Smarcel else 768130812Smarcel error (rpcerr); 769130812Smarcel} 770130812Smarcel 771130812Smarcel/* Emulate ptrace using RPC calls to the VxWorks target system. 772130812Smarcel Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise. */ 773130812Smarcel 774130812Smarcelstatic int 775130812Smarcelnet_ptrace_clnt_call (enum ptracereq request, Rptrace *pPtraceIn, 776130812Smarcel Ptrace_return *pPtraceOut) 777130812Smarcel{ 778130812Smarcel enum clnt_stat status; 779130812Smarcel 780130812Smarcel status = net_clnt_call (request, xdr_rptrace, pPtraceIn, xdr_ptrace_return, 781130812Smarcel pPtraceOut); 782130812Smarcel 783130812Smarcel if (status != RPC_SUCCESS) 784130812Smarcel return -1; 785130812Smarcel 786130812Smarcel return 0; 787130812Smarcel} 788130812Smarcel 789130812Smarcel/* Query the target for the name of the file from which VxWorks was 790130812Smarcel booted. pBootFile is the address of a pointer to the buffer to 791130812Smarcel receive the file name; if the pointer pointed to by pBootFile is 792130812Smarcel NULL, memory for the buffer will be allocated by XDR. 793130812Smarcel Returns -1 if rpc failed, 0 otherwise. */ 794130812Smarcel 795130812Smarcelstatic int 796130812Smarcelnet_get_boot_file (char **pBootFile) 797130812Smarcel{ 798130812Smarcel enum clnt_stat status; 799130812Smarcel 800130812Smarcel status = net_clnt_call (VX_BOOT_FILE_INQ, xdr_void, (char *) 0, 801130812Smarcel xdr_wrapstring, pBootFile); 802130812Smarcel return (status == RPC_SUCCESS) ? 0 : -1; 803130812Smarcel} 804130812Smarcel 805130812Smarcel/* Fetch a list of loaded object modules from the VxWorks target 806130812Smarcel and store in PLOADTABLE. 807130812Smarcel Returns -1 if rpc failed, 0 otherwise 808130812Smarcel There's no way to check if the returned loadTable is correct. 809130812Smarcel VxWorks doesn't check it. */ 810130812Smarcel 811130812Smarcelstatic int 812130812Smarcelnet_get_symbols (ldtabl *pLoadTable) 813130812Smarcel{ 814130812Smarcel enum clnt_stat status; 815130812Smarcel 816130812Smarcel memset ((char *) pLoadTable, '\0', sizeof (struct ldtabl)); 817130812Smarcel 818130812Smarcel status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable); 819130812Smarcel return (status == RPC_SUCCESS) ? 0 : -1; 820130812Smarcel} 821130812Smarcel 822130812Smarcel/* Look up a symbol in the VxWorks target's symbol table. 823130812Smarcel Returns status of symbol read on target side (0=success, -1=fail) 824130812Smarcel Returns -1 and complain()s if rpc fails. */ 825130812Smarcel 826130812Smarcelstatic int 827130812Smarcelvx_lookup_symbol (char *name, /* symbol name */ 828130812Smarcel CORE_ADDR *pAddr) 829130812Smarcel{ 830130812Smarcel enum clnt_stat status; 831130812Smarcel SYMBOL_ADDR symbolAddr; 832130812Smarcel 833130812Smarcel *pAddr = 0; 834130812Smarcel memset ((char *) &symbolAddr, '\0', sizeof (symbolAddr)); 835130812Smarcel 836130812Smarcel status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name, 837130812Smarcel xdr_SYMBOL_ADDR, &symbolAddr); 838130812Smarcel if (status != RPC_SUCCESS) 839130812Smarcel { 840130812Smarcel complaint (&symfile_complaints, "Lost contact with VxWorks target"); 841130812Smarcel return -1; 842130812Smarcel } 843130812Smarcel 844130812Smarcel *pAddr = symbolAddr.addr; 845130812Smarcel return symbolAddr.status; 846130812Smarcel} 847130812Smarcel 848130812Smarcel/* Check to see if the VxWorks target has a floating point coprocessor. 849130812Smarcel Returns 1 if target has floating point processor, 0 otherwise. 850130812Smarcel Calls error() if rpc fails. */ 851130812Smarcel 852130812Smarcelstatic int 853130812Smarcelnet_check_for_fp (void) 854130812Smarcel{ 855130812Smarcel enum clnt_stat status; 856130812Smarcel bool_t fp = 0; /* true if fp processor is present on target board */ 857130812Smarcel 858130812Smarcel status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp); 859130812Smarcel if (status != RPC_SUCCESS) 860130812Smarcel error (rpcerr); 861130812Smarcel 862130812Smarcel return (int) fp; 863130812Smarcel} 864130812Smarcel 865130812Smarcel/* Establish an RPC connection with the VxWorks target system. 866130812Smarcel Calls error () if unable to establish connection. */ 867130812Smarcel 868130812Smarcelstatic void 869130812Smarcelnet_connect (char *host) 870130812Smarcel{ 871130812Smarcel struct sockaddr_in destAddr; 872130812Smarcel struct hostent *destHost; 873130812Smarcel unsigned long addr; 874130812Smarcel 875130812Smarcel /* Get the internet address for the given host. Allow a numeric 876130812Smarcel IP address or a hostname. */ 877130812Smarcel 878130812Smarcel addr = inet_addr (host); 879130812Smarcel if (addr == -1) 880130812Smarcel { 881130812Smarcel destHost = (struct hostent *) gethostbyname (host); 882130812Smarcel if (destHost == NULL) 883130812Smarcel /* FIXME: Probably should include hostname here in quotes. 884130812Smarcel For example if the user types "target vxworks vx960 " it should 885130812Smarcel say "Invalid host `vx960 '." not just "Invalid hostname". */ 886130812Smarcel error ("Invalid hostname. Couldn't find remote host address."); 887130812Smarcel addr = *(unsigned long *) destHost->h_addr; 888130812Smarcel } 889130812Smarcel 890130812Smarcel memset (&destAddr, '\0', sizeof (destAddr)); 891130812Smarcel 892130812Smarcel destAddr.sin_addr.s_addr = addr; 893130812Smarcel destAddr.sin_family = AF_INET; 894130812Smarcel destAddr.sin_port = 0; /* set to actual port that remote 895130812Smarcel ptrace is listening on. */ 896130812Smarcel 897130812Smarcel /* Create a tcp client transport on which to issue 898130812Smarcel calls to the remote ptrace server. */ 899130812Smarcel 900130812Smarcel ptraceSock = RPC_ANYSOCK; 901130812Smarcel pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0); 902130812Smarcel /* FIXME, here is where we deal with different version numbers of the 903130812Smarcel proto */ 904130812Smarcel 905130812Smarcel if (pClient == NULL) 906130812Smarcel { 907130812Smarcel clnt_pcreateerror ("\tnet_connect"); 908130812Smarcel error ("Couldn't connect to remote target."); 909130812Smarcel } 910130812Smarcel} 911130812Smarcel 912130812Smarcel/* Sleep for the specified number of milliseconds 913130812Smarcel * (assumed to be less than 1000). 914130812Smarcel * If select () is interrupted, returns immediately; 915130812Smarcel * takes an error exit if select () fails for some other reason. 916130812Smarcel */ 917130812Smarcel 918130812Smarcelstatic void 919130812Smarcelsleep_ms (long ms) 920130812Smarcel{ 921130812Smarcel struct timeval select_timeout; 922130812Smarcel int status; 923130812Smarcel 924130812Smarcel select_timeout.tv_sec = 0; 925130812Smarcel select_timeout.tv_usec = ms * 1000; 926130812Smarcel 927130812Smarcel status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, 928130812Smarcel &select_timeout); 929130812Smarcel 930130812Smarcel if (status < 0 && errno != EINTR) 931130812Smarcel perror_with_name ("select"); 932130812Smarcel} 933130812Smarcel 934130812Smarcelstatic ptid_t 935130812Smarcelvx_wait (ptid_t ptid_to_wait_for, struct target_waitstatus *status) 936130812Smarcel{ 937130812Smarcel int pid; 938130812Smarcel RDB_EVENT rdbEvent; 939130812Smarcel int quit_failed; 940130812Smarcel 941130812Smarcel do 942130812Smarcel { 943130812Smarcel /* If CTRL-C is hit during this loop, 944130812Smarcel suspend the inferior process. */ 945130812Smarcel 946130812Smarcel quit_failed = 0; 947130812Smarcel if (quit_flag) 948130812Smarcel { 949130812Smarcel quit_failed = (net_quit () == -1); 950130812Smarcel quit_flag = 0; 951130812Smarcel } 952130812Smarcel 953130812Smarcel /* If a net_quit () or net_wait () call has failed, 954130812Smarcel allow the user to break the connection with the target. 955130812Smarcel We can't simply error () out of this loop, since the 956130812Smarcel data structures representing the state of the inferior 957130812Smarcel are in an inconsistent state. */ 958130812Smarcel 959130812Smarcel if (quit_failed || net_wait (&rdbEvent) == -1) 960130812Smarcel { 961130812Smarcel terminal_ours (); 962130812Smarcel if (query ("Can't %s. Disconnect from target system? ", 963130812Smarcel (quit_failed) ? "suspend remote task" 964130812Smarcel : "get status of remote task")) 965130812Smarcel { 966130812Smarcel target_mourn_inferior (); 967130812Smarcel error ("Use the \"target\" command to reconnect."); 968130812Smarcel } 969130812Smarcel else 970130812Smarcel { 971130812Smarcel terminal_inferior (); 972130812Smarcel continue; 973130812Smarcel } 974130812Smarcel } 975130812Smarcel 976130812Smarcel pid = rdbEvent.taskId; 977130812Smarcel if (pid == 0) 978130812Smarcel { 979130812Smarcel sleep_ms (200); /* FIXME Don't kill the network too badly */ 980130812Smarcel } 981130812Smarcel else if (pid != PIDGET (inferior_ptid)) 982130812Smarcel internal_error (__FILE__, __LINE__, 983130812Smarcel "Bad pid for debugged task: %s\n", 984130812Smarcel local_hex_string ((unsigned long) pid)); 985130812Smarcel } 986130812Smarcel while (pid == 0); 987130812Smarcel 988130812Smarcel /* The mostly likely kind. */ 989130812Smarcel status->kind = TARGET_WAITKIND_STOPPED; 990130812Smarcel 991130812Smarcel switch (rdbEvent.eventType) 992130812Smarcel { 993130812Smarcel case EVENT_EXIT: 994130812Smarcel status->kind = TARGET_WAITKIND_EXITED; 995130812Smarcel /* FIXME is it possible to distinguish between a 996130812Smarcel normal vs abnormal exit in VxWorks? */ 997130812Smarcel status->value.integer = 0; 998130812Smarcel break; 999130812Smarcel 1000130812Smarcel case EVENT_START: 1001130812Smarcel /* Task was just started. */ 1002130812Smarcel status->value.sig = TARGET_SIGNAL_TRAP; 1003130812Smarcel break; 1004130812Smarcel 1005130812Smarcel case EVENT_STOP: 1006130812Smarcel status->value.sig = TARGET_SIGNAL_TRAP; 1007130812Smarcel /* XXX was it stopped by a signal? act accordingly */ 1008130812Smarcel break; 1009130812Smarcel 1010130812Smarcel case EVENT_BREAK: /* Breakpoint was hit. */ 1011130812Smarcel status->value.sig = TARGET_SIGNAL_TRAP; 1012130812Smarcel break; 1013130812Smarcel 1014130812Smarcel case EVENT_SUSPEND: /* Task was suspended, probably by ^C. */ 1015130812Smarcel status->value.sig = TARGET_SIGNAL_INT; 1016130812Smarcel break; 1017130812Smarcel 1018130812Smarcel case EVENT_BUS_ERR: /* Task made evil nasty reference. */ 1019130812Smarcel status->value.sig = TARGET_SIGNAL_BUS; 1020130812Smarcel break; 1021130812Smarcel 1022130812Smarcel case EVENT_ZERO_DIV: /* Division by zero */ 1023130812Smarcel status->value.sig = TARGET_SIGNAL_FPE; 1024130812Smarcel break; 1025130812Smarcel 1026130812Smarcel case EVENT_SIGNAL: 1027130812Smarcel#ifdef I80960 1028130812Smarcel status->value.sig = i960_fault_to_signal (rdbEvent.sigType); 1029130812Smarcel#else 1030130812Smarcel /* Back in the old days, before enum target_signal, this code used 1031130812Smarcel to add NSIG to the signal number and claim that PRINT_RANDOM_SIGNAL 1032130812Smarcel would take care of it. But PRINT_RANDOM_SIGNAL has never been 1033130812Smarcel defined except on the i960, so I don't really know what we are 1034130812Smarcel supposed to do on other architectures. */ 1035130812Smarcel status->value.sig = TARGET_SIGNAL_UNKNOWN; 1036130812Smarcel#endif 1037130812Smarcel break; 1038130812Smarcel } /* switch */ 1039130812Smarcel return pid_to_ptid (pid); 1040130812Smarcel} 1041130812Smarcel 1042130812Smarcelstatic int 1043130812Smarcelsymbol_stub (char *arg) 1044130812Smarcel{ 1045130812Smarcel symbol_file_add_main (arg, 0); 1046130812Smarcel return 1; 1047130812Smarcel} 1048130812Smarcel 1049130812Smarcelstatic int 1050130812Smarceladd_symbol_stub (char *arg) 1051130812Smarcel{ 1052130812Smarcel struct ldfile *pLoadFile = (struct ldfile *) arg; 1053130812Smarcel 1054130812Smarcel printf_unfiltered ("\t%s: ", pLoadFile->name); 1055130812Smarcel vx_add_symbols (pLoadFile->name, 0, pLoadFile->txt_addr, 1056130812Smarcel pLoadFile->data_addr, pLoadFile->bss_addr); 1057130812Smarcel printf_unfiltered ("ok\n"); 1058130812Smarcel return 1; 1059130812Smarcel} 1060130812Smarcel/* Target command for VxWorks target systems. 1061130812Smarcel 1062130812Smarcel Used in vxgdb. Takes the name of a remote target machine 1063130812Smarcel running vxWorks and connects to it to initialize remote network 1064130812Smarcel debugging. */ 1065130812Smarcel 1066130812Smarcelstatic void 1067130812Smarcelvx_open (char *args, int from_tty) 1068130812Smarcel{ 1069130812Smarcel extern int close (); 1070130812Smarcel char *bootFile; 1071130812Smarcel extern char *source_path; 1072130812Smarcel struct ldtabl loadTable; 1073130812Smarcel struct ldfile *pLoadFile; 1074130812Smarcel int i; 1075130812Smarcel extern CLIENT *pClient; 1076130812Smarcel int symbols_added = 0; 1077130812Smarcel 1078130812Smarcel if (!args) 1079130812Smarcel error_no_arg ("target machine name"); 1080130812Smarcel 1081130812Smarcel target_preopen (from_tty); 1082130812Smarcel 1083130812Smarcel unpush_target (&vx_ops); 1084130812Smarcel printf_unfiltered ("Attaching remote machine across net...\n"); 1085130812Smarcel gdb_flush (gdb_stdout); 1086130812Smarcel 1087130812Smarcel /* Allow the user to kill the connect attempt by typing ^C. 1088130812Smarcel Wait until the call to target_has_fp () completes before 1089130812Smarcel disallowing an immediate quit, since even if net_connect () 1090130812Smarcel is successful, the remote debug server might be hung. */ 1091130812Smarcel 1092130812Smarcel immediate_quit++; 1093130812Smarcel 1094130812Smarcel net_connect (args); 1095130812Smarcel target_has_fp = net_check_for_fp (); 1096130812Smarcel printf_filtered ("Connected to %s.\n", args); 1097130812Smarcel 1098130812Smarcel immediate_quit--; 1099130812Smarcel 1100130812Smarcel push_target (&vx_ops); 1101130812Smarcel 1102130812Smarcel /* Save a copy of the target host's name. */ 1103130812Smarcel vx_host = savestring (args, strlen (args)); 1104130812Smarcel 1105130812Smarcel /* Find out the name of the file from which the target was booted 1106130812Smarcel and load its symbol table. */ 1107130812Smarcel 1108130812Smarcel printf_filtered ("Looking in Unix path for all loaded modules:\n"); 1109130812Smarcel bootFile = NULL; 1110130812Smarcel if (!net_get_boot_file (&bootFile)) 1111130812Smarcel { 1112130812Smarcel if (*bootFile) 1113130812Smarcel { 1114130812Smarcel printf_filtered ("\t%s: ", bootFile); 1115130812Smarcel /* This assumes that the kernel is never relocated. Hope that is an 1116130812Smarcel accurate assumption. */ 1117130812Smarcel if (catch_errors 1118130812Smarcel (symbol_stub, 1119130812Smarcel bootFile, 1120130812Smarcel "Error while reading symbols from boot file:\n", 1121130812Smarcel RETURN_MASK_ALL)) 1122130812Smarcel puts_filtered ("ok\n"); 1123130812Smarcel } 1124130812Smarcel else if (from_tty) 1125130812Smarcel printf_unfiltered ("VxWorks kernel symbols not loaded.\n"); 1126130812Smarcel } 1127130812Smarcel else 1128130812Smarcel error ("Can't retrieve boot file name from target machine."); 1129130812Smarcel 1130130812Smarcel clnt_freeres (pClient, xdr_wrapstring, &bootFile); 1131130812Smarcel 1132130812Smarcel if (net_get_symbols (&loadTable) != 0) 1133130812Smarcel error ("Can't read loaded modules from target machine"); 1134130812Smarcel 1135130812Smarcel i = 0 - 1; 1136130812Smarcel while (++i < loadTable.tbl_size) 1137130812Smarcel { 1138130812Smarcel QUIT; /* FIXME, avoids clnt_freeres below: mem leak */ 1139130812Smarcel pLoadFile = &loadTable.tbl_ent[i]; 1140130812Smarcel#ifdef WRS_ORIG 1141130812Smarcel { 1142130812Smarcel int desc; 1143130812Smarcel struct cleanup *old_chain; 1144130812Smarcel char *fullname = NULL; 1145130812Smarcel 1146130812Smarcel desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname); 1147130812Smarcel if (desc < 0) 1148130812Smarcel perror_with_name (pLoadFile->name); 1149130812Smarcel old_chain = make_cleanup (close, desc); 1150130812Smarcel add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr, 1151130812Smarcel pLoadFile->bss_addr); 1152130812Smarcel do_cleanups (old_chain); 1153130812Smarcel } 1154130812Smarcel#else 1155130812Smarcel /* FIXME: Is there something better to search than the PATH? (probably 1156130812Smarcel not the source path, since source might be in different directories 1157130812Smarcel than objects. */ 1158130812Smarcel 1159130812Smarcel if (catch_errors (add_symbol_stub, (char *) pLoadFile, (char *) 0, 1160130812Smarcel RETURN_MASK_ALL)) 1161130812Smarcel symbols_added = 1; 1162130812Smarcel#endif 1163130812Smarcel } 1164130812Smarcel printf_filtered ("Done.\n"); 1165130812Smarcel 1166130812Smarcel clnt_freeres (pClient, xdr_ldtabl, &loadTable); 1167130812Smarcel 1168130812Smarcel /* Getting new symbols may change our opinion about what is 1169130812Smarcel frameless. */ 1170130812Smarcel if (symbols_added) 1171130812Smarcel reinit_frame_cache (); 1172130812Smarcel} 1173130812Smarcel 1174130812Smarcel/* Takes a task started up outside of gdb and ``attaches'' to it. 1175130812Smarcel This stops it cold in its tracks and allows us to start tracing it. */ 1176130812Smarcel 1177130812Smarcelstatic void 1178130812Smarcelvx_attach (char *args, int from_tty) 1179130812Smarcel{ 1180130812Smarcel unsigned long pid; 1181130812Smarcel char *cptr = 0; 1182130812Smarcel Rptrace ptrace_in; 1183130812Smarcel Ptrace_return ptrace_out; 1184130812Smarcel int status; 1185130812Smarcel 1186130812Smarcel if (!args) 1187130812Smarcel error_no_arg ("process-id to attach"); 1188130812Smarcel 1189130812Smarcel pid = strtoul (args, &cptr, 0); 1190130812Smarcel if ((cptr == args) || (*cptr != '\0')) 1191130812Smarcel error ("Invalid process-id -- give a single number in decimal or 0xhex"); 1192130812Smarcel 1193130812Smarcel if (from_tty) 1194130812Smarcel printf_unfiltered ("Attaching pid %s.\n", 1195130812Smarcel local_hex_string ((unsigned long) pid)); 1196130812Smarcel 1197130812Smarcel memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in)); 1198130812Smarcel memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out)); 1199130812Smarcel ptrace_in.pid = pid; 1200130812Smarcel 1201130812Smarcel status = net_ptrace_clnt_call (PTRACE_ATTACH, &ptrace_in, &ptrace_out); 1202130812Smarcel if (status == -1) 1203130812Smarcel error (rpcerr); 1204130812Smarcel if (ptrace_out.status == -1) 1205130812Smarcel { 1206130812Smarcel errno = ptrace_out.errno_num; 1207130812Smarcel perror_with_name ("Attaching remote process"); 1208130812Smarcel } 1209130812Smarcel 1210130812Smarcel /* It worked... */ 1211130812Smarcel 1212130812Smarcel inferior_ptid = pid_to_ptid (pid); 1213130812Smarcel push_target (&vx_run_ops); 1214130812Smarcel 1215130812Smarcel if (vx_running) 1216130812Smarcel xfree (vx_running); 1217130812Smarcel vx_running = 0; 1218130812Smarcel} 1219130812Smarcel 1220130812Smarcel/* detach_command -- 1221130812Smarcel takes a program previously attached to and detaches it. 1222130812Smarcel The program resumes execution and will no longer stop 1223130812Smarcel on signals, etc. We better not have left any breakpoints 1224130812Smarcel in the program or it'll die when it hits one. For this 1225130812Smarcel to work, it may be necessary for the process to have been 1226130812Smarcel previously attached. It *might* work if the program was 1227130812Smarcel started via the normal ptrace (PTRACE_TRACEME). */ 1228130812Smarcel 1229130812Smarcelstatic void 1230130812Smarcelvx_detach (char *args, int from_tty) 1231130812Smarcel{ 1232130812Smarcel Rptrace ptrace_in; 1233130812Smarcel Ptrace_return ptrace_out; 1234130812Smarcel int signal = 0; 1235130812Smarcel int status; 1236130812Smarcel 1237130812Smarcel if (args) 1238130812Smarcel error ("Argument given to VxWorks \"detach\"."); 1239130812Smarcel 1240130812Smarcel if (from_tty) 1241130812Smarcel printf_unfiltered ("Detaching pid %s.\n", 1242130812Smarcel local_hex_string ( 1243130812Smarcel (unsigned long) PIDGET (inferior_ptid))); 1244130812Smarcel 1245130812Smarcel if (args) /* FIXME, should be possible to leave suspended */ 1246130812Smarcel signal = atoi (args); 1247130812Smarcel 1248130812Smarcel memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in)); 1249130812Smarcel memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out)); 1250130812Smarcel ptrace_in.pid = PIDGET (inferior_ptid); 1251130812Smarcel 1252130812Smarcel status = net_ptrace_clnt_call (PTRACE_DETACH, &ptrace_in, &ptrace_out); 1253130812Smarcel if (status == -1) 1254130812Smarcel error (rpcerr); 1255130812Smarcel if (ptrace_out.status == -1) 1256130812Smarcel { 1257130812Smarcel errno = ptrace_out.errno_num; 1258130812Smarcel perror_with_name ("Detaching VxWorks process"); 1259130812Smarcel } 1260130812Smarcel 1261130812Smarcel inferior_ptid = null_ptid; 1262130812Smarcel pop_target (); /* go back to non-executing VxWorks connection */ 1263130812Smarcel} 1264130812Smarcel 1265130812Smarcel/* vx_kill -- takes a running task and wipes it out. */ 1266130812Smarcel 1267130812Smarcelstatic void 1268130812Smarcelvx_kill (void) 1269130812Smarcel{ 1270130812Smarcel Rptrace ptrace_in; 1271130812Smarcel Ptrace_return ptrace_out; 1272130812Smarcel int status; 1273130812Smarcel 1274130812Smarcel printf_unfiltered ("Killing pid %s.\n", local_hex_string ((unsigned long) PIDGET (inferior_ptid))); 1275130812Smarcel 1276130812Smarcel memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in)); 1277130812Smarcel memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out)); 1278130812Smarcel ptrace_in.pid = PIDGET (inferior_ptid); 1279130812Smarcel 1280130812Smarcel status = net_ptrace_clnt_call (PTRACE_KILL, &ptrace_in, &ptrace_out); 1281130812Smarcel if (status == -1) 1282130812Smarcel warning (rpcerr); 1283130812Smarcel else if (ptrace_out.status == -1) 1284130812Smarcel { 1285130812Smarcel errno = ptrace_out.errno_num; 1286130812Smarcel perror_with_name ("Killing VxWorks process"); 1287130812Smarcel } 1288130812Smarcel 1289130812Smarcel /* If it gives good status, the process is *gone*, no events remain. 1290130812Smarcel If the kill failed, assume the process is gone anyhow. */ 1291130812Smarcel inferior_ptid = null_ptid; 1292130812Smarcel pop_target (); /* go back to non-executing VxWorks connection */ 1293130812Smarcel} 1294130812Smarcel 1295130812Smarcel/* Clean up from the VxWorks process target as it goes away. */ 1296130812Smarcel 1297130812Smarcelstatic void 1298130812Smarcelvx_proc_close (int quitting) 1299130812Smarcel{ 1300130812Smarcel inferior_ptid = null_ptid; /* No longer have a process. */ 1301130812Smarcel if (vx_running) 1302130812Smarcel xfree (vx_running); 1303130812Smarcel vx_running = 0; 1304130812Smarcel} 1305130812Smarcel 1306130812Smarcel/* Make an RPC call to the VxWorks target. 1307130812Smarcel Returns RPC status. */ 1308130812Smarcel 1309130812Smarcelstatic enum clnt_stat 1310130812Smarcelnet_clnt_call (enum ptracereq procNum, xdrproc_t inProc, char *in, 1311130812Smarcel xdrproc_t outProc, char *out) 1312130812Smarcel{ 1313130812Smarcel enum clnt_stat status; 1314130812Smarcel 1315130812Smarcel status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout); 1316130812Smarcel 1317130812Smarcel if (status != RPC_SUCCESS) 1318130812Smarcel clnt_perrno (status); 1319130812Smarcel 1320130812Smarcel return status; 1321130812Smarcel} 1322130812Smarcel 1323130812Smarcel/* Clean up before losing control. */ 1324130812Smarcel 1325130812Smarcelstatic void 1326130812Smarcelvx_close (int quitting) 1327130812Smarcel{ 1328130812Smarcel if (pClient) 1329130812Smarcel clnt_destroy (pClient); /* The net connection */ 1330130812Smarcel pClient = 0; 1331130812Smarcel 1332130812Smarcel if (vx_host) 1333130812Smarcel xfree (vx_host); /* The hostname */ 1334130812Smarcel vx_host = 0; 1335130812Smarcel} 1336130812Smarcel 1337130812Smarcel/* A vxprocess target should be started via "run" not "target". */ 1338130812Smarcelstatic void 1339130812Smarcelvx_proc_open (char *name, int from_tty) 1340130812Smarcel{ 1341130812Smarcel error ("Use the \"run\" command to start a VxWorks process."); 1342130812Smarcel} 1343130812Smarcel 1344130812Smarcelstatic void 1345130812Smarcelinit_vx_ops (void) 1346130812Smarcel{ 1347130812Smarcel vx_ops.to_shortname = "vxworks"; 1348130812Smarcel vx_ops.to_longname = "VxWorks target memory via RPC over TCP/IP"; 1349130812Smarcel vx_ops.to_doc = "Use VxWorks target memory. \n\ 1350130812SmarcelSpecify the name of the machine to connect to."; 1351130812Smarcel vx_ops.to_open = vx_open; 1352130812Smarcel vx_ops.to_close = vx_close; 1353130812Smarcel vx_ops.to_attach = vx_attach; 1354130812Smarcel vx_ops.to_xfer_memory = vx_xfer_memory; 1355130812Smarcel vx_ops.to_files_info = vx_files_info; 1356130812Smarcel vx_ops.to_load = vx_load_command; 1357130812Smarcel vx_ops.to_lookup_symbol = vx_lookup_symbol; 1358130812Smarcel vx_ops.to_create_inferior = vx_create_inferior; 1359130812Smarcel vx_ops.to_stratum = core_stratum; 1360130812Smarcel vx_ops.to_has_all_memory = 1; 1361130812Smarcel vx_ops.to_has_memory = 1; 1362130812Smarcel vx_ops.to_magic = OPS_MAGIC; /* Always the last thing */ 1363130812Smarcel}; 1364130812Smarcel 1365130812Smarcelstatic void 1366130812Smarcelinit_vx_run_ops (void) 1367130812Smarcel{ 1368130812Smarcel vx_run_ops.to_shortname = "vxprocess"; 1369130812Smarcel vx_run_ops.to_longname = "VxWorks process"; 1370130812Smarcel vx_run_ops.to_doc = "VxWorks process; started by the \"run\" command."; 1371130812Smarcel vx_run_ops.to_open = vx_proc_open; 1372130812Smarcel vx_run_ops.to_close = vx_proc_close; 1373130812Smarcel vx_run_ops.to_detach = vx_detach; 1374130812Smarcel vx_run_ops.to_resume = vx_resume; 1375130812Smarcel vx_run_ops.to_wait = vx_wait; 1376130812Smarcel vx_run_ops.to_fetch_registers = vx_read_register; 1377130812Smarcel vx_run_ops.to_store_registers = vx_write_register; 1378130812Smarcel vx_run_ops.to_prepare_to_store = vx_prepare_to_store; 1379130812Smarcel vx_run_ops.to_xfer_memory = vx_xfer_memory; 1380130812Smarcel vx_run_ops.to_files_info = vx_run_files_info; 1381130812Smarcel vx_run_ops.to_insert_breakpoint = vx_insert_breakpoint; 1382130812Smarcel vx_run_ops.to_remove_breakpoint = vx_remove_breakpoint; 1383130812Smarcel vx_run_ops.to_kill = vx_kill; 1384130812Smarcel vx_run_ops.to_load = vx_load_command; 1385130812Smarcel vx_run_ops.to_lookup_symbol = vx_lookup_symbol; 1386130812Smarcel vx_run_ops.to_mourn_inferior = vx_mourn_inferior; 1387130812Smarcel vx_run_ops.to_stratum = process_stratum; 1388130812Smarcel vx_run_ops.to_has_memory = 1; 1389130812Smarcel vx_run_ops.to_has_stack = 1; 1390130812Smarcel vx_run_ops.to_has_registers = 1; 1391130812Smarcel vx_run_ops.to_has_execution = 1; 1392130812Smarcel vx_run_ops.to_magic = OPS_MAGIC; 1393130812Smarcel} 1394130812Smarcel 1395130812Smarcelvoid 1396130812Smarcel_initialize_vx (void) 1397130812Smarcel{ 1398130812Smarcel init_vx_ops (); 1399130812Smarcel add_target (&vx_ops); 1400130812Smarcel init_vx_run_ops (); 1401130812Smarcel add_target (&vx_run_ops); 1402130812Smarcel 1403130812Smarcel add_show_from_set 1404130812Smarcel (add_set_cmd ("vxworks-timeout", class_support, var_uinteger, 1405130812Smarcel (char *) &rpcTimeout.tv_sec, 1406130812Smarcel "Set seconds to wait for rpc calls to return.\n\ 1407130812SmarcelSet the number of seconds to wait for rpc calls to return.", &setlist), 1408130812Smarcel &showlist); 1409130812Smarcel} 1410