gdbstub.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. /******************************************************************************
  2. * Copyright 2015 Espressif Systems
  3. *
  4. * Description: A stub to make the ESP8266 debuggable by GDB over the serial
  5. * port.
  6. *
  7. * License: ESPRESSIF MIT License
  8. *******************************************************************************/
  9. #include "gdbstub.h"
  10. #include "ets_sys.h"
  11. #include "eagle_soc.h"
  12. #include "c_types.h"
  13. #include "gpio.h"
  14. #include "xtensa/corebits.h"
  15. #include "driver/uart.h"
  16. #include "gdbstub.h"
  17. #include "gdbstub-entry.h"
  18. #include "gdbstub-cfg.h"
  19. //From xtruntime-frames.h
  20. struct XTensa_exception_frame_s {
  21. uint32_t pc;
  22. uint32_t ps;
  23. uint32_t sar;
  24. uint32_t vpri;
  25. uint32_t a0;
  26. uint32_t a[14]; //a2..a15
  27. //These are added manually by the exception code; the HAL doesn't set these on an exception.
  28. uint32_t litbase;
  29. uint32_t sr176;
  30. uint32_t sr208;
  31. uint32_t a1;
  32. //'reason' is abused for both the debug and the exception vector: if bit 7 is set,
  33. //this contains an exception reason, otherwise it contains a debug vector bitmap.
  34. uint32_t reason;
  35. };
  36. struct XTensa_rtos_int_frame_s {
  37. uint32_t exitPtr;
  38. uint32_t pc;
  39. uint32_t ps;
  40. uint32_t a[16];
  41. uint32_t sar;
  42. };
  43. #if GDBSTUB_FREERTOS
  44. /*
  45. Definitions for FreeRTOS. This redefines some os_* functions to use their non-os* counterparts. It
  46. also sets up some function pointers for ROM functions that aren't in the FreeRTOS ld files.
  47. */
  48. #include <string.h>
  49. #include <stdio.h>
  50. void _xt_isr_attach(int inum, void *fn);
  51. void _xt_isr_unmask(int inum);
  52. void os_install_putc1(void (*p)(char c));
  53. #define os_printf(...) printf(__VA_ARGS__)
  54. #define os_memcpy(a,b,c) memcpy(a,b,c)
  55. typedef void wdtfntype();
  56. static wdtfntype *ets_wdt_disable=(wdtfntype *)0x400030f0;
  57. static wdtfntype *ets_wdt_enable=(wdtfntype *)0x40002fa0;
  58. #else
  59. /*
  60. OS-less SDK defines. Defines some headers for things that aren't in the include files, plus
  61. the xthal stack frame struct.
  62. */
  63. #include "osapi.h"
  64. #include "user_interface.h"
  65. //void _xtos_set_exception_handler(int cause, void (exhandler)(struct XTensa_exception_frame_s *frame));
  66. int os_printf_plus(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
  67. extern void xthal_set_intenable(int);
  68. #endif
  69. #define EXCEPTION_GDB_SP_OFFSET 0x100
  70. //We need some UART register defines.
  71. #define ETS_UART_INUM 5
  72. #define REG_UART_BASE( i ) (0x60000000+(i)*0xf00)
  73. #define UART_STATUS( i ) (REG_UART_BASE( i ) + 0x1C)
  74. #define UART_RXFIFO_CNT 0x000000FF
  75. #define UART_RXFIFO_CNT_S 0
  76. #define UART_TXFIFO_CNT 0x000000FF
  77. #define UART_TXFIFO_CNT_S 16
  78. #define UART_FIFO( i ) (REG_UART_BASE( i ) + 0x0)
  79. //#define UART_INT_ENA(i) (REG_UART_BASE(i) + 0xC)
  80. //#define UART_INT_CLR(i) (REG_UART_BASE(i) + 0x10)
  81. #define UART_RXFIFO_TOUT_INT_ENA (BIT(8))
  82. #define UART_RXFIFO_FULL_INT_ENA (BIT(0))
  83. #define UART_RXFIFO_TOUT_INT_CLR (BIT(8))
  84. #define UART_RXFIFO_FULL_INT_CLR (BIT(0))
  85. //Length of buffer used to reserve GDB commands. Has to be at least able to fit the G command, which
  86. //implies a minimum size of about 190 bytes.
  87. #define PBUFLEN 256
  88. //Length of gdb stdout buffer, for console redirection
  89. #define OBUFLEN 32
  90. //The asm stub saves the Xtensa registers here when a debugging exception happens.
  91. struct XTensa_exception_frame_s gdbstub_savedRegs;
  92. #if GDBSTUB_USE_OWN_STACK
  93. //This is the debugging exception stack.
  94. int exceptionStack[256];
  95. #endif
  96. static unsigned char cmd[PBUFLEN]; //GDB command input buffer
  97. static char chsum; //Running checksum of the output packet
  98. static unsigned char obuf[OBUFLEN]; //GDB stdout buffer
  99. static int obufpos=0; //Current position in the buffer
  100. static int32_t singleStepPs=-1; //Stores ps when single-stepping instruction. -1 when not in use.
  101. //Small function to feed the hardware watchdog. Needed to stop the ESP from resetting
  102. //due to a watchdog timeout while reading a command.
  103. static void ATTR_GDBFN keepWDTalive() {
  104. uint64_t *wdtval=(uint64_t*)0x3ff21048;
  105. uint64_t *wdtovf=(uint64_t*)0x3ff210cc;
  106. int *wdtctl=(int*)0x3ff210c8;
  107. *wdtovf=*wdtval+1600000;
  108. *wdtctl|=(1<<31);
  109. }
  110. //Receive a char from the uart. Uses polling and feeds the watchdog.
  111. static int ATTR_GDBFN gdbRecvChar() {
  112. int i;
  113. while (((READ_PERI_REG(UART_STATUS(0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT)==0) {
  114. keepWDTalive();
  115. }
  116. i=READ_PERI_REG(UART_FIFO(0));
  117. return i;
  118. }
  119. //Send a char to the uart.
  120. static void ATTR_GDBFN gdbSendChar(char c) {
  121. while (((READ_PERI_REG(UART_STATUS(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ;
  122. WRITE_PERI_REG(UART_FIFO(0), c);
  123. }
  124. //Send the start of a packet; reset checksum calculation.
  125. static void ATTR_GDBFN gdbPacketStart() {
  126. chsum=0;
  127. gdbSendChar('$');
  128. }
  129. //Send a char as part of a packet
  130. static void ATTR_GDBFN gdbPacketChar(char c) {
  131. if (c=='#' || c=='$' || c=='}' || c=='*') {
  132. gdbSendChar('}');
  133. gdbSendChar(c^0x20);
  134. chsum+=(c^0x20)+'}';
  135. } else {
  136. gdbSendChar(c);
  137. chsum+=c;
  138. }
  139. }
  140. //Send a string as part of a packet
  141. static void ATTR_GDBFN gdbPacketStr(char *c) {
  142. while (*c!=0) {
  143. gdbPacketChar(*c);
  144. c++;
  145. }
  146. }
  147. //Send a hex val as part of a packet. 'bits'/4 dictates the number of hex chars sent.
  148. static void ATTR_GDBFN gdbPacketHex(int val, int bits) {
  149. char hexChars[]="0123456789abcdef";
  150. int i;
  151. for (i=bits; i>0; i-=4) {
  152. gdbPacketChar(hexChars[(val>>(i-4))&0xf]);
  153. }
  154. }
  155. //Finish sending a packet.
  156. static void ATTR_GDBFN gdbPacketEnd() {
  157. gdbSendChar('#');
  158. gdbPacketHex(chsum, 8);
  159. }
  160. //Error states used by the routines that grab stuff from the incoming gdb packet
  161. #define ST_ENDPACKET -1
  162. #define ST_ERR -2
  163. #define ST_OK -3
  164. #define ST_CONT -4
  165. //Grab a hex value from the gdb packet. Ptr will get positioned on the end
  166. //of the hex string, as far as the routine has read into it. Bits/4 indicates
  167. //the max amount of hex chars it gobbles up. Bits can be -1 to eat up as much
  168. //hex chars as possible.
  169. static long ATTR_GDBFN gdbGetHexVal(unsigned char **ptr, int bits) {
  170. int i;
  171. int no;
  172. unsigned int v=0;
  173. char c;
  174. no=bits/4;
  175. if (bits==-1) no=64;
  176. for (i=0; i<no; i++) {
  177. c=**ptr;
  178. (*ptr)++;
  179. if (c>='0' && c<='9') {
  180. v<<=4;
  181. v|=(c-'0');
  182. } else if (c>='A' && c<='F') {
  183. v<<=4;
  184. v|=(c-'A')+10;
  185. } else if (c>='a' && c<='f') {
  186. v<<=4;
  187. v|=(c-'a')+10;
  188. } else if (c=='#') {
  189. if (bits==-1) {
  190. (*ptr)--;
  191. return v;
  192. }
  193. return ST_ENDPACKET;
  194. } else {
  195. if (bits==-1) {
  196. (*ptr)--;
  197. return v;
  198. }
  199. return ST_ERR;
  200. }
  201. }
  202. return v;
  203. }
  204. //Swap an int into the form gdb wants it
  205. static int ATTR_GDBFN iswap(int i) {
  206. int r;
  207. r=((i>>24)&0xff);
  208. r|=((i>>16)&0xff)<<8;
  209. r|=((i>>8)&0xff)<<16;
  210. r|=((i>>0)&0xff)<<24;
  211. return r;
  212. }
  213. //Read a byte from the ESP8266 memory.
  214. static unsigned char ATTR_GDBFN readbyte(unsigned int p) {
  215. int *i=(int*)(p&(~3));
  216. if (p<0x20000000 || p>=0x60000000) return -1;
  217. return *i>>((p&3)*8);
  218. }
  219. //Write a byte to the ESP8266 memory.
  220. static void ATTR_GDBFN writeByte(unsigned int p, unsigned char d) {
  221. int *i=(int*)(p&(~3));
  222. if (p<0x20000000 || p>=0x60000000) return;
  223. if ((p&3)==0) *i=(*i&0xffffff00)|(d<<0);
  224. if ((p&3)==1) *i=(*i&0xffff00ff)|(d<<8);
  225. if ((p&3)==2) *i=(*i&0xff00ffff)|(d<<16);
  226. if ((p&3)==3) *i=(*i&0x00ffffff)|(d<<24);
  227. }
  228. //Returns 1 if it makes sense to write to addr p
  229. static int ATTR_GDBFN validWrAddr(int p) {
  230. if (p>=0x3ff00000 && p<0x40000000) return 1;
  231. if (p>=0x40100000 && p<0x40140000) return 1;
  232. if (p>=0x60000000 && p<0x60002000) return 1;
  233. return 0;
  234. }
  235. /*
  236. Register file in the format lx106 gdb port expects it.
  237. Inspired by gdb/regformats/reg-xtensa.dat from
  238. https://github.com/jcmvbkbc/crosstool-NG/blob/lx106-g%2B%2B/overlays/xtensa_lx106.tar
  239. As decoded by Cesanta.
  240. */
  241. struct regfile {
  242. uint32_t a[16];
  243. uint32_t pc;
  244. uint32_t sar;
  245. uint32_t litbase;
  246. uint32_t sr176;
  247. uint32_t sr208;
  248. uint32_t ps;
  249. };
  250. //Send the reason execution is stopped to GDB.
  251. static void ATTR_GDBFN sendReason() {
  252. #if 0
  253. char *reason=""; //default
  254. #endif
  255. //exception-to-signal mapping
  256. char exceptionSignal[]={4,31,11,11,2,6,8,0,6,7,0,0,7,7,7,7};
  257. int i=0;
  258. gdbPacketStart();
  259. gdbPacketChar('T');
  260. if (gdbstub_savedRegs.reason==0xff) {
  261. gdbPacketHex(2, 8); //sigint
  262. } else if (gdbstub_savedRegs.reason&0x80) {
  263. //We stopped because of an exception. Convert exception code to a signal number and send it.
  264. i=gdbstub_savedRegs.reason&0x7f;
  265. if (i<sizeof(exceptionSignal)) gdbPacketHex(exceptionSignal[i], 8); else gdbPacketHex(11, 8);
  266. } else {
  267. //We stopped because of a debugging exception.
  268. gdbPacketHex(5, 8); //sigtrap
  269. //Current Xtensa GDB versions don't seem to request this, so let's leave it off.
  270. #if 0
  271. if (gdbstub_savedRegs.reason&(1<<0)) reason="break";
  272. if (gdbstub_savedRegs.reason&(1<<1)) reason="hwbreak";
  273. if (gdbstub_savedRegs.reason&(1<<2)) reason="watch";
  274. if (gdbstub_savedRegs.reason&(1<<3)) reason="swbreak";
  275. if (gdbstub_savedRegs.reason&(1<<4)) reason="swbreak";
  276. gdbPacketStr(reason);
  277. gdbPacketChar(':');
  278. //ToDo: watch: send address
  279. #endif
  280. }
  281. gdbPacketEnd();
  282. }
  283. //Handle a command as received from GDB.
  284. static int ATTR_GDBFN gdbHandleCommand(unsigned char *cmd, int len) {
  285. //Handle a command
  286. int i, j, k;
  287. unsigned char *data=cmd+1;
  288. if (cmd[0]=='g') { //send all registers to gdb
  289. gdbPacketStart();
  290. gdbPacketHex(iswap(gdbstub_savedRegs.a0), 32);
  291. gdbPacketHex(iswap(gdbstub_savedRegs.a1), 32);
  292. for (i=2; i<16; i++) gdbPacketHex(iswap(gdbstub_savedRegs.a[i-2]), 32);
  293. gdbPacketHex(iswap(gdbstub_savedRegs.pc), 32);
  294. gdbPacketHex(iswap(gdbstub_savedRegs.sar), 32);
  295. gdbPacketHex(iswap(gdbstub_savedRegs.litbase), 32);
  296. gdbPacketHex(iswap(gdbstub_savedRegs.sr176), 32);
  297. gdbPacketHex(0, 32);
  298. gdbPacketHex(iswap(gdbstub_savedRegs.ps), 32);
  299. gdbPacketEnd();
  300. } else if (cmd[0]=='G') { //receive content for all registers from gdb
  301. gdbstub_savedRegs.a0=iswap(gdbGetHexVal(&data, 32));
  302. gdbstub_savedRegs.a1=iswap(gdbGetHexVal(&data, 32));
  303. for (i=2; i<16; i++) gdbstub_savedRegs.a[i-2]=iswap(gdbGetHexVal(&data, 32));
  304. gdbstub_savedRegs.pc=iswap(gdbGetHexVal(&data, 32));
  305. gdbstub_savedRegs.sar=iswap(gdbGetHexVal(&data, 32));
  306. gdbstub_savedRegs.litbase=iswap(gdbGetHexVal(&data, 32));
  307. gdbstub_savedRegs.sr176=iswap(gdbGetHexVal(&data, 32));
  308. gdbGetHexVal(&data, 32);
  309. gdbstub_savedRegs.ps=iswap(gdbGetHexVal(&data, 32));
  310. gdbPacketStart();
  311. gdbPacketStr("OK");
  312. gdbPacketEnd();
  313. } else if (cmd[0]=='m') { //read memory to gdb
  314. i=gdbGetHexVal(&data, -1);
  315. data++;
  316. j=gdbGetHexVal(&data, -1);
  317. gdbPacketStart();
  318. for (k=0; k<j; k++) {
  319. gdbPacketHex(readbyte(i++), 8);
  320. }
  321. gdbPacketEnd();
  322. } else if (cmd[0]=='M') { //write memory from gdb
  323. i=gdbGetHexVal(&data, -1); //addr
  324. data++; //skip ,
  325. j=gdbGetHexVal(&data, -1); //length
  326. data++; //skip :
  327. if (validWrAddr(i) && validWrAddr(i+j)) {
  328. for (k=0; k<j; k++) {
  329. writeByte(i, gdbGetHexVal(&data, 8));
  330. i++;
  331. }
  332. //Make sure caches are up-to-date. Procedure according to Xtensa ISA document, ISYNC inst desc.
  333. asm volatile("ISYNC\nISYNC\n");
  334. gdbPacketStart();
  335. gdbPacketStr("OK");
  336. gdbPacketEnd();
  337. } else {
  338. //Trying to do a software breakpoint on a flash proc, perhaps?
  339. gdbPacketStart();
  340. gdbPacketStr("E01");
  341. gdbPacketEnd();
  342. }
  343. } else if (cmd[0]=='?') { //Reply with stop reason
  344. sendReason();
  345. // } else if (strncmp(cmd, "vCont?", 6)==0) {
  346. // gdbPacketStart();
  347. // gdbPacketStr("vCont;c;s");
  348. // gdbPacketEnd();
  349. } else if (strncmp((char*)cmd, "vCont;c", 7)==0 || cmd[0]=='c') { //continue execution
  350. return ST_CONT;
  351. } else if (strncmp((char*)cmd, "vCont;s", 7)==0 || cmd[0]=='s') { //single-step instruction
  352. //Single-stepping can go wrong if an interrupt is pending, especially when it is e.g. a task switch:
  353. //the ICOUNT register will overflow in the task switch code. That is why we disable interupts when
  354. //doing single-instruction stepping.
  355. singleStepPs=gdbstub_savedRegs.ps;
  356. gdbstub_savedRegs.ps=(gdbstub_savedRegs.ps & ~0xf)|(XCHAL_DEBUGLEVEL-1);
  357. gdbstub_icount_ena_single_step();
  358. return ST_CONT;
  359. } else if (cmd[0]=='q') { //Extended query
  360. if (strncmp((char*)&cmd[1], "Supported", 9)==0) { //Capabilities query
  361. gdbPacketStart();
  362. gdbPacketStr("swbreak+;hwbreak+;PacketSize=255");
  363. gdbPacketEnd();
  364. } else {
  365. //We don't support other queries.
  366. gdbPacketStart();
  367. gdbPacketEnd();
  368. return ST_ERR;
  369. }
  370. } else if (cmd[0]=='Z') { //Set hardware break/watchpoint.
  371. data+=2; //skip 'x,'
  372. i=gdbGetHexVal(&data, -1);
  373. data++; //skip ','
  374. j=gdbGetHexVal(&data, -1);
  375. gdbPacketStart();
  376. if (cmd[1]=='1') { //Set breakpoint
  377. if (gdbstub_set_hw_breakpoint(i, j)) {
  378. gdbPacketStr("OK");
  379. } else {
  380. gdbPacketStr("E01");
  381. }
  382. } else if (cmd[1]=='2' || cmd[1]=='3' || cmd[1]=='4') { //Set watchpoint
  383. int access=0;
  384. int mask=0;
  385. if (cmd[1]=='2') access=2; //write
  386. if (cmd[1]=='3') access=1; //read
  387. if (cmd[1]=='4') access=3; //access
  388. if (j==1) mask=0x3F;
  389. if (j==2) mask=0x3E;
  390. if (j==4) mask=0x3C;
  391. if (j==8) mask=0x38;
  392. if (j==16) mask=0x30;
  393. if (j==32) mask=0x20;
  394. if (j==64) mask=0x00;
  395. if (mask!=0 && gdbstub_set_hw_watchpoint(i,mask, access)) {
  396. gdbPacketStr("OK");
  397. } else {
  398. gdbPacketStr("E01");
  399. }
  400. }
  401. gdbPacketEnd();
  402. } else if (cmd[0]=='z') { //Clear hardware break/watchpoint
  403. data+=2; //skip 'x,'
  404. i=gdbGetHexVal(&data, -1);
  405. data++; //skip ','
  406. j=gdbGetHexVal(&data, -1);
  407. gdbPacketStart();
  408. if (cmd[1]=='1') { //hardware breakpoint
  409. if (gdbstub_del_hw_breakpoint(i)) {
  410. gdbPacketStr("OK");
  411. } else {
  412. gdbPacketStr("E01");
  413. }
  414. } else if (cmd[1]=='2' || cmd[1]=='3' || cmd[1]=='4') { //hardware watchpoint
  415. if (gdbstub_del_hw_watchpoint(i)) {
  416. gdbPacketStr("OK");
  417. } else {
  418. gdbPacketStr("E01");
  419. }
  420. }
  421. gdbPacketEnd();
  422. } else {
  423. //We don't recognize or support whatever GDB just sent us.
  424. gdbPacketStart();
  425. gdbPacketEnd();
  426. return ST_ERR;
  427. }
  428. return ST_OK;
  429. }
  430. //Lower layer: grab a command packet and check the checksum
  431. //Calls gdbHandleCommand on the packet if the checksum is OK
  432. //Returns ST_OK on success, ST_ERR when checksum fails, a
  433. //character if it is received instead of the GDB packet
  434. //start char.
  435. static int ATTR_GDBFN gdbReadCommand() {
  436. unsigned char c;
  437. unsigned char chsum=0, rchsum;
  438. unsigned char sentchs[2];
  439. int p=0;
  440. unsigned char *ptr;
  441. c=gdbRecvChar();
  442. if (c!='$') return c;
  443. while(1) {
  444. c=gdbRecvChar();
  445. if (c=='#') { //end of packet, checksum follows
  446. cmd[p]=0;
  447. break;
  448. }
  449. chsum+=c;
  450. if (c=='$') {
  451. //Wut, restart packet?
  452. chsum=0;
  453. p=0;
  454. continue;
  455. }
  456. if (c=='}') { //escape the next char
  457. c=gdbRecvChar();
  458. chsum+=c;
  459. c^=0x20;
  460. }
  461. cmd[p++]=c;
  462. if (p>=PBUFLEN) return ST_ERR;
  463. }
  464. //A # has been received. Get and check the received chsum.
  465. sentchs[0]=gdbRecvChar();
  466. sentchs[1]=gdbRecvChar();
  467. ptr=&sentchs[0];
  468. rchsum=gdbGetHexVal(&ptr, 8);
  469. // os_printf("c %x r %x\n", chsum, rchsum);
  470. if (rchsum!=chsum) {
  471. gdbSendChar('-');
  472. return ST_ERR;
  473. } else {
  474. gdbSendChar('+');
  475. return gdbHandleCommand(cmd, p);
  476. }
  477. }
  478. //Get the value of one of the A registers
  479. static unsigned int ATTR_GDBFN getaregval(int reg) {
  480. if (reg==0) return gdbstub_savedRegs.a0;
  481. if (reg==1) return gdbstub_savedRegs.a1;
  482. return gdbstub_savedRegs.a[reg-2];
  483. }
  484. //Set the value of one of the A registers
  485. static void ATTR_GDBFN setaregval(int reg, unsigned int val) {
  486. os_printf("%x -> %x\n", val, reg);
  487. if (reg==0) gdbstub_savedRegs.a0=val;
  488. if (reg==1) gdbstub_savedRegs.a1=val;
  489. gdbstub_savedRegs.a[reg-2]=val;
  490. }
  491. //Emulate the l32i/s32i instruction we're stopped at.
  492. static void ATTR_GDBFN emulLdSt() {
  493. unsigned char i0=readbyte(gdbstub_savedRegs.pc);
  494. unsigned char i1=readbyte(gdbstub_savedRegs.pc+1);
  495. unsigned char i2=readbyte(gdbstub_savedRegs.pc+2);
  496. int *p;
  497. if ((i0&0xf)==2 && (i1&0xf0)==0x20) {
  498. //l32i
  499. p=(int*)getaregval(i1&0xf)+(i2*4);
  500. setaregval(i0>>4, *p);
  501. gdbstub_savedRegs.pc+=3;
  502. } else if ((i0&0xf)==0x8) {
  503. //l32i.n
  504. p=(int*)getaregval(i1&0xf)+((i1>>4)*4);
  505. setaregval(i0>>4, *p);
  506. gdbstub_savedRegs.pc+=2;
  507. } else if ((i0&0xf)==2 && (i1&0xf0)==0x60) {
  508. //s32i
  509. p=(int*)getaregval(i1&0xf)+(i2*4);
  510. *p=getaregval(i0>>4);
  511. gdbstub_savedRegs.pc+=3;
  512. } else if ((i0&0xf)==0x9) {
  513. //s32i.n
  514. p=(int*)getaregval(i1&0xf)+((i1>>4)*4);
  515. *p=getaregval(i0>>4);
  516. gdbstub_savedRegs.pc+=2;
  517. } else {
  518. os_printf("GDBSTUB: No l32i/s32i instruction: %x %x %x. Huh?", i2, i1, i0);
  519. }
  520. }
  521. //We just caught a debug exception and need to handle it. This is called from an assembly
  522. //routine in gdbstub-entry.S
  523. void ATTR_GDBFN gdbstub_handle_debug_exception() {
  524. ets_wdt_disable();
  525. if (singleStepPs!=-1) {
  526. //We come here after single-stepping an instruction. Interrupts are disabled
  527. //for the single step. Re-enable them here.
  528. gdbstub_savedRegs.ps=(gdbstub_savedRegs.ps&~0xf)|(singleStepPs&0xf);
  529. singleStepPs=-1;
  530. }
  531. sendReason();
  532. xthal_set_intenable(0);
  533. while(gdbReadCommand()!=ST_CONT);
  534. if ((gdbstub_savedRegs.reason&0x84)==0x4) {
  535. //We stopped due to a watchpoint. We can't re-execute the current instruction
  536. //because it will happily re-trigger the same watchpoint, so we emulate it
  537. //while we're still in debugger space.
  538. emulLdSt();
  539. } else if ((gdbstub_savedRegs.reason&0x88)==0x8) {
  540. //We stopped due to a BREAK instruction. Skip over it.
  541. //Check the instruction first; gdb may have replaced it with the original instruction
  542. //if it's one of the breakpoints it set.
  543. if (readbyte(gdbstub_savedRegs.pc+2)==0 &&
  544. (readbyte(gdbstub_savedRegs.pc+1)&0xf0)==0x40 &&
  545. (readbyte(gdbstub_savedRegs.pc)&0x0f)==0x00) {
  546. gdbstub_savedRegs.pc+=3;
  547. }
  548. } else if ((gdbstub_savedRegs.reason&0x90)==0x10) {
  549. //We stopped due to a BREAK.N instruction. Skip over it, after making sure the instruction
  550. //actually is a BREAK.N
  551. if ((readbyte(gdbstub_savedRegs.pc+1)&0xf0)==0xf0 &&
  552. readbyte(gdbstub_savedRegs.pc)==0x2d) {
  553. gdbstub_savedRegs.pc+=3;
  554. }
  555. }
  556. ets_wdt_enable();
  557. }
  558. #if GDBSTUB_FREERTOS
  559. //Freetos exception. This routine is called by an assembly routine in gdbstub-entry.S
  560. void ATTR_GDBFN gdbstub_handle_user_exception() {
  561. ets_wdt_disable();
  562. gdbstub_savedRegs.reason|=0x80; //mark as an exception reason
  563. sendReason();
  564. while(gdbReadCommand()!=ST_CONT);
  565. ets_wdt_enable();
  566. }
  567. #else
  568. //Non-OS exception handler. Gets called by the Xtensa HAL.
  569. static void ATTR_GDBFN gdb_exception_handler(struct XTensa_exception_frame_s *frame) {
  570. //Save the extra registers the Xtensa HAL doesn't save
  571. gdbstub_save_extra_sfrs_for_exception();
  572. //Copy registers the Xtensa HAL did save to gdbstub_savedRegs
  573. os_memcpy(&gdbstub_savedRegs, frame, 19*4);
  574. //Credits go to Cesanta for this trick. A1 seems to be destroyed, but because it
  575. //has a fixed offset from the address of the passed frame, we can recover it.
  576. gdbstub_savedRegs.a1=(uint32_t)frame+EXCEPTION_GDB_SP_OFFSET;
  577. gdbstub_savedRegs.reason|=0x80; //mark as an exception reason
  578. ets_wdt_disable();
  579. sendReason();
  580. xthal_set_intenable(0);
  581. while(gdbReadCommand()!=ST_CONT);
  582. ets_wdt_enable();
  583. //Copy any changed registers back to the frame the Xtensa HAL uses.
  584. os_memcpy(frame, &gdbstub_savedRegs, 19*4);
  585. }
  586. #endif
  587. static void ATTR_GDBFN gdb_flush_output_buffer() {
  588. if (obufpos > 0) {
  589. int i;
  590. gdbPacketStart();
  591. gdbPacketChar('O');
  592. for (i=0; i<obufpos; i++) gdbPacketHex(obuf[i], 8);
  593. gdbPacketEnd();
  594. obufpos=0;
  595. }
  596. }
  597. //Replacement putchar1 routine. Instead of spitting out the character directly, it will buffer up to
  598. //OBUFLEN characters (or up to a \n, whichever comes earlier) and send it out as a gdb stdout packet.
  599. static void ATTR_GDBFN gdb_semihost_putchar1(char c) {
  600. obuf[obufpos++]=c;
  601. if (c=='\n' || obufpos==OBUFLEN) {
  602. gdb_flush_output_buffer();
  603. }
  604. }
  605. #if !GDBSTUB_FREERTOS
  606. //The OS-less SDK uses the Xtensa HAL to handle exceptions. We can use those functions to catch any
  607. //fatal exceptions and invoke the debugger when this happens.
  608. static void ATTR_GDBINIT install_exceptions() {
  609. int i;
  610. int exno[]={EXCCAUSE_ILLEGAL, EXCCAUSE_SYSCALL, EXCCAUSE_INSTR_ERROR, EXCCAUSE_LOAD_STORE_ERROR,
  611. EXCCAUSE_DIVIDE_BY_ZERO, EXCCAUSE_UNALIGNED, EXCCAUSE_INSTR_DATA_ERROR, EXCCAUSE_LOAD_STORE_DATA_ERROR,
  612. EXCCAUSE_INSTR_ADDR_ERROR, EXCCAUSE_LOAD_STORE_ADDR_ERROR, EXCCAUSE_INSTR_PROHIBITED,
  613. EXCCAUSE_LOAD_PROHIBITED, EXCCAUSE_STORE_PROHIBITED};
  614. for (i=0; i<(sizeof(exno)/sizeof(exno[0])); i++) {
  615. _xtos_set_exception_handler(exno[i], (exception_handler_fn) gdb_exception_handler);
  616. }
  617. }
  618. #else
  619. //FreeRTOS doesn't use the Xtensa HAL for exceptions, but uses its own fatal exception handler.
  620. //We use a small hack to replace that with a jump to our own handler, which then has the task of
  621. //decyphering and re-instating the registers the FreeRTOS code left.
  622. extern void user_fatal_exception_handler();
  623. extern void gdbstub_user_exception_entry();
  624. static void ATTR_GDBINIT install_exceptions() {
  625. //Replace the user_fatal_exception_handler by a jump to our own code
  626. int *ufe=(int*)user_fatal_exception_handler;
  627. //This mess encodes as a relative jump instruction to user_fatal_exception_handler
  628. *ufe=((((int)gdbstub_user_exception_entry-(int)user_fatal_exception_handler)-4)<<6)|6;
  629. }
  630. #endif
  631. #if GDBSTUB_CTRLC_BREAK
  632. #if !GDBSTUB_FREERTOS
  633. static void ATTR_GDBFN uart_hdlr(void *arg, void *frame) {
  634. int doDebug=0, fifolen=0;
  635. //Save the extra registers the Xtensa HAL doesn't save
  636. gdbstub_save_extra_sfrs_for_exception();
  637. fifolen=(READ_PERI_REG(UART_STATUS(0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
  638. while (fifolen!=0) {
  639. if ((READ_PERI_REG(UART_FIFO(0)) & 0xFF)==0x3) doDebug=1; //Check if any of the chars is control-C. Throw away rest.
  640. fifolen--;
  641. }
  642. WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_FULL_INT_CLR|UART_RXFIFO_TOUT_INT_CLR);
  643. if (doDebug) {
  644. //Copy registers the Xtensa HAL did save to gdbstub_savedRegs
  645. os_memcpy(&gdbstub_savedRegs, frame, 19*4);
  646. gdbstub_savedRegs.a1=(uint32_t)frame+EXCEPTION_GDB_SP_OFFSET;
  647. gdbstub_savedRegs.reason=0xff; //mark as user break reason
  648. ets_wdt_disable();
  649. sendReason();
  650. xthal_set_intenable(0);
  651. while(gdbReadCommand()!=ST_CONT);
  652. ets_wdt_enable();
  653. //Copy any changed registers back to the frame the Xtensa HAL uses.
  654. os_memcpy(frame, &gdbstub_savedRegs, 19*4);
  655. }
  656. }
  657. static void ATTR_GDBINIT install_uart_hdlr() {
  658. ets_isr_attach(ETS_UART_INUM, uart_hdlr, NULL);
  659. SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
  660. ets_isr_unmask((1<<ETS_UART_INUM)); //enable uart interrupt
  661. }
  662. #else
  663. void ATTR_GDBFN gdbstub_handle_uart_int(struct XTensa_rtos_int_frame_s *frame) {
  664. int doDebug=0, fifolen=0, x;
  665. fifolen=(READ_PERI_REG(UART_STATUS(0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
  666. while (fifolen!=0) {
  667. if ((READ_PERI_REG(UART_FIFO(0)) & 0xFF)==0x3) doDebug=1; //Check if any of the chars is control-C. Throw away rest.
  668. fifolen--;
  669. }
  670. WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_FULL_INT_CLR|UART_RXFIFO_TOUT_INT_CLR);
  671. if (doDebug) {
  672. //Copy registers the Xtensa HAL did save to gdbstub_savedRegs
  673. gdbstub_savedRegs.pc=frame->pc;
  674. gdbstub_savedRegs.ps=frame->ps;
  675. gdbstub_savedRegs.sar=frame->sar;
  676. gdbstub_savedRegs.a0=frame->a[0];
  677. gdbstub_savedRegs.a1=frame->a[1];
  678. for (x=2; x<16; x++) gdbstub_savedRegs.a[x-2]=frame->a[x];
  679. // gdbstub_savedRegs.a1=(uint32_t)frame+EXCEPTION_GDB_SP_OFFSET;
  680. gdbstub_savedRegs.reason=0xff; //mark as user break reason
  681. // ets_wdt_disable();
  682. sendReason();
  683. while(gdbReadCommand()!=ST_CONT);
  684. // ets_wdt_enable();
  685. //Copy any changed registers back to the frame the Xtensa HAL uses.
  686. frame->pc=gdbstub_savedRegs.pc;
  687. frame->ps=gdbstub_savedRegs.ps;
  688. frame->sar=gdbstub_savedRegs.sar;
  689. frame->a[0]=gdbstub_savedRegs.a0;
  690. frame->a[1]=gdbstub_savedRegs.a1;
  691. for (x=2; x<16; x++) frame->a[x]=gdbstub_savedRegs.a[x-2];
  692. }
  693. }
  694. static void ATTR_GDBINIT install_uart_hdlr() {
  695. _xt_isr_attach(ETS_UART_INUM, gdbstub_uart_entry);
  696. SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
  697. _xt_isr_unmask((1<<ETS_UART_INUM)); //enable uart interrupt
  698. }
  699. #endif
  700. #endif
  701. void ATTR_GDBINIT gdbstub_redirect_output(int enable) {
  702. if (enable) {
  703. os_install_putc1(gdb_semihost_putchar1);
  704. uart_set_alt_output_uart0(gdb_semihost_putchar1);
  705. } else {
  706. gdb_flush_output_buffer();
  707. os_install_putc1(uart0_putc);
  708. }
  709. }
  710. //gdbstub initialization routine.
  711. void ATTR_GDBINIT gdbstub_init() {
  712. #if GDBSTUB_REDIRECT_CONSOLE_OUTPUT
  713. os_install_putc1(gdb_semihost_putchar1);
  714. #endif
  715. #if GDBSTUB_CTRLC_BREAK
  716. install_uart_hdlr();
  717. #endif
  718. install_exceptions();
  719. gdbstub_init_debug_entry();
  720. #if GDBSTUB_BREAK_ON_INIT
  721. gdbstub_do_break();
  722. #endif
  723. }