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

📄 pcore.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 4 页
字号:
	/*	 * Allocate and initialize a ps_prochandle structure for the core.	 * There are several key pieces of initialization here:	 *	 * 1. The PS_DEAD state flag marks this prochandle as a core file.	 *    PS_DEAD also thus prevents all operations which require state	 *    to be PS_STOP from operating on this handle.	 *	 * 2. We keep the core file fd in P->asfd since the core file contains	 *    the remnants of the process address space.	 *	 * 3. We set the P->info_valid bit because all information about the	 *    core is determined by the end of this function; there is no need	 *    for proc_update_maps() to reload mappings at any later point.	 *	 * 4. The read/write ops vector uses our core_rw() function defined	 *    above to handle i/o requests.	 */	if ((P = malloc(sizeof (struct ps_prochandle))) == NULL) {		*perr = G_STRANGE;		return (NULL);	}	(void) memset(P, 0, sizeof (struct ps_prochandle));	(void) mutex_init(&P->proc_lock, USYNC_THREAD, NULL);	P->state = PS_DEAD;	P->pid = (pid_t)-1;	P->asfd = core.e_fd;	P->ctlfd = -1;	P->statfd = -1;	P->agentctlfd = -1;	P->agentstatfd = -1;	P->info_valid = 1;	P->ops = &P_core_ops;	Pinitsym(P);	/*	 * Fstat and open the core file and make sure it is a valid ELF core.	 */	if (fstat64(P->asfd, &stbuf) == -1) {		*perr = G_STRANGE;		goto err;	}	if (core_elf_fdopen(&core, ET_CORE, perr) == -1)		goto err;	/*	 * 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 = malloc(sizeof (core_info_t))) == NULL) {		*perr = G_STRANGE;		goto err;	}	list_link(&P->core->core_lwp_head, NULL);	P->core->core_errno = 0;	P->core->core_lwp = NULL;	P->core->core_nlwp = 0;	P->core->core_size = stbuf.st_size;	P->core->core_platform = NULL;	P->core->core_uts = NULL;	P->core->core_cred = NULL;	/*	 * 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 |	    CC_CONTENT_DATA | CC_CONTENT_RODATA | CC_CONTENT_ANON |	    CC_CONTENT_SHANON;	P->core->core_priv = NULL;	P->core->core_priv_size = 0;	P->core->core_privinfo = NULL;	P->core->core_zonename = NULL;	P->core->core_ppii = NULL;#if defined(__i386) || defined(__amd64)	P->core->core_ldt = NULL;	P->core->core_nldt = 0;#endif	switch (core.e_hdr.e_ident[EI_CLASS]) {	case ELFCLASS32:		P->core->core_dmodel = PR_MODEL_ILP32;		break;	case ELFCLASS64:		P->core->core_dmodel = PR_MODEL_LP64;		break;	default:		*perr = G_FORMAT;		goto err;	}	/*	 * Because the core file may be a large file, we can't use libelf to	 * read the Phdrs.  We use e_phnum and e_phentsize to simplify things.	 */	nbytes = core.e_hdr.e_phnum * core.e_hdr.e_phentsize;	if ((phbuf = malloc(nbytes)) == NULL) {		*perr = G_STRANGE;		goto err;	}	if (pread64(core_fd, phbuf, nbytes, core.e_hdr.e_phoff) != nbytes) {		*perr = G_STRANGE;		free(phbuf);		goto err;	}	/*	 * First, determine the number of mappings in the corefile	 */	nmap = 0;	for (php = phbuf, notes = 0, i = 0; i < core.e_hdr.e_phnum; i++) {		if (core.e_hdr.e_ident[EI_CLASS] == ELFCLASS64)			(void) memcpy(&phdr, php, sizeof (GElf_Phdr));		else			core_phdr_to_gelf(php, &phdr);		if (phdr.p_type == PT_LOAD)			nmap++;		php = (char *)php + core.e_hdr.e_phentsize;	}	if (nmap != 0)		P->mappings = malloc(nmap * sizeof (map_info_t));	/*	 * Now iterate through the program headers in the core file.	 * We're interested in two types of Phdrs: PT_NOTE (which	 * contains a set of saved /proc structures), and PT_LOAD (which	 * represents a memory mapping from the process's address space).	 * In the case of PT_NOTE, we're interested in the last PT_NOTE	 * in the core file; currently the first PT_NOTE (if present)	 * contains /proc structs in the pre-2.6 unstructured /proc format.	 */	for (php = phbuf, notes = 0, i = 0; i < core.e_hdr.e_phnum; i++) {		if (core.e_hdr.e_ident[EI_CLASS] == ELFCLASS64)			(void) memcpy(&phdr, php, sizeof (GElf_Phdr));		else			core_phdr_to_gelf(php, &phdr);		switch (phdr.p_type) {		case PT_NOTE:			note_phdr = phdr;			notes++;			break;		case PT_LOAD:			if (core_add_mapping(P, &phdr) == -1) {				*perr = G_STRANGE;				free(phbuf);				goto err;			}			break;		}		php = (char *)php + core.e_hdr.e_phentsize;	}	free(phbuf);	/*	 * If we couldn't find anything of type PT_NOTE, or only one PT_NOTE	 * was present, abort.  The core file is either corrupt or too old.	 */	if (notes == 0 || notes == 1) {		*perr = G_NOTE;		goto err;	}	/*	 * Advance the seek pointer to the start of the PT_NOTE data	 */	if (lseek64(P->asfd, note_phdr.p_offset, SEEK_SET) == (off64_t)-1) {		dprintf("Pgrab_core: failed to lseek to PT_NOTE data\n");		*perr = G_STRANGE;		goto err;	}	/*	 * Now process the PT_NOTE structures.  Each one is preceded by	 * an Elf{32/64}_Nhdr structure describing its type and size.	 *	 *  +--------+	 *  | header |	 *  +--------+	 *  | name   |	 *  | ...    |	 *  +--------+	 *  | desc   |	 *  | ...    |	 *  +--------+	 */	for (nleft = note_phdr.p_filesz; nleft > 0; ) {		Elf64_Nhdr nhdr;		off64_t off, namesz;		/*		 * Although <sys/elf.h> defines both Elf32_Nhdr and Elf64_Nhdr		 * as different types, they are both of the same content and		 * size, so we don't need to worry about 32/64 conversion here.		 */		if (read(P->asfd, &nhdr, sizeof (nhdr)) != sizeof (nhdr)) {			dprintf("Pgrab_core: failed to read ELF note header\n");			*perr = G_NOTE;			goto err;		}		/*		 * According to the System V ABI, the amount of padding		 * following the name field should align the description		 * field on a 4 byte boundary for 32-bit binaries or on an 8		 * byte boundary for 64-bit binaries. However, this change		 * was not made correctly during the 64-bit port so all		 * descriptions can assume only 4-byte alignment. We ignore		 * the name field and the padding to 4-byte alignment.		 */		namesz = P2ROUNDUP((off64_t)nhdr.n_namesz, (off64_t)4);		if (lseek64(P->asfd, namesz, SEEK_CUR) == (off64_t)-1) {			dprintf("failed to seek past name and padding\n");			*perr = G_STRANGE;			goto err;		}		dprintf("Note hdr n_type=%u n_namesz=%u n_descsz=%u\n",		    nhdr.n_type, nhdr.n_namesz, nhdr.n_descsz);		off = lseek64(P->asfd, (off64_t)0L, SEEK_CUR);		/*		 * Invoke the note handler function from our table		 */		if (nhdr.n_type < sizeof (nhdlrs) / sizeof (nhdlrs[0])) {			if (nhdlrs[nhdr.n_type](P, nhdr.n_descsz) < 0) {				*perr = G_NOTE;				goto err;			}		} else			(void) note_notsup(P, nhdr.n_descsz);		/*		 * Seek past the current note data to the next Elf_Nhdr		 */		if (lseek64(P->asfd, off + nhdr.n_descsz,		    SEEK_SET) == (off64_t)-1) {			dprintf("Pgrab_core: failed to seek to next nhdr\n");			*perr = G_STRANGE;			goto err;		}		/*		 * Subtract the size of the header and its data from what		 * we have left to process.		 */		nleft -= sizeof (nhdr) + namesz + nhdr.n_descsz;	}	if (nleft != 0) {		dprintf("Pgrab_core: note section malformed\n");		*perr = G_STRANGE;		goto err;	}	if ((pagesize = Pgetauxval(P, AT_PAGESZ)) == -1) {		pagesize = getpagesize();		dprintf("AT_PAGESZ missing; defaulting to %d\n", pagesize);	}	qsort(P->mappings, P->map_count, sizeof (map_info_t),	    core_cmp_mapping);	/*	 * Locate and label the mappings corresponding to the end of the	 * heap (MA_BREAK) and the base of the stack (MA_STACK).	 */	if ((P->status.pr_brkbase != 0 || P->status.pr_brksize != 0) &&	    (brk_mp = Paddr2mptr(P, P->status.pr_brkbase +	    P->status.pr_brksize - 1)) != NULL)		brk_mp->map_pmap.pr_mflags |= MA_BREAK;	else		brk_mp = NULL;	if ((stk_mp = Paddr2mptr(P, P->status.pr_stkbase)) != NULL)		stk_mp->map_pmap.pr_mflags |= MA_STACK;	/*	 * At this point, we have enough information to look for the	 * executable and open it: we have access to the auxv, a psinfo_t,	 * and the ability to read from mappings provided by the core file.	 */	(void) Pfindexec(P, aout_path, core_exec_open, &aout);	dprintf("P->execname = \"%s\"\n", P->execname ? P->execname : "NULL");	execname = P->execname ? P->execname : "a.out";	/*	 * Iterate through the sections, looking for the .dynamic and .interp	 * sections.  If we encounter them, remember their section pointers.	 */	for (scn = NULL; (scn = elf_nextscn(aout.e_elf, scn)) != NULL; ) {		char *sname;		if ((gelf_getshdr(scn, &shdr) == NULL) ||		    (sname = elf_strptr(aout.e_elf, aout.e_hdr.e_shstrndx,		    (size_t)shdr.sh_name)) == NULL)			continue;		if (strcmp(sname, ".interp") == 0)			intp_scn = scn;	}	/*	 * Get the AT_BASE auxv element.  If this is missing (-1), then	 * we assume this is a statically-linked executable.	 */	base_addr = Pgetauxval(P, AT_BASE);	/*	 * In order to get librtld_db initialized, we'll need to identify	 * and name the mapping corresponding to the run-time linker.  The	 * AT_BASE auxv element tells us the address where it was mapped,	 * and the .interp section of the executable tells us its path.	 * If for some reason that doesn't pan out, just use ld.so.1.	 */	if (intp_scn != NULL && (dp = elf_getdata(intp_scn, NULL)) != NULL &&	    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)			interp = "/usr/lib/64/ld.so.1";		else			interp = "/usr/lib/ld.so.1";		dprintf(".interp section is missing or could not be read; "		    "defaulting to %s\n", interp);	} else		dprintf("detected statically linked executable\n");	/*	 * If we have an AT_BASE element, name the mapping at that address	 * using the interpreter pathname.  Name the corresponding data	 * mapping after the interpreter as well.	 */	if (base_addr != (uintptr_t)-1L) {		elf_file_t intf;		P->map_ldso = core_name_mapping(P, base_addr, interp);		if (core_elf_open(&intf, interp, ET_DYN, NULL) == 0) {			rd_loadobj_t rl;			map_info_t *dmp;			rl.rl_base = base_addr;			dmp = core_find_data(P, intf.e_elf, &rl);			if (dmp != NULL) {				dprintf("renamed data at %p to %s\n",				    (void *)rl.rl_data_base, interp);				(void) strncpy(dmp->map_pmap.pr_mapname,				    interp, PRMAPSZ);				dmp->map_pmap.pr_mapname[PRMAPSZ - 1] = '\0';			}		}		core_elf_close(&intf);	}	/*	 * If we have an AT_ENTRY element, name the mapping at that address	 * using the special name "a.out" just like /proc does.	 */	if ((addr = Pgetauxval(P, AT_ENTRY)) != (uintptr_t)-1L)		P->map_exec = core_name_mapping(P, addr, "a.out");	/*	 * If we're a statically linked executable, then just locate the	 * executable's text and data and name them after the executable.	 */	if (base_addr == (uintptr_t)-1L) {		map_info_t *tmp, *dmp;		file_info_t *fp;		rd_loadobj_t rl;		if ((tmp = core_find_text(P, aout.e_elf, &rl)) != NULL &&		    (dmp = core_find_data(P, aout.e_elf, &rl)) != NULL) {			(void) strncpy(tmp->map_pmap.pr_mapname,			    execname, PRMAPSZ);			tmp->map_pmap.pr_mapname[PRMAPSZ - 1] = '\0';			(void) strncpy(dmp->map_pmap.pr_mapname,			    execname, PRMAPSZ);			dmp->map_pmap.pr_mapname[PRMAPSZ - 1] = '\0';		}		if ((P->map_exec = tmp) != NULL &&		    (fp = malloc(sizeof (file_info_t))) != NULL) {			(void) memset(fp, 0, sizeof (file_info_t));			list_link(fp, &P->file_head);			tmp->map_file = fp;			P->num_files++;			fp->file_ref = 1;			fp->file_fd = -1;			fp->file_lo = malloc(sizeof (rd_loadobj_t));			fp->file_lname = strdup(execname);			if (fp->file_lo)				*fp->file_lo = rl;			if (fp->file_lname)				fp->file_lbase = basename(fp->file_lname);			(void) strcpy(fp->file_pname,			    P->mappings[0].map_pmap.pr_mapname);			fp->file_map = tmp;			Pbuild_file_symtab(P, fp);			if (dmp != NULL) {				dmp->map_file = fp;				fp->file_ref++;			}		}	}	core_elf_close(&aout);	/*	 * We now have enough information to initialize librtld_db.	 * After it warms up, we can iterate through the load object chain	 * in the core, which will allow us to construct the file info	 * we need to provide symbol information for the other shared	 * libraries, and also to fill in the missing mapping names.	 */	rd_log(_libproc_debug);	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;			*perr = G_STRANGE;			goto err;		}	} else		dprintf("failed to initialize rtld_db agent\n");	/*	 * If there are sections, load them and process the data from any	 * sections that we can use to annotate the file_info_t's.	 */	core_load_shdrs(P, &core);	/*	 * If we previously located a stack or break mapping, and they are	 * still anonymous, we now assume that they were MAP_ANON mappings.	 * If brk_mp turns out to now have a name, then the heap is still	 * sitting at the end of the executable's data+bss mapping: remove	 * the previous MA_BREAK setting to be consistent with /proc.	 */	if (stk_mp != NULL && stk_mp->map_pmap.pr_mapname[0] == '\0')		stk_mp->map_pmap.pr_mflags |= MA_ANON;	if (brk_mp != NULL && brk_mp->map_pmap.pr_mapname[0] == '\0')		brk_mp->map_pmap.pr_mflags |= MA_ANON;	else if (brk_mp != NULL)		brk_mp->map_pmap.pr_mflags &= ~MA_BREAK;	*perr = 0;	return (P);err:	Pfree(P);	core_elf_close(&aout);	return (NULL);}/* * Grab a core file using a pathname.  We just open it and call Pfgrab_core(). */struct ps_prochandle *Pgrab_core(const char *core, const char *aout, int gflag, int *perr){	int fd, oflag = (gflag & PGRAB_RDONLY) ? O_RDONLY : O_RDWR;	if ((fd = open64(core, oflag)) >= 0)		return (Pfgrab_core(fd, aout, perr));	if (errno != ENOENT)		*perr = G_STRANGE;	else		*perr = G_NOCORE;	return (NULL);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -