syms.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <dlfcn.h>
#include <strings.h>
#include "msg.h"
#include "_debug.h"
#include "libld.h"
/*
* Print out a single `symbol table node' entry.
*/
#if !defined(_ELF64)
void
Gelf_sym_table_title(GElf_Ehdr *ehdr, const char *index, const char *name)
{
if ((int)ehdr->e_ident[EI_CLASS] == ELFCLASS64) {
if (DBG_NOTLONG())
dbg_print(MSG_ORIG(MSG_SYM_TITLE_64), index, name);
else
dbg_print(MSG_ORIG(MSG_SYM_L_TITLE_64), index, name);
} else {
if (DBG_NOTLONG())
dbg_print(MSG_ORIG(MSG_SYM_TITLE), index, name);
else
dbg_print(MSG_ORIG(MSG_SYM_L_TITLE), index, name);
}
}
void
Elf_sym_table_entry(const char *prestr, Elf32_Ehdr *ehdr, Elf32_Sym *sym,
Elf32_Word verndx, const char *sec, const char *poststr)
{
const char *msg;
if (DBG_NOTLONG())
msg = MSG_ORIG(MSG_SYM_ENTRY);
else
msg = MSG_ORIG(MSG_SYM_L_ENTRY);
dbg_print(msg, prestr,
conv_sym_value_str(ehdr->e_machine, ELF32_ST_TYPE(sym->st_info),
EC_XWORD(sym->st_value)), EC_XWORD(sym->st_size),
conv_info_type_str(ehdr->e_machine, ELF32_ST_TYPE(sym->st_info)),
conv_info_bind_str(ELF32_ST_BIND(sym->st_info)),
conv_sym_stother(sym->st_other), EC_WORD(verndx),
sec ? sec : conv_shndx_str(sym->st_shndx),
_Dbg_sym_dem(poststr));
}
void
Gelf_sym_table_entry(const char *prestr, GElf_Ehdr *ehdr, GElf_Sym *sym,
GElf_Word verndx, const char *sec, const char *poststr)
{
const char *msg;
if ((int)ehdr->e_ident[EI_CLASS] == ELFCLASS64) {
if (DBG_NOTLONG())
msg = MSG_ORIG(MSG_SYM_ENTRY_64);
else
msg = MSG_ORIG(MSG_SYM_L_ENTRY_64);
} else {
if (DBG_NOTLONG())
msg = MSG_ORIG(MSG_SYM_ENTRY);
else
msg = MSG_ORIG(MSG_SYM_L_ENTRY);
}
dbg_print(msg, prestr, conv_sym_value_str(ehdr->e_machine,
GELF_ST_TYPE(sym->st_info), EC_XWORD(sym->st_value)),
EC_XWORD(sym->st_size),
conv_info_type_str(ehdr->e_machine, GELF_ST_TYPE(sym->st_info)),
conv_info_bind_str(GELF_ST_BIND(sym->st_info)),
conv_sym_stother(sym->st_other), EC_WORD(verndx),
sec ? sec : conv_shndx_str(sym->st_shndx),
_Dbg_sym_dem(poststr));
}
void
Gelf_syminfo_title()
{
dbg_print(MSG_INTL(MSG_SYMI_TITLE2));
}
void
Gelf_syminfo_entry(int ndx, GElf_Syminfo *sip, const char *sname,
const char *needed)
{
const char *bind_str;
char flags[16], index[32], bind_index[32] = " ";
int flgndx = 0;
Half symflags;
symflags = sip->si_flags;
if (symflags & SYMINFO_FLG_DIRECT) {
if (sip->si_boundto == SYMINFO_BT_SELF)
bind_str = MSG_INTL(MSG_SYMI_SELF);
else if (sip->si_boundto == SYMINFO_BT_PARENT)
bind_str = MSG_INTL(MSG_SYMI_PARENT);
else {
bind_str = needed;
(void) sprintf(bind_index, MSG_ORIG(MSG_FMT_INDEX),
sip->si_boundto);
}
flags[flgndx++] = 'D';
symflags &= ~SYMINFO_FLG_DIRECT;
} else if (symflags & (SYMINFO_FLG_FILTER | SYMINFO_FLG_AUXILIARY)) {
bind_str = needed;
(void) sprintf(bind_index, MSG_ORIG(MSG_FMT_INDEX),
sip->si_boundto);
if (symflags & SYMINFO_FLG_FILTER) {
flags[flgndx++] = 'F';
symflags &= ~SYMINFO_FLG_FILTER;
}
if (symflags & SYMINFO_FLG_AUXILIARY) {
flags[flgndx++] = 'A';
symflags &= ~SYMINFO_FLG_AUXILIARY;
}
} else if (sip->si_boundto == SYMINFO_BT_EXTERN) {
bind_str = MSG_INTL(MSG_SYMI_EXTERN);
} else
bind_str = MSG_ORIG(MSG_STR_EMPTY);
if (symflags & SYMINFO_FLG_DIRECTBIND) {
flags[flgndx++] = 'B';
symflags &= ~SYMINFO_FLG_DIRECTBIND;
}
if (symflags & SYMINFO_FLG_COPY) {
flags[flgndx++] = 'C';
symflags &= ~SYMINFO_FLG_COPY;
}
if (symflags & SYMINFO_FLG_LAZYLOAD) {
flags[flgndx++] = 'L';
symflags &= ~SYMINFO_FLG_LAZYLOAD;
}
if (symflags & SYMINFO_FLG_NOEXTDIRECT) {
flags[flgndx++] = 'N';
symflags &= ~SYMINFO_FLG_NOEXTDIRECT;
}
/*
* Did we account for all of the flags?
*/
if (symflags)
(void) sprintf(&flags[flgndx], " 0x%x", symflags);
else
flags[flgndx] = '\0';
(void) sprintf(index, MSG_ORIG(MSG_FMT_INDEX), ndx);
dbg_print(MSG_ORIG(MSG_SYMI_FMT), index, flags, bind_index, bind_str,
_Dbg_sym_dem(sname));
}
const char *
Gelf_sym_dem(const char *name)
{
return (conv_sym_dem(name));
}
const char *
_Dbg_sym_dem(const char *name)
{
if (DBG_NOTCLASS(DBG_DEMANGLE))
return (name);
return (conv_sym_dem(name));
}
void
Dbg_syms_ar_title(const char *file, int again)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
dbg_print(MSG_INTL(MSG_SYM_AR_FILE), file,
again ? MSG_INTL(MSG_STR_AGAIN) : MSG_ORIG(MSG_STR_EMPTY));
}
void
Dbg_syms_lazy_rescan(const char *name)
{
if (DBG_NOTCLASS(DBG_SYMBOLS | DBG_FILES))
return;
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
dbg_print(MSG_INTL(MSG_SYM_LAZY_RESCAN), _Dbg_sym_dem(name));
}
#endif /* !defined(_ELF64) */
void
Dbg_syms_ar_entry(Xword ndx, Elf_Arsym *arsym)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_INTL(MSG_SYM_AR_ENTRY), EC_XWORD(ndx),
_Dbg_sym_dem(arsym->as_name));
}
void
Dbg_syms_ar_checking(Xword ndx, Elf_Arsym *arsym, const char *name)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_INTL(MSG_SYM_AR_CHECK), EC_XWORD(ndx),
_Dbg_sym_dem(arsym->as_name), name);
}
void
Dbg_syms_ar_resolve(Xword ndx, Elf_Arsym *arsym, const char *fname, int flag)
{
const char *fmt;
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (flag)
fmt = MSG_INTL(MSG_SYM_AR_FORCEDEXRT);
else
fmt = MSG_INTL(MSG_SYM_AR_RESOLVE);
dbg_print(fmt, EC_XWORD(ndx), _Dbg_sym_dem(arsym->as_name), fname);
}
void
Dbg_syms_spec_title()
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
dbg_print(MSG_INTL(MSG_SYM_SPECIAL));
}
void
Dbg_syms_discarded(Sym_desc *sdp, Is_desc *disp)
{
const char *sectname;
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (DBG_NOTDETAIL())
return;
if ((sectname = disp->is_basename) == 0)
sectname = disp->is_name;
dbg_print(MSG_INTL(MSG_SYM_DISCARDED), _Dbg_sym_dem(sdp->sd_name),
sectname, disp->is_file->ifl_name);
}
void
Dbg_syms_entered(Ehdr *ehdr, Sym *sym, Sym_desc *sdp)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (DBG_NOTDETAIL())
return;
Elf_sym_table_entry(MSG_INTL(MSG_STR_ENTERED), ehdr, sym, sdp->sd_aux ?
sdp->sd_aux->sa_overndx : 0, NULL, conv_deftag_str(sdp->sd_ref));
}
void
Dbg_syms_process(Ifl_desc *ifl)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
dbg_print(MSG_INTL(MSG_SYM_PROCESS), ifl->ifl_name,
conv_etype_str(ifl->ifl_ehdr->e_type));
}
void
Dbg_syms_entry(Xword ndx, Sym_desc *sdp)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_INTL(MSG_SYM_BASIC), EC_XWORD(ndx),
_Dbg_sym_dem(sdp->sd_name));
}
void
Dbg_syms_global(Xword ndx, const char *name)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_INTL(MSG_SYM_ADDING), EC_XWORD(ndx), _Dbg_sym_dem(name));
}
void
Dbg_syms_sec_title()
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (DBG_NOTDETAIL())
return;
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
dbg_print(MSG_INTL(MSG_SYM_INDEX));
}
void
Dbg_syms_sec_entry(int ndx, Sg_desc *sgp, Os_desc *osp)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (DBG_NOTDETAIL())
return;
dbg_print(MSG_INTL(MSG_SYM_SECTION), ndx, osp->os_name,
(*sgp->sg_name ? sgp->sg_name : MSG_INTL(MSG_STR_NULL)));
}
void
Dbg_syms_up_title(Ehdr *ehdr)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (DBG_NOTDETAIL())
return;
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
dbg_print(MSG_INTL(MSG_SYM_FINAL));
/* LINTED */
Gelf_sym_table_title((GElf_Ehdr *)ehdr,
MSG_ORIG(MSG_STR_EMPTY), MSG_ORIG(MSG_STR_EMPTY));
}
void
Dbg_syms_ignore(Ehdr *ehdr, Sym_desc *sdp)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (DBG_NOTDETAIL())
return;
Elf_sym_table_entry(MSG_INTL(MSG_STR_IGNORE), ehdr, sdp->sd_sym,
0, NULL, MSG_INTL(MSG_STR_UNUSED));
}
void
Dbg_syms_old(Ehdr *ehdr, Sym_desc *sdp)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (DBG_NOTDETAIL())
return;
Elf_sym_table_entry(MSG_INTL(MSG_STR_OLD), ehdr, sdp->sd_sym,
sdp->sd_aux ? sdp->sd_aux->sa_overndx : 0, NULL, sdp->sd_name);
}
void
Dbg_syms_new(Ehdr *ehdr, Sym *sym, Sym_desc *sdp)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (DBG_NOTDETAIL())
return;
Elf_sym_table_entry(MSG_INTL(MSG_STR_NEW), ehdr, sym,
sdp->sd_aux ? sdp->sd_aux->sa_overndx : 0, NULL,
conv_deftag_str(sdp->sd_ref));
}
void
Dbg_syms_updated(Ehdr *ehdr, Sym_desc *sdp, const char *name)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_INTL(MSG_SYM_UPDATE), name);
if (DBG_NOTDETAIL())
return;
Elf_sym_table_entry(MSG_ORIG(MSG_STR_EMPTY), ehdr, sdp->sd_sym,
sdp->sd_aux ? sdp->sd_aux->sa_overndx : 0, NULL,
conv_deftag_str(sdp->sd_ref));
}
void
Dbg_syms_created(const char *name)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_INTL(MSG_SYM_CREATE), _Dbg_sym_dem(name));
}
void
Dbg_syms_resolving1(Xword ndx, const char *name, int row, int col)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_INTL(MSG_SYM_RESOLVING), EC_XWORD(ndx),
_Dbg_sym_dem(name), row, col);
}
void
Dbg_syms_resolving2(Ehdr *ehdr, Sym *osym, Sym *nsym, Sym_desc *sdp,
Ifl_desc *ifl)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (DBG_NOTDETAIL())
return;
Elf_sym_table_entry(MSG_INTL(MSG_STR_OLD), ehdr, osym, sdp->sd_aux ?
sdp->sd_aux->sa_overndx : 0, NULL, sdp->sd_file->ifl_name);
Elf_sym_table_entry(MSG_INTL(MSG_STR_NEW), ehdr, nsym, 0, NULL,
ifl->ifl_name);
}
void
Dbg_syms_resolved(Ehdr *ehdr, Sym_desc *sdp)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (DBG_NOTDETAIL())
return;
Elf_sym_table_entry(MSG_INTL(MSG_STR_RESOLVED), ehdr, sdp->sd_sym,
sdp->sd_aux ? sdp->sd_aux->sa_overndx : 0, NULL,
conv_deftag_str(sdp->sd_ref));
}
void
Dbg_syms_nl()
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
}
static Boolean symbol_title = TRUE;
static void
_Dbg_syms_reloc_title()
{
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
dbg_print(MSG_INTL(MSG_SYM_BSS));
symbol_title = FALSE;
}
void
Dbg_syms_reloc(Ehdr *ehdr, Sym_desc *sdp)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (symbol_title)
_Dbg_syms_reloc_title();
dbg_print(MSG_INTL(MSG_SYM_UPDATE), _Dbg_sym_dem(sdp->sd_name));
if (DBG_NOTDETAIL())
return;
Elf_sym_table_entry(MSG_ORIG(MSG_SYM_COPY), ehdr, sdp->sd_sym,
sdp->sd_aux ? sdp->sd_aux->sa_overndx : 0, NULL,
conv_deftag_str(sdp->sd_ref));
}
void
Dbg_syms_lookup_aout(const char *name)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_INTL(MSG_SYM_AOUT), _Dbg_sym_dem(name));
}
void
Dbg_syms_lookup(const char *name, const char *file, const char *type)
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
dbg_print(MSG_INTL(MSG_SYM_LOOKUP), _Dbg_sym_dem(name), file, type);
}
void
Dbg_syms_dlsym(const char *sym, const char *from, const char *next, int flag)
{
const char *str;
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (flag == DBG_DLSYM_NEXT)
str = MSG_ORIG(MSG_SYM_NEXT);
else if (flag == DBG_DLSYM_DEFAULT)
str = MSG_ORIG(MSG_SYM_DEFAULT);
else if (flag == DBG_DLSYM_SELF)
str = MSG_ORIG(MSG_SYM_SELF);
else if (flag == DBG_DLSYM_PROBE)
str = MSG_ORIG(MSG_SYM_PROBE);
else
str = MSG_ORIG(MSG_STR_EMPTY);
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
if (next == 0)
dbg_print(MSG_INTL(MSG_SYM_DLSYM_1), _Dbg_sym_dem(sym),
from, str);
else
dbg_print(MSG_INTL(MSG_SYM_DLSYM_2), _Dbg_sym_dem(sym),
from, next, str);
}
void
Dbg_syms_reduce(int which, Ehdr *ehdr, Sym_desc *sdp,
int idx, const char *sname)
{
static Boolean sym_reduce_title = TRUE;
static Boolean sym_retain_title = TRUE;
Boolean isfromglobal = (which == DBG_SYM_REDUCE_GLOBAL);
Boolean isfromretain = (which == DBG_SYM_REDUCE_RETAIN);
if (DBG_NOTCLASS(DBG_SYMBOLS | DBG_VERSIONS))
return;
if (sym_reduce_title && isfromglobal) {
sym_reduce_title = FALSE;
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
dbg_print(MSG_INTL(MSG_SYM_REDUCED));
} else if (sym_retain_title && isfromretain) {
sym_retain_title = FALSE;
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
dbg_print(MSG_INTL(MSG_SYM_RETAINING));
}
if ((sdp->sd_flags1 & FLG_SY1_ELIM) && isfromglobal)
dbg_print(MSG_INTL(MSG_SYM_ELIMINATING),
_Dbg_sym_dem(sdp->sd_name));
else if (isfromglobal)
dbg_print(MSG_INTL(MSG_SYM_REDUCING),
_Dbg_sym_dem(sdp->sd_name));
else
dbg_print(MSG_INTL(MSG_SYM_NOTELIMINATE),
_Dbg_sym_dem(sdp->sd_name), sname, idx);
if (DBG_NOTDETAIL())
return;
Elf_sym_table_entry(MSG_ORIG(MSG_SYM_LOCAL), ehdr, sdp->sd_sym,
sdp->sd_aux ? sdp->sd_aux->sa_overndx : 0, NULL,
sdp->sd_file->ifl_name);
}
void
Dbg_syminfo_title()
{
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (DBG_NOTDETAIL())
return;
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
dbg_print(MSG_INTL(MSG_SYMI_TITLE1));
Gelf_syminfo_title();
}
void
Dbg_syminfo_entry(int ndx, Syminfo *sip, Sym *sym, const char *strtab,
Dyn *dyn)
{
const char *needed;
if (DBG_NOTCLASS(DBG_SYMBOLS))
return;
if (DBG_NOTDETAIL())
return;
if (sip->si_boundto < SYMINFO_BT_LOWRESERVE)
needed = strtab + dyn[sip->si_boundto].d_un.d_val;
else
needed = 0;
Gelf_syminfo_entry(ndx, (GElf_Syminfo *)sip,
_Dbg_sym_dem(strtab + sym->st_name), needed);
}