dynamic.c revision 2766:897bcb036a29
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/*
29 * String conversion routine for .dynamic tag entries.
30 */
31#include	<stdio.h>
32#include	<string.h>
33#include	<sys/elf_SPARC.h>
34#include	"rtld.h"
35#include	"_conv.h"
36#include	"dynamic_msg.h"
37
38#define	POSSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
39		MSG_DFP_LAZYLOAD_ALT_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
40		MSG_DFP_GROUPPERM_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
41		CONV_INV_STRSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
42
43const char *
44conv_dyn_posflag1(Xword flags, int fmt_flags)
45{
46	static char	string[POSSZ];
47	static Val_desc vda[] = {
48		{ DF_P1_LAZYLOAD,	MSG_ORIG(MSG_DFP_LAZYLOAD) },
49		{ DF_P1_GROUPPERM,	MSG_ORIG(MSG_DFP_GROUPPERM) },
50		{ 0,			0 }
51	};
52	static CONV_EXPN_FIELD_ARG conv_arg = { string, sizeof (string), vda };
53	static Val_desc vda_alt[] = {
54		{ DF_P1_LAZYLOAD,	MSG_ORIG(MSG_DFP_LAZYLOAD_ALT) },
55		{ DF_P1_GROUPPERM,	MSG_ORIG(MSG_DFP_GROUPPERM) },
56		{ 0,			0 }
57	};
58	static CONV_EXPN_FIELD_ARG conv_arg_alt = { string, sizeof (string),
59		vda_alt, NULL, 0, 0, MSG_ORIG(MSG_STR_EMPTY), NULL,
60		MSG_ORIG(MSG_STR_EMPTY) };
61
62	CONV_EXPN_FIELD_ARG *arg;
63
64	if (flags == 0)
65		return (MSG_ORIG(MSG_GBL_ZERO));
66
67	arg = (fmt_flags & CONV_FMT_ALTDUMP) ? &conv_arg_alt : &conv_arg;
68	arg->oflags = arg->rflags = flags;
69	(void) conv_expn_field(arg);
70
71	return ((const char *)string);
72}
73
74#define	FLAGSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
75		MSG_DF_ORIGIN_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
76		MSG_DF_SYMBOLIC_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
77		MSG_DF_TEXTREL_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
78		MSG_DF_BIND_NOW_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
79		MSG_DF_STATIC_TLS_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
80		CONV_INV_STRSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
81
82const char *
83conv_dyn_flag(Xword flags, int fmt_flags)
84{
85	static char	string[FLAGSZ];
86	static Val_desc vda[] = {
87		{ DF_ORIGIN,		MSG_ORIG(MSG_DF_ORIGIN) },
88		{ DF_SYMBOLIC,		MSG_ORIG(MSG_DF_SYMBOLIC) },
89		{ DF_TEXTREL,		MSG_ORIG(MSG_DF_TEXTREL) },
90		{ DF_BIND_NOW,		MSG_ORIG(MSG_DF_BIND_NOW) },
91		{ DF_STATIC_TLS,	MSG_ORIG(MSG_DF_STATIC_TLS) },
92		{ 0,			0 }
93	};
94	static CONV_EXPN_FIELD_ARG conv_arg = { string, sizeof (string), vda };
95
96	if (flags == 0)
97		return (MSG_ORIG(MSG_GBL_ZERO));
98
99	conv_arg.oflags = conv_arg.rflags = flags;
100	if (fmt_flags & CONV_FMT_ALTDUMP) {
101		conv_arg.prefix = conv_arg.suffix = MSG_ORIG(MSG_STR_EMPTY);
102	} else {
103		conv_arg.prefix = conv_arg.suffix = NULL;
104	}
105	(void) conv_expn_field(&conv_arg);
106
107	return ((const char *)string);
108}
109
110#define	FLAG1SZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
111		MSG_DF1_NOW_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
112		MSG_DF1_GLOBAL_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
113		MSG_DF1_GROUP_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
114		MSG_DF1_NODELETE_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
115		MSG_DF1_LOADFLTR_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
116		MSG_DF1_INITFIRST_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
117		MSG_DF1_NOOPEN_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
118		MSG_DF1_ORIGIN_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
119		MSG_DF1_DIRECT_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
120		MSG_DF1_TRANS_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
121		MSG_DF1_INTERPOSE_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
122		MSG_DF1_NODEFLIB_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
123		MSG_DF1_NODUMP_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
124		MSG_DF1_CONFALT_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
125		MSG_DF1_ENDFILTEE_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
126		MSG_DF1_DISPRELPND_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
127		MSG_DF1_DISPRELDNE_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
128		MSG_DF1_NODIRECT_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
129		MSG_DF1_IGNMULDEF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
130		MSG_DF1_NOKSYMS_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
131		MSG_DF1_NORELOC_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
132		MSG_DF1_NOHDR_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
133		CONV_INV_STRSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
134
135const char *
136conv_dyn_flag1(Xword flags)
137{
138	static char	string[FLAG1SZ];
139	static Val_desc vda[] = {
140		{ DF_1_NOW,		MSG_ORIG(MSG_DF1_NOW) },
141		{ DF_1_GLOBAL,		MSG_ORIG(MSG_DF1_GLOBAL) },
142		{ DF_1_GROUP,		MSG_ORIG(MSG_DF1_GROUP) },
143		{ DF_1_NODELETE,	MSG_ORIG(MSG_DF1_NODELETE) },
144		{ DF_1_LOADFLTR,	MSG_ORIG(MSG_DF1_LOADFLTR) },
145		{ DF_1_INITFIRST,	MSG_ORIG(MSG_DF1_INITFIRST) },
146		{ DF_1_NOOPEN,		MSG_ORIG(MSG_DF1_NOOPEN) },
147		{ DF_1_ORIGIN,		MSG_ORIG(MSG_DF1_ORIGIN) },
148		{ DF_1_DIRECT,		MSG_ORIG(MSG_DF1_DIRECT) },
149		{ DF_1_TRANS,		MSG_ORIG(MSG_DF1_TRANS) },
150		{ DF_1_INTERPOSE,	MSG_ORIG(MSG_DF1_INTERPOSE) },
151		{ DF_1_NODEFLIB,	MSG_ORIG(MSG_DF1_NODEFLIB) },
152		{ DF_1_NODUMP,		MSG_ORIG(MSG_DF1_NODUMP) },
153		{ DF_1_CONFALT,		MSG_ORIG(MSG_DF1_CONFALT) },
154		{ DF_1_ENDFILTEE,	MSG_ORIG(MSG_DF1_ENDFILTEE) },
155		{ DF_1_DISPRELPND,	MSG_ORIG(MSG_DF1_DISPRELPND) },
156		{ DF_1_DISPRELDNE,	MSG_ORIG(MSG_DF1_DISPRELDNE) },
157		{ DF_1_NODIRECT,	MSG_ORIG(MSG_DF1_NODIRECT) },
158		{ DF_1_IGNMULDEF,	MSG_ORIG(MSG_DF1_IGNMULDEF) },
159		{ DF_1_NOKSYMS,		MSG_ORIG(MSG_DF1_NOKSYMS) },
160		{ DF_1_NORELOC,		MSG_ORIG(MSG_DF1_NORELOC) },
161		{ DF_1_NOHDR,		MSG_ORIG(MSG_DF1_NOHDR) },
162		{ 0,			0 }
163	};
164	static CONV_EXPN_FIELD_ARG conv_arg = { string, sizeof (string), vda };
165
166	if (flags == 0)
167		return (MSG_ORIG(MSG_GBL_ZERO));
168
169	conv_arg.oflags = conv_arg.rflags = flags;
170	(void) conv_expn_field(&conv_arg);
171
172	return ((const char *)string);
173}
174
175#define	FEATSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
176		MSG_DTF_PARINIT_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
177		MSG_DTF_CONFEXP_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
178		CONV_INV_STRSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
179
180const char *
181conv_dyn_feature1(Xword flags, int fmt_flags)
182{
183	static char	string[FEATSZ];
184	static Val_desc vda[] = {
185		{ DTF_1_PARINIT,	MSG_ORIG(MSG_DTF_PARINIT) },
186		{ DTF_1_CONFEXP,	MSG_ORIG(MSG_DTF_CONFEXP) },
187		{ 0,			0 }
188	};
189	static CONV_EXPN_FIELD_ARG conv_arg = { string, sizeof (string), vda };
190
191	if (flags == 0)
192		return (MSG_ORIG(MSG_GBL_ZERO));
193
194	conv_arg.oflags = conv_arg.rflags = flags;
195	if (fmt_flags & CONV_FMT_ALTDUMP) {
196		conv_arg.prefix = conv_arg.suffix = MSG_ORIG(MSG_STR_EMPTY);
197	} else {
198		conv_arg.prefix = conv_arg.suffix = NULL;
199	}
200	(void) conv_expn_field(&conv_arg);
201
202	return ((const char *)string);
203}
204
205const char *
206conv_dyn_tag(Xword tag, Half mach, int fmt_flags)
207{
208	static char		string[CONV_INV_STRSIZE];
209	static const Msg	tags[DT_MAXPOSTAGS] = {
210		MSG_DYN_NULL,		MSG_DYN_NEEDED,
211		MSG_DYN_PLTRELSZ,	MSG_DYN_PLTGOT,
212		MSG_DYN_HASH,		MSG_DYN_STRTAB,
213		MSG_DYN_SYMTAB,		MSG_DYN_RELA,
214		MSG_DYN_RELASZ,		MSG_DYN_RELAENT,
215		MSG_DYN_STRSZ,		MSG_DYN_SYMENT,
216		MSG_DYN_INIT,		MSG_DYN_FINI,
217		MSG_DYN_SONAME,		MSG_DYN_RPATH,
218		MSG_DYN_SYMBOLIC,	MSG_DYN_REL,
219		MSG_DYN_RELSZ,		MSG_DYN_RELENT,
220		MSG_DYN_PLTREL,		MSG_DYN_DEBUG,
221		MSG_DYN_TEXTREL,	MSG_DYN_JMPREL,
222		MSG_DYN_BIND_NOW,	MSG_DYN_INIT_ARRAY,
223		MSG_DYN_FINI_ARRAY,	MSG_DYN_INIT_ARRAYSZ,
224		MSG_DYN_FINI_ARRAYSZ,	MSG_DYN_RUNPATH,
225		MSG_DYN_FLAGS,		MSG_DYN_NULL,
226		MSG_DYN_PREINIT_ARRAY,	MSG_DYN_PREINIT_ARRAYSZ
227	};
228	static const Msg	tags_alt[DT_MAXPOSTAGS] = {
229		MSG_DYN_NULL,		MSG_DYN_NEEDED,
230		MSG_DYN_PLTRELSZ_ALT,	MSG_DYN_PLTGOT,
231		MSG_DYN_HASH,		MSG_DYN_STRTAB,
232		MSG_DYN_SYMTAB,		MSG_DYN_RELA,
233		MSG_DYN_RELASZ,		MSG_DYN_RELAENT,
234		MSG_DYN_STRSZ,		MSG_DYN_SYMENT,
235		MSG_DYN_INIT,		MSG_DYN_FINI,
236		MSG_DYN_SONAME,		MSG_DYN_RPATH,
237		MSG_DYN_SYMBOLIC_ALT,	MSG_DYN_REL,
238		MSG_DYN_RELSZ,		MSG_DYN_RELENT,
239		MSG_DYN_PLTREL,		MSG_DYN_DEBUG,
240		MSG_DYN_TEXTREL,	MSG_DYN_JMPREL,
241		MSG_DYN_BIND_NOW,	MSG_DYN_INIT_ARRAY,
242		MSG_DYN_FINI_ARRAY,	MSG_DYN_INIT_ARRAYSZ,
243		MSG_DYN_FINI_ARRAYSZ,	MSG_DYN_RUNPATH,
244		MSG_DYN_FLAGS,		MSG_DYN_NULL,
245		MSG_DYN_PREINIT_ARRAY,	MSG_DYN_PREINIT_ARRAYSZ
246	};
247
248	if (tag < DT_MAXPOSTAGS) {
249		/*
250		 * Generic dynamic tags.
251		 */
252		return ((fmt_flags & CONV_FMTALTMASK)
253			? MSG_ORIG(tags_alt[tag]) : MSG_ORIG(tags[tag]));
254	} else {
255		/*
256		 * SUNW: DT_LOOS -> DT_HIOS range.
257		 */
258		if (tag == DT_SUNW_AUXILIARY)
259			return (MSG_ORIG(MSG_DYN_SUNW_AUXILIARY));
260		else if (tag == DT_SUNW_RTLDINF)
261			return (MSG_ORIG(MSG_DYN_SUNW_RTLDINF));
262		else if (tag == DT_SUNW_FILTER)
263			return (MSG_ORIG(MSG_DYN_SUNW_FILTER));
264		else if (tag == DT_SUNW_CAP)
265			return (MSG_ORIG(MSG_DYN_SUNW_CAP));
266		else if (tag == DT_SUNW_SYMTAB)
267			return (MSG_ORIG(MSG_DYN_SUNW_SYMTAB));
268		else if (tag == DT_SUNW_SYMSZ)
269			return (MSG_ORIG(MSG_DYN_SUNW_SYMSZ));
270
271		/*
272		 * SUNW: DT_VALRNGLO - DT_VALRNGHI range.
273		 */
274		else if (tag == DT_CHECKSUM)
275			return (MSG_ORIG(MSG_DYN_CHECKSUM));
276		else if (tag == DT_PLTPADSZ)
277			return (MSG_ORIG(MSG_DYN_PLTPADSZ));
278		else if (tag == DT_MOVEENT)
279			return (MSG_ORIG(MSG_DYN_MOVEENT));
280		else if (tag == DT_MOVESZ)
281			return (MSG_ORIG(MSG_DYN_MOVESZ));
282		else if (tag == DT_FEATURE_1)
283			return (MSG_ORIG(MSG_DYN_FEATURE_1));
284		else if (tag == DT_POSFLAG_1)
285			return (MSG_ORIG(MSG_DYN_POSFLAG_1));
286		else if (tag == DT_SYMINSZ)
287			return (MSG_ORIG(MSG_DYN_SYMINSZ));
288		else if (tag == DT_SYMINENT)
289			return (MSG_ORIG(MSG_DYN_SYMINENT));
290
291		/*
292		 * SUNW: DT_ADDRRNGLO - DT_ADDRRNGHI range.
293		 */
294		else if (tag == DT_CONFIG)
295			return (MSG_ORIG(MSG_DYN_CONFIG));
296		else if (tag == DT_DEPAUDIT)
297			return (MSG_ORIG(MSG_DYN_DEPAUDIT));
298		else if (tag == DT_AUDIT)
299			return (MSG_ORIG(MSG_DYN_AUDIT));
300		else if (tag == DT_PLTPAD)
301			return (MSG_ORIG(MSG_DYN_PLTPAD));
302		else if (tag == DT_MOVETAB)
303			return (MSG_ORIG(MSG_DYN_MOVETAB));
304		else if (tag == DT_SYMINFO)
305			return (MSG_ORIG(MSG_DYN_SYMINFO));
306
307		/*
308		 * SUNW: generic range.
309		 */
310		else if (tag == DT_VERSYM)
311			return (MSG_ORIG(MSG_DYN_VERSYM));
312		else if (tag == DT_RELACOUNT)
313			return (MSG_ORIG(MSG_DYN_RELACOUNT));
314		else if (tag == DT_RELCOUNT)
315			return (MSG_ORIG(MSG_DYN_RELCOUNT));
316		else if (tag == DT_FLAGS_1)
317			return (MSG_ORIG(MSG_DYN_FLAGS_1));
318		else if (tag == DT_VERDEF)
319			return (MSG_ORIG(MSG_DYN_VERDEF));
320		else if (tag == DT_VERDEFNUM)
321			return (MSG_ORIG(MSG_DYN_VERDEFNUM));
322		else if (tag == DT_VERNEED)
323			return (MSG_ORIG(MSG_DYN_VERNEED));
324		else if (tag == DT_VERNEEDNUM)
325			return (MSG_ORIG(MSG_DYN_VERNEEDNUM));
326		else if (tag == DT_AUXILIARY)
327			return (MSG_ORIG(MSG_DYN_AUXILIARY));
328		else if (tag == DT_USED)
329			return (MSG_ORIG(MSG_DYN_USED));
330		else if (tag == DT_FILTER)
331			return (MSG_ORIG(MSG_DYN_FILTER));
332
333		/*
334		 * SUNW: machine specific range.
335		 */
336		else if (((mach == EM_SPARC) || (mach == EM_SPARCV9) ||
337		    (mach == EM_SPARC32PLUS)) && (tag == DT_SPARC_REGISTER))
338			/* this is so x86 can display a sparc binary */
339			return (MSG_ORIG(MSG_DYN_REGISTER));
340		else if (tag == DT_DEPRECATED_SPARC_REGISTER)
341			return (MSG_ORIG(MSG_DYN_REGISTER));
342		else
343			return (conv_invalid_val(string, CONV_INV_STRSIZE,
344			    tag, fmt_flags));
345	}
346}
347
348#define	BINDTSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
349		MSG_BND_NEEDED_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
350		MSG_BND_REFER_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
351		MSG_BND_FILTER_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
352		CONV_INV_STRSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
353
354const char *
355conv_bnd_type(uint_t flags)
356{
357	static char	string[BINDTSZ];
358	static Val_desc vda[] = {
359		{ BND_NEEDED,		MSG_ORIG(MSG_BND_NEEDED) },
360		{ BND_REFER,		MSG_ORIG(MSG_BND_REFER) },
361		{ BND_FILTER,		MSG_ORIG(MSG_BND_FILTER) },
362		{ 0,			0 }
363	};
364	static CONV_EXPN_FIELD_ARG conv_arg = { string, sizeof (string), vda };
365
366	if (flags == 0)
367		return (MSG_ORIG(MSG_STR_EMPTY));
368
369	conv_arg.oflags = conv_arg.rflags = flags;
370	(void) conv_expn_field(&conv_arg);
371
372	return ((const char *)string);
373}
374
375/*
376 * Note, conv_bnd_obj() is called with either:
377 *	LML_FLG_OBJADDED (possibly with LML_FLG_OBJREEVAL added), or
378 *	LML_FLG_OBJDELETED, or
379 *	LML_FLG_ATEXIT.
380 */
381#define	BINDOSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
382		MSG_BND_ADDED_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
383		MSG_BND_REEVAL_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
384		CONV_INV_STRSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
385
386const char *
387conv_bnd_obj(uint_t flags)
388{
389	static char	string[BINDOSZ];
390	static Val_desc vda[] = {
391		{ LML_FLG_OBJADDED,	MSG_ORIG(MSG_BND_ADDED) },
392		{ LML_FLG_OBJREEVAL,	MSG_ORIG(MSG_BND_REEVAL) },
393		{ LML_FLG_OBJDELETED,	MSG_ORIG(MSG_BND_DELETED) },
394		{ LML_FLG_ATEXIT,	MSG_ORIG(MSG_BND_ATEXIT) },
395		{ 0,			0 }
396	};
397	static CONV_EXPN_FIELD_ARG conv_arg = { string, sizeof (string), vda };
398
399	if ((flags & (LML_FLG_OBJADDED | LML_FLG_OBJREEVAL |
400	    LML_FLG_OBJDELETED | LML_FLG_ATEXIT)) == 0)
401		return (MSG_ORIG(MSG_BND_REVISIT));
402
403	/*
404	 * Note, we're not worried about unknown flags for this family, only
405	 * the selected flags are of interest, so we leave conv_arg.rflags
406	 * set to 0.
407	 */
408	conv_arg.oflags = flags;
409	(void) conv_expn_field(&conv_arg);
410
411	return ((const char *)string);
412}
413