C获取函数地址

时间:2017-07-17 10:31:10

标签: java c java-native-interface jvmti

在我的项目中,我正在实现一个JNI代理,它将所有java本机方法重新绑定到我的自定义" .c"中的自定义方法。文件。因此,由于JNI代理在运行时绑定本机方法,因此我将仅讨论运行时解决方案。

当JNI绑定本机方法时,将调用以下函数:

void JNICALL NativeMethodBind(jvmtiEnv *jvmti_env,
    JNIEnv* jni_env,
    jthread thread,
    jmethodID method,
    void* address,
    void** new_address_ptr)

此时,除非您将某些内容放入void* address,否则将在void** new_address_ptr中绑定一个java方法。因此,为了重新绑定幕布方法,我只需要覆盖new_address_ptr - 变量。

现在,我想在我的自定义.c文件中将函数重新绑定到函数地址,该文件包含数百种不同的方法。这就是我被困的地方。拥有.c文件和函数的字符串名称时,如何在我的.c文件中获取相应函数的地址?

我正在使用gcc 4.9.1

在windows64机器上运行该项目

2 个答案:

答案 0 :(得分:2)

如果您可以编辑自定义*.c文件,那么您尝试实现的目标可以使用结构完成,然后您可以拥有一个包含两个成员的结构:

struct func_details{
     char func_name[20];
     void (*custom_func)(void);
};

然后声明一个结构数组:

struct func_details my_functions[] = {
         {"function1 name as string", respective_func1}
         {"function2 name as string", respective_func2}
         {"function3 name as string", respective_func3}
};

现在,您可以在

这样的循环中执行strcmp()
for(i=0; i<3; i++)
{
   if(strcmp(function_string, my_functions[i].func_name) == 0)
   {
      if(my_functions[i].custom_func != NULL)
          /*Call you method to update the address with my_functions[i].custom_func*/
   }
}

希望,我已经回答了你的问题。

答案 1 :(得分:1)

这是你需要的吗?

#include <stdio.h>

#define MAX_FN 1024
#define SYMBOL_ENTRY(i, name) do { \
        _fn_table[i].fn_name = #name; \
        _fn_table[i].fn_addr = &name; \
} while(0)

struct fn_table {
        const char *fn_name;
        void *fn_addr;
};

static struct fn_table _fn_table[MAX_FN] = { };

static void test0(void) {
        printf("%s [%d]\n", __func__, __LINE__);
}

static void test1(int a) {
        printf("%s [%d] %d\n", __func__, __LINE__, a);
}

static struct fn_table _fn_table_statically_initialization[] = {
        { "test0", &test0 },
        { "test1", &test1 }
};


int main(int argc, char *argv[]) {
        // build table
        SYMBOL_ENTRY(0, test0);
        SYMBOL_ENTRY(1, test1);

        // let's print out
        printf("%p\n", _fn_table[0].fn_addr);
        printf("%p\n", _fn_table[1].fn_addr);
        printf("%p\n", _fn_table_statically_initialization[0].fn_addr);

        // try to call
        if (_fn_table[0].fn_addr) {
                void (*fn)(void) = _fn_table[0].fn_addr;

                fn();
        }

        if (_fn_table[1].fn_addr) {
                void (*fn)(int) = _fn_table[1].fn_addr;

                fn(12);
        }

        return 0;
}