diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f05ff8b5d9..833e539fe8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1413,6 +1413,7 @@ set(BASIC_TESTS userfaultfd utimes vdso_parts + vdso_symbols vfork_done vfork_flush vfork_setopts diff --git a/src/preload/rr_page.ld.in b/src/preload/rr_page.ld.in index 3f5cf6e1a8c..d7abf7d73fc 100644 --- a/src/preload/rr_page.ld.in +++ b/src/preload/rr_page.ld.in @@ -8,7 +8,8 @@ PHDRS } SECTIONS { - . = 0x70000000 - 3 * @PRELOAD_LIBRARY_PAGE_SIZE@ + SIZEOF_HEADERS; + rr_page_start = 3 * @PRELOAD_LIBRARY_PAGE_SIZE@; + . = SIZEOF_HEADERS; .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } :text :eh_frame .eh_frame : { KEEP (*(.eh_frame)) *(.eh_frame.*) } :text :eh_frame .note.gnu.build-id : { *(.note.gnu.build-id) } :text :note @@ -23,19 +24,19 @@ SECTIONS .gnu.version_r : { *(.gnu.version_r) } :text .got : { *(.got) } :text .got.plt : { *(.got.plt) } :text - . = 0x70000000 - 2 * @PRELOAD_LIBRARY_PAGE_SIZE@; + . = rr_page_start - 2 * @PRELOAD_LIBRARY_PAGE_SIZE@; /* This space in .sh_placeholder is reserved for the section table symtab/strtab, which ordinarily go after the text sections, but we need to have before the rr page. We move it there in a post-processing step, since linker scripts can't specify these locations for legacy reasons */ .sh_placeholder : { *(.sh_placeholder) } :text - . = 0x70000000 - @PRELOAD_LIBRARY_PAGE_SIZE@; + . = rr_page_start - @PRELOAD_LIBRARY_PAGE_SIZE@; .plt : { *(.plt) } :text .vdso.text : { *(.vdso.text) } :text - . = 0x70000000; + . = rr_page_start; .record.text : { *(.record.text) } :text - . = 0x70000000 + @PRELOAD_LIBRARY_PAGE_SIZE@; + . = rr_page_start + @PRELOAD_LIBRARY_PAGE_SIZE@; .replay.text : { *(.replay.text) } :replay /DISCARD/ : { *(.debug_* ) } } diff --git a/src/test/vdso_symbols.c b/src/test/vdso_symbols.c new file mode 100644 index 00000000000..f658a2dd246 --- /dev/null +++ b/src/test/vdso_symbols.c @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ + +#include "util.h" + +#ifdef __x86_64__ +typedef Elf64_Ehdr Ehdr; +typedef Elf64_Shdr Shdr; +typedef Elf64_Sym Sym; +#else +typedef Elf32_Ehdr Ehdr; +typedef Elf32_Shdr Shdr; +typedef Elf32_Sym Sym; +#endif + +static const char* find_string(Ehdr* ehdr, uintptr_t offset) { + Shdr* strings = (Shdr*)((char*)ehdr + ehdr->e_shoff + ehdr->e_shstrndx*ehdr->e_shentsize); + return (char*)ehdr + strings->sh_offset + offset; +} + +static Shdr* find_section(Ehdr* ehdr, const char* name) { + for (int i = 0; i < ehdr->e_shnum; ++i) { + Shdr* hdr = (Shdr*)((char*)ehdr + ehdr->e_shoff + i*ehdr->e_shentsize); + if (!strcmp(find_string(ehdr, hdr->sh_name), name)) { + return hdr; + } + } + return NULL; +} + +int main(void) { + char* vdso = (char*)getauxval(AT_SYSINFO_EHDR); + Ehdr* ehdr = (Ehdr*)vdso; + Shdr* dynsym = find_section(ehdr, ".dynsym"); + if (!dynsym) { + atomic_puts("dynsym not found in VDSO"); + return 1; + } + + for (int si = 0; si*dynsym->sh_entsize < dynsym->sh_size; ++si) { + Sym* sym = (Sym*)(vdso + dynsym->sh_offset) + si; + // All symbols must be within the VDSO size, i.e. not the + // absolute address. We assume the VDSO is less than 64K. + test_assert(sym->st_value < 0x10000); + } + + atomic_puts("EXIT-SUCCESS"); + return 0; +}