⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nlmacc.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:


#ifdef DEBUG_ME
void DumpRegs( msb *m, char *str )
{
    if( DebugClasses & (D_THREAD|D_ERROR) ) {
        ConsolePrintf( "EAX:%8.8x EBX:%8.8x ECX:%8.8x EDX:%8.8x ESI:%8.8x ESI:%8.8x\r\n",
                   m->cpu.EAX, m->cpu.EBX, m->cpu.ECX, m->cpu.EDX,
                   m->cpu.ESI, m->cpu.EDI );
        ConsolePrintf( "ESP:%8.8x EBP:%8.8x EIP:%8.8x EFL:%8.8x %s=%8.8x\r\n",
                   m->cpu.ESP, m->cpu.EBP, m->cpu.EIP, m->cpu.EFL, str, m );
    }
}
#else
#define DumpRegs( m, s )
#endif

static void BigKludge( msb *m );
#pragma aux BigKludge parm [ esi ];

static LONG DebugEntry( StackFrame *frame )
{
    msb         *m;
    struct LoadDefinitionStructure *load;
    int         exception_number;
    char        *description;
    long        error_code;

    exception_number = FieldExceptionNumber( frame );
    description = FieldExceptionDescription( frame );
    error_code = FieldErrorCode( frame );
    _DBG_EVENT(( "*DebugEntry: Event %d (%s): RunningProcess=%8.8x\r\n",
                exception_number, description, RunningProcess ));
    if( !ExpectingEvent ) {
        _DBG_EVENT(( "  Not expecting event\r\n" ));
        return( RETURN_TO_NEXT_DEBUGGER );
    }
    if( DebuggerRunning &&
        (  ( exception_number == KEYBOARD_BREAK_EVENT )
        || ( exception_number == ENTER_DEBUGGER_EVENT )
        || ( exception_number == KEYBOARD_BREAK_EVENT )
        || ( exception_number == INVALID_INTERRUPT_ABEND )
        || ( exception_number == ASSEMBLY_ABEND ) ) ) {
        return( RETURN_TO_NEXT_DEBUGGER );
    }
    if( exception_number == 1 && !TrapInt1 && !FakeBreak ) {
        return( RETURN_TO_NEXT_DEBUGGER ); /* Break set by system debugger */
    }
    if( exception_number == 2 ) { /* NMI */
        if( DebuggerRunning ) {
            return( RETURN_TO_NEXT_DEBUGGER );
        } else {
            FieldEFLAGS( frame ) |= FLG_T;
            FakeBreak = TRUE;
            return( RETURN_TO_PROGRAM );
        }
    }

    FreeInvalidThreads();
    load = (struct LoadDefinitionStructure *)error_code;
    switch( exception_number ) {
    case START_NLM_EVENT:
        /* The NLM is being loaded. We are on the loader thread here */
        _DBG_EVENT(( "  START_NLM_EVENT: LDS=%x (%s) D_LDS=%x NLMState=%x\r\n",
                        load, &(load->LDFileName[1]),
                        DebuggerLoadedNLM, NLMState ));
        if( NLMState == NLM_LOADED ) {
            m = LocateThread( RunningProcess );
            m->load = load;
            NewNLMListEntry( load );
            _DBG_EVENT(( "MSB=%x NLMState = NLM_LOADED\r\n", m ));
            break;
        } else if( NLMState == NLM_PRELOADING
                && !DebuggerLoadedNLM
                && memcmp( load->LDFileName, NLMName, NLMName[0] + 1 )
                      == 0  ) {
            m = LocateThread( RunningProcess );
            m->description = NULL;
            m->load = load;
            m->in_start_proc = TRUE;
            SavedFirstByte = *(byte *)(m->load->LDInitializationProcedure);
            *(byte *)(m->load->LDInitializationProcedure) = 0xCC;
            NLMState = NLM_LOADING;
            _DBG_EVENT(( "MSB=%x NLMState = NLM_LOADING\r\n", m ));
        } else {
            _DBG_EVENT(( "NLMState = unknown state\r\n" ));
        }
        return( RETURN_TO_PROGRAM );
    case TERMINATE_NLM_EVENT:
        _DBG_EVENT(( "  TERMINATE_NLM_EVENT: LDS=%x (%s) D_LDS=%x\r\n",
                        load, &(load->LDFileName[1]), DebuggerLoadedNLM ));
        if( load == DebuggerLoadedNLM ) {
            DebuggerLoadedNLM = NULL;
            ExpectingEvent = FALSE;
            MSB = NULL;
            WakeDebugger();
        } else {
            DeadNLMListEntry( load );
            if( DebuggerLoadedNLM != NULL )
                break;
        }
        return( RETURN_TO_PROGRAM );
    case START_THREAD_EVENT:
        load = GetNLMFromPID( RunningProcess );
        _DBG_EVENT(( "  START_THREAD_EVENT: LDS=%x (%s) D_LDS=%x\r\n",
                        load, &(load->LDFileName[1]), DebuggerLoadedNLM ));
        m = LocateThread( RunningProcess );
        m->load = load;
        if( load == DebuggerLoadedNLM ) {
            m->clib_created = TRUE;
        }
        _DBG_EVENT(( "MSB=%x\r\n", m ));
        return( RETURN_TO_PROGRAM );
    case TERMINATE_THREAD_EVENT:
        /* The thread is terminating. Free it's control block and let it die */
        load = GetNLMFromPID( RunningProcess ); // returns NULL
        _DBG_EVENT(( "  TERMINATE_THREAD_EVENT: LDS=%x (%s) D_LDS=%x,\r\n",
                        load, &(load->LDFileName[1]), DebuggerLoadedNLM ));
        m = LocateThread( RunningProcess );
        _DBG_EVENT(( "MSB=%x, NLM=%x\r\n", m, m->load ));
        FreeThread( m );
        return( RETURN_TO_PROGRAM );
    case THREAD_BOOBY_TRAP_EVENT:
        _DBG_EVENT(( "  THREAD_BOOBY_TRAPEVENT:\r\n" ));
#ifdef __NW40__
        if( GetFileServerMinorVersionNumber() < 10 ) {
//          FieldESP( frame ) += 4; // SignalDebuggerEvent points to return address
        }
#endif
    case ENTER_DEBUGGER_EVENT:
    case KEYBOARD_BREAK_EVENT:
    case INVALID_INTERRUPT_ABEND:
    case ASSEMBLY_ABEND:
    case BREAKPOINT_FUNCTION_EVENT:
        m = LocateThread( RunningProcess );
        break;
    case NLM_FAILED_INIT_EVENT:
        _DBG_EVENT(( "  NLM_FAILED_INIT_EVENT:\r\n" ));
        if( NLMState != NLM_FORCED_INIT_FAILURE ) {
            m = LocateThread( RunningProcess );
            DebuggerLoadedNLM = NULL;
            ExpectingEvent = FALSE;
            MSB = NULL;
            WakeDebugger();
        }
        return( RETURN_TO_PROGRAM );
        break;
    case 3:
        m = LocateThread( RunningProcess );
        if( NLMState == NLM_LOADING && m->in_start_proc ) {
            _DBG_EVENT(( "  3: Helper thread hits initial break\r\n" ));
            /* the helper thread hits a break point we set at start procedure */
            SaveRegs( HelperThreadRegs );
            DebuggerLoadedNLM = m->load;
            --(FieldEIP( frame ));
            *(byte *)(FieldEIP( frame )) = SavedFirstByte;
            NLMState = NLM_IN_START_PROC;
            _DBG_EVENT(( "  3: NLMState = NLM_IN_START_PROC\r\n" ));
        } else {
            --(FieldEIP( frame ));
#if 0
            if( !CheckIfBreakOKInOS( FieldEIP( frame ) ) ) {
                return( RETURN_TO_NEXT_DEBUGGER );
            }
#endif
        }
        break;
    default:
        if( exception_number > 31 ) {
            return( RETURN_TO_NEXT_DEBUGGER );
        }
        m = LocateThread( RunningProcess );
#if 0
        if( !CheckIfBreakOKInOS( FieldEIP( frame ) ) ) {
            return( RETURN_TO_NEXT_DEBUGGER );
        }
#endif
        break;
    }
    m->xnum = exception_number;
    m->errnum = error_code;
    m->description = FieldExceptionDescription( frame );
    SaveRegs( m->cpu );
    DumpRegs( m, "DebugEntry" );
    if( NPX() != X86_NO ) {
        Read387( &m->fpu );
    }
/*
 *
 * This requires comment. Netware doesn't allow us to relinquish control
 * at interrupt time. This means we have to fake the application into
 * returning to the following routine and "becoming" the debugger.
 *
 */
    _DBG_EVENT(( "DebugEntry: Leaving MSB=%8x xnum=%d PID=%8x\r\n", m, m->xnum, m->os_id ));
    FieldESI( frame ) = (LONG)m;
    FieldEIP( frame ) = (LONG)&BigKludge;
    return( RETURN_TO_PROGRAM );
}

void JumpTo( msb *m )
{
    long        ax,bx,cx,dx,si,di,bp,sp,fl,ip;

    ax = m->cpu.EAX;
    bx = m->cpu.EBX;
    cx = m->cpu.ECX;
    dx = m->cpu.EDX;
    si = m->cpu.ESI;
    di = m->cpu.EDI;
    bp = m->cpu.EBP;
    sp = m->cpu.ESP;
    fl = m->cpu.EFL;
    ip = m->cpu.EIP;
    DumpRegs( m, "JumpTo" );
    if( m->to_be_killed )
        FreeThread( m );
    DoALongJumpTo( ax,bx,cx,dx,si,di,bp,sp,fl,ip );
}


void BigKludge( msb *m )
{
    _DBG_EVENT(( "*BigKludge: MSB=%8x xnum=%d PID=%8x\r\n", m, m->xnum, m->os_id ));
    m->asleep = TRUE;
#if defined ( _USE_NEW_KERNEL )
    if( NULL == m->ksem ){
        m->ksem = kSemaphoreAlloc( NULL, 0 );
        if( NULL == m->ksem ){
            _DBG_ERROR(( "*BigKludge: Failed to allocate semaphore\r\n" ));
        }
    }
#else
    if( m->sem == 0 ) {
        m->sem = CAllocSemaphore( 0, SemaphoreTag );
    }
#endif
    if( m->xnum != THREAD_BOOBY_TRAP_EVENT ) {
        _DBG_EVENT(( "  Waking up the debugger for debug event\r\n" ));
        BoobyTrapPID( m->os_id ); /* catch all other threads in NLM */
        if( !DebuggerRunning ) {
            MSB = m;
        }
        WakeDebugger();
    }
#if defined ( _USE_NEW_KERNEL )
    _DBG_THREAD(( "Putting to sleep MSB=%8x on sem=%8x\r\n", m, m->ksem ));
    kSemaphoreWait( m->ksem );
#else
    _DBG_THREAD(( "Putting to sleep MSB=%8x on sem=%8x\r\n", m, m->sem ));
    CPSemaphore( m->sem );
#endif
    m->asleep = FALSE;
    _DBG_EVENT(( "  Waking up as MSB=%8x\r\n", m ));
    if( NPX() != X86_NO ) {
        Write387( &m->fpu );
    }
    if( ( m->cpu.EFL & FLG_T ) && m->cpu.EIP == (dword)DebugEntry ) {
        /* If we are about to trace through this routine, don't! Ouch! */
        m->cpu.EFL &= ~FLG_T;
    }
    ActivateDebugRegs();
    UnBoobyTrapPID( m->os_id );
    //_DBG_THREAD(( "Rolling. EIP=%8x, ESP=%8x, Process=%8x\r\n", m->cpu.EIP, m->cpu.ESP, RunningProcess ));
    if( m->to_be_killed ) {
        if( m->in_start_proc ) {
            int         newESP;
            //_DBG_THREAD(( "     Attempting to kill myself!!!\r\n" ));
            newESP = m->cpu.ESP;
            FreeThread( m );
            if( newESP <= HelperThreadRegs.ESP ) {
                /* the stack frame has not already gone */
                m->cpu = HelperThreadRegs;
                ReturnESP = m->cpu.ESP;
                m->cpu.EIP = (dword)Return;
                m->cpu.EAX = -1;
                NLMState = NLM_FORCED_INIT_FAILURE;
                _DBG_EVENT(( "  NLMState = NLM_FORCED_INIT_FAILURE\r\n" ));
            }
        } else if( m->clib_created ) {
#if defined ( __NW50__ )
            int type = get_app_type();

            if( type & LIBRARY_CLIB ) {
                _DBG_THREAD(( "     Warping off to _exit!!!\r\n" ));
                m->cpu.EIP = (dword)_exit;
            } else if( type & LIBRARY_LIBC) {
                _DBG_THREAD(( "     Warping off to NXVMExit!!!\r\n" ));
                m->cpu.EIP = (dword)NXVmExit;
            } else {
                _DBG_THREAD(( "     Warping off to suicide!!!\r\n" ));
                m->cpu.EIP = (dword)Suicide;
            }
#else
            _DBG_THREAD(( "     Warping off to _exit!!!\r\n" ));
            m->cpu.EIP = (dword)_exit;
#endif
        } else {
            _DBG_THREAD(( "     Suicide!!!\r\n" ));
            m->cpu.EIP = (dword)Suicide;
        }
    }
    JumpTo( m );
}

#if defined ( __NW50__ )    /* This is duplicate to 4.0 but I want to change soon */
    static struct debuggerStructure DbgStruct = {
        NULL,
        NULL,
        (LONG(*)(StackFrame *))DebugEntry,
        AT_FIRST,
        TSS_FRAME_BIT
    };
#elif defined ( __NW40__ )
    static struct debuggerStructure DbgStruct = {
        NULL,
        NULL,
        (LONG(*)(StackFrame *))DebugEntry,
        AT_FIRST,
        TSS_FRAME_BIT
    };
#elif defined ( __NW30__ )
    static T_DebuggerStruct DbgStruct = {
        NULL,
        NULL,
        DebugEntry
    };
#endif

unsigned ReqGet_sys_config( void )
{
    get_sys_config_ret  *ret;

    ret = GetOutPtr(0);
    ret->sys.cpu = X86CPUType();
    ret->sys.fpu = NPX();
    ret->sys.osmajor = FileServerMajorVersionNumber;
    ret->sys.osminor = FileServerMinorVersionNumber;
    ret->sys.os = OS_NW386;
    ret->sys.huge_shift = 12;
    ret->sys.mad = MAD_X86;
    return( sizeof( *ret ) );
}

unsigned ReqMap_addr( void )
{
    nlm_entry   *curr;
    map_addr_req        *acc;
    map_addr_ret        *ret;
    struct LoadDefinitionStructure *ld;

    //NYI: needs work for DWARF flat mode
    acc = GetInPtr(0);
    ret = GetOutPtr(0);
    ret->out_addr.segment = acc->in_addr.segment;
    ret->out_addr.offset = acc->in_addr.offset;
    ret->lo_bound = 0;
    ret->hi_bound = 0;
    _DBG_MISC(( "AccMapAddr\r\n" ));
    curr = (nlm_entry *)acc->handle;
    if( curr == NULL ) { // main NLM
        _DBG_MISC(( "Main NLM\r\n" ));
        if( MSB == NULL )
            return( sizeof( *ret ) );
        if( MSB->load == NULL )
            return( sizeof( *ret ) );
        ld = MSB->load;
    } else {
        ld = &curr->ld;
    }
    ret->hi_bound = ~(addr48_off)0;
    _DBG_MISC(( "Mapping %4x:%8x\r\n", acc->in_addr.segment, acc->in_addr.offset ));
    switch( acc->in_addr.segment ) {
    case MAP_FLAT_CODE_SELECTOR:
    case MAP_FLAT_DATA_SELECTOR:
        if( ret->out_addr.offset & NOV_EXP_ISCODE ) {
            ret->lo_bound = NOV_EXP_ISCODE;
            ret->out_addr.offset &= ~NOV_EXP_ISCODE;
            ret->out_addr.offset += ld->LDCodeImageOffset;
        } else {
            ret->hi_bound = NOV_EXP_ISCODE - 1;
            ret->out_addr.offset += ld->LDDataImageOffset;
        }
        if( acc->in_addr.segment == MAP_FLAT_CODE_SELECTOR ) {
            ret->out_addr.segment = GetCS();
        } else {
            ret->out_addr.segment = GetDS();
        }
        break;
    case 1:
        ret->out_addr.offset += ld->LDCodeImageOffset;
        ret->out_addr.segment = GetCS();
        break;
    case 2:
        ret->out_addr.offset += ld->LDDataImageOffset;
        ret->out_addr.segment = GetDS();
        break;
    }
    _DBG_MISC(( "------  %4x:%8x\r\n", ret->out_addr.segment, ret->out_addr.offset ));
    return( sizeof( *ret ) );
}

//obsolete
unsigned ReqAddr_info( void )
{
    addr_info_ret       *ret;

    ret = GetOutPtr( 0 );
    ret->is_32 = TRUE;
    return( sizeof( *ret ) );
}

unsigned ReqMachine_data( void )
{
    machine_data_ret    *ret;
    unsigned_8          *data;

    ret = GetOutPtr( 0 );
    data = GetOutPtr( sizeof( *ret ) );
    ret->cache_start = 0;
    ret->cache_end = ~(addr_off)0;
    *data = X86AC_BIG;
    return( sizeof( *ret ) + sizeof( *data ) );
}

static int ReadMemory( addr48_ptr *addr, unsigned long req, void *buf )
{
    if( MSB == NULL )
        return( -1 );
    if( CValidatePointer( (char *)addr->offset ) == NULL )
        return( -1 );
    if( CValidatePointer( (char *)addr->offset+req-1 ) == NULL )
        return( -1 );
    memcpy( buf, (void *)addr->offset, req );
    return( 0 );
}

static int WriteMemory( addr48_ptr *addr, unsigned long req, void *buf )
{
    if( MSB == NULL )
        return( -1 );
    if( CValidatePointer( (char *)addr->offset ) == NULL )
        return( -1 );
    if( CValidatePointer( (char *)addr->offset+req-1 ) == NULL )
        return( -1 );
    memcpy( (void *)addr->offset, buf, req );
    return( 0 );
}

static unsigned short ReadWrite( int (*rtn)(), addr48_ptr *addr,
                                char *buff, unsigned short requested )
{
    int                 err;
    unsigned short      len;

    err = rtn( addr, (unsigned long)requested, buff );
    if( err == 0 ) {
        addr->offset += requested;
        return( requested );
    }
    len = requested;
    while( len != 0 ) {
        if( rtn( addr, 1UL, buff++ ) != 0 )
            break;
        --len;
        addr->offset++;
    }
    return( requested - len );
}


unsigned ReqChecksum_mem( void )
{
    unsigned short      len;
    addr48_ptr          addr;
    int                 i;
    checksum_mem_req    *acc;
    checksum_mem_ret    *ret;
    long                want;
    long                got;

    acc = GetInPtr(0);
    ret = GetOutPtr(0);
    len = acc->len;
    addr.offset = acc->in_addr.offset;
    addr.segment = acc->in_addr.segment;
    ret->result = 0;
    while( len > 0 ) {
        want = len;
        if( want > BUFF_SIZE )
            want = BUFF_SIZE;
        got = ReadWrite( ReadMemory, &addr, UtilBuff, want );
        for( i = 0; i < got; ++i ) {
            ret->result += UtilBuff[ i ];
        }
        if( got != want )
            break;
        len -= want;
    }
    return( sizeof( *ret ) );
}


unsigned ReqRead_mem( void )
{
    addr48_ptr          addr;
    read_mem_req        *acc;
    unsigned            len;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -