gecko-dev/ef/Tools/Disass/Disass.c

136 строки
3.8 KiB
C

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <windows.h>
#include <native.h>
#include <stdio.h>
#include <assert.h>
#include "Disass.h"
#include "VM.h"
#include "XDisAsm.h"
Uint32 knownStub[] =
{
0x55076A50, 0x04246C8D, 0x6A535756, 0x73E85500,
0x89FFFFFB, 0x64500445, 0x000035FF, 0xC7640000,
0x00000005, 0xFFFFFF00, 0x0875FFFF, 0x000023E8,
0x058F6400, 0x00000000, 0x840FC00B, 0x0002C832,
0x3FE8F08B, 0x8BFFFFFB, 0x5F5B5BC6, 0x59595D5E,
0x1860FF58, 0x57565553
};
const Uint32 knownStubSize = sizeof(knownStub);
DWORD __cdecl
RNIGetCompatibleVersion()
{
return RNIVER;
}
static long printMethod(struct HDisass *pThis, MethodBlock* method)
{
Uint8* code;
Uint8* limit;
Uint8* start;
CodeCacheEntry* codeCache;
code = method->code;
// If the code is not yet compiled then the first instruction
// to be executed will be a call to the compile stub.
if (code[0] == CALL_OPCODE) {
Int32 offset;
Uint8* staticCompileStub;
Uint8* newCompileStub;
staticCompileStub = &code[5] + *(Int32 *) &code[1];
if (memcmp(staticCompileStub, knownStub, knownStubSize) != 0) {
fprintf(stderr, "Unknown stub for this method");
return Disass_UNKNOWN_STUB;
}
newCompileStub = (Uint8 *) malloc(knownStubSize);
memcpy(newCompileStub, staticCompileStub, knownStubSize);
// Replace the call offsets.
offset = *(Int32 *) &staticCompileStub[15];
*(Int32 *) &newCompileStub[15] = offset + (staticCompileStub - newCompileStub);
offset = *(Int32 *) &staticCompileStub[45];
*(Int32 *) &newCompileStub[45] = offset + (staticCompileStub - newCompileStub);
offset = *(Int32 *) &staticCompileStub[67];
*(Int32 *) &newCompileStub[67] = offset + (staticCompileStub - newCompileStub);
// Put a return at the end of the code instead of the jump code.
newCompileStub[81] = RETURN_OPCODE;
_asm {
call stub
jmp end
stub:
push method
jmp newCompileStub
end:
}
code = method->code;
}
codeCache = (CodeCacheEntry *) (code - sizeof(CodeCacheEntry));
limit = ((Uint8 *) codeCache) + codeCache->length + 4;
start = code;
while ((code < limit) && (0 != *(Uint32 *) code)) {
fprintf(stdout, "%p:\t", code - start);
fprintf(stdout, "%s\n", disasmx86(code - start, &code, limit + 1, kDisAsmFlag32BitSegments));
}
return Disass_SUCCESS;
}
__declspec(dllexport) long __cdecl
Disass_disassemble(struct HDisass *pThis, struct Hjava_lang_String *jClassName, struct Hjava_lang_String *jMethodName,
struct Hjava_lang_String *jSignature)
{
ClassClass* classclass;
MethodBlock* method;
char cClassName[1024];
char cMethodName[1024];
char cSignature[1024];
javaString2CString(jClassName, cClassName, 1024);
javaString2CString(jMethodName, cMethodName, 1024);
javaString2CString(jSignature, cSignature, 1024);
classclass = FindClassEx(cClassName, FINDCLASSEX_IGNORECASE);
if (classclass == NULL)
return Disass_CLASS_NOT_FOUND;
method = (MethodBlock*) Class_GetMethod(classclass, cMethodName, cSignature);
if (method == NULL)
return Disass_METHOD_NOT_FOUND;
return printMethod(pThis, method);
}