Print this page
3946 ::gcore
Reviewed by: Adam Leventhal <ahl@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>


   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2013, Joyent, Inc. All rights reserved.

  25  */
  26 
  27 #include <assert.h>
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <stddef.h>
  31 #include <unistd.h>
  32 #include <ctype.h>
  33 #include <fcntl.h>
  34 #include <string.h>
  35 #include <strings.h>
  36 #include <memory.h>
  37 #include <errno.h>
  38 #include <dirent.h>
  39 #include <signal.h>
  40 #include <limits.h>
  41 #include <libgen.h>
  42 #include <sys/types.h>
  43 #include <sys/stat.h>
  44 #include <sys/systeminfo.h>
  45 #include <sys/sysmacros.h>
  46 
  47 #include "libproc.h"
  48 #include "Pcontrol.h"
  49 #include "Putil.h"
  50 #include "Psymtab_machelf.h"
  51 
  52 static file_info_t *build_map_symtab(struct ps_prochandle *, map_info_t *);
  53 static map_info_t *exec_map(struct ps_prochandle *);
  54 static map_info_t *object_to_map(struct ps_prochandle *, Lmid_t, const char *);
  55 static map_info_t *object_name_to_map(struct ps_prochandle *,
  56         Lmid_t, const char *);
  57 static GElf_Sym *sym_by_name(sym_tbl_t *, const char *, GElf_Sym *, uint_t *);
  58 static int read_ehdr32(struct ps_prochandle *, Elf32_Ehdr *, uint_t *,
  59     uintptr_t);
  60 #ifdef _LP64
  61 static int read_ehdr64(struct ps_prochandle *, Elf64_Ehdr *, uint_t *,
  62     uintptr_t);
  63 #endif
  64 


 417 static void
 418 load_static_maps(struct ps_prochandle *P)
 419 {
 420         map_info_t *mptr;
 421 
 422         /*
 423          * Construct the map for the a.out.
 424          */
 425         if ((mptr = object_name_to_map(P, PR_LMID_EVERY, PR_OBJ_EXEC)) != NULL)
 426                 map_set(P, mptr, "a.out");
 427 
 428         /*
 429          * If the dynamic linker exists for this process,
 430          * construct the map for it.
 431          */
 432         if (Pgetauxval(P, AT_BASE) != -1L &&
 433             (mptr = object_name_to_map(P, PR_LMID_EVERY, PR_OBJ_LDSO)) != NULL)
 434                 map_set(P, mptr, "ld.so.1");
 435 }
 436 






 437 /*
 438  * Go through all the address space mappings, validating or updating
 439  * the information already gathered, or gathering new information.
 440  *
 441  * This function is only called when we suspect that the mappings have changed
 442  * because this is the first time we're calling it or because of rtld activity.
 443  */
 444 void
 445 Pupdate_maps(struct ps_prochandle *P)
 446 {
 447         char mapfile[PATH_MAX];
 448         int mapfd;
 449         struct stat statb;
 450         prmap_t *Pmap = NULL;
 451         prmap_t *pmap;
 452         ssize_t nmap;
 453         int i;
 454         uint_t oldmapcount;
 455         map_info_t *newmap, *newp;
 456         map_info_t *mptr;
 457 
 458         if (P->info_valid || P->state == PS_UNDEAD)
 459                 return;
 460 
 461         Preadauxvec(P);
 462 
 463         (void) snprintf(mapfile, sizeof (mapfile), "%s/%d/map",
 464             procfs_path, (int)P->pid);
 465         if ((mapfd = open(mapfile, O_RDONLY)) < 0 ||
 466             fstat(mapfd, &statb) != 0 ||
 467             statb.st_size < sizeof (prmap_t) ||
 468             (Pmap = malloc(statb.st_size)) == NULL ||
 469             (nmap = pread(mapfd, Pmap, statb.st_size, 0L)) <= 0 ||
 470             (nmap /= sizeof (prmap_t)) == 0) {
 471                 if (Pmap != NULL)
 472                         free(Pmap);
 473                 if (mapfd >= 0)
 474                         (void) close(mapfd);
 475                 Preset_maps(P); /* utter failure; destroy tables */
 476                 return;
 477         }
 478         (void) close(mapfd);
 479 
 480         if ((newmap = calloc(1, nmap * sizeof (map_info_t))) == NULL)
 481                 return;
 482 
 483         /*
 484          * We try to merge any file information we may have for existing
 485          * mappings, to avoid having to rebuild the file info.
 486          */
 487         mptr = P->mappings;
 488         pmap = Pmap;
 489         newp = newmap;
 490         oldmapcount = P->map_count;
 491         for (i = 0; i < nmap; i++, pmap++, newp++) {
 492 
 493                 if (oldmapcount == 0) {
 494                         /*
 495                          * We've exhausted all the old mappings.  Every new
 496                          * mapping should be added.
 497                          */
 498                         newp->map_pmap = *pmap;


 831 {
 832         map_info_t *mptr;
 833         file_info_t *fptr;
 834 
 835         if (name == PR_OBJ_EVERY)
 836                 return (NULL);
 837 
 838         if ((mptr = object_name_to_map(P, lmid, name)) == NULL ||
 839             (fptr = mptr->map_file) == NULL)
 840                 return (NULL);
 841 
 842         return (Pbuild_file_ctf(P, fptr));
 843 }
 844 
 845 ctf_file_t *
 846 Pname_to_ctf(struct ps_prochandle *P, const char *name)
 847 {
 848         return (Plmid_to_ctf(P, PR_LMID_EVERY, name));
 849 }
 850 
 851 /*
 852  * If we're not a core file, re-read the /proc/<pid>/auxv file and store
 853  * its contents in P->auxv.  In the case of a core file, we either
 854  * initialized P->auxv in Pcore() from the NT_AUXV, or we don't have an
 855  * auxv because the note was missing.
 856  */
 857 void
 858 Preadauxvec(struct ps_prochandle *P)
 859 {
 860         char auxfile[64];
 861         struct stat statb;
 862         ssize_t naux;
 863         int fd;
 864 
 865         if (P->state == PS_DEAD)
 866                 return; /* Already read during Pgrab_core() */
 867         if (P->state == PS_IDLE)
 868                 return; /* No aux vec for Pgrab_file() */
 869 
 870         if (P->auxv != NULL) {
 871                 free(P->auxv);
 872                 P->auxv = NULL;
 873                 P->nauxv = 0;
 874         }
 875 
 876         (void) snprintf(auxfile, sizeof (auxfile), "%s/%d/auxv",
 877             procfs_path, (int)P->pid);
 878         if ((fd = open(auxfile, O_RDONLY)) < 0)
 879                 return;
 880 
 881         if (fstat(fd, &statb) == 0 &&
 882             statb.st_size >= sizeof (auxv_t) &&
 883             (P->auxv = malloc(statb.st_size + sizeof (auxv_t))) != NULL) {
 884                 if ((naux = read(fd, P->auxv, statb.st_size)) < 0 ||
 885                     (naux /= sizeof (auxv_t)) < 1) {
 886                         free(P->auxv);
 887                         P->auxv = NULL;
 888                 } else {
 889                         P->auxv[naux].a_type = AT_NULL;
 890                         P->auxv[naux].a_un.a_val = 0L;
 891                         P->nauxv = (int)naux;
 892                 }
 893         }
 894 
 895         (void) close(fd);
 896 }
 897 
 898 /*
 899  * Return a requested element from the process's aux vector.
 900  * Return -1 on failure (this is adequate for our purposes).
 901  */
 902 long
 903 Pgetauxval(struct ps_prochandle *P, int type)
 904 {
 905         auxv_t *auxv;
 906 
 907         if (P->auxv == NULL)
 908                 Preadauxvec(P);
 909 
 910         if (P->auxv == NULL)
 911                 return (-1);
 912 
 913         for (auxv = P->auxv; auxv->a_type != AT_NULL; auxv++) {
 914                 if (auxv->a_type == type)
 915                         return (auxv->a_un.a_val);


1666                 if (fptr->file_rname != NULL)
1667                         name = fptr->file_rname;
1668                 else if (fptr->file_lname != NULL)
1669                         name = fptr->file_lname;
1670                 else
1671                         name = fptr->file_pname;
1672                 (void) strlcpy(objectfile, name, sizeof (objectfile));
1673         } else {
1674                 (void) snprintf(objectfile, sizeof (objectfile),
1675                     "%s/%d/object/%s",
1676                     procfs_path, (int)P->pid, fptr->file_pname);
1677         }
1678 
1679         /*
1680          * Open the object file, create the elf file, and then get the elf
1681          * header and .shstrtab data buffer so we can process sections by
1682          * name. If anything goes wrong try to fake up an elf file from
1683          * the in-core elf image.
1684          */
1685 
1686         if (_libproc_incore_elf) {
1687                 dprintf("Pbuild_file_symtab: using in-core data for: %s\n",
1688                     fptr->file_pname);
1689 
1690                 if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) ==
1691                     NULL)
1692                         return;
1693 
1694         } else if ((fptr->file_fd = open(objectfile, O_RDONLY)) < 0) {
1695                 dprintf("Pbuild_file_symtab: failed to open %s: %s\n",
1696                     objectfile, strerror(errno));
1697 
1698                 if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) ==
1699                     NULL)
1700                         return;
1701 
1702         } else if ((elf = elf_begin(fptr->file_fd, ELF_C_READ, NULL)) == NULL ||
1703             elf_kind(elf) != ELF_K_ELF ||
1704             gelf_getehdr(elf, &ehdr) == NULL ||
1705             elf_getshdrnum(elf, &nshdrs) == -1 ||
1706             elf_getshdrstrndx(elf, &shstrndx) == -1 ||


2952             PRO_NATURAL, (proc_xsym_f *)func, cd));
2953 }
2954 
2955 int
2956 Psymbol_iter_by_addr(struct ps_prochandle *P,
2957     const char *object_name, int which, int mask, proc_sym_f *func, void *cd)
2958 {
2959         return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask,
2960             PRO_BYADDR, (proc_xsym_f *)func, cd));
2961 }
2962 
2963 int
2964 Psymbol_iter_by_name(struct ps_prochandle *P,
2965     const char *object_name, int which, int mask, proc_sym_f *func, void *cd)
2966 {
2967         return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask,
2968             PRO_BYNAME, (proc_xsym_f *)func, cd));
2969 }
2970 
2971 /*
2972  * Get the platform string from the core file if we have it;
2973  * just perform the system call for the caller if this is a live process.
2974  */
2975 char *
2976 Pplatform(struct ps_prochandle *P, char *s, size_t n)
2977 {
2978         if (P->state == PS_IDLE) {
2979                 errno = ENODATA;
2980                 return (NULL);
2981         }
2982 
2983         if (P->state == PS_DEAD) {
2984                 if (P->core->core_platform == NULL) {
2985                         errno = ENODATA;
2986                         return (NULL);
2987                 }
2988                 (void) strncpy(s, P->core->core_platform, n - 1);
2989                 s[n - 1] = '\0';
2990 
2991         } else if (sysinfo(SI_PLATFORM, s, n) == -1)
2992                 return (NULL);
2993 
2994         return (s);
2995 }
2996 
2997 /*
2998  * Get the uname(2) information from the core file if we have it;
2999  * just perform the system call for the caller if this is a live process.
3000  */
3001 int
3002 Puname(struct ps_prochandle *P, struct utsname *u)
3003 {
3004         if (P->state == PS_IDLE) {
3005                 errno = ENODATA;
3006                 return (-1);
3007         }
3008 
3009         if (P->state == PS_DEAD) {
3010                 if (P->core->core_uts == NULL) {
3011                         errno = ENODATA;
3012                         return (-1);
3013                 }
3014                 (void) memcpy(u, P->core->core_uts, sizeof (struct utsname));
3015                 return (0);
3016         }
3017         return (uname(u));
3018 }
3019 
3020 /*
3021  * Called from Pcreate(), Pgrab(), and Pfgrab_core() to initialize
3022  * the symbol table heads in the new ps_prochandle.
3023  */
3024 void
3025 Pinitsym(struct ps_prochandle *P)
3026 {
3027         P->num_files = 0;
3028         list_link(&P->file_head, NULL);
3029 }
3030 
3031 /*
3032  * Called from Prelease() to destroy the symbol tables.
3033  * Must be called by the client after an exec() in the victim process.
3034  */
3035 void
3036 Preset_maps(struct ps_prochandle *P)
3037 {




   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  25  * Copyright (c) 2013 by Delphix. All rights reserved.
  26  */
  27 
  28 #include <assert.h>
  29 #include <stdio.h>
  30 #include <stdlib.h>
  31 #include <stddef.h>
  32 #include <unistd.h>
  33 #include <ctype.h>
  34 #include <fcntl.h>
  35 #include <string.h>
  36 #include <strings.h>
  37 #include <memory.h>
  38 #include <errno.h>
  39 #include <dirent.h>
  40 #include <signal.h>
  41 #include <limits.h>
  42 #include <libgen.h>
  43 #include <sys/types.h>
  44 #include <sys/stat.h>

  45 #include <sys/sysmacros.h>
  46 
  47 #include "libproc.h"
  48 #include "Pcontrol.h"
  49 #include "Putil.h"
  50 #include "Psymtab_machelf.h"
  51 
  52 static file_info_t *build_map_symtab(struct ps_prochandle *, map_info_t *);
  53 static map_info_t *exec_map(struct ps_prochandle *);
  54 static map_info_t *object_to_map(struct ps_prochandle *, Lmid_t, const char *);
  55 static map_info_t *object_name_to_map(struct ps_prochandle *,
  56         Lmid_t, const char *);
  57 static GElf_Sym *sym_by_name(sym_tbl_t *, const char *, GElf_Sym *, uint_t *);
  58 static int read_ehdr32(struct ps_prochandle *, Elf32_Ehdr *, uint_t *,
  59     uintptr_t);
  60 #ifdef _LP64
  61 static int read_ehdr64(struct ps_prochandle *, Elf64_Ehdr *, uint_t *,
  62     uintptr_t);
  63 #endif
  64 


 417 static void
 418 load_static_maps(struct ps_prochandle *P)
 419 {
 420         map_info_t *mptr;
 421 
 422         /*
 423          * Construct the map for the a.out.
 424          */
 425         if ((mptr = object_name_to_map(P, PR_LMID_EVERY, PR_OBJ_EXEC)) != NULL)
 426                 map_set(P, mptr, "a.out");
 427 
 428         /*
 429          * If the dynamic linker exists for this process,
 430          * construct the map for it.
 431          */
 432         if (Pgetauxval(P, AT_BASE) != -1L &&
 433             (mptr = object_name_to_map(P, PR_LMID_EVERY, PR_OBJ_LDSO)) != NULL)
 434                 map_set(P, mptr, "ld.so.1");
 435 }
 436 
 437 int
 438 Preadmaps(struct ps_prochandle *P, prmap_t **Pmapp, ssize_t *nmapp)
 439 {
 440         return (P->ops.pop_read_maps(P, Pmapp, nmapp, P->data));
 441 }
 442 
 443 /*
 444  * Go through all the address space mappings, validating or updating
 445  * the information already gathered, or gathering new information.
 446  *
 447  * This function is only called when we suspect that the mappings have changed
 448  * because this is the first time we're calling it or because of rtld activity.
 449  */
 450 void
 451 Pupdate_maps(struct ps_prochandle *P)
 452 {



 453         prmap_t *Pmap = NULL;
 454         prmap_t *pmap;
 455         ssize_t nmap;
 456         int i;
 457         uint_t oldmapcount;
 458         map_info_t *newmap, *newp;
 459         map_info_t *mptr;
 460 
 461         if (P->info_valid || P->state == PS_UNDEAD)
 462                 return;
 463 
 464         Preadauxvec(P);
 465 
 466         if (Preadmaps(P, &Pmap, &nmap) != 0)












 467                 return;


 468 
 469         if ((newmap = calloc(1, nmap * sizeof (map_info_t))) == NULL)
 470                 return;
 471 
 472         /*
 473          * We try to merge any file information we may have for existing
 474          * mappings, to avoid having to rebuild the file info.
 475          */
 476         mptr = P->mappings;
 477         pmap = Pmap;
 478         newp = newmap;
 479         oldmapcount = P->map_count;
 480         for (i = 0; i < nmap; i++, pmap++, newp++) {
 481 
 482                 if (oldmapcount == 0) {
 483                         /*
 484                          * We've exhausted all the old mappings.  Every new
 485                          * mapping should be added.
 486                          */
 487                         newp->map_pmap = *pmap;


 820 {
 821         map_info_t *mptr;
 822         file_info_t *fptr;
 823 
 824         if (name == PR_OBJ_EVERY)
 825                 return (NULL);
 826 
 827         if ((mptr = object_name_to_map(P, lmid, name)) == NULL ||
 828             (fptr = mptr->map_file) == NULL)
 829                 return (NULL);
 830 
 831         return (Pbuild_file_ctf(P, fptr));
 832 }
 833 
 834 ctf_file_t *
 835 Pname_to_ctf(struct ps_prochandle *P, const char *name)
 836 {
 837         return (Plmid_to_ctf(P, PR_LMID_EVERY, name));
 838 }
 839 






 840 void
 841 Preadauxvec(struct ps_prochandle *P)
 842 {










 843         if (P->auxv != NULL) {
 844                 free(P->auxv);
 845                 P->auxv = NULL;
 846                 P->nauxv = 0;
 847         }
 848 
 849         P->ops.pop_read_aux(P, &P->auxv, &P->nauxv, P->data);



















 850 }
 851 
 852 /*
 853  * Return a requested element from the process's aux vector.
 854  * Return -1 on failure (this is adequate for our purposes).
 855  */
 856 long
 857 Pgetauxval(struct ps_prochandle *P, int type)
 858 {
 859         auxv_t *auxv;
 860 
 861         if (P->auxv == NULL)
 862                 Preadauxvec(P);
 863 
 864         if (P->auxv == NULL)
 865                 return (-1);
 866 
 867         for (auxv = P->auxv; auxv->a_type != AT_NULL; auxv++) {
 868                 if (auxv->a_type == type)
 869                         return (auxv->a_un.a_val);


1620                 if (fptr->file_rname != NULL)
1621                         name = fptr->file_rname;
1622                 else if (fptr->file_lname != NULL)
1623                         name = fptr->file_lname;
1624                 else
1625                         name = fptr->file_pname;
1626                 (void) strlcpy(objectfile, name, sizeof (objectfile));
1627         } else {
1628                 (void) snprintf(objectfile, sizeof (objectfile),
1629                     "%s/%d/object/%s",
1630                     procfs_path, (int)P->pid, fptr->file_pname);
1631         }
1632 
1633         /*
1634          * Open the object file, create the elf file, and then get the elf
1635          * header and .shstrtab data buffer so we can process sections by
1636          * name. If anything goes wrong try to fake up an elf file from
1637          * the in-core elf image.
1638          */
1639 
1640         if (_libproc_incore_elf || (P->flags & INCORE)) {
1641                 dprintf("Pbuild_file_symtab: using in-core data for: %s\n",
1642                     fptr->file_pname);
1643 
1644                 if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) ==
1645                     NULL)
1646                         return;
1647 
1648         } else if ((fptr->file_fd = open(objectfile, O_RDONLY)) < 0) {
1649                 dprintf("Pbuild_file_symtab: failed to open %s: %s\n",
1650                     objectfile, strerror(errno));
1651 
1652                 if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) ==
1653                     NULL)
1654                         return;
1655 
1656         } else if ((elf = elf_begin(fptr->file_fd, ELF_C_READ, NULL)) == NULL ||
1657             elf_kind(elf) != ELF_K_ELF ||
1658             gelf_getehdr(elf, &ehdr) == NULL ||
1659             elf_getshdrnum(elf, &nshdrs) == -1 ||
1660             elf_getshdrstrndx(elf, &shstrndx) == -1 ||


2906             PRO_NATURAL, (proc_xsym_f *)func, cd));
2907 }
2908 
2909 int
2910 Psymbol_iter_by_addr(struct ps_prochandle *P,
2911     const char *object_name, int which, int mask, proc_sym_f *func, void *cd)
2912 {
2913         return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask,
2914             PRO_BYADDR, (proc_xsym_f *)func, cd));
2915 }
2916 
2917 int
2918 Psymbol_iter_by_name(struct ps_prochandle *P,
2919     const char *object_name, int which, int mask, proc_sym_f *func, void *cd)
2920 {
2921         return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask,
2922             PRO_BYNAME, (proc_xsym_f *)func, cd));
2923 }
2924 
2925 /*
2926  * Get the platform string.

2927  */
2928 char *
2929 Pplatform(struct ps_prochandle *P, char *s, size_t n)
2930 {
2931         return (P->ops.pop_platform(P, s, n, P->data));
















2932 }
2933 
2934 /*
2935  * Get the uname(2) information.

2936  */
2937 int
2938 Puname(struct ps_prochandle *P, struct utsname *u)
2939 {
2940         return (P->ops.pop_uname(P, u, P->data));













2941 }
2942 
2943 /*
2944  * Called from Pcreate(), Pgrab(), and Pfgrab_core() to initialize
2945  * the symbol table heads in the new ps_prochandle.
2946  */
2947 void
2948 Pinitsym(struct ps_prochandle *P)
2949 {
2950         P->num_files = 0;
2951         list_link(&P->file_head, NULL);
2952 }
2953 
2954 /*
2955  * Called from Prelease() to destroy the symbol tables.
2956  * Must be called by the client after an exec() in the victim process.
2957  */
2958 void
2959 Preset_maps(struct ps_prochandle *P)
2960 {