public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: "H.J. Lu" <hongjiu.lu@intel.com>
To: binutils@sourceware.org
Subject: [PATCH] ELF: Resolve referenced __start_XXX/__stop_XXX symbols
Date: Fri, 09 Jun 2017 22:05:00 -0000	[thread overview]
Message-ID: <20170609220526.GA24413@gmail.com> (raw)

Normally, linker will define __start_XXX/__stop_XXX symbols only for
orphaned sections.   However, during garbage collection, ELF linker
marks all sections with references to __start_XXX/__stop_XXX symbols
as used.  When section XXX isn't an orphaned section, __start_XXX and
__stop_XXX symbols are left undefined even if section XXX does exist.
This patch adds SEC_ELF_NEED_START_STOP to section flags to indicate
that __start_XXX and/or __stop_XXX symbols should be defined and avoid
defining them as orphaned section.  Instead, ELF linker resolves
references to __start_XXX/__stop_XXX symbols together with .startof.
symbol.

OK for master?


H.J.
---
bfd/

	PR ld/21562
	* elflink.c (_bfd_elf_gc_mark_rsec): Set SEC_ELF_NEED_START_STOP
	if a section references __start_XXX/__stop_XXX symbols.
	* section (SEC_ELF_NEED_START_STOP): New.
	* bfd-in2.h: Regenerated.

ld/

	PR ld/21562
	* ldlang.c (lang_insert_orphan): Don't define __start_XXX nor
	__stop_XXX symbols for ELF linker if SEC_ELF_NEED_START_STOP is
	set.
	(lang_set_startof): Resolve references to __start_XXX and
	__stop_XXX symbols for ELF linker if SEC_ELF_NEED_START_STOP is
	set.
	* testsuite/ld-elf/pr21557.t: New test.
	* testsuite/ld-elf/pr21557a.d: Likewise.
	* testsuite/ld-elf/pr21557a.s: Likewise.
	* testsuite/ld-elf/pr21557b.d: Likewise.
	* testsuite/ld-elf/pr21557b.s: Likewise.
	* testsuite/ld-elf/pr21557c.d: Likewise.
	* testsuite/ld-elf/pr21557d.d: Likewise.
---
 bfd/bfd-in2.h                  |  4 ++++
 bfd/elflink.c                  |  1 +
 bfd/section.c                  |  4 ++++
 ld/ldlang.c                    | 49 ++++++++++++++++++++++++++++++++++++------
 ld/testsuite/ld-elf/pr21557.t  |  3 +++
 ld/testsuite/ld-elf/pr21557a.d |  9 ++++++++
 ld/testsuite/ld-elf/pr21557a.s |  8 +++++++
 ld/testsuite/ld-elf/pr21557b.d |  9 ++++++++
 ld/testsuite/ld-elf/pr21557b.s |  8 +++++++
 ld/testsuite/ld-elf/pr21557c.d | 10 +++++++++
 ld/testsuite/ld-elf/pr21557d.d | 10 +++++++++
 11 files changed, 109 insertions(+), 6 deletions(-)
 create mode 100644 ld/testsuite/ld-elf/pr21557.t
 create mode 100644 ld/testsuite/ld-elf/pr21557a.d
 create mode 100644 ld/testsuite/ld-elf/pr21557a.s
 create mode 100644 ld/testsuite/ld-elf/pr21557b.d
 create mode 100644 ld/testsuite/ld-elf/pr21557b.s
 create mode 100644 ld/testsuite/ld-elf/pr21557c.d
 create mode 100644 ld/testsuite/ld-elf/pr21557d.d

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index a23bb98..a072f68 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1464,6 +1464,10 @@ typedef struct bfd_section
      when memory read flag isn't set. */
 #define SEC_COFF_NOREAD 0x40000000
 
+  /* Indicate that __start_XXX and/or __stop_XXX symbols should be
+     defined for this section.  */
+#define SEC_ELF_NEED_START_STOP 0x40000000
+
   /* Indicate that section has the purecode flag set.  */
 #define SEC_ELF_PURECODE 0x80000000
 
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 1b447bb..54586d5 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12782,6 +12782,7 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
 	  if (s != NULL)
 	    {
 	      *start_stop = !s->gc_mark;
+	      s->flags |= SEC_ELF_NEED_START_STOP;
 	      return s;
 	    }
 	}
diff --git a/bfd/section.c b/bfd/section.c
index 28eee7f..bc2749a 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -361,6 +361,10 @@ CODE_FRAGMENT
 .     when memory read flag isn't set. *}
 .#define SEC_COFF_NOREAD 0x40000000
 .
+.  {* Indicate that __start_XXX and/or __stop_XXX symbols should be
+.     defined for this section.  *}
+.#define SEC_ELF_NEED_START_STOP 0x40000000
+.
 .  {* Indicate that section has the purecode flag set.  *}
 .#define SEC_ELF_PURECODE 0x80000000
 .
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 252400b..0ad3698 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1854,7 +1854,10 @@ lang_insert_orphan (asection *s,
 
   ps = NULL;
   start_assign = NULL;
-  if (config.build_constructors && *os_tail == os)
+  if (config.build_constructors
+      && *os_tail == os
+      && (bfd_get_flavour (link_info.output_bfd) != bfd_target_elf_flavour
+	  || (s->flags & SEC_ELF_NEED_START_STOP) == 0))
     {
       /* If the name of the section is representable in C, then create
 	 symbols to mark the start and the end of the section.  */
@@ -5924,12 +5927,14 @@ section_for_dot (void)
   return bfd_abs_section_ptr;
 }
 
-/* Fix any .startof. or .sizeof. symbols.  When the assemblers see the
-   operator .startof. (section_name), it produces an undefined symbol
-   .startof.section_name.  Similarly, when it sees
+/* Fix any .startof., .sizeof., __start or __stop symbols.  When the
+   assemblers see the operator .startof. (section_name), it produces
+   an undefined symbol .startof.section_name.  Similarly, when it sees
    .sizeof. (section_name), it produces an undefined symbol
-   .sizeof.section_name.  For all the output sections, we look for
-   such symbols, and set them to the correct value.  */
+   .sizeof.section_name.  Also for ELF linker, __start_XXX or __stop_XXX
+   symbols should be resolved to the start and end of section XXX.  For
+   all the output sections, we look for such symbols, and set them to
+   the correct value.  */
 
 static void
 lang_set_startof (void)
@@ -5966,6 +5971,38 @@ lang_set_startof (void)
 	  h->u.def.section = bfd_abs_section_ptr;
 	}
 
+      if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
+	  && (s->flags & SEC_ELF_NEED_START_STOP) != 0)
+	{
+	  char leading_char
+	    = bfd_get_symbol_leading_char (link_info.output_bfd);
+
+	  buf[0] = leading_char;
+	  sprintf (buf + (buf[0] != 0), "__start_%s", secname);
+	  h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+				    TRUE);
+	  if (h != NULL
+	      && (h->type == bfd_link_hash_undefined
+		  || h->type == bfd_link_hash_undefweak))
+	    {
+	      h->type = bfd_link_hash_defined;
+	      h->u.def.value = 0;
+	      h->u.def.section = s;
+	    }
+
+	  buf[0] = leading_char;
+	  sprintf (buf + (buf[0] != 0), "__stop_%s", secname);
+	  h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+				    TRUE);
+	  if (h != NULL
+	      && (h->type == bfd_link_hash_undefined
+		  || h->type == bfd_link_hash_undefweak))
+	    {
+	      h->type = bfd_link_hash_defined;
+	      h->u.def.value = TO_ADDR (s->size);
+	      h->u.def.section = s;
+	    }
+	}
       free (buf);
     }
 }
diff --git a/ld/testsuite/ld-elf/pr21557.t b/ld/testsuite/ld-elf/pr21557.t
new file mode 100644
index 0000000..01478e6
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21557.t
@@ -0,0 +1,3 @@
+SECTIONS {
+        scnfoo : { *(scnfoo) }
+}
diff --git a/ld/testsuite/ld-elf/pr21557a.d b/ld/testsuite/ld-elf/pr21557a.d
new file mode 100644
index 0000000..f91d6d3
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21557a.d
@@ -0,0 +1,9 @@
+#ld: -shared -z defs --gc-sections
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21557a.s b/ld/testsuite/ld-elf/pr21557a.s
new file mode 100644
index 0000000..d825dfe
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21557a.s
@@ -0,0 +1,8 @@
+        .section        scnfoo,"aw",%progbits
+        .zero 0x10
+
+        .globl  bar
+        .data
+        .type   bar, %object
+bar:
+        .quad   __start_scnfoo
diff --git a/ld/testsuite/ld-elf/pr21557b.d b/ld/testsuite/ld-elf/pr21557b.d
new file mode 100644
index 0000000..dc86066
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21557b.d
@@ -0,0 +1,9 @@
+#ld: -shared -z defs --gc-sections
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21557b.s b/ld/testsuite/ld-elf/pr21557b.s
new file mode 100644
index 0000000..d6795e1
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21557b.s
@@ -0,0 +1,8 @@
+        .section        scnfoo,"aw",%progbits
+        .zero 0x10
+
+        .globl  bar
+        .data
+        .type   bar, %object
+bar:
+        .quad   __stop_scnfoo
diff --git a/ld/testsuite/ld-elf/pr21557c.d b/ld/testsuite/ld-elf/pr21557c.d
new file mode 100644
index 0000000..5bb966b
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21557c.d
@@ -0,0 +1,10 @@
+#source: pr21557a.s
+#ld: -shared -z defs --gc-sections -T pr21557.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21557d.d b/ld/testsuite/ld-elf/pr21557d.d
new file mode 100644
index 0000000..7ccd6d4
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21557d.d
@@ -0,0 +1,10 @@
+#source: pr21557b.s
+#ld: -shared -z defs --gc-sections -T pr21557.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
-- 
2.9.4

             reply	other threads:[~2017-06-09 22:05 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-09 22:05 H.J. Lu [this message]
2017-06-10  0:08 ` H.J. Lu

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=20170609220526.GA24413@gmail.com \
    --to=hongjiu.lu@intel.com \
    --cc=binutils@sourceware.org \
    --cc=hjl.tools@gmail.com \
    /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).