From owner-p4-projects@FreeBSD.ORG Sat May 3 15:12:59 2003 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 170EB37B404; Sat, 3 May 2003 15:12:59 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id AA64D37B401 for ; Sat, 3 May 2003 15:12:58 -0700 (PDT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 0AF3F43FBD for ; Sat, 3 May 2003 15:12:58 -0700 (PDT) (envelope-from marcel@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.6/8.12.6) with ESMTP id h43MCv0U084330 for ; Sat, 3 May 2003 15:12:57 -0700 (PDT) (envelope-from marcel@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.6/8.12.6/Submit) id h43MCvM2084327 for perforce@freebsd.org; Sat, 3 May 2003 15:12:57 -0700 (PDT) Date: Sat, 3 May 2003 15:12:57 -0700 (PDT) Message-Id: <200305032212.h43MCvM2084327@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to marcel@freebsd.org using -f From: Marcel Moolenaar To: Perforce Change Reviews Subject: PERFORCE change 30481 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 03 May 2003 22:13:00 -0000 http://perforce.freebsd.org/chv.cgi?CH=30481 Change 30481 by marcel@marcel_nfs on 2003/05/03 15:12:53 Get i386 to compile again. MD support functions for GDB support have been put in db_interface.c. This should have the MI framework mostly in good shape. The only real hardcoding is in the first packet: we assume there's a PC, FP and SP. Porting the other architectures should make it clear whether we can get away with it or not. I'll cross that bridge when I come to it. Affected files ... .. //depot/projects/sio/sys/ddb/db_gdb.c#2 edit .. //depot/projects/sio/sys/i386/i386/db_interface.c#3 edit .. //depot/projects/sio/sys/i386/include/db_machdep.h#3 edit Differences ... ==== //depot/projects/sio/sys/ddb/db_gdb.c#2 (text+ko) ==== @@ -224,6 +224,94 @@ static int encdecsz; static __inline void +gdb_dec_begin(char *buf, int size) +{ + encdecp = buf; + encdecsz = size; +} + +static __inline int +gdb_dec_char(void) +{ + int c; + if (encdecsz > 0) { + c = *encdecp++; + encdecsz--; + } else + c = -1; + return (c); +} + +static __inline int +gdb_dec_int8(void) +{ + int h, l; + h = gdb_hex(gdb_dec_char()); + l = gdb_hex(gdb_dec_char()); + if (h != -1 && l != -1) + return ((h << 4) | (l & 0xf)); + else + return (-1); +} + +static __inline int +gdb_dec_int16(void) +{ + int h, l; + h = gdb_dec_int8(); + l = gdb_dec_int8(); + if (h != -1 && l != -1) + return ((h << 8) | (l & 0xff)); + else + return (-1); +} + +static __inline int32_t +gdb_dec_int32(void) +{ + int32_t h, l; + h = gdb_dec_int16(); + l = gdb_dec_int16(); + if (h != -1 && l != -1) + return ((h << 16) | (l & 0xffff)); + else + return (-1); +} + +static __inline uint64_t +gdb_dec_int64(void) +{ + int64_t h, l; + h = gdb_dec_int32(); + l = gdb_dec_int32(); + if (h != -1 && l != -1) + return ((h << 32) | (l & 0xffffffff)); + else + return (-1); +} + +static __inline int +gdb_dec_block(gdb_addr addr, int len) +{ + uint8_t *p = (void*)(intptr_t)addr; + int c; + while (len > 0) { + c = gdb_dec_int8(); + if (c == -1) + return (-1); + *p++ = c; + len--; + } + return 0; +} + +static __inline int +gdb_dec_registers(struct gdb_registers *regs) +{ + return (gdb_dec_block((intptr_t)regs, sizeof(*regs))); +} + +static __inline void gdb_enc_begin(char *buf, int size) { encdecp = buf; @@ -280,6 +368,20 @@ gdb_enc_int32(i & 0xffffffff); } +static __inline void +gdb_enc_block(gdb_addr addr, int len) +{ + uint8_t *p = (void*)(intptr_t)addr; + while (len > 0) + gdb_enc_int8(*p++), len--; +} + +static __inline void +gdb_enc_registers(struct gdb_registers *regs) +{ + gdb_enc_block((intptr_t)regs, sizeof(*regs)); +} + /* * gdb_handle_exception * @@ -327,8 +429,12 @@ int gdb_handle_exception(db_regs_t *raw_regs, int type) { - char *ptr; - int addr, error, length, regno; + struct gdb_registers regs; + gdb_addr addr; + gdb_reg reg; + int c, error, len, regno; + + gdb_getregs(®s, raw_regs); /* "TxxPC:xxxxxxxx;FP:xxxxxxxx;SP:xxxxxxxx;" */ gdb_enc_begin(gdb_buffer, sizeof(gdb_buffer)); @@ -336,19 +442,18 @@ gdb_enc_int8(gdb_signal(type)); gdb_enc_int8(GDB_REGNUM_PC); gdb_enc_char(':'); - gdb_enc_register(raw_regs->eip); + gdb_enc_reg(gdb_getreg(®s, GDB_REGNUM_PC)); gdb_enc_char(';'); gdb_enc_int8(GDB_REGNUM_FP); gdb_enc_char(':'); - gdb_enc_register(raw_regs->ebp); + gdb_enc_reg(gdb_getreg(®s, GDB_REGNUM_FP)); gdb_enc_char(';'); gdb_enc_int8(GDB_REGNUM_SP); gdb_enc_char(':'); - gdb_enc_register(raw_regs->esp); + gdb_enc_reg(gdb_getreg(®s, GDB_REGNUM_SP)); gdb_enc_char(';'); - error = gdb_enc_end(); - if (!error) - error = gdb_putpacket(gdb_buffer); + gdb_enc_end(); + error = gdb_putpacket(gdb_buffer); if (error) return (error); @@ -356,7 +461,8 @@ error = gdb_getpacket(gdb_buffer); if (error) return (error); - switch (*gdb_buffer) { + gdb_dec_begin(gdb_buffer, sizeof(gdb_buffer)); + switch (gdb_dec_char()) { case '?': gdb_enc_begin(gdb_buffer, sizeof(gdb_buffer)); gdb_enc_char('S'); @@ -373,25 +479,25 @@ case 'g': /* Return the value of the CPU registers */ - mem2hex((vm_offset_t)®isters, gdb_buffer, - NUMREGBYTES); + gdb_enc_begin(gdb_buffer, sizeof(gdb_buffer)); + gdb_enc_registers(®s); + gdb_enc_end(); gdb_putpacket(gdb_buffer); break; case 'G': /* Set the value of the CPU registers - return OK */ - hex2mem(gdb_buffer + 1, (vm_offset_t)®isters, - NUMREGBYTES); + gdb_dec_registers(®s); gdb_putpacket("OK"); break; case 'P': /* Set the value of one register */ - ptr = gdb_buffer + 1; - if (hexToInt(&ptr, ®no) && *ptr++ == '=' && - regno < NUM_REGS) { - hex2mem(ptr, - (vm_offset_t)®isters + regno * 4, 4); + regno = gdb_dec_int32(); + c = gdb_dec_char(); + reg = gdb_dec_reg(); + if (regno > 0 && c == '=') { + gdb_setreg(®s, regno, reg); gdb_putpacket("OK"); } else gdb_putpacket("P01"); @@ -400,15 +506,15 @@ case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ /* Try to read %x,%x. */ - ptr = gdb_buffer + 1; - if (hexToInt(&ptr, &addr) && *(ptr++) == ',' && - hexToInt (&ptr, &length)) { - if (mem2hex((vm_offset_t)addr, - gdb_buffer, length) == NULL) - gdb_putpacket("E03"); - else - gdb_putpacket(gdb_buffer); - break; + addr = gdb_dec_addr(); + c = gdb_dec_char(); + len = gdb_dec_int32(); + if (c == ',' && len > 0) { + gdb_enc_begin(gdb_buffer, sizeof(gdb_buffer)); + gdb_enc_block(addr, len); + gdb_enc_end(); + gdb_putpacket(gdb_buffer); + /* XXX return "E03" when encoding fails. */ } else gdb_putpacket("E01"); break; @@ -417,31 +523,34 @@ /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA */ /* return OK */ /* Try to read '%x,%x:'. */ - ptr = gdb_buffer + 1; - if (hexToInt(&ptr,&addr) && *(ptr++) == ',' && - hexToInt(&ptr, &length) && *(ptr++) == ':') { - if (hex2mem(ptr, (vm_offset_t)addr, length) - == NULL) - gdb_putpacket("E03"); - else - gdb_putpacket("OK"); + addr = gdb_dec_addr(); + c = gdb_dec_char(); + len = gdb_dec_int32(); + if (c == ',' && len > 0 && gdb_dec_char() == ':') { + gdb_dec_block(addr, len); + gdb_putpacket("OK"); + /* XXX return "E03" when decoding fails. */ } else gdb_putpacket("E02"); break; case 'c' : /* cAA..AA Continue at address AA..AA (opt) */ - /* FALLTHROUGH */ + gdb_singlestep(®s, 0); + addr = gdb_dec_addr(); + if (addr != ~0U) + gdb_setreg(®s, GDB_REGNUM_PC, addr); + gdb_setregs(®s, raw_regs); + return (0); + case 's' : /* sAA..AA Step one instruction from AA..AA (opt) */ - gdb_cpu_set_regs(®s); - /* try to read optional parameter */ - ptr = gdb_buffer + 1; - if (hexToInt(&ptr,&addr)) - gdb_cpu_set_pc(addr); - /* set the trace bit if we're stepping */ - gdb_cpu_singlestep((*gdb_buffer == 's') ? 1 : 0); - return 0; + gdb_singlestep(®s, 1); + addr = gdb_dec_addr(); + if (addr != ~0U) + gdb_setreg(®s, GDB_REGNUM_PC, addr); + gdb_setregs(®s, raw_regs); + return (0); } /* switch */ } ==== //depot/projects/sio/sys/i386/i386/db_interface.c#3 (text+ko) ==== @@ -303,6 +303,100 @@ } } +int +gdb_signal(int vector) +{ + switch (vector & ~T_USER) { + case 0: return (SIGFPE); /* divide by zero */ + case 1: return (SIGTRAP); /* debug exception */ + case 3: return (SIGTRAP); /* breakpoint */ + case 4: return (SIGURG); /* into instr (overflow) */ + case 5: return (SIGURG); /* bound instruction */ + case 6: return (SIGILL); /* Invalid opcode */ + case 7: return (SIGFPE); /* npx not available */ + case 8: return (SIGEMT); /* double fault */ + case 9: return (SIGSEGV); /* npx segment overrun */ + case 10: return (SIGTRAP); /* Invalid TSS (also single-step) */ + case 11: return (SIGSEGV); /* Segment not present */ + case 12: return (SIGSEGV); /* stack exception */ + case 13: return (SIGSEGV); /* general protection */ + case 14: return (SIGSEGV); /* page fault */ + case 16: return (SIGEMT); /* coprocessor error */ + } + return (SIGEMT); +} + +gdb_reg +gdb_getreg(struct gdb_registers *regs, int regnum) +{ + gdb_reg *regp; + + regp = (void*)regs; + if ((void*)(regp + regnum) < (void*)(regs + 1)) + return (regp[regnum]); + /* XXX complain. */ + return (~0); +} + +void +gdb_setreg(struct gdb_registers *regs, int regnum, gdb_reg val) +{ + gdb_reg *regp; + + regp = (void*)regs; + if ((void*)(regp + regnum) < (void*)(regs + 1)) + regp[regnum] = val; +} + +void +gdb_getregs(struct gdb_registers *regs, db_regs_t *raw_regs) +{ + + regs->eax = raw_regs->tf_eax; + regs->ebx = raw_regs->tf_ebx; + regs->ecx = raw_regs->tf_ecx; + regs->edx = raw_regs->tf_edx; + regs->esp = raw_regs->tf_esp; + regs->ebp = raw_regs->tf_ebp; + regs->esi = raw_regs->tf_esi; + regs->edi = raw_regs->tf_edi; + regs->eip = raw_regs->tf_eip; + regs->eflags = raw_regs->tf_eflags; + regs->cs = raw_regs->tf_cs; + regs->ss = raw_regs->tf_ss; + regs->ds = raw_regs->tf_ds; + regs->es = raw_regs->tf_es; +} + +void +gdb_setregs(struct gdb_registers *regs, db_regs_t *raw_regs) +{ + + raw_regs->tf_eax = regs->eax; + raw_regs->tf_ebx = regs->ebx; + raw_regs->tf_ecx = regs->ecx; + raw_regs->tf_edx = regs->edx; + raw_regs->tf_esp = regs->esp; + raw_regs->tf_ebp = regs->ebp; + raw_regs->tf_esi = regs->esi; + raw_regs->tf_edi = regs->edi; + raw_regs->tf_eip = regs->eip; + raw_regs->tf_eflags = regs->eflags; + raw_regs->tf_cs = regs->cs; + raw_regs->tf_ss = regs->ss; + raw_regs->tf_ds = regs->ds; + raw_regs->tf_es = regs->es; +} + +void +gdb_singlestep(struct gdb_registers *regs, int set) +{ + if (set) + regs->eflags |= PSL_T; + else + regs->eflags &= ~PSL_T; +} + /* * XXX * Move this to machdep.c and allow it to be called if any debugger is ==== //depot/projects/sio/sys/i386/include/db_machdep.h#3 (text+ko) ==== @@ -97,9 +97,35 @@ #define GDB_REGNUM_FP 5 #define GDB_REGNUM_PC 8 -/* What size are registers? */ -#define gdb_enc_register gdb_enc_int32 +typedef uint32_t gdb_reg; +typedef uint32_t gdb_addr; + +#define gdb_dec_addr gdb_dec_int32 +#define gdb_dec_reg gdb_dec_int32 +#define gdb_enc_reg gdb_enc_int32 + +struct gdb_registers { + gdb_reg eax; + gdb_reg ecx; + gdb_reg edx; + gdb_reg ebx; + gdb_reg esp; + gdb_reg ebp; + gdb_reg esi; + gdb_reg edi; + gdb_reg eip; + gdb_reg eflags; + gdb_reg cs; + gdb_reg ss; + gdb_reg ds; + gdb_reg es; +}; -int gdb_signal(int); +gdb_reg gdb_getreg(struct gdb_registers *, int); +void gdb_getregs(struct gdb_registers *, db_regs_t *); +void gdb_setreg(struct gdb_registers *, int, gdb_reg); +void gdb_setregs(struct gdb_registers *, db_regs_t *); +void gdb_singlestep(struct gdb_registers *, int); +int gdb_signal(int); #endif /* !_MACHINE_DB_MACHDEP_H_ */