commos.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321
  1. /*++
  2. Copyright (c) 2017 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. commos.c
  9. Abstract:
  10. This module implements the common POSIX-like debugger functionality.
  11. Author:
  12. Evan Green 20-Mar-2017
  13. Environment:
  14. POSIX
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <assert.h>
  20. #include <errno.h>
  21. #include <fcntl.h>
  22. #include <poll.h>
  23. #include <pthread.h>
  24. #include <pwd.h>
  25. #include <signal.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <sys/types.h>
  30. #include <sys/wait.h>
  31. #include <unistd.h>
  32. #include <minoca/lib/types.h>
  33. #include <minoca/lib/tty.h>
  34. #include <minoca/debug/spproto.h>
  35. #include <minoca/debug/dbgext.h>
  36. #include "dbgrprof.h"
  37. #include "console.h"
  38. #include "sock.h"
  39. //
  40. // ---------------------------------------------------------------- Definitions
  41. //
  42. #ifndef O_BINARY
  43. #define O_BINARY 0x0000
  44. #endif
  45. //
  46. // ------------------------------------------------------ Data Type Definitions
  47. //
  48. //
  49. // ----------------------------------------------- Internal Function Prototypes
  50. //
  51. void
  52. DbgrConsoleInterruptHandler (
  53. int Signal
  54. );
  55. //
  56. // -------------------------------------------------------------------- Globals
  57. //
  58. //
  59. // Store the file descriptor of the open kernel serial connection.
  60. //
  61. int DbgKdDescriptor = -1;
  62. struct termios DbgOriginalKdSettings;
  63. //
  64. // Store the ID of the terminals' initial process group.
  65. //
  66. pid_t DbgInitialTerminalInputForegroundProcessGroup;
  67. pid_t DbgInitialTerminalOutputForegroundProcessGroup;
  68. pid_t DbgInitialTerminalErrorForegroundProcessGroup;
  69. //
  70. // Store the desired terminal parameters and the previous terminal parameters.
  71. //
  72. struct termios DbgTerminalSettings;
  73. struct termios DbgOriginalTerminalSettings;
  74. struct sigaction DbgOriginalSigint;
  75. //
  76. // Store the ID of the terminal's original foreground process group.
  77. //
  78. pid_t DbgOriginalTerminalForegroundProcessGroupId;
  79. //
  80. // Store the remote pipe.
  81. //
  82. int DbgRemoteInputPipe[2] = {-1, -1};
  83. //
  84. // ------------------------------------------------------------------ Functions
  85. //
  86. INT
  87. main (
  88. INT ArgumentCount,
  89. CHAR **Arguments
  90. )
  91. /*++
  92. Routine Description:
  93. This routine is the main entry point for the program. It collects the
  94. options passed to it, and creates the output image.
  95. Arguments:
  96. ArgumentCount - Supplies the number of command line arguments the program
  97. was invoked with.
  98. Arguments - Supplies a tokenized array of command line arguments.
  99. Return Value:
  100. Returns an integer exit code. 0 for success, nonzero otherwise.
  101. --*/
  102. {
  103. return DbgrMain(ArgumentCount, Arguments);
  104. }
  105. BOOL
  106. DbgrOsInitializeConsole (
  107. PBOOL EchoCommands
  108. )
  109. /*++
  110. Routine Description:
  111. This routine performs any initialization steps necessary before the console
  112. can be used.
  113. Arguments:
  114. EchoCommands - Supplies a pointer where a boolean will be returned
  115. indicating if the debugger should echo commands received (TRUE) or if
  116. the console has already echoed the command (FALSE).
  117. Return Value:
  118. Returns TRUE on success, FALSE on failure.
  119. --*/
  120. {
  121. struct sigaction Action;
  122. int Result;
  123. if (tcgetattr(STDIN_FILENO, &DbgTerminalSettings) != 0) {
  124. perror("Cannot get terminal settings");
  125. return FALSE;
  126. }
  127. //
  128. // Set 8 bit characters.
  129. //
  130. DbgTerminalSettings.c_cflag |= CS8;
  131. //
  132. // Change the local mode to enable canonical mode, echo, erase, extended
  133. // functions, and signal characters.
  134. //
  135. DbgTerminalSettings.c_lflag |= ECHO | ICANON | ISIG | ECHONL;
  136. DbgInitialTerminalInputForegroundProcessGroup = tcgetpgrp(STDIN_FILENO);
  137. DbgInitialTerminalOutputForegroundProcessGroup = tcgetpgrp(STDOUT_FILENO);
  138. DbgInitialTerminalErrorForegroundProcessGroup = tcgetpgrp(STDERR_FILENO);
  139. Result = pipe(DbgRemoteInputPipe);
  140. if (Result != 0) {
  141. return FALSE;
  142. }
  143. //
  144. // Set the Control+C handler.
  145. //
  146. memset(&Action, 0, sizeof(Action));
  147. Action.sa_handler = DbgrConsoleInterruptHandler;
  148. sigaction(SIGINT, &Action, &DbgOriginalSigint);
  149. return TRUE;
  150. }
  151. VOID
  152. DbgrOsDestroyConsole (
  153. VOID
  154. )
  155. /*++
  156. Routine Description:
  157. This routine cleans up anything related to console functionality as a
  158. debugger is exiting.
  159. Arguments:
  160. None.
  161. Return Value:
  162. None.
  163. --*/
  164. {
  165. struct sigaction OriginalAction;
  166. int Result;
  167. struct sigaction SignalAction;
  168. sigaction(SIGINT, &DbgOriginalSigint, NULL);
  169. //
  170. // Temporarily ignore SIGTTOU as the current process may not be in the
  171. // foreground process group, causing the SIGTTOU signal to fire.
  172. //
  173. memset(&SignalAction, 0, sizeof(struct sigaction));
  174. SignalAction.sa_handler = SIG_IGN;
  175. Result = sigaction(SIGTTOU, &SignalAction, &OriginalAction);
  176. if (Result == 0) {
  177. tcsetpgrp(STDIN_FILENO, DbgInitialTerminalInputForegroundProcessGroup);
  178. tcsetpgrp(STDOUT_FILENO,
  179. DbgInitialTerminalOutputForegroundProcessGroup);
  180. tcsetpgrp(STDERR_FILENO, DbgInitialTerminalErrorForegroundProcessGroup);
  181. sigaction(SIGTTOU, &OriginalAction, NULL);
  182. }
  183. if (DbgRemoteInputPipe[0] != -1) {
  184. close(DbgRemoteInputPipe[0]);
  185. }
  186. if (DbgRemoteInputPipe[1] != -1) {
  187. close(DbgRemoteInputPipe[1]);
  188. }
  189. return;
  190. }
  191. INT
  192. DbgrOsCreateThread (
  193. PDBGR_THREAD_ROUTINE ThreadRoutine,
  194. PVOID Parameter
  195. )
  196. /*++
  197. Routine Description:
  198. This routine creates a new thread.
  199. Arguments:
  200. ThreadRoutine - Supplies a pointer to the routine to run in the new thread.
  201. The thread is destroyed when the supplied routine returns.
  202. Parameter - Supplies a pointer to a parameter to pass to the thread.
  203. Return Value:
  204. 0 on success.
  205. Returns an error code on failure.
  206. --*/
  207. {
  208. int Result;
  209. pthread_t Thread;
  210. Result = pthread_create(&Thread, NULL, ThreadRoutine, Parameter);
  211. if (Result == 0) {
  212. pthread_detach(Thread);
  213. }
  214. return Result;
  215. }
  216. int
  217. DbgrOsCreatePipe (
  218. int FileDescriptors[2]
  219. )
  220. /*++
  221. Routine Description:
  222. This routine creates an anonymous pipe.
  223. Arguments:
  224. FileDescriptors - Supplies a pointer where handles will be returned
  225. representing the read and write ends of the pipe.
  226. Return Value:
  227. 0 on success.
  228. -1 on failure. The errno variable will be set to indicate the error.
  229. --*/
  230. {
  231. return pipe(FileDescriptors);
  232. }
  233. char *
  234. DbgrOsGetUserName (
  235. void
  236. )
  237. /*++
  238. Routine Description:
  239. This routine returns the user name of the current process.
  240. Arguments:
  241. None.
  242. Return Value:
  243. Returns a pointer to a string containing the user name if it can be found.
  244. The caller should not free or modify this memory, and it may be reused on
  245. subsequent calls.
  246. --*/
  247. {
  248. struct passwd *Information;
  249. Information = getpwuid(geteuid());
  250. if ((Information == NULL) || (Information->pw_name == NULL) ||
  251. (*(Information->pw_name) == '\0')) {
  252. return getenv("USER");
  253. }
  254. return Information->pw_name;
  255. }
  256. char *
  257. DbgrOsGetHostName (
  258. void
  259. )
  260. /*++
  261. Routine Description:
  262. This routine returns the host name of the current machine.
  263. Arguments:
  264. None.
  265. Return Value:
  266. Returns a pointer to a string containing the user name if it can be found.
  267. The caller is responsible for freeing this memory.
  268. --*/
  269. {
  270. char LocalHost[100];
  271. int Result;
  272. Result = gethostname(LocalHost, sizeof(LocalHost));
  273. if (Result != 0) {
  274. return NULL;
  275. }
  276. return strdup(LocalHost);
  277. }
  278. VOID
  279. DbgrOsPrepareToReadInput (
  280. VOID
  281. )
  282. /*++
  283. Routine Description:
  284. This routine is called before the debugger begins to read a line of input
  285. from the user.
  286. Arguments:
  287. None.
  288. Return Value:
  289. None.
  290. --*/
  291. {
  292. struct sigaction OriginalAction;
  293. int Result;
  294. struct sigaction SignalAction;
  295. if (tcgetattr(STDIN_FILENO, &DbgOriginalTerminalSettings) != 0) {
  296. return;
  297. }
  298. DbgOriginalTerminalForegroundProcessGroupId = tcgetpgrp(STDIN_FILENO);
  299. tcsetattr(STDIN_FILENO, TCSANOW, &DbgTerminalSettings);
  300. //
  301. // Make the debugger's process group the foreground process ground. This
  302. // was saved when the debugger launched. Ignore SIGTTOU for this operation,
  303. // otherwise the debugger will be sent a stop signal as its in the
  304. // background process group.
  305. //
  306. memset(&SignalAction, 0, sizeof(struct sigaction));
  307. SignalAction.sa_handler = SIG_IGN;
  308. Result = sigaction(SIGTTOU, &SignalAction, &OriginalAction);
  309. if (Result == 0) {
  310. tcsetpgrp(STDIN_FILENO, DbgInitialTerminalInputForegroundProcessGroup);
  311. sigaction(SIGTTOU, &OriginalAction, NULL);
  312. }
  313. return;
  314. }
  315. BOOL
  316. DbgrOsGetCharacter (
  317. PUCHAR Key,
  318. PUCHAR ControlKey
  319. )
  320. /*++
  321. Routine Description:
  322. This routine gets one character from the standard input console.
  323. Arguments:
  324. Key - Supplies a pointer that receives the printable character. If this
  325. parameter is NULL, printing characters will be discarded from the input
  326. buffer.
  327. ControlKey - Supplies a pointer that receives the non-printable character.
  328. If this parameter is NULL, non-printing characters will be discarded
  329. from the input buffer.
  330. Return Value:
  331. Returns TRUE on success, FALSE on failure.
  332. --*/
  333. {
  334. ssize_t BytesRead;
  335. UCHAR Character;
  336. UCHAR ControlKeyValue;
  337. struct pollfd Events[2];
  338. int Result;
  339. ControlKeyValue = 0;
  340. while (TRUE) {
  341. fflush(NULL);
  342. //
  343. // Wait for either standard in or a remote command.
  344. //
  345. Events[0].fd = STDIN_FILENO;
  346. Events[0].events = POLLIN;
  347. Events[0].revents = 0;
  348. Events[1].fd = DbgRemoteInputPipe[1];
  349. Events[1].events = POLLIN;
  350. Events[1].revents = 0;
  351. Result = poll(Events, 2, -1);
  352. if (Result == -1) {
  353. if (errno == EINTR) {
  354. continue;
  355. } else {
  356. DbgOut("Failed to poll: %s\n", strerror(errno));
  357. return FALSE;
  358. }
  359. }
  360. //
  361. // Grab a character from standard in.
  362. //
  363. if ((Events[0].revents & POLLIN) != 0) {
  364. do {
  365. BytesRead = read(STDIN_FILENO, &Character, 1);
  366. } while ((BytesRead < 0) && (errno == EINTR));
  367. if (BytesRead <= 0) {
  368. return FALSE;
  369. }
  370. break;
  371. //
  372. // Perform the read from the pipe to get the data out. The data
  373. // itself doesn't matter, the pipe is just a signaling mechanism.
  374. //
  375. } else if ((Events[1].revents & POLLIN) != 0) {
  376. do {
  377. BytesRead = read(DbgRemoteInputPipe[1], &Character, 1);
  378. } while ((BytesRead < 0) && (errno == EINTR));
  379. Character = 0;
  380. ControlKeyValue = KEY_REMOTE;
  381. break;
  382. } else {
  383. DbgOut("Poll succeeded, but nothing available.\n");
  384. }
  385. }
  386. //
  387. // Handle non-printing characters.
  388. //
  389. if (Character == '\n') {
  390. Character = 0;
  391. ControlKeyValue = KEY_RETURN;
  392. }
  393. if (Key != NULL) {
  394. *Key = Character;
  395. }
  396. if (ControlKey != NULL) {
  397. *ControlKey = ControlKeyValue;
  398. }
  399. return TRUE;
  400. }
  401. VOID
  402. DbgrOsRemoteInputAdded (
  403. VOID
  404. )
  405. /*++
  406. Routine Description:
  407. This routine is called after a remote command is received and placed on the
  408. standard input remote command list. It wakes up a thread blocked on local
  409. user input in an OS-dependent fashion.
  410. Arguments:
  411. None.
  412. Return Value:
  413. None.
  414. --*/
  415. {
  416. ssize_t BytesWritten;
  417. char Character;
  418. //
  419. // It doesn't matter what the character is, just write something into the
  420. // pipe being used for inter-thread communication.
  421. //
  422. Character = 'r';
  423. do {
  424. BytesWritten = write(DbgRemoteInputPipe[1], &Character, 1);
  425. } while ((BytesWritten < 0) && (errno == EINTR));
  426. return;
  427. }
  428. VOID
  429. DbgrOsPostInputCallback (
  430. VOID
  431. )
  432. /*++
  433. Routine Description:
  434. This routine is called after a line of input is read from the user, giving
  435. the OS specific code a chance to restore anything it did in the prepare
  436. to read input function.
  437. Arguments:
  438. None.
  439. Return Value:
  440. None.
  441. --*/
  442. {
  443. //
  444. // This change of the foreground process group does not need to ignore
  445. // SIGTTOU because the debugger should be in the current foreground process
  446. // group.
  447. //
  448. tcsetpgrp(STDIN_FILENO, DbgOriginalTerminalForegroundProcessGroupId);
  449. tcsetattr(STDIN_FILENO, TCSANOW, &DbgOriginalTerminalSettings);
  450. return;
  451. }
  452. BOOL
  453. UiLoadSourceFile (
  454. PSTR Path,
  455. PVOID Contents,
  456. ULONGLONG Size
  457. )
  458. /*++
  459. Routine Description:
  460. This routine loads the contents of a file into the source window.
  461. Arguments:
  462. Path - Supplies the path of the file being loaded. If this is NULL, then
  463. the source window should be cleared.
  464. Contents - Supplies the source file data. This can be NULL.
  465. Size - Supplies the size of the source file data in bytes.
  466. Return Value:
  467. Returns TRUE if there was no error, or FALSE if there was an error.
  468. --*/
  469. {
  470. return TRUE;
  471. }
  472. BOOL
  473. UiHighlightExecutingLine (
  474. LONG LineNumber,
  475. BOOL Enable
  476. )
  477. /*++
  478. Routine Description:
  479. This routine highlights the currently executing source line and scrolls to
  480. it.
  481. Arguments:
  482. LineNumber - Supplies the 1-based line number to highlight (ie the first
  483. line in the source file is line 1).
  484. Enable - Supplies a flag indicating whether to highlight this line (TRUE)
  485. or restore the line to its original color (FALSE).
  486. Return Value:
  487. Returns TRUE if there was no error, or FALSE if there was an error.
  488. --*/
  489. {
  490. return TRUE;
  491. }
  492. VOID
  493. UiEnableCommands (
  494. BOOL Enable
  495. )
  496. /*++
  497. Routine Description:
  498. This routine enables or disables the command edit control from being
  499. enabled. If disabled, the edit control will be made read only.
  500. Arguments:
  501. Enable - Supplies a flag indicating whether or not to enable (TRUE) or
  502. disable (FALSE) the command box.
  503. Return Value:
  504. None.
  505. --*/
  506. {
  507. return;
  508. }
  509. VOID
  510. UiSetCommandText (
  511. PSTR Text
  512. )
  513. /*++
  514. Routine Description:
  515. This routine sets the text inside the command edit box.
  516. Arguments:
  517. Text - Supplies a pointer to a null terminated string to set the command
  518. text to.
  519. Return Value:
  520. None.
  521. --*/
  522. {
  523. return;
  524. }
  525. VOID
  526. UiSetPromptText (
  527. PSTR Text
  528. )
  529. /*++
  530. Routine Description:
  531. This routine sets the text inside the prompt edit box.
  532. Arguments:
  533. Text - Supplies a pointer to a null terminated string to set the prompt
  534. text to.
  535. Return Value:
  536. None.
  537. --*/
  538. {
  539. return;
  540. }
  541. VOID
  542. UiDisplayProfilerData (
  543. PROFILER_DATA_TYPE DataType,
  544. PROFILER_DISPLAY_REQUEST DisplayRequest,
  545. ULONG Threshold
  546. )
  547. /*++
  548. Routine Description:
  549. This routine displays the profiler data collected by the core debugging
  550. infrastructure.
  551. Arguments:
  552. DataType - Supplies the type of profiler data that is to be displayed.
  553. DisplayRequest - Supplies a value requesting a display action, which can
  554. either be to display data once, continually, or to stop continually
  555. displaying data.
  556. Threshold - Supplies the minimum percentage a stack entry hit must be in
  557. order to be displayed.
  558. Return Value:
  559. None.
  560. --*/
  561. {
  562. DbgrDisplayCommandLineProfilerData(DataType, DisplayRequest, Threshold);
  563. return;
  564. }
  565. BOOL
  566. InitializeCommunications (
  567. PSTR Channel,
  568. ULONG Baudrate
  569. )
  570. /*++
  571. Routine Description:
  572. This routine initializes the communication medium the debugger uses to
  573. communicate with the target.
  574. Arguments:
  575. Channel - Supplies a description of the communication medium.
  576. Baudrate - Supplies the baudrate to use for serial based communications.
  577. Return Value:
  578. Returns TRUE on success, FALSE on failure.
  579. --*/
  580. {
  581. PSTR AfterScan;
  582. PSTR Colon;
  583. PSTR HostCopy;
  584. unsigned long Port;
  585. BOOL Result;
  586. struct termios Termios;
  587. PTTY_BAUD_RATE Rate;
  588. HostCopy = NULL;
  589. Result = FALSE;
  590. if (strncasecmp(Channel, "tcp:", 4) == 0) {
  591. if (DbgrSocketInitializeLibrary() != 0) {
  592. DbgOut("Failed to initialize socket library.\n");
  593. return FALSE;
  594. }
  595. HostCopy = strdup(Channel + 4);
  596. if (HostCopy == NULL) {
  597. return FALSE;
  598. }
  599. Colon = strrchr(HostCopy, ':');
  600. if (Colon == NULL) {
  601. DbgOut("Error: Port number expected in the form host:port.\n");
  602. goto InitializeCommunicationsEnd;
  603. }
  604. *Colon = '\0';
  605. Port = strtoul(Colon + 1, &AfterScan, 10);
  606. if ((*AfterScan != '\0') || (AfterScan == Colon + 1)) {
  607. DbgOut("Error: Invalid port '%s'.\n", Colon + 1);
  608. }
  609. DbgKdDescriptor = DbgrSocketCreateStreamSocket();
  610. if (DbgKdDescriptor < 0) {
  611. DbgOut("Failed to create socket.\n");
  612. goto InitializeCommunicationsEnd;
  613. }
  614. DbgOut("Connecting via TCP to %s on port %u...", HostCopy, Port);
  615. if (DbgrSocketConnect(DbgKdDescriptor, HostCopy, Port) != 0) {
  616. DbgOut("Failed to connect: %s", strerror(errno));
  617. goto InitializeCommunicationsEnd;
  618. }
  619. } else {
  620. DbgKdDescriptor = open(Channel, O_RDWR | O_BINARY);
  621. if (DbgKdDescriptor < 0) {
  622. DbgOut("Cannot open %s: %s\n", Channel, strerror(errno));
  623. return FALSE;
  624. }
  625. if (tcgetattr(DbgKdDescriptor, &Termios) == 0) {
  626. memcpy(&DbgOriginalKdSettings, &Termios, sizeof(Termios));
  627. Termios.c_cflag = CS8 | CREAD | HUPCL;
  628. Termios.c_lflag = 0;
  629. Termios.c_iflag = 0;
  630. Termios.c_oflag = 0;
  631. //
  632. // Convert the baud rate into a speed_t value.
  633. //
  634. for (Rate = TtyBaudRates; Rate->Name != NULL; Rate += 1) {
  635. if (Rate->Rate == Baudrate) {
  636. break;
  637. }
  638. }
  639. if (Rate->Name == NULL) {
  640. DbgOut("Invalid baud rate: %lu\n", Baudrate);
  641. return FALSE;
  642. }
  643. cfsetispeed(&Termios, Rate->Value);
  644. cfsetospeed(&Termios, Rate->Value);
  645. if (tcsetattr(DbgKdDescriptor, TCSANOW, &Termios) != 0) {
  646. DbgOut("Warning: Failed to set serial settings on %s: %s\n",
  647. Channel,
  648. strerror(errno));
  649. }
  650. }
  651. }
  652. Result = TRUE;
  653. InitializeCommunicationsEnd:
  654. if (HostCopy != NULL) {
  655. free(HostCopy);
  656. }
  657. if (Result == FALSE) {
  658. if (DbgKdDescriptor >= 0) {
  659. DbgrSocketClose(DbgKdDescriptor);
  660. DbgKdDescriptor = -1;
  661. }
  662. }
  663. return Result;
  664. }
  665. VOID
  666. DestroyCommunications (
  667. VOID
  668. )
  669. /*++
  670. Routine Description:
  671. This routine tears down the debug communication channel.
  672. Arguments:
  673. None.
  674. Return Value:
  675. None.
  676. --*/
  677. {
  678. if (DbgKdDescriptor >= 0) {
  679. tcsetattr(DbgKdDescriptor, TCSANOW, &DbgOriginalKdSettings);
  680. close(DbgKdDescriptor);
  681. DbgKdDescriptor = -1;
  682. }
  683. return;
  684. }
  685. BOOL
  686. CommReceive (
  687. PVOID Buffer,
  688. ULONG BytesToRead
  689. )
  690. /*++
  691. Routine Description:
  692. This routine receives a number of bytes from the debugger/debuggee
  693. connection.
  694. Arguments:
  695. Buffer - Supplies a pointer to the buffer where the data should be returned.
  696. BytesToRead - Supplies the number of bytes that should be received into the
  697. buffer.
  698. Return Value:
  699. Returns TRUE on success, FALSE on failure.
  700. --*/
  701. {
  702. ssize_t BytesRead;
  703. do {
  704. do {
  705. BytesRead = read(DbgKdDescriptor, Buffer, BytesToRead);
  706. } while ((BytesRead < 0) && (errno == EINTR));
  707. if (BytesRead == 0) {
  708. return FALSE;
  709. }
  710. BytesToRead -= BytesRead;
  711. Buffer += BytesRead;
  712. } while (BytesToRead != 0);
  713. return TRUE;
  714. }
  715. BOOL
  716. CommSend (
  717. PVOID Buffer,
  718. ULONG BytesToSend
  719. )
  720. /*++
  721. Routine Description:
  722. This routine sends a number of bytes through the debugger/debuggee
  723. connection.
  724. Arguments:
  725. Buffer - Supplies a pointer to the buffer where the data to be sent resides.
  726. BytesToSend - Supplies the number of bytes that should be sent.
  727. Return Value:
  728. Returns TRUE on success, FALSE on failure.
  729. --*/
  730. {
  731. ssize_t BytesWritten;
  732. do {
  733. do {
  734. BytesWritten = write(DbgKdDescriptor, Buffer, BytesToSend);
  735. } while ((BytesWritten < 0) && (errno == EINTR));
  736. if (BytesWritten <= 0) {
  737. return FALSE;
  738. }
  739. Buffer += BytesWritten;
  740. BytesToSend -= BytesWritten;
  741. } while (BytesToSend != 0);
  742. return TRUE;
  743. }
  744. BOOL
  745. CommReceiveBytesReady (
  746. VOID
  747. )
  748. /*++
  749. Routine Description:
  750. This routine determines whether or not bytes can be read from the
  751. debugger connection.
  752. Arguments:
  753. None.
  754. Return Value:
  755. TRUE if there are bytes ready to be read.
  756. FALSE if no bytes are ready at this time.
  757. --*/
  758. {
  759. struct pollfd Poll;
  760. Poll.fd = DbgKdDescriptor;
  761. Poll.events = POLLIN;
  762. if (poll(&Poll, 1, 0) <= 0) {
  763. return FALSE;
  764. }
  765. return TRUE;
  766. }
  767. VOID
  768. CommStall (
  769. ULONG Milliseconds
  770. )
  771. /*++
  772. Routine Description:
  773. This routine pauses for the given amount of time.
  774. Arguments:
  775. Milliseconds - Supplies the amount of time, in milliseconds, to stall the
  776. current thread for.
  777. Return Value:
  778. None.
  779. --*/
  780. {
  781. poll(NULL, 0, Milliseconds);
  782. return;
  783. }
  784. HANDLE
  785. CreateDebuggerLock (
  786. VOID
  787. )
  788. /*++
  789. Routine Description:
  790. This routine creates a debugger lock.
  791. Arguments:
  792. None.
  793. Return Value:
  794. Returns a handle to a debugger lock on success, or NULL on failure.
  795. --*/
  796. {
  797. pthread_mutex_t *Lock;
  798. Lock = malloc(sizeof(pthread_mutex_t));
  799. if (Lock == NULL) {
  800. return NULL;
  801. }
  802. pthread_mutex_init(Lock, NULL);
  803. return (HANDLE)Lock;
  804. }
  805. VOID
  806. AcquireDebuggerLock (
  807. HANDLE Lock
  808. )
  809. /*++
  810. Routine Description:
  811. This routine acquires a debugger lock. This routine does not return until
  812. the lock is required.
  813. Arguments:
  814. Lock - Supplies a handle to the lock that is to be acquired.
  815. Return Value:
  816. None.
  817. --*/
  818. {
  819. pthread_mutex_t *Mutex;
  820. Mutex = (pthread_mutex_t *)Lock;
  821. pthread_mutex_lock(Mutex);
  822. return;
  823. }
  824. VOID
  825. ReleaseDebuggerLock (
  826. HANDLE Lock
  827. )
  828. /*++
  829. Routine Description:
  830. This routine releases a debugger lock.
  831. Arguments:
  832. Lock - Supplies a handle to the lock that is to be released.
  833. Return Value:
  834. None.
  835. --*/
  836. {
  837. pthread_mutex_t *Mutex;
  838. Mutex = (pthread_mutex_t *)Lock;
  839. pthread_mutex_unlock(Mutex);
  840. return;
  841. }
  842. VOID
  843. DestroyDebuggerLock (
  844. HANDLE Lock
  845. )
  846. /*++
  847. Routine Description:
  848. This routine destroys a debugger lock.
  849. Arguments:
  850. Lock - Supplies a handle to the lock that is to be destroyed.
  851. Return Value:
  852. None.
  853. --*/
  854. {
  855. pthread_mutex_t *Mutex;
  856. Mutex = (pthread_mutex_t *)Lock;
  857. pthread_mutex_destroy(Mutex);
  858. free(Mutex);
  859. return;
  860. }
  861. //
  862. // --------------------------------------------------------- Internal Functions
  863. //
  864. void
  865. DbgrConsoleInterruptHandler (
  866. int Signal
  867. )
  868. /*++
  869. Routine Description:
  870. This routine is called when a debug process receives SIGINT, for example
  871. using Control+C. It requests a break in.
  872. Arguments:
  873. Signal - Supplies the number of triggered signal. Should be SIGINT.
  874. Return Value:
  875. None.
  876. --*/
  877. {
  878. DbgrRequestBreakIn();
  879. return;
  880. }