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