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