⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtl-stub.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * RTLinux Debugger modifications are written by Michael Barabanov * (baraban@fsmlabs.com) and * are Copyright (C) 2000, Finite State Machine Labs Inc. * */ /**************************************************************************** *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ * *  Module name: remcom.c $ *  Revision: 1.34 $ *  Date: 91/03/09 12:29:49 $ *  Contributor:     Lake Stevens Instrument Division$ * *  Description:     low level support for gdb debugger. $ * *  Considerations:  only works on target hardware $ * *  Written by:      Glenn Engel $ *  Updated by:	     David Grothe <dave@gcom.com> *  ModuleState:     Experimental $ * *  NOTES:           See Below $ * *  Modified for 386 by Jim Kingdon, Cygnus Support. *  Compatibility with 2.1.xx kernel by David Grothe <dave@gcom.com> *  Integrated into 2.2.5 kernel by Tigran Aivazian <tigran@sco.com> *  Modified for RTLinux by Michael Barabanov (baraban@fsmlabs.com) * *  To enable debugger support, two things need to happen.  One, a *  call to set_debug_traps() is necessary in order to allow any breakpoints *  or error conditions to be properly intercepted and reported to gdb. *  Two, a breakpoint needs to be generated to begin communication.  This *  is most easily accomplished by a call to breakpoint().  Breakpoint() *  simulates a breakpoint by executing an int 3. * ************* * *    The following gdb commands are supported: * * command          function                               Return value * *    g             return the value of the CPU registers  hex data or ENN *    G             set the value of the CPU registers     OK or ENN * *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN * *    c             Resume at current address              SNN   ( signal NN) *    cAA..AA       Continue at address AA..AA             SNN * *    s             Step one instruction                   SNN *    sAA..AA       Step one instruction from AA..AA       SNN * *    k             kill * *    ?             What was the last sigval ?             SNN   (signal NN) * * All commands and responses are sent with a packet which includes a * checksum.  A packet consists of * * $<packet info>#<checksum>. * * where * <packet info> :: <characters representing the command or response> * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>> * * When a packet is received, it is first acknowledged with either '+' or '-'. * '+' indicates a successful transfer.  '-' indicates a failed transfer. * * Example: * * Host:                  Reply: * $m0,10#2a               +$00010203040506070809101112131415#42 * ****************************************************************************/#include <linux/string.h>#include <linux/kernel.h>#include <asm/vm86.h>#include <asm/system.h>#include <asm/ptrace.h>			/* for linux pt_regs struct */#include <linux/signal.h>/* RTLinux support */#define __NO_VERSION__#include <linux/module.h>#include <rtl_sync.h>#include <rtl_sched.h>#define strtoul simple_strtoul#include <psc.h>#define rtl_running_linux() (pthread_self() == &LOCAL_SCHED->rtl_linux_task)int rtl_debug_initialized = 0;/* end of RTLinux support *//************************************************************************ * * external low-level support routines */typedef void (*Function)(void);           /* pointer to a function */extern int putDebugChar(int);   /* write a single character      */extern int getDebugChar(void);   /* read and return a single char *//************************************************************************//* BUFMAX defines the maximum number of characters in inbound/outbound buffers*//* at least NUMREGBYTES*2 are needed for register packets */#define BUFMAX 800static int     remote_debug = 0;/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */static const char hexchars[]="0123456789abcdef";/* Number of bytes of registers.  */#define NUMREGBYTES 64/* * Note that this register image is in a different order than * the register image that Linux produces at interrupt time. * * Linux's register image is defined by struct pt_regs in ptrace.h. * Just why GDB uses a different order is a historical mystery. */enum regnames {_EAX,		/* 0 */	       _ECX,		/* 1 */	       _EDX,		/* 2 */	       _EBX,		/* 3 */	       _ESP,		/* 4 */	       _EBP,		/* 5 */	       _ESI,		/* 6 */	       _EDI,		/* 7 */	       _PC 		/* 8 also known as eip */,	       _PS		/* 9 also known as eflags */,	       _CS,		/* 10 */	       _SS,		/* 11 */	       _DS,		/* 12 */	       _ES,		/* 13 */	       _FS,		/* 14 */	       _GS};		/* 15 *//***************************  ASSEMBLY CODE MACROS *************************//* 									   *//* Put the error code here just in case the user cares.  */int gdb_i386errcode;/* Likewise, the vector number here (since GDB only gets the signal   number through the usual means, and that's not very specific).  */int gdb_i386vector = -1;int hex(char ch){  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);  if ((ch >= '0') && (ch <= '9')) return (ch-'0');  if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);  return (-1);}/* scan for the sequence $<data>#<checksum>     */void getpacket(char * buffer){  unsigned char checksum;  unsigned char xmitcsum;  int  i;  int  count;  char ch;  do {    /* wait around for the start character, ignore all other characters */    while ((ch = (getDebugChar() & 0x7f)) != '$');    checksum = 0;    xmitcsum = -1;    count = 0;    /* now, read until a # or end of buffer is found */    while (count < BUFMAX) {      ch = getDebugChar() & 0x7f;      if (ch == '#') break;      checksum = checksum + ch;      buffer[count] = ch;      count = count + 1;      }    buffer[count] = 0;    if (ch == '#') {      xmitcsum = hex(getDebugChar() & 0x7f) << 4;      xmitcsum += hex(getDebugChar() & 0x7f);      if ((remote_debug ) && (checksum != xmitcsum)) {        printk ("bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",		 checksum,xmitcsum,buffer);      }      if (checksum != xmitcsum) putDebugChar('-');  /* failed checksum */      else {	 putDebugChar('+');  /* successful transfer */	 /* if a sequence char is present, reply the sequence ID */	 if (buffer[2] == ':') {	    putDebugChar( buffer[0] );	    putDebugChar( buffer[1] );	    /* remove sequence chars from buffer */	    count = strlen(buffer);	    for (i=3; i <= count; i++) buffer[i-3] = buffer[i];	 }      }    }  } while (checksum != xmitcsum);  if (remote_debug)    printk("R:%s\n", buffer) ;}/* send the packet in buffer.  */void putpacket(char * buffer){  unsigned char checksum;  int  count;  char ch;  /*  $<packet info>#<checksum>. */  do {  if (remote_debug)    printk("T:%s\n", buffer) ;  putDebugChar('$');  checksum = 0;  count    = 0;  while ((ch=buffer[count])) {    if (! putDebugChar(ch)) return;    checksum += ch;    count += 1;  }  putDebugChar('#');  putDebugChar(hexchars[checksum >> 4]);  putDebugChar(hexchars[checksum % 16]);  } while ((getDebugChar() & 0x7f) != '+');}static char  remcomInBuffer[BUFMAX];static char  remcomOutBuffer[BUFMAX];static short error;void debug_error( char * format, char * parm){  if (remote_debug) printk (format,parm);}static void print_regs(struct pt_regs *regs){    printk("EAX=%08lx ", regs->eax);    printk("EBX=%08lx ", regs->ebx);    printk("ECX=%08lx ", regs->ecx);    printk("EDX=%08lx ", regs->edx);    printk("\n");    printk("ESI=%08lx ", regs->esi);    printk("EDI=%08lx ", regs->edi);    printk("EBP=%08lx ", regs->ebp);    printk("ESP=%08lx ", (long) (regs+1));    printk("\n");    printk(" DS=%08x ", regs->xds);    printk(" ES=%08x ", regs->xes);    printk(" SS=%08x ", __KERNEL_DS);    printk(" FL=%08lx ", regs->eflags);    printk("\n");    printk(" CS=%08x ", regs->xcs);    printk(" IP=%08lx ", regs->eip);#if 0    printk(" FS=%08x ", regs->fs);    printk(" GS=%08x ", regs->gs);#endif    printk("\n");} /* print_regs */static void regs_to_gdb_regs(int *gdb_regs, struct pt_regs *regs){    gdb_regs[_EAX] =  regs->eax;    gdb_regs[_EBX] =  regs->ebx;    gdb_regs[_ECX] =  regs->ecx;    gdb_regs[_EDX] =  regs->edx;    gdb_regs[_ESI] =  regs->esi;    gdb_regs[_EDI] =  regs->edi;    gdb_regs[_EBP] =  regs->ebp;    gdb_regs[ _DS] =  regs->xds;    gdb_regs[ _ES] =  regs->xes;    gdb_regs[ _PS] =  regs->eflags;    gdb_regs[ _CS] =  regs->xcs;    gdb_regs[ _PC] =  regs->eip;    gdb_regs[_ESP] =  (int) (&regs->esp) ;    gdb_regs[ _SS] =  __KERNEL_DS;    gdb_regs[ _FS] =  0xFFFF;    gdb_regs[ _GS] =  0xFFFF;} /* regs_to_gdb_regs */static void gdb_regs_to_regs(int *gdb_regs, struct pt_regs *regs){    regs->eax	=     gdb_regs[_EAX] ;    regs->ebx	=     gdb_regs[_EBX] ;    regs->ecx	=     gdb_regs[_ECX] ;    regs->edx	=     gdb_regs[_EDX] ;    regs->esi	=     gdb_regs[_ESI] ;    regs->edi	=     gdb_regs[_EDI] ;    regs->ebp	=     gdb_regs[_EBP] ;    regs->xds	=     gdb_regs[ _DS] ;    regs->xes	=     gdb_regs[ _ES] ;    regs->eflags=     gdb_regs[ _PS] ;    regs->xcs	=     gdb_regs[ _CS] ;    regs->eip	=     gdb_regs[ _PC] ;#if 0					/* can't change these */    regs->esp	=     gdb_regs[_ESP] ;    regs->xss	=     gdb_regs[ _SS] ;    regs->fs	=     gdb_regs[ _FS] ;    regs->gs	=     gdb_regs[ _GS] ;#endif} /* gdb_regs_to_regs *//* Indicate to caller of mem2hex or hex2mem that there has been an   error.  */static volatile int real_mem_err [NR_CPUS];static volatile int real_mem_err_expected [NR_CPUS];#define mem_err (real_mem_err[rtl_getcpuid()])#define mem_err_expected (real_mem_err_expected[rtl_getcpuid()])static          int garbage_loc = -1 ;intget_char (char *addr){  return *addr;}voidset_char ( char *addr, int val){  *addr = val;}/* Convert the memory pointed to by mem into hex, placing result in buf. * Return a pointer to the last char put in buf (null), in case of mem fault, * return 0. */char* mem2hex( char* mem, char* buf, int   count)	       {      int i;      unsigned char ch;      int may_fault = 1;      if (may_fault)      {	  mem_err_expected = 1 ;	  mem_err = 0 ;      }      for (i=0;i<count;i++) {	  /* printk("%lx = ", mem) ; */	  ch = get_char (mem++);	  /* printk("%02x\n", ch & 0xFF) ; */	  if (may_fault && mem_err)	  {	    if (remote_debug)		printk("Mem fault fetching from addr %lx\n", (long)(mem-1));	    *buf = 0 ;				/* truncate buffer */	    return 0;	  }          *buf++ = hexchars[ch >> 4];          *buf++ = hexchars[ch % 16];      }      *buf = 0;      if (may_fault)	  mem_err_expected = 0 ;      return(buf);}/* convert the hex array pointed to by buf into binary to be placed in mem *//* return a pointer to the character AFTER the last byte written */char* hex2mem( char* buf,	       char* mem,	       int   count){      int i;      unsigned char ch;      int may_fault = 1;      if (may_fault)      {	  mem_err_expected = 1 ;	  mem_err = 0 ;      }      for (i=0;i<count;i++) {          ch = hex(*buf++) << 4;          ch = ch + hex(*buf++);	  set_char (mem++, ch);	  if (may_fault && mem_err)	  {	    if (remote_debug)		printk("Mem fault storing to addr %lx\n", (long)(mem-1));	    return 0;	  }      }      if (may_fault)	  mem_err_expected = 0 ;      return(mem);}/**********************************************//* WHILE WE FIND NICE HEX CHARS, BUILD AN INT *//* RETURN NUMBER OF CHARS PROCESSED           *//**********************************************/int hexToInt(char **ptr, int *intValue){    int numChars = 0;    int hexValue;    *intValue = 0;    while (**ptr)    {        hexValue = hex(**ptr);        if (hexValue >=0)        {            *intValue = (*intValue <<4) | hexValue;            numChars ++;        }        else            break;        (*ptr)++;    }    return (numChars);}/* * This function does all command procesing for interfacing to gdb. * * NOTE:  The INT nn instruction leaves the state of the interrupt *        enable flag UNCHANGED.  That means that when this routine *        is entered via a breakpoint (INT 3) instruction from code *        that has interrupts enabled, then interrupts will STILL BE *        enabled when this routine is entered.  The first thing that *        we do here is disable interrupts so as to prevent recursive *        entries and bothersome serial interrupts while we are *        trying to run the serial port in polled mode. *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -