📄 psymtab.c
字号:
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 + -