public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Alan Modra <amodra@gmail.com>
To: binutils@sourceware.org
Subject: Delay evaluation of alignment expressions in output sections
Date: Sun, 26 Aug 2018 13:17:00 -0000	[thread overview]
Message-ID: <20180826131713.GW1544@bubble.grove.modra.org> (raw)

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.

diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 463b85481d..663d4ce862 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -2165,7 +2165,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
 			       &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;
 	}
     }
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index 1a7394ea46..1dc1664f98 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -1962,7 +1962,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
 			       &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;
 	}
     }
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 4ca812e9b2..e123f0e35f 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -1523,10 +1523,26 @@ exp_get_vma (etree_type *tree, bfd_vma def, char *name)
   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 *
diff --git a/ld/ldexp.h b/ld/ldexp.h
index d58cacba1c..094911127e 100644
--- 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
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 350baf2912..8878ccdb63 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1199,8 +1199,8 @@ output_section_statement_newfunc (struct bfd_hash_entry *entry,
   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_type *s, flagword flags)
     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 from_script)
     }
 }
 
-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 (const char *output_section_statement_name,
     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;
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 3d66169687..dfac0b1b68 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -143,6 +143,8 @@ typedef struct lang_output_section_statement_struct
   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_statement_struct
   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;
diff --git a/ld/testsuite/ld-scripts/align.exp b/ld/testsuite/ld-scripts/align.exp
index f9523d26af..25d4f6dfed 100644
--- 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
+}
diff --git a/ld/testsuite/ld-scripts/pr23571.d b/ld/testsuite/ld-scripts/pr23571.d
new file mode 100644
index 0000000000..adf479660b
--- /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 .*
diff --git a/ld/testsuite/ld-scripts/pr23571.t b/ld/testsuite/ld-scripts/pr23571.t
new file mode 100644
index 0000000000..290cdf50df
--- /dev/null
+++ b/ld/testsuite/ld-scripts/pr23571.t
@@ -0,0 +1,11 @@
+SECTIONS
+{
+  .text CONSTANT(COMMONPAGESIZE) : {
+    *(.text)
+  }
+
+  .data : ALIGN(CONSTANT(COMMONPAGESIZE)) {
+    *(.data)
+  }
+  /DISCARD/ : {*(*)}
+}

-- 
Alan Modra
Australia Development Lab, IBM

                 reply	other threads:[~2018-08-26 13:17 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180826131713.GW1544@bubble.grove.modra.org \
    --to=amodra@gmail.com \
    --cc=binutils@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).