• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*--------------------------------------------------------------------*/
3 /*--- Dumping core.                                 coredump-elf.c ---*/
4 /*--------------------------------------------------------------------*/
5 
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9 
10    Copyright (C) 2000-2017 Julian Seward
11       jseward@acm.org
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_linux)
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_libcbase.h"
38 #include "pub_core_machine.h"
39 #include "pub_core_coredump.h"
40 #include "pub_core_libcprint.h"
41 #include "pub_core_libcfile.h"    // VG_(close) et al
42 #include "pub_core_libcproc.h"    // VG_(geteuid), VG_(getegid)
43 #include "pub_core_libcassert.h"  // VG_(exit), vg_assert
44 #include "pub_core_mallocfree.h"  // VG_(malloc), VG_(free)
45 #include "pub_core_threadstate.h"
46 #include "pub_core_xarray.h"
47 #include "pub_core_clientstate.h"
48 #include "pub_core_options.h"
49 
50 /*
51   Dump core
52 
53   Generate a standard ELF core file corresponding to the client state
54   at the time of a crash.
55  */
56 #include <elf.h>
57 #ifndef NT_PRXFPREG
58 #define NT_PRXFPREG    0x46e62b7f /* copied from gdb5.1/include/elf/common.h */
59 #endif /* NT_PRXFPREG */
60 
61 #if	VG_WORDSIZE == 8
62 #define ESZ(x)	Elf64_##x
63 #elif	VG_WORDSIZE == 4
64 #define ESZ(x)	Elf32_##x
65 #else
66 #error VG_WORDSIZE needs to ==4 or ==8
67 #endif
68 
69 /* If true, then this Segment may be mentioned in the core */
may_dump(const NSegment * seg)70 static Bool may_dump(const NSegment *seg)
71 {
72    if (seg->kind == SkAnonC ||
73        seg->kind == SkShmC ||
74        (seg->kind == SkFileC &&
75         !VKI_S_ISCHR(seg->mode) && !VKI_S_ISBLK(seg->mode)))
76       return True;
77 
78    return False;
79 }
80 
81 /* If true, then this Segment's contents will be in the core */
should_dump(const NSegment * seg)82 static Bool should_dump(const NSegment *seg)
83 {
84    return may_dump(seg); // && seg->hasW;
85 }
86 
fill_ehdr(ESZ (Ehdr)* ehdr,Int num_phdrs)87 static void fill_ehdr(ESZ(Ehdr) *ehdr, Int num_phdrs)
88 {
89    VG_(memset)(ehdr, 0, sizeof(*ehdr));
90 
91    VG_(memcpy)(ehdr->e_ident, ELFMAG, SELFMAG);
92    ehdr->e_ident[EI_CLASS]   = VG_ELF_CLASS;
93    ehdr->e_ident[EI_DATA]    = VG_ELF_DATA2XXX;
94    ehdr->e_ident[EI_VERSION] = EV_CURRENT;
95 
96    ehdr->e_type = ET_CORE;
97    ehdr->e_machine = VG_ELF_MACHINE;
98    ehdr->e_version = EV_CURRENT;
99    ehdr->e_entry = 0;
100    ehdr->e_phoff = sizeof(ESZ(Ehdr));
101    ehdr->e_shoff = 0;
102    ehdr->e_flags = 0;
103    ehdr->e_ehsize = sizeof(ESZ(Ehdr));
104    ehdr->e_phentsize = sizeof(ESZ(Phdr));
105    ehdr->e_phnum = num_phdrs;
106    ehdr->e_shentsize = 0;
107    ehdr->e_shnum = 0;
108    ehdr->e_shstrndx = 0;
109 
110 }
111 
fill_phdr(ESZ (Phdr)* phdr,const NSegment * seg,UInt off,Bool write)112 static void fill_phdr(ESZ(Phdr) *phdr, const NSegment *seg, UInt off, Bool write)
113 {
114    SizeT len = seg->end - seg->start + 1;
115 
116    write = write && should_dump(seg);
117 
118    VG_(memset)(phdr, 0, sizeof(*phdr));
119 
120    phdr->p_type = PT_LOAD;
121    phdr->p_offset = off;
122    phdr->p_vaddr = seg->start;
123    phdr->p_paddr = 0;
124    phdr->p_filesz = write ? len : 0;
125    phdr->p_memsz = len;
126    phdr->p_flags = 0;
127 
128    if (seg->hasR)
129       phdr->p_flags |= PF_R;
130    if (seg->hasW)
131       phdr->p_flags |= PF_W;
132    if (seg->hasX)
133       phdr->p_flags |= PF_X;
134 
135    phdr->p_align = VKI_PAGE_SIZE;
136 }
137 
138 #if 0 /* We've had Elf32_Nhdr since at least froyo! */
139 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
140     || defined(VGPV_mips32_linux_android)
141 /* Android's libc doesn't provide a definition for this.  Hence: */
142 typedef
143    struct {
144       Elf32_Word n_namesz;
145       Elf32_Word n_descsz;
146       Elf32_Word n_type;
147    }
148    Elf32_Nhdr;
149 #endif
150 #endif
151 
152 struct note {
153    struct note *next;
154    ESZ(Nhdr) note;
155    HChar name[0];
156 };
157 
note_size(const struct note * n)158 static UInt note_size(const struct note *n)
159 {
160    return sizeof(ESZ(Nhdr)) + VG_ROUNDUP(VG_(strlen)(n->name)+1, 4)
161                             + VG_ROUNDUP(n->note.n_descsz, 4);
162 }
163 
164 #if !defined(VGPV_arm_linux_android) \
165     && !defined(VGPV_x86_linux_android) \
166     && !defined(VGPV_mips32_linux_android) \
167     && !defined(VGPV_arm64_linux_android)
add_note(struct note ** list,const HChar * name,UInt type,const void * data,UInt datasz)168 static void add_note(struct note **list, const HChar *name, UInt type,
169                      const void *data, UInt datasz)
170 {
171    Int namelen = VG_(strlen)(name)+1;
172    Int notelen = sizeof(struct note) +
173       VG_ROUNDUP(namelen, 4) +
174       VG_ROUNDUP(datasz, 4);
175    struct note *n = VG_(malloc)("coredump-elf.an.1", notelen);
176 
177    VG_(memset)(n, 0, notelen);
178 
179    n->next = *list;
180    *list = n;
181 
182    n->note.n_type = type;
183    n->note.n_namesz = namelen;
184    n->note.n_descsz = datasz;
185 
186    VG_(memcpy)(n->name, name, namelen);
187    VG_(memcpy)(n->name+VG_ROUNDUP(namelen,4), data, datasz);
188 }
189 #endif /* !defined(VGPV_*_linux_android) */
190 
write_note(Int fd,const struct note * n)191 static void write_note(Int fd, const struct note *n)
192 {
193    VG_(write)(fd, &n->note, note_size(n));
194 }
195 
fill_prpsinfo(const ThreadState * tst,struct vki_elf_prpsinfo * prpsinfo)196 static void fill_prpsinfo(const ThreadState *tst,
197                           struct vki_elf_prpsinfo *prpsinfo)
198 {
199    VG_(memset)(prpsinfo, 0, sizeof(*prpsinfo));
200 
201    switch(tst->status) {
202    case VgTs_Runnable:
203    case VgTs_Yielding:
204       prpsinfo->pr_sname = 'R';
205       break;
206 
207    case VgTs_WaitSys:
208       prpsinfo->pr_sname = 'S';
209       break;
210 
211    case VgTs_Zombie:
212       prpsinfo->pr_sname = 'Z';
213       break;
214 
215    case VgTs_Empty:
216    case VgTs_Init:
217       prpsinfo->pr_sname = '?';
218       break;
219    }
220 
221    prpsinfo->pr_uid = 0;
222    prpsinfo->pr_gid = 0;
223 
224    VG_(client_fname)(prpsinfo->pr_fname, sizeof(prpsinfo->pr_fname), False);
225 }
226 
fill_prstatus(const ThreadState * tst,struct vki_elf_prstatus * prs,const vki_siginfo_t * si)227 static void fill_prstatus(const ThreadState *tst,
228 			  /*OUT*/struct vki_elf_prstatus *prs,
229 			  const vki_siginfo_t *si)
230 {
231 #if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
232    vki_elf_greg_t *regs;
233 #else
234    struct vki_user_regs_struct *regs;
235 #endif
236    const ThreadArchState* arch = &tst->arch;
237 
238    VG_(memset)(prs, 0, sizeof(*prs));
239 
240    prs->pr_info.si_signo = si->si_signo;
241    prs->pr_info.si_code = si->si_code;
242    prs->pr_info.si_errno = 0;
243 
244    prs->pr_cursig = si->si_signo;
245 
246    prs->pr_pid = tst->os_state.lwpid;
247    prs->pr_ppid = 0;
248    prs->pr_pgrp = VG_(getpgrp)();
249    prs->pr_sid = VG_(getpgrp)();
250 
251 #if defined(VGP_s390x_linux)
252    /* prs->pr_reg has struct type. Need to take address. */
253    regs = (struct vki_user_regs_struct *)&(prs->pr_reg);
254 #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
255    regs = (vki_elf_greg_t *)prs->pr_reg;
256 #else
257    regs = (struct vki_user_regs_struct *)prs->pr_reg;
258    vg_assert(sizeof(*regs) == sizeof(prs->pr_reg));
259 #endif
260 
261 #if defined(VGP_x86_linux)
262    regs->eflags = LibVEX_GuestX86_get_eflags( &arch->vex );
263    regs->esp    = arch->vex.guest_ESP;
264    regs->eip    = arch->vex.guest_EIP;
265 
266    regs->ebx    = arch->vex.guest_EBX;
267    regs->ecx    = arch->vex.guest_ECX;
268    regs->edx    = arch->vex.guest_EDX;
269    regs->esi    = arch->vex.guest_ESI;
270    regs->edi    = arch->vex.guest_EDI;
271    regs->ebp    = arch->vex.guest_EBP;
272    regs->eax    = arch->vex.guest_EAX;
273 
274    regs->cs     = arch->vex.guest_CS;
275    regs->ds     = arch->vex.guest_DS;
276    regs->ss     = arch->vex.guest_SS;
277    regs->es     = arch->vex.guest_ES;
278    regs->fs     = arch->vex.guest_FS;
279    regs->gs     = arch->vex.guest_GS;
280 
281 #elif defined(VGP_amd64_linux)
282    regs->eflags = LibVEX_GuestAMD64_get_rflags( &arch->vex );
283    regs->rsp    = arch->vex.guest_RSP;
284    regs->rip    = arch->vex.guest_RIP;
285 
286    regs->rbx    = arch->vex.guest_RBX;
287    regs->rcx    = arch->vex.guest_RCX;
288    regs->rdx    = arch->vex.guest_RDX;
289    regs->rsi    = arch->vex.guest_RSI;
290    regs->rdi    = arch->vex.guest_RDI;
291    regs->rbp    = arch->vex.guest_RBP;
292    regs->rax    = arch->vex.guest_RAX;
293    regs->r8     = arch->vex.guest_R8;
294    regs->r9     = arch->vex.guest_R9;
295    regs->r10    = arch->vex.guest_R10;
296    regs->r11    = arch->vex.guest_R11;
297    regs->r12    = arch->vex.guest_R12;
298    regs->r13    = arch->vex.guest_R13;
299    regs->r14    = arch->vex.guest_R14;
300    regs->r15    = arch->vex.guest_R15;
301 
302 #elif defined(VGP_ppc32_linux)
303 #  define DO(n)  regs->gpr[n] = arch->vex.guest_GPR##n
304    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
305    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
306    DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
307    DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
308 #  undef DO
309 
310    regs->nip = arch->vex.guest_CIA;
311    regs->msr = 0xf032;   /* pretty arbitrary */
312    regs->orig_gpr3 = arch->vex.guest_GPR3;
313    regs->ctr = arch->vex.guest_CTR;
314    regs->link = arch->vex.guest_LR;
315    regs->xer = LibVEX_GuestPPC32_get_XER( &arch->vex );
316    regs->ccr = LibVEX_GuestPPC32_get_CR( &arch->vex );
317    regs->mq = 0;
318    regs->trap = 0;
319    regs->dar = 0; /* should be fault address? */
320    regs->dsisr = 0;
321    regs->result = 0;
322 
323 #elif defined(VGP_ppc64be_linux)
324 #  define DO(n)  regs->gpr[n] = arch->vex.guest_GPR##n
325    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
326    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
327    DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
328    DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
329 #  undef DO
330 
331    regs->nip = arch->vex.guest_CIA;
332    regs->msr = 0xf032;   /* pretty arbitrary */
333    regs->orig_gpr3 = arch->vex.guest_GPR3;
334    regs->ctr = arch->vex.guest_CTR;
335    regs->link = arch->vex.guest_LR;
336    regs->xer = LibVEX_GuestPPC64_get_XER( &arch->vex );
337    regs->ccr = LibVEX_GuestPPC64_get_CR( &arch->vex );
338    /* regs->mq = 0; */
339    regs->trap = 0;
340    regs->dar = 0; /* should be fault address? */
341    regs->dsisr = 0;
342    regs->result = 0;
343 
344 #elif defined(VGP_ppc64le_linux)
345 #  define DO(n)  regs->gpr[n] = arch->vex.guest_GPR##n
346    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
347    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
348    DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
349    DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
350 #  undef DO
351 
352    regs->nip = arch->vex.guest_CIA;
353    regs->msr = 0xf033;   /* pretty arbitrary */
354    regs->orig_gpr3 = arch->vex.guest_GPR3;
355    regs->ctr = arch->vex.guest_CTR;
356    regs->link = arch->vex.guest_LR;
357    regs->xer = LibVEX_GuestPPC64_get_XER( &(arch->vex) );
358    regs->ccr = LibVEX_GuestPPC64_get_CR( &(arch->vex) );
359    /* regs->mq = 0; */
360    regs->trap = 0;
361    regs->dar = 0; /* should be fault address? */
362    regs->dsisr = 0;
363    regs->result = 0;
364 
365 #elif defined(VGP_arm_linux)
366    regs->ARM_r0   = arch->vex.guest_R0;
367    regs->ARM_r1   = arch->vex.guest_R1;
368    regs->ARM_r2   = arch->vex.guest_R2;
369    regs->ARM_r3   = arch->vex.guest_R3;
370    regs->ARM_r4   = arch->vex.guest_R4;
371    regs->ARM_r5   = arch->vex.guest_R5;
372    regs->ARM_r6   = arch->vex.guest_R6;
373    regs->ARM_r7   = arch->vex.guest_R7;
374    regs->ARM_r8   = arch->vex.guest_R8;
375    regs->ARM_r9   = arch->vex.guest_R9;
376    regs->ARM_r10  = arch->vex.guest_R10;
377    regs->ARM_fp   = arch->vex.guest_R11;
378    regs->ARM_ip   = arch->vex.guest_R12;
379    regs->ARM_sp   = arch->vex.guest_R13;
380    regs->ARM_lr   = arch->vex.guest_R14;
381    regs->ARM_pc   = arch->vex.guest_R15T;
382    regs->ARM_cpsr = LibVEX_GuestARM_get_cpsr( &arch->vex );
383 
384 #elif defined(VGP_arm64_linux)
385    (void)arch;
386    I_die_here;
387 
388 #elif defined(VGP_s390x_linux)
389 #  define DO(n)  regs->gprs[n] = arch->vex.guest_r##n
390    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
391    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
392 #  undef DO
393 #  define DO(n)  regs->acrs[n] = arch->vex.guest_a##n
394    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
395    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
396 #  undef DO
397    regs->orig_gpr2 = arch->vex.guest_r2;
398 
399 #elif defined(VGP_mips32_linux)
400 #  define DO(n)  regs[VKI_MIPS32_EF_R##n] = arch->vex.guest_r##n
401    DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);  DO(8);
402    DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); DO(16);
403    DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); DO(24);
404    DO(25); DO(28); DO(29); DO(30); DO(31);
405 #  undef DO
406    regs[VKI_MIPS32_EF_LO]         = arch->vex.guest_LO;
407    regs[VKI_MIPS32_EF_HI]         = arch->vex.guest_HI;
408    regs[VKI_MIPS32_EF_CP0_STATUS] = arch->vex.guest_CP0_status;
409    regs[VKI_MIPS32_EF_CP0_EPC]    = arch->vex.guest_PC;
410 #elif defined(VGP_mips64_linux)
411 #  define DO(n)  regs[VKI_MIPS64_EF_R##n] = arch->vex.guest_r##n
412    DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);  DO(8);
413    DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); DO(16);
414    DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); DO(24);
415    DO(25); DO(28); DO(29); DO(30); DO(31);
416 #  undef DO
417    regs[VKI_MIPS64_EF_LO]         = arch->vex.guest_LO;
418    regs[VKI_MIPS64_EF_HI]         = arch->vex.guest_HI;
419    regs[VKI_MIPS64_EF_CP0_STATUS] = arch->vex.guest_CP0_status;
420    regs[VKI_MIPS64_EF_CP0_EPC]    = arch->vex.guest_PC;
421 #else
422 #  error Unknown ELF platform
423 #endif
424 }
425 
fill_fpu(const ThreadState * tst,vki_elf_fpregset_t * fpu)426 static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu)
427 {
428    __attribute__((unused))
429    const ThreadArchState* arch = &tst->arch;
430 
431 #if defined(VGP_x86_linux)
432 //:: static void fill_fpu(vki_elf_fpregset_t *fpu, const HChar *from)
433 //:: {
434 //::    if (VG_(have_ssestate)) {
435 //::       UShort *to;
436 //::       Int i;
437 //::
438 //::       /* This is what the kernel does */
439 //::       VG_(memcpy)(fpu, from, 7*sizeof(long));
440 //::
441 //::       to = (UShort *)&fpu->st_space[0];
442 //::       from += 18 * sizeof(UShort);
443 //::
444 //::       for (i = 0; i < 8; i++, to += 5, from += 8)
445 //:: 	 VG_(memcpy)(to, from, 5*sizeof(UShort));
446 //::    } else
447 //::       VG_(memcpy)(fpu, from, sizeof(*fpu));
448 //:: }
449 
450 //::    fill_fpu(fpu, (const HChar *)&arch->m_sse);
451 
452 #elif defined(VGP_amd64_linux)
453 //::    fpu->cwd = ?;
454 //::    fpu->swd = ?;
455 //::    fpu->twd = ?;
456 //::    fpu->fop = ?;
457 //::    fpu->rip = ?;
458 //::    fpu->rdp = ?;
459 //::    fpu->mxcsr = ?;
460 //::    fpu->mxcsr_mask = ?;
461 //::    fpu->st_space = ?;
462 
463 #  define DO(n)  VG_(memcpy)(fpu->xmm_space + n * 4, \
464                              &arch->vex.guest_YMM##n[0], 16)
465    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
466    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
467 #  undef DO
468 
469    VG_(memset)(fpu->padding, 0, sizeof(fpu->padding));
470 
471 #elif defined(VGP_ppc32_linux)
472    /* The guest state has the FPR fields declared as ULongs, so need
473       to fish out the values without converting them.
474       NOTE: The 32 FP registers map to the first 32 VSX registers.*/
475 #  define DO(n)  (*fpu)[n] = *(double*)(&arch->vex.guest_VSR##n)
476    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
477    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
478    DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
479    DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
480 #  undef DO
481 
482 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
483    /* The guest state has the FPR fields declared as ULongs, so need
484       to fish out the values without converting them.
485       NOTE: The 32 FP registers map to the first 32 VSX registers.*/
486 #  define DO(n)  (*fpu)[n] = *(double*)(&arch->vex.guest_VSR##n)
487    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
488    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
489    DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
490    DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
491 #  undef DO
492 
493 #elif defined(VGP_arm_linux)
494    // umm ...
495 
496 #elif defined(VGP_arm64_linux)
497    I_die_here;
498 
499 #elif defined(VGP_s390x_linux)
500 #  define DO(n)  fpu->fprs[n].ui = arch->vex.guest_f##n
501    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
502    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
503 # undef DO
504 #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
505 #  define DO(n)  (*fpu)[n] = *(const double*)(&arch->vex.guest_f##n)
506    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
507    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
508    DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
509    DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
510 #  undef DO
511 #else
512 #  error Unknown ELF platform
513 #endif
514 }
515 
516 #if defined(VGP_x86_linux) && !defined(VGPV_x86_linux_android)
fill_xfpu(const ThreadState * tst,vki_elf_fpxregset_t * xfpu)517 static void fill_xfpu(const ThreadState *tst, vki_elf_fpxregset_t *xfpu)
518 {
519    const ThreadArchState* arch = &tst->arch;
520 
521 //::    xfpu->cwd = ?;
522 //::    xfpu->swd = ?;
523 //::    xfpu->twd = ?;
524 //::    xfpu->fop = ?;
525 //::    xfpu->fip = ?;
526 //::    xfpu->fcs = ?;
527 //::    xfpu->foo = ?;
528 //::    xfpu->fos = ?;
529 //::    xfpu->mxcsr = ?;
530    xfpu->reserved = 0;
531 //::    xfpu->st_space = ?;
532 
533 #  define DO(n)  VG_(memcpy)(xfpu->xmm_space + n * 4, &arch->vex.guest_XMM##n, sizeof(arch->vex.guest_XMM##n))
534    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
535 #  undef DO
536 
537    VG_(memset)(xfpu->padding, 0, sizeof(xfpu->padding));
538 }
539 #endif
540 
541 static
dump_one_thread(struct note ** notelist,const vki_siginfo_t * si,ThreadId tid)542 void dump_one_thread(struct note **notelist, const vki_siginfo_t *si, ThreadId tid)
543 {
544    vki_elf_fpregset_t  fpu;
545    struct vki_elf_prstatus prstatus;
546 #     if defined(VGP_x86_linux) && !defined(VGPV_x86_linux_android)
547       {
548          vki_elf_fpxregset_t xfpu;
549          fill_xfpu(&VG_(threads)[tid], &xfpu);
550          add_note(notelist, "LINUX", NT_PRXFPREG, &xfpu, sizeof(xfpu));
551       }
552 #     endif
553 
554       fill_fpu(&VG_(threads)[tid], &fpu);
555 #     if !defined(VGPV_arm_linux_android) \
556          && !defined(VGPV_x86_linux_android) \
557          && !defined(VGPV_mips32_linux_android) \
558          && !defined(VGPV_arm64_linux_android)
559       add_note(notelist, "CORE", NT_FPREGSET, &fpu, sizeof(fpu));
560 #     endif
561 
562       fill_prstatus(&VG_(threads)[tid], &prstatus, si);
563 #     if !defined(VGPV_arm_linux_android) \
564          && !defined(VGPV_x86_linux_android) \
565          && !defined(VGPV_mips32_linux_android) \
566          && !defined(VGPV_arm64_linux_android)
567       add_note(notelist, "CORE", NT_PRSTATUS, &prstatus, sizeof(prstatus));
568 #     endif
569 }
570 
571 static
make_elf_coredump(ThreadId tid,const vki_siginfo_t * si,ULong max_size)572 void make_elf_coredump(ThreadId tid, const vki_siginfo_t *si, ULong max_size)
573 {
574    HChar* buf = NULL;
575    const HChar *basename = "vgcore";
576    const HChar *coreext = "";
577    Int seq = 0;
578    Int core_fd;
579    NSegment const * seg;
580    ESZ(Ehdr) ehdr;
581    ESZ(Phdr) *phdrs;
582    Int num_phdrs;
583    Int i, idx;
584    UInt off;
585    struct note *notelist, *note;
586    UInt notesz;
587    struct vki_elf_prpsinfo prpsinfo;
588    Addr *seg_starts;
589    Int n_seg_starts;
590 
591    if (VG_(clo_log_fname_unexpanded) != NULL) {
592       coreext = ".core";
593       basename = VG_(expand_file_name)("--log-file",
594                                        VG_(clo_log_fname_unexpanded));
595    }
596 
597    vg_assert(coreext);
598    vg_assert(basename);
599    buf = VG_(malloc)( "coredump-elf.mec.1",
600                       VG_(strlen)(coreext) + VG_(strlen)(basename)
601                          + 100/*for the two %ds. */ );
602 
603    for(;;) {
604       Int oflags = VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC;
605       SysRes sres;
606 
607       if (seq == 0)
608 	 VG_(sprintf)(buf, "%s%s.%d",
609 		      basename, coreext, VG_(getpid)());
610       else
611 	 VG_(sprintf)(buf, "%s%s.%d.%d",
612 		      basename, coreext, VG_(getpid)(), seq);
613       seq++;
614 
615 #     if defined(VKI_O_LARGEFILE)
616       oflags |= VKI_O_LARGEFILE;
617 #     endif
618 
619       sres = VG_(open)(buf, oflags, VKI_S_IRUSR|VKI_S_IWUSR);
620       if (!sr_isError(sres)) {
621          core_fd = sr_Res(sres);
622 	 break;
623       }
624 
625       if (sr_isError(sres) && sr_Err(sres) != VKI_EEXIST)
626 	 return;		/* can't create file */
627    }
628 
629    /* Get the client segments */
630    seg_starts = VG_(get_segment_starts)(SkFileC | SkAnonC | SkShmC,
631                                         &n_seg_starts);
632 
633    /* First, count how many memory segments to dump */
634    num_phdrs = 1;		/* start with notes */
635    for(i = 0; i < n_seg_starts; i++) {
636       if (!may_dump(VG_(am_find_nsegment)(seg_starts[i])))
637 	 continue;
638 
639       num_phdrs++;
640    }
641 
642    fill_ehdr(&ehdr, num_phdrs);
643 
644    notelist = NULL;
645 
646    /* Second, work out their layout */
647    phdrs = VG_(malloc)("coredump-elf.mec.1", sizeof(*phdrs) * num_phdrs);
648 
649    /* Add details for all threads except the one that faulted */
650    for(i = 1; i < VG_N_THREADS; i++) {
651 
652       if (VG_(threads)[i].status == VgTs_Empty)
653 	 continue;
654 
655       if (i == tid)
656 	 continue;
657 
658       dump_one_thread(&notelist, si, i);
659    }
660 
661    /* Add details for the faulting thread. Note that because we are
662       adding to the head of a linked list this thread will actually
663       come out first in the core file, which seems to be how
664       debuggers determine that it is the faulting thread. */
665    dump_one_thread(&notelist, si, tid);
666 
667    fill_prpsinfo(&VG_(threads)[tid], &prpsinfo);
668 #  if !defined(VGPV_arm_linux_android) \
669       && !defined(VGPV_x86_linux_android) \
670       && !defined(VGPV_mips32_linux_android) \
671       && !defined(VGPV_arm64_linux_android)
672    add_note(&notelist, "CORE", NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo));
673 #  endif
674 
675    for (note = notelist, notesz = 0; note != NULL; note = note->next)
676       notesz += note_size(note);
677 
678    off = sizeof(ehdr) + sizeof(*phdrs) * num_phdrs;
679 
680    phdrs[0].p_type = PT_NOTE;
681    phdrs[0].p_offset = off;
682    phdrs[0].p_vaddr = 0;
683    phdrs[0].p_paddr = 0;
684    phdrs[0].p_filesz = notesz;
685    phdrs[0].p_memsz = 0;
686    phdrs[0].p_flags = 0;
687    phdrs[0].p_align = 0;
688 
689    off += notesz;
690 
691    off = VG_PGROUNDUP(off);
692 
693    for(i = 0, idx = 1; i < n_seg_starts; i++) {
694       seg = VG_(am_find_nsegment)(seg_starts[i]);
695 
696       if (!may_dump(seg))
697 	 continue;
698 
699       fill_phdr(&phdrs[idx], seg, off,
700                 (seg->end - seg->start + 1 + off) < max_size);
701 
702       off += phdrs[idx].p_filesz;
703 
704       idx++;
705    }
706 
707    /* write everything out */
708    VG_(write)(core_fd, &ehdr, sizeof(ehdr));
709    VG_(write)(core_fd, phdrs, sizeof(*phdrs) * num_phdrs);
710 
711    for(note = notelist; note != NULL; note = note->next)
712       write_note(core_fd, note);
713 
714    VG_(lseek)(core_fd, phdrs[1].p_offset, VKI_SEEK_SET);
715 
716    for(i = 0, idx = 1; i < n_seg_starts; i++) {
717       seg = VG_(am_find_nsegment)(seg_starts[i]);
718 
719       if (!should_dump(seg))
720 	 continue;
721 
722       if (phdrs[idx].p_filesz > 0) {
723 	 vg_assert(VG_(lseek)(core_fd, phdrs[idx].p_offset, VKI_SEEK_SET)
724                    == phdrs[idx].p_offset);
725 	 vg_assert(seg->end - seg->start + 1 >= phdrs[idx].p_filesz);
726 
727 	 (void)VG_(write)(core_fd, (void *)seg->start, phdrs[idx].p_filesz);
728       }
729       idx++;
730    }
731 
732    VG_(free)(seg_starts);
733 
734    VG_(close)(core_fd);
735 }
736 
VG_(make_coredump)737 void VG_(make_coredump)(ThreadId tid, const vki_siginfo_t *si, ULong max_size)
738 {
739    make_elf_coredump(tid, si, max_size);
740 }
741 
742 #endif // defined(VGO_linux)
743 
744 /*--------------------------------------------------------------------*/
745 /*--- end                                                          ---*/
746 /*--------------------------------------------------------------------*/
747