Exemple #1
0
/*
 * AddLib - a new library has loaded
 */
static void AddLib( struct link_map *lmap )
{
    lib_load_info       *lli;

    /* This code is not terribly efficient */
    ModuleTop++;
    lli = malloc( ModuleTop * sizeof( lib_load_info ) );
    memset( lli, 0, ModuleTop * sizeof( lib_load_info ) );
    memcpy( lli, moduleInfo, (ModuleTop - 1) * sizeof( lib_load_info ) );
    free( moduleInfo );
    moduleInfo = lli;
    lli = &moduleInfo[ModuleTop - 1];

    lli->offset = lmap->l_addr;
    lli->dbg_dyn_sect = (addr_off)lmap->l_ld;
    dbg_strcpy( pid, lli->filename, lmap->l_name );
    lli->newly_loaded = true;
    lli->newly_unloaded = false;
    lli->offset = lmap->l_addr;

    Out( "Added library: ofs/dyn = " );
    OutNum( lmap->l_addr );
    Out( "/" );
    OutNum( (addr_off)lmap->l_ld );
    Out( " " );
    Out( lli->filename );
    Out( "\n" );
}
Exemple #2
0
unsigned ReqClear_break( void )
{
    clear_break_req *acc;
    bp_t            opcode;

    acc = GetInPtr( 0 );
    CONV_LE_32( acc->break_addr.offset );
    CONV_LE_16( acc->break_addr.segment );
    opcode = acc->old;
    WriteMem( pid, &opcode, acc->break_addr.offset, sizeof( opcode ) );
    Out( "ReqClear_break at " );
    OutNum( acc->break_addr.offset );
    Out( " (setting to " );
    OutNum( opcode );
    Out( ")\n" );
    return( 0 );
}
Exemple #3
0
/*
 * AccGetLibName - get lib name of current module
 */
trap_retval ReqGet_lib_name( void )
{
    get_lib_name_req    *acc;
    get_lib_name_ret    *ret;
    char                *name;
    unsigned            i;
    trap_elen           ret_len;

    acc = GetInPtr( 0 );
    CONV_LE_32( acc->mod_handle );
    ret = GetOutPtr( 0 );
    name = GetOutPtr( sizeof( *ret ) );

    ret->mod_handle = 0;
    ret_len = sizeof( *ret );

    for( i = 0; i < ModuleTop; ++i ) {
        if( moduleInfo[i].newly_unloaded ) {
            Out( "(newly unloaded) " );
            ret->mod_handle = i;
            *name = '\0';
            moduleInfo[i].newly_unloaded = false;
            ++ret_len;
            break;
        } else if( moduleInfo[i].newly_loaded ) {
            Out( "(newly loaded) " );
            ret->mod_handle = i;
            strcpy( name, moduleInfo[i].filename );
            moduleInfo[i].newly_loaded = false;
            ret_len += strlen( name ) + 1;
            break;
        }
    }
    Out( "ReqGet_lib_name: in handle " );
    OutNum( acc->mod_handle );
    Out( " out handle " );
    OutNum( ret->mod_handle );
    Out( "\n" );
    CONV_LE_32( ret->mod_handle );
    return( ret_len );
}
Exemple #4
0
static void OutBuff( TRACEBUF far *buf )
{
    Out( "pid   = " ); OutNum( buf->pid ); Out( "\r\n" );
    Out( "tid   = " ); OutNum( buf->tid ); Out( "\r\n" );
    Out( "cmd   = " ); OutNum( buf->cmd ); Out( "\r\n" );
    Out( "value = " ); OutNum( buf->value ); Out( "\r\n" );
    Out( "offv  = " ); OutNum( buf->offv ); Out( "\r\n" );
    Out( "segv  = " ); OutNum( buf->segv ); Out( "\r\n" );
    Out( "mte   = " ); OutNum( buf->mte ); Out( "\r\n" );
}
Exemple #5
0
unsigned ReqSet_break( void )
{
    set_break_req   *acc;
    set_break_ret   *ret;
    bp_t            opcode;

    acc = GetInPtr( 0 );
    ret = GetOutPtr( 0 );
    CONV_LE_32( acc->break_addr.offset );
    CONV_LE_16( acc->break_addr.segment );
    ReadMem( pid, &opcode, acc->break_addr.offset, sizeof( opcode ) );
    ret->old = opcode;
    opcode = BRK_POINT;
    WriteMem( pid, &opcode, acc->break_addr.offset, sizeof( opcode ) );
    Out( "ReqSet_break at " );
    OutNum( acc->break_addr.offset );
    Out( " (was " );
    OutNum( ret->old );
    Out( ")\n" );
    return( sizeof( *ret ) );
}
Exemple #6
0
/*
 * AccMapAddr - map address in image from link-time virtual address to
 * actual linear address as loaded in memory. For executables, this will
 * in effect return the address unchanged (image base 0x08048100 equals
 * linear 0x08048100), for shared libs this will typically add the offset
 * from zero (link time VA) to actual load base.
 */
trap_retval ReqMap_addr( void )
{
    map_addr_req    *acc;
    map_addr_ret    *ret;
    unsigned long   val;
    lib_load_info   *lli;

    // Note: Info about the process address space is stored in the user register
    //       for GDB, so we can use that to find out what we need to convert these
    //       values in here...
    acc = GetInPtr( 0 );
    CONV_LE_32( acc->in_addr.offset );
    CONV_LE_16( acc->in_addr.segment );
    CONV_LE_32( acc->mod_handle );
    ret = GetOutPtr( 0 );
    ret->lo_bound = 0;
    ret->hi_bound = ~(addr_off)0;
    errno = 0;
    if( (val = ptrace( PTRACE_PEEKUSER, pid, (void *)(offsetof( user_struct, start_code )), 0 )) == -1 ) {
        if( errno ) {
            Out( "ReqMap_addr: first PTRACE_PEEKUSER failed!\n" );
            val = 0;
        }
    }
#ifdef __MIPS__
    // Hack for MIPS - the above call seems to be failing but isn't returning
    // an error; it's possible that the call just isn't valid.
    val = 0;
#endif
    ret->out_addr.offset = acc->in_addr.offset + val;

    if( acc->mod_handle > ModuleTop ) {
        Out( "ReqMap_addr: Invalid handle passed!\n" );
        return( sizeof( *ret ) );
    } else {
        lli = &moduleInfo[acc->mod_handle];
    }

    Out( "ReqMap_addr: addr " );
    OutNum( acc->in_addr.segment );
    Out( ":" );
    OutNum( acc->in_addr.offset );
    Out( " in module " );
    OutNum( acc->mod_handle );
    if( acc->in_addr.segment == MAP_FLAT_DATA_SELECTOR ||
        acc->in_addr.segment == flatDS ) {
        if( (val = ptrace( PTRACE_PEEKUSER, pid, (void *)offsetof( user_struct, u_tsize ), 0 )) == -1 ) {
            if( errno ) {
                Out( "ReqMap_addr: second PTRACE_PEEKUSER failed!\n" );
                val = 0;
            }
        }
        ret->out_addr.offset += val;
        ret->out_addr.segment = flatDS;
    } else {
        ret->out_addr.segment = flatCS;
    }
    ret->out_addr.offset += lli->offset;
    Out( " to " );
    OutNum( ret->out_addr.offset );
    Out( "\n" );
    CONV_LE_32( ret->out_addr.offset );
    CONV_LE_16( ret->out_addr.segment );
    CONV_LE_32( ret->lo_bound );
    CONV_LE_32( ret->hi_bound );
    return( sizeof( *ret ) );
}
Exemple #7
0
static unsigned ProgRun( int step )
{
    static int          ptrace_sig = 0;
    static int          ld_state = 0;
    user_regs_struct    regs;
    int                 status;
    prog_go_ret         *ret;
    void                (*old)(int);
    int                 debug_continue;

    if( pid == 0 )
        return( 0 );
    ret = GetOutPtr( 0 );

    if( at_end ) {
        ptrace_sig = 0;
        ret->conditions = COND_TERMINATE;
        goto end;
    }

    /* we only want child-generated SIGINTs now */
    do {
        old = setsig( SIGINT, SIG_IGN );
        if( step ) {
            Out( "PTRACE_SINGLESTEP\n" );
            if( ptrace( PTRACE_SINGLESTEP, pid, NULL, (void *)ptrace_sig ) == -1 )
                perror( "PTRACE_SINGLESTEP" );
        } else {
            Out( "PTRACE_CONT\n" );
            if( ptrace( PTRACE_CONT, pid, NULL, (void *)ptrace_sig ) == -1 )
                perror( "PTRACE_CONT" );
        }
        waitpid( pid, &status, 0 );
        setsig( SIGINT, old );

#if defined( MD_x86 )
        ptrace( PTRACE_GETREGS, pid, NULL, &regs );
#elif defined( MD_ppc )
        regs.eip = ptrace( PTRACE_PEEKUSER, pid, REGSIZE * PT_NIP, NULL );
        regs.esp = ptrace( PTRACE_PEEKUSER, pid, REGSIZE * PT_R1, NULL );
#elif defined( MD_mips )
        regs.eip = ptrace( PTRACE_PEEKUSER, pid, (void *)PC, NULL );
        regs.esp = ptrace( PTRACE_PEEKUSER, pid, (void *)29, NULL );
#endif
        Out( " eip " );
        OutNum( regs.eip );
        Out( "\n" );

        debug_continue = FALSE;
        if( WIFSTOPPED( status ) ) {
            switch( ( ptrace_sig = WSTOPSIG( status ) ) ) {
            case SIGSEGV:
            case SIGILL:
            case SIGFPE:
            case SIGABRT:
            case SIGBUS:
            case SIGQUIT:
            case SIGSYS:
                last_sig = ptrace_sig;
                ret->conditions = COND_EXCEPTION;
                ptrace_sig = 0;
                break;
            case SIGINT:
                ret->conditions = COND_USER;
                ptrace_sig = 0;
                break;
            case SIGTRAP:
                ret->conditions = step ? COND_TRACE : COND_BREAK;
                Out( "sigtrap\n" );
                ptrace_sig = 0;
                break;
            default:
                /* For signals that we do not wish to handle, we need
                 * to continue the debuggee until we get a signal
                 * that we need to handle
                 */
                Out( "Unknown signal " );
                OutNum( ptrace_sig );
                Out( "\n" );
                debug_continue = TRUE;
                break;
            }
        } else if( WIFEXITED( status ) ) {
            Out( "WIFEXITED\n" );
            at_end = TRUE;
            ret->conditions = COND_TERMINATE;
            ptrace_sig = 0;
            goto end;
        }
    } while( debug_continue );

    if( ret->conditions == COND_BREAK ) {
#if defined( MD_x86 )
        if( regs.eip == rdebug.r_brk + sizeof( old_ld_bp ) ) {
#elif defined( MD_ppc ) || defined( MD_mips )
        if( regs.eip == rdebug.r_brk ) {
#endif
            int         psig = 0;
            void        (*oldsig)(int);
            bp_t        opcode = BRK_POINT;

            /* The dynamic linker breakpoint was hit, meaning that
             * libraries are being loaded or unloaded. This gets a bit
             * tricky because we must restore the original code that was
             * at the breakpoint and execute it, but we still want to
             * keep the breakpoint.
             */
            WriteMem( pid, &old_ld_bp, rdebug.r_brk, sizeof( old_ld_bp ) );
            ReadMem( pid, &rdebug, (addr48_off)dbg_rdebug, sizeof( rdebug ) );
            Out( "ld breakpoint hit, state is " );
            switch( rdebug.r_state ) {
            case RT_ADD:
                Out( "RT_ADD\n" );
                ld_state = RT_ADD;
                AddOneLib( rdebug.r_map );
                break;
            case RT_DELETE:
                Out( "RT_DELETE\n" );
                ld_state = RT_DELETE;
                break;
            case RT_CONSISTENT:
                Out( "RT_CONSISTENT\n" );
                if( ld_state == RT_DELETE )
                    DelOneLib( rdebug.r_map );
                ld_state = RT_CONSISTENT;
                break;
            default:
                Out( "error!\n" );
                break;
            }
            regs.orig_eax = -1;
#if defined( MD_x86 )
            regs.eip--;
            ptrace( PTRACE_SETREGS, pid, NULL, &regs );
#endif
            oldsig = setsig( SIGINT, SIG_IGN );
            ptrace( PTRACE_SINGLESTEP, pid, NULL, (void *)psig );
            waitpid( pid, &status, 0 );
            setsig( SIGINT, oldsig );
            WriteMem( pid, &opcode, rdebug.r_brk, sizeof( old_ld_bp ) );
            ret->conditions = COND_LIBRARIES;
        } else {
#if defined( MD_x86 )
            Out( "decrease eip(sigtrap)\n" );
            regs.orig_eax = -1;
            regs.eip--;
            ptrace( PTRACE_SETREGS, pid, NULL, &regs );
#endif
        }
    }
    orig_eax = regs.orig_eax;
    last_eip = regs.eip;
    ret->program_counter.offset = regs.eip;
    ret->program_counter.segment = regs.cs;
    ret->stack_pointer.offset = regs.esp;
    ret->stack_pointer.segment = regs.ss;
    ret->conditions |= COND_CONFIG;

    /* If debuggee has dynamic section, try getting the r_debug struct
     * every time the debuggee stops. The r_debug data may not be available
     * immediately after the debuggee process loads.
     */
    if( !have_rdebug && (dbg_dyn != NULL) ) {
        if( Get_ld_info( pid, dbg_dyn, &rdebug, &dbg_rdebug ) ) {
            bp_t        opcode;

            AddInitialLibs( rdebug.r_map );
            have_rdebug = TRUE;
            ret->conditions |= COND_LIBRARIES;

            /* Set a breakpoint in dynamic linker. That way we can be
             * informed on dynamic library load/unload events.
             */
            ReadMem( pid, &old_ld_bp, rdebug.r_brk, sizeof( old_ld_bp ) );
            Out( "Setting ld breakpoint at " );
            OutNum( rdebug.r_brk );
            Out( " old opcode was " );
            OutNum( old_ld_bp );
            Out( "\n" );
            opcode = BRK_POINT;
            WriteMem( pid, &opcode, rdebug.r_brk, sizeof( opcode ) );
        }
    }
 end:
    CONV_LE_32( ret->stack_pointer.offset );
    CONV_LE_16( ret->stack_pointer.segment );
    CONV_LE_32( ret->program_counter.offset );
    CONV_LE_16( ret->program_counter.segment );
    CONV_LE_16( ret->conditions );
    return( sizeof( *ret ) );
}

unsigned ReqProg_step( void )
{
    return( ProgRun( TRUE ) );
}

unsigned ReqProg_go( void )
{
    return( ProgRun( FALSE ) );
}

unsigned ReqRedirect_stdin( void  )
{
    redirect_stdin_ret *ret;

    ret = GetOutPtr( 0 );
    ret->err = 1;
    return( sizeof( *ret ) );
}