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