This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Linker script PROVIDE statements


Alan Modra wrote:
On Fri, Feb 20, 2004 at 05:06:28PM +0000, Nathan Sidwell wrote:

Simply creating an undefined symbol in fold_name is insufficient.


I expected so, which is why I said "Try".  :)  The patch looks mostly
good, except for this hunk which just seems to complicate the logic
without actually changing much.
yup, it would have added a redefined error, if I could figure the shared
object problem, but that's really a different issue.

I think you could just use the following, which also fixes a bug in
that we should follow indirect symbols here.
correct, I have installed the attached, after i686-pc-linux-gnu testing.

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2004-02-23  Nathan Sidwell  <nathan@codesourcery.com>

	* ldlang.h (struct lang_output_section_state): Change processed
	field's type.
	* ldexp.c (check, invalid): Remove.
	(fold_name): Move valid_p assignments. Create undefined symbol
	when needed. Directly exampine section's processd flag.
	* ldlang.c (lang_output_section_statement_lookup): Adjust
	processed field init.
	(lang_size_sections_1): Allow LOADADDR when determining section's
	VMA. Adjust error message. Fold data statement's expr.
	(lang_size_sections): Correctly increment lang_statement_iteration.

	* ld-scripts/provide.exp: New.
	* ld-scripts/provide-{1,2,3}.{s,t,d}.exp: New.

2004-02-23  Alan Modra <amodra@bigpond.net.au>

	* ldexp.c (fold_tree): Follow indirect symbols.
	
Index: ld/ldexp.c
===================================================================
RCS file: /cvs/src/src/ld/ldexp.c,v
retrieving revision 1.28
diff -c -3 -p -r1.28 ldexp.c
*** ld/ldexp.c	20 Feb 2004 15:31:09 -0000	1.28
--- ld/ldexp.c	23 Feb 2004 09:59:57 -0000
*************** new_abs (bfd_vma value)
*** 141,157 ****
    return new;
  }
  
- static void
- check (lang_output_section_statement_type *os,
-        const char *name,
-        const char *op)
- {
-   if (os == NULL)
-     einfo (_("%F%P: %s uses undefined section %s\n"), op, name);
-   if (! os->processed)
-     einfo (_("%F%P: %s forward reference of section %s\n"), op, name);
- }
- 
  etree_type *
  exp_intop (bfd_vma value)
  {
--- 141,146 ----
*************** fold_trinary (etree_type *tree,
*** 460,473 ****
    return result;
  }
  
- etree_value_type
- invalid (void)
- {
-   etree_value_type new;
-   new.valid_p = FALSE;
-   return new;
- }
- 
  static etree_value_type
  fold_name (etree_type *tree,
  	   lang_output_section_statement_type *current_section,
--- 449,454 ----
*************** fold_name (etree_type *tree,
*** 476,500 ****
  {
    etree_value_type result;
  
    switch (tree->type.node_code)
      {
      case SIZEOF_HEADERS:
        if (allocation_done != lang_first_phase_enum)
! 	{
! 	  result = new_abs (bfd_sizeof_headers (output_bfd,
! 						link_info.relocatable));
! 	}
!       else
! 	{
! 	  result.valid_p = FALSE;
! 	}
        break;
      case DEFINED:
        if (allocation_done == lang_first_phase_enum)
! 	{
! 	  lang_track_definedness (tree->name.name);
! 	  result.valid_p = FALSE;
! 	}
        else
  	{
  	  struct bfd_link_hash_entry *h;
--- 457,474 ----
  {
    etree_value_type result;
  
+   result.valid_p = FALSE;
+   
    switch (tree->type.node_code)
      {
      case SIZEOF_HEADERS:
        if (allocation_done != lang_first_phase_enum)
! 	result = new_abs (bfd_sizeof_headers (output_bfd,
! 					      link_info.relocatable));
        break;
      case DEFINED:
        if (allocation_done == lang_first_phase_enum)
! 	lang_track_definedness (tree->name.name);
        else
  	{
  	  struct bfd_link_hash_entry *h;
*************** fold_name (etree_type *tree,
*** 515,527 ****
  	}
        break;
      case NAME:
-       result.valid_p = FALSE;
        if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
  	{
  	  if (allocation_done != lang_first_phase_enum)
  	    result = new_rel_from_section (dot, current_section);
- 	  else
- 	    result = invalid ();
  	}
        else if (allocation_done != lang_first_phase_enum)
  	{
--- 489,498 ----
*************** fold_name (etree_type *tree,
*** 529,538 ****
  
  	  h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
  					    tree->name.name,
! 					    FALSE, FALSE, TRUE);
! 	  if (h != NULL
! 	      && (h->type == bfd_link_hash_defined
! 		  || h->type == bfd_link_hash_defweak))
  	    {
  	      if (bfd_is_abs_section (h->u.def.section))
  		result = new_abs (h->u.def.value);
--- 500,510 ----
  
  	  h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
  					    tree->name.name,
! 					    TRUE, FALSE, TRUE);
! 	  if (!h)
! 	    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
! 	  else if (h->type == bfd_link_hash_defined
! 		   || h->type == bfd_link_hash_defweak)
  	    {
  	      if (bfd_is_abs_section (h->u.def.section))
  		result = new_abs (h->u.def.value);
*************** fold_name (etree_type *tree,
*** 565,570 ****
--- 537,548 ----
  	  else if (allocation_done == lang_final_phase_enum)
  	    einfo (_("%F%S: undefined symbol `%s' referenced in expression\n"),
  		   tree->name.name);
+ 	  else if (h->type == bfd_link_hash_new)
+ 	    {
+ 	      h->type = bfd_link_hash_undefined;
+ 	      h->u.undef.abfd = NULL;
+ 	      bfd_link_add_undef (link_info.hash, h);
+ 	    }
  	}
        break;
  
*************** fold_name (etree_type *tree,
*** 574,584 ****
  	  lang_output_section_statement_type *os;
  
  	  os = lang_output_section_find (tree->name.name);
! 	  check (os, tree->name.name, "ADDR");
! 	  result = new_rel (0, NULL, os);
  	}
-       else
- 	result = invalid ();
        break;
  
      case LOADADDR:
--- 552,560 ----
  	  lang_output_section_statement_type *os;
  
  	  os = lang_output_section_find (tree->name.name);
! 	  if (os && os->processed > 0)
! 	    result = new_rel (0, NULL, os);
  	}
        break;
  
      case LOADADDR:
*************** fold_name (etree_type *tree,
*** 587,602 ****
  	  lang_output_section_statement_type *os;
  
  	  os = lang_output_section_find (tree->name.name);
! 	  check (os, tree->name.name, "LOADADDR");
! 	  if (os->load_base == NULL)
! 	    result = new_rel (0, NULL, os);
! 	  else
! 	    result = exp_fold_tree_no_dot (os->load_base,
! 					   abs_output_section,
! 					   allocation_done);
  	}
-       else
- 	result = invalid ();
        break;
  
      case SIZEOF:
--- 563,578 ----
  	  lang_output_section_statement_type *os;
  
  	  os = lang_output_section_find (tree->name.name);
! 	  if (os && os->processed != 0)
! 	    {
! 	      if (os->load_base == NULL)
! 		result = new_rel (0, NULL, os);
! 	      else
! 		result = exp_fold_tree_no_dot (os->load_base,
! 					       abs_output_section,
! 					       allocation_done);
! 	    }
  	}
        break;
  
      case SIZEOF:
*************** fold_name (etree_type *tree,
*** 606,616 ****
  	  lang_output_section_statement_type *os;
  
  	  os = lang_output_section_find (tree->name.name);
! 	  check (os, tree->name.name, "SIZEOF");
! 	  result = new_abs (os->bfd_section->_raw_size / opb);
  	}
-       else
- 	result = invalid ();
        break;
  
      default:
--- 582,590 ----
  	  lang_output_section_statement_type *os;
  
  	  os = lang_output_section_find (tree->name.name);
! 	  if (os && os->processed > 0)
! 	    result = new_abs (os->bfd_section->_raw_size / opb);
  	}
        break;
  
      default:
*************** exp_fold_tree (etree_type *tree,
*** 733,746 ****
  	      else
  		create = FALSE;
  	      h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
! 					create, FALSE, FALSE);
  	      if (h == NULL)
  		{
! 		  if (tree->type.node_class == etree_assign)
  		    einfo (_("%P%F:%s: hash creation failed\n"),
  			   tree->assign.dst);
  		}
  	      else if (tree->type.node_class == etree_provide
  		       && h->type != bfd_link_hash_undefined
  		       && h->type != bfd_link_hash_common)
  		{
--- 707,721 ----
  	      else
  		create = FALSE;
  	      h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
! 					create, FALSE, TRUE);
  	      if (h == NULL)
  		{
! 		  if (create)
  		    einfo (_("%P%F:%s: hash creation failed\n"),
  			   tree->assign.dst);
  		}
  	      else if (tree->type.node_class == etree_provide
+ 		       && h->type != bfd_link_hash_new
  		       && h->type != bfd_link_hash_undefined
  		       && h->type != bfd_link_hash_common)
  		{
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.137
diff -c -3 -p -r1.137 ldlang.c
*** ld/ldlang.c	19 Feb 2004 14:08:31 -0000	1.137
--- ld/ldlang.c	23 Feb 2004 10:00:07 -0000
*************** lang_output_section_statement_lookup (co
*** 622,628 ****
  
        lookup->next = NULL;
        lookup->bfd_section = NULL;
!       lookup->processed = FALSE;
        lookup->sectype = normal_section;
        lookup->addr_tree = NULL;
        lang_list_init (&lookup->children);
--- 622,628 ----
  
        lookup->next = NULL;
        lookup->bfd_section = NULL;
!       lookup->processed = 0;
        lookup->sectype = normal_section;
        lookup->addr_tree = NULL;
        lang_list_init (&lookup->children);
*************** lang_size_sections_1
*** 2984,2995 ****
  		  {
  		    etree_value_type r;
  
  		    r = exp_fold_tree (os->addr_tree,
  				       abs_output_section,
  				       lang_allocating_phase_enum,
  				       dot, &dot);
  		    if (!r.valid_p)
! 		      einfo (_("%F%S: non constant address expression for section %s\n"),
  			     os->name);
  
  		    dot = r.value + r.section->bfd_section->vma;
--- 2984,2998 ----
  		  {
  		    etree_value_type r;
  
+ 		    os->processed = -1;
  		    r = exp_fold_tree (os->addr_tree,
  				       abs_output_section,
  				       lang_allocating_phase_enum,
  				       dot, &dot);
+ 		    os->processed = 0;
+ 		    
  		    if (!r.valid_p)
! 		      einfo (_("%F%S: non constant or forward reference address expression for section %s\n"),
  			     os->name);
  
  		    dot = r.value + r.section->bfd_section->vma;
*************** lang_size_sections_1
*** 3027,3033 ****
  		= TO_SIZE (after - os->bfd_section->vma);
  
  	    dot = os->bfd_section->vma + TO_ADDR (os->bfd_section->_raw_size);
! 	    os->processed = TRUE;
  
  	    if (os->update_dot_tree != 0)
  	      exp_fold_tree (os->update_dot_tree, abs_output_section,
--- 3030,3036 ----
  		= TO_SIZE (after - os->bfd_section->vma);
  
  	    dot = os->bfd_section->vma + TO_ADDR (os->bfd_section->_raw_size);
! 	    os->processed = 1;
  
  	    if (os->update_dot_tree != 0)
  	      exp_fold_tree (os->update_dot_tree, abs_output_section,
*************** lang_size_sections_1
*** 3089,3094 ****
--- 3092,3102 ----
  	    s->data_statement.output_section =
  	      output_section_statement->bfd_section;
  
+ 	    /* We might refer to provided symbols in the expression, and
+ 	       need to mark them as needed.  */
+ 	    exp_fold_tree (s->data_statement.exp, abs_output_section,
+ 			   lang_allocating_phase_enum, dot, &dot);
+ 
  	    switch (s->data_statement.type)
  	      {
  	      default:
*************** lang_size_sections
*** 3294,3299 ****
--- 3302,3308 ----
  	  && first + last <= exp_data_seg.pagesize)
  	{
  	  exp_data_seg.phase = exp_dataseg_adjust;
+ 	  lang_statement_iteration++;
  	  result = lang_size_sections_1 (s, output_section_statement, prev,
  					 fill, dot, relax, check_regions);
  	}
Index: ld/ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.34
diff -c -3 -p -r1.34 ldlang.h
*** ld/ldlang.h	13 Jan 2004 11:10:53 -0000	1.34
--- ld/ldlang.h	23 Feb 2004 10:00:08 -0000
*************** typedef struct lang_output_section_state
*** 134,140 ****
    union lang_statement_union *next;
    const char *name;
  
!   bfd_boolean processed;
  
    asection *bfd_section;
    flagword flags;		/* Or together of all input sections.  */
--- 134,140 ----
    union lang_statement_union *next;
    const char *name;
  
!   int processed;
  
    asection *bfd_section;
    flagword flags;		/* Or together of all input sections.  */
Index: ld/testsuite/ld-scripts/provide-1.d
===================================================================
RCS file: ld/testsuite/ld-scripts/provide-1.d
diff -N ld/testsuite/ld-scripts/provide-1.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-scripts/provide-1.d	23 Feb 2004 10:00:08 -0000
***************
*** 0 ****
--- 1,8 ----
+ #source: provide-1.s
+ #ld: -T provide-1.t
+ #objdump: -s -j .data
+ 
+ .*:     file format .*
+ 
+ Contents of section .data:
+  0000 (08)?000000(08)? (0c)?000000(0c)? 00000000           ............    
Index: ld/testsuite/ld-scripts/provide-1.s
===================================================================
RCS file: ld/testsuite/ld-scripts/provide-1.s
diff -N ld/testsuite/ld-scripts/provide-1.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-scripts/provide-1.s	23 Feb 2004 10:00:08 -0000
***************
*** 0 ****
--- 1,3 ----
+ 	.data
+ 	.globl foo
+ foo:	.long 0
Index: ld/testsuite/ld-scripts/provide-1.t
===================================================================
RCS file: ld/testsuite/ld-scripts/provide-1.t
diff -N ld/testsuite/ld-scripts/provide-1.t
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-scripts/provide-1.t	23 Feb 2004 10:00:08 -0000
***************
*** 0 ****
--- 1,11 ----
+ SECTIONS 
+ {
+   .data :
+   {
+     LONG (foo)
+     LONG (bar)
+     *(.data)
+   }
+   PROVIDE (foo = .);
+   PROVIDE (bar = .);
+ }
Index: ld/testsuite/ld-scripts/provide-2.d
===================================================================
RCS file: ld/testsuite/ld-scripts/provide-2.d
diff -N ld/testsuite/ld-scripts/provide-2.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-scripts/provide-2.d	23 Feb 2004 10:00:08 -0000
***************
*** 0 ****
--- 1,6 ----
+ #source: provide-2.s
+ #ld: -T provide-2.t
+ #nm: -B
+ 0+3 A baz
+ 0+0 D foo
+ 
Index: ld/testsuite/ld-scripts/provide-2.s
===================================================================
RCS file: ld/testsuite/ld-scripts/provide-2.s
diff -N ld/testsuite/ld-scripts/provide-2.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-scripts/provide-2.s	23 Feb 2004 10:00:08 -0000
***************
*** 0 ****
--- 1,6 ----
+ 	.data
+ 	.globl foo
+ foo:	.long 0
+ 
+ 	.globl baz
+ 	.long baz
Index: ld/testsuite/ld-scripts/provide-2.t
===================================================================
RCS file: ld/testsuite/ld-scripts/provide-2.t
diff -N ld/testsuite/ld-scripts/provide-2.t
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-scripts/provide-2.t	23 Feb 2004 10:00:08 -0000
***************
*** 0 ****
--- 1,10 ----
+ SECTIONS 
+ {
+   PROVIDE (foo = 1);
+   PROVIDE (bar = 2);
+   PROVIDE (baz = 3);
+   .data :
+   {
+     *(.data)
+   }
+ }
Index: ld/testsuite/ld-scripts/provide-3.d
===================================================================
RCS file: ld/testsuite/ld-scripts/provide-3.d
diff -N ld/testsuite/ld-scripts/provide-3.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-scripts/provide-3.d	23 Feb 2004 10:00:08 -0000
***************
*** 0 ****
--- 1,3 ----
+ #source: provide-2.s
+ #ld: -T provide-2.t
+ #error: symbol defined in linker script and object file
Index: ld/testsuite/ld-scripts/provide-3.s
===================================================================
RCS file: ld/testsuite/ld-scripts/provide-3.s
diff -N ld/testsuite/ld-scripts/provide-3.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-scripts/provide-3.s	23 Feb 2004 10:00:08 -0000
***************
*** 0 ****
--- 1,3 ----
+ 	.data
+ 	.globl foo
+ foo:	.long 0
Index: ld/testsuite/ld-scripts/provide-3.t
===================================================================
RCS file: ld/testsuite/ld-scripts/provide-3.t
diff -N ld/testsuite/ld-scripts/provide-3.t
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-scripts/provide-3.t	23 Feb 2004 10:00:08 -0000
***************
*** 0 ****
--- 1,11 ----
+ SECTIONS 
+ {
+   .data :
+   {
+     LONG (foo)
+     LONG (bar)
+     *(.data)
+   }
+   foo = .;
+   bar = .;
+ }
Index: ld/testsuite/ld-scripts/provide.exp
===================================================================
RCS file: ld/testsuite/ld-scripts/provide.exp
diff -N ld/testsuite/ld-scripts/provide.exp
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-scripts/provide.exp	23 Feb 2004 10:00:08 -0000
***************
*** 0 ****
--- 1,25 ----
+ # Test PROVIDE in a linker script.
+ # By Nathan Sidwell, CodeSourcery LLC
+ #   Copyright 2004
+ #   Free Software Foundation, Inc.
+ #
+ # This file is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or
+ # (at your option) any later version.
+ # 
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ # GNU General Public License for more details.
+ # 
+ # You should have received a copy of the GNU General Public License
+ # along with this program; if not, write to the Free Software
+ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+ set testname "provide"
+ 
+ run_dump_test provide-1
+ run_dump_test provide-2
+ setup_xfail *-*-*
+ run_dump_test provide-3

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]