This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: cyg_user_start() in a library


>>>>> "Patrick" == Patrick Doyle <wpd@delcomsys.com> writes:

    Patrick> I would like to place my version of 'cyg_user_start()' in
    Patrick> a library. My version calls yet another 'main()'
    Patrick> replacement, 'mymain()' which is supplied by the
    Patrick> application. The problem is, the linker finds the version
    Patrick> of 'cyg_user_start()' in the eCos library before it finds
    Patrick> my version of 'cyg_user_start()'. Does anybody have any
    Patrick> suggestions as to how I can override the version of
    Patrick> 'cyg_user_start()' in the eCos library with a version in
    Patrick> a second library? (For the moment, I am working around
    Patrick> this problem by explicitly listing the filename
    Patrick> containing my version of 'cyg_user_start()' on the linker
    Patrick> command line, but that is a little cumbersome).

    Patrick> Not knowing anything at all about the "weak" attribute
    Patrick> supported by GCC, I guess I would have assumed that,
    Patrick> since the version of 'cyg_user_start()' declared in the
    Patrick> eCos library was given a "weak" attribute, I could
    Patrick> override it in another library. Obviously, if I create my
    Patrick> own version of 'cyg_user_start()' and specify the file
    Patrick> containing it on the command line for the linker, it will
    Patrick> always override a version listed in a library, regardless
    Patrick> of whether the library version has a "weak" attribute or
    Patrick> not. So, what does the "weak" attribute do?

I am not an expert on this, but from the gcc documentation:

  `weak'
     The `weak' attribute causes the declaration to be emitted as a weak
     symbol rather than a global.  This is primarily useful in defining
     library functions which can be overridden in user code, though it
     can also be used with non-function declarations.  Weak symbols are
     supported for ELF targets, and also for a.out targets when using
     the GNU assembler and linker.

So the normal use of weak symbols is to allow application code to
override library code. Remember the traditional module-based linking
model: the library's cyg_user_start() function might be in the same
module as several other functions which are also needed directly or
indirectly by application code. If the application code defined
cyg_user_start() in a .o file, and then the library module which
contains cyg_user_start() was pulled in, you would have a duplicate
definition problem. The use of weak symbols here avoids such problems,
although in theory section-based linking makes it unnecessary.

I believe that another use of weak symbols would be to allow one
package to override another. For example there can be a generic
implementation of memcpy(), defined weakly, and a more efficient
architecture-specific implementation in some HAL package.

Things can get confusing when you have multiple libraries, and it
helps to be aware of how the linking process works. Consider something
like:

    gcc -o app main.o aux.o -L<path> -Ttarget.ld -lmylib ...

The linker reads in the object files main.o and aux.o and builds a
list of unresolved symbols. These symbols needs to be resolved from
the various libraries. Next, -Ttarget.ld causes the linker script to
be read in and, as a side effect, causes libtarget.a to be read in.
The linker tries to resolve all unresolved symbols from libtarget.a.
If there remain unresolved symbols, the linker then moves on to the
next library libmylib.a, and so on.

So if both libtarget.a and libmylib.a contain definitions for
cyg_user_start(), the former will get used. It does not matter that
that definition is weak and the other one is strong, the linker has
managed to resolve the symbol after processing the first library. If
the linker tried to replace the first library's cyg_user_start() with
the second one, things could get very messy: the first implementation
may have pulled in additional functions which might no longer be
required, etc.

If instead the command line read:

    gcc -o app main.o aux.o -L<path> -lmylib -Ttarget.ld

then if I understand the ld documentation correctly libmylib.a will
now get searched before libtarget.a, so you should get the behaviour
you want.

Bart

-- 
Before posting, please read the FAQ: http://sources.redhat.com/fom/ecos
and search the list archive: http://sources.redhat.com/ml/ecos-discuss


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]