elfdump.c revision 8521e5e6630b57b9883c3979cd5589e53f09e044
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or http://www.opensolaris.org/os/licensing.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
f645cd15cd9c30aa3b568ad85bd8a63996112c4bMilan Jurik/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#pragma ident "%Z%%M% %I% %E% SMI"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Dump an elf file.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <machdep.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/elf_386.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/elf_amd64.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/elf_SPARC.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <dwarf.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <unistd.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <errno.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <strings.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <debug.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <conv.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <msg.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <_elfdump.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * VERSYM_STATE is used to maintain information about the VERSYM section
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * in the object being analyzed. It is filled in by versions(), and used
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * by init_symtbl_state() when displaying symbol information.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Note that the value of the gnu field is a hueristic guess,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * based on the section names.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortetypedef struct {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cache *cache; /* Pointer to cache entry for VERSYM */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Versym *data; /* Pointer to versym array */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int num_verdef; /* # of versions defined in object */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int gnu; /* True if we think obj produced by GNU tools */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte} VERSYM_STATE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SYMTBL_STATE is used to maintain information about a single symbol
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * table section, for use by the routines that display symbol information.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortetypedef struct {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *file; /* Name of file */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Ehdr *ehdr; /* ELF header for file */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cache *cache; /* Cache of all section headers */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word shnum; /* # of sections in cache */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cache *seccache; /* Cache of symbol table section hdr */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word secndx; /* Index of symbol table section hdr */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *secname; /* Name of section */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint_t flags; /* Command line option flags */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct { /* Extended section index data */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int checked; /* TRUE if already checked for shxndx */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word *data; /* NULL, or extended section index */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* used for symbol table entries */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint_t n; /* # items in shxndx.data */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } shxndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte VERSYM_STATE *versym; /* NULL, or associated VERSYM section */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Sym *sym; /* Array of symbols */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Word symn; /* # of symbols */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik} SYMTBL_STATE;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Focal point for verifying symbol names.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic const char *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestring(Cache *refsec, Word ndx, Cache *strsec, const char *file, Word name)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte static Cache *osec = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte static int nostr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *strs;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word strn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (strsec->c_data == NULL)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte strs = (char *)strsec->c_data->d_buf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte strn = strsec->c_data->d_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Only print a diagnostic regarding an empty string table once per
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * input section being processed.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (osec != refsec) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte osec = refsec;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte nostr = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Is the string table offset within range of the available strings?
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (name >= strn) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Do we have a empty string table?
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (strs == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (nostr == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, strsec->c_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte nostr++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSTOFF),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, refsec->c_name, EC_WORD(ndx), strsec->c_name,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_WORD(name), EC_WORD(strn - 1));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Return the empty string so that the calling function can
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * continue it's output diagnostics.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (MSG_INTL(MSG_STR_UNKNOWN));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (strs + name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * Relocations can reference section symbols and standard symbols. If the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * former, establish the section name.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic const char *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forterelsymname(Cache *cache, Cache *csec, Cache *strsec, Word symndx, Word symnum,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Word relndx, Sym *syms, char *secstr, size_t secsz, const char *file,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint_t flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Sym *sym;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (symndx >= symnum) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_RELBADSYMNDX),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, EC_WORD(symndx), EC_WORD(relndx));
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik return (MSG_INTL(MSG_STR_UNKNOWN));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik sym = (Sym *)(syms + symndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the symbol represents a section offset construct an appropriate
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * string.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) && (sym->st_name == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (flags & FLG_LONGNAME)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) snprintf(secstr, secsz,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_STR_L_SECTION),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cache[sym->st_shndx].c_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) snprintf(secstr, secsz,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_STR_SECTION),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik cache[sym->st_shndx].c_name);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik return ((const char *)secstr);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik return (string(csec, symndx, strsec, file, sym->st_name));
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik}
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * Focal point for establishing a string table section. Data such as the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * dynamic information simply points to a string table. Data such as
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * relocations, reference a symbol table, which in turn is associated with a
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * string table.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestringtbl(Cache *cache, int symtab, Word ndx, Word shnum, const char *file,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word *symnum, Cache **symsec, Cache **strsec)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *shdr = cache[ndx].c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (symtab) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Validate the symbol table section.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, cache[ndx].c_name, EC_WORD(shdr->sh_link));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, cache[ndx].c_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Obtain, and verify the symbol table data.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cache[ndx].c_data == NULL) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (cache[ndx].c_data->d_buf == NULL)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, cache[ndx].c_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Establish the string table index.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx = shdr->sh_link;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte shdr = cache[ndx].c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Return symbol table information.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (symnum)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *symnum = (shdr->sh_size / shdr->sh_entsize);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (symsec)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *symsec = &cache[ndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Validate the associated string table section.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, cache[ndx].c_name, EC_WORD(shdr->sh_link));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (strsec)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *strsec = &cache[shdr->sh_link];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Lookup a symbol and set Sym accordingly.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesymlookup(const char *name, Cache *cache, Word shnum, Sym **sym,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cache *symtab, const char *file)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word symn, cnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Sym *syms;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (symtab == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte shdr = symtab->c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine the symbol data and number.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, symtab->c_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (symtab->c_data == NULL)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* LINTED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte symn = (Word)(shdr->sh_size / shdr->sh_entsize);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte syms = (Sym *)symtab->c_data->d_buf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Get the associated string table section.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, symtab->c_name, EC_WORD(shdr->sh_link));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Loop through the symbol table to find a match.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (cnt = 0; cnt < symn; syms++, cnt++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *symname;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte symname = string(symtab, cnt, &cache[shdr->sh_link], file,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte syms->st_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (symname && (strcmp(name, symname) == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *sym = syms;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik return (1);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Print section headers.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesections(const char *file, Cache *cache, Word shnum, Ehdr *ehdr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *name)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size_t seccnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik for (seccnt = 1; seccnt < shnum; seccnt++) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Cache *_cache = &cache[seccnt];
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Shdr *shdr = _cache->c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *secname = _cache->c_name;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Although numerous section header entries can be zero, it's
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * usually a sign of trouble if the type is zero.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (shdr->sh_type == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, secname, EC_WORD(shdr->sh_type));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (name && strcmp(name, secname))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * Identify any sections that are suspicious. A .got section
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * shouldn't exist in a relocatable object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ehdr->e_type == ET_REL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (strncmp(secname, MSG_ORIG(MSG_ELF_GOT),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_ELF_GOT_SIZE) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_GOT_UNEXPECTED), file,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte secname);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_INTL(MSG_ELF_SHDR), EC_WORD(seccnt), secname);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Elf_shdr(0, ehdr->e_machine, shdr);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * A couple of instances of unwind data are printed as tables of 8 data items
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * expressed as 0x?? integers.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik#define UNWINDTBLSZ 10 + (8 * 5) + 1
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteunwindtbl(uint64_t *ndx, uint_t len, uchar_t *data, uint64_t doff,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *msg, const char *pre, size_t plen)
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char buffer[UNWINDTBLSZ];
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik uint_t boff = plen, cnt = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, msg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) strncpy(buffer, pre, UNWINDTBLSZ);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (*ndx < (len + 4)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cnt == 8) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik dbg_print(0, buffer);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik boff = plen;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik cnt = 0;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (void) snprintf(&buffer[boff], UNWINDTBLSZ - boff,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik MSG_ORIG(MSG_UNW_TBLENTRY), data[doff + (*ndx)++]);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik boff += 5;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cnt++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cnt)
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik dbg_print(0, buffer);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Obtain a specified Phdr entry.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurikstatic Phdr *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortegetphdr(Word phnum, Word type, const char *file, Elf *elf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word cnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Phdr *phdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((phdr = elf_getphdr(elf)) == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik for (cnt = 0; cnt < phnum; phdr++, cnt++) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (phdr->p_type == type)
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik return (phdr);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteunwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *name,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *file, Elf *elf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word cnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Phdr *uphdr = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For the moment - UNWIND is only relevant for a AMD64 object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ehdr->e_machine != EM_AMD64)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (phnum)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uphdr = getphdr(phnum, PT_SUNW_UNWIND, file, elf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (cnt = 1; cnt < shnum; cnt++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cache *_cache = &cache[cnt];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *shdr = _cache->c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uchar_t *data;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size_t datasize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t off, ndx, frame_ptr, fde_cnt, tabndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * AMD64 - this is a strmcp() just to find the gcc produced
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * sections. Soon gcc should be setting the section type - and
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * we'll not need this strcmp().
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_type != SHT_AMD64_UNWIND) &&
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik MSG_SCN_FRM_SIZE) != 0) &&
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik MSG_SCN_FRMHDR_SIZE) != 0))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (name && strcmp(name, _cache->c_name))
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (_cache->c_data == NULL)
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte data = (uchar_t *)(_cache->c_data->d_buf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte datasize = _cache->c_data->d_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte off = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Is this a .eh_frame_hdr
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_SCN_FRMHDR_SIZE) == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte vers = data[ndx++];
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik frame_ptr_enc = data[ndx++];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fde_cnt_enc = data[ndx++];
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik table_enc = data[ndx++];
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ehdr->e_ident, shdr->sh_addr + ndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik conv_dwarf_ehe(frame_ptr_enc), EC_XWORD(frame_ptr));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ehdr->e_ident, shdr->sh_addr + ndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte conv_dwarf_ehe(fde_cnt_enc), EC_XWORD(fde_cnt));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_TABENC),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte conv_dwarf_ehe(table_enc));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (tabndx = 0; tabndx < fde_cnt; tabndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_XWORD(dwarf_ehe_extract(data, &ndx,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte table_enc, ehdr->e_ident, shdr->sh_addr)),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_XWORD(dwarf_ehe_extract(data, &ndx,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte table_enc, ehdr->e_ident, shdr->sh_addr)));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Walk the Eh_frame's
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (off < datasize) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint_t cieid, cielength, cieversion,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cieretaddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int cieRflag, cieLflag, ciePflag, cieZflag;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint_t cieaugndx, length, id;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t ciecalign, ciedalign;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char *cieaugstr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * extract length in lsb format
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte length = LSB32EXTRACT(data + off + ndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx += 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * extract CIE id in lsb format
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte id = LSB32EXTRACT(data + off + ndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx += 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * A CIE record has a id of '0', otherwise this is a
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * FDE entry and the 'id' is the CIE pointer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (id == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t persVal;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik cielength = length;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik cieid = id;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cieLflag = ciePflag = cieRflag = cieZflag = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_CIE),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_XWORD(shdr->sh_addr + off));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cielength, cieid);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cieversion = data[off + ndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx += 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cieaugstr = (char *)(&data[off + ndx]);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx += strlen(cieaugstr) + 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cieversion, cieaugstr);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ciecalign = uleb_extract(&data[off], &ndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ciedalign = sleb_extract(&data[off], &ndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cieretaddr = data[off + ndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx += 1;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_XWORD(ciecalign), EC_XWORD(ciedalign),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cieretaddr);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cieaugstr[0])
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_CIEAUXVAL));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (cieaugndx = 0; cieaugstr[cieaugndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cieaugndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint_t val;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (cieaugstr[cieaugndx]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 'z':
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte val = uleb_extract(&data[off],
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &ndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_ORIG(MSG_UNW_CIEAUXSIZE),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte val);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cieZflag = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 'P':
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ciePflag = data[off + ndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx += 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte persVal = dwarf_ehe_extract(
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &data[off],
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik &ndx, ciePflag, ehdr->e_ident,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte shdr->sh_addr + off + ndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_ORIG(MSG_UNW_CIEAUXPERS),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ciePflag,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte conv_dwarf_ehe(ciePflag),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_XWORD(persVal));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 'R':
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte val = data[off + ndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx += 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_ORIG(MSG_UNW_CIEAUXCENC),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte val, conv_dwarf_ehe(val));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cieRflag = val;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 'L':
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte val = data[off + ndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx += 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_ORIG(MSG_UNW_CIEAUXLSDA),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte val, conv_dwarf_ehe(val));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cieLflag = val;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik MSG_ORIG(MSG_UNW_CIEAUXUNEC),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik cieaugstr[cieaugndx]);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cielength + 4) > ndx)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unwindtbl(&ndx, cielength, data, off,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_ORIG(MSG_UNW_CIECFI),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_ORIG(MSG_UNW_CIEPRE),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_UNW_CIEPRE_SIZE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte off += cielength + 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint_t fdelength = length;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int fdecieptr = id;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t fdeinitloc, fdeaddrrange;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_FDE),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_XWORD(shdr->sh_addr + off));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fdelength, fdecieptr);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik fdeinitloc = dwarf_ehe_extract(&data[off],
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik &ndx, cieRflag, ehdr->e_ident,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik shdr->sh_addr + off + ndx);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik fdeaddrrange = dwarf_ehe_extract(&data[off],
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik &ndx, (cieRflag & ~DW_EH_PE_pcrel),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ehdr->e_ident,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte shdr->sh_addr + off + ndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_XWORD(fdeinitloc),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_XWORD(fdeaddrrange));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cieaugstr[0])
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik MSG_ORIG(MSG_UNW_FDEAUXVAL));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cieZflag) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t val;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte val = uleb_extract(&data[off], &ndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_ORIG(MSG_UNW_FDEAUXSIZE),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_XWORD(val));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (val & cieLflag) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fdeinitloc = dwarf_ehe_extract(
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &data[off], &ndx, cieLflag,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ehdr->e_ident,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte shdr->sh_addr + off + ndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_ORIG(MSG_UNW_FDEAUXLSDA),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_XWORD(val));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((fdelength + 4) > ndx)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unwindtbl(&ndx, fdelength, data, off,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_ORIG(MSG_UNW_FDECFI),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_ORIG(MSG_UNW_FDEPRE),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik MSG_UNW_FDEPRE_SIZE);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik off += fdelength + 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Print the hardware/software capabilities. For executables and shared objects
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * this should be accompanied with a program header.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurikstatic void
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurikcap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Elf *elf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word cnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *cshdr = 0;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Cache *ccache;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Off cphdr_off = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Xword cphdr_sz;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine if a hardware/software capabilities header exists.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (phnum) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Phdr *phdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((phdr = elf_getphdr(elf)) == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (cnt = 0; cnt < phnum; phdr++, cnt++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (phdr->p_type == PT_SUNWCAP) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cphdr_off = phdr->p_offset;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cphdr_sz = phdr->p_filesz;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine if a hardware/software capabilities section exists.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik for (cnt = 1; cnt < shnum; cnt++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cache *_cache = &cache[cnt];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *shdr = _cache->c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (shdr->sh_type != SHT_SUNW_cap)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cphdr_off && ((cphdr_off < shdr->sh_offset) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size)))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (_cache->c_data == NULL)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ccache = _cache;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cshdr = shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cshdr == 0) && (cphdr_off == 0))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, ccache->c_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Print the hardware/software capabilities section.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (cshdr) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word ndx, capn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cap *cap = (Cap *)ccache->c_data->d_buf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Elf_cap_title(0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte capn = (Word)(cshdr->sh_size / cshdr->sh_entsize);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik for (ndx = 0; ndx < capn; cap++, ndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cap->c_tag != CA_SUNW_NULL)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Elf_cap_entry(0, cap, ndx, ehdr->e_machine);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If this object is an executable or shared object, then the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * hardware/software capabilities section should have an accompanying
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * program header.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (cphdr_off == 0)
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik file, ccache->c_name);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik else if ((cphdr_off != cshdr->sh_offset) ||
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (cphdr_sz != cshdr->sh_size))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, ccache->c_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Print the interpretor.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteinterp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word cnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *ishdr = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cache *icache;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Off iphdr_off = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Xword iphdr_fsz;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine if an interp header exists.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (phnum) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Phdr *phdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if ((phdr = getphdr(phnum, PT_INTERP, file, elf)) != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iphdr_off = phdr->p_offset;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik iphdr_fsz = phdr->p_filesz;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (iphdr_off == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine if an interp section exists.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (cnt = 1; cnt < shnum; cnt++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cache *_cache = &cache[cnt];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *shdr = _cache->c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Scan sections to find a section which contains the PT_INTERP
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * string. The target section can't be in a NOBITS section.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_type == SHT_NOBITS) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iphdr_off < shdr->sh_offset) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iphdr_off + iphdr_fsz) > (shdr->sh_offset + shdr->sh_size))
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik icache = _cache;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ishdr = shdr;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * Print the interpreter string based on the offset defined in the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * program header, as this is the offset used by the kernel.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ishdr && icache->c_data) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik dbg_print(0, MSG_ORIG(MSG_FMT_INDENT),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (char *)icache->c_data->d_buf +
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iphdr_off - ishdr->sh_offset));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * If there are any inconsistences between the program header and
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * section information, flag them.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ishdr && ((iphdr_off != ishdr->sh_offset) ||
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (iphdr_fsz != ishdr->sh_size))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik icache->c_name);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik}
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Print the syminfo section.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Juriksyminfo(Cache *cache, Word shnum, const char *file)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *infoshdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Syminfo *info;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Sym *syms;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Dyn *dyns;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Word infonum, cnt, ndx, symnum;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Cache *infocache = 0, *symsec, *strsec;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (cnt = 1; cnt < shnum; cnt++) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte infocache = &cache[cnt];
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik break;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (infocache == 0)
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte infoshdr = infocache->c_shdr;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if ((infoshdr->sh_entsize == 0) || (infoshdr->sh_size == 0)) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, infocache->c_name);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (infocache->c_data == NULL)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik infonum = (Word)(infoshdr->sh_size / infoshdr->sh_entsize);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik info = (Syminfo *)infocache->c_data->d_buf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Get the data buffer of the associated dynamic section.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((infoshdr->sh_info == 0) || (infoshdr->sh_info >= shnum)) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik file, infocache->c_name, EC_WORD(infoshdr->sh_info));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cache[infoshdr->sh_info].c_data == NULL)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik dyns = cache[infoshdr->sh_info].c_data->d_buf;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (dyns == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik file, cache[infoshdr->sh_info].c_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Get the data buffer for the associated symbol table and string table.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stringtbl(cache, 1, cnt, shnum, file,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik &symnum, &symsec, &strsec) == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte syms = symsec->c_data->d_buf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Loop through the syminfo entries.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMINFO), infocache->c_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Elf_syminfo_title(0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ndx = 1, info++; ndx < infonum; ndx++, info++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Sym *sym;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik const char *needed = 0, *name;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if ((info->si_flags == 0) && (info->si_boundto == 0))
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik sym = &syms[ndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte name = string(infocache, ndx, strsec, file, sym->st_name);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (info->si_boundto < SYMINFO_BT_LOWRESERVE) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Dyn *dyn = &dyns[info->si_boundto];
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte needed = string(infocache, info->si_boundto,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik strsec, file, dyn->d_un.d_val);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Elf_syminfo_entry(0, ndx, info, name, needed);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Print version definition section entries.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteversion_def(Verdef *vdf, Word shnum, Cache *vcache, Cache *scache,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *file)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word cnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char index[MAXNDXSIZE];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Elf_ver_def_title(0);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik for (cnt = 1; cnt <= shnum; cnt++,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik const char *name, *dep;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Half vcnt = vdf->vd_cnt - 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Half ndx = vdf->vd_ndx;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Verdaux *vdap = (Verdaux *)((uintptr_t)vdf +
f645cd15cd9c30aa3b568ad85bd8a63996112c4bMilan Jurik vdf->vd_aux);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Obtain the name and first dependency (if any).
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte name = string(vcache, cnt, scache, file, vdap->vda_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (vcnt)
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik dep = string(vcache, cnt, scache, file, vdap->vda_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik dep = MSG_ORIG(MSG_STR_EMPTY);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_XWORD(ndx));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Elf_ver_line_1(0, index, name, dep,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte conv_ver_flags(vdf->vd_flags));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Print any additional dependencies.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (vcnt) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (vcnt--; vcnt; vcnt--,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte vdap = (Verdaux *)((uintptr_t)vdap +
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik vdap->vda_next)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dep = string(vcache, cnt, scache, file,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik vdap->vda_name);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Elf_ver_line_2(0, MSG_ORIG(MSG_STR_EMPTY), dep);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Print a version needed section entries.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurikstatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteversion_need(Verneed *vnd, Word shnum, Cache *vcache, Cache *scache,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *file)
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word cnt;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Elf_ver_need_title(0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik for (cnt = 1; cnt <= shnum; cnt++,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik const char *name, *dep;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Half vcnt = vnd->vn_cnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Vernaux *vnap = (Vernaux *)((uintptr_t)vnd +
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte vnd->vn_aux);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Obtain the name of the needed file and the version name
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * within it that we're dependent on. Note that the count
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * should be at least one, otherwise this is a pretty bogus
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * entry.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik name = string(vcache, cnt, scache, file, vnd->vn_file);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (vcnt)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dep = string(vcache, cnt, scache, file, vnap->vna_name);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik else
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik dep = MSG_INTL(MSG_STR_NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Elf_ver_line_1(0, MSG_ORIG(MSG_STR_EMPTY), name, dep,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte conv_ver_flags(vnap->vna_flags));
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Print any additional version dependencies.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (vcnt) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (vcnt--; vcnt; vcnt--,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik vnap = (Vernaux *)((uintptr_t)vnap +
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik vnap->vna_next)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dep = string(vcache, cnt, scache, file,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik vnap->vna_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Elf_ver_line_3(0, MSG_ORIG(MSG_STR_EMPTY), dep,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte conv_ver_flags(vnap->vna_flags));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Display version section information if the flags require it.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Return version information needed by other output.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * entry:
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * cache - Cache of all section headers
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * shnum - # of sections in cache
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * file - Name of file
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * flags - Command line option flags
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * versym - VERSYM_STATE block to be filled in.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteversions(Cache *cache, Word shnum, const char *file, uint_t flags,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte VERSYM_STATE *versym)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik GElf_Word cnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *gnu_prefix;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik size_t gnu_prefix_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(versym, sizeof (*versym));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte gnu_prefix = MSG_ORIG(MSG_GNU_VERNAMPREFIX);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik gnu_prefix_len = strlen(gnu_prefix);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (cnt = 1; cnt < shnum; cnt++) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik void *ver;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik uint_t num;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cache *_cache = &cache[cnt];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *shdr = _cache->c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *secname = _cache->c_name;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the section names starts with the .gnu.version prefix,
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * then this object was almost certainly produced by the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * GNU ld and not the native Solaris ld.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (strncmp(gnu_prefix, secname, gnu_prefix_len) == 0)
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik versym->gnu = 1;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If this is the version symbol table record its data
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * address for later symbol processing.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if ((shdr->sh_type == SHT_SUNW_versym) &&
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (_cache->c_data != NULL)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte versym->cache = _cache;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte versym->data = _cache->c_data->d_buf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If this is a version definition section, retain # of
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * version definitions for later symbol processing.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (shdr->sh_type == SHT_SUNW_verdef)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte versym->num_verdef = shdr->sh_info;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((flags & FLG_VERSIONS) == 0)
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_type != SHT_SUNW_verdef) &&
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (shdr->sh_type != SHT_SUNW_verneed))
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik continue;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * Determine the version section data and number.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if ((_cache->c_data == NULL) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((ver = (void *)_cache->c_data->d_buf) == NULL)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, secname);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((num = shdr->sh_info) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik file, secname, EC_WORD(shdr->sh_info));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * Get the data buffer for the associated string table.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik file, secname, EC_WORD(shdr->sh_link));
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (shdr->sh_type == SHT_SUNW_verdef) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERDEF), secname);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte version_def((Verdef *)ver, num, _cache,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &cache[shdr->sh_link], file);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (shdr->sh_type == SHT_SUNW_verneed) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERNEED), secname);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte version_need((Verneed *)ver, num, _cache,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &cache[shdr->sh_link], file);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Initialize a symbol table state structure
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * entry:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * state - State structure to be initialized
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * cache - Cache of all section headers
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * shnum - # of sections in cache
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * secndx - Index of symbol table section
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ehdr - ELF header for file
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * versym - Information about versym section
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file - Name of file
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * flags - Command line option flags
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteinit_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Ehdr *ehdr, VERSYM_STATE *versym, const char *file, uint_t flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->file = file;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->ehdr = ehdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->cache = cache;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->shnum = shnum;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->seccache = &cache[secndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->secndx = secndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->secname = state->seccache->c_name;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->flags = flags;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->shxndx.checked = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->shxndx.data = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->shxndx.n = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte shdr = state->seccache->c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check the symbol data and per-item size.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, state->secname);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (state->seccache->c_data == NULL)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* LINTED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->symn = (Word)(shdr->sh_size / shdr->sh_entsize);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->sym = (Sym *)state->seccache->c_data->d_buf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check associated string table section.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, state->secname, EC_WORD(shdr->sh_link));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine if there is a associated Versym section
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * with this Symbol Table.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (versym->cache &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (versym->cache->c_shdr->sh_link == state->secndx))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->versym = versym;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->versym = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine the extended section index used for symbol tables entries.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesymbols_getxindex(SYMTBL_STATE * state)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint_t symn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word symcnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->shxndx.checked = 1; /* Note that we've been called */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (symcnt = 1; symcnt < state->shnum; symcnt++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cache *_cache = &state->cache[symcnt];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *shdr = _cache->c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_type != SHT_SYMTAB_SHNDX) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (shdr->sh_link != state->secndx))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((shdr->sh_entsize) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* LINTED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (_cache->c_data == NULL)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->shxndx.data = _cache->c_data->d_buf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->shxndx.n = symn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik}
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Produce a line of output for the given symbol
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * entry:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * state - Symbol table state
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * symndx - Index of symbol within the table
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * symndx_disp - Index to display. This may not be the same
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * as symndx if the display is relative to the logical
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * combination of the SUNW_ldynsym/dynsym tables.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * sym - Symbol to display
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteoutput_symbol(SYMTBL_STATE *state, Word symndx, Word disp_symndx, Sym *sym)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /*
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * Symbol types for which we check that the specified
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * address/size land inside the target section.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik static const int addr_symtype[STT_NUM] = {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik 0, /* STT_NOTYPE */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik 1, /* STT_OBJECT */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik 1, /* STT_FUNC */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik 0, /* STT_SECTION */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik 0, /* STT_FILE */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik 1, /* STT_COMMON */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik 0, /* STT_TLS */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik };
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik#if STT_NUM != (STT_TLS + 1)
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik#error "STT_NUM has grown. Update addr_symtype[]"
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik#endif
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik char index[MAXNDXSIZE], *sec;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik const char *symname;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Versym verndx;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik uchar_t type;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Shdr *tshdr;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik Word shndx;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /* Ensure symbol index is in range */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (symndx >= state->symn) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORTNDX),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik state->file, state->secname, EC_WORD(symndx));
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik return;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * If we are using extended symbol indexes, find the
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * corresponding SHN_SYMTAB_SHNDX table.
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0))
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik symbols_getxindex(state);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /* LINTED */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik symname = string(state->seccache, symndx,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &state->cache[state->seccache->c_shdr->sh_link], state->file,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sym->st_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte tshdr = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sec = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if ((state->ehdr->e_type == ET_CORE))
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik sec = (char *)MSG_INTL(MSG_STR_UNKNOWN);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik else if ((sym->st_shndx < SHN_LORESERVE) &&
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik (sym->st_shndx < state->shnum)) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik shndx = sym->st_shndx;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik tshdr = state->cache[shndx].c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sec = state->cache[shndx].c_name;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik } else if (sym->st_shndx == SHN_XINDEX) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (state->shxndx.data) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word _shxndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (symndx > state->shxndx.n) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_ERR_BADSYMXINDEX1),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->file, state->secname, EC_WORD(symndx));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if ((_shxndx =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->shxndx.data[symndx]) > state->shnum) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_ERR_BADSYMXINDEX2),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->file, state->secname, EC_WORD(symndx),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_WORD(_shxndx));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte shndx = _shxndx;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik tshdr = state->cache[shndx].c_shdr;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik sec = state->cache[shndx].c_name;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_ERR_BADSYMXINDEX3),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->file, state->secname, EC_WORD(symndx));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if ((sym->st_shndx < SHN_LORESERVE) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (sym->st_shndx >= state->shnum)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_ERR_BADSYM5), state->file,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->secname, demangle(symname, state->flags),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sym->st_shndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If versioning is available display the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * version index. If not, then use 0.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (state->versym) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte verndx = state->versym->data[symndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check to see if this is a defined symbol with a
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * version index that is outside the valid range for
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the file. If so, then there are two possiblities:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * - Files produced by the GNU ld use the top (16th) bit
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * as a "hidden symbol" marker. If we have
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * detected that this object comes from GNU ld,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * then check to see if this is the case and that
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the resulting masked version is in range. If so,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * issue a warning describing it.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * - If this is not a GNU "hidden bit" issue, then
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * issue a generic "out of range" error.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (VERNDX_INVALID(sym->st_shndx, state->versym->num_verdef,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->versym->data, verndx)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (state->versym->gnu && (verndx & 0x8000) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((verndx & ~0x8000) <=
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->versym->num_verdef)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_WARN_GNUVER), state->file,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->secname, EC_WORD(symndx),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_HALF(verndx & ~0x8000));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else { /* Generic version range error */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_ERR_BADVER), state->file,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->secname, EC_WORD(symndx),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_HALF(verndx), state->versym->num_verdef);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte verndx = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Error checking for TLS.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte type = ELF_ST_TYPE(sym->st_info);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (type == STT_TLS) {
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (tshdr &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (sym->st_shndx != SHN_UNDEF) &&
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik ((tshdr->sh_flags & SHF_TLS) == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_ERR_BADSYM3), state->file,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->secname, demangle(symname, state->flags));
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if ((type != STT_SECTION) && sym->st_size &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte tshdr && (tshdr->sh_flags & SHF_TLS)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_ERR_BADSYM4), state->file,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->secname, demangle(symname, state->flags));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If a symbol with non-zero size has a type that
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * specifies an address, then make sure the location
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * it references is actually contained within the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * section. UNDEF symbols don't count in this case,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * so we ignore them.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The meaning of the st_value field in a symbol
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * depends on the type of object. For a relocatable
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * object, it is the offset within the section.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For sharable objects, it is the offset relative to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the base of the object, and for other types, it is
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the virtual address. To get an offset within the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * section for non-ET_REL files, we subtract the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * base address of the section.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (addr_symtype[type] && (sym->st_size > 0) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (sym->st_shndx != SHN_UNDEF) && ((sym->st_shndx < SHN_LORESERVE) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (sym->st_shndx == SHN_XINDEX)) && (tshdr != NULL)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word v = sym->st_value;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (state->ehdr->e_type != ET_REL)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte v -= tshdr->sh_addr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((v + sym->st_size) > tshdr->sh_size)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_ERR_BADSYM6), state->file,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->secname, demangle(symname, state->flags),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_WORD(shndx), EC_XWORD(tshdr->sh_size),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_XWORD(sym->st_value), EC_XWORD(sym->st_size));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) snprintf(index, MAXNDXSIZE,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(disp_symndx));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state->ehdr->e_machine, sym, verndx, sec, symname);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Search for and process any symbol tables.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurikvoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesymbols(Cache *cache, Word shnum, Ehdr *ehdr, const char *name,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte VERSYM_STATE *versym, const char *file, uint_t flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte SYMTBL_STATE state;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cache *_cache;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word secndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (secndx = 1; secndx < shnum; secndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word symcnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte _cache = &cache[secndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte shdr = _cache->c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if ((shdr->sh_type != SHT_SYMTAB) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (shdr->sh_type != SHT_DYNSYM) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (shdr->sh_type != SHT_SUNW_LDYNSYM))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (name && strcmp(name, _cache->c_name))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!init_symtbl_state(&state, cache, shnum, secndx, ehdr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte versym, file, flags))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Loop through the symbol tables entries.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), state.secname);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (symcnt = 0; symcnt < state.symn; symcnt++)
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik output_symbol(&state, symcnt, symcnt,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte state.sym + symcnt);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Search for and process any SHT_SUNW_symsort or SHT_SUNW_tlssort sections.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * These sections are always associated with the .SUNW_ldynsym./.dynsym pair.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, const char *name,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte VERSYM_STATE *versym, const char *file, uint_t flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte SYMTBL_STATE ldynsym_state, dynsym_state;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Cache *sortcache, *symcache;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Shdr *sortshdr, *symshdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word sortsecndx, symsecndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word ldynsym_cnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word *ndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word ndxn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int output_cnt = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (sortsecndx = 1; sortsecndx < shnum; sortsecndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sortcache = &cache[sortsecndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sortshdr = sortcache->c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((sortshdr->sh_type != SHT_SUNW_symsort) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (sortshdr->sh_type != SHT_SUNW_tlssort))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (name && strcmp(name, sortcache->c_name))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the section references a SUNW_ldynsym, then we
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * expect to see the associated .dynsym immediately
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * following. If it references a .dynsym, there is no
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SUNW_ldynsym. If it is any other type, then we don't
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * know what to do with it.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((sortshdr->sh_link == 0) || (sortshdr->sh_link >= shnum)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, sortcache->c_name,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EC_WORD(sortshdr->sh_link));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte symcache = &cache[sortshdr->sh_link];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte symshdr = symcache->c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte symsecndx = sortshdr->sh_link;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ldynsym_cnt = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (symshdr->sh_type) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case SHT_SUNW_LDYNSYM:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!init_symtbl_state(&ldynsym_state, cache, shnum,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte symsecndx, ehdr, versym, file, flags))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ldynsym_cnt = ldynsym_state.symn;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /*
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * We know that the dynsym follows immediately
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * after the SUNW_ldynsym, and so, should be at
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (sortshdr->sh_link + 1). However, elfdump is a
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * diagnostic tool, so we do the full paranoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * search instead.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (symsecndx = 1; symsecndx < shnum; symsecndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte symcache = &cache[symsecndx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte symshdr = symcache->c_shdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (symshdr->sh_type == SHT_DYNSYM)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik if (symsecndx >= shnum) { /* Dynsym not found! */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_ERR_NODYNSYM),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte file, sortcache->c_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik }
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /* Fallthrough to process associated dynsym */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /*FALLTHROUGH*/
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case SHT_DYNSYM:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!init_symtbl_state(&dynsym_state, cache, shnum,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte symsecndx, ehdr, versym, file, flags))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADNDXSEC),
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik file, sortcache->c_name, conv_sec_type(
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik ehdr->e_machine, symshdr->sh_type, 0));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik /*
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik * Output header
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik */
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ldynsym_cnt > 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT2),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sortcache->c_name, ldynsym_state.secname,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dynsym_state.secname);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The data for .SUNW_ldynsym and dynsym sections
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is supposed to be adjacent with SUNW_ldynsym coming
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * first. Check, and issue a warning if it isn't so.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ldynsym_state.sym + ldynsym_state.symn)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte != dynsym_state.sym)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) fprintf(stderr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MSG_INTL(MSG_ERR_LDYNNOTADJ), file,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ldynsym_state.secname,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dynsym_state.secname);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT1),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sortcache->c_name, dynsym_state.secname);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If not first one, insert a line of whitespace */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (output_cnt++ > 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SUNW_dynsymsort and SUNW_dyntlssort are arrays of
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * symbol indices. Iterate over the array entries,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * dispaying the referenced symbols.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndxn = sortshdr->sh_size / sortshdr->sh_entsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx = (Word *)sortcache->c_data->d_buf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (; ndxn-- > 0; ndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (*ndx >= ldynsym_cnt) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Word sec_ndx = *ndx - ldynsym_cnt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte output_symbol(&dynsym_state, sec_ndx,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *ndx, dynsym_state.sym + sec_ndx);
fc23152c0568d631ad6c47a2537542c6c8fab02cMilan Jurik } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte output_symbol(&ldynsym_state, *ndx,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *ndx, ldynsym_state.sym + *ndx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
/*
* Search for and process any relocation sections.
*/
static void
reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, const char *file,
uint_t flags)
{
Word cnt;
for (cnt = 1; cnt < shnum; cnt++) {
Word type, symnum;
Xword relndx, relnum, relsize;
void *rels;
Sym *syms;
Cache *symsec, *strsec;
Cache *_cache = &cache[cnt];
Shdr *shdr = _cache->c_shdr;
char *relname = _cache->c_name;
if (((type = shdr->sh_type) != SHT_RELA) &&
(type != SHT_REL))
continue;
if (name && strcmp(name, relname))
continue;
/*
* Decide entry size.
*/
if (((relsize = shdr->sh_entsize) == 0) ||
(relsize > shdr->sh_size)) {
if (type == SHT_RELA)
relsize = sizeof (Rela);
else
relsize = sizeof (Rel);
}
/*
* Determine the number of relocations available.
*/
if (shdr->sh_size == 0) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
file, relname);
continue;
}
if (_cache->c_data == NULL)
continue;
rels = _cache->c_data->d_buf;
relnum = shdr->sh_size / relsize;
/*
* Get the data buffer for the associated symbol table and
* string table.
*/
if (stringtbl(cache, 1, cnt, shnum, file,
&symnum, &symsec, &strsec) == 0)
continue;
syms = symsec->c_data->d_buf;
/*
* Loop through the relocation entries.
*/
dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name);
Elf_reloc_title(0, ELF_DBG_ELFDUMP, type);
for (relndx = 0; relndx < relnum; relndx++,
rels = (void *)((char *)rels + relsize)) {
char section[BUFSIZ];
const char *symname;
Word symndx, reltype;
Rela *rela;
Rel *rel;
/*
* Unravel the relocation and determine the symbol with
* which this relocation is associated.
*/
if (type == SHT_RELA) {
rela = (Rela *)rels;
symndx = ELF_R_SYM(rela->r_info);
reltype = ELF_R_TYPE(rela->r_info);
} else {
rel = (Rel *)rels;
symndx = ELF_R_SYM(rel->r_info);
reltype = ELF_R_TYPE(rel->r_info);
}
symname = relsymname(cache, _cache, strsec, symndx,
symnum, relndx, syms, section, BUFSIZ, file,
flags);
/*
* A zero symbol index is only valid for a few
* relocations.
*/
if (symndx == 0) {
Half mach = ehdr->e_machine;
int badrel = 0;
if ((mach == EM_SPARC) ||
(mach == EM_SPARC32PLUS) ||
(mach == EM_SPARCV9)) {
if ((reltype != R_SPARC_NONE) &&
(reltype != R_SPARC_REGISTER) &&
(reltype != R_SPARC_RELATIVE))
badrel++;
} else if (mach == EM_386) {
if ((reltype != R_386_NONE) &&
(reltype != R_386_RELATIVE))
badrel++;
} else if (mach == EM_AMD64) {
if ((reltype != R_AMD64_NONE) &&
(reltype != R_AMD64_RELATIVE))
badrel++;
}
if (badrel) {
(void) fprintf(stderr,
MSG_INTL(MSG_ERR_BADREL1), file,
conv_reloc_type(mach, reltype, 0));
}
}
Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP,
MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type,
rels, relname, symname, 0);
}
}
}
/*
* Search for and process a .dynamic section.
*/
static void
dynamic(Cache *cache, Word shnum, Ehdr *ehdr, const char *file)
{
Word cnt;
for (cnt = 1; cnt < shnum; cnt++) {
Dyn *dyn;
ulong_t numdyn;
int ndx, end_ndx;
Cache *_cache = &cache[cnt], *strsec;
Shdr *shdr = _cache->c_shdr;
if (shdr->sh_type != SHT_DYNAMIC)
continue;
/*
* Verify the associated string table section.
*/
if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0)
continue;
if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
file, _cache->c_name);
continue;
}
if (_cache->c_data == NULL)
continue;
numdyn = shdr->sh_size / shdr->sh_entsize;
dyn = (Dyn *)_cache->c_data->d_buf;
dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name);
Elf_dyn_title(0);
for (ndx = 0; ndx < numdyn; dyn++, ndx++) {
const char *name;
/*
* Print the information numerically, and if possible
* as a string.
*/
switch (dyn->d_tag) {
case DT_NULL:
/*
* Special case: DT_NULLs can come in groups
* that we prefer to reduce to a single line.
*/
end_ndx = ndx;
while ((end_ndx < (numdyn - 1)) &&
((dyn + 1)->d_tag == DT_NULL)) {
dyn++;
end_ndx++;
}
Elf_dyn_null_entry(0, dyn, ndx, end_ndx);
ndx = end_ndx;
continue;
/*
* Print the information numerically, and if possible
* as a string.
*/
case DT_NEEDED:
case DT_SONAME:
case DT_FILTER:
case DT_AUXILIARY:
case DT_CONFIG:
case DT_RPATH:
case DT_RUNPATH:
case DT_USED:
case DT_DEPAUDIT:
case DT_AUDIT:
case DT_SUNW_AUXILIARY:
case DT_SUNW_FILTER:
name = string(_cache, ndx, strsec,
file, dyn->d_un.d_ptr);
break;
case DT_FLAGS:
name = conv_dyn_flag(dyn->d_un.d_val, 0);
break;
case DT_FLAGS_1:
name = conv_dyn_flag1(dyn->d_un.d_val);
break;
case DT_POSFLAG_1:
name = conv_dyn_posflag1(dyn->d_un.d_val, 0);
break;
case DT_FEATURE_1:
name = conv_dyn_feature1(dyn->d_un.d_val, 0);
break;
case DT_DEPRECATED_SPARC_REGISTER:
name = MSG_INTL(MSG_STR_DEPRECATED);
break;
default:
name = MSG_ORIG(MSG_STR_EMPTY);
break;
}
Elf_dyn_entry(0, dyn, ndx, name, ehdr->e_machine);
}
}
}
/*
* Search for and process a MOVE section.
*/
static void
move(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags)
{
Word cnt;
const char *fmt = 0;
for (cnt = 1; cnt < shnum; cnt++) {
Word movenum, symnum, ndx;
Sym *syms;
Cache *_cache = &cache[cnt];
Shdr *shdr = _cache->c_shdr;
Cache *symsec, *strsec;
Move *move;
if (shdr->sh_type != SHT_SUNW_move)
continue;
if (name && strcmp(name, _cache->c_name))
continue;
/*
* Determine the move data and number.
*/
if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
file, _cache->c_name);
continue;
}
if (_cache->c_data == NULL)
continue;
move = (Move *)_cache->c_data->d_buf;
movenum = shdr->sh_size / shdr->sh_entsize;
/*
* Get the data buffer for the associated symbol table and
* string table.
*/
if (stringtbl(cache, 1, cnt, shnum, file,
&symnum, &symsec, &strsec) == 0)
return;
syms = (Sym *)symsec->c_data->d_buf;
dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name);
dbg_print(0, MSG_INTL(MSG_MOVE_TITLE));
if (fmt == 0)
fmt = MSG_INTL(MSG_MOVE_ENTRY);
for (ndx = 0; ndx < movenum; move++, ndx++) {
const char *symname;
char index[MAXNDXSIZE], section[BUFSIZ];
Word symndx, shndx;
Sym *sym;
/*
* Check for null entries
*/
if ((move->m_info == 0) && (move->m_value == 0) &&
(move->m_poffset == 0) && (move->m_repeat == 0) &&
(move->m_stride == 0)) {
dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY),
EC_XWORD(move->m_poffset), 0, 0, 0,
EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY));
continue;
}
if (((symndx = ELF_M_SYM(move->m_info)) == 0) ||
(symndx >= symnum)) {
(void) fprintf(stderr,
MSG_INTL(MSG_ERR_BADMINFO), file,
_cache->c_name, EC_XWORD(move->m_info));
(void) snprintf(index, MAXNDXSIZE,
MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx));
dbg_print(0, fmt, index,
EC_XWORD(move->m_poffset),
ELF_M_SIZE(move->m_info), move->m_repeat,
move->m_stride, move->m_value,
MSG_INTL(MSG_STR_UNKNOWN));
continue;
}
symname = relsymname(cache, _cache, strsec,
symndx, symnum, ndx, syms, section, BUFSIZ, file,
flags);
sym = (Sym *)(syms + symndx);
/*
* Additional sanity check.
*/
shndx = sym->st_shndx;
if (!((shndx == SHN_COMMON) ||
(((shndx >= 1) && (shndx <= shnum)) &&
(cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) {
(void) fprintf(stderr,
MSG_INTL(MSG_ERR_BADSYM2), file,
_cache->c_name, demangle(symname, flags));
}
(void) snprintf(index, MAXNDXSIZE,
MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx));
dbg_print(0, fmt, index, EC_XWORD(move->m_poffset),
ELF_M_SIZE(move->m_info), move->m_repeat,
move->m_stride, move->m_value,
demangle(symname, flags));
}
}
}
/*
* Traverse a note section analyzing each note information block.
* The data buffers size is used to validate references before they are made,
* and is decremented as each element is processed.
*/
void
note_entry(Cache *cache, Word *data, size_t size, const char *file)
{
size_t bsize = size;
/*
* Print out a single `note' information block.
*/
while (size > 0) {
size_t namesz, descsz, type, pad, noteoff;
noteoff = bsize - size;
/*
* Make sure we can at least reference the 3 initial entries
* (4-byte words) of the note information block.
*/
if (size >= (sizeof (Word) * 3))
size -= (sizeof (Word) * 3);
else {
(void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ),
file, cache->c_name, EC_WORD(noteoff));
return;
}
/*
* Make sure any specified name string can be referenced.
*/
if ((namesz = *data++) != 0) {
if (size >= namesz)
size -= namesz;
else {
(void) fprintf(stderr,
MSG_INTL(MSG_NOTE_BADNMSZ), file,
cache->c_name, EC_WORD(noteoff),
EC_WORD(namesz));
return;
}
}
/*
* Make sure any specified descriptor can be referenced.
*/
if ((descsz = *data++) != 0) {
/*
* If namesz isn't a 4-byte multiple, account for any
* padding that must exist before the descriptor.
*/
if ((pad = (namesz & (sizeof (Word) - 1))) != 0) {
pad = sizeof (Word) - pad;
size -= pad;
}
if (size >= descsz)
size -= descsz;
else {
(void) fprintf(stderr,
MSG_INTL(MSG_NOTE_BADDESZ), file,
cache->c_name, EC_WORD(noteoff),
EC_WORD(namesz));
return;
}
}
type = *data++;
dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE), EC_WORD(type));
dbg_print(0, MSG_ORIG(MSG_NOTE_NAMESZ), EC_WORD(namesz));
if (namesz) {
char *name = (char *)data;
/*
* Since the name string may have 'null' bytes
* in it (ia32 .string) - we just write the
* whole stream in a single fwrite.
*/
(void) fwrite(name, namesz, 1, stdout);
name = name + ((namesz + (sizeof (Word) - 1)) &
~(sizeof (Word) - 1));
/* LINTED */
data = (Word *)name;
dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
}
/*
* If multiple information blocks exist within a .note section
* account for any padding that must exist before the next
* information block.
*/
if ((pad = (descsz & (sizeof (Word) - 1))) != 0) {
pad = sizeof (Word) - pad;
if (size > pad)
size -= pad;
}
dbg_print(0, MSG_ORIG(MSG_NOTE_DESCSZ), EC_WORD(descsz));
if (descsz) {
int ndx, byte, word;
char string[58], *str = string;
uchar_t *desc = (uchar_t *)data;
/*
* Dump descriptor bytes.
*/
for (ndx = byte = word = 0; descsz; descsz--, desc++) {
int tok = *desc;
(void) snprintf(str, 58, MSG_ORIG(MSG_NOTE_TOK),
tok);
str += 3;
if (++byte == 4) {
*str++ = ' ', *str++ = ' ';
word++;
byte = 0;
}
if (word == 4) {
*str = '\0';
dbg_print(0, MSG_ORIG(MSG_NOTE_DESC),
ndx, string);
word = 0;
ndx += 16;
str = string;
}
}
if (byte || word) {
*str = '\0';
dbg_print(0, MSG_ORIG(MSG_NOTE_DESC),
ndx, string);
}
desc += pad;
/* LINTED */
data = (Word *)desc;
}
}
}
/*
* Search for and process a .note section.
*/
static void
note(Cache *cache, Word shnum, const char *name, const char *file)
{
Word cnt;
/*
* Otherwise look for any .note sections.
*/
for (cnt = 1; cnt < shnum; cnt++) {
Cache *_cache = &cache[cnt];
Shdr *shdr = _cache->c_shdr;
if (shdr->sh_type != SHT_NOTE)
continue;
if (name && strcmp(name, _cache->c_name))
continue;
/*
* As these sections are often hand rolled, make sure they're
* properly aligned before proceeding.
*/
if (shdr->sh_offset & (sizeof (Word) - 1)) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN),
file, _cache->c_name);
continue;
}
if (_cache->c_data == NULL)
continue;
dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
dbg_print(0, MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name);
note_entry(_cache, (Word *)_cache->c_data->d_buf,
/* LINTED */
(Word)_cache->c_data->d_size, file);
}
}
/*
* Determine an individual hash entry. This may be the initial hash entry,
* or an associated chain entry.
*/
static void
hash_entry(Cache *refsec, Cache *strsec, const char *hsecname, Word hashndx,
Word symndx, Word symn, Sym *syms, const char *file, ulong_t bkts,
uint_t flags, int chain)
{
Sym *sym;
const char *symname, *str;
char _bucket[MAXNDXSIZE], _symndx[MAXNDXSIZE];
ulong_t nbkt, nhash;
if (symndx > symn) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_HSBADSYMNDX), file,
EC_WORD(symndx), EC_WORD(hashndx));
symname = MSG_INTL(MSG_STR_UNKNOWN);
} else {
sym = (Sym *)(syms + symndx);
symname = string(refsec, symndx, strsec, file, sym->st_name);
}
if (chain == 0) {
(void) snprintf(_bucket, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER),
hashndx);
str = (const char *)_bucket;
} else
str = MSG_ORIG(MSG_STR_EMPTY);
(void) snprintf(_symndx, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX2),
EC_WORD(symndx));
dbg_print(0, MSG_ORIG(MSG_FMT_HASH_INFO), str, _symndx,
demangle(symname, flags));
/*
* Determine if this string is in the correct bucket.
*/
nhash = elf_hash(symname);
nbkt = nhash % bkts;
if (nbkt != hashndx) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADHASH), file,
hsecname, symname, EC_WORD(hashndx), nbkt);
}
}
#define MAXCOUNT 500
static void
hash(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags)
{
static int count[MAXCOUNT];
Word cnt;
ulong_t ndx, bkts;
char number[MAXNDXSIZE];
for (cnt = 1; cnt < shnum; cnt++) {
uint_t *hash, *chain;
Cache *_cache = &cache[cnt];
Shdr *sshdr, *hshdr = _cache->c_shdr;
char *ssecname, *hsecname = _cache->c_name;
Sym *syms;
Word symn;
if (hshdr->sh_type != SHT_HASH)
continue;
if (name && strcmp(name, hsecname))
continue;
/*
* Determine the hash table data and size.
*/
if ((hshdr->sh_entsize == 0) || (hshdr->sh_size == 0)) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
file, hsecname);
continue;
}
if (_cache->c_data == NULL)
continue;
hash = (uint_t *)_cache->c_data->d_buf;
bkts = *hash;
chain = hash + 2 + bkts;
hash += 2;
/*
* Get the data buffer for the associated symbol table.
*/
if ((hshdr->sh_link == 0) || (hshdr->sh_link >= shnum)) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
file, hsecname, EC_WORD(hshdr->sh_link));
continue;
}
_cache = &cache[hshdr->sh_link];
ssecname = _cache->c_name;
if (_cache->c_data == NULL)
continue;
if ((syms = (Sym *)_cache->c_data->d_buf) == NULL) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
file, ssecname);
continue;
}
sshdr = _cache->c_shdr;
/* LINTED */
symn = (Word)(sshdr->sh_size / sshdr->sh_entsize);
/*
* Get the associated string table section.
*/
if ((sshdr->sh_link == 0) || (sshdr->sh_link >= shnum)) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
file, ssecname, EC_WORD(sshdr->sh_link));
continue;
}
dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
dbg_print(0, MSG_INTL(MSG_ELF_SCN_HASH), hsecname);
dbg_print(0, MSG_INTL(MSG_ELF_HASH_INFO));
/*
* Loop through the hash buckets, printing the appropriate
* symbols.
*/
for (ndx = 0; ndx < bkts; ndx++, hash++) {
Word _ndx, _cnt;
if (*hash == 0) {
count[0]++;
continue;
}
hash_entry(_cache, &cache[sshdr->sh_link], hsecname,
ndx, *hash, symn, syms, file, bkts, flags, 0);
/*
* Determine if any other symbols are chained to this
* bucket.
*/
_ndx = chain[*hash];
_cnt = 1;
while (_ndx) {
hash_entry(_cache, &cache[sshdr->sh_link],
hsecname, ndx, _ndx, symn, syms, file,
bkts, flags, 1);
_ndx = chain[_ndx];
_cnt++;
}
if (_cnt >= MAXCOUNT) {
(void) fprintf(stderr,
MSG_INTL(MSG_HASH_OVERFLW), file,
_cache->c_name, EC_WORD(ndx),
EC_WORD(_cnt));
} else
count[_cnt]++;
}
break;
}
/*
* Print out the count information.
*/
bkts = cnt = 0;
dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
for (ndx = 0; ndx < MAXCOUNT; ndx++) {
Word _cnt;
if ((_cnt = count[ndx]) == 0)
continue;
(void) snprintf(number, MAXNDXSIZE,
MSG_ORIG(MSG_FMT_INTEGER), _cnt);
dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS1), number,
EC_WORD(ndx));
bkts += _cnt;
cnt += (Word)(ndx * _cnt);
}
if (cnt) {
(void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER),
bkts);
dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS2), number,
EC_WORD(cnt));
}
}
static void
group(Cache *cache, Word shnum, const char *name, const char *file,
uint_t flags)
{
Word scnt;
for (scnt = 1; scnt < shnum; scnt++) {
Cache *_cache = &cache[scnt];
Shdr *shdr = _cache->c_shdr;
Word *grpdata, gcnt, grpcnt, symnum, unknown;
Cache *symsec, *strsec;
Sym *syms, *sym;
char flgstrbuf[MSG_GRP_COMDAT_SIZE + 10];
if (shdr->sh_type != SHT_GROUP)
continue;
if (name && strcmp(name, _cache->c_name))
continue;
if ((_cache->c_data == NULL) ||
((grpdata = (Word *)_cache->c_data->d_buf) == NULL))
continue;
grpcnt = shdr->sh_size / sizeof (Word);
/*
* Get the data buffer for the associated symbol table and
* string table.
*/
if (stringtbl(cache, 1, scnt, shnum, file,
&symnum, &symsec, &strsec) == 0)
return;
syms = symsec->c_data->d_buf;
dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
dbg_print(0, MSG_INTL(MSG_ELF_SCN_GRP), _cache->c_name);
dbg_print(0, MSG_INTL(MSG_GRP_TITLE));
/*
* The first element of the group defines the group. The
* associated symbol is defined by the sh_link field.
*/
if ((shdr->sh_info == SHN_UNDEF) || (shdr->sh_info > symnum)) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO),
file, _cache->c_name, EC_WORD(shdr->sh_info));
return;
}
(void) strcpy(flgstrbuf, MSG_ORIG(MSG_STR_OSQBRKT));
if (grpdata[0] & GRP_COMDAT) {
(void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_COMDAT));
}
if ((unknown = (grpdata[0] & ~GRP_COMDAT)) != 0) {
size_t len = strlen(flgstrbuf);
(void) snprintf(&flgstrbuf[len],
(MSG_GRP_COMDAT_SIZE + 10 - len),
MSG_ORIG(MSG_GRP_UNKNOWN), unknown);
}
(void) strcat(flgstrbuf, MSG_ORIG(MSG_STR_CSQBRKT));
sym = (Sym *)(syms + shdr->sh_info);
dbg_print(0, MSG_INTL(MSG_GRP_SIGNATURE), flgstrbuf,
demangle(string(_cache, 0, strsec, file, sym->st_name),
flags));
for (gcnt = 1; gcnt < grpcnt; gcnt++) {
char index[MAXNDXSIZE];
const char *name;
(void) snprintf(index, MAXNDXSIZE,
MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(gcnt));
if (grpdata[gcnt] >= shnum)
name = MSG_INTL(MSG_GRP_INVALSCN);
else
name = cache[grpdata[gcnt]].c_name;
(void) printf(MSG_ORIG(MSG_GRP_ENTRY), index, name,
EC_XWORD(grpdata[gcnt]));
}
}
}
static void
got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, uint_t flags)
{
Cache *gotcache = 0, *symtab = 0, *_cache;
Addr gotbgn, gotend;
Shdr *gotshdr;
Word cnt, gotents, gotndx;
size_t gentsize;
Got_info *gottable;
char *gotdata;
Sym *gotsym;
Xword gotsymaddr;
/*
* First, find the got.
*/
for (cnt = 1; cnt < shnum; cnt++) {
_cache = &cache[cnt];
if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT),
MSG_ELF_GOT_SIZE) == 0) {
gotcache = _cache;
break;
}
}
if (gotcache == 0)
return;
/*
* A got section within a relocatable object is suspicious.
*/
if (ehdr->e_type == ET_REL) {
(void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file,
_cache->c_name);
}
gotshdr = gotcache->c_shdr;
if (gotshdr->sh_size == 0) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
file, gotcache->c_name);
return;
}
gotbgn = gotshdr->sh_addr;
gotend = gotbgn + gotshdr->sh_size;
/*
* Some architectures don't properly set the sh_entsize for the GOT
* table. If it's not set, default to a size of a pointer.
*/
if ((gentsize = gotshdr->sh_entsize) == 0)
gentsize = sizeof (Xword);
if (gotcache->c_data == NULL)
return;
/* LINTED */
gotents = (Word)(gotshdr->sh_size / gentsize);
gotdata = gotcache->c_data->d_buf;
if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) {
int err = errno;
(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), file,
strerror(err));
return;
}
/*
* Now we scan through all the sections looking for any relocations
* that may be against the GOT. Since these may not be isolated to a
* .rel[a].got section we check them all.
* While scanning sections save the symbol table entry (a symtab
* overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_.
*/
for (cnt = 1; cnt < shnum; cnt++) {
Word type, symnum;
Xword relndx, relnum, relsize;
void *rels;
Sym *syms;
Cache *symsec, *strsec;
Cache *_cache = &cache[cnt];
Shdr *shdr;
shdr = _cache->c_shdr;
type = shdr->sh_type;
if ((symtab == 0) && (type == SHT_DYNSYM)) {
symtab = _cache;
continue;
}
if (type == SHT_SYMTAB) {
symtab = _cache;
continue;
}
if ((type != SHT_RELA) && (type != SHT_REL))
continue;
/*
* Decide entry size.
*/
if (((relsize = shdr->sh_entsize) == 0) ||
(relsize > shdr->sh_size)) {
if (type == SHT_RELA)
relsize = sizeof (Rela);
else
relsize = sizeof (Rel);
}
/*
* Determine the number of relocations available.
*/
if (shdr->sh_size == 0) {
(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
file, _cache->c_name);
continue;
}
if (_cache->c_data == NULL)
continue;
rels = _cache->c_data->d_buf;
relnum = shdr->sh_size / relsize;
/*
* Get the data buffer for the associated symbol table and
* string table.
*/
if (stringtbl(cache, 1, cnt, shnum, file,
&symnum, &symsec, &strsec) == 0)
continue;
syms = symsec->c_data->d_buf;
/*
* Loop through the relocation entries.
*/
for (relndx = 0; relndx < relnum; relndx++,
rels = (void *)((char *)rels + relsize)) {
char section[BUFSIZ];
Addr offset;
Got_info *gip;
Word symndx, reltype;
Rela *rela;
Rel *rel;
/*
* Unravel the relocation.
*/
if (type == SHT_RELA) {
rela = (Rela *)rels;
symndx = ELF_R_SYM(rela->r_info);
reltype = ELF_R_TYPE(rela->r_info);
offset = rela->r_offset;
} else {
rel = (Rel *)rels;
symndx = ELF_R_SYM(rel->r_info);
reltype = ELF_R_TYPE(rel->r_info);
offset = rel->r_offset;
}
/*
* Only pay attention to relocations against the GOT.
*/
if ((offset < gotbgn) || (offset > gotend))
continue;
/* LINTED */
gotndx = (Word)((offset - gotbgn) /
gotshdr->sh_entsize);
gip = &gottable[gotndx];
if (gip->g_reltype != 0) {
(void) fprintf(stderr,
MSG_INTL(MSG_GOT_MULTIPLE), file,
EC_WORD(gotndx), EC_ADDR(offset));
continue;
}
if (symndx)
gip->g_symname = relsymname(cache, _cache,
strsec, symndx, symnum, relndx, syms,
section, BUFSIZ, file, flags);
gip->g_reltype = reltype;
gip->g_rel = rels;
}
}
if (symlookup(MSG_ORIG(MSG_GOT_SYM), cache, shnum, &gotsym, symtab,
file))
gotsymaddr = gotsym->st_value;
else
gotsymaddr = gotbgn;
dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name);
Elf_got_title(0);
for (gotndx = 0; gotndx < gotents; gotndx++) {
Got_info *gip;
Sword gindex;
Addr gaddr;
Xword gotentry;
gip = &gottable[gotndx];
gaddr = gotbgn + (gotndx * gentsize);
gindex = (Sword)(gaddr - gotsymaddr) / (Sword)gentsize;
if (gentsize == sizeof (Word))
/* LINTED */
gotentry = (Xword)(*((Word *)(gotdata) + gotndx));
else
/* LINTED */
gotentry = *((Xword *)(gotdata) + gotndx);
Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine,
gip->g_reltype, gip->g_rel, gip->g_symname);
}
free(gottable);
}
void
checksum(Elf *elf)
{
dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
dbg_print(0, MSG_INTL(MSG_STR_CHECKSUM), elf_checksum(elf));
}
void
regular(const char *file, Elf *elf, uint_t flags, char *Nname, int wfd)
{
Elf_Scn *scn;
Ehdr *ehdr;
Elf_Data *data;
size_t cnt, shstrndx, shnum, phnum;
Shdr *nameshdr, *shdr;
char *names = 0;
Cache *cache, *_cache;
VERSYM_STATE versym;
if ((ehdr = elf_getehdr(elf)) == NULL) {
failure(file, MSG_ORIG(MSG_ELF_GETEHDR));
return;
}
if (elf_getshnum(elf, &shnum) == 0) {
failure(file, MSG_ORIG(MSG_ELF_GETSHNUM));
return;
}
if (elf_getshstrndx(elf, &shstrndx) == 0) {
failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX));
return;
}
if (elf_getphnum(elf, &phnum) == 0) {
failure(file, MSG_ORIG(MSG_ELF_GETPHNUM));
return;
}
if ((scn = elf_getscn(elf, 0)) != NULL) {
if ((shdr = elf_getshdr(scn)) == NULL) {
failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0);
return;
}
} else
shdr = 0;
/*
* Print the elf header.
*/
if (flags & FLG_EHDR)
Elf_ehdr(0, ehdr, shdr);
/*
* Print the program headers.
*/
if ((flags & FLG_PHDR) && (phnum != 0)) {
Phdr *phdr;
if ((phdr = elf_getphdr(elf)) == NULL) {
failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
return;
}
for (cnt = 0; cnt < phnum; phdr++, cnt++) {
if (Nname &&
(strcmp(Nname, conv_phdr_type(ehdr->e_machine,
phdr->p_type, CONV_FMT_ALTFILE)) != 0))
continue;
dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
dbg_print(0, MSG_INTL(MSG_ELF_PHDR), EC_WORD(cnt));
Elf_phdr(0, ehdr->e_machine, phdr);
}
}
/*
* Return now if there are no section, if there's just one section to
* act as an extension of the ELF header, or if on section information
* was requested.
*/
if ((shnum <= 1) || (flags && (flags & ~(FLG_EHDR | FLG_PHDR)) == 0)) {
if ((ehdr->e_type == ET_CORE) && (flags & FLG_NOTE))
note(0, shnum, 0, file);
return;
}
/*
* Obtain the .shstrtab data buffer to provide the required section
* name strings.
*/
if ((scn = elf_getscn(elf, shstrndx)) == NULL) {
failure(file, MSG_ORIG(MSG_ELF_GETSCN));
(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR),
EC_XWORD(shstrndx));
} else if ((data = elf_getdata(scn, NULL)) == NULL) {
failure(file, MSG_ORIG(MSG_ELF_GETDATA));
(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA),
EC_XWORD(shstrndx));
} else if ((nameshdr = elf_getshdr(scn)) == NULL) {
failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN),
EC_WORD(elf_ndxscn(scn)));
} else if ((names = data->d_buf) == 0)
(void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file);
/*
* Allocate a cache to maintain a descriptor for each section.
*/
if ((cache = malloc(shnum * sizeof (Cache))) == 0) {
int err = errno;
(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
file, strerror(err));
return;
}
*cache = cache_init;
_cache = cache;
_cache++;
/*
* Traverse the sections of the file. This gathering of data is
* carried out in two passes. First, the section headers are captured
* and the section header names are evaluated. A verification pass is
* then carried out over the section information. Files have been
* known to exhibit overlapping (and hence erroneous) section header
* information.
*
* Finally, the data for each section is obtained. This processing is
* carried out after section verification because should any section
* header overlap occur, and a file needs translating (ie. xlate'ing
* information from a non-native architecture file), then the process
* of translation can corrupt the section header information. Of
* course, if there is any section overlap, the data related to the
* sections is going to be compromised. However, it is the translation
* of this data that has caused problems with elfdump()'s ability to
* extract the data.
*/
for (cnt = 1, scn = NULL; scn = elf_nextscn(elf, scn);
cnt++, _cache++) {
char scnndxnm[100];
_cache->c_scn = scn;
if ((_cache->c_shdr = elf_getshdr(scn)) == NULL) {
failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN),
EC_WORD(elf_ndxscn(scn)));
}
/*
* If a shstrtab exists, assign the section name.
*/
if (names && _cache->c_shdr) {
if (_cache->c_shdr->sh_name &&
/* LINTED */
(nameshdr->sh_size > _cache->c_shdr->sh_name)) {
_cache->c_name =
names + _cache->c_shdr->sh_name;
continue;
}
/*
* Generate an error if the section name index is zero
* or exceeds the shstrtab data. Fall through to
* fabricate a section name.
*/
if ((_cache->c_shdr->sh_name == 0) ||
/* LINTED */
(nameshdr->sh_size <= _cache->c_shdr->sh_name)) {
(void) fprintf(stderr,
MSG_INTL(MSG_ERR_BADSHNAME), file,
EC_WORD(cnt),
EC_XWORD(_cache->c_shdr->sh_name));
}
}
/*
* If there exists no shstrtab data, or a section header has no
* name (an invalid index of 0), then compose a name for the
* section.
*/
(void) snprintf(scnndxnm, sizeof (scnndxnm),
MSG_INTL(MSG_FMT_SCNNDX), cnt);
if ((_cache->c_name = malloc(strlen(scnndxnm) + 1)) == 0) {
int err = errno;
(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
file, strerror(err));
return;
}
(void) strcpy(_cache->c_name, scnndxnm);
}
/*
* Having collected all the sections, validate their address range.
* Cases have existed where the section information has been invalid.
* This can lead to all sorts of other, hard to diagnose errors, as
* each section is processed individually (ie. with elf_getdata()).
* Here, we carry out some address comparisons to catch a family of
* overlapping memory issues we have observed (likely, there are others
* that we have yet to discover).
*
* Note, should any memory overlap occur, obtaining any additional
* data from the file is questionable. However, it might still be
* possible to inspect the ELF header, Programs headers, or individual
* sections, so rather than bailing on an error condition, continue
* processing to see if any data can be salvaged.
*/
for (cnt = 1; cnt < shnum; cnt++) {
Cache *_cache = &cache[cnt];
Shdr *shdr = _cache->c_shdr;
Off bgn1, bgn = shdr->sh_offset;
Off end1, end = shdr->sh_offset + shdr->sh_size;
int cnt1;
if ((shdr->sh_size == 0) || (shdr->sh_type == SHT_NOBITS))
continue;
for (cnt1 = 1; cnt1 < shnum; cnt1++) {
Cache *_cache1 = &cache[cnt1];
Shdr *shdr1 = _cache1->c_shdr;
bgn1 = shdr1->sh_offset;
end1 = shdr1->sh_offset + shdr1->sh_size;
if ((cnt1 == cnt) || (shdr->sh_size == 0) ||
(shdr1->sh_type == SHT_NOBITS))
continue;
if (((bgn1 <= bgn) && (end1 > bgn)) ||
((bgn1 < end) && (end1 >= end))) {
(void) fprintf(stderr,
MSG_INTL(MSG_ERR_SECMEMOVER), file,
EC_WORD(elf_ndxscn(_cache1->c_scn)),
_cache1->c_name, EC_OFF(bgn1), EC_OFF(end1),
EC_WORD(elf_ndxscn(_cache->c_scn)),
_cache->c_name, EC_OFF(bgn), EC_OFF(end));
}
}
/*
* And finally, make sure this section doesn't overlap the
* section header itself.
*/
bgn1 = ehdr->e_shoff;
end1 = ehdr->e_shoff + (ehdr->e_shentsize * ehdr->e_shnum);
if (((bgn1 <= bgn) && (end1 > bgn)) ||
((bgn1 < end) && (end1 >= end))) {
(void) fprintf(stderr,
MSG_INTL(MSG_ERR_SHDRMEMOVER), file, EC_OFF(bgn1),
EC_OFF(end1),
EC_WORD(elf_ndxscn(_cache->c_scn)),
_cache->c_name, EC_OFF(bgn), EC_OFF(end));
}
}
/*
* Finally, obtain the data for each section.
*/
for (cnt = 1; cnt < shnum; cnt++) {
Cache *_cache = &cache[cnt];
Elf_Scn *scn = _cache->c_scn;
if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) {
failure(file, MSG_ORIG(MSG_ELF_GETDATA));
(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA),
EC_WORD(elf_ndxscn(scn)));
}
/*
* Do we wish to write the section out?
*/
if (wfd && Nname && (strcmp(Nname, _cache->c_name) == 0) &&
_cache->c_data) {
(void) write(wfd, _cache->c_data->d_buf,
_cache->c_data->d_size);
}
}
if (flags & FLG_SHDR)
sections(file, cache, shnum, ehdr, Nname);
if (flags & FLG_INTERP)
interp(file, cache, shnum, phnum, elf);
versions(cache, shnum, file, flags, &versym);
if (flags & FLG_SYMBOLS)
symbols(cache, shnum, ehdr, Nname, &versym, file, flags);
if (flags & FLG_SORT)
sunw_sort(cache, shnum, ehdr, Nname, &versym, file, flags);
if (flags & FLG_HASH)
hash(cache, shnum, Nname, file, flags);
if (flags & FLG_GOT)
got(cache, shnum, ehdr, file, flags);
if (flags & FLG_GROUP)
group(cache, shnum, Nname, file, flags);
if (flags & FLG_SYMINFO)
syminfo(cache, shnum, file);
if (flags & FLG_RELOC)
reloc(cache, shnum, ehdr, Nname, file, flags);
if (flags & FLG_DYNAMIC)
dynamic(cache, shnum, ehdr, file);
if (flags & FLG_NOTE)
note(cache, shnum, Nname, file);
if (flags & FLG_MOVE)
move(cache, shnum, Nname, file, flags);
if (flags & FLG_CHECKSUM)
checksum(elf);
if (flags & FLG_CAP)
cap(file, cache, shnum, phnum, ehdr, elf);
if (flags & FLG_UNWIND)
unwind(cache, shnum, phnum, ehdr, Nname, file, elf);
free(cache);
}