📄 gdb_interface.c
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees * of Leland Stanford Junior University. * * This file is part of the SimOS distribution. * See LICENSE file for terms of the license. * *//***************************************************************** * Interface to GDB. For debugging OS or Apps ontop of simulator. *****************************************************************/#ifndef _LONGLONG#define _LONGLONG#endif#define R4000 1#include <sys/types.h>#include <sys/file.h>#include <unistd.h>#include <sys/socket.h>#include <memory.h>#include <sys/mman.h>#include <sys/signal.h>#include <sys/time.h>#include <netinet/in.h>#include <netinet/tcp.h>#include <string.h>#include "simutil.h"#include <setjmp.h>#include "sim.h"#include "simtypes.h"#include "syslimits.h"#include "arch_specifics.h"#include "machine_params.h"#include "cpu_interface.h"#include "sim_error.h"#include "gdb_interface.h"static int sfd; /* Open socket for connection */static int rfd = -1; /* Open fd for connection */static int debug_from_poll = 0; /* we entered the debugger because the * poll on the socket showed something */static int remote_debug = 0;static int AttachGdb(int sfd, int fdactive);static int read_cpu(char* buf);static int fromhex(int);static int tohex(int);static int putpkt(int fd, char *buf);static int readchar(int fd);static int getpkt(int fd, char *buf);static void write_ok(char *buf);static void write_enn(char *buf);static void convert_int_to_ascii(char *from, char *to, int n);static void convert_ascii_to_int(char *from, char *to, int n);static int read_memory(char* buf, VA memaddr, unsigned int len, uint cpuno);static int write_memory(char* buf, VA memaddr, unsigned int len, uint cpuno);static char* findchar(char* s, int c);static void prepare_resume_reply(char *buf, unsigned int sig, unsigned int cpuno);int DebugPort; /* default value */#ifdef __alpha#define MEMORY_SCANF "%x,%lx,%x"#else#define MEMORY_SCANF "%x,%llx,%x"#endif/***************************************************************** * Simdebug_init * * Initialize the debugger c module. *****************************************************************/voidSimdebug_init(void){ struct sockaddr_in sockaddr; int tmp; if (!DebugPort) { return; } sfd = socket (PF_INET, SOCK_STREAM, 0); if (sfd < 0) { CPUWarning("Can't open debug socket"); ASSERT(0); return; } /* Allow rapid reuse of this port. */ tmp = 1; if (setsockopt (sfd, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp, sizeof(tmp)) < 0) { CPUWarning("simdebug setsockopt SO_REUSEADDR"); /* Not fatal */ } bzero((char *)&sockaddr, sizeof(struct sockaddr_in)); sockaddr.sin_family = PF_INET; sockaddr.sin_port = htons(DebugPort); sockaddr.sin_addr.s_addr = INADDR_ANY; while (bind (sfd, (struct sockaddr *)&sockaddr, sizeof (sockaddr)) || listen (sfd, 1)) { DebugPort++; sockaddr.sin_port = htons(DebugPort); }}/**************************************************************** * AttachGdb * ****************************************************************/static intAttachGdb(int fd, int fdactive){ struct sockaddr_in sockaddr; int tmp; int gdb_fd; if (!fdactive) CPUWarning("\nEnter debugger, port = %d, waiting...\n ", DebugPort); tmp = sizeof (sockaddr); gdb_fd = accept (fd, (struct sockaddr *)&sockaddr, &tmp); if (gdb_fd == -1) { CPUWarning("Debugger accept failed\n"); return gdb_fd; } if (!fdactive) CPUWarning("attached\n"); /* Tell TCP not to delay small packets. This greatly speeds up interactive response. */ tmp = 1; setsockopt (gdb_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof(tmp)); return gdb_fd;}/***************************************************************** * Simdebug_pollfd and Simdebug_fdactive * * someone needs to poll the gdb connection if it is open in case * the user types ^C. This is currently piggy-backed onto the * select polling done by the Visual control subsystem * (see visual.c::VisualControl). * * when the gdb connection is closed, we poll the listener fd (sfd) * so a gdb attach request causes us to enter the debugger immediately. * *****************************************************************/int Simdebug_pollfd(void){ if (rfd != -1) { return rfd; } else { return sfd; }}void Simdebug_fdactive(void){ /* gdb sent us something. This won't get called in the * middle of Simdebug_run because the debug run loop owns * the system during that time, so the visual callback won't * happen. * * That's good, because on embra this passes through a few * functions and calls right into simdebug_run. */ if (remote_debug) { CPUWarning("Simdebug_fdactive: poll saw data on debugger port\n"); } debug_from_poll = 1; CPUVec.Handle_Debug_Signal(-1, 0); /* -1 => any cpu, 0 => this * is a direct debug request, * not a signal that should * fire the sigusr annotation */}static int CanSingleStep(CPUType cpuType){#if defined(SIM_MIPS32) || defined(SIM_MIPS64) return (cpuType == MIPSY);#elif defined(SIM_X86) return (cpuType == X86SIM);#else return 0;#endif}/***************************************************************** * Simdebug_run * * Main call to handle the simulator side of a gdb session. *****************************************************************/Simdebug_resultSimdebug_run(int sig, int start_cpuno){ char *b; static char cmd_buf[BUFSIZ+1]; int i = 0; Simdebug_result ret = SD_CONTINUE; int pid; unsigned int cpuno = 0; /* current cpu number */ if (remote_debug) { CPUWarning("Simdebug_run: sig %d, start_cpuno %d\n", sig, start_cpuno); } if (rfd <= 0) { /* establishing a new connection. GDB does not expect to see * a reason-for-stop packet 'S' in this initial setup transaction. */ rfd = AttachGdb(sfd, debug_from_poll); if (rfd < 0) { return SD_CONTINUE; /* could not get debugger */ } debug_from_poll = 0; /* whether or not we entered from poll doesn't * matter this time, but we'd better reset it * before next time this function runs */ } else { /* reestablish an old connection. We might get here either * for internal reasons (hitting a breakpoint) or for external * reasons (gdb sent us a ^C). If external, we need to swallow * the break packet. Then in either case, let GDB know why * we stopped. */ if (debug_from_poll) { debug_from_poll = 0; if (getpkt (rfd, cmd_buf) < 0) goto errout; /* the only thing we expect to see when polling is the * break instruction */ if (cmd_buf[0] != 'b') { CPUWarning("Simdebug_run: unexpected command from gdb, expected ^C\n"); } /* make gdb happy: it sent a ^C so it should get one back */ sig = SIGINT; } /* Inform the remote debugger we have entered debugging mode. */ sprintf (cmd_buf, "S%02x%02x", sig, start_cpuno); if (putpkt (rfd, cmd_buf) < 0) goto errout; } while (1) { char ch; i = 0; if (getpkt (rfd, cmd_buf) < 0) goto errout; if (remote_debug) { CPUWarning( "GETPKT: %s\n", cmd_buf); } ch = cmd_buf[i++]; SIM_DEBUG(('g', "gdb command %c \n",ch)); switch (ch) { case '?': prepare_resume_reply (cmd_buf, sig, start_cpuno); break; case 'b': /* nop: this is the packet sent when the user types ^C. No * effect during main loop */ write_enn (cmd_buf); break; case 'g': { int i; cpuno = read_cpu(cmd_buf+1); if (cpuno >= TOTAL_CPUS) { write_enn (cmd_buf); } else { Reg r=0; b = cmd_buf; for (i = 0; i < GDB_NUM_REGS; i++) { if (CPUVec.GetRegister(cpuno, i, &r) == FAILURE) { r = 0; } /* * flip the bytes around */#if defined(SIM_ALPHA) || defined(SIM_MIPS64) /* * bugnion: * 64 bit support * actually, the ifdef should be based on which remote gdb we * are talking to. Maybe a good thing to have an exchange protocol * at startup to make sure that gdb is not going to be confused */ r = HO2MO_8(r); convert_int_to_ascii ((char *) &r, b, 4*2); b += 8*2;#else r = HO2MO_4((int)r); convert_int_to_ascii ((char *) &r, b, 4); b += 8;#endif } *b = 0; } break; } case 'G': { cpuno = read_cpu(cmd_buf+1); if (cpuno >= TOTAL_CPUS) { write_enn (cmd_buf); } else { int succeeded = 1; b = cmd_buf + 3; for (i = 0; i < GDB_NUM_REGS; i++) { unsigned int reg = 0;#if defined(SIM_ALPHA) || defined(SIM_MIPS64) convert_ascii_to_int (b, (char *) ®, 4*2); reg = MO2HO_8(reg); if (CPUVec.PutRegister(cpuno, i, reg) == FAILURE) { } b += 8*2;#else convert_ascii_to_int (b, (char *) ®, 4); reg = MO2HO_4(reg); if (CPUVec.PutRegister(cpuno, i, (Reg)(Reg32_s)reg) == FAILURE) { } b += 8;#endif } if (succeeded) { write_ok (cmd_buf); } else { write_enn (cmd_buf); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -