📄 remote-vx.c
字号:
/* Memory-access and commands for remote VxWorks processes, for GDB. Copyright 1990, 1991, 1992 Free Software Foundation, Inc. Contributed by Wind River Systems and Cygnus Support.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "defs.h"#include "frame.h"#include "inferior.h"#include "wait.h"#include "target.h"#include "gdbcore.h"#include "command.h"#include "symtab.h"#include "symfile.h" /* for struct complaint */#include <string.h>#include <errno.h>#include <signal.h>#include <fcntl.h>#include <sys/types.h>#include <sys/socket.h>#define malloc bogon_malloc /* Sun claims "char *malloc()" not void * */#define free bogon_free /* Sun claims "int free()" not void */#define realloc bogon_realloc /* Sun claims "char *realloc()", not void * */#include <rpc/rpc.h>#undef malloc#undef free#undef realloc#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */#include <netdb.h>#include "vx-share/ptrace.h"#include "vx-share/xdr_ptrace.h"#include "vx-share/xdr_ld.h"#include "vx-share/xdr_rdb.h"#include "vx-share/dbgRpcLib.h"#include "vx-share/reg.h"#include <symtab.h>extern void symbol_file_command ();extern int stop_soon_quietly; /* for wait_for_inferior */static int net_ptrace_clnt_call (); /* Forward decl */static enum clnt_stat net_clnt_call (); /* Forward decl */extern struct target_ops vx_ops, vx_run_ops; /* Forward declaration *//* Saved name of target host and called function for "info files". Both malloc'd. */static char *vx_host;static char *vx_running; /* Called function *//* Nonzero means target that is being debugged remotely has a floating point processor. */static int target_has_fp;/* Default error message when the network is forking up. */static const char rpcerr[] = "network target debugging: rpc error";CLIENT *pClient; /* client used in net debugging */static int ptraceSock = RPC_ANYSOCK;enum clnt_stat net_clnt_call();static void parse_args ();static struct timeval rpcTimeout = { 10, 0 };static char *skip_white_space ();static char *find_white_space (); /* Tell the VxWorks target system to download a file. The load addresses of the text, data, and bss segments are stored in *pTextAddr, *pDataAddr, and *pBssAddr (respectively). Returns 0 for success, -1 for failure. */static intnet_load (filename, pTextAddr, pDataAddr, pBssAddr) char *filename; CORE_ADDR *pTextAddr; CORE_ADDR *pDataAddr; CORE_ADDR *pBssAddr; { enum clnt_stat status; struct ldfile ldstruct; struct timeval load_timeout; bzero ((char *) &ldstruct, sizeof (ldstruct)); /* We invoke clnt_call () here directly, instead of through net_clnt_call (), because we need to set a large timeout value. The load on the target side can take quite a while, easily more than 10 seconds. The user can kill this call by typing CTRL-C if there really is a problem with the load. Do not change the tv_sec value without checking -- select() imposes a limit of 10**8 on it for no good reason that I can see... */ load_timeout.tv_sec = 99999999; /* A large number, effectively inf. */ load_timeout.tv_usec = 0; status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile, &ldstruct, load_timeout); if (status == RPC_SUCCESS) { if (*ldstruct.name == 0) /* load failed on VxWorks side */ return -1; *pTextAddr = ldstruct.txt_addr; *pDataAddr = ldstruct.data_addr; *pBssAddr = ldstruct.bss_addr; return 0; } else return -1; } /* returns 0 if successful, errno if RPC failed or VxWorks complains. */static intnet_break (addr, procnum) int addr; u_long procnum; { enum clnt_stat status; int break_status; Rptrace ptrace_in; /* XXX This is stupid. It doesn't need to be a ptrace structure. How about something smaller? */ bzero ((char *) &ptrace_in, sizeof (ptrace_in)); break_status = 0; ptrace_in.addr = addr; ptrace_in.pid = inferior_pid; status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int, &break_status); if (status != RPC_SUCCESS) return errno; if (break_status == -1) return ENOMEM; return break_status; /* probably (FIXME) zero */ } /* returns 0 if successful, errno otherwise */static intvx_insert_breakpoint (addr) int addr; { return net_break (addr, VX_BREAK_ADD); }/* returns 0 if successful, errno otherwise */static intvx_remove_breakpoint (addr) int addr; { return net_break (addr, VX_BREAK_DELETE); }/* Start an inferior process and sets inferior_pid to its pid. EXEC_FILE is the file to run. ALLARGS is a string containing the arguments to the program. ENV is the environment vector to pass. Returns process id. Errors reported with error(). On VxWorks, we ignore exec_file. */ static voidvx_create_inferior (exec_file, args, env) char *exec_file; char *args; char **env;{ enum clnt_stat status; arg_array passArgs; TASK_START taskStart; bzero ((char *) &passArgs, sizeof (passArgs)); bzero ((char *) &taskStart, sizeof (taskStart)); /* parse arguments, put them in passArgs */ parse_args (args, &passArgs); if (passArgs.arg_array_len == 0) error ("You must specify a function name to run, and arguments if any"); status = net_clnt_call (PROCESS_START, xdr_arg_array, &passArgs, xdr_TASK_START, &taskStart); if ((status != RPC_SUCCESS) || (taskStart.status == -1)) error ("Can't create process on remote target machine"); /* Save the name of the running function */ vx_running = savestring (passArgs.arg_array_val[0], strlen (passArgs.arg_array_val[0]));#ifdef CREATE_INFERIOR_HOOK CREATE_INFERIOR_HOOK (pid);#endif push_target (&vx_run_ops); inferior_pid = taskStart.pid; /* We will get a trace trap after one instruction. Insert breakpoints and continue. */ init_wait_for_inferior (); /* Set up the "saved terminal modes" of the inferior based on what modes we are starting it with. */ target_terminal_init (); /* Install inferior's terminal modes. */ target_terminal_inferior (); stop_soon_quietly = 1; wait_for_inferior (); /* Get the task spawn event */ stop_soon_quietly = 0; /* insert_step_breakpoint (); FIXME, do we need this? */ proceed(-1, -1, 0);}/* Fill ARGSTRUCT in argc/argv form with the arguments from the argument string ARGSTRING. */static voidparse_args (arg_string, arg_struct) register char *arg_string; arg_array *arg_struct;{ register int arg_count = 0; /* number of arguments */ register int arg_index = 0; register char *p0; bzero ((char *) arg_struct, sizeof (arg_array)); /* first count how many arguments there are */ p0 = arg_string; while (*p0 != '\0') { if (*(p0 = skip_white_space (p0)) == '\0') break; p0 = find_white_space (p0); arg_count++; } arg_struct->arg_array_len = arg_count; arg_struct->arg_array_val = (char **) xmalloc ((arg_count + 1) * sizeof (char *)); /* now copy argument strings into arg_struct. */ while (*(arg_string = skip_white_space (arg_string))) { p0 = find_white_space (arg_string); arg_struct->arg_array_val[arg_index++] = savestring (arg_string, p0 - arg_string); arg_string = p0; } arg_struct->arg_array_val[arg_count] = NULL;}/* Advance a string pointer across whitespace and return a pointer to the first non-white character. */static char *skip_white_space (p) register char *p;{ while (*p == ' ' || *p == '\t') p++; return p;} /* Search for the first unquoted whitespace character in a string. Returns a pointer to the character, or to the null terminator if no whitespace is found. */static char *find_white_space (p) register char *p;{ register int c; while ((c = *p) != ' ' && c != '\t' && c) { if (c == '\'' || c == '"') { while (*++p != c && *p) { if (*p == '\\') p++; } if (!*p) break; } p++; } return p;} /* Poll the VxWorks target system for an event related to the debugged task. Returns -1 if remote wait failed, task status otherwise. */static intnet_wait (pEvent) RDB_EVENT *pEvent;{ int pid; enum clnt_stat status; bzero ((char *) pEvent, sizeof (RDB_EVENT)); pid = inferior_pid; status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT, pEvent); return (status == RPC_SUCCESS)? pEvent->status: -1;} /* Suspend the remote task. Returns -1 if suspend fails on target system, 0 otherwise. */static intnet_quit (){ int pid; int quit_status; enum clnt_stat status; quit_status = 0; /* don't let rdbTask suspend itself by passing a pid of 0 */ if ((pid = inferior_pid) == 0) return -1; status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int, &quit_status); return (status == RPC_SUCCESS)? quit_status: -1;}/* Read a register or registers from the remote system. */static voidvx_read_register (regno) int regno;{ int status; Rptrace ptrace_in; Ptrace_return ptrace_out; C_bytes in_data; C_bytes out_data; extern char registers[]; bzero ((char *) &ptrace_in, sizeof (ptrace_in)); bzero ((char *) &ptrace_out, sizeof (ptrace_out)); /* FIXME, eventually only get the ones we need. */ registers_fetched (); ptrace_in.pid = inferior_pid; ptrace_out.info.more_data = (caddr_t) &out_data;#ifndef I80960 out_data.len = 18 * REGISTER_RAW_SIZE (0); /* FIXME 68k hack */#else out_data.len = (16 + 16 + 3) * REGISTER_RAW_SIZE (0);#endif out_data.bytes = (caddr_t) registers; status = net_ptrace_clnt_call (PTRACE_GETREGS, &ptrace_in, &ptrace_out); if (status) error (rpcerr); if (ptrace_out.status == -1) { errno = ptrace_out.errno; perror_with_name ("net_ptrace_clnt_call(PTRACE_GETREGS)"); } #ifdef I80960 { /* If the target has floating point registers, fetch them. Otherwise, zero the floating point register values in registers[] for good measure, even though we might not need to. */ /* @@ Can't use this -- the rdb library for the 960 target doesn't support setting or retrieving FP regs. KR */#if 0 struct fp_status inferior_fp_registers; if (target_has_fp) { ptrace_in.pid = inferior_pid; ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers; status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out); if (status) error (rpcerr); if (ptrace_out.status == -1) { errno = ptrace_out.errno; perror_with_name ("net_ptrace_clnt_call(PTRACE_GETFPREGS)"); } bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)], REGISTER_RAW_SIZE (FP0_REGNUM) * 4); } else { bzero ((char *) ®isters[REGISTER_BYTE (FP0_REGNUM)], REGISTER_RAW_SIZE (FP0_REGNUM) * 4); }#endif }#else /* not 960, thus must be 68000: FIXME! */ if (target_has_fp) { ptrace_in.pid = inferior_pid; ptrace_out.info.more_data = (caddr_t) &out_data; out_data.len = 8 * REGISTER_RAW_SIZE (FP0_REGNUM) /* FIXME */ + (3 * sizeof (REGISTER_TYPE)); out_data.bytes = (caddr_t) ®isters[REGISTER_BYTE (FP0_REGNUM)]; status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out); if (status) error (rpcerr); if (ptrace_out.status == -1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -