diff options
author | Edward Pilatowicz <Edward.Pilatowicz@Sun.COM> | 2009-07-29 10:29:28 -0700 |
---|---|---|
committer | Edward Pilatowicz <Edward.Pilatowicz@Sun.COM> | 2009-07-29 10:29:28 -0700 |
commit | d9452f237f843c1321abb5810d2f9ee6cbeae43c (patch) | |
tree | dfcdd5236a225b33960c91dc69b82c7e8f76cd1c /usr/src/lib/libproc/common | |
parent | 88bb18d257c743ee382a1694604771c6b7dee061 (diff) | |
download | illumos-gate-d9452f237f843c1321abb5810d2f9ee6cbeae43c.tar.gz |
6863263 libproc doesn't access in-core elf data correctly
Diffstat (limited to 'usr/src/lib/libproc/common')
-rw-r--r-- | usr/src/lib/libproc/common/Pcontrol.c | 7 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pcore.c | 11 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Psymtab.c | 101 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Psymtab_machelf32.c | 249 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/libproc.h | 1 |
5 files changed, 233 insertions, 136 deletions
diff --git a/usr/src/lib/libproc/common/Pcontrol.c b/usr/src/lib/libproc/common/Pcontrol.c index fd4e10fb74..deccb122c3 100644 --- a/usr/src/lib/libproc/common/Pcontrol.c +++ b/usr/src/lib/libproc/common/Pcontrol.c @@ -20,14 +20,13 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Portions Copyright 2007 Chad Mynhier */ -#pragma ident "%Z%%M% %I% %E% SMI" - +#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -59,6 +58,7 @@ int _libproc_debug; /* set non-zero to enable debugging printfs */ int _libproc_no_qsort; /* set non-zero to inhibit sorting */ /* of symbol tables */ +int _libproc_incore_elf; /* only use in-core elf data */ sigset_t blockable_sigs; /* signals to block when we need to be safe */ static int minfd; /* minimum file descriptor returned by dupfd(fd, 0) */ @@ -99,6 +99,7 @@ _libproc_init(void) { _libproc_debug = getenv("LIBPROC_DEBUG") != NULL; _libproc_no_qsort = getenv("LIBPROC_NO_QSORT") != NULL; + _libproc_incore_elf = getenv("LIBPROC_INCORE_ELF") != NULL; (void) sigfillset(&blockable_sigs); (void) sigdelset(&blockable_sigs, SIGKILL); diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c index 2357be4364..234538eb0b 100644 --- a/usr/src/lib/libproc/common/Pcore.c +++ b/usr/src/lib/libproc/common/Pcore.c @@ -810,9 +810,16 @@ fake_up_symtab(struct ps_prochandle *P, const elf_file_header_t *ehdr, if (symtab->sh_addr == 0 || (mp = Paddr2mptr(P, symtab->sh_addr)) == NULL || - (fp = mp->map_file) == NULL || - fp->file_symtab.sym_data_pri != NULL) { + (fp = mp->map_file) == NULL) { dprintf("fake_up_symtab: invalid section\n"); + dprintf("fp->file_symtab.sym_data_pri == %lx\n", + (long)fp->file_symtab.sym_data_pri); + return; + } + + if (fp->file_symtab.sym_data_pri != NULL) { + dprintf("Symbol table already loaded (sh_addr 0x%lx)\n", + (long)symtab->sh_addr); return; } diff --git a/usr/src/lib/libproc/common/Psymtab.c b/usr/src/lib/libproc/common/Psymtab.c index 725a765798..7a71fa155d 100644 --- a/usr/src/lib/libproc/common/Psymtab.c +++ b/usr/src/lib/libproc/common/Psymtab.c @@ -1587,6 +1587,31 @@ optimize_symtab(sym_tbl_t *symtab) free(syms); } + +static Elf * +build_fake_elf(struct ps_prochandle *P, file_info_t *fptr, GElf_Ehdr *ehdr, + size_t *nshdrs, Elf_Data **shdata) +{ + size_t shstrndx; + Elf_Scn *scn; + Elf *elf; + + if ((elf = fake_elf(P, fptr)) == NULL || + elf_kind(elf) != ELF_K_ELF || + gelf_getehdr(elf, ehdr) == NULL || + elf_getshdrnum(elf, nshdrs) == -1 || + elf_getshdrstrndx(elf, &shstrndx) == -1 || + (scn = elf_getscn(elf, shstrndx)) == NULL || + (*shdata = elf_getdata(scn, NULL)) == NULL) { + if (elf != NULL) + (void) elf_end(elf); + dprintf("failed to fake up ELF file\n"); + return (NULL); + } + + return (elf); +} + /* * Build the symbol table for the given mapped file. */ @@ -1657,20 +1682,22 @@ Pbuild_file_symtab(struct ps_prochandle *P, file_info_t *fptr) * name. If anything goes wrong try to fake up an elf file from * the in-core elf image. */ - if ((fptr->file_fd = open(objectfile, O_RDONLY)) < 0) { + + if (_libproc_incore_elf) { + dprintf("Pbuild_file_symtab: using in-core data for: %s\n", + fptr->file_pname); + + if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) == + NULL) + return; + + } else if ((fptr->file_fd = open(objectfile, O_RDONLY)) < 0) { dprintf("Pbuild_file_symtab: failed to open %s: %s\n", objectfile, strerror(errno)); - if ((elf = fake_elf(P, fptr)) == NULL || - elf_kind(elf) != ELF_K_ELF || - gelf_getehdr(elf, &ehdr) == NULL || - elf_getshdrnum(elf, &nshdrs) == -1 || - elf_getshdrstrndx(elf, &shstrndx) == -1 || - (scn = elf_getscn(elf, shstrndx)) == NULL || - (shdata = elf_getdata(scn, NULL)) == NULL) { - dprintf("failed to fake up ELF file\n"); + if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) == + NULL) return; - } } else if ((elf = elf_begin(fptr->file_fd, ELF_C_READ, NULL)) == NULL || elf_kind(elf) != ELF_K_ELF || @@ -1683,17 +1710,11 @@ Pbuild_file_symtab(struct ps_prochandle *P, file_info_t *fptr) dprintf("failed to process ELF file %s: %s\n", objectfile, (err == 0) ? "<null>" : elf_errmsg(err)); + (void) elf_end(elf); - if ((elf = fake_elf(P, fptr)) == NULL || - elf_kind(elf) != ELF_K_ELF || - gelf_getehdr(elf, &ehdr) == NULL || - elf_getshdrnum(elf, &nshdrs) == -1 || - elf_getshdrstrndx(elf, &shstrndx) == -1 || - (scn = elf_getscn(elf, shstrndx)) == NULL || - (shdata = elf_getdata(scn, NULL)) == NULL) { - dprintf("failed to fake up ELF file\n"); - goto bad; - } + if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) == + NULL) + return; } else if (file_differs(P, elf, fptr)) { Elf *newelf; @@ -1704,23 +1725,14 @@ Pbuild_file_symtab(struct ps_prochandle *P, file_info_t *fptr) * they don't agree, we try to fake up a new elf file and * proceed with that instead. */ - dprintf("ELF file %s (%lx) doesn't match in-core image\n", fptr->file_pname, (ulong_t)fptr->file_map->map_pmap.pr_vaddr); - if ((newelf = fake_elf(P, fptr)) == NULL || - elf_kind(newelf) != ELF_K_ELF || - gelf_getehdr(newelf, &ehdr) == NULL || - elf_getshdrnum(newelf, &nshdrs) == -1 || - elf_getshdrstrndx(newelf, &shstrndx) == -1 || - (scn = elf_getscn(newelf, shstrndx)) == NULL || - (shdata = elf_getdata(scn, NULL)) == NULL) { - dprintf("failed to fake up ELF file\n"); - } else { + if ((newelf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) + != NULL) { (void) elf_end(elf); elf = newelf; - dprintf("switched to faked up ELF file\n"); } } @@ -1910,13 +1922,36 @@ Pbuild_file_symtab(struct ps_prochandle *P, file_info_t *fptr) GElf_Dyn d; for (i = 0; i < ndyn; i++) { - if (gelf_getdyn(dyn->c_data, i, &d) != NULL && - d.d_tag == DT_JMPREL) { + if (gelf_getdyn(dyn->c_data, i, &d) == NULL) + continue; + + switch (d.d_tag) { + case DT_JMPREL: dprintf("DT_JMPREL is %p\n", (void *)(uintptr_t)d.d_un.d_ptr); fptr->file_jmp_rel = d.d_un.d_ptr + fptr->file_dyn_base; break; + case DT_STRTAB: + dprintf("DT_STRTAB is %p\n", + (void *)(uintptr_t)d.d_un.d_ptr); + break; + case DT_PLTGOT: + dprintf("DT_PLTGOT is %p\n", + (void *)(uintptr_t)d.d_un.d_ptr); + break; + case DT_SUNW_SYMTAB: + dprintf("DT_SUNW_SYMTAB is %p\n", + (void *)(uintptr_t)d.d_un.d_ptr); + break; + case DT_SYMTAB: + dprintf("DT_SYMTAB is %p\n", + (void *)(uintptr_t)d.d_un.d_ptr); + break; + case DT_HASH: + dprintf("DT_HASH is %p\n", + (void *)(uintptr_t)d.d_un.d_ptr); + break; } } diff --git a/usr/src/lib/libproc/common/Psymtab_machelf32.c b/usr/src/lib/libproc/common/Psymtab_machelf32.c index 704e41547c..9c57b3e5c7 100644 --- a/usr/src/lib/libproc/common/Psymtab_machelf32.c +++ b/usr/src/lib/libproc/common/Psymtab_machelf32.c @@ -20,15 +20,15 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - +#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <stddef.h> +#include <string.h> #include <memory.h> #include <sys/sysmacros.h> #include <sys/machelf.h> @@ -146,14 +146,14 @@ * 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_PLTGOT GOT PLT entry offset (on x86) or PLT offset (on sparc) * 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. + * We can use the number of relocation entries to calculate the size of + * the PLT. We get the address of the PLT by looking up the + * _PROCEDURE_LINKAGE_TABLE_ symbol. * * For more information, check out the System V Generic ABI. */ @@ -245,7 +245,7 @@ fake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr, size_t size = 0; caddr_t elfdata = NULL; Elf *elf; - size_t dynsym_size, ldynsym_size; + size_t dynsym_size = 0, ldynsym_size; int dynstr_shndx; Ehdr *ep; Shdr *sp; @@ -253,7 +253,9 @@ fake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr, Dyn *d[DI_NENT] = { 0 }; uint_t i; Off off; - size_t pltsz = 0, pltentsz; + size_t pltsz = 0, pltentries = 0; + uintptr_t hptr = NULL; + Word hnchains, hnbuckets; if (ehdr->e_type == ET_DYN) phdr->p_vaddr += addr; @@ -327,18 +329,6 @@ fake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr, goto bad; } - 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; - if (d[DI_SUNW_SYMTAB] != NULL) - d[DI_SUNW_SYMTAB]->d_un.d_ptr += addr; - } - /* SUNW_ldynsym must be adjacent to dynsym. Ignore if not */ if ((d[DI_SUNW_SYMTAB] != NULL) && (d[DI_SUNW_SYMSZ] != NULL) && ((d[DI_SYMTAB]->d_un.d_ptr <= d[DI_SUNW_SYMTAB]->d_un.d_ptr) || @@ -359,6 +349,23 @@ fake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr, size += sizeof (Shdr); size += roundup(sizeof (shstr), SH_ADDRALIGN); + if (d[DI_HASH] != NULL) { + Word hash[2]; + + hptr = d[DI_HASH]->d_un.d_ptr; + if (ehdr->e_type == ET_DYN) + hptr += addr; + + if (Pread(P, hash, sizeof (hash), hptr) != sizeof (hash)) { + dprintf("Pread of .hash at %lx failed\n", + (long)(hptr)); + goto bad; + } + + hnbuckets = hash[0]; + hnchains = hash[1]; + } + /* * .dynsym and .SUNW_ldynsym sections. * @@ -374,16 +381,7 @@ fake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr, ldynsym_size -= dynsym_size; dynstr_shndx = 4; } else { - Word nchain; - - if (Pread(P, &nchain, sizeof (nchain), - d[DI_HASH]->d_un.d_ptr + sizeof (nchain)) != - sizeof (nchain)) { - dprintf("Pread of .dynsym at %lx failed\n", - (long)(d[DI_HASH]->d_un.d_val + sizeof (nchain))); - goto bad; - } - dynsym_size = sizeof (Sym) * nchain; + dynsym_size = sizeof (Sym) * hnchains; ldynsym_size = 0; dynstr_shndx = 3; } @@ -400,64 +398,41 @@ fake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr, /* .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 entries = pltrelsz / sizeof (Rela); - Rela r[2]; - - if (entries < PLTREL_MIN_ENTRIES) { - dprintf("too few PLT relocation entries " - "(found %d, expected at least %d)\n", - entries, PLTREL_MIN_ENTRIES); - goto bad; - } - if (entries < PLTREL_MIN_ENTRIES + 2) - goto done_with_plt; - - if (Pread(P, r, sizeof (r), jmprel + sizeof (r[0]) * - entries - sizeof (r)) != sizeof (r)) { - dprintf("Pread of DT_RELA failed\n"); - goto bad; - } - - penult = r[0].r_offset; - ult = r[1].r_offset; - + pltentries = pltrelsz / sizeof (Rela); } else if (d[DI_PLTREL]->d_un.d_val == DT_REL) { - uint_t entries = pltrelsz / sizeof (Rel); - Rel r[2]; - - if (entries < PLTREL_MIN_ENTRIES) { - dprintf("too few PLT relocation entries " - "(found %d, expected at least %d)\n", - entries, PLTREL_MIN_ENTRIES); - goto bad; - } - if (entries < PLTREL_MIN_ENTRIES + 2) - goto done_with_plt; - - if (Pread(P, r, sizeof (r), jmprel + sizeof (r[0]) * - entries - sizeof (r)) != sizeof (r)) { - dprintf("Pread of DT_REL failed\n"); - goto bad; - } - - penult = r[0].r_offset; - ult = r[1].r_offset; + pltentries = pltrelsz / sizeof (Rel); } else { - dprintf(".plt: unknown jmprel value\n"); - goto bad; + /* fall back to the platform default */ +#if ((defined(__i386) || defined(__amd64)) && !defined(_ELF64)) + pltentries = pltrelsz / sizeof (Rel); + dprintf("DI_PLTREL not found, defaulting to Rel"); +#else /* (!(__i386 || __amd64)) || _ELF64 */ + pltentries = pltrelsz / sizeof (Rela); + dprintf("DI_PLTREL not found, defaulting to Rela"); +#endif /* (!(__i386 || __amd64) || _ELF64 */ } - pltentsz = ult - penult; - - if (ehdr->e_type == ET_DYN) - ult += addr; - - pltsz = ult - d[DI_PLTGOT]->d_un.d_ptr + pltentsz; + if (pltentries < PLTREL_MIN_ENTRIES) { + dprintf("too few PLT relocation entries " + "(found %lu, expected at least %d)\n", + (long)pltentries, PLTREL_MIN_ENTRIES); + goto bad; + } + if (pltentries < PLTREL_MIN_ENTRIES + 2) + goto done_with_plt; + + /* + * Now that we know the number of plt relocation entries + * we can calculate the size of the plt. + */ + pltsz = (pltentries + M_PLT_XNumber) * M_PLT_ENTSIZE; +#if defined(__sparc) + /* The sparc PLT always has a (delay slot) nop at the end */ + pltsz += 4; +#endif /* __sparc */ size += sizeof (Shdr); size += roundup(pltsz, SH_ADDRALIGN); @@ -532,7 +507,7 @@ done_with_plt: sp->sh_flags = SHF_ALLOC; sp->sh_addr = d[DI_SUNW_SYMTAB]->d_un.d_ptr; if (ehdr->e_type == ET_DYN) - sp->sh_addr -= addr; + sp->sh_addr += addr; sp->sh_offset = off; sp->sh_size = ldynsym_size; sp->sh_link = dynstr_shndx; @@ -542,9 +517,9 @@ done_with_plt: sp->sh_entsize = sizeof (Sym); if (Pread(P, &elfdata[off], sp->sh_size, - d[DI_SUNW_SYMTAB]->d_un.d_ptr) != sp->sh_size) { + sp->sh_addr) != sp->sh_size) { dprintf("failed to read .SUNW_ldynsym at %lx\n", - (long)d[DI_SUNW_SYMTAB]->d_un.d_ptr); + (long)sp->sh_addr); goto bad; } off += sp->sh_size; @@ -560,7 +535,7 @@ done_with_plt: 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_addr += addr; sp->sh_offset = off; sp->sh_size = dynsym_size; sp->sh_link = dynstr_shndx; @@ -569,9 +544,9 @@ done_with_plt: sp->sh_entsize = sizeof (Sym); if (Pread(P, &elfdata[off], sp->sh_size, - d[DI_SYMTAB]->d_un.d_ptr) != sp->sh_size) { + sp->sh_addr) != sp->sh_size) { dprintf("failed to read .dynsym at %lx\n", - (long)d[DI_SYMTAB]->d_un.d_ptr); + (long)sp->sh_addr); goto bad; } @@ -586,7 +561,7 @@ done_with_plt: 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_addr += addr; sp->sh_offset = off; sp->sh_size = d[DI_STRSZ]->d_un.d_val; sp->sh_link = 0; @@ -595,7 +570,7 @@ done_with_plt: sp->sh_entsize = 0; if (Pread(P, &elfdata[off], sp->sh_size, - d[DI_STRTAB]->d_un.d_ptr) != sp->sh_size) { + sp->sh_addr) != sp->sh_size) { dprintf("failed to read .dynstr\n"); goto bad; } @@ -626,28 +601,108 @@ done_with_plt: * Section Header: .plt */ if (pltsz != 0) { + ulong_t plt_symhash; + uint_t htmp, ndx; + uintptr_t strtabptr, strtabname; + Sym sym, *symtabptr; + uint_t *hash; + char strbuf[sizeof ("_PROCEDURE_LINKAGE_TABLE_")]; + + /* + * Now we need to find the address of the plt by looking + * up the "_PROCEDURE_LINKAGE_TABLE_" symbol. + */ + + /* get the address of the symtab and strtab sections */ + strtabptr = d[DI_STRTAB]->d_un.d_ptr; + symtabptr = (Sym *)(uintptr_t)d[DI_SYMTAB]->d_un.d_ptr; + if (ehdr->e_type == ET_DYN) { + strtabptr += addr; + symtabptr = (Sym*)((uintptr_t)symtabptr + addr); + } + + /* find the .hash bucket address for this symbol */ + plt_symhash = elf_hash("_PROCEDURE_LINKAGE_TABLE_"); + htmp = plt_symhash % hnbuckets; + hash = &((uint_t *)hptr)[2 + htmp]; + + /* read the elf hash bucket index */ + if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) != + sizeof (ndx)) { + dprintf("Pread of .hash at %lx failed\n", (long)hash); + goto bad; + } + + while (ndx) { + if (Pread(P, &sym, sizeof (sym), + (uintptr_t)&symtabptr[ndx]) != sizeof (sym)) { + dprintf("Pread of .symtab at %lx failed\n", + (long)&symtabptr[ndx]); + goto bad; + } + + strtabname = strtabptr + sym.st_name; + if (Pread_string(P, strbuf, sizeof (strbuf), + strtabname) < 0) { + dprintf("Pread of .strtab at %lx failed\n", + (long)strtabname); + goto bad; + } + + if (strcmp("_PROCEDURE_LINKAGE_TABLE_", strbuf) == 0) + break; + + hash = &((uint_t *)hptr)[2 + hnbuckets + ndx]; + if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) != + sizeof (ndx)) { + dprintf("Pread of .hash at %lx failed\n", + (long)hash); + goto bad; + } + } + +#if defined(__sparc) + if (sym.st_value != d[DI_PLTGOT]->d_un.d_ptr) { + dprintf("warning: DI_PLTGOT (%lx) doesn't match " + ".plt symbol pointer (%lx)", + (long)d[DI_PLTGOT]->d_un.d_ptr, + (long)sym.st_value); + } +#endif /* __sparc */ + + if (ndx == 0) { + dprintf( + "Failed to find \"_PROCEDURE_LINKAGE_TABLE_\"\n"); + goto bad; + } + sp->sh_name = SHSTR_NDX_plt; sp->sh_type = SHT_PROGBITS; sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR; - sp->sh_addr = d[DI_PLTGOT]->d_un.d_ptr; + sp->sh_addr = sym.st_value; if (ehdr->e_type == ET_DYN) - sp->sh_addr -= addr; + sp->sh_addr += addr; sp->sh_offset = off; sp->sh_size = pltsz; sp->sh_link = 0; sp->sh_info = 0; sp->sh_addralign = SH_ADDRALIGN; - sp->sh_entsize = pltentsz; + sp->sh_entsize = M_PLT_ENTSIZE; - if (Pread(P, &elfdata[off], sp->sh_size, - d[DI_PLTGOT]->d_un.d_ptr) != sp->sh_size) { - dprintf("failed to read .plt\n"); + if (Pread(P, &elfdata[off], sp->sh_size, sp->sh_addr) != + sp->sh_size) { + dprintf("failed to read .plt at %lx\n", + (long)sp->sh_addr); goto bad; } off += roundup(sp->sh_size, SH_ADDRALIGN); sp++; } + /* make sure we didn't write past the end of allocated memory */ + sp++; + assert(((uintptr_t)(sp) - 1) < ((uintptr_t)elfdata + size)); + free(dp); if ((elf = elf_memory(elfdata, size)) == NULL) { free(elfdata); @@ -664,6 +719,4 @@ bad: if (elfdata != NULL) free(elfdata); return (NULL); - - } diff --git a/usr/src/lib/libproc/common/libproc.h b/usr/src/lib/libproc/common/libproc.h index a425d3c211..8f3730c3a0 100644 --- a/usr/src/lib/libproc/common/libproc.h +++ b/usr/src/lib/libproc/common/libproc.h @@ -85,6 +85,7 @@ struct ps_lwphandle; extern int _libproc_debug; /* set non-zero to enable debugging fprintfs */ extern int _libproc_no_qsort; /* set non-zero to inhibit sorting */ /* of symbol tables */ +extern int _libproc_incore_elf; /* only use in-core elf data */ #if defined(__sparc) #define R_RVAL1 R_O0 /* register holding a function return value */ |