[KDGDB]
[reactos.git] / reactos / drivers / base / kdgdb / gdb_send.c
1 /*
2 * COPYRIGHT: GPL, see COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/base/kddll/gdb_send.c
5 * PURPOSE: Base functions for the kernel debugger.
6 */
7
8 #include "kdgdb.h"
9
10 /* LOCALS *********************************************************************/
11 const char hex_chars[] = "0123456789abcdef";
12
13 /* PRIVATE FUNCTIONS **********************************************************/
14 static
15 char*
16 exception_code_to_gdb(NTSTATUS code, char* out)
17 {
18 unsigned char SigVal;
19
20 switch (code)
21 {
22 case STATUS_INTEGER_DIVIDE_BY_ZERO:
23 SigVal = 8; /* divide by zero */
24 break;
25 case STATUS_SINGLE_STEP:
26 case STATUS_BREAKPOINT:
27 SigVal = 5; /* breakpoint */
28 break;
29 case STATUS_INTEGER_OVERFLOW:
30 case STATUS_ARRAY_BOUNDS_EXCEEDED:
31 SigVal = 16; /* bound instruction */
32 break;
33 case STATUS_ILLEGAL_INSTRUCTION:
34 SigVal = 4; /* Invalid opcode */
35 break;
36 case STATUS_STACK_OVERFLOW:
37 case STATUS_DATATYPE_MISALIGNMENT:
38 case STATUS_ACCESS_VIOLATION:
39 SigVal = 11; /* access violation */
40 break;
41 default:
42 SigVal = 7; /* "software generated" */
43 }
44 *out++ = hex_chars[(SigVal >> 4) & 0xf];
45 *out++ = hex_chars[SigVal & 0xf];
46 return out;
47 }
48
49 /* GLOBAL FUNCTIONS ***********************************************************/
50 void
51 send_gdb_packet(_In_ CHAR* Buffer)
52 {
53 UCHAR ack;
54
55 do {
56 CHAR* ptr = Buffer;
57 CHAR check_sum = 0;
58
59 KdpSendByte('$');
60
61 /* Calculate checksum */
62 check_sum = 0;
63 while (*ptr)
64 {
65 check_sum += *ptr;
66 KdpSendByte(*ptr++);
67 }
68
69 /* append it */
70 KdpSendByte('#');
71 KdpSendByte(hex_chars[(check_sum >> 4) & 0xf]);
72 KdpSendByte(hex_chars[check_sum & 0xf]);
73
74 /* Wait for acknowledgement */
75 if (KdpReceiveByte(&ack) != KdPacketReceived)
76 {
77 KD_DEBUGGER_NOT_PRESENT = TRUE;
78 break;
79 }
80 } while (ack != '+');
81 }
82
83 void
84 send_gdb_memory(
85 _In_ VOID* Buffer,
86 _In_ size_t Length)
87 {
88 UCHAR ack;
89
90 do {
91 CHAR* ptr = Buffer;
92 CHAR check_sum = 0;
93 size_t len = Length;
94 CHAR Byte;
95
96 KdpSendByte('$');
97
98 /* Send the data */
99 check_sum = 0;
100 while (len--)
101 {
102 Byte = hex_chars[(*ptr >> 4) & 0xf];
103 KdpSendByte(Byte);
104 check_sum += Byte;
105 Byte = hex_chars[*ptr++ & 0xf];
106 KdpSendByte(Byte);
107 check_sum += Byte;
108 }
109
110 /* append check sum */
111 KdpSendByte('#');
112 KdpSendByte(hex_chars[(check_sum >> 4) & 0xf]);
113 KdpSendByte(hex_chars[check_sum & 0xf]);
114
115 /* Wait for acknowledgement */
116 if (KdpReceiveByte(&ack) != KdPacketReceived)
117 {
118 KD_DEBUGGER_NOT_PRESENT = TRUE;
119 break;
120 }
121 } while (ack != '+');
122 }
123
124 void
125 gdb_send_debug_io(
126 _In_ PSTRING String)
127 {
128 UCHAR ack;
129
130 do {
131 CHAR* ptr = String->Buffer;
132 CHAR check_sum;
133 USHORT Length = String->Length;
134 CHAR Byte;
135
136 KdpSendByte('$');
137
138 KdpSendByte('O');
139
140 /* Send the data */
141 check_sum = 'O';
142 while (Length--)
143 {
144 Byte = hex_chars[(*ptr >> 4) & 0xf];
145 KdpSendByte(Byte);
146 check_sum += Byte;
147 Byte = hex_chars[*ptr++ & 0xf];
148 KdpSendByte(Byte);
149 check_sum += Byte;
150 }
151
152 /* append check sum */
153 KdpSendByte('#');
154 KdpSendByte(hex_chars[(check_sum >> 4) & 0xf]);
155 KdpSendByte(hex_chars[check_sum & 0xf]);
156
157 /* Wait for acknowledgement */
158 if (KdpReceiveByte(&ack) != KdPacketReceived)
159 {
160 KD_DEBUGGER_NOT_PRESENT = TRUE;
161 break;
162 }
163 } while (ack != '+');
164 }
165
166 void
167 gdb_send_exception(void)
168 {
169 char gdb_out[1024];
170 char* ptr = gdb_out;
171 DBGKM_EXCEPTION64* Exception = NULL;
172
173 if (CurrentStateChange.NewState == DbgKdExceptionStateChange)
174 Exception = &CurrentStateChange.u.Exception;
175
176 /* Report to GDB */
177 *ptr++ = 'T';
178 if (Exception)
179 ptr = exception_code_to_gdb(Exception->ExceptionRecord.ExceptionCode, ptr);
180 else
181 ptr += sprintf(ptr, "05");
182 ptr += sprintf(ptr, "thread:p%p.%p;",
183 PsGetThreadProcessId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread),
184 PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread));
185 ptr += sprintf(ptr, "core:%x;", CurrentStateChange.Processor);
186 send_gdb_packet(gdb_out);
187 }
188
189 #ifdef KDDEBUG
190 ULONG KdpDbgPrint(const char* Format, ...)
191 {
192 va_list ap;
193 CHAR Buffer[512];
194 struct _STRING Str;
195 int Length;
196
197 va_start(ap, Format);
198 Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
199 va_end(ap);
200
201 /* Check if we went past the buffer */
202 if (Length == -1)
203 {
204 /* Terminate it if we went over-board */
205 Buffer[sizeof(Buffer) - 1] = '\n';
206
207 /* Put maximum */
208 Length = sizeof(Buffer);
209 }
210
211 Str.Buffer = Buffer;
212 Str.Length = Length;
213 Str.MaximumLength = sizeof(Buffer);
214
215 gdb_send_debug_io(&Str);
216
217 return 0;
218 }
219 #endif
220