Preconditions
A third-party has provided a C++ executable fooapp
that uses a shared object libfoo.so
. The library also comes with a header foo.hpp
so developers can build other applications:
/* foo.hpp */
namespace foo {
void bar(int a, int b);
// More code below here <--- NOTE!!!
}
Success example
This is a standard LD_PRELOAD
-based function interposition workflow.
First, I write my own version of the library, myfoo.cpp
that exactly mirrors part of foo.hpp
:
/* myfoo.hpp */
# include <ofstream>
namespace foo {
void bar(int a, int b) {
std::cout << a << "," << b << std::endl;
}
// NOTHING below here <-- NOTE!!!
}
Then I compile my library into libmyfoo.so
and see the following:
$ nm libfoo.so -C | fgrep bar
0000000000021fc0 T foo::bar(int, int)
$ nm libmyfoo.so -C | fgrep bar
0000000000010c30 T foo::bar(int, int)
$ LD_DEBUG=bindings LD_DEBUG_OUTPUT=ld_debug.log LD_PRELOAD=./libmyfoo.so fooapp
Success! ld_debug.log
shows binding as expected, and bar(...)
generates output to the console.
Failure example
For the failure example, I'm going to (1) change one character in myfoo.hpp
and (2) then fix that character in the binary using objcopy
:
/* myfoo.hpp */
# include <ofstream>
namespace foq { // <-- NAME CHANGE!
void bar(int a, int b) {
std::cout << a << "," << b << std::endl;
}
// NOTHING below here <-- NOTE!!!
}
When I compile my library into libmyfoq.so
I see the following:
$ nm libfoo.so -C | fgrep bar
0000000000021fc0 T foo::bar(int, int) # <-- Sames as before
$ nm libmyfoq.so -C | fgrep bar
0000000000010c30 T foq::bar(int, int) # <-- New name as expected
$ objcopy --redefine-syms=sym.map libmyfoq.so libmyfoo.so # <-- NEW STEP!
$ nm libmyfoo.so -C | fgrep bar
0000000000010c30 T foo::bar(int, int) # <-- SUCCESSful name update
$ LD_DEBUG=bindings LD_DEBUG_OUTPUT=ld_debug.log LD_PRELOAD=./libmyfoo.so fooapp
Failure! ld_debug.log
shows NO binding of fooapp
symbols to libmyfoo.so
.
(PS -- If you're curious, sym.map
contains a mapping between the mangled name of foq::bar
and the mangled name of foo::bar
. You can see these if you drop the -C
from the nm
command. See man objcopy
for additional details.)
WHY?
In summary:
objcopy
is renaming the symbol correctly.- The symbol name hasn't changed size.
- BUT the loader is ignoring it at load time.
What's the story here?