gdb-stub.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:12k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  arch/s390/kernel/gdb-stub.c
  3.  *
  4.  *  S390 version
  5.  *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  6.  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  7.  *
  8.  *  Originally written by Glenn Engel, Lake Stevens Instrument Division
  9.  *
  10.  *  Contributed by HP Systems
  11.  *
  12.  *  Modified for SPARC by Stu Grossman, Cygnus Support.
  13.  *
  14.  *  Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
  15.  *  Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
  16.  *
  17.  *  Copyright (C) 1995 Andreas Busse
  18.  */
  19. /*
  20.  *  To enable debugger support, two things need to happen.  One, a
  21.  *  call to set_debug_traps() is necessary in order to allow any breakpoints
  22.  *  or error conditions to be properly intercepted and reported to gdb.
  23.  *  Two, a breakpoint needs to be generated to begin communication.  This
  24.  *  is most easily accomplished by a call to breakpoint().  Breakpoint()
  25.  *  simulates a breakpoint by executing a BREAK instruction.
  26.  *
  27.  *
  28.  *    The following gdb commands are supported:
  29.  *
  30.  * command          function                               Return value
  31.  *
  32.  *    g             return the value of the CPU registers  hex data or ENN
  33.  *    G             set the value of the CPU registers     OK or ENN
  34.  *
  35.  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
  36.  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
  37.  *
  38.  *    c             Resume at current address              SNN   ( signal NN)
  39.  *    cAA..AA       Continue at address AA..AA             SNN
  40.  *
  41.  *    s             Step one instruction                   SNN
  42.  *    sAA..AA       Step one instruction from AA..AA       SNN
  43.  *
  44.  *    k             kill
  45.  *
  46.  *    ?             What was the last sigval ?             SNN   (signal NN)
  47.  *
  48.  *
  49.  * All commands and responses are sent with a packet which includes a
  50.  * checksum.  A packet consists of
  51.  *
  52.  * $<packet info>#<checksum>.
  53.  *
  54.  * where
  55.  * <packet info> :: <characters representing the command or response>
  56.  * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
  57.  *
  58.  * When a packet is received, it is first acknowledged with either '+' or '-'.
  59.  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
  60.  *
  61.  * Example:
  62.  *
  63.  * Host:                  Reply:
  64.  * $m0,10#2a               +$00010203040506070809101112131415#42
  65.  *
  66.  */
  67. #define TRUE 1
  68. #define FALSE 0
  69. #include <asm/gdb-stub.h>
  70. #include <linux/string.h>
  71. #include <linux/kernel.h>
  72. #include <linux/signal.h>
  73. #include <linux/sched.h>
  74. #include <linux/mm.h>
  75. #include <asm/pgtable.h>
  76. #include <asm/system.h>
  77. #include <linux/stddef.h>
  78. #define S390_REGS_COMMON_SIZE offsetof(struct gdb_pt_regs,orig_gpr2)
  79. /*
  80.  * external low-level support routines
  81.  */
  82. extern void fltr_set_mem_err(void);
  83. extern void trap_low(void);
  84. /*
  85.  * breakpoint and test functions
  86.  */
  87. extern void breakpoint(void);
  88. extern void breakinst(void);
  89. /*
  90.  * local prototypes
  91.  */
  92. static void getpacket(char *buffer);
  93. static void putpacket(char *buffer);
  94. static int hex(unsigned char ch);
  95. static int hexToInt(char **ptr, int *intValue);
  96. static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
  97. /*
  98.  * BUFMAX defines the maximum number of characters in inbound/outbound buffers
  99.  * at least NUMREGBYTES*2 are needed for register packets
  100.  */
  101. #define BUFMAX 2048
  102. static char input_buffer[BUFMAX];
  103. static char output_buffer[BUFMAX];
  104. int gdb_stub_initialised = FALSE;
  105. static const char hexchars[]="0123456789abcdef";
  106. /*
  107.  * Convert ch from a hex digit to an int
  108.  */
  109. static int hex(unsigned char ch)
  110. {
  111. if (ch >= 'a' && ch <= 'f')
  112. return ch-'a'+10;
  113. if (ch >= '0' && ch <= '9')
  114. return ch-'0';
  115. if (ch >= 'A' && ch <= 'F')
  116. return ch-'A'+10;
  117. return -1;
  118. }
  119. /*
  120.  * scan for the sequence $<data>#<checksum>
  121.  */
  122. static void getpacket(char *buffer)
  123. {
  124. unsigned char checksum;
  125. unsigned char xmitcsum;
  126. int i;
  127. int count;
  128. unsigned char ch;
  129. do {
  130. /*
  131.  * wait around for the start character,
  132.  * ignore all other characters
  133.  */
  134. while ((ch = (getDebugChar() & 0x7f)) != '$') ;
  135. checksum = 0;
  136. xmitcsum = -1;
  137. count = 0;
  138. /*
  139.  * now, read until a # or end of buffer is found
  140.  */
  141. while (count < BUFMAX) {
  142. ch = getDebugChar() & 0x7f;
  143. if (ch == '#')
  144. break;
  145. checksum = checksum + ch;
  146. buffer[count] = ch;
  147. count = count + 1;
  148. }
  149. if (count >= BUFMAX)
  150. continue;
  151. buffer[count] = 0;
  152. if (ch == '#') {
  153. xmitcsum = hex(getDebugChar() & 0x7f) << 4;
  154. xmitcsum |= hex(getDebugChar() & 0x7f);
  155. if (checksum != xmitcsum)
  156. putDebugChar('-'); /* failed checksum */
  157. else {
  158. putDebugChar('+'); /* successful transfer */
  159. /*
  160.  * if a sequence char is present,
  161.  * reply the sequence ID
  162.  */
  163. if (buffer[2] == ':') {
  164. putDebugChar(buffer[0]);
  165. putDebugChar(buffer[1]);
  166. /*
  167.  * remove sequence chars from buffer
  168.  */
  169. count = strlen(buffer);
  170. for (i=3; i <= count; i++)
  171. buffer[i-3] = buffer[i];
  172. }
  173. }
  174. }
  175. }
  176. while (checksum != xmitcsum);
  177. }
  178. /*
  179.  * send the packet in buffer.
  180.  */
  181. static void putpacket(char *buffer)
  182. {
  183. unsigned char checksum;
  184. int count;
  185. unsigned char ch;
  186. /*
  187.  * $<packet info>#<checksum>.
  188.  */
  189. do {
  190. putDebugChar('$');
  191. checksum = 0;
  192. count = 0;
  193. while ((ch = buffer[count]) != 0) {
  194. if (!(putDebugChar(ch)))
  195. return;
  196. checksum += ch;
  197. count += 1;
  198. }
  199. putDebugChar('#');
  200. putDebugChar(hexchars[checksum >> 4]);
  201. putDebugChar(hexchars[checksum & 0xf]);
  202. }
  203. while ((getDebugChar() & 0x7f) != '+');
  204. }
  205. /*
  206.  * Convert the memory pointed to by mem into hex, placing result in buf.
  207.  * Return a pointer to the last char put in buf (null), in case of mem fault,
  208.  * return 0.
  209.  * If MAY_FAULT is non-zero, then we will handle memory faults by returning
  210.  * a 0, else treat a fault like any other fault in the stub.
  211.  */
  212. static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
  213. {
  214. unsigned char ch;
  215. /* set_mem_fault_trap(may_fault); */
  216. while (count-- > 0) {
  217. ch = *(mem++);
  218. #if 0
  219. if (mem_err)
  220. return 0;
  221. #endif
  222. *buf++ = hexchars[ch >> 4];
  223. *buf++ = hexchars[ch & 0xf];
  224. }
  225. *buf = 0;
  226. /* set_mem_fault_trap(0); */
  227. return buf;
  228. }
  229. /*
  230.  * convert the hex array pointed to by buf into binary to be placed in mem
  231.  * return a pointer to the character AFTER the last byte written
  232.  */
  233. static char *hex2mem(char *buf, char *mem, int count, int may_fault)
  234. {
  235. int i;
  236. unsigned char ch;
  237. /* set_mem_fault_trap(may_fault); */
  238. for (i=0; i<count; i++)
  239. {
  240. ch = hex(*buf++) << 4;
  241. ch |= hex(*buf++);
  242. *(mem++) = ch;
  243. #if 0
  244. if (mem_err)
  245. return 0;
  246. #endif
  247. }
  248. /* set_mem_fault_trap(0); */
  249. return mem;
  250. }
  251. /*
  252.  * Set up exception handlers for tracing and breakpoints
  253.  */
  254. void set_debug_traps(void)
  255. {
  256. // unsigned long flags;
  257. unsigned char c;
  258. // save_and_cli(flags);
  259. /*
  260.  * In case GDB is started before us, ack any packets
  261.  * (presumably "$?#xx") sitting there.
  262.  */
  263. while((c = getDebugChar()) != '$');
  264. while((c = getDebugChar()) != '#');
  265. c = getDebugChar(); /* eat first csum byte */
  266. c = getDebugChar(); /* eat second csum byte */
  267. putDebugChar('+'); /* ack it */
  268. gdb_stub_initialised = TRUE;
  269. // restore_flags(flags);
  270. }
  271. /*
  272.  * Trap handler for memory errors.  This just sets mem_err to be non-zero.  It
  273.  * assumes that %l1 is non-zero.  This should be safe, as it is doubtful that
  274.  * 0 would ever contain code that could mem fault.  This routine will skip
  275.  * past the faulting instruction after setting mem_err.
  276.  */
  277. extern void fltr_set_mem_err(void)
  278. {
  279.   /* FIXME: Needs to be written... */
  280. }
  281. /*
  282.  * While we find nice hex chars, build an int.
  283.  * Return number of chars processed.
  284.  */
  285. static int hexToInt(char **ptr, int *intValue)
  286. {
  287. int numChars = 0;
  288. int hexValue;
  289. *intValue = 0;
  290. while (**ptr)
  291. {
  292. hexValue = hex(**ptr);
  293. if (hexValue < 0)
  294. break;
  295. *intValue = (*intValue << 4) | hexValue;
  296. numChars ++;
  297. (*ptr)++;
  298. }
  299. return (numChars);
  300. }
  301. void gdb_stub_get_non_pt_regs(struct gdb_pt_regs *regs)
  302. {
  303. s390_fp_regs *fpregs=&regs->fp_regs;
  304. int has_ieee=save_fp_regs1(fpregs);
  305. if(!has_ieee)
  306. {
  307. fpregs->fpc=0;
  308. fpregs->fprs[1].d=
  309. fpregs->fprs[3].d=
  310. fpregs->fprs[5].d=
  311. fpregs->fprs[7].d=0;
  312. memset(&fpregs->fprs[8].d,0,sizeof(freg_t)*8);
  313. }
  314. }
  315. void gdb_stub_set_non_pt_regs(struct gdb_pt_regs *regs)
  316. {
  317. restore_fp_regs1(&regs->fp_regs);
  318. }
  319. void gdb_stub_send_signal(int sigval)
  320. {
  321. char *ptr;
  322. ptr = output_buffer;
  323. /*
  324.  * Send trap type (converted to signal)
  325.  */
  326. *ptr++ = 'S';
  327. *ptr++ = hexchars[sigval >> 4];
  328. *ptr++ = hexchars[sigval & 0xf];
  329. *ptr++ = 0;
  330. putpacket(output_buffer); /* send it off... */
  331. }
  332. /*
  333.  * This function does all command processing for interfacing to gdb.  It
  334.  * returns 1 if you should skip the instruction at the trap address, 0
  335.  * otherwise.
  336.  */
  337. void gdb_stub_handle_exception(struct gdb_pt_regs *regs,int sigval)
  338. {
  339. int trap; /* Trap type */
  340. int addr;
  341. int length;
  342. char *ptr;
  343. unsigned long *stack;
  344. /*
  345.  * reply to host that an exception has occurred
  346.  */
  347. #if 0
  348. send_signal(sigval);
  349. #endif
  350. /*
  351.  * Wait for input from remote GDB
  352.  */
  353. while (1) 
  354. {
  355. output_buffer[0] = 0;
  356. getpacket(input_buffer);
  357. switch (input_buffer[0])
  358. {
  359. case '?':
  360. #if 0
  361. send_signal(sigval);
  362. #endif
  363. continue;
  364. case 'd':
  365. /* toggle debug flag */
  366. break;
  367. /*
  368.  * Return the value of the CPU registers
  369.  */
  370. case 'g':
  371. gdb_stub_get_non_pt_regs(regs);
  372. ptr = output_buffer;
  373. ptr=  mem2hex((char *)regs,ptr,S390_REGS_COMMON_SIZE,FALSE);
  374. ptr=  mem2hex((char *)&regs->crs[0],ptr,NUM_CRS*CR_SIZE,FALSE);
  375. ptr = mem2hex((char *)&regs->fp_regs, ptr,sizeof(s390_fp_regs),FALSE);
  376. break;
  377.   
  378. /*
  379.  * set the value of the CPU registers - return OK
  380.  * FIXME: Needs to be written
  381.  */
  382. case 'G':
  383. ptr=input_buffer;
  384. hex2mem (ptr, (char *)regs,S390_REGS_COMMON_SIZE, FALSE);
  385. ptr+=S390_REGS_COMMON_SIZE*2;
  386. hex2mem (ptr, (char *)regs->crs[0],NUM_CRS*CR_SIZE, FALSE);
  387. ptr+=NUM_CRS*CR_SIZE*2;
  388. hex2mem (ptr, (char *)&regs->fp_regs,sizeof(s390_fp_regs), FALSE);
  389. gdb_stub_set_non_pt_regs(regs);
  390. strcpy(output_buffer,"OK");
  391. break;
  392. /*
  393.  * mAA..AA,LLLL  Read LLLL bytes at address AA..AA
  394.  */
  395. case 'm':
  396. ptr = &input_buffer[1];
  397. if (hexToInt(&ptr, &addr)
  398. && *ptr++ == ','
  399. && hexToInt(&ptr, &length)) {
  400. if (mem2hex((char *)addr, output_buffer, length, 1))
  401. break;
  402. strcpy (output_buffer, "E03");
  403. } else
  404. strcpy(output_buffer,"E01");
  405. break;
  406. /*
  407.  * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
  408.  */
  409. case 'M': 
  410. ptr = &input_buffer[1];
  411. if (hexToInt(&ptr, &addr)
  412. && *ptr++ == ','
  413. && hexToInt(&ptr, &length)
  414. && *ptr++ == ':') 
  415. {
  416. if (hex2mem(ptr, (char *)addr, length, 1))
  417. strcpy(output_buffer, "OK");
  418. else
  419. strcpy(output_buffer, "E03");
  420. }
  421. else
  422. strcpy(output_buffer, "E02");
  423. break;
  424. /*
  425.  * cAA..AA    Continue at address AA..AA(optional)
  426.  */
  427. case 'c':    
  428. /* try to read optional parameter, pc unchanged if no parm */
  429. ptr = &input_buffer[1];
  430. if (hexToInt(&ptr, &addr))
  431. regs->psw.addr = addr;
  432. /*
  433.  * Need to flush the instruction cache here, as we may
  434.  * have deposited a breakpoint, and the icache probably
  435.  * has no way of knowing that a data ref to some location
  436.  * may have changed something that is in the instruction
  437.  * cache.
  438.  * NB: We flush both caches, just to be sure...
  439.  */
  440. flush_cache_all();
  441. return;
  442. /* NOTREACHED */
  443. break;
  444. /*
  445.  * kill the program
  446.  */
  447. case 'k' :
  448. break; /* do nothing */
  449. /*
  450.  * Reset the whole machine (FIXME: system dependent)
  451.  */
  452. case 'r':
  453. break;
  454. /*
  455.  * Step to next instruction
  456.  */
  457. case 's':
  458. /*
  459.  * There is no single step insn in the MIPS ISA, so we
  460.  * use breakpoints and continue, instead.
  461.  */
  462. #if 0
  463. single_step(regs);
  464. #endif
  465. flush_cache_all();
  466. return;
  467. /* NOTREACHED */
  468. break;
  469. }      /* switch */
  470. /*
  471.  * reply to the request
  472.  */
  473. putpacket(output_buffer);
  474. } /* while */
  475. }
  476. /*
  477.  * This function will generate a breakpoint exception.  It is used at the
  478.  * beginning of a program to sync up with a debugger and can be used
  479.  * otherwise as a quick means to stop program execution and "break" into
  480.  * the debugger.
  481.  */
  482. void breakpoint(void)
  483. {
  484. if (!gdb_stub_initialised)
  485. return;
  486. asm volatile (".globl breakinstn"
  487. "breakinst:t.word   %0"
  488. : : "i" (S390_BREAKPOINT_U16) );
  489. }