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

📄 psymtab.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (P->rap == NULL && P->state != PS_DEAD && P->state != PS_IDLE) {		Pupdate_maps(P);		if (P->num_files == 0)			load_static_maps(P);		rd_log(_libproc_debug);		if ((P->rap = rd_new(P)) != NULL)			(void) rd_loadobj_iter(P->rap, map_iter, P);	}	return (P->rap);}/* * Return the prmap_t structure containing 'addr', but only if it * is in the dynamic linker's link map and is the text section. */const prmap_t *Paddr_to_text_map(struct ps_prochandle *P, uintptr_t addr){	map_info_t *mptr;	if (!P->info_valid)		Pupdate_maps(P);	if ((mptr = Paddr2mptr(P, addr)) != NULL) {		file_info_t *fptr = build_map_symtab(P, mptr);		const prmap_t *pmp = &mptr->map_pmap;		if (fptr != NULL && fptr->file_lo != NULL &&		    fptr->file_lo->rl_base >= pmp->pr_vaddr &&		    fptr->file_lo->rl_base < pmp->pr_vaddr + pmp->pr_size)			return (pmp);	}	return (NULL);}/* * Return the prmap_t structure containing 'addr' (no restrictions on * the type of mapping). */const prmap_t *Paddr_to_map(struct ps_prochandle *P, uintptr_t addr){	map_info_t *mptr;	if (!P->info_valid)		Pupdate_maps(P);	if ((mptr = Paddr2mptr(P, addr)) != NULL)		return (&mptr->map_pmap);	return (NULL);}/* * Convert a full or partial load object name to the prmap_t for its * corresponding primary text mapping. */const prmap_t *Plmid_to_map(struct ps_prochandle *P, Lmid_t lmid, const char *name){	map_info_t *mptr;	if (name == PR_OBJ_EVERY)		return (NULL); /* A reasonable mistake */	if ((mptr = object_name_to_map(P, lmid, name)) != NULL)		return (&mptr->map_pmap);	return (NULL);}const prmap_t *Pname_to_map(struct ps_prochandle *P, const char *name){	return (Plmid_to_map(P, PR_LMID_EVERY, name));}const rd_loadobj_t *Paddr_to_loadobj(struct ps_prochandle *P, uintptr_t addr){	map_info_t *mptr;	if (!P->info_valid)		Pupdate_maps(P);	if ((mptr = Paddr2mptr(P, addr)) == NULL)		return (NULL);	/*	 * By building the symbol table, we implicitly bring the PLT	 * information up to date in the load object.	 */	(void) build_map_symtab(P, mptr);	return (mptr->map_file->file_lo);}const rd_loadobj_t *Plmid_to_loadobj(struct ps_prochandle *P, Lmid_t lmid, const char *name){	map_info_t *mptr;	if (name == PR_OBJ_EVERY)		return (NULL);	if ((mptr = object_name_to_map(P, lmid, name)) == NULL)		return (NULL);	/*	 * By building the symbol table, we implicitly bring the PLT	 * information up to date in the load object.	 */	(void) build_map_symtab(P, mptr);	return (mptr->map_file->file_lo);}const rd_loadobj_t *Pname_to_loadobj(struct ps_prochandle *P, const char *name){	return (Plmid_to_loadobj(P, PR_LMID_EVERY, name));}ctf_file_t *Pbuild_file_ctf(struct ps_prochandle *P, file_info_t *fptr){	ctf_sect_t ctdata, symtab, strtab;	sym_tbl_t *symp;	int err;	if (fptr->file_ctfp != NULL)		return (fptr->file_ctfp);	Pbuild_file_symtab(P, fptr);	if (fptr->file_ctf_size == 0)		return (NULL);	symp = fptr->file_ctf_dyn ? &fptr->file_dynsym : &fptr->file_symtab;	if (symp->sym_data == NULL)		return (NULL);	/*	 * The buffer may alread be allocated if this is a core file that	 * contained CTF data for this file.	 */	if (fptr->file_ctf_buf == NULL) {		fptr->file_ctf_buf = malloc(fptr->file_ctf_size);		if (fptr->file_ctf_buf == NULL) {			dprintf("failed to allocate ctf buffer\n");			return (NULL);		}		if (pread(fptr->file_fd, fptr->file_ctf_buf,		    fptr->file_ctf_size, fptr->file_ctf_off) !=		    fptr->file_ctf_size) {			free(fptr->file_ctf_buf);			fptr->file_ctf_buf = NULL;			dprintf("failed to read ctf data\n");			return (NULL);		}	}	ctdata.cts_name = ".SUNW_ctf";	ctdata.cts_type = SHT_PROGBITS;	ctdata.cts_flags = 0;	ctdata.cts_data = fptr->file_ctf_buf;	ctdata.cts_size = fptr->file_ctf_size;	ctdata.cts_entsize = 1;	ctdata.cts_offset = 0;	symtab.cts_name = fptr->file_ctf_dyn ? ".dynsym" : ".symtab";	symtab.cts_type = symp->sym_hdr.sh_type;	symtab.cts_flags = symp->sym_hdr.sh_flags;	symtab.cts_data = symp->sym_data->d_buf;	symtab.cts_size = symp->sym_hdr.sh_size;	symtab.cts_entsize = symp->sym_hdr.sh_entsize;	symtab.cts_offset = symp->sym_hdr.sh_offset;	strtab.cts_name = fptr->file_ctf_dyn ? ".dynstr" : ".strtab";	strtab.cts_type = symp->sym_strhdr.sh_type;	strtab.cts_flags = symp->sym_strhdr.sh_flags;	strtab.cts_data = symp->sym_strs;	strtab.cts_size = symp->sym_strhdr.sh_size;	strtab.cts_entsize = symp->sym_strhdr.sh_entsize;	strtab.cts_offset = symp->sym_strhdr.sh_offset;	fptr->file_ctfp = ctf_bufopen(&ctdata, &symtab, &strtab, &err);	if (fptr->file_ctfp == NULL) {		free(fptr->file_ctf_buf);		fptr->file_ctf_buf = NULL;		return (NULL);	}	dprintf("loaded %lu bytes of CTF data for %s\n",	    (ulong_t)fptr->file_ctf_size, fptr->file_pname);	return (fptr->file_ctfp);}ctf_file_t *Paddr_to_ctf(struct ps_prochandle *P, uintptr_t addr){	map_info_t *mptr;	file_info_t *fptr;	if (!P->info_valid)		Pupdate_maps(P);	if ((mptr = Paddr2mptr(P, addr)) == NULL ||	    (fptr = mptr->map_file) == NULL)		return (NULL);	return (Pbuild_file_ctf(P, fptr));}ctf_file_t *Plmid_to_ctf(struct ps_prochandle *P, Lmid_t lmid, const char *name){	map_info_t *mptr;	file_info_t *fptr;	if (name == PR_OBJ_EVERY)		return (NULL);	if ((mptr = object_name_to_map(P, lmid, name)) == NULL ||	    (fptr = mptr->map_file) == NULL)		return (NULL);	return (Pbuild_file_ctf(P, fptr));}ctf_file_t *Pname_to_ctf(struct ps_prochandle *P, const char *name){	return (Plmid_to_ctf(P, PR_LMID_EVERY, name));}/* * If we're not a core file, re-read the /proc/<pid>/auxv file and store * its contents in P->auxv.  In the case of a core file, we either * initialized P->auxv in Pcore() from the NT_AUXV, or we don't have an * auxv because the note was missing. */voidPreadauxvec(struct ps_prochandle *P){	char auxfile[64];	struct stat statb;	ssize_t naux;	int fd;	if (P->state == PS_DEAD)		return; /* Already read during Pgrab_core() */	if (P->state == PS_IDLE)		return; /* No aux vec for Pgrab_file() */	if (P->auxv != NULL) {		free(P->auxv);		P->auxv = NULL;		P->nauxv = 0;	}	(void) sprintf(auxfile, "/proc/%d/auxv", (int)P->pid);	if ((fd = open(auxfile, O_RDONLY)) < 0)		return;	if (fstat(fd, &statb) == 0 &&	    statb.st_size >= sizeof (auxv_t) &&	    (P->auxv = malloc(statb.st_size + sizeof (auxv_t))) != NULL) {		if ((naux = read(fd, P->auxv, statb.st_size)) < 0 ||		    (naux /= sizeof (auxv_t)) < 1) {			free(P->auxv);			P->auxv = NULL;		} else {			P->auxv[naux].a_type = AT_NULL;			P->auxv[naux].a_un.a_val = 0L;			P->nauxv = (int)naux;		}	}	(void) close(fd);}/* * Return a requested element from the process's aux vector. * Return -1 on failure (this is adequate for our purposes). */longPgetauxval(struct ps_prochandle *P, int type){	auxv_t *auxv;	if (P->auxv == NULL)		Preadauxvec(P);	if (P->auxv == NULL)		return (-1);	for (auxv = P->auxv; auxv->a_type != AT_NULL; auxv++) {		if (auxv->a_type == type)			return (auxv->a_un.a_val);	}	return (-1);}/* * Return a pointer to our internal copy of the process's aux vector. * The caller should not hold on to this pointer across any libproc calls. */const auxv_t *Pgetauxvec(struct ps_prochandle *P){	static const auxv_t empty = { AT_NULL, 0L };	if (P->auxv == NULL)		Preadauxvec(P);	if (P->auxv == NULL)		return (&empty);	return (P->auxv);}/* * Find or build the symbol table for the given mapping. */static file_info_t *build_map_symtab(struct ps_prochandle *P, map_info_t *mptr){	prmap_t *pmap = &mptr->map_pmap;	file_info_t *fptr;	rd_loadobj_t *lop;	uint_t i;	if ((fptr = mptr->map_file) != NULL) {		Pbuild_file_symtab(P, fptr);		return (fptr);	}	if (pmap->pr_mapname[0] == '\0')		return (NULL);	/*	 * Attempt to find a matching file.	 * (A file can be mapped at several different addresses.)	 */	for (i = 0, fptr = list_next(&P->file_head); i < P->num_files;	    i++, fptr = list_next(fptr)) {		if (strcmp(fptr->file_pname, pmap->pr_mapname) == 0 &&		    (lop = fptr->file_lo) != NULL &&		    ((pmap->pr_vaddr <= lop->rl_base &&		    lop->rl_base < pmap->pr_vaddr + pmap->pr_size) ||		    (pmap->pr_vaddr <= lop->rl_data_base &&		    lop->rl_data_base < pmap->pr_vaddr + pmap->pr_size))) {			mptr->map_file = fptr;			fptr->file_ref++;			Pbuild_file_symtab(P, fptr);			return (fptr);		}	}	/*	 * If we need to create a new file_info structure, iterate	 * through the load objects in order to attempt to connect	 * this new file with its primary text mapping.  We again	 * need to handle ld.so as a special case because we need	 * to be able to bootstrap librtld_db.	 */	if ((fptr = file_info_new(P, mptr)) == NULL)		return (NULL);	if (P->map_ldso != mptr) {		if (P->rap != NULL)			(void) rd_loadobj_iter(P->rap, map_iter, P);		else			(void) Prd_agent(P);	} else {		fptr->file_map = mptr;	}	/*	 * If librtld_db wasn't able to help us connect the file to a primary	 * text mapping, set file_map to the current mapping because we require	 * fptr->file_map to be set in Pbuild_file_symtab.  librtld_db may be	 * unaware of what's going on in the rare case that a legitimate ELF	 * file has been mmap(2)ed into the process address space *without*	 * the use of dlopen(3x).  Why would this happen?  See pwdx ... :)	 */	if (fptr->file_map == NULL)		fptr->file_map = mptr;	Pbuild_file_symtab(P, fptr);	return (fptr);}static intread_ehdr32(struct ps_prochandle *P, Elf32_Ehdr *ehdr, uintptr_t addr){	if (Pread(P, ehdr, sizeof (*ehdr), addr) != sizeof (*ehdr))		return (-1);	if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||	    ehdr->e_ident[EI_MAG1] != ELFMAG1 ||	    ehdr->e_ident[EI_MAG2] != ELFMAG2 ||	    ehdr->e_ident[EI_MAG3] != ELFMAG3 ||	    ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||#ifdef _BIG_ENDIAN	    ehdr->e_ident[EI_DATA] != ELFDATA2MSB ||#else	    ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||#endif	    ehdr->e_ident[EI_VERSION] != EV_CURRENT)		return (-1);	return (0);}static intread_dynamic_phdr32(struct ps_prochandle *P, const Elf32_Ehdr *ehdr,    Elf32_Phdr *phdr, uintptr_t addr){	uint_t i;	for (i = 0; i < ehdr->e_phnum; i++) {		uintptr_t a = addr + ehdr->e_phoff + i * ehdr->e_phentsize;		if (Pread(P, phdr, sizeof (*phdr), a) != sizeof (*phdr))			return (-1);		if (phdr->p_type == PT_DYNAMIC)			return (0);	}	return (-1);}#ifdef _LP64static intread_ehdr64(struct ps_prochandle *P, Elf64_Ehdr *ehdr, uintptr_t addr){	if (Pread(P, ehdr, sizeof (Elf64_Ehdr), addr) != sizeof (Elf64_Ehdr))		return (-1);	if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||	    ehdr->e_ident[EI_MAG1] != ELFMAG1 ||	    ehdr->e_ident[EI_MAG2] != ELFMAG2 ||	    ehdr->e_ident[EI_MAG3] != ELFMAG3 ||	    ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||#ifdef _BIG_ENDIAN	    ehdr->e_ident[EI_DATA] != ELFDATA2MSB ||#else	    ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||#endif	    ehdr->e_ident[EI_VERSION] != EV_CURRENT)		return (-1);	return (0);}static intread_dynamic_phdr64(struct ps_prochandle *P, const Elf64_Ehdr *ehdr,    Elf64_Phdr *phdr, uintptr_t addr){	uint_t i;	for (i = 0; i < ehdr->e_phnum; i++) {		uintptr_t a = addr + ehdr->e_phoff + i * ehdr->e_phentsize;		if (Pread(P, phdr, sizeof (*phdr), a) != sizeof (*phdr))			return (-1);		if (phdr->p_type == PT_DYNAMIC)			return (0);	}	return (-1);}#endif	/* _LP64 *//* * The text segment for each load object contains the elf header and * program headers. We can use this information to determine if the * file that corresponds to the load object is the same file that * was loaded into the process's address space. There can be a discrepency * if a file is recompiled after the process is started or if the target * represents a core file from a differently configured system -- two * common examples. The DT_CHECKSUM entry in the dynamic section * provides an easy method of comparison. It is important to note that * the dynamic section usually lives in the data segment, but the meta * data we use to find the dynamic section lives in the text segment so * if either of those segments is absent we can't proceed. * * We're looking through the elf file for several items: the symbol tables * (both dynsym and symtab), the procedure linkage table (PLT) base, * size, and relocation base, and the CTF information. Most of this can * be recovered from the loaded image of the file itself, the exceptions * being the symtab and CTF data. * * First we try to open the file that we think corresponds to the load * object, if the DT_CHECKSUM values match, we're all set, and can simply * recover all the information we need from the file. If the values of * DT_CHECKSUM don't match, or if we can't access the file for whatever * reasaon, we fake up a elf file to use in its stead. If we can't read * the elf data in the process's address space, we fall back to using * the file even though it may give inaccurate information. * * The elf file that we fake up has to consist of sections for the * dynsym, the PLT and the dynamic section. Note that in the case of a * core file, we'll get the CTF data in the file_info_t later on from * a section embedded the core file (if it's present). * * file_differs() conservatively looks for mismatched files, identifying * a match when there is any ambiguity (since that's the legacy behavior).

⌨️ 快捷键说明

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