Пример #1
0
// DAC global pointer table initialization
void DacGlobals::Initialize()
{
    TADDR baseAddress = PTR_TO_TADDR(PAL_GetSymbolModuleBase((void *)DacGlobals::Initialize));
    g_dacTable.InitializeEntries(baseAddress);
#ifdef FEATURE_SVR_GC
    g_dacTable.InitializeSVREntries(baseAddress);
#endif
}
Пример #2
0
// DAC global pointer table initialization
void DacGlobals::Initialize()
{
    TADDR baseAddress = PTR_TO_TADDR(PAL_GetSymbolModuleBase((void *)DacGlobals::Initialize));
    g_dacTable.InitializeEntries(baseAddress);
#ifdef FEATURE_SVR_GC
    g_dacTable.InitializeSVREntries(baseAddress);
#endif
    PAL_PublishDacTableAddress((PVOID)baseAddress, &g_dacTable, sizeof(g_dacTable));
}
Пример #3
0
static bool shouldEnterCall(PTR_BYTE ip) {
    SUPPORTS_DAC;

    int datasize; // helper variable for decoding of address modes
    int mod;      // helper variable for decoding of mod r/m
    int rm;       // helper variable for decoding of mod r/m

    int pushes = 0;

    // we should start unbalenced pops within 48 instrs. If not, it is not a special epilog function
    // the only reason we need as many instructions as we have below is because  coreclr
    // gets instrumented for profiling, code coverage, BBT etc, and we want these things to
    // just work.
    for (int i = 0; i < 48; i++) {
        switch(*ip) {
            case 0x68:              // push 0xXXXXXXXX
                ip += 5;

                // For office profiler.  They morph tail calls into push TARGET; jmp helper
                // so if you see
                // 
                // push XXXX
                // jmp xxxx
                // 
                // and we notice that coreclr has been instrumented and
                // xxxx starts with a JMP [] then do what you would do for jmp XXXX
                if (*ip == 0xE9 && callsInstrumented()) {        // jmp helper
                    PTR_BYTE tmpIp = ip + 5;
                    PTR_BYTE target = tmpIp + (__int32)*((PTR_TADDR)(PTR_TO_TADDR(tmpIp) - 4));
                    if (target[0] == 0xFF && target[1] == 0x25) {                // jmp [xxxx] (to external dll)
                        ip = PTR_BYTE(*((PTR_TADDR)(PTR_TO_TADDR(ip) - 4)));
                    }
                }
                else {
                pushes++;
                }
                break;

            case 0x50:              // push EAX
            case 0x51:              // push ECX
            case 0x52:              // push EDX
            case 0x53:              // push EBX
            case 0x55:              // push EBP
            case 0x56:              // push ESI
            case 0x57:              // push EDI
                pushes++;
                ip++;
                break;
                
            case 0xE8:              // call <disp32>
                ip += 5;
                pushes = 0;         // This assumes that all of the previous pushes are arguments to this call 
                break;

            case 0xFF:        
                if (ip[1] != 0x15)  // call [XXXX] is OK (prolog of epilog helper is intrumented)
                    return false;   // but everything else is not OK. 
                ip += 6;
                pushes = 0;         // This assumes that all of the previous pushes are arguments to this call 
                break;

            case 0x9C:              // pushfd
            case 0x9D:              // popfd
                // a pushfd can never be an argument, so we model a pair of
                // these instruction as not changing the stack so that a call
                // that occurs between them does not consume the value of pushfd
                ip++;
                break;

            case 0x5D:              // pop EBP
            case 0x5E:              // pop ESI
            case 0x5F:              // pop EDI
            case 0x5B:              // pop EBX
            case 0x58:              // pop EAX
            case 0x59:              // pop ECX
            case 0x5A:              // pop EDX
                if (pushes <= 0) {
                    // We now have more pops than pushes.  This is our indication
                    // that we are in an EH_epilog function so we return true.
                    // This is the only way to exit this method with a retval of true.
                    return true;
                }
                --pushes;
                ip++;
                break;

            case 0xA1:              // MOV EAX, [XXXX]
                ip += 5;
                break;

            case 0xC6:              // MOV r/m8, imm8
                datasize = 1;
                goto decodeRM;

            case 0x89:              // MOV r/m, reg
                if (ip[1] == 0xE5)  // MOV EBP, ESP
                    return false;
                if (ip[1] == 0xEC)  // MOV ESP, EBP
                    return false;
                goto move;

            case 0x8B:              // MOV reg, r/m
                if (ip[1] == 0xE5)  // MOV ESP, EBP
                    return false;
                if (ip[1] == 0xEC)  // MOV EBP, ESP
                    return false;
                goto move;

            case 0x88:              // MOV reg, r/m (BYTE)
            case 0x8A:              // MOV r/m, reg (BYTE)

            case 0x31:              // XOR
            case 0x32:              // XOR
            case 0x33:              // XOR

        move:
                datasize = 0;

        decodeRM:
                // Note that we don't want to read from ip[] after
                // we do ANY incrementing of ip

                mod = (ip[1] & 0xC0) >> 6;
                if (mod != 3) {
                    rm  = (ip[1] & 0x07);
                    if (mod == 0) {         // (mod == 0) 
                        if      (rm == 5)
                            ip += 4;            // disp32
                        else if (rm == 4)
                            ip += 1;            // [reg*K+reg]
                                                // otherwise [reg]

                    }
                    else if (mod == 1) {    // (mod == 1) 
                        ip += 1;                // for disp8
                        if (rm == 4)
                            ip += 1;            // [reg*K+reg+disp8]
                                                // otherwise [reg+disp8]
                    }
                    else {                  // (mod == 2) 
                        ip += 4;                // for disp32
                        if (rm == 4)
                            ip += 1;            // [reg*K+reg+disp32]
                                                // otherwise [reg+disp32]
                    }
                }

                ip += 2;
                ip += datasize;
                break;

            case 0x64:              // FS: prefix
                ip++;
                break;

            case 0xEB:              // jmp <disp8>
                ip += (signed __int8) ip[1] + 2;
                break;

            case 0xE9:              // jmp <disp32>
                ip += (__int32)*PTR_DWORD(PTR_TO_TADDR(ip) + 1) + 5; 
                break;

            case 0xF7:               // test r/m32, imm32
                // Magellan code coverage build
                if ( (ip[1] & 0x38) == 0x00)
                {
                    datasize = 4;
                    goto decodeRM;
                }
                else
                {
                    return false;
                }
                break;

            case 0x75:              // jnz <target>
                // Magellan code coverage build
                // We always follow forward jump to avoid possible looping.
                {
                    PTR_BYTE tmpIp = ip + (TADDR)(signed __int8) ip[1] + 2;
                    if (tmpIp > ip) {
                        ip = tmpIp;     // follow forwards jump
                    }
                    else {
                        return false;   // backwards jump implies not EH_epilog function
                    }
                }
                break;

            case 0xC2:                // ret
            case 0xC3:                // ret n
            default:
                return false;
        }
    }

    return false;
}