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(¬elist, 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(¬elist, 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(¬elist, "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