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(¬e, 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(¬e, 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(¬e, 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(¬e, 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