std library hooks

H. S. Teoh hsteoh at quickfur.ath.cx
Sat Apr 14 23:01:43 PDT 2012


On Sat, Apr 14, 2012 at 10:26:55PM -0700, H. S. Teoh wrote:
> On Sun, Apr 15, 2012 at 01:08:35AM -0400, Nick Sabalausky wrote:
> > "Walter Bright" <newshound2 at digitalmars.com> wrote in message 
> > news:jmdhof$1v3v$1 at digitalmars.com...
> > > On 4/14/2012 4:54 PM, Manu wrote:
> > >> I just tried it, and I got the error I expected:
> > >>
> > >> LIBCMTD.lib(atox.obj) : error LNK2005: _atoi already defined in Unit.obj
> > >>
> > >> In C, I would always explicitly declare weak linkage to do this...
> > >> what's the point of the weak attribute if not for this?
> > >
> > > First you need to find out why you have multiple definitions of the
> > > same symbol being linked together. For example, do not specify
> > > libcmtd.lib to the linker, then link, then see what your unresolved
> > > symbols are.
> > 
> > This contradicts what you said earlier about symbols in obj files
> > always overriding ones in lib files. Either obj symbols override lib
> > symbols or they conflict. Manu demonstrated that they conflict, rather
> > than override.  How is your suggestion for replacing druntime
> > functions supposed to work when the linker is just going to bitch
> > about them being "already defined"?
> [...]
> 
> Symbols in obj files do not override anything unless the library exports
> weak symbols. Normal exports from the library will cause a conflict. At
> least, that's how ld works; I can't speak for optlink.
[...]

OK, what I said wasn't the whole truth. There's more to ld than I
thought. After some actual testing with some C code, I found that the
order you pass parameters to ld makes a difference in whether you can
define a function multiple times, and which version it picks up.

I made a one-function library called mylib.a, that exports a single
function 'mylibfunc'. Then I wrote some code in aux.c that calls
'mylibfunc', and then in main.c, I define a different version of
'mylibfunc' along with main(). Here's the result of various orderings of
the linker command-line (each .c file is compiled with gcc -c
beforehand):

1) ld mylib.a aux.o main.o
	Works, main's version of 'mylibfunc' is picked up

2) ld aux.o mylib.a main.o
	Fails: ld complains that 'mylibfunc' is multiply defined

3) ld aux.o main.o mylib.a
	Works, main's version of 'mylibfunc' is picked up

4) ld main.o aux.o mylib.a
	Works, main's version of 'mylibfunc' is picked up

So here's my understanding of what happens:

For (1), ld doesn't even care about mylib.a because there are no
unresolved symbols to resolve yet. Then it sees aux.o, which has
unresolved reference to 'mylibfunc', then it sees main.o, which resolves
this symbol, so it finishes successfully.

For (2), ld sees aux.o first, which has unresolved symbol 'mylibfunc',
so it searches mylib.a next, and finds 'mylibfunc' in mylib.a, so it
links that in. Now when it sees main.o next, it sees 'mylibfunc' again,
and complains that it's already been defined.

For (3), ld sees aux.o first, which references unresolved symbol
'mylibfunc', then it sees main.o, which defines 'mylibfunc', so now all
symbols are resolved. So when it sees mylib.a next, it does nothing 'cos
there are no more symbols to resolve. So this leaves us with main's
version of 'mylibfunc' linked.

For (4), ld sees main.o first, which exports 'mylibfunc', so when it
sees aux.o next, which references 'mylibfunc', it resolves it to main's
version of 'mylibfunc'. Then it sees mylib.a but does nothing because
all symbols have already been resolved.

Conclusion: defining your own version of library functions work... if
you link the library after your own version. If the library's version
gets picked up first, the linker will complain about duplicate symbols.


T

-- 
People say I'm indecisive, but I'm not sure about that. -- YHL, CONLANG


More information about the Digitalmars-d mailing list