blob: 434c8a3dbb7cf388bb398031ce3505c982eda72c [file] [log] [blame]
Weiwei Li3b572542023-04-05 16:58:12 +08001/*
2 * Support for writing ELF notes for RISC-V architectures
Yifei Jiang43a96582021-02-01 20:44:58 +08003 *
4 * Copyright (C) 2021 Huawei Technologies Co., Ltd
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2 or later, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "qemu/osdep.h"
20#include "cpu.h"
21#include "elf.h"
22#include "sysemu/dump.h"
23
24/* struct user_regs_struct from arch/riscv/include/uapi/asm/ptrace.h */
25struct riscv64_user_regs {
26 uint64_t pc;
27 uint64_t regs[31];
28} QEMU_PACKED;
29
30QEMU_BUILD_BUG_ON(sizeof(struct riscv64_user_regs) != 256);
31
32/* struct elf_prstatus from include/linux/elfcore.h */
33struct riscv64_elf_prstatus {
34 char pad1[32]; /* 32 == offsetof(struct elf_prstatus, pr_pid) */
35 uint32_t pr_pid;
36 char pad2[76]; /* 76 == offsetof(struct elf_prstatus, pr_reg) -
37 offsetof(struct elf_prstatus, pr_ppid) */
38 struct riscv64_user_regs pr_reg;
39 char pad3[8];
40} QEMU_PACKED;
41
42QEMU_BUILD_BUG_ON(sizeof(struct riscv64_elf_prstatus) != 376);
43
44struct riscv64_note {
45 Elf64_Nhdr hdr;
46 char name[8]; /* align_up(sizeof("CORE"), 4) */
47 struct riscv64_elf_prstatus prstatus;
48} QEMU_PACKED;
49
50#define RISCV64_NOTE_HEADER_SIZE offsetof(struct riscv64_note, prstatus)
51#define RISCV64_PRSTATUS_NOTE_SIZE \
52 (RISCV64_NOTE_HEADER_SIZE + sizeof(struct riscv64_elf_prstatus))
53
54static void riscv64_note_init(struct riscv64_note *note, DumpState *s,
55 const char *name, Elf64_Word namesz,
56 Elf64_Word type, Elf64_Word descsz)
57{
58 memset(note, 0, sizeof(*note));
59
60 note->hdr.n_namesz = cpu_to_dump32(s, namesz);
61 note->hdr.n_descsz = cpu_to_dump32(s, descsz);
62 note->hdr.n_type = cpu_to_dump32(s, type);
63
64 memcpy(note->name, name, namesz);
65}
66
67int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
Janosch Frank1af00062022-08-11 12:10:54 +000068 int cpuid, DumpState *s)
Yifei Jiang43a96582021-02-01 20:44:58 +080069{
70 struct riscv64_note note;
71 RISCVCPU *cpu = RISCV_CPU(cs);
72 CPURISCVState *env = &cpu->env;
Yifei Jiang43a96582021-02-01 20:44:58 +080073 int ret, i = 0;
74 const char name[] = "CORE";
75
76 riscv64_note_init(&note, s, name, sizeof(name),
77 NT_PRSTATUS, sizeof(note.prstatus));
78
79 note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
80
81 note.prstatus.pr_reg.pc = cpu_to_dump64(s, env->pc);
82
83 for (i = 0; i < 31; i++) {
84 note.prstatus.pr_reg.regs[i] = cpu_to_dump64(s, env->gpr[i + 1]);
85 }
86
87 ret = f(&note, RISCV64_PRSTATUS_NOTE_SIZE, s);
88 if (ret < 0) {
89 return -1;
90 }
91
92 return ret;
93}
94
95struct riscv32_user_regs {
96 uint32_t pc;
97 uint32_t regs[31];
98} QEMU_PACKED;
99
100QEMU_BUILD_BUG_ON(sizeof(struct riscv32_user_regs) != 128);
101
102struct riscv32_elf_prstatus {
103 char pad1[24]; /* 24 == offsetof(struct elf_prstatus, pr_pid) */
104 uint32_t 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;
108 char pad3[4];
109} QEMU_PACKED;
110
111QEMU_BUILD_BUG_ON(sizeof(struct riscv32_elf_prstatus) != 204);
112
113struct riscv32_note {
114 Elf32_Nhdr hdr;
115 char name[8]; /* align_up(sizeof("CORE"), 4) */
116 struct riscv32_elf_prstatus prstatus;
117} QEMU_PACKED;
118
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))
122
123static void riscv32_note_init(struct riscv32_note *note, DumpState *s,
124 const char *name, Elf32_Word namesz,
125 Elf32_Word type, Elf32_Word descsz)
126{
127 memset(note, 0, sizeof(*note));
128
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);
132
133 memcpy(note->name, name, namesz);
134}
135
136int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
Janosch Frank1af00062022-08-11 12:10:54 +0000137 int cpuid, DumpState *s)
Yifei Jiang43a96582021-02-01 20:44:58 +0800138{
139 struct riscv32_note note;
140 RISCVCPU *cpu = RISCV_CPU(cs);
141 CPURISCVState *env = &cpu->env;
Yifei Jiang43a96582021-02-01 20:44:58 +0800142 int ret, i;
143 const char name[] = "CORE";
144
145 riscv32_note_init(&note, s, name, sizeof(name),
146 NT_PRSTATUS, sizeof(note.prstatus));
147
148 note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
149
150 note.prstatus.pr_reg.pc = cpu_to_dump32(s, env->pc);
151
152 for (i = 0; i < 31; i++) {
153 note.prstatus.pr_reg.regs[i] = cpu_to_dump32(s, env->gpr[i + 1]);
154 }
155
156 ret = f(&note, RISCV32_PRSTATUS_NOTE_SIZE, s);
157 if (ret < 0) {
158 return -1;
159 }
160
161 return ret;
162}
163
164int cpu_get_dump_info(ArchDumpInfo *info,
165 const GuestPhysBlockList *guest_phys_blocks)
166{
167 RISCVCPU *cpu;
168 CPURISCVState *env;
169
170 if (first_cpu == NULL) {
171 return -1;
172 }
173 cpu = RISCV_CPU(first_cpu);
174 env = &cpu->env;
175
176 info->d_machine = EM_RISCV;
177
178#if defined(TARGET_RISCV64)
179 info->d_class = ELFCLASS64;
180#else
181 info->d_class = ELFCLASS32;
182#endif
183
Weiwei Lic45eff32023-04-05 16:58:11 +0800184 info->d_endian = (env->mstatus & MSTATUS_UBE) != 0 ?
185 ELFDATA2MSB : ELFDATA2LSB;
Yifei Jiang43a96582021-02-01 20:44:58 +0800186
187 return 0;
188}
189
190ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
191{
192 size_t note_size;
193
194 if (class == ELFCLASS64) {
195 note_size = RISCV64_PRSTATUS_NOTE_SIZE;
196 } else {
197 note_size = RISCV32_PRSTATUS_NOTE_SIZE;
198 }
199
200 return note_size * nr_cpus;
201}