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