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 (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26/*
27 * String conversion routine for .dynamic tag entries.
28 */
29#include	<stdio.h>
30#include	<string.h>
31#include	<sys/elf_SPARC.h>
32#include	"rtld.h"
33#include	"_conv.h"
34#include	"dynamic_msg.h"
35
36
37
38const Val_desc *
39conv_dyn_posflag1_strings(Conv_fmt_flags_t fmt_flags)
40{
41#define	POSSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
42	MSG_DF_P1_LAZYLOAD_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
43	MSG_DF_P1_GROUPPERM_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
44	MSG_DF_P1_DEFERRED_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
45	CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
46
47	/*
48	 * Ensure that Conv_dyn_posflag1_buf_t is large enough:
49	 *
50	 * POSSZ is the real minimum size of the buffer required by
51	 * conv_dyn_posflag1(). However, Conv_dyn_posflag1_buf_t uses
52	 * CONV_DYN_POSFLAG1_BUFSIZE to set the buffer size. We do things
53	 * this way because the definition of POSSZ uses
54	 * information that is not available in the environment of other
55	 * programs that include the conv.h header file.
56	 */
57#if (CONV_DYN_POSFLAG1_BUFSIZE != POSSZ) && !defined(__lint)
58#define	REPORT_BUFSIZE POSSZ
59#include "report_bufsize.h"
60#error "CONV_DYN_POSFLAG1_BUFSIZE does not match POSSZ"
61#endif
62
63	static const Val_desc vda_def[] = {
64		{ DF_P1_LAZYLOAD,	MSG_DF_P1_LAZYLOAD_DEF },
65		{ DF_P1_GROUPPERM,	MSG_DF_P1_GROUPPERM_DEF },
66		{ DF_P1_DEFERRED,	MSG_DF_P1_DEFERRED_DEF },
67		{ 0,			0 }
68	};
69	static const Val_desc vda_cf[] = {
70		{ DF_P1_LAZYLOAD,	MSG_DF_P1_LAZYLOAD_CF },
71		{ DF_P1_GROUPPERM,	MSG_DF_P1_GROUPPERM_CF },
72		{ DF_P1_DEFERRED,	MSG_DF_P1_DEFERRED_CF },
73		{ 0,			0 }
74	};
75	static const Val_desc vda_cfnp[] = {
76		{ DF_P1_LAZYLOAD,	MSG_DF_P1_LAZYLOAD_CFNP },
77		{ DF_P1_GROUPPERM,	MSG_DF_P1_GROUPPERM_CFNP },
78		{ DF_P1_DEFERRED,	MSG_DF_P1_DEFERRED_CFNP },
79		{ 0,			0 }
80	};
81	static const Val_desc vda_nf[] = {
82		{ DF_P1_LAZYLOAD,	MSG_DF_P1_LAZYLOAD_NF },
83		{ DF_P1_GROUPPERM,	MSG_DF_P1_GROUPPERM_NF },
84		{ DF_P1_DEFERRED,	MSG_DF_P1_DEFERRED_NF },
85		{ 0,			0 }
86	};
87
88	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
89	case CONV_FMT_ALT_DUMP:
90	case CONV_FMT_ALT_CFNP:
91		return (vda_cfnp);
92	case CONV_FMT_ALT_CF:
93		return (vda_cf);
94	case CONV_FMT_ALT_NF:
95		return (vda_nf);
96	}
97
98	return (vda_def);
99}
100
101conv_iter_ret_t
102conv_iter_dyn_posflag1(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
103    void *uvalue)
104{
105	return (conv_iter_vd(conv_dyn_posflag1_strings(fmt_flags),
106	    func, uvalue));
107}
108
109const Val_desc *
110conv_dyn_flag_strings(Conv_fmt_flags_t fmt_flags)
111{
112#define	FLAGSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
113	MSG_DF_ORIGIN_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
114	MSG_DF_SYMBOLIC_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
115	MSG_DF_TEXTREL_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
116	MSG_DF_BIND_NOW_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
117	MSG_DF_STATIC_TLS_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
118	CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
119
120	/*
121	 * Ensure that Conv_dyn_flag_buf_t is large enough:
122	 *
123	 * FLAGSZ is the real minimum size of the buffer required by
124	 * conv_dyn_flag(). However, Conv_dyn_flag_buf_t uses
125	 * CONV_DYN_FLAG_BUFSIZE to set the buffer size. We do things this
126	 * way because the definition of FLAGSZ uses information that is not
127	 * available in the environment of other programs that include the
128	 * conv.h header file.
129	 */
130#if (CONV_DYN_FLAG_BUFSIZE != FLAGSZ) && !defined(__lint)
131#define	REPORT_BUFSIZE FLAGSZ
132#include "report_bufsize.h"
133#error "CONV_DYN_FLAG_BUFSIZE does not match FLAGSZ"
134#endif
135
136	static const Val_desc vda_cf[] = {
137		{ DF_ORIGIN,		MSG_DF_ORIGIN_CF },
138		{ DF_SYMBOLIC,		MSG_DF_SYMBOLIC_CF },
139		{ DF_TEXTREL,		MSG_DF_TEXTREL_CF },
140		{ DF_BIND_NOW,		MSG_DF_BIND_NOW_CF },
141		{ DF_STATIC_TLS,	MSG_DF_STATIC_TLS_CF },
142		{ 0 }
143	};
144	static const Val_desc vda_cfnp[] = {
145		{ DF_ORIGIN,		MSG_DF_ORIGIN_CFNP },
146		{ DF_SYMBOLIC,		MSG_DF_SYMBOLIC_CFNP },
147		{ DF_TEXTREL,		MSG_DF_TEXTREL_CFNP },
148		{ DF_BIND_NOW,		MSG_DF_BIND_NOW_CFNP },
149		{ DF_STATIC_TLS,	MSG_DF_STATIC_TLS_CFNP },
150		{ 0 }
151	};
152	static const Val_desc vda_nf[] = {
153		{ DF_ORIGIN,		MSG_DF_ORIGIN_NF },
154		{ DF_SYMBOLIC,		MSG_DF_SYMBOLIC_NF },
155		{ DF_TEXTREL,		MSG_DF_TEXTREL_NF },
156		{ DF_BIND_NOW,		MSG_DF_BIND_NOW_NF },
157		{ DF_STATIC_TLS,	MSG_DF_STATIC_TLS_NF },
158		{ 0 }
159	};
160
161	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
162	case CONV_FMT_ALT_CF:
163		return (vda_cf);
164	case CONV_FMT_ALT_NF:
165		return (vda_nf);
166	}
167
168	return (vda_cfnp);
169}
170
171conv_iter_ret_t
172conv_iter_dyn_flag(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
173    void *uvalue)
174{
175	return (conv_iter_vd(conv_dyn_flag_strings(fmt_flags), func, uvalue));
176}
177
178const Val_desc *
179conv_dyn_flag1_strings(Conv_fmt_flags_t fmt_flags)
180{
181#define	FLAG1SZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
182	MSG_DF_1_NOW_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
183	MSG_DF_1_GLOBAL_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
184	MSG_DF_1_GROUP_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
185	MSG_DF_1_NODELETE_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
186	MSG_DF_1_LOADFLTR_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
187	MSG_DF_1_INITFIRST_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
188	MSG_DF_1_NOOPEN_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
189	MSG_DF_1_ORIGIN_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
190	MSG_DF_1_DIRECT_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
191	MSG_DF_1_TRANS_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
192	MSG_DF_1_INTERPOSE_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
193	MSG_DF_1_NODEFLIB_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
194	MSG_DF_1_NODUMP_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
195	MSG_DF_1_CONFALT_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
196	MSG_DF_1_ENDFILTEE_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
197	MSG_DF_1_DISPRELPND_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
198	MSG_DF_1_DISPRELDNE_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
199	MSG_DF_1_NODIRECT_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
200	MSG_DF_1_IGNMULDEF_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
201	MSG_DF_1_NOKSYMS_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
202	MSG_DF_1_NOHDR_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
203	MSG_DF_1_NORELOC_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
204	MSG_DF_1_SYMINTPOSE_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
205	MSG_DF_1_GLOBAUDIT_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
206	MSG_DF_1_SINGLETON_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
207	CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
208
209	/*
210	 * Ensure that Conv_dyn_flag1_buf_t is large enough:
211	 *
212	 * FLAG1SZ is the real minimum size of the buffer required by
213	 * conv_dyn_flag1(). However, Conv_dyn_flag1_buf_t uses
214	 * CONV_DYN_FLAG1_BUFSIZE to set the buffer size. We do things this
215	 * way because the definition of FLAG1SZ uses information that is not
216	 * available in the environment of other programs that include the
217	 * conv.h header file.
218	 */
219#if (CONV_DYN_FLAG1_BUFSIZE != FLAG1SZ) && !defined(__lint)
220#define	REPORT_BUFSIZE FLAG1SZ
221#include "report_bufsize.h"
222#error "CONV_DYN_FLAG1_BUFSIZE does not match FLAG1SZ"
223#endif
224
225	static const Val_desc vda_def[] = {
226		{ DF_1_NOW,		MSG_DF_1_NOW_CFNP },
227		{ DF_1_GLOBAL,		MSG_DF_1_GLOBAL_CFNP },
228		{ DF_1_GROUP,		MSG_DF_1_GROUP_CFNP },
229		{ DF_1_NODELETE,	MSG_DF_1_NODELETE_CFNP },
230		{ DF_1_LOADFLTR,	MSG_DF_1_LOADFLTR_CFNP },
231		{ DF_1_INITFIRST,	MSG_DF_1_INITFIRST_CFNP },
232		{ DF_1_NOOPEN,		MSG_DF_1_NOOPEN_CFNP },
233		{ DF_1_ORIGIN,		MSG_DF_1_ORIGIN_CFNP },
234		{ DF_1_DIRECT,		MSG_DF_1_DIRECT_CFNP },
235		{ DF_1_TRANS,		MSG_DF_1_TRANS_CFNP },
236		{ DF_1_INTERPOSE,	MSG_DF_1_INTERPOSE_DEF },
237		{ DF_1_NODEFLIB,	MSG_DF_1_NODEFLIB_CFNP },
238		{ DF_1_NODUMP,		MSG_DF_1_NODUMP_CFNP },
239		{ DF_1_CONFALT,		MSG_DF_1_CONFALT_CFNP },
240		{ DF_1_ENDFILTEE,	MSG_DF_1_ENDFILTEE_CFNP },
241		{ DF_1_DISPRELDNE,	MSG_DF_1_DISPRELDNE_DEF },
242		{ DF_1_DISPRELPND,	MSG_DF_1_DISPRELPND_DEF },
243		{ DF_1_NODIRECT,	MSG_DF_1_NODIRECT_CFNP },
244		{ DF_1_IGNMULDEF,	MSG_DF_1_IGNMULDEF_DEF },
245		{ DF_1_NOKSYMS,		MSG_DF_1_NOKSYMS_CFNP },
246		{ DF_1_NOHDR,		MSG_DF_1_NOHDR_CFNP },
247		{ DF_1_EDITED,		MSG_DF_1_EDITED_CFNP },
248		{ DF_1_NORELOC,		MSG_DF_1_NORELOC_CFNP },
249		{ DF_1_SYMINTPOSE,	MSG_DF_1_SYMINTPOSE_DEF },
250		{ DF_1_GLOBAUDIT,	MSG_DF_1_GLOBAUDIT_DEF },
251		{ DF_1_SINGLETON,	MSG_DF_1_SINGLETON_DEF },
252		{ 0,			0 }
253	};
254	static const Val_desc vda_cf[] = {
255		{ DF_1_NOW,		MSG_DF_1_NOW_CF },
256		{ DF_1_GLOBAL,		MSG_DF_1_GLOBAL_CF },
257		{ DF_1_GROUP,		MSG_DF_1_GROUP_CF },
258		{ DF_1_NODELETE,	MSG_DF_1_NODELETE_CF },
259		{ DF_1_LOADFLTR,	MSG_DF_1_LOADFLTR_CF },
260		{ DF_1_INITFIRST,	MSG_DF_1_INITFIRST_CF },
261		{ DF_1_NOOPEN,		MSG_DF_1_NOOPEN_CF },
262		{ DF_1_ORIGIN,		MSG_DF_1_ORIGIN_CF },
263		{ DF_1_DIRECT,		MSG_DF_1_DIRECT_CF },
264		{ DF_1_TRANS,		MSG_DF_1_TRANS_CF },
265		{ DF_1_INTERPOSE,	MSG_DF_1_INTERPOSE_CF },
266		{ DF_1_NODEFLIB,	MSG_DF_1_NODEFLIB_CF },
267		{ DF_1_NODUMP,		MSG_DF_1_NODUMP_CF },
268		{ DF_1_CONFALT,		MSG_DF_1_CONFALT_CF },
269		{ DF_1_ENDFILTEE,	MSG_DF_1_ENDFILTEE_CF },
270		{ DF_1_DISPRELDNE,	MSG_DF_1_DISPRELDNE_CF },
271		{ DF_1_DISPRELPND,	MSG_DF_1_DISPRELPND_CF },
272		{ DF_1_NODIRECT,	MSG_DF_1_NODIRECT_CF },
273		{ DF_1_IGNMULDEF,	MSG_DF_1_IGNMULDEF_CF },
274		{ DF_1_NOKSYMS,		MSG_DF_1_NOKSYMS_CF },
275		{ DF_1_NOHDR,		MSG_DF_1_NOHDR_CF },
276		{ DF_1_EDITED,		MSG_DF_1_EDITED_CF },
277		{ DF_1_NORELOC,		MSG_DF_1_NORELOC_CF },
278		{ DF_1_SYMINTPOSE,	MSG_DF_1_SYMINTPOSE_CF },
279		{ DF_1_GLOBAUDIT,	MSG_DF_1_GLOBAUDIT_CF },
280		{ DF_1_SINGLETON,	MSG_DF_1_SINGLETON_CF },
281		{ 0,			0 }
282	};
283	static const Val_desc vda_cfnp[] = {
284		{ DF_1_NOW,		MSG_DF_1_NOW_CFNP },
285		{ DF_1_GLOBAL,		MSG_DF_1_GLOBAL_CFNP },
286		{ DF_1_GROUP,		MSG_DF_1_GROUP_CFNP },
287		{ DF_1_NODELETE,	MSG_DF_1_NODELETE_CFNP },
288		{ DF_1_LOADFLTR,	MSG_DF_1_LOADFLTR_CFNP },
289		{ DF_1_INITFIRST,	MSG_DF_1_INITFIRST_CFNP },
290		{ DF_1_NOOPEN,		MSG_DF_1_NOOPEN_CFNP },
291		{ DF_1_ORIGIN,		MSG_DF_1_ORIGIN_CFNP },
292		{ DF_1_DIRECT,		MSG_DF_1_DIRECT_CFNP },
293		{ DF_1_TRANS,		MSG_DF_1_TRANS_CFNP },
294		{ DF_1_INTERPOSE,	MSG_DF_1_INTERPOSE_CFNP },
295		{ DF_1_NODEFLIB,	MSG_DF_1_NODEFLIB_CFNP },
296		{ DF_1_NODUMP,		MSG_DF_1_NODUMP_CFNP },
297		{ DF_1_CONFALT,		MSG_DF_1_CONFALT_CFNP },
298		{ DF_1_ENDFILTEE,	MSG_DF_1_ENDFILTEE_CFNP },
299		{ DF_1_DISPRELDNE,	MSG_DF_1_DISPRELDNE_CFNP },
300		{ DF_1_DISPRELPND,	MSG_DF_1_DISPRELPND_CFNP },
301		{ DF_1_NODIRECT,	MSG_DF_1_NODIRECT_CFNP },
302		{ DF_1_IGNMULDEF,	MSG_DF_1_IGNMULDEF_CFNP },
303		{ DF_1_NOKSYMS,		MSG_DF_1_NOKSYMS_CFNP },
304		{ DF_1_NOHDR,		MSG_DF_1_NOHDR_CFNP },
305		{ DF_1_EDITED,		MSG_DF_1_EDITED_CFNP },
306		{ DF_1_NORELOC,		MSG_DF_1_NORELOC_CFNP },
307		{ DF_1_SYMINTPOSE,	MSG_DF_1_SYMINTPOSE_CFNP },
308		{ DF_1_GLOBAUDIT,	MSG_DF_1_GLOBAUDIT_CFNP },
309		{ DF_1_SINGLETON,	MSG_DF_1_SINGLETON_CFNP },
310		{ 0,			0 }
311	};
312	static const Val_desc vda_nf[] = {
313		{ DF_1_NOW,		MSG_DF_1_NOW_NF },
314		{ DF_1_GLOBAL,		MSG_DF_1_GLOBAL_NF },
315		{ DF_1_GROUP,		MSG_DF_1_GROUP_NF },
316		{ DF_1_NODELETE,	MSG_DF_1_NODELETE_NF },
317		{ DF_1_LOADFLTR,	MSG_DF_1_LOADFLTR_NF },
318		{ DF_1_INITFIRST,	MSG_DF_1_INITFIRST_NF },
319		{ DF_1_NOOPEN,		MSG_DF_1_NOOPEN_NF },
320		{ DF_1_ORIGIN,		MSG_DF_1_ORIGIN_NF },
321		{ DF_1_DIRECT,		MSG_DF_1_DIRECT_NF },
322		{ DF_1_TRANS,		MSG_DF_1_TRANS_NF },
323		{ DF_1_INTERPOSE,	MSG_DF_1_INTERPOSE_NF },
324		{ DF_1_NODEFLIB,	MSG_DF_1_NODEFLIB_NF },
325		{ DF_1_NODUMP,		MSG_DF_1_NODUMP_NF },
326		{ DF_1_CONFALT,		MSG_DF_1_CONFALT_NF },
327		{ DF_1_ENDFILTEE,	MSG_DF_1_ENDFILTEE_NF },
328		{ DF_1_DISPRELDNE,	MSG_DF_1_DISPRELDNE_NF },
329		{ DF_1_DISPRELPND,	MSG_DF_1_DISPRELPND_NF },
330		{ DF_1_NODIRECT,	MSG_DF_1_NODIRECT_NF },
331		{ DF_1_IGNMULDEF,	MSG_DF_1_IGNMULDEF_NF },
332		{ DF_1_NOKSYMS,		MSG_DF_1_NOKSYMS_NF },
333		{ DF_1_NOHDR,		MSG_DF_1_NOHDR_NF },
334		{ DF_1_EDITED,		MSG_DF_1_EDITED_NF },
335		{ DF_1_NORELOC,		MSG_DF_1_NORELOC_NF },
336		{ DF_1_SYMINTPOSE,	MSG_DF_1_SYMINTPOSE_NF },
337		{ DF_1_GLOBAUDIT,	MSG_DF_1_GLOBAUDIT_NF },
338		{ DF_1_SINGLETON,	MSG_DF_1_SINGLETON_NF },
339		{ 0,			0 }
340	};
341
342	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
343	case CONV_FMT_ALT_CF:
344		return (vda_cf);
345	case CONV_FMT_ALT_CFNP:
346		return (vda_cfnp);
347	case CONV_FMT_ALT_NF:
348		return (vda_nf);
349	}
350
351	return (vda_def);
352}
353
354conv_iter_ret_t
355conv_iter_dyn_flag1(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
356    void *uvalue)
357{
358	return (conv_iter_vd(conv_dyn_flag1_strings(fmt_flags), func, uvalue));
359}
360
361const Val_desc *
362conv_dyn_feature1_strings(Conv_fmt_flags_t fmt_flags)
363{
364#define	FEATSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
365	MSG_DTF_1_PARINIT_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
366	MSG_DTF_1_CONFEXP_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
367	CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
368
369	/*
370	 * Ensure that Conv_dyn_feature1_buf_t is large enough:
371	 *
372	 * FEATSZ is the real min size of the buffer required by
373	 * conv_dyn_feature1(). However, Conv_dyn_feature1_buf_t uses
374	 * CONV_DYN_FEATURE1_BUFSIZE to set the buffer size. We do things
375	 * this way because the definition of FEATSZ uses information that
376	 * is not available in the environment of other programs that include
377	 * the conv.h header file.
378	 */
379#if (CONV_DYN_FEATURE1_BUFSIZE != FEATSZ) && !defined(__lint)
380#define	REPORT_BUFSIZE FEATSZ
381#include "report_bufsize.h"
382#error "CONV_DYN_FEATURE1_BUFSIZE does not match FEATSZ"
383#endif
384
385	static const Val_desc vda_cf[] = {
386		{ DTF_1_PARINIT,	MSG_DTF_1_PARINIT_CF },
387		{ DTF_1_CONFEXP,	MSG_DTF_1_CONFEXP_CF },
388		{ 0,			0 }
389	};
390	static const Val_desc vda_cfnp[] = {
391		{ DTF_1_PARINIT,	MSG_DTF_1_PARINIT_CFNP },
392		{ DTF_1_CONFEXP,	MSG_DTF_1_CONFEXP_CFNP },
393		{ 0,			0 }
394	};
395	static const Val_desc vda_nf[] = {
396		{ DTF_1_PARINIT,	MSG_DTF_1_PARINIT_NF },
397		{ DTF_1_CONFEXP,	MSG_DTF_1_CONFEXP_NF },
398		{ 0,			0 }
399	};
400
401	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
402	case CONV_FMT_ALT_CF:
403		return (vda_cf);
404	case CONV_FMT_ALT_NF:
405		return (vda_nf);
406	}
407
408	return (vda_cfnp);
409}
410
411conv_iter_ret_t
412conv_iter_dyn_feature1(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
413    void *uvalue)
414{
415	return (conv_iter_vd(conv_dyn_feature1_strings(fmt_flags),
416	    func, uvalue));
417}
418
419const conv_ds_t **
420conv_dyn_tag_strings(conv_iter_osabi_t osabi, Half mach,
421    Conv_fmt_flags_t fmt_flags)
422{
423	/*
424	 * Maximum # of items that can be in the returned array. Size this
425	 * by counting the maximum depth in the switch statement that fills
426	 * retarr at the end of this function.
427	 */
428#define	MAX_RET	12
429
430	/*
431	 * Generic dynamic tags:
432	 * -	Note hole between DT_FLAGS and DT_PREINIT_ARRAY (tag 32).
433	 *	We use a 0, which is the signal for "not defined".
434	 * -	This range has alternative names for dump, requiring an
435	 *	additional array.
436	 */
437	static const Msg	tags_null_cf[] = {
438		MSG_DT_NULL_CF,			MSG_DT_NEEDED_CF,
439		MSG_DT_PLTRELSZ_CF,		MSG_DT_PLTGOT_CF,
440		MSG_DT_HASH_CF,			MSG_DT_STRTAB_CF,
441		MSG_DT_SYMTAB_CF,		MSG_DT_RELA_CF,
442		MSG_DT_RELASZ_CF,		MSG_DT_RELAENT_CF,
443		MSG_DT_STRSZ_CF,		MSG_DT_SYMENT_CF,
444		MSG_DT_INIT_CF,			MSG_DT_FINI_CF,
445		MSG_DT_SONAME_CF,		MSG_DT_RPATH_CF,
446		MSG_DT_SYMBOLIC_CF,		MSG_DT_REL_CF,
447		MSG_DT_RELSZ_CF,		MSG_DT_RELENT_CF,
448		MSG_DT_PLTREL_CF,		MSG_DT_DEBUG_CF,
449		MSG_DT_TEXTREL_CF,		MSG_DT_JMPREL_CF,
450		MSG_DT_BIND_NOW_CF,		MSG_DT_INIT_ARRAY_CF,
451		MSG_DT_FINI_ARRAY_CF,		MSG_DT_INIT_ARRAYSZ_CF,
452		MSG_DT_FINI_ARRAYSZ_CF,		MSG_DT_RUNPATH_CF,
453		MSG_DT_FLAGS_CF,		0,
454		MSG_DT_PREINIT_ARRAY_CF,	MSG_DT_PREINIT_ARRAYSZ_CF
455	};
456	static const Msg	tags_null_cfnp[] = {
457		MSG_DT_NULL_CFNP,		MSG_DT_NEEDED_CFNP,
458		MSG_DT_PLTRELSZ_CFNP,		MSG_DT_PLTGOT_CFNP,
459		MSG_DT_HASH_CFNP,		MSG_DT_STRTAB_CFNP,
460		MSG_DT_SYMTAB_CFNP,		MSG_DT_RELA_CFNP,
461		MSG_DT_RELASZ_CFNP,		MSG_DT_RELAENT_CFNP,
462		MSG_DT_STRSZ_CFNP,		MSG_DT_SYMENT_CFNP,
463		MSG_DT_INIT_CFNP,		MSG_DT_FINI_CFNP,
464		MSG_DT_SONAME_CFNP,		MSG_DT_RPATH_CFNP,
465		MSG_DT_SYMBOLIC_CFNP,		MSG_DT_REL_CFNP,
466		MSG_DT_RELSZ_CFNP,		MSG_DT_RELENT_CFNP,
467		MSG_DT_PLTREL_CFNP,		MSG_DT_DEBUG_CFNP,
468		MSG_DT_TEXTREL_CFNP,		MSG_DT_JMPREL_CFNP,
469		MSG_DT_BIND_NOW_CFNP,		MSG_DT_INIT_ARRAY_CFNP,
470		MSG_DT_FINI_ARRAY_CFNP,		MSG_DT_INIT_ARRAYSZ_CFNP,
471		MSG_DT_FINI_ARRAYSZ_CFNP,	MSG_DT_RUNPATH_CFNP,
472		MSG_DT_FLAGS_CFNP,		0,
473		MSG_DT_PREINIT_ARRAY_CFNP,	MSG_DT_PREINIT_ARRAYSZ_CFNP
474	};
475	static const Msg	tags_null_nf[] = {
476		MSG_DT_NULL_NF,			MSG_DT_NEEDED_NF,
477		MSG_DT_PLTRELSZ_NF,		MSG_DT_PLTGOT_NF,
478		MSG_DT_HASH_NF,			MSG_DT_STRTAB_NF,
479		MSG_DT_SYMTAB_NF,		MSG_DT_RELA_NF,
480		MSG_DT_RELASZ_NF,		MSG_DT_RELAENT_NF,
481		MSG_DT_STRSZ_NF,		MSG_DT_SYMENT_NF,
482		MSG_DT_INIT_NF,			MSG_DT_FINI_NF,
483		MSG_DT_SONAME_NF,		MSG_DT_RPATH_NF,
484		MSG_DT_SYMBOLIC_NF,		MSG_DT_REL_NF,
485		MSG_DT_RELSZ_NF,		MSG_DT_RELENT_NF,
486		MSG_DT_PLTREL_NF,		MSG_DT_DEBUG_NF,
487		MSG_DT_TEXTREL_NF,		MSG_DT_JMPREL_NF,
488		MSG_DT_BIND_NOW_NF,		MSG_DT_INIT_ARRAY_NF,
489		MSG_DT_FINI_ARRAY_NF,		MSG_DT_INIT_ARRAYSZ_NF,
490		MSG_DT_FINI_ARRAYSZ_NF,		MSG_DT_RUNPATH_NF,
491		MSG_DT_FLAGS_NF,		0,
492		MSG_DT_PREINIT_ARRAY_NF,	MSG_DT_PREINIT_ARRAYSZ_NF
493	};
494	static const Msg	tags_null_dmp[] = {
495		MSG_DT_NULL_CFNP,		MSG_DT_NEEDED_CFNP,
496		MSG_DT_PLTRELSZ_DMP,		MSG_DT_PLTGOT_CFNP,
497		MSG_DT_HASH_CFNP,		MSG_DT_STRTAB_CFNP,
498		MSG_DT_SYMTAB_CFNP,		MSG_DT_RELA_CFNP,
499		MSG_DT_RELASZ_CFNP,		MSG_DT_RELAENT_CFNP,
500		MSG_DT_STRSZ_CFNP,		MSG_DT_SYMENT_CFNP,
501		MSG_DT_INIT_CFNP,		MSG_DT_FINI_CFNP,
502		MSG_DT_SONAME_CFNP,		MSG_DT_RPATH_CFNP,
503		MSG_DT_SYMBOLIC_DMP,		MSG_DT_REL_CFNP,
504		MSG_DT_RELSZ_CFNP,		MSG_DT_RELENT_CFNP,
505		MSG_DT_PLTREL_CFNP,		MSG_DT_DEBUG_CFNP,
506		MSG_DT_TEXTREL_CFNP,		MSG_DT_JMPREL_CFNP,
507		MSG_DT_BIND_NOW_CFNP,		MSG_DT_INIT_ARRAY_CFNP,
508		MSG_DT_FINI_ARRAY_CFNP,		MSG_DT_INIT_ARRAYSZ_CFNP,
509		MSG_DT_FINI_ARRAYSZ_CFNP,	MSG_DT_RUNPATH_CFNP,
510		MSG_DT_FLAGS_CFNP,		0,
511		MSG_DT_PREINIT_ARRAY_CFNP,	MSG_DT_PREINIT_ARRAYSZ_CFNP
512	};
513	static const conv_ds_msg_t ds_null_cf = {
514	    CONV_DS_MSG_INIT(DT_NULL, tags_null_cf) };
515	static const conv_ds_msg_t ds_null_cfnp = {
516	    CONV_DS_MSG_INIT(DT_NULL, tags_null_cfnp) };
517	static const conv_ds_msg_t ds_null_nf = {
518	    CONV_DS_MSG_INIT(DT_NULL, tags_null_nf) };
519	static const conv_ds_msg_t ds_null_dmp = {
520	    CONV_DS_MSG_INIT(DT_NULL, tags_null_dmp) };
521
522	/*
523	 * DT_SPARC_REGISTER was originally assigned 0x7000001. It is processor
524	 * specific, and should have been in the range DT_LOPROC-DT_HIPROC
525	 * instead of here. When the error was fixed,
526	 * DT_DEPRECATED_SPARC_REGISTER was created to maintain backward
527	 * compatability.
528	 */
529	static const Msg	tags_sdreg_cf[] = {
530	    MSG_DT_DEP_SPARC_REG_CF };
531	static const Msg	tags_sdreg_cfnp[] = {
532	    MSG_DT_DEP_SPARC_REG_CFNP };
533	static const Msg	tags_sdreg_nf[] = {
534	    MSG_DT_DEP_SPARC_REG_NF };
535
536	static const conv_ds_msg_t ds_sdreg_cf = {
537	    CONV_DS_MSG_INIT(DT_DEPRECATED_SPARC_REGISTER, tags_sdreg_cf) };
538	static const conv_ds_msg_t ds_sdreg_cfnp = {
539	    CONV_DS_MSG_INIT(DT_DEPRECATED_SPARC_REGISTER, tags_sdreg_cfnp) };
540	static const conv_ds_msg_t ds_sdreg_nf = {
541	    CONV_DS_MSG_INIT(DT_DEPRECATED_SPARC_REGISTER, tags_sdreg_nf) };
542
543
544	/*
545	 * SUNW: DT_LOOS -> DT_HIOS range. Note holes between DT_SUNW_TLSSORTSZ,
546	 * DT_SUNW_STRPAD, and DT_SUNW_LDMACH. We handle the outliers
547	 * separately below as single values.
548	 */
549	static const Msg	tags_sunw_auxiliary_cf[] = {
550		MSG_DT_SUNW_AUXILIARY_CF,	MSG_DT_SUNW_RTLDINF_CF,
551		MSG_DT_SUNW_FILTER_CF,		MSG_DT_SUNW_CAP_CF,
552		MSG_DT_SUNW_SYMTAB_CF,		MSG_DT_SUNW_SYMSZ_CF,
553		MSG_DT_SUNW_SORTENT_CF,		MSG_DT_SUNW_SYMSORT_CF,
554		MSG_DT_SUNW_SYMSORTSZ_CF,	MSG_DT_SUNW_TLSSORT_CF,
555		MSG_DT_SUNW_TLSSORTSZ_CF,	MSG_DT_SUNW_CAPINFO_CF,
556		MSG_DT_SUNW_STRPAD_CF,		MSG_DT_SUNW_CAPCHAIN_CF,
557		MSG_DT_SUNW_LDMACH_CF,		0,
558		MSG_DT_SUNW_CAPCHAINENT_CF,	0,
559		MSG_DT_SUNW_CAPCHAINSZ_CF,	0,
560		0,				0,
561		MSG_DT_SUNW_ASLR_CF,		0,
562		0,				0,
563		MSG_DT_SUNW_KMOD_CF
564	};
565	static const Msg	tags_sunw_auxiliary_cfnp[] = {
566		MSG_DT_SUNW_AUXILIARY_CFNP,	MSG_DT_SUNW_RTLDINF_CFNP,
567		MSG_DT_SUNW_FILTER_CFNP,	MSG_DT_SUNW_CAP_CFNP,
568		MSG_DT_SUNW_SYMTAB_CFNP,	MSG_DT_SUNW_SYMSZ_CFNP,
569		MSG_DT_SUNW_SORTENT_CFNP,	MSG_DT_SUNW_SYMSORT_CFNP,
570		MSG_DT_SUNW_SYMSORTSZ_CFNP,	MSG_DT_SUNW_TLSSORT_CFNP,
571		MSG_DT_SUNW_TLSSORTSZ_CFNP,	MSG_DT_SUNW_CAPINFO_CFNP,
572		MSG_DT_SUNW_STRPAD_CFNP,	MSG_DT_SUNW_CAPCHAIN_CFNP,
573		MSG_DT_SUNW_LDMACH_CFNP,	0,
574		MSG_DT_SUNW_CAPCHAINENT_CFNP,	0,
575		MSG_DT_SUNW_CAPCHAINSZ_CFNP,	0,
576		0,				0,
577		MSG_DT_SUNW_ASLR_CFNP,		0,
578		0,				0,
579		MSG_DT_SUNW_KMOD_CFNP
580	};
581	static const Msg	tags_sunw_auxiliary_nf[] = {
582		MSG_DT_SUNW_AUXILIARY_NF,	MSG_DT_SUNW_RTLDINF_NF,
583		MSG_DT_SUNW_FILTER_NF,		MSG_DT_SUNW_CAP_NF,
584		MSG_DT_SUNW_SYMTAB_NF,		MSG_DT_SUNW_SYMSZ_NF,
585		MSG_DT_SUNW_SORTENT_NF,		MSG_DT_SUNW_SYMSORT_NF,
586		MSG_DT_SUNW_SYMSORTSZ_NF,	MSG_DT_SUNW_TLSSORT_NF,
587		MSG_DT_SUNW_TLSSORTSZ_NF,	MSG_DT_SUNW_CAPINFO_NF,
588		MSG_DT_SUNW_STRPAD_NF,		MSG_DT_SUNW_CAPCHAIN_NF,
589		MSG_DT_SUNW_LDMACH_NF,		0,
590		MSG_DT_SUNW_CAPCHAINENT_NF,	0,
591		MSG_DT_SUNW_CAPCHAINSZ_NF,	0,
592		0,				0,
593		MSG_DT_SUNW_ASLR_NF,		0,
594		0,				0,
595		MSG_DT_SUNW_KMOD_NF
596	};
597	static const conv_ds_msg_t ds_sunw_auxiliary_cf = {
598	    CONV_DS_MSG_INIT(DT_SUNW_AUXILIARY, tags_sunw_auxiliary_cf) };
599	static const conv_ds_msg_t ds_sunw_auxiliary_cfnp = {
600	    CONV_DS_MSG_INIT(DT_SUNW_AUXILIARY, tags_sunw_auxiliary_cfnp) };
601	static const conv_ds_msg_t ds_sunw_auxiliary_nf = {
602	    CONV_DS_MSG_INIT(DT_SUNW_AUXILIARY, tags_sunw_auxiliary_nf) };
603
604	/*
605	 * GNU: (In DT_VALRNGLO section) DT_GNU_PRELINKED - DT_GNU_LIBLISTSZ
606	 */
607	static const Msg	tags_gnu_prelinked_cf[] = {
608		MSG_DT_GNU_PRELINKED_CF,	MSG_DT_GNU_CONFLICTSZ_CF,
609		MSG_DT_GNU_LIBLISTSZ_CF
610	};
611	static const Msg	tags_gnu_prelinked_cfnp[] = {
612		MSG_DT_GNU_PRELINKED_CFNP,	MSG_DT_GNU_CONFLICTSZ_CFNP,
613		MSG_DT_GNU_LIBLISTSZ_CFNP
614	};
615	static const Msg	tags_gnu_prelinked_nf[] = {
616		MSG_DT_GNU_PRELINKED_NF,	MSG_DT_GNU_CONFLICTSZ_NF,
617		MSG_DT_GNU_LIBLISTSZ_NF
618	};
619	static const conv_ds_msg_t ds_gnu_prelinked_cf = {
620	    CONV_DS_MSG_INIT(DT_GNU_PRELINKED, tags_gnu_prelinked_cf) };
621	static const conv_ds_msg_t ds_gnu_prelinked_cfnp = {
622	    CONV_DS_MSG_INIT(DT_GNU_PRELINKED, tags_gnu_prelinked_cfnp) };
623	static const conv_ds_msg_t ds_gnu_prelinked_nf = {
624	    CONV_DS_MSG_INIT(DT_GNU_PRELINKED, tags_gnu_prelinked_nf) };
625
626	/*
627	 * SUNW: DT_VALRNGLO - DT_VALRNGHI range.
628	 */
629	static const Msg	tags_checksum_cf[] = {
630		MSG_DT_CHECKSUM_CF,		MSG_DT_PLTPADSZ_CF,
631		MSG_DT_MOVEENT_CF,		MSG_DT_MOVESZ_CF,
632		MSG_DT_FEATURE_1_CF,		MSG_DT_POSFLAG_1_CF,
633		MSG_DT_SYMINSZ_CF,		MSG_DT_SYMINENT_CF
634	};
635	static const Msg	tags_checksum_cfnp[] = {
636		MSG_DT_CHECKSUM_CFNP,		MSG_DT_PLTPADSZ_CFNP,
637		MSG_DT_MOVEENT_CFNP,		MSG_DT_MOVESZ_CFNP,
638		MSG_DT_FEATURE_1_CFNP,		MSG_DT_POSFLAG_1_CFNP,
639		MSG_DT_SYMINSZ_CFNP,		MSG_DT_SYMINENT_CFNP
640	};
641	static const Msg	tags_checksum_nf[] = {
642		MSG_DT_CHECKSUM_NF,		MSG_DT_PLTPADSZ_NF,
643		MSG_DT_MOVEENT_NF,		MSG_DT_MOVESZ_NF,
644		MSG_DT_FEATURE_1_NF,		MSG_DT_POSFLAG_1_NF,
645		MSG_DT_SYMINSZ_NF,		MSG_DT_SYMINENT_NF
646	};
647	static const conv_ds_msg_t ds_checksum_cf = {
648	    CONV_DS_MSG_INIT(DT_CHECKSUM, tags_checksum_cf) };
649	static const conv_ds_msg_t ds_checksum_cfnp = {
650	    CONV_DS_MSG_INIT(DT_CHECKSUM, tags_checksum_cfnp) };
651	static const conv_ds_msg_t ds_checksum_nf = {
652	    CONV_DS_MSG_INIT(DT_CHECKSUM, tags_checksum_nf) };
653
654	/*
655	 * GNU: (In DT_ADDRRNGLO section) DT_GNU_HASH - DT_GNU_LIBLIST
656	 */
657	static const Msg	tags_gnu_hash_cf[] = {
658		MSG_DT_GNU_HASH_CF,		MSG_DT_TLSDESC_PLT_CF,
659		MSG_DT_TLSDESC_GOT_CF,		MSG_DT_GNU_CONFLICT_CF,
660		MSG_DT_GNU_LIBLIST_CF
661	};
662	static const Msg	tags_gnu_hash_cfnp[] = {
663		MSG_DT_GNU_HASH_CFNP,		MSG_DT_TLSDESC_PLT_CFNP,
664		MSG_DT_TLSDESC_GOT_CFNP,	MSG_DT_GNU_CONFLICT_CFNP,
665		MSG_DT_GNU_LIBLIST_CFNP
666	};
667	static const Msg	tags_gnu_hash_nf[] = {
668		MSG_DT_GNU_HASH_NF,		MSG_DT_TLSDESC_PLT_NF,
669		MSG_DT_TLSDESC_GOT_NF,		MSG_DT_GNU_CONFLICT_NF,
670		MSG_DT_GNU_LIBLIST_NF
671	};
672	static const conv_ds_msg_t ds_gnu_hash_cf = {
673	    CONV_DS_MSG_INIT(DT_GNU_HASH, tags_gnu_hash_cf) };
674	static const conv_ds_msg_t ds_gnu_hash_cfnp = {
675	    CONV_DS_MSG_INIT(DT_GNU_HASH, tags_gnu_hash_cfnp) };
676	static const conv_ds_msg_t ds_gnu_hash_nf = {
677	    CONV_DS_MSG_INIT(DT_GNU_HASH, tags_gnu_hash_nf) };
678
679	/*
680	 * SUNW: DT_ADDRRNGLO - DT_ADDRRNGHI range.
681	 */
682	static const Msg	tags_config_cf[] = {
683		MSG_DT_CONFIG_CF,		MSG_DT_DEPAUDIT_CF,
684		MSG_DT_AUDIT_CF,		MSG_DT_PLTPAD_CF,
685		MSG_DT_MOVETAB_CF,		MSG_DT_SYMINFO_CF
686	};
687	static const Msg	tags_config_cfnp[] = {
688		MSG_DT_CONFIG_CFNP,		MSG_DT_DEPAUDIT_CFNP,
689		MSG_DT_AUDIT_CFNP,		MSG_DT_PLTPAD_CFNP,
690		MSG_DT_MOVETAB_CFNP,		MSG_DT_SYMINFO_CFNP
691	};
692	static const Msg	tags_config_nf[] = {
693		MSG_DT_CONFIG_NF,		MSG_DT_DEPAUDIT_NF,
694		MSG_DT_AUDIT_NF,		MSG_DT_PLTPAD_NF,
695		MSG_DT_MOVETAB_NF,		MSG_DT_SYMINFO_NF
696	};
697	static const conv_ds_msg_t ds_config_cf = {
698	    CONV_DS_MSG_INIT(DT_CONFIG, tags_config_cf) };
699	static const conv_ds_msg_t ds_config_cfnp = {
700	    CONV_DS_MSG_INIT(DT_CONFIG, tags_config_cfnp) };
701	static const conv_ds_msg_t ds_config_nf = {
702	    CONV_DS_MSG_INIT(DT_CONFIG, tags_config_nf) };
703
704	/*
705	 * SUNW: generic range. Note hole between DT_VERSYM and DT_RELACOUNT.
706	 */
707	static const Msg	tags_versym_cf[] = { MSG_DT_VERSYM_CF };
708	static const Msg	tags_versym_cfnp[] = { MSG_DT_VERSYM_CFNP };
709	static const Msg	tags_versym_nf[] = { MSG_DT_VERSYM_NF };
710	static const conv_ds_msg_t ds_versym_cf = {
711	    CONV_DS_MSG_INIT(DT_VERSYM, tags_versym_cf) };
712	static const conv_ds_msg_t ds_versym_cfnp = {
713	    CONV_DS_MSG_INIT(DT_VERSYM, tags_versym_cfnp) };
714	static const conv_ds_msg_t ds_versym_nf = {
715	    CONV_DS_MSG_INIT(DT_VERSYM, tags_versym_nf) };
716
717	static const Msg	tags_relacount_cf[] = {
718		MSG_DT_RELACOUNT_CF,		MSG_DT_RELCOUNT_CF,
719		MSG_DT_FLAGS_1_CF,		MSG_DT_VERDEF_CF,
720		MSG_DT_VERDEFNUM_CF,		MSG_DT_VERNEED_CF,
721		MSG_DT_VERNEEDNUM_CF
722	};
723	static const Msg	tags_relacount_cfnp[] = {
724		MSG_DT_RELACOUNT_CFNP,		MSG_DT_RELCOUNT_CFNP,
725		MSG_DT_FLAGS_1_CFNP,		MSG_DT_VERDEF_CFNP,
726		MSG_DT_VERDEFNUM_CFNP,		MSG_DT_VERNEED_CFNP,
727		MSG_DT_VERNEEDNUM_CFNP
728	};
729	static const Msg	tags_relacount_nf[] = {
730		MSG_DT_RELACOUNT_NF,		MSG_DT_RELCOUNT_NF,
731		MSG_DT_FLAGS_1_NF,		MSG_DT_VERDEF_NF,
732		MSG_DT_VERDEFNUM_NF,		MSG_DT_VERNEED_NF,
733		MSG_DT_VERNEEDNUM_NF
734	};
735	static const conv_ds_msg_t ds_relacount_cf = {
736	    CONV_DS_MSG_INIT(DT_RELACOUNT, tags_relacount_cf) };
737	static const conv_ds_msg_t ds_relacount_cfnp = {
738	    CONV_DS_MSG_INIT(DT_RELACOUNT, tags_relacount_cfnp) };
739	static const conv_ds_msg_t ds_relacount_nf = {
740	    CONV_DS_MSG_INIT(DT_RELACOUNT, tags_relacount_nf) };
741
742	/*
743	 * DT_LOPROC - DT_HIPROC range: solaris/sparc-only
744	 */
745	static const Msg tags_sparc_reg_cf[] = { MSG_DT_SPARC_REGISTER_CF };
746	static const Msg tags_sparc_reg_cfnp[] = { MSG_DT_SPARC_REGISTER_CFNP };
747	static const Msg tags_sparc_reg_nf[] = { MSG_DT_SPARC_REGISTER_NF };
748	static const Msg tags_sparc_reg_dmp[] = { MSG_DT_SPARC_REGISTER_DMP };
749	static const conv_ds_msg_t ds_sparc_reg_cf = {
750	    CONV_DS_MSG_INIT(DT_SPARC_REGISTER, tags_sparc_reg_cf) };
751	static const conv_ds_msg_t ds_sparc_reg_cfnp = {
752	    CONV_DS_MSG_INIT(DT_SPARC_REGISTER, tags_sparc_reg_cfnp) };
753	static const conv_ds_msg_t ds_sparc_reg_nf = {
754	    CONV_DS_MSG_INIT(DT_SPARC_REGISTER, tags_sparc_reg_nf) };
755	static const conv_ds_msg_t ds_sparc_reg_dmp = {
756	    CONV_DS_MSG_INIT(DT_SPARC_REGISTER, tags_sparc_reg_dmp) };
757
758	/*
759	 * DT_LOPROC - DT_HIPROC range: Solaris osabi, all hardware
760	 */
761	static const Msg	tags_auxiliary_cf[] = {
762		MSG_DT_AUXILIARY_CF,	MSG_DT_USED_CF,
763		MSG_DT_FILTER_CF
764	};
765	static const Msg	tags_auxiliary_cfnp[] = {
766		MSG_DT_AUXILIARY_CFNP,	MSG_DT_USED_CFNP,
767		MSG_DT_FILTER_CFNP
768	};
769	static const Msg	tags_auxiliary_nf[] = {
770		MSG_DT_AUXILIARY_NF,	MSG_DT_USED_NF,
771		MSG_DT_FILTER_NF
772	};
773	static const conv_ds_msg_t ds_auxiliary_cf = {
774	    CONV_DS_MSG_INIT(DT_AUXILIARY, tags_auxiliary_cf) };
775	static const conv_ds_msg_t ds_auxiliary_cfnp = {
776	    CONV_DS_MSG_INIT(DT_AUXILIARY, tags_auxiliary_cfnp) };
777	static const conv_ds_msg_t ds_auxiliary_nf = {
778	    CONV_DS_MSG_INIT(DT_AUXILIARY, tags_auxiliary_nf) };
779
780
781	static const conv_ds_t	*retarr[MAX_RET];
782
783	int	ndx = 0;
784	int	fmt_osabi = CONV_TYPE_FMT_ALT(fmt_flags);
785	int	mach_sparc, osabi_solaris, osabi_linux;
786
787
788
789	osabi_solaris = (osabi == ELFOSABI_NONE) ||
790	    (osabi == ELFOSABI_SOLARIS) || (osabi == CONV_OSABI_ALL);
791	osabi_linux = (osabi == ELFOSABI_LINUX) || (osabi == CONV_OSABI_ALL);
792	mach_sparc = (mach == EM_SPARC) || (mach == EM_SPARCV9) ||
793	    (mach == EM_SPARC32PLUS) || (mach == CONV_MACH_ALL);
794
795	/*
796	 * Fill in retarr with the descriptors for the messages that
797	 * apply to the current osabi. Note that we order these items such
798	 * that the more common are placed at the beginning, and the less
799	 * likely at the end. This should speed the common case.
800	 *
801	 * Note that the CFNP and DMP styles are very similar, so they
802	 * are combined in 'default', and fmt_osabi is consulted when there
803	 * are differences.
804	 */
805	switch (fmt_osabi) {
806	case CONV_FMT_ALT_CF:
807		retarr[ndx++] = CONV_DS_ADDR(ds_null_cf);
808		if (osabi_solaris)
809			retarr[ndx++] = CONV_DS_ADDR(ds_sunw_auxiliary_cf);
810		retarr[ndx++] = CONV_DS_ADDR(ds_checksum_cf);
811		retarr[ndx++] = CONV_DS_ADDR(ds_config_cf);
812		retarr[ndx++] = CONV_DS_ADDR(ds_versym_cf);
813		retarr[ndx++] = CONV_DS_ADDR(ds_relacount_cf);
814		if (osabi_solaris) {
815			retarr[ndx++] = CONV_DS_ADDR(ds_auxiliary_cf);
816			if (mach_sparc) {
817				retarr[ndx++] = CONV_DS_ADDR(ds_sparc_reg_cf);
818				retarr[ndx++] = CONV_DS_ADDR(ds_sdreg_cf);
819			}
820		}
821		if (osabi_linux) {
822			retarr[ndx++] = CONV_DS_ADDR(ds_gnu_prelinked_cf);
823			retarr[ndx++] = CONV_DS_ADDR(ds_gnu_hash_cf);
824		}
825		break;
826
827	case CONV_FMT_ALT_NF:
828		retarr[ndx++] = CONV_DS_ADDR(ds_null_nf);
829		if (osabi_solaris)
830			retarr[ndx++] = CONV_DS_ADDR(ds_sunw_auxiliary_nf);
831		retarr[ndx++] = CONV_DS_ADDR(ds_checksum_nf);
832		retarr[ndx++] = CONV_DS_ADDR(ds_config_nf);
833		retarr[ndx++] = CONV_DS_ADDR(ds_versym_nf);
834		retarr[ndx++] = CONV_DS_ADDR(ds_relacount_nf);
835		if (osabi_solaris) {
836			retarr[ndx++] = CONV_DS_ADDR(ds_auxiliary_nf);
837			if (mach_sparc) {
838				retarr[ndx++] = CONV_DS_ADDR(ds_sparc_reg_nf);
839				retarr[ndx++] = CONV_DS_ADDR(ds_sdreg_nf);
840			}
841		}
842		if (osabi_linux) {
843			retarr[ndx++] = CONV_DS_ADDR(ds_gnu_prelinked_nf);
844			retarr[ndx++] = CONV_DS_ADDR(ds_gnu_hash_nf);
845		}
846		break;
847	default:
848		/*
849		 * The default style for the generic range is CFNP,
850		 * while dump has a couple of different strings.
851		 */
852
853		retarr[ndx++] = (fmt_osabi == CONV_FMT_ALT_DUMP) ?
854		    CONV_DS_ADDR(ds_null_dmp) : CONV_DS_ADDR(ds_null_cfnp);
855		if (osabi_solaris)
856			retarr[ndx++] = CONV_DS_ADDR(ds_sunw_auxiliary_cfnp);
857		retarr[ndx++] = CONV_DS_ADDR(ds_checksum_cfnp);
858		retarr[ndx++] = CONV_DS_ADDR(ds_config_cfnp);
859		retarr[ndx++] = CONV_DS_ADDR(ds_versym_cfnp);
860		retarr[ndx++] = CONV_DS_ADDR(ds_relacount_cfnp);
861		if (osabi_solaris) {
862			retarr[ndx++] = CONV_DS_ADDR(ds_auxiliary_cfnp);
863			if (mach_sparc) {
864				/*
865				 * The default style for DT_SPARC_REGISTER
866				 * is the dump style, which omits the 'SPARC_'.
867				 * CFNP keeps the prefix.
868				 */
869				retarr[ndx++] =
870				    (fmt_osabi == CONV_FMT_ALT_CFNP) ?
871				    CONV_DS_ADDR(ds_sparc_reg_cfnp) :
872				    CONV_DS_ADDR(ds_sparc_reg_dmp);
873				retarr[ndx++] = CONV_DS_ADDR(ds_sdreg_cfnp);
874			}
875		}
876		if (osabi_linux) {
877			retarr[ndx++] = CONV_DS_ADDR(ds_gnu_prelinked_cfnp);
878			retarr[ndx++] = CONV_DS_ADDR(ds_gnu_hash_cfnp);
879		}
880		break;
881	}
882
883	retarr[ndx++] = NULL;
884	assert(ndx <= MAX_RET);
885	return (retarr);
886}
887
888conv_iter_ret_t
889conv_iter_dyn_tag(conv_iter_osabi_t osabi, Half mach,
890    Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func, void *uvalue)
891{
892	return (conv_iter_ds(osabi, mach,
893	    conv_dyn_tag_strings(osabi, mach, fmt_flags), func, uvalue));
894}
895
896
897#define	BINDTSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE +			\
898		MSG_BND_NEEDED_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
899		MSG_BND_REFER_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
900		MSG_BND_FILTER_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
901		CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
902
903/*
904 * Ensure that Conv_bnd_type_buf_t is large enough:
905 *
906 * BINDTSZ is the real minimum size of the buffer required by conv_bnd_type().
907 * However, Conv_bnd_type_buf_t uses CONV_BND_TYPE_BUFSIZE to set the
908 * buffer size. We do things this way because the definition of BINDTSZ uses
909 * information that is not available in the environment of other programs
910 * that include the conv.h header file.
911 */
912#if (CONV_BND_TYPE_BUFSIZE != BINDTSZ) && !defined(__lint)
913#define	REPORT_BUFSIZE BINDTSZ
914#include "report_bufsize.h"
915#error "CONV_BND_TYPE_BUFSIZE does not match BINDTSZ"
916#endif
917
918const char *
919conv_bnd_type(uint_t flags, Conv_bnd_type_buf_t *bnd_type_buf)
920{
921	static const Val_desc vda[] = {
922		{ BND_NEEDED,		MSG_BND_NEEDED },
923		{ BND_REFER,		MSG_BND_REFER },
924		{ BND_FILTER,		MSG_BND_FILTER },
925		{ 0,			0 }
926	};
927	static CONV_EXPN_FIELD_ARG conv_arg = {
928	    NULL, sizeof (bnd_type_buf->buf) };
929
930	if (flags == 0)
931		return (MSG_ORIG(MSG_STR_EMPTY));
932
933	conv_arg.buf = bnd_type_buf->buf;
934	conv_arg.oflags = conv_arg.rflags = flags;
935	(void) conv_expn_field(&conv_arg, vda, 0);
936
937	return ((const char *)bnd_type_buf->buf);
938}
939
940/*
941 * Note, conv_bnd_obj() is called with either:
942 *	LML_FLG_OBJADDED (possibly with LML_FLG_OBJREEVAL added), or
943 *	LML_FLG_OBJDELETED, or
944 *	LML_FLG_ATEXIT.
945 */
946#define	BINDOSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
947		MSG_BND_ADDED_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
948		MSG_BND_REEVAL_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
949		CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
950
951/*
952 * Ensure that Conv_bnd_obj_buf_t is large enough:
953 *
954 * BINDOSZ is the real minimum size of the buffer required by conv_bnd_obj().
955 * However, Conv_bnd_obj_buf_t uses CONV_BND_OBJ_BUFSIZE to set the
956 * buffer size. We do things this way because the definition of BINDOSZ uses
957 * information that is not available in the environment of other programs
958 * that include the conv.h header file.
959 */
960#if (CONV_BND_OBJ_BUFSIZE != BINDOSZ) && !defined(__lint)
961#define	REPORT_BUFSIZE BINDOSZ
962#include "report_bufsize.h"
963#error "CONV_BND_OBJ_BUFSIZE does not match BINDOSZ"
964#endif
965
966const char *
967conv_bnd_obj(uint_t flags, Conv_bnd_obj_buf_t *bnd_obj_buf)
968{
969	static const Val_desc vda[] = {
970		{ LML_FLG_OBJADDED,	MSG_BND_ADDED },
971		{ LML_FLG_OBJREEVAL,	MSG_BND_REEVAL },
972		{ LML_FLG_OBJDELETED,	MSG_BND_DELETED },
973		{ LML_FLG_ATEXIT,	MSG_BND_ATEXIT },
974		{ 0,			0 }
975	};
976	static CONV_EXPN_FIELD_ARG conv_arg = {
977	    NULL, sizeof (bnd_obj_buf->buf) };
978
979	if ((flags & (LML_FLG_OBJADDED | LML_FLG_OBJREEVAL |
980	    LML_FLG_OBJDELETED | LML_FLG_ATEXIT)) == 0)
981		return (MSG_ORIG(MSG_BND_REVISIT));
982
983	/*
984	 * Note, we're not worried about unknown flags for this family, only
985	 * the selected flags are of interest, so we leave conv_arg.rflags
986	 * set to 0.
987	 */
988	conv_arg.buf = bnd_obj_buf->buf;
989	conv_arg.oflags = flags;
990	(void) conv_expn_field(&conv_arg, vda, 0);
991
992	return ((const char *)bnd_obj_buf->buf);
993}
994