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/>.
21 #include "qemu/osdep.h"
24 #include "sysemu/dump.h"
26 /* struct user_pt_regs from arch/arm64/include/uapi/asm/ptrace.h */
27 struct aarch64_user_regs
{
34 QEMU_BUILD_BUG_ON(sizeof(struct aarch64_user_regs
) != 272);
36 /* struct elf_prstatus from include/uapi/linux/elfcore.h */
37 struct aarch64_elf_prstatus
{
38 char pad1
[32]; /* 32 == offsetof(struct elf_prstatus, pr_pid) */
40 char pad2
[76]; /* 76 == offsetof(struct elf_prstatus, pr_reg) -
41 offsetof(struct elf_prstatus, pr_ppid) */
42 struct aarch64_user_regs pr_reg
;
47 QEMU_BUILD_BUG_ON(sizeof(struct aarch64_elf_prstatus
) != 392);
49 /* struct user_fpsimd_state from arch/arm64/include/uapi/asm/ptrace.h
51 * While the vregs member of user_fpsimd_state is of type __uint128_t,
52 * QEMU uses an array of uint64_t, where the high half of the 128-bit
53 * value is always in the 2n+1'th index. Thus we also break the 128-
54 * bit values into two halves in this reproduction of user_fpsimd_state.
56 struct aarch64_user_vfp_state
{
63 QEMU_BUILD_BUG_ON(sizeof(struct aarch64_user_vfp_state
) != 528);
67 char name
[8]; /* align_up(sizeof("CORE"), 4) */
69 struct aarch64_elf_prstatus prstatus
;
70 struct aarch64_user_vfp_state vfp
;
74 #define AARCH64_NOTE_HEADER_SIZE offsetof(struct aarch64_note, prstatus)
75 #define AARCH64_PRSTATUS_NOTE_SIZE \
76 (AARCH64_NOTE_HEADER_SIZE + sizeof(struct aarch64_elf_prstatus))
77 #define AARCH64_PRFPREG_NOTE_SIZE \
78 (AARCH64_NOTE_HEADER_SIZE + sizeof(struct aarch64_user_vfp_state))
80 static void aarch64_note_init(struct aarch64_note
*note
, DumpState
*s
,
81 const char *name
, Elf64_Word namesz
,
82 Elf64_Word type
, Elf64_Word descsz
)
84 memset(note
, 0, sizeof(*note
));
86 note
->hdr
.n_namesz
= cpu_to_dump32(s
, namesz
);
87 note
->hdr
.n_descsz
= cpu_to_dump32(s
, descsz
);
88 note
->hdr
.n_type
= cpu_to_dump32(s
, type
);
90 memcpy(note
->name
, name
, namesz
);
93 static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f
,
94 CPUARMState
*env
, int cpuid
,
97 struct aarch64_note note
;
100 aarch64_note_init(¬e
, s
, "CORE", 5, NT_PRFPREG
, sizeof(note
.vfp
));
102 for (i
= 0; i
< 32; ++i
) {
103 uint64_t *q
= aa64_vfp_qreg(env
, i
);
104 note
.vfp
.vregs
[2*i
+ 0] = cpu_to_dump64(s
, q
[0]);
105 note
.vfp
.vregs
[2*i
+ 1] = cpu_to_dump64(s
, q
[1]);
108 if (s
->dump_info
.d_endian
== ELFDATA2MSB
) {
109 /* For AArch64 we must always swap the vfp.regs's 2n and 2n+1
110 * entries when generating BE notes, because even big endian
111 * hosts use 2n+1 for the high half.
113 for (i
= 0; i
< 32; ++i
) {
114 uint64_t tmp
= note
.vfp
.vregs
[2*i
];
115 note
.vfp
.vregs
[2*i
] = note
.vfp
.vregs
[2*i
+1];
116 note
.vfp
.vregs
[2*i
+1] = tmp
;
120 note
.vfp
.fpsr
= cpu_to_dump32(s
, vfp_get_fpsr(env
));
121 note
.vfp
.fpcr
= cpu_to_dump32(s
, vfp_get_fpcr(env
));
123 ret
= f(¬e
, AARCH64_PRFPREG_NOTE_SIZE
, s
);
131 int arm_cpu_write_elf64_note(WriteCoreDumpFunction f
, CPUState
*cs
,
132 int cpuid
, void *opaque
)
134 struct aarch64_note note
;
135 CPUARMState
*env
= &ARM_CPU(cs
)->env
;
136 DumpState
*s
= opaque
;
140 aarch64_note_init(¬e
, s
, "CORE", 5, NT_PRSTATUS
, sizeof(note
.prstatus
));
142 note
.prstatus
.pr_pid
= cpu_to_dump32(s
, cpuid
);
143 note
.prstatus
.pr_fpvalid
= cpu_to_dump32(s
, 1);
146 aarch64_sync_32_to_64(env
);
147 pstate
= cpsr_read(env
);
150 pstate
= pstate_read(env
);
154 for (i
= 0; i
< 31; ++i
) {
155 note
.prstatus
.pr_reg
.regs
[i
] = cpu_to_dump64(s
, env
->xregs
[i
]);
157 note
.prstatus
.pr_reg
.sp
= cpu_to_dump64(s
, sp
);
158 note
.prstatus
.pr_reg
.pc
= cpu_to_dump64(s
, env
->pc
);
159 note
.prstatus
.pr_reg
.pstate
= cpu_to_dump64(s
, pstate
);
161 ret
= f(¬e
, AARCH64_PRSTATUS_NOTE_SIZE
, s
);
166 return aarch64_write_elf64_prfpreg(f
, env
, cpuid
, s
);
169 /* struct pt_regs from arch/arm/include/asm/ptrace.h */
170 struct arm_user_regs
{
175 QEMU_BUILD_BUG_ON(sizeof(struct arm_user_regs
) != 72);
177 /* struct elf_prstatus from include/uapi/linux/elfcore.h */
178 struct arm_elf_prstatus
{
179 char pad1
[24]; /* 24 == offsetof(struct elf_prstatus, pr_pid) */
181 char pad2
[44]; /* 44 == offsetof(struct elf_prstatus, pr_reg) -
182 offsetof(struct elf_prstatus, pr_ppid) */
183 struct arm_user_regs pr_reg
;
185 } QEMU_PACKED arm_elf_prstatus
;
187 QEMU_BUILD_BUG_ON(sizeof(struct arm_elf_prstatus
) != 148);
189 /* struct user_vfp from arch/arm/include/asm/user.h */
190 struct arm_user_vfp_state
{
195 QEMU_BUILD_BUG_ON(sizeof(struct arm_user_vfp_state
) != 260);
199 char name
[8]; /* align_up(sizeof("LINUX"), 4) */
201 struct arm_elf_prstatus prstatus
;
202 struct arm_user_vfp_state vfp
;
206 #define ARM_NOTE_HEADER_SIZE offsetof(struct arm_note, prstatus)
207 #define ARM_PRSTATUS_NOTE_SIZE \
208 (ARM_NOTE_HEADER_SIZE + sizeof(struct arm_elf_prstatus))
209 #define ARM_VFP_NOTE_SIZE \
210 (ARM_NOTE_HEADER_SIZE + sizeof(struct arm_user_vfp_state))
212 static void arm_note_init(struct arm_note
*note
, DumpState
*s
,
213 const char *name
, Elf32_Word namesz
,
214 Elf32_Word type
, Elf32_Word descsz
)
216 memset(note
, 0, sizeof(*note
));
218 note
->hdr
.n_namesz
= cpu_to_dump32(s
, namesz
);
219 note
->hdr
.n_descsz
= cpu_to_dump32(s
, descsz
);
220 note
->hdr
.n_type
= cpu_to_dump32(s
, type
);
222 memcpy(note
->name
, name
, namesz
);
225 static int arm_write_elf32_vfp(WriteCoreDumpFunction f
, CPUARMState
*env
,
226 int cpuid
, DumpState
*s
)
228 struct arm_note note
;
231 arm_note_init(¬e
, s
, "LINUX", 6, NT_ARM_VFP
, sizeof(note
.vfp
));
233 for (i
= 0; i
< 32; ++i
) {
234 note
.vfp
.vregs
[i
] = cpu_to_dump64(s
, *aa32_vfp_dreg(env
, i
));
237 note
.vfp
.fpscr
= cpu_to_dump32(s
, vfp_get_fpscr(env
));
239 ret
= f(¬e
, ARM_VFP_NOTE_SIZE
, s
);
247 int arm_cpu_write_elf32_note(WriteCoreDumpFunction f
, CPUState
*cs
,
248 int cpuid
, void *opaque
)
250 struct arm_note note
;
251 CPUARMState
*env
= &ARM_CPU(cs
)->env
;
252 DumpState
*s
= opaque
;
253 int ret
, i
, fpvalid
= !!arm_feature(env
, ARM_FEATURE_VFP
);
255 arm_note_init(¬e
, s
, "CORE", 5, NT_PRSTATUS
, sizeof(note
.prstatus
));
257 note
.prstatus
.pr_pid
= cpu_to_dump32(s
, cpuid
);
258 note
.prstatus
.pr_fpvalid
= cpu_to_dump32(s
, fpvalid
);
260 for (i
= 0; i
< 16; ++i
) {
261 note
.prstatus
.pr_reg
.regs
[i
] = cpu_to_dump32(s
, env
->regs
[i
]);
263 note
.prstatus
.pr_reg
.regs
[16] = cpu_to_dump32(s
, cpsr_read(env
));
265 ret
= f(¬e
, ARM_PRSTATUS_NOTE_SIZE
, s
);
268 } else if (fpvalid
) {
269 return arm_write_elf32_vfp(f
, env
, cpuid
, s
);
275 int cpu_get_dump_info(ArchDumpInfo
*info
,
276 const GuestPhysBlockList
*guest_phys_blocks
)
280 GuestPhysBlock
*block
;
281 hwaddr lowest_addr
= ULLONG_MAX
;
283 if (first_cpu
== NULL
) {
287 cpu
= ARM_CPU(first_cpu
);
290 /* Take a best guess at the phys_base. If we get it wrong then crash
291 * will need '--machdep phys_offset=<phys-offset>' added to its command
292 * line, which isn't any worse than assuming we can use zero, but being
293 * wrong. This is the same algorithm the crash utility uses when
294 * attempting to guess as it loads non-dumpfile formatted files.
296 QTAILQ_FOREACH(block
, &guest_phys_blocks
->head
, next
) {
297 if (block
->target_start
< lowest_addr
) {
298 lowest_addr
= block
->target_start
;
302 if (arm_feature(env
, ARM_FEATURE_AARCH64
)) {
303 info
->d_machine
= EM_AARCH64
;
304 info
->d_class
= ELFCLASS64
;
305 info
->page_size
= (1 << 16); /* aarch64 max pagesize */
306 if (lowest_addr
!= ULLONG_MAX
) {
307 info
->phys_base
= lowest_addr
;
310 info
->d_machine
= EM_ARM
;
311 info
->d_class
= ELFCLASS32
;
312 info
->page_size
= (1 << 12);
313 if (lowest_addr
< UINT_MAX
) {
314 info
->phys_base
= lowest_addr
;
318 /* We assume the relevant endianness is that of EL1; this is right
319 * for kernels, but might give the wrong answer if you're trying to
320 * dump a hypervisor that happens to be running an opposite-endian
323 info
->d_endian
= (env
->cp15
.sctlr_el
[1] & SCTLR_EE
) != 0
324 ? ELFDATA2MSB
: ELFDATA2LSB
;
329 ssize_t
cpu_get_note_size(int class, int machine
, int nr_cpus
)
331 ARMCPU
*cpu
= ARM_CPU(first_cpu
);
332 CPUARMState
*env
= &cpu
->env
;
335 if (class == ELFCLASS64
) {
336 note_size
= AARCH64_PRSTATUS_NOTE_SIZE
;
337 note_size
+= AARCH64_PRFPREG_NOTE_SIZE
;
339 note_size
= ARM_PRSTATUS_NOTE_SIZE
;
340 if (arm_feature(env
, ARM_FEATURE_VFP
)) {
341 note_size
+= ARM_VFP_NOTE_SIZE
;
345 return note_size
* nr_cpus
;