📄 gdbserve.c
字号:
if (remote_debug) { ConsolePrintf ("vector=%d: %s, pc=%08x, thread=%08x\r\n", frame->ExceptionNumber, frame->ExceptionDescription, frame->ExceptionPC, GetThreadID ()); } switch (frame->ExceptionNumber) { case START_NLM_EVENT: /* If the NLM just started, we record the module load information and the thread ID, and set a breakpoint at the first instruction in the program. */ ldinfo = ((struct DBG_LoadDefinitionStructure *) frame->ExceptionErrorCode); memcpy (first_insn, ldinfo->LDInitializationProcedure, BREAKPOINT_SIZE); memcpy (ldinfo->LDInitializationProcedure, breakpoint_insn, BREAKPOINT_SIZE); flush_i_cache (); return RETURN_TO_PROGRAM; case ENTER_DEBUGGER_EVENT: case KEYBOARD_BREAK_EVENT: /* Pass some events on to the next debugger, in case it will handle them. */ return RETURN_TO_NEXT_DEBUGGER; case 3: /* Breakpoint */ /* After we've reached the initial breakpoint, reset it. */ if (frame->ExceptionPC - DECR_PC_AFTER_BREAK == (LONG) ldinfo->LDInitializationProcedure && memcmp (ldinfo->LDInitializationProcedure, breakpoint_insn, BREAKPOINT_SIZE) == 0) { memcpy (ldinfo->LDInitializationProcedure, first_insn, BREAKPOINT_SIZE); frame->ExceptionPC -= DECR_PC_AFTER_BREAK; flush_i_cache (); } /* Normal breakpoints end up here */ do_status (remcomOutBuffer, frame); break; default: /* At the moment, we don't care about most of the unusual NetWare exceptions. */ if (frame->ExceptionNumber > 31) return RETURN_TO_PROGRAM; /* Most machine level exceptions end up here */ do_status (remcomOutBuffer, frame); break; case 11: /* Segment not present */ case 13: /* General protection */ case 14: /* Page fault */ /* If we get a GP fault, and mem_may_fault is set, and the instruction pointer is near set_char or get_char, then we caused the fault ourselves accessing an illegal memory location. */ if (mem_may_fault && ((frame->ExceptionPC >= (long) &set_char && frame->ExceptionPC < (long) &set_char + 50) || (frame->ExceptionPC >= (long) &get_char && frame->ExceptionPC < (long) &get_char + 50))) { mem_err = 1; /* Point the instruction pointer at an assembly language stub which just returns from the function. */ frame->ExceptionPC += 4; /* Skip the load or store */ /* Keep going. This will act as though it returned from set_char or get_char. The calling routine will check mem_err, and do the right thing. */ return RETURN_TO_PROGRAM; } /* Random mem fault, report it */ do_status (remcomOutBuffer, frame); break; case TERMINATE_NLM_EVENT: /* There is no way to get the exit status. */ sprintf (remcomOutBuffer, "W%02x", 0); break; /* We generate our own status */ } /* FIXME: How do we know that this exception has anything to do with the program we are debugging? We can check whether the PC is in the range of the module we are debugging, but that doesn't help much since an error could occur in a library routine. */ clear_step_traps (frame); if (! putpacket(remcomOutBuffer)) return RETURN_TO_NEXT_DEBUGGER; if (frame->ExceptionNumber == TERMINATE_NLM_EVENT) { ResumeThread (mainthread); return RETURN_TO_PROGRAM; } while (1) { error = 0; remcomOutBuffer[0] = 0; if (! getpacket (remcomInBuffer)) return RETURN_TO_NEXT_DEBUGGER; switch (remcomInBuffer[0]) { case '?': do_status (remcomOutBuffer, frame); break; case 'd': remote_debug = !(remote_debug); /* toggle debug flag */ break; case 'g': /* return the value of the CPU registers */ frame_to_registers (frame, remcomOutBuffer); break; case 'G': /* set the value of the CPU registers - return OK */ registers_to_frame (&remcomInBuffer[1], frame); strcpy(remcomOutBuffer,"OK"); break; case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ ptr = &remcomInBuffer[1]; if (hexToInt(&ptr,&addr)) if (*(ptr++) == ',') if (hexToInt(&ptr,&length)) { ptr = 0; mem_err = 0; mem2hex((char*) addr, remcomOutBuffer, length, 1); if (mem_err) { strcpy (remcomOutBuffer, "E03"); debug_error ("memory fault"); } } if (ptr) { strcpy(remcomOutBuffer,"E01"); debug_error("malformed read memory command: %s",remcomInBuffer); } break; case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ ptr = &remcomInBuffer[1]; if (hexToInt(&ptr,&addr)) if (*(ptr++) == ',') if (hexToInt(&ptr,&length)) if (*(ptr++) == ':') { mem_err = 0; hex2mem(ptr, (char*) addr, length, 1); if (mem_err) { strcpy (remcomOutBuffer, "E03"); debug_error ("memory fault"); } else { strcpy(remcomOutBuffer,"OK"); } ptr = 0; } if (ptr) { strcpy(remcomOutBuffer,"E02"); debug_error("malformed write memory command: %s",remcomInBuffer); } break; case 'c': case 's': /* cAA..AA Continue at address AA..AA(optional) */ /* sAA..AA Step one instruction from AA..AA(optional) */ /* try to read optional parameter, pc unchanged if no parm */ ptr = &remcomInBuffer[1]; if (hexToInt(&ptr,&addr)) {/* registers[PC_REGNUM].lo = addr;*/ fprintf (stderr, "Setting PC to 0x%x\n", addr); while (1); } if (remcomInBuffer[0] == 's') set_step_traps (frame); flush_i_cache (); return RETURN_TO_PROGRAM; case 'k': /* kill the program */ KillMe (ldinfo); ResumeThread (mainthread); return RETURN_TO_PROGRAM; case 'q': /* Query message */ if (strcmp (&remcomInBuffer[1], "Offsets") == 0) { sprintf (remcomOutBuffer, "Text=%x;Data=%x;Bss=%x", ldinfo->LDCodeImageOffset, ldinfo->LDDataImageOffset, ldinfo->LDDataImageOffset + ldinfo->LDDataImageLength); } else sprintf (remcomOutBuffer, "E04, Unknown query %s", &remcomInBuffer[1]); break; } /* reply to the request */ if (! putpacket(remcomOutBuffer)) return RETURN_TO_NEXT_DEBUGGER; }}char *progname;struct bitRate { BYTE bitRate; const char *bitRateString;};struct bitRate bitRateTable[] = { { AIO_BAUD_50 , "50" }, { AIO_BAUD_75 , "75" }, { AIO_BAUD_110 , "110" }, { AIO_BAUD_134p5 , "134.5" }, { AIO_BAUD_150 , "150" }, { AIO_BAUD_300 , "300" }, { AIO_BAUD_600 , "600" }, { AIO_BAUD_1200 , "1200" }, { AIO_BAUD_1800 , "1800" }, { AIO_BAUD_2000 , "2000" }, { AIO_BAUD_2400 , "2400" }, { AIO_BAUD_3600 , "3600" }, { AIO_BAUD_4800 , "4800" }, { AIO_BAUD_7200 , "7200" }, { AIO_BAUD_9600 , "9600" }, { AIO_BAUD_19200 , "19200" }, { AIO_BAUD_38400 , "38400" }, { AIO_BAUD_57600 , "57600" }, { AIO_BAUD_115200, "115200" }, { -1, NULL }};char dataBitsTable[] = "5678";char *stopBitsTable[] = { "1", "1.5", "2" };char parity[] = "NOEMS";/* Start up. The main thread opens the named serial I/O port, loads the named NLM module and then goes to sleep. The serial I/O port is named as a board number and a port number. It would be more DOS like to provide a menu of available serial ports, but I don't want to have to figure out how to do that. */intmain (int argc, char **argv){ int hardware, board, port; BYTE bitRate; BYTE dataBits; BYTE stopBits; BYTE parityMode; LONG err; struct debuggerStructure s; int cmdindx; char *cmdlin; int i; /* set progname */ progname = "gdbserve"; /* set default serial line */ hardware = -1; board = 0; port = 0; /* set default serial line characteristics */ bitRate = AIO_BAUD_9600; dataBits = AIO_DATA_BITS_8; stopBits = AIO_STOP_BITS_1; parityMode = AIO_PARITY_NONE; cmdindx = 0; for (argc--, argv++; *argv; argc--, argv++) { char *bp; char *ep; if (strnicmp(*argv, "BAUD=", 5) == 0) { struct bitRate *brp; bp = *argv + 5; for (brp = bitRateTable; brp->bitRate != (BYTE) -1; brp++) { if (strcmp(brp->bitRateString, bp) == 0) { bitRate = brp->bitRate; break; } } if (brp->bitRateString == NULL) { fprintf(stderr, "%s: %s: unknown or unsupported bit rate", progname, bp); exit (1); } } else if (strnicmp(*argv, "BOARD=", 6) == 0) { bp = *argv + 6; board = strtol (bp, &ep, 0); if (ep == bp || *ep != '\0') { fprintf (stderr, "%s: %s: expected integer argument\n", progname, bp); exit(1); } }#if 1 /* FIXME: this option has been depricated */ else if (strnicmp(*argv, "NODE=", 5) == 0) { bp = *argv + 5; board = strtol (bp, &ep, 0); if (ep == bp || *ep != '\0') { fprintf (stderr, "%s: %s: expected integer argument\n", progname, bp); exit(1); } }#endif else if (strnicmp(*argv, "PORT=", 5) == 0) { bp = *argv + 5; port = strtol (bp, &ep, 0); if (ep == bp || *ep != '\0') { fprintf (stderr, "%s: %s: expected integer argument\n", progname, bp); exit(1); } } else { break; } cmdindx++; } if (argc == 0) { fprintf (stderr, "Usage: load %s [options] program [arguments]\n", progname); exit (1); } err = AIOAcquirePort (&hardware, &board, &port, &AIOhandle); if (err != AIO_SUCCESS) { switch (err) { case AIO_PORT_NOT_AVAILABLE: fprintf (stderr, "Port not available\n"); break; case AIO_BOARD_NUMBER_INVALID: case AIO_PORT_NUMBER_INVALID: fprintf (stderr, "No such port\n"); break; default: fprintf (stderr, "Could not open port: %d\n", err); break; } exit (1); } err = AIOConfigurePort (AIOhandle, bitRate, dataBits, stopBits, parityMode, AIO_HARDWARE_FLOW_CONTROL_OFF); if (err == AIO_QUALIFIED_SUCCESS) { AIOPORTCONFIG portConfig; fprintf (stderr, "Port configuration changed!\n"); portConfig.returnLength = sizeof(portConfig); AIOGetPortConfiguration (AIOhandle, &portConfig, NULL); fprintf (stderr, " Bit Rate: %s, Data Bits: %c, Stop Bits: %s, Parity: %c,\ Flow:%s\n", bitRateTable[portConfig.bitRate].bitRateString, dataBitsTable[portConfig.dataBits], stopBitsTable[portConfig.stopBits], parity[portConfig.parityMode], portConfig.flowCtrlMode ? "ON" : "OFF"); } else if (err != AIO_SUCCESS) { fprintf (stderr, "Could not configure port: %d\n", err); AIOReleasePort (AIOhandle); exit (1); } if (AIOSetExternalControl(AIOhandle, AIO_EXTERNAL_CONTROL, (AIO_EXTCTRL_DTR | AIO_EXTCTRL_RTS)) != AIO_SUCCESS) { LONG extStatus, chgdExtStatus; fprintf (stderr, "Could not set desired port controls!\n"); AIOGetExternalStatus (AIOhandle, &extStatus, &chgdExtStatus); fprintf (stderr, "Port controls now: %d, %d\n", extStatus, chgdExtStatus); } /* Register ourselves as an alternate debugger. */ memset (&s, 0, sizeof s); s.DDSResourceTag = ((struct ResourceTagStructure *) AllocateResourceTag (GetNLMHandle (), (BYTE *)"gdbserver", DebuggerSignature)); if (s.DDSResourceTag == 0) { fprintf (stderr, "AllocateResourceTag failed\n"); AIOReleasePort (AIOhandle); exit (1); } s.DDSdebuggerEntry = handle_exception; s.DDSFlags = TSS_FRAME_BIT; err = RegisterDebuggerRTag (&s, AT_FIRST); if (err != 0) { fprintf (stderr, "RegisterDebuggerRTag failed\n"); AIOReleasePort (AIOhandle); exit (1); } /* Get the command line we were invoked with, and advance it past our name and the board and port arguments. */ cmdlin = getcmd ((char *) NULL); for (i = 0; i < cmdindx; i++) { while (! isspace (*cmdlin)) ++cmdlin; while (isspace (*cmdlin)) ++cmdlin; } /* In case GDB is started before us, ack any packets (presumably "$?#xx") sitting there. */ if (! putDebugChar ('+')) { fprintf (stderr, "putDebugChar failed\n"); UnRegisterDebugger (&s); AIOReleasePort (AIOhandle); exit (1); } mainthread = GetThreadID (); if (remote_debug > 0) ConsolePrintf ("About to call LoadModule with \"%s\" %08x\r\n", cmdlin, __GetScreenID (GetCurrentScreen())); /* Start up the module to be debugged. */ err = LoadModule ((struct ScreenStruct *) __GetScreenID (GetCurrentScreen()), (BYTE *)cmdlin, LO_DEBUG); if (err != 0) { fprintf (stderr, "LoadModule failed: %d\n", err); UnRegisterDebugger (&s); AIOReleasePort (AIOhandle); exit (1); } /* Wait for the debugger to wake us up. */ if (remote_debug > 0) ConsolePrintf ("Suspending main thread (%08x)\r\n", mainthread); SuspendThread (mainthread); if (remote_debug > 0) ConsolePrintf ("Resuming main thread (%08x)\r\n", mainthread); /* If we are woken up, print an optional error message, deregister ourselves and exit. */ if (error_message != NULL) fprintf (stderr, "%s\n", error_message); UnRegisterDebugger (&s); AIOReleasePort (AIOhandle); exit (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -