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 2007 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 Conv_inv_buf_t inv_buf; 203 const char *secname; 204 205 if (DBG_NOTCLASS(DBG_C_RELOC)) 206 return; 207 if (DBG_NOTDETAIL()) 208 return; 209 210 if (osp) { 211 secname = osp->os_name; 212 off += osp->os_shdr->sh_offset; 213 } else 214 secname = MSG_ORIG(MSG_STR_EMPTY); 215 216 Elf_reloc_entry_2(lml, caller, MSG_ORIG(MSG_STR_EMPTY), type, 217 conv_reloc_type(mach, rtype, 0, &inv_buf), 218 off, value, secname, symname, MSG_ORIG(MSG_STR_EMPTY)); 219 } 220 221 void 222 Dbg_reloc_dooutrel(Lm_list *lml, Word type) 223 { 224 if (DBG_NOTCLASS(DBG_C_RELOC)) 225 return; 226 if (DBG_NOTDETAIL()) 227 return; 228 229 Dbg_util_nl(lml, DBG_NL_STD); 230 dbg_print(lml, MSG_INTL(MSG_REL_CREATING)); 231 Elf_reloc_title(lml, ELF_DBG_LD, type); 232 } 233 234 void 235 Dbg_reloc_discard(Lm_list *lml, Half mach, Rel_desc *rsp) 236 { 237 Conv_inv_buf_t inv_buf; 238 Is_desc *isp; 239 240 if (DBG_NOTCLASS(DBG_C_RELOC)) 241 return; 242 if (DBG_NOTDETAIL()) 243 return; 244 245 isp = rsp->rel_isdesc; 246 dbg_print(lml, MSG_INTL(MSG_REL_DISCARDED), isp->is_basename, 247 isp->is_file->ifl_name, 248 conv_reloc_type(mach, rsp->rel_rtype, 0, &inv_buf), 249 EC_OFF(rsp->rel_roffset)); 250 } 251 252 void 253 Dbg_reloc_transition(Lm_list *lml, Half mach, Word rtype, Rel_desc *rsp) 254 { 255 Conv_inv_buf_t inv_buf1, inv_buf2; 256 Is_desc *isp; 257 258 if (DBG_NOTCLASS(DBG_C_RELOC)) 259 return; 260 261 isp = rsp->rel_isdesc; 262 dbg_print(lml, MSG_INTL(MSG_REL_TRANSITION), 263 conv_reloc_type(mach, rsp->rel_rtype, 0, &inv_buf1), 264 isp->is_basename, isp->is_file->ifl_name, 265 EC_OFF(rsp->rel_roffset), rsp->rel_sname, 266 conv_reloc_type(mach, rtype, 0, &inv_buf2)); 267 } 268 269 void 270 Dbg_reloc_out(Ofl_desc *ofl, int caller, Word type, void *reloc, 271 const char *secname, const char *symname) 272 { 273 if (DBG_NOTCLASS(DBG_C_RELOC)) 274 return; 275 if (DBG_NOTDETAIL()) 276 return; 277 278 Elf_reloc_entry_1(ofl->ofl_lml, caller, MSG_ORIG(MSG_STR_EMPTY), 279 ofl->ofl_dehdr->e_machine, type, reloc, secname, symname, 280 MSG_ORIG(MSG_STR_EMPTY)); 281 } 282 283 void 284 Dbg_reloc_in(Lm_list *lml, int caller, Half mach, Word type, void *reloc, 285 const char *secname, const char *symname) 286 { 287 if (DBG_NOTCLASS(DBG_C_RELOC)) 288 return; 289 if (DBG_NOTDETAIL()) 290 return; 291 292 Elf_reloc_entry_1(lml, caller, MSG_INTL(MSG_STR_IN), mach, type, reloc, 293 secname, symname, MSG_ORIG(MSG_STR_EMPTY)); 294 } 295 296 /* 297 * Used by ld when '-z relaxreloc' is in use and a relocation 298 * is redirected to a kept section. 299 * 300 * entry: 301 * lml - Link map control list 302 * sdp - The replacement symbol to be used with the relocation, 303 * which references the kept section. 304 */ 305 void 306 Dbg_reloc_sloppycomdat(Lm_list *lml, const char *secname, Sym_desc *sdp) 307 { 308 const char *nfname; 309 310 if (DBG_NOTCLASS(DBG_C_RELOC) || DBG_NOTDETAIL()) 311 return; 312 313 nfname = (sdp && sdp->sd_file && sdp->sd_file->ifl_name) 314 ? sdp->sd_file->ifl_name : MSG_INTL(MSG_STR_NULL); 315 316 dbg_print(lml, MSG_INTL(MSG_REL_SLOPPYCOMDAT), secname, nfname); 317 } 318 319 /* 320 * Print a output relocation structure (Rel_desc). 321 */ 322 void 323 Dbg_reloc_ors_entry(Lm_list *lml, int caller, Word type, Half mach, 324 Rel_desc *orsp) 325 { 326 Conv_inv_buf_t inv_buf; 327 const char *secname, *symname; 328 329 if (DBG_NOTCLASS(DBG_C_RELOC)) 330 return; 331 if (DBG_NOTDETAIL()) 332 return; 333 334 if (orsp->rel_flags & (FLG_REL_GOT | FLG_REL_RFPTR1 | FLG_REL_RFPTR2)) 335 secname = MSG_ORIG(MSG_SCN_GOT); 336 else if (orsp->rel_flags & FLG_REL_PLT) 337 secname = MSG_ORIG(MSG_SCN_PLT); 338 else if (orsp->rel_flags & FLG_REL_BSS) 339 secname = MSG_ORIG(MSG_SCN_BSS); 340 else if (orsp->rel_osdesc) 341 secname = orsp->rel_osdesc->os_name; 342 else 343 secname = MSG_INTL(MSG_STR_NULL); 344 345 /* 346 * Register symbols can be relocated/initialized to a constant, which 347 * is a special case where the symbol index is 0. 348 */ 349 if (orsp->rel_sym != NULL) 350 symname = orsp->rel_sym->sd_name; 351 else 352 symname = MSG_ORIG(MSG_STR_EMPTY); 353 354 Elf_reloc_entry_2(lml, caller, MSG_INTL(MSG_STR_OUT), type, 355 conv_reloc_type(mach, orsp->rel_rtype, 0, &inv_buf), 356 orsp->rel_roffset, orsp->rel_raddend, secname, symname, 357 MSG_ORIG(MSG_STR_EMPTY)); 358 } 359 360 /* 361 * Print a Active relocation structure (Rel_desc). 362 */ 363 void 364 Dbg_reloc_ars_entry(Lm_list *lml, int caller, Word type, Half mach, 365 Rel_desc *arsp) 366 { 367 Conv_inv_buf_t inv_buf; 368 const char *secname; 369 370 if (DBG_NOTCLASS(DBG_C_RELOC)) 371 return; 372 if (DBG_NOTDETAIL()) 373 return; 374 375 if (arsp->rel_flags & (FLG_REL_GOT | FLG_REL_FPTR)) 376 secname = MSG_ORIG(MSG_SCN_GOT); 377 else 378 secname = arsp->rel_osdesc->os_name; 379 380 Elf_reloc_entry_2(lml, caller, MSG_INTL(MSG_STR_ACT), type, 381 conv_reloc_type(mach, arsp->rel_rtype, 0, &inv_buf), 382 arsp->rel_roffset, arsp->rel_raddend, secname, 383 arsp->rel_sym->sd_name, MSG_ORIG(MSG_STR_EMPTY)); 384 } 385 386 void 387 Dbg_reloc_entry(Lm_list *lml, const char *prestr, Half mach, Word type, 388 void *reloc, const char *secname, const char *symname, const char *poststr) 389 { 390 /* 391 * Register relocations can use a constant initializer, in which case 392 * the associated symbol is 0. 393 */ 394 if (symname == NULL) 395 symname = MSG_ORIG(MSG_STR_EMPTY); 396 397 Elf_reloc_entry_1(lml, ELF_DBG_LD, prestr, mach, type, reloc, secname, 398 symname, poststr); 399 } 400 401 #if defined(_ELF64) 402 403 void 404 Dbg64_pltpad_to(Lm_list *lml, const char *file, Addr pltpad, 405 const char *dfile, const char *symname) 406 { 407 if (DBG_NOTCLASS(DBG_C_RELOC)) 408 return; 409 if (DBG_NOTDETAIL()) 410 return; 411 412 dbg_print(lml, MSG_INTL(MSG_BND_PLTPAD_TO), EC_ADDR(pltpad), file, 413 dfile, symname); 414 } 415 416 void 417 Dbg64_pltpad_from(Lm_list *lml, const char *file, const char *sname, 418 Addr pltpad) 419 { 420 if (DBG_NOTCLASS(DBG_C_RELOC)) 421 return; 422 if (DBG_NOTDETAIL()) 423 return; 424 425 dbg_print(lml, MSG_INTL(MSG_BND_PLTPAD_FROM), EC_ADDR(pltpad), file, 426 Dbg_demangle_name(sname)); 427 } 428 429 #endif 430 431 /* 432 * Relocation output can differ depending on the caller and the type of 433 * relocation record. However, the final diagnostic is maintained here so 434 * that the various message strings remain consistent. 435 * 436 * elfdump: 437 * type offset addend section symbol 438 * X X X X X (Rela) 439 * 440 * type offset section symbol 441 * X X X X (Rel) 442 * 443 * Note, it could be argued that the section name output with elfdump(1) is 444 * unnecessary, as the table itself is identified with a title that reveals 445 * the section name. However, the output does provide for grep(1)'ing for 446 * individual entries and obtaining the section name with this type of input. 447 * 448 * ld.so.1: 449 * (prestr) type offset addend symbol 450 * value 451 * in X X X X (Rela) 452 * apply X X 453 * 454 * (prestr) type offset value symbol 455 * in X X X (Rel) 456 * apply X X 457 * 458 * ld: 459 * (prestr) type offset addend section symbol 460 * in X X X X X (Rela) 461 * act X X X X 462 * out X X X X 463 * 464 * (prestr) type offset section symbol 465 * in X X X X (Rel) 466 * act X X X X 467 * out X X X X 468 * 469 * Both Rela and Rel active relocations are printed as: 470 * 471 * type offset value section symbol 472 * X X X X X 473 */ 474 void 475 Elf_reloc_title(Lm_list *lml, int caller, Word type) 476 { 477 if (caller == ELF_DBG_ELFDUMP) { 478 if (type == SHT_RELA) { 479 if (DBG_NOTLONG()) 480 dbg_print(lml, MSG_INTL(MSG_REL_EFSA_TITLE)); 481 else 482 dbg_print(lml, MSG_INTL(MSG_REL_EFLA_TITLE)); 483 } else { 484 if (DBG_NOTLONG()) 485 dbg_print(lml, MSG_INTL(MSG_REL_EFSN_TITLE)); 486 else 487 dbg_print(lml, MSG_INTL(MSG_REL_EFLN_TITLE)); 488 } 489 return; 490 } 491 if (caller == ELF_DBG_RTLD) { 492 if (type == SHT_RELA) { 493 dbg_print(lml, MSG_INTL(MSG_REL_RTA_TITLE)); 494 dbg_print(lml, MSG_INTL(MSG_REL_RTV_TITLE)); 495 } else 496 dbg_print(lml, MSG_INTL(MSG_REL_RTN_TITLE)); 497 return; 498 } 499 if (caller == ELF_DBG_LD) { 500 if (type == 0) { 501 if (DBG_NOTLONG()) 502 dbg_print(lml, MSG_INTL(MSG_REL_LDSV_TITLE)); 503 else 504 dbg_print(lml, MSG_INTL(MSG_REL_LDLV_TITLE)); 505 return; 506 } 507 if (type == SHT_RELA) { 508 if (DBG_NOTLONG()) 509 dbg_print(lml, MSG_INTL(MSG_REL_LDSA_TITLE)); 510 else 511 dbg_print(lml, MSG_INTL(MSG_REL_LDLA_TITLE)); 512 } else { 513 if (DBG_NOTLONG()) 514 dbg_print(lml, MSG_INTL(MSG_REL_LDSN_TITLE)); 515 else 516 dbg_print(lml, MSG_INTL(MSG_REL_LDLN_TITLE)); 517 } 518 } 519 } 520 521 void 522 Elf_reloc_entry_2(Lm_list *lml, int caller, const char *prestr, Word type, 523 const char *typestr, Addr off, Sxword add, const char *secname, 524 const char *symname, const char *poststr) 525 { 526 if (symname) 527 symname = Elf_demangle_name(symname); 528 else 529 symname = MSG_ORIG(MSG_STR_EMPTY); 530 531 if (caller == ELF_DBG_ELFDUMP) { 532 if (type == SHT_RELA) { 533 if (DBG_NOTLONG()) 534 dbg_print(lml, MSG_INTL(MSG_REL_EFSA_ENTRY), 535 typestr, EC_OFF(off), EC_SXWORD(add), 536 secname, symname); 537 else 538 dbg_print(lml, MSG_INTL(MSG_REL_EFLA_ENTRY), 539 typestr, EC_OFF(off), EC_SXWORD(add), 540 secname, symname); 541 } else { 542 if (DBG_NOTLONG()) 543 dbg_print(lml, MSG_INTL(MSG_REL_EFSN_ENTRY), 544 typestr, EC_OFF(off), secname, symname); 545 else 546 dbg_print(lml, MSG_INTL(MSG_REL_EFLN_ENTRY), 547 typestr, EC_OFF(off), secname, symname); 548 } 549 return; 550 } 551 if (caller == ELF_DBG_RTLD) { 552 if (type == SHT_RELA) 553 dbg_print(lml, MSG_INTL(MSG_REL_RTA_ENTRY), prestr, 554 typestr, EC_OFF(off), EC_SXWORD(add), symname, 555 poststr); 556 else 557 dbg_print(lml, MSG_INTL(MSG_REL_RTN_ENTRY), prestr, 558 typestr, EC_OFF(off), symname, poststr); 559 return; 560 } 561 if (caller == ELF_DBG_LD) { 562 if (type == SHT_RELA) { 563 if (DBG_NOTLONG()) 564 dbg_print(lml, MSG_INTL(MSG_REL_LDSA_ENTRY), 565 prestr, typestr, EC_OFF(off), 566 EC_SXWORD(add), secname, symname, poststr); 567 else 568 dbg_print(lml, MSG_INTL(MSG_REL_LDLA_ENTRY), 569 prestr, typestr, EC_OFF(off), 570 EC_SXWORD(add), secname, symname, poststr); 571 } else { 572 if (DBG_NOTLONG()) 573 dbg_print(lml, MSG_INTL(MSG_REL_LDSN_ENTRY), 574 prestr, typestr, EC_OFF(off), secname, 575 symname, poststr); 576 else 577 dbg_print(lml, MSG_INTL(MSG_REL_LDLN_ENTRY), 578 prestr, typestr, EC_OFF(off), secname, 579 symname, poststr); 580 } 581 } 582 } 583 584 void 585 Elf_reloc_entry_1(Lm_list *lml, int caller, const char *prestr, Half mach, 586 Word type, void *reloc, const char *secname, const char *symname, 587 const char *poststr) 588 { 589 Conv_inv_buf_t inv_buf; 590 Addr off; 591 Sxword add; 592 const char *str; 593 594 if (type == SHT_RELA) { 595 Rela *rela = (Rela *)reloc; 596 597 str = conv_reloc_type(mach, ELF_R_TYPE(rela->r_info), 598 0, &inv_buf); 599 off = rela->r_offset; 600 add = rela->r_addend; 601 } else { 602 Rel *rel = (Rel *)reloc; 603 604 str = conv_reloc_type(mach, ELF_R_TYPE(rel->r_info), 605 0, &inv_buf); 606 off = rel->r_offset; 607 add = 0; 608 } 609 Elf_reloc_entry_2(lml, caller, prestr, type, str, off, add, secname, 610 symname, poststr); 611 } 612 613 /* 614 * Display any applied relocations. Presently, these are only called from 615 * ld.so.1, but the interfaces are maintained here to insure consistency with 616 * other relocation diagnostics. 617 */ 618 void 619 Elf_reloc_apply_val(Lm_list *lml, int caller, Xword offset, Xword value) 620 { 621 if (caller == ELF_DBG_RTLD) 622 dbg_print(lml, MSG_INTL(MSG_REL_RT_APLVAL), EC_XWORD(offset), 623 EC_XWORD(value)); 624 } 625 void 626 Elf_reloc_apply_reg(Lm_list *lml, int caller, Half mach, Xword offset, 627 Xword value) 628 { 629 Conv_inv_buf_t inv_buf; 630 631 if (caller == ELF_DBG_RTLD) 632 dbg_print(lml, MSG_INTL(MSG_REL_RT_APLREG), 633 conv_sym_value(mach, STT_SPARC_REGISTER, 634 offset, &inv_buf), EC_XWORD(value)); 635 } 636