consio.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /*++
  2. Copyright (c) 2013 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. consio.c
  9. Abstract:
  10. This module implements standard input and output functionality for the
  11. debugger.
  12. Author:
  13. Evan Green 30-Dec-2013
  14. Environment:
  15. Debug
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include "dbgrtl.h"
  21. #include <minoca/debug/spproto.h>
  22. #include <minoca/lib/im.h>
  23. #include <minoca/debug/dbgext.h>
  24. #include "disasm.h"
  25. #include "dbgapi.h"
  26. #include "dbgrprof.h"
  27. #include "console.h"
  28. #include "symbols.h"
  29. #include "dbgrcomm.h"
  30. #include "dbgsym.h"
  31. #include "extsp.h"
  32. #include "consio.h"
  33. #include "remsrv.h"
  34. #include <assert.h>
  35. #include <errno.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <sys/stat.h>
  40. #include <unistd.h>
  41. //
  42. // ---------------------------------------------------------------- Definitions
  43. //
  44. #define DBGR_IO_BUFFER_SIZE 1024
  45. //
  46. // ------------------------------------------------------ Data Type Definitions
  47. //
  48. //
  49. // ----------------------------------------------- Internal Function Prototypes
  50. //
  51. BOOL
  52. DbgrpFormatWriteCharacter (
  53. INT Character,
  54. PPRINT_FORMAT_CONTEXT Context
  55. );
  56. //
  57. // -------------------------------------------------------------------- Globals
  58. //
  59. //
  60. // Store a pointer to the global context. Currently only one debugger context
  61. // is supported for output functions.
  62. //
  63. PDEBUGGER_CONTEXT DbgConsoleContext;
  64. //
  65. // ------------------------------------------------------------------ Functions
  66. //
  67. INT
  68. DbgrInitializeConsoleIo (
  69. PDEBUGGER_CONTEXT Context
  70. )
  71. /*++
  72. Routine Description:
  73. This routine initializes console I/O for the debugger.
  74. Arguments:
  75. Context - Supplies a pointer to the debugger context.
  76. Return Value:
  77. 0 on success.
  78. Returns an error code on failure.
  79. --*/
  80. {
  81. BOOL EchoCommands;
  82. INT Result;
  83. assert(DbgConsoleContext == NULL);
  84. DbgConsoleContext = Context;
  85. EchoCommands = FALSE;
  86. Result = DbgrOsInitializeConsole(&EchoCommands);
  87. if (Result == FALSE) {
  88. Result = EINVAL;
  89. goto InitializeConsoleIoEnd;
  90. }
  91. if (EchoCommands != FALSE) {
  92. Context->Flags |= DEBUGGER_FLAG_ECHO_COMMANDS;
  93. }
  94. assert(Context->StandardOut.ConsoleBuffer == NULL);
  95. Context->StandardOut.ConsoleBuffer = malloc(DBGR_IO_BUFFER_SIZE);
  96. if (Context->StandardOut.ConsoleBuffer == NULL) {
  97. Result = ENOMEM;
  98. goto InitializeConsoleIoEnd;
  99. }
  100. Context->StandardOut.ConsoleBufferCapacity = DBGR_IO_BUFFER_SIZE;
  101. Context->StandardOut.ConsoleBufferSize = 0;
  102. Context->StandardOut.Lock = CreateDebuggerLock();
  103. if (Context->StandardOut.Lock == NULL) {
  104. Result = ENOMEM;
  105. goto InitializeConsoleIoEnd;
  106. }
  107. Context->StandardIn.Lock = CreateDebuggerLock();
  108. if (Context->StandardIn.Lock == NULL) {
  109. Result = ENOMEM;
  110. goto InitializeConsoleIoEnd;
  111. }
  112. Result = 0;
  113. InitializeConsoleIoEnd:
  114. return Result;
  115. }
  116. VOID
  117. DbgrDestroyConsoleIo (
  118. PDEBUGGER_CONTEXT Context
  119. )
  120. /*++
  121. Routine Description:
  122. This routine destroys console I/O for the debugger.
  123. Arguments:
  124. Context - Supplies a pointer to the debugger context.
  125. Return Value:
  126. None.
  127. --*/
  128. {
  129. DbgrOsDestroyConsole();
  130. if (Context->StandardOut.ConsoleBuffer != NULL) {
  131. free(Context->StandardOut.ConsoleBuffer);
  132. }
  133. if (Context->StandardOut.Prompt != NULL) {
  134. free(Context->StandardOut.Prompt);
  135. }
  136. if (Context->StandardOut.Lock != NULL) {
  137. DestroyDebuggerLock(Context->StandardOut.Lock);
  138. }
  139. if (Context->StandardIn.Lock != NULL) {
  140. DestroyDebuggerLock(Context->StandardIn.Lock);
  141. }
  142. DbgConsoleContext = NULL;
  143. return;
  144. }
  145. INT
  146. DbgOut (
  147. const char *Format,
  148. ...
  149. )
  150. /*++
  151. Routine Description:
  152. This routine prints a formatted string to the debugger console.
  153. Arguments:
  154. Format - Supplies the printf format string.
  155. ... - Supplies a variable number of arguments, as required by the printf
  156. format string argument.
  157. Return Value:
  158. Returns the number of bytes successfully converted, not including the null
  159. terminator.
  160. Returns a negative number if an error was encountered.
  161. --*/
  162. {
  163. va_list Arguments;
  164. int Result;
  165. assert(DbgConsoleContext != NULL);
  166. va_start(Arguments, Format);
  167. Result = DbgOutVaList(DbgConsoleContext, Format, Arguments);
  168. va_end(Arguments);
  169. return Result;
  170. }
  171. INT
  172. DbgOutVaList (
  173. PDEBUGGER_CONTEXT Context,
  174. const char *Format,
  175. va_list Arguments
  176. )
  177. /*++
  178. Routine Description:
  179. This routine prints a formatted string to the given debugger console.
  180. Arguments:
  181. Context - Supplies a pointer to the debugger context to output to.
  182. Format - Supplies the printf format string.
  183. Arguments - Supplies the argument list to the format string. The va_end
  184. macro is not invoked on this list.
  185. Return Value:
  186. Returns the number of bytes successfully converted. A null terminator is
  187. not written.
  188. Returns a negative number if an error was encountered.
  189. --*/
  190. {
  191. PRINT_FORMAT_CONTEXT PrintContext;
  192. if (Context == NULL) {
  193. Context = DbgConsoleContext;
  194. }
  195. memset(&PrintContext, 0, sizeof(PRINT_FORMAT_CONTEXT));
  196. PrintContext.Context = Context;
  197. PrintContext.WriteCharacter = DbgrpFormatWriteCharacter;
  198. RtlInitializeMultibyteState(&(PrintContext.State),
  199. CharacterEncodingDefault);
  200. AcquireDebuggerLock(Context->StandardOut.Lock);
  201. RtlFormat(&PrintContext, (PSTR)Format, Arguments);
  202. //
  203. // If something was written poke all the clients to send the data along to
  204. // them too.
  205. //
  206. if (PrintContext.CharactersWritten != 0) {
  207. DbgrpServerNotifyClients(Context);
  208. }
  209. ReleaseDebuggerLock(Context->StandardOut.Lock);
  210. return PrintContext.CharactersWritten;
  211. }
  212. //
  213. // --------------------------------------------------------- Internal Functions
  214. //
  215. BOOL
  216. DbgrpFormatWriteCharacter (
  217. INT Character,
  218. PPRINT_FORMAT_CONTEXT Context
  219. )
  220. /*++
  221. Routine Description:
  222. This routine writes a character to the output during a printf-style
  223. formatting operation.
  224. Arguments:
  225. Character - Supplies the character to be written.
  226. Context - Supplies a pointer to the printf-context.
  227. Return Value:
  228. TRUE on success.
  229. FALSE on failure.
  230. --*/
  231. {
  232. PDEBUGGER_CONTEXT DebuggerContext;
  233. PVOID NewBuffer;
  234. ULONGLONG NewCapacity;
  235. PDEBUGGER_STANDARD_OUT Out;
  236. DebuggerContext = Context->Context;
  237. Out = &(DebuggerContext->StandardOut);
  238. //
  239. // Reallocate the console buffer if needed.
  240. //
  241. if (Out->ConsoleBufferSize + 2 > Out->ConsoleBufferCapacity) {
  242. NewCapacity = Out->ConsoleBufferCapacity * 2;
  243. assert(NewCapacity > Out->ConsoleBufferSize + 2);
  244. NewBuffer = realloc(Out->ConsoleBuffer, NewCapacity);
  245. if (NewBuffer == NULL) {
  246. return FALSE;
  247. }
  248. Out->ConsoleBuffer = NewBuffer;
  249. Out->ConsoleBufferCapacity = NewCapacity;
  250. }
  251. //
  252. // Add the character to the console buffer.
  253. //
  254. Out->ConsoleBuffer[Out->ConsoleBufferSize] = Character;
  255. Out->ConsoleBufferSize += 1;
  256. if (fputc(Character, stdout) == -1) {
  257. return FALSE;
  258. }
  259. return TRUE;
  260. }