libvx32/FreeBSD: better handling of segmentation fault, breakpoint - vx32 - Local 9vx git repository for patches.
       
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
 (DIR) commit c82f48a95967c71d4f81debf6ae9c15a3b60ebe9
 (DIR) parent d2d43ccb6890cbd0afaaa45a24db7b8d6b05129c
 (HTM) Author: Russ Cox <rsc@swtch.com>
       Date:   Sun, 29 Jun 2008 21:46:25 -0400
       
       libvx32/FreeBSD: better handling of segmentation fault, breakpoint
       
       Diffstat:
         src/libvx32/freebsd.c               |      41 +++++++++++++++++--------------
       
       1 file changed, 22 insertions(+), 19 deletions(-)
       ---
 (DIR) diff --git a/src/libvx32/freebsd.c b/src/libvx32/freebsd.c
       @@ -157,13 +157,10 @@ int vx32_sighandler(int signo, siginfo_t *si, void *v)
                vxemu *emu;
                ucontext_t *uc;
                mcontext_t *mc;
       -        uint32_t cr2;
        
                uc = v;
                mc = &uc->uc_mcontext;
        
       -        cr2 = (uint32_t)si->si_addr;
       -
                // We can't be sure that vxemu is running,
                // and thus that %VSEG is actually mapped to a
                // valid vxemu.  The only way to tell is to look at %VSEG.
       @@ -207,39 +204,45 @@ int vx32_sighandler(int signo, siginfo_t *si, void *v)
                // so that thread-local storage and such works.
                vxrun_cleanup(emu);
                
       -        // dumpmcontext(mc, cr2);
       +        // dumpmcontext(mc, (uint32_t)si->si_addr);
        
       +        uint32_t addr;
                int newtrap;
       +        addr = 0;
                switch(signo){
                case SIGSEGV:
       +                newtrap = VXTRAP_PAGEFAULT;
       +                addr = (uint32_t)si->si_addr;
       +                break;
                case SIGBUS:
       +                /*
       +                 * On FreeBSD, SIGBUS means segmentation limit fault.
       +                 * The supplied address is bogus.
       +                 */
                        newtrap = VXTRAP_PAGEFAULT;
       +                addr = 0;
                        break;
                
                case SIGFPE:
       -                // iprint("fpe %d\n", si->si_code);
       +                // vxprint("fpe %d\n", si->si_code);
                        newtrap = VXTRAP_FLOAT;
       +                addr = 0;
                        break;
                
                case SIGVTALRM:
                        newtrap = VXTRAP_IRQ + VXIRQ_TIMER;
       +                addr = 0;
                        break;
        
                case SIGTRAP:
       -#warning "FreeBSD: need to test single-stepping"
       -                // Linux sends SIGTRAP when it gets a processor 
       +                // FreeBSD sends SIGTRAP when it gets a processor 
                        // debug exception, which is caused by single-stepping
       -                // with the TF bit, among other things.  The processor
       -                // turns off the TF bit before generating the trap, but
       -                // it appears that Linux turns it back on for us.
       -                // Let's use it to confirm that this is a single-step trap.
       -                if (mc->mc_eflags & EFLAGS_TF){
       -                        newtrap = VXTRAP_SINGLESTEP;
       -                        mc->mc_eflags &= ~EFLAGS_TF;
       -                }else{
       -                        vxprint("Unexpected sigtrap eflags=%#x\n", mc->mc_eflags);
       -                        newtrap = VXTRAP_SIGNAL + signo;
       -                }
       +                // with the TF bit, among other things.  
       +                // It appears that FreeBSD does not turn the flag back on
       +                // before entering the signal handler.
       +                addr = 0;
       +                newtrap = VXTRAP_SINGLESTEP;
       +                mc->mc_eflags &= ~EFLAGS_TF;        // Just in case.
                        break;
        
                default:
       @@ -323,7 +326,7 @@ int vx32_sighandler(int signo, siginfo_t *si, void *v)
                        if (emu->trapenv == NULL)
                                return 0;
                        emu->cpu.traperr = mc->mc_err;
       -                emu->cpu.trapva = cr2;
       +                emu->cpu.trapva = addr;
                        memmove(&mc->mc_gs, &emu->trapenv->mc_gs, 19*4);
                        return 1;
                }