* ldexp.c (fold_name): In case NAME, permit an absolute symbol

in lang_allocating_phase_enum.
PR 6259.
This commit is contained in:
Ian Lance Taylor
1995-01-31 17:40:50 +00:00
parent 3e46110757
commit 1abb243d51
2 changed files with 145 additions and 80 deletions

View File

@ -1,3 +1,14 @@
Tue Jan 31 12:37:09 1995 Ian Lance Taylor <ian@cygnus.com>
* ldexp.c (fold_name): In case NAME, permit an absolute symbol
in lang_allocating_phase_enum.
Mon Jan 30 11:33:25 1995 Ian Lance Taylor <ian@cygnus.com>
* Makefile.in (distclean): Depend upon clean. Don't bother to
remove files which will be removed by clean. From patch by
alan@SPRI.Levels.UniSA.Edu.Au (Alan Modra).
Fri Jan 27 16:27:34 1995 Ian Lance Taylor <ian@cygnus.com> Fri Jan 27 16:27:34 1995 Ian Lance Taylor <ian@cygnus.com>
* emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): For * emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): For

View File

@ -1,5 +1,5 @@
/* This module handles expression trees. /* This module handles expression trees.
Copyright (C) 1991, 1993 Free Software Foundation, Inc. Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support (sac@cygnus.com). Written by Steve Chamberlain of Cygnus Support (sac@cygnus.com).
This file is part of GLD, the Gnu Linker. This file is part of GLD, the Gnu Linker.
@ -215,72 +215,99 @@ static etree_value_type
fold_binary (tree, current_section, allocation_done, dot, dotp) fold_binary (tree, current_section, allocation_done, dot, dotp)
etree_type *tree; etree_type *tree;
lang_output_section_statement_type *current_section; lang_output_section_statement_type *current_section;
lang_phase_type allocation_done; lang_phase_type allocation_done;
bfd_vma dot; bfd_vma dot;
bfd_vma *dotp; bfd_vma *dotp;
{ {
etree_value_type result; etree_value_type result;
result = exp_fold_tree(tree->binary.lhs, current_section, result = exp_fold_tree (tree->binary.lhs, current_section,
allocation_done, dot, dotp); allocation_done, dot, dotp);
if (result.valid) { if (result.valid)
etree_value_type other; {
other = exp_fold_tree(tree->binary.rhs, etree_value_type other;
current_section,
allocation_done, dot,dotp) ;
if (other.valid) {
/* If values are from different sections, or this is an */
/* absolute expression, make both source args absolute */
if (result.section != other.section ||
current_section == abs_output_section)
{
make_abs(&result);
make_abs(&other);
}
switch (tree->type.node_code) other = exp_fold_tree (tree->binary.rhs,
current_section,
allocation_done, dot,dotp) ;
if (other.valid)
{ {
case '%': /* If the values are from different sections, or this is an
/* Mod, both absolule*/ absolute expression, make both the source arguments
absolute. However, adding or subtracting an absolute
value from a relative value is meaningful, and is an
exception. */
if (current_section != abs_output_section
&& (result.section == abs_output_section
|| other.section == abs_output_section)
&& (tree->type.node_code == '+'
|| tree->type.node_code == '-'))
{
etree_value_type hold;
if (other.value == 0) { /* If there is only one absolute term, make sure it is the
einfo("%F%S %% by zero\n"); second one. */
} if (result.section == abs_output_section)
result.value = (int)result.value % (int)other.value; {
break; hold = result;
case '/': result = other;
if (other.value == 0) { other = hold;
einfo("%F%S / by zero\n"); }
} }
result.value = (int)result.value / (int) other.value; else if (result.section != other.section
break; || current_section == abs_output_section)
#define BOP(x,y) case x : result.value = result.value y other.value;break; {
BOP('+',+); make_abs(&result);
BOP('*',*); make_abs(&other);
BOP('-',-); }
BOP(LSHIFT,<<);
BOP(RSHIFT,>>); switch (tree->type.node_code)
BOP(EQ,==); {
BOP(NE,!=); case '%':
BOP('<',<); if (other.value == 0)
BOP('>',>); einfo ("%F%S %% by zero\n");
BOP(LE,<=); result.value = ((bfd_signed_vma) result.value
BOP(GE,>=); % (bfd_signed_vma) other.value);
BOP('&',&); break;
BOP('^',^);
BOP('|',|); case '/':
BOP(ANDAND,&&); if (other.value == 0)
BOP(OROR,||); einfo ("%F%S / by zero\n");
default: result.value = ((bfd_signed_vma) result.value
FAIL(); / (bfd_signed_vma) other.value);
break;
#define BOP(x,y) case x : result.value = result.value y other.value; break;
BOP('+',+);
BOP('*',*);
BOP('-',-);
BOP(LSHIFT,<<);
BOP(RSHIFT,>>);
BOP(EQ,==);
BOP(NE,!=);
BOP('<',<);
BOP('>',>);
BOP(LE,<=);
BOP(GE,>=);
BOP('&',&);
BOP('^',^);
BOP('|',|);
BOP(ANDAND,&&);
BOP(OROR,||);
default:
FAIL();
}
}
else
{
result.valid = false;
} }
} }
else {
result.valid = false;
}
}
return result; return result;
} }
etree_value_type etree_value_type
invalid () invalid ()
{ {
@ -312,17 +339,20 @@ fold_name (tree, current_section, allocation_done, dot)
} }
break; break;
case DEFINED: case DEFINED:
{ if (allocation_done == lang_first_phase_enum)
struct bfd_link_hash_entry *h; result.valid = false;
else
{
struct bfd_link_hash_entry *h;
h = bfd_link_hash_lookup (link_info.hash, tree->name.name, h = bfd_link_hash_lookup (link_info.hash, tree->name.name,
false, false, true); false, false, true);
result.value = (h != (struct bfd_link_hash_entry *) NULL result.value = (h != (struct bfd_link_hash_entry *) NULL
&& (h->type == bfd_link_hash_defined && (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_common)); || h->type == bfd_link_hash_common));
result.section = 0; result.section = 0;
result.valid = true; result.valid = true;
} }
break; break;
case NAME: case NAME:
result.valid = false; result.valid = false;
@ -333,29 +363,33 @@ fold_name (tree, current_section, allocation_done, dot)
else else
result = invalid(); result = invalid();
} }
else if (allocation_done == lang_final_phase_enum) else if (allocation_done != lang_first_phase_enum)
{ {
struct bfd_link_hash_entry *h; struct bfd_link_hash_entry *h;
h = bfd_link_hash_lookup (link_info.hash, tree->name.name, h = bfd_link_hash_lookup (link_info.hash, tree->name.name,
false, false, true); false, false, true);
if (h != (struct bfd_link_hash_entry *) NULL if (h != NULL && h->type == bfd_link_hash_defined)
&& h->type == bfd_link_hash_defined)
{ {
lang_output_section_statement_type *os; if (bfd_is_abs_section (h->u.def.section))
result = new_abs (h->u.def.value);
else if (allocation_done == lang_final_phase_enum)
{
lang_output_section_statement_type *os;
os = (lang_output_section_statement_lookup os = (lang_output_section_statement_lookup
(h->u.def.section->output_section->name)); (h->u.def.section->output_section->name));
/* FIXME: Is this correct if this section is being /* FIXME: Is this correct if this section is being
linked with -R? */ linked with -R? */
result = new_rel ((h->u.def.value result = new_rel ((h->u.def.value
+ h->u.def.section->output_offset), + h->u.def.section->output_offset),
os); os);
}
} }
if (result.valid == false) else if (allocation_done == lang_final_phase_enum)
einfo("%F%S: undefined symbol `%s' referenced in expression\n", einfo ("%F%S: undefined symbol `%s' referenced in expression\n",
tree->name.name); tree->name.name);
} }
break; break;
@ -852,3 +886,23 @@ exp_get_value_int (tree,def,name, allocation_done)
return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done); return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done);
} }
int
exp_get_abs_int (tree, def, name, allocation_done)
etree_type *tree;
int def;
char *name;
lang_phase_type allocation_done;
{
etree_value_type res;
res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
if (res.valid)
{
res.value += res.section->bfd_section->vma;
}
else {
einfo ("%F%S non constant expression for %s\n",name);
}
return res.value;
}