Files
cpp-project-template/third_party/microprofile/distorm/examples/java/jdistorm.c
tqcq c8b9782baa
Some checks failed
sm-rpc / build (Debug, aarch64-linux-gnu) (push) Failing after 13m15s
sm-rpc / build (Release, mipsel-linux-gnu) (push) Failing after 13m1s
sm-rpc / build (Release, host.gcc) (push) Failing after 13m14s
sm-rpc / build (Release, arm-linux-gnueabihf) (push) Failing after 13m35s
sm-rpc / build (Release, aarch64-linux-gnu) (push) Failing after 13m56s
sm-rpc / build (Debug, mipsel-linux-gnu) (push) Failing after 14m22s
sm-rpc / build (Debug, host.gcc) (push) Failing after 14m49s
sm-rpc / build (Debug, arm-linux-gnueabihf) (push) Failing after 15m13s
feat add microprile, remove prometheus
2025-08-25 11:23:55 +08:00

406 lines
16 KiB
C

/*
* diStorm3 JNI wrapper.
* Gil Dabah, October 2010.
*/
#include "jdistorm.h"
#include "../../include/distorm.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "../../distorm.lib")
static struct _CodeInfoIds {
jclass jCls;
jfieldID ID_CodeOffset;
jfieldID ID_Code;
jfieldID ID_DecodeType;
jfieldID ID_Features;
} g_CodeInfoIds;
static struct _DecodedResultIds {
jclass jCls;
jfieldID ID_Instructions;
jfieldID ID_MaxInstructions;
} g_DecodedResultIds;
static struct _DecodedInstIds {
jclass jCls;
jfieldID ID_Mnemonic;
jfieldID ID_Operands;
jfieldID ID_Hex;
jfieldID ID_Size;
jfieldID ID_Offset;
} g_DecodedInstIds;
static struct _DecomposedResultIds {
jclass jCls;
jfieldID ID_Instructions;
jfieldID ID_MaxInstructions;
} g_DecomposedResultIds;
static struct _DecomposedInstIds {
jclass jCls;
jfieldID ID_Address;
jfieldID ID_Size;
jfieldID ID_Flags;
jfieldID ID_Segment;
jfieldID ID_Base;
jfieldID ID_Scale;
jfieldID ID_Opcode;
jfieldID ID_Operands;
jfieldID ID_Disp;
jfieldID ID_Imm;
jfieldID ID_UnusedPrefixesMask;
jfieldID ID_Meta;
jfieldID ID_RegistersMask;
jfieldID ID_ModifiedFlagsMask;
jfieldID ID_TestedFlagsMask;
jfieldID ID_UndefinedFlagsMask;
} g_DecomposedInstIds;
static struct _OperandIds {
jclass jCls;
jfieldID ID_Type;
jfieldID ID_Index;
jfieldID ID_Size;
} g_OperandIds;
static struct _ImmIds {
jclass jCls;
jfieldID ID_Value;
jfieldID ID_Size;
} g_ImmIds;
static struct _DispIds {
jclass jCls;
jfieldID ID_Displacement;
jfieldID ID_Size;
} g_DispIds;
void JThrowByName(JNIEnv* env, const char *name, const char* msg)
{
jclass cls = (*env)->FindClass(env, name);
if (cls != NULL) {
(*env)->ThrowNew(env, cls, msg);
}
(*env)->DeleteLocalRef(env, cls);
}
_CodeInfo* AcquireCodeInfoStruct(JNIEnv *env, jobject jciObj)
{
jobject jCodeObj = NULL;
_CodeInfo* ci = (_CodeInfo*)malloc(sizeof(_CodeInfo));
if (ci == NULL) {
JThrowByName(env, "java/lang/OutOfMemoryError", NULL);
return NULL;
}
memset(ci, 0, sizeof(_CodeInfo));
ci->codeOffset = (*env)->GetLongField(env, jciObj, g_CodeInfoIds.ID_CodeOffset);
jCodeObj = (*env)->GetObjectField(env, jciObj, g_CodeInfoIds.ID_Code);
ci->code = (uint8_t*) (*env)->GetDirectBufferAddress(env, jCodeObj);
ci->codeLen = (int)(*env)->GetDirectBufferCapacity(env, jCodeObj);
ci->dt = (*env)->GetIntField(env, jciObj, g_CodeInfoIds.ID_DecodeType);
ci->features = (*env)->GetIntField(env, jciObj, g_CodeInfoIds.ID_Features);
return ci;
}
jobject CreateDecodedInstObj(JNIEnv* env, const _DecodedInst* inst)
{
jobject jInst = (*env)->AllocObject(env, g_DecodedInstIds.jCls);
if (jInst == NULL) return NULL;
(*env)->SetObjectField(env, jInst, g_DecodedInstIds.ID_Mnemonic, (*env)->NewStringUTF(env, (const char*)inst->mnemonic.p));
(*env)->SetObjectField(env, jInst, g_DecodedInstIds.ID_Operands, (*env)->NewStringUTF(env, (const char*)inst->operands.p));
(*env)->SetObjectField(env, jInst, g_DecodedInstIds.ID_Hex, (*env)->NewStringUTF(env, (const char*)inst->instructionHex.p));
(*env)->SetIntField(env, jInst, g_DecodedInstIds.ID_Size, inst->size);
(*env)->SetLongField(env, jInst, g_DecodedInstIds.ID_Offset, inst->offset);
return jInst;
}
JNIEXPORT void JNICALL Java_diStorm3_distorm3_Decode
(JNIEnv *env, jobject thiz, jobject jciObj, jobject jdrObj)
{
jarray jInsts = NULL;
jobject jInst = NULL;
_CodeInfo* ci = NULL;
_DecodedInst* insts = NULL;
jint maxInstructions = 0;
unsigned int usedInstructionsCount = 0, i = 0;
thiz; /* Unused. */
ci = AcquireCodeInfoStruct(env, jciObj);
if (ci == NULL) {
JThrowByName(env, "java/lang/OutOfMemoryError", NULL);
return;
}
maxInstructions = (*env)->GetIntField(env, jdrObj, g_DecodedResultIds.ID_MaxInstructions);
insts = (_DecodedInst*)malloc(maxInstructions * sizeof(_DecodedInst));
if (insts == NULL) goto Cleanup;
distorm_decode(ci->codeOffset, ci->code, ci->codeLen, ci->dt, insts, maxInstructions, &usedInstructionsCount);
jInsts = (*env)->NewObjectArray(env, usedInstructionsCount, g_DecodedInstIds.jCls, NULL);
if (jInsts == NULL) goto Cleanup;
for (i = 0; i < usedInstructionsCount; i++) {
jInst = CreateDecodedInstObj(env, &insts[i]);
if (jInst == NULL) goto Cleanup;
(*env)->SetObjectArrayElement(env, jInsts, i, jInst);
}
(*env)->SetObjectField(env, jdrObj, g_DecodedResultIds.ID_Instructions, jInsts);
Cleanup:
/* In case of an error, jInsts will get cleaned automatically. */
if (ci != NULL) free(ci);
if (insts != NULL) free(insts);
}
JNIEXPORT void JNICALL Java_diStorm3_distorm3_Decompose
(JNIEnv *env, jobject thiz, jobject jciObj, jobject jdrObj)
{
jarray jInsts = NULL, jOperands = NULL;
jobject jInst = NULL, jOperand = NULL, jImm = NULL, jDisp = NULL;
_CodeInfo* ci = NULL;
_DInst* insts = NULL;
jint maxInstructions = 0;
unsigned int usedInstructionsCount = 0, i = 0, j = 0, operandsNo = 0;
int success = 0;
thiz; /* Unused. */
ci = AcquireCodeInfoStruct(env, jciObj);
if (ci == NULL) {
JThrowByName(env, "java/lang/OutOfMemoryError", NULL);
return;
}
maxInstructions = (*env)->GetIntField(env, jdrObj, g_DecomposedResultIds.ID_MaxInstructions);
insts = (_DInst*)malloc(maxInstructions * sizeof(_DInst));
if (insts == NULL) goto Cleanup;
distorm_decompose(ci, insts, maxInstructions, &usedInstructionsCount);
jInsts = (*env)->NewObjectArray(env, usedInstructionsCount, g_DecomposedInstIds.jCls, NULL);
if (jInsts == NULL) goto Cleanup;
for (i = 0; i < usedInstructionsCount; i++) {
jInst = (*env)->AllocObject(env, g_DecomposedInstIds.jCls);
if (jInst == NULL) goto Cleanup;
/* Simple fields: */
(*env)->SetLongField(env, jInst, g_DecomposedInstIds.ID_Address, insts[i].addr);
(*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Flags, insts[i].flags);
(*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Size, insts[i].size);
(*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Segment, insts[i].segment);
(*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Base, insts[i].base);
(*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Scale, insts[i].scale);
(*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Opcode, insts[i].opcode);
(*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_UnusedPrefixesMask, insts[i].unusedPrefixesMask);
(*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Meta, insts[i].meta);
(*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_RegistersMask, insts[i].usedRegistersMask);
(*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_ModifiedFlagsMask, insts[i].modifiedFlagsMask);
(*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_TestedFlagsMask, insts[i].testedFlagsMask);
(*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_UndefinedFlagsMask, insts[i].undefinedFlagsMask);
/* Immediate variant. */
jImm = (*env)->AllocObject(env, g_ImmIds.jCls);
if (jImm == NULL) goto Cleanup;
(*env)->SetLongField(env, jImm, g_ImmIds.ID_Value, insts[i].imm.qword);
/* The size of the immediate is in one of the operands, if at all. Look for it below. Zero by default. */
(*env)->SetIntField(env, jImm, g_ImmIds.ID_Size, 0);
/* Count operands. */
for (operandsNo = 0; operandsNo < OPERANDS_NO; operandsNo++) {
if (insts[i].ops[operandsNo].type == O_NONE) break;
}
jOperands = (*env)->NewObjectArray(env, operandsNo, g_OperandIds.jCls, NULL);
if (jOperands == NULL) goto Cleanup;
for (j = 0; j < operandsNo; j++) {
if (insts[i].ops[j].type == O_IMM) {
/* Set the size of the immediate operand. */
(*env)->SetIntField(env, jImm, g_ImmIds.ID_Size, insts[i].ops[j].size);
}
jOperand = (*env)->AllocObject(env, g_OperandIds.jCls);
if (jOperand == NULL) goto Cleanup;
(*env)->SetIntField(env, jOperand, g_OperandIds.ID_Type, insts[i].ops[j].type);
(*env)->SetIntField(env, jOperand, g_OperandIds.ID_Index, insts[i].ops[j].index);
(*env)->SetIntField(env, jOperand, g_OperandIds.ID_Size, insts[i].ops[j].size);
(*env)->SetObjectArrayElement(env, jOperands, j, jOperand);
}
(*env)->SetObjectField(env, jInst, g_DecomposedInstIds.ID_Operands, jOperands);
/* Attach the immediate variant. */
(*env)->SetObjectField(env, jInst, g_DecomposedInstIds.ID_Imm, jImm);
/* Displacement variant. */
jDisp = (*env)->AllocObject(env, g_DispIds.jCls);
if (jDisp == NULL) goto Cleanup;
(*env)->SetLongField(env, jDisp, g_DispIds.ID_Displacement, insts[i].disp);
(*env)->SetIntField(env, jDisp, g_DispIds.ID_Size, insts[i].dispSize);
(*env)->SetObjectField(env, jInst, g_DecomposedInstIds.ID_Disp, jDisp);
(*env)->SetObjectArrayElement(env, jInsts, i, jInst);
}
(*env)->SetObjectField(env, jdrObj, g_DecodedResultIds.ID_Instructions, jInsts);
Cleanup:
/* In case of an error, jInsts will get cleaned automatically. */
if (ci != NULL) free(ci);
if (insts != NULL) free(insts);
}
JNIEXPORT jobject JNICALL Java_diStorm3_distorm3_Format
(JNIEnv *env, jobject thiz, jobject jciObj, jobject jdiObj)
{
_CodeInfo* ci = NULL;
_DInst input = {0};
_DecodedInst output = {0};
jobject ret = NULL, jOperands = NULL, jOp = NULL, jTmp = NULL;
jsize i, opsCount;
thiz; /* Unused. */
ci = AcquireCodeInfoStruct(env, jciObj);
if (ci == NULL) {
JThrowByName(env, "java/lang/OutOfMemoryError", NULL);
return NULL;
}
input.addr = (*env)->GetLongField(env, jdiObj, g_DecomposedInstIds.ID_Address);
input.flags = (uint16_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Flags);
input.size = (uint8_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Size);
input.segment = (uint8_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Segment);
input.base = (uint8_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Base);
input.scale = (uint8_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Scale);
input.opcode = (uint16_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Opcode);
/* unusedPrefixesMask is unused indeed, lol. */
input.meta = (uint16_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Meta);
/* Nor usedRegistersMask. */
jOperands = (*env)->GetObjectField(env, jdiObj, g_DecomposedInstIds.ID_Operands);
if (jOperands != NULL) {
opsCount = (*env)->GetArrayLength(env, jOperands);
for (i = 0; i < opsCount; i++) {
jOp = (*env)->GetObjectArrayElement(env, jOperands, i);
if (jOp != NULL) {
input.ops[i].index = (uint8_t) (*env)->GetIntField(env, jOp, g_OperandIds.ID_Index);
input.ops[i].type = (uint8_t) (*env)->GetIntField(env, jOp, g_OperandIds.ID_Type);
input.ops[i].size = (uint16_t) (*env)->GetIntField(env, jOp, g_OperandIds.ID_Size);
}
}
}
jTmp = (*env)->GetObjectField(env, jdiObj, g_DecomposedInstIds.ID_Imm);
if (jTmp != NULL) {
input.imm.qword = (uint64_t) (*env)->GetLongField(env, jTmp, g_ImmIds.ID_Value);
}
jTmp = (*env)->GetObjectField(env, jdiObj, g_DecomposedInstIds.ID_Disp);
if (jTmp != NULL) {
input.disp = (uint64_t) (*env)->GetLongField(env, jTmp, g_DispIds.ID_Displacement);
input.dispSize = (uint8_t) (*env)->GetIntField(env, jTmp, g_DispIds.ID_Size);
}
distorm_format(ci, &input, &output);
ret = CreateDecodedInstObj(env, &output);
if (ci != NULL) free(ci);
return ret;
}
/* Cache all ID's and classes! Release in unload. */
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
jclass jCls = NULL;
JNIEnv* env = NULL;
if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) {
return JNI_VERSION_1_6;
}
jCls = (*env)->FindClass(env, PACKAGE_PREFIX "CodeInfo");
g_CodeInfoIds.jCls = (*env)->NewWeakGlobalRef(env, jCls);
g_CodeInfoIds.ID_CodeOffset = (*env)->GetFieldID(env, jCls, "mCodeOffset", "J");
g_CodeInfoIds.ID_Code = (*env)->GetFieldID(env, jCls, "mCode", "Ljava/nio/ByteBuffer;");
g_CodeInfoIds.ID_DecodeType = (*env)->GetFieldID(env, jCls, "mDecodeType", "I");
g_CodeInfoIds.ID_Features = (*env)->GetFieldID(env, jCls, "mFeatures", "I");
jCls = (*env)->FindClass(env, PACKAGE_PREFIX "DecodedResult");
g_DecodedResultIds.jCls = (*env)->NewWeakGlobalRef(env, jCls);
g_DecodedResultIds.ID_MaxInstructions = (*env)->GetFieldID(env, jCls, "mMaxInstructions", "I");
g_DecodedResultIds.ID_Instructions = (*env)->GetFieldID(env, jCls, "mInstructions", "[L" PACKAGE_PREFIX "DecodedInst;");
jCls = (*env)->FindClass(env, PACKAGE_PREFIX "DecodedInst");
g_DecodedInstIds.jCls = (*env)->NewWeakGlobalRef(env, jCls);
g_DecodedInstIds.ID_Mnemonic = (*env)->GetFieldID(env, jCls, "mMnemonic", "Ljava/lang/String;");
g_DecodedInstIds.ID_Operands = (*env)->GetFieldID(env, jCls, "mOperands", "Ljava/lang/String;");
g_DecodedInstIds.ID_Hex = (*env)->GetFieldID(env, jCls, "mHex", "Ljava/lang/String;");
g_DecodedInstIds.ID_Size = (*env)->GetFieldID(env, jCls, "mSize", "I");
g_DecodedInstIds.ID_Offset = (*env)->GetFieldID(env, jCls, "mOffset", "J");
jCls = (*env)->FindClass(env, PACKAGE_PREFIX "DecomposedResult");
g_DecomposedResultIds.jCls = (*env)->NewWeakGlobalRef(env, jCls);
g_DecomposedResultIds.ID_Instructions = (*env)->GetFieldID(env, jCls, "mInstructions", "[L" PACKAGE_PREFIX "DecomposedInst;");
g_DecomposedResultIds.ID_MaxInstructions = (*env)->GetFieldID(env, jCls, "mMaxInstructions", "I");
jCls = (*env)->FindClass(env, PACKAGE_PREFIX "DecomposedInst");
g_DecomposedInstIds.jCls = (*env)->NewWeakGlobalRef(env, jCls);
g_DecomposedInstIds.ID_Address = (*env)->GetFieldID(env, jCls, "mAddr", "J");
g_DecomposedInstIds.ID_Size = (*env)->GetFieldID(env, jCls, "mSize", "I");
g_DecomposedInstIds.ID_Flags = (*env)->GetFieldID(env, jCls, "mFlags", "I");
g_DecomposedInstIds.ID_Segment = (*env)->GetFieldID(env, jCls, "mSegment", "I");
g_DecomposedInstIds.ID_Base = (*env)->GetFieldID(env, jCls, "mBase", "I");
g_DecomposedInstIds.ID_Scale = (*env)->GetFieldID(env, jCls, "mScale", "I");
g_DecomposedInstIds.ID_Opcode = (*env)->GetFieldID(env, jCls, "mOpcode", "I");
g_DecomposedInstIds.ID_Operands = (*env)->GetFieldID(env, jCls, "mOperands", "[L" PACKAGE_PREFIX "Operand;");
g_DecomposedInstIds.ID_Disp = (*env)->GetFieldID(env, jCls, "mDisp", "L" PACKAGE_PREFIX "DecomposedInst$DispVariant;");
g_DecomposedInstIds.ID_Imm = (*env)->GetFieldID(env, jCls, "mImm", "L" PACKAGE_PREFIX "DecomposedInst$ImmVariant;");
g_DecomposedInstIds.ID_UnusedPrefixesMask = (*env)->GetFieldID(env, jCls, "mUnusedPrefixesMask", "I");
g_DecomposedInstIds.ID_Meta = (*env)->GetFieldID(env, jCls, "mMeta", "I");
g_DecomposedInstIds.ID_RegistersMask = (*env)->GetFieldID(env, jCls, "mRegistersMask", "I");
g_DecomposedInstIds.ID_ModifiedFlagsMask = (*env)->GetFieldID(env, jCls, "mModifiedFlagsMask", "I");
g_DecomposedInstIds.ID_TestedFlagsMask = (*env)->GetFieldID(env, jCls, "mTestedFlagsMask", "I");
g_DecomposedInstIds.ID_UndefinedFlagsMask = (*env)->GetFieldID(env, jCls, "mUndefinedFlagsMask", "I");
jCls = (*env)->FindClass(env, PACKAGE_PREFIX "Operand");
g_OperandIds.jCls = (*env)->NewWeakGlobalRef(env, jCls);
g_OperandIds.ID_Type = (*env)->GetFieldID(env, jCls, "mType", "I");
g_OperandIds.ID_Index = (*env)->GetFieldID(env, jCls, "mIndex", "I");
g_OperandIds.ID_Size = (*env)->GetFieldID(env, jCls, "mSize", "I");
jCls = (*env)->FindClass(env, PACKAGE_PREFIX "DecomposedInst$ImmVariant");
g_ImmIds.jCls = (*env)->NewWeakGlobalRef(env, jCls);
g_ImmIds.ID_Value = (*env)->GetFieldID(env, jCls, "mValue", "J");
g_ImmIds.ID_Size = (*env)->GetFieldID(env, jCls, "mSize", "I");
jCls = (*env)->FindClass(env, PACKAGE_PREFIX "DecomposedInst$DispVariant");
g_DispIds.jCls = (*env)->NewWeakGlobalRef(env, jCls);
g_DispIds.ID_Displacement = (*env)->GetFieldID(env, jCls, "mDisplacement", "J");
g_DispIds.ID_Size = (*env)->GetFieldID(env, jCls, "mSize", "I");
return JNI_VERSION_1_6;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
{
/* Free global weak refs. */
}