📄 remote-vx.c
字号:
vx_wait (status) int *status;{ register int pid; WAITTYPE w; RDB_EVENT rdbEvent; int quit_failed; do { /* If CTRL-C is hit during this loop, suspend the inferior process. */ quit_failed = 0; if (quit_flag) { quit_failed = (net_quit () == -1); quit_flag = 0; } /* If a net_quit () or net_wait () call has failed, allow the user to break the connection with the target. We can't simply error () out of this loop, since the data structures representing the state of the inferior are in an inconsistent state. */ if (quit_failed || net_wait (&rdbEvent) == -1) { terminal_ours (); if (query ("Can't %s. Disconnect from target system? ", (quit_failed) ? "suspend remote task" : "get status of remote task")) { target_mourn_inferior(); error ("Use the \"target\" command to reconnect."); } else { terminal_inferior (); continue; } } pid = rdbEvent.taskId; if (pid == 0) { sleep_ms (200); /* FIXME Don't kill the network too badly */ } else if (pid != inferior_pid) fatal ("Bad pid for debugged task: %s\n", local_hex_string(pid)); } while (pid == 0); /* FIXME, eventually do more then SIGTRAP on everything... */ switch (rdbEvent.eventType) { case EVENT_EXIT: WSETEXIT (w, 0); /* FIXME is it possible to distinguish between a XXX normal vs abnormal exit in VxWorks? */ break; case EVENT_START: /* Task was just started. */ WSETSTOP (w, SIGTRAP); break; case EVENT_STOP: WSETSTOP (w, SIGTRAP); /* XXX was it stopped by a signal? act accordingly */ break; case EVENT_BREAK: /* Breakpoint was hit. */ WSETSTOP (w, SIGTRAP); break; case EVENT_SUSPEND: /* Task was suspended, probably by ^C. */ WSETSTOP (w, SIGINT); break; case EVENT_BUS_ERR: /* Task made evil nasty reference. */ WSETSTOP (w, SIGBUS); break; case EVENT_ZERO_DIV: /* Division by zero */ WSETSTOP (w, SIGFPE); /* Like Unix, call it a float exception. */ break; case EVENT_SIGNAL: /* The target is not running Unix, and its faults/traces do not map nicely into Unix signals. Make sure they do not get confused with Unix signals by numbering them with values higher than the highest legal Unix signal. code in the arch-dependent PRINT_RANDOM_SIGNAL routine will interpret the value for wait_for_inferior. */ WSETSTOP (w, rdbEvent.sigType + NSIG); break; } /* switch */ *status = *(int *)&w; /* Grumble union wait crap Grumble */ return pid;}static intsymbol_stub (arg) char *arg;{ symbol_file_command (arg, 0); return 1;}static intadd_symbol_stub (arg) char *arg;{ struct ldfile *pLoadFile = (struct ldfile *)arg; printf("\t%s: ", pLoadFile->name); symbol_file_add (pLoadFile->name, 0, pLoadFile->txt_addr, 0, 0, 0); printf ("ok\n"); return 1;}/* Target command for VxWorks target systems. Used in vxgdb. Takes the name of a remote target machine running vxWorks and connects to it to initialize remote network debugging. */static voidvx_open (args, from_tty) char *args; int from_tty;{ extern int close (); char *bootFile; extern char *source_path; struct ldtabl loadTable; struct ldfile *pLoadFile; int i; extern CLIENT *pClient; if (!args) error_no_arg ("target machine name"); target_preopen (from_tty); unpush_target (&vx_ops); printf ("Attaching remote machine across net...\n"); fflush (stdout); /* Allow the user to kill the connect attempt by typing ^C. Wait until the call to target_has_fp () completes before disallowing an immediate quit, since even if net_connect () is successful, the remote debug server might be hung. */ immediate_quit++; net_connect (args); target_has_fp = net_check_for_fp (); printf_filtered ("Connected to %s.\n", args); immediate_quit--; push_target (&vx_ops); /* Save a copy of the target host's name. */ vx_host = savestring (args, strlen (args)); /* Find out the name of the file from which the target was booted and load its symbol table. */ printf_filtered ("Looking in Unix path for all loaded modules:\n"); bootFile = NULL; if (!net_get_boot_file (&bootFile)) { if (*bootFile) { printf_filtered ("\t%s: ", bootFile); if (catch_errors (symbol_stub, bootFile, "Error while reading symbols from boot file:\n")) puts_filtered ("ok\n"); } else if (from_tty) printf ("VxWorks kernel symbols not loaded.\n"); } else error ("Can't retrieve boot file name from target machine."); clnt_freeres (pClient, xdr_wrapstring, &bootFile); if (net_get_symbols (&loadTable) != 0) error ("Can't read loaded modules from target machine"); i = 0-1; while (++i < loadTable.tbl_size) { QUIT; /* FIXME, avoids clnt_freeres below: mem leak */ pLoadFile = &loadTable.tbl_ent [i];#ifdef WRS_ORIG { register int desc; struct cleanup *old_chain; char *fullname = NULL; desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname); if (desc < 0) perror_with_name (pLoadFile->name); old_chain = make_cleanup (close, desc); add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr, pLoadFile->bss_addr); do_cleanups (old_chain); }#else /* Botches, FIXME: (1) Searches the PATH, not the source path. (2) data and bss are assumed to be at the usual offsets from text. */ catch_errors (add_symbol_stub, (char *)pLoadFile, (char *)0);#endif } printf_filtered ("Done.\n"); clnt_freeres (pClient, xdr_ldtabl, &loadTable);}/* Takes a task started up outside of gdb and ``attaches'' to it. This stops it cold in its tracks and allows us to start tracing it. */static voidvx_attach (args, from_tty) char *args; int from_tty;{ int pid; char *cptr = 0; Rptrace ptrace_in; Ptrace_return ptrace_out; int status; if (!args) error_no_arg ("process-id to attach"); pid = strtol (args, &cptr, 0); if ((cptr == args) || (*cptr != '\0')) error ("Invalid process-id -- give a single number in decimal or 0xhex"); if (from_tty) printf ("Attaching pid %s.\n", local_hex_string(pid)); bzero ((char *)&ptrace_in, sizeof (ptrace_in)); bzero ((char *)&ptrace_out, sizeof (ptrace_out)); ptrace_in.pid = pid; status = net_ptrace_clnt_call (PTRACE_ATTACH, &ptrace_in, &ptrace_out); if (status == -1) error (rpcerr); if (ptrace_out.status == -1) { errno = ptrace_out.errno; perror_with_name ("Attaching remote process"); } /* It worked... */ push_target (&vx_run_ops); inferior_pid = pid; vx_running = 0;}/* detach_command -- takes a program previously attached to and detaches it. The program resumes execution and will no longer stop on signals, etc. We better not have left any breakpoints in the program or it'll die when it hits one. For this to work, it may be necessary for the process to have been previously attached. It *might* work if the program was started via the normal ptrace (PTRACE_TRACEME). */static voidvx_detach (args, from_tty) char *args; int from_tty;{ Rptrace ptrace_in; Ptrace_return ptrace_out; int signal = 0; int status; if (args) error ("Argument given to VxWorks \"detach\"."); if (from_tty) printf ("Detaching pid %s.\n", local_hex_string(inferior_pid)); if (args) /* FIXME, should be possible to leave suspended */ signal = atoi (args); bzero ((char *)&ptrace_in, sizeof (ptrace_in)); bzero ((char *)&ptrace_out, sizeof (ptrace_out)); ptrace_in.pid = inferior_pid; status = net_ptrace_clnt_call (PTRACE_DETACH, &ptrace_in, &ptrace_out); if (status == -1) error (rpcerr); if (ptrace_out.status == -1) { errno = ptrace_out.errno; perror_with_name ("Detaching VxWorks process"); } inferior_pid = 0; pop_target (); /* go back to non-executing VxWorks connection */}/* vx_kill -- takes a running task and wipes it out. */static voidvx_kill (){ Rptrace ptrace_in; Ptrace_return ptrace_out; int status; printf ("Killing pid %s.\n", local_hex_string(inferior_pid)); bzero ((char *)&ptrace_in, sizeof (ptrace_in)); bzero ((char *)&ptrace_out, sizeof (ptrace_out)); ptrace_in.pid = inferior_pid; status = net_ptrace_clnt_call (PTRACE_KILL, &ptrace_in, &ptrace_out); if (status == -1) error (rpcerr); if (ptrace_out.status == -1) { errno = ptrace_out.errno; perror_with_name ("Killing VxWorks process"); } /* If it gives good status, the process is *gone*, no events remain. */ inferior_pid = 0; pop_target (); /* go back to non-executing VxWorks connection */}/* Clean up from the VxWorks process target as it goes away. */static voidvx_proc_close (quitting) int quitting;{ inferior_pid = 0; /* No longer have a process. */ if (vx_running) free (vx_running); vx_running = 0;}/* Make an RPC call to the VxWorks target. Returns RPC status. */static enum clnt_statnet_clnt_call (procNum, inProc, in, outProc, out) enum ptracereq procNum; xdrproc_t inProc; char *in; xdrproc_t outProc; char *out;{ enum clnt_stat status; status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout); if (status != RPC_SUCCESS) clnt_perrno (status); return status;}/* Clean up before losing control. */static voidvx_close (quitting) int quitting;{ if (pClient) clnt_destroy (pClient); /* The net connection */ pClient = 0; if (vx_host) free (vx_host); /* The hostname */ vx_host = 0;}/* A vxprocess target should be started via "run" not "target". *//*ARGSUSED*/static voidvx_proc_open (name, from_tty) char *name; int from_tty;{ error ("Use the \"run\" command to start a VxWorks process.");}/* Target ops structure for accessing memory and such over the net */struct target_ops vx_ops = { "vxworks", "VxWorks target memory via RPC over TCP/IP", "Use VxWorks target memory. \n\Specify the name of the machine to connect to.", vx_open, vx_close, vx_attach, 0, /* vx_detach, */ 0, 0, /* resume, wait */ 0, 0, /* read_reg, write_reg */ 0, /* prep_to_store, */ vx_xfer_memory, vx_files_info, 0, 0, /* insert_breakpoint, remove_breakpoint */ 0, 0, 0, 0, 0, /* terminal stuff */ 0, /* vx_kill, */ vx_load_command, vx_lookup_symbol, vx_create_inferior, 0, /* mourn_inferior */ 0, /* can_run */ 0, /* notice_signals */ core_stratum, 0, /* next */ 1, 1, 0, 0, 0, /* all mem, mem, stack, regs, exec */ 0, 0, /* Section pointers */ OPS_MAGIC, /* Always the last thing */};/* Target ops structure for accessing VxWorks child processes over the net */struct target_ops vx_run_ops = { "vxprocess", "VxWorks process", "VxWorks process, started by the \"run\" command.", vx_proc_open, vx_proc_close, 0, vx_detach, /* vx_attach */ vx_resume, vx_wait, vx_read_register, vx_write_register, vx_prepare_to_store, vx_xfer_memory, vx_run_files_info, vx_insert_breakpoint, vx_remove_breakpoint, 0, 0, 0, 0, 0, /* terminal stuff */ vx_kill, vx_load_command, vx_lookup_symbol, 0, vx_mourn_inferior, 0, /* can_run */ 0, /* notice_signals */ process_stratum, 0, /* next */ 0, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ /* all_mem is off to avoid spurious msg in "i files" */ 0, 0, /* Section pointers */ OPS_MAGIC, /* Always the last thing */};/* ==> Remember when reading at end of file, there are two "ops" structs here. */void_initialize_vx (){ add_target (&vx_ops); add_target (&vx_run_ops);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -