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

📄 psymtab.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 5 页
字号:
 */static intfile_differs(struct ps_prochandle *P, Elf *elf, file_info_t *fptr){	Elf_Scn *scn;	GElf_Shdr shdr;	GElf_Dyn dyn;	Elf_Data *data;	uint_t i, ndyn;	GElf_Xword cksum;	uintptr_t addr;	if (fptr->file_map == NULL)		return (0);	if ((Pcontent(P) & (CC_CONTENT_TEXT | CC_CONTENT_DATA)) !=	    (CC_CONTENT_TEXT | CC_CONTENT_DATA))		return (0);	/*	 * First, we find the checksum value in the elf file.	 */	scn = NULL;	while ((scn = elf_nextscn(elf, scn)) != NULL) {		if (gelf_getshdr(scn, &shdr) != NULL &&		    shdr.sh_type == SHT_DYNAMIC)			goto found_shdr;	}	return (0);found_shdr:	if ((data = elf_getdata(scn, NULL)) == NULL)		return (0);	if (P->status.pr_dmodel == PR_MODEL_ILP32)		ndyn = shdr.sh_size / sizeof (Elf32_Dyn);#ifdef _LP64	else if (P->status.pr_dmodel == PR_MODEL_LP64)		ndyn = shdr.sh_size / sizeof (Elf64_Dyn);#endif	else		return (0);	for (i = 0; i < ndyn; i++) {		if (gelf_getdyn(data, i, &dyn) != NULL &&		    dyn.d_tag == DT_CHECKSUM)			goto found_cksum;	}	return (0);found_cksum:	cksum = dyn.d_un.d_val;	dprintf("elf cksum value is %llx\n", (u_longlong_t)cksum);	/*	 * Get the base of the text mapping that corresponds to this file.	 */	addr = fptr->file_map->map_pmap.pr_vaddr;	if (P->status.pr_dmodel == PR_MODEL_ILP32) {		Elf32_Ehdr ehdr;		Elf32_Phdr phdr;		Elf32_Dyn dync, *dynp;		uint_t i;		if (read_ehdr32(P, &ehdr, addr) != 0 ||		    read_dynamic_phdr32(P, &ehdr, &phdr, addr) != 0)			return (0);		if (ehdr.e_type == ET_DYN)			phdr.p_vaddr += addr;		if ((dynp = malloc(phdr.p_filesz)) == NULL)			return (0);		dync.d_tag = DT_NULL;		if (Pread(P, dynp, phdr.p_filesz, phdr.p_vaddr) !=		    phdr.p_filesz) {			free(dynp);			return (0);		}		for (i = 0; i < phdr.p_filesz / sizeof (Elf32_Dyn); i++) {			if (dynp[i].d_tag == DT_CHECKSUM)				dync = dynp[i];		}		free(dynp);		if (dync.d_tag != DT_CHECKSUM)			return (0);		dprintf("image cksum value is %llx\n",		    (u_longlong_t)dync.d_un.d_val);		return (dync.d_un.d_val != cksum);#ifdef _LP64	} else if (P->status.pr_dmodel == PR_MODEL_LP64) {		Elf64_Ehdr ehdr;		Elf64_Phdr phdr;		Elf64_Dyn dync, *dynp;		uint_t i;		if (read_ehdr64(P, &ehdr, addr) != 0 ||		    read_dynamic_phdr64(P, &ehdr, &phdr, addr) != 0)			return (0);		if (ehdr.e_type == ET_DYN)			phdr.p_vaddr += addr;		if ((dynp = malloc(phdr.p_filesz)) == NULL)			return (0);		dync.d_tag = DT_NULL;		if (Pread(P, dynp, phdr.p_filesz, phdr.p_vaddr) !=		    phdr.p_filesz) {			free(dynp);			return (0);		}		for (i = 0; i < phdr.p_filesz / sizeof (Elf64_Dyn); i++) {			if (dynp[i].d_tag == DT_CHECKSUM)				dync = dynp[i];		}		free(dynp);		if (dync.d_tag != DT_CHECKSUM)			return (0);		dprintf("image cksum value is %llx\n",		    (u_longlong_t)dync.d_un.d_val);		return (dync.d_un.d_val != cksum);#endif	/* _LP64 */	}	return (0);}static Elf *fake_elf(struct ps_prochandle *P, file_info_t *fptr){	enum {		DI_PLTGOT = 0,		DI_JMPREL,		DI_PLTRELSZ,		DI_PLTREL,		DI_SYMTAB,		DI_HASH,		DI_SYMENT,		DI_STRTAB,		DI_STRSZ,		DI_NENT	};	uintptr_t addr;	size_t size = 0;	caddr_t elfdata = NULL;	Elf *elf;	Elf32_Word nchain;	static char shstr[] = ".shstrtab\0.dynsym\0.dynstr\0.dynamic\0.plt";	if (fptr->file_map == NULL)		return (NULL);	if ((Pcontent(P) & (CC_CONTENT_TEXT | CC_CONTENT_DATA)) !=	    (CC_CONTENT_TEXT | CC_CONTENT_DATA))		return (NULL);	addr = fptr->file_map->map_pmap.pr_vaddr;	/*	 * We're building a in memory elf file that will let us use libelf	 * for most of the work we need to later (e.g. symbol table lookups).	 * We need sections for the dynsym, dynstr, and plt, and we need	 * the program headers from the text section. The former is used in	 * Pbuild_file_symtab(); the latter is used in several functions in	 * Pcore.c to reconstruct the origin of each mapping from the load	 * object that spawned it.	 *	 * Here are some useful pieces of elf trivia that will help	 * to elucidate this code.	 *	 * All the information we need about the dynstr can be found in these	 * two entries in the dynamic section:	 *	 *	DT_STRTAB	base of dynstr	 *	DT_STRSZ	size of dynstr	 *	 * So deciphering the dynstr is pretty straightforward.	 *	 * The dynsym is a little trickier.	 *	 *	DT_SYMTAB	base of dynsym	 *	DT_SYMENT	size of a dynstr entry (Elf{32,64}_Sym)	 *	DT_HASH		base of hash table for dynamic lookups	 *	 * The DT_SYMTAB entry gives us any easy way of getting to the base	 * of the dynsym, but getting the size involves rooting around in the	 * dynamic lookup hash table. Here's the layout of the hash table:	 *	 *		+-------------------+	 *		|	nbucket	    |	All values are of type	 *		+-------------------+	Elf32_Word	 *		|	nchain	    |	 *		+-------------------+	 *		|	bucket[0]   |	 *		|	. . .	    |	 *		| bucket[nbucket-1] |	 *		+-------------------+	 *		|	chain[0]    |	 *		|	. . .	    |	 *		|  chain[nchain-1]  |	 *		+-------------------+	 *	(figure 5-12 from the SYS V Generic ABI)	 *	 * Symbols names are hashed into a particular bucket which contains	 * an index into the symbol table. Each entry in the symbol table	 * has a corresponding entry in the chain table which tells the	 * consumer where the next entry in the hash chain is. We can use	 * the nchain field to find out the size of the dynsym.	 *	 * We can figure out the size of the .plt section, but it takes some	 * doing. We need to use the following information:	 *	 *	DT_PLTGOT	base of the PLT	 *	DT_JMPREL	base of the PLT's relocation section	 *	DT_PLTRELSZ	size of the PLT's relocation section	 *	DT_PLTREL	type of the PLT's relocation section	 *	 * We can use the relocation section to figure out the address of the	 * last entry and subtract off the value of DT_PLTGOT to calculate	 * the size of the PLT.	 *	 * For more information, check out the System V Generic ABI.	 */	if (P->status.pr_dmodel == PR_MODEL_ILP32) {		Elf32_Ehdr ehdr, *ep;		Elf32_Phdr phdr;		Elf32_Shdr *sp;		Elf32_Dyn *dp;		Elf32_Dyn *d[DI_NENT] = { 0 };		uint_t i, dcount = 0;		uint32_t off;		size_t pltsz = 0, pltentsz;		if (read_ehdr32(P, &ehdr, addr) != 0 ||		    read_dynamic_phdr32(P, &ehdr, &phdr, addr) != 0)			return (NULL);		if (ehdr.e_type == ET_DYN)			phdr.p_vaddr += addr;		if ((dp = malloc(phdr.p_filesz)) == NULL)			return (NULL);		if (Pread(P, dp, phdr.p_filesz, phdr.p_vaddr) !=		    phdr.p_filesz) {			free(dp);			return (NULL);		}		for (i = 0; i < phdr.p_filesz / sizeof (Elf32_Dyn); i++) {			switch (dp[i].d_tag) {			/*			 * For the .plt section.			 */			case DT_PLTGOT:				d[DI_PLTGOT] = &dp[i];				continue;			case DT_JMPREL:				d[DI_JMPREL] = &dp[i];				continue;			case DT_PLTRELSZ:				d[DI_PLTRELSZ] = &dp[i];				continue;			case DT_PLTREL:				d[DI_PLTREL] = &dp[i];				continue;			default:				continue;			/*			 * For the .dynsym section.			 */			case DT_SYMTAB:				d[DI_SYMTAB] = &dp[i];				break;			case DT_HASH:				d[DI_HASH] = &dp[i];				break;			case DT_SYMENT:				d[DI_SYMENT] = &dp[i];				break;			/*			 * For the .dynstr section.			 */			case DT_STRTAB:				d[DI_STRTAB] = &dp[i];				break;			case DT_STRSZ:				d[DI_STRSZ] = &dp[i];				break;			}			dcount++;		}		/*		 * We need all of those dynamic entries in order to put		 * together a complete set of elf sections, but we'll		 * let the PLT section slide if need be. The dynsym- and		 * dynstr-related dynamic entries are mandatory in both		 * executables and shared objects so if one of those is		 * missing, we're in some trouble and should abort.		 */		if (dcount + 4 != DI_NENT) {			dprintf("text section missing required dynamic "			    "entries\n");			return (NULL);		}		if (ehdr.e_type == ET_DYN) {			if (d[DI_PLTGOT] != NULL)				d[DI_PLTGOT]->d_un.d_ptr += addr;			if (d[DI_JMPREL] != NULL)				d[DI_JMPREL]->d_un.d_ptr += addr;			d[DI_SYMTAB]->d_un.d_ptr += addr;			d[DI_HASH]->d_un.d_ptr += addr;			d[DI_STRTAB]->d_un.d_ptr += addr;		}		/* elf header */		size = sizeof (Elf32_Ehdr);		/* program headers from in-core elf fragment */		size += ehdr.e_phnum * ehdr.e_phentsize;		/* unused shdr, and .shstrtab section */		size += sizeof (Elf32_Shdr);		size += sizeof (Elf32_Shdr);		size += roundup(sizeof (shstr), 4);		/* .dynsym section */		size += sizeof (Elf32_Shdr);		if (Pread(P, &nchain, sizeof (nchain),		    d[DI_HASH]->d_un.d_ptr + 4) != sizeof (nchain))			goto bad32;		size += sizeof (Elf32_Sym) * nchain;		/* .dynstr section */		size += sizeof (Elf32_Shdr);		size += roundup(d[DI_STRSZ]->d_un.d_val, 4);		/* .dynamic section */		size += sizeof (Elf32_Shdr);		size += roundup(phdr.p_filesz, 4);		/* .plt section */		if (d[DI_PLTGOT] != NULL && d[DI_JMPREL] != NULL &&		    d[DI_PLTRELSZ] != NULL && d[DI_PLTREL] != NULL) {			uintptr_t penult, ult;			uintptr_t jmprel = d[DI_JMPREL]->d_un.d_ptr;			size_t pltrelsz = d[DI_PLTRELSZ]->d_un.d_val;			if (d[DI_PLTREL]->d_un.d_val == DT_RELA) {				uint_t ndx = pltrelsz / sizeof (Elf32_Rela) - 2;				Elf32_Rela r[2];				if (Pread(P, r, sizeof (r), jmprel +				    sizeof (r[0]) * ndx) != sizeof (r))					goto bad32;				penult = r[0].r_offset;				ult = r[1].r_offset;			} else if (d[DI_PLTREL]->d_un.d_val == DT_REL) {				uint_t ndx = pltrelsz / sizeof (Elf32_Rel) - 2;				Elf32_Rel r[2];				if (Pread(P, r, sizeof (r), jmprel +				    sizeof (r[0]) * ndx) != sizeof (r))					goto bad32;				penult = r[0].r_offset;				ult = r[1].r_offset;			} else {				goto bad32;			}			pltentsz = ult - penult;			if (ehdr.e_type == ET_DYN)				ult += addr;			pltsz = ult - d[DI_PLTGOT]->d_un.d_ptr + pltentsz;			size += sizeof (Elf32_Shdr);			size += roundup(pltsz, 4);		}		if ((elfdata = calloc(1, size)) == NULL)			goto bad32;		/* LINTED - alignment */		ep = (Elf32_Ehdr *)elfdata;		(void) memcpy(ep, &ehdr, offsetof(Elf32_Ehdr, e_phoff));		ep->e_ehsize = sizeof (Elf32_Ehdr);		ep->e_phoff = sizeof (Elf32_Ehdr);		ep->e_phentsize = ehdr.e_phentsize;		ep->e_phnum = ehdr.e_phnum;		ep->e_shoff = ep->e_phoff + ep->e_phnum * ep->e_phentsize;		ep->e_shentsize = sizeof (Elf32_Shdr);		ep->e_shnum = (pltsz == 0) ? 5 : 6;		ep->e_shstrndx = 1;		/* LINTED - alignment */		sp = (Elf32_Shdr *)(elfdata + ep->e_shoff);		off = ep->e_shoff + ep->e_shentsize * ep->e_shnum;		/*		 * Copying the program headers directly from the process's		 * address space is a little suspect, but since we only		 * use them for their address and size values, this is fine.		 */		if (Pread(P, &elfdata[ep->e_phoff],		    ep->e_phnum * ep->e_phentsize, addr + ehdr.e_phoff) !=		    ep->e_phnum * ep->e_phentsize) {			free(elfdata);			goto bad32;		}		/*		 * The first elf section is always skipped.		 */		sp++;		/*		 * Section Header[1]  sh_name: .shstrtab		 */		sp->sh_name = 0;		sp->sh_type = SHT_STRTAB;		sp->sh_flags = SHF_STRINGS;		sp->sh_addr = 0;		sp->sh_offset = off;		sp->sh_size = sizeof (shstr);		sp->sh_link = 0;		sp->sh_info = 0;		sp->sh_addralign = 1;		sp->sh_entsize = 0;		(void) memcpy(&elfdata[off], shstr, sizeof (shstr));		off += roundup(sp->sh_size, 4);		sp++;		/*		 * Section Header[2]  sh_name: .dynsym		 */		sp->sh_name = 10;		sp->sh_type = SHT_DYNSYM;		sp->sh_flags = SHF_ALLOC;		sp->sh_addr = d[DI_SYMTAB]->d_un.d_ptr;		if (ehdr.e_type == ET_DYN)			sp->sh_addr -= addr;		sp->sh_offset = off;		sp->sh_size = nchain * sizeof (Elf32_Sym);		sp->sh_link = 3;		sp->sh_info = 1;		sp->sh_addralign = 4;		sp->sh_entsize = sizeof (Elf32_Sym);		if (Pread(P, &elfdata[off], sp->sh_size,		    d[DI_SYMTAB]->d_un.d_ptr) != sp->sh_size) {			free(elfdata);			goto bad32;		}		off += roundup(sp->sh_size, 4);		sp++;		/*		 * Section Header[3]  sh_name: .dynstr		 */		sp->sh_name = 18;		sp->sh_type = SHT_STRTAB;		sp->sh_flags = SHF_ALLOC | SHF_STRINGS;		sp->sh_addr = d[DI_STRTAB]->d_un.d_ptr;		if (ehdr.e_type == ET_DYN)			sp->sh_addr -= addr;		sp->sh_offset = off;		sp->sh_size = d[DI_STRSZ]->d_un.d_val;		sp->sh_link = 0;		sp->sh_info = 0;		sp->sh_addralign = 1;		sp->sh_entsize = 0;		if (Pread(P, &elfdata[off], sp->sh_size,		    d[DI_STRTAB]->d_un.d_ptr) != sp->sh_size) {			free(elfdata);			goto bad32;		}		off += roundup(sp->sh_size, 4);		sp++;		/*		 * Section Header[4]  sh_name: .dynamic		 */		sp->sh_name = 26;		sp->sh_type = SHT_DYNAMIC;		sp->sh_flags = SHF_WRITE | SHF_ALLOC;		sp->sh_addr = phdr.p_vaddr;		if (ehdr.e_type == ET_DYN)			sp->sh_addr -= addr;		sp->sh_offset = off;		sp->sh_size = phdr.p_filesz;		sp->sh_link = 3;		sp->sh_info = 0;		sp->sh_addralign = 4;

⌨️ 快捷键说明

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