summaryrefslogtreecommitdiff
path: root/usr/src/lib/libproc/common/Psymtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libproc/common/Psymtab.c')
-rw-r--r--usr/src/lib/libproc/common/Psymtab.c101
1 files changed, 68 insertions, 33 deletions
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;
}
}