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 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/elf_SPARC.h> 29 #include <debug.h> 30 #include <libld.h> 31 #include <conv.h> 32 #include "_debug.h" 33 #include "msg.h" 34 35 void 36 Dbg_reloc_apply_reg(Lm_list *lml, int caller, Half mach, Xword off, Xword value) 37 { 38 if (DBG_NOTCLASS(DBG_C_RELOC)) 39 return; 40 if (DBG_NOTDETAIL()) 41 return; 42 43 /* 44 * Print the actual relocation being applied to the specified output 45 * section, the offset represents the actual relocation address, and the 46 * value is the new data being written to that address. 47 */ 48 Elf_reloc_apply_reg(lml, caller, mach, off, value); 49 } 50 51 void 52 Dbg_reloc_apply_val(Lm_list *lml, int caller, Xword off, Xword value) 53 { 54 if (DBG_NOTCLASS(DBG_C_RELOC)) 55 return; 56 if (DBG_NOTDETAIL()) 57 return; 58 59 /* 60 * Print the actual relocation being applied to the specified output 61 * section, the offset represents the actual relocation address, and the 62 * value is the new data being written to that address. 63 */ 64 Elf_reloc_apply_val(lml, caller, off, value); 65 } 66 67 void 68 Dbg_reloc_error(Lm_list *lml, int caller, Half mach, Word type, void *reloc, 69 const char *sname) 70 { 71 if (DBG_NOTCLASS(DBG_C_RELOC)) 72 return; 73 if (DBG_NOTDETAIL()) 74 return; 75 76 Elf_reloc_entry_1(lml, caller, MSG_INTL(MSG_STR_IN), mach, type, reloc, 77 NULL, sname, MSG_INTL(MSG_REL_BADROFFSET)); 78 } 79 80 void 81 Dbg_reloc_run(Rt_map *lmp, uint_t rtype, int info, int dtype) 82 { 83 Lm_list *lml = LIST(lmp); 84 const char *str, *name = NAME(lmp); 85 86 if (DBG_NOTCLASS(DBG_C_RELOC)) 87 return; 88 89 if (dtype == DBG_REL_FINISH) { 90 if (info) 91 str = MSG_ORIG(MSG_STR_EMPTY); 92 else 93 str = MSG_INTL(MSG_REL_FAIL); 94 } else { 95 if (info) 96 str = MSG_INTL(MSG_REL_PLT); 97 else 98 str = MSG_ORIG(MSG_STR_EMPTY); 99 } 100 101 if (dtype == DBG_REL_START) { 102 Dbg_util_nl(lml, DBG_NL_STD); 103 dbg_print(lml, MSG_INTL(MSG_REL_START), name, str); 104 105 if (DBG_NOTDETAIL()) 106 return; 107 108 Elf_reloc_title(lml, ELF_DBG_RTLD, rtype); 109 110 } else { 111 if (dtype == DBG_REL_NONE) { 112 dbg_print(lml, MSG_ORIG(MSG_STR_EMPTY)); 113 dbg_print(lml, MSG_INTL(MSG_REL_NONE), name, str); 114 } else 115 dbg_print(lml, MSG_INTL(MSG_REL_FINISH), name, 116 str); 117 118 Dbg_util_nl(lml, DBG_NL_STD); 119 } 120 } 121 122 void 123 Dbg_reloc_copy(Rt_map *dlmp, Rt_map *nlmp, const char *name, int zero) 124 { 125 const char *str; 126 127 if (DBG_NOTCLASS(DBG_C_RELOC)) 128 return; 129 if (DBG_NOTDETAIL()) 130 return; 131 132 if (zero) 133 str = MSG_INTL(MSG_STR_COPYZERO); 134 else 135 str = MSG_ORIG(MSG_STR_EMPTY); 136 137 dbg_print(LIST(dlmp), MSG_INTL(MSG_REL_COPY), NAME(dlmp), NAME(nlmp), 138 name, str); 139 } 140 141 void 142 Dbg_reloc_generate(Lm_list *lml, Os_desc *osp, Word type) 143 { 144 if (DBG_NOTCLASS(DBG_C_RELOC)) 145 return; 146 147 Dbg_util_nl(lml, DBG_NL_STD); 148 dbg_print(lml, MSG_INTL(MSG_REL_GENERATE), osp->os_name); 149 150 if (DBG_NOTDETAIL()) 151 return; 152 153 Elf_reloc_title(lml, ELF_DBG_LD, type); 154 } 155 156 void 157 Dbg_reloc_proc(Lm_list *lml, Os_desc *osp, Is_desc *isp, Is_desc *risp) 158 { 159 const char *str1, *str2; 160 161 if (DBG_NOTCLASS(DBG_C_RELOC)) 162 return; 163 164 if (osp && osp->os_name) 165 str1 = osp->os_name; 166 else 167 str1 = MSG_INTL(MSG_STR_NULL); 168 169 if (isp && isp->is_file) 170 str2 = isp->is_file->ifl_name; 171 else if (risp && risp->is_file) 172 str2 = risp->is_file->ifl_name; 173 else 174 str2 = MSG_INTL(MSG_STR_NULL); 175 176 Dbg_util_nl(lml, DBG_NL_STD); 177 dbg_print(lml, MSG_INTL(MSG_REL_COLLECT), str1, str2); 178 179 if (DBG_NOTDETAIL()) 180 return; 181 182 Elf_reloc_title(lml, ELF_DBG_LD, risp->is_shdr->sh_type); 183 } 184 185 void 186 Dbg_reloc_doact_title(Lm_list *lml) 187 { 188 if (DBG_NOTCLASS(DBG_C_RELOC)) 189 return; 190 if (DBG_NOTDETAIL()) 191 return; 192 193 Dbg_util_nl(lml, DBG_NL_STD); 194 dbg_print(lml, MSG_INTL(MSG_REL_ACTIVE)); 195 Elf_reloc_title(lml, ELF_DBG_LD, 0); 196 } 197 198 void 199 Dbg_reloc_doact(Lm_list *lml, int caller, Half mach, Word type, Word rtype, 200 Xword off, Xword value, const char *symname, Os_desc *osp) 201 { 202 const char *secname; 203 204 if (DBG_NOTCLASS(DBG_C_RELOC)) 205 return; 206 if (DBG_NOTDETAIL()) 207 return; 208 209 if (osp) { 210 secname = osp->os_name; 211 off += osp->os_shdr->sh_offset; 212 } else 213 secname = MSG_ORIG(MSG_STR_EMPTY); 214 215 Elf_reloc_entry_2(lml, caller, MSG_ORIG(MSG_STR_EMPTY), type, 216 conv_reloc_type(mach, rtype, 0), off, value, secname, symname, 217 MSG_ORIG(MSG_STR_EMPTY)); 218 } 219 220 void 221 Dbg_reloc_dooutrel(Lm_list *lml, Word type) 222 { 223 if (DBG_NOTCLASS(DBG_C_RELOC)) 224 return; 225 if (DBG_NOTDETAIL()) 226 return; 227 228 Dbg_util_nl(lml, DBG_NL_STD); 229 dbg_print(lml, MSG_INTL(MSG_REL_CREATING)); 230 Elf_reloc_title(lml, ELF_DBG_LD, type); 231 } 232 233 void 234 Dbg_reloc_discard(Lm_list *lml, Half mach, Rel_desc *rsp) 235 { 236 if (DBG_NOTCLASS(DBG_C_RELOC)) 237 return; 238 if (DBG_NOTDETAIL()) 239 return; 240 241 dbg_print(lml, MSG_INTL(MSG_REL_DISCARDED), 242 rsp->rel_isdesc->is_basename, rsp->rel_isdesc->is_file->ifl_name, 243 conv_reloc_type(mach, rsp->rel_rtype, 0), 244 EC_OFF(rsp->rel_roffset)); 245 } 246 247 void 248 Dbg_reloc_transition(Lm_list *lml, Half mach, Word oldrtype, Word newrtype, 249 Xword off, const char *sym) 250 { 251 if (DBG_NOTCLASS(DBG_C_RELOC)) 252 return; 253 254 dbg_print(lml, MSG_INTL(MSG_REL_TRANS), EC_OFF(off), 255 conv_reloc_type(mach, oldrtype, 0) + M_R_STR_LEN, 256 conv_reloc_type(mach, newrtype, 0) + M_R_STR_LEN, sym); 257 } 258 259 void 260 Dbg_reloc_out(Ofl_desc *ofl, int caller, Word type, void *reloc, 261 const char *secname, const char *symname) 262 { 263 if (DBG_NOTCLASS(DBG_C_RELOC)) 264 return; 265 if (DBG_NOTDETAIL()) 266 return; 267 268 Elf_reloc_entry_1(ofl->ofl_lml, caller, MSG_ORIG(MSG_STR_EMPTY), 269 ofl->ofl_dehdr->e_machine, type, reloc, secname, symname, 270 MSG_ORIG(MSG_STR_EMPTY)); 271 } 272 273 void 274 Dbg_reloc_in(Lm_list *lml, int caller, Half mach, Word type, void *reloc, 275 const char *secname, const char *symname) 276 { 277 if (DBG_NOTCLASS(DBG_C_RELOC)) 278 return; 279 if (DBG_NOTDETAIL()) 280 return; 281 282 Elf_reloc_entry_1(lml, caller, MSG_INTL(MSG_STR_IN), mach, type, reloc, 283 secname, symname, MSG_ORIG(MSG_STR_EMPTY)); 284 } 285 286 /* 287 * Print a output relocation structure (Rel_desc). 288 */ 289 void 290 Dbg_reloc_ors_entry(Lm_list *lml, int caller, Word type, Half mach, 291 Rel_desc *orsp) 292 { 293 const char *secname, *symname; 294 295 if (DBG_NOTCLASS(DBG_C_RELOC)) 296 return; 297 if (DBG_NOTDETAIL()) 298 return; 299 300 if (orsp->rel_flags & (FLG_REL_GOT | FLG_REL_RFPTR1 | FLG_REL_RFPTR2)) 301 secname = MSG_ORIG(MSG_SCN_GOT); 302 else if (orsp->rel_flags & FLG_REL_PLT) 303 secname = MSG_ORIG(MSG_SCN_PLT); 304 else if (orsp->rel_flags & FLG_REL_BSS) 305 secname = MSG_ORIG(MSG_SCN_BSS); 306 else if (orsp->rel_osdesc) 307 secname = orsp->rel_osdesc->os_name; 308 else 309 secname = MSG_INTL(MSG_STR_NULL); 310 311 /* 312 * Register symbols can be relocated/initialized to a constant, which 313 * is a special case where the symbol index is 0. 314 */ 315 if (orsp->rel_sym != NULL) 316 symname = orsp->rel_sym->sd_name; 317 else 318 symname = MSG_ORIG(MSG_STR_EMPTY); 319 320 Elf_reloc_entry_2(lml, caller, MSG_INTL(MSG_STR_OUT), type, 321 conv_reloc_type(mach, orsp->rel_rtype, 0), orsp->rel_roffset, 322 orsp->rel_raddend, secname, symname, MSG_ORIG(MSG_STR_EMPTY)); 323 } 324 325 /* 326 * Print a Active relocation structure (Rel_desc). 327 */ 328 void 329 Dbg_reloc_ars_entry(Lm_list *lml, int caller, Word type, Half mach, 330 Rel_desc *arsp) 331 { 332 const char *secname; 333 334 if (DBG_NOTCLASS(DBG_C_RELOC)) 335 return; 336 if (DBG_NOTDETAIL()) 337 return; 338 339 if (arsp->rel_flags & (FLG_REL_GOT | FLG_REL_FPTR)) 340 secname = MSG_ORIG(MSG_SCN_GOT); 341 else 342 secname = arsp->rel_osdesc->os_name; 343 344 Elf_reloc_entry_2(lml, caller, MSG_INTL(MSG_STR_ACT), type, 345 conv_reloc_type(mach, arsp->rel_rtype, 0), arsp->rel_roffset, 346 arsp->rel_raddend, secname, arsp->rel_sym->sd_name, 347 MSG_ORIG(MSG_STR_EMPTY)); 348 } 349 350 void 351 Dbg_reloc_entry(Lm_list *lml, const char *prestr, Half mach, Word type, 352 void *reloc, const char *secname, const char *symname, const char *poststr) 353 { 354 /* 355 * Register relocations can use a constant initializer, in which case 356 * the associated symbol is 0. 357 */ 358 if (symname == NULL) 359 symname = MSG_ORIG(MSG_STR_EMPTY); 360 361 Elf_reloc_entry_1(lml, ELF_DBG_LD, prestr, mach, type, reloc, secname, 362 symname, poststr); 363 } 364 365 #if defined(_ELF64) 366 367 void 368 Dbg64_pltpad_to(Lm_list *lml, const char *file, Addr pltpad, 369 const char *dfile, const char *symname) 370 { 371 if (DBG_NOTCLASS(DBG_C_RELOC)) 372 return; 373 if (DBG_NOTDETAIL()) 374 return; 375 376 dbg_print(lml, MSG_INTL(MSG_BND_PLTPAD_TO), EC_ADDR(pltpad), file, 377 dfile, symname); 378 } 379 380 void 381 Dbg64_pltpad_from(Lm_list *lml, const char *file, const char *sname, 382 Addr pltpad) 383 { 384 if (DBG_NOTCLASS(DBG_C_RELOC)) 385 return; 386 if (DBG_NOTDETAIL()) 387 return; 388 389 dbg_print(lml, MSG_INTL(MSG_BND_PLTPAD_FROM), EC_ADDR(pltpad), file, 390 Dbg_demangle_name(sname)); 391 } 392 393 #endif 394 395 /* 396 * Relocation output can differ depending on the caller and the type of 397 * relocation record. However, the final diagnostic is maintained here so 398 * that the various message strings remain consistent. 399 * 400 * elfdump: 401 * type offset addend section symbol 402 * X X X X X (Rela) 403 * 404 * type offset section symbol 405 * X X X X (Rel) 406 * 407 * Note, it could be argued that the section name output with elfdump(1) is 408 * unnecessary, as the table itself is identified with a title that reveals 409 * the section name. However, the output does provide for grep(1)'ing for 410 * individual entries and obtaining the section name with this type of input. 411 * 412 * ld.so.1: 413 * (prestr) type offset addend symbol 414 * value 415 * in X X X X (Rela) 416 * apply X X 417 * 418 * (prestr) type offset value symbol 419 * in X X X (Rel) 420 * apply X X 421 * 422 * ld: 423 * (prestr) type offset addend section symbol 424 * in X X X X X (Rela) 425 * act X X X X 426 * out X X X X 427 * 428 * (prestr) type offset section symbol 429 * in X X X X (Rel) 430 * act X X X X 431 * out X X X X 432 * 433 * Both Rela and Rel active relocations are printed as: 434 * 435 * type offset value section symbol 436 * X X X X X 437 */ 438 void 439 Elf_reloc_title(Lm_list *lml, int caller, Word type) 440 { 441 if (caller == ELF_DBG_ELFDUMP) { 442 if (type == SHT_RELA) { 443 if (DBG_NOTLONG()) 444 dbg_print(lml, MSG_INTL(MSG_REL_EFSA_TITLE)); 445 else 446 dbg_print(lml, MSG_INTL(MSG_REL_EFLA_TITLE)); 447 } else { 448 if (DBG_NOTLONG()) 449 dbg_print(lml, MSG_INTL(MSG_REL_EFSN_TITLE)); 450 else 451 dbg_print(lml, MSG_INTL(MSG_REL_EFLN_TITLE)); 452 } 453 return; 454 } 455 if (caller == ELF_DBG_RTLD) { 456 if (type == SHT_RELA) { 457 dbg_print(lml, MSG_INTL(MSG_REL_RTA_TITLE)); 458 dbg_print(lml, MSG_INTL(MSG_REL_RTV_TITLE)); 459 } else 460 dbg_print(lml, MSG_INTL(MSG_REL_RTN_TITLE)); 461 return; 462 } 463 if (caller == ELF_DBG_LD) { 464 if (type == 0) { 465 if (DBG_NOTLONG()) 466 dbg_print(lml, MSG_INTL(MSG_REL_LDSV_TITLE)); 467 else 468 dbg_print(lml, MSG_INTL(MSG_REL_LDLV_TITLE)); 469 return; 470 } 471 if (type == SHT_RELA) { 472 if (DBG_NOTLONG()) 473 dbg_print(lml, MSG_INTL(MSG_REL_LDSA_TITLE)); 474 else 475 dbg_print(lml, MSG_INTL(MSG_REL_LDLA_TITLE)); 476 } else { 477 if (DBG_NOTLONG()) 478 dbg_print(lml, MSG_INTL(MSG_REL_LDSN_TITLE)); 479 else 480 dbg_print(lml, MSG_INTL(MSG_REL_LDLN_TITLE)); 481 } 482 } 483 } 484 485 void 486 Elf_reloc_entry_2(Lm_list *lml, int caller, const char *prestr, Word type, 487 const char *typestr, Addr off, Sxword add, const char *secname, 488 const char *symname, const char *poststr) 489 { 490 if (symname) 491 symname = Elf_demangle_name(symname); 492 else 493 symname = MSG_ORIG(MSG_STR_EMPTY); 494 495 if (caller == ELF_DBG_ELFDUMP) { 496 if (type == SHT_RELA) { 497 if (DBG_NOTLONG()) 498 dbg_print(lml, MSG_INTL(MSG_REL_EFSA_ENTRY), 499 typestr, EC_OFF(off), EC_SXWORD(add), 500 secname, symname); 501 else 502 dbg_print(lml, MSG_INTL(MSG_REL_EFLA_ENTRY), 503 typestr, EC_OFF(off), EC_SXWORD(add), 504 secname, symname); 505 } else { 506 if (DBG_NOTLONG()) 507 dbg_print(lml, MSG_INTL(MSG_REL_EFSN_ENTRY), 508 typestr, EC_OFF(off), secname, symname); 509 else 510 dbg_print(lml, MSG_INTL(MSG_REL_EFLN_ENTRY), 511 typestr, EC_OFF(off), secname, symname); 512 } 513 return; 514 } 515 if (caller == ELF_DBG_RTLD) { 516 if (type == SHT_RELA) 517 dbg_print(lml, MSG_INTL(MSG_REL_RTA_ENTRY), prestr, 518 typestr, EC_OFF(off), EC_SXWORD(add), symname); 519 else 520 dbg_print(lml, MSG_INTL(MSG_REL_RTN_ENTRY), prestr, 521 typestr, EC_OFF(off), symname); 522 return; 523 } 524 if (caller == ELF_DBG_LD) { 525 if (type == SHT_RELA) { 526 if (DBG_NOTLONG()) 527 dbg_print(lml, MSG_INTL(MSG_REL_LDSA_ENTRY), 528 prestr, typestr, EC_OFF(off), 529 EC_SXWORD(add), secname, symname, poststr); 530 else 531 dbg_print(lml, MSG_INTL(MSG_REL_LDLA_ENTRY), 532 prestr, typestr, EC_OFF(off), 533 EC_SXWORD(add), secname, symname, poststr); 534 } else { 535 if (DBG_NOTLONG()) 536 dbg_print(lml, MSG_INTL(MSG_REL_LDSN_ENTRY), 537 prestr, typestr, EC_OFF(off), secname, 538 symname, poststr); 539 else 540 dbg_print(lml, MSG_INTL(MSG_REL_LDLN_ENTRY), 541 prestr, typestr, EC_OFF(off), secname, 542 symname, poststr); 543 } 544 } 545 } 546 547 void 548 Elf_reloc_entry_1(Lm_list *lml, int caller, const char *prestr, Half mach, 549 Word type, void *reloc, const char *secname, const char *symname, 550 const char *poststr) 551 { 552 Addr off; 553 Sxword add; 554 const char *str; 555 556 if (type == SHT_RELA) { 557 Rela *rela = (Rela *)reloc; 558 559 str = conv_reloc_type(mach, ELF_R_TYPE(rela->r_info), 0); 560 off = rela->r_offset; 561 add = rela->r_addend; 562 } else { 563 Rel *rel = (Rel *)reloc; 564 565 str = conv_reloc_type(mach, ELF_R_TYPE(rel->r_info), 0); 566 off = rel->r_offset; 567 add = 0; 568 } 569 Elf_reloc_entry_2(lml, caller, prestr, type, str, off, add, secname, 570 symname, poststr); 571 } 572 573 /* 574 * Display any applied relocations. Presently, these are only called from 575 * ld.so.1, but the interfaces are maintained here to insure consistency with 576 * other relocation diagnostics. 577 */ 578 void 579 Elf_reloc_apply_val(Lm_list *lml, int caller, Xword offset, Xword value) 580 { 581 if (caller == ELF_DBG_RTLD) 582 dbg_print(lml, MSG_INTL(MSG_REL_RT_APLVAL), EC_XWORD(offset), 583 EC_XWORD(value)); 584 } 585 void 586 Elf_reloc_apply_reg(Lm_list *lml, int caller, Half mach, Xword offset, 587 Xword value) 588 { 589 if (caller == ELF_DBG_RTLD) 590 dbg_print(lml, MSG_INTL(MSG_REL_RT_APLREG), 591 conv_sym_value(mach, STT_SPARC_REGISTER, offset), 592 EC_XWORD(value)); 593 } 594