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/param.h> 32 #include <sys/procfs.h> 33 #include <sys/ptrace.h> 34 #include <sys/queue.h> 35 #include <sys/linker_set.h> 36 #include <sys/sbuf.h> 37 #include <sys/sysctl.h> 38 #include <sys/user.h> 39 #include <sys/wait.h> 40 #include <machine/elf.h> 41 #include <vm/vm_param.h> 42 #include <vm/vm.h> 43 #include <vm/pmap.h> 44 #include <vm/vm_map.h> 45 #include <assert.h> 46 #include <err.h> 47 #include <errno.h> 48 #include <fcntl.h> 49 #include <stdint.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <unistd.h> 54 #include <libutil.h> 55 56 #include "extern.h" 57 58 /* 59 * Code for generating ELF core dumps. 60 */ 61 62 typedef void (*segment_callback)(vm_map_entry_t, void *); 63 64 /* Closure for cb_put_phdr(). */ 65 struct phdr_closure { 66 Elf_Phdr *phdr; /* Program header to fill in */ 67 Elf_Off offset; /* Offset of segment in core file */ 68 }; 69 70 /* Closure for cb_size_segment(). */ 71 struct sseg_closure { 72 int count; /* Count of writable segments. */ 73 size_t size; /* Total size of all writable segments. */ 74 }; 75 76 typedef void* (*notefunc_t)(void *, size_t *); 77 78 static void cb_put_phdr(vm_map_entry_t, void *); 79 static void cb_size_segment(vm_map_entry_t, void *); 80 static void each_writable_segment(vm_map_entry_t, segment_callback, 81 void *closure); 82 static void elf_detach(void); /* atexit() handler. */ 83 static void *elf_note_fpregset(void *, size_t *); 84 static void *elf_note_prpsinfo(void *, size_t *); 85 static void *elf_note_prstatus(void *, size_t *); 86 static void *elf_note_thrmisc(void *, size_t *); 87 static void *elf_note_procstat_auxv(void *, size_t *); 88 static void *elf_note_procstat_files(void *, size_t *); 89 static void *elf_note_procstat_groups(void *, size_t *); 90 static void *elf_note_procstat_osrel(void *, size_t *); 91 static void *elf_note_procstat_proc(void *, size_t *); 92 static void *elf_note_procstat_psstrings(void *, size_t *); 93 static void *elf_note_procstat_rlimit(void *, size_t *); 94 static void *elf_note_procstat_umask(void *, size_t *); 95 static void *elf_note_procstat_vmmap(void *, size_t *); 96 static void elf_puthdr(pid_t, vm_map_entry_t, void *, size_t, size_t, size_t, 97 int); 98 static void elf_putnote(int, notefunc_t, void *, struct sbuf *); 99 static void elf_putnotes(pid_t, struct sbuf *, size_t *); 100 static void freemap(vm_map_entry_t); 101 static vm_map_entry_t readmap(pid_t); 102 static void *procstat_sysctl(void *, int, size_t, size_t *sizep); 103 104 static pid_t g_pid; /* Pid being dumped, global for elf_detach */ 105 106 static int 107 elf_ident(int efd, pid_t pid __unused, char *binfile __unused) 108 { 109 Elf_Ehdr hdr; 110 int cnt; 111 112 cnt = read(efd, &hdr, sizeof(hdr)); 113 if (cnt != sizeof(hdr)) 114 return (0); 115 if (IS_ELF(hdr)) 116 return (1); 117 return (0); 118 } 119 120 static void 121 elf_detach(void) 122 { 123 124 if (g_pid != 0) 125 ptrace(PT_DETACH, g_pid, (caddr_t)1, 0); 126 } 127 128 /* 129 * Write an ELF coredump for the given pid to the given fd. 130 */ 131 static void 132 elf_coredump(int efd __unused, int fd, pid_t pid) 133 { 134 vm_map_entry_t map; 135 struct sseg_closure seginfo; 136 struct sbuf *sb; 137 void *hdr; 138 size_t hdrsize, notesz, segoff; 139 ssize_t n, old_len; 140 Elf_Phdr *php; 141 int i; 142 143 /* Attach to process to dump. */ 144 g_pid = pid; 145 if (atexit(elf_detach) != 0) 146 err(1, "atexit"); 147 errno = 0; 148 ptrace(PT_ATTACH, pid, NULL, 0); 149 if (errno) 150 err(1, "PT_ATTACH"); 151 if (waitpid(pid, NULL, 0) == -1) 152 err(1, "waitpid"); 153 154 /* Get the program's memory map. */ 155 map = readmap(pid); 156 157 /* Size the program segments. */ 158 seginfo.count = 0; 159 seginfo.size = 0; 160 each_writable_segment(map, cb_size_segment, &seginfo); 161 162 /* 163 * Build the header and the notes using sbuf and write to the file. 164 */ 165 sb = sbuf_new_auto(); 166 hdrsize = sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * (1 + seginfo.count); 167 /* Start header + notes section. */ 168 sbuf_start_section(sb, NULL); 169 /* Make empty header subsection. */ 170 sbuf_start_section(sb, &old_len); 171 sbuf_putc(sb, 0); 172 sbuf_end_section(sb, old_len, hdrsize, 0); 173 /* Put notes. */ 174 elf_putnotes(pid, sb, ¬esz); 175 /* Align up to a page boundary for the program segments. */ 176 sbuf_end_section(sb, -1, PAGE_SIZE, 0); 177 if (sbuf_finish(sb) != 0) 178 err(1, "sbuf_finish"); 179 hdr = sbuf_data(sb); 180 segoff = sbuf_len(sb); 181 /* Fill in the header. */ 182 elf_puthdr(pid, map, hdr, hdrsize, notesz, segoff, seginfo.count); 183 184 n = write(fd, hdr, segoff); 185 if (n == -1) 186 err(1, "write"); 187 if (n < segoff) 188 errx(1, "short write"); 189 190 /* Write the contents of all of the writable segments. */ 191 php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1; 192 for (i = 0; i < seginfo.count; i++) { 193 struct ptrace_io_desc iorequest; 194 uintmax_t nleft = php->p_filesz; 195 196 iorequest.piod_op = PIOD_READ_D; 197 iorequest.piod_offs = (caddr_t)php->p_vaddr; 198 while (nleft > 0) { 199 char buf[8*1024]; 200 size_t nwant; 201 ssize_t ngot; 202 203 if (nleft > sizeof(buf)) 204 nwant = sizeof buf; 205 else 206 nwant = nleft; 207 iorequest.piod_addr = buf; 208 iorequest.piod_len = nwant; 209 ptrace(PT_IO, pid, (caddr_t)&iorequest, 0); 210 ngot = iorequest.piod_len; 211 if ((size_t)ngot < nwant) 212 errx(1, "short read wanted %zu, got %zd", 213 nwant, ngot); 214 ngot = write(fd, buf, nwant); 215 if (ngot == -1) 216 err(1, "write of segment %d failed", i); 217 if ((size_t)ngot != nwant) 218 errx(1, "short write"); 219 nleft -= nwant; 220 iorequest.piod_offs += ngot; 221 } 222 php++; 223 } 224 sbuf_delete(sb); 225 freemap(map); 226 } 227 228 /* 229 * A callback for each_writable_segment() to write out the segment's 230 * program header entry. 231 */ 232 static void 233 cb_put_phdr(vm_map_entry_t entry, void *closure) 234 { 235 struct phdr_closure *phc = (struct phdr_closure *)closure; 236 Elf_Phdr *phdr = phc->phdr; 237 238 phc->offset = round_page(phc->offset); 239 240 phdr->p_type = PT_LOAD; 241 phdr->p_offset = phc->offset; 242 phdr->p_vaddr = entry->start; 243 phdr->p_paddr = 0; 244 phdr->p_filesz = phdr->p_memsz = entry->end - entry->start; 245 phdr->p_align = PAGE_SIZE; 246 phdr->p_flags = 0; 247 if (entry->protection & VM_PROT_READ) 248 phdr->p_flags |= PF_R; 249 if (entry->protection & VM_PROT_WRITE) 250 phdr->p_flags |= PF_W; 251 if (entry->protection & VM_PROT_EXECUTE) 252 phdr->p_flags |= PF_X; 253 254 phc->offset += phdr->p_filesz; 255 phc->phdr++; 256 } 257 258 /* 259 * A callback for each_writable_segment() to gather information about 260 * the number of segments and their total size. 261 */ 262 static void 263 cb_size_segment(vm_map_entry_t entry, void *closure) 264 { 265 struct sseg_closure *ssc = (struct sseg_closure *)closure; 266 267 ssc->count++; 268 ssc->size += entry->end - entry->start; 269 } 270 271 /* 272 * For each segment in the given memory map, call the given function 273 * with a pointer to the map entry and some arbitrary caller-supplied 274 * data. 275 */ 276 static void 277 each_writable_segment(vm_map_entry_t map, segment_callback func, void *closure) 278 { 279 vm_map_entry_t entry; 280 281 for (entry = map; entry != NULL; entry = entry->next) 282 (*func)(entry, closure); 283 } 284 285 static void 286 elf_putnotes(pid_t pid, struct sbuf *sb, size_t *sizep) 287 { 288 lwpid_t *tids; 289 size_t threads, old_len; 290 ssize_t size; 291 int i; 292 293 errno = 0; 294 threads = ptrace(PT_GETNUMLWPS, pid, NULL, 0); 295 if (errno) 296 err(1, "PT_GETNUMLWPS"); 297 tids = malloc(threads * sizeof(*tids)); 298 if (tids == NULL) 299 errx(1, "out of memory"); 300 errno = 0; 301 ptrace(PT_GETLWPLIST, pid, (void *)tids, threads); 302 if (errno) 303 err(1, "PT_GETLWPLIST"); 304 305 sbuf_start_section(sb, &old_len); 306 elf_putnote(NT_PRPSINFO, elf_note_prpsinfo, &pid, sb); 307 308 for (i = 0; i < threads; ++i) { 309 elf_putnote(NT_PRSTATUS, elf_note_prstatus, tids + i, sb); 310 elf_putnote(NT_FPREGSET, elf_note_fpregset, tids + i, sb); 311 elf_putnote(NT_THRMISC, elf_note_thrmisc, tids + i, sb); 312 } 313 314 elf_putnote(NT_PROCSTAT_PROC, elf_note_procstat_proc, &pid, sb); 315 elf_putnote(NT_PROCSTAT_FILES, elf_note_procstat_files, &pid, sb); 316 elf_putnote(NT_PROCSTAT_VMMAP, elf_note_procstat_vmmap, &pid, sb); 317 elf_putnote(NT_PROCSTAT_GROUPS, elf_note_procstat_groups, &pid, sb); 318 elf_putnote(NT_PROCSTAT_UMASK, elf_note_procstat_umask, &pid, sb); 319 elf_putnote(NT_PROCSTAT_RLIMIT, elf_note_procstat_rlimit, &pid, sb); 320 elf_putnote(NT_PROCSTAT_OSREL, elf_note_procstat_osrel, &pid, sb); 321 elf_putnote(NT_PROCSTAT_PSSTRINGS, elf_note_procstat_psstrings, &pid, 322 sb); 323 elf_putnote(NT_PROCSTAT_AUXV, elf_note_procstat_auxv, &pid, sb); 324 325 size = sbuf_end_section(sb, old_len, 1, 0); 326 if (size == -1) 327 err(1, "sbuf_end_section"); 328 free(tids); 329 *sizep = size; 330 } 331 332 /* 333 * Emit one note section to sbuf. 334 */ 335 static void 336 elf_putnote(int type, notefunc_t notefunc, void *arg, struct sbuf *sb) 337 { 338 Elf_Note note; 339 size_t descsz; 340 ssize_t old_len; 341 void *desc; 342 343 desc = notefunc(arg, &descsz); 344 note.n_namesz = 8; /* strlen("FreeBSD") + 1 */ 345 note.n_descsz = descsz; 346 note.n_type = type; 347 348 sbuf_bcat(sb, ¬e, sizeof(note)); 349 sbuf_start_section(sb, &old_len); 350 sbuf_bcat(sb, "FreeBSD", note.n_namesz); 351 sbuf_end_section(sb, old_len, sizeof(Elf32_Size), 0); 352 if (descsz == 0) 353 return; 354 sbuf_start_section(sb, &old_len); 355 sbuf_bcat(sb, desc, descsz); 356 sbuf_end_section(sb, old_len, sizeof(Elf32_Size), 0); 357 free(desc); 358 } 359 360 /* 361 * Generate the ELF coredump header. 362 */ 363 static void 364 elf_puthdr(pid_t pid, vm_map_entry_t map, void *hdr, size_t hdrsize, 365 size_t notesz, size_t segoff, int numsegs) 366 { 367 Elf_Ehdr *ehdr; 368 Elf_Phdr *phdr; 369 struct phdr_closure phc; 370 371 ehdr = (Elf_Ehdr *)hdr; 372 phdr = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)); 373 374 ehdr->e_ident[EI_MAG0] = ELFMAG0; 375 ehdr->e_ident[EI_MAG1] = ELFMAG1; 376 ehdr->e_ident[EI_MAG2] = ELFMAG2; 377 ehdr->e_ident[EI_MAG3] = ELFMAG3; 378 ehdr->e_ident[EI_CLASS] = ELF_CLASS; 379 ehdr->e_ident[EI_DATA] = ELF_DATA; 380 ehdr->e_ident[EI_VERSION] = EV_CURRENT; 381 ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; 382 ehdr->e_ident[EI_ABIVERSION] = 0; 383 ehdr->e_ident[EI_PAD] = 0; 384 ehdr->e_type = ET_CORE; 385 ehdr->e_machine = ELF_ARCH; 386 ehdr->e_version = EV_CURRENT; 387 ehdr->e_entry = 0; 388 ehdr->e_phoff = sizeof(Elf_Ehdr); 389 ehdr->e_flags = 0; 390 ehdr->e_ehsize = sizeof(Elf_Ehdr); 391 ehdr->e_phentsize = sizeof(Elf_Phdr); 392 ehdr->e_phnum = numsegs + 1; 393 ehdr->e_shentsize = sizeof(Elf_Shdr); 394 ehdr->e_shnum = 0; 395 ehdr->e_shstrndx = SHN_UNDEF; 396 397 /* 398 * Fill in the program header entries. 399 */ 400 401 /* The note segement. */ 402 phdr->p_type = PT_NOTE; 403 phdr->p_offset = hdrsize; 404 phdr->p_vaddr = 0; 405 phdr->p_paddr = 0; 406 phdr->p_filesz = notesz; 407 phdr->p_memsz = 0; 408 phdr->p_flags = PF_R; 409 phdr->p_align = sizeof(Elf32_Size); 410 phdr++; 411 412 /* All the writable segments from the program. */ 413 phc.phdr = phdr; 414 phc.offset = segoff; 415 each_writable_segment(map, cb_put_phdr, &phc); 416 } 417 418 /* 419 * Free the memory map. 420 */ 421 static void 422 freemap(vm_map_entry_t map) 423 { 424 425 while (map != NULL) { 426 vm_map_entry_t next = map->next; 427 free(map); 428 map = next; 429 } 430 } 431 432 /* 433 * Read the process's memory map using kinfo_getvmmap(), and return a list of 434 * VM map entries. Only the non-device read/writable segments are 435 * returned. The map entries in the list aren't fully filled in; only 436 * the items we need are present. 437 */ 438 static vm_map_entry_t 439 readmap(pid_t pid) 440 { 441 vm_map_entry_t ent, *linkp, map; 442 struct kinfo_vmentry *vmentl, *kve; 443 int i, nitems; 444 445 vmentl = kinfo_getvmmap(pid, &nitems); 446 if (vmentl == NULL) 447 err(1, "cannot retrieve mappings for %u process", pid); 448 449 map = NULL; 450 linkp = ↦ 451 for (i = 0; i < nitems; i++) { 452 kve = &vmentl[i]; 453 454 /* 455 * Ignore 'malformed' segments or ones representing memory 456 * mapping with MAP_NOCORE on. 457 * If the 'full' support is disabled, just dump the most 458 * meaningful data segments. 459 */ 460 if ((kve->kve_protection & KVME_PROT_READ) == 0 || 461 (kve->kve_flags & KVME_FLAG_NOCOREDUMP) != 0 || 462 kve->kve_type == KVME_TYPE_DEAD || 463 kve->kve_type == KVME_TYPE_UNKNOWN || 464 ((pflags & PFLAGS_FULL) == 0 && 465 kve->kve_type != KVME_TYPE_DEFAULT && 466 kve->kve_type != KVME_TYPE_VNODE && 467 kve->kve_type != KVME_TYPE_SWAP)) 468 continue; 469 470 ent = calloc(1, sizeof(*ent)); 471 if (ent == NULL) 472 errx(1, "out of memory"); 473 ent->start = (vm_offset_t)kve->kve_start; 474 ent->end = (vm_offset_t)kve->kve_end; 475 ent->protection = VM_PROT_READ | VM_PROT_WRITE; 476 if ((kve->kve_protection & KVME_PROT_EXEC) != 0) 477 ent->protection |= VM_PROT_EXECUTE; 478 479 *linkp = ent; 480 linkp = &ent->next; 481 } 482 free(vmentl); 483 return (map); 484 } 485 486 /* 487 * Miscellaneous note out functions. 488 */ 489 490 static void * 491 elf_note_prpsinfo(void *arg, size_t *sizep) 492 { 493 pid_t pid; 494 prpsinfo_t *psinfo; 495 struct kinfo_proc kip; 496 size_t len; 497 int name[4]; 498 499 pid = *(pid_t *)arg; 500 psinfo = calloc(1, sizeof(*psinfo)); 501 if (psinfo == NULL) 502 errx(1, "out of memory"); 503 psinfo->pr_version = PRPSINFO_VERSION; 504 psinfo->pr_psinfosz = sizeof(prpsinfo_t); 505 506 name[0] = CTL_KERN; 507 name[1] = KERN_PROC; 508 name[2] = KERN_PROC_PID; 509 name[3] = pid; 510 len = sizeof(kip); 511 if (sysctl(name, 4, &kip, &len, NULL, 0) == -1) 512 err(1, "kern.proc.pid.%u", pid); 513 if (kip.ki_pid != pid) 514 err(1, "kern.proc.pid.%u", pid); 515 strncpy(psinfo->pr_fname, kip.ki_comm, MAXCOMLEN); 516 strncpy(psinfo->pr_psargs, psinfo->pr_fname, PRARGSZ); 517 518 *sizep = sizeof(*psinfo); 519 return (psinfo); 520 } 521 522 static void * 523 elf_note_prstatus(void *arg, size_t *sizep) 524 { 525 lwpid_t tid; 526 prstatus_t *status; 527 528 tid = *(lwpid_t *)arg; 529 status = calloc(1, sizeof(*status)); 530 if (status == NULL) 531 errx(1, "out of memory"); 532 status->pr_version = PRSTATUS_VERSION; 533 status->pr_statussz = sizeof(prstatus_t); 534 status->pr_gregsetsz = sizeof(gregset_t); 535 status->pr_fpregsetsz = sizeof(fpregset_t); 536 status->pr_osreldate = __FreeBSD_version; 537 status->pr_pid = tid; 538 ptrace(PT_GETREGS, tid, (void *)&status->pr_reg, 0); 539 540 *sizep = sizeof(*status); 541 return (status); 542 } 543 544 static void * 545 elf_note_fpregset(void *arg, size_t *sizep) 546 { 547 lwpid_t tid; 548 prfpregset_t *fpregset; 549 550 tid = *(lwpid_t *)arg; 551 fpregset = calloc(1, sizeof(*fpregset)); 552 if (fpregset == NULL) 553 errx(1, "out of memory"); 554 ptrace(PT_GETFPREGS, tid, (void *)fpregset, 0); 555 556 *sizep = sizeof(*fpregset); 557 return (fpregset); 558 } 559 560 static void * 561 elf_note_thrmisc(void *arg, size_t *sizep) 562 { 563 lwpid_t tid; 564 struct ptrace_lwpinfo lwpinfo; 565 thrmisc_t *thrmisc; 566 567 tid = *(lwpid_t *)arg; 568 thrmisc = calloc(1, sizeof(*thrmisc)); 569 if (thrmisc == NULL) 570 errx(1, "out of memory"); 571 ptrace(PT_LWPINFO, tid, (void *)&lwpinfo, 572 sizeof(lwpinfo)); 573 memset(&thrmisc->_pad, 0, sizeof(thrmisc->_pad)); 574 strcpy(thrmisc->pr_tname, lwpinfo.pl_tdname); 575 576 *sizep = sizeof(*thrmisc); 577 return (thrmisc); 578 } 579 580 static void * 581 procstat_sysctl(void *arg, int what, size_t structsz, size_t *sizep) 582 { 583 size_t len, oldlen; 584 pid_t pid; 585 int name[4], structsize; 586 void *buf, *p; 587 588 pid = *(pid_t *)arg; 589 structsize = structsz; 590 name[0] = CTL_KERN; 591 name[1] = KERN_PROC; 592 name[2] = what; 593 name[3] = pid; 594 len = 0; 595 if (sysctl(name, 4, NULL, &len, NULL, 0) == -1) 596 err(1, "kern.proc.%d.%u", what, pid); 597 buf = calloc(1, sizeof(structsize) + len * 4 / 3); 598 if (buf == NULL) 599 errx(1, "out of memory"); 600 bcopy(&structsize, buf, sizeof(structsize)); 601 p = (char *)buf + sizeof(structsize); 602 if (sysctl(name, 4, p, &len, NULL, 0) == -1) 603 err(1, "kern.proc.%d.%u", what, pid); 604 605 *sizep = sizeof(structsize) + len; 606 return (buf); 607 } 608 609 static void * 610 elf_note_procstat_proc(void *arg, size_t *sizep) 611 { 612 613 return (procstat_sysctl(arg, KERN_PROC_PID | KERN_PROC_INC_THREAD, 614 sizeof(struct kinfo_proc), sizep)); 615 } 616 617 static void * 618 elf_note_procstat_files(void *arg, size_t *sizep) 619 { 620 621 return (procstat_sysctl(arg, KERN_PROC_FILEDESC, 622 sizeof(struct kinfo_file), sizep)); 623 } 624 625 static void * 626 elf_note_procstat_vmmap(void *arg, size_t *sizep) 627 { 628 629 return (procstat_sysctl(arg, KERN_PROC_VMMAP, 630 sizeof(struct kinfo_vmentry), sizep)); 631 } 632 633 static void * 634 elf_note_procstat_groups(void *arg, size_t *sizep) 635 { 636 637 return (procstat_sysctl(arg, KERN_PROC_GROUPS, sizeof(gid_t), sizep)); 638 } 639 640 static void * 641 elf_note_procstat_umask(void *arg, size_t *sizep) 642 { 643 644 return (procstat_sysctl(arg, KERN_PROC_UMASK, sizeof(u_short), sizep)); 645 } 646 647 static void * 648 elf_note_procstat_osrel(void *arg, size_t *sizep) 649 { 650 651 return (procstat_sysctl(arg, KERN_PROC_OSREL, sizeof(int), sizep)); 652 } 653 654 static void * 655 elf_note_procstat_psstrings(void *arg, size_t *sizep) 656 { 657 658 return (procstat_sysctl(arg, KERN_PROC_PS_STRINGS, 659 sizeof(vm_offset_t), sizep)); 660 } 661 662 static void * 663 elf_note_procstat_auxv(void *arg, size_t *sizep) 664 { 665 666 return (procstat_sysctl(arg, KERN_PROC_AUXV, 667 sizeof(Elf_Auxinfo), sizep)); 668 } 669 670 static void * 671 elf_note_procstat_rlimit(void *arg, size_t *sizep) 672 { 673 pid_t pid; 674 size_t len; 675 int i, name[5], structsize; 676 void *buf, *p; 677 678 pid = *(pid_t *)arg; 679 structsize = sizeof(struct rlimit) * RLIM_NLIMITS; 680 buf = calloc(1, sizeof(structsize) + structsize); 681 if (buf == NULL) 682 errx(1, "out of memory"); 683 bcopy(&structsize, buf, sizeof(structsize)); 684 p = (char *)buf + sizeof(structsize); 685 name[0] = CTL_KERN; 686 name[1] = KERN_PROC; 687 name[2] = KERN_PROC_RLIMIT; 688 name[3] = pid; 689 len = sizeof(struct rlimit); 690 for (i = 0; i < RLIM_NLIMITS; i++) { 691 name[4] = i; 692 if (sysctl(name, 5, p, &len, NULL, 0) == -1) 693 err(1, "kern.proc.rlimit.%u", pid); 694 if (len != sizeof(struct rlimit)) 695 errx(1, "kern.proc.rlimit.%u: short read", pid); 696 p += len; 697 } 698 699 *sizep = sizeof(structsize) + structsize; 700 return (buf); 701 } 702 703 struct dumpers elfdump = { elf_ident, elf_coredump }; 704 TEXT_SET(dumpset, elfdump); 705