/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright 2018 Jason King */ #include "msg.h" #include "_debug.h" #include "libld.h" /* * If any run-time linker debugging is being carried out always indicate the * fact and specify the point at which we transfer control to the main program. */ void Dbg_util_call_main(Rt_map *lmp) { Lm_list *lml = LIST(lmp); Dbg_util_nl(lml, DBG_NL_FRC); dbg_print(lml, MSG_INTL(MSG_UTL_TRANS), NAME(lmp)); Dbg_util_nl(lml, DBG_NL_FRC); } void Dbg_util_call_init(Rt_map *lmp, int flag) { Lm_list *lml = LIST(lmp); const char *str; if (DBG_NOTCLASS(DBG_C_INIT)) return; if (flag == DBG_INIT_SORT) str = MSG_INTL(MSG_UTL_SORT); else if (flag == DBG_INIT_PEND) str = MSG_INTL(MSG_UTL_PEND); else if (flag == DBG_INIT_DYN) str = MSG_INTL(MSG_UTL_DYN); else str = MSG_INTL(MSG_UTL_DONE); Dbg_util_nl(lml, DBG_NL_STD); dbg_print(lml, MSG_INTL(MSG_UTL_INIT), str, NAME(lmp)); Dbg_util_nl(lml, DBG_NL_STD); } void Dbg_util_intoolate(Rt_map *lmp) { Lm_list *lml = LIST(lmp); Dbg_util_nl(lml, DBG_NL_STD); dbg_print(lml, MSG_INTL(MSG_UTL_INTOOLATE), NAME(lmp)); Dbg_util_nl(lml, DBG_NL_STD); } void Dbg_util_dbnotify(Lm_list *lml, rd_event_e event, r_state_e state) { const char *estr; const char *sstr; if (DBG_NOTCLASS(DBG_C_FILES)) return; if (DBG_NOTDETAIL()) return; switch (event) { case RD_PREINIT: estr = MSG_ORIG(MSG_UTL_EVNT_PREINIT); sstr = MSG_INTL(MSG_STR_NULL); break; case RD_POSTINIT: estr = MSG_ORIG(MSG_UTL_EVNT_POSTINIT); sstr = MSG_INTL(MSG_STR_NULL); break; case RD_DLACTIVITY: estr = MSG_ORIG(MSG_UTL_EVNT_DLACT); switch (state) { case RT_CONSISTENT: sstr = MSG_ORIG(MSG_UTL_STA_CONSIST); break; case RT_ADD: sstr = MSG_ORIG(MSG_UTL_STA_ADD); break; case RT_DELETE: sstr = MSG_ORIG(MSG_UTL_STA_DELETE); break; default: sstr = MSG_INTL(MSG_STR_NULL); break; } break; default: sstr = MSG_INTL(MSG_STR_NULL); estr = MSG_INTL(MSG_STR_UNKNOWN); break; } Dbg_util_nl(lml, DBG_NL_STD); dbg_print(lml, MSG_INTL(MSG_UTL_DBNOTIFY), estr, sstr); Dbg_util_nl(lml, DBG_NL_STD); } void Dbg_util_call_array(Rt_map *lmp, void *addr, int ndx, Word shtype) { Lm_list *lml = LIST(lmp); const char *str; if (DBG_NOTCLASS(DBG_C_INIT)) return; if (shtype == SHT_INIT_ARRAY) str = MSG_ORIG(MSG_SCN_INITARRAY); else if (shtype == SHT_FINI_ARRAY) str = MSG_ORIG(MSG_SCN_FINIARRAY); else str = MSG_ORIG(MSG_SCN_PREINITARRAY); dbg_print(lml, MSG_INTL(MSG_UTL_ARRAY), str, ndx, EC_NATPTR(addr), NAME(lmp)); } void Dbg_util_call_fini(Rt_map *lmp) { Lm_list *lml = LIST(lmp); if (DBG_NOTCLASS(DBG_C_INIT)) return; Dbg_util_nl(lml, DBG_NL_STD); dbg_print(lml, MSG_INTL(MSG_UTL_FINI), NAME(lmp)); Dbg_util_nl(lml, DBG_NL_STD); } void Dbg_util_str(Lm_list *lml, const char *str) { Dbg_util_nl(lml, DBG_NL_STD); Dbg_util_nl(lml, DBG_NL_FRC); dbg_print(lml, MSG_ORIG(MSG_FMT_STR), str); Dbg_util_nl(lml, DBG_NL_FRC); Dbg_util_nl(lml, DBG_NL_STD); } void Dbg_util_scc_title(Lm_list *lml, int sec) { const char *_sec; if (DBG_NOTCLASS(DBG_C_INIT)) return; if (DBG_NOTDETAIL()) return; if (sec) _sec = MSG_INTL(MSG_UTL_SCC_SUBI); else _sec = MSG_INTL(MSG_UTL_SCC_SUBF); Dbg_util_nl(lml, DBG_NL_STD); dbg_print(lml, MSG_INTL(MSG_UTL_SCC_TITLE), _sec); } void Dbg_util_scc_entry(Rt_map *lmp, uint_t idx) { if (DBG_NOTCLASS(DBG_C_INIT)) return; if (DBG_NOTDETAIL()) return; dbg_print(LIST(lmp), MSG_ORIG(MSG_UTL_SCC_ENTRY), idx, NAME(lmp)); } static int ectoggle = 0; void Dbg_util_edge_in(Lm_list *lml, Rt_map *clmp, uint_t flags, Rt_map *dlmp, int ndx, int flag) { Conv_bnd_type_buf_t bnd_type_buf; const char *str; if (DBG_NOTCLASS(DBG_C_INIT)) return; if (DBG_NOTDETAIL()) return; if (flag & RT_SORT_REV) str = MSG_ORIG(MSG_SCN_INIT); else str = MSG_ORIG(MSG_SCN_FINI); if ((clmp == 0) || (ectoggle == 0)) Dbg_util_nl(lml, DBG_NL_STD); if (clmp == 0) { if (flag & RT_SORT_INTPOSE) dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_TITLE_I), str); else dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_TITLE_S), str); dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_START), ndx, NAME(dlmp)); } else dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_IN), ndx, NAME(dlmp), NAME(clmp), conv_bnd_type(flags, &bnd_type_buf)); ectoggle = 1; } void Dbg_util_edge_out(Rt_map *clmp, Rt_map *dlmp) { if (DBG_NOTCLASS(DBG_C_INIT)) return; if (DBG_NOTDETAIL()) return; dbg_print(LIST(clmp), MSG_INTL(MSG_UTL_EDGE_OUT), SORTVAL(clmp), NAME(clmp), NAME(dlmp)); } void Dbg_util_collect(Rt_map *lmp, int ndx, int flag) { Lm_list *lml = LIST(lmp); const char *str; if (DBG_NOTCLASS(DBG_C_INIT)) return; if (DBG_NOTDETAIL()) return; if (flag & RT_SORT_REV) str = MSG_ORIG(MSG_SCN_INIT); else str = MSG_ORIG(MSG_SCN_FINI); if (ectoggle == 1) { Dbg_util_nl(lml, DBG_NL_STD); ectoggle = 0; } dbg_print(lml, MSG_INTL(MSG_UTL_COLLECT), ndx, NAME(lmp), str); } static const Msg tags[] = { MSG_CI_NULL, /* MSG_ORIG(MSG_CI_NULL) */ MSG_CI_VERSION, /* MSG_ORIG(MSG_CI_VERSION) */ MSG_CI_ATEXIT, /* MSG_ORIG(MSG_CI_ATEXIT) */ MSG_CI_LCMESSAGES, /* MSG_ORIG(MSG_CI_LCMESSAGES) */ MSG_CI_BIND_GUARD, /* MSG_ORIG(MSG_CI_BIND_GUARD) */ MSG_CI_BIND_CLEAR, /* MSG_ORIG(MSG_CI_BIND_CLEAR) */ MSG_CI_THR_SELF, /* MSG_ORIG(MSG_CI_THR_SELF) */ MSG_CI_TLS_MODADD, /* MSG_ORIG(MSG_CI_TLS_MODADD) */ MSG_CI_TLS_MODREM, /* MSG_ORIG(MSG_CI_TLS_MODREM) */ MSG_CI_TLS_STATMOD, /* MSG_ORIG(MSG_CI_TLS_STATMOD) */ MSG_CI_THRINIT, /* MSG_ORIG(MSG_CI_THRINIT) */ MSG_CI_CRITICAL /* MSG_ORIG(MSG_CI_CRITICAL) */ }; void Dbg_util_lcinterface(Rt_map *lmp, int tag, char *val) { const char *str; Conv_inv_buf_t inv_buf; if (DBG_NOTDETAIL()) return; if (tag < CI_MAX) str = MSG_ORIG(tags[tag]); else str = conv_invalid_val(&inv_buf, tag, 0); dbg_print(LIST(lmp), MSG_INTL(MSG_UTL_LCINTERFACE), NAME(lmp), str, EC_NATPTR(val)); } void Dbg_unused_lcinterface(Rt_map *nlmp, Rt_map *olmp, int tag) { const char *str; Conv_inv_buf_t inv_buf; if (DBG_NOTCLASS(DBG_C_UNUSED)) return; if (tag < CI_MAX) str = MSG_ORIG(tags[tag]); else str = conv_invalid_val(&inv_buf, tag, 0); dbg_print(LIST(nlmp), MSG_INTL(MSG_USD_LCINTERFACE), NAME(nlmp), str, NAME(olmp)); } /* * Generic new line generator. To prevent multiple newlines from being * generated, a flag is maintained in the global debug descriptor. This flag * is cleared by the callers dbg_print() function to indicate that a newline * (actually, any line) has been printed. Multiple newlines can be generated * using the DBG_NL_FRC flag. */ void Dbg_util_nl(Lm_list *lml, int flag) { if ((flag == DBG_NL_STD) && (dbg_desc->d_extra & DBG_E_STDNL)) return; dbg_print(lml, MSG_ORIG(MSG_STR_EMPTY)); if (flag == DBG_NL_STD) dbg_desc->d_extra |= DBG_E_STDNL; } /* * Define name demanglers. */ const char * Dbg_demangle_name(const char *name) { static char *buf = NULL; if (DBG_NOTCLASS(DBG_C_DEMANGLE)) return (name); free(buf); buf = (char *)conv_demangle_name(name); if (buf == name) { buf = NULL; return (name); } return (buf); } const char * Elf_demangle_name(const char *name) { static char *buf = NULL; if (!DBG_ISDEMANGLE()) return (name); free(buf); buf = (char *)conv_demangle_name(name); if (buf == name) { buf = NULL; return (name); } return (buf); }