1 
2 /*--------------------------------------------------------------------*/
3 /*--- Dumping core on Solaris.                  coredump-solaris.c ---*/
4 /*--------------------------------------------------------------------*/
5 
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9 
10    Copyright (C) 2013-2015 Ivo Raisr
11       ivosh@ivosh.net
12 
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.
17 
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.
22 
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
26    02111-1307, USA.
27 
28    The GNU General Public License is contained in the file COPYING.
29 */
30 
31 #if defined(VGO_solaris)
32 
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"
51 
52 typedef struct __attribute__ ((__packed__)) note {
53    struct note *next;
54    VKI_ESZ(Nhdr) nhdr;
55    HChar name[8];
56    HChar data[0];
57 } note_t;
58 
59 static void add_note(note_t **list, UInt type, const void *data,
60                      UInt datasz);
61 
62 /* If true, then this Segment may be mentioned in the core */
may_dump(const NSegment * seg)63 static Bool may_dump(const NSegment *seg)
64 {
65    if ((seg->kind == SkAnonC) ||
66        (seg->kind == SkShmC) ||
67        ((seg->kind == SkFileC) &&
68         !VKI_S_ISCHR(seg->mode) && !VKI_S_ISBLK(seg->mode)))
69       return True;
70 
71    return False;
72 }
73 
74 /* If true, then this Segment's contents will be in the core */
should_dump(const NSegment * seg)75 static Bool should_dump(const NSegment *seg)
76 {
77    return may_dump(seg);
78 }
79 
80 #if defined(SOLARIS_PRXREGSET_T)
should_dump_xregs(const ThreadState * tst)81 static Bool should_dump_xregs(const ThreadState *tst)
82 {
83 #if defined(VGP_x86_solaris)
84    return False;
85 #elif defined(VGP_amd64_solaris)
86    const ThreadArchState *arch = (const ThreadArchState *) &tst->arch;
87 
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))
107       return True;
108 
109    return False;
110 
111    #undef YMM_NON_ZERO
112 #else
113 #  error Unknown ELF platform
114 #endif
115 }
116 #endif /* SOLARIS_PRXREGSET_T */
117 
write_part(Int fd,const HChar * filename,void * buf,SizeT buf_size,const HChar * part)118 static void write_part(Int fd, const HChar *filename,
119                        void *buf, SizeT buf_size, const HChar *part)
120 {
121    Int ret = VG_(write)(fd, buf, buf_size);
122    if (ret < 0) {
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);
128    }
129 }
130 
131 /*====================================================================*/
132 /*=== Miscellaneous getters                                        ===*/
133 /*====================================================================*/
134 
get_uid(void)135 static Int get_uid(void)
136 {
137    return sr_Res(VG_(do_syscall0)(SYS_getuid));
138 }
139 
get_gid(void)140 static Int get_gid(void)
141 {
142    return sr_Res(VG_(do_syscall0)(SYS_getgid));
143 }
144 
get_dmodel(void)145 static Int get_dmodel(void)
146 {
147 #if defined(VGP_x86_solaris)
148    return PR_MODEL_ILP32;
149 #elif defined(VGP_amd64_solaris)
150    return PR_MODEL_LP64;
151 #else
152 #  error "Unknown platform"
153 #endif
154 }
155 
get_zoneid(void)156 static vki_zoneid_t get_zoneid(void)
157 {
158    SysRes sres = VG_(do_syscall2)(SYS_zone, VKI_ZONE_LOOKUP,
159                                   (UWord) NULL);
160    if (sr_isError(sres))
161        return 0;
162 
163    return sr_Res(sres);
164 }
165 
count_auxv(void)166 static UInt count_auxv(void)
167 {
168    UInt count = 1;
169 
170    vki_auxv_t *auxv = (vki_auxv_t *) VG_(client_auxv);
171    while (auxv->a_type != VKI_AT_NULL) {
172       count += 1;
173       auxv++;
174    }
175 
176    return count;
177 }
178 
compute_stkbase(const ThreadState * tst)179 static Addr compute_stkbase(const ThreadState *tst)
180 {
181    return tst->client_stack_highest_byte + 1
182           - tst->client_stack_szB;
183 }
184 
get_wstat(const vki_siginfo_t * si)185 static Int get_wstat(const vki_siginfo_t *si)
186 {
187    return (si->si_signo & 0xff) | WCOREFLG;
188 }
189 
190 /*====================================================================*/
191 /*=== Utility fillers                                              ===*/
192 /*====================================================================*/
193 
fill_platform(HChar * buf,UInt buf_size)194 static void fill_platform(HChar *buf, UInt buf_size)
195 {
196    vg_assert(buf != NULL);
197    vg_assert(buf_size >= 1);
198 
199    buf[0] = '\0';
200 
201    VG_(do_syscall3)(SYS_systeminfo, VKI_SI_PLATFORM,
202                     (UWord) buf, buf_size);
203 }
204 
fill_zonename(HChar * buf,UInt buf_size)205 static void fill_zonename(HChar *buf, UInt buf_size)
206 {
207    vg_assert(buf != NULL);
208    vg_assert(buf_size >= 1);
209 
210    buf[0] = '\0';
211 
212    VG_(do_syscall5)(SYS_zone, VKI_ZONE_GETATTR, get_zoneid(),
213                     VKI_ZONE_ATTR_NAME, (UWord) buf, buf_size);
214 }
215 
fill_thread_state(const ThreadState * tst,HChar * state,HChar * sname)216 static void fill_thread_state(const ThreadState *tst,
217                               HChar *state, HChar *sname)
218 {
219    switch (tst->status) {
220    case VgTs_Runnable:
221    case VgTs_Yielding:
222       *state = VKI_SRUN;
223       *sname = 'R';
224       break;
225 
226    case VgTs_WaitSys:
227       *state = VKI_SSLEEP;
228       *sname = 'S';
229       break;
230 
231    case VgTs_Zombie:
232       *state = VKI_SZOMB;
233       *sname = 'Z';
234       break;
235 
236    case VgTs_Empty:
237    case VgTs_Init:
238       *state = 0;
239       *sname = '?';
240       break;
241    }
242 }
243 
fill_siginfo(const vki_siginfo_t * si,vki_siginfo_t * di,Short * signo)244 static void fill_siginfo(const vki_siginfo_t *si, vki_siginfo_t *di,
245                          Short *signo)
246 {
247    di->si_signo = si->si_signo;
248    di->si_code  = si->si_code;
249    di->si_errno = 0;
250    di->si_addr = si->si_addr;
251    *signo = si->si_signo;
252 }
253 
fill_argv(Int * argc,Addr * argv)254 static void fill_argv(Int *argc, Addr *argv)
255 {
256    Addr *ptr = (Addr *) VG_(get_initial_client_SP)();
257    *argc = *ptr++;
258    *argv = (Addr) ptr;
259 }
260 
fill_scheduling_class(HChar * buf,SizeT buf_size)261 static void fill_scheduling_class(HChar *buf, SizeT buf_size)
262 {
263    vg_assert(buf != NULL);
264    vg_assert(buf_size >= 1);
265 
266    /* Valgrind currently schedules one thread at time which
267       resembles the default timeshare class. */
268    VG_(strncpy)(buf, "TS", buf_size);
269 }
270 
fill_regset(vki_prgregset_t * regs,const ThreadState * tst)271 static void fill_regset(vki_prgregset_t *regs, const ThreadState *tst)
272 {
273    const ThreadArchState *arch = (const ThreadArchState *) &tst->arch;
274 
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);
319 #else
320 #  error "Unknown platform"
321 #endif
322 }
323 
fill_fpregset(vki_fpregset_t * fpu,const ThreadState * tst)324 static void fill_fpregset(vki_fpregset_t *fpu, const ThreadState *tst)
325 {
326    const ThreadArchState *arch = (const ThreadArchState *) &tst->arch;
327 
328 #if defined(VGP_x86_solaris)
329    VG_(memset)(fpu, 0, sizeof(*fpu));
330 
331    struct vki_fpchip_state *fs = &fpu->fp_reg_set.fpchip_state;
332    vg_assert(sizeof(fs->state) == 108);
333 
334    LibVEX_GuestX86_get_x87(CONST_CAST(VexGuestX86State *, &arch->vex),
335                            (UChar *) &fs->state);
336 
337    /* SSE */
338    UInt mxcsr = LibVEX_GuestX86_get_mxcsr(CONST_CAST(VexGuestX86State *,
339                                                      &arch->vex));
340    fs->mxcsr = mxcsr;
341 
342    /* XMM registers */
343    #define COPY_OUT_XMM(dest, src) \
344       do {                      \
345          dest._l[0] = src[0];   \
346          dest._l[1] = src[1];   \
347          dest._l[2] = src[2];   \
348          dest._l[3] = src[3];   \
349       } while (0);
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);
358    #undef COPY_OUT_XMM
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;
362 
363    /* LibVEX_GuestAMD64_fxsave() requires at least 416 bytes. */
364    vg_assert(sizeof(*fs) >= 416);
365    LibVEX_GuestAMD64_fxsave(CONST_CAST(VexGuestAMD64State *, &arch->vex),
366                             (Addr) fs);
367 #else
368 #  error Unknown platform
369 #endif
370 }
371 
372 /*====================================================================*/
373 /*=== Header fillers                                               ===*/
374 /*====================================================================*/
375 
fill_ehdr(VKI_ESZ (Ehdr)* ehdr,Int num_phdrs)376 static void fill_ehdr(VKI_ESZ(Ehdr) *ehdr, Int num_phdrs)
377 {
378    VG_(memset)(ehdr, 0, sizeof(*ehdr));
379 
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;
384 
385    ehdr->e_type = VKI_ET_CORE;
386    ehdr->e_machine = VG_ELF_MACHINE;
387    ehdr->e_version = VKI_EV_CURRENT;
388    ehdr->e_entry = 0;
389    ehdr->e_flags = 0;
390    ehdr->e_ehsize = sizeof(VKI_ESZ(Ehdr));
391 
392    ehdr->e_phoff = sizeof(VKI_ESZ(Ehdr));
393    ehdr->e_phentsize = sizeof(VKI_ESZ(Phdr));
394 
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
398     * at index 0.
399     */
400    if (num_phdrs >= VKI_PN_XNUM) {
401       ehdr->e_phnum = VKI_PN_XNUM;
402       ehdr->e_shnum = 1;
403       ehdr->e_shoff = ehdr->e_phoff + ehdr->e_phentsize * num_phdrs;
404       ehdr->e_shentsize = sizeof(VKI_ESZ(Shdr));
405    } else {
406       ehdr->e_phnum = num_phdrs;
407       ehdr->e_shnum = 0;
408       ehdr->e_shoff = 0;
409       ehdr->e_shentsize = 0;
410    }
411 
412    ehdr->e_shstrndx = 0;
413 }
414 
fill_phdr(VKI_ESZ (Phdr)* phdr,const NSegment * seg,UInt off,Bool really_write)415 static void fill_phdr(VKI_ESZ(Phdr) *phdr, const NSegment *seg, UInt off,
416                       Bool really_write)
417 {
418    SizeT len = seg->end - seg->start + 1;
419 
420    really_write = really_write && should_dump(seg);
421 
422    VG_(memset)(phdr, 0, sizeof(*phdr));
423 
424    phdr->p_type = PT_LOAD;
425    phdr->p_offset = off;
426    phdr->p_vaddr = seg->start;
427    phdr->p_paddr = 0;
428    phdr->p_filesz = really_write ? len : 0;
429    phdr->p_memsz = len;
430    phdr->p_flags = 0;
431 
432    if (seg->hasR)
433       phdr->p_flags |= PF_R;
434    if (seg->hasW)
435       phdr->p_flags |= PF_W;
436    if (seg->hasX)
437       phdr->p_flags |= PF_X;
438 
439    phdr->p_align = VKI_PAGE_SIZE;
440 }
441 
442 /* Fills the section header at index zero when num_phdrs >= PN_XNUM. */
fill_zero_shdr(VKI_ESZ (Shdr)* shdr,UInt num_phdrs)443 static void fill_zero_shdr(VKI_ESZ(Shdr) *shdr, UInt num_phdrs)
444 {
445    vg_assert(num_phdrs >= VKI_PN_XNUM);
446 
447    VG_(memset)(shdr, 0, sizeof(*shdr));
448 
449    shdr->sh_name = 0; // STR_NONE
450    shdr->sh_info = num_phdrs;
451 }
452 
fill_prpsinfo(vki_elf_prpsinfo_t * prpsinfo,const ThreadState * tst,const vki_siginfo_t * si)453 static void fill_prpsinfo(vki_elf_prpsinfo_t *prpsinfo,
454                           const ThreadState *tst,
455                           const vki_siginfo_t *si)
456 {
457    VG_(memset)(prpsinfo, 0, sizeof(*prpsinfo));
458 
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();
476 }
477 
fill_prstatus(vki_elf_prstatus_t * prs,const ThreadState * tst,const vki_siginfo_t * si)478 static void fill_prstatus(vki_elf_prstatus_t *prs,
479                           const ThreadState *tst,
480 			  const vki_siginfo_t *si)
481 {
482    VG_(memset)(prs, 0, sizeof(*prs));
483 
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);
499 }
500 
fill_psinfo(vki_psinfo_t * psinfo,const ThreadState * tst,const vki_siginfo_t * si)501 static void fill_psinfo(vki_psinfo_t *psinfo, const ThreadState *tst,
502                         const vki_siginfo_t *si)
503 {
504    VG_(memset)(psinfo, 0, sizeof(*psinfo));
505 
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();
523 
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));
529 }
530 
fill_pstatus(vki_pstatus_t * pstatus,const ThreadState * tst,const vki_siginfo_t * si)531 static void fill_pstatus(vki_pstatus_t *pstatus,
532                          const ThreadState *tst,
533                          const vki_siginfo_t *si)
534 {
535    VG_(memset)(pstatus, 0, sizeof(*pstatus));
536 
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();
549 
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);
559 }
560 
561 #if defined(SOLARIS_PRXREGSET_T)
fill_xregs(vki_prxregset_t * xregs,const ThreadState * tst)562 static void fill_xregs(vki_prxregset_t *xregs, const ThreadState *tst)
563 {
564    const ThreadArchState *arch = (const ThreadArchState *) &tst->arch;
565 
566 #if defined(VGP_x86_solaris)
567    VG_(memset)(xregs, 0, sizeof(*xregs));
568    xregs->pr_xsize = sizeof(xregs->pr_un.pr_xsave);
569 
570    /* SSE */
571    UInt mxcsr = LibVEX_GuestX86_get_mxcsr(CONST_CAST(VexGuestX86State *,
572                                                      &arch->vex));
573    xregs->pr_un.pr_xsave.pr_mxcsr = mxcsr;
574 
575    /* XMM registers */
576    #define COPY_OUT_XMM(dest, src) \
577       do {                      \
578          dest._l[0] = src[0];   \
579          dest._l[1] = src[1];   \
580          dest._l[2] = src[2];   \
581          dest._l[3] = src[3];   \
582       } while (0);
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);
591    #undef COPY_OUT_XMM
592 
593 #elif defined(VGP_amd64_solaris)
594    VG_(memset)(xregs, 0, sizeof(*xregs));
595    xregs->pr_xsize = sizeof(xregs->pr_un.pr_xsave);
596 
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);
601 #else
602 #  error "Unknown platform"
603 #endif
604 }
605 #endif /* SOLARIS_PRXREGSET_T */
606 
fill_utsname(struct vki_utsname * uts)607 static void fill_utsname(struct vki_utsname *uts)
608 {
609    VG_(memset)(uts, 0, sizeof(*uts));
610 
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));
621 }
622 
create_prcred(SizeT * size)623 static vki_prcred_t *create_prcred(SizeT *size)
624 {
625    UInt group_list[VKI_NGROUPS_MAX];
626    Int ngroups = VG_(getgroups)(VKI_NGROUPS_MAX, group_list);
627    if (ngroups == -1)
628       ngroups = 0;
629 
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);
633 
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;
641 
642    UInt i;
643    for (i = 0; i < ngroups; i++)
644       prcred->pr_groups[i] = group_list[i];
645 
646    return prcred;
647 }
648 
fill_core_content(vki_core_content_t * content)649 static void fill_core_content(vki_core_content_t *content)
650 {
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;
656 }
657 
create_prpriv(SizeT * size)658 static vki_prpriv_t *create_prpriv(SizeT *size)
659 {
660    Int fd = VG_(fd_open)("/proc/self/priv", O_RDONLY, 0);
661    if (fd < 0)
662       return NULL;
663 
664    struct vg_stat stats;
665    if (VG_(fstat)(fd, &stats) != 0) {
666       VG_(close)(fd);
667       return NULL;
668    }
669 
670    vki_prpriv_t *prpriv = VG_(malloc)("coredump-elf.cp.1", stats.size);
671 
672    if (VG_(read)(fd, prpriv, stats.size) != stats.size) {
673       VG_(free)(prpriv);
674       VG_(close)(fd);
675       return NULL;
676    }
677 
678    VG_(close)(fd);
679    *size = stats.size;
680    return prpriv;
681 }
682 
create_priv_info(SizeT * size)683 static vki_priv_impl_info_t *create_priv_info(SizeT *size)
684 {
685    /* Size of the returned priv_impl_info_t is apriori unkown. */
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,
689                                   sizeof(first_cut));
690    if (sr_isError(sres))
691        return NULL;
692 
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",
696                                                  real_size);
697 
698    if (real_size <= sizeof(first_cut)) {
699       /* if the first_cut was large enough */
700       VG_(memcpy)(priv_info, first_cut, real_size);
701    } else {
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);
707           return NULL;
708       }
709    }
710 
711    *size = real_size;
712    return priv_info;
713 }
714 
fill_lwpsinfo(vki_lwpsinfo_t * lwp,const ThreadState * tst)715 static void fill_lwpsinfo(vki_lwpsinfo_t *lwp,
716                           const ThreadState *tst)
717 {
718    VG_(memset)(lwp, 0, sizeof(*lwp));
719 
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));
723 }
724 
fill_lwpstatus(vki_lwpstatus_t * lwp,const ThreadState * tst,const vki_siginfo_t * si)725 static void fill_lwpstatus(vki_lwpstatus_t *lwp,
726                            const ThreadState *tst,
727 			   const vki_siginfo_t *si)
728 {
729    VG_(memset)(lwp, 0, sizeof(*lwp));
730 
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);
737 }
738 
fill_old_note_for_thread(note_t ** notes,const ThreadState * tst,const vki_siginfo_t * si)739 static void fill_old_note_for_thread(note_t **notes,
740                                      const ThreadState *tst,
741                                      const vki_siginfo_t *si)
742 {
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));
746 
747    vki_fpregset_t fpu;
748    fill_fpregset(&fpu, tst);
749    add_note(notes, VKI_NT_PRFPREG, &fpu, sizeof(vki_fpregset_t));
750 
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));
756    }
757 #endif /* SOLARIS_PRXREGSET_T */
758 }
759 
fill_new_note_for_thread(note_t ** notes,const ThreadState * tst,const vki_siginfo_t * si)760 static void fill_new_note_for_thread(note_t **notes,
761                                      const ThreadState *tst,
762                                      const vki_siginfo_t *si)
763 {
764    vki_lwpsinfo_t lwpsinfo;
765    fill_lwpsinfo(&lwpsinfo, tst);
766    add_note(notes, VKI_NT_LWPSINFO, &lwpsinfo, sizeof(vki_lwpsinfo_t));
767 
768    vki_lwpstatus_t lwpstatus;
769    fill_lwpstatus(&lwpstatus, tst, si);
770    add_note(notes, VKI_NT_LWPSTATUS, &lwpstatus, sizeof(vki_lwpstatus_t));
771 
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));
777    }
778 #endif /* SOLARIS_PRXREGSET_T */
779 }
780 
781 /*====================================================================*/
782 /*=== Note utility functions                                       ===*/
783 /*====================================================================*/
784 
add_note(note_t ** list,UInt type,const void * data,UInt datasz)785 static void add_note(note_t **list, UInt type, const void *data,
786                      UInt datasz)
787 {
788    UInt note_size = sizeof(note_t) + VG_ROUNDUP(datasz, 4);
789 
790    note_t *n = VG_(malloc)("coredump-elf.an.1", note_size);
791 
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);
798 
799    if (*list == NULL) {
800       *list = n;
801       return;
802    }
803 
804    note_t *tail = *list;
805    while (tail->next != NULL)
806       tail = tail->next;
807    tail->next = n;
808 }
809 
note_size(const note_t * note)810 static UInt note_size(const note_t *note)
811 {
812    return sizeof(note_t) - sizeof(note_t *) + note->nhdr.n_descsz;
813 }
814 
notes_size(const note_t * list)815 static UInt notes_size(const note_t *list)
816 {
817    UInt size = 0;
818    const note_t *note;
819 
820    for (note = list; note != NULL; note = note->next)
821       size += note_size(note);
822 
823    return size;
824 }
825 
fill_notes_phdr(VKI_ESZ (Phdr)* phdr,UInt offset,UInt size_of_notes)826 static void fill_notes_phdr(VKI_ESZ(Phdr) *phdr, UInt offset,
827                             UInt size_of_notes)
828 {
829    phdr->p_type = PT_NOTE;
830    phdr->p_offset = offset;
831    phdr->p_vaddr = 0;
832    phdr->p_paddr = 0;
833    phdr->p_filesz = size_of_notes;
834    phdr->p_memsz = 0;
835    phdr->p_flags = PF_R;
836    phdr->p_align = 0;
837 }
838 
write_notes(Int fd,const HChar * filename,const note_t * list)839 static void write_notes(Int fd, const HChar *filename,
840                         const note_t *list)
841 {
842    const note_t *note;
843 
844    for (note = list; note != NULL; note = note->next)
845       write_part(fd, filename, CONST_CAST(void *, &note->nhdr),
846                  note_size(note), "notes");
847 }
848 
free_notes(note_t * list)849 static void free_notes(note_t *list)
850 {
851    while (list != NULL) {
852       note_t *next = list->next;
853       VG_(free)(list);
854       list = next;
855    }
856 }
857 
858 /*====================================================================*/
859 /*=== Main coredump function                                       ===*/
860 /*====================================================================*/
861 
VG_(make_coredump)862 void VG_(make_coredump)(ThreadId tid, const vki_siginfo_t *si,
863                         ULong max_size)
864 {
865    const HChar *basename = "vgcore";
866    const HChar *coreext = "";
867    Int core_fd;
868 
869    if (VG_(clo_log_fname_expanded) != NULL) {
870       coreext = ".core";
871       basename = VG_(expand_file_name)("--log-file",
872                                        VG_(clo_log_fname_expanded));
873    }
874 
875    vg_assert(coreext != NULL);
876    vg_assert(basename != NULL);
877 
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);
881 
882    /* Try to come with a non-existent coredump filename. */
883    UInt seq = 0;
884    for (;;) {
885       Int oflags = VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC;
886 
887       if (seq == 0)
888 	 VG_(snprintf)(filename, filename_size, "%s%s.%d",
889 		      basename, coreext, VG_(getpid)());
890       else
891 	 VG_(snprintf)(filename, filename_size, "%s%s.%d.%d",
892 		      basename, coreext, VG_(getpid)(), seq);
893       seq++;
894 
895 #ifdef VKI_O_LARGEFILE
896       oflags |= VKI_O_LARGEFILE;
897 #endif
898 
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);
903 	 break;
904       }
905 
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));
909          VG_(free)(filename);
910 	 return;
911       }
912    }
913 
914    /* Get the client segments. Free seg_starts after use. */
915    Int n_seg_starts;
916    Addr *seg_starts = VG_(get_segment_starts)(SkFileC | SkAnonC | SkShmC,
917                                               &n_seg_starts);
918 
919    /* Count how many memory segments to dump. */
920    Int i;
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]))))
924 	 continue;
925 
926       num_phdrs++;
927    }
928 
929    VKI_ESZ(Ehdr) ehdr;
930    fill_ehdr(&ehdr, num_phdrs);
931 
932    VKI_ESZ(Shdr) shdr;
933    if (ehdr.e_shnum > 0)
934       fill_zero_shdr(&shdr, num_phdrs);
935    UInt phdrs_size = num_phdrs * ehdr.e_phentsize;
936 
937    /* Construct the old-style notes. */
938    note_t *old_notes = NULL;
939 
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));
944 
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);
949 
950    add_note(&old_notes, VKI_NT_AUXV, VG_(client_auxv),
951             count_auxv() * sizeof(auxv_t));
952 
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);
957 
958    /* Now add details for all threads except the one that faulted. */
959    ThreadId t_idx;
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)) {
963          if (t_idx == tid)
964             continue;
965 
966          fill_old_note_for_thread(&old_notes, &VG_(threads)[t_idx], si);
967    }
968 
969    /* Construct the new-style notes. */
970    note_t *new_notes = NULL;
971    vki_psinfo_t psinfo;
972    fill_psinfo(&psinfo, &VG_(threads)[tid], si);
973    add_note(&new_notes, VKI_NT_PSINFO, &psinfo, sizeof(vki_psinfo_t));
974 
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));
978 
979    add_note(&new_notes, VKI_NT_PLATFORM, platform,
980             VG_(strlen)(platform) + 1);
981 
982    add_note(&new_notes, VKI_NT_AUXV, VG_(client_auxv),
983             count_auxv() * sizeof(auxv_t));
984 
985    struct vki_utsname uts;
986    fill_utsname(&uts);
987    add_note(&new_notes, VKI_NT_UTSNAME, &uts,
988             sizeof(struct vki_utsname));
989 
990    SizeT prcred_size;
991    vki_prcred_t *prcred = create_prcred(&prcred_size);
992    if (prcred != NULL) {
993       add_note(&new_notes, VKI_NT_PRCRED, prcred, prcred_size);
994       VG_(free)(prcred);
995    }
996 
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));
1001 
1002    SizeT priv_size;
1003    vki_prpriv_t *prpriv = create_prpriv(&priv_size);
1004    if (prpriv != NULL) {
1005       add_note(&new_notes, VKI_NT_PRPRIV, prpriv, priv_size);
1006       VG_(free)(prpriv);
1007    }
1008 
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);
1013    }
1014 
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);
1019 
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);
1024 
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)) {
1029          if (t_idx == tid)
1030             continue;
1031 
1032          fill_new_note_for_thread(&new_notes, &VG_(threads)[t_idx], si);
1033       }
1034    }
1035 
1036    VKI_ESZ(Phdr) *phdrs = VG_(malloc)("coredump-elf.mc.2", phdrs_size);
1037 
1038    UInt size_of_notes = notes_size(old_notes);
1039    UInt offset = ehdr.e_ehsize + phdrs_size +
1040                  (ehdr.e_shnum * ehdr.e_shentsize);
1041 
1042    /* fill program header for old notes */
1043    fill_notes_phdr(&phdrs[0], offset, size_of_notes);
1044    offset += size_of_notes;
1045 
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;
1050 
1051    /* fill program headers for segments */
1052    UInt idx;
1053    for (i = 0, idx = 2; i < n_seg_starts; i++) {
1054       NSegment const *seg = VG_(am_find_nsegment(seg_starts[i]));
1055 
1056       if (!may_dump(seg))
1057 	 continue;
1058 
1059       fill_phdr(&phdrs[idx], seg, offset,
1060                 (seg->end - seg->start + 1 + offset) < max_size);
1061 
1062       offset += phdrs[idx].p_filesz;
1063 
1064       idx++;
1065    }
1066 
1067    /* write everything out */
1068    write_part(core_fd, filename, &ehdr, sizeof(ehdr),
1069              "elf headers");
1070    write_part(core_fd, filename, phdrs, phdrs_size,
1071               "program headers");
1072    if (ehdr.e_shnum > 0)
1073       write_part(core_fd, filename, &shdr, sizeof(shdr),
1074                  "section headers");
1075    write_notes(core_fd, filename, old_notes);
1076    write_notes(core_fd, filename, new_notes);
1077 
1078    VG_(lseek)(core_fd, phdrs[2].p_offset, VKI_SEEK_SET);
1079 
1080    for (i = 0, idx = 2; i < n_seg_starts; i++) {
1081       NSegment const *seg = VG_(am_find_nsegment(seg_starts[i]));
1082 
1083       if (!should_dump(seg))
1084 	 continue;
1085 
1086       if (phdrs[idx].p_filesz > 0) {
1087          Off64T off = VG_(lseek)(core_fd, phdrs[idx].p_offset,
1088                                  VKI_SEEK_SET);
1089          vg_assert(off == phdrs[idx].p_offset);
1090          vg_assert(seg->end - seg->start + 1 >= phdrs[idx].p_filesz);
1091 
1092          write_part(core_fd, filename, (void *) seg->start,
1093                     phdrs[idx].p_filesz, "program segment");
1094       }
1095       idx++;
1096    }
1097 
1098    VG_(close)(core_fd);
1099    VG_(free)(filename);
1100    VG_(free)(phdrs);
1101    free_notes(old_notes);
1102    free_notes(new_notes);
1103    VG_(free)(seg_starts);
1104 }
1105 
1106 #endif
1107 
1108 /*--------------------------------------------------------------------*/
1109 /*--- end                                                          ---*/
1110 /*--------------------------------------------------------------------*/
1111