Skip to contentSkip to conversation

x86,vdso: Restore a bunch of section headers

PATCH In review Andy Lutomirski 3 participants 9 messages Jun 20, 2014 – Apr 30, 2019 x86

lore
Share & tools
lore
#0 lore raw

v2 cover x86,vdso: Restore a bunch of section headers

This series makes me sad. It brings the 64-bit vdso back above 4kB, like it was in 3.15. It's also just silly, but it seems to be needed to keep binutils happy when debugging the vdso.

Patch 5 isn't really necessary, and is likely not 3.16 material. It's useful for testing the rest of this series, though.

Only patch 5 changed from v1:
- Fix for old binutils.
- Pass --build-id, since normal binutils may not have it on by default.

Andy Lutomirski (5):
x86,vdso: Discard the __bug_table section x86,vdso2c: Use better macros for ELF bitness x86,vdso: Improve the fake section headers x86,vdso: Remove some redundant in-memory section headers x86,vdso: Create .build-id links for unstripped vdso files

 arch/x86/vdso/Makefile                   |  20 +++-
 arch/x86/vdso/vdso-fakesections.c        |  41 +++----
 arch/x86/vdso/vdso-layout.lds.S          |  64 +++++++---
 arch/x86/vdso/vdso.lds.S                 |   2 +
 arch/x86/vdso/vdso2c.c                   |  73 ++++++------
 arch/x86/vdso/vdso2c.h                   | 197 ++++++++++++++++++++++++++-----
 arch/x86/vdso/vdso32/vdso-fakesections.c |   1 +
 arch/x86/vdso/vdsox32.lds.S              |   2 +
 8 files changed, 284 insertions(+), 116 deletions(-)
 create mode 100644 arch/x86/vdso/vdso32/vdso-fakesections.c
Signature · 1 line
1.9.3
#1 lore raw

PATCH v2 1/5 x86,vdso: Discard the __bug_table section

It serves no purpose in user code.

---
 arch/x86/vdso/vdso-layout.lds.S | 1 +
 1 file changed, 1 insertion(+)
arch/x86/vdso/vdso-layout.lds.S +1 -0
index 2ec72f6..c84166c 100644
@@ -75,6 +75,7 @@ SECTIONS
 	/DISCARD/ : {
 		*(.discard)
 		*(.discard.*)
+		*(__bug_table)
 	}
 }
 
Signature · 1 line
1.9.3
#2 lore raw

PATCH v2 2/5 x86,vdso2c: Use better macros for ELF bitness

In reply to Andy Lutomirski

Rather than using a separate macro for each replacement, use generic macros.

---
 arch/x86/vdso/vdso2c.c | 42 +++++++++++++-----------------------------
 arch/x86/vdso/vdso2c.h | 23 ++++++++++++-----------
 2 files changed, 25 insertions(+), 40 deletions(-)
arch/x86/vdso/vdso2c.c +13 -29
index 7a6bf50..7343899 100644
@@ -83,37 +83,21 @@ extern void bad_put_le(void);
 
 #define NSYMS (sizeof(required_syms) / sizeof(required_syms[0]))
 
-#define BITS 64
-#define GOFUNC go64
-#define Elf_Ehdr Elf64_Ehdr
-#define Elf_Shdr Elf64_Shdr
-#define Elf_Phdr Elf64_Phdr
-#define Elf_Sym Elf64_Sym
-#define Elf_Dyn Elf64_Dyn
+#define BITSFUNC3(name, bits) name##bits
+#define BITSFUNC2(name, bits) BITSFUNC3(name, bits)
+#define BITSFUNC(name) BITSFUNC2(name, ELF_BITS)
+
+#define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x
+#define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x)
+#define ELF(x) ELF_BITS_XFORM(ELF_BITS, x)
+
+#define ELF_BITS 64
 #include "vdso2c.h"
-#undef BITS
-#undef GOFUNC
-#undef Elf_Ehdr
-#undef Elf_Shdr
-#undef Elf_Phdr
-#undef Elf_Sym
-#undef Elf_Dyn
-
-#define BITS 32
-#define GOFUNC go32
-#define Elf_Ehdr Elf32_Ehdr
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Phdr Elf32_Phdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Dyn Elf32_Dyn
+#undef ELF_BITS
+
+#define ELF_BITS 32
 #include "vdso2c.h"
-#undef BITS
-#undef GOFUNC
-#undef Elf_Ehdr
-#undef Elf_Shdr
-#undef Elf_Phdr
-#undef Elf_Sym
-#undef Elf_Dyn
+#undef ELF_BITS
 
 static void go(void *addr, size_t len, FILE *outfile, const char *name)
 {
arch/x86/vdso/vdso2c.h +12 -11
index c6eefaf..8e185ce 100644
@@ -4,23 +4,24 @@
  * are built for 32-bit userspace.
  */
 
-static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name)
+static void BITSFUNC(go)(void *addr, size_t len,
+			 FILE *outfile, const char *name)
 {
 	int found_load = 0;
 	unsigned long load_size = -1;  /* Work around bogus warning */
 	unsigned long data_size;
-	Elf_Ehdr *hdr = (Elf_Ehdr *)addr;
+	ELF(Ehdr) *hdr = (ELF(Ehdr) *)addr;
 	int i;
 	unsigned long j;
-	Elf_Shdr *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr,
+	ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr,
 		*alt_sec = NULL;
-	Elf_Dyn *dyn = 0, *dyn_end = 0;
+	ELF(Dyn) *dyn = 0, *dyn_end = 0;
 	const char *secstrings;
 	uint64_t syms[NSYMS] = {};
 
 	uint64_t fake_sections_value = 0, fake_sections_size = 0;
 
-	Elf_Phdr *pt = (Elf_Phdr *)(addr + GET_LE(&hdr->e_phoff));
+	ELF(Phdr) *pt = (ELF(Phdr) *)(addr + GET_LE(&hdr->e_phoff));
 
 	/* Walk the segment table. */
 	for (i = 0; i < GET_LE(&hdr->e_phnum); i++) {
@@ -61,7 +62,7 @@ static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name)
 		GET_LE(&hdr->e_shentsize)*GET_LE(&hdr->e_shstrndx);
 	secstrings = addr + GET_LE(&secstrings_hdr->sh_offset);
 	for (i = 0; i < GET_LE(&hdr->e_shnum); i++) {
-		Elf_Shdr *sh = addr + GET_LE(&hdr->e_shoff) +
+		ELF(Shdr) *sh = addr + GET_LE(&hdr->e_shoff) +
 			GET_LE(&hdr->e_shentsize) * i;
 		if (GET_LE(&sh->sh_type) == SHT_SYMTAB)
 			symtab_hdr = sh;
@@ -82,7 +83,7 @@ static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name)
 	     i < GET_LE(&symtab_hdr->sh_size) / GET_LE(&symtab_hdr->sh_entsize);
 	     i++) {
 		int k;
-		Elf_Sym *sym = addr + GET_LE(&symtab_hdr->sh_offset) +
+		ELF(Sym) *sym = addr + GET_LE(&symtab_hdr->sh_offset) +
 			GET_LE(&symtab_hdr->sh_entsize) * i;
 		const char *name = addr + GET_LE(&strtab_hdr->sh_offset) +
 			GET_LE(&sym->st_name);
@@ -123,12 +124,12 @@ static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name)
 		fail("end_mapping must be a multiple of 4096\n");
 
 	/* Remove sections or use fakes */
-	if (fake_sections_size % sizeof(Elf_Shdr))
+	if (fake_sections_size % sizeof(ELF(Shdr)))
 		fail("vdso_fake_sections size is not a multiple of %ld\n",
-		     (long)sizeof(Elf_Shdr));
+		     (long)sizeof(ELF(Shdr)));
 	PUT_LE(&hdr->e_shoff, fake_sections_value);
-	PUT_LE(&hdr->e_shentsize, fake_sections_value ? sizeof(Elf_Shdr) : 0);
-	PUT_LE(&hdr->e_shnum, fake_sections_size / sizeof(Elf_Shdr));
+	PUT_LE(&hdr->e_shentsize, fake_sections_value ? sizeof(ELF(Shdr)) : 0);
+	PUT_LE(&hdr->e_shnum, fake_sections_size / sizeof(ELF(Shdr)));
 	PUT_LE(&hdr->e_shstrndx, SHN_UNDEF);
 
 	if (!name) {
Signature · 1 line
1.9.3
#3 lore raw

PATCH v2 3/5 x86,vdso: Improve the fake section headers

In reply to Andy Lutomirski

Fully stripping the vDSO has other unfortunate side effects:

- binutils is unable to find ELF notes without a SHT_NOTE section.

- Even elfutils has trouble: it can find ELF notes without a section table at all, but if a section table is present, it won't look for PT_NOTE.

- gdb wants section names to match between stripped DSOs and their symbols; otherwise it will corrupt symbol addresses.

We're also breaking the rules: section 0 is supposed to be SHT_NULL.

Fix these problems by building a better fake section table. While we're at it, we might as well let buggy Go versions keep working well by giving the SHT_DYNSYM entry the correct size.

This is a bit unfortunate: it adds quite a bit of size to the vdso image.

If/when binutils improves and the improved versions become widespread, it would be worth considering dropping most of this.

---
 arch/x86/vdso/Makefile                   |   4 +-
 arch/x86/vdso/vdso-fakesections.c        |  44 ++++----
 arch/x86/vdso/vdso-layout.lds.S          |  40 +++++--
 arch/x86/vdso/vdso.lds.S                 |   2 +
 arch/x86/vdso/vdso2c.c                   |  31 ++++--
 arch/x86/vdso/vdso2c.h                   | 180 +++++++++++++++++++++++++++----
 arch/x86/vdso/vdso32/vdso-fakesections.c |   1 +
 arch/x86/vdso/vdsox32.lds.S              |   2 +
 8 files changed, 237 insertions(+), 67 deletions(-)
 create mode 100644 arch/x86/vdso/vdso32/vdso-fakesections.c
arch/x86/vdso/Makefile +2 -2
index 3c0809a..2c1ca98 100644
@@ -11,7 +11,6 @@ VDSO32-$(CONFIG_COMPAT)		:= y
 
 # files to link into the vdso
 vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o vdso-fakesections.o
-vobjs-nox32 := vdso-fakesections.o
 
 # files to link into kernel
 obj-y				+= vma.o
@@ -134,7 +133,7 @@ override obj-dirs = $(dir $(obj)) $(obj)/vdso32/
 
 targets += vdso32/vdso32.lds
 targets += vdso32/note.o vdso32/vclock_gettime.o $(vdso32.so-y:%=vdso32/%.o)
-targets += vdso32/vclock_gettime.o
+targets += vdso32/vclock_gettime.o vdso32/vdso-fakesections.o
 
 $(obj)/vdso32.o: $(vdso32-images:%=$(obj)/%)
 
@@ -155,6 +154,7 @@ $(vdso32-images:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_32)
 $(vdso32-images:%=$(obj)/%.dbg): $(obj)/vdso32-%.so.dbg: FORCE \
 				 $(obj)/vdso32/vdso32.lds \
 				 $(obj)/vdso32/vclock_gettime.o \
+				 $(obj)/vdso32/vdso-fakesections.o \
 				 $(obj)/vdso32/note.o \
 				 $(obj)/vdso32/%.o
 	$(call if_changed,vdso)
arch/x86/vdso/vdso-fakesections.c +18 -26

49 lines not on this page · raw message

arch/x86/vdso/vdso-layout.lds.S +32 -8
index c84166c..e4cbc21 100644
@@ -6,6 +6,16 @@
  * This script controls its layout.
  */
 
+#if defined(BUILD_VDSO64)
+# define SHDR_SIZE 64
+#elif defined(BUILD_VDSO32) || defined(BUILD_VDSOX32)
+# define SHDR_SIZE 40
+#else
+# error unknown VDSO target
+#endif
+
+#define NUM_FAKE_SHDRS 16
+
 SECTIONS
 {
 	. = SIZEOF_HEADERS;
@@ -25,15 +35,29 @@ SECTIONS
 
 	.dynamic	: { *(.dynamic) }		:text	:dynamic
 
-	.rodata		: { *(.rodata*) }		:text
+	.rodata		: {
+		*(.rodata*)
+
+		/*
+		 * Ideally this would live in a C file, but that won't
+		 * work cleanly for x32 until we start building the x32
+		 * C code using an x32 toolchain.
+		 */
+		VDSO_FAKE_SECTION_TABLE_START = .;
+		. = . + NUM_FAKE_SHDRS * SHDR_SIZE;
+		VDSO_FAKE_SECTION_TABLE_END = .;
+	}						:text
+
+	.fake_shstrtab	: { *(.fake_shstrtab) }		:text
+
 	.data		: {
-	      *(.data*)
-	      *(.sdata*)
-	      *(.got.plt) *(.got)
-	      *(.gnu.linkonce.d.*)
-	      *(.bss*)
-	      *(.dynbss*)
-	      *(.gnu.linkonce.b.*)
+		*(.data*)
+		*(.sdata*)
+		*(.got.plt) *(.got)
+		*(.gnu.linkonce.d.*)
+		*(.bss*)
+		*(.dynbss*)
+		*(.gnu.linkonce.b.*)
 	}
 
 	.altinstructions	: { *(.altinstructions) }
arch/x86/vdso/vdso.lds.S +2 -0
index 75e3404..6807932 100644
@@ -6,6 +6,8 @@
  * the DSO.
  */
 
+#define BUILD_VDSO64
+
 #include "vdso-layout.lds.S"
 
 /*
arch/x86/vdso/vdso2c.c +22 -9
index 7343899..238dbe82 100644
@@ -23,6 +23,8 @@ enum {
 	sym_vvar_page,
 	sym_hpet_page,
 	sym_end_mapping,
+	sym_VDSO_FAKE_SECTION_TABLE_START,
+	sym_VDSO_FAKE_SECTION_TABLE_END,
 };
 
 const int special_pages[] = {
@@ -30,15 +32,26 @@ const int special_pages[] = {
 	sym_hpet_page,
 };
 
-char const * const required_syms[] = {
-	[sym_vvar_page] = "vvar_page",
-	[sym_hpet_page] = "hpet_page",
-	[sym_end_mapping] = "end_mapping",
-	"VDSO32_NOTE_MASK",
-	"VDSO32_SYSENTER_RETURN",
-	"__kernel_vsyscall",
-	"__kernel_sigreturn",
-	"__kernel_rt_sigreturn",
+struct vdso_sym {
+	const char *name;
+	bool export;
+};
+
+struct vdso_sym required_syms[] = {
+	[sym_vvar_page] = {"vvar_page", true},
+	[sym_hpet_page] = {"hpet_page", true},
+	[sym_end_mapping] = {"end_mapping", true},
+	[sym_VDSO_FAKE_SECTION_TABLE_START] = {
+		"VDSO_FAKE_SECTION_TABLE_START", false
+	},
+	[sym_VDSO_FAKE_SECTION_TABLE_END] = {
+		"VDSO_FAKE_SECTION_TABLE_END", false
+	},
+	{"VDSO32_NOTE_MASK", true},
+	{"VDSO32_SYSENTER_RETURN", true},
+	{"__kernel_vsyscall", true},
+	{"__kernel_sigreturn", true},
+	{"__kernel_rt_sigreturn", true},
 };
 
 __attribute__((format(printf, 1, 2))) __attribute__((noreturn))
arch/x86/vdso/vdso2c.h +158 -22

228 lines not on this page · raw message

arch/x86/vdso/vdso32/vdso-fakesections.c new file +1 -0
new file mode 100644
index 0000000..541468e
@@ -0,0 +1 @@
+#include "../vdso-fakesections.c"
arch/x86/vdso/vdsox32.lds.S +2 -0
index 46b991b..697c11e 100644
@@ -6,6 +6,8 @@
  * the DSO.
  */
 
+#define BUILD_VDSOX32
+
 #include "vdso-layout.lds.S"
 
 /*
Signature · 1 line
1.9.3
#4 lore raw

PATCH v2 4/5 x86,vdso: Remove some redundant in-memory section headers

In reply to Andy Lutomirski

.data doesn't need to be separate from .rodata: they're both readonly.

.altinstructions and .altinstr_replacement aren't needed by anything except vdso2c; strip them from the final image.

While we're at it, rather than aligning the actual executable text, just shove some unused-at-runtime data in between real data and text.

My vdso image is still above 4k, but I'm disinclined to try to trim it harder for 3.16. For future trimming, I suspect that these sections could be moved to later in the file and dropped from the in-memory image:

.gnu.version and .gnu.version_d   (this may lose versions in gdb)
.eh_frame                         (should be harmless)
.eh_frame_hdr                     (I'm not really sure)
.hash                             (AFAIK nothing needs this section header)
---
 arch/x86/vdso/vdso-fakesections.c |  3 ---
 arch/x86/vdso/vdso-layout.lds.S   | 43 +++++++++++++++++++++------------------
 arch/x86/vdso/vdso2c.h            |  4 +++-
 3 files changed, 26 insertions(+), 24 deletions(-)
arch/x86/vdso/vdso-fakesections.c +0 -3
index 56927a7..aa5fbfa 100644
@@ -16,9 +16,6 @@ const char fake_shstrtab[] __attribute__((section(".fake_shstrtab"))) =
 	".rodata\0"
 	".fake_shstrtab\0"  /* Yay, self-referential code. */
 	".note\0"
-	".data\0"
-	".altinstructions\0"
-	".altinstr_replacement\0"
 	".eh_frame_hdr\0"
 	".eh_frame\0"
 	".text";
arch/x86/vdso/vdso-layout.lds.S +23 -20

73 lines not on this page · raw message

arch/x86/vdso/vdso2c.h +3 -1
index f01ed4b..f42e2dd 100644
@@ -92,7 +92,9 @@ static void BITSFUNC(copy_section)(struct BITSFUNC(fake_sections) *out,
 {
 	uint64_t flags = GET_LE(&in->sh_flags);
 
-	bool copy = flags & SHF_ALLOC;
+	bool copy = flags & SHF_ALLOC &&
+		strcmp(name, ".altinstructions") &&
+		strcmp(name, ".altinstr_replacement");
 
 	if (!copy)
 		return;
Signature · 1 line
1.9.3
#5 lore raw

PATCH v2 5/5 x86,vdso: Create .build-id links for unstripped vdso files

In reply to Andy Lutomirski

With this change, doing 'make vdso_install' and telling gdb:

set debug-file-directory /lib/modules/KVER/vdso

will enable vdso debugging with symbols. This is useful for testing, but kernel RPM builds will probably want to manually delete these symlinks or otherwise do something sensible when they strip the vdso/*.so files.

If ld does not support --build-id, then the symlinks will not be created.

Note that kernel packagers that use vdso_install may need to adjust their packaging scripts to accomdate this change. For example, Fedora's scripts create build-id symlinks themselves in a different location, so the spec should probably be updated to remove the symlinks created by make vdso_install.

---
 arch/x86/vdso/Makefile | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)
arch/x86/vdso/Makefile +13 -3
index 2c1ca98..68a15c4 100644
@@ -169,14 +169,24 @@ quiet_cmd_vdso = VDSO    $@
 		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
 
 VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
-	-Wl,-Bsymbolic $(LTO_CFLAGS)
+	$(call cc-ldoption, -Wl$(comma)--build-id) -Wl,-Bsymbolic $(LTO_CFLAGS)
 GCOV_PROFILE := n
 
 #
-# Install the unstripped copies of vdso*.so.
+# Install the unstripped copies of vdso*.so.  If our toolchain supports
+# build-id, install .build-id links as well.
 #
 quiet_cmd_vdso_install = INSTALL $(@:install_%=%)
-      cmd_vdso_install = cp $< $(MODLIB)/vdso/$(@:install_%=%)
+define cmd_vdso_install
+	cp $< "$(MODLIB)/vdso/$(@:install_%=%)"; \
+	if readelf -n $< |grep -q 'Build ID'; then \
+	  buildid=`readelf -n $< |grep 'Build ID' |sed -e 's/^.*Build ID: \(.*\)$$/\1/'`; \
+	  first=`echo $$buildid | cut -b-2`; \
+	  last=`echo $$buildid | cut -b3-`; \
+	  mkdir -p "$(MODLIB)/vdso/.build-id/$$first"; \
+	  ln -sf "../../$(@:install_%=%)" "$(MODLIB)/vdso/.build-id/$$first/$$last.debug"; \
+	fi
+endef
 
 vdso_img_insttargets := $(vdso_img_sodbg:%.dbg=install_%)
 
Signature · 1 line
1.9.3
#6 lore raw

[tip:x86/urgent] x86/vdso: Create .build-id links for unstripped vdso files

x86/vdso: Create .build-id links for unstripped vdso files
Commit-ID:  dda1e95cee38b416b23f751cac65421d781e3c10
Gitweb:     http://git.kernel.org/tip/dda1e95cee38b416b23f751cac65421d781e3c10
Author:     Andy Lutomirski <[email protected]>
AuthorDate: Fri, 20 Jun 2014 12:20:44 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Fri, 20 Jun 2014 13:18:49 -0700

x86/vdso: Create .build-id links for unstripped vdso files

With this change, doing 'make vdso_install' and telling gdb:

set debug-file-directory /lib/modules/KVER/vdso

will enable vdso debugging with symbols. This is useful for testing, but kernel RPM builds will probably want to manually delete these symlinks or otherwise do something sensible when they strip the vdso/*.so files.

If ld does not support --build-id, then the symlinks will not be created.

Note that kernel packagers that use vdso_install may need to adjust their packaging scripts to accomdate this change. For example, Fedora's scripts create build-id symlinks themselves in a different location, so the spec should probably be updated to remove the symlinks created by make vdso_install.

---
 arch/x86/vdso/Makefile | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)
arch/x86/vdso/Makefile +13 -3
index 2c1ca98..68a15c4 100644
@@ -169,14 +169,24 @@ quiet_cmd_vdso = VDSO    $@
 		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
 
 VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
-	-Wl,-Bsymbolic $(LTO_CFLAGS)
+	$(call cc-ldoption, -Wl$(comma)--build-id) -Wl,-Bsymbolic $(LTO_CFLAGS)
 GCOV_PROFILE := n
 
 #
-# Install the unstripped copies of vdso*.so.
+# Install the unstripped copies of vdso*.so.  If our toolchain supports
+# build-id, install .build-id links as well.
 #
 quiet_cmd_vdso_install = INSTALL $(@:install_%=%)
-      cmd_vdso_install = cp $< $(MODLIB)/vdso/$(@:install_%=%)
+define cmd_vdso_install
+	cp $< "$(MODLIB)/vdso/$(@:install_%=%)"; \
+	if readelf -n $< |grep -q 'Build ID'; then \
+	  buildid=`readelf -n $< |grep 'Build ID' |sed -e 's/^.*Build ID: \(.*\)$$/\1/'`; \
+	  first=`echo $$buildid | cut -b-2`; \
+	  last=`echo $$buildid | cut -b3-`; \
+	  mkdir -p "$(MODLIB)/vdso/.build-id/$$first"; \
+	  ln -sf "../../$(@:install_%=%)" "$(MODLIB)/vdso/.build-id/$$first/$$last.debug"; \
+	fi
+endef
 
 vdso_img_insttargets := $(vdso_img_sodbg:%.dbg=install_%)
 
#7 lore raw

Re: [PATCH v2 5/5] x86,vdso: Create .build-id links for unstripped vdso files

In reply to Andy Lutomirski

Hi Andy,

Quoted 13 lines · Andy Lutomirski

With this change, doing 'make vdso_install' and telling gdb:

set debug-file-directory /lib/modules/KVER/vdso

will enable vdso debugging with symbols. This is useful for testing, but kernel RPM builds will probably want to manually delete these symlinks or otherwise do something sensible when they strip the vdso/*.so files.

If ld does not support --build-id, then the symlinks will not be created.

Quoted 8 lines

Note that kernel packagers that use vdso_install may need to adjust their packaging scripts to accomdate this change. For example, Fedora's scripts create build-id symlinks themselves in a different location, so the spec should probably be updated to remove the symlinks created by make vdso_install.

---

I was looking into this, but
I am not familiar enough with this area.

Could you tell me how it works?

I use Ubuntu 18.04 LTS.
Luckily, it has build-id symlinks by default,
so I should be able to test it easily.

masahiro@pug:~$ uname -r
4.15.0-47-generic
masahiro@pug:~$ cd /lib/modules/4.15.0-47-generic/vdso/
masahiro@pug:/lib/modules/4.15.0-47-generic/vdso$ file vdso64.so
vdso64.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV),
dynamically linked,
BuildID[sha1]=d742540fb9ded5c3650dbe9ae20c0f39e386464c, with
debug_info, not stripped
masahiro@pug:/lib/modules/4.15.0-47-generic/vdso$ ls -l
.build-id/d7/42540fb9ded5c3650dbe9ae20c0f39e386464c.debug
lrwxrwxrwx 1 root root 15 Mar 13 13:37
.build-id/d7/42540fb9ded5c3650dbe9ae20c0f39e386464c.debug ->
../../vdso64.so

I dumped the vdso embedded in the kernel,
and I confirmed its build-id matches
to the one of unstripped vdso.

So, I expect the vdso with symbol info will be automatically loaded by setting debug-file-directory to /lib/modules/4.15.0-47-generic/vdso. Am I right?

If it works as expected, how should it look like?

I started gdb like this:

$ gdb date

Then, I did:

(gdb) set debug-file-directory /usr/lib/debug:/lib/modules/4.15.0-47-generic/vdso (gdb) show debug-file-directory
The directory where separate debug symbols are searched for is "/usr/lib/debug:/lib/modules/4.15.0-47-generic/vdso". (gdb) run

The list of shared library looks like follows:

(gdb) info sharedlibrary

From                To                  Syms Read   Shared Object Library
0x00007ffff7dd5f10  0x00007ffff7df4b20  Yes         /lib64/ld-linux-x86-64.so.2
0x00007ffff7a052d0  0x00007ffff7b7dc3c  Yes

/lib/x86_64-linux-gnu/libc.so.6
No linux-vdso.so.1

The first two shared objects shows "Yes" because debug info is available under /usr/lib/debug/lib/x86_64-linux-gnu/ and associated by .gnu_debuglink.

linux-vdso.so.1 shows "No".
Does it mean no symbol was included ?

Thank you.

Masahiro Yamada

Quoted 43 lines
 arch/x86/vdso/Makefile | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)
arch/x86/vdso/Makefile +13 -4
index 2c1ca98..68a15c4 100644
@@ -169,14 +169,24 @@ quiet_cmd_vdso = VDSO    $@
                 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
 
 VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
-       -Wl,-Bsymbolic $(LTO_CFLAGS)
+       $(call cc-ldoption, -Wl$(comma)--build-id) -Wl,-Bsymbolic $(LTO_CFLAGS)
 GCOV_PROFILE := n
 
 #
-# Install the unstripped copies of vdso*.so.
+# Install the unstripped copies of vdso*.so.  If our toolchain supports
+# build-id, install .build-id links as well.
 #
 quiet_cmd_vdso_install = INSTALL $(@:install_%=%)
-      cmd_vdso_install = cp $< $(MODLIB)/vdso/$(@:install_%=%)
+define cmd_vdso_install
+       cp $< "$(MODLIB)/vdso/$(@:install_%=%)"; \
+       if readelf -n $< |grep -q 'Build ID'; then \
+         buildid=`readelf -n $< |grep 'Build ID' |sed -e 's/^.*Build ID: \(.*\)$$/\1/'`; \
+         first=`echo $$buildid | cut -b-2`; \
+         last=`echo $$buildid | cut -b3-`; \
+         mkdir -p "$(MODLIB)/vdso/.build-id/$$first"; \
+         ln -sf "../../$(@:install_%=%)" "$(MODLIB)/vdso/.build-id/$$first/$$last.debug"; \
+       fi
+endef
 
 vdso_img_insttargets := $(vdso_img_sodbg:%.dbg=install_%)
 
--

1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Signature · 2 lines
Best Regards
Masahiro Yamada
#8 lore raw

Re: [PATCH v2 5/5] x86,vdso: Create .build-id links for unstripped vdso files

Quoted 91 lines · Masahiro Yamada

Hi Andy,

Quoted 13 lines · Andy Lutomirski

With this change, doing 'make vdso_install' and telling gdb:

set debug-file-directory /lib/modules/KVER/vdso

will enable vdso debugging with symbols. This is useful for testing, but kernel RPM builds will probably want to manually delete these symlinks or otherwise do something sensible when they strip the vdso/*.so files.

If ld does not support --build-id, then the symlinks will not be created.

Quoted 8 lines

Note that kernel packagers that use vdso_install may need to adjust their packaging scripts to accomdate this change. For example, Fedora's scripts create build-id symlinks themselves in a different location, so the spec should probably be updated to remove the symlinks created by make vdso_install.

---

I was looking into this, but
I am not familiar enough with this area.

Could you tell me how it works?

I use Ubuntu 18.04 LTS.
Luckily, it has build-id symlinks by default,
so I should be able to test it easily.

masahiro@pug:~$ uname -r
4.15.0-47-generic
masahiro@pug:~$ cd /lib/modules/4.15.0-47-generic/vdso/
masahiro@pug:/lib/modules/4.15.0-47-generic/vdso$ file vdso64.so
vdso64.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV),
dynamically linked,
BuildID[sha1]=d742540fb9ded5c3650dbe9ae20c0f39e386464c, with
debug_info, not stripped
masahiro@pug:/lib/modules/4.15.0-47-generic/vdso$ ls -l
.build-id/d7/42540fb9ded5c3650dbe9ae20c0f39e386464c.debug
lrwxrwxrwx 1 root root 15 Mar 13 13:37
.build-id/d7/42540fb9ded5c3650dbe9ae20c0f39e386464c.debug ->
../../vdso64.so

I dumped the vdso embedded in the kernel,
and I confirmed its build-id matches
to the one of unstripped vdso.

So, I expect the vdso with symbol info will be automatically loaded by setting debug-file-directory to /lib/modules/4.15.0-47-generic/vdso. Am I right?

If it works as expected, how should it look like?

I started gdb like this:

$ gdb date

Then, I did:

(gdb) set debug-file-directory /usr/lib/debug:/lib/modules/4.15.0-47-generic/vdso (gdb) show debug-file-directory
The directory where separate debug symbols are searched for is "/usr/lib/debug:/lib/modules/4.15.0-47-generic/vdso". (gdb) run

The list of shared library looks like follows:

(gdb) info sharedlibrary

From                To                  Syms Read   Shared Object Library
0x00007ffff7dd5f10  0x00007ffff7df4b20  Yes         /lib64/ld-linux-x86-64.so.2
0x00007ffff7a052d0  0x00007ffff7b7dc3c  Yes

/lib/x86_64-linux-gnu/libc.so.6
No linux-vdso.so.1

Quoted 8 lines

The first two shared objects shows "Yes" because debug info is available under /usr/lib/debug/lib/x86_64-linux-gnu/ and associated by .gnu_debuglink.

linux-vdso.so.1 shows "No".
Does it mean no symbol was included ?

It's been a long time since I've looked at this, and I don't remember all the details. I think your best bet may be to run gdb under strace and to try to figure out what it's doing.