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, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 #if defined(VGO_solaris)
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_coredump.h"
36 #include "pub_core_debuglog.h"
37 #include "pub_core_libcassert.h"
38 #include "pub_core_libcbase.h"
39 #include "pub_core_libcfile.h"
40 #include "pub_core_libcprint.h"
41 #include "pub_core_libcproc.h"
42 #include "pub_core_machine.h"
43 #include "pub_core_mallocfree.h"
44 #include "pub_core_options.h"
45 #include "pub_core_syscall.h"
46 #include "pub_core_threadstate.h"
47 #include "pub_core_xarray.h"
48 #include "pub_core_clientstate.h"
50 typedef struct __attribute__ ((__packed__
)) note
{
57 static void add_note(note_t
**list
, UInt type
, const void *data
,
60 /* If true, then this Segment may be mentioned in the core */
61 static Bool
may_dump(const NSegment
*seg
)
63 if ((seg
->kind
== SkAnonC
) ||
64 (seg
->kind
== SkShmC
) ||
65 ((seg
->kind
== SkFileC
) &&
66 !VKI_S_ISCHR(seg
->mode
) && !VKI_S_ISBLK(seg
->mode
)))
72 /* If true, then this Segment's contents will be in the core */
73 static Bool
should_dump(const NSegment
*seg
)
78 #if defined(SOLARIS_PRXREGSET_T)
79 static Bool
should_dump_xregs(const ThreadState
*tst
)
81 #if defined(VGP_x86_solaris)
83 #elif defined(VGP_amd64_solaris)
84 const ThreadArchState
*arch
= (const ThreadArchState
*) &tst
->arch
;
86 /* Dump 256-bit wide %ymm only when their upper half is non-zero. */
87 #define YMM_NON_ZERO(reg) \
88 ((reg[4] != 0) || (reg[5] != 0) || (reg[6] != 0) || (reg[7] != 0))
89 if (YMM_NON_ZERO(arch
->vex
.guest_YMM0
) ||
90 YMM_NON_ZERO(arch
->vex
.guest_YMM1
) ||
91 YMM_NON_ZERO(arch
->vex
.guest_YMM2
) ||
92 YMM_NON_ZERO(arch
->vex
.guest_YMM3
) ||
93 YMM_NON_ZERO(arch
->vex
.guest_YMM4
) ||
94 YMM_NON_ZERO(arch
->vex
.guest_YMM5
) ||
95 YMM_NON_ZERO(arch
->vex
.guest_YMM6
) ||
96 YMM_NON_ZERO(arch
->vex
.guest_YMM7
) ||
97 YMM_NON_ZERO(arch
->vex
.guest_YMM9
) ||
98 YMM_NON_ZERO(arch
->vex
.guest_YMM0
) ||
99 YMM_NON_ZERO(arch
->vex
.guest_YMM10
) ||
100 YMM_NON_ZERO(arch
->vex
.guest_YMM11
) ||
101 YMM_NON_ZERO(arch
->vex
.guest_YMM12
) ||
102 YMM_NON_ZERO(arch
->vex
.guest_YMM13
) ||
103 YMM_NON_ZERO(arch
->vex
.guest_YMM14
) ||
104 YMM_NON_ZERO(arch
->vex
.guest_YMM15
))
111 # error Unknown ELF platform
114 #endif /* SOLARIS_PRXREGSET_T */
116 static void write_part(Int fd
, const HChar
*filename
,
117 void *buf
, SizeT buf_size
, const HChar
*part
)
119 Int ret
= VG_(write
)(fd
, buf
, buf_size
);
121 VG_(umsg
)("Failed to write %s to coredump file %s, it may be "
122 "incomplete.\n", part
, filename
);
123 VG_(debugLog
)(1, "coredump-solaris", "write_part: failed to write "
124 "%s to file %s. Buffer address=%p, length=%lu. "
125 "Error=%d.\n", part
, filename
, buf
, buf_size
, -ret
);
129 /*====================================================================*/
130 /*=== Miscellaneous getters ===*/
131 /*====================================================================*/
133 static Int
get_uid(void)
135 return sr_Res(VG_(do_syscall0
)(SYS_getuid
));
138 static Int
get_gid(void)
140 return sr_Res(VG_(do_syscall0
)(SYS_getgid
));
143 static Int
get_dmodel(void)
145 #if defined(VGP_x86_solaris)
146 return PR_MODEL_ILP32
;
147 #elif defined(VGP_amd64_solaris)
148 return PR_MODEL_LP64
;
150 # error "Unknown platform"
154 static vki_zoneid_t
get_zoneid(void)
156 SysRes sres
= VG_(do_syscall2
)(SYS_zone
, VKI_ZONE_LOOKUP
,
158 if (sr_isError(sres
))
164 static UInt
count_auxv(void)
168 vki_auxv_t
*auxv
= (vki_auxv_t
*) VG_(client_auxv
);
169 while (auxv
->a_type
!= VKI_AT_NULL
) {
177 static Addr
compute_stkbase(const ThreadState
*tst
)
179 return tst
->client_stack_highest_byte
+ 1
180 - tst
->client_stack_szB
;
183 static Int
get_wstat(const vki_siginfo_t
*si
)
185 return (si
->si_signo
& 0xff) | WCOREFLG
;
188 /*====================================================================*/
189 /*=== Utility fillers ===*/
190 /*====================================================================*/
192 static void fill_platform(HChar
*buf
, UInt buf_size
)
194 vg_assert(buf
!= NULL
);
195 vg_assert(buf_size
>= 1);
199 VG_(do_syscall3
)(SYS_systeminfo
, VKI_SI_PLATFORM
,
200 (UWord
) buf
, buf_size
);
203 static void fill_zonename(HChar
*buf
, UInt buf_size
)
205 vg_assert(buf
!= NULL
);
206 vg_assert(buf_size
>= 1);
210 VG_(do_syscall5
)(SYS_zone
, VKI_ZONE_GETATTR
, get_zoneid(),
211 VKI_ZONE_ATTR_NAME
, (UWord
) buf
, buf_size
);
214 static void fill_thread_state(const ThreadState
*tst
,
215 HChar
*state
, HChar
*sname
)
217 switch (tst
->status
) {
242 static void fill_siginfo(const vki_siginfo_t
*si
, vki_siginfo_t
*di
,
245 di
->si_signo
= si
->si_signo
;
246 di
->si_code
= si
->si_code
;
248 di
->si_addr
= si
->si_addr
;
249 *signo
= si
->si_signo
;
252 static void fill_argv(Int
*argc
, Addr
*argv
)
254 Addr
*ptr
= (Addr
*) VG_(get_initial_client_SP
)();
259 static void fill_scheduling_class(HChar
*buf
, SizeT buf_size
)
261 vg_assert(buf
!= NULL
);
262 vg_assert(buf_size
>= 1);
264 /* Valgrind currently schedules one thread at time which
265 resembles the default timeshare class. */
266 VG_(strncpy
)(buf
, "TS", buf_size
);
269 static void fill_regset(vki_prgregset_t
*regs
, const ThreadState
*tst
)
271 const ThreadArchState
*arch
= (const ThreadArchState
*) &tst
->arch
;
273 #if defined(VGP_x86_solaris)
274 (*regs
)[VKI_EIP
] = arch
->vex
.guest_EIP
;
275 (*regs
)[VKI_EAX
] = arch
->vex
.guest_EAX
;
276 (*regs
)[VKI_EBX
] = arch
->vex
.guest_EBX
;
277 (*regs
)[VKI_ECX
] = arch
->vex
.guest_ECX
;
278 (*regs
)[VKI_EDX
] = arch
->vex
.guest_EDX
;
279 (*regs
)[VKI_ESI
] = arch
->vex
.guest_ESI
;
280 (*regs
)[VKI_EDI
] = arch
->vex
.guest_EDI
;
281 (*regs
)[VKI_EBP
] = arch
->vex
.guest_EBP
;
282 (*regs
)[VKI_UESP
] = arch
->vex
.guest_ESP
;
283 (*regs
)[VKI_SS
] = arch
->vex
.guest_SS
;
284 (*regs
)[VKI_CS
] = arch
->vex
.guest_CS
;
285 (*regs
)[VKI_DS
] = arch
->vex
.guest_DS
;
286 (*regs
)[VKI_ES
] = arch
->vex
.guest_ES
;
287 (*regs
)[VKI_FS
] = arch
->vex
.guest_FS
;
288 (*regs
)[VKI_GS
] = arch
->vex
.guest_GS
;
289 (*regs
)[VKI_EFL
] = LibVEX_GuestX86_get_eflags(&arch
->vex
);
290 #elif defined(VGP_amd64_solaris)
291 (*regs
)[VKI_REG_RIP
] = arch
->vex
.guest_RIP
;
292 (*regs
)[VKI_REG_RAX
] = arch
->vex
.guest_RAX
;
293 (*regs
)[VKI_REG_RBX
] = arch
->vex
.guest_RBX
;
294 (*regs
)[VKI_REG_RCX
] = arch
->vex
.guest_RCX
;
295 (*regs
)[VKI_REG_RDX
] = arch
->vex
.guest_RDX
;
296 (*regs
)[VKI_REG_RBP
] = arch
->vex
.guest_RBP
;
297 (*regs
)[VKI_REG_RSI
] = arch
->vex
.guest_RSI
;
298 (*regs
)[VKI_REG_RDI
] = arch
->vex
.guest_RDI
;
299 (*regs
)[VKI_REG_R8
] = arch
->vex
.guest_R8
;
300 (*regs
)[VKI_REG_R9
] = arch
->vex
.guest_R9
;
301 (*regs
)[VKI_REG_R10
] = arch
->vex
.guest_R10
;
302 (*regs
)[VKI_REG_R11
] = arch
->vex
.guest_R11
;
303 (*regs
)[VKI_REG_R12
] = arch
->vex
.guest_R12
;
304 (*regs
)[VKI_REG_R13
] = arch
->vex
.guest_R13
;
305 (*regs
)[VKI_REG_R14
] = arch
->vex
.guest_R14
;
306 (*regs
)[VKI_REG_R15
] = arch
->vex
.guest_R15
;
307 (*regs
)[VKI_REG_RSP
] = arch
->vex
.guest_RSP
;
308 (*regs
)[VKI_REG_CS
] = VKI_UCS_SEL
;
309 (*regs
)[VKI_REG_DS
] = 0;
310 (*regs
)[VKI_REG_ES
] = 0;
311 (*regs
)[VKI_REG_FS
] = 0;
312 (*regs
)[VKI_REG_GS
] = 0;
313 (*regs
)[VKI_REG_SS
] = VKI_UDS_SEL
;
314 (*regs
)[VKI_REG_FSBASE
] = arch
->vex
.guest_FS_CONST
;
315 (*regs
)[VKI_REG_GSBASE
] = 0;
316 (*regs
)[VKI_REG_RFL
] = LibVEX_GuestAMD64_get_rflags(&arch
->vex
);
318 # error "Unknown platform"
322 static void fill_fpregset(vki_fpregset_t
*fpu
, const ThreadState
*tst
)
324 const ThreadArchState
*arch
= (const ThreadArchState
*) &tst
->arch
;
326 #if defined(VGP_x86_solaris)
327 VG_(memset
)(fpu
, 0, sizeof(*fpu
));
329 struct vki_fpchip_state
*fs
= &fpu
->fp_reg_set
.fpchip_state
;
330 vg_assert(sizeof(fs
->state
) == 108);
332 LibVEX_GuestX86_get_x87(CONST_CAST(VexGuestX86State
*, &arch
->vex
),
333 (UChar
*) &fs
->state
);
336 UInt mxcsr
= LibVEX_GuestX86_get_mxcsr(CONST_CAST(VexGuestX86State
*,
341 #define COPY_OUT_XMM(dest, src) \
343 dest._l[0] = src[0]; \
344 dest._l[1] = src[1]; \
345 dest._l[2] = src[2]; \
346 dest._l[3] = src[3]; \
348 COPY_OUT_XMM(fs
->xmm
[0], arch
->vex
.guest_XMM0
);
349 COPY_OUT_XMM(fs
->xmm
[1], arch
->vex
.guest_XMM1
);
350 COPY_OUT_XMM(fs
->xmm
[2], arch
->vex
.guest_XMM2
);
351 COPY_OUT_XMM(fs
->xmm
[3], arch
->vex
.guest_XMM3
);
352 COPY_OUT_XMM(fs
->xmm
[4], arch
->vex
.guest_XMM4
);
353 COPY_OUT_XMM(fs
->xmm
[5], arch
->vex
.guest_XMM5
);
354 COPY_OUT_XMM(fs
->xmm
[6], arch
->vex
.guest_XMM6
);
355 COPY_OUT_XMM(fs
->xmm
[7], arch
->vex
.guest_XMM7
);
357 #elif defined(VGP_amd64_solaris)
358 VG_(memset
)(fpu
, 0, sizeof(*fpu
));
359 struct vki_fpchip_state
*fs
= &fpu
->fp_reg_set
.fpchip_state
;
361 /* LibVEX_GuestAMD64_fxsave() requires at least 416 bytes. */
362 vg_assert(sizeof(*fs
) >= 416);
363 LibVEX_GuestAMD64_fxsave(CONST_CAST(VexGuestAMD64State
*, &arch
->vex
),
366 # error Unknown platform
370 /*====================================================================*/
371 /*=== Header fillers ===*/
372 /*====================================================================*/
374 static void fill_ehdr(VKI_ESZ(Ehdr
) *ehdr
, Int num_phdrs
)
376 VG_(memset
)(ehdr
, 0, sizeof(*ehdr
));
378 VG_(memcpy
)(ehdr
->e_ident
, VKI_ELFMAG
, VKI_SELFMAG
);
379 ehdr
->e_ident
[VKI_EI_CLASS
] = VG_ELF_CLASS
;
380 ehdr
->e_ident
[VKI_EI_DATA
] = VG_ELF_DATA2XXX
;
381 ehdr
->e_ident
[VKI_EI_VERSION
] = VKI_EV_CURRENT
;
383 ehdr
->e_type
= VKI_ET_CORE
;
384 ehdr
->e_machine
= VG_ELF_MACHINE
;
385 ehdr
->e_version
= VKI_EV_CURRENT
;
388 ehdr
->e_ehsize
= sizeof(VKI_ESZ(Ehdr
));
390 ehdr
->e_phoff
= sizeof(VKI_ESZ(Ehdr
));
391 ehdr
->e_phentsize
= sizeof(VKI_ESZ(Phdr
));
393 /* If the count of program headers can't fit in the mere 16 bits
394 * shortsightedly allotted to them in the ELF header, we use the
395 * extended formats and put the real values in the section header
398 if (num_phdrs
>= VKI_PN_XNUM
) {
399 ehdr
->e_phnum
= VKI_PN_XNUM
;
401 ehdr
->e_shoff
= ehdr
->e_phoff
+ ehdr
->e_phentsize
* num_phdrs
;
402 ehdr
->e_shentsize
= sizeof(VKI_ESZ(Shdr
));
404 ehdr
->e_phnum
= num_phdrs
;
407 ehdr
->e_shentsize
= 0;
410 ehdr
->e_shstrndx
= 0;
413 static void fill_phdr(VKI_ESZ(Phdr
) *phdr
, const NSegment
*seg
, UInt off
,
416 SizeT len
= seg
->end
- seg
->start
+ 1;
418 really_write
= really_write
&& should_dump(seg
);
420 VG_(memset
)(phdr
, 0, sizeof(*phdr
));
422 phdr
->p_type
= PT_LOAD
;
423 phdr
->p_offset
= off
;
424 phdr
->p_vaddr
= seg
->start
;
426 phdr
->p_filesz
= really_write
? len
: 0;
431 phdr
->p_flags
|= PF_R
;
433 phdr
->p_flags
|= PF_W
;
435 phdr
->p_flags
|= PF_X
;
437 phdr
->p_align
= VKI_PAGE_SIZE
;
440 /* Fills the section header at index zero when num_phdrs >= PN_XNUM. */
441 static void fill_zero_shdr(VKI_ESZ(Shdr
) *shdr
, UInt num_phdrs
)
443 vg_assert(num_phdrs
>= VKI_PN_XNUM
);
445 VG_(memset
)(shdr
, 0, sizeof(*shdr
));
447 shdr
->sh_name
= 0; // STR_NONE
448 shdr
->sh_info
= num_phdrs
;
451 static void fill_prpsinfo(vki_elf_prpsinfo_t
*prpsinfo
,
452 const ThreadState
*tst
,
453 const vki_siginfo_t
*si
)
455 VG_(memset
)(prpsinfo
, 0, sizeof(*prpsinfo
));
457 fill_thread_state(tst
, &prpsinfo
->pr_state
, &prpsinfo
->pr_sname
);
458 prpsinfo
->pr_uid
= get_uid();
459 prpsinfo
->pr_gid
= get_gid();
460 prpsinfo
->pr_pid
= VG_(getpid
)();
461 prpsinfo
->pr_ppid
= VG_(getppid
)();
462 prpsinfo
->pr_pgrp
= VG_(getpgrp
)();
463 prpsinfo
->pr_sid
= VG_(getpgrp
)();
464 fill_scheduling_class(prpsinfo
->pr_clname
, sizeof(prpsinfo
->pr_clname
));
465 VG_(client_fname
)(prpsinfo
->pr_fname
, sizeof(prpsinfo
->pr_fname
), True
);
466 VG_(client_cmd_and_args
)(prpsinfo
->pr_psargs
,
467 sizeof(prpsinfo
->pr_psargs
));
468 fill_argv(&prpsinfo
->pr_argc
, (Addr
*) &prpsinfo
->pr_argv
);
469 prpsinfo
->pr_envp
= (char **) VG_(client_envp
);
470 prpsinfo
->pr_wstat
= get_wstat(si
);
471 prpsinfo
->pr_euid
= VG_(geteuid
)();
472 prpsinfo
->pr_egid
= VG_(getegid
)();
473 prpsinfo
->pr_dmodel
= get_dmodel();
476 static void fill_prstatus(vki_elf_prstatus_t
*prs
,
477 const ThreadState
*tst
,
478 const vki_siginfo_t
*si
)
480 VG_(memset
)(prs
, 0, sizeof(*prs
));
482 prs
->pr_flags
= VKI_ELF_OLD_PR_PCINVAL
;
483 fill_siginfo(si
, &prs
->pr_info
, &prs
->pr_cursig
);
484 prs
->pr_nlwp
= VG_(count_living_threads
)();
485 prs
->pr_sighold
= tst
->sig_mask
;
486 prs
->pr_pid
= VG_(getpid
)();
487 prs
->pr_ppid
= VG_(getppid
)();
488 prs
->pr_pgrp
= VG_(getpgrp
)();
489 prs
->pr_sid
= VG_(getpgrp
)();
490 fill_scheduling_class(prs
->pr_clname
, sizeof(prs
->pr_clname
));
491 prs
->pr_who
= tst
->os_state
.lwpid
;
492 prs
->pr_brkbase
= (vki_caddr_t
) VG_(brk_base
);
493 prs
->pr_brksize
= VG_(brk_limit
) - VG_(brk_base
);
494 prs
->pr_stkbase
= (vki_caddr_t
) compute_stkbase(tst
);
495 prs
->pr_stksize
= tst
->client_stack_szB
;
496 fill_regset(&prs
->pr_reg
, tst
);
499 static void fill_psinfo(vki_psinfo_t
*psinfo
, const ThreadState
*tst
,
500 const vki_siginfo_t
*si
)
502 VG_(memset
)(psinfo
, 0, sizeof(*psinfo
));
504 psinfo
->pr_nlwp
= VG_(count_living_threads
)();
505 psinfo
->pr_uid
= get_uid();
506 psinfo
->pr_gid
= get_gid();
507 psinfo
->pr_pid
= VG_(getpid
)();
508 psinfo
->pr_ppid
= VG_(getppid
)();
509 psinfo
->pr_pgid
= VG_(getpgrp
)();
510 psinfo
->pr_sid
= VG_(getpgrp
)();
511 psinfo
->pr_euid
= VG_(geteuid
)();
512 psinfo
->pr_egid
= VG_(getegid
)();
513 VG_(client_fname
)(psinfo
->pr_fname
, sizeof(psinfo
->pr_fname
), True
);
514 psinfo
->pr_wstat
= get_wstat(si
);
515 VG_(client_cmd_and_args
)(psinfo
->pr_psargs
,
516 sizeof(psinfo
->pr_psargs
));
517 fill_argv(&psinfo
->pr_argc
, (Addr
*) &psinfo
->pr_argv
);
518 psinfo
->pr_envp
= (uintptr_t) VG_(client_envp
);
519 psinfo
->pr_dmodel
= get_dmodel();
520 psinfo
->pr_zoneid
= get_zoneid();
522 psinfo
->pr_lwp
.pr_lwpid
= tst
->os_state
.lwpid
;
523 fill_thread_state(tst
, &psinfo
->pr_lwp
.pr_state
,
524 &psinfo
->pr_lwp
.pr_sname
);
525 fill_scheduling_class(psinfo
->pr_lwp
.pr_clname
,
526 sizeof(psinfo
->pr_lwp
.pr_clname
));
529 static void fill_pstatus(vki_pstatus_t
*pstatus
,
530 const ThreadState
*tst
,
531 const vki_siginfo_t
*si
)
533 VG_(memset
)(pstatus
, 0, sizeof(*pstatus
));
535 pstatus
->pr_flags
= VKI_PR_PCINVAL
;
536 pstatus
->pr_nlwp
= VG_(count_living_threads
)();
537 pstatus
->pr_pid
= VG_(getpid
)();
538 pstatus
->pr_ppid
= VG_(getppid
)();
539 pstatus
->pr_pgid
= VG_(getpgrp
)();
540 pstatus
->pr_sid
= VG_(getpgrp
)();
541 pstatus
->pr_brkbase
= (uintptr_t) VG_(brk_base
);
542 pstatus
->pr_brksize
= VG_(brk_limit
) - VG_(brk_base
);
543 pstatus
->pr_stkbase
= (uintptr_t) compute_stkbase(tst
);
544 pstatus
->pr_stksize
= tst
->client_stack_szB
;
545 pstatus
->pr_dmodel
= get_dmodel();
546 pstatus
->pr_zoneid
= get_zoneid();
548 pstatus
->pr_lwp
.pr_flags
= VKI_PR_PCINVAL
;
549 pstatus
->pr_lwp
.pr_lwpid
= tst
->os_state
.lwpid
;
550 fill_siginfo(si
, &pstatus
->pr_lwp
.pr_info
,
551 &pstatus
->pr_lwp
.pr_cursig
);
552 pstatus
->pr_lwp
.pr_lwphold
= tst
->sig_mask
;
553 fill_scheduling_class(pstatus
->pr_lwp
.pr_clname
,
554 sizeof(pstatus
->pr_lwp
.pr_clname
));
555 fill_regset(&pstatus
->pr_lwp
.pr_reg
, tst
);
556 fill_fpregset(&pstatus
->pr_lwp
.pr_fpreg
, tst
);
559 #if defined(SOLARIS_PRXREGSET_T)
560 static void fill_xregs(vki_prxregset_t
*xregs
, const ThreadState
*tst
)
562 const ThreadArchState
*arch
= (const ThreadArchState
*) &tst
->arch
;
564 #if defined(VGP_x86_solaris)
565 VG_(memset
)(xregs
, 0, sizeof(*xregs
));
566 xregs
->pr_xsize
= sizeof(xregs
->pr_un
.pr_xsave
);
569 UInt mxcsr
= LibVEX_GuestX86_get_mxcsr(CONST_CAST(VexGuestX86State
*,
571 xregs
->pr_un
.pr_xsave
.pr_mxcsr
= mxcsr
;
574 #define COPY_OUT_XMM(dest, src) \
576 dest._l[0] = src[0]; \
577 dest._l[1] = src[1]; \
578 dest._l[2] = src[2]; \
579 dest._l[3] = src[3]; \
581 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[0], arch
->vex
.guest_XMM0
);
582 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[1], arch
->vex
.guest_XMM1
);
583 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[2], arch
->vex
.guest_XMM2
);
584 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[3], arch
->vex
.guest_XMM3
);
585 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[4], arch
->vex
.guest_XMM4
);
586 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[5], arch
->vex
.guest_XMM5
);
587 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[6], arch
->vex
.guest_XMM6
);
588 COPY_OUT_XMM(xregs
->pr_un
.pr_xsave
.pr_xmm
[7], arch
->vex
.guest_XMM7
);
591 #elif defined(VGP_amd64_solaris)
592 VG_(memset
)(xregs
, 0, sizeof(*xregs
));
593 xregs
->pr_xsize
= sizeof(xregs
->pr_un
.pr_xsave
);
595 /* LibVEX_GuestAMD64_fxsave() requires at least 416 bytes. */
596 vg_assert(sizeof(xregs
->pr_un
.pr_xsave
) >= 416);
597 LibVEX_GuestAMD64_fxsave(CONST_CAST(VexGuestAMD64State
*, &arch
->vex
),
598 (Addr
) &xregs
->pr_un
.pr_xsave
);
600 # error "Unknown platform"
603 #endif /* SOLARIS_PRXREGSET_T */
605 static void fill_utsname(struct vki_utsname
*uts
)
607 VG_(memset
)(uts
, 0, sizeof(*uts
));
609 VG_(do_syscall3
)(SYS_systeminfo
, VKI_SI_SYSNAME
,
610 (UWord
) &uts
->sysname
, sizeof(uts
->sysname
));
611 VG_(do_syscall3
)(SYS_systeminfo
, VKI_SI_HOSTNAME
,
612 (UWord
) &uts
->nodename
, sizeof(uts
->nodename
));
613 VG_(do_syscall3
)(SYS_systeminfo
, VKI_SI_RELEASE
,
614 (UWord
) &uts
->release
, sizeof(uts
->release
));
615 VG_(do_syscall3
)(SYS_systeminfo
, VKI_SI_VERSION
,
616 (UWord
) &uts
->version
, sizeof(uts
->version
));
617 VG_(do_syscall3
)(SYS_systeminfo
, VKI_SI_MACHINE
,
618 (UWord
) &uts
->machine
, sizeof(uts
->machine
));
621 static vki_prcred_t
*create_prcred(SizeT
*size
)
623 UInt group_list
[VKI_NGROUPS_MAX
];
624 Int ngroups
= VG_(getgroups
)(VKI_NGROUPS_MAX
, group_list
);
628 *size
= sizeof(vki_prcred_t
) + (ngroups
- 1) * sizeof(gid_t
);
629 vki_prcred_t
*prcred
= VG_(malloc
)("coredump-elf.cp.1", *size
);
630 VG_(memset
)(prcred
, 0, *size
);
632 prcred
->pr_euid
= VG_(geteuid
)();
633 prcred
->pr_ruid
= get_uid();
634 prcred
->pr_suid
= prcred
->pr_euid
;
635 prcred
->pr_egid
= VG_(getegid
)();
636 prcred
->pr_rgid
= get_gid();
637 prcred
->pr_sgid
= prcred
->pr_egid
;
638 prcred
->pr_ngroups
= ngroups
;
641 for (i
= 0; i
< ngroups
; i
++)
642 prcred
->pr_groups
[i
] = group_list
[i
];
647 static void fill_core_content(vki_core_content_t
*content
)
649 *content
= VKI_CC_CONTENT_STACK
| VKI_CC_CONTENT_HEAP
650 | VKI_CC_CONTENT_SHANON
| VKI_CC_CONTENT_TEXT
651 | VKI_CC_CONTENT_DATA
| VKI_CC_CONTENT_RODATA
652 | VKI_CC_CONTENT_ANON
| VKI_CC_CONTENT_SHM
653 | VKI_CC_CONTENT_ISM
| VKI_CC_CONTENT_DISM
;
656 static vki_prpriv_t
*create_prpriv(SizeT
*size
)
658 Int fd
= VG_(fd_open
)("/proc/self/priv", O_RDONLY
, 0);
662 struct vg_stat stats
;
663 if (VG_(fstat
)(fd
, &stats
) != 0) {
668 vki_prpriv_t
*prpriv
= VG_(malloc
)("coredump-elf.cp.1", stats
.size
);
670 if (VG_(read
)(fd
, prpriv
, stats
.size
) != stats
.size
) {
681 static vki_priv_impl_info_t
*create_priv_info(SizeT
*size
)
683 /* Size of the returned priv_impl_info_t is apriori unknown. */
684 vki_priv_impl_info_t first_cut
[100];
685 SysRes sres
= VG_(do_syscall5
)(SYS_privsys
, VKI_PRIVSYS_GETIMPLINFO
,
686 0, 0, (UWord
) first_cut
,
688 if (sr_isError(sres
))
691 SizeT real_size
= first_cut
[0].priv_headersize
692 + first_cut
[0].priv_globalinfosize
;
693 vki_priv_impl_info_t
*priv_info
= VG_(malloc
)("coredump-elf.cpi.1",
696 if (real_size
<= sizeof(first_cut
)) {
697 /* if the first_cut was large enough */
698 VG_(memcpy
)(priv_info
, first_cut
, real_size
);
700 /* otherwise repeat the syscall with buffer large enough */
701 sres
= VG_(do_syscall5
)(SYS_privsys
, VKI_PRIVSYS_GETIMPLINFO
,
702 0, 0, (UWord
) priv_info
, real_size
);
703 if (sr_isError(sres
)) {
704 VG_(free
)(priv_info
);
713 static void fill_lwpsinfo(vki_lwpsinfo_t
*lwp
,
714 const ThreadState
*tst
)
716 VG_(memset
)(lwp
, 0, sizeof(*lwp
));
718 lwp
->pr_lwpid
= tst
->os_state
.lwpid
;
719 fill_thread_state(tst
, &lwp
->pr_state
, &lwp
->pr_sname
);
720 fill_scheduling_class(lwp
->pr_clname
, sizeof(lwp
->pr_clname
));
723 static void fill_lwpstatus(vki_lwpstatus_t
*lwp
,
724 const ThreadState
*tst
,
725 const vki_siginfo_t
*si
)
727 VG_(memset
)(lwp
, 0, sizeof(*lwp
));
729 lwp
->pr_flags
= VKI_PR_PCINVAL
;
730 lwp
->pr_lwpid
= tst
->os_state
.lwpid
;
731 fill_siginfo(si
, &lwp
->pr_info
, &lwp
->pr_cursig
);
732 fill_scheduling_class(lwp
->pr_clname
, sizeof(lwp
->pr_clname
));
733 fill_regset(&lwp
->pr_reg
, tst
);
734 fill_fpregset(&lwp
->pr_fpreg
, tst
);
737 static void fill_old_note_for_thread(note_t
**notes
,
738 const ThreadState
*tst
,
739 const vki_siginfo_t
*si
)
741 vki_elf_prstatus_t prstatus
;
742 fill_prstatus(&prstatus
, tst
, si
);
743 add_note(notes
, VKI_NT_PRSTATUS
, &prstatus
, sizeof(vki_elf_prstatus_t
));
746 fill_fpregset(&fpu
, tst
);
747 add_note(notes
, VKI_NT_PRFPREG
, &fpu
, sizeof(vki_fpregset_t
));
749 #if defined(SOLARIS_PRXREGSET_T)
750 if (should_dump_xregs(tst
)) {
751 vki_prxregset_t xregs
;
752 fill_xregs(&xregs
, tst
);
753 add_note(notes
, VKI_NT_PRXREG
, &xregs
, sizeof(vki_prxregset_t
));
755 #endif /* SOLARIS_PRXREGSET_T */
758 static void fill_new_note_for_thread(note_t
**notes
,
759 const ThreadState
*tst
,
760 const vki_siginfo_t
*si
)
762 vki_lwpsinfo_t lwpsinfo
;
763 fill_lwpsinfo(&lwpsinfo
, tst
);
764 add_note(notes
, VKI_NT_LWPSINFO
, &lwpsinfo
, sizeof(vki_lwpsinfo_t
));
766 vki_lwpstatus_t lwpstatus
;
767 fill_lwpstatus(&lwpstatus
, tst
, si
);
768 add_note(notes
, VKI_NT_LWPSTATUS
, &lwpstatus
, sizeof(vki_lwpstatus_t
));
770 #if defined(SOLARIS_PRXREGSET_T)
771 if (should_dump_xregs(tst
)) {
772 vki_prxregset_t xregs
;
773 fill_xregs(&xregs
, tst
);
774 add_note(notes
, VKI_NT_PRXREG
, &xregs
, sizeof(vki_prxregset_t
));
776 #endif /* SOLARIS_PRXREGSET_T */
779 /*====================================================================*/
780 /*=== Note utility functions ===*/
781 /*====================================================================*/
783 static void add_note(note_t
**list
, UInt type
, const void *data
,
786 UInt note_size
= sizeof(note_t
) + VG_ROUNDUP(datasz
, 4);
788 note_t
*n
= VG_(malloc
)("coredump-elf.an.1", note_size
);
790 VG_(memset
)(n
, 0, note_size
);
791 n
->nhdr
.n_type
= type
;
792 n
->nhdr
.n_namesz
= 5;
793 n
->nhdr
.n_descsz
= VG_ROUNDUP(datasz
, 4);
794 VG_(memcpy
)(n
->name
, "CORE", 4);
795 VG_(memcpy
)(n
->data
, data
, datasz
);
802 note_t
*tail
= *list
;
803 while (tail
->next
!= NULL
)
808 static UInt
note_size(const note_t
*note
)
810 return sizeof(note_t
) - sizeof(note_t
*) + note
->nhdr
.n_descsz
;
813 static UInt
notes_size(const note_t
*list
)
818 for (note
= list
; note
!= NULL
; note
= note
->next
)
819 size
+= note_size(note
);
824 static void fill_notes_phdr(VKI_ESZ(Phdr
) *phdr
, UInt offset
,
827 phdr
->p_type
= PT_NOTE
;
828 phdr
->p_offset
= offset
;
831 phdr
->p_filesz
= size_of_notes
;
833 phdr
->p_flags
= PF_R
;
837 static void write_notes(Int fd
, const HChar
*filename
,
842 for (note
= list
; note
!= NULL
; note
= note
->next
)
843 write_part(fd
, filename
, CONST_CAST(void *, ¬e
->nhdr
),
844 note_size(note
), "notes");
847 static void free_notes(note_t
*list
)
849 while (list
!= NULL
) {
850 note_t
*next
= list
->next
;
856 /*====================================================================*/
857 /*=== Main coredump function ===*/
858 /*====================================================================*/
860 void VG_(make_coredump
)(ThreadId tid
, const vki_siginfo_t
*si
,
863 const HChar
*basename
= "vgcore";
864 const HChar
*coreext
= "";
867 if (VG_(clo_log_fname_unexpanded
) != NULL
) {
869 basename
= VG_(expand_file_name
)("--log-file",
870 VG_(clo_log_fname_unexpanded
));
873 vg_assert(coreext
!= NULL
);
874 vg_assert(basename
!= NULL
);
876 UInt filename_size
= VG_(strlen
)(coreext
) + VG_(strlen
)(basename
)
877 + 100; /* for the two %d's */
878 HChar
*filename
= VG_(malloc
)("coredump-elf.mc.1", filename_size
);
880 /* Try to come with a non-existent coredump filename. */
883 Int oflags
= VKI_O_CREAT
|VKI_O_WRONLY
|VKI_O_EXCL
|VKI_O_TRUNC
;
886 VG_(snprintf
)(filename
, filename_size
, "%s%s.%d",
887 basename
, coreext
, VG_(getpid
)());
889 VG_(snprintf
)(filename
, filename_size
, "%s%s.%d.%u",
890 basename
, coreext
, VG_(getpid
)(), seq
);
893 #ifdef VKI_O_LARGEFILE
894 oflags
|= VKI_O_LARGEFILE
;
897 SysRes sres
= VG_(open
)(filename
, oflags
,
898 VKI_S_IRUSR
|VKI_S_IWUSR
);
899 if (!sr_isError(sres
)) {
900 core_fd
= sr_Res(sres
);
904 if (sr_isError(sres
) && sr_Err(sres
) != VKI_EEXIST
) {
905 VG_(umsg
)("Cannot create coredump file %s (%lu)\n",
906 filename
, sr_Err(sres
));
912 /* Get the client segments. Free seg_starts after use. */
914 Addr
*seg_starts
= VG_(get_segment_starts
)(SkFileC
| SkAnonC
| SkShmC
,
917 /* Count how many memory segments to dump. */
919 UInt num_phdrs
= 2; /* two CORE note sections */
920 for (i
= 0; i
< n_seg_starts
; i
++) {
921 if (!may_dump(VG_(am_find_nsegment
)(seg_starts
[i
])))
928 fill_ehdr(&ehdr
, num_phdrs
);
931 if (ehdr
.e_shnum
> 0)
932 fill_zero_shdr(&shdr
, num_phdrs
);
933 UInt phdrs_size
= num_phdrs
* ehdr
.e_phentsize
;
935 /* Construct the old-style notes. */
936 note_t
*old_notes
= NULL
;
938 vki_elf_prpsinfo_t prpsinfo
;
939 fill_prpsinfo(&prpsinfo
, &VG_(threads
)[tid
], si
);
940 add_note(&old_notes
, VKI_NT_PRPSINFO
, &prpsinfo
,
941 sizeof(vki_elf_prpsinfo_t
));
943 HChar platform
[256 + 1];
944 fill_platform(platform
, sizeof(platform
));
945 add_note(&old_notes
, VKI_NT_PLATFORM
, platform
,
946 VG_(strlen
)(platform
) + 1);
948 add_note(&old_notes
, VKI_NT_AUXV
, VG_(client_auxv
),
949 count_auxv() * sizeof(auxv_t
));
951 /* Add detail about the faulting thread as the first note.
952 This is how gdb determines which thread faulted. Note that
953 mdb does not need such aid. */
954 fill_old_note_for_thread(&old_notes
, &VG_(threads
)[tid
], si
);
956 /* Now add details for all threads except the one that faulted. */
958 for (t_idx
= 1; t_idx
< VG_N_THREADS
; t_idx
++)
959 if ((VG_(threads
)[t_idx
].status
!= VgTs_Empty
) &&
960 (VG_(threads
)[t_idx
].status
!= VgTs_Zombie
)) {
964 fill_old_note_for_thread(&old_notes
, &VG_(threads
)[t_idx
], si
);
967 /* Construct the new-style notes. */
968 note_t
*new_notes
= NULL
;
970 fill_psinfo(&psinfo
, &VG_(threads
)[tid
], si
);
971 add_note(&new_notes
, VKI_NT_PSINFO
, &psinfo
, sizeof(vki_psinfo_t
));
973 vki_pstatus_t pstatus
;
974 fill_pstatus(&pstatus
, &VG_(threads
)[tid
], si
);
975 add_note(&new_notes
, VKI_NT_PSTATUS
, &pstatus
, sizeof(vki_pstatus_t
));
977 add_note(&new_notes
, VKI_NT_PLATFORM
, platform
,
978 VG_(strlen
)(platform
) + 1);
980 add_note(&new_notes
, VKI_NT_AUXV
, VG_(client_auxv
),
981 count_auxv() * sizeof(auxv_t
));
983 struct vki_utsname uts
;
985 add_note(&new_notes
, VKI_NT_UTSNAME
, &uts
,
986 sizeof(struct vki_utsname
));
989 vki_prcred_t
*prcred
= create_prcred(&prcred_size
);
990 if (prcred
!= NULL
) {
991 add_note(&new_notes
, VKI_NT_PRCRED
, prcred
, prcred_size
);
995 vki_core_content_t core_content
;
996 fill_core_content(&core_content
);
997 add_note(&new_notes
, VKI_NT_CONTENT
, &core_content
,
998 sizeof(vki_core_content_t
));
1001 vki_prpriv_t
*prpriv
= create_prpriv(&priv_size
);
1002 if (prpriv
!= NULL
) {
1003 add_note(&new_notes
, VKI_NT_PRPRIV
, prpriv
, priv_size
);
1007 vki_priv_impl_info_t
*priv_info
= create_priv_info(&priv_size
);
1008 if (priv_info
!= NULL
) {
1009 add_note(&new_notes
, VKI_NT_PRPRIVINFO
, priv_info
, priv_size
);
1010 VG_(free
)(priv_info
);
1013 HChar zonename
[VKI_ZONENAME_MAX
+ 1];
1014 fill_zonename(zonename
, sizeof(zonename
));
1015 add_note(&new_notes
, VKI_NT_ZONENAME
, zonename
,
1016 VG_(strlen
)(zonename
) + 1);
1018 /* Add detail about the faulting thread as the first note.
1019 This is how gdb determines which thread faulted. Note that
1020 mdb does not need such aid. */
1021 fill_new_note_for_thread(&new_notes
, &VG_(threads
)[tid
], si
);
1023 /* Now add details for all threads except the one that faulted. */
1024 for (t_idx
= 1; t_idx
< VG_N_THREADS
; t_idx
++) {
1025 if ((VG_(threads
)[t_idx
].status
!= VgTs_Empty
) &&
1026 (VG_(threads
)[t_idx
].status
!= VgTs_Zombie
)) {
1030 fill_new_note_for_thread(&new_notes
, &VG_(threads
)[t_idx
], si
);
1034 VKI_ESZ(Phdr
) *phdrs
= VG_(malloc
)("coredump-elf.mc.2", phdrs_size
);
1036 UInt size_of_notes
= notes_size(old_notes
);
1037 UInt offset
= ehdr
.e_ehsize
+ phdrs_size
+
1038 (ehdr
.e_shnum
* ehdr
.e_shentsize
);
1040 /* fill program header for old notes */
1041 fill_notes_phdr(&phdrs
[0], offset
, size_of_notes
);
1042 offset
+= size_of_notes
;
1044 size_of_notes
= notes_size(new_notes
);
1045 /* fill program header for new notes */
1046 fill_notes_phdr(&phdrs
[1], offset
, size_of_notes
);
1047 offset
+= size_of_notes
;
1049 /* fill program headers for segments */
1051 for (i
= 0, idx
= 2; i
< n_seg_starts
; i
++) {
1052 NSegment
const *seg
= VG_(am_find_nsegment
)(seg_starts
[i
]);
1057 fill_phdr(&phdrs
[idx
], seg
, offset
,
1058 (seg
->end
- seg
->start
+ 1 + offset
) < max_size
);
1060 offset
+= phdrs
[idx
].p_filesz
;
1065 /* write everything out */
1066 write_part(core_fd
, filename
, &ehdr
, sizeof(ehdr
),
1068 write_part(core_fd
, filename
, phdrs
, phdrs_size
,
1070 if (ehdr
.e_shnum
> 0)
1071 write_part(core_fd
, filename
, &shdr
, sizeof(shdr
),
1073 write_notes(core_fd
, filename
, old_notes
);
1074 write_notes(core_fd
, filename
, new_notes
);
1076 VG_(lseek
)(core_fd
, phdrs
[2].p_offset
, VKI_SEEK_SET
);
1078 for (i
= 0, idx
= 2; i
< n_seg_starts
; i
++) {
1079 NSegment
const *seg
= VG_(am_find_nsegment
)(seg_starts
[i
]);
1081 if (!should_dump(seg
))
1084 if (phdrs
[idx
].p_filesz
> 0) {
1085 Off64T off
= VG_(lseek
)(core_fd
, phdrs
[idx
].p_offset
,
1087 vg_assert(off
== phdrs
[idx
].p_offset
);
1088 vg_assert(seg
->end
- seg
->start
+ 1 >= phdrs
[idx
].p_filesz
);
1090 write_part(core_fd
, filename
, (void *) seg
->start
,
1091 phdrs
[idx
].p_filesz
, "program segment");
1096 VG_(close
)(core_fd
);
1097 VG_(free
)(filename
);
1099 free_notes(old_notes
);
1100 free_notes(new_notes
);
1101 VG_(free
)(seg_starts
);
1106 /*--------------------------------------------------------------------*/
1108 /*--------------------------------------------------------------------*/