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

📄 psymtab.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 5 页
字号:
		sp->sh_entsize = sizeof (Elf32_Dyn);		(void) memcpy(&elfdata[off], dp, sp->sh_size);		off += roundup(sp->sh_size, 4);		sp++;		/*		 * Section Header[5]  sh_name: .plt		 */		if (pltsz != 0) {			sp->sh_name = 35;			sp->sh_type = SHT_PROGBITS;			sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR;			sp->sh_addr = d[DI_PLTGOT]->d_un.d_ptr;			if (ehdr.e_type == ET_DYN)				sp->sh_addr -= addr;			sp->sh_offset = off;			sp->sh_size = pltsz;			sp->sh_link = 0;			sp->sh_info = 0;			sp->sh_addralign = 4;			sp->sh_entsize = pltentsz;			if (Pread(P, &elfdata[off], sp->sh_size,			    d[DI_PLTGOT]->d_un.d_ptr) != sp->sh_size) {				free(elfdata);				goto bad32;			}			off += roundup(sp->sh_size, 4);			sp++;		}		free(dp);		goto good;bad32:		free(dp);		return (NULL);#ifdef _LP64	} else if (P->status.pr_dmodel == PR_MODEL_LP64) {		Elf64_Ehdr ehdr, *ep;		Elf64_Phdr phdr;		Elf64_Shdr *sp;		Elf64_Dyn *dp;		Elf64_Dyn *d[DI_NENT] = { 0 };		uint_t i, dcount = 0;		uint64_t off;		size_t pltsz = 0, pltentsz;		if (read_ehdr64(P, &ehdr, addr) != 0 ||		    read_dynamic_phdr64(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 (Elf64_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 (Elf64_Ehdr);		/* program headers from in-core elf fragment */		size += ehdr.e_phnum * ehdr.e_phentsize;		/* unused shdr, and .shstrtab section */		size += sizeof (Elf64_Shdr);		size += sizeof (Elf64_Shdr);		size += roundup(sizeof (shstr), 8);		/* .dynsym section */		size += sizeof (Elf64_Shdr);		if (Pread(P, &nchain, sizeof (nchain),		    d[DI_HASH]->d_un.d_ptr + 4) != sizeof (nchain))			goto bad64;		size += sizeof (Elf64_Sym) * nchain;		/* .dynstr section */		size += sizeof (Elf64_Shdr);		size += roundup(d[DI_STRSZ]->d_un.d_val, 8);		/* .dynamic section */		size += sizeof (Elf64_Shdr);		size += roundup(phdr.p_filesz, 8);		/* .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 (Elf64_Rela) - 2;				Elf64_Rela r[2];				if (Pread(P, r, sizeof (r), jmprel +				    sizeof (r[0]) * ndx) != sizeof (r))					goto bad64;				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 (Elf64_Rel) - 2;				Elf64_Rel r[2];				if (Pread(P, r, sizeof (r), jmprel +				    sizeof (r[0]) * ndx) != sizeof (r))					goto bad64;				penult = r[0].r_offset;				ult = r[1].r_offset;			} else {				goto bad64;			}			pltentsz = ult - penult;			if (ehdr.e_type == ET_DYN)				ult += addr;			pltsz = ult - d[DI_PLTGOT]->d_un.d_ptr + pltentsz;			size += sizeof (Elf64_Shdr);			size += roundup(pltsz, 8);		}		if ((elfdata = calloc(1, size)) == NULL)			goto bad64;		/* LINTED - alignment */		ep = (Elf64_Ehdr *)elfdata;		(void) memcpy(ep, &ehdr, offsetof(Elf64_Ehdr, e_phoff));		ep->e_ehsize = sizeof (Elf64_Ehdr);		ep->e_phoff = sizeof (Elf64_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 (Elf64_Shdr);		ep->e_shnum = (pltsz == 0) ? 5 : 6;		ep->e_shstrndx = 1;		/* LINTED - alignment */		sp = (Elf64_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 bad64;		}		/*		 * 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, 8);		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 (Elf64_Sym);		sp->sh_link = 3;		sp->sh_info = 1;		sp->sh_addralign = 8;		sp->sh_entsize = sizeof (Elf64_Sym);		if (Pread(P, &elfdata[off], sp->sh_size,		    d[DI_SYMTAB]->d_un.d_ptr) != sp->sh_size) {			free(elfdata);			goto bad64;		}		off += roundup(sp->sh_size, 8);		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 bad64;		}		off += roundup(sp->sh_size, 8);		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 = 8;		sp->sh_entsize = sizeof (Elf64_Dyn);		(void) memcpy(&elfdata[off], dp, sp->sh_size);		off += roundup(sp->sh_size, 8);		sp++;		/*		 * Section Header[5]  sh_name: .plt		 */		if (pltsz != 0) {			sp->sh_name = 35;			sp->sh_type = SHT_PROGBITS;			sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR;			sp->sh_addr = d[DI_PLTGOT]->d_un.d_ptr;			if (ehdr.e_type == ET_DYN)				sp->sh_addr -= addr;			sp->sh_offset = off;			sp->sh_size = pltsz;			sp->sh_link = 0;			sp->sh_info = 0;			sp->sh_addralign = 8;			sp->sh_entsize = pltentsz;			if (Pread(P, &elfdata[off], sp->sh_size,			    d[DI_PLTGOT]->d_un.d_ptr) != sp->sh_size) {				free(elfdata);				goto bad64;			}			off += roundup(sp->sh_size, 8);			sp++;		}		free(dp);		goto good;bad64:		free(dp);		return (NULL);#endif	/* _LP64 */	}good:	if ((elf = elf_memory(elfdata, size)) == NULL) {		free(elfdata);		return (NULL);	}	fptr->file_elfmem = elfdata;	return (elf);}/* * We wouldn't need these if qsort(3C) took an argument for the callback... */static mutex_t sort_mtx = DEFAULTMUTEX;static char *sort_strs;static GElf_Sym *sort_syms;intbyaddr_cmp_common(GElf_Sym *a, char *aname, GElf_Sym *b, char *bname){	if (a->st_value < b->st_value)		return (-1);	if (a->st_value > b->st_value)		return (1);	/*	 * Prefer the function to the non-function.	 */	if (GELF_ST_TYPE(a->st_info) != GELF_ST_TYPE(b->st_info)) {		if (GELF_ST_TYPE(a->st_info) == STT_FUNC)			return (-1);		if (GELF_ST_TYPE(b->st_info) == STT_FUNC)			return (1);	}	/*	 * Prefer the weak or strong global symbol to the local symbol.	 */	if (GELF_ST_BIND(a->st_info) != GELF_ST_BIND(b->st_info)) {		if (GELF_ST_BIND(b->st_info) == STB_LOCAL)			return (-1);		if (GELF_ST_BIND(a->st_info) == STB_LOCAL)			return (1);	}	/*	 * Prefer the name with fewer leading underscores in the name.	 */	while (*aname == '_' && *bname == '_') {		aname++;		bname++;	}	if (*bname == '_')		return (-1);	if (*aname == '_')		return (1);	/*	 * Prefer the symbol with the smaller size.	 */	if (a->st_size < b->st_size)		return (-1);	if (a->st_size > b->st_size)		return (1);	/*	 * All other factors being equal, fall back to lexicographic order.	 */	return (strcmp(aname, bname));}static intbyaddr_cmp(const void *aa, const void *bb){	GElf_Sym *a = &sort_syms[*(uint_t *)aa];	GElf_Sym *b = &sort_syms[*(uint_t *)bb];	char *aname = sort_strs + a->st_name;	char *bname = sort_strs + b->st_name;	return (byaddr_cmp_common(a, aname, b, bname));}static intbyname_cmp(const void *aa, const void *bb){	GElf_Sym *a = &sort_syms[*(uint_t *)aa];	GElf_Sym *b = &sort_syms[*(uint_t *)bb];	char *aname = sort_strs + a->st_name;	char *bname = sort_strs + b->st_name;	return (strcmp(aname, bname));}voidoptimize_symtab(sym_tbl_t *symtab){	GElf_Sym *symp, *syms;	uint_t i, *indexa, *indexb;	Elf_Data *data;	size_t symn, strsz, count;	if (symtab == NULL || symtab->sym_data == NULL ||	    symtab->sym_byaddr != NULL)		return;	data = symtab->sym_data;	symn = symtab->sym_symn;	strsz = symtab->sym_strsz;	symp = syms = malloc(sizeof (GElf_Sym) * symn);	/*	 * First record all the symbols into a table and count up the ones	 * that we're interested in. We mark symbols as invalid by setting	 * the st_name to an illegal value.	 */	for (i = 0, count = 0; i < symn; i++, symp++) {		if (gelf_getsym(data, i, symp) != NULL &&		    symp->st_name < strsz &&		    IS_DATA_TYPE(GELF_ST_TYPE(symp->st_info)))			count++;		else			symp->st_name = strsz;	}	/*	 * Allocate sufficient space for both tables and populate them	 * with the same symbols we just counted.	 */	symtab->sym_count = count;	indexa = symtab->sym_byaddr = calloc(sizeof (uint_t), count);	indexb = symtab->sym_byname = calloc(sizeof (uint_t), count);	for (i = 0, symp = syms; i < symn; i++, symp++) {		if (symp->st_name < strsz)			*indexa++ = *indexb++ = i;	}	/*	 * Sort the two tables according to the appropriate criteria.	 */	(void) mutex_lock(&sort_mtx);	sort_strs = symtab->sym_strs;	sort_syms = syms;	qsort(symtab->sym_byaddr, count, sizeof (uint_t), byaddr_cmp);	qsort(symtab->sym_byname, count, sizeof (uint_t), byname_cmp);	sort_strs = NULL;	sort_syms = NULL;

⌨️ 快捷键说明

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