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