📄 pcore.c
字号:
/* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only. * See the file usr/src/LICENSING.NOTICE in this distribution or * http://www.opensolaris.org/license/ for details. */#pragma ident "@(#)Pcore.c 1.23 04/11/15 SMI"#include <sys/types.h>#include <sys/utsname.h>#include <sys/sysmacros.h>#include <alloca.h>#include <rtld_db.h>#include <libgen.h>#include <limits.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <gelf.h>#include <stddef.h>#include "Pcontrol.h"#include "P32ton.h"#include "Putil.h"/* * Pcore.c - Code to initialize a ps_prochandle from a core dump. We * allocate an additional structure to hold information from the core * file, and attach this to the standard ps_prochandle in place of the * ability to examine /proc/<pid>/ files. *//* * Basic i/o function for reading and writing from the process address space * stored in the core file and associated shared libraries. We compute the * appropriate fd and offsets, and let the provided prw function do the rest. */static ssize_tcore_rw(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr, ssize_t (*prw)(int, void *, size_t, off64_t)){ ssize_t resid = n; while (resid != 0) { map_info_t *mp = Paddr2mptr(P, addr); uintptr_t mapoff; ssize_t len; off64_t off; int fd; if (mp == NULL) break; /* No mapping for this address */ if (mp->map_pmap.pr_mflags & MA_RESERVED1) { if (mp->map_file == NULL || mp->map_file->file_fd < 0) break; /* No file or file not open */ fd = mp->map_file->file_fd; } else fd = P->asfd; mapoff = addr - mp->map_pmap.pr_vaddr; len = MIN(resid, mp->map_pmap.pr_size - mapoff); off = mp->map_offset + mapoff; if ((len = prw(fd, buf, len, off)) <= 0) break; resid -= len; addr += len; buf = (char *)buf + len; } /* * Important: Be consistent with the behavior of i/o on the as file: * writing to an invalid address yields EIO; reading from an invalid * address falls through to returning success and zero bytes. */ if (resid == n && n != 0 && prw != pread64) { errno = EIO; return (-1); } return (n - resid);}static ssize_tPread_core(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr){ return (core_rw(P, buf, n, addr, pread64));}static ssize_tPwrite_core(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr){ 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 };/* * 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); lwp_info_t *next; uint_t i; for (i = 0; i < P->core->core_nlwp; i++, lwp = list_next(lwp)) { if (lwp->lwp_id == id) { P->core->core_lwp = lwp; return (lwp); } if (lwp->lwp_id < id) { break; } } next = lwp; if ((lwp = calloc(1, sizeof (lwp_info_t))) == NULL) return (NULL); list_link(lwp, next); lwp->lwp_id = id; P->core->core_lwp = lwp; P->core->core_nlwp++; return (lwp);}/* * The core file itself contains a series of NOTE segments containing saved * structures from /proc at the time the process died. For each note we * comprehend, we define a function to read it in from the core file, * convert it to our native data model if necessary, and store it inside * the ps_prochandle. Each function is invoked by Pfgrab_core() with the * seek pointer on P->asfd positioned appropriately. We populate a table * of pointers to these note functions below. */static intnote_pstatus(struct ps_prochandle *P, size_t nbytes){#ifdef _LP64 if (P->core->core_dmodel == PR_MODEL_ILP32) { pstatus32_t ps32; if (nbytes < sizeof (pstatus32_t) || read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32)) goto err; pstatus_32_to_n(&ps32, &P->status); } else#endif if (nbytes < sizeof (pstatus_t) || read(P->asfd, &P->status, sizeof (pstatus_t)) != sizeof (pstatus_t)) goto err; P->orig_status = P->status; P->pid = P->status.pr_pid; return (0);err: dprintf("Pgrab_core: failed to read NT_PSTATUS\n"); return (-1);}static intnote_lwpstatus(struct ps_prochandle *P, size_t nbytes){ lwp_info_t *lwp; lwpstatus_t lps;#ifdef _LP64 if (P->core->core_dmodel == PR_MODEL_ILP32) { lwpstatus32_t l32; if (nbytes < sizeof (lwpstatus32_t) || read(P->asfd, &l32, sizeof (l32)) != sizeof (l32)) goto err; lwpstatus_32_to_n(&l32, &lps); } else#endif if (nbytes < sizeof (lwpstatus_t) || read(P->asfd, &lps, sizeof (lps)) != sizeof (lps)) goto err; if ((lwp = lwpid2info(P, lps.pr_lwpid)) == NULL) { dprintf("Pgrab_core: failed to add NT_LWPSTATUS\n"); return (-1); } /* * Erase a useless and confusing artifact of the kernel implementation: * the lwps which did *not* create the core will show SIGKILL. We can * be assured this is bogus because SIGKILL can't produce core files. */ if (lps.pr_cursig == SIGKILL) lps.pr_cursig = 0; (void) memcpy(&lwp->lwp_status, &lps, sizeof (lps)); return (0);err: dprintf("Pgrab_core: failed to read NT_LWPSTATUS\n"); return (-1);}static intnote_psinfo(struct ps_prochandle *P, size_t nbytes){#ifdef _LP64 if (P->core->core_dmodel == PR_MODEL_ILP32) { psinfo32_t ps32; if (nbytes < sizeof (psinfo32_t) || read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32)) goto err; psinfo_32_to_n(&ps32, &P->psinfo); } else#endif if (nbytes < sizeof (psinfo_t) || read(P->asfd, &P->psinfo, sizeof (psinfo_t)) != sizeof (psinfo_t)) goto err; dprintf("pr_fname = <%s>\n", P->psinfo.pr_fname); dprintf("pr_psargs = <%s>\n", P->psinfo.pr_psargs); dprintf("pr_wstat = 0x%x\n", P->psinfo.pr_wstat); return (0);err: dprintf("Pgrab_core: failed to read NT_PSINFO\n"); return (-1);}static intnote_lwpsinfo(struct ps_prochandle *P, size_t nbytes){ lwp_info_t *lwp; lwpsinfo_t lps;#ifdef _LP64 if (P->core->core_dmodel == PR_MODEL_ILP32) { lwpsinfo32_t l32; if (nbytes < sizeof (lwpsinfo32_t) || read(P->asfd, &l32, sizeof (l32)) != sizeof (l32)) goto err; lwpsinfo_32_to_n(&l32, &lps); } else#endif if (nbytes < sizeof (lwpsinfo_t) || read(P->asfd, &lps, sizeof (lps)) != sizeof (lps)) goto err; if ((lwp = lwpid2info(P, lps.pr_lwpid)) == NULL) { dprintf("Pgrab_core: failed to add NT_LWPSINFO\n"); return (-1); } (void) memcpy(&lwp->lwp_psinfo, &lps, sizeof (lps)); return (0);err: dprintf("Pgrab_core: failed to read NT_LWPSINFO\n"); return (-1);}static intnote_platform(struct ps_prochandle *P, size_t nbytes){ char *plat; if (P->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; } return (0);}static intnote_utsname(struct ps_prochandle *P, size_t nbytes){ size_t ubytes = sizeof (struct utsname); struct utsname *utsp; if (P->core->core_uts != NULL || nbytes < ubytes) return (0); /* Already seen or bad size */ if ((utsp = malloc(ubytes)) == NULL) return (-1); if (read(P->asfd, utsp, ubytes) != ubytes) { dprintf("Pgrab_core: failed to read NT_UTSNAME\n"); free(utsp); return (-1); } if (_libproc_debug) { dprintf("uts.sysname = \"%s\"\n", utsp->sysname); dprintf("uts.nodename = \"%s\"\n", utsp->nodename); 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; return (0);}static intnote_content(struct ps_prochandle *P, size_t nbytes){ core_content_t content; if (sizeof (P->core->core_content) != nbytes) return (-1); if (read(P->asfd, &content, sizeof (content)) != sizeof (content)) return (-1); P->core->core_content = content; dprintf("core content = %llx\n", content); return (0);}static intnote_cred(struct ps_prochandle *P, size_t nbytes){ prcred_t *pcrp; int ngroups; const size_t min_size = sizeof (prcred_t) - sizeof (gid_t); /* * 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) return (0); /* Already seen or bad size */ ngroups = (nbytes - min_size) / sizeof (gid_t); nbytes = sizeof (prcred_t) + (ngroups - 1) * sizeof (gid_t); if ((pcrp = malloc(nbytes)) == NULL) return (-1); if (read(P->asfd, pcrp, nbytes) != nbytes) { dprintf("Pgrab_core: failed to read NT_PRCRED\n"); free(pcrp); return (-1); } if (pcrp->pr_ngroups > ngroups) { 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; return (0);}#if defined(__i386) || defined(__amd64)static intnote_ldt(struct ps_prochandle *P, size_t nbytes){ struct ssd *pldt; uint_t nldt; if (P->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); if ((pldt = malloc(nbytes)) == NULL) return (-1); if (read(P->asfd, pldt, nbytes) != nbytes) { dprintf("Pgrab_core: failed to read NT_LDT\n"); free(pldt); return (-1); } P->core->core_ldt = pldt; P->core->core_nldt = nldt; return (0);}#endif /* __i386 */static intnote_priv(struct ps_prochandle *P, size_t nbytes){ prpriv_t *pprvp; if (P->core->core_priv != NULL || nbytes < sizeof (prpriv_t)) return (0); /* Already seen or bad size */ if ((pprvp = malloc(nbytes)) == NULL) return (-1); if (read(P->asfd, pprvp, nbytes) != nbytes) { dprintf("Pgrab_core: failed to read NT_PRPRIV\n"); free(pprvp); return (-1); } P->core->core_priv = pprvp; P->core->core_priv_size = nbytes; return (0);}static intnote_priv_info(struct ps_prochandle *P, size_t nbytes){ extern void *__priv_parse_info(); priv_impl_info_t *ppii; if (P->core->core_privinfo != NULL || nbytes < sizeof (priv_impl_info_t)) return (0); /* Already seen or bad size */ if ((ppii = malloc(nbytes)) == NULL) return (-1); if (read(P->asfd, ppii, nbytes) != nbytes || PRIV_IMPL_INFO_SIZE(ppii) != nbytes) { 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; return (0);}static intnote_zonename(struct ps_prochandle *P, size_t nbytes){ char *zonename; if (P->core->core_zonename != NULL) return (0); /* Already seen */ if (nbytes != 0) { if ((zonename = malloc(nbytes)) == NULL) return (-1); if (read(P->asfd, zonename, nbytes) != nbytes) { dprintf("Pgrab_core: failed to read NT_ZONENAME\n"); free(zonename); return (-1); } zonename[nbytes - 1] = '\0'; P->core->core_zonename = zonename; } return (0);}static intnote_auxv(struct ps_prochandle *P, size_t nbytes){ size_t n, i;#ifdef _LP64 if (P->core->core_dmodel == PR_MODEL_ILP32) { auxv32_t *a32; n = nbytes / sizeof (auxv32_t); nbytes = n * sizeof (auxv32_t); a32 = alloca(nbytes); if (read(P->asfd, a32, nbytes) != nbytes) { dprintf("Pgrab_core: failed to read NT_AUXV\n"); return (-1); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -