C获取函数地址
C getting functions address
在我的项目中,我正在实施一个 JNI 代理,它将所有 java 本机方法重新绑定到我自定义“.c”文件中的自定义方法。因此,由于 JNI 代理在运行时绑定本地方法,因此我将只讨论运行时解决方案。
当 JNI 绑定本机方法时,将调用以下函数:
void JNICALL NativeMethodBind(jvmtiEnv *jvmti_env,
JNIEnv* jni_env,
jthread thread,
jmethodID method,
void* address,
void** new_address_ptr)
此时,java 方法将绑定到 void* address
中的地址,除非您将某些内容放入 void** new_address_ptr
。因此,为了重新绑定窗帘方法,我只需要覆盖 new_address_ptr
- 变量。
现在,我想将函数重新绑定到我的自定义 .c 文件中的函数地址,该文件包含数百种不同的方法。这就是我被困的地方。在拥有 .c 文件和函数的字符串名称的同时,如何在我的 .c 文件中获取相应函数的地址?
我是 运行 windows64 机器上的项目,gcc 4.9.1
如果您可以编辑自定义 *.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*/
}
}
希望,我已经回答了你的问题。
这是你需要的吗?
#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;
}
在我的项目中,我正在实施一个 JNI 代理,它将所有 java 本机方法重新绑定到我自定义“.c”文件中的自定义方法。因此,由于 JNI 代理在运行时绑定本地方法,因此我将只讨论运行时解决方案。
当 JNI 绑定本机方法时,将调用以下函数:
void JNICALL NativeMethodBind(jvmtiEnv *jvmti_env,
JNIEnv* jni_env,
jthread thread,
jmethodID method,
void* address,
void** new_address_ptr)
此时,java 方法将绑定到 void* address
中的地址,除非您将某些内容放入 void** new_address_ptr
。因此,为了重新绑定窗帘方法,我只需要覆盖 new_address_ptr
- 变量。
现在,我想将函数重新绑定到我的自定义 .c 文件中的函数地址,该文件包含数百种不同的方法。这就是我被困的地方。在拥有 .c 文件和函数的字符串名称的同时,如何在我的 .c 文件中获取相应函数的地址?
我是 运行 windows64 机器上的项目,gcc 4.9.1
如果您可以编辑自定义 *.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*/
}
}
希望,我已经回答了你的问题。
这是你需要的吗?
#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;
}