@ -3133,12 +3133,63 @@ print_output_section_statement
output_section_statement ) ;
}
/* Scan for the use of the destination in the right hand side
of an expression . In such cases we will not compute the
correct expression , since the value of DST that is used on
the right hand side will be its final value , not its value
just before this expression is evaluated . */
static bfd_boolean
scan_for_self_assignment ( const char * dst , etree_type * rhs )
{
if ( rhs = = NULL | | dst = = NULL )
return FALSE ;
switch ( rhs - > type . node_class )
{
case etree_binary :
return scan_for_self_assignment ( dst , rhs - > binary . lhs )
| | scan_for_self_assignment ( dst , rhs - > binary . rhs ) ;
case etree_trinary :
return scan_for_self_assignment ( dst , rhs - > trinary . lhs )
| | scan_for_self_assignment ( dst , rhs - > trinary . rhs ) ;
case etree_assign :
case etree_provided :
case etree_provide :
if ( strcmp ( dst , rhs - > assign . dst ) = = 0 )
return TRUE ;
return scan_for_self_assignment ( dst , rhs - > assign . src ) ;
case etree_unary :
return scan_for_self_assignment ( dst , rhs - > unary . child ) ;
case etree_value :
if ( rhs - > value . str )
return strcmp ( dst , rhs - > value . str ) = = 0 ;
return FALSE ;
case etree_name :
if ( rhs - > name . name )
return strcmp ( dst , rhs - > name . name ) = = 0 ;
return FALSE ;
default :
break ;
}
return FALSE ;
}
static void
print_assignment ( lang_assignment_statement_type * assignment ,
lang_output_section_statement_type * output_section )
{
int i ;
int is_dot ;
unsigned int i ;
bfd_boolean is_dot ;
bfd_boolean computation_is_valid = TRUE ;
etree_type * tree ;
etree_value_type result ;
@ -3147,14 +3198,17 @@ print_assignment (lang_assignment_statement_type *assignment,
if ( assignment - > exp - > type . node_class = = etree_assert )
{
is_dot = 0 ;
is_dot = FALSE ;
tree = assignment - > exp - > assert_s . child ;
computation_is_valid = TRUE ;
}
else
{
const char * dst = assignment - > exp - > assign . dst ;
is_dot = dst [ 0 ] = = ' . ' & & dst [ 1 ] = = 0 ;
is_dot = ( dst [ 0 ] = = ' . ' & & dst [ 1 ] = = 0 ) ;
tree = assignment - > exp - > assign . src ;
computation_is_valid = is_dot | | ( scan_for_self_assignment ( dst , tree ) = = FALSE ) ;
}
result = exp_fold_tree ( tree , output_section , lang_final_phase_enum ,
@ -3163,11 +3217,29 @@ print_assignment (lang_assignment_statement_type *assignment,
{
bfd_vma value ;
value = result . value + result . section - > bfd_section - > vma ;
if ( computation_is_valid )
{
value = result . value + result . section - > bfd_section - > vma ;
minfo ( " 0x%V " , value ) ;
if ( is_dot )
print_dot = value ;
minfo ( " 0x%V " , value ) ;
if ( is_dot )
print_dot = value ;
}
else
{
struct bfd_link_hash_entry * h ;
h = bfd_link_hash_lookup ( link_info . hash , assignment - > exp - > assign . dst ,
FALSE , FALSE , TRUE ) ;
if ( h )
{
value = h - > u . def . value + result . section - > bfd_section - > vma ;
minfo ( " [0x%V] " , value ) ;
}
else
minfo ( " [unresolved] " ) ;
}
}
else
{