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