The handling of various sections in the VDSO linker script
looks pretty haphazard. This patch series cleans it up in
these regards:
- improve the coding style
- remove superfluous sections
- issue a linker error if a section is encountered which
is known not to work
- check that the .got section is empty, except for the
three entries defined by the ABI
- discard sections which are not useful to user-space
Petr Tesarik (8):
x86: Adjust the coding style of vdso-layout.lds.S
x86: Remove .sdata from the vDSO linker script
x86: Remove .dynbss from the vDSO linker script
x86: add .broken section to the vDSO linker script
x86: mark altinstr-related sections in vDSO as broken
x86: mark some standard sections as broken in a vDSO
x86: check the size of GOT in vDSO
x86: remove unneeded section from the vDSO
arch/x86/vdso/Makefile | 5 +-
arch/x86/vdso/vdso-layout.lds.S | 144 +++++++++++++++++++++++++++++++-------
2 files changed, 120 insertions(+), 29 deletions(-)
This section should not contain anything unless the vDSO is
broken. It is intended to hold sections which are known not
to work correctly inside a vDSO.
If such a "broken" section is found at link-time, the linker
issues an error with a hint how to find out more.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 0386c92..23da4a1 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -70,8 +70,30 @@ SECTIONS
.text : {
*(.text* .gnu.linkonce.t.*)
} :text =0x90909090
+
+ /* Some sections require some additional work from the dynamic
+ * linker to work properly. However, there is no dynamic-link
+ * pass for the vDSO, so these sections will not work.
+ * Put them into a special section and raise a link-time error
+ * if they get used by accident.
+ */
+ .broken : {
+ }
}
+/* This assert is triggered if the linker finds a section in one of its
+ * input files which is known not to work inside a vDSO.
+ *
+ * To see which is the offending sections, you may:
+ * a. use objdump -h on the object files which make up the vDSO, or
+ * b. add -Wl,-M to VDSO_LDFLAGS and examine the linker map.
+ *
+ * See individual comments in the definition of the .broken section
+ * above for more information on why any given section is considered
+ * "broken".
+ */
+ASSERT(!SIZEOF(.broken), "The vdso linker script found a section that is bad. See vdso-layout.lds.S for details.");
+
/*
* Very old versions of ld do not recognize this name token; use the constant.
*/
--
1.6.0.2
Some standard sections are not useful in the resulting binary.
.gnu.warning.* is only interesting for the linker.
.note.* may be discarded, except:
.note.Linux which contains the Linux version
.note.gnu.build-id which may be useful for identifying
the vDSO
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index ea9ef58..93e0b40 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -31,7 +31,8 @@ SECTIONS
}
.note : {
- *(.note.*)
+ *(.note.Linux)
+ *(.note.gnu.build-id)
} :text :note
.eh_frame_hdr : {
@@ -98,6 +99,12 @@ SECTIONS
*(.altinstructions)
*(.altinstr_replacement)
}
+
+ /* These sections are not useful to user-space */
+ /DISCARD/ : {
+ *(.gnu.warning.*)
+ *(.note.*)
+ }
}
/* This assert is triggered if the linker finds a section in one of its
--
1.6.0.2
There are several reasons why this does not work for the vDSO.
1. The alt_instr records are not processed by anybody.
The .altinstruction sections end up in the vDSO binary, which
is then incorporated verbatim inside a completely different
section, so it is not seen by the main kernel.
There is no code to interpret them during vDSO setup either.
2. The pointers in the alt_instr records are wrong.
They point to the instructions and replacements at the prelinked
addresses, but that's neither where the vDSO blob is located at
startup, nor where it is copied to by the vDSO setup.
The .altinstr_replacement section is not broken per se, but it is
useless dead code without the accompanying .alt_instr section.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 12 +++++-------
1 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 23da4a1..2f0830f 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -54,13 +54,6 @@ SECTIONS
*(.bss* .gnu.linkonce.b.*)
}
- .altinstructions : {
- *(.altinstructions)
- }
- .altinstr_replacement : {
- *(.altinstr_replacement)
- }
-
/*
* Align the actual code well away from the non-instruction data.
* This is the best thing for the I-cache.
@@ -78,6 +71,11 @@ SECTIONS
* if they get used by accident.
*/
.broken : {
+ /* The vDSO setup code does not handle alternative
+ * instructions.
+ */
+ *(.altinstructions)
+ *(.altinstr_replacement)
}
}
--
1.6.0.2
As far as I can see, the .dynbss section does not make any sense
and cannot even appear in a shared library.
Remove it.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 11 ++++-------
1 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index af3fa61..0386c92 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -46,15 +46,12 @@ SECTIONS
} :text :dynamic
.rodata : {
- *(.rodata*)
+ *(.rodata* .gnu.linkonce.r.*)
} :text
.data : {
- *(.data*)
+ *(.data* .gnu.linkonce.d.*)
*(.got.plt) *(.got)
- *(.gnu.linkonce.d.*)
- *(.bss*)
- *(.dynbss*)
- *(.gnu.linkonce.b.*)
+ *(.bss* .gnu.linkonce.b.*)
}
.altinstructions : {
@@ -71,7 +68,7 @@ SECTIONS
. = ALIGN(0x100);
.text : {
- *(.text*)
+ *(.text* .gnu.linkonce.t.*)
} :text =0x90909090
}
--
1.6.0.2
There is no .sdata section on either i386 or x86_64.
The existence of this line probably dates back to the (long abandoned)
idea that x86_64 would have .sdata for "small" data and .data for large
data. However, the final ABI has .data for "normal" data and .ldata
for large data, so this line is no longer pertinent.
---
arch/x86/vdso/vdso-layout.lds.S | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 917df03..af3fa61 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -50,7 +50,6 @@ SECTIONS
} :text
.data : {
*(.data*)
- *(.sdata*)
*(.got.plt) *(.got)
*(.gnu.linkonce.d.*)
*(.bss*)
--
1.6.0.2
Some standard sections can't work in a vDSO. Although most of them
are not very likely to ever appear there, it doesn't hurt to list
them as a precaution.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 2f0830f..0da3db0 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -71,6 +71,25 @@ SECTIONS
* if they get used by accident.
*/
.broken : {
+ /* Code in the Procedure Linkage Table will segfault */
+ *(.plt)
+
+ /* Relocation will not be done, so any pointers will
+ * still point to the prelinked address, which is wrong
+ */
+ *(.data.rel.ro*)
+ *(.gnu.linkonce.d.rel.ro.*)
+
+ /* Initialization/termination won't work this way */
+ *(.init) *(.fini)
+ *(.preinit_array) *(.init_array*)
+ *(.fini_array*)
+
+ /* Thread-local storage cannot be defined like this */
+ *(.tdata .tdata.* .gnu.linkonce.td.*)
+ *(.tbss .tbss.* .gnu.linkonce.tb.*)
+ *(.tcommon)
+
/* The vDSO setup code does not handle alternative
* instructions.
*/
--
1.6.0.2
The style we try to introduce for .lds files in
arch/$ARCH/kernel/vmlinux.lds.S is much more C-like.
Use the same style in the vDSO linker script to get a consistent
style in linker scripts.
Credits to Sam Ravnborg for suggesting this change.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 76 +++++++++++++++++++++++++++------------
1 files changed, 53 insertions(+), 23 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 634a2cf..917df03 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -8,34 +8,62 @@ SECTIONS
{
. = VDSO_PRELINK + SIZEOF_HEADERS;
- .hash : { *(.hash) } :text
- .gnu.hash : { *(.gnu.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
+ .hash : {
+ *(.hash)
+ } :text
+ .gnu.hash : {
+ *(.gnu.hash)
+ }
+ .dynsym : {
+ *(.dynsym)
+ }
+ .dynstr : {
+ *(.dynstr)
+ }
+ .gnu.version : {
+ *(.gnu.version)
+ }
+ .gnu.version_d : {
+ *(.gnu.version_d)
+ }
+ .gnu.version_r : {
+ *(.gnu.version_r)
+ }
- .note : { *(.note.*) } :text :note
+ .note : {
+ *(.note.*)
+ } :text :note
- .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
- .eh_frame : { KEEP (*(.eh_frame)) } :text
+ .eh_frame_hdr : {
+ *(.eh_frame_hdr)
+ } :text :eh_frame_hdr
+ .eh_frame : {
+ KEEP (*(.eh_frame))
+ } :text
- .dynamic : { *(.dynamic) } :text :dynamic
+ .dynamic : {
+ *(.dynamic)
+ } :text :dynamic
- .rodata : { *(.rodata*) } :text
- .data : {
- *(.data*)
- *(.sdata*)
- *(.got.plt) *(.got)
- *(.gnu.linkonce.d.*)
- *(.bss*)
- *(.dynbss*)
- *(.gnu.linkonce.b.*)
+ .rodata : {
+ *(.rodata*)
+ } :text
+ .data : {
+ *(.data*)
+ *(.sdata*)
+ *(.got.plt) *(.got)
+ *(.gnu.linkonce.d.*)
+ *(.bss*)
+ *(.dynbss*)
+ *(.gnu.linkonce.b.*)
}
- .altinstructions : { *(.altinstructions) }
- .altinstr_replacement : { *(.altinstr_replacement) }
+ .altinstructions : {
+ *(.altinstructions)
+ }
+ .altinstr_replacement : {
+ *(.altinstr_replacement)
+ }
/*
* Align the actual code well away from the non-instruction data.
@@ -43,7 +71,9 @@ SECTIONS
*/
. = ALIGN(0x100);
- .text : { *(.text*) } :text =0x90909090
+ .text : {
+ *(.text*)
+ } :text =0x90909090
}
/*
--
1.6.0.2
There should be no real entries in the GOT, because they are basically
pointers to dynamic symbols, and that will not work correctly without
a real dynamic linker for the vDSO.
However, the ABI pre-defines three entries in the GOT which are always
present, so the GOT section is never completely empty. We can check
that there are no extra entries beyond these three.
To make it work:
- move the GOT into a separate section
- check the size of that section
- pass -m32 or -m64 to the pre-processor to get the correct
definition of __SIZEOF_POINTER__
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/Makefile | 5 +++--
arch/x86/vdso/vdso-layout.lds.S | 20 +++++++++++++++++++-
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
index 16a9020..8c7f06a 100644
--- a/arch/x86/vdso/Makefile
+++ b/arch/x86/vdso/Makefile
@@ -23,7 +23,8 @@ $(obj)/vdso.o: $(obj)/vdso.so
targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
-export CPPFLAGS_vdso.lds += -P -C
+vdso-cppflags = -P -C
+export CPPFLAGS_vdso.lds += -m64 $(vdso-cppflags)
VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \
-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
@@ -68,7 +69,7 @@ vdso32.so-$(VDSO32-y) += sysenter
vdso32-images = $(vdso32.so-y:%=vdso32-%.so)
-CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
+CPPFLAGS_vdso32.lds = -m32 $(vdso-cppflags)
VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1
# This makes sure the $(obj) subdirectory exists even though vdso32/
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 0da3db0..ea9ef58 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -44,13 +44,15 @@ SECTIONS
.dynamic : {
*(.dynamic)
} :text :dynamic
+ .got : {
+ *(.got.plt) *(.got)
+ } :text
.rodata : {
*(.rodata* .gnu.linkonce.r.*)
} :text
.data : {
*(.data* .gnu.linkonce.d.*)
- *(.got.plt) *(.got)
*(.bss* .gnu.linkonce.b.*)
}
@@ -111,6 +113,22 @@ SECTIONS
*/
ASSERT(!SIZEOF(.broken), "The vdso linker script found a section that is bad. See vdso-layout.lds.S for details.");
+/* This assert is triggered if the resulting GOT is larger than the
+ * minimum defined by the ABI, i.e. there is some actual use of the
+ * GOT.
+ *
+ * To find the offending symbols you may:
+ * 1. temporarily disable this check
+ * 2. examine the dynamic relocations of the resulting vDSO with
+ * objdump -R
+ *
+ * To find the places where the symbols were used, you may:
+ * 1. add -Wl,--emit-relocs to VDSO_LDFLAGS
+ * 2. run objdump -r on the resulting vDSO and look for all
+ * GOT-type relocations.
+ */
+ASSERT(SIZEOF(.got) == 3*__SIZEOF_POINTER__, "The vdso linker script found a wrong reference to an external object. See vdso-layout.lds.S for details.");
+
/*
* Very old versions of ld do not recognize this name token; use the constant.
*/
--
1.6.0.2
Petr Tesarik píše v Pá 12. 06. 2009 v 15:25 +0200:
> As far as I can see, the .dynbss section does not make any sense
> and cannot even appear in a shared library.
>
> Remove it.
Argh, this commit was wrong. But it changes the context for some of the
following patches. :/ I'll just send the whole patch series again.
Sorry.
Petr Tesarik
> Signed-off-by: Petr Tesarik <[email protected]>
> ---
> arch/x86/vdso/vdso-layout.lds.S | 11 ++++-------
> 1 files changed, 4 insertions(+), 7 deletions(-)
>
> diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
> index af3fa61..0386c92 100644
> --- a/arch/x86/vdso/vdso-layout.lds.S
> +++ b/arch/x86/vdso/vdso-layout.lds.S
> @@ -46,15 +46,12 @@ SECTIONS
> } :text :dynamic
>
> .rodata : {
> - *(.rodata*)
> + *(.rodata* .gnu.linkonce.r.*)
> } :text
> .data : {
> - *(.data*)
> + *(.data* .gnu.linkonce.d.*)
> *(.got.plt) *(.got)
> - *(.gnu.linkonce.d.*)
> - *(.bss*)
> - *(.dynbss*)
> - *(.gnu.linkonce.b.*)
> + *(.bss* .gnu.linkonce.b.*)
> }
>
> .altinstructions : {
> @@ -71,7 +68,7 @@ SECTIONS
> . = ALIGN(0x100);
>
> .text : {
> - *(.text*)
> + *(.text* .gnu.linkonce.t.*)
> } :text =0x90909090
> }
>