📄 remote-st2000.c
字号:
}/* Read the remote registers into the block REGS. */static voidst2000_fetch_registers (){ int regno; /* Yeah yeah, I know this is horribly inefficient. But it isn't done very often... I'll clean it up later. */ for (regno = 0; regno <= PC_REGNUM; regno++) st2000_fetch_register(regno);}/* Fetch register REGNO, or all registers if REGNO is -1. Returns errno value. */static voidst2000_fetch_register (regno) int regno;{ if (regno == -1) st2000_fetch_registers (); else { char *name = get_reg_name (regno); printf_stdebug ("DR %s\r", name); expect (name, 1); expect (" : ", 1); get_hex_regs (1, regno); expect_prompt (1); } return;}/* Store the remote registers from the contents of the block REGS. */static voidst2000_store_registers (){ int regno; for (regno = 0; regno <= PC_REGNUM; regno++) st2000_store_register(regno); registers_changed ();}/* Store register REGNO, or all if REGNO == 0. Return errno value. */static voidst2000_store_register (regno) int regno;{ if (regno == -1) st2000_store_registers (); else { printf_stdebug ("PR %s %x\r", get_reg_name (regno), read_register (regno)); expect_prompt (1); }}/* Get ready to modify the registers array. On machines which store individual registers, this doesn't need to do anything. On machines which store all the registers in one fell swoop, this makes sure that registers contains all the registers from the program being debugged. */static voidst2000_prepare_to_store (){ /* Do nothing, since we can store individual regs */}static voidst2000_files_info (){ printf ("\tAttached to %s at %d baud.\n", dev_name, baudrate);}/* Copy LEN bytes of data from debugger memory at MYADDR to inferior's memory at MEMADDR. Returns length moved. */static intst2000_write_inferior_memory (memaddr, myaddr, len) CORE_ADDR memaddr; unsigned char *myaddr; int len;{ int i; for (i = 0; i < len; i++) { printf_stdebug ("PM.B %x %x\r", memaddr + i, myaddr[i]); expect_prompt (1); } return len;}/* Read LEN bytes from inferior memory at MEMADDR. Put the result at debugger address MYADDR. Returns length moved. */static intst2000_read_inferior_memory(memaddr, myaddr, len) CORE_ADDR memaddr; char *myaddr; int len;{ int i; /* Number of bytes read so far. */ int count; /* Starting address of this pass. */ unsigned long startaddr; /* Number of bytes to read in this pass. */ int len_this_pass; /* Note that this code works correctly if startaddr is just less than UINT_MAX (well, really CORE_ADDR_MAX if there was such a thing). That is, something like st2000_read_bytes (CORE_ADDR_MAX - 4, foo, 4) works--it never adds len to memaddr and gets 0. */ /* However, something like st2000_read_bytes (CORE_ADDR_MAX - 3, foo, 4) doesn't need to work. Detect it and give up if there's an attempt to do that. */ if (((memaddr - 1) + len) < memaddr) { errno = EIO; return 0; } startaddr = memaddr; count = 0; while (count < len) { len_this_pass = 16; if ((startaddr % 16) != 0) len_this_pass -= startaddr % 16; if (len_this_pass > (len - count)) len_this_pass = (len - count); printf_stdebug ("DI.L %x %x\r", startaddr, len_this_pass); expect (": ", 1); for (i = 0; i < len_this_pass; i++) get_hex_byte (&myaddr[count++]); expect_prompt (1); startaddr += len_this_pass; } return len;}/* FIXME-someday! Merge these two. */static intst2000_xfer_inferior_memory (memaddr, myaddr, len, write, target) CORE_ADDR memaddr; char *myaddr; int len; int write; struct target_ops *target; /* ignored */{ if (write) return st2000_write_inferior_memory (memaddr, myaddr, len); else return st2000_read_inferior_memory (memaddr, myaddr, len);}static voidst2000_kill (args, from_tty) char *args; int from_tty;{ return; /* Ignore attempts to kill target system */}/* Clean up when a program exits. The program actually lives on in the remote processor's RAM, and may be run again without a download. Don't leave it full of breakpoint instructions. */static voidst2000_mourn_inferior (){ remove_breakpoints (); generic_mourn_inferior (); /* Do all the proper things now */}#define MAX_STDEBUG_BREAKPOINTS 16extern int memory_breakpoint_size;static CORE_ADDR breakaddr[MAX_STDEBUG_BREAKPOINTS] = {0};static intst2000_insert_breakpoint (addr, shadow) CORE_ADDR addr; char *shadow;{ int i; for (i = 0; i <= MAX_STDEBUG_BREAKPOINTS; i++) if (breakaddr[i] == 0) { breakaddr[i] = addr; st2000_read_inferior_memory(addr, shadow, memory_breakpoint_size); printf_stdebug("BR %x H\r", addr); expect_prompt(1); return 0; } fprintf(stderr, "Too many breakpoints (> 16) for STDBUG\n"); return 1;}static intst2000_remove_breakpoint (addr, shadow) CORE_ADDR addr; char *shadow;{ int i; for (i = 0; i < MAX_STDEBUG_BREAKPOINTS; i++) if (breakaddr[i] == addr) { breakaddr[i] = 0; printf_stdebug("CB %d\r", i); expect_prompt(1); return 0; } fprintf(stderr, "Can't find breakpoint associated with 0x%x\n", addr); return 1;}/* Put a command string, in args, out to STDBUG. Output from STDBUG is placed on the users terminal until the prompt is seen. */static voidst2000_command (args, fromtty) char *args; int fromtty;{ if (st2000_desc < 0) error("st2000 target not open."); if (!args) error("Missing command."); printf_stdebug("%s\r", args); expect_prompt(0);}/* Connect the user directly to STDBUG. This command acts just like the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */static struct ttystate ttystate;static voidcleanup_tty(){ printf("\r\n[Exiting connect mode]\r\n"); serial_restore(0, &ttystate);}static voidconnect_command (args, fromtty) char *args; int fromtty;{ fd_set readfds; int numfds; int c; char cur_esc = 0; dont_repeat(); if (st2000_desc < 0) error("st2000 target not open."); if (args) fprintf("This command takes no args. They have been ignored.\n"); printf("[Entering connect mode. Use ~. or ~^D to escape]\n"); serial_raw(0, &ttystate); make_cleanup(cleanup_tty, 0); FD_ZERO(&readfds); while (1) { do { FD_SET(0, &readfds); FD_SET(st2000_desc, &readfds); numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0); } while (numfds == 0); if (numfds < 0) perror_with_name("select"); if (FD_ISSET(0, &readfds)) { /* tty input, send to stdebug */ c = getchar(); if (c < 0) perror_with_name("connect"); printf_stdebug("%c", c); switch (cur_esc) { case 0: if (c == '\r') cur_esc = c; break; case '\r': if (c == '~') cur_esc = c; else cur_esc = 0; break; case '~': if (c == '.' || c == '\004') return; else cur_esc = 0; } } if (FD_ISSET(st2000_desc, &readfds)) { while (1) { c = readchar(0); if (c < 0) break; putchar(c); } fflush(stdout); } }}/* Define the target subroutine names */struct target_ops st2000_ops = { "st2000", "Remote serial Tandem ST2000 target", "Use a remote computer running STDEBUG connected by a serial line,\n\or a network connection.\n\Arguments are the name of the device for the serial line,\n\the speed to connect at in bits per second.", st2000_open, st2000_close, 0, st2000_detach, st2000_resume, st2000_wait, st2000_fetch_register, st2000_store_register, st2000_prepare_to_store, st2000_xfer_inferior_memory, st2000_files_info, st2000_insert_breakpoint, st2000_remove_breakpoint, /* Breakpoints */ 0, 0, 0, 0, 0, /* Terminal handling */ st2000_kill, 0, /* load */ 0, /* lookup_symbol */ st2000_create_inferior, st2000_mourn_inferior, 0, /* can_run */ 0, /* notice_signals */ process_stratum, 0, /* next */ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ 0, 0, /* Section pointers */ OPS_MAGIC, /* Always the last thing */};void_initialize_remote_st2000 (){ add_target (&st2000_ops); add_com ("st2000 <command>", class_obscure, st2000_command, "Send a command to the STDBUG monitor."); add_com ("connect", class_obscure, connect_command, "Connect the terminal directly up to the STDBUG command monitor.\n\Use <CR>~. or <CR>~^D to break out.");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -