This is the mail archive of the
mailing list for the binutils project.
Re: Linker script values as absolute / relative / number confusion
- From: Alan Modra <amodra at gmail dot com>
- To: Andrew Burgess <aburgess at broadcom dot com>
- Cc: Binutils <binutils at sourceware dot org>
- Date: Mon, 17 Sep 2012 07:49:58 +0930
- Subject: Re: Linker script values as absolute / relative / number confusion
- References: <5053596A.email@example.com>
On Fri, Sep 14, 2012 at 05:20:58PM +0100, Andrew Burgess wrote:
> (1) The thing I've ended up with doesn't feel great. I create
> _pad_to as an absolute symbol, but then need to wrap it in ABSOLUTE
> in order to use it as an absolute symbol. Is this /really/ the
> intended behaviour. I'm sure there's a really good reason for the
> whole absolute addresses to numbers behaviour, but even after
> reading the docs I don't understand why we'd want it this way, I'm
> hoping someone can help me understand.
If you've read the history then you know that ld script expression
evaluation was such an ad-hoc mess that it couldn't be documented
without pages of rules. People wrote ld scripts without the benefit
of much documentation and experimented until "it worked". The changes
I made probably didn't go far enough, but if I had rewritten
expression evaluation to be completely sane that would have broken too
many existing ld scripts. Incidentally, a rewrite from scratch would
have been a much easier task than trying to minimize incompatibility.
> (2) In my second attempt, with the version of the line:
> . += (ABSOLUTE(.) < _pad_to) ? (_pad_to - ABSOLUTE(.)) : 0;
> I see the size of "_pad_to - ABSOLUTE(.)" as "0x1fc", given that the
> ".padding" section starts at 0x104, contains 1 byte then rounds up
> to an 0x8 bounday, I think the value of ABSOLUTE(.) should be 0x108.
Yes, it is.
> Given that then after converting the number 0x200 to be an absolute
> address ld comes up with the value "0x1fc + 0x108" = "0x304". Given
> that 0x200 (the original value of _pad_to) must be involved
> somewhere, then all I can think is that ld believes the absolute
> address for where this line is being executed is at 0x104, but this
> seems wrong to me, should it not be 0x108?
ld is doing ". = 0x200". That results in the section ending at
0x104+0x200 = 0x304. Neglecting the condition, your expression is
. = . + (_pad_to - ABSOLUTE(.));
So let's start with the innermost value of ".".
This has value 4, in section ".padding".
ABSOLUTE(.) then is 0x108, in the absolute section.
_pad_to is 0x200, and the ld docs say "Expressions appearing inside an
output section definition treat absolute symbols as numbers". So this
is just a number without any section.
So, what is the result of the subtraction? According to the ld docs,
since one operand is absolute the other should first be made absolute.
That doesn't happen here! The ld docs are missing a rule. Instead
the number is used as is, and the result is 0xf8 absolute. Now we add
this to ".", which has value 4, section ".padding". Given two
different sections, ld converts both values to absolute, to get
0x108 + 0xf8. So the net result is ". = 0x200".
When you instead use ABSOLUTE(_pad_to) in the expression, the value of
ABSOLUTE(_pad_to) is 0x200 absolute. 0x200 absolute - 0x108 absolute
is 0xf8, and because the sections (absolute in this case) were the
same, the result is a plain number. So . + 0xf8 results in 0xfc.
Net result, ". = 0xfc", as you require.
* ld.texinfo (Expression Section): Correct description of
conversions for a binary operation involving an absolute symbol
and a number.
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.284
diff -u -p -r1.284 ld.texinfo
--- ld/ld.texinfo 6 Aug 2012 22:27:52 -0000 1.284
+++ ld/ld.texinfo 16 Sep 2012 13:03:02 -0000
@@ -5646,14 +5646,18 @@ addresses, ld follows these rules to eva
+Unary operations on an absolute address or number, and binary
+operations on two absolute addresses or two numbers, or between one
+absolute address and a number, apply the operator to the value(s).
Unary operations on a relative address, and binary operations on two
relative addresses in the same section or between one relative address
and a number, apply the operator to the offset part of the address(es).
-Unary operations on an absolute address, and binary operations on one
-or more absolute addresses or on two relative addresses not in the
-same section, first convert any non-absolute term to an absolute
-address before applying the operator.
+Other binary operations, that is, between two relative addresses not
+in the same section, or between a relative address and an absolute
+address, first convert any non-absolute term to an absolute address
+before applying the operator.
The result section of each sub-expression is as follows:
Australia Development Lab, IBM