elf.c revision 9273:9a0603d78ad3
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 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * String conversion routines for ELF header attributes.
29 */
30#include	<stdio.h>
31#include	<string.h>
32#include	"_conv.h"
33#include	"elf_msg.h"
34#include	<sys/elf_SPARC.h>
35
36
37
38static const conv_ds_t **
39ehdr_class_strings(Conv_fmt_flags_t fmt_flags)
40{
41	static const Msg	class_cf[] = {
42		MSG_ELFCLASSNONE_CF, MSG_ELFCLASS32_CF, MSG_ELFCLASS64_CF
43	};
44	static const Msg	class_nf[] = {
45		MSG_ELFCLASSNONE_NF, MSG_ELFCLASS32_NF, MSG_ELFCLASS64_NF
46	};
47	static const Msg	class_dump[] = {
48		MSG_ELFCLASSNONE_DMP, MSG_ELFCLASS32_DMP, MSG_ELFCLASS64_DMP
49	};
50
51	static const conv_ds_msg_t ds_classes_cf = {
52	    CONV_DS_MSG_INIT(ELFCLASSNONE, class_cf) };
53	static const conv_ds_msg_t ds_classes_nf = {
54	    CONV_DS_MSG_INIT(ELFCLASSNONE, class_nf) };
55	static const conv_ds_msg_t ds_classes_dump = {
56	    CONV_DS_MSG_INIT(ELFCLASSNONE, class_dump) };
57
58	static const conv_ds_t *ds_cf[] = { CONV_DS_ADDR(ds_classes_cf), NULL };
59	static const conv_ds_t *ds_nf[] = { CONV_DS_ADDR(ds_classes_nf), NULL };
60	static const conv_ds_t *ds_dump[] = {
61	    CONV_DS_ADDR(ds_classes_dump), NULL };
62
63	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
64	case CONV_FMT_ALT_DUMP:
65	case CONV_FMT_ALT_FILE:
66		return (ds_dump);
67	case CONV_FMT_ALT_NF:
68		return (ds_nf);
69	}
70
71	return (ds_cf);
72}
73
74const char *
75conv_ehdr_class(uchar_t class, Conv_fmt_flags_t fmt_flags,
76    Conv_inv_buf_t *inv_buf)
77{
78	return (conv_map_ds(ELFOSABI_NONE, EM_NONE, class,
79	    ehdr_class_strings(fmt_flags), fmt_flags, inv_buf));
80}
81
82conv_iter_ret_t
83conv_iter_ehdr_class(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
84    void *uvalue)
85{
86	return (conv_iter_ds(ELFOSABI_NONE, EM_NONE,
87	    ehdr_class_strings(fmt_flags), func, uvalue));
88}
89
90static const conv_ds_t **
91ehdr_data_strings(Conv_fmt_flags_t fmt_flags)
92{
93	static const Msg	data_cf[] = {
94		MSG_ELFDATANONE_CF, MSG_ELFDATA2LSB_CF, MSG_ELFDATA2MSB_CF
95	};
96	static const Msg	data_nf[] = {
97		MSG_ELFDATANONE_NF, MSG_ELFDATA2LSB_NF, MSG_ELFDATA2MSB_NF
98	};
99	static const Msg	data_dump[] = {
100		MSG_ELFDATANONE_DMP, MSG_ELFDATA2LSB_DMP, MSG_ELFDATA2MSB_DMP
101	};
102	static const Msg	data_file[] = {
103		MSG_ELFDATANONE_DMP, MSG_ELFDATA2LSB_FIL, MSG_ELFDATA2MSB_FIL
104	};
105
106
107	static const conv_ds_msg_t ds_data_cf = {
108	    CONV_DS_MSG_INIT(ELFCLASSNONE, data_cf) };
109	static const conv_ds_msg_t ds_data_nf = {
110	    CONV_DS_MSG_INIT(ELFCLASSNONE, data_nf) };
111	static const conv_ds_msg_t ds_data_dump = {
112	    CONV_DS_MSG_INIT(ELFCLASSNONE, data_dump) };
113	static const conv_ds_msg_t ds_data_file = {
114	    CONV_DS_MSG_INIT(ELFCLASSNONE, data_file) };
115
116	static const conv_ds_t *ds_cf[] = { CONV_DS_ADDR(ds_data_cf), NULL };
117	static const conv_ds_t *ds_nf[] = { CONV_DS_ADDR(ds_data_nf), NULL };
118	static const conv_ds_t *ds_dump[] = { CONV_DS_ADDR(ds_data_dump),
119	    NULL };
120	static const conv_ds_t *ds_file[] = { CONV_DS_ADDR(ds_data_file),
121	    NULL };
122
123	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
124	case CONV_FMT_ALT_DUMP:
125		return (ds_dump);
126	case CONV_FMT_ALT_FILE:
127		return (ds_file);
128	case CONV_FMT_ALT_NF:
129		return (ds_nf);
130	}
131
132	return (ds_cf);
133}
134
135const char *
136conv_ehdr_data(uchar_t data, Conv_fmt_flags_t fmt_flags,
137    Conv_inv_buf_t *inv_buf)
138{
139	return (conv_map_ds(ELFOSABI_NONE, EM_NONE, data,
140	    ehdr_data_strings(fmt_flags), fmt_flags, inv_buf));
141}
142
143conv_iter_ret_t
144conv_iter_ehdr_data(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
145    void *uvalue)
146{
147	return (conv_iter_ds(ELFOSABI_NONE, EM_NONE,
148	    ehdr_data_strings(fmt_flags), func, uvalue));
149}
150
151static const conv_ds_t **
152ehdr_mach_strings(Conv_fmt_flags_t fmt_flags)
153{
154
155	static const Msg mach_0_11_cf[] = {
156		MSG_EM_NONE_CF,		MSG_EM_M32_CF,
157		MSG_EM_SPARC_CF,	MSG_EM_386_CF,
158		MSG_EM_68K_CF,		MSG_EM_88K_CF,
159		MSG_EM_486_CF,		MSG_EM_860_CF,
160		MSG_EM_MIPS_CF,		MSG_EM_S370_CF,
161		MSG_EM_MIPS_RS3_LE_CF,	MSG_EM_RS6000_CF
162	};
163	static const Msg mach_0_11_nf[] = {
164		MSG_EM_NONE_NF,		MSG_EM_M32_NF,
165		MSG_EM_SPARC_NF,	MSG_EM_386_NF,
166		MSG_EM_68K_NF,		MSG_EM_88K_NF,
167		MSG_EM_486_NF,		MSG_EM_860_NF,
168		MSG_EM_MIPS_NF,		MSG_EM_S370_NF,
169		MSG_EM_MIPS_RS3_LE_NF,	MSG_EM_RS6000_NF
170	};
171	static const Msg mach_0_11_dmp[] = {
172		MSG_EM_NONE_DMP,	MSG_EM_M32_DMP,
173		MSG_EM_SPARC_DMP,	MSG_EM_386_DMP,
174		MSG_EM_68K_DMP,		MSG_EM_88K_DMP,
175		MSG_EM_486_DMP,		MSG_EM_860_DMP,
176		MSG_EM_MIPS_DMP,	MSG_EM_S370_CF,
177		MSG_EM_MIPS_RS3_LE_DMP,	MSG_EM_RS6000_DMP
178	};
179	static const conv_ds_msg_t ds_mach_0_11_cf = {
180	    CONV_DS_MSG_INIT(EM_NONE, mach_0_11_cf) };
181	static const conv_ds_msg_t ds_mach_0_11_nf = {
182	    CONV_DS_MSG_INIT(EM_NONE, mach_0_11_nf) };
183	static const conv_ds_msg_t ds_mach_0_11_dmp = {
184	    CONV_DS_MSG_INIT(EM_NONE, mach_0_11_dmp) };
185
186
187	static const Msg mach_15_22_cf[] = {
188		MSG_EM_PA_RISC_CF,	MSG_EM_NCUBE_CF,
189		MSG_EM_VPP500_CF,	MSG_EM_SPARC32PLUS_CF,
190		MSG_EM_960_CF,		MSG_EM_PPC_CF,
191		MSG_EM_PPC64_CF,	MSG_EM_S390_CF
192	};
193	static const Msg mach_15_22_nf[] = {
194		MSG_EM_PA_RISC_NF,	MSG_EM_NCUBE_NF,
195		MSG_EM_VPP500_NF,	MSG_EM_SPARC32PLUS_NF,
196		MSG_EM_960_NF,		MSG_EM_PPC_NF,
197		MSG_EM_PPC64_NF,	MSG_EM_S390_NF
198	};
199	static const Msg mach_15_22_dmp[] = {
200		MSG_EM_PA_RISC_DMP,	MSG_EM_NCUBE_DMP,
201		MSG_EM_VPP500_DMP,	MSG_EM_SPARC32PLUS_DMP,
202		MSG_EM_960_CF,		MSG_EM_PPC_DMP,
203		MSG_EM_PPC64_DMP,	MSG_EM_S390_CF
204	};
205	static const conv_ds_msg_t ds_mach_15_22_cf = {
206	    CONV_DS_MSG_INIT(EM_PA_RISC, mach_15_22_cf) };
207	static const conv_ds_msg_t ds_mach_15_22_nf = {
208	    CONV_DS_MSG_INIT(EM_PA_RISC, mach_15_22_nf) };
209	static const conv_ds_msg_t ds_mach_15_22_dmp = {
210	    CONV_DS_MSG_INIT(EM_PA_RISC, mach_15_22_dmp) };
211
212
213	static const Msg mach_36_63_cf[] = {
214		MSG_EM_V800_CF,		MSG_EM_FR20_CF,
215		MSG_EM_RH32_CF,		MSG_EM_RCE_CF,
216		MSG_EM_ARM_CF,		MSG_EM_ALPHA_CF,
217		MSG_EM_SH_CF,		MSG_EM_SPARCV9_CF,
218		MSG_EM_TRICORE_CF,	MSG_EM_ARC_CF,
219		MSG_EM_H8_300_CF,	MSG_EM_H8_300H_CF,
220		MSG_EM_H8S_CF,		MSG_EM_H8_500_CF,
221		MSG_EM_IA_64_CF,	MSG_EM_MIPS_X_CF,
222		MSG_EM_COLDFIRE_CF,	MSG_EM_68HC12_CF,
223		MSG_EM_MMA_CF,		MSG_EM_PCP_CF,
224		MSG_EM_NCPU_CF,		MSG_EM_NDR1_CF,
225		MSG_EM_STARCORE_CF,	MSG_EM_ME16_CF,
226		MSG_EM_ST100_CF,	MSG_EM_TINYJ_CF,
227		MSG_EM_AMD64_CF,	MSG_EM_PDSP_CF
228	};
229	static const Msg mach_36_63_nf[] = {
230		MSG_EM_V800_NF,		MSG_EM_FR20_NF,
231		MSG_EM_RH32_NF,		MSG_EM_RCE_NF,
232		MSG_EM_ARM_NF,		MSG_EM_ALPHA_NF,
233		MSG_EM_SH_NF,		MSG_EM_SPARCV9_NF,
234		MSG_EM_TRICORE_NF,	MSG_EM_ARC_NF,
235		MSG_EM_H8_300_NF,	MSG_EM_H8_300H_NF,
236		MSG_EM_H8S_NF,		MSG_EM_H8_500_NF,
237		MSG_EM_IA_64_NF,	MSG_EM_MIPS_X_NF,
238		MSG_EM_COLDFIRE_NF,	MSG_EM_68HC12_NF,
239		MSG_EM_MMA_NF,		MSG_EM_PCP_NF,
240		MSG_EM_NCPU_NF,		MSG_EM_NDR1_NF,
241		MSG_EM_STARCORE_NF,	MSG_EM_ME16_NF,
242		MSG_EM_ST100_NF,	MSG_EM_TINYJ_NF,
243		MSG_EM_AMD64_NF,	MSG_EM_PDSP_NF
244	};
245	static const Msg mach_36_63_dmp[] = {
246		MSG_EM_V800_CF,		MSG_EM_FR20_CF,
247		MSG_EM_RH32_CF,		MSG_EM_RCE_CF,
248		MSG_EM_ARM_DMP,		MSG_EM_ALPHA_DMP,
249		MSG_EM_SH_CF,		MSG_EM_SPARCV9_DMP,
250		MSG_EM_TRICORE_CF,	MSG_EM_ARC_CF,
251		MSG_EM_H8_300_CF,	MSG_EM_H8_300H_CF,
252		MSG_EM_H8S_CF,		MSG_EM_H8_500_CF,
253		MSG_EM_IA_64_DMP,	MSG_EM_MIPS_X_CF,
254		MSG_EM_COLDFIRE_CF,	MSG_EM_68HC12_CF,
255		MSG_EM_MMA_CF,		MSG_EM_PCP_CF,
256		MSG_EM_NCPU_CF,		MSG_EM_NDR1_CF,
257		MSG_EM_STARCORE_CF,	MSG_EM_ME16_CF,
258		MSG_EM_ST100_CF,	MSG_EM_TINYJ_CF,
259		MSG_EM_AMD64_DMP,	MSG_EM_PDSP_CF
260	};
261	static const conv_ds_msg_t ds_mach_36_63_cf = {
262	    CONV_DS_MSG_INIT(EM_V800, mach_36_63_cf) };
263	static const conv_ds_msg_t ds_mach_36_63_nf = {
264	    CONV_DS_MSG_INIT(EM_V800, mach_36_63_nf) };
265	static const conv_ds_msg_t ds_mach_36_63_dmp = {
266	    CONV_DS_MSG_INIT(EM_V800, mach_36_63_dmp) };
267
268
269	static const Msg mach_66_94_cf[] = {
270		MSG_EM_FX66_CF,		MSG_EM_ST9PLUS_CF,
271		MSG_EM_ST7_CF,		MSG_EM_68HC16_CF,
272		MSG_EM_68HC11_CF,	MSG_EM_68HC08_CF,
273		MSG_EM_68HC05_CF,	MSG_EM_SVX_CF,
274		MSG_EM_ST19_CF,		MSG_EM_VAX_CF,
275		MSG_EM_CRIS_CF,		MSG_EM_JAVELIN_CF,
276		MSG_EM_FIREPATH_CF,	MSG_EM_ZSP_CF,
277		MSG_EM_MMIX_CF,		MSG_EM_HUANY_CF,
278		MSG_EM_PRISM_CF,	MSG_EM_AVR_CF,
279		MSG_EM_FR30_CF,		MSG_EM_D10V_CF,
280		MSG_EM_D30V_CF,		MSG_EM_V850_CF,
281		MSG_EM_M32R_CF,		MSG_EM_MN10300_CF,
282		MSG_EM_MN10200_CF,	MSG_EM_PJ_CF,
283		MSG_EM_OPENRISC_CF,	MSG_EM_ARC_A5_CF,
284		MSG_EM_XTENSA_CF
285	};
286	static const Msg mach_66_94_nf[] = {
287		MSG_EM_FX66_NF,		MSG_EM_ST9PLUS_NF,
288		MSG_EM_ST7_NF,		MSG_EM_68HC16_NF,
289		MSG_EM_68HC11_NF,	MSG_EM_68HC08_NF,
290		MSG_EM_68HC05_NF,	MSG_EM_SVX_NF,
291		MSG_EM_ST19_NF,		MSG_EM_VAX_NF,
292		MSG_EM_CRIS_NF,		MSG_EM_JAVELIN_NF,
293		MSG_EM_FIREPATH_NF,	MSG_EM_ZSP_NF,
294		MSG_EM_MMIX_NF,		MSG_EM_HUANY_NF,
295		MSG_EM_PRISM_NF,	MSG_EM_AVR_NF,
296		MSG_EM_FR30_NF,		MSG_EM_D10V_NF,
297		MSG_EM_D30V_NF,		MSG_EM_V850_NF,
298		MSG_EM_M32R_NF,		MSG_EM_MN10300_NF,
299		MSG_EM_MN10200_NF,	MSG_EM_PJ_NF,
300		MSG_EM_OPENRISC_NF,	MSG_EM_ARC_A5_NF,
301		MSG_EM_XTENSA_NF
302	};
303	static const Msg mach_66_94_dmp[] = {
304		MSG_EM_FX66_CF,		MSG_EM_ST9PLUS_CF,
305		MSG_EM_ST7_CF,		MSG_EM_68HC16_CF,
306		MSG_EM_68HC11_CF,	MSG_EM_68HC08_CF,
307		MSG_EM_68HC05_CF,	MSG_EM_SVX_CF,
308		MSG_EM_ST19_CF,		MSG_EM_VAX_DMP,
309		MSG_EM_CRIS_CF,		MSG_EM_JAVELIN_CF,
310		MSG_EM_FIREPATH_CF,	MSG_EM_ZSP_CF,
311		MSG_EM_MMIX_CF,		MSG_EM_HUANY_CF,
312		MSG_EM_PRISM_CF,	MSG_EM_AVR_CF,
313		MSG_EM_FR30_CF,		MSG_EM_D10V_CF,
314		MSG_EM_D30V_CF,		MSG_EM_V850_CF,
315		MSG_EM_M32R_CF,		MSG_EM_MN10300_CF,
316		MSG_EM_MN10200_CF,	MSG_EM_PJ_CF,
317		MSG_EM_OPENRISC_CF,	MSG_EM_ARC_A5_CF,
318		MSG_EM_XTENSA_CF
319	};
320#if	(EM_NUM != (EM_XTENSA + 1))
321#error	"EM_NUM has grown"
322#endif
323	static const conv_ds_msg_t ds_mach_66_94_cf = {
324	    CONV_DS_MSG_INIT(EM_FX66, mach_66_94_cf) };
325	static const conv_ds_msg_t ds_mach_66_94_nf = {
326	    CONV_DS_MSG_INIT(EM_FX66, mach_66_94_nf) };
327	static const conv_ds_msg_t ds_mach_66_94_dmp = {
328	    CONV_DS_MSG_INIT(EM_FX66, mach_66_94_dmp) };
329
330
331	/* Build NULL terminated return arrays for each string style */
332	static const const conv_ds_t	*ds_cf[] = {
333		CONV_DS_ADDR(ds_mach_0_11_cf), CONV_DS_ADDR(ds_mach_15_22_cf),
334		CONV_DS_ADDR(ds_mach_36_63_cf), CONV_DS_ADDR(ds_mach_66_94_cf),
335		NULL
336	};
337	static const const conv_ds_t	*ds_nf[] = {
338		CONV_DS_ADDR(ds_mach_0_11_nf), CONV_DS_ADDR(ds_mach_15_22_nf),
339		CONV_DS_ADDR(ds_mach_36_63_nf), CONV_DS_ADDR(ds_mach_66_94_nf),
340		NULL
341	};
342	static const const conv_ds_t	*ds_dmp[] = {
343		CONV_DS_ADDR(ds_mach_0_11_dmp), CONV_DS_ADDR(ds_mach_15_22_dmp),
344		CONV_DS_ADDR(ds_mach_36_63_dmp),
345		CONV_DS_ADDR(ds_mach_66_94_dmp), NULL
346	};
347
348
349	/* Select the strings to use */
350	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
351	case CONV_FMT_ALT_DUMP:
352	case CONV_FMT_ALT_FILE:
353		return (ds_dmp);
354	case CONV_FMT_ALT_NF:
355		return (ds_nf);
356	}
357
358	return (ds_cf);
359}
360
361const char *
362conv_ehdr_mach(Half machine, Conv_fmt_flags_t fmt_flags,
363    Conv_inv_buf_t *inv_buf)
364{
365	return (conv_map_ds(ELFOSABI_NONE, EM_NONE, machine,
366	    ehdr_mach_strings(fmt_flags), fmt_flags, inv_buf));
367}
368
369conv_iter_ret_t
370conv_iter_ehdr_mach(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
371    void *uvalue)
372{
373	static const Val_desc extra_dmp_nf[] = {
374		{ EM_M32,		MSG_EM_M32_DMP},
375		{ EM_386,		MSG_EM_386_DMP },
376		{ EM_68K,		MSG_EM_68K_DMP },
377		{ EM_88K,		MSG_EM_88K_DMP },
378		{ EM_486,		MSG_EM_486_DMP },
379		{ EM_860,		MSG_EM_860_DMP },
380		{ EM_MIPS,		MSG_EM_MIPS_DMP },
381		{ EM_MIPS_RS3_LE,	MSG_EM_MIPS_RS3_LE_DMP },
382		{ EM_PPC,		MSG_EM_PPC_DMP },
383		{ EM_PPC64,		MSG_EM_PPC64_DMP },
384
385		{ 0 }
386	};
387
388	if (conv_iter_ds(ELFOSABI_NONE, EM_NONE,
389	    ehdr_mach_strings(fmt_flags), func, uvalue) == CONV_ITER_DONE)
390		return (CONV_ITER_DONE);
391
392	/*
393	 * For the NF style, we also supply a few of the traditional
394	 * dump versions for iteration, but not for display.
395	 */
396	if (CONV_TYPE_FMT_ALT(fmt_flags) == CONV_FMT_ALT_NF)
397		return (conv_iter_vd(extra_dmp_nf, func, uvalue));
398
399	return (CONV_ITER_CONT);
400}
401
402
403
404static const conv_ds_t **
405ehdr_eident_strings(Conv_fmt_flags_t fmt_flags)
406{
407	static const Msg	eident_cf[] = {
408		MSG_EI_MAG0_CF,		MSG_EI_MAG1_CF,
409		MSG_EI_MAG2_CF,		MSG_EI_MAG3_CF,
410		MSG_EI_CLASS_CF,	MSG_EI_DATA_CF,
411		MSG_EI_VERSION_CF,	MSG_EI_OSABI_CF,
412		MSG_EI_ABIVERSION_CF
413	};
414	static const Msg	eident_nf[] = {
415		MSG_EI_MAG0_NF,		MSG_EI_MAG1_NF,
416		MSG_EI_MAG2_NF,		MSG_EI_MAG3_NF,
417		MSG_EI_CLASS_NF,	MSG_EI_DATA_NF,
418		MSG_EI_VERSION_NF,	MSG_EI_OSABI_NF,
419		MSG_EI_ABIVERSION_NF
420	};
421#if EI_PAD != (EI_ABIVERSION + 1)
422error "EI_PAD has grown. Update etypes[]"
423#endif
424	static const conv_ds_msg_t ds_eident_cf = {
425		CONV_DS_MSG_INIT(EI_MAG0, eident_cf) };
426	static const conv_ds_msg_t ds_eident_nf = {
427		CONV_DS_MSG_INIT(EI_MAG0, eident_nf) };
428
429	/* Build NULL terminated return arrays for each string style */
430	static const const conv_ds_t	*ds_cf[] = {
431		CONV_DS_ADDR(ds_eident_cf), NULL };
432	static const conv_ds_t	*ds_nf[] = {
433		CONV_DS_ADDR(ds_eident_nf), NULL };
434
435	/* Select the strings to use */
436	return ((CONV_TYPE_FMT_ALT(fmt_flags) == CONV_FMT_ALT_CF) ?
437	    ds_cf : ds_nf);
438}
439
440conv_iter_ret_t
441conv_iter_ehdr_eident(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
442    void *uvalue)
443{
444	return (conv_iter_ds(ELFOSABI_NONE, EM_NONE,
445	    ehdr_eident_strings(fmt_flags), func, uvalue));
446}
447
448static const conv_ds_t **
449ehdr_type_strings(Conv_fmt_flags_t fmt_flags)
450{
451#define	SOL	ELFOSABI_SOLARIS, EM_NONE
452
453	static const Msg	type_cf[] = {
454		MSG_ET_NONE_CF,		MSG_ET_REL_CF,		MSG_ET_EXEC_CF,
455		MSG_ET_DYN_CF,		MSG_ET_CORE_CF
456	};
457	static const Msg	type_nf[] = {
458		MSG_ET_NONE_NF,		MSG_ET_REL_NF,		MSG_ET_EXEC_NF,
459		MSG_ET_DYN_NF,		MSG_ET_CORE_NF
460	};
461	static const Msg	type_dmp[] = {
462		MSG_ET_NONE_DMP,	MSG_ET_REL_DMP,		MSG_ET_EXEC_DMP,
463		MSG_ET_DYN_DMP,		MSG_ET_CORE_DMP
464	};
465#if ET_NUM != (ET_CORE + 1)
466error "ET_NUM has grown. Update types[]"
467#endif
468	static const conv_ds_msg_t ds_type_cf = {
469		CONV_DS_MSG_INIT(ET_NONE, type_cf) };
470	static const conv_ds_msg_t ds_type_nf = {
471		CONV_DS_MSG_INIT(ET_NONE, type_nf) };
472	static const conv_ds_msg_t ds_type_dmp = {
473		CONV_DS_MSG_INIT(ET_NONE, type_dmp) };
474
475	static const Val_desc2 type_osabi_cf[] = {
476		{ ET_SUNWPSEUDO,	SOL,	MSG_ET_SUNWPSEUDO_CF },
477		{ 0 }
478	};
479	static const Val_desc2 type_osabi_nf[] = {
480		{ ET_SUNWPSEUDO,	SOL,	MSG_ET_SUNWPSEUDO_NF },
481		{ 0 }
482	};
483	static const Val_desc2 type_osabi_dmp[] = {
484		{ ET_SUNWPSEUDO,	SOL,	MSG_ET_SUNWPSEUDO_DMP },
485		{ 0 }
486	};
487#if ET_LOSUNW != ET_SUNWPSEUDO
488error "ET_LOSUNW has grown. Update type_osabi[]"
489#endif
490	static const conv_ds_vd2_t ds_type_osabi_cf = {
491	    CONV_DS_VD2, ET_LOOS, ET_HIOS, type_osabi_cf };
492	static const conv_ds_vd2_t ds_type_osabi_nf = {
493	    CONV_DS_VD2, ET_LOOS, ET_HIOS, type_osabi_nf };
494	static const conv_ds_vd2_t ds_type_osabi_dmp = {
495	    CONV_DS_VD2, ET_LOOS, ET_HIOS, type_osabi_dmp };
496
497
498	/* Build NULL terminated return arrays for each string style */
499	static const const conv_ds_t	*ds_cf[] = {
500		CONV_DS_ADDR(ds_type_cf), CONV_DS_ADDR(ds_type_osabi_cf),
501		NULL };
502	static const conv_ds_t	*ds_nf[] = {
503		CONV_DS_ADDR(ds_type_nf), CONV_DS_ADDR(ds_type_osabi_nf),
504		NULL };
505	static const conv_ds_t	*ds_dmp[] = {
506		CONV_DS_ADDR(ds_type_dmp), CONV_DS_ADDR(ds_type_osabi_dmp),
507		NULL };
508
509	/* Select the strings to use */
510	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
511	case CONV_FMT_ALT_DUMP:
512		return (ds_dmp);
513	case CONV_FMT_ALT_NF:
514		return (ds_nf);
515	}
516
517	return (ds_cf);
518
519#undef SOL
520}
521
522const char *
523conv_ehdr_type(uchar_t osabi, Half etype, Conv_fmt_flags_t fmt_flags,
524    Conv_inv_buf_t *inv_buf)
525{
526	return (conv_map_ds(osabi, EM_NONE, etype,
527	    ehdr_type_strings(fmt_flags), fmt_flags, inv_buf));
528}
529
530conv_iter_ret_t
531conv_iter_ehdr_type(conv_iter_osabi_t osabi, Conv_fmt_flags_t fmt_flags,
532    conv_iter_cb_t func, void *uvalue)
533{
534	return (conv_iter_ds(osabi, EM_NONE,
535	    ehdr_type_strings(fmt_flags), func, uvalue));
536}
537
538static const conv_ds_t **
539ehdr_vers_strings(Conv_fmt_flags_t fmt_flags)
540{
541	static const Msg	versions_cf[] = {
542		MSG_EV_NONE_CF,		MSG_EV_CURRENT_CF
543	};
544	static const Msg	versions_nf[] = {
545		MSG_EV_NONE_NF,		MSG_EV_CURRENT_NF
546	};
547	static const Msg	versions_dmp[] = {
548		MSG_EV_NONE_DMP,	MSG_EV_CURRENT_DMP
549	};
550#if EV_NUM != 2
551error "EV_NUM has grown. Update versions[]"
552#endif
553	static const conv_ds_msg_t ds_versions_cf = {
554		CONV_DS_MSG_INIT(EV_NONE, versions_cf) };
555	static const conv_ds_msg_t ds_versions_nf = {
556		CONV_DS_MSG_INIT(EV_NONE, versions_nf) };
557	static const conv_ds_msg_t ds_versions_dmp = {
558		CONV_DS_MSG_INIT(EV_NONE, versions_dmp) };
559
560	/* Build NULL terminated return arrays for each string style */
561	static const const conv_ds_t	*ds_cf[] = {
562		CONV_DS_ADDR(ds_versions_cf), NULL };
563	static const conv_ds_t	*ds_nf[] = {
564		CONV_DS_ADDR(ds_versions_nf), NULL };
565	static const conv_ds_t	*ds_dmp[] = {
566		CONV_DS_ADDR(ds_versions_dmp), NULL };
567
568	/* Select the strings to use */
569	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
570	case CONV_FMT_ALT_DUMP:
571		return (ds_dmp);
572	case CONV_FMT_ALT_NF:
573		return (ds_nf);
574	}
575
576	return (ds_cf);
577}
578
579const char *
580conv_ehdr_vers(Word version, Conv_fmt_flags_t fmt_flags,
581    Conv_inv_buf_t *inv_buf)
582{
583	return (conv_map_ds(ELFOSABI_NONE, EM_NONE, version,
584	    ehdr_vers_strings(fmt_flags), fmt_flags, inv_buf));
585}
586
587conv_iter_ret_t
588conv_iter_ehdr_vers(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
589    void *uvalue)
590{
591	return (conv_iter_ds(ELFOSABI_NONE, EM_NONE,
592	    ehdr_vers_strings(fmt_flags), func, uvalue));
593}
594
595static void
596conv_ehdr_sparc_flags_strings(Conv_fmt_flags_t fmt_flags,
597    const conv_ds_msg_t **mm_msg, const Val_desc **flag_desc)
598{
599#define	EFLAGSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
600	MSG_EF_SPARCV9_TSO_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE +  \
601	MSG_EF_SPARC_SUN_US1_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE +  \
602	MSG_EF_SPARC_HAL_R1_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE +  \
603	MSG_EF_SPARC_SUN_US3_CF_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE +  \
604	CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
605
606	/*
607	 * Ensure that Conv_ehdr_flags_buf_t is large enough:
608	 *
609	 * EFLAGSZ is the real minimum size of the buffer required by
610	 * conv_ehdr_flags(). However, Conv_ehdr_flags_buf_t uses
611	 * CONV_EHDR_FLAG_BUFSIZE to set the buffer size. We do things
612	 * this way because the definition of EFLAGSZ uses information
613	 * that is not available in the environment of other programs
614	 * that include the conv.h header file.
615	 */
616#if (CONV_EHDR_FLAGS_BUFSIZE != EFLAGSZ) && !defined(__lint)
617#define	REPORT_BUFSIZE EFLAGSZ
618#include "report_bufsize.h"
619#error "CONV_EHDR_FLAGS_BUFSIZE does not match EFLAGSZ"
620#endif
621
622	static const Msg mm_flags_cf[] = {
623		MSG_EF_SPARCV9_TSO_CF,	MSG_EF_SPARCV9_PSO_CF,
624		MSG_EF_SPARCV9_RMO_CF
625	};
626	static const Msg mm_flags_nf[] = {
627		MSG_EF_SPARCV9_TSO_NF,	MSG_EF_SPARCV9_PSO_NF,
628		MSG_EF_SPARCV9_RMO_NF
629	};
630	static const conv_ds_msg_t ds_mm_flags_cf = {
631		CONV_DS_MSG_INIT(EF_SPARCV9_TSO, mm_flags_cf) };
632	static const conv_ds_msg_t ds_mm_flags_nf = {
633		CONV_DS_MSG_INIT(EF_SPARCV9_TSO, mm_flags_nf) };
634
635
636	static const Val_desc vda_cf[] = {
637		{ EF_SPARC_32PLUS,	MSG_EF_SPARC_32PLUS_CF },
638		{ EF_SPARC_SUN_US1,	MSG_EF_SPARC_SUN_US1_CF },
639		{ EF_SPARC_HAL_R1,	MSG_EF_SPARC_HAL_R1_CF },
640		{ EF_SPARC_SUN_US3,	MSG_EF_SPARC_SUN_US3_CF },
641		{ 0 }
642	};
643	static const Val_desc vda_nf[] = {
644		{ EF_SPARC_32PLUS,	MSG_EF_SPARC_32PLUS_NF },
645		{ EF_SPARC_SUN_US1,	MSG_EF_SPARC_SUN_US1_NF },
646		{ EF_SPARC_HAL_R1,	MSG_EF_SPARC_HAL_R1_NF },
647		{ EF_SPARC_SUN_US3,	MSG_EF_SPARC_SUN_US3_NF },
648		{ 0 }
649	};
650
651	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
652	default:
653		*mm_msg = &ds_mm_flags_cf;
654		*flag_desc = vda_cf;
655		break;
656	case CONV_FMT_ALT_NF:
657		*mm_msg = &ds_mm_flags_nf;
658		*flag_desc = vda_nf;
659		break;
660	}
661}
662
663/*
664 * Make a string representation of the e_flags field.
665 */
666const char *
667conv_ehdr_flags(Half mach, Word flags, Conv_fmt_flags_t fmt_flags,
668    Conv_ehdr_flags_buf_t *flags_buf)
669{
670	static const char *leading_str_arr[2];
671	static CONV_EXPN_FIELD_ARG conv_arg = {
672	    NULL, sizeof (flags_buf->buf), leading_str_arr };
673
674	const char **lstr;
675	const conv_ds_msg_t	*mm_msg;
676	const Val_desc		*vdp;
677	Word			mm;
678
679	/*
680	 * Non-SPARC architectures presently provide no known flags.
681	 */
682	if ((mach != EM_SPARCV9) && (((mach != EM_SPARC) &&
683	    (mach != EM_SPARC32PLUS)) || (flags == 0)))
684		return (conv_invalid_val(&flags_buf->inv_buf, flags,
685		    CONV_FMT_DECIMAL));
686
687	conv_arg.buf = flags_buf->buf;
688	conv_ehdr_sparc_flags_strings(fmt_flags, &mm_msg, &vdp);
689	conv_arg.oflags = conv_arg.rflags = flags;
690
691	mm = flags & EF_SPARCV9_MM;
692	lstr = leading_str_arr;
693	if ((mach == EM_SPARCV9) && (mm <= mm_msg->ds_topval)) {
694		*lstr++ = MSG_ORIG(mm_msg->ds_msg[mm]);
695		conv_arg.rflags &= ~EF_SPARCV9_MM;
696	}
697	*lstr = NULL;
698
699	(void) conv_expn_field(&conv_arg, vdp, fmt_flags);
700
701	return (conv_arg.buf);
702}
703
704conv_iter_ret_t
705conv_iter_ehdr_flags(Half mach, Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
706    void *uvalue)
707{
708
709	if ((mach == EM_SPARCV9) || (mach == EM_SPARC) ||
710	    (mach == EM_SPARC32PLUS) || (mach == CONV_MACH_ALL)) {
711		const conv_ds_msg_t	*ds_msg_mm;
712		const Val_desc		*vdp;
713
714		conv_ehdr_sparc_flags_strings(fmt_flags, &ds_msg_mm, &vdp);
715
716		if (mach == EM_SPARCV9) {
717			const conv_ds_t *ds[2];
718
719			ds[0] = CONV_DS_ADDR(ds_msg_mm);
720			ds[1] = NULL;
721
722			if (conv_iter_ds(ELFOSABI_NONE, mach, ds,
723			    func, uvalue) == CONV_ITER_DONE)
724				return (CONV_ITER_DONE);
725		}
726
727		return (conv_iter_vd(vdp, func, uvalue));
728	}
729
730	return (CONV_ITER_CONT);
731}
732
733static const conv_ds_t **
734ehdr_osabi_strings(Conv_fmt_flags_t fmt_flags)
735{
736
737	static const Msg osabi_0_3_cf[] = {
738		MSG_OSABI_NONE_CF,	MSG_OSABI_HPUX_CF,
739		MSG_OSABI_NETBSD_CF,	MSG_OSABI_LINUX_CF
740	};
741	static const Msg osabi_0_3_nf[] = {
742		MSG_OSABI_NONE_NF,	MSG_OSABI_HPUX_NF,
743		MSG_OSABI_NETBSD_NF,	MSG_OSABI_LINUX_NF
744	};
745	static const Msg osabi_0_3_dmp[] = {
746		MSG_OSABI_NONE_DMP,	MSG_OSABI_HPUX_DMP,
747		MSG_OSABI_NETBSD_DMP,	MSG_OSABI_LINUX_DMP
748	};
749	static const conv_ds_msg_t ds_osabi_0_3_cf = {
750	    CONV_DS_MSG_INIT(ELFOSABI_NONE, osabi_0_3_cf) };
751	static const conv_ds_msg_t ds_osabi_0_3_nf = {
752	    CONV_DS_MSG_INIT(ELFOSABI_NONE, osabi_0_3_nf) };
753	static const conv_ds_msg_t ds_osabi_0_3_dmp = {
754	    CONV_DS_MSG_INIT(ELFOSABI_NONE, osabi_0_3_dmp) };
755
756
757	static const Msg osabi_6_15_cf[] = {
758		MSG_OSABI_SOLARIS_CF,	MSG_OSABI_AIX_CF,
759		MSG_OSABI_IRIX_CF,	MSG_OSABI_FREEBSD_CF,
760		MSG_OSABI_TRU64_CF,	MSG_OSABI_MODESTO_CF,
761		MSG_OSABI_OPENBSD_CF,	MSG_OSABI_OPENVMS_CF,
762		MSG_OSABI_NSK_CF,	MSG_OSABI_AROS_CF
763	};
764	static const Msg osabi_6_15_nf[] = {
765		MSG_OSABI_SOLARIS_NF,	MSG_OSABI_AIX_NF,
766		MSG_OSABI_IRIX_NF,	MSG_OSABI_FREEBSD_NF,
767		MSG_OSABI_TRU64_NF,	MSG_OSABI_MODESTO_NF,
768		MSG_OSABI_OPENBSD_NF,	MSG_OSABI_OPENVMS_NF,
769		MSG_OSABI_NSK_NF,	MSG_OSABI_AROS_NF
770	};
771	static const Msg osabi_6_15_dmp[] = {
772		MSG_OSABI_SOLARIS_DMP,	MSG_OSABI_AIX_DMP,
773		MSG_OSABI_IRIX_DMP,	MSG_OSABI_FREEBSD_DMP,
774		MSG_OSABI_TRU64_DMP,	MSG_OSABI_MODESTO_DMP,
775		MSG_OSABI_OPENBSD_DMP,	MSG_OSABI_OPENVMS_DMP,
776		MSG_OSABI_NSK_DMP,	MSG_OSABI_AROS_DMP
777	};
778	static const conv_ds_msg_t ds_osabi_6_15_cf = {
779	    CONV_DS_MSG_INIT(ELFOSABI_SOLARIS, osabi_6_15_cf) };
780	static const conv_ds_msg_t ds_osabi_6_15_nf = {
781	    CONV_DS_MSG_INIT(ELFOSABI_SOLARIS, osabi_6_15_nf) };
782	static const conv_ds_msg_t ds_osabi_6_15_dmp = {
783	    CONV_DS_MSG_INIT(ELFOSABI_SOLARIS, osabi_6_15_dmp) };
784
785
786	static const Val_desc osabi_misc_cf[] = {
787		{ ELFOSABI_ARM,			MSG_OSABI_ARM_CF },
788		{ ELFOSABI_STANDALONE,		MSG_OSABI_STANDALONE_CF },
789		{ 0 }
790	};
791	static const Val_desc osabi_misc_nf[] = {
792		{ ELFOSABI_ARM,			MSG_OSABI_ARM_NF },
793		{ ELFOSABI_STANDALONE,		MSG_OSABI_STANDALONE_NF },
794		{ 0 }
795	};
796	static const Val_desc osabi_misc_dmp[] = {
797		{ ELFOSABI_ARM,			MSG_OSABI_ARM_DMP },
798		{ ELFOSABI_STANDALONE,		MSG_OSABI_STANDALONE_DMP },
799		{ 0 }
800	};
801	static const conv_ds_vd_t ds_osabi_misc_cf = {
802	    CONV_DS_VD, ELFOSABI_ARM, ELFOSABI_STANDALONE, osabi_misc_cf };
803	static const conv_ds_vd_t ds_osabi_misc_nf = {
804	    CONV_DS_VD, ELFOSABI_ARM, ELFOSABI_STANDALONE, osabi_misc_nf };
805	static const conv_ds_vd_t ds_osabi_misc_dmp = {
806	    CONV_DS_VD, ELFOSABI_ARM, ELFOSABI_STANDALONE, osabi_misc_dmp };
807
808	/* Build NULL terminated return arrays for each string style */
809	static const const conv_ds_t	*ds_cf[] = {
810		CONV_DS_ADDR(ds_osabi_0_3_cf), CONV_DS_ADDR(ds_osabi_6_15_cf),
811		CONV_DS_ADDR(ds_osabi_misc_cf), NULL };
812	static const const conv_ds_t	*ds_nf[] = {
813		CONV_DS_ADDR(ds_osabi_0_3_nf), CONV_DS_ADDR(ds_osabi_6_15_nf),
814		CONV_DS_ADDR(ds_osabi_misc_nf), NULL };
815	static const const conv_ds_t	*ds_dmp[] = {
816		CONV_DS_ADDR(ds_osabi_0_3_dmp), CONV_DS_ADDR(ds_osabi_6_15_dmp),
817		CONV_DS_ADDR(ds_osabi_misc_dmp), NULL };
818
819	/* Select the strings to use */
820	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
821	case CONV_FMT_ALT_DUMP:
822		return (ds_dmp);
823	case CONV_FMT_ALT_NF:
824		return (ds_nf);
825	}
826
827	return (ds_cf);
828}
829
830/*
831 * Make a string representation of the e_ident[EI_OSABI] field.
832 */
833const char *
834conv_ehdr_osabi(uchar_t osabi, Conv_fmt_flags_t fmt_flags,
835    Conv_inv_buf_t *inv_buf)
836{
837	return (conv_map_ds(ELFOSABI_NONE, EM_NONE, osabi,
838	    ehdr_osabi_strings(fmt_flags), fmt_flags, inv_buf));
839}
840
841conv_iter_ret_t
842conv_iter_ehdr_osabi(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
843    void *uvalue)
844{
845	if (conv_iter_ds(ELFOSABI_NONE, EM_NONE, ehdr_osabi_strings(fmt_flags),
846	    func, uvalue) == CONV_ITER_DONE)
847		return (CONV_ITER_DONE);
848
849	/*
850	 * ELFOSABI_NONE might have been better named ELFOSABI_SYSV. For the
851	 * CF and NF sytles, we supply that name for 0 in addition to NONE.
852	 */
853	switch (CONV_TYPE_FMT_ALT(fmt_flags)) {
854	case CONV_FMT_ALT_CF:
855		return ((* func)(MSG_ORIG(MSG_OSABI_SYSV_CF),
856		    ELFOSABI_NONE, uvalue));
857	case CONV_FMT_ALT_NF:
858		return ((* func)(MSG_ORIG(MSG_OSABI_SYSV_NF),
859		    ELFOSABI_NONE, uvalue));
860	}
861
862		return (CONV_ITER_CONT);
863}
864
865static const conv_ds_t **
866ehdr_abivers_strings(conv_iter_osabi_t osabi, Conv_fmt_flags_t fmt_flags)
867{
868	static const Msg	abiversions_cf[] = {
869		MSG_EAV_SUNW_NONE_CF,	MSG_EAV_SUNW_CURRENT_CF
870	};
871	static const Msg	abiversions_nf[] = {
872		MSG_EAV_SUNW_NONE_NF,	MSG_EAV_SUNW_CURRENT_NF
873	};
874#if EAV_SUNW_NUM != 2
875error "EAV_SUNW_NUM has grown. Update abiversions[]"
876#endif
877	static const conv_ds_msg_t ds_abiversions_cf = {
878		CONV_DS_MSG_INIT(EV_NONE, abiversions_cf) };
879	static const conv_ds_msg_t ds_abiversions_nf = {
880		CONV_DS_MSG_INIT(EV_NONE, abiversions_nf) };
881
882	/* Build NULL terminated return arrays for each string style */
883	static const const conv_ds_t	*ds_cf[] = {
884		CONV_DS_ADDR(ds_abiversions_cf), NULL };
885	static const conv_ds_t	*ds_nf[] = {
886		CONV_DS_ADDR(ds_abiversions_nf), NULL };
887
888	/* For non-Solaris OSABI, we don't have symbolic names */
889	static const conv_ds_t	*ds_none[] = { NULL };
890
891
892	/*
893	 * Select the strings to use. This is a rare case where
894	 * we don't treat ELFOSABI_NONE and ELFOSABI_SOLARIS
895	 * as the same thing. We should never create a Solaris
896	 * object tagged as ELFOSABI_NONE for which the abiversion
897	 * is non-zero.
898	 */
899	if ((osabi == ELFOSABI_SOLARIS) || (osabi == CONV_OSABI_ALL))
900		return ((CONV_TYPE_FMT_ALT(fmt_flags) == CONV_FMT_ALT_NF) ?
901		    ds_nf : ds_cf);
902
903	return (ds_none);
904}
905
906const char *
907conv_ehdr_abivers(uchar_t osabi, Word version, Conv_fmt_flags_t fmt_flags,
908    Conv_inv_buf_t *inv_buf)
909{
910	return (conv_map_ds(osabi, EM_NONE, version,
911	    ehdr_abivers_strings(osabi, fmt_flags), fmt_flags, inv_buf));
912}
913
914conv_iter_ret_t
915conv_iter_ehdr_abivers(conv_iter_osabi_t osabi, Conv_fmt_flags_t fmt_flags,
916    conv_iter_cb_t func, void *uvalue)
917{
918	return (conv_iter_ds(osabi, EM_NONE,
919	    ehdr_abivers_strings(osabi, fmt_flags), func, uvalue));
920}
921
922/*
923 * A generic means of returning additional information for a rejected file in
924 * terms of a string. ELFOSABI_SOLARIS is assummed.
925 */
926const char *
927conv_reject_desc(Rej_desc * rej, Conv_reject_desc_buf_t *reject_desc_buf,
928    Half mach)
929{
930	ushort_t	type = rej->rej_type;
931	uint_t		info = rej->rej_info;
932
933	switch (type) {
934	case SGS_REJ_MACH:
935		return (conv_ehdr_mach((Half)info, 0,
936		    &reject_desc_buf->inv_buf));
937	case SGS_REJ_CLASS:
938		return (conv_ehdr_class((uchar_t)info, 0,
939		    &reject_desc_buf->inv_buf));
940	case SGS_REJ_DATA:
941		return (conv_ehdr_data((uchar_t)info, 0,
942		    &reject_desc_buf->inv_buf));
943	case SGS_REJ_TYPE:
944		return (conv_ehdr_type(ELFOSABI_SOLARIS, (Half)info, 0,
945		    &reject_desc_buf->inv_buf));
946	case SGS_REJ_BADFLAG:
947	case SGS_REJ_MISFLAG:
948	case SGS_REJ_HAL:
949	case SGS_REJ_US3:
950		return (conv_ehdr_flags(mach, (Word)info, 0,
951		    &reject_desc_buf->flags_buf));
952	case SGS_REJ_UNKFILE:
953		return ((const char *)0);
954	case SGS_REJ_STR:
955	case SGS_REJ_HWCAP_1:
956	case SGS_REJ_SFCAP_1:
957		if (rej->rej_str)
958			return ((const char *)rej->rej_str);
959		else
960			return (MSG_ORIG(MSG_STR_EMPTY));
961	default:
962		return (conv_invalid_val(&reject_desc_buf->inv_buf, info,
963		    CONV_FMT_DECIMAL));
964	}
965}
966