1 /* Support for writing ELF notes for RISC-V architectures
3 * Copyright (C) 2021 Huawei Technologies Co., Ltd
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2 or later, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "qemu/osdep.h"
21 #include "sysemu/dump.h"
23 /* struct user_regs_struct from arch/riscv/include/uapi/asm/ptrace.h */
24 struct riscv64_user_regs
{
29 QEMU_BUILD_BUG_ON(sizeof(struct riscv64_user_regs
) != 256);
31 /* struct elf_prstatus from include/linux/elfcore.h */
32 struct riscv64_elf_prstatus
{
33 char pad1
[32]; /* 32 == offsetof(struct elf_prstatus, pr_pid) */
35 char pad2
[76]; /* 76 == offsetof(struct elf_prstatus, pr_reg) -
36 offsetof(struct elf_prstatus, pr_ppid) */
37 struct riscv64_user_regs pr_reg
;
41 QEMU_BUILD_BUG_ON(sizeof(struct riscv64_elf_prstatus
) != 376);
45 char name
[8]; /* align_up(sizeof("CORE"), 4) */
46 struct riscv64_elf_prstatus prstatus
;
49 #define RISCV64_NOTE_HEADER_SIZE offsetof(struct riscv64_note, prstatus)
50 #define RISCV64_PRSTATUS_NOTE_SIZE \
51 (RISCV64_NOTE_HEADER_SIZE + sizeof(struct riscv64_elf_prstatus))
53 static void riscv64_note_init(struct riscv64_note
*note
, DumpState
*s
,
54 const char *name
, Elf64_Word namesz
,
55 Elf64_Word type
, Elf64_Word descsz
)
57 memset(note
, 0, sizeof(*note
));
59 note
->hdr
.n_namesz
= cpu_to_dump32(s
, namesz
);
60 note
->hdr
.n_descsz
= cpu_to_dump32(s
, descsz
);
61 note
->hdr
.n_type
= cpu_to_dump32(s
, type
);
63 memcpy(note
->name
, name
, namesz
);
66 int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f
, CPUState
*cs
,
67 int cpuid
, void *opaque
)
69 struct riscv64_note note
;
70 RISCVCPU
*cpu
= RISCV_CPU(cs
);
71 CPURISCVState
*env
= &cpu
->env
;
72 DumpState
*s
= opaque
;
74 const char name
[] = "CORE";
76 riscv64_note_init(¬e
, s
, name
, sizeof(name
),
77 NT_PRSTATUS
, sizeof(note
.prstatus
));
79 note
.prstatus
.pr_pid
= cpu_to_dump32(s
, cpuid
);
81 note
.prstatus
.pr_reg
.pc
= cpu_to_dump64(s
, env
->pc
);
83 for (i
= 0; i
< 31; i
++) {
84 note
.prstatus
.pr_reg
.regs
[i
] = cpu_to_dump64(s
, env
->gpr
[i
+ 1]);
87 ret
= f(¬e
, RISCV64_PRSTATUS_NOTE_SIZE
, s
);
95 struct riscv32_user_regs
{
100 QEMU_BUILD_BUG_ON(sizeof(struct riscv32_user_regs
) != 128);
102 struct riscv32_elf_prstatus
{
103 char pad1
[24]; /* 24 == offsetof(struct elf_prstatus, pr_pid) */
105 char pad2
[44]; /* 44 == offsetof(struct elf_prstatus, pr_reg) -
106 offsetof(struct elf_prstatus, pr_ppid) */
107 struct riscv32_user_regs pr_reg
;
111 QEMU_BUILD_BUG_ON(sizeof(struct riscv32_elf_prstatus
) != 204);
113 struct riscv32_note
{
115 char name
[8]; /* align_up(sizeof("CORE"), 4) */
116 struct riscv32_elf_prstatus prstatus
;
119 #define RISCV32_NOTE_HEADER_SIZE offsetof(struct riscv32_note, prstatus)
120 #define RISCV32_PRSTATUS_NOTE_SIZE \
121 (RISCV32_NOTE_HEADER_SIZE + sizeof(struct riscv32_elf_prstatus))
123 static void riscv32_note_init(struct riscv32_note
*note
, DumpState
*s
,
124 const char *name
, Elf32_Word namesz
,
125 Elf32_Word type
, Elf32_Word descsz
)
127 memset(note
, 0, sizeof(*note
));
129 note
->hdr
.n_namesz
= cpu_to_dump32(s
, namesz
);
130 note
->hdr
.n_descsz
= cpu_to_dump32(s
, descsz
);
131 note
->hdr
.n_type
= cpu_to_dump32(s
, type
);
133 memcpy(note
->name
, name
, namesz
);
136 int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f
, CPUState
*cs
,
137 int cpuid
, void *opaque
)
139 struct riscv32_note note
;
140 RISCVCPU
*cpu
= RISCV_CPU(cs
);
141 CPURISCVState
*env
= &cpu
->env
;
142 DumpState
*s
= opaque
;
144 const char name
[] = "CORE";
146 riscv32_note_init(¬e
, s
, name
, sizeof(name
),
147 NT_PRSTATUS
, sizeof(note
.prstatus
));
149 note
.prstatus
.pr_pid
= cpu_to_dump32(s
, cpuid
);
151 note
.prstatus
.pr_reg
.pc
= cpu_to_dump32(s
, env
->pc
);
153 for (i
= 0; i
< 31; i
++) {
154 note
.prstatus
.pr_reg
.regs
[i
] = cpu_to_dump32(s
, env
->gpr
[i
+ 1]);
157 ret
= f(¬e
, RISCV32_PRSTATUS_NOTE_SIZE
, s
);
165 int cpu_get_dump_info(ArchDumpInfo
*info
,
166 const GuestPhysBlockList
*guest_phys_blocks
)
171 if (first_cpu
== NULL
) {
174 cpu
= RISCV_CPU(first_cpu
);
177 info
->d_machine
= EM_RISCV
;
179 #if defined(TARGET_RISCV64)
180 info
->d_class
= ELFCLASS64
;
182 info
->d_class
= ELFCLASS32
;
185 info
->d_endian
= (env
->mstatus
& MSTATUS_UBE
) != 0
186 ? ELFDATA2MSB
: ELFDATA2LSB
;
191 ssize_t
cpu_get_note_size(int class, int machine
, int nr_cpus
)
195 if (class == ELFCLASS64
) {
196 note_size
= RISCV64_PRSTATUS_NOTE_SIZE
;
198 note_size
= RISCV32_PRSTATUS_NOTE_SIZE
;
201 return note_size
* nr_cpus
;