summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorAli Bahrami <Ali.Bahrami@Sun.COM>2009-03-18 13:28:28 -0600
committerAli Bahrami <Ali.Bahrami@Sun.COM>2009-03-18 13:28:28 -0600
commit7e16fca05dfbcfd32c2ebc9e4d1abdac1cd8657c (patch)
tree5033ac748bcd6544a0981e069919df2d213acead /usr/src
parentc13e065d8ffc8eafc02caf1091e66e146a2b2ce4 (diff)
downloadillumos-gate-7e16fca05dfbcfd32c2ebc9e4d1abdac1cd8657c.tar.gz
6813909 generalize eh_frame support to non-amd64 platforms
--HG-- rename : usr/src/cmd/sgs/libld/common/unwind.amd.c => usr/src/cmd/sgs/libld/common/unwind.c
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_gelf.c14
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_target.c12
-rw-r--r--usr/src/cmd/sgs/elfdump/Makefile.com11
-rw-r--r--usr/src/cmd/sgs/elfdump/common/_elfdump.h8
-rw-r--r--usr/src/cmd/sgs/elfdump/common/dwarf.c675
-rw-r--r--usr/src/cmd/sgs/elfdump/common/elfdump.c418
-rw-r--r--usr/src/cmd/sgs/elfdump/common/elfdump.msg73
-rw-r--r--usr/src/cmd/sgs/elfdump/common/fake_shdr.c4
-rw-r--r--usr/src/cmd/sgs/elfdump/common/main.c23
-rw-r--r--usr/src/cmd/sgs/elfedit/common/elfconst.c6
-rw-r--r--usr/src/cmd/sgs/elfedit/common/elfedit.msg6
-rw-r--r--usr/src/cmd/sgs/include/conv.h6
-rw-r--r--usr/src/cmd/sgs/include/dwarf.h24
-rw-r--r--usr/src/cmd/sgs/include/i386/machdep_x86.h27
-rw-r--r--usr/src/cmd/sgs/include/libld.h5
-rw-r--r--usr/src/cmd/sgs/include/sparc/machdep_sparc.h24
-rw-r--r--usr/src/cmd/sgs/libconv/Makefile.com10
-rw-r--r--usr/src/cmd/sgs/libconv/common/dwarf.c222
-rw-r--r--usr/src/cmd/sgs/libconv/common/dwarf.msg203
-rw-r--r--usr/src/cmd/sgs/libconv/common/phdr.c15
-rw-r--r--usr/src/cmd/sgs/libconv/common/phdr.msg6
-rw-r--r--usr/src/cmd/sgs/libconv/common/symbols.c7
-rw-r--r--usr/src/cmd/sgs/libconv/common/symbols.msg8
-rw-r--r--usr/src/cmd/sgs/libelf/demo/dispsyms.c58
-rw-r--r--usr/src/cmd/sgs/libld/Makefile.com6
-rw-r--r--usr/src/cmd/sgs/libld/common/README.XLINK7
-rw-r--r--usr/src/cmd/sgs/libld/common/_libld.h39
-rw-r--r--usr/src/cmd/sgs/libld/common/entry.c11
-rw-r--r--usr/src/cmd/sgs/libld/common/files.c177
-rw-r--r--usr/src/cmd/sgs/libld/common/globals.c8
-rw-r--r--usr/src/cmd/sgs/libld/common/ldmain.c7
-rw-r--r--usr/src/cmd/sgs/libld/common/machrel.amd.c10
-rw-r--r--usr/src/cmd/sgs/libld/common/machrel.intel.c9
-rw-r--r--usr/src/cmd/sgs/libld/common/machrel.sparc.c11
-rw-r--r--usr/src/cmd/sgs/libld/common/outfile.c5
-rw-r--r--usr/src/cmd/sgs/libld/common/sections.c5
-rw-r--r--usr/src/cmd/sgs/libld/common/unwind.amd.h49
-rw-r--r--usr/src/cmd/sgs/libld/common/unwind.c (renamed from usr/src/cmd/sgs/libld/common/unwind.amd.c)108
-rw-r--r--usr/src/cmd/sgs/libld/common/update.c16
-rw-r--r--usr/src/cmd/sgs/packages/common/SUNWonld-README1
-rw-r--r--usr/src/cmd/sgs/rtld/common/elf.c1
-rw-r--r--usr/src/cmd/sgs/tools/common/leb128.c33
-rw-r--r--usr/src/lib/libdtrace/common/dt_module.c16
-rw-r--r--usr/src/lib/libproc/common/Psymtab.c12
-rw-r--r--usr/src/uts/common/sys/elf.h58
-rw-r--r--usr/src/uts/common/sys/link.h13
46 files changed, 1804 insertions, 663 deletions
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_gelf.c b/usr/src/cmd/mdb/common/mdb/mdb_gelf.c
index bc680aad79..8cedd78014 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_gelf.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_gelf.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -927,6 +927,10 @@ gelf32_symtab_sort(mdb_gelf_symtab_t *gst)
static void
gelf32_symtab_init(mdb_gelf_symtab_t *gst)
{
+#if STT_NUM != (STT_IFUNC + 1)
+#error "STT_NUM has grown. update gelf32_symtab_init()"
+#endif
+
const char *base = (const char *)gst->gst_ssect->gs_data;
Elf32_Sym *sym = gst->gst_dsect->gs_data;
mdb_nv_t *nv = &gst->gst_nv;
@@ -950,7 +954,7 @@ gelf32_symtab_init(mdb_gelf_symtab_t *gst)
const char *name = base + sym->st_name;
uchar_t type = ELF32_ST_TYPE(sym->st_info);
- if (type >= STT_NUM || type == STT_SECTION)
+ if (type >= STT_IFUNC || type == STT_SECTION)
continue; /* skip sections and unknown types */
if (sym->st_name >= ss_size || name[0] < '!' || name[0] > '~') {
@@ -1020,6 +1024,10 @@ gelf64_symtab_sort(mdb_gelf_symtab_t *gst)
static void
gelf64_symtab_init(mdb_gelf_symtab_t *gst)
{
+#if STT_NUM != (STT_IFUNC + 1)
+#error "STT_NUM has grown. update gelf64_symtab_init()"
+#endif
+
const char *base = (const char *)gst->gst_ssect->gs_data;
Elf64_Sym *sym = gst->gst_dsect->gs_data;
mdb_nv_t *nv = &gst->gst_nv;
@@ -1043,7 +1051,7 @@ gelf64_symtab_init(mdb_gelf_symtab_t *gst)
const char *name = base + sym->st_name;
uchar_t type = ELF64_ST_TYPE(sym->st_info);
- if (type >= STT_NUM || type == STT_SECTION)
+ if (type >= STT_IFUNC || type == STT_SECTION)
continue; /* skip sections and unknown types */
if (sym->st_name >= ss_size || name[0] < '!' || name[0] > '~') {
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_target.c b/usr/src/cmd/mdb/common/mdb/mdb_target.c
index cd05e72459..8720ae080e 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_target.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_target.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 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"
-
/*
* MDB Target Layer
*
@@ -1904,6 +1902,10 @@ mdb_tgt_xdata_delete(mdb_tgt_t *t, const char *name)
int
mdb_tgt_sym_match(const GElf_Sym *sym, uint_t mask)
{
+#if STT_NUM != (STT_IFUNC + 1)
+#error "STT_NUM has grown. update mdb_tgt_sym_match()"
+#endif
+
uchar_t s_bind = GELF_ST_BIND(sym->st_info);
uchar_t s_type = GELF_ST_TYPE(sym->st_info);
@@ -1911,10 +1913,10 @@ mdb_tgt_sym_match(const GElf_Sym *sym, uint_t mask)
* In case you haven't already guessed, this relies on the bitmask
* used by <mdb/mdb_target.h> and <libproc.h> for encoding symbol
* type and binding matching the order of STB and STT constants
- * in <sys/elf.h>. ELF can't change without breaking binary
+ * in <sys/elf.h>. Changes to ELF must maintain binary
* compatibility, so I think this is reasonably fair game.
*/
- if (s_bind < STB_NUM && s_type < STT_NUM) {
+ if (s_bind < STB_NUM && s_type < STT_IFUNC) {
uint_t type = (1 << (s_type + 8)) | (1 << s_bind);
return ((type & ~mask) == 0);
}
diff --git a/usr/src/cmd/sgs/elfdump/Makefile.com b/usr/src/cmd/sgs/elfdump/Makefile.com
index 81cc5c31c5..19c8c82ba5 100644
--- a/usr/src/cmd/sgs/elfdump/Makefile.com
+++ b/usr/src/cmd/sgs/elfdump/Makefile.com
@@ -20,20 +20,19 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
PROG= elfdump
include $(SRC)/cmd/Makefile.cmd
include $(SRC)/cmd/sgs/Makefile.com
-COMOBJ = main.o corenote.o struct_layout.o \
- struct_layout_i386.o struct_layout_amd64.o \
- struct_layout_sparc.o struct_layout_sparcv9.o
+COMOBJ = main.o corenote.o \
+ dwarf.o struct_layout.o \
+ struct_layout_i386.o struct_layout_amd64.o \
+ struct_layout_sparc.o struct_layout_sparcv9.o
COMOBJ32 = elfdump32.o fake_shdr32.o
diff --git a/usr/src/cmd/sgs/elfdump/common/_elfdump.h b/usr/src/cmd/sgs/elfdump/common/_elfdump.h
index 0bf02e33f2..50c96c7042 100644
--- a/usr/src/cmd/sgs/elfdump/common/_elfdump.h
+++ b/usr/src/cmd/sgs/elfdump/common/_elfdump.h
@@ -20,15 +20,13 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef __ELFDUMP_H
#define __ELFDUMP_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <_machelf.h>
#include <debug.h>
@@ -224,7 +222,9 @@ typedef enum {
#endif
extern corenote_ret_t corenote(Half, int, Word, const char *, Word);
-extern void dump_hex_bytes(const char *, size_t, int, int, int);
+extern void dump_eh_frame(uchar_t *, size_t, uint64_t, Half e_machine,
+ uchar_t *e_ident);
+extern void dump_hex_bytes(const void *, size_t, int, int, int);
extern int fake_shdr_cache32(const char *, int, Elf *, Elf32_Ehdr *,
Cache **, size_t *);
diff --git a/usr/src/cmd/sgs/elfdump/common/dwarf.c b/usr/src/cmd/sgs/elfdump/common/dwarf.c
new file mode 100644
index 0000000000..ae95e09630
--- /dev/null
+++ b/usr/src/cmd/sgs/elfdump/common/dwarf.c
@@ -0,0 +1,675 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <_libelf.h>
+#include <dwarf.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <strings.h>
+#include <debug.h>
+#include <conv.h>
+#include <msg.h>
+#include <_elfdump.h>
+
+
+/*
+ * Data from eh_frame section used by dump_cfi()
+ */
+typedef struct {
+ Half e_machine; /* ehdr->e_machine */
+ uchar_t *e_ident; /* ehdr->e_ident */
+ uint64_t sh_addr; /* Address of eh_frame section */
+ int do_swap; /* True if object and system byte */
+ /* order differs */
+ int cieRflag; /* R flag from current CIE */
+ uint64_t ciecalign; /* CIE code align factor */
+ int64_t ciedalign; /* CIE data align factor */
+ uint64_t fdeinitloc; /* FDE initial location */
+} dump_cfi_state_t;
+
+
+/*
+ * Extract an unsigned integer value from an .eh_frame section, converting it
+ * from its native byte order to that of the running machine if necessary.
+ *
+ * entry:
+ * data - Base address from which to extract datum
+ * ndx - Address of variable giving index to start byte in data.
+ * size - # of bytes in datum. Must be one of: 1, 2, 4, 8
+ * do_swap - True if the data is in a different byte order than that
+ * of the host system.
+ *
+ * exit:
+ * *ndx is incremented by the size of the extracted datum.
+ *
+ * The requested datum is extracted, byte swapped if necessary,
+ * and returned.
+ */
+static uint64_t
+dwarf_extract_uint(uchar_t *data, uint64_t *ndx, int size, int do_swap)
+{
+ switch (size) {
+ case 1:
+ return (data[(*ndx)++]);
+ case 2:
+ {
+ Half r;
+ uchar_t *p = (uchar_t *)&r;
+
+ data += *ndx;
+ if (do_swap)
+ UL_ASSIGN_BSWAP_HALF(p, data);
+ else
+ UL_ASSIGN_HALF(p, data);
+
+ (*ndx) += 2;
+ return (r);
+ }
+ case 4:
+ {
+ Word r;
+ uchar_t *p = (uchar_t *)&r;
+
+ data += *ndx;
+ if (do_swap)
+ UL_ASSIGN_BSWAP_WORD(p, data);
+ else
+ UL_ASSIGN_WORD(p, data);
+
+ (*ndx) += 4;
+ return (r);
+ }
+
+ case 8:
+ {
+ uint64_t r;
+ uchar_t *p = (uchar_t *)&r;
+
+ data += *ndx;
+ if (do_swap)
+ UL_ASSIGN_BSWAP_LWORD(p, data);
+ else
+ UL_ASSIGN_LWORD(p, data);
+
+ (*ndx) += 8;
+ return (r);
+ }
+ }
+
+ /* If here, an invalid size was specified */
+ assert(0);
+ return (0);
+}
+
+/*
+ * Map a DWARF register constant to the machine register name it
+ * corresponds to, formatting the result into buf.
+ *
+ * The assignment of DWARF register numbers is part of the system
+ * specific ABI for each platform.
+ *
+ * entry:
+ * regno - DWARF register number
+ * mach - ELF machine code for platform
+ * buf, bufsize - Buffer to receive the formatted result string
+ *
+ * exit:
+ * The results are formatted into buf, and buf is returned.
+ * If the generated output would exceed the size of the buffer
+ * provided, it will be clipped to fit.
+ */
+static const char *
+dwarf_regname(Half mach, int regno, char *buf, size_t bufsize)
+{
+ Conv_inv_buf_t inv_buf;
+ const char *name;
+ int good_name;
+
+ name = conv_dwarf_regname(mach, regno, 0, &good_name, &inv_buf);
+
+ /*
+ * If there is a good mnemonic machine name for the register,
+ * format the result as 'r# (mnemonic)'. If there is no good
+ * name for it, then simply format the dwarf name as 'r#'.
+ */
+ if (good_name)
+ (void) snprintf(buf, bufsize, MSG_ORIG(MSG_REG_FMT_NAME),
+ regno, name);
+ else
+ (void) snprintf(buf, bufsize, MSG_ORIG(MSG_REG_FMT_BASIC),
+ regno);
+
+ return (buf);
+}
+
+
+/*
+ * Decode eh_frame Call Frame Instructions, printing each one on a
+ * separate line.
+ *
+ * entry:
+ * data - Address of base of eh_frame section being processed
+ * off - Offset of current FDE within eh_frame
+ * ndx - Index of current position within current FDE
+ * len - Length of eh_frame section
+ * state - Object, CIE, and FDE state for current request
+ * msg - Header message to issue before producing output.
+ * indent - # of indentation characters issued for each line of output.
+ *
+ * exit:
+ * The Call Frame Instructions have been decoded and printed.
+ *
+ * *ndx has been incremented to contain the index of the next
+ * byte of data to be processed in eh_frame.
+ *
+ * note:
+ * The format of Call Frame Instructions in .eh_frame sections is based
+ * on the DWARF specification.
+ */
+static void
+dump_cfi(uchar_t *data, uint64_t off, uint64_t *ndx, uint_t len,
+ dump_cfi_state_t *state, const char *msg, int indent)
+{
+ /*
+ * We use %*s%s to insert leading whitespace and the op name.
+ * PREFIX supplies these arguments.
+ */
+#define PREFIX indent, MSG_ORIG(MSG_STR_EMPTY), opname
+
+ /* Hide boilerplate clutter in calls to dwarf_regname() */
+#define REGNAME(_rnum, _buf) \
+ dwarf_regname(state->e_machine, _rnum, _buf, sizeof (_buf))
+
+ /* Extract the lower 6 bits from an op code */
+#define LOW_OP(_op) (_op & 0x3f)
+
+ char rbuf1[32], rbuf2[32];
+ Conv_inv_buf_t inv_buf;
+ uchar_t op;
+ const char *opname;
+ uint64_t oper1, oper2, cur_pc;
+ int64_t soper;
+ const char *loc_str;
+ int i;
+
+ dbg_print(0, msg);
+
+ /*
+ * In a CIE/FDE, the length field does not include it's own
+ * size. Hence, the value passed in is 4 less than the index
+ * of the actual final location.
+ */
+ len += 4;
+
+ /*
+ * There is a concept of the 'current location', which is the PC
+ * to which the current item applies. It starts out set to the
+ * FDE initial location, and can be set or incremented by
+ * various OP codes. cur_pc is used to track this.
+ *
+ * We want to use 'initloc' in the output the first time the location
+ * is referenced, and then switch to 'loc' for subsequent references.
+ * loc_str is used to manage that.
+ */
+ cur_pc = state->fdeinitloc;
+ loc_str = MSG_ORIG(MSG_STR_INITLOC);
+
+ while (*ndx < len) {
+ /*
+ * The first byte contains the primary op code in the top
+ * 2 bits, so there are 4 of them. Primary OP code
+ * 0 uses the lower 6 bits to specify a sub-opcode, allowing
+ * for 64 of them. The other 3 primary op codes use the
+ * lower 6 bits to hold an operand (a register #, or value).
+ *
+ * Check the primary OP code. If it's 1-3, handle it
+ * and move to the next loop iteration. For OP code 0,
+ * fall through to decode the sub-code.
+ */
+ op = data[off + (*ndx)++];
+ opname = conv_dwarf_cfa(op, 0, &inv_buf);
+ switch (op >> 6) {
+ case 0x1: /* v2: DW_CFA_advance_loc, delta */
+ oper1 = state->ciecalign * LOW_OP(op);
+ cur_pc += oper1;
+ dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
+ loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
+ loc_str = MSG_ORIG(MSG_STR_LOC);
+ continue;
+
+ case 0x2: /* v2: DW_CFA_offset, reg, offset */
+ soper = uleb_extract(&data[off], ndx) *
+ state->ciedalign;
+ dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
+ REGNAME(LOW_OP(op), rbuf1), EC_SXWORD(soper));
+ continue;
+
+ case 0x3: /* v2: DW_CFA_restore, reg */
+ dbg_print(0, MSG_ORIG(MSG_CFA_REG), PREFIX,
+ REGNAME(LOW_OP(op), rbuf1));
+ continue;
+ }
+
+ /*
+ * If we're here, the high order 2 bits are 0. The low 6 bits
+ * specify a sub-opcode defining the operation.
+ */
+ switch (op) {
+ case 0x00: /* v2: DW_CFA_nop */
+ /*
+ * No-ops are used to fill unused space required
+ * for alignment. It is common for there to be
+ * multiple adjacent nops. It saves space to report
+ * them all with a single line of output.
+ */
+ for (i = 1;
+ (*ndx < len) && (data[off + *ndx] == 0);
+ i++, (*ndx)++)
+ ;
+ dbg_print(0, MSG_ORIG(MSG_CFA_SIMPLEREP), PREFIX, i);
+ break;
+
+ case 0x0a: /* v2: DW_CFA_remember_state */
+ case 0x0b: /* v2: DW_CFA_restore_state */
+ case 0x2d: /* GNU: DW_CFA_GNU_window_save */
+ dbg_print(0, MSG_ORIG(MSG_CFA_SIMPLE), PREFIX);
+ break;
+
+ case 0x01: /* v2: DW_CFA_set_loc, address */
+ cur_pc = dwarf_ehe_extract(&data[off], ndx,
+ state->cieRflag, state->e_ident,
+ state->sh_addr, off + *ndx);
+ dbg_print(0, MSG_ORIG(MSG_CFA_CFASET), PREFIX,
+ EC_XWORD(cur_pc));
+ break;
+
+ case 0x02: /* v2: DW_CFA_advance_loc_1, 1-byte delta */
+ case 0x03: /* v2: DW_CFA_advance_loc_2, 2-byte delta */
+ case 0x04: /* v2: DW_CFA_advance_loc_4, 4-byte delta */
+ /*
+ * Since the codes are contiguous, and the sizes are
+ * powers of 2, we can compute the word width from
+ * the code.
+ */
+ i = 1 << (op - 0x02);
+ oper1 = dwarf_extract_uint(data + off, ndx, i,
+ state->do_swap) * state->ciecalign;
+ cur_pc += oper1;
+ dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
+ loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
+ loc_str = MSG_ORIG(MSG_STR_LOC);
+ break;
+
+ case 0x05: /* v2: DW_CFA_offset_extended,reg,off */
+ oper1 = uleb_extract(&data[off], ndx);
+ soper = uleb_extract(&data[off], ndx) *
+ state->ciedalign;
+ dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
+ REGNAME(oper1, rbuf1), EC_SXWORD(soper));
+ break;
+
+ case 0x06: /* v2: DW_CFA_restore_extended, reg */
+ case 0x0d: /* v2: DW_CFA_def_cfa_register, reg */
+ case 0x08: /* v2: DW_CFA_same_value, reg */
+ case 0x07: /* v2: DW_CFA_undefined, reg */
+ oper1 = uleb_extract(&data[off], ndx);
+ dbg_print(0, MSG_ORIG(MSG_CFA_REG), PREFIX,
+ REGNAME(oper1, rbuf1));
+ break;
+
+
+ case 0x09: /* v2: DW_CFA_register, reg, reg */
+ oper1 = uleb_extract(&data[off], ndx);
+ oper2 = uleb_extract(&data[off], ndx);
+ dbg_print(0, MSG_ORIG(MSG_CFA_REG_REG), PREFIX,
+ REGNAME(oper1, rbuf1), REGNAME(oper2, rbuf2));
+ break;
+
+ case 0x0c: /* v2: DW_CFA_def_cfa, reg, offset */
+ oper1 = uleb_extract(&data[off], ndx);
+ oper2 = uleb_extract(&data[off], ndx);
+ dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLU), PREFIX,
+ REGNAME(oper1, rbuf1), EC_XWORD(oper2));
+ break;
+
+ case 0x0e: /* v2: DW_CFA_def_cfa_offset, offset */
+ oper1 = uleb_extract(&data[off], ndx);
+ dbg_print(0, MSG_ORIG(MSG_CFA_LLU), PREFIX,
+ EC_XWORD(oper1));
+ break;
+
+ case 0x0f: /* v3: DW_CFA_def_cfa_expression, blk */
+ oper1 = uleb_extract(&data[off], ndx);
+ dbg_print(0, MSG_ORIG(MSG_CFA_EBLK), PREFIX,
+ EC_XWORD(oper1));
+ /* We currently do not decode the expression block */
+ *ndx += oper1;
+ break;
+
+ case 0x10: /* v3: DW_CFA_expression, reg, blk */
+ case 0x16: /* v3: DW_CFA_val_expression,reg,blk */
+ oper1 = uleb_extract(&data[off], ndx);
+ oper2 = uleb_extract(&data[off], ndx);
+ dbg_print(0, MSG_ORIG(MSG_CFA_REG_EBLK), PREFIX,
+ REGNAME(oper1, rbuf1), EC_XWORD(oper2));
+ /* We currently do not decode the expression block */
+ *ndx += oper2;
+ break;
+
+ case 0x11: /* v3: DW_CFA_offset_extended_sf, reg, off */
+ oper1 = uleb_extract(&data[off], ndx);
+ soper = sleb_extract(&data[off], ndx) *
+ state->ciedalign;
+ dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
+ REGNAME(oper1, rbuf1), EC_SXWORD(soper));
+ break;
+
+ case 0x12: /* v3: DW_CFA_def_cfa_sf, reg, offset */
+ oper1 = uleb_extract(&data[off], ndx);
+ soper = sleb_extract(&data[off], ndx) *
+ state->ciedalign;
+ dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
+ REGNAME(oper1, rbuf1), EC_SXWORD(soper));
+ break;
+
+ case 0x13: /* DW_CFA_def_cfa_offset_sf, offset */
+ soper = sleb_extract(&data[off], ndx) *
+ state->ciedalign;
+ dbg_print(0, MSG_ORIG(MSG_CFA_LLD), PREFIX,
+ EC_SXWORD(soper));
+ break;
+
+ case 0x14: /* v3: DW_CFA_val_offset, reg, offset */
+ oper1 = uleb_extract(&data[off], ndx);
+ soper = uleb_extract(&data[off], ndx) *
+ state->ciedalign;
+ dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
+ REGNAME(oper1, rbuf1), EC_SXWORD(soper));
+ break;
+
+ case 0x15: /* v3: DW_CFA_val_offset_sf, reg, offset */
+ oper1 = uleb_extract(&data[off], ndx);
+ soper = sleb_extract(&data[off], ndx) *
+ state->ciedalign;
+ dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
+ REGNAME(oper1, rbuf1), EC_SXWORD(soper));
+ break;
+
+ case 0x1d: /* GNU: DW_CFA_MIPS_advance_loc8, delta */
+ oper1 = dwarf_extract_uint(data + off, ndx, i,
+ state->do_swap) * state->ciecalign;
+ cur_pc += oper1;
+ dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
+ loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
+ loc_str = MSG_ORIG(MSG_STR_LOC);
+ break;
+
+ case 0x2e: /* GNU: DW_CFA_GNU_args_size, size */
+ oper1 = uleb_extract(&data[off], ndx);
+ dbg_print(0, MSG_ORIG(MSG_CFA_LLU), PREFIX,
+ EC_XWORD(oper1));
+
+ break;
+
+ case 0x2f: /* GNU:DW_CFA_GNU_negative_offset_extended,reg,off */
+ oper1 = uleb_extract(&data[off], ndx);
+ soper = -uleb_extract(&data[off], ndx) *
+ state->ciedalign;
+ dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
+ REGNAME(oper1, rbuf1), EC_SXWORD(soper));
+ break;
+
+ default:
+ /*
+ * Unrecognized OP code: DWARF data is variable length,
+ * so we don't know how many bytes to skip in order to
+ * advance to the next item. We cannot decode beyond
+ * this point, so dump the remainder in hex.
+ */
+ (*ndx)--; /* Back up to unrecognized opcode */
+ dump_hex_bytes(data + off + *ndx, len - *ndx,
+ indent, 8, 1);
+ (*ndx) = len;
+ break;
+ }
+ }
+
+#undef PREFIX
+#undef REGNAME
+#undef LOW_OP
+}
+
+void
+dump_eh_frame(uchar_t *data, size_t datasize, uint64_t sh_addr,
+ Half e_machine, uchar_t *e_ident)
+{
+ Conv_dwarf_ehe_buf_t dwarf_ehe_buf;
+ dump_cfi_state_t cfi_state;
+ uint64_t off, ndx;
+ uint_t cieid, cielength, cieversion, cieretaddr;
+ int ciePflag, cieZflag, cieLflag, cieLflag_present;
+ uint_t cieaugndx, length, id;
+ char *cieaugstr;
+
+ cfi_state.e_machine = e_machine;
+ cfi_state.e_ident = e_ident;
+ cfi_state.sh_addr = sh_addr;
+ cfi_state.do_swap = _elf_sys_encoding() != e_ident[EI_DATA];
+
+ off = 0;
+ while (off < datasize) {
+ ndx = 0;
+
+ /*
+ * Extract length in native format. A zero length indicates
+ * that this CIE is a terminator and that processing for this
+ * unwind information should end. However, skip this entry and
+ * keep processing, just in case there is any other information
+ * remaining in this section. Note, ld(1) will terminate the
+ * processing of the .eh_frame contents for this file after a
+ * zero length CIE, thus any information that does follow is
+ * ignored by ld(1), and is therefore questionable.
+ */
+ length = (uint_t)dwarf_extract_uint(data + off, &ndx,
+ 4, cfi_state.do_swap);
+ if (length == 0) {
+ dbg_print(0, MSG_ORIG(MSG_UNW_ZEROTERM));
+ off += 4;
+ continue;
+ }
+
+ /*
+ * extract CIE id in native format
+ */
+ id = (uint_t)dwarf_extract_uint(data + off, &ndx,
+ 4, cfi_state.do_swap);
+
+ /*
+ * A CIE record has an id of '0', otherwise this is a
+ * FDE entry and the 'id' is the CIE pointer.
+ */
+ if (id == 0) {
+ uint64_t persVal, ndx_save;
+ uint_t axsize;
+
+ cielength = length;
+ cieid = id;
+ ciePflag = cfi_state.cieRflag = cieZflag = 0;
+ cieLflag = cieLflag_present = 0;
+
+ dbg_print(0, MSG_ORIG(MSG_UNW_CIE),
+ EC_XWORD(sh_addr + off));
+ dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH),
+ cielength, cieid);
+
+ cieversion = data[off + ndx];
+ ndx += 1;
+ cieaugstr = (char *)(&data[off + ndx]);
+ ndx += strlen(cieaugstr) + 1;
+
+ dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS),
+ cieversion, cieaugstr);
+
+ cfi_state.ciecalign = uleb_extract(&data[off], &ndx);
+ cfi_state.ciedalign = sleb_extract(&data[off], &ndx);
+ cieretaddr = data[off + ndx];
+ ndx += 1;
+
+ dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN),
+ EC_XWORD(cfi_state.ciecalign),
+ EC_XWORD(cfi_state.ciedalign), cieretaddr);
+
+ if (cieaugstr[0])
+ dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXVAL));
+
+ for (cieaugndx = 0; cieaugstr[cieaugndx]; cieaugndx++) {
+ switch (cieaugstr[cieaugndx]) {
+ case 'z':
+ axsize = uleb_extract(&data[off], &ndx);
+ dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXSIZ),
+ axsize);
+ cieZflag = 1;
+ /*
+ * The auxiliary section can contain
+ * unused padding bytes at the end, so
+ * save the current index. Along with
+ * axsize, we will use it to set ndx to
+ * the proper continuation index after
+ * the aux data has been processed.
+ */
+ ndx_save = ndx;
+ break;
+ case 'P':
+ ciePflag = data[off + ndx];
+ ndx += 1;
+
+ persVal = dwarf_ehe_extract(&data[off],
+ &ndx, ciePflag, e_ident,
+ sh_addr, off + ndx);
+ dbg_print(0,
+ MSG_ORIG(MSG_UNW_CIEAXPERS));
+ dbg_print(0,
+ MSG_ORIG(MSG_UNW_CIEAXPERSENC),
+ ciePflag, conv_dwarf_ehe(ciePflag,
+ &dwarf_ehe_buf));
+ dbg_print(0,
+ MSG_ORIG(MSG_UNW_CIEAXPERSRTN),
+ EC_XWORD(persVal));
+ break;
+ case 'R':
+ cfi_state.cieRflag = data[off + ndx];
+ ndx += 1;
+ dbg_print(0,
+ MSG_ORIG(MSG_UNW_CIEAXCENC),
+ cfi_state.cieRflag,
+ conv_dwarf_ehe(cfi_state.cieRflag,
+ &dwarf_ehe_buf));
+ break;
+ case 'L':
+ cieLflag_present = 1;
+ cieLflag = data[off + ndx];
+ ndx += 1;
+ dbg_print(0,
+ MSG_ORIG(MSG_UNW_CIEAXLSDA),
+ cieLflag, conv_dwarf_ehe(
+ cieLflag, &dwarf_ehe_buf));
+ break;
+ default:
+ dbg_print(0,
+ MSG_ORIG(MSG_UNW_CIEAXUNEC),
+ cieaugstr[cieaugndx]);
+ break;
+ }
+ }
+
+ /*
+ * If the z flag was present, reposition ndx using the
+ * length given. This will safely move us past any
+ * unaccessed padding bytes in the auxiliary section.
+ */
+ if (cieZflag)
+ ndx = ndx_save + axsize;
+
+ /*
+ * Any remaining data are Call Frame Instructions
+ */
+ if ((cielength + 4) > ndx)
+ dump_cfi(data, off, &ndx, cielength, &cfi_state,
+ MSG_ORIG(MSG_UNW_CIECFI), 3);
+ off += cielength + 4;
+
+ } else {
+ uint_t fdelength = length;
+ int fdecieptr = id;
+ uint64_t fdeaddrrange;
+
+ dbg_print(0, MSG_ORIG(MSG_UNW_FDE),
+ EC_XWORD(sh_addr + off));
+ dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH),
+ fdelength, fdecieptr);
+
+ cfi_state.fdeinitloc = dwarf_ehe_extract(&data[off],
+ &ndx, cfi_state.cieRflag, e_ident,
+ sh_addr, off + ndx);
+ fdeaddrrange = dwarf_ehe_extract(&data[off], &ndx,
+ (cfi_state.cieRflag & ~DW_EH_PE_pcrel),
+ e_ident, sh_addr, off + ndx);
+
+ dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC),
+ EC_XWORD(cfi_state.fdeinitloc),
+ EC_XWORD(fdeaddrrange),
+ EC_XWORD(cfi_state.fdeinitloc + fdeaddrrange - 1));
+
+ if (cieaugstr[0])
+ dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXVAL));
+ if (cieZflag) {
+ uint64_t val;
+ uint64_t lndx;
+
+ val = uleb_extract(&data[off], &ndx);
+ lndx = ndx;
+ ndx += val;
+ dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXSIZE),
+ EC_XWORD(val));
+ if (val && cieLflag_present) {
+ uint64_t lsda;
+
+ lsda = dwarf_ehe_extract(&data[off],
+ &lndx, cieLflag, e_ident,
+ sh_addr, off + lndx);
+ dbg_print(0,
+ MSG_ORIG(MSG_UNW_FDEAXLSDA),
+ EC_XWORD(lsda));
+ }
+ }
+ if ((fdelength + 4) > ndx)
+ dump_cfi(data, off, &ndx, fdelength, &cfi_state,
+ MSG_ORIG(MSG_UNW_FDECFI), 6);
+ off += fdelength + 4;
+ }
+ }
+}
diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.c b/usr/src/cmd/sgs/elfdump/common/elfdump.c
index d7c74f7bad..7d0668c64f 100644
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.c
+++ b/usr/src/cmd/sgs/elfdump/common/elfdump.c
@@ -185,7 +185,7 @@ string(Cache *refsec, Word ndx, Cache *strsec, const char *file, Word name)
/*
* Do we have a empty string table?
*/
- if (strs == 0) {
+ if (strs == NULL) {
if (!strsec_err) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
file, strsec->c_name);
@@ -411,92 +411,109 @@ sections(const char *file, Cache *cache, Word shnum, Ehdr *ehdr)
}
/*
- * A couple of instances of unwind data are printed as tables of 8 data items
- * expressed as 0x?? integers.
- */
-#define UNWINDTBLSZ 10 + (8 * 5) + 1
-
-static void
-unwindtbl(uint64_t *ndx, uint_t len, uchar_t *data, uint64_t doff,
- const char *msg, const char *pre, size_t plen)
-{
- char buffer[UNWINDTBLSZ];
- uint_t boff = plen, cnt = 0;
-
- dbg_print(0, msg);
- (void) strncpy(buffer, pre, UNWINDTBLSZ);
-
- while (*ndx < (len + 4)) {
- if (cnt == 8) {
- dbg_print(0, buffer);
- boff = plen;
- cnt = 0;
- }
- (void) snprintf(&buffer[boff], UNWINDTBLSZ - boff,
- MSG_ORIG(MSG_UNW_TBLENTRY), data[doff + (*ndx)++]);
- boff += 5;
- cnt++;
- }
- if (cnt)
- dbg_print(0, buffer);
-}
-
-/*
* Obtain a specified Phdr entry.
*/
static Phdr *
-getphdr(Word phnum, Word type, const char *file, Elf *elf)
+getphdr(Word phnum, Word *type_arr, Word type_cnt, const char *file, Elf *elf)
{
- Word cnt;
+ Word cnt, tcnt;
Phdr *phdr;
if ((phdr = elf_getphdr(elf)) == NULL) {
failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
- return (0);
+ return (NULL);
}
for (cnt = 0; cnt < phnum; phdr++, cnt++) {
- if (phdr->p_type == type)
- return (phdr);
+ for (tcnt = 0; tcnt < type_cnt; tcnt++) {
+ if (phdr->p_type == type_arr[tcnt])
+ return (phdr);
+ }
}
- return (0);
+ return (NULL);
}
static void
unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *file,
Elf *elf)
{
+#if defined(_ELF64)
+#define MSG_UNW_BINSRTAB2 MSG_UNW_BINSRTAB2_64
+#define MSG_UNW_BINSRTABENT MSG_UNW_BINSRTABENT_64
+#else
+#define MSG_UNW_BINSRTAB2 MSG_UNW_BINSRTAB2_32
+#define MSG_UNW_BINSRTABENT MSG_UNW_BINSRTABENT_32
+#endif
+
+ static Word phdr_types[] = { PT_SUNW_UNWIND, PT_SUNW_EH_FRAME };
+
+ int frame_cnt = 0, hdr_cnt = 0, frame_ndx, hdr_ndx;
+ uint64_t save_frame_ptr, save_frame_base;
Conv_dwarf_ehe_buf_t dwarf_ehe_buf;
- Word cnt;
- Phdr *uphdr = 0;
+ Word cnt;
+ Phdr *uphdr = NULL;
/*
- * For the moment - UNWIND is only relevant for a AMD64 object.
+ * Historical background: .eh_frame and .eh_frame_hdr sections
+ * come from the GNU compilers (particularly C++), and are used
+ * under all architectures. Their format is based on DWARF. When
+ * the amd64 ABI was defined, these sections were adopted wholesale
+ * from the existing practice.
+ *
+ * When amd64 support was added to Solaris, support for these
+ * sections was added, using the SHT_AMD64_UNWIND section type
+ * to identify them. At first, we ignored them in objects for
+ * non-amd64 targets, but later broadened our support to include
+ * other architectures in order to better support gcc-generated
+ * objects.
+ *
+ * We match these sections by name, rather than section type,
+ * because they can come in as either SHT_AMD64_UNWIND, or as
+ * SHT_PROGBITS, and because we need to distinquish between
+ * the two types (.eh_frame and .eh_frame_hdr).
*/
- if (ehdr->e_machine != EM_AMD64)
- return;
if (phnum)
- uphdr = getphdr(phnum, PT_SUNW_UNWIND, file, elf);
+ uphdr = getphdr(phnum, phdr_types,
+ sizeof (phdr_types) / sizeof (*phdr_types), file, elf);
for (cnt = 1; cnt < shnum; cnt++) {
Cache *_cache = &cache[cnt];
Shdr *shdr = _cache->c_shdr;
uchar_t *data;
size_t datasize;
- uint64_t off, ndx, frame_ptr, fde_cnt, tabndx;
+ uint64_t ndx, frame_ptr, fde_cnt, tabndx;
uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc;
/*
- * AMD64 - this is a strmcp() just to find the gcc produced
- * sections. Soon gcc should be setting the section type - and
- * we'll not need this strcmp().
+ * Skip sections of the wrong type. On amd64, Solaris tags
+ * these as SHT_AMD64_UNWIND, while gcc started out issuing
+ * them as SHT_PROGBITS and switched over when the amd64 ABI
+ * was finalized. On non-amd64, they're all SHT_PROGBITS.
*/
- if ((shdr->sh_type != SHT_AMD64_UNWIND) &&
- (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM),
- MSG_SCN_FRM_SIZE) != 0) &&
- (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR),
- MSG_SCN_FRMHDR_SIZE) != 0))
+ switch (shdr->sh_type) {
+ case SHT_PROGBITS:
+ if (ehdr->e_machine == EM_AMD64)
+ continue;
+ break;
+ case SHT_AMD64_UNWIND:
+ if (ehdr->e_machine != EM_AMD64)
+ continue;
+ break;
+ default:
+ continue;
+ }
+
+ /*
+ * Only sections with names starting with .eh_frame or
+ * .eh_frame_hdr are of interest. We do a prefix comparison,
+ * allowing for naming conventions like .eh_frame.foo, hence
+ * the use of strncmp() rather than strcmp(). This means that
+ * we only really need to test for .eh_frame, as it's a
+ * prefix of .eh_frame_hdr.
+ */
+ if (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM),
+ MSG_SCN_FRM_SIZE) != 0)
continue;
if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type))
@@ -510,7 +527,6 @@ unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *file,
data = (uchar_t *)(_cache->c_data->d_buf);
datasize = _cache->c_data->d_size;
- off = 0;
/*
* Is this a .eh_frame_hdr
@@ -518,6 +534,15 @@ unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *file,
if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) ||
(strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR),
MSG_SCN_FRMHDR_SIZE) == 0)) {
+ /*
+ * There can only be a single .eh_frame_hdr.
+ * Flag duplicates.
+ */
+ if (++hdr_cnt > 1)
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ERR_MULTEHFRMHDR), file,
+ EC_WORD(cnt), _cache->c_name);
+
dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR));
ndx = 0;
@@ -529,14 +554,18 @@ unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *file,
dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers);
frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc,
- ehdr->e_ident, shdr->sh_addr + ndx);
+ ehdr->e_ident, shdr->sh_addr, ndx);
+ if (hdr_cnt == 1) {
+ hdr_ndx = cnt;
+ save_frame_ptr = frame_ptr;
+ }
dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC),
conv_dwarf_ehe(frame_ptr_enc, &dwarf_ehe_buf),
EC_XWORD(frame_ptr));
fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc,
- ehdr->e_ident, shdr->sh_addr + ndx);
+ ehdr->e_ident, shdr->sh_addr, ndx);
dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC),
conv_dwarf_ehe(fde_cnt_enc, &dwarf_ehe_buf),
@@ -549,197 +578,46 @@ unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *file,
for (tabndx = 0; tabndx < fde_cnt; tabndx++) {
dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT),
EC_XWORD(dwarf_ehe_extract(data, &ndx,
- table_enc, ehdr->e_ident, shdr->sh_addr)),
+ table_enc, ehdr->e_ident, shdr->sh_addr,
+ ndx)),
EC_XWORD(dwarf_ehe_extract(data, &ndx,
- table_enc, ehdr->e_ident, shdr->sh_addr)));
+ table_enc, ehdr->e_ident, shdr->sh_addr,
+ ndx)));
}
- continue;
+ } else { /* Display the .eh_frame section */
+ frame_cnt++;
+ if (frame_cnt == 1) {
+ frame_ndx = cnt;
+ save_frame_base = shdr->sh_addr;
+ } else if ((frame_cnt > 1) &&
+ (ehdr->e_type != ET_REL)) {
+ Conv_inv_buf_t inv_buf;
+
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_WARN_MULTEHFRM), file,
+ EC_WORD(cnt), _cache->c_name,
+ conv_ehdr_type(ehdr->e_type, 0, &inv_buf));
+ }
+ dump_eh_frame(data, datasize, shdr->sh_addr,
+ ehdr->e_machine, ehdr->e_ident);
}
/*
- * Walk the Eh_frame's
+ * If we've seen the .eh_frame_hdr and the first
+ * .eh_frame section, compare the header frame_ptr
+ * to the address of the actual frame section to ensure
+ * the link-editor got this right.
*/
- while (off < datasize) {
- uint_t cieid, cielength, cieversion;
- uint_t cieretaddr;
- int cieRflag, cieLflag, ciePflag, cieZflag;
- uint_t cieaugndx, length, id;
- uint64_t ciecalign, ciedalign;
- char *cieaugstr;
-
- ndx = 0;
- /*
- * Extract length in lsb format. A zero length
- * indicates that this CIE is a terminator and that
- * processing for this unwind information should end.
- * However, skip this entry and keep processing, just
- * in case there is any other information remaining in
- * this section. Note, ld(1) will terminate the
- * processing of the .eh_frame contents for this file
- * after a zero length CIE, thus any information that
- * does follow is ignored by ld(1), and is therefore
- * questionable.
- */
- if ((length = LSB32EXTRACT(data + off + ndx)) == 0) {
- dbg_print(0, MSG_ORIG(MSG_UNW_ZEROTERM));
- off += 4;
- continue;
- }
- ndx += 4;
-
- /*
- * extract CIE id in lsb format
- */
- id = LSB32EXTRACT(data + off + ndx);
- ndx += 4;
-
- /*
- * A CIE record has a id of '0', otherwise this is a
- * FDE entry and the 'id' is the CIE pointer.
- */
- if (id == 0) {
- uint64_t persVal;
-
- cielength = length;
- cieid = id;
- cieLflag = ciePflag = cieRflag = cieZflag = 0;
-
- dbg_print(0, MSG_ORIG(MSG_UNW_CIE),
- EC_XWORD(shdr->sh_addr + off));
- dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH),
- cielength, cieid);
-
- cieversion = data[off + ndx];
- ndx += 1;
- cieaugstr = (char *)(&data[off + ndx]);
- ndx += strlen(cieaugstr) + 1;
-
- dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS),
- cieversion, cieaugstr);
-
- ciecalign = uleb_extract(&data[off], &ndx);
- ciedalign = sleb_extract(&data[off], &ndx);
- cieretaddr = data[off + ndx];
- ndx += 1;
-
- dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN),
- EC_XWORD(ciecalign), EC_XWORD(ciedalign),
- cieretaddr);
-
- if (cieaugstr[0])
- dbg_print(0,
- MSG_ORIG(MSG_UNW_CIEAXVAL));
-
- for (cieaugndx = 0; cieaugstr[cieaugndx];
- cieaugndx++) {
- uint_t val;
-
- switch (cieaugstr[cieaugndx]) {
- case 'z':
- val = uleb_extract(&data[off],
- &ndx);
- dbg_print(0,
- MSG_ORIG(MSG_UNW_CIEAXSIZ),
- val);
- cieZflag = 1;
- break;
- case 'P':
- ciePflag = data[off + ndx];
- ndx += 1;
-
- persVal = dwarf_ehe_extract(
- &data[off], &ndx, ciePflag,
- ehdr->e_ident,
- shdr->sh_addr + off + ndx);
- dbg_print(0,
- MSG_ORIG(MSG_UNW_CIEAXPERS),
- ciePflag,
- conv_dwarf_ehe(ciePflag,
- &dwarf_ehe_buf),
- EC_XWORD(persVal));
- break;
- case 'R':
- val = data[off + ndx];
- ndx += 1;
- dbg_print(0,
- MSG_ORIG(MSG_UNW_CIEAXCENC),
- val, conv_dwarf_ehe(val,
- &dwarf_ehe_buf));
- cieRflag = val;
- break;
- case 'L':
- val = data[off + ndx];
- ndx += 1;
- dbg_print(0,
- MSG_ORIG(MSG_UNW_CIEAXLSDA),
- val, conv_dwarf_ehe(val,
- &dwarf_ehe_buf));
- cieLflag = val;
- break;
- default:
- dbg_print(0,
- MSG_ORIG(MSG_UNW_CIEAXUNEC),
- cieaugstr[cieaugndx]);
- break;
- }
- }
- if ((cielength + 4) > ndx)
- unwindtbl(&ndx, cielength, data, off,
- MSG_ORIG(MSG_UNW_CIECFI),
- MSG_ORIG(MSG_UNW_CIEPRE),
- MSG_UNW_CIEPRE_SIZE);
- off += cielength + 4;
-
- } else {
- uint_t fdelength = length;
- int fdecieptr = id;
- uint64_t fdeinitloc, fdeaddrrange;
-
- dbg_print(0, MSG_ORIG(MSG_UNW_FDE),
- EC_XWORD(shdr->sh_addr + off));
- dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH),
- fdelength, fdecieptr);
-
- fdeinitloc = dwarf_ehe_extract(&data[off],
- &ndx, cieRflag, ehdr->e_ident,
- shdr->sh_addr + off + ndx);
- fdeaddrrange = dwarf_ehe_extract(&data[off],
- &ndx, (cieRflag & ~DW_EH_PE_pcrel),
- ehdr->e_ident,
- shdr->sh_addr + off + ndx);
-
- dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC),
- EC_XWORD(fdeinitloc),
- EC_XWORD(fdeaddrrange));
-
- if (cieaugstr[0])
- dbg_print(0,
- MSG_ORIG(MSG_UNW_FDEAXVAL));
- if (cieZflag) {
- uint64_t val;
- val = uleb_extract(&data[off], &ndx);
- dbg_print(0,
- MSG_ORIG(MSG_UNW_FDEAXSIZE),
- EC_XWORD(val));
- if (val & cieLflag) {
- fdeinitloc = dwarf_ehe_extract(
- &data[off], &ndx, cieLflag,
- ehdr->e_ident,
- shdr->sh_addr + off + ndx);
- dbg_print(0,
- MSG_ORIG(MSG_UNW_FDEAXLSDA),
- EC_XWORD(val));
- }
- }
- if ((fdelength + 4) > ndx)
- unwindtbl(&ndx, fdelength, data, off,
- MSG_ORIG(MSG_UNW_FDECFI),
- MSG_ORIG(MSG_UNW_FDEPRE),
- MSG_UNW_FDEPRE_SIZE);
- off += fdelength + 4;
- }
- }
+ if ((hdr_cnt > 0) && (frame_cnt > 0) &&
+ (save_frame_ptr != save_frame_base))
+ (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADEHFRMPTR),
+ file, EC_WORD(hdr_ndx), cache[hdr_ndx].c_name,
+ EC_XWORD(save_frame_ptr), EC_WORD(frame_ndx),
+ cache[frame_ndx].c_name, EC_XWORD(save_frame_base));
}
+
+#undef MSG_UNW_BINSRTAB2
+#undef MSG_UNW_BINSRTABENT
}
/*
@@ -864,8 +742,11 @@ cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr,
static void
interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf)
{
+ static Word phdr_types[] = { PT_INTERP };
+
+
Word cnt;
- Shdr *ishdr = 0;
+ Shdr *ishdr = NULL;
Cache *icache;
Off iphdr_off = 0;
Xword iphdr_fsz;
@@ -876,7 +757,9 @@ interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf)
if (phnum) {
Phdr *phdr;
- if ((phdr = getphdr(phnum, PT_INTERP, file, elf)) != 0) {
+ phdr = getphdr(phnum, phdr_types,
+ sizeof (phdr_types) / sizeof (*phdr_types), file, elf);
+ if (phdr != NULL) {
iphdr_off = phdr->p_offset;
iphdr_fsz = phdr->p_filesz;
}
@@ -941,7 +824,7 @@ syminfo(Cache *cache, Word shnum, const char *file)
Sym *syms;
Dyn *dyns;
Word infonum, cnt, ndx, symnum;
- Cache *infocache = 0, *symsec, *strsec;
+ Cache *infocache = NULL, *symsec, *strsec;
for (cnt = 1; cnt < shnum; cnt++) {
if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) {
@@ -949,7 +832,7 @@ syminfo(Cache *cache, Word shnum, const char *file)
break;
}
}
- if (infocache == 0)
+ if (infocache == NULL)
return;
infoshdr = infocache->c_shdr;
@@ -976,7 +859,7 @@ syminfo(Cache *cache, Word shnum, const char *file)
return;
dyns = cache[infoshdr->sh_info].c_data->d_buf;
- if (dyns == 0) {
+ if (dyns == NULL) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
file, cache[infoshdr->sh_info].c_name);
return;
@@ -1000,7 +883,7 @@ syminfo(Cache *cache, Word shnum, const char *file)
for (ndx = 1, info++; ndx < infonum; ndx++, info++) {
Sym *sym;
- const char *needed = 0, *name;
+ const char *needed = NULL, *name;
if ((info->si_flags == 0) && (info->si_boundto == 0))
continue;
@@ -1510,7 +1393,7 @@ output_symbol(SYMTBL_STATE *state, Word symndx, Word info, Word disp_symndx,
* Symbol types for which we check that the specified
* address/size land inside the target section.
*/
- static const int addr_symtype[STT_NUM] = {
+ static const int addr_symtype[] = {
0, /* STT_NOTYPE */
1, /* STT_OBJECT */
1, /* STT_FUNC */
@@ -1518,8 +1401,17 @@ output_symbol(SYMTBL_STATE *state, Word symndx, Word info, Word disp_symndx,
0, /* STT_FILE */
1, /* STT_COMMON */
0, /* STT_TLS */
+ 0, /* STT_IFUNC */
+ 0, /* 8 */
+ 0, /* 9 */
+ 0, /* 10 */
+ 0, /* 11 */
+ 0, /* 12 */
+ 0, /* STT_SPARC_REGISTER */
+ 0, /* 14 */
+ 0, /* 15 */
};
-#if STT_NUM != (STT_TLS + 1)
+#if STT_NUM != (STT_IFUNC + 1)
#error "STT_NUM has grown. Update addr_symtype[]"
#endif
@@ -1551,7 +1443,7 @@ output_symbol(SYMTBL_STATE *state, Word symndx, Word info, Word disp_symndx,
&state->cache[state->seccache->c_shdr->sh_link], state->file,
sym->st_name);
- tshdr = 0;
+ tshdr = NULL;
sec = NULL;
if (state->ehdr->e_type == ET_CORE) {
@@ -2692,7 +2584,7 @@ static void
move(Cache *cache, Word shnum, const char *file, uint_t flags)
{
Word cnt;
- const char *fmt = 0;
+ const char *fmt = NULL;
for (cnt = 1; cnt < shnum; cnt++) {
Word movenum, symnum, ndx;
@@ -2735,7 +2627,7 @@ move(Cache *cache, Word shnum, const char *file, uint_t flags)
dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name);
dbg_print(0, MSG_INTL(MSG_MOVE_TITLE));
- if (fmt == 0)
+ if (fmt == NULL)
fmt = MSG_INTL(MSG_MOVE_ENTRY);
for (ndx = 0; ndx < movenum; move++, ndx++) {
@@ -3589,7 +3481,7 @@ shdr_cache(const char *file, Elf *elf, Ehdr *ehdr, size_t shstrndx,
Elf_Data *data;
size_t ndx;
Shdr *nameshdr;
- char *names = 0;
+ char *names = NULL;
Cache *cache, *_cache;
size_t *shdr_ndx_arr, shdr_ndx_arr_cnt;
@@ -3620,7 +3512,7 @@ shdr_cache(const char *file, Elf *elf, Ehdr *ehdr, size_t shstrndx,
(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN),
EC_WORD(elf_ndxscn(scn)));
- } else if ((names = data->d_buf) == 0)
+ } else if ((names = data->d_buf) == NULL)
(void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file);
/*
@@ -3743,6 +3635,7 @@ shdr_cache(const char *file, Elf *elf, Ehdr *ehdr, size_t shstrndx,
MSG_ORIG(MSG_FMT_SECSYM),
EC_WORD(secsz), secname, symname);
}
+
continue;
}
@@ -3938,7 +3831,7 @@ regular(const char *file, int fd, Elf *elf, uint_t flags,
return (ret);
}
} else
- shdr = 0;
+ shdr = NULL;
/*
* Print the elf header.
@@ -4083,10 +3976,15 @@ regular(const char *file, int fd, Elf *elf, uint_t flags,
case SHT_PROGBITS:
/*
* Heuristic time: It is usually bad form
- * to assume that specific section names
- * have a given meaning. However, the
- * ELF ABI does specify a few such names. Try
- * to match them:
+ * to assume the meaning/format of a PROGBITS
+ * section based on its name. However, there
+ * are exceptions: The ELF ABI specifies
+ * .interp and .got sections by name. Existing
+ * practice has similarly pinned down the
+ * meaning of unwind sections (.eh_frame and
+ * .eh_frame_hdr).
+ *
+ * Check for these special names.
*/
if (strcmp(_cache->c_name,
MSG_ORIG(MSG_ELF_INTERP)) == 0)
@@ -4094,6 +3992,10 @@ regular(const char *file, int fd, Elf *elf, uint_t flags,
else if (strcmp(_cache->c_name,
MSG_ORIG(MSG_ELF_GOT)) == 0)
flags |= FLG_SHOW_GOT;
+ else if (strncmp(_cache->c_name,
+ MSG_ORIG(MSG_SCN_FRM),
+ MSG_SCN_FRM_SIZE) == 0)
+ flags |= FLG_SHOW_UNWIND;
break;
case SHT_SYMTAB:
diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.msg b/usr/src/cmd/sgs/elfdump/common/elfdump.msg
index f3c60c27cb..1f7d0ebc99 100644
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg
+++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg
@@ -149,6 +149,10 @@
@ MSG_ERR_DYNSYMVAL "%s: %s: symbol value does not match \
DT_%s entry: %s: value: %#llx\n"
@ MSG_ERR_MALSTR "%s: %s: malformed string table, initial or final byte\n"
+@ MSG_ERR_MULTEHFRMHDR "%s: [%d: %s] multiple .eh_frame_hdr sections seen \
+ (1 expected)\n"
+@ MSG_ERR_BADEHFRMPTR "%s: section[%d: %s] FramePtr (%#llx) does not match \
+ shdr[%d: %s].sh_addr (%#llx)\n"
@ MSG_WARN_INVINTERP1 "%s: PT_INTERP header has no associated section\n"
@@ -161,6 +165,8 @@
header have conflicting size or offsets\n"
@ MSG_WARN_INADDR32SF1 "%s: capabilities section %s: software capability \
ADDR32: is ineffective within a 32-bit object\n"
+@ MSG_WARN_MULTEHFRM "%s: section[%d: %s]: %s object has multiple \
+ .eh_frame sections\n"
# Elf Output Messages
@@ -292,6 +298,8 @@
@ MSG_STR_8SP " "
@ MSG_STR_EMPTY ""
@ MSG_STR_CORE "CORE"
+@ MSG_STR_LOC "loc"
+@ MSG_STR_INITLOC "initloc"
@ MSG_FMT_INDENT " %s"
@ MSG_FMT_INDEX " [%lld]"
@@ -319,37 +327,60 @@
@ MSG_UNW_FRMHDR "Frame Header:"
@ MSG_UNW_FRMVERS " Version: %d"
-@ MSG_UNW_FRPTRENC " FramePtrEnc: %-20s FramePtr: 0x%llx"
+@ MSG_UNW_FRPTRENC " FramePtrEnc: %-20s FramePtr: %#llx"
@ MSG_UNW_FDCNENC " FdeCntEnc: %-20s FdeCnt: %lld"
@ MSG_UNW_TABENC " TableEnc: %-20s"
@ MSG_UNW_BINSRTAB1 " Binary Search Table:"
-@ MSG_UNW_BINSRTAB2 " InitialLoc FdeLoc"
-@ MSG_UNW_BINSRTABENT " 0x%016llx 0x%016llx"
+@ MSG_UNW_BINSRTAB2_32 " InitialLoc FdeLoc"
+@ MSG_UNW_BINSRTAB2_64 " InitialLoc FdeLoc"
+@ MSG_UNW_BINSRTABENT_32 " 0x%08llx 0x%08llx"
+@ MSG_UNW_BINSRTABENT_64 " 0x%016llx 0x%016llx"
@ MSG_UNW_ZEROTERM "ZERO terminator: [0x00000000]"
-@ MSG_UNW_CIE "CIE: [0x%08llx]"
+@ MSG_UNW_CIE "CIE: [%#llx]"
@ MSG_UNW_CIELNGTH " length: 0x%02x cieid: %d"
-@ MSG_UNW_CIEVERS " version: %d augstring: `%s'"
-@ MSG_UNW_CIECALGN " codealign: 0x%llx dataalign: %lld \
+@ MSG_UNW_CIEVERS " version: %d augmentation: `%s'"
+@ MSG_UNW_CIECALGN " codealign: %#llx dataalign: %lld \
retaddr: %d"
-@ MSG_UNW_CIEAXVAL " Auxiliary vals:"
+@ MSG_UNW_CIEAXVAL " Augmentation Data:"
@ MSG_UNW_CIEAXSIZ " size: %d"
-@ MSG_UNW_CIEAXPERS " pers: 0x%02x %s 0x%08llx"
-@ MSG_UNW_CIEAXCENC " cenc: 0x%02x %s"
-@ MSG_UNW_CIEAXLSDA " lsda: 0x%02x %s"
+@ MSG_UNW_CIEAXPERS " personality:"
+@ MSG_UNW_CIEAXPERSENC " encoding: 0x%02x %s"
+@ MSG_UNW_CIEAXPERSRTN " routine: %#08llx"
+@ MSG_UNW_CIEAXCENC " code pointer encoding: 0x%02x %s"
+@ MSG_UNW_CIEAXLSDA " lsda encoding: 0x%02x %s"
@ MSG_UNW_CIEAXUNEC " Unexpected aug val: %c"
@ MSG_UNW_CIECFI " CallFrameInstructions:"
-@ MSG_UNW_CIEPRE " "
-@ MSG_UNW_FDE " FDE: [0x%08llx]"
-@ MSG_UNW_FDELNGTH " length: 0x%02x cieptr: 0x%02x"
-@ MSG_UNW_FDEINITLOC " initloc: 0x%08llx addrrange: 0x%04llx"
-@ MSG_UNW_FDEAXVAL " Auxiliary vals:"
-@ MSG_UNW_FDEAXSIZE " size: 0x%llx"
-@ MSG_UNW_FDEAXLSDA " lsda: 0x%llx"
-@ MSG_UNW_FDECFI " CallFrameInstructions:"
-@ MSG_UNW_FDEPRE " "
+@ MSG_UNW_FDE " FDE: [%#llx]"
+@ MSG_UNW_FDELNGTH " length: %#x cieptr: %#x"
+@ MSG_UNW_FDEINITLOC " initloc: %#llx addrrange: %#llx endloc: %#llx"
+@ MSG_UNW_FDEAXVAL " Augmentation Data:"
+@ MSG_UNW_FDEAXSIZE " size: %#llx"
+@ MSG_UNW_FDEAXLSDA " lsda: %#llx"
+@ MSG_UNW_FDECFI " CallFrameInstructions:"
+
+# Unwind section Call Frame Instructions. These all start with a leading
+# "%*s%s", used to insert leading whitespace and the opcode name.
+
+@ MSG_CFA_ADV_LOC "%*s%s: %s + %llu => %#llx"
+@ MSG_CFA_CFAOFF "%*s%s: %s, cfa%+lld"
+@ MSG_CFA_CFASET "%*s%s: cfa=%#llx"
+@ MSG_CFA_LLD "%*s%s: %lld"
+@ MSG_CFA_LLU "%*s%s: %llu"
+@ MSG_CFA_REG "%*s%s: %s"
+@ MSG_CFA_REG_OFFLLD "%*s%s: %s, offset=%lld"
+@ MSG_CFA_REG_OFFLLU "%*s%s: %s, offset=%llu"
+@ MSG_CFA_REG_REG "%*s%s: %s, %s"
+@ MSG_CFA_SIMPLE "%*s%s"
+@ MSG_CFA_SIMPLEREP "%*s%s [%d]"
+@ MSG_CFA_EBLK "%*s%s: expr(%llu bytes)"
+@ MSG_CFA_REG_EBLK "%*s%s: %s, expr(%llu bytes)"
+
+# Architecture specific register name formats
+
+@ MSG_REG_FMT_BASIC "r%d"
+@ MSG_REG_FMT_NAME "r%d (%s)"
-@ MSG_UNW_TBLENTRY "0x%02x "
# Note messages
@@ -653,6 +684,8 @@
@ MSG_PT_TLS_ALT1 "tls"
@ MSG_PT_SUNW_UNWIND "PT_SUNW_UNWIND" # 0x6464e550
@ MSG_PT_SUNW_UNWIND_ALT1 "sunw_unwind"
+@ MSG_PT_SUNW_EH_FRAME "PT_SUNW_EH_FRAME" # 0x6474e550
+@ MSG_PT_SUNW_EH_FRAME_ALT1 "sunw_eh_frame"
@ MSG_PT_SUNWBSS "PT_SUNWBSS" # 0x6ffffffa
@ MSG_PT_SUNWBSS_ALT1 "sunwbss"
@ MSG_PT_SUNWSTACK "PT_SUNWSTACK" # 0x6ffffffb
diff --git a/usr/src/cmd/sgs/elfdump/common/fake_shdr.c b/usr/src/cmd/sgs/elfdump/common/fake_shdr.c
index 64991a353b..29f7bc1c99 100644
--- a/usr/src/cmd/sgs/elfdump/common/fake_shdr.c
+++ b/usr/src/cmd/sgs/elfdump/common/fake_shdr.c
@@ -20,10 +20,9 @@
*/
/*
- * 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"
/*
* Generate a cache of section header information for an ELF
@@ -1173,6 +1172,7 @@ fake_shdr_cache(const char *file, int fd, Elf *elf, Ehdr *ehdr,
break;
case PT_SUNW_UNWIND:
+ case PT_SUNW_EH_FRAME:
sec.unwind.type = SINFO_T_UNWIND;
sinfo = &sec.unwind;
break;
diff --git a/usr/src/cmd/sgs/elfdump/common/main.c b/usr/src/cmd/sgs/elfdump/common/main.c
index f7dfc4c5cd..e58ddea7c2 100644
--- a/usr/src/cmd/sgs/elfdump/common/main.c
+++ b/usr/src/cmd/sgs/elfdump/common/main.c
@@ -20,10 +20,9 @@
*/
/*
- * 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"
/*
* Dump an elf file.
@@ -250,6 +249,9 @@ static atoui_sym_t sym_pt[] = {
{ MSG_ORIG(MSG_PT_SUNW_UNWIND), PT_SUNW_UNWIND },
{ MSG_ORIG(MSG_PT_SUNW_UNWIND_ALT1), PT_SUNW_UNWIND },
+ { MSG_ORIG(MSG_PT_SUNW_EH_FRAME), PT_SUNW_EH_FRAME },
+ { MSG_ORIG(MSG_PT_SUNW_EH_FRAME_ALT1), PT_SUNW_EH_FRAME },
+
{ MSG_ORIG(MSG_PT_SUNWBSS), PT_SUNWBSS },
{ MSG_ORIG(MSG_PT_SUNWBSS_ALT1), PT_SUNWBSS },
@@ -348,9 +350,10 @@ detail_usage()
* shows (bytes_per_col * col_per_row) bytes of data.
*/
void
-dump_hex_bytes(const char *data, size_t n, int indent,
+dump_hex_bytes(const void *data, size_t n, int indent,
int bytes_per_col, int col_per_row)
{
+ const uchar_t *ldata = data;
int bytes_per_row = bytes_per_col * col_per_row;
int ndx, byte, word;
char string[128], *str = string;
@@ -372,12 +375,12 @@ dump_hex_bytes(const char *data, size_t n, int indent,
index_width = strlen(index);
index_width = S_ROUND(index_width, 8);
- for (ndx = byte = word = 0; n > 0; n--, data++) {
+ for (ndx = byte = word = 0; n > 0; n--, ldata++) {
while (sp_prefix-- > 0)
*str++ = ' ';
(void) snprintf(str, sizeof (string),
- MSG_ORIG(MSG_HEXDUMP_TOK), (int)*data);
+ MSG_ORIG(MSG_HEXDUMP_TOK), (int)*ldata);
str += 2;
sp_prefix = 1;
@@ -741,9 +744,9 @@ archive(const char *file, int fd, Elf *elf, uint_t flags,
{
Elf_Cmd cmd = ELF_C_READ;
Elf_Arhdr *arhdr;
- Elf *_elf = 0;
+ Elf *_elf = NULL;
size_t ptr;
- Elf_Arsym *arsym = 0;
+ Elf_Arsym *arsym = NULL;
/*
* Determine if the archive symbol table itself is required.
@@ -795,15 +798,15 @@ archive(const char *file, int fd, Elf *elf, uint_t flags,
if (elf_rand(elf, arsym->as_off) !=
arsym->as_off) {
failure(file, MSG_ORIG(MSG_ELF_RAND));
- arhdr = 0;
+ arhdr = NULL;
} else if ((_elf = elf_begin(fd,
ELF_C_READ, elf)) == 0) {
failure(file, MSG_ORIG(MSG_ELF_BEGIN));
- arhdr = 0;
+ arhdr = NULL;
} else if ((arhdr = elf_getarhdr(_elf)) == 0) {
failure(file,
MSG_ORIG(MSG_ELF_GETARHDR));
- arhdr = 0;
+ arhdr = NULL;
}
_offset = arsym->as_off;
diff --git a/usr/src/cmd/sgs/elfedit/common/elfconst.c b/usr/src/cmd/sgs/elfedit/common/elfconst.c
index 90cf71c4de..bf2edb792d 100644
--- a/usr/src/cmd/sgs/elfedit/common/elfconst.c
+++ b/usr/src/cmd/sgs/elfedit/common/elfconst.c
@@ -20,10 +20,9 @@
*/
/*
- * 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 <stdlib.h>
#include <stdio.h>
@@ -1133,6 +1132,9 @@ static elfedit_atoui_sym_t sym_pt[] = {
{ MSG_ORIG(MSG_PT_SUNW_UNWIND), PT_SUNW_UNWIND },
{ MSG_ORIG(MSG_PT_SUNW_UNWIND_ALT1), PT_SUNW_UNWIND },
+ { MSG_ORIG(MSG_PT_SUNW_EH_FRAME), PT_SUNW_EH_FRAME },
+ { MSG_ORIG(MSG_PT_SUNW_EH_FRAME_ALT1), PT_SUNW_EH_FRAME },
+
{ MSG_ORIG(MSG_PT_SUNWBSS), PT_SUNWBSS },
{ MSG_ORIG(MSG_PT_SUNWBSS_ALT1), PT_SUNWBSS },
diff --git a/usr/src/cmd/sgs/elfedit/common/elfedit.msg b/usr/src/cmd/sgs/elfedit/common/elfedit.msg
index 4d9c66f203..8833187662 100644
--- a/usr/src/cmd/sgs/elfedit/common/elfedit.msg
+++ b/usr/src/cmd/sgs/elfedit/common/elfedit.msg
@@ -20,11 +20,9 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
@ _START_
@@ -1246,6 +1244,8 @@
@ MSG_PT_TLS_ALT1 "tls"
@ MSG_PT_SUNW_UNWIND "PT_SUNW_UNWIND" # 0x6464e550
@ MSG_PT_SUNW_UNWIND_ALT1 "sunw_unwind"
+@ MSG_PT_SUNW_EH_FRAME "PT_SUNW_EH_FRAME" # 0x6474e550
+@ MSG_PT_SUNW_EH_FRAME_ALT1 "sunw_eh_frame"
@ MSG_PT_SUNWBSS "PT_SUNWBSS" # 0x6ffffffa
@ MSG_PT_SUNWBSS_ALT1 "sunwbss"
@ MSG_PT_SUNWSTACK "PT_SUNWSTACK" # 0x6ffffffb
diff --git a/usr/src/cmd/sgs/include/conv.h b/usr/src/cmd/sgs/include/conv.h
index d9fccb6a62..1facea96d1 100644
--- a/usr/src/cmd/sgs/include/conv.h
+++ b/usr/src/cmd/sgs/include/conv.h
@@ -23,7 +23,7 @@
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -860,7 +860,11 @@ extern const char *conv_demangle_name(const char *);
extern const char *conv_dl_flag(int, Conv_fmt_flags_t,
Conv_dl_flag_buf_t *);
extern const char *conv_dl_mode(int, int, Conv_dl_mode_buf_t *);
+extern const char *conv_dwarf_cfa(uchar_t, Conv_fmt_flags_t,
+ Conv_inv_buf_t *);
extern const char *conv_dwarf_ehe(uint_t, Conv_dwarf_ehe_buf_t *);
+extern const char *conv_dwarf_regname(Half, Word, Conv_fmt_flags_t,
+ int *, Conv_inv_buf_t *);
extern const char *conv_elfdata_type(Elf_Type, Conv_inv_buf_t *);
extern const char *conv_grphdl_flags(uint_t, Conv_grphdl_flags_buf_t *);
extern const char *conv_grpdesc_flags(uint_t, Conv_grpdesc_flags_buf_t *);
diff --git a/usr/src/cmd/sgs/include/dwarf.h b/usr/src/cmd/sgs/include/dwarf.h
index 980d059934..31c295d17c 100644
--- a/usr/src/cmd/sgs/include/dwarf.h
+++ b/usr/src/cmd/sgs/include/dwarf.h
@@ -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.
@@ -24,15 +23,13 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _DWARF_H
#define _DWARF_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
@@ -254,20 +251,7 @@ typedef enum _LANG {
extern uint64_t uleb_extract(unsigned char *, uint64_t *);
extern int64_t sleb_extract(unsigned char *, uint64_t *);
extern uint64_t dwarf_ehe_extract(unsigned char *, uint64_t *,
- uint_t, unsigned char *, uint64_t);
-
-/*
- * LSB32EXTRACT()
- *
- * Extract a LSB encoded int which may or may not be
- * aligned on a 4 byte boundary. This macro will work
- * on either a MSB or LSB based system.
- */
-#define LSB32EXTRACT(lsbptr) ((unsigned int)(\
- ((unsigned const char *)(lsbptr))[0] + \
- (((unsigned const char *)(lsbptr))[1] << 8) + \
- (((unsigned const char *)(lsbptr))[2] << 16) + \
- (((unsigned const char *)(lsbptr))[3] << 24)))
+ uint_t, unsigned char *, uint64_t, uint64_t);
#ifdef __cplusplus
}
diff --git a/usr/src/cmd/sgs/include/i386/machdep_x86.h b/usr/src/cmd/sgs/include/i386/machdep_x86.h
index eee31216c4..9904a8d7c6 100644
--- a/usr/src/cmd/sgs/include/i386/machdep_x86.h
+++ b/usr/src/cmd/sgs/include/i386/machdep_x86.h
@@ -267,24 +267,25 @@ extern "C" {
#define M_ID_INTERP 0x03 /* SHF_ALLOC */
#define M_ID_CAP 0x04
-#define M_ID_UNWINDHDR 0x05
-#define M_ID_UNWIND 0x06
-#define M_ID_SYMINFO 0x07
-#define M_ID_HASH 0x08
-#define M_ID_LDYNSYM 0x09 /* always right before DYNSYM */
-#define M_ID_DYNSYM 0x0a
-#define M_ID_DYNSTR 0x0b
-#define M_ID_VERSION 0x0c
-#define M_ID_DYNSORT 0x0d
-#define M_ID_REL 0x0e
-#define M_ID_PLT 0x0f /* SHF_ALLOC + SHF_EXECISNTR */
-#define M_ID_TEXT 0x10
+#define M_ID_UNWINDHDR 0x06
+#define M_ID_UNWIND 0x07
+#define M_ID_SYMINFO 0x08
+#define M_ID_HASH 0x09
+#define M_ID_LDYNSYM 0x0a /* always right before DYNSYM */
+#define M_ID_DYNSYM 0x0b
+#define M_ID_DYNSTR 0x0c
+#define M_ID_VERSION 0x0d
+#define M_ID_DYNSORT 0x0e
+#define M_ID_REL 0x0f
+#define M_ID_PLT 0x10 /* SHF_ALLOC + SHF_EXECISNTR */
+#define M_ID_TEXT 0x11
#define M_ID_DATA 0x20
-/* M_ID_USER 0x02 dual entry - listed above */
+/* M_ID_USER 0x01 dual entry - listed above */
#define M_ID_GOT 0x03 /* SHF_ALLOC + SHF_WRITE */
#define M_ID_DYNAMIC 0x05
#define M_ID_ARRAY 0x06
+/* M_ID_UNWIND 0x07 dual entry - listed above */
#define M_ID_UNKNOWN 0xfb /* just before TLS */
diff --git a/usr/src/cmd/sgs/include/libld.h b/usr/src/cmd/sgs/include/libld.h
index 2f7980e4ab..2403c1abdb 100644
--- a/usr/src/cmd/sgs/include/libld.h
+++ b/usr/src/cmd/sgs/include/libld.h
@@ -201,10 +201,8 @@ struct ofl_desc {
List ofl_rtldinfo; /* list of rtldinfo syms */
List ofl_osgroups; /* list of output GROUP sections */
List ofl_ostlsseg; /* pointer to sections in TLS segment */
-#if defined(_ELF64) /* for amd64 target only */
- List ofl_unwind; /* list of unwind output sections */
+ APlist *ofl_unwind; /* list of unwind output sections */
Os_desc *ofl_unwindhdr; /* Unwind hdr */
-#endif
avl_tree_t ofl_symavl; /* pointer to head of Syms AVL tree */
Sym_desc **ofl_regsyms; /* array of potential register */
Word ofl_regsymsno; /* symbols and array count */
@@ -607,6 +605,7 @@ struct is_desc { /* input section descriptor */
#define FLG_IS_GROUPS 0x0200 /* section has groups to process */
#define FLG_IS_PLACE 0x0400 /* section requires to be placed */
#define FLG_IS_COMDAT 0x0800 /* section is COMDAT */
+#define FLG_IS_EHFRAME 0x1000 /* section is .eh_frame */
/*
* Map file and output file processing structures
diff --git a/usr/src/cmd/sgs/include/sparc/machdep_sparc.h b/usr/src/cmd/sgs/include/sparc/machdep_sparc.h
index 2fc05ca4f5..22c8f512c6 100644
--- a/usr/src/cmd/sgs/include/sparc/machdep_sparc.h
+++ b/usr/src/cmd/sgs/include/sparc/machdep_sparc.h
@@ -271,16 +271,19 @@ extern "C" {
#define M_ID_INTERP 0x02 /* SHF_ALLOC */
#define M_ID_CAP 0x03
-#define M_ID_SYMINFO 0x04
-#define M_ID_HASH 0x05
-#define M_ID_LDYNSYM 0x06 /* always right before DYNSYM */
-#define M_ID_DYNSYM 0x07
-#define M_ID_DYNSTR 0x08
-#define M_ID_VERSION 0x09
-#define M_ID_DYNSORT 0x0a
-#define M_ID_REL 0x0b
-#define M_ID_TEXT 0x0c /* SHF_ALLOC + SHF_EXECINSTR */
-#define M_ID_DATA 0x0d
+#define M_ID_UNWINDHDR 0x06
+#define M_ID_UNWIND 0x07
+
+#define M_ID_SYMINFO 0x08
+#define M_ID_HASH 0x09
+#define M_ID_LDYNSYM 0x0a /* always right before DYNSYM */
+#define M_ID_DYNSYM 0x0b
+#define M_ID_DYNSTR 0x0c
+#define M_ID_VERSION 0x0d
+#define M_ID_DYNSORT 0x0e
+#define M_ID_REL 0x0f
+#define M_ID_TEXT 0x10 /* SHF_ALLOC + SHF_EXECINSTR */
+#define M_ID_DATA 0x20
/* M_ID_USER 0x01 dual entry - listed above */
#define M_ID_GOTDATA 0x02 /* SHF_ALLOC + SHF_WRITE */
@@ -288,6 +291,7 @@ extern "C" {
#define M_ID_PLT 0x04
#define M_ID_DYNAMIC 0x05
#define M_ID_ARRAY 0x06
+/* M_ID_UNWIND 0x07 dual entry - listed above */
#define M_ID_UNKNOWN 0xfc /* just before TLS */
diff --git a/usr/src/cmd/sgs/libconv/Makefile.com b/usr/src/cmd/sgs/libconv/Makefile.com
index e2c64589d2..bf4c15418d 100644
--- a/usr/src/cmd/sgs/libconv/Makefile.com
+++ b/usr/src/cmd/sgs/libconv/Makefile.com
@@ -20,11 +20,9 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
LIBRARY = libconv.a
@@ -48,9 +46,9 @@ COMOBJS= arch.o c_literal.o \
config.o corenote.o \
data.o deftag.o \
demangle.o dl.o \
- dwarf_ehe.o group.o \
- lddstub.o segments.o \
- version.o
+ dwarf.o dwarf_ehe.o \
+ group.o lddstub.o \
+ segments.o version.o
COMOBJS_NOMSG = tokens.o
diff --git a/usr/src/cmd/sgs/libconv/common/dwarf.c b/usr/src/cmd/sgs/libconv/common/dwarf.c
new file mode 100644
index 0000000000..c32eb9e322
--- /dev/null
+++ b/usr/src/cmd/sgs/libconv/common/dwarf.c
@@ -0,0 +1,222 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <strings.h>
+#include <dwarf.h>
+#include "_conv.h"
+#include <dwarf_msg.h>
+
+/*
+ * This code is primarily of interest to elfdump. Separating it from dwarf_ehe
+ * allows other tools to use dwarf_ehe without also pulling this in.
+ */
+
+/* Instantiate a local copy of conv_map2str() from _conv.h */
+DEFINE_conv_map2str
+
+
+/*
+ * Translate DW_CFA_ codes, used to identify Call Frame Instructions.
+ */
+const char *
+conv_dwarf_cfa(uchar_t op, Conv_fmt_flags_t fmt_flags, Conv_inv_buf_t *inv_buf)
+{
+ static const Msg cfa[] = {
+ MSG_DW_CFA_NOP, MSG_DW_CFA_SET_LOC,
+ MSG_DW_CFA_ADVANCE_LOC_1, MSG_DW_CFA_ADVANCE_LOC_2,
+ MSG_DW_CFA_ADVANCE_LOC_4, MSG_DW_CFA_OFFSET_EXTENDED,
+ MSG_DW_CFA_RESTORE_EXTENDED, MSG_DW_CFA_UNDEFINED,
+ MSG_DW_CFA_SAME_VALUE, MSG_DW_CFA_REGISTER,
+ MSG_DW_CFA_REMEMBER_STATE, MSG_DW_CFA_RESTORE_STATE,
+ MSG_DW_CFA_DEF_CFA, MSG_DW_CFA_DEF_CFA_REGISTER,
+ MSG_DW_CFA_DEF_CFA_OFFSET, MSG_DW_CFA_DEF_CFA_EXPRESSION,
+ MSG_DW_CFA_EXPRESSION, MSG_DW_CFA_OFFSET_EXTENDED_SF,
+ MSG_DW_CFA_DEF_CFA_SF, MSG_DW_CFA_DEF_CFA_OFFSET_SF,
+ MSG_DW_CFA_VAL_OFFSET, MSG_DW_CFA_VAL_OFFSET_SF,
+ MSG_DW_CFA_VAL_EXPRESSION
+ };
+ static const Msg gnu[] = {
+ MSG_DW_CFA_GNU_WINDOW_SAVE, MSG_DW_CFA_GNU_ARGS_SIZE,
+ MSG_DW_CFA_GNU_NEGATIVE_OFF_X
+ };
+
+ /*
+ * DWARF CFA opcodes are bytes. The top 2 bits are a primary
+ * opcode, and if zero, the lower 6 bits specify a sub-opcode
+ */
+ switch (op >> 6) {
+ case 0x1:
+ return (MSG_ORIG(MSG_DW_CFA_ADVANCE_LOC));
+ case 0x2:
+ return (MSG_ORIG(MSG_DW_CFA_OFFSET));
+ case 0x3:
+ return (MSG_ORIG(MSG_DW_CFA_RESTORE));
+ }
+
+ if (op == 0x1d)
+ return (MSG_ORIG(MSG_DW_CFA_MIPS_ADV_LOC8));
+
+ if ((op >= 0x2d) && (op <= 0x2f))
+ return (conv_map2str(inv_buf, (op - 0x2d),
+ fmt_flags, ARRAY_NELTS(gnu), gnu));
+
+ return (conv_map2str(inv_buf, op, fmt_flags, ARRAY_NELTS(cfa), cfa));
+}
+
+/*
+ * Translate DWARF register numbers to hardware specific names
+ *
+ * If good_name is non-NULL, conv_dwarf_regname() will set the variable to
+ * True(1) if the returned string is considered to be a good name to
+ * display, and False(0) otherwise. To be considered "good":
+ *
+ * - The name must be a well known mnemonic for a register
+ * from the machine type in question.
+ *
+ * - The name must be different than the DWARF name for
+ * the same register.
+ *
+ * The returned string is usable, regardless of the value returned in
+ * *good_name.
+ */
+const char *
+conv_dwarf_regname(Half mach, Word regno, Conv_fmt_flags_t fmt_flags,
+ int *good_name, Conv_inv_buf_t *inv_buf)
+{
+ static const Msg reg_amd64[67] = {
+ MSG_REG_RAX, MSG_REG_RDX,
+ MSG_REG_RCX, MSG_REG_RBX,
+ MSG_REG_RSI, MSG_REG_RDI,
+ MSG_REG_RBP, MSG_REG_RSP,
+ MSG_REG_R8, MSG_REG_R9,
+ MSG_REG_R10, MSG_REG_R11,
+ MSG_REG_R12, MSG_REG_R13,
+ MSG_REG_R14, MSG_REG_R15,
+ MSG_REG_RA, MSG_REG_PERXMM0,
+ MSG_REG_PERXMM1, MSG_REG_PERXMM2,
+ MSG_REG_PERXMM3, MSG_REG_PERXMM4,
+ MSG_REG_PERXMM5, MSG_REG_PERXMM6,
+ MSG_REG_PERXMM7, MSG_REG_PERXMM8,
+ MSG_REG_PERXMM9, MSG_REG_PERXMM10,
+ MSG_REG_PERXMM11, MSG_REG_PERXMM12,
+ MSG_REG_PERXMM13, MSG_REG_PERXMM14,
+ MSG_REG_PERXMM15, MSG_REG_PERST0,
+ MSG_REG_PERST1, MSG_REG_PERST2,
+ MSG_REG_PERST3, MSG_REG_PERST4,
+ MSG_REG_PERST5, MSG_REG_PERST6,
+ MSG_REG_PERST7, MSG_REG_PERMM0,
+ MSG_REG_PERMM1, MSG_REG_PERMM2,
+ MSG_REG_PERMM3, MSG_REG_PERMM4,
+ MSG_REG_PERMM5, MSG_REG_PERMM6,
+ MSG_REG_PERMM7, MSG_REG_PERRFLAGS,
+ MSG_REG_PERES, MSG_REG_PERCS,
+ MSG_REG_PERSS, MSG_REG_PERDS,
+ MSG_REG_PERFS, MSG_REG_PERGS,
+ MSG_REG_RESERVED, MSG_REG_RESERVED,
+ MSG_REG_PERFSDOTBASE, MSG_REG_PERGSDOTBASE,
+ MSG_REG_RESERVED, MSG_REG_RESERVED,
+ MSG_REG_PERTR, MSG_REG_PERLDTR,
+ MSG_REG_PERMXCSR, MSG_REG_PERFCW,
+ MSG_REG_PERFSW
+ };
+
+ static const Msg reg_i386[8] = {
+ MSG_REG_EAX, MSG_REG_ECX,
+ MSG_REG_EDX, MSG_REG_EBX,
+ MSG_REG_UESP, MSG_REG_EBP,
+ MSG_REG_ESI, MSG_REG_EDI
+ };
+
+ static const Msg reg_sparc[64] = {
+ MSG_REG_G0, MSG_REG_G1,
+ MSG_REG_G2, MSG_REG_G3,
+ MSG_REG_G4, MSG_REG_G5,
+ MSG_REG_G6, MSG_REG_G7,
+ MSG_REG_O0, MSG_REG_O1,
+ MSG_REG_O2, MSG_REG_O3,
+ MSG_REG_O4, MSG_REG_O5,
+ MSG_REG_O6, MSG_REG_O7,
+ MSG_REG_L0, MSG_REG_L1,
+ MSG_REG_L2, MSG_REG_L3,
+ MSG_REG_L4, MSG_REG_L5,
+ MSG_REG_L6, MSG_REG_L7,
+ MSG_REG_I0, MSG_REG_I1,
+ MSG_REG_I2, MSG_REG_I3,
+ MSG_REG_I4, MSG_REG_I5,
+ MSG_REG_I6, MSG_REG_I7,
+ MSG_REG_F0, MSG_REG_F1,
+ MSG_REG_F2, MSG_REG_F3,
+ MSG_REG_F4, MSG_REG_F5,
+ MSG_REG_F6, MSG_REG_F7,
+ MSG_REG_F8, MSG_REG_F9,
+ MSG_REG_F10, MSG_REG_F11,
+ MSG_REG_F12, MSG_REG_F13,
+ MSG_REG_F14, MSG_REG_F15,
+ MSG_REG_F16, MSG_REG_F17,
+ MSG_REG_F18, MSG_REG_F19,
+ MSG_REG_F20, MSG_REG_F21,
+ MSG_REG_F22, MSG_REG_F23,
+ MSG_REG_F24, MSG_REG_F25,
+ MSG_REG_F26, MSG_REG_F27,
+ MSG_REG_F28, MSG_REG_F29,
+ MSG_REG_F30, MSG_REG_F31
+ };
+
+ switch (mach) {
+ case EM_AMD64:
+ /*
+ * amd64 has several in-bounds names we'd rather not
+ * use. R8-R15 have the same name as their DWARF counterparts.
+ * 56-57, and 60-61 are reserved, and don't have a good name.
+ */
+ if (good_name)
+ *good_name = ((regno < 8) || (regno > 15)) &&
+ (regno != 56) && (regno != 57) &&
+ (regno != 60) && (regno != 61) &&
+ (regno < ARRAY_NELTS(reg_amd64));
+ return (conv_map2str(inv_buf, regno,
+ fmt_flags, ARRAY_NELTS(reg_amd64), reg_amd64));
+
+ case EM_386:
+ case EM_486:
+ if (good_name)
+ *good_name = (regno < ARRAY_NELTS(reg_i386));
+ return (conv_map2str(inv_buf, regno,
+ fmt_flags, ARRAY_NELTS(reg_i386), reg_i386));
+
+ case EM_SPARC:
+ case EM_SPARC32PLUS:
+ case EM_SPARCV9:
+ if (good_name)
+ *good_name = (regno < ARRAY_NELTS(reg_sparc));
+ return (conv_map2str(inv_buf, regno,
+ fmt_flags, ARRAY_NELTS(reg_sparc), reg_sparc));
+ }
+
+ if (good_name)
+ *good_name = 0;
+ return (conv_invalid_val(inv_buf, regno, 0));
+}
diff --git a/usr/src/cmd/sgs/libconv/common/dwarf.msg b/usr/src/cmd/sgs/libconv/common/dwarf.msg
new file mode 100644
index 0000000000..1a2cbaf30d
--- /dev/null
+++ b/usr/src/cmd/sgs/libconv/common/dwarf.msg
@@ -0,0 +1,203 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Call Frame Information op codes
+#
+@ MSG_DW_CFA_ADVANCE_LOC "DW_CFA_advance_loc"
+@ MSG_DW_CFA_ADVANCE_LOC_1 "DW_CFA_advance_loc_1"
+@ MSG_DW_CFA_ADVANCE_LOC_2 "DW_CFA_advance_loc_2"
+@ MSG_DW_CFA_ADVANCE_LOC_4 "DW_CFA_advance_loc_4"
+@ MSG_DW_CFA_DEF_CFA "DW_CFA_def_cfa"
+@ MSG_DW_CFA_DEF_CFA_EXPRESSION "DW_CFA_def_cfa_expression"
+@ MSG_DW_CFA_DEF_CFA_OFFSET "DW_CFA_def_cfa_offset"
+@ MSG_DW_CFA_DEF_CFA_OFFSET_SF "DW_CFA_def_cfa_offset_sf"
+@ MSG_DW_CFA_DEF_CFA_REGISTER "DW_CFA_def_cfa_register"
+@ MSG_DW_CFA_DEF_CFA_SF "DW_CFA_def_cfa_sf"
+@ MSG_DW_CFA_EXPRESSION "DW_CFA_expression"
+@ MSG_DW_CFA_GNU_ARGS_SIZE "DW_CFA_GNU_args_size"
+@ MSG_DW_CFA_GNU_NEGATIVE_OFF_X "DW_CFA_GNU_negative_offset_extended"
+@ MSG_DW_CFA_GNU_WINDOW_SAVE "DW_CFA_GNU_window_save"
+@ MSG_DW_CFA_MIPS_ADV_LOC8 "DW_CFA_MIPS_advance_loc8"
+@ MSG_DW_CFA_NOP "DW_CFA_nop"
+@ MSG_DW_CFA_OFFSET "DW_CFA_offset"
+@ MSG_DW_CFA_OFFSET_EXTENDED "DW_CFA_offset_extended"
+@ MSG_DW_CFA_OFFSET_EXTENDED_SF "DW_CFA_offset_extended_sf"
+@ MSG_DW_CFA_REGISTER "DW_CFA_register"
+@ MSG_DW_CFA_REMEMBER_STATE "DW_CFA_remember_state"
+@ MSG_DW_CFA_RESTORE_STATE "DW_CFA_restore_state"
+@ MSG_DW_CFA_RESTORE "DW_CFA_restore"
+@ MSG_DW_CFA_RESTORE_EXTENDED "DW_CFA_restore_extended"
+@ MSG_DW_CFA_SAME_VALUE "DW_CFA_same_value"
+@ MSG_DW_CFA_SET_LOC "DW_CFA_set_loc"
+@ MSG_DW_CFA_UNDEFINED "DW_CFA_undefined"
+@ MSG_DW_CFA_VAL_EXPRESSION "DW_CFA_val_expression"
+@ MSG_DW_CFA_VAL_OFFSET "DW_CFA_val_offset"
+@ MSG_DW_CFA_VAL_OFFSET_SF "DW_CFA_val_offset_sf"
+
+#
+# Names for registers on various machines
+#
+@ MSG_REG_EAX "eax"
+@ MSG_REG_EBP "ebp"
+@ MSG_REG_EBX "ebx"
+@ MSG_REG_ECX "ecx"
+@ MSG_REG_EDX "edx"
+@ MSG_REG_EDI "edi"
+@ MSG_REG_ESI "esi"
+@ MSG_REG_F0 "f0"
+@ MSG_REG_F1 "f1"
+@ MSG_REG_F2 "f2"
+@ MSG_REG_F3 "f3"
+@ MSG_REG_F4 "f4"
+@ MSG_REG_F5 "f5"
+@ MSG_REG_F6 "f6"
+@ MSG_REG_F7 "f7"
+@ MSG_REG_F8 "f8"
+@ MSG_REG_F9 "f9"
+@ MSG_REG_F10 "f10"
+@ MSG_REG_F11 "f11"
+@ MSG_REG_F12 "f12"
+@ MSG_REG_F13 "f13"
+@ MSG_REG_F14 "f14"
+@ MSG_REG_F15 "f15"
+@ MSG_REG_F16 "f16"
+@ MSG_REG_F17 "f17"
+@ MSG_REG_F18 "f18"
+@ MSG_REG_F19 "f19"
+@ MSG_REG_F20 "f20"
+@ MSG_REG_F21 "f21"
+@ MSG_REG_F22 "f22"
+@ MSG_REG_F23 "f23"
+@ MSG_REG_F24 "f24"
+@ MSG_REG_F25 "f25"
+@ MSG_REG_F26 "f26"
+@ MSG_REG_F27 "f27"
+@ MSG_REG_F28 "f28"
+@ MSG_REG_F29 "f29"
+@ MSG_REG_F30 "f30"
+@ MSG_REG_F31 "f31"
+@ MSG_REG_G0 "g0"
+@ MSG_REG_G1 "g1"
+@ MSG_REG_G2 "g2"
+@ MSG_REG_G3 "g3"
+@ MSG_REG_G4 "g4"
+@ MSG_REG_G5 "g5"
+@ MSG_REG_G6 "g6"
+@ MSG_REG_G7 "g7"
+@ MSG_REG_I0 "i0"
+@ MSG_REG_I1 "i1"
+@ MSG_REG_I2 "i2"
+@ MSG_REG_I3 "i3"
+@ MSG_REG_I4 "i4"
+@ MSG_REG_I5 "i5"
+@ MSG_REG_I6 "i6"
+@ MSG_REG_I7 "i7"
+@ MSG_REG_L0 "l0"
+@ MSG_REG_L1 "l1"
+@ MSG_REG_L2 "l2"
+@ MSG_REG_L3 "l3"
+@ MSG_REG_L4 "l4"
+@ MSG_REG_L5 "l5"
+@ MSG_REG_L6 "l6"
+@ MSG_REG_L7 "l7"
+@ MSG_REG_O0 "o0"
+@ MSG_REG_O1 "o1"
+@ MSG_REG_O2 "o2"
+@ MSG_REG_O3 "o3"
+@ MSG_REG_O4 "o4"
+@ MSG_REG_O5 "o5"
+@ MSG_REG_O6 "o6"
+@ MSG_REG_O7 "o7"
+@ MSG_REG_PERCS "%%cs"
+@ MSG_REG_PERDS "%%ds"
+@ MSG_REG_PERES "%%es"
+@ MSG_REG_PERFCW "%%fcw"
+@ MSG_REG_PERFSW "%%fsw"
+@ MSG_REG_PERFS "%%fs"
+@ MSG_REG_PERFSDOTBASE "%%fs.base"
+@ MSG_REG_PERGS "%%gs"
+@ MSG_REG_PERGSDOTBASE "%%gs.base"
+@ MSG_REG_PERLDTR "%%ldtr"
+@ MSG_REG_PERMM0 "%%mm0"
+@ MSG_REG_PERMM1 "%%mm1"
+@ MSG_REG_PERMM2 "%%mm2"
+@ MSG_REG_PERMM3 "%%mm3"
+@ MSG_REG_PERMM4 "%%mm4"
+@ MSG_REG_PERMM5 "%%mm5"
+@ MSG_REG_PERMM6 "%%mm6"
+@ MSG_REG_PERMM7 "%%mm7"
+@ MSG_REG_PERMXCSR "%%mxcsr"
+@ MSG_REG_PERRFLAGS "%%rFLAGS"
+@ MSG_REG_PERSS "%%ss"
+@ MSG_REG_PERST0 "%%st0"
+@ MSG_REG_PERST1 "%%st1"
+@ MSG_REG_PERST2 "%%st2"
+@ MSG_REG_PERST3 "%%st3"
+@ MSG_REG_PERST4 "%%st4"
+@ MSG_REG_PERST5 "%%st5"
+@ MSG_REG_PERST6 "%%st6"
+@ MSG_REG_PERST7 "%%st7"
+@ MSG_REG_PERTR "%%tr"
+@ MSG_REG_PERXMM0 "%%xmm0"
+@ MSG_REG_PERXMM1 "%%xmm1"
+@ MSG_REG_PERXMM2 "%%xmm2"
+@ MSG_REG_PERXMM3 "%%xmm3"
+@ MSG_REG_PERXMM4 "%%xmm4"
+@ MSG_REG_PERXMM5 "%%xmm5"
+@ MSG_REG_PERXMM6 "%%xmm6"
+@ MSG_REG_PERXMM7 "%%xmm7"
+@ MSG_REG_PERXMM8 "%%xmm8"
+@ MSG_REG_PERXMM9 "%%xmm9"
+@ MSG_REG_PERXMM10 "%%xmm10"
+@ MSG_REG_PERXMM11 "%%xmm11"
+@ MSG_REG_PERXMM12 "%%xmm12"
+@ MSG_REG_PERXMM13 "%%xmm13"
+@ MSG_REG_PERXMM14 "%%xmm14"
+@ MSG_REG_PERXMM15 "%%xmm15"
+@ MSG_REG_R8 "r8"
+@ MSG_REG_R9 "r9"
+@ MSG_REG_R10 "r10"
+@ MSG_REG_R11 "r11"
+@ MSG_REG_R12 "r12"
+@ MSG_REG_R13 "r13"
+@ MSG_REG_R14 "r14"
+@ MSG_REG_R15 "r15"
+@ MSG_REG_RA "ra"
+@ MSG_REG_RAX "rax"
+@ MSG_REG_RBP "rbp"
+@ MSG_REG_RBX "rbx"
+@ MSG_REG_RCX "rcx"
+@ MSG_REG_RDX "rdx"
+@ MSG_REG_RDI "rdi"
+@ MSG_REG_RESERVED "reserved"
+@ MSG_REG_RSI "rsi"
+@ MSG_REG_RSP "rsp"
+@ MSG_REG_UESP "uesp"
+
+
+@ MSG_GBL_OSQBRKT "["
+@ MSG_GBL_CSQBRKT "]"
diff --git a/usr/src/cmd/sgs/libconv/common/phdr.c b/usr/src/cmd/sgs/libconv/common/phdr.c
index cc32f6f8bc..233387f238 100644
--- a/usr/src/cmd/sgs/libconv/common/phdr.c
+++ b/usr/src/cmd/sgs/libconv/common/phdr.c
@@ -20,12 +20,10 @@
*/
/*
- * Copyright 2007 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"
-
/*
* String conversion routines for program header attributes.
*/
@@ -36,6 +34,7 @@
/* Instantiate a local copy of conv_map2str() from _conv.h */
DEFINE_conv_map2str
+/*ARGSUSED*/
const char *
conv_phdr_type(Half mach, Word type, Conv_fmt_flags_t fmt_flags,
Conv_inv_buf_t *inv_buf)
@@ -87,7 +86,7 @@ error "PT_NUM has grown. Update phdrs[]"
return (conv_map2str(inv_buf, (type - PT_SUNWBSS),
fmt_flags, ARRAY_NELTS(uphdrs), uphdrs));
}
- } else if ((type == PT_SUNW_UNWIND) && (mach == EM_AMD64)) {
+ } else if (type == PT_SUNW_UNWIND) {
switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
case CONV_FMT_ALT_DUMP:
case CONV_FMT_ALT_FILE:
@@ -95,6 +94,14 @@ error "PT_NUM has grown. Update phdrs[]"
default:
return (MSG_ORIG(MSG_PT_SUNW_UNWIND));
}
+ } else if (type == PT_SUNW_EH_FRAME) {
+ switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
+ case CONV_FMT_ALT_DUMP:
+ case CONV_FMT_ALT_FILE:
+ return (MSG_ORIG(MSG_PT_SUNW_EH_FRAME_ALT));
+ default:
+ return (MSG_ORIG(MSG_PT_SUNW_EH_FRAME));
+ }
} else
return (conv_invalid_val(inv_buf, type, 0));
}
diff --git a/usr/src/cmd/sgs/libconv/common/phdr.msg b/usr/src/cmd/sgs/libconv/common/phdr.msg
index b1f1684f92..dbb251c560 100644
--- a/usr/src/cmd/sgs/libconv/common/phdr.msg
+++ b/usr/src/cmd/sgs/libconv/common/phdr.msg
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -50,8 +50,10 @@
@ MSG_PT_SUNWCAP "[ PT_SUNWCAP ]"
@ MSG_PT_SUNWCAP_ALT "PT_SUNWCAP"
-@ MSG_PT_SUNW_UNWIND "[ PT_SUNW_UNWIND ]"
+@ MSG_PT_SUNW_UNWIND "[ PT_SUNW_UNWIND ]"
@ MSG_PT_SUNW_UNWIND_ALT "PT_SUNW_UNWIND"
+@ MSG_PT_SUNW_EH_FRAME "[ PT_SUNW_EH_FRAME ]"
+@ MSG_PT_SUNW_EH_FRAME_ALT "PT_SUNW_EH_FRAME"
@ MSG_PF_X "PF_X"
@ MSG_PF_W "PF_W"
diff --git a/usr/src/cmd/sgs/libconv/common/symbols.c b/usr/src/cmd/sgs/libconv/common/symbols.c
index fc29b70927..0ec4c04854 100644
--- a/usr/src/cmd/sgs/libconv/common/symbols.c
+++ b/usr/src/cmd/sgs/libconv/common/symbols.c
@@ -20,10 +20,9 @@
*/
/*
- * 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"
/*
* String conversion routines for symbol attributes.
@@ -99,14 +98,14 @@ conv_sym_info_type(Half mach, uchar_t type, Conv_fmt_flags_t fmt_flags,
MSG_STT_NOTYPE, MSG_STT_OBJECT,
MSG_STT_FUNC, MSG_STT_SECTION,
MSG_STT_FILE, MSG_STT_COMMON,
- MSG_STT_TLS
+ MSG_STT_TLS, MSG_STT_IFUNC
};
static const Msg types_alt[] = {
MSG_STT_NOTYPE_ALT, MSG_STT_OBJECT_ALT,
MSG_STT_FUNC_ALT, MSG_STT_SECTION_ALT,
MSG_STT_FILE_ALT, MSG_STT_COMMON_ALT,
- MSG_STT_TLS_ALT
+ MSG_STT_TLS_ALT, MSG_STT_IFUNC_ALT
};
if (type < STT_NUM) {
diff --git a/usr/src/cmd/sgs/libconv/common/symbols.msg b/usr/src/cmd/sgs/libconv/common/symbols.msg
index 316ee1fa66..f14a159d69 100644
--- a/usr/src/cmd/sgs/libconv/common/symbols.msg
+++ b/usr/src/cmd/sgs/libconv/common/symbols.msg
@@ -19,11 +19,9 @@
# CDDL HEADER END
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
@ MSG_STT_NOTYPE "NOTY"
@ MSG_STT_NOTYPE_ALT "STT_NOTYPE"
@@ -37,8 +35,10 @@
@ MSG_STT_FILE_ALT "STT_FILE"
@ MSG_STT_COMMON "COMM"
@ MSG_STT_COMMON_ALT "STT_COMMON"
-@ MSG_STT_TLS "TLS "
+@ MSG_STT_TLS "TLS"
@ MSG_STT_TLS_ALT "STT_TLS"
+@ MSG_STT_IFUNC "IFUNC"
+@ MSG_STT_IFUNC_ALT "STT_IFUNC"
@ MSG_STT_SPARC_REGISTER "REGI"
@ MSG_STT_SPARC_REGISTER_ALT "STT_SPARC_REGISTER"
diff --git a/usr/src/cmd/sgs/libelf/demo/dispsyms.c b/usr/src/cmd/sgs/libelf/demo/dispsyms.c
index baa56d0f5e..95a4304be8 100644
--- a/usr/src/cmd/sgs/libelf/demo/dispsyms.c
+++ b/usr/src/cmd/sgs/libelf/demo/dispsyms.c
@@ -19,10 +19,9 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 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"
/*
* dispsyms: Display Symbols
@@ -62,8 +61,11 @@ static const char *symtype[STT_NUM] = {
/* STT_FILE */ "FILE",
/* STT_COMMON */ "COMM",
/* STT_TLS */ "TLS"
+/* STT_IFUNC */ "IFUNC"
};
-
+#if STT_NUM != (STT_IFUNC + 1)
+#error "STT_NUM has grown. Update symtype[]."
+#endif
#define INTSTRLEN 32
@@ -79,13 +81,13 @@ print_symtab(Elf *elf, const char *file)
if (gelf_getehdr(elf, &ehdr) == 0) {
(void) fprintf(stderr, "%s: elf_getehdr() failed: %s\n",
- file, elf_errmsg(0));
+ file, elf_errmsg(0));
return;
}
if (elf_getshstrndx(elf, &shstrndx) == 0) {
(void) fprintf(stderr, "%s: elf_getshstrndx() failed: %s\n",
- file, elf_errmsg(0));
+ file, elf_errmsg(0));
return;
}
@@ -99,8 +101,8 @@ print_symtab(Elf *elf, const char *file)
if (gelf_getshdr(scn, &shdr) == 0) {
(void) fprintf(stderr,
- "%s: elf_getshdr() failed: %s\n",
- file, elf_errmsg(0));
+ "%s: elf_getshdr() failed: %s\n",
+ file, elf_errmsg(0));
return;
}
if ((shdr.sh_type != SHT_SYMTAB) &&
@@ -114,8 +116,8 @@ print_symtab(Elf *elf, const char *file)
*/
if ((symdata = elf_getdata(scn, 0)) == 0) {
(void) fprintf(stderr,
- "%s: elf_getdata() failed: %s\n",
- file, elf_errmsg(0));
+ "%s: elf_getdata() failed: %s\n",
+ file, elf_errmsg(0));
return;
}
@@ -123,9 +125,9 @@ print_symtab(Elf *elf, const char *file)
* Print symbol table title and header for symbol display
*/
(void) printf("\nSymTab: %s:%s\n", file,
- elf_strptr(elf, shstrndx, shdr.sh_name));
+ elf_strptr(elf, shstrndx, shdr.sh_name));
(void) printf(" index value size type "
- "bind oth shndx name\n");
+ "bind oth shndx name\n");
/*
* We now iterate over the full symbol table printing
@@ -153,8 +155,8 @@ print_symtab(Elf *elf, const char *file)
if (gelf_getsymshndx(symdata, shndxdata, ndx,
&sym, &shndx) == NULL) {
(void) fprintf(stderr,
- "%s: gelf_getsymshndx() failed: %s\n",
- file, elf_errmsg(0));
+ "%s: gelf_getsymshndx() failed: %s\n",
+ file, elf_errmsg(0));
return;
}
/*
@@ -200,9 +202,9 @@ print_symtab(Elf *elf, const char *file)
(gelf_getsymshndx(symdata, shndxdata, ndx,
&sym, &shndx) == NULL)) {
(void) fprintf(stderr,
- "%s: gelf_getsymshndx() "
- "failed: %s\n",
- file, elf_errmsg(0));
+ "%s: gelf_getsymshndx() "
+ "failed: %s\n",
+ file, elf_errmsg(0));
return;
}
/*
@@ -227,7 +229,7 @@ print_symtab(Elf *elf, const char *file)
typestr = symtype[type];
else {
(void) snprintf(typebuf, INTSTRLEN,
- "%d", type);
+ "%d", type);
typestr = typebuf;
}
@@ -235,7 +237,7 @@ print_symtab(Elf *elf, const char *file)
bindstr = symbind[bind];
else {
(void) snprintf(bindbuf, INTSTRLEN,
- "%d", bind);
+ "%d", bind);
bindstr = bindbuf;
}
@@ -261,12 +263,12 @@ print_symtab(Elf *elf, const char *file)
shndxstr = (const char *)"XIND";
else {
(void) snprintf(shndxbuf, INTSTRLEN,
- "%ld", shndx);
+ "%ld", shndx);
shndxstr = shndxbuf;
}
} else {
(void) snprintf(shndxbuf, INTSTRLEN,
- "%ld", shndx);
+ "%ld", shndx);
shndxstr = shndxbuf;
}
@@ -274,10 +276,10 @@ print_symtab(Elf *elf, const char *file)
* Display the symbol entry.
*/
(void) printf("[%3d] 0x%08llx 0x%08llx %-4s "
- "%-6s %2d %5s %s\n",
- ndx, sym.st_value, sym.st_size,
- typestr, bindstr, sym.st_other, shndxstr,
- elf_strptr(elf, shdr.sh_link, sym.st_name));
+ "%-6s %2d %5s %s\n",
+ ndx, sym.st_value, sym.st_size,
+ typestr, bindstr, sym.st_other, shndxstr,
+ elf_strptr(elf, shdr.sh_link, sym.st_name));
}
}
}
@@ -317,7 +319,7 @@ process_elf(Elf *elf, char *file, int fd, int member)
* 'archivename(membername)'.
*/
(void) snprintf(buffer, 1024, "%s(%s)",
- file, arhdr->ar_name);
+ file, arhdr->ar_name);
/*
* recursivly process the ELF members.
@@ -330,8 +332,8 @@ process_elf(Elf *elf, char *file, int fd, int member)
default:
if (!member)
(void) fprintf(stderr,
- "%s: unexpected elf_kind(): 0x%x\n",
- file, elf_kind(elf));
+ "%s: unexpected elf_kind(): 0x%x\n",
+ file, elf_kind(elf));
return;
}
}
@@ -354,7 +356,7 @@ main(int argc, char **argv)
*/
if (elf_version(EV_CURRENT) == EV_NONE) {
(void) fprintf(stderr,
- "elf_version() failed: %s\n", elf_errmsg(0));
+ "elf_version() failed: %s\n", elf_errmsg(0));
return (1);
}
diff --git a/usr/src/cmd/sgs/libld/Makefile.com b/usr/src/cmd/sgs/libld/Makefile.com
index 0e6d1a6c65..cfa5fc3b6b 100644
--- a/usr/src/cmd/sgs/libld/Makefile.com
+++ b/usr/src/cmd/sgs/libld/Makefile.com
@@ -33,14 +33,14 @@ COMOBJS32 = args32.o entry32.o exit32.o groups32.o \
libs32.o files32.o map32.o order32.o \
outfile32.o place32.o relocate32.o resolve32.o \
sections32.o sunwmove32.o support32.o syms32.o \
- update32.o version32.o
+ update32.o unwind32.o version32.o
COMOBJS64 = args64.o entry64.o exit64.o groups64.o \
ldentry64.o ldlibs64.o ldmachdep64.o ldmain64.o \
libs64.o files64.o map64.o order64.o \
outfile64.o place64.o relocate64.o resolve64.o \
sections64.o sunwmove64.o support64.o syms64.o \
- update64.o version64.o
+ update64.o unwind64.o version64.o
TOOLOBJS = alist.o assfail.o findprime.o string_table.o \
strhash.o
@@ -58,7 +58,7 @@ L_SPARC_MACHOBJS64 = machrel.sparc64.o machsym.sparc64.o
# Target specific objects (i386/amd64)
E_X86_TOOLOBJS = leb128.o
L_X86_MACHOBJS32 = machrel.intel32.o
-L_X86_MACHOBJS64 = machrel.amd64.o unwind.amd64.o
+L_X86_MACHOBJS64 = machrel.amd64.o
# All target specific objects rolled together
diff --git a/usr/src/cmd/sgs/libld/common/README.XLINK b/usr/src/cmd/sgs/libld/common/README.XLINK
index 2eebe59ee2..5eba8e52f4 100644
--- a/usr/src/cmd/sgs/libld/common/README.XLINK
+++ b/usr/src/cmd/sgs/libld/common/README.XLINK
@@ -20,10 +20,9 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
@@ -72,8 +71,8 @@ In addition, the target-specific files usually include the target
in their name (i.e. machrel.sparc.c).
Although the target dependent and independent (common) code is well separated,
-they are interdependent. For example, the common code is aware of
-the target-specific section types that can occur only for some targets
+they are interdependent. The common code is explicitly aware of
+target-specific section types that can occur only for some targets
(i.e. SHT_AMD64_UNWIND). This is not an architecture that allows
for arbitrary target support to be dynamically plugged into an unchanged
platform independent core. Rather, it is an organization that allows
diff --git a/usr/src/cmd/sgs/libld/common/_libld.h b/usr/src/cmd/sgs/libld/common/_libld.h
index 42a1dc82da..61d09a73a0 100644
--- a/usr/src/cmd/sgs/libld/common/_libld.h
+++ b/usr/src/cmd/sgs/libld/common/_libld.h
@@ -98,6 +98,9 @@ typedef struct {
Word m_plt_reservsz;
Word m_plt_shf_flags;
+ /* Section type of .eh_frame/.eh_frame_hdr sections */
+ Word m_sht_unwind;
+
Word m_dt_register;
} Target_mach;
@@ -134,6 +137,7 @@ typedef struct {
Word id_tlsbss;
Word id_unknown;
Word id_unwind;
+ Word id_unwindhdr;
Word id_user;
Word id_version;
} Target_machid;
@@ -218,26 +222,12 @@ typedef struct {
int (* ms_reg_enter)(Sym_desc *, Ofl_desc *);
} Target_machsym;
-/*
- * amd64 unwind header support
- *
- * These fields are allowed to be NULL for targets that do not support
- * amd64 unwind headers. If any of these fields are non-NULL, all of them are
- * required to be present (use empty stub routines if necessary).
- */
-typedef struct {
- uintptr_t (* uw_make_unwindhdr)(Ofl_desc *);
- uintptr_t (* uw_populate_unwindhdr)(Ofl_desc *);
- uintptr_t (* uw_append_unwind)(Os_desc *, Ofl_desc *);
-} Target_unwind;
-
typedef struct {
Target_mach t_m;
Target_machid t_id;
Target_nullfunc t_nf;
Target_machrel t_mr;
Target_machsym t_ms;
- Target_unwind t_uw;
} Target;
@@ -330,16 +320,17 @@ typedef struct {
/*
* Define Alist initialization sizes.
*/
-#define AL_CNT_IFL_GROUPS 20 /* ifl_groups initial alist count */
-#define AL_CNT_OFL_DTSFLTRS 4 /* ofl_dtsfltrs initial alist count */
-#define AL_CNT_OFL_SYMFLTRS 20 /* ofl_symfltrs initial alist count */
+#define AL_CNT_IFL_GROUPS 20 /* ifl_groups */
+#define AL_CNT_OFL_DTSFLTRS 4 /* ofl_dtsfltrs */
+#define AL_CNT_OFL_SYMFLTRS 20 /* ofl_symfltrs */
#define AL_CNT_OS_MSTRISDESCS 10 /* os_mstrisdescs */
#define AL_CNT_OS_RELISDESCS 100 /* os_relisdescs */
#define AL_CNT_OS_COMDATS 20 /* os_comdats */
-#define AL_CNT_SG_OSDESC 40 /* sg_osdescs initial alist count */
-#define AL_CNT_SG_SECORDER 40 /* sg_secorder initial alist count */
+#define AL_CNT_SG_OSDESC 40 /* sg_osdescs */
+#define AL_CNT_SG_SECORDER 40 /* sg_secorder */
#define AL_CNT_STRMRGREL 500 /* ld_make_strmerge() reloc alist cnt */
#define AL_CNT_STRMRGSYM 20 /* ld_make_strmerge() sym alist cnt */
+#define AL_CNT_UNWIND 1 /* ofl_unwind */
/*
* Return codes for {tls|got}_fixups() routines
@@ -590,6 +581,9 @@ extern Sdf_desc *sdf_find(const char *, List *);
#define ld_targ ld64_targ
#define ld_targ_init_sparc ld64_targ_init_sparc
#define ld_targ_init_x86 ld64_targ_init_x86
+#define ld_unwind_make_hdr ld64_unwind_make_hdr
+#define ld_unwind_populate_hdr ld64_unwind_populate_hdr
+#define ld_unwind_register ld64_unwind_register
#define ld_vers_base ld64_vers_base
#define ld_vers_check_defs ld64_vers_check_defs
#define ld_vers_check_need ld64_vers_check_need
@@ -673,6 +667,9 @@ extern Sdf_desc *sdf_find(const char *, List *);
#define ld_targ ld32_targ
#define ld_targ_init_sparc ld32_targ_init_sparc
#define ld_targ_init_x86 ld32_targ_init_x86
+#define ld_unwind_make_hdr ld32_unwind_make_hdr
+#define ld_unwind_populate_hdr ld32_unwind_populate_hdr
+#define ld_unwind_register ld32_unwind_register
#define ld_vers_base ld32_vers_base
#define ld_vers_check_defs ld32_vers_check_defs
#define ld_vers_check_need ld32_vers_check_need
@@ -792,6 +789,10 @@ extern Target ld_targ;
extern const Target *ld_targ_init_sparc(void);
extern const Target *ld_targ_init_x86(void);
+extern uintptr_t ld_unwind_make_hdr(Ofl_desc *);
+extern uintptr_t ld_unwind_populate_hdr(Ofl_desc *);
+extern uintptr_t ld_unwind_register(Os_desc *, Ofl_desc *);
+
extern Ver_desc *ld_vers_base(Ofl_desc *);
extern uintptr_t ld_vers_check_defs(Ofl_desc *);
extern uintptr_t ld_vers_check_need(Ofl_desc *);
diff --git a/usr/src/cmd/sgs/libld/common/entry.c b/usr/src/cmd/sgs/libld/common/entry.c
index d06df73030..175b0ac342 100644
--- a/usr/src/cmd/sgs/libld/common/entry.c
+++ b/usr/src/cmd/sgs/libld/common/entry.c
@@ -23,7 +23,7 @@
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -53,9 +53,7 @@ typedef enum {
LD_DYN,
LD_DTRACE,
LD_TLS,
-#if defined(_ELF64)
- LD_UNWIND, /* (amd64-only) */
-#endif
+ LD_UNWIND,
LD_NOTE,
LD_EXTRA,
LD_NUM
@@ -138,11 +136,9 @@ static const Sg_desc sg_desc[LD_NUM] = {
SG_DESC_INIT(PT_TLS, PF_R, MSG_ORIG(MSG_ENT_TLS),
(FLG_SG_TYPE | FLG_SG_FLAGS)),
-#if defined(_ELF64)
- /* LD_UNWIND (amd64-only) */
+ /* LD_UNWIND */
SG_DESC_INIT(PT_SUNW_UNWIND, PF_R, MSG_ORIG(MSG_ENT_UNWIND),
(FLG_SG_TYPE | FLG_SG_FLAGS)),
-#endif
/* LD_NOTE */
SG_DESC_INIT(PT_NOTE, 0, MSG_ORIG(MSG_ENT_NOTE), FLG_SG_TYPE),
@@ -297,7 +293,6 @@ ld_ent_setup(Ofl_desc *ofl, Xword segalign)
switch (idx) {
case LD_LRODATA:
case LD_LDATA:
- case LD_UNWIND:
if ((ld_targ.t_m.m_mach != EM_AMD64))
continue;
}
diff --git a/usr/src/cmd/sgs/libld/common/files.c b/usr/src/cmd/sgs/libld/common/files.c
index 26700a1fed..63b3d565f0 100644
--- a/usr/src/cmd/sgs/libld/common/files.c
+++ b/usr/src/cmd/sgs/libld/common/files.c
@@ -555,7 +555,9 @@ static uintptr_t
process_progbits(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn,
Word ndx, int ident, Ofl_desc *ofl)
{
- int stab_index = 0;
+ int stab_index = 0;
+ Word is_flags = 0;
+ uintptr_t r;
/*
* Never include .stab.excl sections in any output file.
@@ -587,37 +589,93 @@ process_progbits(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn,
* our own version, so don't allow any input sections of these types to
* be added to the output section list (why a relocatable object would
* have a .plt or .got is a mystery, but stranger things have occurred).
+ *
+ * If there are any unwind sections, and this is a platform that uses
+ * SHT_PROGBITS for unwind sections, then set their ident to reflect
+ * that.
*/
if (ident) {
- if (shdr->sh_flags & SHF_TLS)
+ if (shdr->sh_flags & SHF_TLS) {
ident = ld_targ.t_id.id_tls;
- else if ((shdr->sh_flags & ~ALL_SHF_IGNORE) ==
- (SHF_ALLOC | SHF_EXECINSTR))
+ } else if ((shdr->sh_flags & ~ALL_SHF_IGNORE) ==
+ (SHF_ALLOC | SHF_EXECINSTR)) {
ident = ld_targ.t_id.id_text;
- else if (shdr->sh_flags & SHF_ALLOC) {
- if ((strcmp(name, MSG_ORIG(MSG_SCN_PLT)) == 0) ||
- (strcmp(name, MSG_ORIG(MSG_SCN_GOT)) == 0))
- ident = ld_targ.t_id.id_null;
- else if (stab_index) {
- /*
- * This is a work-around for x86 compilers that
- * have set SHF_ALLOC for the .stab.index
- * section.
- *
- * Because of this, make sure that the
- * .stab.index does not end up as the last
- * section in the text segment. Older linkers
- * can produce segmentation violations when they
- * strip (ld -s) against a shared object whose
- * last section in the text segment is a .stab.
- */
- ident = ld_targ.t_id.id_interp;
- } else
- ident = ld_targ.t_id.id_data;
+ } else if (shdr->sh_flags & SHF_ALLOC) {
+ int done = 0;
+
+ if (name[0] == '.') {
+ switch (name[1]) {
+ case 'e':
+ if ((ld_targ.t_m.m_sht_unwind ==
+ SHT_PROGBITS) &&
+ (strcmp(name,
+ MSG_ORIG(MSG_SCN_EHFRAME)) == 0)) {
+ ident = ld_targ.t_id.id_unwind;
+ is_flags = FLG_IS_EHFRAME;
+ done = 1;
+ }
+ break;
+ case 'g':
+ if (strcmp(name,
+ MSG_ORIG(MSG_SCN_GOT)) == 0) {
+ ident = ld_targ.t_id.id_null;
+ done = 1;
+ break;
+ }
+ if ((ld_targ.t_m.m_sht_unwind ==
+ SHT_PROGBITS)&&
+ (strcmp(name,
+ MSG_ORIG(MSG_SCN_GCC_X_TBL)) ==
+ 0)) {
+ ident = ld_targ.t_id.id_unwind;
+ done = 1;
+ break;
+ }
+ break;
+ case 'p':
+ if (strcmp(name,
+ MSG_ORIG(MSG_SCN_PLT)) == 0) {
+ ident = ld_targ.t_id.id_null;
+ done = 1;
+ }
+ break;
+ }
+ }
+ if (!done) {
+ if (stab_index) {
+ /*
+ * This is a work-around for x86
+ * compilers that have set SHF_ALLOC
+ * for the .stab.index section.
+ *
+ * Because of this, make sure that the
+ * .stab.index does not end up as the
+ * last section in the text segment.
+ * Older linkers can produce
+ * segmentation violations when they
+ * strip (ld -s) against a shared
+ * object whose last section in the
+ * text segment is a .stab.
+ */
+ ident = ld_targ.t_id.id_interp;
+ } else {
+ ident = ld_targ.t_id.id_data;
+ }
+ }
} else
ident = ld_targ.t_id.id_note;
}
- return (process_section(name, ifl, shdr, scn, ndx, ident, ofl));
+
+ r = process_section(name, ifl, shdr, scn, ndx, ident, ofl);
+
+ /*
+ * On success, process_section() creates an input section descriptor.
+ * Now that it exists, we can add any pending input section flags.
+ */
+ if ((is_flags != 0) && (r == 1))
+ ifl->ifl_isdesc[ndx]->is_flags |= is_flags;
+
+ return (r);
}
/*
@@ -1277,6 +1335,21 @@ process_dynamic(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
}
/*
+ * Process a progbits section from a relocatable object (ET_REL).
+ * This is used on non-amd64 objects to recognize .eh_frame sections.
+ */
+/*ARGSUSED1*/
+static uintptr_t
+process_progbits_final(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
+{
+ if (isc->is_osdesc && (isc->is_flags & FLG_IS_EHFRAME) &&
+ (ld_unwind_register(isc->is_osdesc, ofl) == S_ERROR))
+ return (S_ERROR);
+
+ return (1);
+}
+
+/*
* Process a group section.
*/
static uintptr_t
@@ -1415,8 +1488,10 @@ process_exclude(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn,
* procedure (ie. things that can only be done when all required sections
* have been collected).
*/
-static uintptr_t (*Initial[SHT_NUM][2])() = {
+typedef uintptr_t (* initial_func_t)(const char *, Ifl_desc *, Shdr *,
+ Elf_Scn *, Word, int, Ofl_desc *);
+static initial_func_t Initial[SHT_NUM][2] = {
/* ET_REL ET_DYN */
/* SHT_NULL */ invalid_section, invalid_section,
@@ -1440,10 +1515,13 @@ static uintptr_t (*Initial[SHT_NUM][2])() = {
/* SHT_SYMTAB_SHNDX */ process_sym_shndx, NULL
};
-static uintptr_t (*Final[SHT_NUM][2])() = {
+typedef uintptr_t (* final_func_t)(Is_desc *, Ifl_desc *, Ofl_desc *);
+
+static final_func_t Final[SHT_NUM][2] = {
+/* ET_REL ET_DYN */
/* SHT_NULL */ NULL, NULL,
-/* SHT_PROGBITS */ NULL, NULL,
+/* SHT_PROGBITS */ process_progbits_final, NULL,
/* SHT_SYMTAB */ ld_sym_process, ld_sym_process,
/* SHT_STRTAB */ NULL, NULL,
/* SHT_RELA */ rel_process, NULL,
@@ -1643,8 +1721,8 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl)
return (S_ERROR);
break;
case SHT_SUNW_cap:
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_null, ofl) == S_ERROR)
return (S_ERROR);
capisp = ifl->ifl_isdesc[ndx];
break;
@@ -1655,13 +1733,13 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl)
return (S_ERROR);
break;
case SHT_SUNW_move:
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_null, ofl) == S_ERROR)
return (S_ERROR);
break;
case SHT_SUNW_syminfo:
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_null, ofl) == S_ERROR)
return (S_ERROR);
sifisp = ifl->ifl_isdesc[ndx];
break;
@@ -1677,20 +1755,20 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl)
ifl->ifl_isdesc[ndx]->is_flags |= FLG_IS_COMDAT;
break;
case SHT_SUNW_verdef:
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_null, ofl) == S_ERROR)
return (S_ERROR);
vdfisp = ifl->ifl_isdesc[ndx];
break;
case SHT_SUNW_verneed:
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_null, ofl) == S_ERROR)
return (S_ERROR);
vndisp = ifl->ifl_isdesc[ndx];
break;
case SHT_SUNW_versym:
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_null, ofl) == S_ERROR)
return (S_ERROR);
vsyisp = ifl->ifl_isdesc[ndx];
break;
@@ -1704,9 +1782,8 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl)
if (ld_targ.t_m.m_mach !=
LD_TARG_BYCLASS(EM_SPARC, EM_SPARCV9))
goto do_default;
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_gotdata, ofl) ==
- S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_gotdata, ofl) == S_ERROR)
return (S_ERROR);
break;
#if defined(_ELF64)
@@ -1732,15 +1809,17 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl)
scn, ndx, ld_targ.t_id.id_unwind,
ofl) == S_ERROR)
return (S_ERROR);
+ ifl->ifl_isdesc[ndx]->is_flags |=
+ FLG_IS_EHFRAME;
}
break;
#endif
default:
do_default:
- if (ident != ld_targ.t_id.id_null)
- ident = ld_targ.t_id.id_user;
- if (process_section(name, ifl, shdr, scn,
- ndx, ident, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ((ident == ld_targ.t_id.id_null) ?
+ ident : ld_targ.t_id.id_user), ofl) ==
+ S_ERROR)
return (S_ERROR);
break;
}
@@ -1935,9 +2014,7 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl)
* objects.
*/
if (osp && (ld_targ.t_m.m_mach == EM_AMD64) &&
- (ld_targ.t_uw.uw_append_unwind != NULL) &&
- ((*ld_targ.t_uw.uw_append_unwind)(osp, ofl) ==
- S_ERROR))
+ (ld_unwind_register(osp, ofl) == S_ERROR))
return (S_ERROR);
#endif
}
diff --git a/usr/src/cmd/sgs/libld/common/globals.c b/usr/src/cmd/sgs/libld/common/globals.c
index 51e81ad867..b1dd5ed72e 100644
--- a/usr/src/cmd/sgs/libld/common/globals.c
+++ b/usr/src/cmd/sgs/libld/common/globals.c
@@ -90,7 +90,7 @@ ldynsym_symtype[] = {
1, /* STT_FILE */
0, /* STT_COMMON */
0, /* STT_TLS */
- 0, /* 7 */
+ 0, /* STT_IFUNC */
0, /* 8 */
0, /* 9 */
0, /* 10 */
@@ -100,7 +100,7 @@ ldynsym_symtype[] = {
0, /* 14 */
0, /* 15 */
};
-#if STT_NUM != (STT_TLS + 1)
+#if STT_NUM != (STT_IFUNC + 1)
#error "STT_NUM has grown. Update ldynsym_symtype[]."
#endif
@@ -117,7 +117,7 @@ dynsymsort_symtype[] = {
0, /* STT_FILE */
1, /* STT_COMMON */
0, /* STT_TLS */
- 0, /* 7 */
+ 0, /* STT_IFUNC */
0, /* 8 */
0, /* 9 */
0, /* 10 */
@@ -127,6 +127,6 @@ dynsymsort_symtype[] = {
0, /* 14 */
0, /* 15 */
};
-#if STT_NUM != (STT_TLS + 1)
+#if STT_NUM != (STT_IFUNC + 1)
#error "STT_NUM has grown. Update dynsymsort_symtype[]."
#endif
diff --git a/usr/src/cmd/sgs/libld/common/ldmain.c b/usr/src/cmd/sgs/libld/common/ldmain.c
index 0f35378b11..e4f8fb731f 100644
--- a/usr/src/cmd/sgs/libld/common/ldmain.c
+++ b/usr/src/cmd/sgs/libld/common/ldmain.c
@@ -348,14 +348,11 @@ ld_main(int argc, char **argv, Half mach)
if (ld_reloc_process(ofl) == S_ERROR)
return (ld_exit(ofl));
-#if defined(_ELF64)
/*
- * Fill in contents for Unwind Header
+ * Fill in contents for unwind header (.eh_frame_hdr)
*/
- if ((ld_targ.t_uw.uw_populate_unwindhdr != NULL) &&
- ((*ld_targ.t_uw.uw_populate_unwindhdr)(ofl) == S_ERROR))
+ if (ld_unwind_populate_hdr(ofl) == S_ERROR)
return (ld_exit(ofl));
-#endif
/*
* Finally create the files elf checksum.
diff --git a/usr/src/cmd/sgs/libld/common/machrel.amd.c b/usr/src/cmd/sgs/libld/common/machrel.amd.c
index 151c29f9d3..a654c30c96 100644
--- a/usr/src/cmd/sgs/libld/common/machrel.amd.c
+++ b/usr/src/cmd/sgs/libld/common/machrel.amd.c
@@ -36,7 +36,6 @@
#include <i386/machdep_x86.h>
#include "msg.h"
#include "_libld.h"
-#include "unwind.amd.h"
/* Forward declarations */
@@ -1595,6 +1594,9 @@ ld_targ_init_x86(void)
M_PLT_RESERVSZ, /* m_plt_reservsz */
M_PLT_SHF_FLAGS, /* m_plt_shf_flags */
+ /* Section type of .eh_frame/.eh_frame_hdr sections */
+ SHT_AMD64_UNWIND, /* m_sht_unwind */
+
M_DT_REGISTER, /* m_dt_register */
},
{ /* Target_machid */
@@ -1626,6 +1628,7 @@ ld_targ_init_x86(void)
M_ID_TLSBSS, /* id_tlsbss */
M_ID_UNKNOWN, /* id_unknown */
M_ID_UNWIND, /* id_unwind */
+ M_ID_UNWINDHDR, /* id_unwindhdr */
M_ID_USER, /* id_user */
M_ID_VERSION, /* id_version */
},
@@ -1662,11 +1665,6 @@ ld_targ_init_x86(void)
NULL, /* ms_is_regsym */
NULL, /* ms_reg_find */
NULL /* ms_reg_enter */
- },
- { /* Target_unwind */
- make_amd64_unwindhdr, /* uw_make_unwindhdr */
- populate_amd64_unwindhdr, /* uw_populate_unwindhdr */
- append_amd64_unwind, /* uw_append_unwind */
}
};
diff --git a/usr/src/cmd/sgs/libld/common/machrel.intel.c b/usr/src/cmd/sgs/libld/common/machrel.intel.c
index 9de8c80fca..65f7c35c86 100644
--- a/usr/src/cmd/sgs/libld/common/machrel.intel.c
+++ b/usr/src/cmd/sgs/libld/common/machrel.intel.c
@@ -1670,6 +1670,9 @@ ld_targ_init_x86(void)
M_PLT_RESERVSZ, /* m_plt_reservsz */
M_PLT_SHF_FLAGS, /* m_plt_shf_flags */
+ /* Section type of .eh_frame/.eh_frame_hdr sections */
+ SHT_PROGBITS, /* m_sht_unwind */
+
M_DT_REGISTER, /* m_dt_register */
},
{ /* Target_machid */
@@ -1701,6 +1704,7 @@ ld_targ_init_x86(void)
M_ID_TLSBSS, /* id_tlsbss */
M_ID_UNKNOWN, /* id_unknown */
M_ID_UNWIND, /* id_unwind */
+ M_ID_UNWINDHDR, /* id_unwindhdr */
M_ID_USER, /* id_user */
M_ID_VERSION, /* id_version */
},
@@ -1737,11 +1741,6 @@ ld_targ_init_x86(void)
NULL, /* ms_is_regsym */
NULL, /* ms_reg_find */
NULL /* ms_reg_enter */
- },
- { /* Target_unwind */
- NULL, /* uw_make_unwindhdr */
- NULL, /* uw_populate_unwindhdr */
- NULL, /* uw_append_unwind */
}
};
diff --git a/usr/src/cmd/sgs/libld/common/machrel.sparc.c b/usr/src/cmd/sgs/libld/common/machrel.sparc.c
index 0d2774af8d..6f83983425 100644
--- a/usr/src/cmd/sgs/libld/common/machrel.sparc.c
+++ b/usr/src/cmd/sgs/libld/common/machrel.sparc.c
@@ -2247,6 +2247,9 @@ ld_targ_init_sparc(void)
M_PLT_RESERVSZ, /* m_plt_reservsz */
M_PLT_SHF_FLAGS, /* m_plt_shf_flags */
+ /* Section type of .eh_frame/.eh_frame_hdr sections */
+ SHT_PROGBITS, /* m_sht_unwind */
+
M_DT_REGISTER, /* m_dt_register */
},
{ /* Target_machid */
@@ -2277,7 +2280,8 @@ ld_targ_init_sparc(void)
M_ID_TLS, /* id_tls */
M_ID_TLSBSS, /* id_tlsbss */
M_ID_UNKNOWN, /* id_unknown */
- M_ID_UNKNOWN, /* id_unwind (unused) */
+ M_ID_UNWIND, /* id_unwind */
+ M_ID_UNWINDHDR, /* id_unwindhdr */
M_ID_USER, /* id_user */
M_ID_VERSION, /* id_version */
},
@@ -2314,11 +2318,6 @@ ld_targ_init_sparc(void)
ld_is_regsym_sparc, /* ms_is_regsym */
ld_reg_find_sparc, /* ms_reg_find */
ld_reg_enter_sparc /* ms_reg_enter */
- },
- { /* Target_unwind */
- NULL, /* uw_make_unwindhdr */
- NULL, /* uw_populate_unwindhdr */
- NULL, /* uw_append_unwind */
}
};
diff --git a/usr/src/cmd/sgs/libld/common/outfile.c b/usr/src/cmd/sgs/libld/common/outfile.c
index d3d735f3fa..6b52f0febc 100644
--- a/usr/src/cmd/sgs/libld/common/outfile.c
+++ b/usr/src/cmd/sgs/libld/common/outfile.c
@@ -456,12 +456,9 @@ ld_create_outfile(Ofl_desc *ofl)
} else if (ptype == PT_TLS) {
if (flags & FLG_OF_TLSPHDR)
nseg++;
-#if defined(_ELF64)
- } else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
- (ptype == PT_SUNW_UNWIND)) {
+ } else if (ptype == PT_SUNW_UNWIND) {
if (ofl->ofl_unwindhdr)
nseg++;
-#endif
} else if (ptype == PT_SUNWDTRACE) {
if (ofl->ofl_dtracesym)
nseg++;
diff --git a/usr/src/cmd/sgs/libld/common/sections.c b/usr/src/cmd/sgs/libld/common/sections.c
index a4cd691c3b..a8119ecb61 100644
--- a/usr/src/cmd/sgs/libld/common/sections.c
+++ b/usr/src/cmd/sgs/libld/common/sections.c
@@ -2771,11 +2771,8 @@ ld_make_sections(Ofl_desc *ofl)
return (S_ERROR);
if (make_dynsym(ofl) == S_ERROR)
return (S_ERROR);
-#if defined(_ELF64)
- if ((ld_targ.t_uw.uw_make_unwindhdr != NULL) &&
- ((*ld_targ.t_uw.uw_make_unwindhdr)(ofl) == S_ERROR))
+ if (ld_unwind_make_hdr(ofl) == S_ERROR)
return (S_ERROR);
-#endif
if (make_dynsort(ofl) == S_ERROR)
return (S_ERROR);
}
diff --git a/usr/src/cmd/sgs/libld/common/unwind.amd.h b/usr/src/cmd/sgs/libld/common/unwind.amd.h
deleted file mode 100644
index eeebb52182..0000000000
--- a/usr/src/cmd/sgs/libld/common/unwind.amd.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * amd64 unwind functionality
- */
-
-#ifndef _UNWIND_DOT_AMD_DOT_H
-#define _UNWIND_DOT_AMD_DOT_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern uintptr_t append_amd64_unwind(Os_desc *, Ofl_desc *);
-extern uintptr_t make_amd64_unwindhdr(Ofl_desc *);
-extern uintptr_t populate_amd64_unwindhdr(Ofl_desc *);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _UNWIND_DOT_AMD_DOT_H */
diff --git a/usr/src/cmd/sgs/libld/common/unwind.amd.c b/usr/src/cmd/sgs/libld/common/unwind.c
index 14bcd12245..b2263e1e55 100644
--- a/usr/src/cmd/sgs/libld/common/unwind.amd.c
+++ b/usr/src/cmd/sgs/libld/common/unwind.c
@@ -24,18 +24,14 @@
* Use is subject to license terms.
*/
-#define ELF_TARGET_AMD64
-
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sgs.h>
#include <debug.h>
-#include <i386/machdep_x86.h>
#include <_libld.h>
#include <dwarf.h>
#include <stdlib.h>
-#include "unwind.amd.h"
/*
* A EH_FRAME_HDR consists of the following:
@@ -112,16 +108,16 @@
* =================
*
* The call frame information needed for unwinding the stack is output in
- * an ELF section(s) of type SHT_AMD64_UNWIND. In the simplest case there
- * will be one such section per object file and it will be named
- * ".eh_frame". An .eh_frame section consists of one or more
+ * an ELF section(s) of type SHT_AMD64_UNWIND (amd64) or SHT_PROGBITS (other).
+ * In the simplest case there will be one such section per object file and it
+ * will be named ".eh_frame". An .eh_frame section consists of one or more
* subsections. Each subsection contains a CIE (Common Information Entry)
* followed by varying number of FDEs (Frame Descriptor Entry). A FDE
* corresponds to an explicit or compiler generated function in a
* compilation unit, all FDEs can access the CIE that begins their
* subsection for data.
*
- * If an object file contains C++ template instantiations there shall be
+ * If an object file contains C++ template instantiations, there shall be
* a separate CIE immediately preceding each FDE corresponding to an
* instantiation.
*
@@ -287,10 +283,28 @@
+static uint_t
+extract_uint(const uchar_t *data, uint64_t *ndx, int do_swap)
+{
+ uint_t r;
+ uchar_t *p = (uchar_t *)&r;
+
+ data += *ndx;
+ if (do_swap)
+ UL_ASSIGN_BSWAP_WORD(p, data);
+ else
+ UL_ASSIGN_WORD(p, data);
+
+ (*ndx) += 4;
+ return (r);
+}
+
/*
- * The job of this function is to determine how much space
- * will be required for the final table. We'll build
- * it later.
+ * Create an unwind header (.eh_frame_hdr) output section.
+ * The section is created and space reserved, but the data
+ * is not copied into place. That is done by a later call
+ * to ld_unwind_populate(), after active relocations have been
+ * processed.
*
* When GNU linkonce processing is in effect, we can end up in a situation
* where the FDEs related to discarded sections remain in the eh_frame
@@ -303,21 +317,22 @@
* where all FDEs are valid.
*/
uintptr_t
-make_amd64_unwindhdr(Ofl_desc *ofl)
+ld_unwind_make_hdr(Ofl_desc *ofl)
{
+ int bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
Shdr *shdr;
Elf_Data *elfdata;
Is_desc *isp;
size_t size;
Xword fde_cnt;
- Listnode *lnp;
+ Aliste idx;
Os_desc *osp;
/*
* we only build a unwind header if we have
* some unwind information in the file.
*/
- if (ofl->ofl_unwind.head == NULL)
+ if (aplist_nitems(ofl->ofl_unwind) == 0)
return (1);
/*
@@ -326,7 +341,7 @@ make_amd64_unwindhdr(Ofl_desc *ofl)
if ((elfdata = libld_calloc(sizeof (Elf_Data), 1)) == 0)
return (S_ERROR);
elfdata->d_type = ELF_T_BYTE;
- elfdata->d_align = M_WORD_ALIGN;
+ elfdata->d_align = ld_targ.t_m.m_word_align;
elfdata->d_version = ofl->ofl_dehdr->e_version;
/*
@@ -334,9 +349,9 @@ make_amd64_unwindhdr(Ofl_desc *ofl)
*/
if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0)
return (S_ERROR);
- shdr->sh_type = SHT_AMD64_UNWIND;
+ shdr->sh_type = ld_targ.t_m.m_sht_unwind;
shdr->sh_flags = SHF_ALLOC;
- shdr->sh_addralign = M_WORD_ALIGN;
+ shdr->sh_addralign = ld_targ.t_m.m_word_align;
shdr->sh_entsize = 0;
/*
@@ -349,7 +364,7 @@ make_amd64_unwindhdr(Ofl_desc *ofl)
isp->is_indata = elfdata;
if ((ofl->ofl_unwindhdr = ld_place_section(ofl, isp,
- M_ID_UNWINDHDR, 0)) == (Os_desc *)S_ERROR)
+ ld_targ.t_id.id_unwindhdr, 0)) == (Os_desc *)S_ERROR)
return (S_ERROR);
/*
@@ -358,7 +373,7 @@ make_amd64_unwindhdr(Ofl_desc *ofl)
* in the binary search table.
*/
fde_cnt = 0;
- for (LIST_TRAVERSE(&ofl->ofl_unwind, lnp, osp)) {
+ for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, osp)) {
Listnode *_lnp;
for (LIST_TRAVERSE(&osp->os_isdescs, _lnp, isp)) {
@@ -370,7 +385,7 @@ make_amd64_unwindhdr(Ofl_desc *ofl)
while (off < size) {
uint_t length, id;
- uint64_t ndx;
+ uint64_t ndx = 0;
/*
* Extract length in lsb format. A zero length
@@ -378,15 +393,14 @@ make_amd64_unwindhdr(Ofl_desc *ofl)
* that processing for unwind information is
* complete.
*/
- if ((length = LSB32EXTRACT(data + off)) == 0)
+ length = extract_uint(data + off, &ndx, bswap);
+ if (length == 0)
break;
/*
* Extract CIE id in lsb format.
*/
- ndx = 4;
- id = LSB32EXTRACT(data + off + ndx);
- ndx += 4;
+ id = extract_uint(data + off, &ndx, bswap);
/*
* A CIE record has a id of '0', otherwise
@@ -470,12 +484,12 @@ bintabcompare(const void *p1, const void *p2)
}
uintptr_t
-populate_amd64_unwindhdr(Ofl_desc *ofl)
+ld_unwind_populate_hdr(Ofl_desc *ofl)
{
uchar_t *hdrdata;
uint_t *binarytable;
uint_t hdroff;
- Listnode *lnp;
+ Aliste idx;
Addr hdraddr;
Os_desc *hdrosp;
Os_desc *osp;
@@ -524,7 +538,7 @@ populate_amd64_unwindhdr(Ofl_desc *ofl)
first_unwind = 0;
fde_count = 0;
- for (LIST_TRAVERSE(&ofl->ofl_unwind, lnp, osp)) {
+ for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, osp)) {
uchar_t *data;
size_t size;
uint64_t off = 0;
@@ -544,22 +558,21 @@ populate_amd64_unwindhdr(Ofl_desc *ofl)
while (off < size) {
uint_t length, id;
- uint64_t ndx;
+ uint64_t ndx = 0;
/*
* Extract length in lsb format. A zero length
* indicates that this CIE is a terminator and that
* processing of unwind information is complete.
*/
- if ((length = LSB32EXTRACT(data + off)) == 0)
+ length = extract_uint(data + off, &ndx, bswap);
+ if (length == 0)
goto done;
/*
* Extract CIE id in lsb format.
*/
- ndx = 4;
- id = LSB32EXTRACT(data + off + ndx);
- ndx += 4;
+ id = extract_uint(data + off, &ndx, bswap);
/*
* A CIE record has a id of '0'; otherwise
@@ -627,7 +640,7 @@ populate_amd64_unwindhdr(Ofl_desc *ofl)
&data[off + ndx],
&ndx, ciePflag,
ofl->ofl_dehdr->e_ident,
- shdr->sh_addr + off + ndx);
+ shdr->sh_addr, off + ndx);
break;
case 'R':
/* code encoding */
@@ -648,7 +661,7 @@ populate_amd64_unwindhdr(Ofl_desc *ofl)
initloc = dwarf_ehe_extract(&data[off],
&ndx, cieRflag, ofl->ofl_dehdr->e_ident,
- shdr->sh_addr + off + ndx);
+ shdr->sh_addr, off + ndx);
/*
* Ignore FDEs with initloc set to 0.
@@ -686,7 +699,7 @@ populate_amd64_unwindhdr(Ofl_desc *ofl)
done:
/*
- * Do a quick sort on the binary table. If this is a cross
+ * Do a quicksort on the binary table. If this is a cross
* link from a system with the opposite byte order, xlate
* the resulting values into LSB order.
*/
@@ -710,7 +723,7 @@ done:
/* LINTED */
uint_ptr = (uint_t *)(&hdrdata[hdroff]);
*uint_ptr = first_unwind->os_shdr->sh_addr -
- hdrosp->os_shdr->sh_addr + hdroff;
+ (hdrosp->os_shdr->sh_addr + hdroff);
if (bswap)
*uint_ptr = ld_bswap_Word(*uint_ptr);
@@ -724,7 +737,7 @@ done:
/*
* If relaxed relocations are active, then there is a chance
* that we didn't use all the space reserved for this section.
- * For details, see the note at head of make_amd64_unwindhdr() above.
+ * For details, see the note at head of ld_unwind_make_hdr() above.
*
* Find the PT_SUNW_UNWIND program header, and change the size values
* to the size of the subset of the section that was actually used.
@@ -745,23 +758,34 @@ done:
return (1);
}
+/*
+ * Append an .eh_frame section to our output list if not already present.
+ *
+ * Usually, there is a single .eh_frame output section. However, there can
+ * be more if there are incompatible section flags on incoming sections.
+ * If this does happen, the frame_ptr field of the eh_frame_hdr section
+ * will point at the base of the first output section, and the other
+ * sections will not be accessible via frame_ptr. However, the .eh_frame_hdr
+ * will be able to access all the data in the different .eh_frame sections,
+ * because the entries in sorted table are all encoded as DW_EH_PE_datarel.
+ */
uintptr_t
-append_amd64_unwind(Os_desc *osp, Ofl_desc * ofl)
+ld_unwind_register(Os_desc *osp, Ofl_desc * ofl)
{
- Listnode *lnp;
- Os_desc *_osp;
+ Aliste idx;
+ Os_desc *_osp;
/*
* Check to see if this output section is already
* on the list.
*/
- for (LIST_TRAVERSE(&ofl->ofl_unwind, lnp, _osp))
+ for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, _osp))
if (osp == _osp)
return (1);
/*
* Append output section to unwind list
*/
- if (list_appendc(&ofl->ofl_unwind, osp) == 0)
+ if (aplist_append(&ofl->ofl_unwind, osp, AL_CNT_UNWIND) == NULL)
return (S_ERROR);
return (1);
}
diff --git a/usr/src/cmd/sgs/libld/common/update.c b/usr/src/cmd/sgs/libld/common/update.c
index 63dda77127..7ee234fbf6 100644
--- a/usr/src/cmd/sgs/libld/common/update.c
+++ b/usr/src/cmd/sgs/libld/common/update.c
@@ -3383,17 +3383,15 @@ ld_update_outfile(Ofl_desc *ofl)
}
/*
- * As the AMD unwind program header occurs after the loadable
- * headers in the segment descriptor table, all the address
- * information for the .eh_frame output section will have been
- * figured out by now.
+ * As the unwind (.eh_frame_hdr) program header occurs after
+ * the loadable headers in the segment descriptor table, all
+ * the address information for the .eh_frame output section
+ * will have been figured out by now.
*/
-#if defined(_ELF64)
- if ((ld_targ.t_m.m_mach == EM_AMD64) &&
- (phdr->p_type == PT_SUNW_UNWIND)) {
+ if (phdr->p_type == PT_SUNW_UNWIND) {
Shdr *shdr;
- if (ofl->ofl_unwindhdr == 0)
+ if (ofl->ofl_unwindhdr == NULL)
continue;
shdr = ofl->ofl_unwindhdr->os_shdr;
@@ -3408,7 +3406,7 @@ ld_update_outfile(Ofl_desc *ofl)
ofl->ofl_phdr[phdrndx++] = *phdr;
continue;
}
-#endif
+
/*
* As the TLS program header occurs after the loadable
* headers in the segment descriptor table, all the address
diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README
index 1fe0253dcd..82fc70dcf6 100644
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README
@@ -1444,3 +1444,4 @@ Bugid Risk Synopsis
6807050 GNU linkonce sections can create duplicate and incompatible
eh_frame FDE entries
6807864 ld.so.1 is susceptible to a fatal dlsym()/setlocale() race
+6813909 generalize eh_frame support to non-amd64 platforms
diff --git a/usr/src/cmd/sgs/rtld/common/elf.c b/usr/src/cmd/sgs/rtld/common/elf.c
index 314e0625ff..1777894109 100644
--- a/usr/src/cmd/sgs/rtld/common/elf.c
+++ b/usr/src/cmd/sgs/rtld/common/elf.c
@@ -1673,6 +1673,7 @@ elf_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize,
cap = (Cap *)((uintptr_t)phdr->p_vaddr + base);
break;
case PT_SUNW_UNWIND:
+ case PT_SUNW_EH_FRAME:
uphdr = phdr;
break;
default:
diff --git a/usr/src/cmd/sgs/tools/common/leb128.c b/usr/src/cmd/sgs/tools/common/leb128.c
index a36ee7a249..1183e6f854 100644
--- a/usr/src/cmd/sgs/tools/common/leb128.c
+++ b/usr/src/cmd/sgs/tools/common/leb128.c
@@ -20,12 +20,10 @@
*/
/*
- * Copyright 2006 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 <stdio.h>
#include <dwarf.h>
#include <sys/types.h>
@@ -183,9 +181,21 @@ sleb_extract(unsigned char *data, uint64_t *dotp)
return (res);
}
+/*
+ * Extract a DWARF encoded datum
+ *
+ * entry:
+ * data - Base of data buffer containing encoded bytes
+ * dotp - Address of variable containing index within data
+ * at which the desired datum starts.
+ * ehe_flags - DWARF encoding
+ * eident - ELF header e_ident[] array for object being processed
+ * sh_base - Base address of ELF section containing desired datum
+ * sh_offset - Offset relative to sh_base of desired datum.
+ */
uint64_t
dwarf_ehe_extract(unsigned char *data, uint64_t *dotp, uint_t ehe_flags,
- unsigned char *eident, uint64_t pcaddr)
+ unsigned char *eident, uint64_t sh_base, uint64_t sh_offset)
{
uint64_t dot = *dotp;
uint_t lsb;
@@ -269,11 +279,18 @@ dwarf_ehe_extract(unsigned char *data, uint64_t *dotp, uint_t ehe_flags,
}
/*
- * If pcrel and we have a value (ie: we've been
- * relocated), then adjust the value.
+ * If value is relative to a base address, adjust it
*/
- if (result && (ehe_flags & DW_EH_PE_pcrel)) {
- result = pcaddr + result;
+ if (result) {
+ switch (ehe_flags & 0xf0) {
+ case DW_EH_PE_pcrel:
+ result += sh_base + sh_offset;
+ break;
+
+ case DW_EH_PE_datarel:
+ result += sh_base;
+ break;
+ }
}
*dotp = dot;
return (result);
diff --git a/usr/src/lib/libdtrace/common/dt_module.c b/usr/src/lib/libdtrace/common/dt_module.c
index 25197031ce..51a1bdd0d1 100644
--- a/usr/src/lib/libdtrace/common/dt_module.c
+++ b/usr/src/lib/libdtrace/common/dt_module.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 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 <sys/types.h>
#include <sys/modctl.h>
#include <sys/kobj.h>
@@ -66,6 +64,10 @@ dt_module_symhash_insert(dt_module_t *dmp, const char *name, uint_t id)
static uint_t
dt_module_syminit32(dt_module_t *dmp)
{
+#if STT_NUM != (STT_IFUNC + 1)
+#error "STT_NUM has grown. update dt_module_syminit32()"
+#endif
+
const Elf32_Sym *sym = dmp->dm_symtab.cts_data;
const char *base = dmp->dm_strtab.cts_data;
size_t ss_size = dmp->dm_strtab.cts_size;
@@ -76,7 +78,7 @@ dt_module_syminit32(dt_module_t *dmp)
const char *name = base + sym->st_name;
uchar_t type = ELF32_ST_TYPE(sym->st_info);
- if (type >= STT_NUM || type == STT_SECTION)
+ if (type >= STT_IFUNC || type == STT_SECTION)
continue; /* skip sections and unknown types */
if (sym->st_name == 0 || sym->st_name >= ss_size)
@@ -95,6 +97,10 @@ dt_module_syminit32(dt_module_t *dmp)
static uint_t
dt_module_syminit64(dt_module_t *dmp)
{
+#if STT_NUM != (STT_IFUNC + 1)
+#error "STT_NUM has grown. update dt_module_syminit64()"
+#endif
+
const Elf64_Sym *sym = dmp->dm_symtab.cts_data;
const char *base = dmp->dm_strtab.cts_data;
size_t ss_size = dmp->dm_strtab.cts_size;
@@ -105,7 +111,7 @@ dt_module_syminit64(dt_module_t *dmp)
const char *name = base + sym->st_name;
uchar_t type = ELF64_ST_TYPE(sym->st_info);
- if (type >= STT_NUM || type == STT_SECTION)
+ if (type >= STT_IFUNC || type == STT_SECTION)
continue; /* skip sections and unknown types */
if (sym->st_name == 0 || sym->st_name >= ss_size)
diff --git a/usr/src/lib/libproc/common/Psymtab.c b/usr/src/lib/libproc/common/Psymtab.c
index 0a5c3dedd1..c279bdcd6a 100644
--- a/usr/src/lib/libproc/common/Psymtab.c
+++ b/usr/src/lib/libproc/common/Psymtab.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -2753,6 +2753,10 @@ static int
Psymbol_iter_com(struct ps_prochandle *P, Lmid_t lmid, const char *object_name,
int which, int mask, pr_order_t order, proc_xsym_f *func, void *cd)
{
+#if STT_NUM != (STT_IFUNC + 1)
+#error "STT_NUM has grown. update Psymbol_iter_com()"
+#endif
+
GElf_Sym sym;
GElf_Shdr shdr;
map_info_t *mptr;
@@ -2833,11 +2837,11 @@ Psymbol_iter_com(struct ps_prochandle *P, Lmid_t lmid, const char *object_name,
* In case you haven't already guessed, this relies on
* the bitmask used in <libproc.h> for encoding symbol
* type and binding matching the order of STB and STT
- * constants in <sys/elf.h>. ELF can't change without
- * breaking binary compatibility, so I think this is
+ * constants in <sys/elf.h>. Changes to ELF must
+ * maintain binary compatibility, so I think this is
* reasonably fair game.
*/
- if (s_bind < STB_NUM && s_type < STT_NUM) {
+ if (s_bind < STB_NUM && s_type < STT_IFUNC) {
type = (1 << (s_type + 8)) | (1 << s_bind);
if ((type & ~mask) != 0)
continue;
diff --git a/usr/src/uts/common/sys/elf.h b/usr/src/uts/common/sys/elf.h
index 903af2e47c..bac5afceb4 100644
--- a/usr/src/uts/common/sys/elf.h
+++ b/usr/src/uts/common/sys/elf.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -322,13 +322,22 @@ typedef struct {
#define PT_LOOS 0x60000000 /* OS specific range */
/*
- * Note: The amd64 psABI defines that the UNWIND program header
- * should reside in the OS specific range of the program
- * headers.
+ * PT_SUNW_UNWIND and PT_SUNW_EH_FRAME perform the same function,
+ * providing access to the .eh_frame_hdr section of the object.
+ * PT_SUNW_UNWIND is the original value, while PT_SUNW_EH_FRAME is
+ * required by the amd64 psABI. The Solaris link-editor (ld) tags output
+ * objects with PT_SUNW_UNWIND, but the Solaris runtime linker (ld.so.1)
+ * will accept and use either value.
*/
-#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */
-#define PT_GNU_EH_FRAME PT_SUNW_UNWIND
+#define PT_SUNW_UNWIND 0x6464e550
+#define PT_SUNW_EH_FRAME 0x6474e550
+#define PT_GNU_EH_FRAME PT_SUNW_EH_FRAME
+/*
+ * Linux specific program headers not currently used by Solaris
+ */
+#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
+#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
#define PT_LOSUNW 0x6ffffffa
#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment (unused) */
@@ -421,15 +430,24 @@ typedef struct {
#define SHT_SUNW_COMDAT 0x6ffffffb
#define SHT_SUNW_syminfo 0x6ffffffc
#define SHT_SUNW_verdef 0x6ffffffd
+#define SHT_GNU_verdef SHT_SUNW_verdef
#define SHT_SUNW_verneed 0x6ffffffe
+#define SHT_GNU_verneed SHT_SUNW_verneed
#define SHT_SUNW_versym 0x6fffffff
+#define SHT_GNU_versym SHT_SUNW_versym
#define SHT_HISUNW 0x6fffffff
#define SHT_HIOS 0x6fffffff
-/* GNU/Linux ABI specific values */
-#define SHT_GNU_verdef 0x6ffffffd
-#define SHT_GNU_verneed 0x6ffffffe
-#define SHT_GNU_versym 0x6fffffff
+/*
+ * GNU/Linux OSABI specific values with different meanings than under Solaris.
+ * Due to the overlap in assigned values with the Solaris OSABI, correct
+ * interpretation of these values requires knowledge of the OSABI used by
+ * the object.
+ */
+#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes */
+#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table */
+#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
+#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content */
#define SHT_LOPROC 0x70000000 /* processor specific range */
#define SHT_HIPROC 0x7fffffff
@@ -520,15 +538,17 @@ typedef struct {
#define STB_LOPROC 13 /* processor specific range */
#define STB_HIPROC 15
-#define STT_NOTYPE 0 /* TYPE */
-#define STT_OBJECT 1
-#define STT_FUNC 2
-#define STT_SECTION 3
-#define STT_FILE 4
-#define STT_COMMON 5
-#define STT_TLS 6
-#define STT_NUM 7
-
+#define STT_NOTYPE 0 /* symbol type is unspecified */
+#define STT_OBJECT 1 /* data object */
+#define STT_FUNC 2 /* code object */
+#define STT_SECTION 3 /* symbol identifies an ELF section */
+#define STT_FILE 4 /* symbol's name is file name */
+#define STT_COMMON 5 /* common data object */
+#define STT_TLS 6 /* thread-local data object */
+#define STT_IFUNC 7 /* indirect code object (unused) */
+#define STT_NUM 8 /* # defined types in generic range */
+#define STT_LOOS 10 /* OS specific range */
+#define STT_HIOS 12
#define STT_LOPROC 13 /* processor specific range */
#define STT_HIPROC 15
diff --git a/usr/src/uts/common/sys/link.h b/usr/src/uts/common/sys/link.h
index 597bc24baa..9d5401da2f 100644
--- a/usr/src/uts/common/sys/link.h
+++ b/usr/src/uts/common/sys/link.h
@@ -23,7 +23,7 @@
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -172,6 +172,10 @@ typedef struct {
* Dyn.d_un.d_val field of the Elf*_Dyn structure.
*/
#define DT_VALRNGLO 0x6ffffd00
+
+#define DT_GNU_PRELINKED 0x6ffffdf5 /* prelinking timestamp (unused) */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* size of conflict section (unused) */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* size of library list (unused) */
#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */
#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */
#define DT_MOVEENT 0x6ffffdfa /* move table entry size */
@@ -192,6 +196,13 @@ typedef struct {
* built, these entries will need to be adjusted.
*/
#define DT_ADDRRNGLO 0x6ffffe00
+
+#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table (unused) */
+#define DT_TLSDESC_PLT 0x6ffffef6 /* GNU (unused) */
+#define DT_TLSDESC_GOT 0x6ffffef7 /* GNU (unused) */
+#define DT_GNU_CONFLICT 0x6ffffef8 /* start of conflict section (unused) */
+#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list (unused) */
+
#define DT_CONFIG 0x6ffffefa /* configuration information */
#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */
#define DT_AUDIT 0x6ffffefc /* object auditing */