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

📄 pcore.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 4 页
字号:
{#ifdef _BIG_ENDIAN	uchar_t order = ELFDATA2MSB;#else	uchar_t order = ELFDATA2LSB;#endif	Elf32_Ehdr e32;	int is_noelf = -1;	int isa_err = 0;	/*	 * Because 32-bit libelf cannot deal with large files, we need to read,	 * check, and convert the file header manually in case type == ET_CORE.	 */	if (pread64(efp->e_fd, &e32, sizeof (e32), 0) != sizeof (e32)) {		if (perr != NULL)			*perr = G_FORMAT;		goto err;	}	if ((is_noelf = memcmp(&e32.e_ident[EI_MAG0], ELFMAG, SELFMAG)) != 0 ||	    e32.e_type != type || (isa_err = (e32.e_ident[EI_DATA] != order)) ||	    e32.e_version != EV_CURRENT) {		if (perr != NULL) {			if (is_noelf == 0 && isa_err) {				*perr = G_ISAINVAL;			} else {				*perr = G_FORMAT;			}		}		goto err;	}	/*	 * If the file is 64-bit and we are 32-bit, fail with G_LP64.  If the	 * file is 64-bit and we are 64-bit, re-read the header as a Elf64_Ehdr.	 * Otherwise, the file is 32-bit, so convert e32 to a GElf_Ehdr.	 */	if (e32.e_ident[EI_CLASS] == ELFCLASS64) {#ifdef _LP64		if (pread64(efp->e_fd, &efp->e_hdr,		    sizeof (GElf_Ehdr), 0) != sizeof (GElf_Ehdr)) {			if (perr != NULL)				*perr = G_FORMAT;			goto err;		}#else	/* _LP64 */		if (perr != NULL)			*perr = G_LP64;		goto err;#endif	/* _LP64 */	} else		core_ehdr_to_gelf(&e32, &efp->e_hdr);	/*	 * The libelf implementation was never ported to be large-file aware.	 * This is typically not a problem for your average executable or	 * shared library, but a large 32-bit core file can exceed 2GB in size.	 * So if type is ET_CORE, we don't bother doing elf_begin; the code	 * in Pfgrab_core() below will do its own i/o and struct conversion.	 */	if (type == ET_CORE) {		efp->e_elf = NULL;		return (0);	}	if ((efp->e_elf = elf_begin(efp->e_fd, ELF_C_READ, NULL)) == NULL) {		if (perr != NULL)			*perr = G_ELF;		goto err;	}	return (0);err:	efp->e_elf = NULL;	return (-1);}/* * Open the specified file and then do a core_elf_fdopen on it. */static intcore_elf_open(elf_file_t *efp, const char *path, GElf_Half type, int *perr){	(void) memset(efp, 0, sizeof (elf_file_t));	if ((efp->e_fd = open64(path, O_RDONLY)) >= 0) {		if (core_elf_fdopen(efp, type, perr) == 0)			return (0);		(void) close(efp->e_fd);		efp->e_fd = -1;	}	return (-1);}/* * Close the ELF handle and file descriptor. */static voidcore_elf_close(elf_file_t *efp){	if (efp->e_elf != NULL) {		(void) elf_end(efp->e_elf);		efp->e_elf = NULL;	}	if (efp->e_fd != -1) {		(void) close(efp->e_fd);		efp->e_fd = -1;	}}/* * Given an ELF file for a statically linked executable, locate the likely * primary text section and fill in rl_base with its virtual address. */static map_info_t *core_find_text(struct ps_prochandle *P, Elf *elf, rd_loadobj_t *rlp){	GElf_Ehdr ehdr;	GElf_Phdr phdr;	uint_t i;	if (gelf_getehdr(elf, &ehdr) != NULL) {		for (i = 0; i < ehdr.e_phnum; i++) {			if (gelf_getphdr(elf, i, &phdr) != NULL &&			    phdr.p_type == PT_LOAD && (phdr.p_flags & PF_X)) {				rlp->rl_base = phdr.p_vaddr;				return (Paddr2mptr(P, rlp->rl_base));			}		}	}	return (NULL);}/* * Given an ELF file and the librtld_db structure corresponding to its primary * text mapping, deduce where its data segment was loaded and fill in * rl_data_base and prmap_t.pr_offset accordingly. */static map_info_t *core_find_data(struct ps_prochandle *P, Elf *elf, rd_loadobj_t *rlp){	GElf_Ehdr ehdr;	GElf_Phdr phdr;	map_info_t *mp;	uint_t i, pagemask;	rlp->rl_data_base = NULL;	/*	 * Find the first loadable, writeable Phdr and compute rl_data_base	 * as the virtual address at which is was loaded.	 */	if (gelf_getehdr(elf, &ehdr) != NULL) {		for (i = 0; i < ehdr.e_phnum; i++) {			if (gelf_getphdr(elf, i, &phdr) != NULL &&			    phdr.p_type == PT_LOAD && (phdr.p_flags & PF_W)) {				rlp->rl_data_base = phdr.p_vaddr;				if (ehdr.e_type == ET_DYN)					rlp->rl_data_base += rlp->rl_base;				break;			}		}	}	/*	 * If we didn't find an appropriate phdr or if the address we	 * computed has no mapping, return NULL.	 */	if (rlp->rl_data_base == NULL ||	    (mp = Paddr2mptr(P, rlp->rl_data_base)) == NULL)		return (NULL);	/*	 * It wouldn't be procfs-related code if we didn't make use of	 * unclean knowledge of segvn, even in userland ... the prmap_t's	 * pr_offset field will be the segvn offset from mmap(2)ing the	 * data section, which will be the file offset & PAGEMASK.	 */	pagemask = ~(mp->map_pmap.pr_pagesize - 1);	mp->map_pmap.pr_offset = phdr.p_offset & pagemask;	return (mp);}/* * Librtld_db agent callback for iterating over load object mappings. * For each load object, we allocate a new file_info_t, perform naming, * and attempt to construct a symbol table for the load object. */static intcore_iter_mapping(const rd_loadobj_t *rlp, struct ps_prochandle *P){	char lname[PATH_MAX];	file_info_t *fp;	map_info_t *mp;	if (Pread_string(P, lname, PATH_MAX, (off_t)rlp->rl_nameaddr) <= 0) {		dprintf("failed to read name %p\n", (void *)rlp->rl_nameaddr);		return (1); /* Keep going; forget this if we can't get a name */	}	dprintf("rd_loadobj name = \"%s\" rl_base = %p\n",	    lname, (void *)rlp->rl_base);	if ((mp = Paddr2mptr(P, rlp->rl_base)) == NULL) {		dprintf("no mapping for %p\n", (void *)rlp->rl_base);		return (1); /* No mapping; advance to next mapping */	}	if ((fp = mp->map_file) == NULL) {		if ((fp = malloc(sizeof (file_info_t))) == NULL) {			P->core->core_errno = errno;			dprintf("failed to malloc mapping data\n");			return (0); /* Abort */		}		(void) memset(fp, 0, sizeof (file_info_t));		list_link(fp, &P->file_head);		mp->map_file = fp;		P->num_files++;		fp->file_ref = 1;		fp->file_fd = -1;	}	if ((fp->file_lo = malloc(sizeof (rd_loadobj_t))) == NULL) {		P->core->core_errno = errno;		dprintf("failed to malloc mapping data\n");		return (0); /* Abort */	}	*fp->file_lo = *rlp;	if (fp->file_lname == NULL &&	    strcmp(mp->map_pmap.pr_mapname, "a.out") == 0) {		/*		 * Naming dance part 1: if the file_info_t is unnamed and		 * it represents the main executable, name it after the		 * execname.		 */		fp->file_lname = P->execname ?		    strdup(P->execname) : strdup("a.out");	}	if (lname[0] != '\0') {		/*		 * Naming dance part 2: if we got a name from librtld_db, then		 * copy this name to the prmap_t if it is unnamed.  If the		 * file_info_t is unnamed, name it after the lname.		 */		if (mp->map_pmap.pr_mapname[0] == '\0') {			(void) strncpy(mp->map_pmap.pr_mapname, lname, PRMAPSZ);			mp->map_pmap.pr_mapname[PRMAPSZ - 1] = '\0';		}		if (fp->file_lname == NULL)			fp->file_lname = strdup(lname);	} else if (fp->file_lname == NULL &&	    mp->map_pmap.pr_mapname[0] != '\0') {		/*		 * Naming dance part 3: if the mapping is named and the		 * file_info_t is not, name the file after the mapping.		 */		fp->file_lname = strdup(mp->map_pmap.pr_mapname);	}	if (fp->file_lname != NULL)		fp->file_lbase = basename(fp->file_lname);	/*	 * Associate the file and the mapping, and attempt to build	 * a symbol table for this file.	 */	(void) strcpy(fp->file_pname, mp->map_pmap.pr_mapname);	fp->file_map = mp;	Pbuild_file_symtab(P, fp);	if (fp->file_elf == NULL)		return (1); /* No symbol table; advance to next mapping */	/*	 * Locate the start of a data segment associated with this file,	 * name it after the file, and establish the mp->map_file link:	 */	if ((mp = core_find_data(P, fp->file_elf, fp->file_lo)) != NULL) {		dprintf("found data for %s at %p (pr_offset 0x%llx)\n",		    fp->file_pname, (void *)fp->file_lo->rl_data_base,		    mp->map_pmap.pr_offset);		for (; mp < P->mappings + P->map_count; mp++) {			if (mp->map_pmap.pr_vaddr > fp->file_lo->rl_bend)				break;			if (mp->map_file == NULL) {				mp->map_file = fp;				fp->file_ref++;			}			if (!(mp->map_pmap.pr_mflags & MA_BREAK))				(void) strcpy(mp->map_pmap.pr_mapname,				    fp->file_pname);		}	}	return (1); /* Advance to next mapping */}/* * Callback function for Pfindexec().  In order to confirm a given pathname, * we verify that we can open it as an ELF file of type ET_EXEC. */static intcore_exec_open(const char *path, void *efp){	return (core_elf_open(efp, path, ET_EXEC, NULL) == 0);}/* * Attempt to load any section headers found in the core file.  If present, * this will refer to non-loadable data added to the core file by the kernel * based on coreadm(1M) settings, including CTF data and the symbol table. */static voidcore_load_shdrs(struct ps_prochandle *P, elf_file_t *efp){	GElf_Shdr *shp, *shdrs = NULL;	char *shstrtab = NULL;	ulong_t shstrtabsz;	const char *name;	map_info_t *mp;	size_t nbytes;	void *buf;	int i;	if (efp->e_hdr.e_shstrndx >= efp->e_hdr.e_shnum) {		dprintf("corrupt shstrndx (%u) exceeds shnum (%u)\n",		    (uint_t)efp->e_hdr.e_shstrndx, (uint_t)efp->e_hdr.e_shnum);		return;	}	/*	 * Read the section header table from the core file and then iterate	 * over the section headers, converting each to a GElf_Shdr.	 */	shdrs = malloc(efp->e_hdr.e_shnum * sizeof (GElf_Shdr));	nbytes = efp->e_hdr.e_shnum * efp->e_hdr.e_shentsize;	buf = malloc(nbytes);	if (shdrs == NULL || buf == NULL) {		dprintf("failed to malloc %u section headers: %s\n",		    (uint_t)efp->e_hdr.e_shnum, strerror(errno));		free(buf);		goto out;	}	if (pread64(efp->e_fd, buf, nbytes, efp->e_hdr.e_shoff) != nbytes) {		dprintf("failed to read section headers at off %lld: %s\n",		    (longlong_t)efp->e_hdr.e_shoff, strerror(errno));		free(buf);		goto out;	}	for (i = 0; i < efp->e_hdr.e_shnum; i++) {		void *p = (uchar_t *)buf + efp->e_hdr.e_shentsize * i;		if (efp->e_hdr.e_ident[EI_CLASS] == ELFCLASS32)			core_shdr_to_gelf(p, &shdrs[i]);		else			(void) memcpy(&shdrs[i], p, sizeof (GElf_Shdr));	}	free(buf);	buf = NULL;	/*	 * Read the .shstrtab section from the core file, terminating it with	 * an extra \0 so that a corrupt section will not cause us to die.	 */	shp = &shdrs[efp->e_hdr.e_shstrndx];	shstrtabsz = shp->sh_size;	if ((shstrtab = malloc(shstrtabsz + 1)) == NULL) {		dprintf("failed to allocate %lu bytes for shstrtab\n",		    (ulong_t)shstrtabsz);		goto out;	}	if (pread64(efp->e_fd, shstrtab, shstrtabsz,	    shp->sh_offset) != shstrtabsz) {		dprintf("failed to read %lu bytes of shstrs at off %lld: %s\n",		    shstrtabsz, (longlong_t)shp->sh_offset, strerror(errno));		goto out;	}	shstrtab[shstrtabsz] = '\0';	/*	 * Now iterate over each section in the section header table, locating	 * sections of interest and initializing more of the ps_prochandle.	 */	for (i = 0; i < efp->e_hdr.e_shnum; i++) {		shp = &shdrs[i];		name = shstrtab + shp->sh_name;		if (shp->sh_name >= shstrtabsz) {			dprintf("skipping section [%d]: corrupt sh_name\n", i);			continue;		}		if (shp->sh_link >= efp->e_hdr.e_shnum) {			dprintf("skipping section [%d]: corrupt sh_link\n", i);			continue;		}		dprintf("found section header %s (sh_addr 0x%llx)\n",		    name, (u_longlong_t)shp->sh_addr);		if (strcmp(name, ".SUNW_ctf") == 0) {			if ((mp = Paddr2mptr(P, shp->sh_addr)) == NULL) {				dprintf("no map at addr 0x%llx for %s [%d]\n",				    (u_longlong_t)shp->sh_addr, name, i);				continue;			}			if (mp->map_file == NULL ||			    mp->map_file->file_ctf_buf != NULL) {				dprintf("no mapping file or duplicate buffer "				    "for %s [%d]\n", name, i);				continue;			}			if ((buf = malloc(shp->sh_size)) == NULL ||			    pread64(efp->e_fd, buf, shp->sh_size,			    shp->sh_offset) != shp->sh_size) {				dprintf("skipping section %s [%d]: %s\n",				    name, i, strerror(errno));				free(buf);				continue;			}			mp->map_file->file_ctf_size = shp->sh_size;			mp->map_file->file_ctf_buf = buf;			if (shdrs[shp->sh_link].sh_type == SHT_DYNSYM)				mp->map_file->file_ctf_dyn = 1;		} else if (strcmp(name, ".symtab") == 0) {			fake_up_symtab(P, &efp->e_hdr,			    shp, &shdrs[shp->sh_link]);		}	}out:	free(shstrtab);	free(shdrs);}/* * Main engine for core file initialization: given an fd for the core file * and an optional pathname, construct the ps_prochandle.  The aout_path can * either be a suggested executable pathname, or a suggested directory to * use as a possible current working directory. */struct ps_prochandle *Pfgrab_core(int core_fd, const char *aout_path, int *perr){	struct ps_prochandle *P;	map_info_t *stk_mp, *brk_mp;	const char *execname;	char *interp;	int i, notes, pagesize;	uintptr_t addr, base_addr;	struct stat64 stbuf;	void *phbuf, *php;	size_t nbytes;	int nmap;	elf_file_t aout;	elf_file_t core;	Elf_Scn *scn, *intp_scn = NULL;	Elf_Data *dp;	GElf_Phdr phdr, note_phdr;	GElf_Shdr shdr;	GElf_Xword nleft;	if (elf_version(EV_CURRENT) == EV_NONE) {		dprintf("libproc ELF version is more recent than libelf\n");		*perr = G_ELF;		return (NULL);	}	aout.e_elf = NULL;	aout.e_fd = -1;	core.e_elf = NULL;	core.e_fd = core_fd;

⌨️ 快捷键说明

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