This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Linker script values as absolute / relative / number confusion
- From: "Andrew Burgess" <aburgess at broadcom dot com>
- To: Binutils <binutils at sourceware dot org>
- Date: Fri, 14 Sep 2012 17:20:58 +0100
- Subject: Linker script values as absolute / relative / number confusion
I trying to take a linker script that used to work on older linkers and
get it running on a more recent (2.22) linker.
I'm running into confusion relating to changes in how symbols in the
linker script are treated as absolute, relative, or just numbers, and
converted from one type to another.
I have a simple example,
> cat obj.s
.text
.4byte 0x0
> as -o obj.o obj.s
> ld -T memmap1.ld -Map link1.map -o obj.x obj.o
> cat memmap1.ld
SECTIONS
{
. = 0x100;
.text :
{
*(.text*)
}
_pad_to = 0x200;
.padding :
{
BYTE(0); . = ALIGN(8);
. += (. < _pad_to) ? (_pad_to - .) : 0;
}
.end :
{
BYTE(0);
}
/DISCARD/ : { *(*) }
}
> grep "\.end" link1.map
## END ##
Ok, so, you'll notice a grep at the end, that's how I'm judging success
/ failure. There's probably lots wrong with the script, so here's what
I'm trying to do,
The ".padding" section should fill enough space so that the section
/after/ it starts at the address in _pad_to. The address of ".end" then
should be 0x200, and the output from the grep, would I hope look like this:
.end 0x0000000000000200 0x1
[ I know there are "correct" ways to force the start address of ".end"
to the right place, lets pretend there's a /really/ good reason why I
want to do things this way for now. ]
On ld 2.19 I do get the behaviour I'd like. On current HEAD I don't,
instead I get:
.end 0x0000000000000304 0x1
The problem it turns out is the line:
. += (. < _pad_to) ? (_pad_to - .) : 0;
So, I read up in the documentation, and in this page:
http://sourceware.org/binutils/docs-2.22/ld/Expression-Section.html#Expression-Section
If I look at the line in bits, first ". < _pad_to", whether "." is
treated as relative or absolute it will be less than "_pad_to", so it's
the "_pad_to - ." that's causing the problem.
The docs say that absolute symbols in output sections are treated as
plain numbers, so I have "<plain-number: 0x200> - <relative-addr: 0x8>".
The docs further suggest that the result of this will be 0x1fc,
leading to my change in behaviour.
Ok, so I apply the following patch to "fix" my linker script, the line
in question now becomes:
. += (ABSOLUTE(.) < _pad_to) ? (_pad_to - ABSOLUTE(.)) : 0;
Now I rerun the test, and grep for my output line .... and nothing has
changed.
So docs again, and indeed, binary operations involving an absolute
address and a plain-number convert the number to an absolute. Gah.
Ok, so I throw a few more ABSOLUTEs at the thing, and I get:
. += (ABSOLUTE(.) < ABSOLUTE(_pad_to)) ? (ABSOLUTE(_pad_to) -
ABSOLUTE(.)) : 0;
Now I rerun the test and joy, things work again.
So, finally, my questions,
(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.
(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. 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?
So, last bit of info is to figure out where all the changes came from.
I'm using the git mirror (git://sourceware.org/git/binutils.git), the
commit that actually changed the behaviour was
dc027516e99b4795b1fba7179de6fe00606910, which was added as a result of
bug, http://sourceware.org/bugzilla/show_bug.cgi?id=12066, which was
raised as a result of commit 557189b0dd1f3dec6b00b91b9b0c5459ece72a52.
The mailing list thread for commit 557189b0 is:
http://sourceware.org/ml/binutils/2010-08/msg00118.html
Thanks for your time,
Andrew
Question 1: