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