Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define an exported symbol's address

Let's say I'm writing a C++ library which must export a variable, a data structure, called, for example, ExpData. So, programs linked against my libray can access this variable (there is a public header defining it as extern void *ExpData[]).

However, this data structure is internally the vtable of a C++ class. The class' name is, for example, InternalType. So, after looking at the generated assembly code, I found out that InternalType's vtable is exported as _ZTV12InternalType.

Then, I need a way to make my library exported variable ExpData be resolved with the same address than _ZTV12InternalType, so that, when an external program reads my library's ExpData variable, it is actually reading InternalType's vtable.

Just to clarify, InternalType's vtable assembly code is:

    .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

So, I need a way to achieve this (or something else with the same effect):

    .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 it possible in the C++ side?

P.S.: I know I shouldn't rely on implementation-dependent details, like name mangling and C++ classes internal data, but just consider my library is going to run on very specific environments.

EDIT

I could solve my problem by passing --defsym ExpData=_ZTV12InternalType to the linker. However, I don't want to attach implementation details to external resources. Let's say I decide to map the class' vtable as a C structure called InternalTypeVTable. So, I could declare ExpData as InternalTypeVTable ExpData;. It would be great if I had to change only the source file, not the makefiles and linker scripts.

like image 513
LuisABOL Avatar asked Jun 09 '14 02:06

LuisABOL


1 Answers

GCC's __attribute__ ((alias())) does exactly why I need.

If I declare ExpData like :

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

in my library's source file, I get the following assembly code:

    .globl  ExpData
ExpData = _ZTV12InternalType

So, the exported symbol ExpData references the same memory address than _ZTV12InternalType.

like image 52
LuisABOL Avatar answered Nov 20 '22 23:11

LuisABOL