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 2010 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * String conversion routines for section attributes.
29 */
30#include	<string.h>
31#include	<sys/param.h>
32#include	<sys/elf_SPARC.h>
33#include	<sys/elf_amd64.h>
34#include	<_conv.h>
35#include	<sections_msg.h>
36
37
38static const conv_ds_t **
39sec_type_strings(conv_iter_osabi_t osabi, Half mach, Conv_fmt_flags_t fmt_flags)
40{
41	/*
42	 * This routine can return an array with 1 generic array, up to
43	 * three osabi arrays, two machine arrays, plus the NULL termination.
44	 */
45#define	MAX_RET	7
46
47	static const Msg secs_def[SHT_NUM] = {
48		MSG_SHT_NULL,			MSG_SHT_PROGBITS,
49		MSG_SHT_SYMTAB,			MSG_SHT_STRTAB,
50		MSG_SHT_RELA,			MSG_SHT_HASH,
51		MSG_SHT_DYNAMIC,		MSG_SHT_NOTE,
52		MSG_SHT_NOBITS,			MSG_SHT_REL,
53		MSG_SHT_SHLIB,			MSG_SHT_DYNSYM,
54		MSG_SHT_UNKNOWN12,		MSG_SHT_UNKNOWN13,
55		MSG_SHT_INIT_ARRAY,		MSG_SHT_FINI_ARRAY,
56		MSG_SHT_PREINIT_ARRAY,		MSG_SHT_GROUP,
57		MSG_SHT_SYMTAB_SHNDX
58	};
59	static const Msg secs_dmp[SHT_NUM] = {
60		MSG_SHT_NULL_DMP,		MSG_SHT_PROGBITS_DMP,
61		MSG_SHT_SYMTAB_DMP,		MSG_SHT_STRTAB_DMP,
62		MSG_SHT_RELA_DMP,		MSG_SHT_HASH_DMP,
63		MSG_SHT_DYNAMIC_DMP,		MSG_SHT_NOTE_DMP,
64		MSG_SHT_NOBITS_DMP,		MSG_SHT_REL_DMP,
65		MSG_SHT_SHLIB_DMP,		MSG_SHT_DYNSYM_DMP,
66		MSG_SHT_UNKNOWN12_DMP,		MSG_SHT_UNKNOWN13_DMP,
67		MSG_SHT_INIT_ARRAY_DMP,		MSG_SHT_FINI_ARRAY_DMP,
68		MSG_SHT_PREINIT_ARRAY_DMP,	MSG_SHT_GROUP_DMP,
69		MSG_SHT_SYMTAB_SHNDX_DMP
70	};
71	static const Msg secs_cf[SHT_NUM] = {
72		MSG_SHT_NULL_CF,		MSG_SHT_PROGBITS_CF,
73		MSG_SHT_SYMTAB_CF,		MSG_SHT_STRTAB_CF,
74		MSG_SHT_RELA_CF,		MSG_SHT_HASH_CF,
75		MSG_SHT_DYNAMIC_CF,		MSG_SHT_NOTE_CF,
76		MSG_SHT_NOBITS_CF,		MSG_SHT_REL_CF,
77		MSG_SHT_SHLIB_CF,		MSG_SHT_DYNSYM_CF,
78		MSG_SHT_UNKNOWN12_CF,		MSG_SHT_UNKNOWN13_CF,
79		MSG_SHT_INIT_ARRAY_CF,		MSG_SHT_FINI_ARRAY_CF,
80		MSG_SHT_PREINIT_ARRAY_CF,	MSG_SHT_GROUP_CF,
81		MSG_SHT_SYMTAB_SHNDX_CF
82	};
83	static const Msg secs_nf[SHT_NUM] = {
84		MSG_SHT_NULL_NF,		MSG_SHT_PROGBITS_NF,
85		MSG_SHT_SYMTAB_NF,		MSG_SHT_STRTAB_NF,
86		MSG_SHT_RELA_NF,		MSG_SHT_HASH_NF,
87		MSG_SHT_DYNAMIC_NF,		MSG_SHT_NOTE_NF,
88		MSG_SHT_NOBITS_NF,		MSG_SHT_REL_NF,
89		MSG_SHT_SHLIB_NF,		MSG_SHT_DYNSYM_NF,
90		MSG_SHT_UNKNOWN12_NF,		MSG_SHT_UNKNOWN13_NF,
91		MSG_SHT_INIT_ARRAY_NF,		MSG_SHT_FINI_ARRAY_NF,
92		MSG_SHT_PREINIT_ARRAY_NF,	MSG_SHT_GROUP_NF,
93		MSG_SHT_SYMTAB_SHNDX_NF
94	};
95#if	(SHT_NUM != (SHT_SYMTAB_SHNDX + 1))
96#error	"SHT_NUM has grown"
97#endif
98	static const conv_ds_msg_t ds_secs_def = {
99	    CONV_DS_MSG_INIT(SHT_NULL, secs_def) };
100	static const conv_ds_msg_t ds_secs_dmp = {
101	    CONV_DS_MSG_INIT(SHT_NULL, secs_dmp) };
102	static const conv_ds_msg_t ds_secs_cf = {
103	    CONV_DS_MSG_INIT(SHT_NULL, secs_cf) };
104	static const conv_ds_msg_t ds_secs_nf = {
105	    CONV_DS_MSG_INIT(SHT_NULL, secs_nf) };
106
107
108	static const Msg usecs_def[SHT_HISUNW - SHT_LOSUNW + 1] = {
109		MSG_SHT_SUNW_CAPCHAIN,		MSG_SHT_SUNW_CAPINFO,
110		MSG_SHT_SUNW_SYMSORT,		MSG_SHT_SUNW_TLSSORT,
111		MSG_SHT_SUNW_LDYNSYM,		MSG_SHT_SUNW_DOF,
112		MSG_SHT_SUNW_CAP,		MSG_SHT_SUNW_SIGNATURE,
113		MSG_SHT_SUNW_ANNOTATE,		MSG_SHT_SUNW_DEBUGSTR,
114		MSG_SHT_SUNW_DEBUG,		MSG_SHT_SUNW_MOVE,
115		MSG_SHT_SUNW_COMDAT,		MSG_SHT_SUNW_SYMINFO,
116		MSG_SHT_SUNW_VERDEF,		MSG_SHT_SUNW_VERNEED,
117		MSG_SHT_SUNW_VERSYM
118	};
119	static const Msg usecs_dmp[SHT_HISUNW - SHT_LOSUNW + 1] = {
120		MSG_SHT_SUNW_CAPCHAIN_DMP,	MSG_SHT_SUNW_CAPINFO_DMP,
121		MSG_SHT_SUNW_SYMSORT_DMP,	MSG_SHT_SUNW_TLSSORT_DMP,
122		MSG_SHT_SUNW_LDYNSYM_DMP,	MSG_SHT_SUNW_DOF_DMP,
123		MSG_SHT_SUNW_CAP_DMP,		MSG_SHT_SUNW_SIGNATURE_DMP,
124		MSG_SHT_SUNW_ANNOTATE_DMP,	MSG_SHT_SUNW_DEBUGSTR_DMP,
125		MSG_SHT_SUNW_DEBUG_DMP,		MSG_SHT_SUNW_MOVE_DMP,
126		MSG_SHT_SUNW_COMDAT_DMP,	MSG_SHT_SUNW_SYMINFO_DMP,
127		MSG_SHT_SUNW_VERDEF_DMP,	MSG_SHT_SUNW_VERNEED_DMP,
128		MSG_SHT_SUNW_VERSYM_DMP
129	};
130	static const Msg usecs_cf[SHT_HISUNW - SHT_LOSUNW + 1] = {
131		MSG_SHT_SUNW_CAPCHAIN_CF,	MSG_SHT_SUNW_CAPINFO_CF,
132		MSG_SHT_SUNW_SYMSORT_CF,	MSG_SHT_SUNW_TLSSORT_CF,
133		MSG_SHT_SUNW_LDYNSYM_CF,	MSG_SHT_SUNW_DOF_CF,
134		MSG_SHT_SUNW_CAP_CF,		MSG_SHT_SUNW_SIGNATURE_CF,
135		MSG_SHT_SUNW_ANNOTATE_CF,	MSG_SHT_SUNW_DEBUGSTR_CF,
136		MSG_SHT_SUNW_DEBUG_CF,		MSG_SHT_SUNW_MOVE_CF,
137		MSG_SHT_SUNW_COMDAT_CF,		MSG_SHT_SUNW_SYMINFO_CF,
138		MSG_SHT_SUNW_VERDEF_CF,		MSG_SHT_SUNW_VERNEED_CF,
139		MSG_SHT_SUNW_VERSYM_CF
140	};
141	static const Msg usecs_nf[SHT_HISUNW - SHT_LOSUNW + 1] = {
142		MSG_SHT_SUNW_CAPCHAIN_NF,	MSG_SHT_SUNW_CAPINFO_NF,
143		MSG_SHT_SUNW_SYMSORT_NF,	MSG_SHT_SUNW_TLSSORT_NF,
144		MSG_SHT_SUNW_LDYNSYM_NF,	MSG_SHT_SUNW_DOF_NF,
145		MSG_SHT_SUNW_CAP_NF,		MSG_SHT_SUNW_SIGNATURE_NF,
146		MSG_SHT_SUNW_ANNOTATE_NF,	MSG_SHT_SUNW_DEBUGSTR_NF,
147		MSG_SHT_SUNW_DEBUG_NF,		MSG_SHT_SUNW_MOVE_NF,
148		MSG_SHT_SUNW_COMDAT_NF,		MSG_SHT_SUNW_SYMINFO_NF,
149		MSG_SHT_SUNW_VERDEF_NF,		MSG_SHT_SUNW_VERNEED_NF,
150		MSG_SHT_SUNW_VERSYM_NF
151	};
152#if	(SHT_LOSUNW != SHT_SUNW_capchain)
153#error	"SHT_LOSUNW has moved"
154#endif
155	static const conv_ds_msg_t ds_usecs_def = {
156	    CONV_DS_MSG_INIT(SHT_SUNW_capchain, usecs_def) };
157	static const conv_ds_msg_t ds_usecs_dmp = {
158	    CONV_DS_MSG_INIT(SHT_SUNW_capchain, usecs_dmp) };
159	static const conv_ds_msg_t ds_usecs_cf = {
160	    CONV_DS_MSG_INIT(SHT_SUNW_capchain, usecs_cf) };
161	static const conv_ds_msg_t ds_usecs_nf = {
162	    CONV_DS_MSG_INIT(SHT_SUNW_capchain, usecs_nf) };
163
164
165	/* The Linux osabi range has two separate sequences */
166	static const Msg usecs_gnu1_def[] = {
167		MSG_SHT_GNU_ATTRIBUTES,		MSG_SHT_GNU_HASH,
168		MSG_SHT_GNU_LIBLIST,		MSG_SHT_CHECKSUM,
169	};
170	static const Msg usecs_gnu1_dmp[] = {
171		MSG_SHT_GNU_ATTRIBUTES_DMP,	MSG_SHT_GNU_HASH_DMP,
172		MSG_SHT_GNU_LIBLIST_DMP,	MSG_SHT_CHECKSUM_DMP,
173	};
174	static const Msg usecs_gnu1_cf[] = {
175		MSG_SHT_GNU_ATTRIBUTES_CF,	MSG_SHT_GNU_HASH_CF,
176		MSG_SHT_GNU_LIBLIST_CF,	MSG_SHT_CHECKSUM_CF,
177	};
178	static const Msg usecs_gnu1_nf[] = {
179		MSG_SHT_GNU_ATTRIBUTES_NF,	MSG_SHT_GNU_HASH_NF,
180		MSG_SHT_GNU_LIBLIST_NF,	MSG_SHT_CHECKSUM_NF,
181	};
182	static const conv_ds_msg_t ds_usecs_gnu1_def = {
183	    CONV_DS_MSG_INIT(SHT_GNU_ATTRIBUTES, usecs_gnu1_def) };
184	static const conv_ds_msg_t ds_usecs_gnu1_dmp = {
185	    CONV_DS_MSG_INIT(SHT_GNU_ATTRIBUTES, usecs_gnu1_dmp) };
186	static const conv_ds_msg_t ds_usecs_gnu1_cf = {
187	    CONV_DS_MSG_INIT(SHT_GNU_ATTRIBUTES, usecs_gnu1_cf) };
188	static const conv_ds_msg_t ds_usecs_gnu1_nf = {
189	    CONV_DS_MSG_INIT(SHT_GNU_ATTRIBUTES, usecs_gnu1_nf) };
190
191
192	static const Msg usecs_gnu2_def[] = {
193		MSG_SHT_GNU_VERDEF,		MSG_SHT_GNU_VERNEED,
194		MSG_SHT_GNU_VERSYM
195	};
196	static const Msg usecs_gnu2_dmp[] = {
197		MSG_SHT_GNU_VERDEF_DMP,		MSG_SHT_GNU_VERNEED_DMP,
198		MSG_SHT_GNU_VERSYM_DMP
199	};
200	static const Msg usecs_gnu2_cf[] = {
201		MSG_SHT_GNU_VERDEF_CF,		MSG_SHT_GNU_VERNEED_CF,
202		MSG_SHT_GNU_VERSYM_CF
203	};
204	static const Msg usecs_gnu2_nf[] = {
205		MSG_SHT_GNU_VERDEF_NF,		MSG_SHT_GNU_VERNEED_NF,
206		MSG_SHT_GNU_VERSYM_NF
207	};
208	static const conv_ds_msg_t ds_usecs_gnu2_def = {
209	    CONV_DS_MSG_INIT(SHT_GNU_verdef, usecs_gnu2_def) };
210	static const conv_ds_msg_t ds_usecs_gnu2_dmp = {
211	    CONV_DS_MSG_INIT(SHT_GNU_verdef, usecs_gnu2_dmp) };
212	static const conv_ds_msg_t ds_usecs_gnu2_cf = {
213	    CONV_DS_MSG_INIT(SHT_GNU_verdef, usecs_gnu2_cf) };
214	static const conv_ds_msg_t ds_usecs_gnu2_nf = {
215	    CONV_DS_MSG_INIT(SHT_GNU_verdef, usecs_gnu2_nf) };
216
217
218	/* sparc processor range */
219	static const Msg sparc_def[] = { MSG_SHT_SPARC_GOTDATA };
220	static const Msg sparc_dmp[] = { MSG_SHT_SPARC_GOTDATA_DMP };
221	static const Msg sparc_cf[] = { MSG_SHT_SPARC_GOTDATA_CF };
222	static const Msg sparc_nf[] = { MSG_SHT_SPARC_GOTDATA_NF };
223	static const conv_ds_msg_t ds_sparc_def = {
224	    CONV_DS_MSG_INIT(SHT_SPARC_GOTDATA, sparc_def) };
225	static const conv_ds_msg_t ds_sparc_dmp = {
226	    CONV_DS_MSG_INIT(SHT_SPARC_GOTDATA, sparc_dmp) };
227	static const conv_ds_msg_t ds_sparc_cf = {
228	    CONV_DS_MSG_INIT(SHT_SPARC_GOTDATA, sparc_cf) };
229	static const conv_ds_msg_t ds_sparc_nf = {
230	    CONV_DS_MSG_INIT(SHT_SPARC_GOTDATA, sparc_nf) };
231
232	/* amd64 processor range */
233	static const Msg amd64_def[] = { MSG_SHT_AMD64_UNWIND };
234	static const Msg amd64_dmp[] = { MSG_SHT_AMD64_UNWIND_DMP };
235	static const Msg amd64_cf[] = { MSG_SHT_AMD64_UNWIND_CF };
236	static const Msg amd64_nf[] = { MSG_SHT_AMD64_UNWIND_NF };
237	static const conv_ds_msg_t ds_amd64_def = {
238	    CONV_DS_MSG_INIT(SHT_AMD64_UNWIND, amd64_def) };
239	static const conv_ds_msg_t ds_amd64_dmp = {
240	    CONV_DS_MSG_INIT(SHT_AMD64_UNWIND, amd64_dmp) };
241	static const conv_ds_msg_t ds_amd64_cf = {
242	    CONV_DS_MSG_INIT(SHT_AMD64_UNWIND, amd64_cf) };
243	static const conv_ds_msg_t ds_amd64_nf = {
244	    CONV_DS_MSG_INIT(SHT_AMD64_UNWIND, amd64_nf) };
245
246
247	static const conv_ds_t	*retarr[MAX_RET];
248	int			retndx = 0;
249
250	/* Select the strings to use, based on string style and OSABI */
251	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
252	case CONV_FMT_ALT_DUMP:
253		retarr[retndx++] = CONV_DS_ADDR(ds_secs_dmp);
254		break;
255	case CONV_FMT_ALT_CF:
256		retarr[retndx++] = CONV_DS_ADDR(ds_secs_cf);
257		break;
258	case CONV_FMT_ALT_NF:
259		retarr[retndx++] = CONV_DS_ADDR(ds_secs_nf);
260		break;
261	default:
262		retarr[retndx++] = CONV_DS_ADDR(ds_secs_def);
263		break;
264	}
265
266	if ((osabi == ELFOSABI_NONE) || (osabi == ELFOSABI_SOLARIS) ||
267	    (osabi == CONV_OSABI_ALL)) {
268		switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
269		case CONV_FMT_ALT_DUMP:
270			retarr[retndx++] = CONV_DS_ADDR(ds_usecs_dmp);
271			break;
272		case CONV_FMT_ALT_CF:
273			retarr[retndx++] = CONV_DS_ADDR(ds_usecs_cf);
274			break;
275		case CONV_FMT_ALT_NF:
276			retarr[retndx++] = CONV_DS_ADDR(ds_usecs_nf);
277			break;
278		default:
279			retarr[retndx++] = CONV_DS_ADDR(ds_usecs_def);
280			break;
281		}
282	}
283
284	if ((osabi == ELFOSABI_LINUX) || (osabi == CONV_OSABI_ALL)) {
285		switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
286		case CONV_FMT_ALT_DUMP:
287			retarr[retndx++] = CONV_DS_ADDR(ds_usecs_gnu1_dmp);
288			retarr[retndx++] = CONV_DS_ADDR(ds_usecs_gnu2_dmp);
289			break;
290		case CONV_FMT_ALT_CF:
291			retarr[retndx++] = CONV_DS_ADDR(ds_usecs_gnu1_cf);
292			retarr[retndx++] = CONV_DS_ADDR(ds_usecs_gnu2_cf);
293			break;
294		case CONV_FMT_ALT_NF:
295			retarr[retndx++] = CONV_DS_ADDR(ds_usecs_gnu1_nf);
296			retarr[retndx++] = CONV_DS_ADDR(ds_usecs_gnu2_nf);
297			break;
298		default:
299			retarr[retndx++] = CONV_DS_ADDR(ds_usecs_gnu1_def);
300			retarr[retndx++] = CONV_DS_ADDR(ds_usecs_gnu2_def);
301			break;
302		}
303	}
304
305	if ((mach == EM_SPARC) || (mach == EM_SPARC32PLUS) ||
306	    (mach == EM_SPARCV9) || (mach == CONV_MACH_ALL)) {
307		switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
308		case CONV_FMT_ALT_DUMP:
309			retarr[retndx++] = CONV_DS_ADDR(ds_sparc_dmp);
310			break;
311		case CONV_FMT_ALT_CF:
312			retarr[retndx++] = CONV_DS_ADDR(ds_sparc_cf);
313			break;
314		case CONV_FMT_ALT_NF:
315			retarr[retndx++] = CONV_DS_ADDR(ds_sparc_nf);
316			break;
317		default:
318			retarr[retndx++] = CONV_DS_ADDR(ds_sparc_def);
319			break;
320		}
321	}
322
323	if ((mach == EM_AMD64) || (mach == CONV_MACH_ALL)) {
324		switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
325		case CONV_FMT_ALT_DUMP:
326			retarr[retndx++] = CONV_DS_ADDR(ds_amd64_dmp);
327			break;
328		case CONV_FMT_ALT_CF:
329			retarr[retndx++] = CONV_DS_ADDR(ds_amd64_cf);
330			break;
331		case CONV_FMT_ALT_NF:
332			retarr[retndx++] = CONV_DS_ADDR(ds_amd64_nf);
333			break;
334		default:
335			retarr[retndx++] = CONV_DS_ADDR(ds_amd64_def);
336			break;
337		}
338	}
339
340	retarr[retndx++] = NULL;
341	assert(retndx <= MAX_RET);
342	return (retarr);
343
344#undef MAX_RET
345}
346
347const char *
348conv_sec_type(uchar_t osabi, Half mach, Word sec, Conv_fmt_flags_t fmt_flags,
349    Conv_inv_buf_t *inv_buf)
350{
351	return (conv_map_ds(osabi, mach, sec,
352	    sec_type_strings(osabi, mach, fmt_flags), fmt_flags, inv_buf));
353}
354
355conv_iter_ret_t
356conv_iter_sec_type(conv_iter_osabi_t osabi, Half mach,
357    Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func, void *uvalue)
358{
359	return (conv_iter_ds(osabi, mach,
360	    sec_type_strings(osabi, mach, fmt_flags), func, uvalue));
361}
362
363
364/*
365 * Special iteration routine that returns strings for all symbol table
366 * sections.
367 */
368conv_iter_ret_t
369conv_iter_sec_symtab(conv_iter_osabi_t osabi, Conv_fmt_flags_t fmt_flags,
370    conv_iter_cb_t func, void *uvalue)
371{
372	static const Val_desc2 symtab_cf[] = {
373		{ SHT_SYMTAB,	0, 0,	MSG_SHT_SYMTAB_CF },
374		{ SHT_DYNSYM,	0, 0,	MSG_SHT_DYNSYM_CF },
375		{ SHT_SUNW_LDYNSYM, ELFOSABI_SOLARIS, 0,
376					MSG_SHT_SUNW_LDYNSYM_CF },
377
378		{ 0 }
379	};
380	static const Val_desc2 symtab_nf[] = {
381		{ SHT_SYMTAB,	0, 0,	MSG_SHT_SYMTAB_NF },
382		{ SHT_DYNSYM,	0, 0,	MSG_SHT_DYNSYM_NF },
383		{ SHT_SUNW_LDYNSYM, ELFOSABI_SOLARIS, 0,
384					MSG_SHT_SUNW_LDYNSYM_NF },
385
386		{ 0 }
387	};
388
389	const Val_desc2 *vdp;
390
391	vdp = (CONV_TYPE_FMT_ALT(fmt_flags) == CONV_FMT_ALT_NF) ?
392	    symtab_nf : symtab_cf;
393
394	return (conv_iter_vd2(osabi, EM_NONE, vdp, func, uvalue));
395}
396
397
398const Val_desc2 *
399conv_sec_flags_strings(Conv_fmt_flags_t fmt_flags)
400{
401#define	FLAGSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
402	MSG_SHF_WRITE_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
403	MSG_SHF_ALLOC_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
404	MSG_SHF_EXECINSTR_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
405	MSG_SHF_MERGE_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
406	MSG_SHF_STRINGS_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
407	MSG_SHF_INFO_LINK_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
408	MSG_SHF_LINK_ORDER_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
409	MSG_SHF_OS_NONCONFORMING_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
410	MSG_SHF_GROUP_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
411	MSG_SHF_TLS_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
412	MSG_SHF_EXCLUDE_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
413	MSG_SHF_ORDERED_CF_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
414	MSG_SHF_AMD64_LARGE_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
415	CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
416
417	/*
418	 * Ensure that Conv_sec_flags_buf_t is large enough:
419	 *
420	 * FLAGSZ is the real minimum size of the buffer required by
421	 * conv_sec_flags(). However, Conv_sec_flags_buf_t uses
422	 * CONV_SEC_FLAGS_BUFSIZE to set the buffer size. We do things this
423	 * way because the definition of FLAGSZ uses information that is not
424	 * available in the environment of other programs that include the
425	 * conv.h header file.
426	 */
427#if (CONV_SEC_FLAGS_BUFSIZE != FLAGSZ) && !defined(__lint)
428#define	REPORT_BUFSIZE FLAGSZ
429#include "report_bufsize.h"
430#error "CONV_SEC_FLAGS_BUFSIZE does not match FLAGSZ"
431#endif
432
433#define	ALL	ELFOSABI_NONE, EM_NONE
434#define	SOL	ELFOSABI_SOLARIS, EM_NONE
435#define	AMD	ELFOSABI_NONE, EM_AMD64
436
437	static const Val_desc2 vda_cf[] = {
438		{ SHF_WRITE,		ALL,	MSG_SHF_WRITE_CF },
439		{ SHF_ALLOC,		ALL,	MSG_SHF_ALLOC_CF },
440		{ SHF_EXECINSTR,	ALL,	MSG_SHF_EXECINSTR_CF },
441		{ SHF_MERGE,		ALL,	MSG_SHF_MERGE_CF },
442		{ SHF_STRINGS,		ALL,	MSG_SHF_STRINGS_CF },
443		{ SHF_INFO_LINK,	ALL,	MSG_SHF_INFO_LINK_CF },
444		{ SHF_LINK_ORDER,	ALL,	MSG_SHF_LINK_ORDER_CF },
445		{ SHF_OS_NONCONFORMING,	ALL,	MSG_SHF_OS_NONCONFORMING_CF },
446		{ SHF_GROUP,		ALL,	MSG_SHF_GROUP_CF },
447		{ SHF_TLS,		ALL,	MSG_SHF_TLS_CF },
448		{ SHF_EXCLUDE,		SOL,	MSG_SHF_EXCLUDE_CF },
449		{ SHF_ORDERED,		SOL,	MSG_SHF_ORDERED_CF },
450		{ SHF_AMD64_LARGE,	AMD,	MSG_SHF_AMD64_LARGE_CF },
451		{ 0,			0 }
452	};
453	static const Val_desc2 vda_nf[] = {
454		{ SHF_WRITE,		ALL,	MSG_SHF_WRITE_NF },
455		{ SHF_ALLOC,		ALL,	MSG_SHF_ALLOC_NF },
456		{ SHF_EXECINSTR,	ALL,	MSG_SHF_EXECINSTR_NF },
457		{ SHF_MERGE,		ALL,	MSG_SHF_MERGE_NF },
458		{ SHF_STRINGS,		ALL,	MSG_SHF_STRINGS_NF },
459		{ SHF_INFO_LINK,	ALL,	MSG_SHF_INFO_LINK_NF },
460		{ SHF_LINK_ORDER,	ALL,	MSG_SHF_LINK_ORDER_NF },
461		{ SHF_OS_NONCONFORMING,	ALL,	MSG_SHF_OS_NONCONFORMING_NF },
462		{ SHF_GROUP,		ALL,	MSG_SHF_GROUP_NF },
463		{ SHF_TLS,		ALL,	MSG_SHF_TLS_NF },
464		{ SHF_EXCLUDE,		SOL,	MSG_SHF_EXCLUDE_NF },
465		{ SHF_ORDERED,		SOL,	MSG_SHF_ORDERED_NF },
466		{ SHF_AMD64_LARGE,	AMD,	MSG_SHF_AMD64_LARGE_NF },
467		{ 0,			0 }
468	};
469
470	return ((CONV_TYPE_FMT_ALT(fmt_flags) == CONV_FMT_ALT_NF) ?
471	    vda_nf : vda_cf);
472
473#undef ALL
474#undef SOL
475#undef AMD
476}
477
478conv_iter_ret_t
479conv_iter_sec_flags(conv_iter_osabi_t osabi, Half mach,
480    Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func, void *uvalue)
481{
482	static const Msg amd64_alias_cf[] = { MSG_SHF_X86_64_LARGE_CF };
483	static const conv_ds_msg_t ds_msg_amd64_alias_cf = {
484	    CONV_DS_MSG_INIT(SHF_X86_64_LARGE, amd64_alias_cf) };
485	static const conv_ds_t	*ds_amd64_alias_cf[] = {
486	    CONV_DS_ADDR(ds_msg_amd64_alias_cf), NULL };
487
488	static const Msg amd64_alias_nf[] = { MSG_SHF_X86_64_LARGE_NF };
489	static const conv_ds_msg_t ds_msg_amd64_alias_nf = {
490	    CONV_DS_MSG_INIT(SHF_X86_64_LARGE, amd64_alias_nf) };
491	static const conv_ds_t	*ds_amd64_alias_nf[] = {
492	    CONV_DS_ADDR(ds_msg_amd64_alias_nf), NULL };
493
494
495	if (conv_iter_vd2(osabi, mach, conv_sec_flags_strings(fmt_flags),
496	    func, uvalue) == CONV_ITER_DONE)
497		return (CONV_ITER_DONE);
498
499	/* SHF_AMD64_LARGE is also known as SHF_X86_64_LARGE */
500	if (mach == EM_AMD64) {
501		const conv_ds_t **ds;
502
503		ds = (CONV_TYPE_FMT_ALT(fmt_flags) == CONV_FMT_ALT_NF) ?
504		    ds_amd64_alias_nf : ds_amd64_alias_cf;
505
506		return (conv_iter_ds(ELFOSABI_NONE, mach, ds, func, uvalue));
507	}
508
509	return (CONV_ITER_CONT);
510}
511