2017-07-17 3 views
1

In meinem Projekt implementiere ich einen JNI-Agent, der alle nativen Java-Methoden an meine benutzerdefinierten Methoden in meiner benutzerdefinierten ".c" Datei binden würde. Da der JNI-Agent native Methoden in Runtime bindet, werde ich nur über die Runtime-Lösung sprechen.C bekommen Funktionen Adresse

Wenn JNI nativen Methoden bindet, wird folgende Funktion aufgerufen:

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

An dieser Stelle ein Java-Methode gebunden wird in void* address adressieren, wenn Sie etwas in void** new_address_ptr setzen. Um eine Vorhangmethode neu zu binden, muss ich nur die new_address_ptr - Variable überschreiben.

Jetzt möchte ich die Funktionen zu Funktion-Adressen in meiner benutzerdefinierten .c-Datei, die mehrere hundert verschiedene Methoden enthält. Und hier stecke ich fest. Wie erhalte ich die .c-Datei und die String-Namen der Funktionen, wie bekomme ich die Adressen der entsprechenden Funktionen in meiner .c-Datei?

Ich betreibe das Projekt auf Windows64 Maschine mit gcc 4.9.1

+0

Wie wahrscheinlich ist, dass der String-Name der Funktion, die Sie haben, in der Datei '* .c' existiert, die Sie haben? – Gaurav

+0

@GauravPathak sehr wahrscheinlich, wie es ist 100% sicher, dass es ... –

+0

In c-code, Funktion Name ist auch seine Adresse, mit Assembly, Hinzufügen von "_" als Präfix. – sdao

Antwort

1

Ist das, was Sie brauchen?

#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; 
} 
+0

ungültige Konvertierung von 'void (*) (int)' zu 'void *' [-fmissiv], bei der Array-Initialisierung .... muss ich -fpermissive irgendwo setzen? –

+0

OK, bearbeitet, ass '&', um stattdessen die Funktionsadresse zu erhalten '_fn_table [i] .fn_addr = &name;' – sdao

2

Was Sie versuchen können zu erreichen, die eine Struktur tun zu verwenden, wenn Sie Ihre benutzerdefinierten *.c Datei bearbeiten können, dann können Sie eine Struktur mit zwei Mitgliedern wie:

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

Dann eine Reihe von Struktur deklarieren:

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

Jetzt können Sie einen strcmp() in einer Schleife l tun ike

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*/ 
    } 
} 

Hoffe, ich habe Ihre Frage beantwortet.