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