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