elfcore.c revision 325837
1/*-
2 * Copyright (c) 2017 Dell EMC
3 * Copyright (c) 2007 Sandvine Incorporated
4 * Copyright (c) 1998 John D. Polstra
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: stable/11/usr.bin/gcore/elfcore.c 325837 2017-11-15 02:03:38Z jhb $");
31
32#include <sys/endian.h>
33#include <sys/param.h>
34#include <sys/procfs.h>
35#include <sys/ptrace.h>
36#include <sys/queue.h>
37#include <sys/linker_set.h>
38#include <sys/sbuf.h>
39#include <sys/sysctl.h>
40#include <sys/user.h>
41#include <sys/wait.h>
42#include <machine/elf.h>
43#include <vm/vm_param.h>
44#include <vm/vm.h>
45#include <vm/pmap.h>
46#include <vm/vm_map.h>
47#include <assert.h>
48#include <err.h>
49#include <errno.h>
50#include <fcntl.h>
51#include <stdbool.h>
52#include <stdint.h>
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <unistd.h>
57#include <libutil.h>
58
59#include "extern.h"
60
61/*
62 * Code for generating ELF core dumps.
63 */
64
65typedef void (*segment_callback)(vm_map_entry_t, void *);
66
67/* Closure for cb_put_phdr(). */
68struct phdr_closure {
69	Elf_Phdr *phdr;		/* Program header to fill in */
70	Elf_Off offset;		/* Offset of segment in core file */
71};
72
73/* Closure for cb_size_segment(). */
74struct sseg_closure {
75	int count;		/* Count of writable segments. */
76	size_t size;		/* Total size of all writable segments. */
77};
78
79#ifdef ELFCORE_COMPAT_32
80typedef struct fpreg32 elfcore_fpregset_t;
81typedef struct reg32   elfcore_gregset_t;
82typedef struct prpsinfo32 elfcore_prpsinfo_t;
83typedef struct prstatus32 elfcore_prstatus_t;
84typedef struct ptrace_lwpinfo32 elfcore_lwpinfo_t;
85static void elf_convert_gregset(elfcore_gregset_t *rd, struct reg *rs);
86static void elf_convert_fpregset(elfcore_fpregset_t *rd, struct fpreg *rs);
87static void elf_convert_lwpinfo(struct ptrace_lwpinfo32 *pld,
88    struct ptrace_lwpinfo *pls);
89#else
90typedef fpregset_t elfcore_fpregset_t;
91typedef gregset_t  elfcore_gregset_t;
92typedef prpsinfo_t elfcore_prpsinfo_t;
93typedef prstatus_t elfcore_prstatus_t;
94typedef struct ptrace_lwpinfo elfcore_lwpinfo_t;
95#define elf_convert_gregset(d,s)	*d = *s
96#define elf_convert_fpregset(d,s)	*d = *s
97#define	elf_convert_lwpinfo(d,s)	*d = *s
98#endif
99
100typedef void* (*notefunc_t)(void *, size_t *);
101
102static void cb_put_phdr(vm_map_entry_t, void *);
103static void cb_size_segment(vm_map_entry_t, void *);
104static void each_writable_segment(vm_map_entry_t, segment_callback,
105    void *closure);
106static void elf_detach(void);	/* atexit() handler. */
107static void *elf_note_fpregset(void *, size_t *);
108static void *elf_note_prpsinfo(void *, size_t *);
109static void *elf_note_prstatus(void *, size_t *);
110static void *elf_note_thrmisc(void *, size_t *);
111static void *elf_note_ptlwpinfo(void *, size_t *);
112#if defined(__arm__)
113static void *elf_note_arm_vfp(void *, size_t *);
114#endif
115#if defined(__i386__) || defined(__amd64__)
116static void *elf_note_x86_xstate(void *, size_t *);
117#endif
118#if defined(__powerpc__)
119static void *elf_note_powerpc_vmx(void *, size_t *);
120#endif
121static void *elf_note_procstat_auxv(void *, size_t *);
122static void *elf_note_procstat_files(void *, size_t *);
123static void *elf_note_procstat_groups(void *, size_t *);
124static void *elf_note_procstat_osrel(void *, size_t *);
125static void *elf_note_procstat_proc(void *, size_t *);
126static void *elf_note_procstat_psstrings(void *, size_t *);
127static void *elf_note_procstat_rlimit(void *, size_t *);
128static void *elf_note_procstat_umask(void *, size_t *);
129static void *elf_note_procstat_vmmap(void *, size_t *);
130static void elf_puthdr(int, pid_t, vm_map_entry_t, void *, size_t, size_t,
131    size_t, int);
132static void elf_putnote(int, notefunc_t, void *, struct sbuf *);
133static void elf_putnotes(pid_t, struct sbuf *, size_t *);
134static void freemap(vm_map_entry_t);
135static vm_map_entry_t readmap(pid_t);
136static void *procstat_sysctl(void *, int, size_t, size_t *sizep);
137
138static pid_t g_pid;		/* Pid being dumped, global for elf_detach */
139static int g_status;		/* proc status after ptrace attach */
140
141static int
142elf_ident(int efd, pid_t pid __unused, char *binfile __unused)
143{
144	Elf_Ehdr hdr;
145	int cnt;
146	uint16_t machine;
147
148	cnt = read(efd, &hdr, sizeof(hdr));
149	if (cnt != sizeof(hdr))
150		return (0);
151	if (!IS_ELF(hdr))
152		return (0);
153	switch (hdr.e_ident[EI_DATA]) {
154	case ELFDATA2LSB:
155		machine = le16toh(hdr.e_machine);
156		break;
157	case ELFDATA2MSB:
158		machine = be16toh(hdr.e_machine);
159		break;
160	default:
161		return (0);
162	}
163	if (!ELF_MACHINE_OK(machine))
164		return (0);
165
166	/* Looks good. */
167	return (1);
168}
169
170static void
171elf_detach(void)
172{
173	int sig;
174
175	if (g_pid != 0) {
176		/*
177		 * Forward any pending signals. SIGSTOP is generated by ptrace
178		 * itself, so ignore it.
179		 */
180		sig = WIFSTOPPED(g_status) ? WSTOPSIG(g_status) : 0;
181		if (sig == SIGSTOP)
182			sig = 0;
183		ptrace(PT_DETACH, g_pid, (caddr_t)1, sig);
184	}
185}
186
187/*
188 * Write an ELF coredump for the given pid to the given fd.
189 */
190static void
191elf_coredump(int efd, int fd, pid_t pid)
192{
193	vm_map_entry_t map;
194	struct sseg_closure seginfo;
195	struct sbuf *sb;
196	void *hdr;
197	size_t hdrsize, notesz, segoff;
198	ssize_t n, old_len;
199	Elf_Phdr *php;
200	int i;
201
202	/* Attach to process to dump. */
203	g_pid = pid;
204	if (atexit(elf_detach) != 0)
205		err(1, "atexit");
206	errno = 0;
207	ptrace(PT_ATTACH, pid, NULL, 0);
208	if (errno)
209		err(1, "PT_ATTACH");
210	if (waitpid(pid, &g_status, 0) == -1)
211		err(1, "waitpid");
212
213	/* Get the program's memory map. */
214	map = readmap(pid);
215
216	/* Size the program segments. */
217	seginfo.count = 0;
218	seginfo.size = 0;
219	each_writable_segment(map, cb_size_segment, &seginfo);
220
221	/*
222	 * Build the header and the notes using sbuf and write to the file.
223	 */
224	sb = sbuf_new_auto();
225	hdrsize = sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * (1 + seginfo.count);
226	/* Start header + notes section. */
227	sbuf_start_section(sb, NULL);
228	/* Make empty header subsection. */
229	sbuf_start_section(sb, &old_len);
230	sbuf_putc(sb, 0);
231	sbuf_end_section(sb, old_len, hdrsize, 0);
232	/* Put notes. */
233	elf_putnotes(pid, sb, &notesz);
234	/* Align up to a page boundary for the program segments. */
235	sbuf_end_section(sb, -1, PAGE_SIZE, 0);
236	if (sbuf_finish(sb) != 0)
237		err(1, "sbuf_finish");
238	hdr = sbuf_data(sb);
239	segoff = sbuf_len(sb);
240	/* Fill in the header. */
241	elf_puthdr(efd, pid, map, hdr, hdrsize, notesz, segoff, seginfo.count);
242
243	n = write(fd, hdr, segoff);
244	if (n == -1)
245		err(1, "write");
246	if (n < segoff)
247              errx(1, "short write");
248
249	/* Write the contents of all of the writable segments. */
250	php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1;
251	for (i = 0;  i < seginfo.count;  i++) {
252		struct ptrace_io_desc iorequest;
253		uintmax_t nleft = php->p_filesz;
254
255		iorequest.piod_op = PIOD_READ_D;
256		iorequest.piod_offs = (caddr_t)(uintptr_t)php->p_vaddr;
257		while (nleft > 0) {
258			char buf[8*1024];
259			size_t nwant;
260			ssize_t ngot;
261
262			if (nleft > sizeof(buf))
263				nwant = sizeof buf;
264			else
265				nwant = nleft;
266			iorequest.piod_addr = buf;
267			iorequest.piod_len = nwant;
268			ptrace(PT_IO, pid, (caddr_t)&iorequest, 0);
269			ngot = iorequest.piod_len;
270			if ((size_t)ngot < nwant)
271				errx(1, "short read wanted %zu, got %zd",
272				    nwant, ngot);
273			ngot = write(fd, buf, nwant);
274			if (ngot == -1)
275				err(1, "write of segment %d failed", i);
276			if ((size_t)ngot != nwant)
277				errx(1, "short write");
278			nleft -= nwant;
279			iorequest.piod_offs += ngot;
280		}
281		php++;
282	}
283	sbuf_delete(sb);
284	freemap(map);
285}
286
287/*
288 * A callback for each_writable_segment() to write out the segment's
289 * program header entry.
290 */
291static void
292cb_put_phdr(vm_map_entry_t entry, void *closure)
293{
294	struct phdr_closure *phc = (struct phdr_closure *)closure;
295	Elf_Phdr *phdr = phc->phdr;
296
297	phc->offset = round_page(phc->offset);
298
299	phdr->p_type = PT_LOAD;
300	phdr->p_offset = phc->offset;
301	phdr->p_vaddr = entry->start;
302	phdr->p_paddr = 0;
303	phdr->p_filesz = phdr->p_memsz = entry->end - entry->start;
304	phdr->p_align = PAGE_SIZE;
305	phdr->p_flags = 0;
306	if (entry->protection & VM_PROT_READ)
307		phdr->p_flags |= PF_R;
308	if (entry->protection & VM_PROT_WRITE)
309		phdr->p_flags |= PF_W;
310	if (entry->protection & VM_PROT_EXECUTE)
311		phdr->p_flags |= PF_X;
312
313	phc->offset += phdr->p_filesz;
314	phc->phdr++;
315}
316
317/*
318 * A callback for each_writable_segment() to gather information about
319 * the number of segments and their total size.
320 */
321static void
322cb_size_segment(vm_map_entry_t entry, void *closure)
323{
324	struct sseg_closure *ssc = (struct sseg_closure *)closure;
325
326	ssc->count++;
327	ssc->size += entry->end - entry->start;
328}
329
330/*
331 * For each segment in the given memory map, call the given function
332 * with a pointer to the map entry and some arbitrary caller-supplied
333 * data.
334 */
335static void
336each_writable_segment(vm_map_entry_t map, segment_callback func, void *closure)
337{
338	vm_map_entry_t entry;
339
340	for (entry = map;  entry != NULL;  entry = entry->next)
341		(*func)(entry, closure);
342}
343
344static void
345elf_putnotes(pid_t pid, struct sbuf *sb, size_t *sizep)
346{
347	lwpid_t *tids;
348	size_t threads, old_len;
349	ssize_t size;
350	int i;
351
352	errno = 0;
353	threads = ptrace(PT_GETNUMLWPS, pid, NULL, 0);
354	if (errno)
355		err(1, "PT_GETNUMLWPS");
356	tids = malloc(threads * sizeof(*tids));
357	if (tids == NULL)
358		errx(1, "out of memory");
359	errno = 0;
360	ptrace(PT_GETLWPLIST, pid, (void *)tids, threads);
361	if (errno)
362		err(1, "PT_GETLWPLIST");
363
364	sbuf_start_section(sb, &old_len);
365	elf_putnote(NT_PRPSINFO, elf_note_prpsinfo, &pid, sb);
366
367	for (i = 0; i < threads; ++i) {
368		elf_putnote(NT_PRSTATUS, elf_note_prstatus, tids + i, sb);
369		elf_putnote(NT_FPREGSET, elf_note_fpregset, tids + i, sb);
370		elf_putnote(NT_THRMISC, elf_note_thrmisc, tids + i, sb);
371		elf_putnote(NT_PTLWPINFO, elf_note_ptlwpinfo, tids + i, sb);
372#if defined(__arm__)
373		elf_putnote(NT_ARM_VFP, elf_note_arm_vfp, tids + i, sb);
374#endif
375#if defined(__i386__) || defined(__amd64__)
376		elf_putnote(NT_X86_XSTATE, elf_note_x86_xstate, tids + i, sb);
377#endif
378#if defined(__powerpc__)
379		elf_putnote(NT_PPC_VMX, elf_note_powerpc_vmx, tids + i, sb);
380#endif
381	}
382
383#ifndef ELFCORE_COMPAT_32
384	elf_putnote(NT_PROCSTAT_PROC, elf_note_procstat_proc, &pid, sb);
385	elf_putnote(NT_PROCSTAT_FILES, elf_note_procstat_files, &pid, sb);
386	elf_putnote(NT_PROCSTAT_VMMAP, elf_note_procstat_vmmap, &pid, sb);
387	elf_putnote(NT_PROCSTAT_GROUPS, elf_note_procstat_groups, &pid, sb);
388	elf_putnote(NT_PROCSTAT_UMASK, elf_note_procstat_umask, &pid, sb);
389	elf_putnote(NT_PROCSTAT_RLIMIT, elf_note_procstat_rlimit, &pid, sb);
390	elf_putnote(NT_PROCSTAT_OSREL, elf_note_procstat_osrel, &pid, sb);
391	elf_putnote(NT_PROCSTAT_PSSTRINGS, elf_note_procstat_psstrings, &pid,
392	    sb);
393	elf_putnote(NT_PROCSTAT_AUXV, elf_note_procstat_auxv, &pid, sb);
394#endif
395
396	size = sbuf_end_section(sb, old_len, 1, 0);
397	if (size == -1)
398		err(1, "sbuf_end_section");
399	free(tids);
400	*sizep = size;
401}
402
403/*
404 * Emit one note section to sbuf.
405 */
406static void
407elf_putnote(int type, notefunc_t notefunc, void *arg, struct sbuf *sb)
408{
409	Elf_Note note;
410	size_t descsz;
411	ssize_t old_len;
412	void *desc;
413
414	desc = notefunc(arg, &descsz);
415	note.n_namesz = 8; /* strlen("FreeBSD") + 1 */
416	note.n_descsz = descsz;
417	note.n_type = type;
418
419	sbuf_bcat(sb, &note, sizeof(note));
420	sbuf_start_section(sb, &old_len);
421	sbuf_bcat(sb, "FreeBSD", note.n_namesz);
422	sbuf_end_section(sb, old_len, sizeof(Elf32_Size), 0);
423	if (descsz == 0)
424		return;
425	sbuf_start_section(sb, &old_len);
426	sbuf_bcat(sb, desc, descsz);
427	sbuf_end_section(sb, old_len, sizeof(Elf32_Size), 0);
428	free(desc);
429}
430
431/*
432 * Generate the ELF coredump header.
433 */
434static void
435elf_puthdr(int efd, pid_t pid, vm_map_entry_t map, void *hdr, size_t hdrsize,
436    size_t notesz, size_t segoff, int numsegs)
437{
438	Elf_Ehdr *ehdr, binhdr;
439	Elf_Phdr *phdr;
440	struct phdr_closure phc;
441	ssize_t cnt;
442
443	cnt = read(efd, &binhdr, sizeof(binhdr));
444	if (cnt < 0)
445		err(1, "Failed to re-read ELF header");
446	else if (cnt != sizeof(binhdr))
447		errx(1, "Failed to re-read ELF header");
448
449	ehdr = (Elf_Ehdr *)hdr;
450	phdr = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr));
451
452	ehdr->e_ident[EI_MAG0] = ELFMAG0;
453	ehdr->e_ident[EI_MAG1] = ELFMAG1;
454	ehdr->e_ident[EI_MAG2] = ELFMAG2;
455	ehdr->e_ident[EI_MAG3] = ELFMAG3;
456	ehdr->e_ident[EI_CLASS] = ELF_CLASS;
457	ehdr->e_ident[EI_DATA] = ELF_DATA;
458	ehdr->e_ident[EI_VERSION] = EV_CURRENT;
459	ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
460	ehdr->e_ident[EI_ABIVERSION] = 0;
461	ehdr->e_ident[EI_PAD] = 0;
462	ehdr->e_type = ET_CORE;
463	ehdr->e_machine = binhdr.e_machine;
464	ehdr->e_version = EV_CURRENT;
465	ehdr->e_entry = 0;
466	ehdr->e_phoff = sizeof(Elf_Ehdr);
467	ehdr->e_flags = binhdr.e_flags;
468	ehdr->e_ehsize = sizeof(Elf_Ehdr);
469	ehdr->e_phentsize = sizeof(Elf_Phdr);
470	ehdr->e_phnum = numsegs + 1;
471	ehdr->e_shentsize = sizeof(Elf_Shdr);
472	ehdr->e_shnum = 0;
473	ehdr->e_shstrndx = SHN_UNDEF;
474
475	/*
476	 * Fill in the program header entries.
477	 */
478
479	/* The note segement. */
480	phdr->p_type = PT_NOTE;
481	phdr->p_offset = hdrsize;
482	phdr->p_vaddr = 0;
483	phdr->p_paddr = 0;
484	phdr->p_filesz = notesz;
485	phdr->p_memsz = 0;
486	phdr->p_flags = PF_R;
487	phdr->p_align = sizeof(Elf32_Size);
488	phdr++;
489
490	/* All the writable segments from the program. */
491	phc.phdr = phdr;
492	phc.offset = segoff;
493	each_writable_segment(map, cb_put_phdr, &phc);
494}
495
496/*
497 * Free the memory map.
498 */
499static void
500freemap(vm_map_entry_t map)
501{
502
503	while (map != NULL) {
504		vm_map_entry_t next = map->next;
505		free(map);
506		map = next;
507	}
508}
509
510/*
511 * Read the process's memory map using kinfo_getvmmap(), and return a list of
512 * VM map entries.  Only the non-device read/writable segments are
513 * returned.  The map entries in the list aren't fully filled in; only
514 * the items we need are present.
515 */
516static vm_map_entry_t
517readmap(pid_t pid)
518{
519	vm_map_entry_t ent, *linkp, map;
520	struct kinfo_vmentry *vmentl, *kve;
521	int i, nitems;
522
523	vmentl = kinfo_getvmmap(pid, &nitems);
524	if (vmentl == NULL)
525		err(1, "cannot retrieve mappings for %u process", pid);
526
527	map = NULL;
528	linkp = &map;
529	for (i = 0; i < nitems; i++) {
530		kve = &vmentl[i];
531
532		/*
533		 * Ignore 'malformed' segments or ones representing memory
534		 * mapping with MAP_NOCORE on.
535		 * If the 'full' support is disabled, just dump the most
536		 * meaningful data segments.
537		 */
538		if ((kve->kve_protection & KVME_PROT_READ) == 0 ||
539		    (kve->kve_flags & KVME_FLAG_NOCOREDUMP) != 0 ||
540		    kve->kve_type == KVME_TYPE_DEAD ||
541		    kve->kve_type == KVME_TYPE_UNKNOWN ||
542		    ((pflags & PFLAGS_FULL) == 0 &&
543		    kve->kve_type != KVME_TYPE_DEFAULT &&
544		    kve->kve_type != KVME_TYPE_VNODE &&
545		    kve->kve_type != KVME_TYPE_SWAP &&
546		    kve->kve_type != KVME_TYPE_PHYS))
547			continue;
548
549		ent = calloc(1, sizeof(*ent));
550		if (ent == NULL)
551			errx(1, "out of memory");
552		ent->start = (vm_offset_t)kve->kve_start;
553		ent->end = (vm_offset_t)kve->kve_end;
554		ent->protection = VM_PROT_READ | VM_PROT_WRITE;
555		if ((kve->kve_protection & KVME_PROT_EXEC) != 0)
556			ent->protection |= VM_PROT_EXECUTE;
557
558		*linkp = ent;
559		linkp = &ent->next;
560	}
561	free(vmentl);
562	return (map);
563}
564
565/*
566 * Miscellaneous note out functions.
567 */
568
569static void *
570elf_note_prpsinfo(void *arg, size_t *sizep)
571{
572	char *cp, *end;
573	pid_t pid;
574	elfcore_prpsinfo_t *psinfo;
575	struct kinfo_proc kip;
576	size_t len;
577	int name[4];
578
579	pid = *(pid_t *)arg;
580	psinfo = calloc(1, sizeof(*psinfo));
581	if (psinfo == NULL)
582		errx(1, "out of memory");
583	psinfo->pr_version = PRPSINFO_VERSION;
584	psinfo->pr_psinfosz = sizeof(*psinfo);
585
586	name[0] = CTL_KERN;
587	name[1] = KERN_PROC;
588	name[2] = KERN_PROC_PID;
589	name[3] = pid;
590	len = sizeof(kip);
591	if (sysctl(name, 4, &kip, &len, NULL, 0) == -1)
592		err(1, "kern.proc.pid.%u", pid);
593	if (kip.ki_pid != pid)
594		err(1, "kern.proc.pid.%u", pid);
595	strlcpy(psinfo->pr_fname, kip.ki_comm, sizeof(psinfo->pr_fname));
596	name[2] = KERN_PROC_ARGS;
597	len = sizeof(psinfo->pr_psargs) - 1;
598	if (sysctl(name, 4, psinfo->pr_psargs, &len, NULL, 0) == 0 && len > 0) {
599		cp = psinfo->pr_psargs;
600		end = cp + len - 1;
601		for (;;) {
602			cp = memchr(cp, '\0', end - cp);
603			if (cp == NULL)
604				break;
605			*cp = ' ';
606		}
607	} else
608		strlcpy(psinfo->pr_psargs, kip.ki_comm,
609		    sizeof(psinfo->pr_psargs));
610	psinfo->pr_pid = pid;
611
612	*sizep = sizeof(*psinfo);
613	return (psinfo);
614}
615
616static void *
617elf_note_prstatus(void *arg, size_t *sizep)
618{
619	lwpid_t tid;
620	elfcore_prstatus_t *status;
621	struct reg greg;
622
623	tid = *(lwpid_t *)arg;
624	status = calloc(1, sizeof(*status));
625	if (status == NULL)
626		errx(1, "out of memory");
627	status->pr_version = PRSTATUS_VERSION;
628	status->pr_statussz = sizeof(*status);
629	status->pr_gregsetsz = sizeof(elfcore_gregset_t);
630	status->pr_fpregsetsz = sizeof(elfcore_fpregset_t);
631	status->pr_osreldate = __FreeBSD_version;
632	status->pr_pid = tid;
633	ptrace(PT_GETREGS, tid, (void *)&greg, 0);
634	elf_convert_gregset(&status->pr_reg, &greg);
635
636	*sizep = sizeof(*status);
637	return (status);
638}
639
640static void *
641elf_note_fpregset(void *arg, size_t *sizep)
642{
643	lwpid_t tid;
644	elfcore_fpregset_t *fpregset;
645	fpregset_t fpreg;
646
647	tid = *(lwpid_t *)arg;
648	fpregset = calloc(1, sizeof(*fpregset));
649	if (fpregset == NULL)
650		errx(1, "out of memory");
651	ptrace(PT_GETFPREGS, tid, (void *)&fpreg, 0);
652	elf_convert_fpregset(fpregset, &fpreg);
653
654	*sizep = sizeof(*fpregset);
655	return (fpregset);
656}
657
658static void *
659elf_note_thrmisc(void *arg, size_t *sizep)
660{
661	lwpid_t tid;
662	struct ptrace_lwpinfo lwpinfo;
663	thrmisc_t *thrmisc;
664
665	tid = *(lwpid_t *)arg;
666	thrmisc = calloc(1, sizeof(*thrmisc));
667	if (thrmisc == NULL)
668		errx(1, "out of memory");
669	ptrace(PT_LWPINFO, tid, (void *)&lwpinfo,
670	    sizeof(lwpinfo));
671	memset(&thrmisc->_pad, 0, sizeof(thrmisc->_pad));
672	strcpy(thrmisc->pr_tname, lwpinfo.pl_tdname);
673
674	*sizep = sizeof(*thrmisc);
675	return (thrmisc);
676}
677
678static void *
679elf_note_ptlwpinfo(void *arg, size_t *sizep)
680{
681	lwpid_t tid;
682	elfcore_lwpinfo_t *elf_info;
683	struct ptrace_lwpinfo lwpinfo;
684	void *p;
685
686	tid = *(lwpid_t *)arg;
687	p = calloc(1, sizeof(int) + sizeof(elfcore_lwpinfo_t));
688	if (p == NULL)
689		errx(1, "out of memory");
690	*(int *)p = sizeof(elfcore_lwpinfo_t);
691	elf_info = (void *)((int *)p + 1);
692	ptrace(PT_LWPINFO, tid, (void *)&lwpinfo, sizeof(lwpinfo));
693	elf_convert_lwpinfo(elf_info, &lwpinfo);
694
695	*sizep = sizeof(int) + sizeof(struct ptrace_lwpinfo);
696	return (p);
697}
698
699#if defined(__arm__)
700static void *
701elf_note_arm_vfp(void *arg, size_t *sizep)
702{
703	lwpid_t tid;
704	struct vfpreg *vfp;
705	static bool has_vfp = true;
706	struct vfpreg info;
707
708	tid = *(lwpid_t *)arg;
709	if (has_vfp) {
710		if (ptrace(PT_GETVFPREGS, tid, (void *)&info, 0) != 0)
711			has_vfp = false;
712	}
713	if (!has_vfp) {
714		*sizep = 0;
715		return (NULL);
716	}
717	vfp = calloc(1, sizeof(*vfp));
718	memcpy(vfp, &info, sizeof(*vfp));
719	*sizep = sizeof(*vfp);
720	return (vfp);
721}
722#endif
723
724#if defined(__i386__) || defined(__amd64__)
725static void *
726elf_note_x86_xstate(void *arg, size_t *sizep)
727{
728	lwpid_t tid;
729	char *xstate;
730	static bool xsave_checked = false;
731	static struct ptrace_xstate_info info;
732
733	tid = *(lwpid_t *)arg;
734	if (!xsave_checked) {
735		if (ptrace(PT_GETXSTATE_INFO, tid, (void *)&info,
736		    sizeof(info)) != 0)
737			info.xsave_len = 0;
738		xsave_checked = true;
739	}
740	if (info.xsave_len == 0) {
741		*sizep = 0;
742		return (NULL);
743	}
744	xstate = calloc(1, info.xsave_len);
745	ptrace(PT_GETXSTATE, tid, xstate, 0);
746	*(uint64_t *)(xstate + X86_XSTATE_XCR0_OFFSET) = info.xsave_mask;
747	*sizep = info.xsave_len;
748	return (xstate);
749}
750#endif
751
752#if defined(__powerpc__)
753static void *
754elf_note_powerpc_vmx(void *arg, size_t *sizep)
755{
756	lwpid_t tid;
757	struct vmxreg *vmx;
758	static bool has_vmx = true;
759	struct vmxreg info;
760
761	tid = *(lwpid_t *)arg;
762	if (has_vmx) {
763		if (ptrace(PT_GETVRREGS, tid, (void *)&info,
764		    sizeof(info)) != 0)
765			has_vmx = false;
766	}
767	if (!has_vmx) {
768		*sizep = 0;
769		return (NULL);
770	}
771	vmx = calloc(1, sizeof(*vmx));
772	memcpy(vmx, &info, sizeof(*vmx));
773	*sizep = sizeof(*vmx);
774	return (vmx);
775}
776#endif
777
778static void *
779procstat_sysctl(void *arg, int what, size_t structsz, size_t *sizep)
780{
781	size_t len;
782	pid_t pid;
783	int name[4], structsize;
784	void *buf, *p;
785
786	pid = *(pid_t *)arg;
787	structsize = structsz;
788	name[0] = CTL_KERN;
789	name[1] = KERN_PROC;
790	name[2] = what;
791	name[3] = pid;
792	len = 0;
793	if (sysctl(name, 4, NULL, &len, NULL, 0) == -1)
794		err(1, "kern.proc.%d.%u", what, pid);
795	buf = calloc(1, sizeof(structsize) + len * 4 / 3);
796	if (buf == NULL)
797		errx(1, "out of memory");
798	bcopy(&structsize, buf, sizeof(structsize));
799	p = (char *)buf + sizeof(structsize);
800	if (sysctl(name, 4, p, &len, NULL, 0) == -1)
801		err(1, "kern.proc.%d.%u", what, pid);
802
803	*sizep = sizeof(structsize) + len;
804	return (buf);
805}
806
807static void *
808elf_note_procstat_proc(void *arg, size_t *sizep)
809{
810
811	return (procstat_sysctl(arg, KERN_PROC_PID | KERN_PROC_INC_THREAD,
812	    sizeof(struct kinfo_proc), sizep));
813}
814
815static void *
816elf_note_procstat_files(void *arg, size_t *sizep)
817{
818
819	return (procstat_sysctl(arg, KERN_PROC_FILEDESC,
820	    sizeof(struct kinfo_file), sizep));
821}
822
823static void *
824elf_note_procstat_vmmap(void *arg, size_t *sizep)
825{
826
827	return (procstat_sysctl(arg, KERN_PROC_VMMAP,
828	    sizeof(struct kinfo_vmentry), sizep));
829}
830
831static void *
832elf_note_procstat_groups(void *arg, size_t *sizep)
833{
834
835	return (procstat_sysctl(arg, KERN_PROC_GROUPS, sizeof(gid_t), sizep));
836}
837
838static void *
839elf_note_procstat_umask(void *arg, size_t *sizep)
840{
841
842	return (procstat_sysctl(arg, KERN_PROC_UMASK, sizeof(u_short), sizep));
843}
844
845static void *
846elf_note_procstat_osrel(void *arg, size_t *sizep)
847{
848
849	return (procstat_sysctl(arg, KERN_PROC_OSREL, sizeof(int), sizep));
850}
851
852static void *
853elf_note_procstat_psstrings(void *arg, size_t *sizep)
854{
855
856	return (procstat_sysctl(arg, KERN_PROC_PS_STRINGS,
857	    sizeof(vm_offset_t), sizep));
858}
859
860static void *
861elf_note_procstat_auxv(void *arg, size_t *sizep)
862{
863
864	return (procstat_sysctl(arg, KERN_PROC_AUXV,
865	    sizeof(Elf_Auxinfo), sizep));
866}
867
868static void *
869elf_note_procstat_rlimit(void *arg, size_t *sizep)
870{
871	pid_t pid;
872	size_t len;
873	int i, name[5], structsize;
874	void *buf, *p;
875
876	pid = *(pid_t *)arg;
877	structsize = sizeof(struct rlimit) * RLIM_NLIMITS;
878	buf = calloc(1, sizeof(structsize) + structsize);
879	if (buf == NULL)
880		errx(1, "out of memory");
881	bcopy(&structsize, buf, sizeof(structsize));
882	p = (char *)buf + sizeof(structsize);
883	name[0] = CTL_KERN;
884	name[1] = KERN_PROC;
885	name[2] = KERN_PROC_RLIMIT;
886	name[3] = pid;
887	len = sizeof(struct rlimit);
888	for (i = 0; i < RLIM_NLIMITS; i++) {
889		name[4] = i;
890		if (sysctl(name, 5, p, &len, NULL, 0) == -1)
891			err(1, "kern.proc.rlimit.%u", pid);
892		if (len != sizeof(struct rlimit))
893			errx(1, "kern.proc.rlimit.%u: short read", pid);
894		p += len;
895	}
896
897	*sizep = sizeof(structsize) + structsize;
898	return (buf);
899}
900
901struct dumpers __elfN(dump) = { elf_ident, elf_coredump };
902TEXT_SET(dumpset, __elfN(dump));
903