For testing the functionality of the vDSO, it is necessary to build userspace programs for multiple different architectures. It is additional work to acquire matching userspace cross-compilers with full C libraries and then building root images out of those. The kernel tree already contains nolibc, a small, header-only C library. By using it, it is possible to build userspace programs without any additional dependencies. For example the kernel.org crosstools or multi-target clang can be used to build test programs for a multitude of architectures. While nolibc is very limited, it is enough for many selftests. With some minor adjustments it is possible to make parse_vdso.c compatible with nolibc. As an example, vdso_standalone_test_x86 is now built from the same C code as the regular vdso_test_gettimeofday, while still being completely standalone.
This should probably go through the kselftest tree.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- Thomas Weißschuh (16): MAINTAINERS: Add vDSO selftests elf, uapi: Add definition for STN_UNDEF elf, uapi: Add definition for DT_GNU_HASH elf, uapi: Add definitions for VER_FLG_BASE and VER_FLG_WEAK elf, uapi: Add type ElfXX_Versym elf, uapi: Add types ElfXX_Verdef and ElfXX_Veraux tools/include: Add uapi/linux/elf.h selftests: Add headers target selftests: vDSO: vdso_standalone_test_x86: Use vdso_init_form_sysinfo_ehdr selftests: vDSO: parse_vdso: Drop vdso_init_from_auxv() selftests: vDSO: parse_vdso: Use UAPI headers instead of libc headers selftests: vDSO: parse_vdso: Test __SIZEOF_LONG__ instead of ULONG_MAX selftests: vDSO: parse_vdso: Make compatible with nolibc selftests: vDSO: vdso_test_gettimeofday: Clean up includes selftests: vDSO: vdso_test_gettimeofday: Make compatible with nolibc selftests: vDSO: vdso_standalone_test_x86: Switch to nolibc
MAINTAINERS | 1 + include/uapi/linux/elf.h | 38 ++ tools/include/uapi/linux/elf.h | 524 +++++++++++++++++++++ tools/testing/selftests/lib.mk | 5 +- tools/testing/selftests/vDSO/Makefile | 11 +- tools/testing/selftests/vDSO/parse_vdso.c | 21 +- tools/testing/selftests/vDSO/parse_vdso.h | 1 - .../selftests/vDSO/vdso_standalone_test_x86.c | 143 +----- .../selftests/vDSO/vdso_test_gettimeofday.c | 4 +- 9 files changed, 584 insertions(+), 164 deletions(-) --- base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b change-id: 20241017-parse_vdso-nolibc-e069baa7ff48
Best regards,
These currently have no maintainer besides the default kselftest ones. Add the general vDSO maintainers, too.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS index 896a307fa06545e2861abe46ea7029f9b4d3628e..959c8a86844eb1e5c6218e8fdbde6c3ebf68e25d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9777,6 +9777,7 @@ F: include/asm-generic/vdso/vsyscall.h F: include/vdso/ F: kernel/time/vsyscall.c F: lib/vdso/ +F: tools/testing/selftests/vDSO/
GENWQE (IBM Generic Workqueue Card) M: Frank Haverkamp haver@linux.ibm.com
The definition is used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the definition to the kernels own UAPI headers.
Link: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.symtab.html Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- include/uapi/linux/elf.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h index b44069d29cecc0f9de90ee66bfffd2137f4275a8..448695c7364042b10682acc8223eb6053ad039dd 100644 --- a/include/uapi/linux/elf.h +++ b/include/uapi/linux/elf.h @@ -125,6 +125,8 @@ typedef __s64 Elf64_Sxword; #define STB_GLOBAL 1 #define STB_WEAK 2
+#define STN_UNDEF 0 + #define STT_NOTYPE 0 #define STT_OBJECT 1 #define STT_FUNC 2
On Mon, Feb 03, 2025 at 10:05:03AM +0100, Thomas Weißschuh wrote:
The definition is used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the definition to the kernels own UAPI headers.
Link: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.symtab.html Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de
Reviewed-by: Kees Cook kees@kernel.org
The definition is used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the define to the kernels own UAPI headers.
Link: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/l... Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- include/uapi/linux/elf.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h index 448695c7364042b10682acc8223eb6053ad039dd..c5383cc7bb13c931fea083de5243c4006f795006 100644 --- a/include/uapi/linux/elf.h +++ b/include/uapi/linux/elf.h @@ -107,6 +107,7 @@ typedef __s64 Elf64_Sxword; #define DT_VALRNGLO 0x6ffffd00 #define DT_VALRNGHI 0x6ffffdff #define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 #define DT_ADDRRNGHI 0x6ffffeff #define DT_VERSYM 0x6ffffff0 #define DT_RELACOUNT 0x6ffffff9
On Mon, Feb 03, 2025 at 10:05:04AM +0100, Thomas Weißschuh wrote:
The definition is used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the define to the kernels own UAPI headers.
Link: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/l... Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de
Reviewed-by: Kees Cook kees@kernel.org
The definitions are used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the definitions to the kernels own UAPI headers.
Link: https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-80869/index.html Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- include/uapi/linux/elf.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h index c5383cc7bb13c931fea083de5243c4006f795006..d040f12ff1c0ae3dde5c371c81d6089118fbe8ed 100644 --- a/include/uapi/linux/elf.h +++ b/include/uapi/linux/elf.h @@ -136,6 +136,9 @@ typedef __s64 Elf64_Sxword; #define STT_COMMON 5 #define STT_TLS 6
+#define VER_FLG_BASE 0x1 +#define VER_FLG_WEAK 0x2 + #define ELF_ST_BIND(x) ((x) >> 4) #define ELF_ST_TYPE(x) ((x) & 0xf) #define ELF32_ST_BIND(x) ELF_ST_BIND(x)
On Mon, Feb 03, 2025 at 10:05:05AM +0100, Thomas Weißschuh wrote:
The definitions are used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the definitions to the kernels own UAPI headers.
For all the UAPI changes, where are the defines "normally" found? i.e. how does adding these to UAPI not break something that already has them? Or have these never been defined before? I'm confused about how removing the libc dependency exposes the lack of these defines. Are they defined in a non-exported libc header somewhere?
-Kees
On Tue, Feb 04, 2025 at 07:10:00AM -0800, Kees Cook wrote:
On Mon, Feb 03, 2025 at 10:05:05AM +0100, Thomas Weißschuh wrote:
The definitions are used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the definitions to the kernels own UAPI headers.
For all the UAPI changes, where are the defines "normally" found? i.e. how does adding these to UAPI not break something that already has them? Or have these never been defined before? I'm confused about how removing the libc dependency exposes the lack of these defines. Are they defined in a non-exported libc header somewhere?
They are normally defined directly in libc <elf.h>, which does not use UAPI headers. Libc elf.h and Linux UAPI elf.h can not be used at the same time because they define the same symbols. In theory some user of UAPI elf.h could have defined these new symbols on their own without ifdef guards. However UAPI elf.h is regularly updated with new symbols.
On Tue, Feb 04, 2025 at 04:17:03PM +0100, Thomas Weißschuh wrote:
On Tue, Feb 04, 2025 at 07:10:00AM -0800, Kees Cook wrote:
On Mon, Feb 03, 2025 at 10:05:05AM +0100, Thomas Weißschuh wrote:
The definitions are used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the definitions to the kernels own UAPI headers.
For all the UAPI changes, where are the defines "normally" found? i.e. how does adding these to UAPI not break something that already has them? Or have these never been defined before? I'm confused about how removing the libc dependency exposes the lack of these defines. Are they defined in a non-exported libc header somewhere?
They are normally defined directly in libc <elf.h>, which does not use UAPI headers. Libc elf.h and Linux UAPI elf.h can not be used at the same time because they define the same symbols. In theory some user of UAPI elf.h could have defined these new symbols on their own without ifdef guards. However UAPI elf.h is regularly updated with new symbols.
Okay, great. As long as the collision risk is low, I'm fine with all the UAPI additions. Thanks for doing this!
On Mon, Feb 03, 2025 at 10:05:05AM +0100, Thomas Weißschuh wrote:
The definitions are used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the definitions to the kernels own UAPI headers.
Link: https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-80869/index.html Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de
Reviewed-by: Kees Cook kees@kernel.org
The types are used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the types to the kernels own UAPI headers.
As documented by elf(5).
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- include/uapi/linux/elf.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h index d040f12ff1c0ae3dde5c371c81d6089118fbe8ed..8846fe03ca5b836c96aad1be6d8fb9daf3d4b1d9 100644 --- a/include/uapi/linux/elf.h +++ b/include/uapi/linux/elf.h @@ -11,6 +11,7 @@ typedef __u16 Elf32_Half; typedef __u32 Elf32_Off; typedef __s32 Elf32_Sword; typedef __u32 Elf32_Word; +typedef __u16 Elf32_Versym;
/* 64-bit ELF base types. */ typedef __u64 Elf64_Addr; @@ -21,6 +22,7 @@ typedef __s32 Elf64_Sword; typedef __u32 Elf64_Word; typedef __u64 Elf64_Xword; typedef __s64 Elf64_Sxword; +typedef __u16 Elf64_Versym;
/* These constants are for the segment types stored in the image headers */ #define PT_NULL 0
On Mon, Feb 03, 2025 at 10:05:06AM +0100, Thomas Weißschuh wrote:
The types are used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the types to the kernels own UAPI headers.
As documented by elf(5).
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de
Reviewed-by: Kees Cook kees@kernel.org
The types are used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the types to the kernels own UAPI headers.
Link: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-gen... Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- include/uapi/linux/elf.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h index 8846fe03ca5b836c96aad1be6d8fb9daf3d4b1d9..49f9f90458d8ca8e7b8f823d32be0a719ff827b3 100644 --- a/include/uapi/linux/elf.h +++ b/include/uapi/linux/elf.h @@ -491,4 +491,34 @@ typedef struct elf64_note { /* Bits for GNU_PROPERTY_AARCH64_FEATURE_1_BTI */ #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0)
+typedef struct { + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + #endif /* _UAPI_LINUX_ELF_H */
On Mon, Feb 03, 2025 at 10:05:07AM +0100, Thomas Weißschuh wrote:
The types are used by tools/testing/selftests/vDSO/parse_vdso.c. To be able to build the vDSO selftests without a libc dependency, add the types to the kernels own UAPI headers.
Link: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-gen... Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de
Reviewed-by: Kees Cook kees@kernel.org
It will be used by the vDSO selftests.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- tools/include/uapi/linux/elf.h | 524 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 524 insertions(+)
diff --git a/tools/include/uapi/linux/elf.h b/tools/include/uapi/linux/elf.h new file mode 100644 index 0000000000000000000000000000000000000000..3d0935a11613bbcf8c381188de3a10bafd6cc29f --- /dev/null +++ b/tools/include/uapi/linux/elf.h @@ -0,0 +1,524 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_ELF_H +#define _LINUX_ELF_H + +#include <linux/types.h> +#include <linux/elf-em.h> + +/* 32-bit ELF base types. */ +typedef __u32 Elf32_Addr; +typedef __u16 Elf32_Half; +typedef __u32 Elf32_Off; +typedef __s32 Elf32_Sword; +typedef __u32 Elf32_Word; +typedef __u16 Elf32_Versym; + +/* 64-bit ELF base types. */ +typedef __u64 Elf64_Addr; +typedef __u16 Elf64_Half; +typedef __s16 Elf64_SHalf; +typedef __u64 Elf64_Off; +typedef __s32 Elf64_Sword; +typedef __u32 Elf64_Word; +typedef __u64 Elf64_Xword; +typedef __s64 Elf64_Sxword; +typedef __u16 Elf64_Versym; + +/* These constants are for the segment types stored in the image headers */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* OS-specific */ +#define PT_HIOS 0x6fffffff /* OS-specific */ +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff +#define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550) +#define PT_GNU_STACK (PT_LOOS + 0x474e551) +#define PT_GNU_RELRO (PT_LOOS + 0x474e552) +#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553) + + +/* ARM MTE memory tag segment type */ +#define PT_AARCH64_MEMTAG_MTE (PT_LOPROC + 0x2) + +/* + * Extended Numbering + * + * If the real number of program header table entries is larger than + * or equal to PN_XNUM(0xffff), it is set to sh_info field of the + * section header at index 0, and PN_XNUM is set to e_phnum + * field. Otherwise, the section header at index 0 is zero + * initialized, if it exists. + * + * Specifications are available in: + * + * - Oracle: Linker and Libraries. + * Part No: 817–1984–19, August 2011. + * https://docs.oracle.com/cd/E18752_01/pdf/817-1984.pdf + * + * - System V ABI AMD64 Architecture Processor Supplement + * Draft Version 0.99.4, + * January 13, 2010. + * http://www.cs.washington.edu/education/courses/cse351/12wi/supp-docs/abi.pdf + */ +#define PN_XNUM 0xffff + +/* These constants define the different elf file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* This is the info that is needed to parse the dynamic section of the file */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_ENCODING 32 +#define OLD_DT_LOOS 0x60000000 +#define DT_LOOS 0x6000000d +#define DT_HIOS 0x6ffff000 +#define DT_VALRNGLO 0x6ffffd00 +#define DT_VALRNGHI 0x6ffffdff +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_VERSYM 0x6ffffff0 +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa +#define DT_FLAGS_1 0x6ffffffb +#define DT_VERDEF 0x6ffffffc +#define DT_VERDEFNUM 0x6ffffffd +#define DT_VERNEED 0x6ffffffe +#define DT_VERNEEDNUM 0x6fffffff +#define OLD_DT_HIOS 0x6fffffff +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* This info is needed when parsing the symbol table */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 + +#define STN_UNDEF 0 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_TLS 6 + +#define VER_FLG_BASE 0x1 +#define VER_FLG_WEAK 0x2 + +#define ELF_ST_BIND(x) ((x) >> 4) +#define ELF_ST_TYPE(x) ((x) & 0xf) +#define ELF32_ST_BIND(x) ELF_ST_BIND(x) +#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) +#define ELF64_ST_BIND(x) ELF_ST_BIND(x) +#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) + +typedef struct { + Elf32_Sword d_tag; + union { + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +typedef struct { + Elf64_Sxword d_tag; /* entry tag value */ + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +/* The following are used with relocations */ +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x) & 0xff) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) + +typedef struct elf32_rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf64_rel { + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ +} Elf64_Rel; + +typedef struct elf32_rela { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct elf64_rela { + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ + Elf64_Sxword r_addend; /* Constant addend used to compute value */ +} Elf64_Rela; + +typedef struct elf32_sym { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +typedef struct elf64_sym { + Elf64_Word st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Type and binding attributes */ + unsigned char st_other; /* No defined meaning, 0 */ + Elf64_Half st_shndx; /* Associated section index */ + Elf64_Addr st_value; /* Value of the symbol */ + Elf64_Xword st_size; /* Associated symbol size */ +} Elf64_Sym; + + +#define EI_NIDENT 16 + +typedef struct elf32_hdr { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; /* Entry point */ + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +typedef struct elf64_hdr { + unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* These constants define the permissions on sections in the program + header, p_flags. */ +#define PF_R 0x4 +#define PF_W 0x2 +#define PF_X 0x1 + +typedef struct elf32_phdr { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +typedef struct elf64_phdr { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment, file & memory */ +} Elf64_Phdr; + +/* sh_type */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* sh_flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_RELA_LIVEPATCH 0x00100000 +#define SHF_RO_AFTER_INIT 0x00200000 +#define SHF_MASKPROC 0xf0000000 + +/* special section indexes */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_LIVEPATCH 0xff20 +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +typedef struct elf32_shdr { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct elf64_shdr { + Elf64_Word sh_name; /* Section name, index in string tbl */ + Elf64_Word sh_type; /* Type of section */ + Elf64_Xword sh_flags; /* Miscellaneous section attributes */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Size of section in bytes */ + Elf64_Word sh_link; /* Index of another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +#ifndef ELF_OSABI +#define ELF_OSABI ELFOSABI_NONE +#endif + +/* + * Notes used in ET_CORE. Architectures export some of the arch register sets + * using the corresponding note types via the PTRACE_GETREGSET and + * PTRACE_SETREGSET requests. + * The note name for these types is "LINUX", except NT_PRFPREG that is named + * "CORE". + */ +#define NT_PRSTATUS 1 +#define NT_PRFPREG 2 +#define NT_PRPSINFO 3 +#define NT_TASKSTRUCT 4 +#define NT_AUXV 6 +/* + * Note to userspace developers: size of NT_SIGINFO note may increase + * in the future to accomodate more fields, don't assume it is fixed! + */ +#define NT_SIGINFO 0x53494749 +#define NT_FILE 0x46494c45 +#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ +#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ +#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ +#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ +#define NT_PPC_TAR 0x103 /* Target Address Register */ +#define NT_PPC_PPR 0x104 /* Program Priority Register */ +#define NT_PPC_DSCR 0x105 /* Data Stream Control Register */ +#define NT_PPC_EBB 0x106 /* Event Based Branch Registers */ +#define NT_PPC_PMU 0x107 /* Performance Monitor Registers */ +#define NT_PPC_TM_CGPR 0x108 /* TM checkpointed GPR Registers */ +#define NT_PPC_TM_CFPR 0x109 /* TM checkpointed FPR Registers */ +#define NT_PPC_TM_CVMX 0x10a /* TM checkpointed VMX Registers */ +#define NT_PPC_TM_CVSX 0x10b /* TM checkpointed VSX Registers */ +#define NT_PPC_TM_SPR 0x10c /* TM Special Purpose Registers */ +#define NT_PPC_TM_CTAR 0x10d /* TM checkpointed Target Address Register */ +#define NT_PPC_TM_CPPR 0x10e /* TM checkpointed Program Priority Register */ +#define NT_PPC_TM_CDSCR 0x10f /* TM checkpointed Data Stream Control Register */ +#define NT_PPC_PKEY 0x110 /* Memory Protection Keys registers */ +#define NT_PPC_DEXCR 0x111 /* PowerPC DEXCR registers */ +#define NT_PPC_HASHKEYR 0x112 /* PowerPC HASHKEYR register */ +#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ +#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ +#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ +/* Old binutils treats 0x203 as a CET state */ +#define NT_X86_SHSTK 0x204 /* x86 SHSTK state */ +#define NT_X86_XSAVE_LAYOUT 0x205 /* XSAVE layout description */ +#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */ +#define NT_S390_TIMER 0x301 /* s390 timer register */ +#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */ +#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ +#define NT_S390_CTRS 0x304 /* s390 control registers */ +#define NT_S390_PREFIX 0x305 /* s390 prefix register */ +#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ +#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ +#define NT_S390_TDB 0x308 /* s390 transaction diagnostic block */ +#define NT_S390_VXRS_LOW 0x309 /* s390 vector registers 0-15 upper half */ +#define NT_S390_VXRS_HIGH 0x30a /* s390 vector registers 16-31 */ +#define NT_S390_GS_CB 0x30b /* s390 guarded storage registers */ +#define NT_S390_GS_BC 0x30c /* s390 guarded storage broadcast control block */ +#define NT_S390_RI_CB 0x30d /* s390 runtime instrumentation */ +#define NT_S390_PV_CPU_DATA 0x30e /* s390 protvirt cpu dump data */ +#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */ +#define NT_ARM_TLS 0x401 /* ARM TLS register */ +#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */ +#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */ +#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */ +#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension registers */ +#define NT_ARM_PAC_MASK 0x406 /* ARM pointer authentication code masks */ +#define NT_ARM_PACA_KEYS 0x407 /* ARM pointer authentication address keys */ +#define NT_ARM_PACG_KEYS 0x408 /* ARM pointer authentication generic key */ +#define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* arm64 tagged address control (prctl()) */ +#define NT_ARM_PAC_ENABLED_KEYS 0x40a /* arm64 ptr auth enabled keys (prctl()) */ +#define NT_ARM_SSVE 0x40b /* ARM Streaming SVE registers */ +#define NT_ARM_ZA 0x40c /* ARM SME ZA registers */ +#define NT_ARM_ZT 0x40d /* ARM SME ZT registers */ +#define NT_ARM_FPMR 0x40e /* ARM floating point mode register */ +#define NT_ARM_POE 0x40f /* ARM POE registers */ +#define NT_ARM_GCS 0x410 /* ARM GCS state */ +#define NT_ARC_V2 0x600 /* ARCv2 accumulator/extra registers */ +#define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note */ +#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */ +#define NT_MIPS_FP_MODE 0x801 /* MIPS floating-point mode */ +#define NT_MIPS_MSA 0x802 /* MIPS SIMD registers */ +#define NT_RISCV_CSR 0x900 /* RISC-V Control and Status Registers */ +#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */ +#define NT_RISCV_TAGGED_ADDR_CTRL 0x902 /* RISC-V tagged address control (prctl()) */ +#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers */ +#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and status registers */ +#define NT_LOONGARCH_LSX 0xa02 /* LoongArch Loongson SIMD Extension registers */ +#define NT_LOONGARCH_LASX 0xa03 /* LoongArch Loongson Advanced SIMD Extension registers */ +#define NT_LOONGARCH_LBT 0xa04 /* LoongArch Loongson Binary Translation registers */ +#define NT_LOONGARCH_HW_BREAK 0xa05 /* LoongArch hardware breakpoint registers */ +#define NT_LOONGARCH_HW_WATCH 0xa06 /* LoongArch hardware watchpoint registers */ + +/* Note types with note name "GNU" */ +#define NT_GNU_PROPERTY_TYPE_0 5 + +/* Note header in a PT_NOTE section */ +typedef struct elf32_note { + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +} Elf32_Nhdr; + +/* Note header in a PT_NOTE section */ +typedef struct elf64_note { + Elf64_Word n_namesz; /* Name size */ + Elf64_Word n_descsz; /* Content size */ + Elf64_Word n_type; /* Content type */ +} Elf64_Nhdr; + +/* .note.gnu.property types for EM_AARCH64: */ +#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 + +/* Bits for GNU_PROPERTY_AARCH64_FEATURE_1_BTI */ +#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0) + +typedef struct { + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + +#endif /* _LINUX_ELF_H */
Some selftests need access to a full UAPI headers tree, for example when building with nolibc which heavily relies on UAPI headers. A reference to such a tree is available in the KHDR_INCLUDES variable, but there is currently no way to populate such a tree automatically.
Provide a target that the tests can depend on to get access to usable UAPI headers.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- tools/testing/selftests/lib.mk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk index d6edcfcb5be832ddee4c3d34b5ad221e9295f878..5303900339292e618dee4fd7ff8a7c2fa3209a68 100644 --- a/tools/testing/selftests/lib.mk +++ b/tools/testing/selftests/lib.mk @@ -228,4 +228,7 @@ $(OUTPUT)/%:%.S $(LINK.S) $^ $(LDLIBS) -o $@ endif
-.PHONY: run_tests all clean install emit_tests gen_mods_dir clean_mods_dir +headers: + $(Q)$(MAKE) -C $(top_srcdir) headers + +.PHONY: run_tests all clean install emit_tests gen_mods_dir clean_mods_dir headers
vdso_standalone_test_x86 is the only user of vdso_init_from_auxv(). Instead of combining the parsing the aux vector with the parsing of the vDSO, split them apart into getauxval() and the regular vdso_init_from_sysinfo_ehdr().
The implementation of getauxval() is taken from tools/include/nolibc/stdlib.h.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de
--- All of this code will be deleted later again. --- .../selftests/vDSO/vdso_standalone_test_x86.c | 27 +++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c b/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c index 644915862af8883131e5defd336f1bd80736fc0f..500608f89c66b5747e3d845ebc54e4c3a35b6ccd 100644 --- a/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c +++ b/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c @@ -15,6 +15,7 @@ #include <sys/time.h> #include <unistd.h> #include <stdint.h> +#include <linux/auxvec.h>
#include "parse_vdso.h"
@@ -84,6 +85,30 @@ void to_base10(char *lastdig, time_t n) } }
+unsigned long getauxval(const unsigned long *auxv, unsigned long type) +{ + unsigned long ret; + + if (!auxv) + return 0; + + while (1) { + if (!auxv[0] && !auxv[1]) { + ret = 0; + break; + } + + if (auxv[0] == type) { + ret = auxv[1]; + break; + } + + auxv += 2; + } + + return ret; +} + void c_main(void **stack) { /* Parse the stack */ @@ -96,7 +121,7 @@ void c_main(void **stack) stack++;
/* Now we're pointing at auxv. Initialize the vDSO parser. */ - vdso_init_from_auxv((void *)stack); + vdso_init_from_sysinfo_ehdr(getauxval((unsigned long *)stack, AT_SYSINFO_EHDR));
/* Find gettimeofday. */ typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
There are no users left.
Also remove the usage of ElfXX_auxv_t, which is not formally standardized.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- tools/testing/selftests/vDSO/parse_vdso.c | 14 -------------- tools/testing/selftests/vDSO/parse_vdso.h | 1 - 2 files changed, 15 deletions(-)
diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c index 2fe5e983cb22f1ed066d0310a54f6aef2ed77ed8..3638fe605e80ca41b29d43c6ac452964eef35d56 100644 --- a/tools/testing/selftests/vDSO/parse_vdso.c +++ b/tools/testing/selftests/vDSO/parse_vdso.c @@ -297,17 +297,3 @@ void *vdso_sym(const char *version, const char *name)
return 0; } - -void vdso_init_from_auxv(void *auxv) -{ - ELF(auxv_t) *elf_auxv = auxv; - for (int i = 0; elf_auxv[i].a_type != AT_NULL; i++) - { - if (elf_auxv[i].a_type == AT_SYSINFO_EHDR) { - vdso_init_from_sysinfo_ehdr(elf_auxv[i].a_un.a_val); - return; - } - } - - vdso_info.valid = false; -} diff --git a/tools/testing/selftests/vDSO/parse_vdso.h b/tools/testing/selftests/vDSO/parse_vdso.h index de0453067d7cd0d8b63f7d3738842f60370db813..09d068ed11f97f0c5c8f4e7b341f08fa261c9735 100644 --- a/tools/testing/selftests/vDSO/parse_vdso.h +++ b/tools/testing/selftests/vDSO/parse_vdso.h @@ -26,6 +26,5 @@ */ void *vdso_sym(const char *version, const char *name); void vdso_init_from_sysinfo_ehdr(uintptr_t base); -void vdso_init_from_auxv(void *auxv);
#endif
To allow the usage of parse_vdso.c together with a limited libc like nolibc, use the kernels own elf.h and auxvec.h headers.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- tools/testing/selftests/vDSO/Makefile | 3 +++ tools/testing/selftests/vDSO/parse_vdso.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/vDSO/Makefile b/tools/testing/selftests/vDSO/Makefile index 1cf14a8da43803249f72fe1b09689c8834806986..bc8ca186fb877dc11740c37f1e07e45e84c2ae92 100644 --- a/tools/testing/selftests/vDSO/Makefile +++ b/tools/testing/selftests/vDSO/Makefile @@ -19,6 +19,9 @@ LDLIBS += -lgcc_s endif
include ../lib.mk + +CFLAGS += $(TOOLS_INCLUDES) + $(OUTPUT)/vdso_test_gettimeofday: parse_vdso.c vdso_test_gettimeofday.c $(OUTPUT)/vdso_test_getcpu: parse_vdso.c vdso_test_getcpu.c $(OUTPUT)/vdso_test_abi: parse_vdso.c vdso_test_abi.c diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c index 3638fe605e80ca41b29d43c6ac452964eef35d56..200c534cc70e2c2381fce3be5c0ebe4cb5675e84 100644 --- a/tools/testing/selftests/vDSO/parse_vdso.c +++ b/tools/testing/selftests/vDSO/parse_vdso.c @@ -19,7 +19,8 @@ #include <stdint.h> #include <string.h> #include <limits.h> -#include <elf.h> +#include <linux/auxvec.h> +#include <linux/elf.h>
#include "parse_vdso.h"
According to limits.h(2) ULONG_MAX is only guaranteed to expand to an expression, not a symbolic constant which can be evaluated by the preprocessor. Specifically the definition of ULONG_MAX from nolibc can no be evaluated by the preprocessor. To provide compatibility with nolibc, check with __SIZEOF_LONG__ instead, with is provided directly by the preprocessor and therefore always a symbolic constant.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- tools/testing/selftests/vDSO/parse_vdso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c index 200c534cc70e2c2381fce3be5c0ebe4cb5675e84..902b8f9984a1f70049d46bcd4f199df24f507dcb 100644 --- a/tools/testing/selftests/vDSO/parse_vdso.c +++ b/tools/testing/selftests/vDSO/parse_vdso.c @@ -26,7 +26,7 @@
/* And here's the code. */ #ifndef ELF_BITS -# if ULONG_MAX > 0xffffffffUL +# if __SIZEOF_LONG__ >= 8 # define ELF_BITS 64 # else # define ELF_BITS 32
nolibc does not provide this header, instead its definitions are available unconditionally.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- tools/testing/selftests/vDSO/parse_vdso.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c index 902b8f9984a1f70049d46bcd4f199df24f507dcb..6ea1d7cca6a3da910097630e8237a3a6daa0cd06 100644 --- a/tools/testing/selftests/vDSO/parse_vdso.c +++ b/tools/testing/selftests/vDSO/parse_vdso.c @@ -18,7 +18,9 @@ #include <stdbool.h> #include <stdint.h> #include <string.h> +#ifndef NOLIBC #include <limits.h> +#endif #include <linux/auxvec.h> #include <linux/elf.h>
Some unnecessary headers are included, remove them.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- tools/testing/selftests/vDSO/vdso_test_gettimeofday.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c b/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c index e31b18ffae338c1576449b54ca7f84d9816d2ecb..636a56ccf8e4e7943ca446fe3fad6897598ca77f 100644 --- a/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c +++ b/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c @@ -10,8 +10,6 @@ * Tested on x86, 32-bit and 64-bit. It may work on other architectures, too. */
-#include <stdint.h> -#include <elf.h> #include <stdio.h> #include <sys/auxv.h> #include <sys/time.h>
nolibc does not provide these headers, instead those definitions are available unconditionally.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- tools/testing/selftests/vDSO/vdso_test_gettimeofday.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c b/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c index 636a56ccf8e4e7943ca446fe3fad6897598ca77f..9ce795b806f0992b83cef78c7e16fac0e54750da 100644 --- a/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c +++ b/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c @@ -11,8 +11,10 @@ */
#include <stdio.h> +#ifndef NOLIBC #include <sys/auxv.h> #include <sys/time.h> +#endif
#include "../kselftest.h" #include "parse_vdso.h"
vdso_standalone_test_x86 provides its own ASM syscall wrappers and _start() implementation. The in-tree nolibc library already provides this functionality for multiple architectures. By making use of nolibc, the standalone testcase can be built from the exact same codebase as the non-standalone version.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- tools/testing/selftests/vDSO/Makefile | 8 +- .../selftests/vDSO/vdso_standalone_test_x86.c | 168 +-------------------- 2 files changed, 7 insertions(+), 169 deletions(-)
diff --git a/tools/testing/selftests/vDSO/Makefile b/tools/testing/selftests/vDSO/Makefile index bc8ca186fb877dc11740c37f1e07e45e84c2ae92..12a0614b9fd4983deffe5d6a7cfa06ba8d92a516 100644 --- a/tools/testing/selftests/vDSO/Makefile +++ b/tools/testing/selftests/vDSO/Makefile @@ -22,13 +22,17 @@ include ../lib.mk
CFLAGS += $(TOOLS_INCLUDES)
+CFLAGS_NOLIBC := -nostdlib -nostdinc -ffreestanding -fno-asynchronous-unwind-tables \ + -fno-stack-protector -include $(top_srcdir)/tools/include/nolibc/nolibc.h \ + -I$(top_srcdir)/tools/include/nolibc/ $(KHDR_INCLUDES) + $(OUTPUT)/vdso_test_gettimeofday: parse_vdso.c vdso_test_gettimeofday.c $(OUTPUT)/vdso_test_getcpu: parse_vdso.c vdso_test_getcpu.c $(OUTPUT)/vdso_test_abi: parse_vdso.c vdso_test_abi.c $(OUTPUT)/vdso_test_clock_getres: vdso_test_clock_getres.c
-$(OUTPUT)/vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c -$(OUTPUT)/vdso_standalone_test_x86: CFLAGS +=-nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector +$(OUTPUT)/vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c | headers +$(OUTPUT)/vdso_standalone_test_x86: CFLAGS:=$(CFLAGS_NOLIBC) $(CFLAGS)
$(OUTPUT)/vdso_test_correctness: vdso_test_correctness.c $(OUTPUT)/vdso_test_correctness: LDFLAGS += -ldl diff --git a/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c b/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c deleted file mode 100644 index 500608f89c66b5747e3d845ebc54e4c3a35b6ccd..0000000000000000000000000000000000000000 --- a/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c +++ /dev/null @@ -1,167 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * vdso_test.c: Sample code to test parse_vdso.c on x86 - * Copyright (c) 2011-2014 Andy Lutomirski - * - * You can amuse yourself by compiling with: - * gcc -std=gnu99 -nostdlib - * -Os -fno-asynchronous-unwind-tables -flto -lgcc_s - * vdso_standalone_test_x86.c parse_vdso.c - * to generate a small binary. On x86_64, you can omit -lgcc_s - * if you want the binary to be completely standalone. - */ - -#include <sys/syscall.h> -#include <sys/time.h> -#include <unistd.h> -#include <stdint.h> -#include <linux/auxvec.h> - -#include "parse_vdso.h" - -/* We need some libc functions... */ -int strcmp(const char *a, const char *b) -{ - /* This implementation is buggy: it never returns -1. */ - while (*a || *b) { - if (*a != *b) - return 1; - if (*a == 0 || *b == 0) - return 1; - a++; - b++; - } - - return 0; -} - -/* - * The clang build needs this, although gcc does not. - * Stolen from lib/string.c. - */ -void *memcpy(void *dest, const void *src, size_t count) -{ - char *tmp = dest; - const char *s = src; - - while (count--) - *tmp++ = *s++; - return dest; -} - -/* ...and two syscalls. This is x86-specific. */ -static inline long x86_syscall3(long nr, long a0, long a1, long a2) -{ - long ret; -#ifdef __x86_64__ - asm volatile ("syscall" : "=a" (ret) : "a" (nr), - "D" (a0), "S" (a1), "d" (a2) : - "cc", "memory", "rcx", - "r8", "r9", "r10", "r11" ); -#else - asm volatile ("int $0x80" : "=a" (ret) : "a" (nr), - "b" (a0), "c" (a1), "d" (a2) : - "cc", "memory" ); -#endif - return ret; -} - -static inline long linux_write(int fd, const void *data, size_t len) -{ - return x86_syscall3(__NR_write, fd, (long)data, (long)len); -} - -static inline void linux_exit(int code) -{ - x86_syscall3(__NR_exit, code, 0, 0); -} - -void to_base10(char *lastdig, time_t n) -{ - while (n) { - *lastdig = (n % 10) + '0'; - n /= 10; - lastdig--; - } -} - -unsigned long getauxval(const unsigned long *auxv, unsigned long type) -{ - unsigned long ret; - - if (!auxv) - return 0; - - while (1) { - if (!auxv[0] && !auxv[1]) { - ret = 0; - break; - } - - if (auxv[0] == type) { - ret = auxv[1]; - break; - } - - auxv += 2; - } - - return ret; -} - -void c_main(void **stack) -{ - /* Parse the stack */ - long argc = (long)*stack; - stack += argc + 2; - - /* Now we're pointing at the environment. Skip it. */ - while(*stack) - stack++; - stack++; - - /* Now we're pointing at auxv. Initialize the vDSO parser. */ - vdso_init_from_sysinfo_ehdr(getauxval((unsigned long *)stack, AT_SYSINFO_EHDR)); - - /* Find gettimeofday. */ - typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz); - gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday"); - - if (!gtod) - linux_exit(1); - - struct timeval tv; - long ret = gtod(&tv, 0); - - if (ret == 0) { - char buf[] = "The time is .000000\n"; - to_base10(buf + 31, tv.tv_sec); - to_base10(buf + 38, tv.tv_usec); - linux_write(1, buf, sizeof(buf) - 1); - } else { - linux_exit(ret); - } - - linux_exit(0); -} - -/* - * This is the real entry point. It passes the initial stack into - * the C entry point. - */ -asm ( - ".text\n" - ".global _start\n" - ".type _start,@function\n" - "_start:\n\t" -#ifdef __x86_64__ - "mov %rsp,%rdi\n\t" - "and $-16,%rsp\n\t" - "sub $8,%rsp\n\t" - "jmp c_main" -#else - "push %esp\n\t" - "call c_main\n\t" - "int $3" -#endif - ); diff --git a/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c b/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c new file mode 120000 index 0000000000000000000000000000000000000000..4d3d96f1e440c965474681a6f35375a60b3921be --- /dev/null +++ b/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c @@ -0,0 +1 @@ +vdso_test_gettimeofday.c \ No newline at end of file
Le 03/02/2025 à 10:05, Thomas Weißschuh a écrit :
For testing the functionality of the vDSO, it is necessary to build userspace programs for multiple different architectures. It is additional work to acquire matching userspace cross-compilers with full C libraries and then building root images out of those. The kernel tree already contains nolibc, a small, header-only C library. By using it, it is possible to build userspace programs without any additional dependencies. For example the kernel.org crosstools or multi-target clang can be used to build test programs for a multitude of architectures. While nolibc is very limited, it is enough for many selftests. With some minor adjustments it is possible to make parse_vdso.c compatible with nolibc. As an example, vdso_standalone_test_x86 is now built from the same C code as the regular vdso_test_gettimeofday, while still being completely standalone.
This should probably go through the kselftest tree.
Not sure what are the expectations with this series.
I gave it a try with vdso_test_gettimeofday and get the following:
$ powerpc64-linux-gcc -nostdlib -nostdinc -ffreestanding -fno-asynchronous-unwind-tables -fno-stack-protector -include /home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/nolibc/nolibc.h -I/home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/nolibc/ -isystem /home/chleroy/linux-powerpc/tools/testing/selftests/../../../usr/include -std=gnu99 -O2 -D_GNU_SOURCE= -isystem /home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/uapi vdso_test_gettimeofday.c parse_vdso.c -o /home/chleroy/linux-powerpc/tools/testing/selftests/vDSO/vdso_test_gettimeofday
make: Entering directory '/home/chleroy/linux-powerpc/tools/testing/selftests/vDSO' powerpc64-linux-gcc -nostdlib -nostdinc -ffreestanding -fno-asynchronous-unwind-tables -fno-stack-protector -include /home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/nolibc/nolibc.h -I/home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/nolibc/ -isystem /home/chleroy/linux-powerpc/tools/testing/selftests/../../../usr/include -std=gnu99 -O2 -D_GNU_SOURCE= -isystem /home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/uapi vdso_test_gettimeofday.c parse_vdso.c -o /home/chleroy/linux-powerpc/tools/testing/selftests/vDSO/vdso_test_gettimeofday parse_vdso.c:38:34: error: unknown type name 'Elf64_Versym' 38 | #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x | ^~~ parse_vdso.c:39:33: note: in expansion of macro 'ELF_BITS_XFORM2' 39 | #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) | ^~~~~~~~~~~~~~~ parse_vdso.c:40:16: note: in expansion of macro 'ELF_BITS_XFORM' 40 | #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) | ^~~~~~~~~~~~~~ parse_vdso.c:63:9: note: in expansion of macro 'ELF' 63 | ELF(Versym) *versym; | ^~~ parse_vdso.c:38:34: error: unknown type name 'Elf64_Verdef' 38 | #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x | ^~~ parse_vdso.c:39:33: note: in expansion of macro 'ELF_BITS_XFORM2' 39 | #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) | ^~~~~~~~~~~~~~~ parse_vdso.c:40:16: note: in expansion of macro 'ELF_BITS_XFORM' 40 | #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) | ^~~~~~~~~~~~~~ parse_vdso.c:64:9: note: in expansion of macro 'ELF' 64 | ELF(Verdef) *verdef; | ^~~ parse_vdso.c: In function 'vdso_init_from_sysinfo_ehdr': parse_vdso.c:38:34: error: 'Elf64_Versym' undeclared (first use in this function); did you mean 'Elf64_Sym'? 38 | #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x | ^~~ parse_vdso.c:39:33: note: in expansion of macro 'ELF_BITS_XFORM2' 39 | #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) | ^~~~~~~~~~~~~~~ parse_vdso.c:40:16: note: in expansion of macro 'ELF_BITS_XFORM' 40 | #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) | ^~~~~~~~~~~~~~ parse_vdso.c:150:45: note: in expansion of macro 'ELF' 150 | vdso_info.versym = (ELF(Versym) *) | ^~~ parse_vdso.c:38:34: note: each undeclared identifier is reported only once for each function it appears in 38 | #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x | ^~~ parse_vdso.c:39:33: note: in expansion of macro 'ELF_BITS_XFORM2' 39 | #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) | ^~~~~~~~~~~~~~~ parse_vdso.c:40:16: note: in expansion of macro 'ELF_BITS_XFORM' 40 | #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) | ^~~~~~~~~~~~~~ parse_vdso.c:150:45: note: in expansion of macro 'ELF' 150 | vdso_info.versym = (ELF(Versym) *) | ^~~ parse_vdso.c:150:58: error: expected expression before ')' token 150 | vdso_info.versym = (ELF(Versym) *) | ^ parse_vdso.c:38:34: error: 'Elf64_Verdef' undeclared (first use in this function); did you mean 'Elf64_Word'? 38 | #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x | ^~~ parse_vdso.c:39:33: note: in expansion of macro 'ELF_BITS_XFORM2' 39 | #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) | ^~~~~~~~~~~~~~~ parse_vdso.c:40:16: note: in expansion of macro 'ELF_BITS_XFORM' 40 | #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) | ^~~~~~~~~~~~~~ parse_vdso.c:155:45: note: in expansion of macro 'ELF' 155 | vdso_info.verdef = (ELF(Verdef) *) | ^~~ parse_vdso.c:155:58: error: expected expression before ')' token 155 | vdso_info.verdef = (ELF(Verdef) *) | ^ parse_vdso.c: At top level: parse_vdso.c:38:34: error: unknown type name 'Elf64_Versym'; did you mean 'Elf64_Sym'? 38 | #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x | ^~~ parse_vdso.c:39:33: note: in expansion of macro 'ELF_BITS_XFORM2' 39 | #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) | ^~~~~~~~~~~~~~~ parse_vdso.c:40:16: note: in expansion of macro 'ELF_BITS_XFORM' 40 | #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) | ^~~~~~~~~~~~~~ parse_vdso.c:177:32: note: in expansion of macro 'ELF' 177 | static bool vdso_match_version(ELF(Versym) ver, | ^~~ parse_vdso.c: In function 'vdso_sym': parse_vdso.c:224:25: error: 'STN_UNDEF' undeclared (first use in this function); did you mean 'SHN_UNDEF'? 224 | for (; chain != STN_UNDEF; chain = vdso_info.chain[chain]) { | ^~~~~~~~~ | SHN_UNDEF parse_vdso.c:240:25: warning: implicit declaration of function 'vdso_match_version' [-Wimplicit-function-declaration] 240 | && !vdso_match_version(vdso_info.versym[chain], | ^~~~~~~~~~~~~~~~~~ make: *** [../lib.mk:222: /home/chleroy/linux-powerpc/tools/testing/selftests/vDSO/vdso_test_gettimeofday] Error 1 make: Leaving directory '/home/chleroy/linux-powerpc/tools/testing/selftests/vDSO'
Christophe
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de
Thomas Weißschuh (16): MAINTAINERS: Add vDSO selftests elf, uapi: Add definition for STN_UNDEF elf, uapi: Add definition for DT_GNU_HASH elf, uapi: Add definitions for VER_FLG_BASE and VER_FLG_WEAK elf, uapi: Add type ElfXX_Versym elf, uapi: Add types ElfXX_Verdef and ElfXX_Veraux tools/include: Add uapi/linux/elf.h selftests: Add headers target selftests: vDSO: vdso_standalone_test_x86: Use vdso_init_form_sysinfo_ehdr selftests: vDSO: parse_vdso: Drop vdso_init_from_auxv() selftests: vDSO: parse_vdso: Use UAPI headers instead of libc headers selftests: vDSO: parse_vdso: Test __SIZEOF_LONG__ instead of ULONG_MAX selftests: vDSO: parse_vdso: Make compatible with nolibc selftests: vDSO: vdso_test_gettimeofday: Clean up includes selftests: vDSO: vdso_test_gettimeofday: Make compatible with nolibc selftests: vDSO: vdso_standalone_test_x86: Switch to nolibc
MAINTAINERS | 1 + include/uapi/linux/elf.h | 38 ++ tools/include/uapi/linux/elf.h | 524 +++++++++++++++++++++ tools/testing/selftests/lib.mk | 5 +- tools/testing/selftests/vDSO/Makefile | 11 +- tools/testing/selftests/vDSO/parse_vdso.c | 21 +- tools/testing/selftests/vDSO/parse_vdso.h | 1 - .../selftests/vDSO/vdso_standalone_test_x86.c | 143 +----- .../selftests/vDSO/vdso_test_gettimeofday.c | 4 +- 9 files changed, 584 insertions(+), 164 deletions(-)
base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b change-id: 20241017-parse_vdso-nolibc-e069baa7ff48
Best regards,
On Mon, Feb 03, 2025 at 12:23:29PM +0100, Christophe Leroy wrote:
Le 03/02/2025 à 10:05, Thomas Weißschuh a écrit :
For testing the functionality of the vDSO, it is necessary to build userspace programs for multiple different architectures. It is additional work to acquire matching userspace cross-compilers with full C libraries and then building root images out of those. The kernel tree already contains nolibc, a small, header-only C library. By using it, it is possible to build userspace programs without any additional dependencies. For example the kernel.org crosstools or multi-target clang can be used to build test programs for a multitude of architectures. While nolibc is very limited, it is enough for many selftests. With some minor adjustments it is possible to make parse_vdso.c compatible with nolibc. As an example, vdso_standalone_test_x86 is now built from the same C code as the regular vdso_test_gettimeofday, while still being completely standalone.
This should probably go through the kselftest tree.
Not sure what are the expectations with this series.
In general it should also work for PPC, thanks for testing it.
I gave it a try with vdso_test_gettimeofday and get the following:
$ powerpc64-linux-gcc -nostdlib -nostdinc -ffreestanding -fno-asynchronous-unwind-tables -fno-stack-protector -include /home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/nolibc/nolibc.h -I/home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/nolibc/ -isystem /home/chleroy/linux-powerpc/tools/testing/selftests/../../../usr/include -std=gnu99 -O2 -D_GNU_SOURCE= -isystem /home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/uapi vdso_test_gettimeofday.c parse_vdso.c -o /home/chleroy/linux-powerpc/tools/testing/selftests/vDSO/vdso_test_gettimeofday
make: Entering directory '/home/chleroy/linux-powerpc/tools/testing/selftests/vDSO' powerpc64-linux-gcc -nostdlib -nostdinc -ffreestanding -fno-asynchronous-unwind-tables -fno-stack-protector -include /home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/nolibc/nolibc.h -I/home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/nolibc/ -isystem /home/chleroy/linux-powerpc/tools/testing/selftests/../../../usr/include -std=gnu99 -O2 -D_GNU_SOURCE= -isystem /home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/uapi vdso_test_gettimeofday.c parse_vdso.c -o /home/chleroy/linux-powerpc/tools/testing/selftests/vDSO/vdso_test_gettimeofday
This log is confusing. It contains traces of "make" output but no "make" invocation. I'm also not sure if there were two different compilations or only one. Can you give the full commandline? For your testing it should be enough to enable "vdso_test_standalone_x86" in the Makefile for PPC.
parse_vdso.c:38:34: error: unknown type name 'Elf64_Versym' 38 | #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x | ^~~ parse_vdso.c:39:33: note: in expansion of macro 'ELF_BITS_XFORM2' 39 | #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) | ^~~~~~~~~~~~~~~ parse_vdso.c:40:16: note: in expansion of macro 'ELF_BITS_XFORM' 40 | #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) | ^~~~~~~~~~~~~~ parse_vdso.c:63:9: note: in expansion of macro 'ELF' 63 | ELF(Versym) *versym; | ^~~ parse_vdso.c:38:34: error: unknown type name 'Elf64_Verdef' 38 | #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x | ^~~ parse_vdso.c:39:33: note: in expansion of macro 'ELF_BITS_XFORM2' 39 | #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) | ^~~~~~~~~~~~~~~ parse_vdso.c:40:16: note: in expansion of macro 'ELF_BITS_XFORM' 40 | #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) | ^~~~~~~~~~~~~~ parse_vdso.c:64:9: note: in expansion of macro 'ELF' 64 | ELF(Verdef) *verdef; | ^~~ parse_vdso.c: In function 'vdso_init_from_sysinfo_ehdr': parse_vdso.c:38:34: error: 'Elf64_Versym' undeclared (first use in this function); did you mean 'Elf64_Sym'? 38 | #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x | ^~~ parse_vdso.c:39:33: note: in expansion of macro 'ELF_BITS_XFORM2' 39 | #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) | ^~~~~~~~~~~~~~~ parse_vdso.c:40:16: note: in expansion of macro 'ELF_BITS_XFORM' 40 | #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) | ^~~~~~~~~~~~~~ parse_vdso.c:150:45: note: in expansion of macro 'ELF' 150 | vdso_info.versym = (ELF(Versym) *) | ^~~ parse_vdso.c:38:34: note: each undeclared identifier is reported only once for each function it appears in 38 | #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x | ^~~ parse_vdso.c:39:33: note: in expansion of macro 'ELF_BITS_XFORM2' 39 | #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) | ^~~~~~~~~~~~~~~ parse_vdso.c:40:16: note: in expansion of macro 'ELF_BITS_XFORM' 40 | #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) | ^~~~~~~~~~~~~~ parse_vdso.c:150:45: note: in expansion of macro 'ELF' 150 | vdso_info.versym = (ELF(Versym) *) | ^~~ parse_vdso.c:150:58: error: expected expression before ')' token 150 | vdso_info.versym = (ELF(Versym) *) | ^ parse_vdso.c:38:34: error: 'Elf64_Verdef' undeclared (first use in this function); did you mean 'Elf64_Word'? 38 | #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x | ^~~ parse_vdso.c:39:33: note: in expansion of macro 'ELF_BITS_XFORM2' 39 | #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) | ^~~~~~~~~~~~~~~ parse_vdso.c:40:16: note: in expansion of macro 'ELF_BITS_XFORM' 40 | #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) | ^~~~~~~~~~~~~~ parse_vdso.c:155:45: note: in expansion of macro 'ELF' 155 | vdso_info.verdef = (ELF(Verdef) *) | ^~~ parse_vdso.c:155:58: error: expected expression before ')' token 155 | vdso_info.verdef = (ELF(Verdef) *) | ^ parse_vdso.c: At top level: parse_vdso.c:38:34: error: unknown type name 'Elf64_Versym'; did you mean 'Elf64_Sym'? 38 | #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x | ^~~ parse_vdso.c:39:33: note: in expansion of macro 'ELF_BITS_XFORM2' 39 | #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) | ^~~~~~~~~~~~~~~ parse_vdso.c:40:16: note: in expansion of macro 'ELF_BITS_XFORM' 40 | #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) | ^~~~~~~~~~~~~~ parse_vdso.c:177:32: note: in expansion of macro 'ELF' 177 | static bool vdso_match_version(ELF(Versym) ver, | ^~~ parse_vdso.c: In function 'vdso_sym': parse_vdso.c:224:25: error: 'STN_UNDEF' undeclared (first use in this function); did you mean 'SHN_UNDEF'? 224 | for (; chain != STN_UNDEF; chain = vdso_info.chain[chain]) { | ^~~~~~~~~ | SHN_UNDEF parse_vdso.c:240:25: warning: implicit declaration of function 'vdso_match_version' [-Wimplicit-function-declaration] 240 | && !vdso_match_version(vdso_info.versym[chain], | ^~~~~~~~~~~~~~~~~~ make: *** [../lib.mk:222: /home/chleroy/linux-powerpc/tools/testing/selftests/vDSO/vdso_test_gettimeofday] Error 1 make: Leaving directory '/home/chleroy/linux-powerpc/tools/testing/selftests/vDSO'
Christophe
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de
Thomas Weißschuh (16): MAINTAINERS: Add vDSO selftests elf, uapi: Add definition for STN_UNDEF elf, uapi: Add definition for DT_GNU_HASH elf, uapi: Add definitions for VER_FLG_BASE and VER_FLG_WEAK elf, uapi: Add type ElfXX_Versym elf, uapi: Add types ElfXX_Verdef and ElfXX_Veraux tools/include: Add uapi/linux/elf.h selftests: Add headers target selftests: vDSO: vdso_standalone_test_x86: Use vdso_init_form_sysinfo_ehdr selftests: vDSO: parse_vdso: Drop vdso_init_from_auxv() selftests: vDSO: parse_vdso: Use UAPI headers instead of libc headers selftests: vDSO: parse_vdso: Test __SIZEOF_LONG__ instead of ULONG_MAX selftests: vDSO: parse_vdso: Make compatible with nolibc selftests: vDSO: vdso_test_gettimeofday: Clean up includes selftests: vDSO: vdso_test_gettimeofday: Make compatible with nolibc selftests: vDSO: vdso_standalone_test_x86: Switch to nolibc
MAINTAINERS | 1 + include/uapi/linux/elf.h | 38 ++ tools/include/uapi/linux/elf.h | 524 +++++++++++++++++++++ tools/testing/selftests/lib.mk | 5 +- tools/testing/selftests/vDSO/Makefile | 11 +- tools/testing/selftests/vDSO/parse_vdso.c | 21 +- tools/testing/selftests/vDSO/parse_vdso.h | 1 - .../selftests/vDSO/vdso_standalone_test_x86.c | 143 +----- .../selftests/vDSO/vdso_test_gettimeofday.c | 4 +- 9 files changed, 584 insertions(+), 164 deletions(-)
base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b change-id: 20241017-parse_vdso-nolibc-e069baa7ff48
Best regards,
Le 03/02/2025 à 14:50, Thomas Weißschuh a écrit :
On Mon, Feb 03, 2025 at 12:23:29PM +0100, Christophe Leroy wrote:
Le 03/02/2025 à 10:05, Thomas Weißschuh a écrit :
For testing the functionality of the vDSO, it is necessary to build userspace programs for multiple different architectures. It is additional work to acquire matching userspace cross-compilers with full C libraries and then building root images out of those. The kernel tree already contains nolibc, a small, header-only C library. By using it, it is possible to build userspace programs without any additional dependencies. For example the kernel.org crosstools or multi-target clang can be used to build test programs for a multitude of architectures. While nolibc is very limited, it is enough for many selftests. With some minor adjustments it is possible to make parse_vdso.c compatible with nolibc. As an example, vdso_standalone_test_x86 is now built from the same C code as the regular vdso_test_gettimeofday, while still being completely standalone.
This should probably go through the kselftest tree.
Not sure what are the expectations with this series.
In general it should also work for PPC, thanks for testing it.
I gave it a try with vdso_test_gettimeofday and get the following:
$ powerpc64-linux-gcc -nostdlib -nostdinc -ffreestanding -fno-asynchronous-unwind-tables -fno-stack-protector -include /home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/nolibc/nolibc.h -I/home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/nolibc/ -isystem /home/chleroy/linux-powerpc/tools/testing/selftests/../../../usr/include -std=gnu99 -O2 -D_GNU_SOURCE= -isystem /home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/uapi vdso_test_gettimeofday.c parse_vdso.c -o /home/chleroy/linux-powerpc/tools/testing/selftests/vDSO/vdso_test_gettimeofday
make: Entering directory '/home/chleroy/linux-powerpc/tools/testing/selftests/vDSO' powerpc64-linux-gcc -nostdlib -nostdinc -ffreestanding -fno-asynchronous-unwind-tables -fno-stack-protector -include /home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/nolibc/nolibc.h -I/home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/nolibc/ -isystem /home/chleroy/linux-powerpc/tools/testing/selftests/../../../usr/include -std=gnu99 -O2 -D_GNU_SOURCE= -isystem /home/chleroy/linux-powerpc/tools/testing/selftests/../../../tools/include/uapi vdso_test_gettimeofday.c parse_vdso.c -o /home/chleroy/linux-powerpc/tools/testing/selftests/vDSO/vdso_test_gettimeofday
This log is confusing. It contains traces of "make" output but no "make" invocation. I'm also not sure if there were two different compilations or only one. Can you give the full commandline? For your testing it should be enough to enable "vdso_test_standalone_x86" in the Makefile for PPC.
Well, yes I copied/pasted too much.
I made some hacky modifications to the Makefile but I forgot the '| header' pattern. With it added it works as expected.
Do you have any plan to get it work with nolibc for all test programs in selftests/vDSO, not only the standalone x86 test ?
Christophe
On Mon, Feb 03, 2025 at 04:43:22PM +0100, Christophe Leroy wrote: <snip>
Do you have any plan to get it work with nolibc for all test programs in selftests/vDSO, not only the standalone x86 test ?
Not directly as next step. I am focussing on some other work which will integrate (vDSO) selftests with nolibc slightly differently. However if you have interest in converting the tests now, that would be great and will also be useful for my future changes. The current issues I see: * Missing architecture support in nolibc (should be fairly easy to implement) * Missing kselftest_harness.h support in nolibc (I'm working on that) * Maybe some users want to stick with their regular libc (Nothing should prevent that, but the mechanism may need some discussion)
Thomas
linux-kselftest-mirror@lists.linaro.org