2014-06-09 29 views
7

Diciamo che sto scrivendo una libreria C++ che deve esportare una variabile, una struttura dati, chiamata, ad esempio, ExpData. Quindi, i programmi collegati al mio libray possono accedere a questa variabile (c'è un'intestazione pubblica che la definisce come extern void *ExpData[]).Come definire l'indirizzo di un simbolo esportato

Tuttavia, questa struttura dati è internamente il vtable di una classe C++. Il nome della classe è, ad esempio, InternalType. Quindi, dopo aver esaminato il codice assembly generato, ho scoperto che vtable di InternalType viene esportato come _ZTV12InternalType.

Poi, ho bisogno di un modo per rendere la mia libreria esportato variabile ExpData essere risolti con lo stesso indirizzo di _ZTV12InternalType, in modo che, quando un programma esterno legge il variabile della mia biblioteca ExpData, in realtà è la lettura InternalType s' vtable.

Giusto per chiarire, il codice assembly vtable InternalType s' è:

.type _ZTV12InternalType,@object # @_ZTV12InternalType 
    .section .data.rel.ro._ZTV12InternalType,"aGw",@progbits,_ZTV12InternalType,comdat 
    .weak _ZTV12InternalType 
    .align 16 
_ZTV12InternalType: 
    .quad 0 
    .quad _ZTI12InternalType 
    .quad _ZN12InternalType8vMethodXEi 
    .size _ZTV12InternalType, 24 

Così, ho bisogno di un modo per raggiungere questo obiettivo (o qualcos'altro con lo stesso effetto):

.type ExpData,@object 
    .globl ExpData 

    .type _ZTV12InternalType,@object 
    .section .data.rel.ro._ZTV12InternalType,"aGw",@progbits,_ZTV12InternalType,comdat 
    .weak _ZTV12InternalType 
    .align 16 
_ZTV12InternalType: 
ExpData: 
    .quad 0 
    .quad _ZTI12InternalType 
    .quad _ZN12InternalType8vMethodXEi 
    .size _ZTV12InternalType, 24 

Is è possibile nel lato C++?

P.S .: So che non devo fare affidamento su dettagli dipendenti dall'implementazione, come il mangling dei nomi e le classi C++ dei dati interni, ma consideriamo la mia libreria che verrà eseguita su ambienti molto specifici.

EDIT

ho potuto risolvere il mio problema passando --defsym ExpData=_ZTV12InternalType al linker. Tuttavia, non voglio allegare dettagli di implementazione a risorse esterne. Diciamo che decido di mappare la classe 'vtable come una struttura C chiamata InternalTypeVTable. Quindi, potrei dichiarare ExpData come InternalTypeVTable ExpData;. Sarebbe bello se dovessi cambiare solo il file sorgente, non i makefile e gli script linker.

+0

Non usi un'intestazione per quello? –

+0

@ColeJohnson Sì, ma l'intestazione deve dichiarare la variabile, non definirla. Quindi, ho bisogno di un modo per definire la mia variabile come punto di ingresso di una struttura generata dal compilatore. – LuisABOL

+0

Quindi vuoi fare una forma grezza di riflessione è quello che sto vedendo? La tua domanda non è completamente chiara per me. –

risposta

4

GCC __attribute__ ((alias())) fa esattamente il motivo per cui ho bisogno.

Se io dichiaro ExpData come:

void *ExpData[0] __attribute__ ((alias("_ZTV12InternalType"))); 

nel file di origine di mia biblioteca, ricevo il seguente codice assembly:

.globl ExpData 
ExpData = _ZTV12InternalType 

Così, il simbolo esportato ExpData riferimenti lo stesso indirizzo di memoria rispetto _ZTV12InternalType .

+0

Sì, ma perché "vuoto **"? Un vtable non è un puntatore, è più simile a un array. –

+0

@ n.m. Sì, un vtable è, in effetti, simile a un array. Ma, se dovessi dichiararlo come una matrice, dovrei definire la sua lunghezza. Dato che non conosco la sua lunghezza esatta, ho deciso di dichiararlo come un puntatore, in modo da poter accedere alle voci vtable proprio come farei se fosse un array ('ExpData [0]', 'ExpData [1]' , 'ExpData [2]', ...). Quindi, in realtà non importa. – LuisABOL

+0

"Ho deciso di dichiararlo come puntatore, in modo da poter accedere alle voci vtable esattamente come farei se fosse un array". Non puoi. 'ExpData' ** risiede in ** lo stesso indirizzo del primo elemento del vtable, che è inizializzato a 0. Non ** contiene ** l'indirizzo del primo elemento del vtable. Contiene 0. Quindi 'ExpData [0]' sarebbe un dereferenziamento puntatore nullo. È possibile estrarre le dimensioni vtable dal file di assieme. Vedete le tre dichiarazioni "quad"? Sono essenzialmente i tre indicatori che costituiscono il vtable. –

Problemi correlati