ld: bug in MEMORY command or docs!

Dave Korn dk@artimi.com
Thu Mar 25 01:57:00 GMT 2004


    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....



More information about the Binutils mailing list