summaryrefslogtreecommitdiff
path: root/usr/src/lib/libproc/common
diff options
context:
space:
mode:
authorEdward Pilatowicz <Edward.Pilatowicz@Sun.COM>2009-07-29 10:29:28 -0700
committerEdward Pilatowicz <Edward.Pilatowicz@Sun.COM>2009-07-29 10:29:28 -0700
commitd9452f237f843c1321abb5810d2f9ee6cbeae43c (patch)
treedfcdd5236a225b33960c91dc69b82c7e8f76cd1c /usr/src/lib/libproc/common
parent88bb18d257c743ee382a1694604771c6b7dee061 (diff)
downloadillumos-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.c7
-rw-r--r--usr/src/lib/libproc/common/Pcore.c11
-rw-r--r--usr/src/lib/libproc/common/Psymtab.c101
-rw-r--r--usr/src/lib/libproc/common/Psymtab_machelf32.c249
-rw-r--r--usr/src/lib/libproc/common/libproc.h1
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 */