gdbstub.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. /******************************************************************************
  14. * Description: A stub to make the ESP32 debuggable by GDB over the serial
  15. * port, at least enough to do a backtrace on panic. This gdbstub is read-only:
  16. * it allows inspecting the ESP32 state
  17. *******************************************************************************/
  18. #include "rom/ets_sys.h"
  19. #include "soc/uart_reg.h"
  20. #include "soc/io_mux_reg.h"
  21. #include "esp_gdbstub.h"
  22. #include "driver/gpio.h"
  23. //Length of buffer used to reserve GDB commands. Has to be at least able to fit the G command, which
  24. //implies a minimum size of about 320 bytes.
  25. #define PBUFLEN 512
  26. static unsigned char cmd[PBUFLEN]; //GDB command input buffer
  27. static char chsum; //Running checksum of the output packet
  28. #define ATTR_GDBFN
  29. //Receive a char from the uart. Uses polling and feeds the watchdog.
  30. static int ATTR_GDBFN gdbRecvChar() {
  31. int i;
  32. while (((READ_PERI_REG(UART_STATUS_REG(0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT)==0) ;
  33. i=READ_PERI_REG(UART_FIFO_REG(0));
  34. return i;
  35. }
  36. //Send a char to the uart.
  37. static void ATTR_GDBFN gdbSendChar(char c) {
  38. while (((READ_PERI_REG(UART_STATUS_REG(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ;
  39. WRITE_PERI_REG(UART_FIFO_REG(0), c);
  40. }
  41. //Send the start of a packet; reset checksum calculation.
  42. static void ATTR_GDBFN gdbPacketStart() {
  43. chsum=0;
  44. gdbSendChar('$');
  45. }
  46. //Send a char as part of a packet
  47. static void ATTR_GDBFN gdbPacketChar(char c) {
  48. if (c=='#' || c=='$' || c=='}' || c=='*') {
  49. gdbSendChar('}');
  50. gdbSendChar(c^0x20);
  51. chsum+=(c^0x20)+'}';
  52. } else {
  53. gdbSendChar(c);
  54. chsum+=c;
  55. }
  56. }
  57. //Send a string as part of a packet
  58. static void ATTR_GDBFN gdbPacketStr(char *c) {
  59. while (*c!=0) {
  60. gdbPacketChar(*c);
  61. c++;
  62. }
  63. }
  64. //Send a hex val as part of a packet. 'bits'/4 dictates the number of hex chars sent.
  65. static void ATTR_GDBFN gdbPacketHex(int val, int bits) {
  66. char hexChars[]="0123456789abcdef";
  67. int i;
  68. for (i=bits; i>0; i-=4) {
  69. gdbPacketChar(hexChars[(val>>(i-4))&0xf]);
  70. }
  71. }
  72. //Finish sending a packet.
  73. static void ATTR_GDBFN gdbPacketEnd() {
  74. gdbSendChar('#');
  75. gdbPacketHex(chsum, 8);
  76. }
  77. //Error states used by the routines that grab stuff from the incoming gdb packet
  78. #define ST_ENDPACKET -1
  79. #define ST_ERR -2
  80. #define ST_OK -3
  81. #define ST_CONT -4
  82. //Grab a hex value from the gdb packet. Ptr will get positioned on the end
  83. //of the hex string, as far as the routine has read into it. Bits/4 indicates
  84. //the max amount of hex chars it gobbles up. Bits can be -1 to eat up as much
  85. //hex chars as possible.
  86. static long ATTR_GDBFN gdbGetHexVal(unsigned char **ptr, int bits) {
  87. int i;
  88. int no;
  89. unsigned int v=0;
  90. char c;
  91. no=bits/4;
  92. if (bits==-1) no=64;
  93. for (i=0; i<no; i++) {
  94. c=**ptr;
  95. (*ptr)++;
  96. if (c>='0' && c<='9') {
  97. v<<=4;
  98. v|=(c-'0');
  99. } else if (c>='A' && c<='F') {
  100. v<<=4;
  101. v|=(c-'A')+10;
  102. } else if (c>='a' && c<='f') {
  103. v<<=4;
  104. v|=(c-'a')+10;
  105. } else if (c=='#') {
  106. if (bits==-1) {
  107. (*ptr)--;
  108. return v;
  109. }
  110. return ST_ENDPACKET;
  111. } else {
  112. if (bits==-1) {
  113. (*ptr)--;
  114. return v;
  115. }
  116. return ST_ERR;
  117. }
  118. }
  119. return v;
  120. }
  121. //Swap an int into the form gdb wants it
  122. static int ATTR_GDBFN iswap(int i) {
  123. int r;
  124. r=((i>>24)&0xff);
  125. r|=((i>>16)&0xff)<<8;
  126. r|=((i>>8)&0xff)<<16;
  127. r|=((i>>0)&0xff)<<24;
  128. return r;
  129. }
  130. //Read a byte from ESP32 memory.
  131. static unsigned char ATTR_GDBFN readbyte(unsigned int p) {
  132. int *i=(int*)(p&(~3));
  133. if (p<0x20000000 || p>=0x80000000) return -1;
  134. return *i>>((p&3)*8);
  135. }
  136. //Register file in the format exp108 gdb port expects it.
  137. //Inspired by gdb/regformats/reg-xtensa.dat
  138. typedef struct {
  139. uint32_t pc;
  140. uint32_t a[64];
  141. uint32_t lbeg;
  142. uint32_t lend;
  143. uint32_t lcount;
  144. uint32_t sar;
  145. uint32_t windowbase;
  146. uint32_t windowstart;
  147. uint32_t configid0;
  148. uint32_t configid1;
  149. uint32_t ps;
  150. uint32_t threadptr;
  151. uint32_t br;
  152. uint32_t scompare1;
  153. uint32_t acclo;
  154. uint32_t acchi;
  155. uint32_t m0;
  156. uint32_t m1;
  157. uint32_t m2;
  158. uint32_t m3;
  159. uint32_t expstate; //I'm going to assume this is exccause...
  160. uint32_t f64r_lo;
  161. uint32_t f64r_hi;
  162. uint32_t f64s;
  163. uint32_t f[16];
  164. uint32_t fcr;
  165. uint32_t fsr;
  166. } GdbRegFile;
  167. GdbRegFile gdbRegFile;
  168. /*
  169. //Register format as the Xtensa HAL has it:
  170. STRUCT_FIELD (long, 4, XT_STK_EXIT, exit)
  171. STRUCT_FIELD (long, 4, XT_STK_PC, pc)
  172. STRUCT_FIELD (long, 4, XT_STK_PS, ps)
  173. STRUCT_FIELD (long, 4, XT_STK_A0, a0)
  174. [..]
  175. STRUCT_FIELD (long, 4, XT_STK_A15, a15)
  176. STRUCT_FIELD (long, 4, XT_STK_SAR, sar)
  177. STRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause)
  178. STRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr)
  179. STRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg)
  180. STRUCT_FIELD (long, 4, XT_STK_LEND, lend)
  181. STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount)
  182. // Temporary space for saving stuff during window spill
  183. STRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0)
  184. STRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1)
  185. STRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2)
  186. STRUCT_FIELD (long, 4, XT_STK_VPRI, vpri)
  187. STRUCT_FIELD (long, 4, XT_STK_OVLY, ovly)
  188. #endif
  189. STRUCT_END(XtExcFrame)
  190. */
  191. static void dumpHwToRegfile(XtExcFrame *frame) {
  192. int i;
  193. long *frameAregs=&frame->a0;
  194. gdbRegFile.pc=frame->pc;
  195. for (i=0; i<16; i++) gdbRegFile.a[i]=frameAregs[i];
  196. for (i=16; i<64; i++) gdbRegFile.a[i]=0xDEADBEEF;
  197. gdbRegFile.lbeg=frame->lbeg;
  198. gdbRegFile.lend=frame->lend;
  199. gdbRegFile.lcount=frame->lcount;
  200. gdbRegFile.sar=frame->sar;
  201. //All windows have been spilled to the stack by the ISR routines. The following values should indicate that.
  202. gdbRegFile.sar=frame->sar;
  203. gdbRegFile.windowbase=0; //0
  204. gdbRegFile.windowstart=0x1; //1
  205. gdbRegFile.configid0=0xdeadbeef; //ToDo
  206. gdbRegFile.configid1=0xdeadbeef; //ToDo
  207. gdbRegFile.ps=frame->ps-PS_EXCM_MASK;
  208. gdbRegFile.threadptr=0xdeadbeef; //ToDo
  209. gdbRegFile.br=0xdeadbeef; //ToDo
  210. gdbRegFile.scompare1=0xdeadbeef; //ToDo
  211. gdbRegFile.acclo=0xdeadbeef; //ToDo
  212. gdbRegFile.acchi=0xdeadbeef; //ToDo
  213. gdbRegFile.m0=0xdeadbeef; //ToDo
  214. gdbRegFile.m1=0xdeadbeef; //ToDo
  215. gdbRegFile.m2=0xdeadbeef; //ToDo
  216. gdbRegFile.m3=0xdeadbeef; //ToDo
  217. gdbRegFile.expstate=frame->exccause; //ToDo
  218. }
  219. //Send the reason execution is stopped to GDB.
  220. static void sendReason() {
  221. //exception-to-signal mapping
  222. char exceptionSignal[]={4,31,11,11,2,6,8,0,6,7,0,0,7,7,7,7};
  223. int i=0;
  224. gdbPacketStart();
  225. gdbPacketChar('T');
  226. i=gdbRegFile.expstate&0x7f;
  227. if (i<sizeof(exceptionSignal)) {
  228. gdbPacketHex(exceptionSignal[i], 8);
  229. } else {
  230. gdbPacketHex(11, 8);
  231. }
  232. gdbPacketEnd();
  233. }
  234. //Handle a command as received from GDB.
  235. static int gdbHandleCommand(unsigned char *cmd, int len) {
  236. //Handle a command
  237. int i, j, k;
  238. unsigned char *data=cmd+1;
  239. if (cmd[0]=='g') { //send all registers to gdb
  240. int *p=(int*)&gdbRegFile;
  241. gdbPacketStart();
  242. for (i=0; i<sizeof(GdbRegFile)/4; i++) gdbPacketHex(iswap(*p++), 32);
  243. gdbPacketEnd();
  244. } else if (cmd[0]=='G') { //receive content for all registers from gdb
  245. int *p=(int*)&gdbRegFile;
  246. for (i=0; i<sizeof(GdbRegFile)/4; i++) *p++=iswap(gdbGetHexVal(&data, 32));;
  247. gdbPacketStart();
  248. gdbPacketStr("OK");
  249. gdbPacketEnd();
  250. } else if (cmd[0]=='m') { //read memory to gdb
  251. i=gdbGetHexVal(&data, -1);
  252. data++;
  253. j=gdbGetHexVal(&data, -1);
  254. gdbPacketStart();
  255. for (k=0; k<j; k++) {
  256. gdbPacketHex(readbyte(i++), 8);
  257. }
  258. gdbPacketEnd();
  259. } else if (cmd[0]=='?') { //Reply with stop reason
  260. sendReason();
  261. } else {
  262. //We don't recognize or support whatever GDB just sent us.
  263. gdbPacketStart();
  264. gdbPacketEnd();
  265. return ST_ERR;
  266. }
  267. return ST_OK;
  268. }
  269. //Lower layer: grab a command packet and check the checksum
  270. //Calls gdbHandleCommand on the packet if the checksum is OK
  271. //Returns ST_OK on success, ST_ERR when checksum fails, a
  272. //character if it is received instead of the GDB packet
  273. //start char.
  274. static int gdbReadCommand() {
  275. unsigned char c;
  276. unsigned char chsum=0, rchsum;
  277. unsigned char sentchs[2];
  278. int p=0;
  279. unsigned char *ptr;
  280. c=gdbRecvChar();
  281. if (c!='$') return c;
  282. while(1) {
  283. c=gdbRecvChar();
  284. if (c=='#') { //end of packet, checksum follows
  285. cmd[p]=0;
  286. break;
  287. }
  288. chsum+=c;
  289. if (c=='$') {
  290. //Wut, restart packet?
  291. chsum=0;
  292. p=0;
  293. continue;
  294. }
  295. if (c=='}') { //escape the next char
  296. c=gdbRecvChar();
  297. chsum+=c;
  298. c^=0x20;
  299. }
  300. cmd[p++]=c;
  301. if (p>=PBUFLEN) return ST_ERR;
  302. }
  303. //A # has been received. Get and check the received chsum.
  304. sentchs[0]=gdbRecvChar();
  305. sentchs[1]=gdbRecvChar();
  306. ptr=&sentchs[0];
  307. rchsum=gdbGetHexVal(&ptr, 8);
  308. if (rchsum!=chsum) {
  309. gdbSendChar('-');
  310. return ST_ERR;
  311. } else {
  312. gdbSendChar('+');
  313. return gdbHandleCommand(cmd, p);
  314. }
  315. }
  316. void esp_gdbstub_panic_handler(XtExcFrame *frame) {
  317. dumpHwToRegfile(frame);
  318. //Make sure txd/rxd are enabled
  319. gpio_pullup_dis(1);
  320. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD);
  321. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD);
  322. sendReason();
  323. while(gdbReadCommand()!=ST_CONT);
  324. while(1);
  325. }