This is the mail archive of the binutils@sourceware.org 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]

[PATCH] ELF: Resolve referenced __start_XXX/__stop_XXX symbols


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


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