FreeBSD: add file descriptor tracking for _umtx_op
[valgrind.git] / coregrind / m_coredump / coredump-elf.c
bloba4632d9e285919e7e86972387e2e57fc7a81400d
2 /*--------------------------------------------------------------------*/
3 /*--- Dumping core. coredump-elf.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2000-2017 Julian Seward
11 jseward@acm.org
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 #if defined(VGO_linux) || defined(VGO_freebsd)
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
33 #include "pub_core_aspacehl.h"
34 #include "pub_core_aspacemgr.h"
35 #include "pub_core_libcbase.h"
36 #include "pub_core_machine.h"
37 #include "pub_core_coredump.h"
38 #include "pub_core_libcprint.h"
39 #include "pub_core_libcfile.h" // VG_(close) et al
40 #include "pub_core_libcproc.h" // VG_(geteuid), VG_(getegid)
41 #include "pub_core_libcassert.h" // VG_(exit), vg_assert
42 #include "pub_core_mallocfree.h" // VG_(malloc), VG_(free)
43 #include "pub_core_threadstate.h"
44 #include "pub_core_xarray.h"
45 #include "pub_core_clientstate.h"
46 #include "pub_core_options.h"
49 Dump core
51 Generate a standard ELF core file corresponding to the client state
52 at the time of a crash.
54 #include <elf.h>
55 #ifndef NT_PRXFPREG
56 #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */
57 #endif /* NT_PRXFPREG */
59 #if VG_WORDSIZE == 8
60 #define ESZ(x) Elf64_##x
61 #elif VG_WORDSIZE == 4
62 #define ESZ(x) Elf32_##x
63 #else
64 #error VG_WORDSIZE needs to ==4 or ==8
65 #endif
67 /* If true, then this Segment may be mentioned in the core */
68 static Bool may_dump(const NSegment *seg)
70 if (seg->kind == SkAnonC ||
71 seg->kind == SkShmC ||
72 (seg->kind == SkFileC &&
73 !VKI_S_ISCHR(seg->mode) && !VKI_S_ISBLK(seg->mode)))
74 return True;
76 return False;
79 /* If true, then this Segment's contents will be in the core */
80 static Bool should_dump(const NSegment *seg)
82 return may_dump(seg); // && seg->hasW;
85 static void fill_ehdr(ESZ(Ehdr) *ehdr, Int num_phdrs)
87 VG_(memset)(ehdr, 0, sizeof(*ehdr));
89 VG_(memcpy)(ehdr->e_ident, ELFMAG, SELFMAG);
90 ehdr->e_ident[EI_CLASS] = VG_ELF_CLASS;
91 ehdr->e_ident[EI_DATA] = VG_ELF_DATA2XXX;
92 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
93 #if defined(VGO_freebsd)
94 ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
95 #endif
97 ehdr->e_type = ET_CORE;
98 ehdr->e_machine = VG_ELF_MACHINE;
99 ehdr->e_version = EV_CURRENT;
100 ehdr->e_entry = 0;
101 ehdr->e_phoff = sizeof(ESZ(Ehdr));
102 ehdr->e_shoff = 0;
103 #if defined(VGP_nanomips_linux)
104 ehdr->e_flags = VKI_EF_NANOMIPS_ABI_P32;
105 #else
106 ehdr->e_flags = 0;
107 #endif
108 ehdr->e_ehsize = sizeof(ESZ(Ehdr));
109 ehdr->e_phentsize = sizeof(ESZ(Phdr));
110 ehdr->e_phnum = num_phdrs;
111 ehdr->e_shentsize = 0;
112 ehdr->e_shnum = 0;
113 ehdr->e_shstrndx = 0;
117 static void fill_phdr(ESZ(Phdr) *phdr, const NSegment *seg, UInt off, Bool write)
119 SizeT len = seg->end - seg->start + 1;
121 write = write && should_dump(seg);
123 VG_(memset)(phdr, 0, sizeof(*phdr));
125 phdr->p_type = PT_LOAD;
126 phdr->p_offset = off;
127 phdr->p_vaddr = seg->start;
128 phdr->p_paddr = 0;
129 phdr->p_filesz = write ? len : 0;
130 phdr->p_memsz = len;
131 phdr->p_flags = 0;
133 if (seg->hasR)
134 phdr->p_flags |= PF_R;
135 if (seg->hasW)
136 phdr->p_flags |= PF_W;
137 if (seg->hasX)
138 phdr->p_flags |= PF_X;
140 phdr->p_align = VKI_PAGE_SIZE;
143 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
144 || defined(VGPV_mips32_linux_android)
145 /* Android's libc doesn't provide a definition for this. Hence: */
146 typedef
147 struct {
148 Elf32_Word n_namesz;
149 Elf32_Word n_descsz;
150 Elf32_Word n_type;
152 Elf32_Nhdr;
153 #endif
155 struct note {
156 struct note *next;
157 ESZ(Nhdr) note;
158 HChar name[0];
161 static UInt note_size(const struct note *n)
163 return sizeof(ESZ(Nhdr)) + VG_ROUNDUP(VG_(strlen)(n->name)+1, 4)
164 + VG_ROUNDUP(n->note.n_descsz, 4);
167 #if !defined(VGPV_arm_linux_android) \
168 && !defined(VGPV_x86_linux_android) \
169 && !defined(VGPV_mips32_linux_android) \
170 && !defined(VGPV_arm64_linux_android)
171 static void add_note(struct note **list, const HChar *name, UInt type,
172 const void *data, UInt datasz)
174 Int namelen = VG_(strlen)(name)+1;
175 Int notelen = sizeof(struct note) +
176 VG_ROUNDUP(namelen, 4) +
177 VG_ROUNDUP(datasz, 4);
178 struct note *n = VG_(malloc)("coredump-elf.an.1", notelen);
180 VG_(memset)(n, 0, notelen);
182 n->next = *list;
183 *list = n;
185 n->note.n_type = type;
186 n->note.n_namesz = namelen;
187 n->note.n_descsz = datasz;
189 VG_(memcpy)(n->name, name, namelen);
190 VG_(memcpy)(n->name+VG_ROUNDUP(namelen,4), data, datasz);
192 #endif /* !defined(VGPV_*_linux_android) */
194 static void write_note(Int fd, const struct note *n)
196 VG_(write)(fd, &n->note, note_size(n));
199 #if defined(VGO_freebsd)
200 static void fill_prpsinfo(const ThreadState *tst,
201 struct vki_elf_prpsinfo *prpsinfo)
203 VG_(memset)(prpsinfo, 0, sizeof(*prpsinfo));
205 prpsinfo->pr_version = VKI_PRPSINFO_VERSION;
206 prpsinfo->pr_psinfosz = sizeof(struct vki_elf_prpsinfo);
207 VG_(client_fname)(prpsinfo->pr_fname, sizeof(prpsinfo->pr_fname), False);
208 // why?
209 VG_(strncpy)(prpsinfo->pr_psargs, prpsinfo->pr_fname, sizeof(prpsinfo->pr_psargs) - 1);
211 #else
212 static void fill_prpsinfo(const ThreadState *tst,
213 struct vki_elf_prpsinfo *prpsinfo)
215 VG_(memset)(prpsinfo, 0, sizeof(*prpsinfo));
217 switch(tst->status) {
218 case VgTs_Runnable:
219 case VgTs_Yielding:
220 prpsinfo->pr_sname = 'R';
221 break;
223 case VgTs_WaitSys:
224 prpsinfo->pr_sname = 'S';
225 break;
227 case VgTs_Zombie:
228 prpsinfo->pr_sname = 'Z';
229 break;
231 case VgTs_Empty:
232 case VgTs_Init:
233 prpsinfo->pr_sname = '?';
234 break;
237 prpsinfo->pr_uid = 0;
238 prpsinfo->pr_gid = 0;
240 VG_(client_fname)(prpsinfo->pr_fname, sizeof(prpsinfo->pr_fname), False);
242 #endif
244 static void fill_prstatus(const ThreadState *tst,
245 /*OUT*/struct vki_elf_prstatus *prs,
246 const vki_siginfo_t *si)
248 #if defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
249 || defined(VGP_nanomips_linux)
250 vki_elf_greg_t *regs;
251 #else
252 struct vki_user_regs_struct *regs;
253 #endif
254 const ThreadArchState* arch = &tst->arch;
256 VG_(memset)(prs, 0, sizeof(*prs));
258 #if defined(VGO_freebsd)
259 prs->pr_version = VKI_PRSTATUS_VERSION;
260 prs->pr_statussz = sizeof(struct vki_elf_prstatus);
261 prs->pr_gregsetsz = sizeof(vki_elf_gregset_t);
262 prs->pr_fpregsetsz = sizeof(vki_elf_fpregset_t);
263 prs->pr_osreldate = VG_(getosreldate)();
265 prs->pr_cursig = si->si_signo;
266 prs->pr_pid = tst->os_state.lwpid;
267 #else
268 prs->pr_info.si_signo = si->si_signo;
269 prs->pr_info.si_code = si->si_code;
270 prs->pr_info.si_errno = 0;
272 prs->pr_cursig = si->si_signo;
274 prs->pr_pid = tst->os_state.lwpid;
275 prs->pr_ppid = 0;
276 prs->pr_pgrp = VG_(getpgrp)();
277 prs->pr_sid = VG_(getpgrp)();
278 #endif
280 #if defined(VGP_s390x_linux)
281 /* prs->pr_reg has struct type. Need to take address. */
282 regs = (struct vki_user_regs_struct *)&(prs->pr_reg);
283 #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
284 || defined(VGP_nanomips_linux)
285 regs = (vki_elf_greg_t *)prs->pr_reg;
286 #else
287 regs = (struct vki_user_regs_struct *)prs->pr_reg;
288 vg_assert(sizeof(*regs) == sizeof(prs->pr_reg));
289 #endif
291 #if defined(VGP_x86_linux)
292 regs->eflags = LibVEX_GuestX86_get_eflags( &arch->vex );
293 regs->esp = arch->vex.guest_ESP;
294 regs->eip = arch->vex.guest_EIP;
296 regs->ebx = arch->vex.guest_EBX;
297 regs->ecx = arch->vex.guest_ECX;
298 regs->edx = arch->vex.guest_EDX;
299 regs->esi = arch->vex.guest_ESI;
300 regs->edi = arch->vex.guest_EDI;
301 regs->ebp = arch->vex.guest_EBP;
302 regs->eax = arch->vex.guest_EAX;
304 regs->cs = arch->vex.guest_CS;
305 regs->ds = arch->vex.guest_DS;
306 regs->ss = arch->vex.guest_SS;
307 regs->es = arch->vex.guest_ES;
308 regs->fs = arch->vex.guest_FS;
309 regs->gs = arch->vex.guest_GS;
311 #elif defined(VGP_amd64_linux)
312 regs->eflags = LibVEX_GuestAMD64_get_rflags( &arch->vex );
313 regs->rsp = arch->vex.guest_RSP;
314 regs->rip = arch->vex.guest_RIP;
316 regs->rbx = arch->vex.guest_RBX;
317 regs->rcx = arch->vex.guest_RCX;
318 regs->rdx = arch->vex.guest_RDX;
319 regs->rsi = arch->vex.guest_RSI;
320 regs->rdi = arch->vex.guest_RDI;
321 regs->rbp = arch->vex.guest_RBP;
322 regs->rax = arch->vex.guest_RAX;
323 regs->r8 = arch->vex.guest_R8;
324 regs->r9 = arch->vex.guest_R9;
325 regs->r10 = arch->vex.guest_R10;
326 regs->r11 = arch->vex.guest_R11;
327 regs->r12 = arch->vex.guest_R12;
328 regs->r13 = arch->vex.guest_R13;
329 regs->r14 = arch->vex.guest_R14;
330 regs->r15 = arch->vex.guest_R15;
332 #elif defined(VGP_ppc32_linux)
333 # define DO(n) regs->gpr[n] = arch->vex.guest_GPR##n
334 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
335 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
336 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
337 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
338 # undef DO
340 regs->nip = arch->vex.guest_CIA;
341 regs->msr = 0xf032; /* pretty arbitrary */
342 regs->orig_gpr3 = arch->vex.guest_GPR3;
343 regs->ctr = arch->vex.guest_CTR;
344 regs->link = arch->vex.guest_LR;
345 regs->xer = LibVEX_GuestPPC32_get_XER( &arch->vex );
346 regs->ccr = LibVEX_GuestPPC32_get_CR( &arch->vex );
347 regs->mq = 0;
348 regs->trap = 0;
349 regs->dar = 0; /* should be fault address? */
350 regs->dsisr = 0;
351 regs->result = 0;
353 #elif defined(VGP_ppc64be_linux)
354 # define DO(n) regs->gpr[n] = arch->vex.guest_GPR##n
355 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
356 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
357 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
358 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
359 # undef DO
361 regs->nip = arch->vex.guest_CIA;
362 regs->msr = 0xf032; /* pretty arbitrary */
363 regs->orig_gpr3 = arch->vex.guest_GPR3;
364 regs->ctr = arch->vex.guest_CTR;
365 regs->link = arch->vex.guest_LR;
366 regs->xer = LibVEX_GuestPPC64_get_XER( &arch->vex );
367 regs->ccr = LibVEX_GuestPPC64_get_CR( &arch->vex );
368 /* regs->mq = 0; */
369 regs->trap = 0;
370 regs->dar = 0; /* should be fault address? */
371 regs->dsisr = 0;
372 regs->result = 0;
374 #elif defined(VGP_ppc64le_linux)
375 # define DO(n) regs->gpr[n] = arch->vex.guest_GPR##n
376 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
377 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
378 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
379 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
380 # undef DO
382 regs->nip = arch->vex.guest_CIA;
383 regs->msr = 0xf033; /* pretty arbitrary */
384 regs->orig_gpr3 = arch->vex.guest_GPR3;
385 regs->ctr = arch->vex.guest_CTR;
386 regs->link = arch->vex.guest_LR;
387 regs->xer = LibVEX_GuestPPC64_get_XER( &(arch->vex) );
388 regs->ccr = LibVEX_GuestPPC64_get_CR( &(arch->vex) );
389 /* regs->mq = 0; */
390 regs->trap = 0;
391 regs->dar = 0; /* should be fault address? */
392 regs->dsisr = 0;
393 regs->result = 0;
395 #elif defined(VGP_arm_linux)
396 regs->ARM_r0 = arch->vex.guest_R0;
397 regs->ARM_r1 = arch->vex.guest_R1;
398 regs->ARM_r2 = arch->vex.guest_R2;
399 regs->ARM_r3 = arch->vex.guest_R3;
400 regs->ARM_r4 = arch->vex.guest_R4;
401 regs->ARM_r5 = arch->vex.guest_R5;
402 regs->ARM_r6 = arch->vex.guest_R6;
403 regs->ARM_r7 = arch->vex.guest_R7;
404 regs->ARM_r8 = arch->vex.guest_R8;
405 regs->ARM_r9 = arch->vex.guest_R9;
406 regs->ARM_r10 = arch->vex.guest_R10;
407 regs->ARM_fp = arch->vex.guest_R11;
408 regs->ARM_ip = arch->vex.guest_R12;
409 regs->ARM_sp = arch->vex.guest_R13;
410 regs->ARM_lr = arch->vex.guest_R14;
411 regs->ARM_pc = arch->vex.guest_R15T;
412 regs->ARM_cpsr = LibVEX_GuestARM_get_cpsr( &arch->vex );
414 #elif defined(VGP_arm64_linux)
415 regs->regs[0] = arch->vex.guest_X0;
416 regs->regs[1] = arch->vex.guest_X1;
417 regs->regs[2] = arch->vex.guest_X2;
418 regs->regs[3] = arch->vex.guest_X3;
419 regs->regs[4] = arch->vex.guest_X4;
420 regs->regs[5] = arch->vex.guest_X5;
421 regs->regs[6] = arch->vex.guest_X6;
422 regs->regs[7] = arch->vex.guest_X7;
423 regs->regs[8] = arch->vex.guest_X8;
424 regs->regs[9] = arch->vex.guest_X9;
425 regs->regs[10] = arch->vex.guest_X10;
426 regs->regs[11] = arch->vex.guest_X11;
427 regs->regs[12] = arch->vex.guest_X12;
428 regs->regs[13] = arch->vex.guest_X13;
429 regs->regs[14] = arch->vex.guest_X14;
430 regs->regs[15] = arch->vex.guest_X15;
431 regs->regs[16] = arch->vex.guest_X16;
432 regs->regs[17] = arch->vex.guest_X17;
433 regs->regs[18] = arch->vex.guest_X18;
434 regs->regs[19] = arch->vex.guest_X19;
435 regs->regs[20] = arch->vex.guest_X20;
436 regs->regs[21] = arch->vex.guest_X21;
437 regs->regs[22] = arch->vex.guest_X22;
438 regs->regs[23] = arch->vex.guest_X23;
439 regs->regs[24] = arch->vex.guest_X24;
440 regs->regs[25] = arch->vex.guest_X25;
441 regs->regs[26] = arch->vex.guest_X26;
442 regs->regs[27] = arch->vex.guest_X27;
443 regs->regs[28] = arch->vex.guest_X28;
444 regs->regs[29] = arch->vex.guest_X29;
445 regs->regs[30] = arch->vex.guest_X30;
446 regs->sp = arch->vex.guest_XSP;
447 regs->pc = arch->vex.guest_PC;
448 regs->pstate = LibVEX_GuestARM64_get_nzcv( &arch->vex ); /* is this correct? */
450 #elif defined(VGP_s390x_linux)
451 # define DO(n) regs->gprs[n] = arch->vex.guest_r##n
452 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
453 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
454 # undef DO
455 # define DO(n) regs->acrs[n] = arch->vex.guest_a##n
456 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
457 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
458 # undef DO
459 regs->orig_gpr2 = arch->vex.guest_r2;
461 #elif defined(VGP_mips32_linux)
462 # define DO(n) regs[VKI_MIPS32_EF_R##n] = arch->vex.guest_r##n
463 DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); DO(8);
464 DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); DO(16);
465 DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); DO(24);
466 DO(25); DO(28); DO(29); DO(30); DO(31);
467 # undef DO
468 regs[VKI_MIPS32_EF_LO] = arch->vex.guest_LO;
469 regs[VKI_MIPS32_EF_HI] = arch->vex.guest_HI;
470 regs[VKI_MIPS32_EF_CP0_STATUS] = arch->vex.guest_CP0_status;
471 regs[VKI_MIPS32_EF_CP0_EPC] = arch->vex.guest_PC;
472 #elif defined(VGP_mips64_linux)
473 # define DO(n) regs[VKI_MIPS64_EF_R##n] = arch->vex.guest_r##n
474 DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); DO(8);
475 DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); DO(16);
476 DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); DO(24);
477 DO(25); DO(28); DO(29); DO(30); DO(31);
478 # undef DO
479 regs[VKI_MIPS64_EF_LO] = arch->vex.guest_LO;
480 regs[VKI_MIPS64_EF_HI] = arch->vex.guest_HI;
481 regs[VKI_MIPS64_EF_CP0_STATUS] = arch->vex.guest_CP0_status;
482 regs[VKI_MIPS64_EF_CP0_EPC] = arch->vex.guest_PC;
483 #elif defined(VGP_nanomips_linux)
484 # define DO(n) regs[VKI_MIPS32_EF_R##n] = arch->vex.guest_r##n
485 DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); DO(8);
486 DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); DO(16);
487 DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); DO(24);
488 DO(25); DO(28); DO(29); DO(30); DO(31);
489 regs[VKI_MIPS32_EF_CP0_STATUS] = arch->vex.guest_CP0_status;
490 regs[VKI_MIPS32_EF_CP0_EPC] = arch->vex.guest_PC;
491 # undef DO
492 #elif defined(VGP_amd64_freebsd)
493 regs->rflags = LibVEX_GuestAMD64_get_rflags( &arch->vex );
494 regs->rsp = arch->vex.guest_RSP;
495 regs->rip = arch->vex.guest_RIP;
496 regs->rbx = arch->vex.guest_RBX;
497 regs->rcx = arch->vex.guest_RCX;
498 regs->rdx = arch->vex.guest_RDX;
499 regs->rsi = arch->vex.guest_RSI;
500 regs->rdi = arch->vex.guest_RDI;
501 regs->rbp = arch->vex.guest_RBP;
502 regs->rax = arch->vex.guest_RAX;
503 regs->r8 = arch->vex.guest_R8;
504 regs->r9 = arch->vex.guest_R9;
505 regs->r10 = arch->vex.guest_R10;
506 regs->r11 = arch->vex.guest_R11;
507 regs->r12 = arch->vex.guest_R12;
508 regs->r13 = arch->vex.guest_R13;
509 regs->r14 = arch->vex.guest_R14;
510 regs->r15 = arch->vex.guest_R15;
511 #elif defined(VGP_x86_freebsd)
512 regs->eflags = LibVEX_GuestX86_get_eflags( &arch->vex );
513 regs->esp = arch->vex.guest_ESP;
514 regs->eip = arch->vex.guest_EIP;
516 regs->ebx = arch->vex.guest_EBX;
517 regs->ecx = arch->vex.guest_ECX;
518 regs->edx = arch->vex.guest_EDX;
519 regs->esi = arch->vex.guest_ESI;
520 regs->edi = arch->vex.guest_EDI;
521 regs->ebp = arch->vex.guest_EBP;
522 regs->eax = arch->vex.guest_EAX;
524 regs->cs = arch->vex.guest_CS;
525 regs->ds = arch->vex.guest_DS;
526 regs->ss = arch->vex.guest_SS;
527 regs->es = arch->vex.guest_ES;
528 regs->fs = arch->vex.guest_FS;
529 regs->gs = arch->vex.guest_GS;
531 #elif defined(VGP_arm64_freebsd)
532 regs->gp_x[0] = arch->vex.guest_X0;
533 regs->gp_x[1] = arch->vex.guest_X1;
534 regs->gp_x[2] = arch->vex.guest_X2;
535 regs->gp_x[3] = arch->vex.guest_X3;
536 regs->gp_x[4] = arch->vex.guest_X4;
537 regs->gp_x[5] = arch->vex.guest_X5;
538 regs->gp_x[6] = arch->vex.guest_X6;
539 regs->gp_x[7] = arch->vex.guest_X7;
540 regs->gp_x[8] = arch->vex.guest_X8;
541 regs->gp_x[9] = arch->vex.guest_X9;
542 regs->gp_x[10] = arch->vex.guest_X10;
543 regs->gp_x[11] = arch->vex.guest_X11;
544 regs->gp_x[12] = arch->vex.guest_X12;
545 regs->gp_x[13] = arch->vex.guest_X13;
546 regs->gp_x[14] = arch->vex.guest_X14;
547 regs->gp_x[15] = arch->vex.guest_X15;
548 regs->gp_x[16] = arch->vex.guest_X16;
549 regs->gp_x[17] = arch->vex.guest_X17;
550 regs->gp_x[18] = arch->vex.guest_X18;
551 regs->gp_x[19] = arch->vex.guest_X19;
552 regs->gp_x[20] = arch->vex.guest_X20;
553 regs->gp_x[21] = arch->vex.guest_X21;
554 regs->gp_x[22] = arch->vex.guest_X22;
555 regs->gp_x[23] = arch->vex.guest_X23;
556 regs->gp_x[24] = arch->vex.guest_X24;
557 regs->gp_x[25] = arch->vex.guest_X25;
558 regs->gp_x[26] = arch->vex.guest_X26;
559 regs->gp_x[27] = arch->vex.guest_X27;
560 regs->gp_x[28] = arch->vex.guest_X28;
561 regs->gp_x[29] = arch->vex.guest_X29;
562 regs->gp_lr = arch->vex.guest_X30;
563 regs->gp_sp = arch->vex.guest_XSP;
564 regs->gp_elr = arch->vex.guest_PC;
565 regs->gp_spsr = LibVEX_GuestARM64_get_nzcv( &arch->vex ); /* is this correct? */
568 #else
569 # error Unknown ELF platform
570 #endif
573 static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu)
575 __attribute__((unused))
576 const ThreadArchState* arch = &tst->arch;
578 #if defined(VGP_x86_linux)
579 //:: static void fill_fpu(vki_elf_fpregset_t *fpu, const HChar *from)
580 //:: {
581 //:: if (VG_(have_ssestate)) {
582 //:: UShort *to;
583 //:: Int i;
584 //::
585 //:: /* This is what the kernel does */
586 //:: VG_(memcpy)(fpu, from, 7*sizeof(long));
587 //::
588 //:: to = (UShort *)&fpu->st_space[0];
589 //:: from += 18 * sizeof(UShort);
590 //::
591 //:: for (i = 0; i < 8; i++, to += 5, from += 8)
592 //:: VG_(memcpy)(to, from, 5*sizeof(UShort));
593 //:: } else
594 //:: VG_(memcpy)(fpu, from, sizeof(*fpu));
595 //:: }
597 //:: fill_fpu(fpu, (const HChar *)&arch->m_sse);
599 #elif defined(VGP_amd64_linux)
600 //:: fpu->cwd = ?;
601 //:: fpu->swd = ?;
602 //:: fpu->twd = ?;
603 //:: fpu->fop = ?;
604 //:: fpu->rip = ?;
605 //:: fpu->rdp = ?;
606 //:: fpu->mxcsr = ?;
607 //:: fpu->mxcsr_mask = ?;
608 //:: fpu->st_space = ?;
610 # define DO(n) VG_(memcpy)(fpu->xmm_space + n * 4, \
611 &arch->vex.guest_YMM##n[0], 16)
612 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
613 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
614 # undef DO
616 VG_(memset)(fpu->padding, 0, sizeof(fpu->padding));
618 #elif defined(VGP_ppc32_linux)
619 /* The guest state has the FPR fields declared as ULongs, so need
620 to fish out the values without converting them.
621 NOTE: The 32 FP registers map to the first 32 VSX registers.*/
622 # define DO(n) (*fpu)[n] = *(double*)(&arch->vex.guest_VSR##n)
623 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
624 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
625 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
626 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
627 # undef DO
629 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
630 /* The guest state has the FPR fields declared as ULongs, so need
631 to fish out the values without converting them.
632 NOTE: The 32 FP registers map to the first 32 VSX registers.*/
633 # define DO(n) (*fpu)[n] = *(double*)(&arch->vex.guest_VSR##n)
634 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
635 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
636 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
637 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
638 # undef DO
640 #elif defined(VGP_arm_linux)
641 // umm ...
643 #elif defined(VGP_arm64_linux)
644 fpu->vregs[0] = *(const __uint128_t*)arch->vex.guest_Q0;
645 fpu->vregs[1] = *(const __uint128_t*)arch->vex.guest_Q1;
646 fpu->vregs[2] = *(const __uint128_t*)arch->vex.guest_Q2;
647 fpu->vregs[3] = *(const __uint128_t*)arch->vex.guest_Q3;
648 fpu->vregs[4] = *(const __uint128_t*)arch->vex.guest_Q4;
649 fpu->vregs[5] = *(const __uint128_t*)arch->vex.guest_Q5;
650 fpu->vregs[6] = *(const __uint128_t*)arch->vex.guest_Q6;
651 fpu->vregs[7] = *(const __uint128_t*)arch->vex.guest_Q7;
652 fpu->vregs[8] = *(const __uint128_t*)arch->vex.guest_Q8;
653 fpu->vregs[9] = *(const __uint128_t*)arch->vex.guest_Q9;
654 fpu->vregs[10] = *(const __uint128_t*)arch->vex.guest_Q10;
655 fpu->vregs[11] = *(const __uint128_t*)arch->vex.guest_Q11;
656 fpu->vregs[12] = *(const __uint128_t*)arch->vex.guest_Q12;
657 fpu->vregs[13] = *(const __uint128_t*)arch->vex.guest_Q13;
658 fpu->vregs[14] = *(const __uint128_t*)arch->vex.guest_Q14;
659 fpu->vregs[15] = *(const __uint128_t*)arch->vex.guest_Q15;
660 fpu->vregs[16] = *(const __uint128_t*)arch->vex.guest_Q16;
661 fpu->vregs[17] = *(const __uint128_t*)arch->vex.guest_Q17;
662 fpu->vregs[18] = *(const __uint128_t*)arch->vex.guest_Q18;
663 fpu->vregs[19] = *(const __uint128_t*)arch->vex.guest_Q19;
664 fpu->vregs[20] = *(const __uint128_t*)arch->vex.guest_Q20;
665 fpu->vregs[21] = *(const __uint128_t*)arch->vex.guest_Q21;
666 fpu->vregs[22] = *(const __uint128_t*)arch->vex.guest_Q22;
667 fpu->vregs[23] = *(const __uint128_t*)arch->vex.guest_Q23;
668 fpu->vregs[24] = *(const __uint128_t*)arch->vex.guest_Q24;
669 fpu->vregs[25] = *(const __uint128_t*)arch->vex.guest_Q25;
670 fpu->vregs[26] = *(const __uint128_t*)arch->vex.guest_Q26;
671 fpu->vregs[27] = *(const __uint128_t*)arch->vex.guest_Q27;
672 fpu->vregs[28] = *(const __uint128_t*)arch->vex.guest_Q28;
673 fpu->vregs[29] = *(const __uint128_t*)arch->vex.guest_Q29;
674 fpu->vregs[30] = *(const __uint128_t*)arch->vex.guest_Q30;
675 fpu->vregs[31] = *(const __uint128_t*)arch->vex.guest_Q31;
676 fpu->fpsr = *(const __vki_u32*)arch->vex.guest_QCFLAG;
677 fpu->fpcr = arch->vex.guest_FPCR;
679 #elif defined(VGP_s390x_linux)
680 /* NOTE: The 16 FP registers map to the first 16 VSX registers. */
681 # define DO(n) fpu->fprs[n].ui = *(const Double*)(&arch->vex.guest_v##n.w64[0])
682 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
683 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
684 # undef DO
685 #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
686 # define DO(n) (*fpu)[n] = *(const double*)(&arch->vex.guest_f##n)
687 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
688 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
689 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
690 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
691 # undef DO
692 #elif defined(VGP_nanomips_linux)
694 #elif defined(VGP_x86_freebsd)
696 #elif defined(VGP_amd64_freebsd)
698 # define DO(n) VG_(memcpy)(fpu->xmm_space + n * 4, \
699 &arch->vex.guest_YMM##n[0], 16)
700 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
701 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
702 # undef DO
704 #elif defined(VGP_arm64_freebsd)
705 fpu->fp_q[0] = *(const __uint128_t*)arch->vex.guest_Q0;
706 fpu->fp_q[1] = *(const __uint128_t*)arch->vex.guest_Q1;
707 fpu->fp_q[2] = *(const __uint128_t*)arch->vex.guest_Q2;
708 fpu->fp_q[3] = *(const __uint128_t*)arch->vex.guest_Q3;
709 fpu->fp_q[4] = *(const __uint128_t*)arch->vex.guest_Q4;
710 fpu->fp_q[5] = *(const __uint128_t*)arch->vex.guest_Q5;
711 fpu->fp_q[6] = *(const __uint128_t*)arch->vex.guest_Q6;
712 fpu->fp_q[7] = *(const __uint128_t*)arch->vex.guest_Q7;
713 fpu->fp_q[8] = *(const __uint128_t*)arch->vex.guest_Q8;
714 fpu->fp_q[9] = *(const __uint128_t*)arch->vex.guest_Q9;
715 fpu->fp_q[10] = *(const __uint128_t*)arch->vex.guest_Q10;
716 fpu->fp_q[11] = *(const __uint128_t*)arch->vex.guest_Q11;
717 fpu->fp_q[12] = *(const __uint128_t*)arch->vex.guest_Q12;
718 fpu->fp_q[13] = *(const __uint128_t*)arch->vex.guest_Q13;
719 fpu->fp_q[14] = *(const __uint128_t*)arch->vex.guest_Q14;
720 fpu->fp_q[15] = *(const __uint128_t*)arch->vex.guest_Q15;
721 fpu->fp_q[16] = *(const __uint128_t*)arch->vex.guest_Q16;
722 fpu->fp_q[17] = *(const __uint128_t*)arch->vex.guest_Q17;
723 fpu->fp_q[18] = *(const __uint128_t*)arch->vex.guest_Q18;
724 fpu->fp_q[19] = *(const __uint128_t*)arch->vex.guest_Q19;
725 fpu->fp_q[20] = *(const __uint128_t*)arch->vex.guest_Q20;
726 fpu->fp_q[21] = *(const __uint128_t*)arch->vex.guest_Q21;
727 fpu->fp_q[22] = *(const __uint128_t*)arch->vex.guest_Q22;
728 fpu->fp_q[23] = *(const __uint128_t*)arch->vex.guest_Q23;
729 fpu->fp_q[24] = *(const __uint128_t*)arch->vex.guest_Q24;
730 fpu->fp_q[25] = *(const __uint128_t*)arch->vex.guest_Q25;
731 fpu->fp_q[26] = *(const __uint128_t*)arch->vex.guest_Q26;
732 fpu->fp_q[27] = *(const __uint128_t*)arch->vex.guest_Q27;
733 fpu->fp_q[28] = *(const __uint128_t*)arch->vex.guest_Q28;
734 fpu->fp_q[29] = *(const __uint128_t*)arch->vex.guest_Q29;
735 fpu->fp_q[30] = *(const __uint128_t*)arch->vex.guest_Q30;
736 fpu->fp_q[31] = *(const __uint128_t*)arch->vex.guest_Q31;
737 fpu->fp_sr = *(const vki_uint32_t*)arch->vex.guest_QCFLAG;
738 fpu->fp_cr = arch->vex.guest_FPCR;
740 #else
741 # error Unknown ELF platform
742 #endif
745 #if defined(VGP_x86_linux) && !defined(VGPV_x86_linux_android)
746 static void fill_xfpu(const ThreadState *tst, vki_elf_fpxregset_t *xfpu)
748 const ThreadArchState* arch = &tst->arch;
750 //:: xfpu->cwd = ?;
751 //:: xfpu->swd = ?;
752 //:: xfpu->twd = ?;
753 //:: xfpu->fop = ?;
754 //:: xfpu->fip = ?;
755 //:: xfpu->fcs = ?;
756 //:: xfpu->foo = ?;
757 //:: xfpu->fos = ?;
758 //:: xfpu->mxcsr = ?;
759 xfpu->reserved = 0;
760 //:: xfpu->st_space = ?;
762 # define DO(n) VG_(memcpy)(xfpu->xmm_space + n * 4, &arch->vex.guest_XMM##n, sizeof(arch->vex.guest_XMM##n))
763 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
764 # undef DO
766 VG_(memset)(xfpu->padding, 0, sizeof(xfpu->padding));
768 #endif
770 static
771 void dump_one_thread(struct note **notelist, const vki_siginfo_t *si, ThreadId tid)
773 vki_elf_fpregset_t fpu;
774 struct vki_elf_prstatus prstatus;
775 const HChar* name;
776 # if !defined(VGO_freebsd)
777 name = "CORE";
778 # else
779 /* lldb on FreeBSD expects a prstatus with name "FreeBSD"
780 * see llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) in ProcessElfCore.cpp
781 * Otherwise it exits with "Could not find NT_PRSTATUS note in core file." */
782 name = "FreeBSD";
783 # endif
784 VG_(memset)(&fpu, 0, sizeof(fpu));
785 VG_(memset)(&prstatus, 0, sizeof(prstatus));
786 # if defined(VGP_x86_linux) && !defined(VGPV_x86_linux_android)
788 vki_elf_fpxregset_t xfpu;
789 VG_(memset)(&xfpu, 0, sizeof(xfpu));
790 fill_xfpu(&VG_(threads)[tid], &xfpu);
791 add_note(notelist, "LINUX", NT_PRXFPREG, &xfpu, sizeof(xfpu));
793 # endif
795 fill_fpu(&VG_(threads)[tid], &fpu);
796 # if !defined(VGPV_arm_linux_android) \
797 && !defined(VGPV_x86_linux_android) \
798 && !defined(VGPV_mips32_linux_android) \
799 && !defined(VGPV_arm64_linux_android) \
800 && !defined(VGP_nanomips_linux)
801 add_note(notelist, name, NT_FPREGSET, &fpu, sizeof(fpu));
802 # endif
804 fill_prstatus(&VG_(threads)[tid], &prstatus, si);
805 # if !defined(VGPV_arm_linux_android) \
806 && !defined(VGPV_x86_linux_android) \
807 && !defined(VGPV_mips32_linux_android) \
808 && !defined(VGPV_arm64_linux_android)
809 add_note(notelist, name, NT_PRSTATUS, &prstatus, sizeof(prstatus));
810 # endif
813 static
814 void make_elf_coredump(ThreadId tid, const vki_siginfo_t *si, ULong max_size)
816 HChar* buf = NULL;
817 HChar *basename;
818 const HChar *coreext = "";
819 Int seq = 0;
820 Int core_fd;
821 NSegment const * seg;
822 ESZ(Ehdr) ehdr;
823 ESZ(Phdr) *phdrs = NULL;
824 Int num_phdrs;
825 Int i, idx;
826 UInt off;
827 struct note *notelist, *note;
828 UInt notesz;
829 struct vki_elf_prpsinfo prpsinfo;
830 Addr *seg_starts = NULL;
831 Int n_seg_starts;
833 if (VG_(clo_log_fname_unexpanded) != NULL) {
834 coreext = ".core";
835 basename = VG_(expand_file_name)("--log-file",
836 VG_(clo_log_fname_unexpanded));
837 } else
838 basename = VG_(strdup)("coredump-elf.mec.1", "vgcore");
840 vg_assert(coreext);
841 vg_assert(basename);
842 buf = VG_(malloc)( "coredump-elf.mec.1",
843 VG_(strlen)(coreext) + VG_(strlen)(basename)
844 + 100/*for the two %ds. */ );
846 for(;;) {
847 Int oflags = VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC;
848 SysRes sres;
850 if (seq == 0)
851 VG_(sprintf)(buf, "%s%s.%d",
852 basename, coreext, VG_(getpid)());
853 else
854 VG_(sprintf)(buf, "%s%s.%d.%d",
855 basename, coreext, VG_(getpid)(), seq);
856 seq++;
858 # if defined(VKI_O_LARGEFILE)
859 oflags |= VKI_O_LARGEFILE;
860 # endif
862 sres = VG_(open)(buf, oflags, VKI_S_IRUSR|VKI_S_IWUSR);
863 if (!sr_isError(sres)) {
864 core_fd = sr_Res(sres);
865 break;
868 if (sr_isError(sres) && sr_Err(sres) != VKI_EEXIST)
869 goto cleanup; /* can't create file */
872 /* Get the client segments */
873 seg_starts = VG_(get_segment_starts)(SkFileC | SkAnonC | SkShmC,
874 &n_seg_starts);
876 /* First, count how many memory segments to dump */
877 num_phdrs = 1; /* start with notes */
878 for(i = 0; i < n_seg_starts; i++) {
879 if (!may_dump(VG_(am_find_nsegment)(seg_starts[i])))
880 continue;
882 num_phdrs++;
885 fill_ehdr(&ehdr, num_phdrs);
887 notelist = NULL;
889 /* Second, work out their layout */
890 phdrs = VG_(malloc)("coredump-elf.mec.1", sizeof(*phdrs) * num_phdrs);
892 /* Add details for all threads except the one that faulted */
893 for(i = 1; i < VG_N_THREADS; i++) {
895 if (VG_(threads)[i].status == VgTs_Empty)
896 continue;
898 if (i == tid)
899 continue;
901 dump_one_thread(&notelist, si, i);
904 /* Add details for the faulting thread. Note that because we are
905 adding to the head of a linked list this thread will actually
906 come out first in the core file, which seems to be how
907 debuggers determine that it is the faulting thread. */
908 dump_one_thread(&notelist, si, tid);
910 fill_prpsinfo(&VG_(threads)[tid], &prpsinfo);
911 # if !defined(VGPV_arm_linux_android) \
912 && !defined(VGPV_x86_linux_android) \
913 && !defined(VGPV_mips32_linux_android) \
914 && !defined(VGPV_arm64_linux_android)
915 add_note(&notelist, "CORE", NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo));
916 # endif
918 for (note = notelist, notesz = 0; note != NULL; note = note->next)
919 notesz += note_size(note);
921 off = sizeof(ehdr) + sizeof(*phdrs) * num_phdrs;
923 phdrs[0].p_type = PT_NOTE;
924 phdrs[0].p_offset = off;
925 phdrs[0].p_vaddr = 0;
926 phdrs[0].p_paddr = 0;
927 phdrs[0].p_filesz = notesz;
928 phdrs[0].p_memsz = 0;
929 phdrs[0].p_flags = 0;
930 phdrs[0].p_align = 0;
932 off += notesz;
934 off = VG_PGROUNDUP(off);
936 for(i = 0, idx = 1; i < n_seg_starts; i++) {
937 seg = VG_(am_find_nsegment)(seg_starts[i]);
939 if (!may_dump(seg))
940 continue;
942 fill_phdr(&phdrs[idx], seg, off,
943 (seg->end - seg->start + 1 + off) < max_size);
945 off += phdrs[idx].p_filesz;
947 idx++;
950 /* write everything out */
951 VG_(write)(core_fd, &ehdr, sizeof(ehdr));
952 VG_(write)(core_fd, phdrs, sizeof(*phdrs) * num_phdrs);
954 for(note = notelist; note != NULL; note = note->next)
955 write_note(core_fd, note);
957 VG_(lseek)(core_fd, phdrs[1].p_offset, VKI_SEEK_SET);
959 for(i = 0, idx = 1; i < n_seg_starts; i++) {
960 seg = VG_(am_find_nsegment)(seg_starts[i]);
962 if (!should_dump(seg))
963 continue;
965 if (phdrs[idx].p_filesz > 0) {
966 vg_assert(VG_(lseek)(core_fd, phdrs[idx].p_offset, VKI_SEEK_SET)
967 == phdrs[idx].p_offset);
968 vg_assert(seg->end - seg->start + 1 >= phdrs[idx].p_filesz);
970 (void)VG_(write)(core_fd, (void *)seg->start, phdrs[idx].p_filesz);
972 idx++;
975 VG_(close)(core_fd);
977 cleanup:
978 VG_(free)(basename);
979 VG_(free)(buf);
980 VG_(free)(seg_starts);
981 VG_(free)(phdrs);
984 void VG_(make_coredump)(ThreadId tid, const vki_siginfo_t *si, ULong max_size)
986 make_elf_coredump(tid, si, max_size);
989 #endif // defined(VGO_linux)
991 /*--------------------------------------------------------------------*/
992 /*--- end ---*/
993 /*--------------------------------------------------------------------*/