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