malat malat - 2 months ago 7
C Question

dladdr: pointer-to-function vs pointer-to-object

Hopefully this is rather a simple C++ question (not a language-lawyer one).

How is one supposed to use the GNU extension

dladdr
in C++ ? Typically one would write the following in C:

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <dlfcn.h>

static void where_am_i() {}

int main()
{
Dl_info info;
dladdr( (void*)&where_am_i, &info );

return 0;
}


However using clang one can see the cast may be invalid:

$ clang --version
Debian clang version 3.6.2-3 (tags/RELEASE_362/final) (based on LLVM 3.6.2)
Target: x86_64-pc-linux-gnu
Thread model: posix
$ clang -Wpedantic -o foo foo.cpp -ldl
foo.cpp:11:11: warning: cast between pointer-to-function and pointer-to-object is an extension [-Wpedantic]
dladdr( (void*)&where_am_i, &info );
^~~~~~~~~~~~~~~~~~
1 warning generated.


The warning seems legitimate to me, so is there a way to work around that ?

Answer

There is no standard way to portably convert a function pointer to void*. As such, there is no standard way to portably use dladdr. Prior to C++11, such conversion was ill-formed (I don't have the document available, but the warning by clang suggests it). Since C++11 however, the conversion is conditionally supported:

[expr.reinterpret.cast]/8 (standard draft)

Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cv-qualification, shall yield the original pointer value.


Since you are already relying on the c library extension that provides dladdr, you might as well rely on the language extension that lets you cast function pointer to void*. In that case, you may want to ask the compiler to not warn about using language extensions by compiling without the -Wpedantic option - or use a standard version where the conversion is at least conditionally supported. If the conversion isn't supported, then so isn't dladdr.