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