This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
ld: bug in MEMORY command or docs!
- From: "Dave Korn" <dk at artimi dot com>
- To: "'Binutils list'" <binutils at sources dot redhat dot com>
- Date: Wed, 24 Mar 2004 17:04:22 -0000
- Subject: ld: bug in MEMORY command or docs!
Hey everyone,
I have this in my linker script:
------->snip<-------
MEMORY
{
text (rwx) : ORIGIN = 0x10000 , LENGTH = 0x10000
data (rw) : ORIGIN = 0x00000 , LENGTH = 0x0c000
}
------->snip<-------
but what I'd really like to do is this:
------->snip<-------
PROVIDE (CODE_START = 0x10000);
PROVIDE (CODE_LEN = 0x10000);
PROVIDE (DATA_START = 0x00000);
PROVIDE (DATA_LEN = 0x0c000);
MEMORY
{
text (rwx) : ORIGIN = CODE_START , LENGTH = CODE_LEN
data (rw) : ORIGIN = DATA_START , LENGTH = DATA_LEN
}
------->snip<-------
which unfortunately gets me an error like this:
------->snip<-------
dk@mace /repository/gcc-build/binutils/ld> ./ld-new.exe --verbose
GNU ld version 2.13.90 20030308
Supported emulations:
elf32_dlx
built in linker script:17 nonconstant expression for origin
dk@mace /repository/gcc-build/binutils/ld>
------>snip<-------
despite the fact that "info ld" says this:
------->snip<-------
The ORIGIN is an expression for the start address of the memory
region. The expression must evaluate to a constant before memory
allocation is performed, which means that you may not use any section
relative symbols.
------->snip<-------
Now, since those PROVIDEs are outside the SECTIONS directive, they ought
to be absolute symbols in any case; and in fact, even using ORIGIN =
ABSOLUTE (CODE_START) doesn't work. 'Nonconstant expression' doesn't seem
to me like a reasonable way to describe a hard-coded constant either.
The reason for this is because of ldgram.y, which evaluates the ORIGIN
directive like this:
------->snip<-------
origin_spec:
ORIGIN '=' mustbe_exp
{ region->current =
region->origin =
exp_get_vma($3, 0L,"origin", lang_first_phase_enum);
}
;
------->snip<-------
passing a tree of type 'name' to exp_get_vma, which relies on
exp_fold_tree_no_dot like this:
------->snip<-------
r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
if (! r.valid_p && name != NULL)
einfo (_("%F%S nonconstant expression for %s\n"), name);
------->snip<-------
and exp_fold_tree_no_dot calls out to exp_fold_tree, which for a name calls
out to fold_name, which simply does the following:
------->snip<-------
switch (tree->type.node_code)
{
....more...
case NAME:
result.valid_p = FALSE;
if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
{
....more...
}
else if (allocation_done != lang_first_phase_enum)
{
....more...
}
break;
....more...
}
return result;
}
------->snip<-------
So, thanks to that "result.valid_p = FALSE", there's no way that the
ORIGIN directive is ever going to accept any kind of symbol whatsoever.
In fact, there's simply no way a symbol can ever be accepted as a valid
expression for anything at all during lang_first_phase_enum. This also
explains why my attempt to use ABSOLUTE(CODE_START) doesn't work either: the
fold_unary function first evaluates the child expression and checks it for
validity before doing its work (and in any case, ABSOLUTE is also only valid
past lang_first_phase_enum).
I don't see why this shouldn't be made to work. I think it ought to be
possible to add a final "else { .... }" clause to case NAME: in fold_name,
which would look up the symbol to see if it was a known constant.
The main problem is I'm not sure where to look it up. The other clause
looks in the output_bfd's link hash table, but during lang_first_phase_enum
there isn't an output_bfd. I'm not sure when the symbols get entered into
the hash table. Perhaps I have to run down the entire statement_list and
look for provides and assigns before examining them to see if they're
absolute? Or can I cause the evaluation of the ORIGIN and LENGTHs of the
memory regions to be deferred until a later point, by which time the hash
table would be set up?
cheers,
DaveK
--
Can't think of a witty .sigline today....