Provide FPU buffer layout in core dumps:

Debuggers have guess the FPU buffer layout in core dumps, which is error
   prone. This is because AMD and Intel layouts differ.
 
   To avoid buggy heuristics add a ELF section which describes the buffer
   layout which can be retrieved by tools.
 -----BEGIN PGP SIGNATURE-----
 
 iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAmbpOuwTHHRnbHhAbGlu
 dXRyb25peC5kZQAKCRCmGPVMDXSYoTRAEACGHPdAYFp5A396c9qUbHUE2gEKIad2
 iuq15TZKLPY/LFqfTwnkp9/nqKtZ0gj4D6XCIucWZjwWJuPgvgGf/tC9Fk+H+C6X
 9+rycP3GdqxU28qLxA428SN2Pg3lvqG4rryVWeHUXQ4x8A0DSMV+3pkNY5YgJ+2+
 fTzNzVi2tkPRAXhKmj3EdcFcgDPiFQBMm1QNBpc+FqrXk4rjJb9Axln0oT8xemDv
 TtJ5BMhFpR73naaiS4IrK8Tk3oFCa8CmafCQfl1zAOor/+EemPQKwMuGeiXE7dLG
 eE+OTw5zuxYwlc9WoaPmM/ZiEc5JptpHQUtyHDBN7BaK87VKjsupAXXVOh6XMRCt
 R2coqq7fqDqMANwWpUKddky3vSwbst1GZpXGAENOy64yU4VoFutr616WSj3sJfUi
 knBauPqLAFeZLhMn/kKr5a0rBgm7VuQSlGPYEhqVdaM3Eb/zJEupFL/bTpqQbbz/
 8lo2hYcfDslhShcEZYBwm4eUg+ytZ96K3ciZ5YgNih9LFBxEOo0SY1CqbQJiRtpB
 3DmgldYtzRdQq5/JtFGNv717uMESn5khG3qHUpXtrDhWfD8spMWiY1yO/cwWvLFJ
 ZS5ATp1dAt1Pbv2MC6r9jQBbW3V7xNNAOJdzUvIZPP04PKeV0ObFOplxhabOzUDj
 OLquyIrjpxeisg==
 =Vqqo
 -----END PGP SIGNATURE-----

Merge tag 'x86-fpu-2024-09-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fpu updates from Thomas Gleixner:
 "Provide FPU buffer layout in core dumps:

  Debuggers have guess the FPU buffer layout in core dumps, which is
  error prone. This is because AMD and Intel layouts differ.

  To avoid buggy heuristics add a ELF section which describes the buffer
  layout which can be retrieved by tools"

* tag 'x86-fpu-2024-09-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/elf: Add a new FPU buffer layout info to x86 core files
This commit is contained in:
Linus Torvalds 2024-09-17 14:46:17 +02:00
commit c3056a7d14
5 changed files with 109 additions and 2 deletions

View File

@ -107,6 +107,7 @@ config X86
select ARCH_HAS_DEBUG_WX
select ARCH_HAS_ZONE_DMA_SET if EXPERT
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_HAVE_EXTRA_ELF_NOTES
select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE
select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
select ARCH_MIGHT_HAVE_PC_PARPORT

View File

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_ASM_X86_ELF_H
#define _UAPI_ASM_X86_ELF_H
#include <linux/types.h>
struct x86_xfeat_component {
__u32 type;
__u32 size;
__u32 offset;
__u32 flags;
} __packed;
_Static_assert(sizeof(struct x86_xfeat_component) % 4 == 0, "x86_xfeat_component is not aligned");
#endif /* _UAPI_ASM_X86_ELF_H */

View File

@ -13,6 +13,7 @@
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <linux/vmalloc.h>
#include <linux/coredump.h>
#include <asm/fpu/api.h>
#include <asm/fpu/regset.h>
@ -23,6 +24,8 @@
#include <asm/prctl.h>
#include <asm/elf.h>
#include <uapi/asm/elf.h>
#include "context.h"
#include "internal.h"
#include "legacy.h"
@ -1841,3 +1844,89 @@ int proc_pid_arch_status(struct seq_file *m, struct pid_namespace *ns,
return 0;
}
#endif /* CONFIG_PROC_PID_ARCH_STATUS */
#ifdef CONFIG_COREDUMP
static const char owner_name[] = "LINUX";
/*
* Dump type, size, offset and flag values for every xfeature that is present.
*/
static int dump_xsave_layout_desc(struct coredump_params *cprm)
{
int num_records = 0;
int i;
for_each_extended_xfeature(i, fpu_user_cfg.max_features) {
struct x86_xfeat_component xc = {
.type = i,
.size = xstate_sizes[i],
.offset = xstate_offsets[i],
/* reserved for future use */
.flags = 0,
};
if (!dump_emit(cprm, &xc, sizeof(xc)))
return 0;
num_records++;
}
return num_records;
}
static u32 get_xsave_desc_size(void)
{
u32 cnt = 0;
u32 i;
for_each_extended_xfeature(i, fpu_user_cfg.max_features)
cnt++;
return cnt * (sizeof(struct x86_xfeat_component));
}
int elf_coredump_extra_notes_write(struct coredump_params *cprm)
{
int num_records = 0;
struct elf_note en;
if (!fpu_user_cfg.max_features)
return 0;
en.n_namesz = sizeof(owner_name);
en.n_descsz = get_xsave_desc_size();
en.n_type = NT_X86_XSAVE_LAYOUT;
if (!dump_emit(cprm, &en, sizeof(en)))
return 1;
if (!dump_emit(cprm, owner_name, en.n_namesz))
return 1;
if (!dump_align(cprm, 4))
return 1;
num_records = dump_xsave_layout_desc(cprm);
if (!num_records)
return 1;
/* Total size should be equal to the number of records */
if ((sizeof(struct x86_xfeat_component) * num_records) != en.n_descsz)
return 1;
return 0;
}
int elf_coredump_extra_notes_size(void)
{
int size;
if (!fpu_user_cfg.max_features)
return 0;
/* .note header */
size = sizeof(struct elf_note);
/* Name plus alignment to 4 bytes */
size += roundup(sizeof(owner_name), 4);
size += get_xsave_desc_size();
return size;
}
#endif /* CONFIG_COREDUMP */

View File

@ -2039,7 +2039,7 @@ static int elf_core_dump(struct coredump_params *cprm)
{
size_t sz = info.size;
/* For cell spufs */
/* For cell spufs and x86 xstate */
sz += elf_coredump_extra_notes_size();
phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
@ -2103,7 +2103,7 @@ static int elf_core_dump(struct coredump_params *cprm)
if (!write_note_info(&info, cprm))
goto end_coredump;
/* For cell spufs */
/* For cell spufs and x86 xstate */
if (elf_coredump_extra_notes_write(cprm))
goto end_coredump;

View File

@ -411,6 +411,7 @@ typedef struct elf64_shdr {
#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 */