⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcore.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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 + -