2014-06-09 4 views
7

Angenommen, ich schreibe eine C++ - Bibliothek, die eine Variable, eine Datenstruktur, exportieren muss, z. B. ExpData. So können Programme, die gegen meine Bibliothek gebunden sind, auf diese Variable zugreifen (es gibt einen öffentlichen Header, der sie als extern void *ExpData[] definiert).So definieren Sie die Adresse eines exportierten Symbols

Diese Datenstruktur ist jedoch intern die vtable einer C++ - Klasse. Der Name der Klasse lautet beispielsweise InternalType. Nach dem Betrachten des generierten Assembly-Codes habe ich herausgefunden, dass die Vtable InternalType als _ZTV12InternalType exportiert wird.

Dann brauche ich eine Möglichkeit, meine Bibliothek zu machen exportierte Variable ExpData als _ZTV12InternalType mit derselben Adresse aufgelöst werden, so dass, wenn ein externes Programm meiner Bibliothek ExpData Variable liest, es ist eigentlich InternalType ‚s VTable lesen.

Nur um zu klären, InternalType ‚s VTable Assembler-Code ist:

.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 

Also, ich brauche einen Weg, um dies (oder etwas anderes mit dem gleichen Effekt) zu erreichen:

.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 

Ist es möglich in der C++ Seite?

P.S .: Ich weiß, dass ich mich nicht auf implementierungsabhängige Details verlassen sollte, wie zum Beispiel Namemangling und C++ - Klassen interne Daten, sondern denke nur, dass meine Bibliothek in sehr spezifischen Umgebungen laufen wird.

EDIT

ich mein Problem, indem --defsym ExpData=_ZTV12InternalType an den Linker lösen könnte. Ich möchte jedoch keine Implementierungsdetails an externe Ressourcen anhängen. Nehmen wir an, ich entscheide mich, die Vtable der Klasse als eine C-Struktur namens InternalTypeVTable zu mappen. So könnte ich ExpData als InternalTypeVTable ExpData; erklären. Es wäre großartig, wenn ich nur die Quelldatei, nicht die Makefiles und Linker-Skripte ändern müsste.

+0

Verwenden Sie keine Kopfzeile dafür? –

+0

@ColeJohnson Ja, aber der Header soll die Variable deklarieren, nicht definieren. Also, ich brauche einen Weg, um meine Variable als Eingangspunkt einer Compiler generierten Struktur zu definieren. – LuisABOL

+0

Sie wollen also eine grobe Form der Reflexion tun, was ich sehe? Deine Frage ist mir nicht ganz klar. –

Antwort

4

GCC __attribute__ ((alias())) tut genau, warum ich brauche.

Wenn ich erklären ExpData wie:

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

in meiner Bibliothek der Quelldatei, erhalte ich die folgende Assembler-Code:

.globl ExpData 
ExpData = _ZTV12InternalType 

Also, das exportierte Symbol ExpData verweist auf die gleiche Speicheradresse als _ZTV12InternalType .

+0

Ja aber warum 'void **'? Eine Vtable ist kein Zeiger, sondern eher ein Array. –

+0

@ n.m. Ja, eine vtable ähnelt tatsächlich einem Array. Aber wenn ich es als Array deklariere, sollte ich seine Länge definieren. Da ich seine genaue Länge nicht kenne, habe ich beschlossen, es als Zeiger zu deklarieren, so dass ich auf die vtable-Einträge genauso zugreifen kann, als wenn ich ein Array wäre ('ExpData [0]', 'ExpData [1]' , 'ExpData [2]', ...). Also ist es eigentlich egal. – LuisABOL

+0

"Ich entschied mich, es als einen Zeiger zu deklarieren, so dass ich wie bei einem Array auf die vtable-Einträge zugreifen kann". Du kannst nicht. 'ExpData' ** befindet sich an ** derselben Adresse wie das erste Element der vtable, das auf 0 initialisiert wird. Es enthält ** nicht die Adresse des ersten Elements der vtable. Es enthält 0. Also wäre 'ExpData [0]' eine Nullzeiger-Dereferenzierung. Sie können die Vtable-Größe aus der Assemblydatei extrahieren. Siehst du die drei 'quad' Deklarationen? Sie sind im Wesentlichen die drei Zeiger, die die V-Tabelle bilden. –

Verwandte Themen