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