2013-03-14 7 views
5

La domanda è come posso ottenere l'indirizzo di funzione dalla libreria condivisa (UNIX/LINUX)?Differenza tra ottenere i puntatori di funzione dalla libreria condivisa

Avevo scritto alcuni test in C (vedi sotto), compilato ed eseguito su Ubuntu 10.04 (amd64) e FreeBSD-8.2 (amd64). Non avevo alcuna differenza, ma voglio sapere di più su possibili problemi.

Eccoli:

  1. test 1

lib.c

char* f0(void) { 
    return "Hello, World!"; 
} 

main.c

#include <dlfcn.h> 
#include <stdlib.h> 
#include <stdio.h> 

void *hlib, *addr; 
char* (*foo)(void); 
char* s; 

int main(int argc, char** argv) { 
    if (!(hlib = dlopen("./lib.so", RTLD_LAZY))) 
     return 1; 
    if (!(addr = foo = dlsym(hlib, "f0"))) 
     return 2; 
    s = foo(); 
    printf("%p => %s\n", addr, s); 
    return 0; 
} 

Ora costruirlo:

gcc -o lib.o -c lib.c -Wall -Werror -O3 -fPIC 
gcc -o lib.so -shared -nostartfiles lib.o 
gcc -o main.o -c main.c -Wall -Werror -O3 
gcc -o prog main.o -ldl 

Stampa l'indirizzo della funzione di libreria f0() e il risultato dell'esecuzione.

  1. prova 2

lib.h (definire qui l'interfaccia standard di librerie di collegamento dinamico)

#ifndef __LIB_H__ 
#define __LIB_H__ 

typedef struct __syminfo { 
    char* name; // function name 
    void* addr; // function address 
} syminfo_t; 

typedef struct __libinfo { 
    int  num; // number of exported functions 
    syminfo_t sym[1]; // vector of exported function information 
} libinfo_t; 

extern int (*__getinfo)(libinfo_t**); 

#endif 
/* __LIB_H__ 
*/ 

lib.c (la libreria stessa)

#include <stdlib.h> 
#include <lib.h> 

static libinfo_t* li; 

char* foo(void); 

__attribute__((constructor)) void __init() { 
    if ((li = calloc(1, sizeof(libinfo_t)))) { 
    li->num = 1; 
    li->sym[0].name = "foo"; 
    li->sym[0].addr = &foo; 
    } 
} 

__attribute__((destructor)) void __free() { 
    if (li) 
    free(li); 
} 

int getinfo(libinfo_t** inf) { 
    if (!inf) 
    return -1; 
    *inf = li; 
    return 0; 
} 

char* foo(void) { 
    return "Hello, World!"; 
} 

main.c

#include <stdio.h> 
#include <dlfcn.h> 
#include <lib.h> 

libinfo_t* inf; 

void* hlib; 

int (*__getinfo)(libinfo_t**); 

char* (*foo)(void); 

char* s; 

int main(int argc, char** argv) { 
    if (!(hlib = dlopen("./lib.so", RTLD_LAZY))) 
    return 1; 
    if (!(__getinfo = dlsym(hlib, "getinfo"))) 
    return 2; 
    if (__getinfo(&inf)) 
    return 3; 
    if (!(foo = inf->sym[0].addr)) 
    return 4; 
    s = foo(); 
    printf("%p => %s\n", inf->sym[0].addr, s);  
    return 0; 
}  

Ora compilarlo (senza -nostartfiles):

gcc -I. -o lib.o -c lib.c -Wall -Werror -O3 -fPIC 
gcc -o lib.so lib.o -shared 
gcc -I. -o main.o -c main.c -Wall -Werror -O3 
gcc -o prog main.o -ldl 

Questa printf lo stesso di Test 1: l'indirizzo della funzione di libreria foo() e il risultato della sua esecuzione.

Ho provato a mostrare come posso ottenere l'indirizzo della funzione di libreria condivisa, ma ho ragione nel secondo test? Devo avere qualche problema con esso?

NOTA: in FreeBSD-8.2 non è necessario utilizzare l'argomento -ldl, tutte le routine dlfcn.h si trovano nella libreria libc.

Rispettoso in attesa di eventuali spiegazioni.

risposta

1

Mi sembra abbastanza normale. L'unica cosa che stai usando potrebbe porre qualche problema è che stai usando gli attributi gcc per creare un costruttore e un distruttore per la tua libreria condivisa. Quello non può essere interamente portatile; dipende da quali piattaforme ti interessano.

Si noti che in questo caso specifico non è necessario fare qualcosa così complicato. Le informazioni che stai tornando dalla libreria condivisa nel tuo secondo esempio sono tutte note al momento della compilazione, quindi puoi semplicemente creare una struct statica con quelle informazioni e recuperare l'indirizzo della struct con dlsym e spostarti in esso dal programma principale o chiamare una funzione conosciuta per restituire la struttura. (Quest'ultimo è leggermente più flessibile in alcuni casi d'angolo, ma entrambi sono abbastanza flessibili.)

+0

Grazie mille ci sono state informazioni utili per me =) – user2168737

Problemi correlati