1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321 |
- /*++
- Copyright (c) 2017 Minoca Corp.
- This file is licensed under the terms of the GNU General Public License
- version 3. Alternative licensing terms are available. Contact
- info@minocacorp.com for details. See the LICENSE file at the root of this
- project for complete licensing information.
- Module Name:
- commos.c
- Abstract:
- This module implements the common POSIX-like debugger functionality.
- Author:
- Evan Green 20-Mar-2017
- Environment:
- POSIX
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <assert.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <poll.h>
- #include <pthread.h>
- #include <pwd.h>
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include <minoca/lib/types.h>
- #include <minoca/lib/tty.h>
- #include <minoca/debug/spproto.h>
- #include <minoca/debug/dbgext.h>
- #include "dbgrprof.h"
- #include "console.h"
- #include "sock.h"
- //
- // ---------------------------------------------------------------- Definitions
- //
- #ifndef O_BINARY
- #define O_BINARY 0x0000
- #endif
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- void
- DbgrConsoleInterruptHandler (
- int Signal
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // Store the file descriptor of the open kernel serial connection.
- //
- int DbgKdDescriptor = -1;
- struct termios DbgOriginalKdSettings;
- //
- // Store the ID of the terminals' initial process group.
- //
- pid_t DbgInitialTerminalInputForegroundProcessGroup;
- pid_t DbgInitialTerminalOutputForegroundProcessGroup;
- pid_t DbgInitialTerminalErrorForegroundProcessGroup;
- //
- // Store the desired terminal parameters and the previous terminal parameters.
- //
- struct termios DbgTerminalSettings;
- struct termios DbgOriginalTerminalSettings;
- struct sigaction DbgOriginalSigint;
- //
- // Store the ID of the terminal's original foreground process group.
- //
- pid_t DbgOriginalTerminalForegroundProcessGroupId;
- //
- // Store the remote pipe.
- //
- int DbgRemoteInputPipe[2] = {-1, -1};
- //
- // ------------------------------------------------------------------ Functions
- //
- INT
- main (
- INT ArgumentCount,
- CHAR **Arguments
- )
- /*++
- Routine Description:
- This routine is the main entry point for the program. It collects the
- options passed to it, and creates the output image.
- Arguments:
- ArgumentCount - Supplies the number of command line arguments the program
- was invoked with.
- Arguments - Supplies a tokenized array of command line arguments.
- Return Value:
- Returns an integer exit code. 0 for success, nonzero otherwise.
- --*/
- {
- return DbgrMain(ArgumentCount, Arguments);
- }
- BOOL
- DbgrOsInitializeConsole (
- PBOOL EchoCommands
- )
- /*++
- Routine Description:
- This routine performs any initialization steps necessary before the console
- can be used.
- Arguments:
- EchoCommands - Supplies a pointer where a boolean will be returned
- indicating if the debugger should echo commands received (TRUE) or if
- the console has already echoed the command (FALSE).
- Return Value:
- Returns TRUE on success, FALSE on failure.
- --*/
- {
- struct sigaction Action;
- int Result;
- if (tcgetattr(STDIN_FILENO, &DbgTerminalSettings) != 0) {
- perror("Cannot get terminal settings");
- return FALSE;
- }
- //
- // Set 8 bit characters.
- //
- DbgTerminalSettings.c_cflag |= CS8;
- //
- // Change the local mode to enable canonical mode, echo, erase, extended
- // functions, and signal characters.
- //
- DbgTerminalSettings.c_lflag |= ECHO | ICANON | ISIG | ECHONL;
- DbgInitialTerminalInputForegroundProcessGroup = tcgetpgrp(STDIN_FILENO);
- DbgInitialTerminalOutputForegroundProcessGroup = tcgetpgrp(STDOUT_FILENO);
- DbgInitialTerminalErrorForegroundProcessGroup = tcgetpgrp(STDERR_FILENO);
- Result = pipe(DbgRemoteInputPipe);
- if (Result != 0) {
- return FALSE;
- }
- //
- // Set the Control+C handler.
- //
- memset(&Action, 0, sizeof(Action));
- Action.sa_handler = DbgrConsoleInterruptHandler;
- sigaction(SIGINT, &Action, &DbgOriginalSigint);
- return TRUE;
- }
- VOID
- DbgrOsDestroyConsole (
- VOID
- )
- /*++
- Routine Description:
- This routine cleans up anything related to console functionality as a
- debugger is exiting.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- {
- struct sigaction OriginalAction;
- int Result;
- struct sigaction SignalAction;
- sigaction(SIGINT, &DbgOriginalSigint, NULL);
- //
- // Temporarily ignore SIGTTOU as the current process may not be in the
- // foreground process group, causing the SIGTTOU signal to fire.
- //
- memset(&SignalAction, 0, sizeof(struct sigaction));
- SignalAction.sa_handler = SIG_IGN;
- Result = sigaction(SIGTTOU, &SignalAction, &OriginalAction);
- if (Result == 0) {
- tcsetpgrp(STDIN_FILENO, DbgInitialTerminalInputForegroundProcessGroup);
- tcsetpgrp(STDOUT_FILENO,
- DbgInitialTerminalOutputForegroundProcessGroup);
- tcsetpgrp(STDERR_FILENO, DbgInitialTerminalErrorForegroundProcessGroup);
- sigaction(SIGTTOU, &OriginalAction, NULL);
- }
- if (DbgRemoteInputPipe[0] != -1) {
- close(DbgRemoteInputPipe[0]);
- }
- if (DbgRemoteInputPipe[1] != -1) {
- close(DbgRemoteInputPipe[1]);
- }
- return;
- }
- INT
- DbgrOsCreateThread (
- PDBGR_THREAD_ROUTINE ThreadRoutine,
- PVOID Parameter
- )
- /*++
- Routine Description:
- This routine creates a new thread.
- Arguments:
- ThreadRoutine - Supplies a pointer to the routine to run in the new thread.
- The thread is destroyed when the supplied routine returns.
- Parameter - Supplies a pointer to a parameter to pass to the thread.
- Return Value:
- 0 on success.
- Returns an error code on failure.
- --*/
- {
- int Result;
- pthread_t Thread;
- Result = pthread_create(&Thread, NULL, ThreadRoutine, Parameter);
- if (Result == 0) {
- pthread_detach(Thread);
- }
- return Result;
- }
- int
- DbgrOsCreatePipe (
- int FileDescriptors[2]
- )
- /*++
- Routine Description:
- This routine creates an anonymous pipe.
- Arguments:
- FileDescriptors - Supplies a pointer where handles will be returned
- representing the read and write ends of the pipe.
- Return Value:
- 0 on success.
- -1 on failure. The errno variable will be set to indicate the error.
- --*/
- {
- return pipe(FileDescriptors);
- }
- char *
- DbgrOsGetUserName (
- void
- )
- /*++
- Routine Description:
- This routine returns the user name of the current process.
- Arguments:
- None.
- Return Value:
- Returns a pointer to a string containing the user name if it can be found.
- The caller should not free or modify this memory, and it may be reused on
- subsequent calls.
- --*/
- {
- struct passwd *Information;
- Information = getpwuid(geteuid());
- if ((Information == NULL) || (Information->pw_name == NULL) ||
- (*(Information->pw_name) == '\0')) {
- return getenv("USER");
- }
- return Information->pw_name;
- }
- char *
- DbgrOsGetHostName (
- void
- )
- /*++
- Routine Description:
- This routine returns the host name of the current machine.
- Arguments:
- None.
- Return Value:
- Returns a pointer to a string containing the user name if it can be found.
- The caller is responsible for freeing this memory.
- --*/
- {
- char LocalHost[100];
- int Result;
- Result = gethostname(LocalHost, sizeof(LocalHost));
- if (Result != 0) {
- return NULL;
- }
- return strdup(LocalHost);
- }
- VOID
- DbgrOsPrepareToReadInput (
- VOID
- )
- /*++
- Routine Description:
- This routine is called before the debugger begins to read a line of input
- from the user.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- {
- struct sigaction OriginalAction;
- int Result;
- struct sigaction SignalAction;
- if (tcgetattr(STDIN_FILENO, &DbgOriginalTerminalSettings) != 0) {
- return;
- }
- DbgOriginalTerminalForegroundProcessGroupId = tcgetpgrp(STDIN_FILENO);
- tcsetattr(STDIN_FILENO, TCSANOW, &DbgTerminalSettings);
- //
- // Make the debugger's process group the foreground process ground. This
- // was saved when the debugger launched. Ignore SIGTTOU for this operation,
- // otherwise the debugger will be sent a stop signal as its in the
- // background process group.
- //
- memset(&SignalAction, 0, sizeof(struct sigaction));
- SignalAction.sa_handler = SIG_IGN;
- Result = sigaction(SIGTTOU, &SignalAction, &OriginalAction);
- if (Result == 0) {
- tcsetpgrp(STDIN_FILENO, DbgInitialTerminalInputForegroundProcessGroup);
- sigaction(SIGTTOU, &OriginalAction, NULL);
- }
- return;
- }
- BOOL
- DbgrOsGetCharacter (
- PUCHAR Key,
- PUCHAR ControlKey
- )
- /*++
- Routine Description:
- This routine gets one character from the standard input console.
- Arguments:
- Key - Supplies a pointer that receives the printable character. If this
- parameter is NULL, printing characters will be discarded from the input
- buffer.
- ControlKey - Supplies a pointer that receives the non-printable character.
- If this parameter is NULL, non-printing characters will be discarded
- from the input buffer.
- Return Value:
- Returns TRUE on success, FALSE on failure.
- --*/
- {
- ssize_t BytesRead;
- UCHAR Character;
- UCHAR ControlKeyValue;
- struct pollfd Events[2];
- int Result;
- ControlKeyValue = 0;
- while (TRUE) {
- fflush(NULL);
- //
- // Wait for either standard in or a remote command.
- //
- Events[0].fd = STDIN_FILENO;
- Events[0].events = POLLIN;
- Events[0].revents = 0;
- Events[1].fd = DbgRemoteInputPipe[1];
- Events[1].events = POLLIN;
- Events[1].revents = 0;
- Result = poll(Events, 2, -1);
- if (Result == -1) {
- if (errno == EINTR) {
- continue;
- } else {
- DbgOut("Failed to poll: %s\n", strerror(errno));
- return FALSE;
- }
- }
- //
- // Grab a character from standard in.
- //
- if ((Events[0].revents & POLLIN) != 0) {
- do {
- BytesRead = read(STDIN_FILENO, &Character, 1);
- } while ((BytesRead < 0) && (errno == EINTR));
- if (BytesRead <= 0) {
- return FALSE;
- }
- break;
- //
- // Perform the read from the pipe to get the data out. The data
- // itself doesn't matter, the pipe is just a signaling mechanism.
- //
- } else if ((Events[1].revents & POLLIN) != 0) {
- do {
- BytesRead = read(DbgRemoteInputPipe[1], &Character, 1);
- } while ((BytesRead < 0) && (errno == EINTR));
- Character = 0;
- ControlKeyValue = KEY_REMOTE;
- break;
- } else {
- DbgOut("Poll succeeded, but nothing available.\n");
- }
- }
- //
- // Handle non-printing characters.
- //
- if (Character == '\n') {
- Character = 0;
- ControlKeyValue = KEY_RETURN;
- }
- if (Key != NULL) {
- *Key = Character;
- }
- if (ControlKey != NULL) {
- *ControlKey = ControlKeyValue;
- }
- return TRUE;
- }
- VOID
- DbgrOsRemoteInputAdded (
- VOID
- )
- /*++
- Routine Description:
- This routine is called after a remote command is received and placed on the
- standard input remote command list. It wakes up a thread blocked on local
- user input in an OS-dependent fashion.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- {
- ssize_t BytesWritten;
- char Character;
- //
- // It doesn't matter what the character is, just write something into the
- // pipe being used for inter-thread communication.
- //
- Character = 'r';
- do {
- BytesWritten = write(DbgRemoteInputPipe[1], &Character, 1);
- } while ((BytesWritten < 0) && (errno == EINTR));
- return;
- }
- VOID
- DbgrOsPostInputCallback (
- VOID
- )
- /*++
- Routine Description:
- This routine is called after a line of input is read from the user, giving
- the OS specific code a chance to restore anything it did in the prepare
- to read input function.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- {
- //
- // This change of the foreground process group does not need to ignore
- // SIGTTOU because the debugger should be in the current foreground process
- // group.
- //
- tcsetpgrp(STDIN_FILENO, DbgOriginalTerminalForegroundProcessGroupId);
- tcsetattr(STDIN_FILENO, TCSANOW, &DbgOriginalTerminalSettings);
- return;
- }
- BOOL
- UiLoadSourceFile (
- PSTR Path,
- PVOID Contents,
- ULONGLONG Size
- )
- /*++
- Routine Description:
- This routine loads the contents of a file into the source window.
- Arguments:
- Path - Supplies the path of the file being loaded. If this is NULL, then
- the source window should be cleared.
- Contents - Supplies the source file data. This can be NULL.
- Size - Supplies the size of the source file data in bytes.
- Return Value:
- Returns TRUE if there was no error, or FALSE if there was an error.
- --*/
- {
- return TRUE;
- }
- BOOL
- UiHighlightExecutingLine (
- LONG LineNumber,
- BOOL Enable
- )
- /*++
- Routine Description:
- This routine highlights the currently executing source line and scrolls to
- it.
- Arguments:
- LineNumber - Supplies the 1-based line number to highlight (ie the first
- line in the source file is line 1).
- Enable - Supplies a flag indicating whether to highlight this line (TRUE)
- or restore the line to its original color (FALSE).
- Return Value:
- Returns TRUE if there was no error, or FALSE if there was an error.
- --*/
- {
- return TRUE;
- }
- VOID
- UiEnableCommands (
- BOOL Enable
- )
- /*++
- Routine Description:
- This routine enables or disables the command edit control from being
- enabled. If disabled, the edit control will be made read only.
- Arguments:
- Enable - Supplies a flag indicating whether or not to enable (TRUE) or
- disable (FALSE) the command box.
- Return Value:
- None.
- --*/
- {
- return;
- }
- VOID
- UiSetCommandText (
- PSTR Text
- )
- /*++
- Routine Description:
- This routine sets the text inside the command edit box.
- Arguments:
- Text - Supplies a pointer to a null terminated string to set the command
- text to.
- Return Value:
- None.
- --*/
- {
- return;
- }
- VOID
- UiSetPromptText (
- PSTR Text
- )
- /*++
- Routine Description:
- This routine sets the text inside the prompt edit box.
- Arguments:
- Text - Supplies a pointer to a null terminated string to set the prompt
- text to.
- Return Value:
- None.
- --*/
- {
- return;
- }
- VOID
- UiDisplayProfilerData (
- PROFILER_DATA_TYPE DataType,
- PROFILER_DISPLAY_REQUEST DisplayRequest,
- ULONG Threshold
- )
- /*++
- Routine Description:
- This routine displays the profiler data collected by the core debugging
- infrastructure.
- Arguments:
- DataType - Supplies the type of profiler data that is to be displayed.
- DisplayRequest - Supplies a value requesting a display action, which can
- either be to display data once, continually, or to stop continually
- displaying data.
- Threshold - Supplies the minimum percentage a stack entry hit must be in
- order to be displayed.
- Return Value:
- None.
- --*/
- {
- DbgrDisplayCommandLineProfilerData(DataType, DisplayRequest, Threshold);
- return;
- }
- BOOL
- InitializeCommunications (
- PSTR Channel,
- ULONG Baudrate
- )
- /*++
- Routine Description:
- This routine initializes the communication medium the debugger uses to
- communicate with the target.
- Arguments:
- Channel - Supplies a description of the communication medium.
- Baudrate - Supplies the baudrate to use for serial based communications.
- Return Value:
- Returns TRUE on success, FALSE on failure.
- --*/
- {
- PSTR AfterScan;
- PSTR Colon;
- PSTR HostCopy;
- unsigned long Port;
- BOOL Result;
- struct termios Termios;
- PTTY_BAUD_RATE Rate;
- HostCopy = NULL;
- Result = FALSE;
- if (strncasecmp(Channel, "tcp:", 4) == 0) {
- if (DbgrSocketInitializeLibrary() != 0) {
- DbgOut("Failed to initialize socket library.\n");
- return FALSE;
- }
- HostCopy = strdup(Channel + 4);
- if (HostCopy == NULL) {
- return FALSE;
- }
- Colon = strrchr(HostCopy, ':');
- if (Colon == NULL) {
- DbgOut("Error: Port number expected in the form host:port.\n");
- goto InitializeCommunicationsEnd;
- }
- *Colon = '\0';
- Port = strtoul(Colon + 1, &AfterScan, 10);
- if ((*AfterScan != '\0') || (AfterScan == Colon + 1)) {
- DbgOut("Error: Invalid port '%s'.\n", Colon + 1);
- }
- DbgKdDescriptor = DbgrSocketCreateStreamSocket();
- if (DbgKdDescriptor < 0) {
- DbgOut("Failed to create socket.\n");
- goto InitializeCommunicationsEnd;
- }
- DbgOut("Connecting via TCP to %s on port %u...", HostCopy, Port);
- if (DbgrSocketConnect(DbgKdDescriptor, HostCopy, Port) != 0) {
- DbgOut("Failed to connect: %s", strerror(errno));
- goto InitializeCommunicationsEnd;
- }
- } else {
- DbgKdDescriptor = open(Channel, O_RDWR | O_BINARY);
- if (DbgKdDescriptor < 0) {
- DbgOut("Cannot open %s: %s\n", Channel, strerror(errno));
- return FALSE;
- }
- if (tcgetattr(DbgKdDescriptor, &Termios) == 0) {
- memcpy(&DbgOriginalKdSettings, &Termios, sizeof(Termios));
- Termios.c_cflag = CS8 | CREAD | HUPCL;
- Termios.c_lflag = 0;
- Termios.c_iflag = 0;
- Termios.c_oflag = 0;
- //
- // Convert the baud rate into a speed_t value.
- //
- for (Rate = TtyBaudRates; Rate->Name != NULL; Rate += 1) {
- if (Rate->Rate == Baudrate) {
- break;
- }
- }
- if (Rate->Name == NULL) {
- DbgOut("Invalid baud rate: %lu\n", Baudrate);
- return FALSE;
- }
- cfsetispeed(&Termios, Rate->Value);
- cfsetospeed(&Termios, Rate->Value);
- if (tcsetattr(DbgKdDescriptor, TCSANOW, &Termios) != 0) {
- DbgOut("Warning: Failed to set serial settings on %s: %s\n",
- Channel,
- strerror(errno));
- }
- }
- }
- Result = TRUE;
- InitializeCommunicationsEnd:
- if (HostCopy != NULL) {
- free(HostCopy);
- }
- if (Result == FALSE) {
- if (DbgKdDescriptor >= 0) {
- DbgrSocketClose(DbgKdDescriptor);
- DbgKdDescriptor = -1;
- }
- }
- return Result;
- }
- VOID
- DestroyCommunications (
- VOID
- )
- /*++
- Routine Description:
- This routine tears down the debug communication channel.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- {
- if (DbgKdDescriptor >= 0) {
- tcsetattr(DbgKdDescriptor, TCSANOW, &DbgOriginalKdSettings);
- close(DbgKdDescriptor);
- DbgKdDescriptor = -1;
- }
- return;
- }
- BOOL
- CommReceive (
- PVOID Buffer,
- ULONG BytesToRead
- )
- /*++
- Routine Description:
- This routine receives a number of bytes from the debugger/debuggee
- connection.
- Arguments:
- Buffer - Supplies a pointer to the buffer where the data should be returned.
- BytesToRead - Supplies the number of bytes that should be received into the
- buffer.
- Return Value:
- Returns TRUE on success, FALSE on failure.
- --*/
- {
- ssize_t BytesRead;
- do {
- do {
- BytesRead = read(DbgKdDescriptor, Buffer, BytesToRead);
- } while ((BytesRead < 0) && (errno == EINTR));
- if (BytesRead == 0) {
- return FALSE;
- }
- BytesToRead -= BytesRead;
- Buffer += BytesRead;
- } while (BytesToRead != 0);
- return TRUE;
- }
- BOOL
- CommSend (
- PVOID Buffer,
- ULONG BytesToSend
- )
- /*++
- Routine Description:
- This routine sends a number of bytes through the debugger/debuggee
- connection.
- Arguments:
- Buffer - Supplies a pointer to the buffer where the data to be sent resides.
- BytesToSend - Supplies the number of bytes that should be sent.
- Return Value:
- Returns TRUE on success, FALSE on failure.
- --*/
- {
- ssize_t BytesWritten;
- do {
- do {
- BytesWritten = write(DbgKdDescriptor, Buffer, BytesToSend);
- } while ((BytesWritten < 0) && (errno == EINTR));
- if (BytesWritten <= 0) {
- return FALSE;
- }
- Buffer += BytesWritten;
- BytesToSend -= BytesWritten;
- } while (BytesToSend != 0);
- return TRUE;
- }
- BOOL
- CommReceiveBytesReady (
- VOID
- )
- /*++
- Routine Description:
- This routine determines whether or not bytes can be read from the
- debugger connection.
- Arguments:
- None.
- Return Value:
- TRUE if there are bytes ready to be read.
- FALSE if no bytes are ready at this time.
- --*/
- {
- struct pollfd Poll;
- Poll.fd = DbgKdDescriptor;
- Poll.events = POLLIN;
- if (poll(&Poll, 1, 0) <= 0) {
- return FALSE;
- }
- return TRUE;
- }
- VOID
- CommStall (
- ULONG Milliseconds
- )
- /*++
- Routine Description:
- This routine pauses for the given amount of time.
- Arguments:
- Milliseconds - Supplies the amount of time, in milliseconds, to stall the
- current thread for.
- Return Value:
- None.
- --*/
- {
- poll(NULL, 0, Milliseconds);
- return;
- }
- HANDLE
- CreateDebuggerLock (
- VOID
- )
- /*++
- Routine Description:
- This routine creates a debugger lock.
- Arguments:
- None.
- Return Value:
- Returns a handle to a debugger lock on success, or NULL on failure.
- --*/
- {
- pthread_mutex_t *Lock;
- Lock = malloc(sizeof(pthread_mutex_t));
- if (Lock == NULL) {
- return NULL;
- }
- pthread_mutex_init(Lock, NULL);
- return (HANDLE)Lock;
- }
- VOID
- AcquireDebuggerLock (
- HANDLE Lock
- )
- /*++
- Routine Description:
- This routine acquires a debugger lock. This routine does not return until
- the lock is required.
- Arguments:
- Lock - Supplies a handle to the lock that is to be acquired.
- Return Value:
- None.
- --*/
- {
- pthread_mutex_t *Mutex;
- Mutex = (pthread_mutex_t *)Lock;
- pthread_mutex_lock(Mutex);
- return;
- }
- VOID
- ReleaseDebuggerLock (
- HANDLE Lock
- )
- /*++
- Routine Description:
- This routine releases a debugger lock.
- Arguments:
- Lock - Supplies a handle to the lock that is to be released.
- Return Value:
- None.
- --*/
- {
- pthread_mutex_t *Mutex;
- Mutex = (pthread_mutex_t *)Lock;
- pthread_mutex_unlock(Mutex);
- return;
- }
- VOID
- DestroyDebuggerLock (
- HANDLE Lock
- )
- /*++
- Routine Description:
- This routine destroys a debugger lock.
- Arguments:
- Lock - Supplies a handle to the lock that is to be destroyed.
- Return Value:
- None.
- --*/
- {
- pthread_mutex_t *Mutex;
- Mutex = (pthread_mutex_t *)Lock;
- pthread_mutex_destroy(Mutex);
- free(Mutex);
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- void
- DbgrConsoleInterruptHandler (
- int Signal
- )
- /*++
- Routine Description:
- This routine is called when a debug process receives SIGINT, for example
- using Control+C. It requests a break in.
- Arguments:
- Signal - Supplies the number of triggered signal. Should be SIGINT.
- Return Value:
- None.
- --*/
- {
- DbgrRequestBreakIn();
- return;
- }
|