This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils 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]

Linker relaxation and "SYM = DEFINED (SYM) ? SYM : other" scriptidiom.


The "SYM = DEFINED (SYM) ? SYM : otherexpression;" linker script
idiom is documented as a recommended way to get a default value
for symbols (like PROVIDE, but always define).

Except it doesn't work for relaxing links, in which SYM is not
defined, and otherexpression changes value over relaxation
rounds.  When the DEFINED part is first evaluated (ignoring the
"first_phase" creating round), SYM isn't defined, leading to SYM
being defined as the value of otherexpression on that round.
On the following linker script processing rounds, SYM is now
*found to be defined* but unexpectedly yielding the value of
otherexpression *from the first relaxation round*.

I don't have a stand-alone test-case, as I found this while
improving the MMIX linker to use relaxation (of code, not just
global register assingment), but it should be repeatable for a
relaxing linker, by adding

Main = DEFINED (Main) ? Main : _start;

to the linker script, do a relaxing linking (aah! 8-) in which
_start changes value at least once over relaxation, and compare
the final value of _start against Main.

This could be solved by keeping track of linker-script-defined
symbols and undefining them when starting a new relaxation
iteration.  On the other hand, that might be perceived as a
change in semantics.  On the third hand, the documentation is
still incorrect, and the recommended way to get a default value
for a symbol would necessarily be something more complicated,
but hopefully not as complicated as:

__Main_was_defined = DEFINED (__Main_was_defined) ? __Main_was_defined : DEFINED (Main);
Main = __Main_was_defined ? Main : defaultexpression;

(now is when you refocus from the bug onto linker script
obfuscation. :-)

BTW, while experimenting, I found that I get a SEGV with the "!"
operator on stuff like !DEFINED (SYM), because "!" expects a
section for its operand.  The above construct also got SEGV for
similar reasons.  (Patch forthcoming.)

Anyway, I'd like to know if there are reasons why the code
should *not* be fixed so the documented construct works.

A fix as such seems simple; add the symbol to an initially empty
list at the creating call to bfd_link_hash_lookup in
exp_fold_tree, and undef them (emptying the list) at the top of
the relaxation round in lang_process. This fix is Forthcoming by
default.

brgds, H-P


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