[PATCH] ld: fix ABSOLUTE for general expressions

Kyrill Tkachov kyrylo.tkachov@foss.arm.com
Thu Sep 29 13:29:00 GMT 2016


Hi Alan,

On 20/07/16 03:44, Alan Modra wrote:
> Like all changes that affect script expressions there is quite a good
> chance that someone is relying on the old behaviour.  For example,
> Jakub called the maxpage3b behaviour a "feature" in
> https://sourceware.org/ml/binutils/2007-01/msg00181.html
> Well, that one seems quite clearly a bug to me.  I'm actually more
> worried about "absolute (<number>)" inside output section statements,
> ie. the behaviour that Tristan thinks should be changed.  Oh well,
> let's see who screams.

I noticed this patch breaks linking of an arm defconfig Linux kernel.
It fails with:
arm-none-linux-gnueabihf-ld: HYP init code too big or misaligned

This is with a linux-4.7.4 kernel configured with:
make ARCH=arm defconfig

Thanks,
Kyrill

> ---
> Early expression evaluation
>
> Folding a constant expression early can lead to loss of tokens, eg.
> ABSOLUTE, that are significant in ld's horrible context sensitive
> expression evaluation.  Also, MAXPAGESIZE and other "constants" may
> not have taken values specified on the command line, leading to the
> wrong value being cached.
>
> 	* ldexp.c (exp_unop, exp_binop, exp_trinop, exp_nameop): Don't
> 	fold expression.
> 	* testsuite/ld-elf/maxpage3b.d: Expect correct maxpagesize.
>
> diff --git a/ld/ldexp.c b/ld/ldexp.c
> index 68c4bc5..a560643 100644
> --- a/ld/ldexp.c
> +++ b/ld/ldexp.c
> @@ -1255,80 +1255,55 @@ exp_fold_tree_no_dot (etree_type *tree)
>   etree_type *
>   exp_binop (int code, etree_type *lhs, etree_type *rhs)
>   {
> -  etree_type value, *new_e;
> -
> -  value.type.node_code = code;
> -  value.type.filename = lhs->type.filename;
> -  value.type.lineno = lhs->type.lineno;
> -  value.binary.lhs = lhs;
> -  value.binary.rhs = rhs;
> -  value.type.node_class = etree_binary;
> -  exp_fold_tree_no_dot (&value);
> -  if (expld.result.valid_p)
> -    return exp_intop (expld.result.value);
> -
> -  new_e = (etree_type *) stat_alloc (sizeof (new_e->binary));
> -  memcpy (new_e, &value, sizeof (new_e->binary));
> +  etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->binary));
> +
> +  new_e->type.node_code = code;
> +  new_e->type.filename = lhs->type.filename;
> +  new_e->type.lineno = lhs->type.lineno;
> +  new_e->binary.lhs = lhs;
> +  new_e->binary.rhs = rhs;
> +  new_e->type.node_class = etree_binary;
>     return new_e;
>   }
>   
>   etree_type *
>   exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
>   {
> -  etree_type value, *new_e;
> -
> -  value.type.node_code = code;
> -  value.type.filename = cond->type.filename;
> -  value.type.lineno = cond->type.lineno;
> -  value.trinary.lhs = lhs;
> -  value.trinary.cond = cond;
> -  value.trinary.rhs = rhs;
> -  value.type.node_class = etree_trinary;
> -  exp_fold_tree_no_dot (&value);
> -  if (expld.result.valid_p)
> -    return exp_intop (expld.result.value);
> -
> -  new_e = (etree_type *) stat_alloc (sizeof (new_e->trinary));
> -  memcpy (new_e, &value, sizeof (new_e->trinary));
> +  etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->trinary));
> +
> +  new_e->type.node_code = code;
> +  new_e->type.filename = cond->type.filename;
> +  new_e->type.lineno = cond->type.lineno;
> +  new_e->trinary.lhs = lhs;
> +  new_e->trinary.cond = cond;
> +  new_e->trinary.rhs = rhs;
> +  new_e->type.node_class = etree_trinary;
>     return new_e;
>   }
>   
>   etree_type *
>   exp_unop (int code, etree_type *child)
>   {
> -  etree_type value, *new_e;
> -
> -  value.unary.type.node_code = code;
> -  value.unary.type.filename = child->type.filename;
> -  value.unary.type.lineno = child->type.lineno;
> -  value.unary.child = child;
> -  value.unary.type.node_class = etree_unary;
> -  exp_fold_tree_no_dot (&value);
> -  if (expld.result.valid_p)
> -    return exp_intop (expld.result.value);
> +  etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->unary));
>   
> -  new_e = (etree_type *) stat_alloc (sizeof (new_e->unary));
> -  memcpy (new_e, &value, sizeof (new_e->unary));
> +  new_e->unary.type.node_code = code;
> +  new_e->unary.type.filename = child->type.filename;
> +  new_e->unary.type.lineno = child->type.lineno;
> +  new_e->unary.child = child;
> +  new_e->unary.type.node_class = etree_unary;
>     return new_e;
>   }
>   
>   etree_type *
>   exp_nameop (int code, const char *name)
>   {
> -  etree_type value, *new_e;
> -
> -  value.name.type.node_code = code;
> -  value.name.type.filename = ldlex_filename ();
> -  value.name.type.lineno = lineno;
> -  value.name.name = name;
> -  value.name.type.node_class = etree_name;
> -
> -  exp_fold_tree_no_dot (&value);
> -  if (expld.result.valid_p)
> -    return exp_intop (expld.result.value);
> +  etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->name));
>   
> -  new_e = (etree_type *) stat_alloc (sizeof (new_e->name));
> -  memcpy (new_e, &value, sizeof (new_e->name));
> +  new_e->name.type.node_code = code;
> +  new_e->name.type.filename = ldlex_filename ();
> +  new_e->name.type.lineno = lineno;
> +  new_e->name.name = name;
> +  new_e->name.type.node_class = etree_name;
>     return new_e;
>   
>   }
> diff --git a/ld/testsuite/ld-elf/maxpage3b.d b/ld/testsuite/ld-elf/maxpage3b.d
> index 4bee0ec..62b50c9 100644
> --- a/ld/testsuite/ld-elf/maxpage3b.d
> +++ b/ld/testsuite/ld-elf/maxpage3b.d
> @@ -4,7 +4,8 @@
>   #target: x86_64-*-linux*
>   
>   #...
> -  \[[ 0-9]+\] \.data[ \t]+PROGBITS[ \t]+0*200000[ \t]+[ \t0-9a-f]+WA?.*
> +  \[[ 0-9]+\] \.data[ \t]+PROGBITS[ \t]+0*10000000[ \t]+[ \t0-9a-f]+WA?.*
>   #...
>     LOAD+.*0x10000000
> +  LOAD+.*0x10000000
>   #pass
>



More information about the Binutils mailing list