Print this page
5383 5234 breaks build on sparc


   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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 /*
  26  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
  27  * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  28  * Copyright (c) 2013 by Delphix. All rights reserved.

  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/utsname.h>
  33 #include <sys/sysmacros.h>
  34 #include <sys/proc.h>
  35 
  36 #include <alloca.h>
  37 #include <rtld_db.h>
  38 #include <libgen.h>
  39 #include <limits.h>
  40 #include <string.h>
  41 #include <stdlib.h>
  42 #include <unistd.h>
  43 #include <errno.h>
  44 #include <gelf.h>
  45 #include <stddef.h>
  46 #include <signal.h>
  47 
  48 #include "libproc.h"
  49 #include "Pcontrol.h"
  50 #include "P32ton.h"
  51 #include "Putil.h"

  52 #include "Pcore_linux.h"

  53 
  54 /*
  55  * Pcore.c - Code to initialize a ps_prochandle from a core dump.  We
  56  * allocate an additional structure to hold information from the core
  57  * file, and attach this to the standard ps_prochandle in place of the
  58  * ability to examine /proc/<pid>/ files.
  59  */
  60 
  61 /*
  62  * Basic i/o function for reading and writing from the process address space
  63  * stored in the core file and associated shared libraries.  We compute the
  64  * appropriate fd and offsets, and let the provided prw function do the rest.
  65  */
  66 static ssize_t
  67 core_rw(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
  68     ssize_t (*prw)(int, void *, size_t, off64_t))
  69 {
  70         ssize_t resid = n;
  71 
  72         while (resid != 0) {


 202                         if (lwp->lwp_asrs != NULL)
 203                                 free(lwp->lwp_asrs);
 204 #endif
 205                         free(lwp);
 206                 }
 207 
 208                 if (core->core_platform != NULL)
 209                         free(core->core_platform);
 210                 if (core->core_uts != NULL)
 211                         free(core->core_uts);
 212                 if (core->core_cred != NULL)
 213                         free(core->core_cred);
 214                 if (core->core_priv != NULL)
 215                         free(core->core_priv);
 216                 if (core->core_privinfo != NULL)
 217                         __priv_free_info(core->core_privinfo);
 218                 if (core->core_ppii != NULL)
 219                         free(core->core_ppii);
 220                 if (core->core_zonename != NULL)
 221                         free(core->core_zonename);
 222 #if defined(__i386) || defined(__amd64)
 223                 if (core->core_ldt != NULL)
 224                         free(core->core_ldt);
 225 #endif
 226 
 227                 free(core);
 228         }
 229 }
 230 
 231 /*ARGSUSED*/
 232 static char *
 233 Pplatform_core(struct ps_prochandle *P, char *s, size_t n, void *data)
 234 {
 235         core_info_t *core = data;
 236 
 237         if (core->core_platform == NULL) {
 238                 errno = ENODATA;
 239                 return (NULL);
 240         }
 241         (void) strncpy(s, core->core_platform, n - 1);
 242         s[n - 1] = '\0';


 254                 return (-1);
 255         }
 256         (void) memcpy(u, core->core_uts, sizeof (struct utsname));
 257         return (0);
 258 }
 259 
 260 /*ARGSUSED*/
 261 static char *
 262 Pzonename_core(struct ps_prochandle *P, char *s, size_t n, void *data)
 263 {
 264         core_info_t *core = data;
 265 
 266         if (core->core_zonename == NULL) {
 267                 errno = ENODATA;
 268                 return (NULL);
 269         }
 270         (void) strlcpy(s, core->core_zonename, n);
 271         return (s);
 272 }
 273 
 274 #if defined(__i386) || defined(__amd64)
 275 /*ARGSUSED*/
 276 static int
 277 Pldt_core(struct ps_prochandle *P, struct ssd *pldt, int nldt, void *data)
 278 {
 279         core_info_t *core = data;
 280 
 281         if (pldt == NULL || nldt == 0)
 282                 return (core->core_nldt);
 283 
 284         if (core->core_ldt != NULL) {
 285                 nldt = MIN(nldt, core->core_nldt);
 286 
 287                 (void) memcpy(pldt, core->core_ldt,
 288                     nldt * sizeof (struct ssd));
 289 
 290                 return (nldt);
 291         }
 292 
 293         errno = ENODATA;
 294         return (-1);
 295 }
 296 #endif
 297 
 298 static const ps_ops_t P_core_ops = {
 299         .pop_pread      = Pread_core,
 300         .pop_pwrite     = Pwrite_core,
 301         .pop_cred       = Pcred_core,
 302         .pop_priv       = Ppriv_core,
 303         .pop_psinfo     = Ppsinfo_core,
 304         .pop_fini       = Pfini_core,
 305         .pop_platform   = Pplatform_core,
 306         .pop_uname      = Puname_core,
 307         .pop_zonename   = Pzonename_core,
 308 #if defined(__i386) || defined(__amd64)
 309         .pop_ldt        = Pldt_core
 310 #endif
 311 };
 312 
 313 /*
 314  * Return the lwp_info_t for the given lwpid.  If no such lwpid has been
 315  * encountered yet, allocate a new structure and return a pointer to it.
 316  * Create a list of lwp_info_t structures sorted in decreasing lwp_id order.
 317  */
 318 static lwp_info_t *
 319 lwpid2info(struct ps_prochandle *P, lwpid_t id)
 320 {
 321         core_info_t *core = P->data;
 322         lwp_info_t *lwp = list_next(&core->core_lwp_head);
 323         lwp_info_t *next;
 324         uint_t i;
 325 
 326         for (i = 0; i < core->core_nlwp; i++, lwp = list_next(lwp)) {
 327                 if (lwp->lwp_id == id) {
 328                         core->core_lwp = lwp;


 414                 dprintf("Pgrab_core: failed to add NT_LWPSTATUS\n");
 415                 return (-1);
 416         }
 417 
 418         /*
 419          * Erase a useless and confusing artifact of the kernel implementation:
 420          * the lwps which did *not* create the core will show SIGKILL.  We can
 421          * be assured this is bogus because SIGKILL can't produce core files.
 422          */
 423         if (lps.pr_cursig == SIGKILL)
 424                 lps.pr_cursig = 0;
 425 
 426         (void) memcpy(&lwp->lwp_status, &lps, sizeof (lps));
 427         return (0);
 428 
 429 err:
 430         dprintf("Pgrab_core: failed to read NT_LWPSTATUS\n");
 431         return (-1);
 432 }
 433 


 434 static void
 435 lx_prpsinfo32_to_psinfo(lx_prpsinfo32_t *p32, psinfo_t *psinfo)
 436 {
 437         psinfo->pr_flag = p32->pr_flag;
 438         psinfo->pr_pid = p32->pr_pid;
 439         psinfo->pr_ppid = p32->pr_ppid;
 440         psinfo->pr_uid = p32->pr_uid;
 441         psinfo->pr_gid = p32->pr_gid;
 442         psinfo->pr_sid = p32->pr_sid;
 443         psinfo->pr_pgid = p32->pr_pgrp;
 444 
 445         (void) memcpy(psinfo->pr_fname, p32->pr_fname,
 446             sizeof (psinfo->pr_fname));
 447         (void) memcpy(psinfo->pr_psargs, p32->pr_psargs,
 448             sizeof (psinfo->pr_psargs));
 449 }
 450 
 451 static void
 452 lx_prpsinfo64_to_psinfo(lx_prpsinfo64_t *p64, psinfo_t *psinfo)
 453 {


 612                     "linux_prstatus\n");
 613                 return (-1);
 614         }
 615 
 616         P->psinfo.pr_nlwp++;
 617         P->status.pr_nlwp++;
 618 
 619         lwp->lwp_status.pr_lwpid = tid;
 620 
 621         if (core->core_dmodel == PR_MODEL_ILP32)
 622                 lx_prstatus32_to_lwp(&prs32, lwp);
 623         else
 624                 lx_prstatus64_to_lwp(&prs64, lwp);
 625 
 626         return (0);
 627 err:
 628         dprintf("Pgrab_core: failed to read NT_PRSTATUS\n");
 629         return (-1);
 630 }
 631 


 632 static int
 633 note_psinfo(struct ps_prochandle *P, size_t nbytes)
 634 {
 635 #ifdef _LP64
 636         core_info_t *core = P->data;
 637 
 638         if (core->core_dmodel == PR_MODEL_ILP32) {
 639                 psinfo32_t ps32;
 640 
 641                 if (nbytes < sizeof (psinfo32_t) ||
 642                     read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32))
 643                         goto err;
 644 
 645                 psinfo_32_to_n(&ps32, &P->psinfo);
 646         } else
 647 #endif
 648         if (nbytes < sizeof (psinfo_t) ||
 649             read(P->asfd, &P->psinfo, sizeof (psinfo_t)) != sizeof (psinfo_t))
 650                 goto err;
 651 


 810 
 811         if ((pcrp = malloc(nbytes)) == NULL)
 812                 return (-1);
 813 
 814         if (read(P->asfd, pcrp, nbytes) != nbytes) {
 815                 dprintf("Pgrab_core: failed to read NT_PRCRED\n");
 816                 free(pcrp);
 817                 return (-1);
 818         }
 819 
 820         if (pcrp->pr_ngroups > ngroups) {
 821                 dprintf("pr_ngroups = %d; resetting to %d based on note size\n",
 822                     pcrp->pr_ngroups, ngroups);
 823                 pcrp->pr_ngroups = ngroups;
 824         }
 825 
 826         core->core_cred = pcrp;
 827         return (0);
 828 }
 829 
 830 #if defined(__i386) || defined(__amd64)
 831 static int
 832 note_ldt(struct ps_prochandle *P, size_t nbytes)
 833 {
 834         core_info_t *core = P->data;
 835         struct ssd *pldt;
 836         uint_t nldt;
 837 
 838         if (core->core_ldt != NULL || nbytes < sizeof (struct ssd))
 839                 return (0);     /* Already seen or bad size */
 840 
 841         nldt = nbytes / sizeof (struct ssd);
 842         nbytes = nldt * sizeof (struct ssd);
 843 
 844         if ((pldt = malloc(nbytes)) == NULL)
 845                 return (-1);
 846 
 847         if (read(P->asfd, pldt, nbytes) != nbytes) {
 848                 dprintf("Pgrab_core: failed to read NT_LDT\n");
 849                 free(pldt);
 850                 return (-1);


1108 err:
1109         dprintf("Pgrab_core: failed to read NT_SPYMASTER\n");
1110         return (-1);
1111 }
1112 
1113 /*ARGSUSED*/
1114 static int
1115 note_notsup(struct ps_prochandle *P, size_t nbytes)
1116 {
1117         dprintf("skipping unsupported note type of size %ld bytes\n",
1118             (ulong_t)nbytes);
1119         return (0);
1120 }
1121 
1122 /*
1123  * Populate a table of function pointers indexed by Note type with our
1124  * functions to process each type of core file note:
1125  */
1126 static int (*nhdlrs[])(struct ps_prochandle *, size_t) = {
1127         note_notsup,            /*  0   unassigned              */

1128         note_linux_prstatus,            /*  1   NT_PRSTATUS (old)       */



1129         note_notsup,            /*  2   NT_PRFPREG (old)        */

1130         note_linux_psinfo,              /*  3   NT_PRPSINFO (old)       */



1131 #ifdef __sparc
1132         note_xreg,              /*  4   NT_PRXREG               */
1133 #else
1134         note_notsup,            /*  4   NT_PRXREG               */
1135 #endif
1136         note_platform,          /*  5   NT_PLATFORM             */
1137         note_auxv,              /*  6   NT_AUXV                 */
1138 #ifdef __sparc
1139         note_gwindows,          /*  7   NT_GWINDOWS             */
1140 #ifdef __sparcv9
1141         note_asrs,              /*  8   NT_ASRS                 */
1142 #else
1143         note_notsup,            /*  8   NT_ASRS                 */
1144 #endif
1145 #else
1146         note_notsup,            /*  7   NT_GWINDOWS             */
1147         note_notsup,            /*  8   NT_ASRS                 */
1148 #endif
1149 #if defined(__i386) || defined(__amd64)
1150         note_ldt,               /*  9   NT_LDT                  */
1151 #else
1152         note_notsup,            /*  9   NT_LDT                  */
1153 #endif
1154         note_pstatus,           /* 10   NT_PSTATUS              */
1155         note_notsup,            /* 11   unassigned              */
1156         note_notsup,            /* 12   unassigned              */
1157         note_psinfo,            /* 13   NT_PSINFO               */
1158         note_cred,              /* 14   NT_PRCRED               */
1159         note_utsname,           /* 15   NT_UTSNAME              */
1160         note_lwpstatus,         /* 16   NT_LWPSTATUS            */
1161         note_lwpsinfo,          /* 17   NT_LWPSINFO             */
1162         note_priv,              /* 18   NT_PRPRIV               */
1163         note_priv_info,         /* 19   NT_PRPRIVINFO           */
1164         note_content,           /* 20   NT_CONTENT              */
1165         note_zonename,          /* 21   NT_ZONENAME             */
1166         note_fdinfo,            /* 22   NT_FDINFO               */
1167         note_spymaster,         /* 23   NT_SPYMASTER            */
1168 };
1169 


2184 
2185 /*
2186  * Main engine for core file initialization: given an fd for the core file
2187  * and an optional pathname, construct the ps_prochandle.  The aout_path can
2188  * either be a suggested executable pathname, or a suggested directory to
2189  * use as a possible current working directory.
2190  */
2191 struct ps_prochandle *
2192 Pfgrab_core(int core_fd, const char *aout_path, int *perr)
2193 {
2194         struct ps_prochandle *P;
2195         core_info_t *core_info;
2196         map_info_t *stk_mp, *brk_mp;
2197         const char *execname;
2198         char *interp;
2199         int i, notes, pagesize;
2200         uintptr_t addr, base_addr;
2201         struct stat64 stbuf;
2202         void *phbuf, *php;
2203         size_t nbytes;

2204         boolean_t from_linux = B_FALSE;

2205 
2206         elf_file_t aout;
2207         elf_file_t core;
2208 
2209         Elf_Scn *scn, *intp_scn = NULL;
2210         Elf_Data *dp;
2211 
2212         GElf_Phdr phdr, note_phdr;
2213         GElf_Shdr shdr;
2214         GElf_Xword nleft;
2215 
2216         if (elf_version(EV_CURRENT) == EV_NONE) {
2217                 dprintf("libproc ELF version is more recent than libelf\n");
2218                 *perr = G_ELF;
2219                 return (NULL);
2220         }
2221 
2222         aout.e_elf = NULL;
2223         aout.e_fd = -1;
2224 


2432 
2433                 dprintf("Note hdr n_type=%u n_namesz=%u n_descsz=%u\n",
2434                     nhdr.n_type, nhdr.n_namesz, nhdr.n_descsz);
2435 
2436                 off = lseek64(P->asfd, (off64_t)0L, SEEK_CUR);
2437 
2438                 /*
2439                  * Invoke the note handler function from our table
2440                  */
2441                 if (nhdr.n_type < sizeof (nhdlrs) / sizeof (nhdlrs[0])) {
2442                         if (nhdlrs[nhdr.n_type](P, nhdr.n_descsz) < 0) {
2443                                 dprintf("handler for type %d returned < 0",
2444                                     nhdr.n_type);
2445                                 *perr = G_NOTE;
2446                                 goto err;
2447                         }
2448                         /*
2449                          * The presence of either of these notes indicates that
2450                          * the dump was generated on Linux.
2451                          */

2452                         if (nhdr.n_type == NT_PRSTATUS ||
2453                             nhdr.n_type == NT_PRPSINFO)
2454                                 from_linux = B_TRUE;

2455                 } else {
2456                         (void) note_notsup(P, nhdr.n_descsz);
2457                 }
2458 
2459                 /*
2460                  * Seek past the current note data to the next Elf_Nhdr
2461                  */
2462                 descsz = P2ROUNDUP((off64_t)nhdr.n_descsz, (off64_t)4);
2463                 if (lseek64(P->asfd, off + descsz, SEEK_SET) == (off64_t)-1) {
2464                         dprintf("Pgrab_core: failed to seek to next nhdr\n");
2465                         *perr = G_STRANGE;
2466                         goto err;
2467                 }
2468 
2469                 /*
2470                  * Subtract the size of the header and its data from what
2471                  * we have left to process.
2472                  */
2473                 nleft -= sizeof (nhdr) + namesz + descsz;
2474         }
2475 

2476         if (from_linux) {
2477                 size_t tcount, pid;
2478                 lwp_info_t *lwp;
2479 
2480                 P->status.pr_dmodel = core_info->core_dmodel;
2481 
2482                 lwp = list_next(&core_info->core_lwp_head);
2483 
2484                 pid = P->status.pr_pid;
2485 
2486                 for (tcount = 0; tcount < core_info->core_nlwp;
2487                     tcount++, lwp = list_next(lwp)) {
2488                         dprintf("Linux thread with id %d\n", lwp->lwp_id);
2489 
2490                         /*
2491                          * In the case we don't have a valid psinfo (i.e. pid is
2492                          * 0, probably because of gdb creating the core) assume
2493                          * lowest pid count is the first thread (what if the
2494                          * next thread wraps the pid around?)
2495                          */


2509                 /*
2510                  * Consumers like mdb expect the first thread to actually have
2511                  * an id of 1, on linux that is actually the pid. Find the the
2512                  * thread with our process id, and set the id to 1
2513                  */
2514                 if ((lwp = lwpid2info(P, pid)) == NULL) {
2515                         dprintf("Couldn't find first thread\n");
2516                         *perr = G_STRANGE;
2517                         goto err;
2518                 }
2519 
2520                 dprintf("setting representative thread: %d\n", lwp->lwp_id);
2521 
2522                 lwp->lwp_id = 1;
2523                 lwp->lwp_status.pr_lwpid = 1;
2524 
2525                 /* set representative thread */
2526                 (void) memcpy(&P->status.pr_lwp, &lwp->lwp_status,
2527                     sizeof (P->status.pr_lwp));
2528         }

2529 
2530         if (nleft != 0) {
2531                 dprintf("Pgrab_core: note section malformed\n");
2532                 *perr = G_STRANGE;
2533                 goto err;
2534         }
2535 
2536         if ((pagesize = Pgetauxval(P, AT_PAGESZ)) == -1) {
2537                 pagesize = getpagesize();
2538                 dprintf("AT_PAGESZ missing; defaulting to %d\n", pagesize);
2539         }
2540 
2541         /*
2542          * Locate and label the mappings corresponding to the end of the
2543          * heap (MA_BREAK) and the base of the stack (MA_STACK).
2544          */
2545         if ((P->status.pr_brkbase != 0 || P->status.pr_brksize != 0) &&
2546             (brk_mp = Paddr2mptr(P, P->status.pr_brkbase +
2547             P->status.pr_brksize - 1)) != NULL)
2548                 brk_mp->map_pmap.pr_mflags |= MA_BREAK;




   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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 /*
  26  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
  27  * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  28  * Copyright (c) 2013 by Delphix. All rights reserved.
  29  * Copyright 2015 Gary Mills
  30  */
  31 
  32 #include <sys/types.h>
  33 #include <sys/utsname.h>
  34 #include <sys/sysmacros.h>
  35 #include <sys/proc.h>
  36 
  37 #include <alloca.h>
  38 #include <rtld_db.h>
  39 #include <libgen.h>
  40 #include <limits.h>
  41 #include <string.h>
  42 #include <stdlib.h>
  43 #include <unistd.h>
  44 #include <errno.h>
  45 #include <gelf.h>
  46 #include <stddef.h>
  47 #include <signal.h>
  48 
  49 #include "libproc.h"
  50 #include "Pcontrol.h"
  51 #include "P32ton.h"
  52 #include "Putil.h"
  53 #ifdef __x86
  54 #include "Pcore_linux.h"
  55 #endif
  56 
  57 /*
  58  * Pcore.c - Code to initialize a ps_prochandle from a core dump.  We
  59  * allocate an additional structure to hold information from the core
  60  * file, and attach this to the standard ps_prochandle in place of the
  61  * ability to examine /proc/<pid>/ files.
  62  */
  63 
  64 /*
  65  * Basic i/o function for reading and writing from the process address space
  66  * stored in the core file and associated shared libraries.  We compute the
  67  * appropriate fd and offsets, and let the provided prw function do the rest.
  68  */
  69 static ssize_t
  70 core_rw(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
  71     ssize_t (*prw)(int, void *, size_t, off64_t))
  72 {
  73         ssize_t resid = n;
  74 
  75         while (resid != 0) {


 205                         if (lwp->lwp_asrs != NULL)
 206                                 free(lwp->lwp_asrs);
 207 #endif
 208                         free(lwp);
 209                 }
 210 
 211                 if (core->core_platform != NULL)
 212                         free(core->core_platform);
 213                 if (core->core_uts != NULL)
 214                         free(core->core_uts);
 215                 if (core->core_cred != NULL)
 216                         free(core->core_cred);
 217                 if (core->core_priv != NULL)
 218                         free(core->core_priv);
 219                 if (core->core_privinfo != NULL)
 220                         __priv_free_info(core->core_privinfo);
 221                 if (core->core_ppii != NULL)
 222                         free(core->core_ppii);
 223                 if (core->core_zonename != NULL)
 224                         free(core->core_zonename);
 225 #ifdef __x86
 226                 if (core->core_ldt != NULL)
 227                         free(core->core_ldt);
 228 #endif
 229 
 230                 free(core);
 231         }
 232 }
 233 
 234 /*ARGSUSED*/
 235 static char *
 236 Pplatform_core(struct ps_prochandle *P, char *s, size_t n, void *data)
 237 {
 238         core_info_t *core = data;
 239 
 240         if (core->core_platform == NULL) {
 241                 errno = ENODATA;
 242                 return (NULL);
 243         }
 244         (void) strncpy(s, core->core_platform, n - 1);
 245         s[n - 1] = '\0';


 257                 return (-1);
 258         }
 259         (void) memcpy(u, core->core_uts, sizeof (struct utsname));
 260         return (0);
 261 }
 262 
 263 /*ARGSUSED*/
 264 static char *
 265 Pzonename_core(struct ps_prochandle *P, char *s, size_t n, void *data)
 266 {
 267         core_info_t *core = data;
 268 
 269         if (core->core_zonename == NULL) {
 270                 errno = ENODATA;
 271                 return (NULL);
 272         }
 273         (void) strlcpy(s, core->core_zonename, n);
 274         return (s);
 275 }
 276 
 277 #ifdef __x86
 278 /*ARGSUSED*/
 279 static int
 280 Pldt_core(struct ps_prochandle *P, struct ssd *pldt, int nldt, void *data)
 281 {
 282         core_info_t *core = data;
 283 
 284         if (pldt == NULL || nldt == 0)
 285                 return (core->core_nldt);
 286 
 287         if (core->core_ldt != NULL) {
 288                 nldt = MIN(nldt, core->core_nldt);
 289 
 290                 (void) memcpy(pldt, core->core_ldt,
 291                     nldt * sizeof (struct ssd));
 292 
 293                 return (nldt);
 294         }
 295 
 296         errno = ENODATA;
 297         return (-1);
 298 }
 299 #endif
 300 
 301 static const ps_ops_t P_core_ops = {
 302         .pop_pread      = Pread_core,
 303         .pop_pwrite     = Pwrite_core,
 304         .pop_cred       = Pcred_core,
 305         .pop_priv       = Ppriv_core,
 306         .pop_psinfo     = Ppsinfo_core,
 307         .pop_fini       = Pfini_core,
 308         .pop_platform   = Pplatform_core,
 309         .pop_uname      = Puname_core,
 310         .pop_zonename   = Pzonename_core,
 311 #ifdef __x86
 312         .pop_ldt        = Pldt_core
 313 #endif
 314 };
 315 
 316 /*
 317  * Return the lwp_info_t for the given lwpid.  If no such lwpid has been
 318  * encountered yet, allocate a new structure and return a pointer to it.
 319  * Create a list of lwp_info_t structures sorted in decreasing lwp_id order.
 320  */
 321 static lwp_info_t *
 322 lwpid2info(struct ps_prochandle *P, lwpid_t id)
 323 {
 324         core_info_t *core = P->data;
 325         lwp_info_t *lwp = list_next(&core->core_lwp_head);
 326         lwp_info_t *next;
 327         uint_t i;
 328 
 329         for (i = 0; i < core->core_nlwp; i++, lwp = list_next(lwp)) {
 330                 if (lwp->lwp_id == id) {
 331                         core->core_lwp = lwp;


 417                 dprintf("Pgrab_core: failed to add NT_LWPSTATUS\n");
 418                 return (-1);
 419         }
 420 
 421         /*
 422          * Erase a useless and confusing artifact of the kernel implementation:
 423          * the lwps which did *not* create the core will show SIGKILL.  We can
 424          * be assured this is bogus because SIGKILL can't produce core files.
 425          */
 426         if (lps.pr_cursig == SIGKILL)
 427                 lps.pr_cursig = 0;
 428 
 429         (void) memcpy(&lwp->lwp_status, &lps, sizeof (lps));
 430         return (0);
 431 
 432 err:
 433         dprintf("Pgrab_core: failed to read NT_LWPSTATUS\n");
 434         return (-1);
 435 }
 436 
 437 #ifdef __x86
 438 
 439 static void
 440 lx_prpsinfo32_to_psinfo(lx_prpsinfo32_t *p32, psinfo_t *psinfo)
 441 {
 442         psinfo->pr_flag = p32->pr_flag;
 443         psinfo->pr_pid = p32->pr_pid;
 444         psinfo->pr_ppid = p32->pr_ppid;
 445         psinfo->pr_uid = p32->pr_uid;
 446         psinfo->pr_gid = p32->pr_gid;
 447         psinfo->pr_sid = p32->pr_sid;
 448         psinfo->pr_pgid = p32->pr_pgrp;
 449 
 450         (void) memcpy(psinfo->pr_fname, p32->pr_fname,
 451             sizeof (psinfo->pr_fname));
 452         (void) memcpy(psinfo->pr_psargs, p32->pr_psargs,
 453             sizeof (psinfo->pr_psargs));
 454 }
 455 
 456 static void
 457 lx_prpsinfo64_to_psinfo(lx_prpsinfo64_t *p64, psinfo_t *psinfo)
 458 {


 617                     "linux_prstatus\n");
 618                 return (-1);
 619         }
 620 
 621         P->psinfo.pr_nlwp++;
 622         P->status.pr_nlwp++;
 623 
 624         lwp->lwp_status.pr_lwpid = tid;
 625 
 626         if (core->core_dmodel == PR_MODEL_ILP32)
 627                 lx_prstatus32_to_lwp(&prs32, lwp);
 628         else
 629                 lx_prstatus64_to_lwp(&prs64, lwp);
 630 
 631         return (0);
 632 err:
 633         dprintf("Pgrab_core: failed to read NT_PRSTATUS\n");
 634         return (-1);
 635 }
 636 
 637 #endif /* __x86 */
 638 
 639 static int
 640 note_psinfo(struct ps_prochandle *P, size_t nbytes)
 641 {
 642 #ifdef _LP64
 643         core_info_t *core = P->data;
 644 
 645         if (core->core_dmodel == PR_MODEL_ILP32) {
 646                 psinfo32_t ps32;
 647 
 648                 if (nbytes < sizeof (psinfo32_t) ||
 649                     read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32))
 650                         goto err;
 651 
 652                 psinfo_32_to_n(&ps32, &P->psinfo);
 653         } else
 654 #endif
 655         if (nbytes < sizeof (psinfo_t) ||
 656             read(P->asfd, &P->psinfo, sizeof (psinfo_t)) != sizeof (psinfo_t))
 657                 goto err;
 658 


 817 
 818         if ((pcrp = malloc(nbytes)) == NULL)
 819                 return (-1);
 820 
 821         if (read(P->asfd, pcrp, nbytes) != nbytes) {
 822                 dprintf("Pgrab_core: failed to read NT_PRCRED\n");
 823                 free(pcrp);
 824                 return (-1);
 825         }
 826 
 827         if (pcrp->pr_ngroups > ngroups) {
 828                 dprintf("pr_ngroups = %d; resetting to %d based on note size\n",
 829                     pcrp->pr_ngroups, ngroups);
 830                 pcrp->pr_ngroups = ngroups;
 831         }
 832 
 833         core->core_cred = pcrp;
 834         return (0);
 835 }
 836 
 837 #ifdef __x86
 838 static int
 839 note_ldt(struct ps_prochandle *P, size_t nbytes)
 840 {
 841         core_info_t *core = P->data;
 842         struct ssd *pldt;
 843         uint_t nldt;
 844 
 845         if (core->core_ldt != NULL || nbytes < sizeof (struct ssd))
 846                 return (0);     /* Already seen or bad size */
 847 
 848         nldt = nbytes / sizeof (struct ssd);
 849         nbytes = nldt * sizeof (struct ssd);
 850 
 851         if ((pldt = malloc(nbytes)) == NULL)
 852                 return (-1);
 853 
 854         if (read(P->asfd, pldt, nbytes) != nbytes) {
 855                 dprintf("Pgrab_core: failed to read NT_LDT\n");
 856                 free(pldt);
 857                 return (-1);


1115 err:
1116         dprintf("Pgrab_core: failed to read NT_SPYMASTER\n");
1117         return (-1);
1118 }
1119 
1120 /*ARGSUSED*/
1121 static int
1122 note_notsup(struct ps_prochandle *P, size_t nbytes)
1123 {
1124         dprintf("skipping unsupported note type of size %ld bytes\n",
1125             (ulong_t)nbytes);
1126         return (0);
1127 }
1128 
1129 /*
1130  * Populate a table of function pointers indexed by Note type with our
1131  * functions to process each type of core file note:
1132  */
1133 static int (*nhdlrs[])(struct ps_prochandle *, size_t) = {
1134         note_notsup,            /*  0   unassigned              */
1135 #ifdef __x86
1136         note_linux_prstatus,            /*  1   NT_PRSTATUS (old)       */
1137 #else
1138         note_notsup,            /*  1   NT_PRSTATUS (old)       */
1139 #endif
1140         note_notsup,            /*  2   NT_PRFPREG (old)        */
1141 #ifdef __x86
1142         note_linux_psinfo,              /*  3   NT_PRPSINFO (old)       */
1143 #else
1144         note_notsup,            /*  3   NT_PRPSINFO (old)       */
1145 #endif
1146 #ifdef __sparc
1147         note_xreg,              /*  4   NT_PRXREG               */
1148 #else
1149         note_notsup,            /*  4   NT_PRXREG               */
1150 #endif
1151         note_platform,          /*  5   NT_PLATFORM             */
1152         note_auxv,              /*  6   NT_AUXV                 */
1153 #ifdef __sparc
1154         note_gwindows,          /*  7   NT_GWINDOWS             */
1155 #ifdef __sparcv9
1156         note_asrs,              /*  8   NT_ASRS                 */
1157 #else
1158         note_notsup,            /*  8   NT_ASRS                 */
1159 #endif
1160 #else
1161         note_notsup,            /*  7   NT_GWINDOWS             */
1162         note_notsup,            /*  8   NT_ASRS                 */
1163 #endif
1164 #ifdef __x86
1165         note_ldt,               /*  9   NT_LDT                  */
1166 #else
1167         note_notsup,            /*  9   NT_LDT                  */
1168 #endif
1169         note_pstatus,           /* 10   NT_PSTATUS              */
1170         note_notsup,            /* 11   unassigned              */
1171         note_notsup,            /* 12   unassigned              */
1172         note_psinfo,            /* 13   NT_PSINFO               */
1173         note_cred,              /* 14   NT_PRCRED               */
1174         note_utsname,           /* 15   NT_UTSNAME              */
1175         note_lwpstatus,         /* 16   NT_LWPSTATUS            */
1176         note_lwpsinfo,          /* 17   NT_LWPSINFO             */
1177         note_priv,              /* 18   NT_PRPRIV               */
1178         note_priv_info,         /* 19   NT_PRPRIVINFO           */
1179         note_content,           /* 20   NT_CONTENT              */
1180         note_zonename,          /* 21   NT_ZONENAME             */
1181         note_fdinfo,            /* 22   NT_FDINFO               */
1182         note_spymaster,         /* 23   NT_SPYMASTER            */
1183 };
1184 


2199 
2200 /*
2201  * Main engine for core file initialization: given an fd for the core file
2202  * and an optional pathname, construct the ps_prochandle.  The aout_path can
2203  * either be a suggested executable pathname, or a suggested directory to
2204  * use as a possible current working directory.
2205  */
2206 struct ps_prochandle *
2207 Pfgrab_core(int core_fd, const char *aout_path, int *perr)
2208 {
2209         struct ps_prochandle *P;
2210         core_info_t *core_info;
2211         map_info_t *stk_mp, *brk_mp;
2212         const char *execname;
2213         char *interp;
2214         int i, notes, pagesize;
2215         uintptr_t addr, base_addr;
2216         struct stat64 stbuf;
2217         void *phbuf, *php;
2218         size_t nbytes;
2219 #ifdef __x86
2220         boolean_t from_linux = B_FALSE;
2221 #endif
2222 
2223         elf_file_t aout;
2224         elf_file_t core;
2225 
2226         Elf_Scn *scn, *intp_scn = NULL;
2227         Elf_Data *dp;
2228 
2229         GElf_Phdr phdr, note_phdr;
2230         GElf_Shdr shdr;
2231         GElf_Xword nleft;
2232 
2233         if (elf_version(EV_CURRENT) == EV_NONE) {
2234                 dprintf("libproc ELF version is more recent than libelf\n");
2235                 *perr = G_ELF;
2236                 return (NULL);
2237         }
2238 
2239         aout.e_elf = NULL;
2240         aout.e_fd = -1;
2241 


2449 
2450                 dprintf("Note hdr n_type=%u n_namesz=%u n_descsz=%u\n",
2451                     nhdr.n_type, nhdr.n_namesz, nhdr.n_descsz);
2452 
2453                 off = lseek64(P->asfd, (off64_t)0L, SEEK_CUR);
2454 
2455                 /*
2456                  * Invoke the note handler function from our table
2457                  */
2458                 if (nhdr.n_type < sizeof (nhdlrs) / sizeof (nhdlrs[0])) {
2459                         if (nhdlrs[nhdr.n_type](P, nhdr.n_descsz) < 0) {
2460                                 dprintf("handler for type %d returned < 0",
2461                                     nhdr.n_type);
2462                                 *perr = G_NOTE;
2463                                 goto err;
2464                         }
2465                         /*
2466                          * The presence of either of these notes indicates that
2467                          * the dump was generated on Linux.
2468                          */
2469 #ifdef __x86
2470                         if (nhdr.n_type == NT_PRSTATUS ||
2471                             nhdr.n_type == NT_PRPSINFO)
2472                                 from_linux = B_TRUE;
2473 #endif
2474                 } else {
2475                         (void) note_notsup(P, nhdr.n_descsz);
2476                 }
2477 
2478                 /*
2479                  * Seek past the current note data to the next Elf_Nhdr
2480                  */
2481                 descsz = P2ROUNDUP((off64_t)nhdr.n_descsz, (off64_t)4);
2482                 if (lseek64(P->asfd, off + descsz, SEEK_SET) == (off64_t)-1) {
2483                         dprintf("Pgrab_core: failed to seek to next nhdr\n");
2484                         *perr = G_STRANGE;
2485                         goto err;
2486                 }
2487 
2488                 /*
2489                  * Subtract the size of the header and its data from what
2490                  * we have left to process.
2491                  */
2492                 nleft -= sizeof (nhdr) + namesz + descsz;
2493         }
2494 
2495 #ifdef __x86
2496         if (from_linux) {
2497                 size_t tcount, pid;
2498                 lwp_info_t *lwp;
2499 
2500                 P->status.pr_dmodel = core_info->core_dmodel;
2501 
2502                 lwp = list_next(&core_info->core_lwp_head);
2503 
2504                 pid = P->status.pr_pid;
2505 
2506                 for (tcount = 0; tcount < core_info->core_nlwp;
2507                     tcount++, lwp = list_next(lwp)) {
2508                         dprintf("Linux thread with id %d\n", lwp->lwp_id);
2509 
2510                         /*
2511                          * In the case we don't have a valid psinfo (i.e. pid is
2512                          * 0, probably because of gdb creating the core) assume
2513                          * lowest pid count is the first thread (what if the
2514                          * next thread wraps the pid around?)
2515                          */


2529                 /*
2530                  * Consumers like mdb expect the first thread to actually have
2531                  * an id of 1, on linux that is actually the pid. Find the the
2532                  * thread with our process id, and set the id to 1
2533                  */
2534                 if ((lwp = lwpid2info(P, pid)) == NULL) {
2535                         dprintf("Couldn't find first thread\n");
2536                         *perr = G_STRANGE;
2537                         goto err;
2538                 }
2539 
2540                 dprintf("setting representative thread: %d\n", lwp->lwp_id);
2541 
2542                 lwp->lwp_id = 1;
2543                 lwp->lwp_status.pr_lwpid = 1;
2544 
2545                 /* set representative thread */
2546                 (void) memcpy(&P->status.pr_lwp, &lwp->lwp_status,
2547                     sizeof (P->status.pr_lwp));
2548         }
2549 #endif /* __x86 */
2550 
2551         if (nleft != 0) {
2552                 dprintf("Pgrab_core: note section malformed\n");
2553                 *perr = G_STRANGE;
2554                 goto err;
2555         }
2556 
2557         if ((pagesize = Pgetauxval(P, AT_PAGESZ)) == -1) {
2558                 pagesize = getpagesize();
2559                 dprintf("AT_PAGESZ missing; defaulting to %d\n", pagesize);
2560         }
2561 
2562         /*
2563          * Locate and label the mappings corresponding to the end of the
2564          * heap (MA_BREAK) and the base of the stack (MA_STACK).
2565          */
2566         if ((P->status.pr_brkbase != 0 || P->status.pr_brksize != 0) &&
2567             (brk_mp = Paddr2mptr(P, P->status.pr_brkbase +
2568             P->status.pr_brksize - 1)) != NULL)
2569                 brk_mp->map_pmap.pr_mflags |= MA_BREAK;