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