I believe that is as designed, a symbol already loaded will take precedence. e.g. if there's any error/error2 (or bar) symbol already loaded, the same named symbols from your shared library will not be relocated. do e.g. nm -D /lib/libc.so.6 |grep error. Your code will refer to the error symbol there, whatever that is.
However,
$nm -D /lib/libc.so.6 |grep error`
42471670 W error
This shows that glibc defines an error
symbol, but it's weakly defined.
This means that if your code, at link time, defines the same symbol, yours will override any weakly
defined symbols. But that does not happen when you dynamically load a library.
That behavior can be overridden by setting the environment variable LD_DYNAMIC_WEAK
- see man ld.so for more info.
So if you run your program like so:
$ LD_DYNAMIC_WEAK=true ./main
it will work