1 /* Support for writing ELF notes for ARM architectures
3 * Copyright (C) 2015 Red Hat Inc.
5 * Author: Andrew Jones <drjones@redhat.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "sysemu/dump.h"
25 /* struct user_pt_regs from arch/arm64/include/uapi/asm/ptrace.h */
26 struct aarch64_user_regs
{
33 QEMU_BUILD_BUG_ON(sizeof(struct aarch64_user_regs
) != 272);
35 /* struct elf_prstatus from include/uapi/linux/elfcore.h */
36 struct aarch64_elf_prstatus
{
37 char pad1
[32]; /* 32 == offsetof(struct elf_prstatus, pr_pid) */
39 char pad2
[76]; /* 76 == offsetof(struct elf_prstatus, pr_reg) -
40 offsetof(struct elf_prstatus, pr_ppid) */
41 struct aarch64_user_regs pr_reg
;
46 QEMU_BUILD_BUG_ON(sizeof(struct aarch64_elf_prstatus
) != 392);
48 /* struct user_fpsimd_state from arch/arm64/include/uapi/asm/ptrace.h
50 * While the vregs member of user_fpsimd_state is of type __uint128_t,
51 * QEMU uses an array of uint64_t, where the high half of the 128-bit
52 * value is always in the 2n+1'th index. Thus we also break the 128-
53 * bit values into two halves in this reproduction of user_fpsimd_state.
55 struct aarch64_user_vfp_state
{
62 QEMU_BUILD_BUG_ON(sizeof(struct aarch64_user_vfp_state
) != 528);
66 char name
[8]; /* align_up(sizeof("CORE"), 4) */
68 struct aarch64_elf_prstatus prstatus
;
69 struct aarch64_user_vfp_state vfp
;
73 #define AARCH64_NOTE_HEADER_SIZE offsetof(struct aarch64_note, prstatus)
74 #define AARCH64_PRSTATUS_NOTE_SIZE \
75 (AARCH64_NOTE_HEADER_SIZE + sizeof(struct aarch64_elf_prstatus))
76 #define AARCH64_PRFPREG_NOTE_SIZE \
77 (AARCH64_NOTE_HEADER_SIZE + sizeof(struct aarch64_user_vfp_state))
79 static void aarch64_note_init(struct aarch64_note
*note
, DumpState
*s
,
80 const char *name
, Elf64_Word namesz
,
81 Elf64_Word type
, Elf64_Word descsz
)
83 memset(note
, 0, sizeof(*note
));
85 note
->hdr
.n_namesz
= cpu_to_dump32(s
, namesz
);
86 note
->hdr
.n_descsz
= cpu_to_dump32(s
, descsz
);
87 note
->hdr
.n_type
= cpu_to_dump32(s
, type
);
89 memcpy(note
->name
, name
, namesz
);
92 static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f
,
93 CPUARMState
*env
, int cpuid
,
96 struct aarch64_note note
;
99 aarch64_note_init(¬e
, s
, "CORE", 5, NT_PRFPREG
, sizeof(note
.vfp
));
101 for (i
= 0; i
< 64; ++i
) {
102 note
.vfp
.vregs
[i
] = cpu_to_dump64(s
, float64_val(env
->vfp
.regs
[i
]));
105 if (s
->dump_info
.d_endian
== ELFDATA2MSB
) {
106 /* For AArch64 we must always swap the vfp.regs's 2n and 2n+1
107 * entries when generating BE notes, because even big endian
108 * hosts use 2n+1 for the high half.
110 for (i
= 0; i
< 32; ++i
) {
111 uint64_t tmp
= note
.vfp
.vregs
[2*i
];
112 note
.vfp
.vregs
[2*i
] = note
.vfp
.vregs
[2*i
+1];
113 note
.vfp
.vregs
[2*i
+1] = tmp
;
117 note
.vfp
.fpsr
= cpu_to_dump32(s
, vfp_get_fpsr(env
));
118 note
.vfp
.fpcr
= cpu_to_dump32(s
, vfp_get_fpcr(env
));
120 ret
= f(¬e
, AARCH64_PRFPREG_NOTE_SIZE
, s
);
128 int arm_cpu_write_elf64_note(WriteCoreDumpFunction f
, CPUState
*cs
,
129 int cpuid
, void *opaque
)
131 struct aarch64_note note
;
132 CPUARMState
*env
= &ARM_CPU(cs
)->env
;
133 DumpState
*s
= opaque
;
137 aarch64_note_init(¬e
, s
, "CORE", 5, NT_PRSTATUS
, sizeof(note
.prstatus
));
139 note
.prstatus
.pr_pid
= cpu_to_dump32(s
, cpuid
);
140 note
.prstatus
.pr_fpvalid
= cpu_to_dump32(s
, 1);
143 aarch64_sync_32_to_64(env
);
144 pstate
= cpsr_read(env
);
147 pstate
= pstate_read(env
);
151 for (i
= 0; i
< 31; ++i
) {
152 note
.prstatus
.pr_reg
.regs
[i
] = cpu_to_dump64(s
, env
->xregs
[i
]);
154 note
.prstatus
.pr_reg
.sp
= cpu_to_dump64(s
, sp
);
155 note
.prstatus
.pr_reg
.pc
= cpu_to_dump64(s
, env
->pc
);
156 note
.prstatus
.pr_reg
.pstate
= cpu_to_dump64(s
, pstate
);
158 ret
= f(¬e
, AARCH64_PRSTATUS_NOTE_SIZE
, s
);
163 return aarch64_write_elf64_prfpreg(f
, env
, cpuid
, s
);
166 /* struct pt_regs from arch/arm/include/asm/ptrace.h */
167 struct arm_user_regs
{
172 QEMU_BUILD_BUG_ON(sizeof(struct arm_user_regs
) != 72);
174 /* struct elf_prstatus from include/uapi/linux/elfcore.h */
175 struct arm_elf_prstatus
{
176 char pad1
[24]; /* 24 == offsetof(struct elf_prstatus, pr_pid) */
178 char pad2
[44]; /* 44 == offsetof(struct elf_prstatus, pr_reg) -
179 offsetof(struct elf_prstatus, pr_ppid) */
180 struct arm_user_regs pr_reg
;
182 } QEMU_PACKED arm_elf_prstatus
;
184 QEMU_BUILD_BUG_ON(sizeof(struct arm_elf_prstatus
) != 148);
186 /* struct user_vfp from arch/arm/include/asm/user.h */
187 struct arm_user_vfp_state
{
192 QEMU_BUILD_BUG_ON(sizeof(struct arm_user_vfp_state
) != 260);
196 char name
[8]; /* align_up(sizeof("LINUX"), 4) */
198 struct arm_elf_prstatus prstatus
;
199 struct arm_user_vfp_state vfp
;
203 #define ARM_NOTE_HEADER_SIZE offsetof(struct arm_note, prstatus)
204 #define ARM_PRSTATUS_NOTE_SIZE \
205 (ARM_NOTE_HEADER_SIZE + sizeof(struct arm_elf_prstatus))
206 #define ARM_VFP_NOTE_SIZE \
207 (ARM_NOTE_HEADER_SIZE + sizeof(struct arm_user_vfp_state))
209 static void arm_note_init(struct arm_note
*note
, DumpState
*s
,
210 const char *name
, Elf32_Word namesz
,
211 Elf32_Word type
, Elf32_Word descsz
)
213 memset(note
, 0, sizeof(*note
));
215 note
->hdr
.n_namesz
= cpu_to_dump32(s
, namesz
);
216 note
->hdr
.n_descsz
= cpu_to_dump32(s
, descsz
);
217 note
->hdr
.n_type
= cpu_to_dump32(s
, type
);
219 memcpy(note
->name
, name
, namesz
);
222 static int arm_write_elf32_vfp(WriteCoreDumpFunction f
, CPUARMState
*env
,
223 int cpuid
, DumpState
*s
)
225 struct arm_note note
;
228 arm_note_init(¬e
, s
, "LINUX", 6, NT_ARM_VFP
, sizeof(note
.vfp
));
230 for (i
= 0; i
< 32; ++i
) {
231 note
.vfp
.vregs
[i
] = cpu_to_dump64(s
, float64_val(env
->vfp
.regs
[i
]));
234 note
.vfp
.fpscr
= cpu_to_dump32(s
, vfp_get_fpscr(env
));
236 ret
= f(¬e
, ARM_VFP_NOTE_SIZE
, s
);
244 int arm_cpu_write_elf32_note(WriteCoreDumpFunction f
, CPUState
*cs
,
245 int cpuid
, void *opaque
)
247 struct arm_note note
;
248 CPUARMState
*env
= &ARM_CPU(cs
)->env
;
249 DumpState
*s
= opaque
;
250 int ret
, i
, fpvalid
= !!arm_feature(env
, ARM_FEATURE_VFP
);
252 arm_note_init(¬e
, s
, "CORE", 5, NT_PRSTATUS
, sizeof(note
.prstatus
));
254 note
.prstatus
.pr_pid
= cpu_to_dump32(s
, cpuid
);
255 note
.prstatus
.pr_fpvalid
= cpu_to_dump32(s
, fpvalid
);
257 for (i
= 0; i
< 16; ++i
) {
258 note
.prstatus
.pr_reg
.regs
[i
] = cpu_to_dump32(s
, env
->regs
[i
]);
260 note
.prstatus
.pr_reg
.regs
[16] = cpu_to_dump32(s
, cpsr_read(env
));
262 ret
= f(¬e
, ARM_PRSTATUS_NOTE_SIZE
, s
);
265 } else if (fpvalid
) {
266 return arm_write_elf32_vfp(f
, env
, cpuid
, s
);
272 int cpu_get_dump_info(ArchDumpInfo
*info
,
273 const GuestPhysBlockList
*guest_phys_blocks
)
275 ARMCPU
*cpu
= ARM_CPU(first_cpu
);
276 CPUARMState
*env
= &cpu
->env
;
277 GuestPhysBlock
*block
;
278 hwaddr lowest_addr
= ULLONG_MAX
;
280 /* Take a best guess at the phys_base. If we get it wrong then crash
281 * will need '--machdep phys_offset=<phys-offset>' added to its command
282 * line, which isn't any worse than assuming we can use zero, but being
283 * wrong. This is the same algorithm the crash utility uses when
284 * attempting to guess as it loads non-dumpfile formatted files.
286 QTAILQ_FOREACH(block
, &guest_phys_blocks
->head
, next
) {
287 if (block
->target_start
< lowest_addr
) {
288 lowest_addr
= block
->target_start
;
292 if (arm_feature(env
, ARM_FEATURE_AARCH64
)) {
293 info
->d_machine
= EM_AARCH64
;
294 info
->d_class
= ELFCLASS64
;
295 info
->page_size
= (1 << 16); /* aarch64 max pagesize */
296 if (lowest_addr
!= ULLONG_MAX
) {
297 info
->phys_base
= lowest_addr
;
300 info
->d_machine
= EM_ARM
;
301 info
->d_class
= ELFCLASS32
;
302 info
->page_size
= (1 << 12);
303 if (lowest_addr
< UINT_MAX
) {
304 info
->phys_base
= lowest_addr
;
308 /* We assume the relevant endianness is that of EL1; this is right
309 * for kernels, but might give the wrong answer if you're trying to
310 * dump a hypervisor that happens to be running an opposite-endian
313 info
->d_endian
= (env
->cp15
.sctlr_el
[1] & SCTLR_EE
) != 0
314 ? ELFDATA2MSB
: ELFDATA2LSB
;
319 ssize_t
cpu_get_note_size(int class, int machine
, int nr_cpus
)
321 ARMCPU
*cpu
= ARM_CPU(first_cpu
);
322 CPUARMState
*env
= &cpu
->env
;
325 if (class == ELFCLASS64
) {
326 note_size
= AARCH64_PRSTATUS_NOTE_SIZE
;
327 note_size
+= AARCH64_PRFPREG_NOTE_SIZE
;
329 note_size
= ARM_PRSTATUS_NOTE_SIZE
;
330 if (arm_feature(env
, ARM_FEATURE_VFP
)) {
331 note_size
+= ARM_VFP_NOTE_SIZE
;
335 return note_size
* nr_cpus
;