1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include        "msg.h"
  28 #include        "_debug.h"
  29 #include        "libld.h"
  30 
  31 /*
  32  * If any run-time linker debugging is being carried out always indicate the
  33  * fact and specify the point at which we transfer control to the main program.
  34  */
  35 void
  36 Dbg_util_call_main(Rt_map *lmp)
  37 {
  38         Lm_list *lml = LIST(lmp);
  39 
  40         Dbg_util_nl(lml, DBG_NL_FRC);
  41         dbg_print(lml, MSG_INTL(MSG_UTL_TRANS), NAME(lmp));
  42         Dbg_util_nl(lml, DBG_NL_FRC);
  43 }
  44 
  45 void
  46 Dbg_util_call_init(Rt_map *lmp, int flag)
  47 {
  48         Lm_list         *lml = LIST(lmp);
  49         const char      *str;
  50 
  51         if (DBG_NOTCLASS(DBG_C_INIT))
  52                 return;
  53 
  54         if (flag == DBG_INIT_SORT)
  55                 str = MSG_INTL(MSG_UTL_SORT);
  56         else if (flag == DBG_INIT_PEND)
  57                 str = MSG_INTL(MSG_UTL_PEND);
  58         else if (flag == DBG_INIT_DYN)
  59                 str = MSG_INTL(MSG_UTL_DYN);
  60         else
  61                 str = MSG_INTL(MSG_UTL_DONE);
  62 
  63         Dbg_util_nl(lml, DBG_NL_STD);
  64         dbg_print(lml, MSG_INTL(MSG_UTL_INIT), str, NAME(lmp));
  65         Dbg_util_nl(lml, DBG_NL_STD);
  66 }
  67 
  68 void
  69 Dbg_util_intoolate(Rt_map *lmp)
  70 {
  71         Lm_list *lml = LIST(lmp);
  72 
  73         Dbg_util_nl(lml, DBG_NL_STD);
  74         dbg_print(lml, MSG_INTL(MSG_UTL_INTOOLATE), NAME(lmp));
  75         Dbg_util_nl(lml, DBG_NL_STD);
  76 }
  77 
  78 void
  79 Dbg_util_dbnotify(Lm_list *lml, rd_event_e event, r_state_e state)
  80 {
  81         const char      *estr;
  82         const char      *sstr;
  83 
  84         if (DBG_NOTCLASS(DBG_C_FILES))
  85                 return;
  86         if (DBG_NOTDETAIL())
  87                 return;
  88 
  89         switch (event) {
  90         case RD_PREINIT:
  91                 estr = MSG_ORIG(MSG_UTL_EVNT_PREINIT);
  92                 sstr = MSG_INTL(MSG_STR_NULL);
  93                 break;
  94         case RD_POSTINIT:
  95                 estr = MSG_ORIG(MSG_UTL_EVNT_POSTINIT);
  96                 sstr = MSG_INTL(MSG_STR_NULL);
  97                 break;
  98         case RD_DLACTIVITY:
  99                 estr = MSG_ORIG(MSG_UTL_EVNT_DLACT);
 100                 switch (state) {
 101                 case RT_CONSISTENT:
 102                         sstr = MSG_ORIG(MSG_UTL_STA_CONSIST);
 103                         break;
 104                 case RT_ADD:
 105                         sstr = MSG_ORIG(MSG_UTL_STA_ADD);
 106                         break;
 107                 case RT_DELETE:
 108                         sstr = MSG_ORIG(MSG_UTL_STA_DELETE);
 109                         break;
 110                 default:
 111                         sstr = MSG_INTL(MSG_STR_NULL);
 112                         break;
 113                 }
 114                 break;
 115         default:
 116                 sstr = MSG_INTL(MSG_STR_NULL);
 117                 estr = MSG_INTL(MSG_STR_UNKNOWN);
 118                 break;
 119         }
 120 
 121         Dbg_util_nl(lml, DBG_NL_STD);
 122         dbg_print(lml, MSG_INTL(MSG_UTL_DBNOTIFY), estr, sstr);
 123         Dbg_util_nl(lml, DBG_NL_STD);
 124 }
 125 
 126 void
 127 Dbg_util_call_array(Rt_map *lmp, void *addr, int ndx, Word shtype)
 128 {
 129         Lm_list         *lml = LIST(lmp);
 130         const char      *str;
 131 
 132         if (DBG_NOTCLASS(DBG_C_INIT))
 133                 return;
 134 
 135         if (shtype == SHT_INIT_ARRAY)
 136                 str = MSG_ORIG(MSG_SCN_INITARRAY);
 137         else if (shtype == SHT_FINI_ARRAY)
 138                 str = MSG_ORIG(MSG_SCN_FINIARRAY);
 139         else
 140                 str = MSG_ORIG(MSG_SCN_PREINITARRAY);
 141 
 142         dbg_print(lml, MSG_INTL(MSG_UTL_ARRAY), str, ndx, EC_NATPTR(addr),
 143             NAME(lmp));
 144 }
 145 
 146 void
 147 Dbg_util_call_fini(Rt_map *lmp)
 148 {
 149         Lm_list *lml = LIST(lmp);
 150 
 151         if (DBG_NOTCLASS(DBG_C_INIT))
 152                 return;
 153 
 154         Dbg_util_nl(lml, DBG_NL_STD);
 155         dbg_print(lml, MSG_INTL(MSG_UTL_FINI), NAME(lmp));
 156         Dbg_util_nl(lml, DBG_NL_STD);
 157 }
 158 
 159 void
 160 Dbg_util_str(Lm_list *lml, const char *str)
 161 {
 162         Dbg_util_nl(lml, DBG_NL_STD);
 163         Dbg_util_nl(lml, DBG_NL_FRC);
 164         dbg_print(lml, MSG_ORIG(MSG_FMT_STR), str);
 165         Dbg_util_nl(lml, DBG_NL_FRC);
 166         Dbg_util_nl(lml, DBG_NL_STD);
 167 }
 168 
 169 void
 170 Dbg_util_scc_title(Lm_list *lml, int sec)
 171 {
 172         const char      *_sec;
 173 
 174         if (DBG_NOTCLASS(DBG_C_INIT))
 175                 return;
 176         if (DBG_NOTDETAIL())
 177                 return;
 178 
 179         if (sec)
 180                 _sec = MSG_INTL(MSG_UTL_SCC_SUBI);
 181         else
 182                 _sec = MSG_INTL(MSG_UTL_SCC_SUBF);
 183 
 184         Dbg_util_nl(lml, DBG_NL_STD);
 185         dbg_print(lml, MSG_INTL(MSG_UTL_SCC_TITLE), _sec);
 186 }
 187 
 188 void
 189 Dbg_util_scc_entry(Rt_map *lmp, uint_t idx)
 190 {
 191         if (DBG_NOTCLASS(DBG_C_INIT))
 192                 return;
 193         if (DBG_NOTDETAIL())
 194                 return;
 195 
 196         dbg_print(LIST(lmp), MSG_ORIG(MSG_UTL_SCC_ENTRY), idx, NAME(lmp));
 197 }
 198 
 199 static  int ectoggle = 0;
 200 
 201 void
 202 Dbg_util_edge_in(Lm_list *lml, Rt_map *clmp, uint_t flags, Rt_map *dlmp,
 203     int ndx, int flag)
 204 {
 205         Conv_bnd_type_buf_t     bnd_type_buf;
 206         const char              *str;
 207 
 208         if (DBG_NOTCLASS(DBG_C_INIT))
 209                 return;
 210         if (DBG_NOTDETAIL())
 211                 return;
 212 
 213         if (flag & RT_SORT_REV)
 214                 str = MSG_ORIG(MSG_SCN_INIT);
 215         else
 216                 str = MSG_ORIG(MSG_SCN_FINI);
 217 
 218         if ((clmp == 0) || (ectoggle == 0))
 219                 Dbg_util_nl(lml, DBG_NL_STD);
 220         if (clmp == 0) {
 221                 if (flag & RT_SORT_INTPOSE)
 222                         dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_TITLE_I), str);
 223                 else
 224                         dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_TITLE_S), str);
 225 
 226                 dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_START), ndx, NAME(dlmp));
 227         } else
 228                 dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_IN), ndx, NAME(dlmp),
 229                     NAME(clmp), conv_bnd_type(flags, &bnd_type_buf));
 230 
 231         ectoggle = 1;
 232 }
 233 
 234 void
 235 Dbg_util_edge_out(Rt_map *clmp, Rt_map *dlmp)
 236 {
 237         if (DBG_NOTCLASS(DBG_C_INIT))
 238                 return;
 239         if (DBG_NOTDETAIL())
 240                 return;
 241 
 242         dbg_print(LIST(clmp), MSG_INTL(MSG_UTL_EDGE_OUT), SORTVAL(clmp),
 243             NAME(clmp), NAME(dlmp));
 244 }
 245 
 246 void
 247 Dbg_util_collect(Rt_map *lmp, int ndx, int flag)
 248 {
 249         Lm_list         *lml = LIST(lmp);
 250         const char      *str;
 251 
 252         if (DBG_NOTCLASS(DBG_C_INIT))
 253                 return;
 254         if (DBG_NOTDETAIL())
 255                 return;
 256 
 257         if (flag & RT_SORT_REV)
 258                 str = MSG_ORIG(MSG_SCN_INIT);
 259         else
 260                 str = MSG_ORIG(MSG_SCN_FINI);
 261 
 262         if (ectoggle == 1) {
 263                 Dbg_util_nl(lml, DBG_NL_STD);
 264                 ectoggle = 0;
 265         }
 266         dbg_print(lml, MSG_INTL(MSG_UTL_COLLECT), ndx, NAME(lmp), str);
 267 }
 268 
 269 static const Msg        tags[] = {
 270         MSG_CI_NULL,            /* MSG_ORIG(MSG_CI_NULL) */
 271         MSG_CI_VERSION,         /* MSG_ORIG(MSG_CI_VERSION) */
 272         MSG_CI_ATEXIT,          /* MSG_ORIG(MSG_CI_ATEXIT) */
 273         MSG_CI_LCMESSAGES,      /* MSG_ORIG(MSG_CI_LCMESSAGES) */
 274         MSG_CI_BIND_GUARD,      /* MSG_ORIG(MSG_CI_BIND_GUARD) */
 275         MSG_CI_BIND_CLEAR,      /* MSG_ORIG(MSG_CI_BIND_CLEAR) */
 276         MSG_CI_THR_SELF,        /* MSG_ORIG(MSG_CI_THR_SELF) */
 277         MSG_CI_TLS_MODADD,      /* MSG_ORIG(MSG_CI_TLS_MODADD) */
 278         MSG_CI_TLS_MODREM,      /* MSG_ORIG(MSG_CI_TLS_MODREM) */
 279         MSG_CI_TLS_STATMOD,     /* MSG_ORIG(MSG_CI_TLS_STATMOD) */
 280         MSG_CI_THRINIT,         /* MSG_ORIG(MSG_CI_THRINIT) */
 281         MSG_CI_CRITICAL         /* MSG_ORIG(MSG_CI_CRITICAL) */
 282 };
 283 
 284 void
 285 Dbg_util_lcinterface(Rt_map *lmp, int tag, char *val)
 286 {
 287         const char      *str;
 288         Conv_inv_buf_t  inv_buf;
 289 
 290         if (DBG_NOTDETAIL())
 291                 return;
 292 
 293         if (tag < CI_MAX)
 294                 str = MSG_ORIG(tags[tag]);
 295         else
 296                 str = conv_invalid_val(&inv_buf, tag, 0);
 297 
 298         dbg_print(LIST(lmp), MSG_INTL(MSG_UTL_LCINTERFACE), NAME(lmp), str,
 299             EC_NATPTR(val));
 300 }
 301 
 302 void
 303 Dbg_unused_lcinterface(Rt_map *nlmp, Rt_map *olmp, int tag)
 304 {
 305         const char      *str;
 306         Conv_inv_buf_t  inv_buf;
 307 
 308         if (DBG_NOTCLASS(DBG_C_UNUSED))
 309                 return;
 310 
 311         if (tag < CI_MAX)
 312                 str = MSG_ORIG(tags[tag]);
 313         else
 314                 str = conv_invalid_val(&inv_buf, tag, 0);
 315 
 316         dbg_print(LIST(nlmp), MSG_INTL(MSG_USD_LCINTERFACE), NAME(nlmp), str,
 317             NAME(olmp));
 318 }
 319 
 320 /*
 321  * Generic new line generator.  To prevent multiple newlines from being
 322  * generated, a flag is maintained in the global debug descriptor.  This flag
 323  * is cleared by the callers dbg_print() function to indicate that a newline
 324  * (actually, any line) has been printed.  Multiple newlines can be generated
 325  * using the DBG_NL_FRC flag.
 326  */
 327 void
 328 Dbg_util_nl(Lm_list *lml, int flag)
 329 {
 330         if ((flag == DBG_NL_STD) && (dbg_desc->d_extra & DBG_E_STDNL))
 331                 return;
 332 
 333         dbg_print(lml, MSG_ORIG(MSG_STR_EMPTY));
 334 
 335         if (flag == DBG_NL_STD)
 336                 dbg_desc->d_extra |= DBG_E_STDNL;
 337 }
 338 
 339 /*
 340  * Define name demanglers.
 341  */
 342 const char *
 343 Dbg_demangle_name(const char *name)
 344 {
 345         if (DBG_NOTCLASS(DBG_C_DEMANGLE))
 346                 return (name);
 347 
 348         return (conv_demangle_name(name));
 349 }
 350 
 351 const char *
 352 Elf_demangle_name(const char *name)
 353 {
 354         if (DBG_ISDEMANGLE())
 355                 return (conv_demangle_name(name));
 356         return (name);
 357 }