Discussion:
[PATCH] x86: Set alignment of output SEC_EXCLUDE section to 1
H.J. Lu
2018-11-29 22:57:36 UTC
Permalink
The first pass of one_lang_size_sections_pass doesn't check the
SEC_EXCLUDE bit in input sections. But the excluded input section
alignment will affect vma and lma of the following sections. When the
excluded input section is stripped by strip_excluded_output_sections
later, the subsequent pass of one_lang_size_sections_pass may move dot
of the following section moving backwards, resulting in a warning and
section lma not being set properly which later leads to a "File truncated"
error. To work around it, we set alignment of the output section to
1 if there is only one excluded input section.

bfd/

PR ld/23930
* elfxx-x86.c (_bfd_x86_elf_size_dynamic_sections): Set alignment
of the output section of the excluded input section to 1 if there
is only one excluded input section.

ld/

PR ld/23930
* testsuite/ld-i386/i386.exp: Run pr23930.
* testsuite/ld-i386/pr23930.d: New file.
* testsuite/ld-x86-64/pr23930-32.t: Likewise.
* testsuite/ld-x86-64/pr23930-x32.d: Likewise.
* testsuite/ld-x86-64/pr23930.d: Likewise.
* testsuite/ld-x86-64/pr23930.t: Likewise.
* testsuite/ld-x86-64/pr23930a.s: Likewise.
* testsuite/ld-x86-64/pr23930b.s: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run pr23930 and pr23930-x32.
---
bfd/elfxx-x86.c | 21 ++++++++++++++++++++-
ld/testsuite/ld-i386/i386.exp | 1 +
ld/testsuite/ld-i386/pr23930.d | 11 +++++++++++
ld/testsuite/ld-x86-64/pr23930-32.t | 10 ++++++++++
ld/testsuite/ld-x86-64/pr23930-x32.d | 11 +++++++++++
ld/testsuite/ld-x86-64/pr23930.d | 11 +++++++++++
ld/testsuite/ld-x86-64/pr23930.t | 10 ++++++++++
ld/testsuite/ld-x86-64/pr23930a.s | 7 +++++++
ld/testsuite/ld-x86-64/pr23930b.s | 14 ++++++++++++++
ld/testsuite/ld-x86-64/x86-64.exp | 2 ++
10 files changed, 97 insertions(+), 1 deletion(-)
create mode 100644 ld/testsuite/ld-i386/pr23930.d
create mode 100644 ld/testsuite/ld-x86-64/pr23930-32.t
create mode 100644 ld/testsuite/ld-x86-64/pr23930-x32.d
create mode 100644 ld/testsuite/ld-x86-64/pr23930.d
create mode 100644 ld/testsuite/ld-x86-64/pr23930.t
create mode 100644 ld/testsuite/ld-x86-64/pr23930a.s
create mode 100644 ld/testsuite/ld-x86-64/pr23930b.s

diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 05f5c6a2f9..cff09adff2 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -1268,7 +1268,26 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
function which decides whether anything needs to go
into these sections. */
if (strip_section)
- s->flags |= SEC_EXCLUDE;
+ {
+ s->flags |= SEC_EXCLUDE;
+ /* NB: The first pass of one_lang_size_sections_pass
+ doesn't check the SEC_EXCLUDE bit in input section.
+ But the input SEC_EXCLUDE section alignment will
+ affect vma and lma of the following sections. When
+ the input SEC_EXCLUDE section is stripped by
+ strip_excluded_output_sections later, the subsequent
+ pass of one_lang_size_sections_pass may move dot of
+ the following section moving backwards, resulting in
+ a warning and section lma not being set properly. It
+ later leads to a "File truncated" error. To work
+ around it, we set alignment of the output section to
+ 1 if there is only one input section. */
+ if (s->output_section
+ && s->map_tail.s == NULL
+ && s->output_section->map_tail.s == s
+ && (s->output_section->flags & SEC_KEEP) == 0)
+ s->output_section->alignment_power = 0;
+ }
continue;
}

diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 76577c4fcb..f86a54d27a 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -482,6 +482,7 @@ run_dump_test "pr23486b"
run_dump_test "pr23486c"
run_dump_test "pr23486d"
run_dump_test "pr23854"
+run_dump_test "pr23930"

if { !([istarget "i?86-*-linux*"]
|| [istarget "i?86-*-gnu*"]
diff --git a/ld/testsuite/ld-i386/pr23930.d b/ld/testsuite/ld-i386/pr23930.d
new file mode 100644
index 0000000000..e9da5106eb
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr23930.d
@@ -0,0 +1,11 @@
+#source: ../ld-x86-64/pr23930a.s
+#source: ../ld-x86-64/pr23930b.s
+#as: --32
+#ld: -m elf_i386 -z separate-code -z norelro -T ../ld-x86-64/pr23930-32.t
+#objdump: --disassemble=main
+
+#...
+[a-f0-9]+ <main>:
+[a-f0-9]+: 31 c0 xor %eax,%eax
+[a-f0-9]+: c3 ret
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr23930-32.t b/ld/testsuite/ld-x86-64/pr23930-32.t
new file mode 100644
index 0000000000..29b5309f48
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930-32.t
@@ -0,0 +1,10 @@
+PHDRS {
+ text PT_LOAD;
+}
+
+SECTIONS
+{
+ . = (0x8000000f + ALIGN(0x1000000, 0x1000000));
+ .text : AT(ADDR(.text) - 0x8000000f) {
+ } :text
+}
diff --git a/ld/testsuite/ld-x86-64/pr23930-x32.d b/ld/testsuite/ld-x86-64/pr23930-x32.d
new file mode 100644
index 0000000000..b01d2b961c
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930-x32.d
@@ -0,0 +1,11 @@
+#source: pr23930a.s
+#source: pr23930b.s
+#as: --x32
+#ld: -m elf32_x86_64 -z separate-code -z norelro -T pr23930-32.t
+#objdump: --disassemble=main
+
+#...
+[a-f0-9]+ <main>:
+[a-f0-9]+: 31 c0 xor %eax,%eax
+[a-f0-9]+: c3 retq
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr23930.d b/ld/testsuite/ld-x86-64/pr23930.d
new file mode 100644
index 0000000000..c849b68c45
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930.d
@@ -0,0 +1,11 @@
+#source: pr23930a.s
+#source: pr23930b.s
+#as: --64
+#ld: -m elf_x86_64 -z separate-code -z norelro -T pr23930.t
+#objdump: --disassemble=main
+
+#...
+[a-f0-9]+ <main>:
+[a-f0-9]+: 31 c0 xor %eax,%eax
+[a-f0-9]+: c3 retq
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr23930.t b/ld/testsuite/ld-x86-64/pr23930.t
new file mode 100644
index 0000000000..2255ed3173
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930.t
@@ -0,0 +1,10 @@
+PHDRS {
+ text PT_LOAD;
+}
+
+SECTIONS
+{
+ . = (0xffffffff8000000f + ALIGN(0x1000000, 0x1000000));
+ .text : AT(ADDR(.text) - 0xffffffff8000000f) {
+ } :text
+}
diff --git a/ld/testsuite/ld-x86-64/pr23930a.s b/ld/testsuite/ld-x86-64/pr23930a.s
new file mode 100644
index 0000000000..e1679a9af4
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930a.s
@@ -0,0 +1,7 @@
+ .text
+ .globl other
+ .type other, @function
+other:
+ xorl %eax, %eax
+ ret
+ .size other, .-other
diff --git a/ld/testsuite/ld-x86-64/pr23930b.s b/ld/testsuite/ld-x86-64/pr23930b.s
new file mode 100644
index 0000000000..e4859c7747
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930b.s
@@ -0,0 +1,14 @@
+ .text
+ .globl orig
+ .type orig, @function
+orig:
+ xorl %eax, %eax
+ ret
+ .size orig, .-orig
+ .section .text.startup,"ax",@progbits
+ .globl main
+ .type main, @function
+main:
+ xorl %eax, %eax
+ ret
+ .size main, .-main
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 8e5348dfea..b51ad7cebc 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -422,6 +422,8 @@ run_dump_test "pr23486c-x32"
run_dump_test "pr23486d"
run_dump_test "pr23486d-x32"
run_dump_test "pr23854"
+run_dump_test "pr23930"
+run_dump_test "pr23930-x32"

if { ![istarget "x86_64-*-linux*"] && ![istarget "x86_64-*-nacl*"]} {
return
--
2.19.2
Jan Beulich
2018-11-30 07:43:36 UTC
Permalink
Post by H.J. Lu
The first pass of one_lang_size_sections_pass doesn't check the
SEC_EXCLUDE bit in input sections. But the excluded input section
alignment will affect vma and lma of the following sections. When the
excluded input section is stripped by strip_excluded_output_sections
later, the subsequent pass of one_lang_size_sections_pass may move dot
of the following section moving backwards, resulting in a warning and
section lma not being set properly which later leads to a "File truncated"
error. To work around it, we set alignment of the output section to
1 if there is only one excluded input section.
Why the special treatment of a single excluded input section?
Doesn't the same apply if multiple excluded input ones contribute
to the same output one? I.e. the treatment would need to occur
when an output section consists of only excluded input ones?

Even in the mixed case I would then wonder whether the
behavior is correct, but I could agree that such a case would
better be prevented by the programmer in the first place.

Jan
H.J. Lu
2018-11-30 13:47:56 UTC
Permalink
Post by Jan Beulich
Post by H.J. Lu
The first pass of one_lang_size_sections_pass doesn't check the
SEC_EXCLUDE bit in input sections. But the excluded input section
alignment will affect vma and lma of the following sections. When the
excluded input section is stripped by strip_excluded_output_sections
later, the subsequent pass of one_lang_size_sections_pass may move dot
of the following section moving backwards, resulting in a warning and
section lma not being set properly which later leads to a "File truncated"
error. To work around it, we set alignment of the output section to
1 if there is only one excluded input section.
Why the special treatment of a single excluded input section?
Doesn't the same apply if multiple excluded input ones contribute
to the same output one? I.e. the treatment would need to occur
when an output section consists of only excluded input ones?
Even in the mixed case I would then wonder whether the
behavior is correct, but I could agree that such a case would
better be prevented by the programmer in the first place.
I will take Alan's approach.

H.J.
Alan Modra
2018-11-30 09:31:48 UTC
Permalink
Post by H.J. Lu
To work around it, we set alignment of the output section to
1 if there is only one excluded input section.
This is a tricky problem to solve, and I suspect what you're doing
here is not correct in general, even for a single input section. For
example, what happens if the output section statement specifies
alignment?

I've faced something similar before on ppc64 with stub sections, and
the solution I found was to create the section with minimal alignment,
then increase to the desired alignment when the section is found to be
non-empty. That idea might work for you too.
--
Alan Modra
Australia Development Lab, IBM
H.J. Lu
2018-11-30 13:55:43 UTC
Permalink
Post by Alan Modra
Post by H.J. Lu
To work around it, we set alignment of the output section to
1 if there is only one excluded input section.
This is a tricky problem to solve, and I suspect what you're doing
here is not correct in general, even for a single input section. For
example, what happens if the output section statement specifies
alignment?
I've faced something similar before on ppc64 with stub sections, and
the solution I found was to create the section with minimal alignment,
then increase to the desired alignment when the section is found to be
non-empty. That idea might work for you too.
Like this.

Thanks.

H.J.
---
From a58108461c4e9710197c12f29cfa6c94b5db240c Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <***@gmail.com>
Date: Wed, 28 Nov 2018 15:29:42 -0800
Subject: [PATCH] x86: Delay setting the iplt section alignment

Delay setting its alignment until we know it is non-empty. Otherwise an
empty iplt section may change vma and lma of the following sections, which
triggers moving dot of the following section backwards, resulting in a
warning and section lma not being set properly. It later leads to a
"File truncated" error.

bfd/

PR ld/23930
* elfxx-x86.c (_bfd_x86_elf_size_dynamic_sections): Update
the iplt section alignment if it is non-empty.
(_bfd_x86_elf_link_setup_gnu_properties): Delay setting the iplt
section alignment.

ld/

PR ld/23930
* testsuite/ld-i386/i386.exp: Run pr23930.
* testsuite/ld-i386/pr23930.d: New file.
* testsuite/ld-x86-64/pr23930-32.t: Likewise.
* testsuite/ld-x86-64/pr23930-x32.d: Likewise.
* testsuite/ld-x86-64/pr23930.d: Likewise.
* testsuite/ld-x86-64/pr23930.t: Likewise.
* testsuite/ld-x86-64/pr23930a.s: Likewise.
* testsuite/ld-x86-64/pr23930b.s: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run pr23930 and pr23930-x32.
---
bfd/elfxx-x86.c | 22 +++++++++++++++++++---
ld/testsuite/ld-i386/i386.exp | 1 +
ld/testsuite/ld-i386/pr23930.d | 11 +++++++++++
ld/testsuite/ld-x86-64/pr23930-32.t | 10 ++++++++++
ld/testsuite/ld-x86-64/pr23930-x32.d | 11 +++++++++++
ld/testsuite/ld-x86-64/pr23930.d | 11 +++++++++++
ld/testsuite/ld-x86-64/pr23930.t | 10 ++++++++++
ld/testsuite/ld-x86-64/pr23930a.s | 7 +++++++
ld/testsuite/ld-x86-64/pr23930b.s | 14 ++++++++++++++
ld/testsuite/ld-x86-64/x86-64.exp | 2 ++
10 files changed, 96 insertions(+), 3 deletions(-)
create mode 100644 ld/testsuite/ld-i386/pr23930.d
create mode 100644 ld/testsuite/ld-x86-64/pr23930-32.t
create mode 100644 ld/testsuite/ld-x86-64/pr23930-x32.d
create mode 100644 ld/testsuite/ld-x86-64/pr23930.d
create mode 100644 ld/testsuite/ld-x86-64/pr23930.t
create mode 100644 ld/testsuite/ld-x86-64/pr23930a.s
create mode 100644 ld/testsuite/ld-x86-64/pr23930b.s

diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 05f5c6a2f9..a6f714d754 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -965,6 +965,7 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
bfd *ibfd;
const struct elf_backend_data *bed
= get_elf_backend_data (output_bfd);
+ unsigned int plt_alignment;

htab = elf_x86_hash_table (info, bed->target_id);
if (htab == NULL)
@@ -973,6 +974,8 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
if (dynobj == NULL)
abort ();

+ plt_alignment = bfd_log2 (htab->plt.plt_entry_size);
+
/* Set up .got offsets for local syms, and space for local dynamic
relocs. */
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
@@ -1275,6 +1278,13 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
if ((s->flags & SEC_HAS_CONTENTS) == 0)
continue;

+ /* NB: Initially, the iplt section has minimal alignment to
+ avoid moving dot of the following section backwards when
+ it is empty. Update its section alignment now since it
+ is non-empty. */
+ if (s == htab->elf.iplt)
+ bfd_set_section_alignment (s->owner, s, plt_alignment);
+
/* Allocate memory for the section contents. We use bfd_zalloc
here in case unused entries are not reclaimed before the
section's contents are written out. This should not happen,
@@ -2910,11 +2920,17 @@ error_alignment:
if (normal_target)
{
/* The .iplt section is used for IFUNC symbols in static
- executables. */
+ executables.
+
+ NB: Delay setting its alignment until we know it is non-empty.
+ Otherwise an empty iplt section may change vma and lma of the
+ following sections, which triggers moving dot of the following
+ section backwards, resulting in a warning and section lma not
+ being set properly. It later leads to a "File truncated"
+ error. */
sec = htab->elf.iplt;
if (sec != NULL
- && !bfd_set_section_alignment (sec->owner, sec,
- plt_alignment))
+ && !bfd_set_section_alignment (sec->owner, sec, 0))
goto error_alignment;
}

diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 76577c4fcb..f86a54d27a 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -482,6 +482,7 @@ run_dump_test "pr23486b"
run_dump_test "pr23486c"
run_dump_test "pr23486d"
run_dump_test "pr23854"
+run_dump_test "pr23930"

if { !([istarget "i?86-*-linux*"]
|| [istarget "i?86-*-gnu*"]
diff --git a/ld/testsuite/ld-i386/pr23930.d b/ld/testsuite/ld-i386/pr23930.d
new file mode 100644
index 0000000000..e9da5106eb
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr23930.d
@@ -0,0 +1,11 @@
+#source: ../ld-x86-64/pr23930a.s
+#source: ../ld-x86-64/pr23930b.s
+#as: --32
+#ld: -m elf_i386 -z separate-code -z norelro -T ../ld-x86-64/pr23930-32.t
+#objdump: --disassemble=main
+
+#...
+[a-f0-9]+ <main>:
+[a-f0-9]+: 31 c0 xor %eax,%eax
+[a-f0-9]+: c3 ret
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr23930-32.t b/ld/testsuite/ld-x86-64/pr23930-32.t
new file mode 100644
index 0000000000..29b5309f48
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930-32.t
@@ -0,0 +1,10 @@
+PHDRS {
+ text PT_LOAD;
+}
+
+SECTIONS
+{
+ . = (0x8000000f + ALIGN(0x1000000, 0x1000000));
+ .text : AT(ADDR(.text) - 0x8000000f) {
+ } :text
+}
diff --git a/ld/testsuite/ld-x86-64/pr23930-x32.d b/ld/testsuite/ld-x86-64/pr23930-x32.d
new file mode 100644
index 0000000000..b01d2b961c
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930-x32.d
@@ -0,0 +1,11 @@
+#source: pr23930a.s
+#source: pr23930b.s
+#as: --x32
+#ld: -m elf32_x86_64 -z separate-code -z norelro -T pr23930-32.t
+#objdump: --disassemble=main
+
+#...
+[a-f0-9]+ <main>:
+[a-f0-9]+: 31 c0 xor %eax,%eax
+[a-f0-9]+: c3 retq
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr23930.d b/ld/testsuite/ld-x86-64/pr23930.d
new file mode 100644
index 0000000000..c849b68c45
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930.d
@@ -0,0 +1,11 @@
+#source: pr23930a.s
+#source: pr23930b.s
+#as: --64
+#ld: -m elf_x86_64 -z separate-code -z norelro -T pr23930.t
+#objdump: --disassemble=main
+
+#...
+[a-f0-9]+ <main>:
+[a-f0-9]+: 31 c0 xor %eax,%eax
+[a-f0-9]+: c3 retq
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr23930.t b/ld/testsuite/ld-x86-64/pr23930.t
new file mode 100644
index 0000000000..2255ed3173
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930.t
@@ -0,0 +1,10 @@
+PHDRS {
+ text PT_LOAD;
+}
+
+SECTIONS
+{
+ . = (0xffffffff8000000f + ALIGN(0x1000000, 0x1000000));
+ .text : AT(ADDR(.text) - 0xffffffff8000000f) {
+ } :text
+}
diff --git a/ld/testsuite/ld-x86-64/pr23930a.s b/ld/testsuite/ld-x86-64/pr23930a.s
new file mode 100644
index 0000000000..e1679a9af4
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930a.s
@@ -0,0 +1,7 @@
+ .text
+ .globl other
+ .type other, @function
+other:
+ xorl %eax, %eax
+ ret
+ .size other, .-other
diff --git a/ld/testsuite/ld-x86-64/pr23930b.s b/ld/testsuite/ld-x86-64/pr23930b.s
new file mode 100644
index 0000000000..e4859c7747
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930b.s
@@ -0,0 +1,14 @@
+ .text
+ .globl orig
+ .type orig, @function
+orig:
+ xorl %eax, %eax
+ ret
+ .size orig, .-orig
+ .section .text.startup,"ax",@progbits
+ .globl main
+ .type main, @function
+main:
+ xorl %eax, %eax
+ ret
+ .size main, .-main
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 8e5348dfea..b51ad7cebc 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -422,6 +422,8 @@ run_dump_test "pr23486c-x32"
run_dump_test "pr23486d"
run_dump_test "pr23486d-x32"
run_dump_test "pr23854"
+run_dump_test "pr23930"
+run_dump_test "pr23930-x32"

if { ![istarget "x86_64-*-linux*"] && ![istarget "x86_64-*-nacl*"]} {
return
--
2.19.2
H.J. Lu
2018-12-01 14:38:21 UTC
Permalink
Post by H.J. Lu
Post by Alan Modra
Post by H.J. Lu
To work around it, we set alignment of the output section to
1 if there is only one excluded input section.
This is a tricky problem to solve, and I suspect what you're doing
here is not correct in general, even for a single input section. For
example, what happens if the output section statement specifies
alignment?
I've faced something similar before on ppc64 with stub sections, and
the solution I found was to create the section with minimal alignment,
then increase to the desired alignment when the section is found to be
non-empty. That idea might work for you too.
Like this.
Thanks.
H.J.
---
Post by Alan Modra
From a58108461c4e9710197c12f29cfa6c94b5db240c Mon Sep 17 00:00:00 2001
Date: Wed, 28 Nov 2018 15:29:42 -0800
Subject: [PATCH] x86: Delay setting the iplt section alignment
Delay setting its alignment until we know it is non-empty. Otherwise an
empty iplt section may change vma and lma of the following sections, which
triggers moving dot of the following section backwards, resulting in a
warning and section lma not being set properly. It later leads to a
"File truncated" error.
bfd/
PR ld/23930
* elfxx-x86.c (_bfd_x86_elf_size_dynamic_sections): Update
the iplt section alignment if it is non-empty.
(_bfd_x86_elf_link_setup_gnu_properties): Delay setting the iplt
section alignment.
This is the patch I am checking in.

H.J.
---
From b44ee3a8cf21294eeb079ffbada7eeb559a9c6b4 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <***@gmail.com>
Date: Sat, 1 Dec 2018 05:42:33 -0800
Subject: [PATCH] x86: Delay setting the iplt section alignment

Delay setting its alignment until we know it is non-empty. Otherwise an
empty iplt section may change vma and lma of the following sections, which
triggers moving dot of the following section backwards, resulting in a
warning and section lma not being set properly. It later leads to a
"File truncated" error.

bfd/

PR ld/23930
* elfxx-x86.c (_bfd_x86_elf_size_dynamic_sections): Update
the iplt section alignment if it is non-empty.
(_bfd_x86_elf_link_setup_gnu_properties): Set plt.iplt_alignment
and delay setting the iplt section alignment.
* elfxx-x86.h (elf_x86_plt_layout): Add iplt_alignment.

ld/

PR ld/23930
* testsuite/ld-i386/i386.exp: Run pr23930.
* testsuite/ld-i386/pr23930.d: New file.
* testsuite/ld-x86-64/pr23930-32.t: Likewise.
* testsuite/ld-x86-64/pr23930-x32.d: Likewise.
* testsuite/ld-x86-64/pr23930.d: Likewise.
* testsuite/ld-x86-64/pr23930.t: Likewise.
* testsuite/ld-x86-64/pr23930a.s: Likewise.
* testsuite/ld-x86-64/pr23930b.s: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run pr23930 and pr23930-x32.
---
bfd/ChangeLog | 9 +++++++++
bfd/elfxx-x86.c | 30 +++++++++++++++++++++-------
bfd/elfxx-x86.h | 3 +++
ld/ChangeLog | 13 ++++++++++++
ld/testsuite/ld-i386/i386.exp | 1 +
ld/testsuite/ld-i386/pr23930.d | 11 ++++++++++
ld/testsuite/ld-x86-64/pr23930-32.t | 10 ++++++++++
ld/testsuite/ld-x86-64/pr23930-x32.d | 11 ++++++++++
ld/testsuite/ld-x86-64/pr23930.d | 11 ++++++++++
ld/testsuite/ld-x86-64/pr23930.t | 10 ++++++++++
ld/testsuite/ld-x86-64/pr23930a.s | 7 +++++++
ld/testsuite/ld-x86-64/pr23930b.s | 14 +++++++++++++
ld/testsuite/ld-x86-64/x86-64.exp | 2 ++
13 files changed, 125 insertions(+), 7 deletions(-)
create mode 100644 ld/testsuite/ld-i386/pr23930.d
create mode 100644 ld/testsuite/ld-x86-64/pr23930-32.t
create mode 100644 ld/testsuite/ld-x86-64/pr23930-x32.d
create mode 100644 ld/testsuite/ld-x86-64/pr23930.d
create mode 100644 ld/testsuite/ld-x86-64/pr23930.t
create mode 100644 ld/testsuite/ld-x86-64/pr23930a.s
create mode 100644 ld/testsuite/ld-x86-64/pr23930b.s

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e0eb155988..3210b0c380 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,12 @@
+2018-12-01 H.J. Lu <***@intel.com>
+
+ PR ld/23930
+ * elfxx-x86.c (_bfd_x86_elf_size_dynamic_sections): Update
+ the iplt section alignment if it is non-empty.
+ (_bfd_x86_elf_link_setup_gnu_properties): Set plt.iplt_alignment
+ and delay setting the iplt section alignment.
+ * elfxx-x86.h (elf_x86_plt_layout): Add iplt_alignment.
+
2018-11-30 Nick Clifton <***@redhat.com>

PR 23942
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 05f5c6a2f9..40aac664f4 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -1275,6 +1275,14 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
if ((s->flags & SEC_HAS_CONTENTS) == 0)
continue;

+ /* NB: Initially, the iplt section has minimal alignment to
+ avoid moving dot of the following section backwards when
+ it is empty. Update its section alignment now since it
+ is non-empty. */
+ if (s == htab->elf.iplt)
+ bfd_set_section_alignment (s->owner, s,
+ htab->plt.iplt_alignment);
+
/* Allocate memory for the section contents. We use bfd_zalloc
here in case unused entries are not reclaimed before the
section's contents are written out. This should not happen,
@@ -2907,15 +2915,23 @@ error_alignment:
}
}

- if (normal_target)
+ /* The .iplt section is used for IFUNC symbols in static
+ executables. */
+ sec = htab->elf.iplt;
+ if (sec != NULL)
{
- /* The .iplt section is used for IFUNC symbols in static
- executables. */
- sec = htab->elf.iplt;
- if (sec != NULL
- && !bfd_set_section_alignment (sec->owner, sec,
- plt_alignment))
+ /* NB: Delay setting its alignment until we know it is non-empty.
+ Otherwise an empty iplt section may change vma and lma of the
+ following sections, which triggers moving dot of the following
+ section backwards, resulting in a warning and section lma not
+ being set properly. It later leads to a "File truncated"
+ error. */
+ if (!bfd_set_section_alignment (sec->owner, sec, 0))
goto error_alignment;
+
+ htab->plt.iplt_alignment = (normal_target
+ ? plt_alignment
+ : bed->plt_alignment);
}

return pbfd;
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index 964843822e..d153623d3e 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -389,6 +389,9 @@ struct elf_x86_plt_layout
This is only used for x86-64. */
unsigned int plt_got_insn_size;

+ /* Alignment of the .iplt section. */
+ unsigned int iplt_alignment;
+
/* .eh_frame covering the .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
diff --git a/ld/ChangeLog b/ld/ChangeLog
index e203edcf2d..80fd06c1ca 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,16 @@
+2018-12-01 H.J. Lu <***@intel.com>
+
+ PR ld/23930
+ * testsuite/ld-i386/i386.exp: Run pr23930.
+ * testsuite/ld-i386/pr23930.d: New file.
+ * testsuite/ld-x86-64/pr23930-32.t: Likewise.
+ * testsuite/ld-x86-64/pr23930-x32.d: Likewise.
+ * testsuite/ld-x86-64/pr23930.d: Likewise.
+ * testsuite/ld-x86-64/pr23930.t: Likewise.
+ * testsuite/ld-x86-64/pr23930a.s: Likewise.
+ * testsuite/ld-x86-64/pr23930b.s: Likewise.
+ * testsuite/ld-x86-64/x86-64.exp: Run pr23930 and pr23930-x32.
+---
2018-11-30 Alan Modra <***@gmail.com>

* testsuite/ld-powerpc/pr23937.d,
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 76577c4fcb..f86a54d27a 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -482,6 +482,7 @@ run_dump_test "pr23486b"
run_dump_test "pr23486c"
run_dump_test "pr23486d"
run_dump_test "pr23854"
+run_dump_test "pr23930"

if { !([istarget "i?86-*-linux*"]
|| [istarget "i?86-*-gnu*"]
diff --git a/ld/testsuite/ld-i386/pr23930.d b/ld/testsuite/ld-i386/pr23930.d
new file mode 100644
index 0000000000..e9da5106eb
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr23930.d
@@ -0,0 +1,11 @@
+#source: ../ld-x86-64/pr23930a.s
+#source: ../ld-x86-64/pr23930b.s
+#as: --32
+#ld: -m elf_i386 -z separate-code -z norelro -T ../ld-x86-64/pr23930-32.t
+#objdump: --disassemble=main
+
+#...
+[a-f0-9]+ <main>:
+[a-f0-9]+: 31 c0 xor %eax,%eax
+[a-f0-9]+: c3 ret
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr23930-32.t b/ld/testsuite/ld-x86-64/pr23930-32.t
new file mode 100644
index 0000000000..29b5309f48
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930-32.t
@@ -0,0 +1,10 @@
+PHDRS {
+ text PT_LOAD;
+}
+
+SECTIONS
+{
+ . = (0x8000000f + ALIGN(0x1000000, 0x1000000));
+ .text : AT(ADDR(.text) - 0x8000000f) {
+ } :text
+}
diff --git a/ld/testsuite/ld-x86-64/pr23930-x32.d b/ld/testsuite/ld-x86-64/pr23930-x32.d
new file mode 100644
index 0000000000..b01d2b961c
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930-x32.d
@@ -0,0 +1,11 @@
+#source: pr23930a.s
+#source: pr23930b.s
+#as: --x32
+#ld: -m elf32_x86_64 -z separate-code -z norelro -T pr23930-32.t
+#objdump: --disassemble=main
+
+#...
+[a-f0-9]+ <main>:
+[a-f0-9]+: 31 c0 xor %eax,%eax
+[a-f0-9]+: c3 retq
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr23930.d b/ld/testsuite/ld-x86-64/pr23930.d
new file mode 100644
index 0000000000..c849b68c45
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930.d
@@ -0,0 +1,11 @@
+#source: pr23930a.s
+#source: pr23930b.s
+#as: --64
+#ld: -m elf_x86_64 -z separate-code -z norelro -T pr23930.t
+#objdump: --disassemble=main
+
+#...
+[a-f0-9]+ <main>:
+[a-f0-9]+: 31 c0 xor %eax,%eax
+[a-f0-9]+: c3 retq
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr23930.t b/ld/testsuite/ld-x86-64/pr23930.t
new file mode 100644
index 0000000000..2255ed3173
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930.t
@@ -0,0 +1,10 @@
+PHDRS {
+ text PT_LOAD;
+}
+
+SECTIONS
+{
+ . = (0xffffffff8000000f + ALIGN(0x1000000, 0x1000000));
+ .text : AT(ADDR(.text) - 0xffffffff8000000f) {
+ } :text
+}
diff --git a/ld/testsuite/ld-x86-64/pr23930a.s b/ld/testsuite/ld-x86-64/pr23930a.s
new file mode 100644
index 0000000000..e1679a9af4
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930a.s
@@ -0,0 +1,7 @@
+ .text
+ .globl other
+ .type other, @function
+other:
+ xorl %eax, %eax
+ ret
+ .size other, .-other
diff --git a/ld/testsuite/ld-x86-64/pr23930b.s b/ld/testsuite/ld-x86-64/pr23930b.s
new file mode 100644
index 0000000000..e4859c7747
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr23930b.s
@@ -0,0 +1,14 @@
+ .text
+ .globl orig
+ .type orig, @function
+orig:
+ xorl %eax, %eax
+ ret
+ .size orig, .-orig
+ .section .text.startup,"ax",@progbits
+ .globl main
+ .type main, @function
+main:
+ xorl %eax, %eax
+ ret
+ .size main, .-main
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 8e5348dfea..b51ad7cebc 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -422,6 +422,8 @@ run_dump_test "pr23486c-x32"
run_dump_test "pr23486d"
run_dump_test "pr23486d-x32"
run_dump_test "pr23854"
+run_dump_test "pr23930"
+run_dump_test "pr23930-x32"

if { ![istarget "x86_64-*-linux*"] && ![istarget "x86_64-*-nacl*"]} {
return
--
2.19.2
Loading...