summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/mdb/common/modules/libproc/libproc.c40
-rw-r--r--usr/src/lib/libproc/Makefile.com4
-rw-r--r--usr/src/lib/libproc/amd64/Makefile10
-rw-r--r--usr/src/lib/libproc/amd64/Pisadep.c11
-rw-r--r--usr/src/lib/libproc/common/Pcontrol.h27
-rw-r--r--usr/src/lib/libproc/common/Pcore.c8
-rw-r--r--usr/src/lib/libproc/common/Pgcore.c25
-rw-r--r--usr/src/lib/libproc/common/Psymtab.c877
-rw-r--r--usr/src/lib/libproc/common/Psymtab_machelf.h48
-rw-r--r--usr/src/lib/libproc/common/Psymtab_machelf32.c637
-rw-r--r--usr/src/lib/libproc/common/Psymtab_machelf64.c34
-rw-r--r--usr/src/lib/libproc/i386/Pisadep.c9
-rw-r--r--usr/src/lib/libproc/sparc/Pisadep.c9
-rw-r--r--usr/src/lib/libproc/sparcv9/Makefile10
-rw-r--r--usr/src/lib/libproc/sparcv9/Pisadep.c11
15 files changed, 918 insertions, 842 deletions
diff --git a/usr/src/cmd/mdb/common/modules/libproc/libproc.c b/usr/src/cmd/mdb/common/modules/libproc/libproc.c
index f1a87503cd..c0a3314f49 100644
--- a/usr/src/cmd/mdb/common/modules/libproc/libproc.c
+++ b/usr/src/cmd/mdb/common/modules/libproc/libproc.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,7 +46,9 @@ static int
pr_symtab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
sym_tbl_t symtab;
- Elf_Data data;
+ Elf_Data data_pri;
+ Elf_Data data_aux;
+ Elf_Data *data;
#ifdef _LP64
Elf64_Sym sym;
int width = 16;
@@ -85,9 +87,25 @@ pr_symtab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_ERR);
}
- if (mdb_vread(&data, sizeof (Elf_Data),
- (uintptr_t)symtab.sym_data) == -1) {
- mdb_warn("failed to read Elf_Data at %p", symtab.sym_data);
+ /*
+ * As described in the libproc header Pcontrol.h, a sym_tbl_t
+ * contains a primary and an optional auxiliary symbol table.
+ * We treat the combination as a single table, with the auxiliary
+ * values coming before the primary ones.
+ *
+ * Read the primary and auxiliary Elf_Data structs.
+ */
+ if (mdb_vread(&data_pri, sizeof (Elf_Data),
+ (uintptr_t)symtab.sym_data_pri) == -1) {
+ mdb_warn("failed to read primary Elf_Data at %p",
+ symtab.sym_data_pri);
+ return (DCMD_ERR);
+ }
+ if ((symtab.sym_symn_aux > 0) &&
+ (mdb_vread(&data_aux, sizeof (Elf_Data),
+ (uintptr_t)symtab.sym_data_aux) == -1)) {
+ mdb_warn("failed to read auxiliary Elf_Data at %p",
+ symtab.sym_data_aux);
return (DCMD_ERR);
}
@@ -116,10 +134,18 @@ pr_symtab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
else
idx = i;
- if (mdb_vread(&sym, sizeof (sym), (uintptr_t)data.d_buf +
+ /* If index is in range of primary symtab, look it up there */
+ if (idx >= symtab.sym_symn_aux) {
+ data = &data_pri;
+ idx -= symtab.sym_symn_aux;
+ } else { /* Look it up in the auxiliary symtab */
+ data = &data_aux;
+ }
+
+ if (mdb_vread(&sym, sizeof (sym), (uintptr_t)data->d_buf +
idx * sizeof (sym)) == -1) {
mdb_warn("failed to read symbol at %p",
- (uintptr_t)data.d_buf + idx * sizeof (sym));
+ (uintptr_t)data->d_buf + idx * sizeof (sym));
if (symlist)
mdb_free(symlist, symlistsz);
return (DCMD_ERR);
diff --git a/usr/src/lib/libproc/Makefile.com b/usr/src/lib/libproc/Makefile.com
index 521381ab6d..e9bd629f9d 100644
--- a/usr/src/lib/libproc/Makefile.com
+++ b/usr/src/lib/libproc/Makefile.com
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -40,6 +40,8 @@ CMNOBJS = \
Plwpregs.o \
Pservice.o \
Psymtab.o \
+ Psymtab_machelf32.o \
+ $(CMNOBJS64) \
Pscantext.o \
Pstack.o \
Psyscall.o \
diff --git a/usr/src/lib/libproc/amd64/Makefile b/usr/src/lib/libproc/amd64/Makefile
index b74d317152..1e20da114e 100644
--- a/usr/src/lib/libproc/amd64/Makefile
+++ b/usr/src/lib/libproc/amd64/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,15 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
+# This is a 64-bit build, and as such needs 64-bit ELF support
+CMNOBJS64 = Psymtab_machelf64.o
+
include ../Makefile.com
include ../../Makefile.lib.64
diff --git a/usr/src/lib/libproc/amd64/Pisadep.c b/usr/src/lib/libproc/amd64/Pisadep.c
index 2583474d58..c2ab4dd3ab 100644
--- a/usr/src/lib/libproc/amd64/Pisadep.c
+++ b/usr/src/lib/libproc/amd64/Pisadep.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -71,7 +70,7 @@ Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr)
if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
(i = ELF64_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
- Elf_Data *data = fp->file_dynsym.sym_data;
+ Elf_Data *data = fp->file_dynsym.sym_data_pri;
Elf64_Sym *symp = &(((Elf64_Sym *)data->d_buf)[i]);
return (fp->file_dynsym.sym_strs + symp->st_name);
@@ -83,7 +82,7 @@ Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr)
if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
(i = ELF32_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
- Elf_Data *data = fp->file_dynsym.sym_data;
+ Elf_Data *data = fp->file_dynsym.sym_data_pri;
Elf32_Sym *symp = &(((Elf32_Sym *)data->d_buf)[i]);
return (fp->file_dynsym.sym_strs + symp->st_name);
diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h
index 8ac88d33cb..5a4d606c9d 100644
--- a/usr/src/lib/libproc/common/Pcontrol.h
+++ b/usr/src/lib/libproc/common/Pcontrol.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -53,12 +53,31 @@ extern "C" {
* These may change without affecting clients of libproc.
*/
+/*
+ * sym_tbl_t contains a primary and an (optional) auxiliary symbol table, which
+ * we wish to treat as a single logical symbol table. In this logical table,
+ * the data from the auxiliary table preceeds that from the primary. Symbol
+ * indices start at [0], which is the first item in the auxiliary table
+ * if there is one. The sole purpose for this is so that we can treat the
+ * combination of .SUNW_ldynsym and .dynsym sections as a logically single
+ * entity without having to violate the public interface to libelf.
+ *
+ * Both tables must share the same string table section.
+ *
+ * The symtab_getsym() function serves as a gelf_getsym() replacement
+ * that is aware of the two tables and makes them look like a single table
+ * to the caller.
+ *
+ */
typedef struct sym_tbl { /* symbol table */
- Elf_Data *sym_data; /* start of table */
- size_t sym_symn; /* number of entries */
+ Elf_Data *sym_data_pri; /* primary table */
+ Elf_Data *sym_data_aux; /* auxiliary table */
+ size_t sym_symn_aux; /* number of entries in auxiliary table */
+ size_t sym_symn; /* total number of entries in both tables */
char *sym_strs; /* ptr to strings */
size_t sym_strsz; /* size of string table */
- GElf_Shdr sym_hdr; /* symbol table section header */
+ GElf_Shdr sym_hdr_pri; /* primary symbol table section header */
+ GElf_Shdr sym_hdr_aux; /* auxiliary symbol table section header */
GElf_Shdr sym_strhdr; /* string table section header */
Elf *sym_elf; /* faked-up ELF handle from core file */
void *sym_elfmem; /* data for faked-up ELF handle */
diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c
index 80b7e16311..b4cfea717a 100644
--- a/usr/src/lib/libproc/common/Pcore.c
+++ b/usr/src/lib/libproc/common/Pcore.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -812,7 +812,7 @@ 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 != NULL) {
+ fp->file_symtab.sym_data_pri != NULL) {
dprintf("fake_up_symtab: invalid section\n");
return;
}
@@ -950,7 +950,7 @@ fake_up_symtab(struct ps_prochandle *P, const elf_file_header_t *ehdr,
}
if ((scn = elf_getscn(fp->file_symtab.sym_elf, 1)) == NULL ||
- (fp->file_symtab.sym_data = elf_getdata(scn, NULL)) == NULL ||
+ (fp->file_symtab.sym_data_pri = elf_getdata(scn, NULL)) == NULL ||
(scn = elf_getscn(fp->file_symtab.sym_elf, 2)) == NULL ||
(data = elf_getdata(scn, NULL)) == NULL) {
dprintf("fake_up_symtab: failed to get section data at %p\n",
@@ -961,7 +961,7 @@ fake_up_symtab(struct ps_prochandle *P, const elf_file_header_t *ehdr,
fp->file_symtab.sym_strs = data->d_buf;
fp->file_symtab.sym_strsz = data->d_size;
fp->file_symtab.sym_symn = symtab->sh_size / symtab->sh_entsize;
- fp->file_symtab.sym_hdr = *symtab;
+ fp->file_symtab.sym_hdr_pri = *symtab;
fp->file_symtab.sym_strhdr = *strtab;
optimize_symtab(&fp->file_symtab);
diff --git a/usr/src/lib/libproc/common/Pgcore.c b/usr/src/lib/libproc/common/Pgcore.c
index cf60653e1d..8bb6781bf3 100644
--- a/usr/src/lib/libproc/common/Pgcore.c
+++ b/usr/src/lib/libproc/common/Pgcore.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -573,13 +572,13 @@ count_sections(pgcore_t *pgc)
hit_symtab = 1;
}
- if (sym->sym_data != NULL && sym->sym_symn != 0 &&
+ if (sym->sym_data_pri != NULL && sym->sym_symn != 0 &&
sym->sym_strs != NULL)
nshdrs += 2;
}
if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab &&
- fptr->file_symtab.sym_data != NULL &&
+ fptr->file_symtab.sym_data_pri != NULL &&
fptr->file_symtab.sym_symn != 0 &&
fptr->file_symtab.sym_strs != NULL) {
nshdrs += 2;
@@ -651,18 +650,18 @@ dump_symtab(pgcore_t *pgc, file_info_t *fptr, uint_t index, int dynsym)
size_t size;
uintptr_t addr = fptr->file_map->map_pmap.pr_vaddr;
- if (sym->sym_data == NULL || sym->sym_symn == 0 ||
+ if (sym->sym_data_pri == NULL || sym->sym_symn == 0 ||
sym->sym_strs == NULL)
return (0);
- size = sym->sym_hdr.sh_size;
- if (pwrite64(pgc->pgc_fd, sym->sym_data->d_buf, size,
+ size = sym->sym_hdr_pri.sh_size;
+ if (pwrite64(pgc->pgc_fd, sym->sym_data_pri->d_buf, size,
*pgc->pgc_doff) != size)
return (-1);
if (write_shdr(pgc, symname, symtype, 0, addr, *pgc->pgc_doff, size,
- index + 1, sym->sym_hdr.sh_info, sym->sym_hdr.sh_addralign,
- sym->sym_hdr.sh_entsize) != 0)
+ index + 1, sym->sym_hdr_pri.sh_info, sym->sym_hdr_pri.sh_addralign,
+ sym->sym_hdr_pri.sh_entsize) != 0)
return (-1);
*pgc->pgc_doff += roundup(size, 8);
@@ -718,7 +717,7 @@ dump_sections(pgcore_t *pgc)
hit_symtab = 1;
}
- if (sym->sym_data != NULL && sym->sym_symn != 0 &&
+ if (sym->sym_data_pri != NULL && sym->sym_symn != 0 &&
sym->sym_strs != NULL) {
symindex = index;
if (dump_symtab(pgc, fptr, index, dynsym) != 0)
@@ -745,7 +744,7 @@ dump_sections(pgcore_t *pgc)
}
if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab &&
- fptr->file_symtab.sym_data != NULL &&
+ fptr->file_symtab.sym_data_pri != NULL &&
fptr->file_symtab.sym_symn != 0 &&
fptr->file_symtab.sym_strs != NULL) {
if (dump_symtab(pgc, fptr, index, 0) != 0)
diff --git a/usr/src/lib/libproc/common/Psymtab.c b/usr/src/lib/libproc/common/Psymtab.c
index 035102fb57..35107c546b 100644
--- a/usr/src/lib/libproc/common/Psymtab.c
+++ b/usr/src/lib/libproc/common/Psymtab.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -50,6 +50,7 @@
#include "libproc.h"
#include "Pcontrol.h"
#include "Putil.h"
+#include "Psymtab_machelf.h"
static file_info_t *build_map_symtab(struct ps_prochandle *, map_info_t *);
static map_info_t *exec_map(struct ps_prochandle *);
@@ -708,7 +709,7 @@ Pbuild_file_ctf(struct ps_prochandle *P, file_info_t *fptr)
return (NULL);
symp = fptr->file_ctf_dyn ? &fptr->file_dynsym : &fptr->file_symtab;
- if (symp->sym_data == NULL)
+ if (symp->sym_data_pri == NULL)
return (NULL);
/*
@@ -741,12 +742,12 @@ Pbuild_file_ctf(struct ps_prochandle *P, file_info_t *fptr)
ctdata.cts_offset = 0;
symtab.cts_name = fptr->file_ctf_dyn ? ".dynsym" : ".symtab";
- symtab.cts_type = symp->sym_hdr.sh_type;
- symtab.cts_flags = symp->sym_hdr.sh_flags;
- symtab.cts_data = symp->sym_data->d_buf;
- symtab.cts_size = symp->sym_hdr.sh_size;
- symtab.cts_entsize = symp->sym_hdr.sh_entsize;
- symtab.cts_offset = symp->sym_hdr.sh_offset;
+ symtab.cts_type = symp->sym_hdr_pri.sh_type;
+ symtab.cts_flags = symp->sym_hdr_pri.sh_flags;
+ symtab.cts_data = symp->sym_data_pri->d_buf;
+ symtab.cts_size = symp->sym_hdr_pri.sh_size;
+ symtab.cts_entsize = symp->sym_hdr_pri.sh_entsize;
+ symtab.cts_offset = symp->sym_hdr_pri.sh_offset;
strtab.cts_name = fptr->file_ctf_dyn ? ".dynstr" : ".strtab";
strtab.cts_type = symp->sym_strhdr.sh_type;
@@ -1294,27 +1295,17 @@ found_cksum:
return (0);
}
+/*
+ * Read data from the specified process and construct an in memory
+ * image of an ELF file that represents it well enough to let
+ * us probe it for information.
+ */
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";
+ uintptr_t addr;
+ uint_t phnum;
if (fptr->file_map == NULL)
return (NULL);
@@ -1325,754 +1316,28 @@ fake_elf(struct ps_prochandle *P, file_info_t *fptr)
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_Ehdr ehdr;
Elf32_Phdr phdr;
- Elf32_Shdr *sp;
- Elf32_Dyn *dp;
- Elf32_Dyn *d[DI_NENT] = { 0 };
- uint_t phnum, i, dcount = 0;
- uint32_t off;
- size_t pltsz = 0, pltentsz;
if ((read_ehdr32(P, &ehdr, &phnum, addr) != 0) ||
read_dynamic_phdr32(P, &ehdr, phnum, &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)
- goto bad32;
-
- /*
- * Allow librtld_db the opportunity to "fix" the program
- * headers, if it needs to, before we process them.
- */
- if (P->rap != NULL && ehdr.e_type == ET_DYN) {
- rd_fix_phdrs(P->rap, dp, phdr.p_filesz, addr);
- }
-
- 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");
- goto bad32;
- }
-
- 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 += 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)) {
- dprintf("Pread of .dynsym at %lx failed\n",
- (long)(d[DI_HASH]->d_un.d_val + 4));
- 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)) {
- dprintf("Pread of DT_RELA failed\n");
- 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)) {
- dprintf("Pread of DT_REL failed\n");
- goto bad32;
- }
-
- penult = r[0].r_offset;
- ult = r[1].r_offset;
- } else {
- dprintf(".plt: unknown jmprel value\n");
- 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 = phnum;
- ep->e_shoff = ep->e_phoff + 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], phnum * ep->e_phentsize,
- addr + ehdr.e_phoff) != phnum * ep->e_phentsize) {
- free(elfdata);
- dprintf("failed to read program headers\n");
- 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);
- dprintf("failed to read .dynsym at %lx\n",
- (long)d[DI_SYMTAB]->d_un.d_ptr);
- 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);
- dprintf("failed to read .dynstr\n");
- 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;
- 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);
- dprintf("failed to read .plt\n");
- goto bad32;
- }
- off += roundup(sp->sh_size, 4);
- sp++;
- }
-
- free(dp);
- goto good;
-
-bad32:
- free(dp);
- return (NULL);
+ elf = fake_elf32(P, fptr, addr, &ehdr, phnum, &phdr);
#ifdef _LP64
- } else if (P->status.pr_dmodel == PR_MODEL_LP64) {
- Elf64_Ehdr ehdr, *ep;
+ } else {
+ Elf64_Ehdr ehdr;
Elf64_Phdr phdr;
- Elf64_Shdr *sp;
- Elf64_Dyn *dp;
- Elf64_Dyn *d[DI_NENT] = { 0 };
- uint_t phnum, i, dcount = 0;
- uint64_t off;
- size_t pltsz = 0, pltentsz;
if (read_ehdr64(P, &ehdr, &phnum, addr) != 0 ||
read_dynamic_phdr64(P, &ehdr, phnum, &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)
- goto bad64;
-
- 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");
- goto bad64;
- }
-
- 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 += 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)) {
- dprintf("Pread jmprel DT_RELA at %p "
- "failed\n",
- (void *)(jmprel +
- sizeof (r[0]) * ndx));
- 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)) {
- dprintf("Pread jmprel DT_REL at %p "
- "failed\n",
- (void *)(jmprel +
- sizeof (r[0]) * ndx));
- goto bad64;
- }
-
- penult = r[0].r_offset;
- ult = r[1].r_offset;
- } else {
- dprintf("DT_PLTREL value %p unknown\n",
- (void *)d[DI_PLTREL]->d_un.d_ptr);
- 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 = phnum;
- ep->e_shoff = ep->e_phoff + 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], phnum * ep->e_phentsize,
- addr + ehdr.e_phoff) != 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);
+ elf = fake_elf64(P, fptr, addr, &ehdr, phnum, &phdr);
+#endif
}
- fptr->file_elfmem = elfdata;
-
return (elf);
}
@@ -2169,23 +1434,46 @@ byname_cmp(const void *aa, const void *bb)
return (strcmp(aname, bname));
}
+/*
+ * Given a symbol index, look up the corresponding symbol from the
+ * given symbol table.
+ *
+ * This function allows the caller to treat the symbol table as a single
+ * logical entity even though there may be 2 actual ELF symbol tables
+ * involved. See the comments in Pcontrol.h for details.
+ */
+static GElf_Sym *
+symtab_getsym(sym_tbl_t *symtab, int ndx, GElf_Sym *dst)
+{
+ /* If index is in range of primary symtab, look it up there */
+ if (ndx >= symtab->sym_symn_aux) {
+ return (gelf_getsym(symtab->sym_data_pri,
+ ndx - symtab->sym_symn_aux, dst));
+ }
+
+ /* Not in primary: Look it up in the auxiliary symtab */
+ return (gelf_getsym(symtab->sym_data_aux, ndx, dst));
+}
+
void
optimize_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 ||
+ if (symtab == NULL || symtab->sym_data_pri == 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);
+ if (symp == NULL) {
+ dprintf("optimize_symtab: failed to malloc symbol array");
+ return;
+ }
/*
* First record all the symbols into a table and count up the ones
@@ -2193,7 +1481,7 @@ optimize_symtab(sym_tbl_t *symtab)
* the st_name to an illegal value.
*/
for (i = 0, count = 0; i < symn; i++, symp++) {
- if (gelf_getsym(data, i, symp) != NULL &&
+ if (symtab_getsym(symtab, i, symp) != NULL &&
symp->st_name < strsz &&
IS_DATA_TYPE(GELF_ST_TYPE(symp->st_info)))
count++;
@@ -2208,7 +1496,17 @@ optimize_symtab(sym_tbl_t *symtab)
symtab->sym_count = count;
indexa = symtab->sym_byaddr = calloc(sizeof (uint_t), count);
indexb = symtab->sym_byname = calloc(sizeof (uint_t), count);
-
+ if (indexa == NULL || indexb == NULL) {
+ dprintf(
+ "optimize_symtab: failed to malloc symbol index arrays");
+ symtab->sym_count = 0;
+ if (indexa != NULL) { /* First alloc succeeded. Free it */
+ free(indexa);
+ symtab->sym_byaddr = NULL;
+ }
+ free(syms);
+ return;
+ }
for (i = 0, symp = syms; i < symn; i++, symp++) {
if (symp->st_name < strsz)
*indexa++ = *indexb++ = i;
@@ -2398,7 +1696,8 @@ Pbuild_file_symtab(struct ps_prochandle *P, file_info_t *fptr)
/*
* Now iterate through the section cache in order to locate info
- * for the .symtab, .dynsym, .dynamic, .plt, and .SUNW_ctf sections:
+ * for the .symtab, .dynsym, .SUNW_ldynsym, .dynamic, .plt,
+ * and .SUNW_ctf sections:
*/
for (i = 1, cp = cache + 1; i < nshdrs; i++, cp++) {
GElf_Shdr *shp = &cp->c_shdr;
@@ -2416,22 +1715,37 @@ Pbuild_file_symtab(struct ps_prochandle *P, file_info_t *fptr)
* with an equivalent one. In either case, this
* check isn't essential, but it's a good idea.
*/
- if (symp->sym_data == NULL) {
+ if (symp->sym_data_pri == NULL) {
dprintf("Symbol table found for %s\n",
objectfile);
- symp->sym_data = cp->c_data;
- symp->sym_symn = shp->sh_size / shp->sh_entsize;
+ symp->sym_data_pri = cp->c_data;
+ symp->sym_symn +=
+ shp->sh_size / shp->sh_entsize;
symp->sym_strs =
cache[shp->sh_link].c_data->d_buf;
symp->sym_strsz =
cache[shp->sh_link].c_data->d_size;
- symp->sym_hdr = cp->c_shdr;
+ symp->sym_hdr_pri = cp->c_shdr;
symp->sym_strhdr = cache[shp->sh_link].c_shdr;
} else {
dprintf("Symbol table already there for %s\n",
objectfile);
}
-
+ } else if (shp->sh_type == SHT_SUNW_LDYNSYM) {
+ /* .SUNW_ldynsym section is auxiliary to .dynsym */
+ if (fptr->file_dynsym.sym_data_aux == NULL) {
+ dprintf(".SUNW_ldynsym symbol table"
+ " found for %s\n", objectfile);
+ fptr->file_dynsym.sym_data_aux = cp->c_data;
+ fptr->file_dynsym.sym_symn_aux =
+ shp->sh_size / shp->sh_entsize;
+ fptr->file_dynsym.sym_symn +=
+ fptr->file_dynsym.sym_symn_aux;
+ fptr->file_dynsym.sym_hdr_aux = cp->c_shdr;
+ } else {
+ dprintf(".SUNW_ldynsym symbol table already"
+ " there for %s\n", objectfile);
+ }
} else if (shp->sh_type == SHT_DYNAMIC) {
dyn = cp;
} else if (strcmp(cp->c_name, ".plt") == 0) {
@@ -2777,12 +2091,11 @@ sym_prefer(GElf_Sym *sym1, char *name1, GElf_Sym *sym2, char *name2)
static GElf_Sym *
sym_by_addr(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp, uint_t *idp)
{
- Elf_Data *data = symtab->sym_data;
GElf_Sym sym, osym;
uint_t i, oid, *byaddr = symtab->sym_byaddr;
int min, max, mid, omid, found = 0;
- if (data == NULL)
+ if (symtab->sym_data_pri == NULL || symtab->sym_count == 0)
return (NULL);
min = 0;
@@ -2797,7 +2110,7 @@ sym_by_addr(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp, uint_t *idp)
mid = (max + min) / 2;
i = byaddr[mid];
- (void) gelf_getsym(data, i, &sym);
+ (void) symtab_getsym(symtab, i, &sym);
if (addr >= sym.st_value &&
addr < sym.st_value + sym.st_size &&
@@ -2829,7 +2142,7 @@ sym_by_addr(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp, uint_t *idp)
break;
oid = byaddr[--omid];
- (void) gelf_getsym(data, oid, &osym);
+ (void) symtab_getsym(symtab, oid, &osym);
} while (addr >= osym.st_value &&
addr < sym.st_value + osym.st_size &&
osym.st_value == sym.st_value);
@@ -2846,12 +2159,12 @@ sym_by_addr(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp, uint_t *idp)
static GElf_Sym *
sym_by_name(sym_tbl_t *symtab, const char *name, GElf_Sym *symp, uint_t *idp)
{
- Elf_Data *data = symtab->sym_data;
char *strs = symtab->sym_strs;
uint_t i, *byname = symtab->sym_byname;
int min, mid, max, cmp;
- if (data == NULL || strs == NULL)
+ if (symtab->sym_data_pri == NULL || strs == NULL ||
+ symtab->sym_count == 0)
return (NULL);
min = 0;
@@ -2861,7 +2174,7 @@ sym_by_name(sym_tbl_t *symtab, const char *name, GElf_Sym *symp, uint_t *idp)
mid = (max + min) / 2;
i = byname[mid];
- (void) gelf_getsym(data, i, symp);
+ (void) symtab_getsym(symtab, i, symp);
if ((cmp = strcmp(name, strs + symp->st_name)) == 0) {
if (idp != NULL)
@@ -3013,7 +2326,7 @@ Pxlookup_by_name(
lmid != fptr->file_lo->rl_lmident)
continue;
- if (fptr->file_symtab.sym_data != NULL &&
+ if (fptr->file_symtab.sym_data_pri != NULL &&
sym_by_name(&fptr->file_symtab, sname, symp, &id)) {
if (sip != NULL) {
sip->prs_id = id;
@@ -3023,7 +2336,7 @@ Pxlookup_by_name(
sip->prs_lmid = fptr->file_lo == NULL ?
LM_ID_BASE : fptr->file_lo->rl_lmident;
}
- } else if (fptr->file_dynsym.sym_data != NULL &&
+ } else if (fptr->file_dynsym.sym_data_pri != NULL &&
sym_by_name(&fptr->file_dynsym, sname, symp, &id)) {
if (sip != NULL) {
sip->prs_id = id;
@@ -3187,7 +2500,6 @@ Psymbol_iter_com(struct ps_prochandle *P, Lmid_t lmid, const char *object_name,
map_info_t *mptr;
file_info_t *fptr;
sym_tbl_t *symtab;
- Elf_Data *data;
size_t symn;
const char *strs;
size_t strsz;
@@ -3222,14 +2534,10 @@ Psymbol_iter_com(struct ps_prochandle *P, Lmid_t lmid, const char *object_name,
si.prs_lmid = fptr->file_lo == NULL ?
LM_ID_BASE : fptr->file_lo->rl_lmident;
- data = symtab->sym_data;
symn = symtab->sym_symn;
strs = symtab->sym_strs;
strsz = symtab->sym_strsz;
- if (data == NULL || strs == NULL)
- return (-1);
-
switch (order) {
case PRO_NATURAL:
map = NULL;
@@ -3247,11 +2555,14 @@ Psymbol_iter_com(struct ps_prochandle *P, Lmid_t lmid, const char *object_name,
return (-1);
}
+ if (symtab->sym_data_pri == NULL || strs == NULL || count == 0)
+ return (-1);
+
rv = 0;
for (i = 0; i < count; i++) {
ndx = map == NULL ? i : map[i];
- if (gelf_getsym(data, ndx, &sym) != NULL) {
+ if (symtab_getsym(symtab, ndx, &sym) != NULL) {
uint_t s_bind, s_type, type;
if (sym.st_name >= strsz) /* invalid st_name */
diff --git a/usr/src/lib/libproc/common/Psymtab_machelf.h b/usr/src/lib/libproc/common/Psymtab_machelf.h
new file mode 100644
index 0000000000..fdf311e8bf
--- /dev/null
+++ b/usr/src/lib/libproc/common/Psymtab_machelf.h
@@ -0,0 +1,48 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _PSYMTAB_MACHELF_H
+#define _PSYMTAB_MACHELF_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern Elf *fake_elf32(struct ps_prochandle *P, file_info_t *fptr,
+ uintptr_t addr, Elf32_Ehdr *ehdr, uint_t phnum, Elf32_Phdr *phdr);
+#ifdef _LP64
+extern Elf *fake_elf64(struct ps_prochandle *P, file_info_t *fptr,
+ uintptr_t addr, Elf64_Ehdr *ehdr, uint_t phnum, Elf64_Phdr *phdr);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PSYMTAB_MACHELF_H */
diff --git a/usr/src/lib/libproc/common/Psymtab_machelf32.c b/usr/src/lib/libproc/common/Psymtab_machelf32.c
new file mode 100644
index 0000000000..69a583dfc0
--- /dev/null
+++ b/usr/src/lib/libproc/common/Psymtab_machelf32.c
@@ -0,0 +1,637 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <memory.h>
+#include <sys/sysmacros.h>
+#include <sys/machelf.h>
+
+#include "Pcontrol.h"
+#include "Psymtab_machelf.h"
+
+
+/*
+ * This file contains code for use by Psymtab.c that is compiled once
+ * for each supported ELFCLASS.
+ *
+ * When processing ELF files, it is common to encounter a situation where
+ * a program with one ELFCLASS (32 or 64-bit) is required to examine a
+ * file with a different ELFCLASS. For example, the 32-bit linker (ld) may
+ * be used to link a 64-bit program. The simplest solution to this problem
+ * is to duplicate each such piece of code, modifying only the data types,
+ * and to use if statements to select the code to run. The problem with
+ * doing it that way is that the resulting code is difficult to maintain.
+ * It is inevitable that the copies will not always get modified identically,
+ * and will drift apart. The only robust solution is to generate the
+ * multiple instances of code automatically from a single piece of code.
+ *
+ * The solution used within the Solaris linker is to write the code once,
+ * using the data types defined in sys/machelf.h, and then to compile that
+ * code twice, once with _ELF64 defined (to generate ELFCLASS64 code) and
+ * once without (to generate ELFCLASS32). We use the same approach here.
+ *
+ * Note that the _ELF64 definition does not refer to the ELFCLASS of
+ * the resulting code, but rather, to the ELFCLASS of the data it
+ * examines. By repeating the above double-compilation for both 32-bit
+ * and 64-bit builds, we end up with 4 instances, which collectively
+ * can handle any combination of program and ELF data class:
+ *
+ * \ Compilation class
+ * \ 32 64
+ * \------------------
+ * |
+ * 32 | X X
+ * ELF Data Class |
+ * 64 | X X
+ */
+
+
+
+/*
+ * Read data from the specified process and construct an in memory
+ * image of an ELF file that will let us use libelf for most of the
+ * work we need to later (e.g. symbol table lookups). This is used
+ * in cases where no usable on-disk image for the process is available.
+ * 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 32-bit
+ * +-------------------+ (Elf32_Word or Elf64_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.
+ *
+ * If there is a dynsym present, there may also be an optional
+ * section called the SUNW_ldynsym that augments the dynsym by
+ * providing local function symbols. When the Solaris linker lays
+ * out a file that has both of these sections, it makes sure that
+ * the data for the two sections is adjacent with the SUNW_ldynsym
+ * in front. This allows the runtime linker to treat these two
+ * symbol tables as being a single larger table. There are two
+ * items in the dynamic section for this:
+ *
+ * DT_SUNW_SYMTAB base of the SUNW_ldynsym
+ * DT_SUNW_SYMSZ total size of SUNW_ldynsym and dynsym
+ * added together. We can figure out the
+ * size of the SUNW_ldynsym section by
+ * subtracting the size of the dynsym
+ * (described above) from this value.
+ *
+ * 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.
+ */
+
+
+/*
+ * The fake_elfXX() function generated by this file uses the following
+ * string as the string table for the section names. Since it is critical
+ * to count correctly, and to improve readability, the SHSTR_NDX_ macros
+ * supply the proper offset for each name within the string.
+ */
+static char shstr[] =
+ ".shstrtab\0.dynsym\0.dynstr\0.dynamic\0.plt\0.SUNW_ldynsym";
+
+/* Offsets within shstr for each name */
+#define SHSTR_NDX_shstrtab 0
+#define SHSTR_NDX_dynsym 10
+#define SHSTR_NDX_dynstr 18
+#define SHSTR_NDX_dynamic 26
+#define SHSTR_NDX_plt 35
+#define SHSTR_NDX_SUNW_ldynsym 40
+
+
+/*
+ * Section header alignment for 32 and 64-bit ELF files differs
+ */
+#ifdef _ELF64
+#define SH_ADDRALIGN 8
+#else
+#define SH_ADDRALIGN 4
+#endif
+
+#ifdef _ELF64
+Elf *
+fake_elf64(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
+ Ehdr *ehdr, uint_t phnum, Phdr *phdr)
+#else
+Elf *
+fake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
+ Ehdr *ehdr, uint_t phnum, Phdr *phdr)
+#endif
+{
+ enum {
+ DI_PLTGOT,
+ DI_JMPREL,
+ DI_PLTRELSZ,
+ DI_PLTREL,
+ DI_SYMTAB,
+ DI_HASH,
+ DI_SYMENT,
+ DI_STRTAB,
+ DI_STRSZ,
+ DI_SUNW_SYMTAB,
+ DI_SUNW_SYMSZ,
+ DI_NENT
+ };
+ /*
+ * Mask of dynamic options that must be present in a well
+ * formed dynamic section. We need all of these in order to
+ * put together a complete set of elf sections. They are
+ * mandatory in both executables and shared objects so if one
+ * of them is missing, we're in some trouble and should abort.
+ * The PLT items are expected, but we will let them slide if
+ * need be. The DI_SUNW_SYM* items are completely optional, so
+ * we use them if they are present and ignore them otherwise.
+ */
+ const int di_req_mask = (1 << DI_SYMTAB) | (1 << DI_HASH) |
+ (1 << DI_SYMENT) | (1 << DI_STRTAB) | (1 << DI_STRSZ);
+ int di_mask = 0;
+ size_t size = 0;
+ caddr_t elfdata = NULL;
+ Elf *elf;
+ size_t dynsym_size, ldynsym_size;
+ int dynstr_shndx;
+ Ehdr *ep;
+ Shdr *sp;
+ Dyn *dp;
+ Dyn *d[DI_NENT] = { 0 };
+ uint_t i;
+ Off off;
+ size_t pltsz = 0, pltentsz;
+
+
+ if (ehdr->e_type == ET_DYN)
+ phdr->p_vaddr += addr;
+
+ if ((dp = malloc(phdr->p_filesz)) == NULL)
+ goto bad;
+
+ if (Pread(P, dp, phdr->p_filesz, phdr->p_vaddr) != phdr->p_filesz)
+ goto bad;
+
+#ifndef _ELF64
+ /*
+ * Allow librtld_db the opportunity to "fix" the program
+ * headers, if it needs to, before we process them.
+ */
+ if (P->rap != NULL && ehdr->e_type == ET_DYN) {
+ rd_fix_phdrs(P->rap, dp, phdr->p_filesz, addr);
+ }
+#endif
+
+ /*
+ * Iterate over the items in the dynamic section, grabbing
+ * the address of items we want and saving them in dp[].
+ */
+ for (i = 0; i < phdr->p_filesz / sizeof (Dyn); i++) {
+ switch (dp[i].d_tag) {
+ /* For the .plt section */
+ case DT_PLTGOT:
+ d[DI_PLTGOT] = &dp[i];
+ break;
+ case DT_JMPREL:
+ d[DI_JMPREL] = &dp[i];
+ break;
+ case DT_PLTRELSZ:
+ d[DI_PLTRELSZ] = &dp[i];
+ break;
+ case DT_PLTREL:
+ d[DI_PLTREL] = &dp[i];
+ break;
+
+ /* For the .dynsym section */
+ case DT_SYMTAB:
+ d[DI_SYMTAB] = &dp[i];
+ di_mask |= (1 << DI_SYMTAB);
+ break;
+ case DT_HASH:
+ d[DI_HASH] = &dp[i];
+ di_mask |= (1 << DI_HASH);
+ break;
+ case DT_SYMENT:
+ d[DI_SYMENT] = &dp[i];
+ di_mask |= (1 << DI_SYMENT);
+ break;
+ case DT_SUNW_SYMTAB:
+ d[DI_SUNW_SYMTAB] = &dp[i];
+ break;
+ case DT_SUNW_SYMSZ:
+ d[DI_SUNW_SYMSZ] = &dp[i];
+ break;
+
+ /* For the .dynstr section */
+ case DT_STRTAB:
+ d[DI_STRTAB] = &dp[i];
+ di_mask |= (1 << DI_STRTAB);
+ break;
+ case DT_STRSZ:
+ d[DI_STRSZ] = &dp[i];
+ di_mask |= (1 << DI_STRSZ);
+ break;
+ }
+ }
+
+ /* Ensure all required entries were collected */
+ if ((di_mask & di_req_mask) != di_req_mask) {
+ dprintf("text section missing required dynamic entries\n");
+ 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) ||
+ (d[DI_SYMTAB]->d_un.d_ptr >= (d[DI_SUNW_SYMTAB]->d_un.d_ptr +
+ d[DI_SUNW_SYMSZ]->d_un.d_val)))) {
+ d[DI_SUNW_SYMTAB] = NULL;
+ d[DI_SUNW_SYMSZ] = NULL;
+ }
+
+ /* elf header */
+ size = sizeof (Ehdr);
+
+ /* program headers from in-core elf fragment */
+ size += phnum * ehdr->e_phentsize;
+
+ /* unused shdr, and .shstrtab section */
+ size += sizeof (Shdr);
+ size += sizeof (Shdr);
+ size += roundup(sizeof (shstr), SH_ADDRALIGN);
+
+ /*
+ * .dynsym and .SUNW_ldynsym sections.
+ *
+ * The string table section used for the symbol table and
+ * dynamic sections lies immediately after the dynsym, so the
+ * presence of SUNW_ldynsym changes the dynstr section index.
+ */
+ if (d[DI_SUNW_SYMTAB] != NULL) {
+ size += sizeof (Shdr); /* SUNW_ldynsym shdr */
+ ldynsym_size = (size_t)d[DI_SUNW_SYMSZ]->d_un.d_val;
+ dynsym_size = ldynsym_size - (d[DI_SYMTAB]->d_un.d_ptr
+ - d[DI_SUNW_SYMTAB]->d_un.d_ptr);
+ 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;
+ ldynsym_size = 0;
+ dynstr_shndx = 3;
+ }
+ size += sizeof (Shdr) + ldynsym_size + dynsym_size;
+
+ /* .dynstr section */
+ size += sizeof (Shdr);
+ size += roundup(d[DI_STRSZ]->d_un.d_val, SH_ADDRALIGN);
+
+ /* .dynamic section */
+ size += sizeof (Shdr);
+ size += roundup(phdr->p_filesz, SH_ADDRALIGN);
+
+ /* .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 (Rela) - 2;
+ Rela r[2];
+
+ if (Pread(P, r, sizeof (r), jmprel +
+ sizeof (r[0]) * ndx) != sizeof (r)) {
+ dprintf("Pread of DT_RELA failed\n");
+ goto bad;
+ }
+
+ 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 (Rel) - 2;
+ Rel r[2];
+
+ if (Pread(P, r, sizeof (r), jmprel +
+ sizeof (r[0]) * ndx) != sizeof (r)) {
+ dprintf("Pread of DT_REL failed\n");
+ goto bad;
+ }
+
+ penult = r[0].r_offset;
+ ult = r[1].r_offset;
+ } else {
+ dprintf(".plt: unknown jmprel value\n");
+ goto bad;
+ }
+
+ pltentsz = ult - penult;
+
+ if (ehdr->e_type == ET_DYN)
+ ult += addr;
+
+ pltsz = ult - d[DI_PLTGOT]->d_un.d_ptr + pltentsz;
+
+ size += sizeof (Shdr);
+ size += roundup(pltsz, SH_ADDRALIGN);
+ }
+
+ if ((elfdata = calloc(1, size)) == NULL)
+ goto bad;
+
+ /* LINTED - alignment */
+ ep = (Ehdr *)elfdata;
+ (void) memcpy(ep, ehdr, offsetof(Ehdr, e_phoff));
+
+ ep->e_ehsize = sizeof (Ehdr);
+ ep->e_phoff = sizeof (Ehdr);
+ ep->e_phentsize = ehdr->e_phentsize;
+ ep->e_phnum = phnum;
+ ep->e_shoff = ep->e_phoff + phnum * ep->e_phentsize;
+ ep->e_shentsize = sizeof (Shdr);
+ /*
+ * Plt and SUNW_ldynsym sections are optional. C logical
+ * binary operators return a 0 or 1 value, so the following
+ * adds 1 for each optional section present.
+ */
+ ep->e_shnum = 5 + (pltsz != 0) + (d[DI_SUNW_SYMTAB] != NULL);
+ ep->e_shstrndx = 1;
+
+ /* LINTED - alignment */
+ sp = (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], phnum * ep->e_phentsize,
+ addr + ehdr->e_phoff) != phnum * ep->e_phentsize) {
+ dprintf("failed to read program headers\n");
+ goto bad;
+ }
+
+ /*
+ * The first elf section is always skipped.
+ */
+ sp++;
+
+ /*
+ * Section Header: .shstrtab
+ */
+ sp->sh_name = SHSTR_NDX_shstrtab;
+ 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, SH_ADDRALIGN);
+ sp++;
+
+ /*
+ * Section Header: .SUNW_ldynsym
+ */
+ if (d[DI_SUNW_SYMTAB] != NULL) {
+ sp->sh_name = SHSTR_NDX_SUNW_ldynsym;
+ sp->sh_type = SHT_SUNW_LDYNSYM;
+ 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_offset = off;
+ sp->sh_size = ldynsym_size;
+ sp->sh_link = dynstr_shndx;
+ /* Index of 1st global in table that has none == # items */
+ sp->sh_info = sp->sh_size / sizeof (Sym);
+ sp->sh_addralign = SH_ADDRALIGN;
+ sp->sh_entsize = sizeof (Sym);
+
+ if (Pread(P, &elfdata[off], sp->sh_size,
+ d[DI_SUNW_SYMTAB]->d_un.d_ptr) != sp->sh_size) {
+ dprintf("failed to read .SUNW_ldynsym at %lx\n",
+ (long)d[DI_SUNW_SYMTAB]->d_un.d_ptr);
+ goto bad;
+ }
+ off += sp->sh_size;
+ /* No need to round up ldynsym data. Dynsym data is same type */
+ sp++;
+ }
+
+ /*
+ * Section Header: .dynsym
+ */
+ sp->sh_name = SHSTR_NDX_dynsym;
+ 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 = dynsym_size;
+ sp->sh_link = dynstr_shndx;
+ sp->sh_info = 1; /* Index of 1st global in table */
+ sp->sh_addralign = SH_ADDRALIGN;
+ sp->sh_entsize = sizeof (Sym);
+
+ if (Pread(P, &elfdata[off], sp->sh_size,
+ d[DI_SYMTAB]->d_un.d_ptr) != sp->sh_size) {
+ dprintf("failed to read .dynsym at %lx\n",
+ (long)d[DI_SYMTAB]->d_un.d_ptr);
+ goto bad;
+ }
+
+ off += roundup(sp->sh_size, SH_ADDRALIGN);
+ sp++;
+
+ /*
+ * Section Header: .dynstr
+ */
+ sp->sh_name = SHSTR_NDX_dynstr;
+ 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) {
+ dprintf("failed to read .dynstr\n");
+ goto bad;
+ }
+ off += roundup(sp->sh_size, SH_ADDRALIGN);
+ sp++;
+
+ /*
+ * Section Header: .dynamic
+ */
+ sp->sh_name = SHSTR_NDX_dynamic;
+ 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 = dynstr_shndx;
+ sp->sh_info = 0;
+ sp->sh_addralign = SH_ADDRALIGN;
+ sp->sh_entsize = sizeof (Dyn);
+
+ (void) memcpy(&elfdata[off], dp, sp->sh_size);
+ off += roundup(sp->sh_size, SH_ADDRALIGN);
+ sp++;
+
+ /*
+ * Section Header: .plt
+ */
+ if (pltsz != 0) {
+ 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;
+ 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 = SH_ADDRALIGN;
+ sp->sh_entsize = pltentsz;
+
+ if (Pread(P, &elfdata[off], sp->sh_size,
+ d[DI_PLTGOT]->d_un.d_ptr) != sp->sh_size) {
+ dprintf("failed to read .plt\n");
+ goto bad;
+ }
+ off += roundup(sp->sh_size, SH_ADDRALIGN);
+ sp++;
+ }
+
+ free(dp);
+ if ((elf = elf_memory(elfdata, size)) == NULL) {
+ free(elfdata);
+ return (NULL);
+ }
+
+ fptr->file_elfmem = elfdata;
+
+ return (elf);
+
+bad:
+ if (dp != NULL)
+ free(dp);
+ if (elfdata != NULL)
+ free(elfdata);
+ return (NULL);
+
+
+}
diff --git a/usr/src/lib/libproc/common/Psymtab_machelf64.c b/usr/src/lib/libproc/common/Psymtab_machelf64.c
new file mode 100644
index 0000000000..d2c2348cea
--- /dev/null
+++ b/usr/src/lib/libproc/common/Psymtab_machelf64.c
@@ -0,0 +1,34 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Defining _ELF64 causes the code in Psymtab_machelf32.c to generate
+ * the ELFCLASS64 version of the code contained in that file.
+ */
+#define _ELF64
+#include "Psymtab_machelf32.c"
diff --git a/usr/src/lib/libproc/i386/Pisadep.c b/usr/src/lib/libproc/i386/Pisadep.c
index f60a2a8fbc..f8334149d7 100644
--- a/usr/src/lib/libproc/i386/Pisadep.c
+++ b/usr/src/lib/libproc/i386/Pisadep.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -70,7 +69,7 @@ Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr)
if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
(i = ELF32_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
- Elf_Data *data = fp->file_dynsym.sym_data;
+ Elf_Data *data = fp->file_dynsym.sym_data_pri;
Elf32_Sym *symp = &(((Elf32_Sym *)data->d_buf)[i]);
return (fp->file_dynsym.sym_strs + symp->st_name);
diff --git a/usr/src/lib/libproc/sparc/Pisadep.c b/usr/src/lib/libproc/sparc/Pisadep.c
index 0c2d35668e..2edf8c024e 100644
--- a/usr/src/lib/libproc/sparc/Pisadep.c
+++ b/usr/src/lib/libproc/sparc/Pisadep.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -75,7 +74,7 @@ Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr)
if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
(i = ELF32_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
- Elf_Data *data = fp->file_dynsym.sym_data;
+ Elf_Data *data = fp->file_dynsym.sym_data_pri;
Elf32_Sym *symp = &(((Elf32_Sym *)data->d_buf)[i]);
return (fp->file_dynsym.sym_strs + symp->st_name);
diff --git a/usr/src/lib/libproc/sparcv9/Makefile b/usr/src/lib/libproc/sparcv9/Makefile
index b74d317152..1e20da114e 100644
--- a/usr/src/lib/libproc/sparcv9/Makefile
+++ b/usr/src/lib/libproc/sparcv9/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,15 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
+# This is a 64-bit build, and as such needs 64-bit ELF support
+CMNOBJS64 = Psymtab_machelf64.o
+
include ../Makefile.com
include ../../Makefile.lib.64
diff --git a/usr/src/lib/libproc/sparcv9/Pisadep.c b/usr/src/lib/libproc/sparcv9/Pisadep.c
index 94ca44c9ea..6d7284a939 100644
--- a/usr/src/lib/libproc/sparcv9/Pisadep.c
+++ b/usr/src/lib/libproc/sparcv9/Pisadep.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -99,7 +98,7 @@ Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr)
if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
(i = ELF64_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
- Elf_Data *data = fp->file_dynsym.sym_data;
+ Elf_Data *data = fp->file_dynsym.sym_data_pri;
Elf64_Sym *symp = &(((Elf64_Sym *)data->d_buf)[i]);
return (fp->file_dynsym.sym_strs + symp->st_name);
@@ -116,7 +115,7 @@ Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr)
if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
(i = ELF32_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
- Elf_Data *data = fp->file_dynsym.sym_data;
+ Elf_Data *data = fp->file_dynsym.sym_data_pri;
Elf32_Sym *symp = &(((Elf32_Sym *)data->d_buf)[i]);
return (fp->file_dynsym.sym_strs + symp->st_name);