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 } 202