📄 thread-packets.c
字号:
//========================================================================//// thread-packets.c//// Provides multi-threaded debug support////========================================================================//####COPYRIGHTBEGIN####// // ------------------------------------------- // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.redhat.com/ // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations under // the License. // // The Original Code is eCos - Embedded Configurable Operating System, // released September 30, 1998. // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND####//========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): Red Hat, nickg// Contributors: Red Hat, nickg// Date: 1998-08-25// Purpose: // Description: Provides multi-threaded debug support// Usage: ////####DESCRIPTIONEND####////========================================================================// Define __ECOS__; allows all eCos specific additions to be easily identified.#define __ECOS__// #ifdef __ECOS__#include <pkgconf/hal.h>#if defined(CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT) \ && defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)// #endif // __ECOS__/* FIXME: Scan this module for correct sizes of fields in packets */#ifdef __ECOS__#include <cyg/hal/dbg-threads-api.h>#else // __ECOS__#include "dbg-threads-api.h"#endif // __ECOS__/* This file should ALWAYS define debug thread support *//* Dont include the object in the link if you dont need the support *//* This is NOT the internal unit debug flag, it is a feature control */#if defined(DEBUG_THREADS)#undef DEBUG_THREADS#endif#define DEBUG_THREADS 1#define UNIT_TEST 0#define GDB_MOCKUP 0#define STUB_BUF_MAX 300 /* for range checking of packet lengths */ #include "thread-pkts.h"#ifdef __ECOS__// Use HAL rather than board.h in eCos#include <cyg/hal/hal_stub.h>#else // __ECOS__#include "board.h"#endif // __ECOS__/* * Export the continue and "general" (context) thread IDs from GDB. */int _gdb_cont_thread ;int _gdb_general_thread ;#if !defined(PKT_DEBUG)#define PKT_DEBUG 0#endifextern void output_string(char * message) ;#if PKT_DEBUGvoid output_threadid(char * title,threadref * ref) ;#warning "PKT_DEBUG macros engaged"#define PKT_TRACE(title,packet) \{ output_string(title) ; output_string(packet) ; output_string("\n") ;}#else#define PKT_TRACE(title,packet) {}#endif /* This is going to be irregular because the various implementations have adopted different names for registers. It would be nice to fix them to have a common convention _stub_registers stub_registers alt_stub_registers */extern target_register_t * _registers ; /* A pointer to the current set of registers */extern target_register_t registers[NUMREGS]; /* The current saved registers */extern target_register_t alt_registers[NUMREGS] ; /* Thread or saved process state */static void stub_copy_registers( target_register_t * dest, target_register_t *src ){ target_register_t * limit ; limit = dest + NUMREGS ; while (dest < limit) *dest++ = *src++ ;}#ifdef __ECOS__void __stub_copy_registers(target_register_t * dest, target_register_t *src){ stub_copy_registers(dest, src);}#endif // __ECOS__extern int stubhex(char ch) ;/* ----- STUB_PACK_NAK ----------------------------------- *//* Pack an error response into the response packet */char * stub_pack_nak(char * outbuf){ *outbuf++ = 'E' ; *outbuf++ = '0' ; *outbuf++ = '2' ; return outbuf ;} /* stub_pack_nak *//* ----- STUB_PACK_ACK -------------------------- *//* Pack an OK achnowledgement */char * stub_pack_ack(char * outbuf){ *outbuf++ = 'O' ; *outbuf++ = 'K' ; return outbuf ;} /* stub_pack_ack *//* ------- STUB_UNPACK_INT ------------------------------- *//* Unpack a few bytes and return its integer value *//* This is where I wish functions could return several values I would also advance the buffer pointer */int stub_unpack_int(char * buff,int fieldlength){ int retval = 0 ; int nibble ; while (fieldlength) { nibble = stubhex(*buff++) ; retval |= nibble ; fieldlength-- ; if (fieldlength) retval = retval << 4 ; } return retval ;} /* stub_unpack_int */static char * unpack_byte(char * buf, int * value){ *value = stub_unpack_int(buf,2) ; return buf + 2 ;}static char * unpack_int(char * buf, int * value){ *value = stub_unpack_int(buf,8) ; return buf + 8 ;}/* We are NOT depending upon extensive libraries */static int ishex(char ch,int *val){ if ((ch >= 'a') && (ch <= 'f')) { *val =ch - 'a' + 10 ; return 1 ; } if ((ch >= 'A') && (ch <= 'F')) { *val = ch - 'A' + 10 ; return 1 ;} if ((ch >= '0') && (ch <= '9')) { *val = ch - '0' ; return 1 ; } return 0 ;} /* ishex */static char * unpack_nibble(char * buf,int * val) { ishex(*buf++,val) ; return buf ;}static const char hexchars[] = "0123456789abcdef";static char * pack_hex_byte(char * pkt, unsigned char byte){ *pkt++ = hexchars[(byte >> 4) & 0xf] ; *pkt++ = hexchars[(byte & 0xf)] ; return pkt ;} /* pack_hex_byte */#ifndef __ECOS__/* ---- STUB_PACK_VARLEN_HEX ------------------------------------- *//* Format a variable length stream of hex bytes */static char * pack_varlen_hex( char * pkt, unsigned int value){ int i ; static unsigned char n[8] ; if (value == 0) { *pkt++ = '0' ; return pkt ; } else { i = 8 ; while (i-- >= 0 ) /* unpack nibbles into a char array */ { n[i] = value & 0x0f ; value = value >> 4 ; } i = 0 ; /* we had decrmented it to -1 */ while (n[i] == 0 ) i++ ; /* drop leading zeroes */ while (i++ < 8) *pkt++ = hexchars[n[i]] ; /* pack the number */ } return pkt ;} /* pack_varlen_hex */#endif // !__ECOS__/* ------ STUB_UNPACK_VARLEN_HEX -------------------------------- *//* Parse a stream of hex bytes which may be of variable length *//* return the pointer to the next char *//* modify a varparm containing the result *//* A failure would look like a non-increment of the buffer pointer *//* This unpacks hex strings that may have been packed using sprintf(%x) *//* We assume some non-hex delimits them */char * unpack_varlen_hex( char * buff, /* packet to parse */ int * result){ int nibble ; int retval ; retval = 0 ; while (ishex(*buff,&nibble)) { buff++ ; retval = retval << 4 ; retval |= nibble & 0x0f ; } *result = retval ; return buff ;} /* stub_unpack_varlen_int *//* ------ UNPACK_THREADID ------------------------------- *//* A threadid is a 64 bit quantity */#define BUFTHREADIDSIZ 16 /* encode 64 bits in 16 chars of hex */static char * unpack_threadid(char * inbuf, threadref * id){ char * altref ; char * limit = inbuf + BUFTHREADIDSIZ ; int x,y ; altref = (char *) id ; while (inbuf < limit) { x = stubhex(*inbuf++) ; y = stubhex(*inbuf++) ; *altref++ = (x << 4) | y ; } return inbuf ;} /* unpack_threadid *//* Pack an integer use leading zeroes */static char * pack_int(char * buf,int value){ buf = pack_hex_byte(buf,(value>> 24)& 0xff) ; buf = pack_hex_byte(buf,(value >>16)& 0xff) ; buf = pack_hex_byte(buf,(value >>8) & 0x0ff) ; buf = pack_hex_byte(buf,(value & 0xff)) ; return buf ;} /* pack_int *//* -------- PACK_STRING ---------------------------------------------- *//* This stupid string better not contain any funny characters *//* Also, the GDB protocol will not cope with NULLs in the string or at the end of it. While is is posable to encapsulate the protocol in ays that preclude filtering for # I am assuming this is a constraint.*/static char * pack_raw_string(char * pkt,char * string){ char ch ; while (0 != (ch = *string++)) *pkt++ = ch ; return pkt ;}static char * pack_string( char * pkt, char * string){ char ch ;#ifdef __ECOS__ int len = 0; char *s = string; while( *s++ ) len++;#else // __ECOS__ int len ; len = strlen(string) ;#endif // __ECOS if (len > 200 ) len = 200 ; /* Bigger than most GDB packets, junk??? */ pkt = pack_hex_byte(pkt,len) ; while (len-- > 0) { ch = *string++ ; if ((ch == '\0') || (ch == '#')) ch = '*' ; /* Protect encapsulation */ *pkt++ = ch ; } return pkt ;} /* pack_string *//* ----- STUB_PACK_THREADID --------------------------------------------- *//* Convert a binary 64 bit threadid and pack it into a xmit buffer *//* Return the advanced buffer pointer */static char * pack_threadid(char * pkt, threadref * id){ char * limit ; unsigned char * altid ; altid = (unsigned char *) id ; limit = pkt + BUFTHREADIDSIZ ; while (pkt < limit) pkt = pack_hex_byte(pkt,*altid++) ; return pkt ;} /* stub_pack_threadid *//* UNFORTUNATELY, not all of the extended debugging system has yet been converted to 64 but thread references and process identifiers. These routines do the conversion. An array of bytes is the correct treatment of an opaque identifier. ints have endian issues. */static void int_to_threadref(threadref * id, int value){ unsigned char * scan ; scan = (unsigned char *) id ; { int i = 4 ; while (i--) *scan++ = 0 ; } *scan++ = (value >> 24) & 0xff ; *scan++ = (value >> 16) & 0xff ; *scan++ = (value >> 8) & 0xff ; *scan++ = (value & 0xff) ;}static int threadref_to_int(threadref * ref){ int value = 0 ; unsigned char * scan ; int i ; scan = (char *) ref ; scan += 4 ; i = 4 ; while (i-- > 0) value = (value << 8) | ((*scan++) & 0xff) ; return value ;} /* threadref_to_int */void copy_threadref(threadref * dest, threadref * src){ int i ; unsigned char * csrc, * cdest ; csrc = (unsigned char *) src ; cdest = (unsigned char *) dest ; i = 8 ; while (i--) *cdest++ = *csrc++ ;}int threadmatch( threadref * dest , threadref * src ){ unsigned char * srcp, * destp ; int i , result ; srcp = (char *) src ; destp = (char *) dest ; i = 8 ; result = 1 ; while (i-- > 0 ) result &= (*srcp++ == *destp++) ? 1 : 0 ; return result ;} /* threadmatch */ static char * Tpkt_threadtag = "thread:" ;/* ----- STUB_PACK_TPKT_THREADID ------------------------------------ *//* retreive, tag and insert a thread identifier into a T packet. *//* Insert nothing if the thread identifier is not available */char * stub_pack_Tpkt_threadid(char * pkt){ static threadref thread ; int fmt = 0 ; /* old format */ PKT_TRACE("Tpkt-id","---") ; if (dbg_currthread(&thread)) { pkt = pack_raw_string(pkt,Tpkt_threadtag) ; if (fmt) pkt = pack_threadid(pkt,&thread) ; else /* Until GDB lengthens its thread ids, we have to MASH the threadid into somthing shorter. PLEASE FIX GDB */ pkt = pack_int(pkt,threadref_to_int(&thread)) ; *pkt++ = ';' ; /* terminate variable length int */ *pkt = '\0' ; /* Null terminate to allow string to be printed, no++ */ } PKT_TRACE("packedTpkt","--") ; return pkt ;} /* stub_pack_Tpkt_threadid */long stub_get_currthread (void){ threadref thread ; if (dbg_currthread(&thread)) return threadref_to_int(&thread) ; else return 0 ;}void stub_pkt_currthread(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -