📄 rtems-stub-glue.c
字号:
case 'L': /* Thread list query */ if (!do_threads) { break; } { int ret, athread, first, max_cnt, i, done, rthread; ret = parse_ql(inbuffer, &first, &max_cnt, &athread); if (!ret) { strcpy(outbuffer, "E02"); break; } if (max_cnt == 0) { strcpy(outbuffer, "E02"); break; } if (max_cnt > QM_MAX_THREADS) { /* Limit max count by buffer size */ max_cnt = QM_MAX_THREADS; } /* Reserve place for output header */ optr = reserve_qm_header(outbuffer); if (first) { rthread = 0; } else { rthread = athread; } done = 0; for (i=0; i<max_cnt; i++) { rthread = rtems_gdb_stub_get_next_thread(rthread); if (rthread <= 0) { done = 1; /* Set done flag */ break; } optr = pack_qm_thread(optr, rthread); } *optr = 0; ASSERT((optr - outbuffer) < BUFMAX); /* Fill header */ pack_qm_header(outbuffer, i, done, athread); } break; default: if (memcmp(inbuffer, "qOffsets", 8) == 0) { unsigned char *t, *d, *b; char *out; if (!rtems_gdb_stub_get_offsets(&t, &d, &b)) { break; } out = outbuffer; *out++ = 'T'; *out++ = 'e'; *out++ = 'x'; *out++ = 't'; *out++ = '='; out = int2vhstr(out, (int)t); *out++ = ';'; *out++ = 'D'; *out++ = 'a'; *out++ = 't'; *out++ = 'a'; *out++ = '='; out = int2vhstr(out, (int)d); *out++ = ';'; *out++ = 'B'; *out++ = 's'; *out++ = 's'; *out++ = '='; out = int2vhstr(out, (int)b); *out++ = ';'; *out++ = 0; break; } /* qCRC, qRcmd, qu and qz will be added here */ break; }}/* Present thread in the variable length string format */char*thread2vhstr(char *buf, int thread){ int i, nibble, shift; ASSERT(buf != NULL); for(i=0, shift=28; i<8; i++, shift-=4) { nibble = (thread >> shift) & 0x0f; if (nibble != 0) { break; } } if (i == 8) { *buf++ = '0'; return buf; } *buf++ = gdb_hexchars[nibble]; for(i++, shift-=4; i<8; i++, shift-=4, buf++) { nibble = (thread >> shift) & 0x0f; *buf = gdb_hexchars[nibble]; } return buf;}/* Present thread in fixed length string format */char*thread2fhstr(char *buf, int thread){ int i, nibble, shift; ASSERT(buf != NULL); for(i=0; i<8; i++, buf++) { *buf = '0'; } for(i=0, shift=28; i<8; i++, shift-=4, buf++) { nibble = (thread >> shift) & 0x0f; *buf = gdb_hexchars[nibble]; } return buf;}/* Parse thread presented in fixed length format */const char*fhstr2thread(const char *buf, int *thread){ int i, val, nibble; ASSERT(buf != NULL); ASSERT(thread != NULL); for(i=0; i<8; i++, buf++) { if (*buf != '0') { return NULL; } } val = 0; for(i=0; i<8; i++, buf++) { if (!hstr2nibble(buf, &nibble)) { return NULL; } ASSERT(nibble >=0 && nibble < 16); val = (val << 4) | nibble; } *thread = val; return buf;}/* Parse thread presented in variable length format */const char*vhstr2thread(const char *buf, int *thread){ int i, val, nibble; int found_zero, lim; ASSERT(buf != NULL); ASSERT(thread != NULL); /* If we have leading zeros, skip them */ found_zero = 0; for(i=0; i<16; i++, buf++) { if (*buf != '0') { break; } found_zero = 1; } /* Process non-zeros */ lim = 16 - i; val = 0; for(i=0; i<lim; i++, buf++) { if (!hstr2nibble(buf, &nibble)) { if (i == 0 && !found_zero) { /* Empty value */ return NULL; } *thread = val; return buf; } ASSERT(nibble >= 0 && nibble < 16); val = (val << 4) | nibble; } if (hstr2nibble(buf, &nibble)) { /* Value is too long */ return NULL; } *thread = val; return buf;}/* Present integer in the variable length string format */char*int2vhstr(char *buf, int val){ int i, nibble, shift; ASSERT(buf != NULL); for(i=0, shift=28; i<8; i++, shift-=4) { nibble = (val >> shift) & 0x0f; if (nibble != 0) { break; } } if (i == 8) { *buf++ = '0'; return buf; } *buf++ = gdb_hexchars[nibble]; for(i++, shift-=4; i<8; i++, shift-=4, buf++) { nibble = (val >> shift) & 0x0f; *buf = gdb_hexchars[nibble]; } return buf;}/* Present int in fixed length string format */char*int2fhstr(char *buf, int val){ int i, nibble, shift; ASSERT(buf != NULL); for(i=0, shift=28; i<8; i++, shift-=4, buf++) { nibble = (val >> shift) & 0x0f; *buf = gdb_hexchars[nibble]; } return buf;}/* Parse int presented in fixed length format */const char*fhstr2int(const char *buf, int *ival){ int i, val, nibble; ASSERT(buf != NULL); ASSERT(ival != NULL); val = 0; for(i=0; i<8; i++, buf++) { if (!hstr2nibble(buf, &nibble)) { return NULL; } ASSERT(nibble >=0 && nibble < 16); val = (val << 4) | nibble; } *ival = val; return buf;}/* Parse int presented in variable length format */const char*vhstr2int(const char *buf, int *ival){ int i, val, nibble; int found_zero, lim; ASSERT(buf != NULL); ASSERT(ival != NULL); /* If we have leading zeros, skip them */ found_zero = 0; for(i=0; i<8; i++, buf++) { if (*buf != '0') { break; } found_zero = 1; } /* Process non-zeros */ lim = 8 - i; val = 0; for(i=0; i<lim; i++, buf++) { if (!hstr2nibble(buf, &nibble)) { if (i == 0 && !found_zero) { /* Empty value */ return NULL; } *ival = val; return buf; } ASSERT(nibble >= 0 && nibble < 16); val = (val << 4) | nibble; } if (hstr2nibble(buf, &nibble)) { /* Value is too long */ return NULL; } *ival = val; return buf;}inthstr2byte(const char *buf, int *bval){ int hnib, lnib; ASSERT(buf != NULL); ASSERT(bval != NULL); if (!hstr2nibble(buf, &hnib) || !hstr2nibble(buf+1, &lnib)) { return 0; } *bval = (hnib << 4) | lnib; return 1;}int hstr2nibble(const char *buf, int *nibble){ int ch; ASSERT(buf != NULL); ASSERT(nibble != NULL); ch = *buf; if (ch >= '0' && ch <= '9') { *nibble = ch - '0'; return 1; } if (ch >= 'a' && ch <= 'f') { *nibble = ch - 'a' + 10; return 1; } if (ch >= 'A' && ch <= 'F') { *nibble = ch - 'A' + 10; return 1; } return 0;}static volatile char mem_err = 0;void set_mem_err(void);static void (*volatile mem_fault_routine) (void) = NULL;/* convert count bytes of the memory pointed to by mem into hex string, placing result in buf, return pointer to next location in hex strng in case of success or NULL otherwise */char*mem2hstr(char *buf, const unsigned char *mem, int count){ int i; unsigned char ch; mem_err = 0; mem_fault_routine = set_mem_err; for (i = 0; i<count; i++, mem++) { ch = get_byte (mem); if (mem_err) { mem_fault_routine = NULL; return NULL; } *buf++ = gdb_hexchars[ch >> 4]; *buf++ = gdb_hexchars[ch & 0x0f]; } *buf = 0; mem_fault_routine = NULL; return buf;}/* convert the hex string to into count bytes of binary to be placed in mem return 1 in case of success and 0 otherwise */inthstr2mem (unsigned char *mem, const char *buf, int count){ int i; int bval; mem_err = 0; mem_fault_routine = set_mem_err; for (i = 0; i < count; i++, mem++, buf+=2) { if (!hstr2byte(buf, &bval)) { mem_fault_routine = NULL; return 0; } ASSERT(bval >=0 && bval < 256); set_byte (mem, bval); if (mem_err) { mem_fault_routine = NULL; return 0; } } mem_fault_routine = NULL; return 1;}voidset_mem_err (void){ mem_err = 1;}/* These are separate functions so that they are so short and sweet that the compiler won't save any registers (if there is a fault to mem_fault, they won't get restored, so there better not be any saved). */unsigned char get_byte (const unsigned char *addr){ return *addr;}voidset_byte (unsigned char *addr, int val){ *addr = val;}/* * From here down, the code is CPU model specific and generally maps * the RTEMS thread context format to gdb's. */#if defined(__i386__)#include "i386-stub.h"/* Packing order of registers */enum i386_stub_regnames { I386_STUB_REG_EAX, I386_STUB_REG_ECX, I386_STUB_REG_EDX, I386_STUB_REG_EBX, I386_STUB_REG_ESP, I386_STUB_REG_EBP, I386_STUB_REG_ESI, I386_STUB_REG_EDI, I386_STUB_REG_PC /* also known as eip */ , I386_STUB_REG_PS /* also known as eflags */ , I386_STUB_REG_CS, I386_STUB_REG_SS, I386_STUB_REG_DS, I386_STUB_REG_ES, I386_STUB_REG_FS, I386_STUB_REG_GS};void rtems_gdb_stub_get_registers_from_context( int *registers, Thread_Control *th){ registers[I386_STUB_REG_EAX] = 0; registers[I386_STUB_REG_ECX] = 0; registers[I386_STUB_REG_EDX] = 0; registers[I386_STUB_REG_EBX] = (int)th->Registers.ebx; registers[I386_STUB_REG_ESP] = (int)th->Registers.esp; registers[I386_STUB_REG_EBP] = (int)th->Registers.ebp; registers[I386_STUB_REG_ESI] = (int)th->Registers.esi; registers[I386_STUB_REG_EDI] = (int)th->Registers.edi; registers[I386_STUB_REG_PC] = *(int *)th->Registers.esp; registers[I386_STUB_REG_PS] = (int)th->Registers.eflags; /* RTEMS never changes base registers (especially once threads are running) */ registers[I386_STUB_REG_CS] = 0x8; /* We just know these values */ registers[I386_STUB_REG_SS] = 0x10; registers[I386_STUB_REG_DS] = 0x10; registers[I386_STUB_REG_ES] = 0x10; registers[I386_STUB_REG_FS] = 0x10; registers[I386_STUB_REG_GS] = 0x10;}int rtems_gdb_stub_get_offsets( unsigned char **text_addr, unsigned char **data_addr, unsigned char **bss_addr){ extern unsigned char _text_start; extern unsigned char _data_start; extern unsigned char _bss_start; *text_addr = &_text_start; *data_addr = &_data_start; *bss_addr = &_bss_start; return 1;}#elif defined(__mips__)void rtems_gdb_stub_get_registers_from_context( int *registers, Thread_Control *th){ registers[S0] = (unsigned)th->Registers.s0; registers[S1] = (unsigned)th->Registers.s1; registers[S2] = (unsigned)th->Registers.s2; registers[S3] = (unsigned)th->Registers.s3; registers[S4] = (unsigned)th->Registers.s4; registers[S5] = (unsigned)th->Registers.s5; registers[S6] = (unsigned)th->Registers.s6; registers[S7] = (unsigned)th->Registers.s7; registers[SP] = (unsigned)th->Registers.sp; registers[RA] = (unsigned)th->Registers.ra; registers[SR] = (unsigned)th->Registers.c0_sr; registers[PC] = (unsigned)th->Registers.c0_epc;}int rtems_gdb_stub_get_offsets( unsigned char **text_addr, unsigned char **data_addr, unsigned char **bss_addr){ /* extern unsigned32 _ftext; extern unsigned32 _fdata; extern unsigned32 _bss_start; *text_addr = &_ftext; *data_addr = &_fdata; *bss_addr = &_bss_start;*/ *text_addr = 0; *data_addr = 0; *bss_addr = 0; return 1;}#elif defined(__mc68000__)void rtems_gdb_stub_get_registers_from_context( int *registers, Thread_Control *th){ /* * how about register D0/D1/A0/A1 * they are located on thread stack ... * -> they are not needed for context switch */ registers[D0] = 0; registers[D1] = 0; registers[D2] = (unsigned32)th->Registers.d2; registers[D3] = (unsigned32)th->Registers.d3; registers[D4] = (unsigned32)th->Registers.d4; registers[D5] = (unsigned32)th->Registers.d5; registers[D6] = (unsigned32)th->Registers.d6; registers[D7] = (unsigned32)th->Registers.d7; registers[A0] = 0; registers[A1] = 0; registers[A2] = (unsigned32)th->Registers.a2; registers[A3] = (unsigned32)th->Registers.a3; registers[A4] = (unsigned32)th->Registers.a4; registers[A5] = (unsigned32)th->Registers.a5; registers[A6] = (unsigned32)th->Registers.a6; registers[A7] = (unsigned32)th->Registers.a7_msp; registers[PS] = (unsigned32)th->Registers.sr;#if 0 registers[PC] = *(unsigned32 *)th->Registers.a7_msp; /* *SP = ret adr */#else registers[PC] = (unsigned32)_CPU_Context_switch;#endif}int rtems_gdb_stub_get_offsets( unsigned char **text_addr, unsigned char **data_addr, unsigned char **bss_addr){ /* extern unsigned32 _ftext; extern unsigned32 _fdata; extern unsigned32 _bss_start; *text_addr = &_ftext; *data_addr = &_fdata; *bss_addr = &_bss_start;*/ *text_addr = 0; *data_addr = 0; *bss_addr = 0; return 1;}#else#error "rtems-gdb-stub.c: Unsupported CPU!"#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -