2 /*--------------------------------------------------------------------*/
3 /*--- Dumping core on Solaris. coredump-solaris.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2013-2017 Ivo Raisr
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, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
31 #if defined(VGO_solaris)
33 #include "pub_core_basics.h"
34 #include "pub_core_vki.h"
35 #include "pub_core_aspacehl.h"
36 #include "pub_core_aspacemgr.h"
37 #include "pub_core_coredump.h"
38 #include "pub_core_debuglog.h"
39 #include "pub_core_libcassert.h"
40 #include "pub_core_libcbase.h"
41 #include "pub_core_libcfile.h"
42 #include "pub_core_libcprint.h"
43 #include "pub_core_libcproc.h"
44 #include "pub_core_machine.h"
45 #include "pub_core_mallocfree.h"
46 #include "pub_core_options.h"
47 #include "pub_core_syscall.h"
48 #include "pub_core_threadstate.h"
49 #include "pub_core_xarray.h"
50 #include "pub_core_clientstate.h"
52 typedef struct __attribute__ ((__packed__
)) note
{
59 static void add_note(note_t
**list
, UInt type
, const void *data
,
62 /* If true, then this Segment may be mentioned in the core */
63 static Bool
may_dump(const NSegment
*seg
)
65 if ((seg
->kind
== SkAnonC
) ||
66 (seg
->kind
== SkShmC
) ||
67 ((seg
->kind
== SkFileC
) &&
68 !VKI_S_ISCHR(seg
->mode
) && !VKI_S_ISBLK(seg
->mode
)))
74 /* If true, then this Segment's contents will be in the core */
75 static Bool
should_dump(const NSegment
*seg
)
80 #if defined(SOLARIS_PRXREGSET_T)
81 static Bool
should_dump_xregs(const ThreadState
*tst
)
83 #if defined(VGP_x86_solaris)
85 #elif defined(VGP_amd64_solaris)
86 const ThreadArchState
*arch
= (const ThreadArchState
*) &tst
->arch
;
88 /* Dump 256-bit wide %ymm only when their upper half is non-zero. */
89 #define YMM_NON_ZERO(reg) \
90 ((reg[4] != 0) || (reg[5] != 0) || (reg[6] != 0) || (reg[7] != 0))
91 if (YMM_NON_ZERO(arch
->vex
.guest_YMM0
) ||
92 YMM_NON_ZERO(arch
->vex
.guest_YMM1
) ||
93 YMM_NON_ZERO(arch
->vex
.guest_YMM2
) ||
94 YMM_NON_ZERO(arch
->vex
.guest_YMM3
) ||
95 YMM_NON_ZERO(arch
->vex
.guest_YMM4
) ||
96 YMM_NON_ZERO(arch
->vex
.guest_YMM5
) ||
97 YMM_NON_ZERO(arch
->vex
.guest_YMM6
) ||
98 YMM_NON_ZERO(arch
->vex
.guest_YMM7
) ||
99 YMM_NON_ZERO(arch
->vex
.guest_YMM9
) ||
100 YMM_NON_ZERO(arch
->vex
.guest_YMM0
) ||
101 YMM_NON_ZERO(arch
->vex
.guest_YMM10
) ||
102 YMM_NON_ZERO(arch
->vex
.guest_YMM11
) ||
103 YMM_NON_ZERO(arch
->vex
.guest_YMM12
) ||
104 YMM_NON_ZERO(arch
->vex
.guest_YMM13
) ||
105 YMM_NON_ZERO(arch
->vex
.guest_YMM14
) ||
106 YMM_NON_ZERO(arch
->vex
.guest_YMM15
))
113 # error Unknown ELF platform
116 #endif /* SOLARIS_PRXREGSET_T */
118 static void write_part(Int fd
, const HChar
*filename
,
119 void *buf
, SizeT buf_size
, const HChar
*part
)
121 Int ret
= VG_(write
)(fd
, buf
, buf_size
);
123 VG_(umsg
)("Failed to write %s to coredump file %s, it may be "
124 "incomplete.\n", part
, filename
);
125 VG_(debugLog
)(1, "coredump-solaris", "write_part: failed to write "
126 "%s to file %s. Buffer address=%p, length=%lu. "
127 "Error=%d.\n", part
, filename
, buf
, buf_size
, -ret
);
131 /*====================================================================*/
132 /*=== Miscellaneous getters ===*/
133 /*====================================================================*/
135 static Int
get_uid(void)
137 return sr_Res(VG_(do_syscall0
)(SYS_getuid
));
140 static Int
get_gid(void)
142 return sr_Res(VG_(do_syscall0
)(SYS_getgid
));
145 static Int
get_dmodel(void)
147 #if defined(VGP_x86_solaris)
148 return PR_MODEL_ILP32
;
149 #elif defined(VGP_amd64_solaris)
150 return PR_MODEL_LP64
;
152 # error "Unknown platform"
156 static vki_zoneid_t
get_zoneid(void)
158 SysRes sres
= VG_(do_syscall2
)(SYS_zone
, VKI_ZONE_LOOKUP
,
160 if (sr_isError(sres
))
166 static UInt
count_auxv(void)
170 vki_auxv_t
*auxv
= (vki_auxv_t
*) VG_(client_auxv
);
171 while (auxv
->a_type
!= VKI_AT_NULL
) {
179 static Addr
compute_stkbase(const ThreadState
*tst
)
181 return tst
->client_stack_highest_byte
+ 1
182 - tst
->client_stack_szB
;
185 static Int
get_wstat(const vki_siginfo_t
*si
)
187 return (si
->si_signo
& 0xff) | WCOREFLG
;
190 /*====================================================================*/
191 /*=== Utility fillers ===*/
192 /*====================================================================*/
194 static void fill_platform(HChar
*buf
, UInt buf_size
)
196 vg_assert(buf
!= NULL
);
197 vg_assert(buf_size
>= 1);
201 VG_(do_syscall3
)(SYS_systeminfo
, VKI_SI_PLATFORM
,
202 (UWord
) buf
, buf_size
);
205 static void fill_zonename(HChar
*buf
, UInt buf_size
)
207 vg_assert(buf
!= NULL
);
208 vg_assert(buf_size
>= 1);
212 VG_(do_syscall5
)(SYS_zone
, VKI_ZONE_GETATTR
, get_zoneid(),
213 VKI_ZONE_ATTR_NAME
, (UWord
) buf
, buf_size
);
216 static void fill_thread_state(const ThreadState
*tst
,
217 HChar
*state
, HChar
*sname
)
219 switch (tst
->status
) {
244 static void fill_siginfo(const vki_siginfo_t
*si
, vki_siginfo_t
*di
,
247 di
->si_signo
= si
->si_signo
;
248 di
->si_code
= si
->si_code
;
250 di
->si_addr
= si
->si_addr
;
251 *signo
= si
->si_signo
;
254 static void fill_argv(Int
*argc
, Addr
*argv
)
256 Addr
*ptr
= (Addr
*) VG_(get_initial_client_SP
)();
261 static void fill_scheduling_class(HChar
*buf
, SizeT buf_size
)
263 vg_assert(buf
!= NULL
);
264 vg_assert(buf_size
>= 1);
266 /* Valgrind currently schedules one thread at time which
267 resembles the default timeshare class. */
268 VG_(strncpy
)(buf
, "TS", buf_size
);
271 static void fill_regset(vki_prgregset_t
*regs
, const ThreadState
*tst
)
273 const ThreadArchState
*arch
= (const ThreadArchState
*) &tst
->arch
;
275 #if defined(VGP_x86_solaris)
276 (*regs
)[VKI_EIP
] = arch
->vex
.guest_EIP
;
277 (*regs
)[VKI_EAX
] = arch
->vex
.guest_EAX
;
278 (*regs
)[VKI_EBX
] = arch
->vex
.guest_EBX
;
279 (*regs
)[VKI_ECX
] = arch
->vex
.guest_ECX
;
280 (*regs
)[VKI_EDX
] = arch
->vex
.guest_EDX
;
281 (*regs
)[VKI_ESI
] = arch
->vex
.guest_ESI
;
282 (*regs
)[VKI_EDI
] = arch
->vex
.guest_EDI
;
283 (*regs
)[VKI_EBP
] = arch
->vex
.guest_EBP
;
284 (*regs
)[VKI_UESP
] = arch
->vex
.guest_ESP
;
285 (*regs
)[VKI_SS
] = arch
->vex
.guest_SS
;
286 (*regs
)[VKI_CS
] = arch
->vex
.guest_CS
;
287 (*regs
)[VKI_DS
] = arch
->vex
.guest_DS
;
288 (*regs
)[VKI_ES
] = arch
->vex
.guest_ES
;
289 (*regs
)[VKI_FS
] = arch
->vex
.guest_FS
;
290 (*regs
)[VKI_GS
] = arch
->vex
.guest_GS
;
291 (*regs
)[VKI_EFL
] = LibVEX_GuestX86_get_eflags(&arch
->vex
);
292 #elif defined(VGP_amd64_solaris)
293 (*regs
)[VKI_REG_RIP
] = arch
->vex
.guest_RIP
;
294 (*regs
)[VKI_REG_RAX
] = arch
->vex
.guest_RAX
;
295 (*regs
)[VKI_REG_RBX
] = arch
->vex
.guest_RBX
;
296 (*regs
)[VKI_REG_RCX
] = arch
->vex
.guest_RCX
;
297 (*regs
)[VKI_REG_RDX
] = arch
->vex
.guest_RDX
;
298 (*regs
)[VKI_REG_RBP
] = arch
->vex
.guest_RBP
;
299 (*regs
)[VKI_REG_RSI
] = arch
->vex
.guest_RSI
;
300 (*regs
)[VKI_REG_RDI
] = arch
->vex
.guest_RDI
;
301 (*regs
)[VKI_REG_R8
] = arch
->vex
.guest_R8
;
302 (*regs
)[VKI_REG_R9
] = arch
->vex
.guest_R9
;
303 (*regs
)[VKI_REG_R10
] = arch
->vex
.guest_R10
;
304 (*regs
)[VKI_REG_R11
] = arch
->vex
.guest_R11
;
305 (*regs
)[VKI_REG_R12
] = arch
->vex
.guest_R12
;
306 (*regs
)[VKI_REG_R13
] = arch
->vex
.guest_R13
;
307 (*regs
)[VKI_REG_R14
] = arch
->vex
.guest_R14
;
308 (*regs
)[VKI_REG_R15
] = arch
->vex
.guest_R15
;
309 (*regs
)[VKI_REG_RSP
] = arch
->vex
.guest_RSP
;
310 (*regs
)[VKI_REG_CS
] = VKI_UCS_SEL
;
311 (*regs
)[VKI_REG_DS
] = 0;
312 (*regs
)[VKI_REG_ES
] = 0;
313 (*regs
)[VKI_REG_FS
] = 0;
314 (*regs
)[VKI_REG_GS
] = 0;
315 (*regs
)[VKI_REG_SS
] = VKI_UDS_SEL
;
316 (*regs
)[VKI_REG_FSBASE
] = arch
->vex
.guest_FS_CONST
;
317 (*regs
)[VKI_REG_GSBASE
] = 0;
318 (*regs
)[VKI_REG_RFL
] = LibVEX_GuestAMD64_get_rflags(&arch
->vex
);
320 # error "Unknown platform"
324 static void fill_fpregset(vki_fpregset_t
*fpu
, const ThreadState
*tst
)
326 const ThreadArchState
*arch
= (const ThreadArchState
*) &tst
->arch
;
328 #if defined(VGP_x86_solaris)
329 VG_(memset
)(fpu
, 0, sizeof(*fpu
));
331 struct vki_fpchip_state
*fs
= &fpu
->fp_reg_set
.fpchip_state
;
332 vg_assert(sizeof(fs
->state
) == 108);
334 LibVEX_GuestX86_get_x87(CONST_CAST(VexGuestX86State
*, &arch
->vex
),
335 (UChar
*) &fs
->state
);
338 UInt mxcsr
= LibVEX_GuestX86_get_mxcsr(CONST_CAST(VexGuestX86State
*,
343 #define COPY_OUT_XMM(dest, src) \
345 dest._l[0] = src[0]; \
346 dest._l[1] = src[1]; \
347 dest._l[2] = src[2]; \
348 dest._l[3] = src[3]; \
350 COPY_OUT_XMM(fs
->xmm
[0], arch
->vex
.guest_XMM0
);
351 COPY_OUT_XMM(fs
->xmm
[1], arch
->vex
.guest_XMM1
);
352 COPY_OUT_XMM(fs
->xmm
[2], arch
->vex
.guest_XMM2
);
353 COPY_OUT_XMM(fs
->xmm
[3], arch
->vex
.guest_XMM3
);
354 COPY_OUT_XMM(fs
->xmm
[4], arch
->vex
.guest_XMM4
);
355 COPY_OUT_XMM(fs
->xmm
[5], arch
->vex
.guest_XMM5
);
356 COPY_OUT_XMM(fs
->xmm
[6], arch
->vex
.guest_XMM6
);
357 COPY_OUT_XMM(fs
->xmm
[7], arch
->vex
.guest_XMM7
);
359 #elif defined(VGP_amd64_solaris)
360 VG_(memset
)(fpu
, 0, sizeof(*fpu
));
361 struct vki_fpchip_state
*fs
= &fpu
->fp_reg_set
.fpchip_state
;
363 /* LibVEX_GuestAMD64_fxsave() requires at least 416 bytes. */
364 vg_assert(sizeof(*fs
) >= 416);
365 LibVEX_GuestAMD64_fxsave(CONST_CAST(VexGuestAMD64State
*, &arch
->vex
),
368 # error Unknown platform
372 /*====================================================================*/
373 /*=== Header fillers ===*/
374 /*====================================================================*/
376 static void fill_ehdr(VKI_ESZ(Ehdr
) *ehdr
, Int num_phdrs
)
378 VG_(memset
)(ehdr
, 0, sizeof(*ehdr
));
380 VG_(memcpy
)(ehdr
->e_ident
, VKI_ELFMAG
, VKI_SELFMAG
);
381 ehdr
->e_ident
[VKI_EI_CLASS
] = VG_ELF_CLASS
;
382 ehdr
->e_ident
[VKI_EI_DATA
] = VG_ELF_DATA2XXX
;
383 ehdr
->e_ident
[VKI_EI_VERSION
] = VKI_EV_CURRENT
;
385 ehdr
->e_type
= VKI_ET_CORE
;
386 ehdr
->e_machine
= VG_ELF_MACHINE
;
387 ehdr
->e_version
= VKI_EV_CURRENT
;
390 ehdr
->e_ehsize
= sizeof(VKI_ESZ(Ehdr
));
392 ehdr
->e_phoff
= sizeof(VKI_ESZ(Ehdr
));
393 ehdr
->e_phentsize
= sizeof(VKI_ESZ(Phdr
));
395 /* If the count of program headers can't fit in the mere 16 bits
396 * shortsightedly allotted to them in the ELF header, we use the
397 * extended formats and put the real values in the section header
400 if (num_phdrs
>= VKI_PN_XNUM
) {
401 ehdr
->e_phnum
= VKI_PN_XNUM
;
403 ehdr
->e_shoff
= ehdr
->e_phoff
+ ehdr
->e_phentsize
* num_phdrs
;
404 ehdr
->e_shentsize
= sizeof(VKI_ESZ(Shdr
));
406 ehdr
->e_phnum
= num_phdrs
;
409 ehdr
->e_shentsize
= 0;
412 ehdr
->e_shstrndx
= 0;
415 static void fill_phdr(VKI_ESZ(Phdr
) *phdr
, const NSegment
*seg
, UInt off
,
418 SizeT len
= seg
->end
- seg
->start
+ 1;
420 really_write
= really_write
&& should_dump(seg
);
422 VG_(memset
)(phdr
, 0, sizeof(*phdr
));
424 phdr
->p_type
= PT_LOAD
;
425 phdr
->p_offset
= off
;
426 phdr
->p_vaddr
= seg
->start
;
428 phdr
->p_filesz
= really_write
? len
: 0;
433 phdr
->p_flags
|= PF_R
;
435 phdr
->p_flags
|= PF_W
;
437 phdr
->p_flags
|= PF_X
;
439 phdr
->p_align
= VKI_PAGE_SIZE
;
442 /* Fills the section header at index zero when num_phdrs >= PN_XNUM. */
443 static void fill_zero_shdr(VKI_ESZ(Shdr
) *shdr
, UInt num_phdrs
)
445 vg_assert(num_phdrs
>= VKI_PN_XNUM
);
447 VG_(memset
)(shdr
, 0, sizeof(*shdr
));
449 shdr
->sh_name
= 0; // STR_NONE
450 shdr
->sh_info
= num_phdrs
;
453 static void fill_prpsinfo(vki_elf_prpsinfo_t
*prpsinfo
,
454 const ThreadState
*tst
,
455 const vki_siginfo_t
*si
)
457 VG_(memset
)(prpsinfo
, 0, sizeof(*prpsinfo
));
459 fill_thread_state(tst
, &prpsinfo
->pr_state
, &prpsinfo
->pr_sname
);
460 prpsinfo
->pr_uid
= get_uid();
461 prpsinfo
->pr_gid
= get_gid();
462 prpsinfo
->pr_pid
= VG_(getpid
)();
463 prpsinfo
->pr_ppid
= VG_(getppid
)();
464 prpsinfo
->pr_pgrp
= VG_(getpgrp
)();
465 prpsinfo
->pr_sid
= VG_(getpgrp
)();
466 fill_scheduling_class(prpsinfo
->pr_clname
, sizeof(prpsinfo
->pr_clname
));
467 VG_(client_fname
)(prpsinfo
->pr_fname
, sizeof(prpsinfo
->pr_fname
), True
);
468 VG_(client_cmd_and_args
)(prpsinfo
->pr_psargs
,
469 sizeof(prpsinfo
->pr_psargs
));
470 fill_argv(&prpsinfo
->pr_argc
, (Addr
*) &prpsinfo
->pr_argv
);
471 prpsinfo
->pr_envp
= (char **) VG_(client_envp
);
472 prpsinfo
->pr_wstat
= get_wstat(si
);
473 prpsinfo
->pr_euid
= VG_(geteuid
)();
474 prpsinfo
->pr_egid
= VG_(getegid
)();
475 prpsinfo
->pr_dmodel
= get_dmodel();
478 static void fill_prstatus(vki_elf_prstatus_t
*prs
,
479 const ThreadState
*tst
,
480 const vki_siginfo_t
*si
)
482 VG_(memset
)(prs
, 0, sizeof(*prs
));
484 prs
->pr_flags
= VKI_ELF_OLD_PR_PCINVAL
;
485 fill_siginfo(si
, &prs
->pr_info
, &prs
->pr_cursig
);
486 prs
->pr_nlwp
= VG_(count_living_threads
)();
487 prs
->pr_sighold
= tst
->sig_mask
;
488 prs
->pr_pid
= VG_(getpid
)();
489 prs
->pr_ppid
= VG_(getppid
)();
490 prs
->pr_pgrp
= VG_(getpgrp
)();
491 prs
->pr_sid
= VG_(getpgrp
)();
492 fill_scheduling_class(prs
->pr_clname
, sizeof(prs
->pr_clname
));
493 prs
->pr_who
= tst
->os_state
.lwpid
;
494 prs
->pr_brkbase
= (vki_caddr_t
) VG_(brk_base
);
495 prs
->pr_brksize
= VG_(brk_limit
) - VG_(brk_base
);
496 prs
->pr_stkbase
= (vki_caddr_t
) compute_stkbase(tst
);
497 prs
->pr_stksize
= tst
->client_stack_szB
;
498 fill_regset(&prs
->pr_reg
, tst
);
501 static void fill_psinfo(vki_psinfo_t
*psinfo
, const ThreadState
*tst
,
502 const vki_siginfo_t
*si
)
504 VG_(memset
)(psinfo
, 0, sizeof(*psinfo
));
506 psinfo
->pr_nlwp
= VG_(count_living_threads
)();
507 psinfo
->pr_uid
= get_uid();
508 psinfo
->pr_gid
= get_gid();
509 psinfo
->pr_pid
= VG_(getpid
)();
510 psinfo
->pr_ppid
= VG_(getppid
)();
511 psinfo
->pr_pgid
= VG_(getpgrp
)();
512 psinfo
->pr_sid
= VG_(getpgrp
)();
513 psinfo
->pr_euid
= VG_(geteuid
)();
514 psinfo
->pr_egid
= VG_(getegid
)();
515 VG_(client_fname
)(psinfo
->pr_fname
, sizeof(psinfo
->pr_fname
), True
);
516 psinfo
->pr_wstat
= get_wstat(si
);
517 VG_(client_cmd_and_args
)(psinfo
->pr_psargs
,
518 sizeof(psinfo
->pr_psargs
));
519 fill_argv(&psinfo
->pr_argc
, (Addr
*) &psinfo
->pr_argv
);
520 psinfo
->pr_envp
= (uintptr_t) VG_(client_envp
);
521 psinfo
->pr_dmodel
= get_dmodel();
522 psinfo
->pr_zoneid
= get_zoneid();
524 psinfo
->pr_lwp
.pr_lwpid
= tst
->os_state
.lwpid
;
525 fill_thread_state(tst
, &psinfo
->pr_lwp
.pr_state
,
526 &psinfo
->pr_lwp
.pr_sname
);
527 fill_scheduling_class(psinfo
->pr_lwp
.pr_clname
,
528 sizeof(psinfo
->pr_lwp
.pr_clname
));
531 static void fill_pstatus(vki_pstatus_t
*pstatus
,
532 const ThreadState
*tst
,
533 const vki_siginfo_t
*si
)
535 VG_(memset
)(pstatus
, 0, sizeof(*pstatus
));
537 pstatus
->pr_flags
= VKI_PR_PCINVAL
;
538 pstatus
->pr_nlwp
= VG_(count_living_threads
)();
539 pstatus
->pr_pid
= VG_(getpid
)();
540 pstatus
->pr_ppid
= VG_(getppid
)();
541 pstatus
->pr_pgid
= VG_(getpgrp
)();
542 pstatus
->pr_sid
= VG_(getpgrp
)();
543 pstatus
->pr_brkbase
= (uintptr_t) VG_(brk_base
);
544 pstatus
->pr_brksize
= VG_(brk_limit
) - VG_(brk_base
);
545 pstatus
->pr_stkbase
= (uintptr_t) compute_stkbase(tst
);
546 pstatus
->pr_stksize
= tst
->client_stack_szB
;
547 pstatus
->pr_dmodel
= get_dmodel();
548 pstatus
->pr_zoneid
= get_zoneid();
550 pstatus
->pr_lwp
.pr_flags
= VKI_PR_PCINVAL
;
551 pstatus
->pr_lwp
.pr_lwpid
= tst
->os_state
.lwpid
;
552 fill_siginfo(si
, &pstatus
->pr_lwp
.pr_info
,
553 &pstatus
->pr_lwp
.pr_cursig
);
554 pstatus
->pr_lwp
.pr_lwphold
= tst
->sig_mask
;
555 fill_scheduling_class(pstatus
->pr_lwp
.pr_clname
,
556 sizeof(pstatus
->pr_lwp
.pr_clname
));
557 fill_regset(&pstatus
->pr_lwp
.pr_reg
, tst
);
558 fill_fpregset(&pstatus
->pr_lwp
.pr_fpreg
, tst
);
561 #if defined(SOLARIS_PRXREGSET_T)
562 static void fill_xregs(vki_prxregset_t
*xregs
, const ThreadState
*tst
)
564 const ThreadArchState
*arch
= (const ThreadArchState
*) &tst
->arch
;
566 #if defined(VGP_x86_solaris)
567 VG_(memset
)(xregs
, 0, sizeof(*xregs
));
568 xregs
->pr_xsize
= sizeof(xregs
->pr_un
.pr_xsave
);
571 UInt mxcsr
= LibVEX_GuestX86_get_mxcsr(CONST_CAST(VexGuestX86State
*,
573 xregs
->pr_un
.pr_xsave
.pr_mxcsr
= mxcsr
;
576 #define COPY_OUT_XMM(dest, src) \
578 dest._l[0] = src[0]; \
579 dest._l[1] = src[1]; \
580 dest._l[2] = src[2]; \
581 dest._l[3] = src[3]; \
583 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[0], arch
->vex
.guest_XMM0
);
584 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[1], arch
->vex
.guest_XMM1
);
585 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[2], arch
->vex
.guest_XMM2
);
586 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[3], arch
->vex
.guest_XMM3
);
587 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[4], arch
->vex
.guest_XMM4
);
588 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[5], arch
->vex
.guest_XMM5
);
589 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[6], arch
->vex
.guest_XMM6
);
590 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[7], arch
->vex
.guest_XMM7
);
593 #elif defined(VGP_amd64_solaris)
594 VG_(memset
)(xregs
, 0, sizeof(*xregs
));
595 xregs
->pr_xsize
= sizeof(xregs
->pr_un
.pr_xsave
);
597 /* LibVEX_GuestAMD64_fxsave() requires at least 416 bytes. */
598 vg_assert(sizeof(xregs
->pr_un
.pr_xsave
) >= 416);
599 LibVEX_GuestAMD64_fxsave(CONST_CAST(VexGuestAMD64State
*, &arch
->vex
),
600 (Addr
) &xregs
->pr_un
.pr_xsave
);
602 # error "Unknown platform"
605 #endif /* SOLARIS_PRXREGSET_T */
607 static void fill_utsname(struct vki_utsname
*uts
)
609 VG_(memset
)(uts
, 0, sizeof(*uts
));
611 VG_(do_syscall3
)(SYS_systeminfo
, VKI_SI_SYSNAME
,
612 (UWord
) &uts
->sysname
, sizeof(uts
->sysname
));
613 VG_(do_syscall3
)(SYS_systeminfo
, VKI_SI_HOSTNAME
,
614 (UWord
) &uts
->nodename
, sizeof(uts
->nodename
));
615 VG_(do_syscall3
)(SYS_systeminfo
, VKI_SI_RELEASE
,
616 (UWord
) &uts
->release
, sizeof(uts
->release
));
617 VG_(do_syscall3
)(SYS_systeminfo
, VKI_SI_VERSION
,
618 (UWord
) &uts
->version
, sizeof(uts
->version
));
619 VG_(do_syscall3
)(SYS_systeminfo
, VKI_SI_MACHINE
,
620 (UWord
) &uts
->machine
, sizeof(uts
->machine
));
623 static vki_prcred_t
*create_prcred(SizeT
*size
)
625 UInt group_list
[VKI_NGROUPS_MAX
];
626 Int ngroups
= VG_(getgroups
)(VKI_NGROUPS_MAX
, group_list
);
630 *size
= sizeof(vki_prcred_t
) + (ngroups
- 1) * sizeof(gid_t
);
631 vki_prcred_t
*prcred
= VG_(malloc
)("coredump-elf.cp.1", *size
);
632 VG_(memset
)(prcred
, 0, *size
);
634 prcred
->pr_euid
= VG_(geteuid
)();
635 prcred
->pr_ruid
= get_uid();
636 prcred
->pr_suid
= prcred
->pr_euid
;
637 prcred
->pr_egid
= VG_(getegid
)();
638 prcred
->pr_rgid
= get_gid();
639 prcred
->pr_sgid
= prcred
->pr_egid
;
640 prcred
->pr_ngroups
= ngroups
;
643 for (i
= 0; i
< ngroups
; i
++)
644 prcred
->pr_groups
[i
] = group_list
[i
];
649 static void fill_core_content(vki_core_content_t
*content
)
651 *content
= VKI_CC_CONTENT_STACK
| VKI_CC_CONTENT_HEAP
652 | VKI_CC_CONTENT_SHANON
| VKI_CC_CONTENT_TEXT
653 | VKI_CC_CONTENT_DATA
| VKI_CC_CONTENT_RODATA
654 | VKI_CC_CONTENT_ANON
| VKI_CC_CONTENT_SHM
655 | VKI_CC_CONTENT_ISM
| VKI_CC_CONTENT_DISM
;
658 static vki_prpriv_t
*create_prpriv(SizeT
*size
)
660 Int fd
= VG_(fd_open
)("/proc/self/priv", O_RDONLY
, 0);
664 struct vg_stat stats
;
665 if (VG_(fstat
)(fd
, &stats
) != 0) {
670 vki_prpriv_t
*prpriv
= VG_(malloc
)("coredump-elf.cp.1", stats
.size
);
672 if (VG_(read
)(fd
, prpriv
, stats
.size
) != stats
.size
) {
683 static vki_priv_impl_info_t
*create_priv_info(SizeT
*size
)
685 /* Size of the returned priv_impl_info_t is apriori unknown. */
686 vki_priv_impl_info_t first_cut
[100];
687 SysRes sres
= VG_(do_syscall5
)(SYS_privsys
, VKI_PRIVSYS_GETIMPLINFO
,
688 0, 0, (UWord
) first_cut
,
690 if (sr_isError(sres
))
693 SizeT real_size
= first_cut
[0].priv_headersize
694 + first_cut
[0].priv_globalinfosize
;
695 vki_priv_impl_info_t
*priv_info
= VG_(malloc
)("coredump-elf.cpi.1",
698 if (real_size
<= sizeof(first_cut
)) {
699 /* if the first_cut was large enough */
700 VG_(memcpy
)(priv_info
, first_cut
, real_size
);
702 /* otherwise repeat the syscall with buffer large enough */
703 sres
= VG_(do_syscall5
)(SYS_privsys
, VKI_PRIVSYS_GETIMPLINFO
,
704 0, 0, (UWord
) priv_info
, real_size
);
705 if (sr_isError(sres
)) {
706 VG_(free
)(priv_info
);
715 static void fill_lwpsinfo(vki_lwpsinfo_t
*lwp
,
716 const ThreadState
*tst
)
718 VG_(memset
)(lwp
, 0, sizeof(*lwp
));
720 lwp
->pr_lwpid
= tst
->os_state
.lwpid
;
721 fill_thread_state(tst
, &lwp
->pr_state
, &lwp
->pr_sname
);
722 fill_scheduling_class(lwp
->pr_clname
, sizeof(lwp
->pr_clname
));
725 static void fill_lwpstatus(vki_lwpstatus_t
*lwp
,
726 const ThreadState
*tst
,
727 const vki_siginfo_t
*si
)
729 VG_(memset
)(lwp
, 0, sizeof(*lwp
));
731 lwp
->pr_flags
= VKI_PR_PCINVAL
;
732 lwp
->pr_lwpid
= tst
->os_state
.lwpid
;
733 fill_siginfo(si
, &lwp
->pr_info
, &lwp
->pr_cursig
);
734 fill_scheduling_class(lwp
->pr_clname
, sizeof(lwp
->pr_clname
));
735 fill_regset(&lwp
->pr_reg
, tst
);
736 fill_fpregset(&lwp
->pr_fpreg
, tst
);
739 static void fill_old_note_for_thread(note_t
**notes
,
740 const ThreadState
*tst
,
741 const vki_siginfo_t
*si
)
743 vki_elf_prstatus_t prstatus
;
744 fill_prstatus(&prstatus
, tst
, si
);
745 add_note(notes
, VKI_NT_PRSTATUS
, &prstatus
, sizeof(vki_elf_prstatus_t
));
748 fill_fpregset(&fpu
, tst
);
749 add_note(notes
, VKI_NT_PRFPREG
, &fpu
, sizeof(vki_fpregset_t
));
751 #if defined(SOLARIS_PRXREGSET_T)
752 if (should_dump_xregs(tst
)) {
753 vki_prxregset_t xregs
;
754 fill_xregs(&xregs
, tst
);
755 add_note(notes
, VKI_NT_PRXREG
, &xregs
, sizeof(vki_prxregset_t
));
757 #endif /* SOLARIS_PRXREGSET_T */
760 static void fill_new_note_for_thread(note_t
**notes
,
761 const ThreadState
*tst
,
762 const vki_siginfo_t
*si
)
764 vki_lwpsinfo_t lwpsinfo
;
765 fill_lwpsinfo(&lwpsinfo
, tst
);
766 add_note(notes
, VKI_NT_LWPSINFO
, &lwpsinfo
, sizeof(vki_lwpsinfo_t
));
768 vki_lwpstatus_t lwpstatus
;
769 fill_lwpstatus(&lwpstatus
, tst
, si
);
770 add_note(notes
, VKI_NT_LWPSTATUS
, &lwpstatus
, sizeof(vki_lwpstatus_t
));
772 #if defined(SOLARIS_PRXREGSET_T)
773 if (should_dump_xregs(tst
)) {
774 vki_prxregset_t xregs
;
775 fill_xregs(&xregs
, tst
);
776 add_note(notes
, VKI_NT_PRXREG
, &xregs
, sizeof(vki_prxregset_t
));
778 #endif /* SOLARIS_PRXREGSET_T */
781 /*====================================================================*/
782 /*=== Note utility functions ===*/
783 /*====================================================================*/
785 static void add_note(note_t
**list
, UInt type
, const void *data
,
788 UInt note_size
= sizeof(note_t
) + VG_ROUNDUP(datasz
, 4);
790 note_t
*n
= VG_(malloc
)("coredump-elf.an.1", note_size
);
792 VG_(memset
)(n
, 0, note_size
);
793 n
->nhdr
.n_type
= type
;
794 n
->nhdr
.n_namesz
= 5;
795 n
->nhdr
.n_descsz
= VG_ROUNDUP(datasz
, 4);
796 VG_(memcpy
)(n
->name
, "CORE", 4);
797 VG_(memcpy
)(n
->data
, data
, datasz
);
804 note_t
*tail
= *list
;
805 while (tail
->next
!= NULL
)
810 static UInt
note_size(const note_t
*note
)
812 return sizeof(note_t
) - sizeof(note_t
*) + note
->nhdr
.n_descsz
;
815 static UInt
notes_size(const note_t
*list
)
820 for (note
= list
; note
!= NULL
; note
= note
->next
)
821 size
+= note_size(note
);
826 static void fill_notes_phdr(VKI_ESZ(Phdr
) *phdr
, UInt offset
,
829 phdr
->p_type
= PT_NOTE
;
830 phdr
->p_offset
= offset
;
833 phdr
->p_filesz
= size_of_notes
;
835 phdr
->p_flags
= PF_R
;
839 static void write_notes(Int fd
, const HChar
*filename
,
844 for (note
= list
; note
!= NULL
; note
= note
->next
)
845 write_part(fd
, filename
, CONST_CAST(void *, ¬e
->nhdr
),
846 note_size(note
), "notes");
849 static void free_notes(note_t
*list
)
851 while (list
!= NULL
) {
852 note_t
*next
= list
->next
;
858 /*====================================================================*/
859 /*=== Main coredump function ===*/
860 /*====================================================================*/
862 void VG_(make_coredump
)(ThreadId tid
, const vki_siginfo_t
*si
,
865 const HChar
*basename
= "vgcore";
866 const HChar
*coreext
= "";
869 if (VG_(clo_log_fname_unexpanded
) != NULL
) {
871 basename
= VG_(expand_file_name
)("--log-file",
872 VG_(clo_log_fname_unexpanded
));
875 vg_assert(coreext
!= NULL
);
876 vg_assert(basename
!= NULL
);
878 UInt filename_size
= VG_(strlen
)(coreext
) + VG_(strlen
)(basename
)
879 + 100; /* for the two %d's */
880 HChar
*filename
= VG_(malloc
)("coredump-elf.mc.1", filename_size
);
882 /* Try to come with a non-existent coredump filename. */
885 Int oflags
= VKI_O_CREAT
|VKI_O_WRONLY
|VKI_O_EXCL
|VKI_O_TRUNC
;
888 VG_(snprintf
)(filename
, filename_size
, "%s%s.%d",
889 basename
, coreext
, VG_(getpid
)());
891 VG_(snprintf
)(filename
, filename_size
, "%s%s.%d.%d",
892 basename
, coreext
, VG_(getpid
)(), seq
);
895 #ifdef VKI_O_LARGEFILE
896 oflags
|= VKI_O_LARGEFILE
;
899 SysRes sres
= VG_(open
)(filename
, oflags
,
900 VKI_S_IRUSR
|VKI_S_IWUSR
);
901 if (!sr_isError(sres
)) {
902 core_fd
= sr_Res(sres
);
906 if (sr_isError(sres
) && sr_Err(sres
) != VKI_EEXIST
) {
907 VG_(umsg
)("Cannot create coredump file %s (%lu)\n",
908 filename
, sr_Err(sres
));
914 /* Get the client segments. Free seg_starts after use. */
916 Addr
*seg_starts
= VG_(get_segment_starts
)(SkFileC
| SkAnonC
| SkShmC
,
919 /* Count how many memory segments to dump. */
921 UInt num_phdrs
= 2; /* two CORE note sections */
922 for (i
= 0; i
< n_seg_starts
; i
++) {
923 if (!may_dump(VG_(am_find_nsegment
)(seg_starts
[i
])))
930 fill_ehdr(&ehdr
, num_phdrs
);
933 if (ehdr
.e_shnum
> 0)
934 fill_zero_shdr(&shdr
, num_phdrs
);
935 UInt phdrs_size
= num_phdrs
* ehdr
.e_phentsize
;
937 /* Construct the old-style notes. */
938 note_t
*old_notes
= NULL
;
940 vki_elf_prpsinfo_t prpsinfo
;
941 fill_prpsinfo(&prpsinfo
, &VG_(threads
)[tid
], si
);
942 add_note(&old_notes
, VKI_NT_PRPSINFO
, &prpsinfo
,
943 sizeof(vki_elf_prpsinfo_t
));
945 HChar platform
[256 + 1];
946 fill_platform(platform
, sizeof(platform
));
947 add_note(&old_notes
, VKI_NT_PLATFORM
, platform
,
948 VG_(strlen
)(platform
) + 1);
950 add_note(&old_notes
, VKI_NT_AUXV
, VG_(client_auxv
),
951 count_auxv() * sizeof(auxv_t
));
953 /* Add detail about the faulting thread as the first note.
954 This is how gdb determines which thread faulted. Note that
955 mdb does not need such aid. */
956 fill_old_note_for_thread(&old_notes
, &VG_(threads
)[tid
], si
);
958 /* Now add details for all threads except the one that faulted. */
960 for (t_idx
= 1; t_idx
< VG_N_THREADS
; t_idx
++)
961 if ((VG_(threads
)[t_idx
].status
!= VgTs_Empty
) &&
962 (VG_(threads
)[t_idx
].status
!= VgTs_Zombie
)) {
966 fill_old_note_for_thread(&old_notes
, &VG_(threads
)[t_idx
], si
);
969 /* Construct the new-style notes. */
970 note_t
*new_notes
= NULL
;
972 fill_psinfo(&psinfo
, &VG_(threads
)[tid
], si
);
973 add_note(&new_notes
, VKI_NT_PSINFO
, &psinfo
, sizeof(vki_psinfo_t
));
975 vki_pstatus_t pstatus
;
976 fill_pstatus(&pstatus
, &VG_(threads
)[tid
], si
);
977 add_note(&new_notes
, VKI_NT_PSTATUS
, &pstatus
, sizeof(vki_pstatus_t
));
979 add_note(&new_notes
, VKI_NT_PLATFORM
, platform
,
980 VG_(strlen
)(platform
) + 1);
982 add_note(&new_notes
, VKI_NT_AUXV
, VG_(client_auxv
),
983 count_auxv() * sizeof(auxv_t
));
985 struct vki_utsname uts
;
987 add_note(&new_notes
, VKI_NT_UTSNAME
, &uts
,
988 sizeof(struct vki_utsname
));
991 vki_prcred_t
*prcred
= create_prcred(&prcred_size
);
992 if (prcred
!= NULL
) {
993 add_note(&new_notes
, VKI_NT_PRCRED
, prcred
, prcred_size
);
997 vki_core_content_t core_content
;
998 fill_core_content(&core_content
);
999 add_note(&new_notes
, VKI_NT_CONTENT
, &core_content
,
1000 sizeof(vki_core_content_t
));
1003 vki_prpriv_t
*prpriv
= create_prpriv(&priv_size
);
1004 if (prpriv
!= NULL
) {
1005 add_note(&new_notes
, VKI_NT_PRPRIV
, prpriv
, priv_size
);
1009 vki_priv_impl_info_t
*priv_info
= create_priv_info(&priv_size
);
1010 if (priv_info
!= NULL
) {
1011 add_note(&new_notes
, VKI_NT_PRPRIVINFO
, priv_info
, priv_size
);
1012 VG_(free
)(priv_info
);
1015 HChar zonename
[VKI_ZONENAME_MAX
+ 1];
1016 fill_zonename(zonename
, sizeof(zonename
));
1017 add_note(&new_notes
, VKI_NT_ZONENAME
, zonename
,
1018 VG_(strlen
)(zonename
) + 1);
1020 /* Add detail about the faulting thread as the first note.
1021 This is how gdb determines which thread faulted. Note that
1022 mdb does not need such aid. */
1023 fill_new_note_for_thread(&new_notes
, &VG_(threads
)[tid
], si
);
1025 /* Now add details for all threads except the one that faulted. */
1026 for (t_idx
= 1; t_idx
< VG_N_THREADS
; t_idx
++) {
1027 if ((VG_(threads
)[t_idx
].status
!= VgTs_Empty
) &&
1028 (VG_(threads
)[t_idx
].status
!= VgTs_Zombie
)) {
1032 fill_new_note_for_thread(&new_notes
, &VG_(threads
)[t_idx
], si
);
1036 VKI_ESZ(Phdr
) *phdrs
= VG_(malloc
)("coredump-elf.mc.2", phdrs_size
);
1038 UInt size_of_notes
= notes_size(old_notes
);
1039 UInt offset
= ehdr
.e_ehsize
+ phdrs_size
+
1040 (ehdr
.e_shnum
* ehdr
.e_shentsize
);
1042 /* fill program header for old notes */
1043 fill_notes_phdr(&phdrs
[0], offset
, size_of_notes
);
1044 offset
+= size_of_notes
;
1046 size_of_notes
= notes_size(new_notes
);
1047 /* fill program header for new notes */
1048 fill_notes_phdr(&phdrs
[1], offset
, size_of_notes
);
1049 offset
+= size_of_notes
;
1051 /* fill program headers for segments */
1053 for (i
= 0, idx
= 2; i
< n_seg_starts
; i
++) {
1054 NSegment
const *seg
= VG_(am_find_nsegment
)(seg_starts
[i
]);
1059 fill_phdr(&phdrs
[idx
], seg
, offset
,
1060 (seg
->end
- seg
->start
+ 1 + offset
) < max_size
);
1062 offset
+= phdrs
[idx
].p_filesz
;
1067 /* write everything out */
1068 write_part(core_fd
, filename
, &ehdr
, sizeof(ehdr
),
1070 write_part(core_fd
, filename
, phdrs
, phdrs_size
,
1072 if (ehdr
.e_shnum
> 0)
1073 write_part(core_fd
, filename
, &shdr
, sizeof(shdr
),
1075 write_notes(core_fd
, filename
, old_notes
);
1076 write_notes(core_fd
, filename
, new_notes
);
1078 VG_(lseek
)(core_fd
, phdrs
[2].p_offset
, VKI_SEEK_SET
);
1080 for (i
= 0, idx
= 2; i
< n_seg_starts
; i
++) {
1081 NSegment
const *seg
= VG_(am_find_nsegment
)(seg_starts
[i
]);
1083 if (!should_dump(seg
))
1086 if (phdrs
[idx
].p_filesz
> 0) {
1087 Off64T off
= VG_(lseek
)(core_fd
, phdrs
[idx
].p_offset
,
1089 vg_assert(off
== phdrs
[idx
].p_offset
);
1090 vg_assert(seg
->end
- seg
->start
+ 1 >= phdrs
[idx
].p_filesz
);
1092 write_part(core_fd
, filename
, (void *) seg
->start
,
1093 phdrs
[idx
].p_filesz
, "program segment");
1098 VG_(close
)(core_fd
);
1099 VG_(free
)(filename
);
1101 free_notes(old_notes
);
1102 free_notes(new_notes
);
1103 VG_(free
)(seg_starts
);
1108 /*--------------------------------------------------------------------*/
1110 /*--------------------------------------------------------------------*/