📄 mips-stub.c
字号:
strcpy (outBuffer, "E01"); /* E01 = bad 'm' command */ break; case 'X': /* XAA..AA,LLLL:<binary data>#cs */ binary = 1; case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA - return OK */ ptr = &inBuffer[1]; if (hexToInt (&ptr, &addr) && *ptr++ == ',' && hexToInt (&ptr, &length) && *ptr++ == ':' && is_writeable (addr, length) ) { if ( binary ) hex2mem (ptr, (void *)addr, length); else bin2mem (ptr, (void *)addr, length); strcpy (outBuffer, "OK"); } else strcpy (outBuffer, "E02"); /* E02 = bad 'M' command */ break; case 'c': /* cAA..AA Continue at address AA..AA(optional) */ case 's': /* sAA..AA Step one instruction from AA..AA(optional) */ { /* try to read optional parameter, pc unchanged if no parm */ ptr = &inBuffer[1]; if (hexToInt (&ptr, &addr)) registers[PC] = addr; if (inBuffer[0] == 's') doSStep (); } goto stubexit; case 'k': /* remove all zbreaks if any */ dumpzbreaks: { { /* Unlink the entire list */ struct z0break *z0, *znxt; while( (z0= z0break_list) ) { /* put back the instruction */ if( z0->instr != 0xffffffff ) *(z0->address) = z0->instr; /* pop off the top entry */ znxt = z0->next; if( znxt ) znxt->prev = NULL; z0break_list = znxt; /* and put it on the free list */ z0->prev = NULL; z0->next = z0break_avail; z0break_avail = z0; } } strcpy(outBuffer, "OK"); } break; case 'q': /* queries */#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) rtems_gdb_process_query( inBuffer, outBuffer, do_threads, thread );#endif break;#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) case 'T': { int testThread; if( vhstr2thread(&inBuffer[1], &testThread) == NULL ) { strcpy(outBuffer, "E01"); break; } if( rtems_gdb_index_to_stub_id(testThread) == NULL ) { strcpy(outBuffer, "E02"); } else { strcpy(outBuffer, "OK"); } } break;#endif case 'H': /* set new thread */#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) if (inBuffer[1] != 'g') { break; } if (!do_threads) { break; } { int tmp, ret; /* Set new generic thread */ if (vhstr2thread(&inBuffer[2], &tmp) == NULL) { strcpy(outBuffer, "E01"); break; } /* 0 means `thread' */ if (tmp == 0) { tmp = thread; } if (tmp == current_thread) { /* No changes */ strcpy(outBuffer, "OK"); break; } /* Save current thread registers if necessary */ if (current_thread != thread) { ret = rtems_gdb_stub_set_thread_regs( current_thread, (unsigned int *) ¤t_thread_registers); ASSERT(ret); } /* Read new registers if necessary */ if (tmp != thread) { ret = rtems_gdb_stub_get_thread_regs( tmp, (unsigned int *) ¤t_thread_registers); if (!ret) { /* Thread does not exist */ strcpy(outBuffer, "E02"); break; } } current_thread = tmp; strcpy(outBuffer, "OK"); }#endif break; case 'Z': /* Add breakpoint */ { int ret, type, len; unsigned *address; struct z0break *z0; ret = parse_zbreak(inBuffer, &type, (unsigned char **)&address, &len); if (!ret) { strcpy(outBuffer, "E01"); break; } if (type != 0) { /* We support only software break points so far */ strcpy(outBuffer, "E02"); break; } if (len != R_SZ) { /* was 1 */ strcpy(outBuffer, "E03"); break; } /* Let us check whether this break point already set */ for (z0=z0break_list; z0!=NULL; z0=z0->next) { if (z0->address == address) { break; } } if (z0 != NULL) { /* we already have a breakpoint for this address */ strcpy(outBuffer, "E04"); break; } /* Let us allocate new break point */ if (z0break_avail == NULL) { strcpy(outBuffer, "E05"); break; } /* Get entry */ z0 = z0break_avail; z0break_avail = z0break_avail->next; /* Let us copy memory from address add stuff the break point in */ /* *if (mem2hstr(z0->buf, address, 1) == NULL || !hstr2mem(address, "cc" , 1)) { * Memory error * z0->next = z0break_avail; z0break_avail = z0; strcpy(outBuffer, "E05"); break; }*/ /* Fill it */ z0->address = address; if( z0->address == (unsigned *) frame->epc ) { /* re-asserting the breakpoint that put us in here, so we'll add the breakpoint but leave the code in place since we'll be returning to it when the user continues */ z0->instr = 0xffffffff; } else { /* grab the instruction */ z0->instr = *(z0->address); /* and insert the break */ *(z0->address) = BREAK_INSTR; } /* Add to the list */ { struct z0break *znxt = z0break_list; z0->prev = NULL; z0->next = znxt; if( znxt ) znxt->prev = z0; z0break_list = z0; } strcpy(outBuffer, "OK"); } break; case 'z': /* remove breakpoint */ if (inBuffer[1] == 'z') { goto dumpzbreaks; /* * zz packet - remove all breaks * z0last = NULL; for (z0=z0break_list; z0!=NULL; z0=z0->next) { if(!hstr2mem(z0->address, z0->buf, R_SZ)) { ret = 0; } z0last = z0; } * Free entries if any * if (z0last != NULL) { z0last->next = z0break_avail; z0break_avail = z0break_list; z0break_list = NULL; } if (ret) { strcpy(outBuffer, "OK"); } else { strcpy(outBuffer, "E04"); } break; */ } else { int ret, type, len; unsigned *address; struct z0break *z0; ret = parse_zbreak(inBuffer, &type, (unsigned char **)&address, &len); if (!ret) { strcpy(outBuffer, "E01"); break; } if (type != 0) { /* We support only software break points so far */ break; } if (len != R_SZ) { strcpy(outBuffer, "E02"); break; } /* Let us check whether this break point set */ for (z0=z0break_list; z0!=NULL; z0=z0->next) { if (z0->address == address) { break; } } if (z0 == NULL) { /* Unknown breakpoint */ strcpy(outBuffer, "E03"); break; } /* if (!hstr2mem(z0->address, z0->buf, R_SZ)) { strcpy(outBuffer, "E04"); break; }*/ if( z0->instr != 0xffffffff ) { /* put the old instruction back */ *(z0->address) = z0->instr; } /* Unlink entry */ { struct z0break *zprv = z0->prev, *znxt = z0->next; if( zprv ) zprv->next = znxt; if( znxt ) znxt->prev = zprv; if( !zprv ) z0break_list = znxt; znxt = z0break_avail; z0break_avail = z0; z0->prev = NULL; z0->next = znxt; } strcpy(outBuffer, "OK"); } break; default: /* do nothing */ break; } /* reply to the request */ putpacket (outBuffer); } stubexit: /* * The original code did this in the assembly wrapper. We should consider * doing it here before we return. * * On exit from the exception handler invalidate each line in the I-cache * and write back each dirty line in the D-cache. This needs to be done * before the target program is resumed in order to ensure that software * breakpoints and downloaded code will actually take effect. This * is because modifications to code in ram will affect the D-cache, * but not necessarily the I-cache. */ { extern void clear_cache(); clear_cache(); } return;}static int numsegs;static struct memseg memsegments[NUM_MEMSEGS];int gdbstub_add_memsegment( unsigned base, unsigned end, int opts ){ if( numsegs == NUM_MEMSEGS ) return -1; memsegments[numsegs].begin = base; memsegments[numsegs].end = end; memsegments[numsegs].opts = opts; ++numsegs; return RTEMS_SUCCESSFUL;}static int is_readable(unsigned ptr, unsigned len){ struct memseg *ms; int i; if( (ptr & 0x3) ) return -1; for(i=0; i<numsegs; i++) { ms= &memsegments[i]; if( ms->begin <= ptr && ptr+len <= ms->end && (ms->opts & MEMOPT_READABLE) ) return -1; } return 0;}static int is_writeable(unsigned ptr, unsigned len){ struct memseg *ms; int i; if( (ptr & 0x3) ) return -1; for(i=0; i<numsegs; i++) { ms= &memsegments[i]; if( ms->begin <= ptr && ptr+len <= ms->end && (ms->opts & MEMOPT_WRITEABLE) ) return -1; } return 0;}static int is_steppable(unsigned ptr){ struct memseg *ms; int i; if( (ptr & 0x3) ) return -1; for(i=0; i<numsegs; i++) { ms= &memsegments[i]; if( ms->begin <= ptr && ptr <= ms->end && (ms->opts & MEMOPT_WRITEABLE) ) return -1; } return 0;}static char initialized = 0; /* 0 means we are not initialized */void mips_gdb_stub_install(int enableThreads) { /* These are the RTEMS-defined vectors for all the MIPS exceptions */ int exceptionVector[]= { MIPS_EXCEPTION_MOD, \ MIPS_EXCEPTION_TLBL, \ MIPS_EXCEPTION_TLBS, \ MIPS_EXCEPTION_ADEL, \ MIPS_EXCEPTION_ADES, \ MIPS_EXCEPTION_IBE, \ MIPS_EXCEPTION_DBE, \ MIPS_EXCEPTION_SYSCALL, \ MIPS_EXCEPTION_BREAK, \ MIPS_EXCEPTION_RI, \ MIPS_EXCEPTION_CPU, \ MIPS_EXCEPTION_OVERFLOW, \ MIPS_EXCEPTION_TRAP, \ MIPS_EXCEPTION_VCEI, \ MIPS_EXCEPTION_FPE, \ MIPS_EXCEPTION_C2E, \ MIPS_EXCEPTION_WATCH, \ MIPS_EXCEPTION_VCED, \ -1 }; int i; rtems_isr_entry old; if (initialized) { ASSERT(0); return; } memset( memsegments,0,sizeof(struct memseg)*NUM_MEMSEGS ); numsegs = 0;#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) if( enableThreads ) do_threads = 1; else do_threads = 0;#endif { struct z0break *z0; z0break_avail = NULL; z0break_list = NULL; /* z0breaks list init, now we'll do it so it makes sense... */ for (i=0; i<BREAKNUM; i++) { memset( (z0= &z0break_arr[i]), 0, sizeof(struct z0break)); z0->next = z0break_avail; z0break_avail = z0; } } for(i=0; exceptionVector[i] > -1; i++) { rtems_interrupt_catch( (rtems_isr_entry) handle_exception, exceptionVector[i], &old ); } initialized = 1; /* get the attention of gdb */ /* mips_break(1); disabled so user code can choose to invoke it or not */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -