elfcore.c revision 223924
140525Sjdp/*- 2199805Sattilio * Copyright (c) 2007 Sandvine Incorporated 340525Sjdp * Copyright (c) 1998 John D. Polstra 440525Sjdp * All rights reserved. 540525Sjdp * 640525Sjdp * Redistribution and use in source and binary forms, with or without 740525Sjdp * modification, are permitted provided that the following conditions 840525Sjdp * are met: 940525Sjdp * 1. Redistributions of source code must retain the above copyright 1040525Sjdp * notice, this list of conditions and the following disclaimer. 1140525Sjdp * 2. Redistributions in binary form must reproduce the above copyright 1240525Sjdp * notice, this list of conditions and the following disclaimer in the 1340525Sjdp * documentation and/or other materials provided with the distribution. 1440525Sjdp * 1540525Sjdp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1640525Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1740525Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1840525Sjdp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1940525Sjdp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2040525Sjdp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2140525Sjdp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2240525Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2340525Sjdp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2440525Sjdp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2540525Sjdp * SUCH DAMAGE. 2640525Sjdp */ 2740525Sjdp 2893215Scharnier#include <sys/cdefs.h> 2993215Scharnier__FBSDID("$FreeBSD: head/usr.bin/gcore/elfcore.c 223924 2011-07-11 05:46:15Z delphij $"); 3093215Scharnier 3140525Sjdp#include <sys/param.h> 3240525Sjdp#include <sys/procfs.h> 33199805Sattilio#include <sys/ptrace.h> 34103302Speter#include <sys/queue.h> 35103299Speter#include <sys/linker_set.h> 36199805Sattilio#include <sys/sysctl.h> 37199805Sattilio#include <sys/user.h> 38199805Sattilio#include <sys/wait.h> 3976224Sobrien#include <machine/elf.h> 4040525Sjdp#include <vm/vm_param.h> 4140525Sjdp#include <vm/vm.h> 4240525Sjdp#include <vm/pmap.h> 4340525Sjdp#include <vm/vm_map.h> 4440525Sjdp#include <err.h> 4540525Sjdp#include <errno.h> 4640525Sjdp#include <fcntl.h> 47102951Siedowse#include <stdint.h> 4840525Sjdp#include <stdio.h> 4940525Sjdp#include <stdlib.h> 5040525Sjdp#include <string.h> 5140525Sjdp#include <unistd.h> 52199805Sattilio#include <libutil.h> 5340525Sjdp 5440525Sjdp#include "extern.h" 5540525Sjdp 5640525Sjdp/* 5740525Sjdp * Code for generating ELF core dumps. 5840525Sjdp */ 5940525Sjdp 6040525Sjdptypedef void (*segment_callback)(vm_map_entry_t, void *); 6140525Sjdp 6240525Sjdp/* Closure for cb_put_phdr(). */ 6340525Sjdpstruct phdr_closure { 6440525Sjdp Elf_Phdr *phdr; /* Program header to fill in */ 6540525Sjdp Elf_Off offset; /* Offset of segment in core file */ 6640525Sjdp}; 6740525Sjdp 6840525Sjdp/* Closure for cb_size_segment(). */ 6940525Sjdpstruct sseg_closure { 7040525Sjdp int count; /* Count of writable segments. */ 7140525Sjdp size_t size; /* Total size of all writable segments. */ 7240525Sjdp}; 7340525Sjdp 7440525Sjdpstatic void cb_put_phdr(vm_map_entry_t, void *); 7540525Sjdpstatic void cb_size_segment(vm_map_entry_t, void *); 7640525Sjdpstatic void each_writable_segment(vm_map_entry_t, segment_callback, 7740525Sjdp void *closure); 78199805Sattiliostatic void elf_detach(void); /* atexit() handler. */ 79199805Sattiliostatic void elf_puthdr(pid_t, vm_map_entry_t, void *, size_t *, int numsegs); 8040525Sjdpstatic void elf_putnote(void *dst, size_t *off, const char *name, int type, 8140525Sjdp const void *desc, size_t descsz); 8240525Sjdpstatic void freemap(vm_map_entry_t); 8340525Sjdpstatic vm_map_entry_t readmap(pid_t); 8440525Sjdp 85199805Sattiliostatic pid_t g_pid; /* Pid being dumped, global for elf_detach */ 86199805Sattilio 87103299Speterstatic int 88125859Sdwmaloneelf_ident(int efd, pid_t pid __unused, char *binfile __unused) 89103299Speter{ 90103299Speter Elf_Ehdr hdr; 91103299Speter int cnt; 92103299Speter 93103299Speter cnt = read(efd, &hdr, sizeof(hdr)); 94103299Speter if (cnt != sizeof(hdr)) 95103299Speter return (0); 96103299Speter if (IS_ELF(hdr)) 97103299Speter return (1); 98103299Speter return (0); 99103299Speter} 100103299Speter 101199805Sattiliostatic void 102199805Sattilioelf_detach(void) 103199805Sattilio{ 104199805Sattilio 105199805Sattilio if (g_pid != 0) 106199805Sattilio ptrace(PT_DETACH, g_pid, (caddr_t)1, 0); 107199805Sattilio} 108199805Sattilio 10940525Sjdp/* 11040525Sjdp * Write an ELF coredump for the given pid to the given fd. 11140525Sjdp */ 112125859Sdwmalonestatic void 113125859Sdwmaloneelf_coredump(int efd __unused, int fd, pid_t pid) 11440525Sjdp{ 11540525Sjdp vm_map_entry_t map; 11640525Sjdp struct sseg_closure seginfo; 11740525Sjdp void *hdr; 11840525Sjdp size_t hdrsize; 11940525Sjdp Elf_Phdr *php; 12040525Sjdp int i; 12140525Sjdp 122199805Sattilio /* Attach to process to dump. */ 123199805Sattilio g_pid = pid; 124199805Sattilio if (atexit(elf_detach) != 0) 125199805Sattilio err(1, "atexit"); 126199805Sattilio errno = 0; 127199805Sattilio ptrace(PT_ATTACH, pid, NULL, 0); 128199805Sattilio if (errno) 129199805Sattilio err(1, "PT_ATTACH"); 130199805Sattilio if (waitpid(pid, NULL, 0) == -1) 131199805Sattilio err(1, "waitpid"); 132199805Sattilio 13340525Sjdp /* Get the program's memory map. */ 13440525Sjdp map = readmap(pid); 13540525Sjdp 13640525Sjdp /* Size the program segments. */ 13740525Sjdp seginfo.count = 0; 13840525Sjdp seginfo.size = 0; 13940525Sjdp each_writable_segment(map, cb_size_segment, &seginfo); 14040525Sjdp 14140525Sjdp /* 14240525Sjdp * Calculate the size of the core file header area by making 14340525Sjdp * a dry run of generating it. Nothing is written, but the 14440525Sjdp * size is calculated. 14540525Sjdp */ 14640525Sjdp hdrsize = 0; 147199805Sattilio elf_puthdr(pid, map, NULL, &hdrsize, seginfo.count); 14840525Sjdp 14940525Sjdp /* 15040525Sjdp * Allocate memory for building the header, fill it up, 15140525Sjdp * and write it out. 15240525Sjdp */ 153199805Sattilio if ((hdr = calloc(1, hdrsize)) == NULL) 15440525Sjdp errx(1, "out of memory"); 15540525Sjdp 156199805Sattilio /* Fill in the header. */ 157199805Sattilio hdrsize = 0; 158199805Sattilio elf_puthdr(pid, map, hdr, &hdrsize, seginfo.count); 159199805Sattilio 160199805Sattilio /* Write it to the core file. */ 161199805Sattilio if (write(fd, hdr, hdrsize) == -1) 162199805Sattilio err(1, "write"); 163199805Sattilio 16440525Sjdp /* Write the contents of all of the writable segments. */ 16540525Sjdp php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1; 16640525Sjdp for (i = 0; i < seginfo.count; i++) { 167199805Sattilio struct ptrace_io_desc iorequest; 168102944Sdwmalone uintmax_t nleft = php->p_filesz; 16940525Sjdp 170199805Sattilio iorequest.piod_op = PIOD_READ_D; 171199805Sattilio iorequest.piod_offs = (caddr_t)php->p_vaddr; 17240525Sjdp while (nleft > 0) { 17340525Sjdp char buf[8*1024]; 174102944Sdwmalone size_t nwant; 175102944Sdwmalone ssize_t ngot; 17640525Sjdp 177102944Sdwmalone if (nleft > sizeof(buf)) 17840525Sjdp nwant = sizeof buf; 179102944Sdwmalone else 180102944Sdwmalone nwant = nleft; 181199805Sattilio iorequest.piod_addr = buf; 182199805Sattilio iorequest.piod_len = nwant; 183199805Sattilio ptrace(PT_IO, pid, (caddr_t)&iorequest, 0); 184199805Sattilio ngot = iorequest.piod_len; 185102944Sdwmalone if ((size_t)ngot < nwant) 186223924Sdelphij errx(1, "short read wanted %zu, got %zd", 18740803Sjdp nwant, ngot); 18840525Sjdp ngot = write(fd, buf, nwant); 18940525Sjdp if (ngot == -1) 19040525Sjdp err(1, "write of segment %d failed", i); 191102944Sdwmalone if ((size_t)ngot != nwant) 19240525Sjdp errx(1, "short write"); 19340525Sjdp nleft -= nwant; 194199805Sattilio iorequest.piod_offs += ngot; 19540525Sjdp } 19640525Sjdp php++; 19740525Sjdp } 19840525Sjdp free(hdr); 19940525Sjdp freemap(map); 20040525Sjdp} 20140525Sjdp 20240525Sjdp/* 20340525Sjdp * A callback for each_writable_segment() to write out the segment's 20440525Sjdp * program header entry. 20540525Sjdp */ 20640525Sjdpstatic void 20740525Sjdpcb_put_phdr(vm_map_entry_t entry, void *closure) 20840525Sjdp{ 20940525Sjdp struct phdr_closure *phc = (struct phdr_closure *)closure; 21040525Sjdp Elf_Phdr *phdr = phc->phdr; 21140525Sjdp 21240525Sjdp phc->offset = round_page(phc->offset); 21340525Sjdp 21440525Sjdp phdr->p_type = PT_LOAD; 21540525Sjdp phdr->p_offset = phc->offset; 21640525Sjdp phdr->p_vaddr = entry->start; 21740525Sjdp phdr->p_paddr = 0; 21840525Sjdp phdr->p_filesz = phdr->p_memsz = entry->end - entry->start; 21940525Sjdp phdr->p_align = PAGE_SIZE; 22040525Sjdp phdr->p_flags = 0; 22140525Sjdp if (entry->protection & VM_PROT_READ) 22240525Sjdp phdr->p_flags |= PF_R; 22340525Sjdp if (entry->protection & VM_PROT_WRITE) 22440525Sjdp phdr->p_flags |= PF_W; 22540525Sjdp if (entry->protection & VM_PROT_EXECUTE) 22640525Sjdp phdr->p_flags |= PF_X; 22740525Sjdp 22840525Sjdp phc->offset += phdr->p_filesz; 22940525Sjdp phc->phdr++; 23040525Sjdp} 23140525Sjdp 23240525Sjdp/* 23340525Sjdp * A callback for each_writable_segment() to gather information about 23440525Sjdp * the number of segments and their total size. 23540525Sjdp */ 23640525Sjdpstatic void 23740525Sjdpcb_size_segment(vm_map_entry_t entry, void *closure) 23840525Sjdp{ 23940525Sjdp struct sseg_closure *ssc = (struct sseg_closure *)closure; 24040525Sjdp 24140525Sjdp ssc->count++; 24240525Sjdp ssc->size += entry->end - entry->start; 24340525Sjdp} 24440525Sjdp 24540525Sjdp/* 24640525Sjdp * For each segment in the given memory map, call the given function 24740525Sjdp * with a pointer to the map entry and some arbitrary caller-supplied 24840525Sjdp * data. 24940525Sjdp */ 25040525Sjdpstatic void 25140525Sjdpeach_writable_segment(vm_map_entry_t map, segment_callback func, void *closure) 25240525Sjdp{ 25340525Sjdp vm_map_entry_t entry; 25440525Sjdp 25540525Sjdp for (entry = map; entry != NULL; entry = entry->next) 25640525Sjdp (*func)(entry, closure); 25740525Sjdp} 25840525Sjdp 25940525Sjdpstatic void 260199805Sattilioelf_getstatus(pid_t pid, prpsinfo_t *psinfo) 26140525Sjdp{ 262199805Sattilio struct kinfo_proc kobj; 263199805Sattilio int name[4]; 264199805Sattilio size_t len; 26540525Sjdp 266199805Sattilio name[0] = CTL_KERN; 267199805Sattilio name[1] = KERN_PROC; 268199805Sattilio name[2] = KERN_PROC_PID; 269199805Sattilio name[3] = pid; 27040525Sjdp 271199805Sattilio len = sizeof(kobj); 272199805Sattilio if (sysctl(name, 4, &kobj, &len, NULL, 0) == -1) 273199805Sattilio err(1, "error accessing kern.proc.pid.%u sysctl", pid); 274199805Sattilio if (kobj.ki_pid != pid) 275199805Sattilio err(1, "error accessing kern.proc.pid.%u sysctl datas", pid); 276199805Sattilio strncpy(psinfo->pr_fname, kobj.ki_comm, MAXCOMLEN); 277199805Sattilio strncpy(psinfo->pr_psargs, psinfo->pr_fname, PRARGSZ); 27840525Sjdp} 27940525Sjdp 28040525Sjdp/* 28140525Sjdp * Generate the ELF coredump header into the buffer at "dst". "dst" may 28240525Sjdp * be NULL, in which case the header is sized but not actually generated. 28340525Sjdp */ 28440525Sjdpstatic void 285199805Sattilioelf_puthdr(pid_t pid, vm_map_entry_t map, void *dst, size_t *off, int numsegs) 28640525Sjdp{ 287215679Sattilio struct ptrace_lwpinfo lwpinfo; 288199805Sattilio struct { 289199805Sattilio prstatus_t status; 290199805Sattilio prfpregset_t fpregset; 291199805Sattilio prpsinfo_t psinfo; 292215679Sattilio thrmisc_t thrmisc; 293199805Sattilio } *tempdata; 29440525Sjdp size_t ehoff; 29540525Sjdp size_t phoff; 29640525Sjdp size_t noteoff; 29740525Sjdp size_t notesz; 298199805Sattilio size_t threads; 299199805Sattilio lwpid_t *tids; 300199805Sattilio int i; 30140525Sjdp 302199805Sattilio prstatus_t *status; 303199805Sattilio prfpregset_t *fpregset; 304199805Sattilio prpsinfo_t *psinfo; 305215679Sattilio thrmisc_t *thrmisc; 306199805Sattilio 30740525Sjdp ehoff = *off; 30840525Sjdp *off += sizeof(Elf_Ehdr); 30940525Sjdp 31040525Sjdp phoff = *off; 31140525Sjdp *off += (numsegs + 1) * sizeof(Elf_Phdr); 31240525Sjdp 31340525Sjdp noteoff = *off; 314199805Sattilio 315199805Sattilio if (dst != NULL) { 316199805Sattilio if ((tempdata = calloc(1, sizeof(*tempdata))) == NULL) 317199805Sattilio errx(1, "out of memory"); 318199805Sattilio status = &tempdata->status; 319199805Sattilio fpregset = &tempdata->fpregset; 320199805Sattilio psinfo = &tempdata->psinfo; 321215679Sattilio thrmisc = &tempdata->thrmisc; 322199805Sattilio } else { 323199805Sattilio tempdata = NULL; 324199805Sattilio status = NULL; 325199805Sattilio fpregset = NULL; 326199805Sattilio psinfo = NULL; 327215679Sattilio thrmisc = NULL; 328199805Sattilio } 329199805Sattilio 330199805Sattilio errno = 0; 331199805Sattilio threads = ptrace(PT_GETNUMLWPS, pid, NULL, 0); 332199805Sattilio if (errno) 333199805Sattilio err(1, "PT_GETNUMLWPS"); 334199805Sattilio 335199805Sattilio if (dst != NULL) { 336199805Sattilio psinfo->pr_version = PRPSINFO_VERSION; 337199805Sattilio psinfo->pr_psinfosz = sizeof(prpsinfo_t); 338199805Sattilio elf_getstatus(pid, psinfo); 339199805Sattilio 340199805Sattilio } 34140525Sjdp elf_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo, 34240525Sjdp sizeof *psinfo); 343199805Sattilio 344199805Sattilio if (dst != NULL) { 345199805Sattilio tids = malloc(threads * sizeof(*tids)); 346199805Sattilio if (tids == NULL) 347199805Sattilio errx(1, "out of memory"); 348199805Sattilio errno = 0; 349199805Sattilio ptrace(PT_GETLWPLIST, pid, (void *)tids, threads); 350199805Sattilio if (errno) 351199805Sattilio err(1, "PT_GETLWPLIST"); 352199805Sattilio } 353199805Sattilio for (i = 0; i < threads; ++i) { 354199805Sattilio if (dst != NULL) { 355199805Sattilio status->pr_version = PRSTATUS_VERSION; 356199805Sattilio status->pr_statussz = sizeof(prstatus_t); 357199805Sattilio status->pr_gregsetsz = sizeof(gregset_t); 358199805Sattilio status->pr_fpregsetsz = sizeof(fpregset_t); 359199805Sattilio status->pr_osreldate = __FreeBSD_version; 360199805Sattilio status->pr_pid = tids[i]; 361199805Sattilio 362199805Sattilio ptrace(PT_GETREGS, tids[i], (void *)&status->pr_reg, 0); 363199805Sattilio ptrace(PT_GETFPREGS, tids[i], (void *)fpregset, 0); 364215679Sattilio ptrace(PT_LWPINFO, tids[i], (void *)&lwpinfo, 365215679Sattilio sizeof(lwpinfo)); 366215679Sattilio memset(&thrmisc->_pad, 0, sizeof(thrmisc->_pad)); 367215679Sattilio strcpy(thrmisc->pr_tname, lwpinfo.pl_tdname); 368199805Sattilio } 369199805Sattilio elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status, 370199805Sattilio sizeof *status); 371199805Sattilio elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset, 372199805Sattilio sizeof *fpregset); 373215679Sattilio elf_putnote(dst, off, "FreeBSD", NT_THRMISC, thrmisc, 374215679Sattilio sizeof *thrmisc); 375199805Sattilio } 376199805Sattilio 37740525Sjdp notesz = *off - noteoff; 37840525Sjdp 379199805Sattilio if (dst != NULL) { 380199805Sattilio free(tids); 381199805Sattilio free(tempdata); 382199805Sattilio } 383199805Sattilio 38440525Sjdp /* Align up to a page boundary for the program segments. */ 38540525Sjdp *off = round_page(*off); 38640525Sjdp 38740525Sjdp if (dst != NULL) { 38840525Sjdp Elf_Ehdr *ehdr; 38940525Sjdp Elf_Phdr *phdr; 39040525Sjdp struct phdr_closure phc; 39140525Sjdp 39240525Sjdp /* 39340525Sjdp * Fill in the ELF header. 39440525Sjdp */ 39540525Sjdp ehdr = (Elf_Ehdr *)((char *)dst + ehoff); 39640525Sjdp ehdr->e_ident[EI_MAG0] = ELFMAG0; 39740525Sjdp ehdr->e_ident[EI_MAG1] = ELFMAG1; 39840525Sjdp ehdr->e_ident[EI_MAG2] = ELFMAG2; 39940525Sjdp ehdr->e_ident[EI_MAG3] = ELFMAG3; 40040525Sjdp ehdr->e_ident[EI_CLASS] = ELF_CLASS; 40140525Sjdp ehdr->e_ident[EI_DATA] = ELF_DATA; 40240525Sjdp ehdr->e_ident[EI_VERSION] = EV_CURRENT; 40359342Sobrien ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; 40459342Sobrien ehdr->e_ident[EI_ABIVERSION] = 0; 40540525Sjdp ehdr->e_ident[EI_PAD] = 0; 40640525Sjdp ehdr->e_type = ET_CORE; 40740525Sjdp ehdr->e_machine = ELF_ARCH; 40840525Sjdp ehdr->e_version = EV_CURRENT; 40940525Sjdp ehdr->e_entry = 0; 41040525Sjdp ehdr->e_phoff = phoff; 41140525Sjdp ehdr->e_flags = 0; 41240525Sjdp ehdr->e_ehsize = sizeof(Elf_Ehdr); 41340525Sjdp ehdr->e_phentsize = sizeof(Elf_Phdr); 41440525Sjdp ehdr->e_phnum = numsegs + 1; 41540525Sjdp ehdr->e_shentsize = sizeof(Elf_Shdr); 41640525Sjdp ehdr->e_shnum = 0; 41740525Sjdp ehdr->e_shstrndx = SHN_UNDEF; 41840525Sjdp 41940525Sjdp /* 42040525Sjdp * Fill in the program header entries. 42140525Sjdp */ 42240525Sjdp phdr = (Elf_Phdr *)((char *)dst + phoff); 42340525Sjdp 42493215Scharnier /* The note segment. */ 42540525Sjdp phdr->p_type = PT_NOTE; 42640525Sjdp phdr->p_offset = noteoff; 42740525Sjdp phdr->p_vaddr = 0; 42840525Sjdp phdr->p_paddr = 0; 42940525Sjdp phdr->p_filesz = notesz; 43040525Sjdp phdr->p_memsz = 0; 43140525Sjdp phdr->p_flags = 0; 43240525Sjdp phdr->p_align = 0; 43340525Sjdp phdr++; 43440525Sjdp 43540525Sjdp /* All the writable segments from the program. */ 43640525Sjdp phc.phdr = phdr; 43740525Sjdp phc.offset = *off; 43840525Sjdp each_writable_segment(map, cb_put_phdr, &phc); 43940525Sjdp } 44040525Sjdp} 44140525Sjdp 44240525Sjdp/* 44340525Sjdp * Emit one note section to "dst", or just size it if "dst" is NULL. 44440525Sjdp */ 44540525Sjdpstatic void 44640525Sjdpelf_putnote(void *dst, size_t *off, const char *name, int type, 44740525Sjdp const void *desc, size_t descsz) 44840525Sjdp{ 44940525Sjdp Elf_Note note; 45040525Sjdp 45140525Sjdp note.n_namesz = strlen(name) + 1; 45240525Sjdp note.n_descsz = descsz; 45340525Sjdp note.n_type = type; 45440525Sjdp if (dst != NULL) 45540525Sjdp bcopy(¬e, (char *)dst + *off, sizeof note); 45640525Sjdp *off += sizeof note; 45740525Sjdp if (dst != NULL) 45840525Sjdp bcopy(name, (char *)dst + *off, note.n_namesz); 45940525Sjdp *off += roundup2(note.n_namesz, sizeof(Elf_Size)); 46040525Sjdp if (dst != NULL) 46140525Sjdp bcopy(desc, (char *)dst + *off, note.n_descsz); 46240525Sjdp *off += roundup2(note.n_descsz, sizeof(Elf_Size)); 46340525Sjdp} 46440525Sjdp 46540525Sjdp/* 46640525Sjdp * Free the memory map. 46740525Sjdp */ 46840525Sjdpstatic void 46940525Sjdpfreemap(vm_map_entry_t map) 47040525Sjdp{ 471103299Speter 47240525Sjdp while (map != NULL) { 47340525Sjdp vm_map_entry_t next = map->next; 47440525Sjdp free(map); 47540525Sjdp map = next; 47640525Sjdp } 47740525Sjdp} 47840525Sjdp 47940525Sjdp/* 480199805Sattilio * Read the process's memory map using kinfo_getvmmap(), and return a list of 48140525Sjdp * VM map entries. Only the non-device read/writable segments are 48240525Sjdp * returned. The map entries in the list aren't fully filled in; only 48340525Sjdp * the items we need are present. 48440525Sjdp */ 48540525Sjdpstatic vm_map_entry_t 48640525Sjdpreadmap(pid_t pid) 48740525Sjdp{ 488199805Sattilio vm_map_entry_t ent, *linkp, map; 489199805Sattilio struct kinfo_vmentry *vmentl, *kve; 490199805Sattilio int i, nitems; 49140525Sjdp 492199805Sattilio vmentl = kinfo_getvmmap(pid, &nitems); 493199805Sattilio if (vmentl == NULL) 494199805Sattilio err(1, "cannot retrieve mappings for %u process", pid); 49540525Sjdp 49640525Sjdp map = NULL; 49740525Sjdp linkp = ↦ 498199805Sattilio for (i = 0; i < nitems; i++) { 499199805Sattilio kve = &vmentl[i]; 50040525Sjdp 501199805Sattilio /* 502210063Sattilio * Ignore 'malformed' segments or ones representing memory 503210063Sattilio * mapping with MAP_NOCORE on. 504210063Sattilio * If the 'full' support is disabled, just dump the most 505210063Sattilio * meaningful data segments. 506199805Sattilio */ 507210063Sattilio if ((kve->kve_protection & KVME_PROT_READ) == 0 || 508210063Sattilio (kve->kve_flags & KVME_FLAG_NOCOREDUMP) != 0 || 509210063Sattilio kve->kve_type == KVME_TYPE_DEAD || 510210063Sattilio kve->kve_type == KVME_TYPE_UNKNOWN || 511210063Sattilio ((pflags & PFLAGS_FULL) == 0 && 512210063Sattilio kve->kve_type != KVME_TYPE_DEFAULT && 513199805Sattilio kve->kve_type != KVME_TYPE_VNODE && 514199805Sattilio kve->kve_type != KVME_TYPE_SWAP)) 51540525Sjdp continue; 51640525Sjdp 517199805Sattilio ent = calloc(1, sizeof(*ent)); 518199805Sattilio if (ent == NULL) 51940525Sjdp errx(1, "out of memory"); 520199805Sattilio ent->start = (vm_offset_t)kve->kve_start; 521199805Sattilio ent->end = (vm_offset_t)kve->kve_end; 52240525Sjdp ent->protection = VM_PROT_READ | VM_PROT_WRITE; 523199805Sattilio if ((kve->kve_protection & KVME_PROT_EXEC) != 0) 524199805Sattilio ent->protection |= VM_PROT_EXECUTE; 52540525Sjdp 52640525Sjdp *linkp = ent; 52740525Sjdp linkp = &ent->next; 52840525Sjdp } 529199805Sattilio free(vmentl); 530199805Sattilio return (map); 53140525Sjdp} 532103299Speter 533103299Speterstruct dumpers elfdump = { elf_ident, elf_coredump }; 534103299SpeterTEXT_SET(dumpset, elfdump); 535