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 } 379