Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Undetected ODR violation at link time

28 views
Skip to first unread message

Sam

unread,
Sep 22, 2018, 2:18:55 PM9/22/18
to
I'm looking for a way to make my linker tell me that the executable it
linked contains the same symbols as in one of the executable's shared
libraries. Apparently this links fine, and the global symbols from the
executable override the ones in the shared library, and not just for
references in the executable itself, but also any references in the shared
library. References to the duplicate symbols from other translation units in
the shared library end up getting bound to the executable at runtime, and
not to the duplicate in the shared library, and hilarity ensues.

I'm using the gold linker on Linux. A contrived example:

/*************************************************************************/

/* log.h */

struct somelog {


somelog();
~somelog();
};

/* log.C */

#include <iostream>
#include "log.H"

somelog::somelog()
{
std::cout << "Constructed " << this << std::endl;
}

somelog::~somelog()
{
std::cout << "Destroyed " << this << std::endl;
}

somelog default_log;

/* main.C: */

#include <iostream>

#include "log.C"

int main()
{
return 0;
}

/*************************************************************************/

Like I said, this is a very contrived example. But nothing apparently goes
wrong during compilation. With gcc 8.1.1 and the gold linker:

$ g++ -shared -o log.so -DPIC -fPIC log.C
$ g++ -o main main.C log.so -Wl,-R`pwd`

And the hilarious part:

$ ./main
Constructed 0x403061
Constructed 0x403061
Destroyed 0x403061
Destroyed 0x403061

I am using every paranoid/hardening/pedantic compilation option I am aware
of, but this slipped by undetected. Perusing ld's manual page doesn't find
anything useful. Perhaps there an option that I missed, that will warn me if
my executable will override any symbols in one of the shared libraries it
links with, directly. I suppose that it's not possible to do anything about
collisions from shared libraries that get linked indirectly, but it should
be possible to warn about directly-linked shared libs.

Paavo Helde

unread,
Sep 23, 2018, 3:18:23 PM9/23/18
to
On 22.09.2018 21:18, Sam wrote:
> I'm looking for a way to make my linker tell me that the executable it
> linked contains the same symbols as in one of the executable's shared
> libraries. Apparently this links fine, and the global symbols from the
> executable override the ones in the shared library,

This can be considered as a feature, not a bug. See a recent thread
"Knowing which function to call" how a program can potentially define
its own pow() function to override both pow() and std::pow() in one go.

Specifically, one Manfred posted the following in that thread:

"I don't think it is undefined behavior, it is a matter of function
replacement instead (20.3.19 and 20.5.4.6). The program creation process
(5.2, p.9) specifies that library linkage is performed last, so that all
extern function definitions provided by the program itself are used
instead of the library supplied ones."

> and not just for
> references in the executable itself, but also any references in the
> shared library.

This is certainly implementation-dependent. For example, with Windows
DLL-s it is always known from which DLL the symbol is imported, so such
late rebinding does not happen. This means for example that one cannot
free() a block of memory allocated by malloc() in another DLL if they
are linked against different C runtime library versions.

In Linux, the dynamic loader attempts to behave more like the static
linking process where there is normally just a single instance of a
symbol in the final executable. This is sometimes good and sometimes
bad. Anyway, this is the mechanism by which some memory diagnostic tools
override malloc/free globally. The LD_PRELOAD mechanism is also often
used for injecting symbols in a process.

So this is a feature, not a bug :-) But Linux tools are typically
infinitely configurable so there might be some way to make them behave
the way you like. For example, there is
__attribute__((visibility("hidden"))); also dlopen() has some
interesting flags like RTLD_DEEPBIND.

Tim Rentsch

unread,
Sep 26, 2018, 11:45:27 AM9/26/18
to
Sam <s...@email-scan.com> writes:

> I'm looking for a way to make my linker tell me that the
> executable it linked contains the same symbols as in one of
> the executable's shared libraries.

Long story short - I suspect you are looking in vain (disclaimer:
I am not a linker expert).

On the plus side, if you are running on Linux it should be fairly
easy to put something together that does what you what want by
using other tools, including in particular 'readelf' (I almost
always use 'readelf -a', because I'm too lazy to learn the options
and I already know how to use grep and awk). You may need another
tool to locate the shared libraries you're interested in, but I
expect you can track that down yourself in another newsgroup where
it's more topical.
0 new messages