This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] ELF: Resolve referenced __start_XXX/__stop_XXX symbols
- From: "H.J. Lu" <hongjiu dot lu at intel dot com>
- To: binutils at sourceware dot org
- Date: Fri, 9 Jun 2017 15:05:26 -0700
- Subject: [PATCH] ELF: Resolve referenced __start_XXX/__stop_XXX symbols
- Authentication-results: sourceware.org; auth=none
- Reply-to: "H.J. Lu" <hjl dot tools at gmail dot com>
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