toolchain/binutils: Fix u-boot on some armhf platforms
Backport commit 3d9c8f6b3f033a6092425b7344647fb51dbed5c6 Without this binutils doesn't properly link u-boot Source: https://sourceware.org/bugzilla/show_bug.cgi?id=23571 Signed-off-by: Daniel Engberg <daniel.engberg.lists@pyret.net>
This commit is contained in:
		 Daniel Engberg
					Daniel Engberg
				
			
				
					committed by
					
						 Hauke Mehrtens
						Hauke Mehrtens
					
				
			
			
				
	
			
			
			 Hauke Mehrtens
						Hauke Mehrtens
					
				
			
						parent
						
							f6159c1e37
						
					
				
				
					commit
					754a08e8d9
				
			| @@ -0,0 +1,276 @@ | ||||
| From 3d9c8f6b3f033a6092425b7344647fb51dbed5c6 Mon Sep 17 00:00:00 2001 | ||||
| From: Alan Modra <amodra@gmail.com> | ||||
| Date: Sun, 26 Aug 2018 14:23:38 +0930 | ||||
| Subject: [PATCH] Delay evaluation of alignment expressions in output sections | ||||
|  | ||||
| git commit 702d16713 broke expressions using CONSTANT(COMMONPAGESIZE) | ||||
| in ALIGN or SUBALIGN of output section statements, because these | ||||
| optional fields were evaluated at script parse time and the patch in | ||||
| question delayed setting of config.commonpagesize.  The right thing to | ||||
| do is keep the tree representation of those fields for later | ||||
| evaluation. | ||||
|  | ||||
| 	PR 23571 | ||||
| 	* ldlang.h (section_alignment): Make it an expression tree. | ||||
| 	(subsection_alignment): Likewise. | ||||
| 	* ldlang.c (topower): Delete. | ||||
| 	(output_section_statement_newfunc): Adjust initialization. | ||||
| 	(init_os): Evaluate section_alignment. | ||||
| 	(lang_size_sections_1): Likewise. | ||||
| 	(size_input_section): Evaluate subsection_alignment. | ||||
| 	(lang_enter_output_section_statement): Don't evaluate here. | ||||
| 	(lang_new_phdr): Use exp_get_vma rather than exp_get_value_int. | ||||
| 	* ldexp.h (exp_get_value_int): Delete. | ||||
| 	(exp_get_power): Declare. | ||||
| 	* ldexp.c (exp_get_value_int): Delete. | ||||
| 	(exp_get_power): New function. | ||||
| 	* emultempl/pe.em (place_orphan): Build expression for section | ||||
| 	alignment. | ||||
| 	* emultempl/pep.em (place_orphan): Likewise. | ||||
| 	* testsuite/ld-scripts/pr23571.d, | ||||
| 	* testsuite/ld-scripts/pr23571.t: New test. | ||||
| 	* testsuite/ld-scripts/align.exp: Run it. | ||||
| --- | ||||
|  ld/ChangeLog                      | 23 +++++++++++++++++++ | ||||
|  ld/emultempl/pe.em                |  2 +- | ||||
|  ld/emultempl/pep.em               |  2 +- | ||||
|  ld/ldexp.c                        | 20 ++++++++++++++-- | ||||
|  ld/ldexp.h                        |  4 ++-- | ||||
|  ld/ldlang.c                       | 48 +++++++++++++-------------------------- | ||||
|  ld/ldlang.h                       |  4 ++-- | ||||
|  ld/testsuite/ld-scripts/align.exp |  4 ++++ | ||||
|  ld/testsuite/ld-scripts/pr23571.d | 10 ++++++++ | ||||
|  ld/testsuite/ld-scripts/pr23571.t | 11 +++++++++ | ||||
|  10 files changed, 88 insertions(+), 40 deletions(-) | ||||
|  create mode 100644 ld/testsuite/ld-scripts/pr23571.d | ||||
|  create mode 100644 ld/testsuite/ld-scripts/pr23571.t | ||||
|  | ||||
| --- a/ld/emultempl/pe.em | ||||
| +++ b/ld/emultempl/pe.em | ||||
| @@ -2165,7 +2165,7 @@ gld_${EMULATION_NAME}_place_orphan (asec | ||||
|  			       &add_child); | ||||
|        if (bfd_link_relocatable (&link_info)) | ||||
|  	{ | ||||
| -	  os->section_alignment = s->alignment_power; | ||||
| +	  os->section_alignment = exp_intop (1U << s->alignment_power); | ||||
|  	  os->bfd_section->alignment_power = s->alignment_power; | ||||
|  	} | ||||
|      } | ||||
| --- a/ld/emultempl/pep.em | ||||
| +++ b/ld/emultempl/pep.em | ||||
| @@ -1962,7 +1962,7 @@ gld_${EMULATION_NAME}_place_orphan (asec | ||||
|  			       &add_child); | ||||
|        if (bfd_link_relocatable (&link_info)) | ||||
|  	{ | ||||
| -	  os->section_alignment = s->alignment_power; | ||||
| +	  os->section_alignment = exp_intop (1U << s->alignment_power); | ||||
|  	  os->bfd_section->alignment_power = s->alignment_power; | ||||
|  	} | ||||
|      } | ||||
| --- a/ld/ldexp.c | ||||
| +++ b/ld/ldexp.c | ||||
| @@ -1522,10 +1522,26 @@ exp_get_vma (etree_type *tree, bfd_vma d | ||||
|    return def; | ||||
|  } | ||||
|   | ||||
| +/* Return the smallest non-negative integer such that two raised to | ||||
| +   that power is at least as large as the vma evaluated at TREE, if | ||||
| +   TREE is a non-NULL expression that can be resolved.  If TREE is | ||||
| +   NULL or cannot be resolved, return -1.  */ | ||||
| + | ||||
|  int | ||||
| -exp_get_value_int (etree_type *tree, int def, char *name) | ||||
| +exp_get_power (etree_type *tree, char *name) | ||||
|  { | ||||
| -  return exp_get_vma (tree, def, name); | ||||
| +  bfd_vma x = exp_get_vma (tree, -1, name); | ||||
| +  bfd_vma p2; | ||||
| +  int n; | ||||
| + | ||||
| +  if (x == (bfd_vma) -1) | ||||
| +    return -1; | ||||
| + | ||||
| +  for (n = 0, p2 = 1; p2 < x; ++n, p2 <<= 1) | ||||
| +    if (p2 == 0) | ||||
| +      break; | ||||
| + | ||||
| +  return n; | ||||
|  } | ||||
|   | ||||
|  fill_type * | ||||
| --- a/ld/ldexp.h | ||||
| +++ b/ld/ldexp.h | ||||
| @@ -229,8 +229,8 @@ void exp_print_tree | ||||
|    (etree_type *); | ||||
|  bfd_vma exp_get_vma | ||||
|    (etree_type *, bfd_vma, char *); | ||||
| -int exp_get_value_int | ||||
| -  (etree_type *, int, char *); | ||||
| +int exp_get_power | ||||
| +  (etree_type *, char *); | ||||
|  fill_type *exp_get_fill | ||||
|    (etree_type *, fill_type *, char *); | ||||
|  bfd_vma exp_get_abs_int | ||||
| --- a/ld/ldlang.c | ||||
| +++ b/ld/ldlang.c | ||||
| @@ -1199,8 +1199,8 @@ output_section_statement_newfunc (struct | ||||
|    ret = (struct out_section_hash_entry *) entry; | ||||
|    memset (&ret->s, 0, sizeof (ret->s)); | ||||
|    ret->s.header.type = lang_output_section_statement_enum; | ||||
| -  ret->s.output_section_statement.subsection_alignment = -1; | ||||
| -  ret->s.output_section_statement.section_alignment = -1; | ||||
| +  ret->s.output_section_statement.subsection_alignment = NULL; | ||||
| +  ret->s.output_section_statement.section_alignment = NULL; | ||||
|    ret->s.output_section_statement.block_value = 1; | ||||
|    lang_list_init (&ret->s.output_section_statement.children); | ||||
|    lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next); | ||||
| @@ -2193,8 +2193,9 @@ init_os (lang_output_section_statement_t | ||||
|      exp_init_os (s->load_base); | ||||
|   | ||||
|    /* If supplied an alignment, set it.  */ | ||||
| -  if (s->section_alignment != -1) | ||||
| -    s->bfd_section->alignment_power = s->section_alignment; | ||||
| +  if (s->section_alignment != NULL) | ||||
| +    s->bfd_section->alignment_power = exp_get_power (s->section_alignment, | ||||
| +						     "section alignment"); | ||||
|  } | ||||
|   | ||||
|  /* Make sure that all output sections mentioned in an expression are | ||||
| @@ -4706,8 +4707,10 @@ size_input_section | ||||
|  	 is greater than any seen before, then record it too.  Perform | ||||
|  	 the alignment by inserting a magic 'padding' statement.  */ | ||||
|   | ||||
| -      if (output_section_statement->subsection_alignment != -1) | ||||
| -	i->alignment_power = output_section_statement->subsection_alignment; | ||||
| +      if (output_section_statement->subsection_alignment != NULL) | ||||
| +	i->alignment_power | ||||
| +	  = exp_get_power (output_section_statement->subsection_alignment, | ||||
| +			   "subsection alignment"); | ||||
|   | ||||
|        if (o->alignment_power < i->alignment_power) | ||||
|  	o->alignment_power = i->alignment_power; | ||||
| @@ -5147,7 +5150,8 @@ lang_size_sections_1 | ||||
|  		    section_alignment = os->bfd_section->alignment_power; | ||||
|  		  } | ||||
|  		else | ||||
| -		  section_alignment = os->section_alignment; | ||||
| +		  section_alignment = exp_get_power (os->section_alignment, | ||||
| +						     "section alignment"); | ||||
|   | ||||
|  		/* Align to what the section needs.  */ | ||||
|  		if (section_alignment > 0) | ||||
| @@ -5225,7 +5229,8 @@ lang_size_sections_1 | ||||
|  		       only align according to the value in the output | ||||
|  		       statement.  */ | ||||
|  		    if (os->lma_region != os->region) | ||||
| -		      section_alignment = os->section_alignment; | ||||
| +		      section_alignment = exp_get_power (os->section_alignment, | ||||
| +							 "section alignment"); | ||||
|  		    if (section_alignment > 0) | ||||
|  		      lma = align_power (lma, section_alignment); | ||||
|  		  } | ||||
| @@ -6673,25 +6678,6 @@ lang_add_output (const char *name, int f | ||||
|      } | ||||
|  } | ||||
|   | ||||
| -static int | ||||
| -topower (int x) | ||||
| -{ | ||||
| -  unsigned int i = 1; | ||||
| -  int l; | ||||
| - | ||||
| -  if (x < 0) | ||||
| -    return -1; | ||||
| - | ||||
| -  for (l = 0; l < 32; l++) | ||||
| -    { | ||||
| -      if (i >= (unsigned int) x) | ||||
| -	return l; | ||||
| -      i <<= 1; | ||||
| -    } | ||||
| - | ||||
| -  return 0; | ||||
| -} | ||||
| - | ||||
|  lang_output_section_statement_type * | ||||
|  lang_enter_output_section_statement (const char *output_section_statement_name, | ||||
|  				     etree_type *address_exp, | ||||
| @@ -6727,10 +6713,8 @@ lang_enter_output_section_statement (con | ||||
|      einfo (_("%F%P:%pS: error: align with input and explicit align specified\n"), | ||||
|  	   NULL); | ||||
|   | ||||
| -  os->subsection_alignment = | ||||
| -    topower (exp_get_value_int (subalign, -1, "subsection alignment")); | ||||
| -  os->section_alignment = | ||||
| -    topower (exp_get_value_int (align, -1, "section alignment")); | ||||
| +  os->subsection_alignment = subalign; | ||||
| +  os->section_alignment = align; | ||||
|   | ||||
|    os->load_base = ebase; | ||||
|    return os; | ||||
| @@ -7748,7 +7732,7 @@ lang_new_phdr (const char *name, | ||||
|    n = (struct lang_phdr *) stat_alloc (sizeof (struct lang_phdr)); | ||||
|    n->next = NULL; | ||||
|    n->name = name; | ||||
| -  n->type = exp_get_value_int (type, 0, "program header type"); | ||||
| +  n->type = exp_get_vma (type, 0, "program header type"); | ||||
|    n->filehdr = filehdr; | ||||
|    n->phdrs = phdrs; | ||||
|    n->at = at; | ||||
| --- a/ld/ldlang.h | ||||
| +++ b/ld/ldlang.h | ||||
| @@ -143,6 +143,8 @@ typedef struct lang_output_section_state | ||||
|    fill_type *fill; | ||||
|    union etree_union *addr_tree; | ||||
|    union etree_union *load_base; | ||||
| +  union etree_union *section_alignment; | ||||
| +  union etree_union *subsection_alignment; | ||||
|   | ||||
|    /* If non-null, an expression to evaluate after setting the section's | ||||
|       size.  The expression is evaluated inside REGION (above) with '.' | ||||
| @@ -153,8 +155,6 @@ typedef struct lang_output_section_state | ||||
|    lang_output_section_phdr_list *phdrs; | ||||
|   | ||||
|    unsigned int block_value; | ||||
| -  int subsection_alignment;	/* Alignment of components.  */ | ||||
| -  int section_alignment;	/* Alignment of start of section.  */ | ||||
|    int constraint; | ||||
|    flagword flags; | ||||
|    enum section_type sectype; | ||||
| --- a/ld/testsuite/ld-scripts/align.exp | ||||
| +++ b/ld/testsuite/ld-scripts/align.exp | ||||
| @@ -53,3 +53,7 @@ if ![is_aout_format] { | ||||
|  } | ||||
|  run_dump_test align2c | ||||
|  set LDFLAGS "$saved_LDFLAGS" | ||||
| + | ||||
| +if { [is_elf_format] && ![is_generic_elf] } { | ||||
| +    run_dump_test pr23571 | ||||
| +} | ||||
| --- /dev/null | ||||
| +++ b/ld/testsuite/ld-scripts/pr23571.d | ||||
| @@ -0,0 +1,10 @@ | ||||
| +#source: align2a.s | ||||
| +#ld: -T pr23571.t -z common-page-size=0x1000 | ||||
| +#objdump: -h -w | ||||
| + | ||||
| +.*: +file format .* | ||||
| + | ||||
| +Sections: | ||||
| +Idx Name +Size +VMA +LMA +File off +Algn +Flags | ||||
| + +0 \.text +[0-9a-f]* +0+1000 +0+1000 .* | ||||
| + +1 \.data +[0-9a-f]* +0+2000 +0+2000 +[0-9a-f]* +2\*\*12 .* | ||||
| --- /dev/null | ||||
| +++ b/ld/testsuite/ld-scripts/pr23571.t | ||||
| @@ -0,0 +1,11 @@ | ||||
| +SECTIONS | ||||
| +{ | ||||
| +  .text CONSTANT(COMMONPAGESIZE) : { | ||||
| +    *(.text) | ||||
| +  } | ||||
| + | ||||
| +  .data : ALIGN(CONSTANT(COMMONPAGESIZE)) { | ||||
| +    *(.data) | ||||
| +  } | ||||
| +  /DISCARD/ : {*(*)} | ||||
| +} | ||||
		Reference in New Issue
	
	Block a user