Sync with trunk r64222.
[reactos.git] / 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 PETHREAD Thread = (PETHREAD)(ULONG_PTR)CurrentStateChange.Thread;
172
173 /* Report to GDB */
174 *ptr++ = 'T';
175
176 if (CurrentStateChange.NewState == DbgKdExceptionStateChange)
177 {
178 EXCEPTION_RECORD64* ExceptionRecord = &CurrentStateChange.u.Exception.ExceptionRecord;
179 ptr = exception_code_to_gdb(ExceptionRecord->ExceptionCode, ptr);
180 }
181 else
182 ptr += sprintf(ptr, "05");
183
184 ptr += sprintf(ptr, "thread:p%" PRIxPTR ".%" PRIxPTR ";",
185 handle_to_gdb_pid(PsGetThreadProcessId(Thread)),
186 handle_to_gdb_tid(PsGetThreadId(Thread)));
187 ptr += sprintf(ptr, "core:%x;", CurrentStateChange.Processor);
188 send_gdb_packet(gdb_out);
189 }
190
191 void
192 send_gdb_ntstatus(
193 _In_ NTSTATUS Status)
194 {
195 /* Just build a EXX packet and send it */
196 char gdb_out[4];
197 gdb_out[0] = 'E';
198 exception_code_to_gdb(Status, &gdb_out[1]);
199 gdb_out[3] = '\0';
200 send_gdb_packet(gdb_out);
201 }