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

@@ -23,10 +23,11 @@
  * Use is subject to license terms.
  */
 /*
  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 #include <sys/types.h>
 #include <sys/utsname.h>
 #include <sys/sysmacros.h>

@@ -109,40 +110,223 @@
         }
 
         return (n - resid);
 }
 
+/*ARGSUSED*/
 static ssize_t
-Pread_core(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr)
+Pread_core(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
+    void *data)
 {
         return (core_rw(P, buf, n, addr, pread64));
 }
 
+/*ARGSUSED*/
 static ssize_t
-Pwrite_core(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr)
+Pwrite_core(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr,
+    void *data)
 {
         return (core_rw(P, (void *)buf, n, addr,
             (ssize_t (*)(int, void *, size_t, off64_t)) pwrite64));
 }
 
-static const ps_rwops_t P_core_ops = { Pread_core, Pwrite_core };
+/*ARGSUSED*/
+static int
+Pcred_core(struct ps_prochandle *P, prcred_t *pcrp, int ngroups, void *data)
+{
+        core_info_t *core = data;
 
+        if (core->core_cred != NULL) {
+                /*
+                 * Avoid returning more supplementary group data than the
+                 * caller has allocated in their buffer.  We expect them to
+                 * check pr_ngroups afterward and potentially call us again.
+                 */
+                ngroups = MIN(ngroups, core->core_cred->pr_ngroups);
+
+                (void) memcpy(pcrp, core->core_cred,
+                    sizeof (prcred_t) + (ngroups - 1) * sizeof (gid_t));
+
+                return (0);
+        }
+
+        errno = ENODATA;
+        return (-1);
+}
+
+/*ARGSUSED*/
+static int
+Ppriv_core(struct ps_prochandle *P, prpriv_t **pprv, void *data)
+{
+        core_info_t *core = data;
+
+        if (core->core_priv == NULL) {
+                errno = ENODATA;
+                return (-1);
+        }
+
+        *pprv = malloc(core->core_priv_size);
+        if (*pprv == NULL) {
+                return (-1);
+        }
+
+        (void) memcpy(*pprv, core->core_priv, core->core_priv_size);
+        return (0);
+}
+
+/*ARGSUSED*/
+static const psinfo_t *
+Ppsinfo_core(struct ps_prochandle *P, psinfo_t *psinfo, void *data)
+{
+        return (&P->psinfo);
+}
+
+/*ARGSUSED*/
+static void
+Pfini_core(struct ps_prochandle *P, void *data)
+{
+        core_info_t *core = data;
+
+        if (core != NULL) {
+                extern void __priv_free_info(void *);
+                lwp_info_t *nlwp, *lwp = list_next(&core->core_lwp_head);
+                int i;
+
+                for (i = 0; i < core->core_nlwp; i++, lwp = nlwp) {
+                        nlwp = list_next(lwp);
+#ifdef __sparc
+                        if (lwp->lwp_gwins != NULL)
+                                free(lwp->lwp_gwins);
+                        if (lwp->lwp_xregs != NULL)
+                                free(lwp->lwp_xregs);
+                        if (lwp->lwp_asrs != NULL)
+                                free(lwp->lwp_asrs);
+#endif
+                        free(lwp);
+                }
+
+                if (core->core_platform != NULL)
+                        free(core->core_platform);
+                if (core->core_uts != NULL)
+                        free(core->core_uts);
+                if (core->core_cred != NULL)
+                        free(core->core_cred);
+                if (core->core_priv != NULL)
+                        free(core->core_priv);
+                if (core->core_privinfo != NULL)
+                        __priv_free_info(core->core_privinfo);
+                if (core->core_ppii != NULL)
+                        free(core->core_ppii);
+                if (core->core_zonename != NULL)
+                        free(core->core_zonename);
+#if defined(__i386) || defined(__amd64)
+                if (core->core_ldt != NULL)
+                        free(core->core_ldt);
+#endif
+
+                free(core);
+        }
+}
+
+/*ARGSUSED*/
+static char *
+Pplatform_core(struct ps_prochandle *P, char *s, size_t n, void *data)
+{
+        core_info_t *core = data;
+
+        if (core->core_platform == NULL) {
+                errno = ENODATA;
+                return (NULL);
+        }
+        (void) strncpy(s, core->core_platform, n - 1);
+        s[n - 1] = '\0';
+        return (s);
+}
+
+/*ARGSUSED*/
+static int
+Puname_core(struct ps_prochandle *P, struct utsname *u, void *data)
+{
+        core_info_t *core = data;
+
+        if (core->core_uts == NULL) {
+                errno = ENODATA;
+                return (-1);
+        }
+        (void) memcpy(u, core->core_uts, sizeof (struct utsname));
+        return (0);
+}
+
+/*ARGSUSED*/
+static char *
+Pzonename_core(struct ps_prochandle *P, char *s, size_t n, void *data)
+{
+        core_info_t *core = data;
+
+        if (core->core_zonename == NULL) {
+                errno = ENODATA;
+                return (NULL);
+        }
+        (void) strlcpy(s, core->core_zonename, n);
+        return (s);
+}
+
+#if defined(__i386) || defined(__amd64)
+/*ARGSUSED*/
+static int
+Pldt_core(struct ps_prochandle *P, struct ssd *pldt, int nldt, void *data)
+{
+        core_info_t *core = data;
+
+        if (pldt == NULL || nldt == 0)
+                return (core->core_nldt);
+
+        if (core->core_ldt != NULL) {
+                nldt = MIN(nldt, core->core_nldt);
+
+                (void) memcpy(pldt, core->core_ldt,
+                    nldt * sizeof (struct ssd));
+
+                return (nldt);
+        }
+
+        errno = ENODATA;
+        return (-1);
+}
+#endif
+
+static const ps_ops_t P_core_ops = {
+        .pop_pread      = Pread_core,
+        .pop_pwrite     = Pwrite_core,
+        .pop_cred       = Pcred_core,
+        .pop_priv       = Ppriv_core,
+        .pop_psinfo     = Ppsinfo_core,
+        .pop_fini       = Pfini_core,
+        .pop_platform   = Pplatform_core,
+        .pop_uname      = Puname_core,
+        .pop_zonename   = Pzonename_core,
+#if defined(__i386) || defined(__amd64)
+        .pop_ldt        = Pldt_core
+#endif
+};
+
 /*
  * Return the lwp_info_t for the given lwpid.  If no such lwpid has been
  * encountered yet, allocate a new structure and return a pointer to it.
  * Create a list of lwp_info_t structures sorted in decreasing lwp_id order.
  */
 static lwp_info_t *
 lwpid2info(struct ps_prochandle *P, lwpid_t id)
 {
-        lwp_info_t *lwp = list_next(&P->core->core_lwp_head);
+        core_info_t *core = P->data;
+        lwp_info_t *lwp = list_next(&core->core_lwp_head);
         lwp_info_t *next;
         uint_t i;
 
-        for (i = 0; i < P->core->core_nlwp; i++, lwp = list_next(lwp)) {
+        for (i = 0; i < core->core_nlwp; i++, lwp = list_next(lwp)) {
                 if (lwp->lwp_id == id) {
-                        P->core->core_lwp = lwp;
+                        core->core_lwp = lwp;
                         return (lwp);
                 }
                 if (lwp->lwp_id < id) {
                         break;
                 }

@@ -153,12 +337,12 @@
                 return (NULL);
 
         list_link(lwp, next);
         lwp->lwp_id = id;
 
-        P->core->core_lwp = lwp;
-        P->core->core_nlwp++;
+        core->core_lwp = lwp;
+        core->core_nlwp++;
 
         return (lwp);
 }
 
 /*

@@ -173,11 +357,13 @@
 
 static int
 note_pstatus(struct ps_prochandle *P, size_t nbytes)
 {
 #ifdef _LP64
-        if (P->core->core_dmodel == PR_MODEL_ILP32) {
+        core_info_t *core = P->data;
+
+        if (core->core_dmodel == PR_MODEL_ILP32) {
                 pstatus32_t ps32;
 
                 if (nbytes < sizeof (pstatus32_t) ||
                     read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32))
                         goto err;

@@ -205,11 +391,13 @@
 {
         lwp_info_t *lwp;
         lwpstatus_t lps;
 
 #ifdef _LP64
-        if (P->core->core_dmodel == PR_MODEL_ILP32) {
+        core_info_t *core = P->data;
+
+        if (core->core_dmodel == PR_MODEL_ILP32) {
                 lwpstatus32_t l32;
 
                 if (nbytes < sizeof (lwpstatus32_t) ||
                     read(P->asfd, &l32, sizeof (l32)) != sizeof (l32))
                         goto err;

@@ -244,11 +432,13 @@
 
 static int
 note_psinfo(struct ps_prochandle *P, size_t nbytes)
 {
 #ifdef _LP64
-        if (P->core->core_dmodel == PR_MODEL_ILP32) {
+        core_info_t *core = P->data;
+
+        if (core->core_dmodel == PR_MODEL_ILP32) {
                 psinfo32_t ps32;
 
                 if (nbytes < sizeof (psinfo32_t) ||
                     read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32))
                         goto err;

@@ -276,11 +466,13 @@
 {
         lwp_info_t *lwp;
         lwpsinfo_t lps;
 
 #ifdef _LP64
-        if (P->core->core_dmodel == PR_MODEL_ILP32) {
+        core_info_t *core = P->data;
+
+        if (core->core_dmodel == PR_MODEL_ILP32) {
                 lwpsinfo32_t l32;
 
                 if (nbytes < sizeof (lwpsinfo32_t) ||
                     read(P->asfd, &l32, sizeof (l32)) != sizeof (l32))
                         goto err;

@@ -326,35 +518,37 @@
 }
 
 static int
 note_platform(struct ps_prochandle *P, size_t nbytes)
 {
+        core_info_t *core = P->data;
         char *plat;
 
-        if (P->core->core_platform != NULL)
+        if (core->core_platform != NULL)
                 return (0);     /* Already seen */
 
         if (nbytes != 0 && ((plat = malloc(nbytes + 1)) != NULL)) {
                 if (read(P->asfd, plat, nbytes) != nbytes) {
                         dprintf("Pgrab_core: failed to read NT_PLATFORM\n");
                         free(plat);
                         return (-1);
                 }
                 plat[nbytes - 1] = '\0';
-                P->core->core_platform = plat;
+                core->core_platform = plat;
         }
 
         return (0);
 }
 
 static int
 note_utsname(struct ps_prochandle *P, size_t nbytes)
 {
+        core_info_t *core = P->data;
         size_t ubytes = sizeof (struct utsname);
         struct utsname *utsp;
 
-        if (P->core->core_uts != NULL || nbytes < ubytes)
+        if (core->core_uts != NULL || nbytes < ubytes)
                 return (0);     /* Already seen or bad size */
 
         if ((utsp = malloc(ubytes)) == NULL)
                 return (-1);
 

@@ -370,35 +564,37 @@
                 dprintf("uts.release = \"%s\"\n", utsp->release);
                 dprintf("uts.version = \"%s\"\n", utsp->version);
                 dprintf("uts.machine = \"%s\"\n", utsp->machine);
         }
 
-        P->core->core_uts = utsp;
+        core->core_uts = utsp;
         return (0);
 }
 
 static int
 note_content(struct ps_prochandle *P, size_t nbytes)
 {
+        core_info_t *core = P->data;
         core_content_t content;
 
-        if (sizeof (P->core->core_content) != nbytes)
+        if (sizeof (core->core_content) != nbytes)
                 return (-1);
 
         if (read(P->asfd, &content, sizeof (content)) != sizeof (content))
                 return (-1);
 
-        P->core->core_content = content;
+        core->core_content = content;
 
         dprintf("core content = %llx\n", content);
 
         return (0);
 }
 
 static int
 note_cred(struct ps_prochandle *P, size_t nbytes)
 {
+        core_info_t *core = P->data;
         prcred_t *pcrp;
         int ngroups;
         const size_t min_size = sizeof (prcred_t) - sizeof (gid_t);
 
         /*

@@ -405,11 +601,11 @@
          * We allow for prcred_t notes that are actually smaller than a
          * prcred_t since the last member isn't essential if there are
          * no group memberships. This allows for more flexibility when it
          * comes to slightly malformed -- but still valid -- notes.
          */
-        if (P->core->core_cred != NULL || nbytes < min_size)
+        if (core->core_cred != NULL || nbytes < min_size)
                 return (0);     /* Already seen or bad size */
 
         ngroups = (nbytes - min_size) / sizeof (gid_t);
         nbytes = sizeof (prcred_t) + (ngroups - 1) * sizeof (gid_t);
 

@@ -426,22 +622,23 @@
                 dprintf("pr_ngroups = %d; resetting to %d based on note size\n",
                     pcrp->pr_ngroups, ngroups);
                 pcrp->pr_ngroups = ngroups;
         }
 
-        P->core->core_cred = pcrp;
+        core->core_cred = pcrp;
         return (0);
 }
 
 #if defined(__i386) || defined(__amd64)
 static int
 note_ldt(struct ps_prochandle *P, size_t nbytes)
 {
+        core_info_t *core = P->data;
         struct ssd *pldt;
         uint_t nldt;
 
-        if (P->core->core_ldt != NULL || nbytes < sizeof (struct ssd))
+        if (core->core_ldt != NULL || nbytes < sizeof (struct ssd))
                 return (0);     /* Already seen or bad size */
 
         nldt = nbytes / sizeof (struct ssd);
         nbytes = nldt * sizeof (struct ssd);
 

@@ -452,22 +649,23 @@
                 dprintf("Pgrab_core: failed to read NT_LDT\n");
                 free(pldt);
                 return (-1);
         }
 
-        P->core->core_ldt = pldt;
-        P->core->core_nldt = nldt;
+        core->core_ldt = pldt;
+        core->core_nldt = nldt;
         return (0);
 }
 #endif  /* __i386 */
 
 static int
 note_priv(struct ps_prochandle *P, size_t nbytes)
 {
+        core_info_t *core = P->data;
         prpriv_t *pprvp;
 
-        if (P->core->core_priv != NULL || nbytes < sizeof (prpriv_t))
+        if (core->core_priv != NULL || nbytes < sizeof (prpriv_t))
                 return (0);     /* Already seen or bad size */
 
         if ((pprvp = malloc(nbytes)) == NULL)
                 return (-1);
 

@@ -475,22 +673,23 @@
                 dprintf("Pgrab_core: failed to read NT_PRPRIV\n");
                 free(pprvp);
                 return (-1);
         }
 
-        P->core->core_priv = pprvp;
-        P->core->core_priv_size = nbytes;
+        core->core_priv = pprvp;
+        core->core_priv_size = nbytes;
         return (0);
 }
 
 static int
 note_priv_info(struct ps_prochandle *P, size_t nbytes)
 {
+        core_info_t *core = P->data;
         extern void *__priv_parse_info();
         priv_impl_info_t *ppii;
 
-        if (P->core->core_privinfo != NULL ||
+        if (core->core_privinfo != NULL ||
             nbytes < sizeof (priv_impl_info_t))
                 return (0);     /* Already seen or bad size */
 
         if ((ppii = malloc(nbytes)) == NULL)
                 return (-1);

@@ -500,21 +699,22 @@
                 dprintf("Pgrab_core: failed to read NT_PRPRIVINFO\n");
                 free(ppii);
                 return (-1);
         }
 
-        P->core->core_privinfo = __priv_parse_info(ppii);
-        P->core->core_ppii = ppii;
+        core->core_privinfo = __priv_parse_info(ppii);
+        core->core_ppii = ppii;
         return (0);
 }
 
 static int
 note_zonename(struct ps_prochandle *P, size_t nbytes)
 {
+        core_info_t *core = P->data;
         char *zonename;
 
-        if (P->core->core_zonename != NULL)
+        if (core->core_zonename != NULL)
                 return (0);     /* Already seen */
 
         if (nbytes != 0) {
                 if ((zonename = malloc(nbytes)) == NULL)
                         return (-1);

@@ -522,11 +722,11 @@
                         dprintf("Pgrab_core: failed to read NT_ZONENAME\n");
                         free(zonename);
                         return (-1);
                 }
                 zonename[nbytes - 1] = '\0';
-                P->core->core_zonename = zonename;
+                core->core_zonename = zonename;
         }
 
         return (0);
 }
 

@@ -534,11 +734,13 @@
 note_auxv(struct ps_prochandle *P, size_t nbytes)
 {
         size_t n, i;
 
 #ifdef _LP64
-        if (P->core->core_dmodel == PR_MODEL_ILP32) {
+        core_info_t *core = P->data;
+
+        if (core->core_dmodel == PR_MODEL_ILP32) {
                 auxv32_t *a32;
 
                 n = nbytes / sizeof (auxv32_t);
                 nbytes = n * sizeof (auxv32_t);
                 a32 = alloca(nbytes);

@@ -592,11 +794,12 @@
 
 #ifdef __sparc
 static int
 note_xreg(struct ps_prochandle *P, size_t nbytes)
 {
-        lwp_info_t *lwp = P->core->core_lwp;
+        core_info_t *core = P->data;
+        lwp_info_t *lwp = core->core_lwp;
         size_t xbytes = sizeof (prxregset_t);
         prxregset_t *xregs;
 
         if (lwp == NULL || lwp->lwp_xregs != NULL || nbytes < xbytes)
                 return (0);     /* No lwp yet, already seen, or bad size */

@@ -615,11 +818,12 @@
 }
 
 static int
 note_gwindows(struct ps_prochandle *P, size_t nbytes)
 {
-        lwp_info_t *lwp = P->core->core_lwp;
+        core_info_t *core = P->data;
+        lwp_info_t *lwp = core->core_lwp;
 
         if (lwp == NULL || lwp->lwp_gwins != NULL || nbytes == 0)
                 return (0);     /* No lwp yet or already seen or no data */
 
         if ((lwp->lwp_gwins = malloc(sizeof (gwindows_t))) == NULL)

@@ -630,11 +834,11 @@
          * actually saved, we just read up to the minimum of the note size
          * and the size of the gwindows_t type.  It doesn't matter if the read
          * fails since we have to zero out gwindows first anyway.
          */
 #ifdef _LP64
-        if (P->core->core_dmodel == PR_MODEL_ILP32) {
+        if (core->core_dmodel == PR_MODEL_ILP32) {
                 gwindows32_t g32;
 
                 (void) memset(&g32, 0, sizeof (g32));
                 (void) read(P->asfd, &g32, MIN(nbytes, sizeof (g32)));
                 gwindows_32_to_n(&g32, lwp->lwp_gwins);

@@ -652,11 +856,12 @@
 
 #ifdef __sparcv9
 static int
 note_asrs(struct ps_prochandle *P, size_t nbytes)
 {
-        lwp_info_t *lwp = P->core->core_lwp;
+        core_info_t *core = P->data;
+        lwp_info_t *lwp = core->core_lwp;
         int64_t *asrs;
 
         if (lwp == NULL || lwp->lwp_asrs != NULL || nbytes < sizeof (asrset_t))
                 return (0);     /* No lwp yet, already seen, or bad size */
 

@@ -677,11 +882,13 @@
 
 static int
 note_spymaster(struct ps_prochandle *P, size_t nbytes)
 {
 #ifdef _LP64
-        if (P->core->core_dmodel == PR_MODEL_ILP32) {
+        core_info_t *core = P->data;
+
+        if (core->core_dmodel == PR_MODEL_ILP32) {
                 psinfo32_t ps32;
 
                 if (nbytes < sizeof (psinfo32_t) ||
                     read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32))
                         goto err;

@@ -828,10 +1035,11 @@
  * PT_LOAD program header.  We fill in more information on the mapping later.
  */
 static int
 core_add_mapping(struct ps_prochandle *P, GElf_Phdr *php)
 {
+        core_info_t *core = P->data;
         prmap_t pmap;
 
         dprintf("mapping base %llx filesz %llu memsz %llu offset %llu\n",
             (u_longlong_t)php->p_vaddr, (u_longlong_t)php->p_filesz,
             (u_longlong_t)php->p_memsz, (u_longlong_t)php->p_offset);

@@ -843,11 +1051,11 @@
          * If Pgcore() or elfcore() fail to write a mapping, they will set
          * PF_SUNW_FAILURE in the Phdr and try to stash away the errno for us.
          */
         if (php->p_flags & PF_SUNW_FAILURE) {
                 core_report_mapping(P, php);
-        } else if (php->p_filesz != 0 && php->p_offset >= P->core->core_size) {
+        } else if (php->p_filesz != 0 && php->p_offset >= core->core_size) {
                 Perror_printf(P, "core file may be corrupt -- data for mapping "
                     "at %p is missing\n", (void *)(uintptr_t)php->p_vaddr);
                 dprintf("core file may be corrupt -- data for mapping "
                     "at %p is missing\n", (void *)(uintptr_t)php->p_vaddr);
         }

@@ -1479,10 +1687,11 @@
  * and attempt to construct a symbol table for the load object.
  */
 static int
 core_iter_mapping(const rd_loadobj_t *rlp, struct ps_prochandle *P)
 {
+        core_info_t *core = P->data;
         char lname[PATH_MAX], buf[PATH_MAX];
         file_info_t *fp;
         map_info_t *mp;
 
         if (Pread_string(P, lname, PATH_MAX, (off_t)rlp->rl_nameaddr) <= 0) {

@@ -1506,19 +1715,19 @@
          * file_info_new() will try to use its section headers to
          * identify any other mappings that belong to this load object.
          */
         if ((fp = mp->map_file) == NULL &&
             (fp = file_info_new(P, mp)) == NULL) {
-                P->core->core_errno = errno;
+                core->core_errno = errno;
                 dprintf("failed to malloc mapping data\n");
                 return (0); /* Abort */
         }
         fp->file_map = mp;
 
         /* Create a local copy of the load object representation */
         if ((fp->file_lo = calloc(1, sizeof (rd_loadobj_t))) == NULL) {
-                P->core->core_errno = errno;
+                core->core_errno = errno;
                 dprintf("failed to malloc mapping data\n");
                 return (0); /* Abort */
         }
         *fp->file_lo = *rlp;
 

@@ -1781,10 +1990,11 @@
  */
 struct ps_prochandle *
 Pfgrab_core(int core_fd, const char *aout_path, int *perr)
 {
         struct ps_prochandle *P;
+        core_info_t *core_info;
         map_info_t *stk_mp, *brk_mp;
         const char *execname;
         char *interp;
         int i, notes, pagesize;
         uintptr_t addr, base_addr;

@@ -1846,11 +2056,11 @@
         P->statfd = -1;
         P->agentctlfd = -1;
         P->agentstatfd = -1;
         P->zoneroot = NULL;
         P->info_valid = 1;
-        P->ops = &P_core_ops;
+        Pinit_ops(&P->ops, &P_core_ops);
 
         Pinitsym(P);
 
         /*
          * Fstat and open the core file and make sure it is a valid ELF core.

@@ -1865,32 +2075,33 @@
 
         /*
          * Allocate and initialize a core_info_t to hang off the ps_prochandle
          * structure.  We keep all core-specific information in this structure.
          */
-        if ((P->core = calloc(1, sizeof (core_info_t))) == NULL) {
+        if ((core_info = calloc(1, sizeof (core_info_t))) == NULL) {
                 *perr = G_STRANGE;
                 goto err;
         }
 
-        list_link(&P->core->core_lwp_head, NULL);
-        P->core->core_size = stbuf.st_size;
+        P->data = core_info;
+        list_link(&core_info->core_lwp_head, NULL);
+        core_info->core_size = stbuf.st_size;
         /*
          * In the days before adjustable core file content, this was the
          * default core file content. For new core files, this value will
          * be overwritten by the NT_CONTENT note section.
          */
-        P->core->core_content = CC_CONTENT_STACK | CC_CONTENT_HEAP |
+        core_info->core_content = CC_CONTENT_STACK | CC_CONTENT_HEAP |
             CC_CONTENT_DATA | CC_CONTENT_RODATA | CC_CONTENT_ANON |
             CC_CONTENT_SHANON;
 
         switch (core.e_hdr.e_ident[EI_CLASS]) {
         case ELFCLASS32:
-                P->core->core_dmodel = PR_MODEL_ILP32;
+                core_info->core_dmodel = PR_MODEL_ILP32;
                 break;
         case ELFCLASS64:
-                P->core->core_dmodel = PR_MODEL_LP64;
+                core_info->core_dmodel = PR_MODEL_LP64;
                 break;
         default:
                 *perr = G_FORMAT;
                 goto err;
         }

@@ -2112,11 +2323,11 @@
             dp->d_size != 0) {
                 dprintf(".interp = <%s>\n", (char *)dp->d_buf);
                 interp = dp->d_buf;
 
         } else if (base_addr != (uintptr_t)-1L) {
-                if (P->core->core_dmodel == PR_MODEL_LP64)
+                if (core_info->core_dmodel == PR_MODEL_LP64)
                         interp = "/usr/lib/64/ld.so.1";
                 else
                         interp = "/usr/lib/ld.so.1";
 
                 dprintf(".interp section is missing or could not be read; "

@@ -2227,12 +2438,12 @@
 
         if ((P->rap = rd_new(P)) != NULL) {
                 (void) rd_loadobj_iter(P->rap, (rl_iter_f *)
                     core_iter_mapping, P);
 
-                if (P->core->core_errno != 0) {
-                        errno = P->core->core_errno;
+                if (core_info->core_errno != 0) {
+                        errno = core_info->core_errno;
                         *perr = G_STRANGE;
                         goto err;
                 }
         } else
                 dprintf("failed to initialize rtld_db agent\n");