ehdr.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#include	<stdio.h>
28#include	<ctype.h>
29#include	<elfedit.h>
30#include	<sys/elf_SPARC.h>
31#include	<sys/elf_amd64.h>
32#include	<strings.h>
33#include	<conv.h>
34#include	<debug.h>
35#include	<ehdr_msg.h>
36
37
38
39
40/*
41 * This module handles changes to the ELF header
42 */
43
44
45
46/*
47 * This module uses shared code for several of the commands.
48 * It is sometimes necessary to know which specific command
49 * is active.
50 */
51typedef enum {
52	/* Dump command, used as module default to display ELF header */
53	EHDR_CMD_T_DUMP =		0,	/* ehdr:dump */
54
55	/* Commands that correspond directly to ELF header fields */
56	EHDR_CMD_T_E_IDENT =		1,	/* ehdr:e_ident */
57	EHDR_CMD_T_E_TYPE =		2,	/* ehdr:e_type */
58	EHDR_CMD_T_E_MACHINE =		3,	/* ehdr:e_machine */
59	EHDR_CMD_T_E_VERSION =		4,	/* ehdr:e_version */
60	EHDR_CMD_T_E_ENTRY =		5,	/* ehdr:e_entry */
61	EHDR_CMD_T_E_PHOFF =		6,	/* ehdr:e_phoff */
62	EHDR_CMD_T_E_SHOFF =		7,	/* ehdr:e_shoff */
63	EHDR_CMD_T_E_FLAGS =		8,	/* ehdr:e_flags */
64	EHDR_CMD_T_E_EHSIZE =		9,	/* ehdr:e_ehsize */
65	EHDR_CMD_T_E_PHENTSIZE =	10,	/* ehdr:e_phentsize */
66	EHDR_CMD_T_E_PHNUM =		11,	/* ehdr:e_phnum */
67	EHDR_CMD_T_E_SHENTSIZE =	12,	/* ehdr:e_shentsize */
68	EHDR_CMD_T_E_SHNUM =		13,	/* ehdr:e_shnum */
69	EHDR_CMD_T_E_SHSTRNDX =		14,	/* ehdr:e_shstrndx */
70
71	/* Commands that correspond to the e_ident[] array in ELF hdr */
72	EHDR_CMD_T_EI_MAG0 =		15,	/* ehdr:ei_mag0 */
73	EHDR_CMD_T_EI_MAG1 =		16,	/* ehdr:ei_mag1 */
74	EHDR_CMD_T_EI_MAG2 =		17,	/* ehdr:ei_mag2 */
75	EHDR_CMD_T_EI_MAG3 =		18,	/* ehdr:ei_mag3 */
76	EHDR_CMD_T_EI_CLASS =		19,	/* ehdr:ei_class */
77	EHDR_CMD_T_EI_DATA =		20,	/* ehdr:ei_data */
78	EHDR_CMD_T_EI_VERSION =		21,	/* ehdr:ei_version */
79	EHDR_CMD_T_EI_OSABI =		22,	/* ehdr:ei_osabi */
80	EHDR_CMD_T_EI_ABIVERSION =	23	/* ehdr:ei_abiversion */
81} EHDR_CMD_T;
82
83
84
85
86
87
88#ifndef _ELF64
89/*
90 * We supply this function for the msg module
91 */
92const char *
93_ehdr_msg(Msg mid)
94{
95	return (gettext(MSG_ORIG(mid)));
96}
97#endif
98
99
100/*
101 * This function is supplied to elfedit through our elfedit_module_t
102 * definition. It translates the opaque elfedit_i18nhdl_t handles
103 * in our module interface into the actual strings for elfedit to
104 * use.
105 *
106 * note:
107 *	This module uses Msg codes for its i18n handle type.
108 *	So the translation is simply to use MSG_INTL() to turn
109 *	it into a string and return it.
110 */
111static const char *
112mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
113{
114	Msg msg = (Msg)hdl;
115
116	return (MSG_INTL(msg));
117}
118
119
120
121/*
122 * The ehdr_opt_t enum specifies a bit value for every optional
123 * argument allowed by a command in this module.
124 */
125typedef enum {
126	EHDR_OPT_F_AND =	1,	/* -and: AND (&) values to dest */
127	EHDR_OPT_F_CMP =	2,	/* -cmp: Complement (~) values */
128	EHDR_OPT_F_OR =		4,	/* -or: OR (|) values to dest */
129	EHDR_OPT_F_SHNDX =	8,	/* -shndx: sec argument is index of */
130					/*	section, not name */
131	EHDR_OPT_F_SHTYP =	16	/* -shtyp: sec argument is type of */
132					/*	section, not name */
133} ehdr_opt_t;
134
135
136/*
137 * A variable of type ARGSTATE is used by each command to maintain
138 * information about the arguments and related things. It is
139 * initialized by process_args(), and used by the other routines.
140 */
141typedef struct {
142	elfedit_obj_state_t	*obj_state;
143	ehdr_opt_t		optmask;   	/* Mask of options used */
144	int			argc;		/* # of plain arguments */
145	const char		**argv;		/* Plain arguments */
146} ARGSTATE;
147
148
149
150/*
151 * Standard argument processing for ehdr module
152 *
153 * entry
154 *	obj_state, argc, argv - Standard command arguments
155 *	argstate - Address of ARGSTATE block to be initialized
156 *
157 * exit:
158 *	On success, *argstate is initialized. On error,
159 *	an error is issued and this routine does not return.
160 */
161static void
162process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
163    ARGSTATE *argstate)
164{
165	elfedit_getopt_state_t	getopt_state;
166	elfedit_getopt_ret_t	*getopt_ret;
167
168	bzero(argstate, sizeof (*argstate));
169	argstate->obj_state = obj_state;
170
171	elfedit_getopt_init(&getopt_state, &argc, &argv);
172	/* Add each new option to the options mask */
173	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL)
174		argstate->optmask |= getopt_ret->gor_idmask;
175
176	/* If there may be an arbitrary amount of output, use a pager */
177	if (argc == 0)
178		elfedit_pager_init();
179
180	/* Return the updated values of argc/argv */
181	argstate->argc = argc;
182	argstate->argv = argv;
183}
184
185
186
187
188
189
190/*
191 * Format the given magic number byte into a buffer
192 *
193 * entry:
194 *	value - Value of the magic value byte given by
195 *		ehdr->ei_ident[EI_MAG?]
196 */
197static const char *
198conv_magic_value(int value)
199{
200	/*
201	 * This routine can be called twice within a single C statement,
202	 * so we use alternating buffers on each call to allow this
203	 * without requiring the caller to supply a buffer (the size of
204	 * which they don't know).
205	 */
206	static char buf1[20];
207	static char buf2[20];
208	static char *buf;
209
210	/* Switch buffers */
211	buf = (buf == buf1) ? buf2 : buf1;
212
213	if (isprint(value))
214		(void) snprintf(buf, sizeof (buf1),
215		    MSG_ORIG(MSG_FMT_HEXNUM_QCHR), value, value);
216	else
217		(void) snprintf(buf, sizeof (buf1),
218		    MSG_ORIG(MSG_FMT_HEXNUM), value);
219	return (buf);
220}
221
222
223
224/*
225 * Print ELF header values, taking the calling command, and output style
226 * into account.
227 *
228 * entry:
229 *	cmd - EHDR_CMD_T_* value giving identify of caller
230 *	e_ident_ndx - Ignored unless cmd is EHDR_CMD_T_E_IDENT. In IDENT
231 *		case, index of item in e_ident[] array to display, or
232 *		-1 to display the entire array.
233 *	autoprint - If True, output is only produced if the elfedit
234 *		autoprint flag is set. If False, output is always produced.
235 *	argstate - Argument state block
236 */
237static void
238print_ehdr(EHDR_CMD_T cmd, int e_ident_ndx, int autoprint,
239    ARGSTATE *argstate)
240{
241	elfedit_outstyle_t	outstyle;
242	Conv_fmt_flags_t	flags_fmt_flags = 0;
243	Ehdr		*ehdr;
244	int		c;
245	Conv_inv_buf_t	inv_buf;
246
247	if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))
248		return;
249
250	/*
251	 * Pick an output style. ehdr:dump is required to use the default
252	 * style. The other commands use the current output style.
253	 */
254	if (cmd == EHDR_CMD_T_DUMP) {
255		outstyle = ELFEDIT_OUTSTYLE_DEFAULT;
256	} else {
257		outstyle = elfedit_outstyle();
258
259		/*
260		 * When the caller specifies the simple output style,
261		 * omit the brackets from around the values.
262		 */
263		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)
264			flags_fmt_flags = CONV_FMT_NOBKT;
265
266		/*
267		 * For things that show a single header item, switch
268		 * from default to simple mode.
269		 */
270		if ((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) &&
271		    ((cmd != EHDR_CMD_T_E_IDENT) || (e_ident_ndx != -1)))
272			outstyle = ELFEDIT_OUTSTYLE_SIMPLE;
273	}
274
275	ehdr = argstate->obj_state->os_ehdr;
276
277	/*
278	 * If doing default output, use elfdump style where we
279	 * show the full ELF header. In this case, the command
280	 * that called us doesn't matter. This can only happen
281	 * from ehdr:dump or ehdr:e_ident/
282	 */
283	if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
284		const char *ndx, *value;
285		char ndx_buf[64], value_buf[20];
286		int i;
287
288		if (cmd == EHDR_CMD_T_DUMP) {
289			Elf_ehdr(NULL, ehdr,
290			    argstate->obj_state->os_secarr[0].sec_shdr);
291			elfedit_printf(MSG_ORIG(MSG_STR_NL));
292		}
293
294		/*
295		 * Elf_ehdr() does not display all of e_ident[], so we
296		 * augment by displaying the entire array separately.
297		 */
298		elfedit_printf(MSG_ORIG(MSG_STR_EIDENT_HDR));
299
300		for (i = 0; i < EI_NIDENT; i++) {
301			ndx = value = NULL;
302
303			switch (i) {
304			case EI_MAG0:
305			case EI_MAG1:
306			case EI_MAG2:
307			case EI_MAG3:
308				ndx = elfedit_atoconst_value_to_str(
309				    ELFEDIT_CONST_EI, i, 1);
310				value = conv_magic_value(ehdr->e_ident[i]);
311				break;
312			case EI_CLASS:
313				ndx = elfedit_atoconst_value_to_str(
314				    ELFEDIT_CONST_EI, EI_CLASS, 1);
315				value = conv_ehdr_class(ehdr->e_ident[EI_CLASS],
316				    0, &inv_buf);
317				break;
318			case EI_DATA:
319				ndx = elfedit_atoconst_value_to_str(
320				    ELFEDIT_CONST_EI, EI_DATA, 1);
321				value = conv_ehdr_data(ehdr->e_ident[EI_DATA],
322				    0, &inv_buf);
323				break;
324			case EI_VERSION:
325				ndx = elfedit_atoconst_value_to_str(
326				    ELFEDIT_CONST_EI, EI_VERSION, 1);
327				value = conv_ehdr_vers(
328				    ehdr->e_ident[EI_VERSION], 0, &inv_buf);
329				break;
330			case EI_OSABI:
331				ndx = elfedit_atoconst_value_to_str(
332				    ELFEDIT_CONST_EI, EI_OSABI, 1);
333				value = conv_ehdr_osabi(ehdr->e_ident[EI_OSABI],
334				    0, &inv_buf);
335				break;
336			case EI_ABIVERSION:
337				ndx = elfedit_atoconst_value_to_str(
338				    ELFEDIT_CONST_EI, EI_ABIVERSION, 1);
339				value = conv_ehdr_abivers(
340				    ehdr->e_ident[EI_OSABI],
341				    ehdr->e_ident[EI_ABIVERSION],
342				    CONV_FMT_DECIMAL, &inv_buf);
343				break;
344			default:
345				value = value_buf;
346				(void) snprintf(value_buf, sizeof (value_buf),
347				    MSG_ORIG(MSG_FMT_HEXNUM), ehdr->e_ident[i]);
348				break;
349			}
350
351			if (ndx == NULL)
352				(void) snprintf(ndx_buf, sizeof (ndx_buf),
353				    MSG_ORIG(MSG_FMT_BKTINT), i);
354			else
355				(void) snprintf(ndx_buf, sizeof (ndx_buf),
356				    MSG_ORIG(MSG_FMT_BKTSTR), ndx);
357			elfedit_printf(MSG_ORIG(MSG_FMT_EI_ELT),
358			    ndx_buf, value);
359		}
360		return;
361	}
362
363
364	switch (cmd) {
365	case EHDR_CMD_T_E_IDENT:
366		{
367			int		i, cnt;
368
369			/* Show one element, or the entire thing? */
370			if (e_ident_ndx == -1) {
371				i = 0;
372				cnt = EI_NIDENT;
373			} else {
374				i = e_ident_ndx;
375				cnt = 1;
376			}
377
378			for (; cnt-- > 0; i++) {
379				/*
380				 * If using numeric style, or there is
381				 * no conversion routine for this item,
382				 * print a simple hex value.
383				 */
384				if ((outstyle == ELFEDIT_OUTSTYLE_NUM) ||
385				    (i > EI_ABIVERSION)) {
386					elfedit_printf(
387					    MSG_ORIG(MSG_FMT_HEXNUMNL),
388					    ehdr->e_ident[i]);
389					continue;
390				}
391
392				/* Handle special cases in simple mode */
393				switch (i) {
394				case EI_MAG0:
395				case EI_MAG1:
396				case EI_MAG2:
397				case EI_MAG3:
398					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
399					    conv_magic_value(ehdr->e_ident[i]));
400					continue;
401				case EI_CLASS:
402					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
403					    conv_ehdr_class(
404					    ehdr->e_ident[EI_CLASS], 0,
405					    &inv_buf));
406					continue;
407				case EI_DATA:
408					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
409					    conv_ehdr_data(
410					    ehdr->e_ident[EI_DATA], 0,
411					    &inv_buf));
412					continue;
413				case EI_VERSION:
414					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
415					    conv_ehdr_vers(
416					    ehdr->e_ident[EI_VERSION], 0,
417					    &inv_buf));
418					continue;
419				case EI_OSABI:
420					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
421					    conv_ehdr_osabi(
422					    ehdr->e_ident[EI_OSABI], 0,
423					    &inv_buf));
424					continue;
425				case EI_ABIVERSION:
426					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
427					    conv_ehdr_abivers(
428					    ehdr->e_ident[EI_OSABI],
429					    ehdr->e_ident[EI_ABIVERSION],
430					    CONV_FMT_DECIMAL, &inv_buf));
431					continue;
432				}
433			}
434		}
435		return;
436
437	case EHDR_CMD_T_E_TYPE:
438		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)
439			elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
440			    conv_ehdr_type(ehdr->e_ident[EI_OSABI],
441			    ehdr->e_type, 0, &inv_buf));
442		else
443			elfedit_printf(MSG_ORIG(MSG_FMT_DECNUMNL),
444			    ehdr->e_type);
445		return;
446
447	case EHDR_CMD_T_E_MACHINE:
448		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
449			elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
450			    conv_ehdr_mach(ehdr->e_machine, 0, &inv_buf));
451		} else {
452			elfedit_printf(MSG_ORIG(MSG_FMT_DECNUMNL),
453			    EC_WORD(ehdr->e_machine));
454		}
455		return;
456
457	case EHDR_CMD_T_E_VERSION:
458		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)
459			elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
460			    conv_ehdr_vers(ehdr->e_version, 0, &inv_buf));
461		else
462			elfedit_printf(MSG_ORIG(MSG_FMT_DECNUMNL),
463			    ehdr->e_version);
464		return;
465
466	case EHDR_CMD_T_E_ENTRY:
467		elfedit_printf(MSG_ORIG(MSG_FMT_HEXNUMNL),
468		    EC_WORD(ehdr->e_entry));
469		return;
470
471	case EHDR_CMD_T_E_PHOFF:
472		elfedit_printf(MSG_ORIG(MSG_FMT_HEXNUMNL),
473		    EC_WORD(ehdr->e_phoff));
474		return;
475
476	case EHDR_CMD_T_E_SHOFF:
477		elfedit_printf(MSG_ORIG(MSG_FMT_HEXNUMNL),
478		    EC_WORD(ehdr->e_shoff));
479		return;
480
481	case EHDR_CMD_T_E_FLAGS:
482		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
483			Conv_ehdr_flags_buf_t	flags_buf;
484
485			elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
486			    conv_ehdr_flags(ehdr->e_machine, ehdr->e_flags,
487			    flags_fmt_flags, &flags_buf));
488		} else {
489			elfedit_printf(MSG_ORIG(MSG_FMT_HEXNUMNL),
490			    ehdr->e_flags);
491		}
492		return;
493
494	case EHDR_CMD_T_E_EHSIZE:
495		elfedit_printf(MSG_ORIG(MSG_FMT_DECNUMNL),
496		    EC_WORD(ehdr->e_ehsize));
497		return;
498
499	case EHDR_CMD_T_E_PHENTSIZE:
500		elfedit_printf(MSG_ORIG(MSG_FMT_DECNUMNL),
501		    EC_WORD(ehdr->e_phentsize));
502		return;
503
504	case EHDR_CMD_T_E_PHNUM:
505		{
506			Word num = ehdr->e_phnum;
507
508			/*
509			 * If using extended indexes, fetch the real
510			 * value from shdr[0].sh_info
511			 */
512			if (num == PN_XNUM)
513				num = argstate->obj_state->
514				    os_secarr[0].sec_shdr->sh_info;
515
516			elfedit_printf(MSG_ORIG(MSG_FMT_DECNUMNL),
517			    EC_WORD(num));
518		}
519		return;
520
521	case EHDR_CMD_T_E_SHENTSIZE:
522		elfedit_printf(MSG_ORIG(MSG_FMT_DECNUMNL),
523		    EC_WORD(ehdr->e_shentsize));
524		return;
525
526	case EHDR_CMD_T_E_SHNUM:
527		{
528			Word num = ehdr->e_shnum;
529
530			/*
531			 * If using extended indexes, fetch the real
532			 * value from shdr[0].sh_size
533			 */
534			if (num == 0)
535				num = argstate->obj_state->
536				    os_secarr[0].sec_shdr->sh_size;
537
538			elfedit_printf(MSG_ORIG(MSG_FMT_DECNUMNL),
539			    EC_WORD(num));
540		}
541		return;
542
543	case EHDR_CMD_T_E_SHSTRNDX:
544		{
545			Word num = ehdr->e_shstrndx;
546
547			/*
548			 * If using extended indexes, fetch the real
549			 * value from shdr[0].sh_link
550			 */
551			if (num == SHN_XINDEX)
552				num = argstate->obj_state->
553				    os_secarr[0].sec_shdr->sh_link;
554
555			elfedit_printf(MSG_ORIG(MSG_FMT_DECNUMNL),
556			    EC_WORD(num));
557		}
558		return;
559
560	case EHDR_CMD_T_EI_MAG0:
561	case EHDR_CMD_T_EI_MAG1:
562	case EHDR_CMD_T_EI_MAG2:
563	case EHDR_CMD_T_EI_MAG3:
564		/* This depends on EHDR_CMD_T_EI_MAG[0-3] being contiguous */
565		c = ehdr->e_ident[cmd - EHDR_CMD_T_EI_MAG0];
566		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)
567			elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
568			    conv_magic_value(c));
569		else
570			elfedit_printf(MSG_ORIG(MSG_FMT_HEXNUMNL), c);
571		return;
572
573	case EHDR_CMD_T_EI_CLASS:
574		c = ehdr->e_ident[EI_CLASS];
575		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)
576			elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
577			    conv_ehdr_class(c, 0, &inv_buf));
578		else
579			elfedit_printf(MSG_ORIG(MSG_FMT_HEXNUMNL), c);
580		return;
581
582	case EHDR_CMD_T_EI_DATA:
583		c = ehdr->e_ident[EI_DATA];
584		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)
585			elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
586			    conv_ehdr_data(c, 0, &inv_buf));
587		else
588			elfedit_printf(MSG_ORIG(MSG_FMT_HEXNUMNL), c);
589		return;
590
591	case EHDR_CMD_T_EI_VERSION:
592		c = ehdr->e_ident[EI_VERSION];
593		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)
594			elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
595			    conv_ehdr_vers(c, 0, &inv_buf));
596		else
597			elfedit_printf(MSG_ORIG(MSG_FMT_HEXNUMNL), c);
598		return;
599
600	case EHDR_CMD_T_EI_OSABI:
601		c = ehdr->e_ident[EI_OSABI];
602		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
603			elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
604			    conv_ehdr_osabi(c, 0, &inv_buf));
605		} else {
606			elfedit_printf(MSG_ORIG(MSG_FMT_HEXNUMNL),
607			    EC_WORD(c));
608		}
609		return;
610
611	case EHDR_CMD_T_EI_ABIVERSION:
612		c = ehdr->e_ident[EI_ABIVERSION];
613		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
614			elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
615			    conv_ehdr_abivers(ehdr->e_ident[EI_OSABI],
616			    c, CONV_FMT_DECIMAL, &inv_buf));
617		} else {
618			elfedit_printf(MSG_ORIG(MSG_FMT_HEXNUMNL),
619			    EC_WORD(c));
620		}
621		return;
622	}
623}
624
625
626/*
627 * Common body for the ehdr: module commands. These commands
628 * share a large amount of common behavior, so it is convenient
629 * to centralize things and use the cmd argument to handle the
630 * small differences.
631 *
632 * entry:
633 *	cmd - One of the EHDR_CMD_T_* constants listed above, specifying
634 *		which command to implement.
635 *	obj_state, argc, argv - Standard command arguments
636 */
637static elfedit_cmdret_t
638cmd_body(EHDR_CMD_T cmd, elfedit_obj_state_t *obj_state,
639    int argc, const char *argv[])
640{
641	/*
642	 * When a call comes in for ehdr:e_ident[ndx], and the
643	 * specified element is one that we have a special command
644	 * for, then we revector to that special command instead
645	 * of using the generic ehdr:e_ident processing. This array,
646	 * which is indexed by the e_ident[] index value is used
647	 * to decide if that is the case. If the resulting value
648	 * is EHDR_CMD_T_E_IDENT, then the generic processing is
649	 * used. Otherwise, we revector to the specified command.
650	 */
651	static const int e_ident_revector[16] = {
652		EHDR_CMD_T_EI_MAG0,		/* 0: EI_MAG0 */
653		EHDR_CMD_T_EI_MAG1,		/* 1: EI_MAG1 */
654		EHDR_CMD_T_EI_MAG2,		/* 2: EI_MAG2 */
655		EHDR_CMD_T_EI_MAG3,		/* 3: EI_MAG3 */
656		EHDR_CMD_T_EI_CLASS,		/* 4: EI_CLASS */
657		EHDR_CMD_T_EI_DATA,		/* 5: EI_DATA */
658		EHDR_CMD_T_EI_VERSION,		/* 6: EI_VERSION */
659		EHDR_CMD_T_EI_OSABI,		/* 7: EI_OSABI */
660		EHDR_CMD_T_EI_ABIVERSION,	/* 8: EI_ABIVERSION */
661		EHDR_CMD_T_E_IDENT,		/* 9: generic */
662		EHDR_CMD_T_E_IDENT,		/* 10: generic */
663		EHDR_CMD_T_E_IDENT,		/* 11: generic */
664		EHDR_CMD_T_E_IDENT,		/* 12: generic */
665		EHDR_CMD_T_E_IDENT,		/* 13: generic */
666		EHDR_CMD_T_E_IDENT,		/* 14: generic */
667		EHDR_CMD_T_E_IDENT,		/* 15: generic */
668	};
669
670
671	ARGSTATE		argstate;
672	Ehdr			*ehdr;
673	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
674	int			e_ident_ndx = -1;
675	Conv_inv_buf_t		inv_buf1, inv_buf2;
676
677	/* Process the optional arguments */
678	process_args(obj_state, argc, argv, &argstate);
679
680	/* Check number of arguments */
681	switch (cmd) {
682	case EHDR_CMD_T_DUMP:
683		/* ehdr:dump does not accept arguments */
684		if (argstate.argc > 0)
685			elfedit_command_usage();
686		break;
687	case EHDR_CMD_T_E_IDENT:
688		/*
689		 * ehdr:e_ident accepts 1 or 2 arguments, the first
690		 * being the index into the array, and the second being
691		 * the value. If there are arguments, then process the
692		 * index, and remove it from the argument list.
693		 */
694		if (argstate.argc > 0) {
695			if (argstate.argc > 2)
696				elfedit_command_usage();
697			e_ident_ndx = (int)
698			    elfedit_atoconst_range(argstate.argv[0],
699			    MSG_ORIG(MSG_STR_INDEX), 0, EI_NIDENT - 1,
700			    ELFEDIT_CONST_EI);
701			argstate.argc--;
702			argstate.argv++;
703
704			/*
705			 * If the index is for one of the e_ident elements
706			 * that we have a special command for, then switch
707			 * to that command. e_ident_revector[] returns
708			 * EHDR_CMD_T_E_IDENT in the cases where such a command
709			 * does not exist, in which case we'll continue with the
710			 * generic code.
711			 */
712			cmd = e_ident_revector[e_ident_ndx];
713		}
714		break;
715	case EHDR_CMD_T_E_FLAGS:
716		/* ehdr:e_flags accepts an arbitrary number of arguments */
717		break;
718	default:
719		/* The remaining commands accept a single optional argument */
720		if (argstate.argc > 1)
721			elfedit_command_usage();
722		break;
723	}
724
725	/* If there are no arguments, dump the ELF header and return */
726	if (argstate.argc == 0) {
727		print_ehdr(cmd, e_ident_ndx, 0, &argstate);
728		return (ELFEDIT_CMDRET_NONE);
729	}
730
731	ehdr = obj_state->os_ehdr;
732	switch (cmd) {
733		/*
734		 * EHDR_CMD_T_DUMP can't get here: It never has an
735		 * argument, and is handled above.
736		 */
737
738	case EHDR_CMD_T_E_IDENT:
739		{
740			/*
741			 * Only those e_ident[] elements for which we
742			 * don't have a specialized command come here.
743			 * The argument is a value to be set in
744			 * e_ident[e_ident_ndx].
745			 */
746			uchar_t value = (uchar_t)
747			    elfedit_atoui_range(argstate.argv[0],
748			    MSG_ORIG(MSG_STR_VALUE), 0, 255, NULL);
749
750			if (ehdr->e_ident[e_ident_ndx] == value) {
751				elfedit_msg(ELFEDIT_MSG_DEBUG,
752				    MSG_INTL(MSG_DEBUG_EI_D_X_OK),
753				    e_ident_ndx, EC_WORD(value));
754			} else {
755				elfedit_msg(ELFEDIT_MSG_DEBUG,
756				    MSG_INTL(MSG_DEBUG_EI_D_X_CHG),
757				    e_ident_ndx, ehdr->e_ident[e_ident_ndx],
758				    value);
759				ret = ELFEDIT_CMDRET_MOD;
760				ehdr->e_ident[e_ident_ndx] = value;
761			}
762		}
763		break;
764
765	case EHDR_CMD_T_E_TYPE:
766		{
767			/* The argument gives the object type */
768			Half type = (Half) elfedit_atoconst(argstate.argv[0],
769			    ELFEDIT_CONST_ET);
770			const char *name = MSG_ORIG(MSG_CMD_E_TYPE);
771
772			if (ehdr->e_type == type) {
773				elfedit_msg(ELFEDIT_MSG_DEBUG,
774				    MSG_INTL(MSG_DEBUG_E_S_OK), name,
775				    conv_ehdr_type(ehdr->e_ident[EI_OSABI],
776				    ehdr->e_type, 0, &inv_buf1));
777			} else {
778				elfedit_msg(ELFEDIT_MSG_DEBUG,
779				    MSG_INTL(MSG_DEBUG_E_S_CHG), name,
780				    conv_ehdr_type(ehdr->e_ident[EI_OSABI],
781				    ehdr->e_type, 0, &inv_buf1),
782				    conv_ehdr_type(ehdr->e_ident[EI_OSABI],
783				    type, 0, &inv_buf2));
784				ret = ELFEDIT_CMDRET_MOD;
785				ehdr->e_type = type;
786			}
787		}
788		break;
789
790	case EHDR_CMD_T_E_MACHINE:
791		{
792			/* The argument gives the machine code */
793			Half mach = (Half) elfedit_atoconst(argstate.argv[0],
794			    ELFEDIT_CONST_EM);
795			const char *name = MSG_ORIG(MSG_CMD_E_MACHINE);
796
797			if (ehdr->e_machine == mach) {
798				elfedit_msg(ELFEDIT_MSG_DEBUG,
799				    MSG_INTL(MSG_DEBUG_E_S_OK), name,
800				    conv_ehdr_mach(ehdr->e_machine, 0,
801				    &inv_buf1));
802			} else {
803				elfedit_msg(ELFEDIT_MSG_DEBUG,
804				    MSG_INTL(MSG_DEBUG_E_S_CHG), name,
805				    conv_ehdr_mach(ehdr->e_machine, 0,
806				    &inv_buf1),
807				    conv_ehdr_mach(mach, 0, &inv_buf2));
808				ret = ELFEDIT_CMDRET_MOD_OS_MACH;
809				ehdr->e_machine = mach;
810
811			}
812		}
813		break;
814
815	case EHDR_CMD_T_E_VERSION:
816		{
817			/* The argument gives the version */
818			Word ver = (Word) elfedit_atoconst(argstate.argv[0],
819			    ELFEDIT_CONST_EV);
820			const char *name = MSG_ORIG(MSG_CMD_E_VERSION);
821
822			if (ehdr->e_version == ver) {
823				elfedit_msg(ELFEDIT_MSG_DEBUG,
824				    MSG_INTL(MSG_DEBUG_E_S_OK), name,
825				    conv_ehdr_vers(ehdr->e_version, 0,
826				    &inv_buf1));
827			} else {
828				elfedit_msg(ELFEDIT_MSG_DEBUG,
829				    MSG_INTL(MSG_DEBUG_E_S_CHG), name,
830				    conv_ehdr_vers(ehdr->e_version, 0,
831				    &inv_buf1),
832				    conv_ehdr_vers(ver, 0, &inv_buf2));
833				ret = ELFEDIT_CMDRET_MOD;
834				ehdr->e_version = ver;
835			}
836		}
837		break;
838
839	case EHDR_CMD_T_E_ENTRY:
840		{
841			/* The argument gives the entry address */
842			Addr entry = (Addr)
843			    elfedit_atoui(argstate.argv[0], NULL);
844			const char *name = MSG_ORIG(MSG_CMD_E_ENTRY);
845
846			if (ehdr->e_entry == entry) {
847				elfedit_msg(ELFEDIT_MSG_DEBUG,
848				    MSG_INTL(MSG_DEBUG_E_LLX_OK), name,
849				    EC_ADDR(ehdr->e_entry));
850			} else {
851				elfedit_msg(ELFEDIT_MSG_DEBUG,
852				    MSG_INTL(MSG_DEBUG_E_LLX_CHG), name,
853				    EC_ADDR(ehdr->e_entry), EC_ADDR(entry));
854				ret = ELFEDIT_CMDRET_MOD;
855				ehdr->e_entry = entry;
856			}
857		}
858		break;
859
860	case EHDR_CMD_T_E_PHOFF:
861		{
862			/* The argument gives the program header offset */
863			Off off = (Off) elfedit_atoui(argstate.argv[0],
864			    NULL);
865			const char *name = MSG_ORIG(MSG_CMD_E_PHOFF);
866
867			if (ehdr->e_phoff == off) {
868				elfedit_msg(ELFEDIT_MSG_DEBUG,
869				    MSG_INTL(MSG_DEBUG_E_LLX_OK), name,
870				    EC_OFF(ehdr->e_phoff));
871			} else {
872				elfedit_msg(ELFEDIT_MSG_DEBUG,
873				    MSG_INTL(MSG_DEBUG_E_LLX_CHG), name,
874				    EC_OFF(ehdr->e_phoff), EC_OFF(off));
875				ret = ELFEDIT_CMDRET_MOD;
876				ehdr->e_phoff = off;
877			}
878		}
879		break;
880
881	case EHDR_CMD_T_E_SHOFF:
882		{
883			/* The argument gives the section header offset */
884			Off off = (Off) elfedit_atoui(argstate.argv[0],
885			    NULL);
886			const char *name = MSG_ORIG(MSG_CMD_E_SHOFF);
887
888			if (ehdr->e_shoff == off) {
889				elfedit_msg(ELFEDIT_MSG_DEBUG,
890				    MSG_INTL(MSG_DEBUG_E_LLX_OK), name,
891				    EC_OFF(ehdr->e_shoff));
892			} else {
893				elfedit_msg(ELFEDIT_MSG_DEBUG,
894				    MSG_INTL(MSG_DEBUG_E_LLX_CHG), name,
895				    EC_OFF(ehdr->e_shoff), EC_OFF(off));
896				ret = ELFEDIT_CMDRET_MOD;
897				ehdr->e_shoff = off;
898			}
899		}
900		break;
901
902	case EHDR_CMD_T_E_FLAGS:
903		{
904			Conv_ehdr_flags_buf_t flags_buf1, flags_buf2;
905			const char *name = MSG_ORIG(MSG_CMD_E_FLAGS);
906			Word flags = 0;
907			int i;
908
909			/* Collect the arguments */
910			for (i = 0; i < argstate.argc; i++)
911				flags |= (Word)
912				    elfedit_atoconst(argstate.argv[i],
913				    ELFEDIT_CONST_EF);
914
915			/* Complement the value? */
916			if (argstate.optmask & EHDR_OPT_F_CMP)
917				flags = ~flags;
918
919			/* Perform any requested bit operations */
920			if (argstate.optmask & EHDR_OPT_F_AND)
921				flags &= ehdr->e_flags;
922			else if (argstate.optmask & EHDR_OPT_F_OR)
923				flags |= ehdr->e_flags;
924
925			/* Set the value */
926			if (ehdr->e_flags == flags) {
927				elfedit_msg(ELFEDIT_MSG_DEBUG,
928				    MSG_INTL(MSG_DEBUG_E_S_OK), name,
929				    conv_ehdr_flags(ehdr->e_machine,
930				    ehdr->e_flags, 0, &flags_buf1));
931			} else {
932				elfedit_msg(ELFEDIT_MSG_DEBUG,
933				    MSG_INTL(MSG_DEBUG_E_S_CHG), name,
934				    conv_ehdr_flags(ehdr->e_machine,
935				    ehdr->e_flags, 0, &flags_buf1),
936				    conv_ehdr_flags(ehdr->e_machine,
937				    flags, 0, &flags_buf2));
938				ret = ELFEDIT_CMDRET_MOD;
939				ehdr->e_flags = flags;
940			}
941		}
942		break;
943
944	case EHDR_CMD_T_E_EHSIZE:
945		{
946			/* The argument gives the ELF header size */
947			Half ehsize = (Half) elfedit_atoui(argstate.argv[0],
948			    NULL);
949			const char *name = MSG_ORIG(MSG_CMD_E_EHSIZE);
950
951			if (ehdr->e_ehsize == ehsize) {
952				elfedit_msg(ELFEDIT_MSG_DEBUG,
953				    MSG_INTL(MSG_DEBUG_E_D_OK), name,
954				    EC_WORD(ehdr->e_ehsize));
955			} else {
956				elfedit_msg(ELFEDIT_MSG_DEBUG,
957				    MSG_INTL(MSG_DEBUG_E_D_CHG), name,
958				    EC_WORD(ehdr->e_ehsize), EC_WORD(ehsize));
959				ret = ELFEDIT_CMDRET_MOD;
960				ehdr->e_ehsize = ehsize;
961			}
962		}
963		break;
964
965	case EHDR_CMD_T_E_PHENTSIZE:
966		{
967			/*
968			 * The argument gives the size of a program
969			 * header element.
970			 */
971			Half phentsize = (Half) elfedit_atoui(argstate.argv[0],
972			    NULL);
973			const char *name = MSG_ORIG(MSG_CMD_E_PHENTSIZE);
974
975			if (ehdr->e_phentsize == phentsize) {
976				elfedit_msg(ELFEDIT_MSG_DEBUG,
977				    MSG_INTL(MSG_DEBUG_E_D_OK), name,
978				    EC_WORD(ehdr->e_phentsize));
979			} else {
980				elfedit_msg(ELFEDIT_MSG_DEBUG,
981				    MSG_INTL(MSG_DEBUG_E_D_CHG), name,
982				    EC_WORD(ehdr->e_phentsize),
983				    EC_WORD(phentsize));
984				ret = ELFEDIT_CMDRET_MOD;
985				ehdr->e_phentsize = phentsize;
986			}
987		}
988		break;
989
990	case EHDR_CMD_T_E_PHNUM:
991		{
992			/* The argument gives the number of program headers */
993			Word phnum = (Word) elfedit_atoui(argstate.argv[0],
994			    NULL);
995			const char *name = MSG_ORIG(MSG_CMD_E_PHNUM);
996			elfedit_section_t *sec0 = &obj_state->os_secarr[0];
997			Shdr *shdr0 = sec0->sec_shdr;
998			Half e_phnum;
999			Word sh_info;
1000
1001			if (phnum >= PN_XNUM) {
1002				e_phnum = PN_XNUM;
1003				sh_info = phnum;
1004			} else {
1005				e_phnum = phnum;
1006				sh_info = 0;
1007			}
1008
1009			if (ehdr->e_phnum == e_phnum) {
1010				elfedit_msg(ELFEDIT_MSG_DEBUG,
1011				    MSG_INTL(MSG_DEBUG_E_D_OK), name,
1012				    EC_WORD(ehdr->e_phnum));
1013			} else {
1014				elfedit_msg(ELFEDIT_MSG_DEBUG,
1015				    MSG_INTL(MSG_DEBUG_E_D_CHG), name,
1016				    EC_WORD(ehdr->e_phnum), e_phnum);
1017				ret = ELFEDIT_CMDRET_MOD;
1018				ehdr->e_phnum = e_phnum;
1019			}
1020			if (shdr0->sh_info == sh_info) {
1021				elfedit_msg(ELFEDIT_MSG_DEBUG,
1022				    MSG_INTL(MSG_DEBUG_SHDR0_D_OK),
1023				    MSG_ORIG(MSG_STR_SH_INFO),
1024				    EC_WORD(shdr0->sh_info));
1025			} else {
1026				elfedit_msg(ELFEDIT_MSG_DEBUG,
1027				    MSG_INTL(MSG_DEBUG_SHDR0_D_CHG),
1028				    MSG_ORIG(MSG_STR_SH_INFO),
1029				    EC_WORD(shdr0->sh_info), sh_info);
1030				ret = ELFEDIT_CMDRET_MOD;
1031				shdr0->sh_info = sh_info;
1032				elfedit_modified_shdr(sec0);
1033			}
1034		}
1035		break;
1036
1037	case EHDR_CMD_T_E_SHENTSIZE:
1038		{
1039			/*
1040			 * The argument gives the size of a program
1041			 * header element.
1042			 */
1043			Half shentsize = (Half) elfedit_atoui(argstate.argv[0],
1044			    NULL);
1045			const char *name = MSG_ORIG(MSG_CMD_E_SHENTSIZE);
1046
1047			if (ehdr->e_shentsize == shentsize) {
1048				elfedit_msg(ELFEDIT_MSG_DEBUG,
1049				    MSG_INTL(MSG_DEBUG_E_D_OK), name,
1050				    EC_WORD(ehdr->e_shentsize));
1051			} else {
1052				elfedit_msg(ELFEDIT_MSG_DEBUG,
1053				    MSG_INTL(MSG_DEBUG_E_D_CHG), name,
1054				    EC_WORD(ehdr->e_shentsize),
1055				    EC_WORD(shentsize));
1056				ret = ELFEDIT_CMDRET_MOD;
1057				ehdr->e_shentsize = shentsize;
1058			}
1059		}
1060		break;
1061
1062	case EHDR_CMD_T_E_SHNUM:
1063		{
1064			/* The argument gives the number of section headers */
1065			Word shnum = (Word) elfedit_atoui(argstate.argv[0],
1066			    NULL);
1067			const char *name = MSG_ORIG(MSG_CMD_E_SHNUM);
1068			elfedit_section_t *sec0 = &obj_state->os_secarr[0];
1069			Shdr *shdr0 = sec0->sec_shdr;
1070			Half e_shnum;
1071			Word sh_size;
1072
1073			if (shnum >= SHN_LORESERVE) {
1074				e_shnum = 0;
1075				sh_size = shnum;
1076			} else {
1077				e_shnum = shnum;
1078				sh_size = 0;
1079			}
1080
1081			if (ehdr->e_shnum == e_shnum) {
1082				elfedit_msg(ELFEDIT_MSG_DEBUG,
1083				    MSG_INTL(MSG_DEBUG_E_D_OK), name,
1084				    EC_WORD(ehdr->e_shnum));
1085			} else {
1086				elfedit_msg(ELFEDIT_MSG_DEBUG,
1087				    MSG_INTL(MSG_DEBUG_E_D_CHG), name,
1088				    EC_WORD(ehdr->e_shnum), e_shnum);
1089				ret = ELFEDIT_CMDRET_MOD;
1090				ehdr->e_shnum = e_shnum;
1091			}
1092			if (shdr0->sh_size == sh_size) {
1093				elfedit_msg(ELFEDIT_MSG_DEBUG,
1094				    MSG_INTL(MSG_DEBUG_SHDR0_D_OK),
1095				    MSG_ORIG(MSG_STR_SH_SIZE),
1096				    EC_WORD(shdr0->sh_size));
1097			} else {
1098				elfedit_msg(ELFEDIT_MSG_DEBUG,
1099				    MSG_INTL(MSG_DEBUG_SHDR0_D_CHG),
1100				    MSG_ORIG(MSG_STR_SH_SIZE),
1101				    EC_WORD(shdr0->sh_size), sh_size);
1102				ret = ELFEDIT_CMDRET_MOD;
1103				shdr0->sh_size = sh_size;
1104				elfedit_modified_shdr(sec0);
1105			}
1106		}
1107		break;
1108
1109	case EHDR_CMD_T_E_SHSTRNDX:
1110		{
1111			const char *name = MSG_ORIG(MSG_CMD_E_SHSTRNDX);
1112			Word shstrndx;
1113			elfedit_section_t *sec0 = &obj_state->os_secarr[0];
1114			Shdr *shdr0 = sec0->sec_shdr;
1115			Half e_shstrndx;
1116			Word sh_link;
1117
1118			/*
1119			 * By default, sec argument is name of section.
1120			 * If -shndx is used, it is a numeric index, and
1121			 * if -shtyp is used, it is a section type.
1122			 */
1123			if (argstate.optmask & EHDR_OPT_F_SHNDX)
1124				shstrndx = elfedit_atoshndx(argstate.argv[0],
1125				    obj_state->os_shnum);
1126			else if (argstate.optmask & EHDR_OPT_F_SHTYP)
1127				shstrndx = elfedit_type_to_shndx(obj_state,
1128				    elfedit_atoconst(argstate.argv[0],
1129				    ELFEDIT_CONST_SHT));
1130			else
1131				shstrndx = elfedit_name_to_shndx(obj_state,
1132				    argstate.argv[0]);
1133
1134			/* Warn if the section isn't a string table */
1135			if ((shstrndx >= obj_state->os_shnum) ||
1136			    ((shstrndx >= SHN_LORESERVE) &&
1137			    (shstrndx <= SHN_HIRESERVE)) ||
1138			    (obj_state->os_secarr[shstrndx].sec_shdr->sh_type !=
1139			    SHT_STRTAB))
1140				elfedit_msg(ELFEDIT_MSG_DEBUG,
1141				    MSG_INTL(MSG_DEBUG_NOTSTRTAB), name,
1142				    EC_WORD(shstrndx));
1143
1144			if (shstrndx >= SHN_LORESERVE) {
1145				e_shstrndx = SHN_XINDEX;
1146				sh_link = shstrndx;
1147			} else {
1148				e_shstrndx = shstrndx;
1149				sh_link = 0;
1150			}
1151
1152			if (ehdr->e_shstrndx == e_shstrndx) {
1153				elfedit_msg(ELFEDIT_MSG_DEBUG,
1154				    MSG_INTL(MSG_DEBUG_E_D_OK), name,
1155				    EC_WORD(ehdr->e_shstrndx));
1156			} else {
1157				elfedit_msg(ELFEDIT_MSG_DEBUG,
1158				    MSG_INTL(MSG_DEBUG_E_D_CHG), name,
1159				    EC_WORD(ehdr->e_shstrndx), e_shstrndx);
1160				ret = ELFEDIT_CMDRET_MOD;
1161				ehdr->e_shstrndx = e_shstrndx;
1162			}
1163			if (shdr0->sh_link == sh_link) {
1164				elfedit_msg(ELFEDIT_MSG_DEBUG,
1165				    MSG_INTL(MSG_DEBUG_SHDR0_D_OK),
1166				    MSG_ORIG(MSG_STR_SH_LINK),
1167				    EC_WORD(shdr0->sh_link));
1168			} else {
1169				elfedit_msg(ELFEDIT_MSG_DEBUG,
1170				    MSG_INTL(MSG_DEBUG_SHDR0_D_CHG),
1171				    MSG_ORIG(MSG_STR_SH_LINK),
1172				    EC_WORD(shdr0->sh_link), sh_link);
1173				ret = ELFEDIT_CMDRET_MOD;
1174				shdr0->sh_link = sh_link;
1175				elfedit_modified_shdr(sec0);
1176			}
1177		}
1178		break;
1179
1180	case EHDR_CMD_T_EI_MAG0:
1181	case EHDR_CMD_T_EI_MAG1:
1182	case EHDR_CMD_T_EI_MAG2:
1183	case EHDR_CMD_T_EI_MAG3:
1184		{
1185			/*
1186			 * This depends on EHDR_CMD_T_EI_MAG[0-3]
1187			 * being contiguous
1188			 */
1189			int ei_ndx = (cmd - EHDR_CMD_T_EI_MAG0) + EI_MAG0;
1190
1191			/* The argument gives the magic number byte */
1192			int mag = (int)elfedit_atoui_range(argstate.argv[0],
1193			    MSG_ORIG(MSG_STR_VALUE), 0, 255, NULL);
1194
1195			if (ehdr->e_ident[ei_ndx] == mag) {
1196				elfedit_msg(ELFEDIT_MSG_DEBUG,
1197				    MSG_INTL(MSG_DEBUG_EI_S_S_OK),
1198				    elfedit_atoconst_value_to_str(
1199				    ELFEDIT_CONST_EI, ei_ndx, 1),
1200				    conv_magic_value(ehdr->e_ident[ei_ndx]));
1201			} else {
1202				elfedit_msg(ELFEDIT_MSG_DEBUG,
1203				    MSG_INTL(MSG_DEBUG_EI_S_S_CHG),
1204				    elfedit_atoconst_value_to_str(
1205				    ELFEDIT_CONST_EI, ei_ndx, 1),
1206				    conv_magic_value(ehdr->e_ident[ei_ndx]),
1207				    conv_magic_value(mag));
1208				ret = ELFEDIT_CMDRET_MOD;
1209				ehdr->e_ident[ei_ndx] = mag;
1210			}
1211		}
1212		break;
1213
1214	case EHDR_CMD_T_EI_CLASS:
1215		{
1216			/* The argument gives the ELFCLASS value */
1217			int class = (int)elfedit_atoconst_range(
1218			    argstate.argv[0], MSG_ORIG(MSG_STR_VALUE), 0, 255,
1219			    ELFEDIT_CONST_ELFCLASS);
1220			const char *name = elfedit_atoconst_value_to_str(
1221			    ELFEDIT_CONST_EI, EI_CLASS, 1);
1222
1223			if (ehdr->e_ident[EI_CLASS] == class) {
1224				elfedit_msg(ELFEDIT_MSG_DEBUG,
1225				    MSG_INTL(MSG_DEBUG_EI_S_S_OK), name,
1226				    conv_ehdr_class(class, 0, &inv_buf1));
1227			} else {
1228				elfedit_msg(ELFEDIT_MSG_DEBUG,
1229				    MSG_INTL(MSG_DEBUG_EI_S_S_CHG), name,
1230				    conv_ehdr_class(ehdr->e_ident[EI_CLASS],
1231				    0, &inv_buf1),
1232				    conv_ehdr_class(class, 0, &inv_buf2));
1233				ret = ELFEDIT_CMDRET_MOD;
1234				ehdr->e_ident[EI_CLASS] = class;
1235			}
1236		}
1237		break;
1238
1239	case EHDR_CMD_T_EI_DATA:
1240		{
1241			/* The argument gives the ELFDATA value */
1242			int data = (int)elfedit_atoconst_range(argstate.argv[0],
1243			    MSG_ORIG(MSG_STR_VALUE), 0, 255,
1244			    ELFEDIT_CONST_ELFDATA);
1245			const char *name = elfedit_atoconst_value_to_str(
1246			    ELFEDIT_CONST_EI, EI_DATA, 1);
1247
1248			if (ehdr->e_ident[EI_DATA] == data) {
1249				elfedit_msg(ELFEDIT_MSG_DEBUG,
1250				    MSG_INTL(MSG_DEBUG_EI_S_S_OK), name,
1251				    conv_ehdr_data(data, 0, &inv_buf1));
1252			} else {
1253				elfedit_msg(ELFEDIT_MSG_DEBUG,
1254				    MSG_INTL(MSG_DEBUG_EI_S_S_CHG), name,
1255				    conv_ehdr_data(ehdr->e_ident[EI_DATA],
1256				    0, &inv_buf1),
1257				    conv_ehdr_data(data, 0, &inv_buf2));
1258				ret = ELFEDIT_CMDRET_MOD;
1259				ehdr->e_ident[EI_DATA] = data;
1260			}
1261		}
1262		break;
1263
1264	case EHDR_CMD_T_EI_VERSION:
1265		{
1266			/* The argument gives the version */
1267			int ver = (int)elfedit_atoconst_range(argstate.argv[0],
1268			    MSG_ORIG(MSG_STR_VALUE), 0, 255, ELFEDIT_CONST_EV);
1269			const char *name = elfedit_atoconst_value_to_str(
1270			    ELFEDIT_CONST_EI, EI_VERSION, 1);
1271
1272			if (ehdr->e_ident[EI_VERSION] == ver) {
1273				elfedit_msg(ELFEDIT_MSG_DEBUG,
1274				    MSG_INTL(MSG_DEBUG_EI_S_S_OK), name,
1275				    conv_ehdr_vers(ver, 0, &inv_buf1));
1276			} else {
1277				elfedit_msg(ELFEDIT_MSG_DEBUG,
1278				    MSG_INTL(MSG_DEBUG_EI_S_S_CHG), name,
1279				    conv_ehdr_vers(ehdr->e_ident[EI_VERSION],
1280				    0, &inv_buf1),
1281				    conv_ehdr_vers(ver, 0, &inv_buf2));
1282				ret = ELFEDIT_CMDRET_MOD;
1283				ehdr->e_ident[EI_VERSION] = ver;
1284			}
1285		}
1286		break;
1287
1288	case EHDR_CMD_T_EI_OSABI:
1289		{
1290			/* The argument gives the ABI code */
1291			int osabi = (int)elfedit_atoconst_range(
1292			    argstate.argv[0], MSG_ORIG(MSG_STR_VALUE), 0, 255,
1293			    ELFEDIT_CONST_ELFOSABI);
1294			const char *name = elfedit_atoconst_value_to_str(
1295			    ELFEDIT_CONST_EI, EI_OSABI, 1);
1296
1297			if (ehdr->e_ident[EI_OSABI] == osabi) {
1298				elfedit_msg(ELFEDIT_MSG_DEBUG,
1299				    MSG_INTL(MSG_DEBUG_EI_S_S_OK), name,
1300				    conv_ehdr_osabi(osabi, 0, &inv_buf1));
1301			} else {
1302				elfedit_msg(ELFEDIT_MSG_DEBUG,
1303				    MSG_INTL(MSG_DEBUG_EI_S_S_CHG), name,
1304				    conv_ehdr_osabi(ehdr->e_ident[EI_OSABI],
1305				    0, &inv_buf1),
1306				    conv_ehdr_osabi(osabi, 0, &inv_buf2));
1307				ret = ELFEDIT_CMDRET_MOD_OS_MACH;
1308				ehdr->e_ident[EI_OSABI] = osabi;
1309			}
1310		}
1311		break;
1312
1313	case EHDR_CMD_T_EI_ABIVERSION:
1314		{
1315			/* The argument gives the ABI version  */
1316			int abiver = (int)elfedit_atoconst_range(
1317			    argstate.argv[0], MSG_ORIG(MSG_STR_VALUE), 0, 255,
1318			    ELFEDIT_CONST_EAV);
1319			const char *name = elfedit_atoconst_value_to_str(
1320			    ELFEDIT_CONST_EI, EI_ABIVERSION, 1);
1321
1322			if (ehdr->e_ident[EI_ABIVERSION] == abiver) {
1323				elfedit_msg(ELFEDIT_MSG_DEBUG,
1324				    MSG_INTL(MSG_DEBUG_EI_S_S_OK), name,
1325				    conv_ehdr_abivers(ehdr->e_ident[EI_OSABI],
1326				    abiver, CONV_FMT_DECIMAL, &inv_buf1));
1327			} else {
1328				elfedit_msg(ELFEDIT_MSG_DEBUG,
1329				    MSG_INTL(MSG_DEBUG_EI_S_S_CHG), name,
1330				    conv_ehdr_abivers(ehdr->e_ident[EI_OSABI],
1331				    ehdr->e_ident[EI_ABIVERSION],
1332				    CONV_FMT_DECIMAL, &inv_buf1),
1333				    conv_ehdr_abivers(ehdr->e_ident[EI_OSABI],
1334				    abiver, CONV_FMT_DECIMAL, &inv_buf2));
1335				ret = ELFEDIT_CMDRET_MOD;
1336				ehdr->e_ident[EI_ABIVERSION] = abiver;
1337			}
1338		}
1339		break;
1340	}
1341
1342	/*
1343	 * If we modified the ELF header, tell libelf.
1344	 */
1345	if (ret == ELFEDIT_CMDRET_MOD)
1346		elfedit_modified_ehdr(obj_state);
1347
1348	/* Do autoprint */
1349	print_ehdr(cmd, e_ident_ndx, 1, &argstate);
1350
1351	return (ret);
1352}
1353
1354
1355
1356
1357/*
1358 * Command completion functions for the various commands
1359 */
1360
1361/*ARGSUSED*/
1362static void
1363cpl_e_ident(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1364    const char *argv[], int num_opt)
1365{
1366	elfedit_atoui_t	ndx;
1367
1368	/*
1369	 * This command doesn't accept options, so num_opt should be
1370	 * 0. This is a defensive measure, in case that should change.
1371	 */
1372	argc -= num_opt;
1373	argv += num_opt;
1374
1375	if (argc == 1) {
1376		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EI);
1377		return;
1378	}
1379
1380	if (argc != 2)
1381		return;
1382
1383	/*
1384	 * In order to offer up the right completion strings for
1385	 * the value, we need to know what index was given for
1386	 * the first argument. If we don't recognize the index,
1387	 * we want to return quietly without issuing an error,
1388	 * so we use elfedit_atoui_range2(), which returns
1389	 * a success/failure result and does not throw any errors.
1390	 */
1391	if (elfedit_atoconst_range2(argv[0], 0, EI_NIDENT - 1,
1392	    ELFEDIT_CONST_EI, &ndx) == 0)
1393		return;
1394	switch (ndx) {
1395	case EI_CLASS:
1396		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_ELFCLASS);
1397		break;
1398	case EI_DATA:
1399		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_ELFDATA);
1400		break;
1401	case EI_VERSION:
1402		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EV);
1403		break;
1404	case EI_OSABI:
1405		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_ELFOSABI);
1406		break;
1407	}
1408}
1409
1410/*ARGSUSED*/
1411static void
1412cpl_e_type(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1413    const char *argv[], int num_opt)
1414{
1415	/*
1416	 * This command doesn't accept options, so num_opt should be
1417	 * 0. This is a defensive measure, in case that should change.
1418	 */
1419	argc -= num_opt;
1420	argv += num_opt;
1421
1422	if (argc == 1)
1423		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_ET);
1424}
1425
1426/*ARGSUSED*/
1427static void
1428cpl_e_machine(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1429    const char *argv[], int num_opt)
1430{
1431	/*
1432	 * This command doesn't accept options, so num_opt should be
1433	 * 0. This is a defensive measure, in case that should change.
1434	 */
1435	argc -= num_opt;
1436	argv += num_opt;
1437
1438	if (argc == 1)
1439		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EM);
1440}
1441
1442/*ARGSUSED*/
1443static void
1444cpl_e_version(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1445    const char *argv[], int num_opt)
1446{
1447	/*
1448	 * This command doesn't accept options, so num_opt should be
1449	 * 0. This is a defensive measure, in case that should change.
1450	 */
1451	argc -= num_opt;
1452	argv += num_opt;
1453
1454	if (argc == 1)
1455		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EV);
1456}
1457
1458/*ARGSUSED*/
1459static void
1460cpl_e_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1461    const char *argv[], int num_opt)
1462{
1463	/* This routine allows multiple flags to be specified */
1464	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EF);
1465}
1466
1467/*ARGSUSED*/
1468static void
1469cpl_e_shstrndx(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1470    const char *argv[], int num_opt)
1471{
1472	enum { NAME, INDEX, TYPE } op;
1473	Word ndx;
1474
1475	/*
1476	 * The plainargument can be a section name, index, or
1477	 * type, based on the options used. All have completions.
1478	 */
1479	if (argc != (num_opt + 1))
1480		return;
1481
1482	op = NAME;
1483	for (ndx = 0; ndx < num_opt; ndx++) {
1484		if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0)
1485			op = INDEX;
1486		else if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0)
1487			op = TYPE;
1488	}
1489
1490	if (obj_state == NULL) {	/* No object available */
1491		if (op == TYPE)
1492			elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT);
1493		return;
1494	}
1495
1496	/*
1497	 * Loop over the sections and supply command completion
1498	 * for the string tables in the file.
1499	 */
1500	for (ndx = 0; ndx < obj_state->os_shnum; ndx++) {
1501		elfedit_section_t *sec = &obj_state->os_secarr[ndx];
1502
1503		if (sec->sec_shdr->sh_type != SHT_STRTAB)
1504			continue;
1505
1506		switch (op) {
1507		case NAME:
1508			elfedit_cpl_match(cpldata, sec->sec_name, 0);
1509			break;
1510		case INDEX:
1511			elfedit_cpl_ndx(cpldata, ndx);
1512			break;
1513		case TYPE:
1514			elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT_STRTAB);
1515			break;
1516		}
1517	}
1518}
1519
1520/*ARGSUSED*/
1521static void
1522cpl_ei_class(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1523    const char *argv[], int num_opt)
1524{
1525	/*
1526	 * This command doesn't accept options, so num_opt should be
1527	 * 0. This is a defensive measure, in case that should change.
1528	 */
1529	argc -= num_opt;
1530	argv += num_opt;
1531
1532	if (argc == 1)
1533		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_ELFCLASS);
1534}
1535
1536/*ARGSUSED*/
1537static void
1538cpl_ei_data(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1539    const char *argv[], int num_opt)
1540{
1541	/*
1542	 * This command doesn't accept options, so num_opt should be
1543	 * 0. This is a defensive measure, in case that should change.
1544	 */
1545	argc -= num_opt;
1546	argv += num_opt;
1547
1548	if (argc == 1)
1549		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_ELFDATA);
1550}
1551
1552/*ARGSUSED*/
1553static void
1554cpl_ei_osabi(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1555    const char *argv[], int num_opt)
1556{
1557	/*
1558	 * This command doesn't accept options, so num_opt should be
1559	 * 0. This is a defensive measure, in case that should change.
1560	 */
1561	argc -= num_opt;
1562	argv += num_opt;
1563
1564	if (argc == 1)
1565		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_ELFOSABI);
1566}
1567
1568/*ARGSUSED*/
1569static void
1570cpl_ei_abiversion(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1571    const char *argv[], int num_opt)
1572{
1573	/*
1574	 * This command doesn't accept options, so num_opt should be
1575	 * 0. This is a defensive measure, in case that should change.
1576	 */
1577	argc -= num_opt;
1578	argv += num_opt;
1579
1580	if (argc == 1)
1581		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EAV);
1582}
1583
1584
1585
1586
1587/*
1588 * Implementation functions for the commands
1589 */
1590static elfedit_cmdret_t
1591cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1592{
1593	return (cmd_body(EHDR_CMD_T_DUMP, obj_state, argc, argv));
1594}
1595
1596
1597static elfedit_cmdret_t
1598cmd_e_ident(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1599{
1600	return (cmd_body(EHDR_CMD_T_E_IDENT, obj_state, argc, argv));
1601}
1602
1603
1604static elfedit_cmdret_t
1605cmd_e_type(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1606{
1607	return (cmd_body(EHDR_CMD_T_E_TYPE, obj_state, argc, argv));
1608}
1609
1610
1611static elfedit_cmdret_t
1612cmd_e_machine(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1613{
1614	return (cmd_body(EHDR_CMD_T_E_MACHINE, obj_state, argc, argv));
1615}
1616
1617
1618static elfedit_cmdret_t
1619cmd_e_version(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1620{
1621	return (cmd_body(EHDR_CMD_T_E_VERSION, obj_state, argc, argv));
1622}
1623
1624
1625static elfedit_cmdret_t
1626cmd_e_entry(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1627{
1628	return (cmd_body(EHDR_CMD_T_E_ENTRY, obj_state, argc, argv));
1629}
1630
1631
1632static elfedit_cmdret_t
1633cmd_e_phoff(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1634{
1635	return (cmd_body(EHDR_CMD_T_E_PHOFF, obj_state, argc, argv));
1636}
1637
1638
1639static elfedit_cmdret_t
1640cmd_e_shoff(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1641{
1642	return (cmd_body(EHDR_CMD_T_E_SHOFF, obj_state, argc, argv));
1643}
1644
1645
1646static elfedit_cmdret_t
1647cmd_e_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1648{
1649	return (cmd_body(EHDR_CMD_T_E_FLAGS, obj_state, argc, argv));
1650}
1651
1652
1653static elfedit_cmdret_t
1654cmd_e_ehsize(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1655{
1656	return (cmd_body(EHDR_CMD_T_E_EHSIZE, obj_state, argc, argv));
1657}
1658
1659
1660static elfedit_cmdret_t
1661cmd_e_phentsize(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1662{
1663	return (cmd_body(EHDR_CMD_T_E_PHENTSIZE, obj_state, argc, argv));
1664}
1665
1666
1667static elfedit_cmdret_t
1668cmd_e_phnum(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1669{
1670	return (cmd_body(EHDR_CMD_T_E_PHNUM, obj_state, argc, argv));
1671}
1672
1673
1674static elfedit_cmdret_t
1675cmd_e_shentsize(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1676{
1677	return (cmd_body(EHDR_CMD_T_E_SHENTSIZE, obj_state, argc, argv));
1678}
1679
1680
1681static elfedit_cmdret_t
1682cmd_e_shnum(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1683{
1684	return (cmd_body(EHDR_CMD_T_E_SHNUM, obj_state, argc, argv));
1685}
1686
1687
1688static elfedit_cmdret_t
1689cmd_e_shstrndx(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1690{
1691	return (cmd_body(EHDR_CMD_T_E_SHSTRNDX, obj_state, argc, argv));
1692}
1693
1694
1695static elfedit_cmdret_t
1696cmd_ei_mag0(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1697{
1698	return (cmd_body(EHDR_CMD_T_EI_MAG0, obj_state, argc, argv));
1699}
1700
1701
1702static elfedit_cmdret_t
1703cmd_ei_mag1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1704{
1705	return (cmd_body(EHDR_CMD_T_EI_MAG1, obj_state, argc, argv));
1706}
1707
1708
1709static elfedit_cmdret_t
1710cmd_ei_mag2(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1711{
1712	return (cmd_body(EHDR_CMD_T_EI_MAG2, obj_state, argc, argv));
1713}
1714
1715
1716static elfedit_cmdret_t
1717cmd_ei_mag3(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1718{
1719	return (cmd_body(EHDR_CMD_T_EI_MAG3, obj_state, argc, argv));
1720}
1721
1722
1723static elfedit_cmdret_t
1724cmd_ei_class(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1725{
1726	return (cmd_body(EHDR_CMD_T_EI_CLASS, obj_state, argc, argv));
1727}
1728
1729
1730static elfedit_cmdret_t
1731cmd_ei_data(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1732{
1733	return (cmd_body(EHDR_CMD_T_EI_DATA, obj_state, argc, argv));
1734}
1735
1736
1737static elfedit_cmdret_t
1738cmd_ei_version(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1739{
1740	return (cmd_body(EHDR_CMD_T_EI_VERSION, obj_state, argc, argv));
1741}
1742
1743
1744static elfedit_cmdret_t
1745cmd_ei_osabi(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1746{
1747	return (cmd_body(EHDR_CMD_T_EI_OSABI, obj_state, argc, argv));
1748}
1749
1750
1751static elfedit_cmdret_t
1752cmd_ei_abiversion(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1753{
1754	return (cmd_body(EHDR_CMD_T_EI_ABIVERSION, obj_state, argc, argv));
1755}
1756
1757
1758
1759
1760/*ARGSUSED*/
1761elfedit_module_t *
1762elfedit_init(elfedit_module_version_t version)
1763{
1764	/* Many of the commands only accept -o */
1765	static elfedit_cmd_optarg_t opt_std[] = {
1766		{ ELFEDIT_STDOA_OPT_O, NULL,
1767		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1768		{ NULL }
1769	};
1770
1771
1772	/* ehdr:dump */
1773	static const char *name_dump[] = {
1774	    MSG_ORIG(MSG_CMD_DUMP),
1775	    MSG_ORIG(MSG_STR_EMPTY),	/* "" makes this the default command */
1776	    NULL
1777	};
1778
1779	/* ehdr:e_ident */
1780	static const char *name_e_ident[] = {
1781		MSG_ORIG(MSG_CMD_E_IDENT), NULL };
1782	static elfedit_cmd_optarg_t arg_e_ident[] = {
1783		{ MSG_ORIG(MSG_STR_INDEX),
1784		    /* MSG_INTL(MSG_ARGDESC_E_IDENT_NDX) */
1785		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_IDENT_NDX),
1786		    ELFEDIT_CMDOA_F_OPT, 0 },
1787		{ MSG_ORIG(MSG_STR_VALUE),
1788		    /* MSG_INTL(MSG_ARGDESC_E_IDENT_VALUE) */
1789		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_IDENT_VALUE),
1790		    ELFEDIT_CMDOA_F_OPT, 0 },
1791		{ NULL }
1792	};
1793
1794	/* ehdr:e_type */
1795	static const char *name_e_type[] = {
1796		MSG_ORIG(MSG_CMD_E_TYPE), NULL };
1797	static elfedit_cmd_optarg_t arg_e_type[] = {
1798		{ MSG_ORIG(MSG_STR_VALUE),
1799		    /* MSG_INTL(MSG_ARGDESC_E_TYPE_VALUE) */
1800		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_TYPE_VALUE),
1801		    ELFEDIT_CMDOA_F_OPT, 0 },
1802		{ NULL }
1803	};
1804
1805	/* ehdr:e_machine */
1806	static const char *name_e_machine[] = {
1807		MSG_ORIG(MSG_CMD_E_MACHINE), NULL };
1808	static elfedit_cmd_optarg_t arg_e_machine[] = {
1809		{ MSG_ORIG(MSG_STR_TYPE),
1810		    /* MSG_INTL(MSG_ARGDESC_E_MACHINE_VALUE) */
1811		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_MACHINE_VALUE),
1812		    ELFEDIT_CMDOA_F_OPT, 0 },
1813		{ NULL }
1814	};
1815
1816	/* ehdr:e_version */
1817	static const char *name_e_version[] = {
1818		MSG_ORIG(MSG_CMD_E_VERSION), NULL };
1819	static elfedit_cmd_optarg_t arg_e_version[] = {
1820		{ MSG_ORIG(MSG_STR_VERSION),
1821		    /* MSG_INTL(MSG_ARGDESC_E_VERSION_VALUE) */
1822		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_VERSION_VALUE),
1823		    ELFEDIT_CMDOA_F_OPT, 0 },
1824		{ NULL }
1825	};
1826
1827	/* ehdr:e_entry */
1828	static const char *name_e_entry[] = {
1829		MSG_ORIG(MSG_CMD_E_ENTRY), NULL };
1830	static elfedit_cmd_optarg_t arg_e_entry[] = {
1831		{ MSG_ORIG(MSG_STR_VALUE),
1832		    /* MSG_INTL(MSG_ARGDESC_E_ENTRY_VALUE) */
1833		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_ENTRY_VALUE),
1834		    ELFEDIT_CMDOA_F_OPT, 0 },
1835		{ NULL }
1836	};
1837
1838	/* ehdr:e_phoff */
1839	static const char *name_e_phoff[] = {
1840		MSG_ORIG(MSG_CMD_E_PHOFF), NULL };
1841	static elfedit_cmd_optarg_t arg_e_phoff[] = {
1842		{ MSG_ORIG(MSG_STR_OFFSET),
1843		    /* MSG_INTL(MSG_ARGDESC_E_PHOFF_VALUE) */
1844		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_PHOFF_VALUE),
1845		    ELFEDIT_CMDOA_F_OPT, 0 },
1846		{ NULL }
1847	};
1848
1849	/* ehdr:e_shoff */
1850	static const char *name_e_shoff[] = {
1851		MSG_ORIG(MSG_CMD_E_SHOFF), NULL };
1852	static elfedit_cmd_optarg_t arg_e_shoff[] = {
1853		{ MSG_ORIG(MSG_STR_OFFSET),
1854		    /* MSG_INTL(MSG_ARGDESC_E_SHOFF_VALUE) */
1855		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_SHOFF_VALUE),
1856		    ELFEDIT_CMDOA_F_OPT, 0 },
1857		{ NULL }
1858	};
1859
1860	/* ehdr:e_flags */
1861	static const char *name_e_flags[] = {
1862		MSG_ORIG(MSG_CMD_E_FLAGS), NULL };
1863	static elfedit_cmd_optarg_t opt_e_flags[] = {
1864		{ ELFEDIT_STDOA_OPT_AND, NULL,
1865		    ELFEDIT_CMDOA_F_INHERIT, EHDR_OPT_F_AND, EHDR_OPT_F_OR },
1866		{ ELFEDIT_STDOA_OPT_CMP, NULL,
1867		    ELFEDIT_CMDOA_F_INHERIT, EHDR_OPT_F_CMP, 0 },
1868		{ ELFEDIT_STDOA_OPT_O, NULL,
1869		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1870		{ ELFEDIT_STDOA_OPT_OR, NULL,
1871		    ELFEDIT_CMDOA_F_INHERIT, EHDR_OPT_F_OR, EHDR_OPT_F_AND },
1872		{ NULL }
1873	};
1874	static elfedit_cmd_optarg_t arg_e_flags[] = {
1875		{ MSG_ORIG(MSG_STR_FLAGVALUE),
1876		    /* MSG_INTL(MSG_ARGDESC_E_FLAGS_VALUE) */
1877		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_FLAGS_VALUE),
1878		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT, 0 },
1879		{ NULL }
1880	};
1881
1882	/* ehdr:e_ehsize */
1883	static const char *name_e_ehsize[] = {
1884		MSG_ORIG(MSG_CMD_E_EHSIZE), NULL };
1885	static elfedit_cmd_optarg_t arg_e_ehsize[] = {
1886		{ MSG_ORIG(MSG_STR_VALUE),
1887		    /* MSG_INTL(MSG_ARGDESC_E_EHSIZE_VALUE) */
1888		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_EHSIZE_VALUE),
1889		    ELFEDIT_CMDOA_F_OPT, 0 },
1890		{ NULL }
1891	};
1892
1893	/* ehdr:e_phentsize */
1894	static const char *name_e_phentsize[] = {
1895		MSG_ORIG(MSG_CMD_E_PHENTSIZE), NULL };
1896	static elfedit_cmd_optarg_t arg_e_phentsize[] = {
1897		{ MSG_ORIG(MSG_STR_VALUE),
1898		    /* MSG_INTL(MSG_ARGDESC_E_PHENTSIZE_VALUE) */
1899		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_PHENTSIZE_VALUE),
1900		    ELFEDIT_CMDOA_F_OPT, 0 },
1901		{ NULL }
1902	};
1903
1904	/* ehdr:e_phnum */
1905	static const char *name_e_phnum[] = {
1906		MSG_ORIG(MSG_CMD_E_PHNUM), NULL };
1907	static elfedit_cmd_optarg_t arg_e_phnum[] = {
1908		{ MSG_ORIG(MSG_STR_VALUE),
1909		    /* MSG_INTL(MSG_ARGDESC_E_PHNUM_VALUE) */
1910		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_PHNUM_VALUE),
1911		    ELFEDIT_CMDOA_F_OPT, 0 },
1912		{ NULL }
1913	};
1914
1915	/* ehdr:e_shentsize */
1916	static const char *name_e_shentsize[] = {
1917		MSG_ORIG(MSG_CMD_E_SHENTSIZE), NULL };
1918	static elfedit_cmd_optarg_t arg_e_shentsize[] = {
1919		{ MSG_ORIG(MSG_STR_VALUE),
1920		    /* MSG_INTL(MSG_ARGDESC_E_SHENTSIZE_VALUE) */
1921		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_SHENTSIZE_VALUE),
1922		    ELFEDIT_CMDOA_F_OPT, 0 },
1923		{ NULL }
1924	};
1925
1926	/* ehdr:e_shnum */
1927	static const char *name_e_shnum[] = {
1928		MSG_ORIG(MSG_CMD_E_SHNUM), NULL };
1929	static elfedit_cmd_optarg_t arg_e_shnum[] = {
1930		{ MSG_ORIG(MSG_STR_VALUE),
1931		    /* MSG_INTL(MSG_ARGDESC_E_SHNUM_VALUE) */
1932		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_SHNUM_VALUE),
1933		    ELFEDIT_CMDOA_F_OPT, 0 },
1934		{ NULL }
1935	};
1936
1937	/* ehdr:e_shstrndx */
1938	static const char *name_e_shstrndx[] = {
1939		MSG_ORIG(MSG_CMD_E_SHSTRNDX), NULL };
1940	static elfedit_cmd_optarg_t opt_e_shstrndx[] = {
1941		{ ELFEDIT_STDOA_OPT_O, NULL,
1942		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1943		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
1944		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
1945		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), 0,
1946		    EHDR_OPT_F_SHNDX, EHDR_OPT_F_SHTYP },
1947		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
1948		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
1949		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), 0,
1950		    EHDR_OPT_F_SHTYP, EHDR_OPT_F_SHNDX,  },
1951		{ NULL }
1952	};
1953	static elfedit_cmd_optarg_t arg_e_shstrndx[] = {
1954		{ MSG_ORIG(MSG_STR_SEC),
1955		    /* MSG_INTL(MSG_ARGDESC_E_SHSTRNDX_SEC) */
1956		    ELFEDIT_I18NHDL(MSG_ARGDESC_E_SHSTRNDX_SEC),
1957		    ELFEDIT_CMDOA_F_OPT, 0 },
1958		{ NULL }
1959	};
1960
1961	/* ehdr:ei_mag0 */
1962	static const char *name_ei_mag0[] = {
1963		MSG_ORIG(MSG_CMD_EI_MAG0), NULL };
1964	static elfedit_cmd_optarg_t arg_ei_mag0[] = {
1965		{ MSG_ORIG(MSG_STR_VALUE),
1966		    /* MSG_INTL(MSG_ARGDESC_EI_MAG0_VALUE) */
1967		    ELFEDIT_I18NHDL(MSG_ARGDESC_EI_MAG0_VALUE),
1968		    ELFEDIT_CMDOA_F_OPT, 0 },
1969		{ NULL }
1970	};
1971
1972	/* ehdr:ei_mag1 */
1973	static const char *name_ei_mag1[] = {
1974		MSG_ORIG(MSG_CMD_EI_MAG1), NULL };
1975	static elfedit_cmd_optarg_t arg_ei_mag1[] = {
1976		{ MSG_ORIG(MSG_STR_VALUE),
1977		    /* MSG_INTL(MSG_ARGDESC_EI_MAG1_VALUE) */
1978		    ELFEDIT_I18NHDL(MSG_ARGDESC_EI_MAG1_VALUE),
1979		    ELFEDIT_CMDOA_F_OPT, 0 },
1980		{ NULL }
1981	};
1982
1983	/* ehdr:ei_mag2 */
1984	static const char *name_ei_mag2[] = {
1985		MSG_ORIG(MSG_CMD_EI_MAG2), NULL };
1986	static elfedit_cmd_optarg_t arg_ei_mag2[] = {
1987		{ MSG_ORIG(MSG_STR_VALUE),
1988		    /* MSG_INTL(MSG_ARGDESC_EI_MAG2_VALUE) */
1989		    ELFEDIT_I18NHDL(MSG_ARGDESC_EI_MAG2_VALUE),
1990		    ELFEDIT_CMDOA_F_OPT, 0 },
1991		{ NULL }
1992	};
1993
1994	/* ehdr:ei_mag3 */
1995	static const char *name_ei_mag3[] = {
1996		MSG_ORIG(MSG_CMD_EI_MAG3), NULL };
1997	static elfedit_cmd_optarg_t arg_ei_mag3[] = {
1998		{ MSG_ORIG(MSG_STR_VALUE),
1999		    /* MSG_INTL(MSG_ARGDESC_EI_MAG3_VALUE) */
2000		    ELFEDIT_I18NHDL(MSG_ARGDESC_EI_MAG3_VALUE),
2001		    ELFEDIT_CMDOA_F_OPT, 0 },
2002		{ NULL }
2003	};
2004
2005	/* ehdr:ei_class */
2006	static const char *name_ei_class[] = {
2007		MSG_ORIG(MSG_CMD_EI_CLASS), NULL };
2008	static elfedit_cmd_optarg_t arg_ei_class[] = {
2009		{ MSG_ORIG(MSG_STR_VALUE),
2010		    /* MSG_INTL(MSG_ARGDESC_EI_CLASS_VALUE) */
2011		    ELFEDIT_I18NHDL(MSG_ARGDESC_EI_CLASS_VALUE),
2012		    ELFEDIT_CMDOA_F_OPT, 0 },
2013		{ NULL }
2014	};
2015
2016	/* ehdr:ei_data */
2017	static const char *name_ei_data[] = {
2018		MSG_ORIG(MSG_CMD_EI_DATA), NULL };
2019	static elfedit_cmd_optarg_t arg_ei_data[] = {
2020		{ MSG_ORIG(MSG_STR_VALUE),
2021		    /* MSG_INTL(MSG_ARGDESC_EI_DATA_VALUE) */
2022		    ELFEDIT_I18NHDL(MSG_ARGDESC_EI_DATA_VALUE),
2023		    ELFEDIT_CMDOA_F_OPT, 0 },
2024		{ NULL }
2025	};
2026
2027	/* ehdr:ei_version */
2028	static const char *name_ei_version[] = {
2029		MSG_ORIG(MSG_CMD_EI_VERSION), NULL };
2030	/* Note: arg_e_version is also used for this command */
2031
2032	/* ehdr:ei_osabi */
2033	static const char *name_ei_osabi[] = {
2034		MSG_ORIG(MSG_CMD_EI_OSABI), NULL };
2035	static elfedit_cmd_optarg_t arg_ei_osabi[] = {
2036		{ MSG_ORIG(MSG_STR_VALUE),
2037		    /* MSG_INTL(MSG_ARGDESC_EI_OSABI_VALUE) */
2038		    ELFEDIT_I18NHDL(MSG_ARGDESC_EI_OSABI_VALUE),
2039		    ELFEDIT_CMDOA_F_OPT, 0 },
2040		{ NULL }
2041	};
2042
2043	/* ehdr:ei_abiversion */
2044	static const char *name_ei_abiversion[] = {
2045		MSG_ORIG(MSG_CMD_EI_ABIVERSION), NULL };
2046	static elfedit_cmd_optarg_t arg_ei_abiversion[] = {
2047		{ MSG_ORIG(MSG_STR_VALUE),
2048		    /* MSG_INTL(MSG_ARGDESC_EI_ABIVERSION_VALUE) */
2049		    ELFEDIT_I18NHDL(MSG_ARGDESC_EI_ABIVERSION_VALUE),
2050		    ELFEDIT_CMDOA_F_OPT, 0 },
2051		{ NULL }
2052	};
2053
2054
2055
2056
2057	static elfedit_cmd_t cmds[] = {
2058		/* ehdr:dump */
2059		{ cmd_dump, NULL, name_dump,
2060		    /* MSG_INTL(MSG_DESC_DUMP) */
2061		    ELFEDIT_I18NHDL(MSG_DESC_DUMP),
2062		    /* MSG_INTL(MSG_HELP_DUMP) */
2063		    ELFEDIT_I18NHDL(MSG_HELP_DUMP),
2064		    NULL, NULL },
2065
2066		/* ehdr:e_ident */
2067		{ cmd_e_ident, cpl_e_ident, name_e_ident,
2068		    /* MSG_INTL(MSG_DESC_E_IDENT) */
2069		    ELFEDIT_I18NHDL(MSG_DESC_E_IDENT),
2070		    /* MSG_INTL(MSG_HELP_E_IDENT) */
2071		    ELFEDIT_I18NHDL(MSG_HELP_E_IDENT),
2072		    opt_std, arg_e_ident },
2073
2074		/* ehdr:e_type */
2075		{ cmd_e_type, cpl_e_type, name_e_type,
2076		    /* MSG_INTL(MSG_DESC_E_TYPE) */
2077		    ELFEDIT_I18NHDL(MSG_DESC_E_TYPE),
2078		    /* MSG_INTL(MSG_HELP_E_TYPE) */
2079		    ELFEDIT_I18NHDL(MSG_HELP_E_TYPE),
2080		    opt_std, arg_e_type },
2081
2082		/* ehdr:e_machine */
2083		{ cmd_e_machine, cpl_e_machine, name_e_machine,
2084		    /* MSG_INTL(MSG_DESC_E_MACHINE) */
2085		    ELFEDIT_I18NHDL(MSG_DESC_E_MACHINE),
2086		    /* MSG_INTL(MSG_HELP_E_MACHINE) */
2087		    ELFEDIT_I18NHDL(MSG_HELP_E_MACHINE),
2088		    opt_std, arg_e_machine },
2089
2090		/* ehdr:e_version */
2091		{ cmd_e_version, cpl_e_version, name_e_version,
2092		    /* MSG_INTL(MSG_DESC_E_VERSION) */
2093		    ELFEDIT_I18NHDL(MSG_DESC_E_VERSION),
2094		    /* MSG_INTL(MSG_HELP_E_VERSION) */
2095		    ELFEDIT_I18NHDL(MSG_HELP_E_VERSION),
2096		    opt_std, arg_e_version },
2097
2098		/* ehdr:e_entry */
2099		{ cmd_e_entry, NULL, name_e_entry,
2100		    /* MSG_INTL(MSG_DESC_E_ENTRY) */
2101		    ELFEDIT_I18NHDL(MSG_DESC_E_ENTRY),
2102		    /* MSG_INTL(MSG_HELP_E_ENTRY) */
2103		    ELFEDIT_I18NHDL(MSG_HELP_E_ENTRY),
2104		    opt_std, arg_e_entry },
2105
2106		/* ehdr:e_phoff */
2107		{ cmd_e_phoff, NULL, name_e_phoff,
2108		    /* MSG_INTL(MSG_DESC_E_PHOFF) */
2109		    ELFEDIT_I18NHDL(MSG_DESC_E_PHOFF),
2110		    /* MSG_INTL(MSG_HELP_E_PHOFF) */
2111		    ELFEDIT_I18NHDL(MSG_HELP_E_PHOFF),
2112		    opt_std, arg_e_phoff },
2113
2114		/* ehdr:e_shoff */
2115		{ cmd_e_shoff, NULL, name_e_shoff,
2116		    /* MSG_INTL(MSG_DESC_E_SHOFF) */
2117		    ELFEDIT_I18NHDL(MSG_DESC_E_SHOFF),
2118		    /* MSG_INTL(MSG_HELP_E_SHOFF) */
2119		    ELFEDIT_I18NHDL(MSG_HELP_E_SHOFF),
2120		    opt_std, arg_e_shoff },
2121
2122		/* ehdr:e_flags */
2123		{ cmd_e_flags, cpl_e_flags, name_e_flags,
2124		    /* MSG_INTL(MSG_DESC_E_FLAGS) */
2125		    ELFEDIT_I18NHDL(MSG_DESC_E_FLAGS),
2126		    /* MSG_INTL(MSG_HELP_E_FLAGS) */
2127		    ELFEDIT_I18NHDL(MSG_HELP_E_FLAGS),
2128		    opt_e_flags, arg_e_flags },
2129
2130		/* ehdr:e_ehsize */
2131		{ cmd_e_ehsize, NULL, name_e_ehsize,
2132		    /* MSG_INTL(MSG_DESC_E_EHSIZE) */
2133		    ELFEDIT_I18NHDL(MSG_DESC_E_EHSIZE),
2134		    /* MSG_INTL(MSG_HELP_E_EHSIZE) */
2135		    ELFEDIT_I18NHDL(MSG_HELP_E_EHSIZE),
2136		    opt_std, arg_e_ehsize },
2137
2138		/* ehdr:e_phentsize */
2139		{ cmd_e_phentsize, NULL, name_e_phentsize,
2140		    /* MSG_INTL(MSG_DESC_E_PHENTSIZE) */
2141		    ELFEDIT_I18NHDL(MSG_DESC_E_PHENTSIZE),
2142		    /* MSG_INTL(MSG_HELP_E_PHENTSIZE) */
2143		    ELFEDIT_I18NHDL(MSG_HELP_E_PHENTSIZE),
2144		    opt_std, arg_e_phentsize },
2145
2146		/* ehdr:e_phnum */
2147		{ cmd_e_phnum, NULL, name_e_phnum,
2148		    /* MSG_INTL(MSG_DESC_E_PHNUM) */
2149		    ELFEDIT_I18NHDL(MSG_DESC_E_PHNUM),
2150		    /* MSG_INTL(MSG_HELP_E_PHNUM) */
2151		    ELFEDIT_I18NHDL(MSG_HELP_E_PHNUM),
2152		    opt_std, arg_e_phnum },
2153
2154		/* ehdr:e_shentsize */
2155		{ cmd_e_shentsize, NULL, name_e_shentsize,
2156		    /* MSG_INTL(MSG_DESC_E_SHENTSIZE) */
2157		    ELFEDIT_I18NHDL(MSG_DESC_E_SHENTSIZE),
2158		    /* MSG_INTL(MSG_HELP_E_SHENTSIZE) */
2159		    ELFEDIT_I18NHDL(MSG_HELP_E_SHENTSIZE),
2160		    opt_std, arg_e_shentsize },
2161
2162		/* ehdr:e_shnum */
2163		{ cmd_e_shnum, NULL, name_e_shnum,
2164		    /* MSG_INTL(MSG_DESC_E_SHNUM) */
2165		    ELFEDIT_I18NHDL(MSG_DESC_E_SHNUM),
2166		    /* MSG_INTL(MSG_HELP_E_SHNUM) */
2167		    ELFEDIT_I18NHDL(MSG_HELP_E_SHNUM),
2168		    opt_std, arg_e_shnum },
2169
2170		/* ehdr:e_shstrndx */
2171		{ cmd_e_shstrndx, cpl_e_shstrndx, name_e_shstrndx,
2172		    /* MSG_INTL(MSG_DESC_E_SHSTRNDX) */
2173		    ELFEDIT_I18NHDL(MSG_DESC_E_SHSTRNDX),
2174		    /* MSG_INTL(MSG_HELP_E_SHSTRNDX) */
2175		    ELFEDIT_I18NHDL(MSG_HELP_E_SHSTRNDX),
2176		    opt_e_shstrndx, arg_e_shstrndx },
2177
2178		/* ehdr:ei_mag0 */
2179		{ cmd_ei_mag0, NULL, name_ei_mag0,
2180		    /* MSG_INTL(MSG_DESC_EI_MAG0) */
2181		    ELFEDIT_I18NHDL(MSG_DESC_EI_MAG0),
2182		    /* MSG_INTL(MSG_HELP_EI_MAG0) */
2183		    ELFEDIT_I18NHDL(MSG_HELP_EI_MAG0),
2184		    opt_std, arg_ei_mag0 },
2185
2186		/* ehdr:ei_mag1 */
2187		{ cmd_ei_mag1, NULL, name_ei_mag1,
2188		    /* MSG_INTL(MSG_DESC_EI_MAG1) */
2189		    ELFEDIT_I18NHDL(MSG_DESC_EI_MAG1),
2190		    /* MSG_INTL(MSG_HELP_EI_MAG1) */
2191		    ELFEDIT_I18NHDL(MSG_HELP_EI_MAG1),
2192		    opt_std, arg_ei_mag1 },
2193
2194		/* ehdr:ei_mag2 */
2195		{ cmd_ei_mag2, NULL, name_ei_mag2,
2196		    /* MSG_INTL(MSG_DESC_EI_MAG2) */
2197		    ELFEDIT_I18NHDL(MSG_DESC_EI_MAG2),
2198		    /* MSG_INTL(MSG_HELP_EI_MAG2) */
2199		    ELFEDIT_I18NHDL(MSG_HELP_EI_MAG2),
2200		    opt_std, arg_ei_mag2 },
2201
2202		/* ehdr:ei_mag3 */
2203		{ cmd_ei_mag3, NULL, name_ei_mag3,
2204		    /* MSG_INTL(MSG_DESC_EI_MAG3) */
2205		    ELFEDIT_I18NHDL(MSG_DESC_EI_MAG3),
2206		    /* MSG_INTL(MSG_HELP_EI_MAG3) */
2207		    ELFEDIT_I18NHDL(MSG_HELP_EI_MAG3),
2208		    opt_std, arg_ei_mag3 },
2209
2210		/* ehdr:ei_class */
2211		{ cmd_ei_class, cpl_ei_class, name_ei_class,
2212		    /* MSG_INTL(MSG_DESC_EI_CLASS) */
2213		    ELFEDIT_I18NHDL(MSG_DESC_EI_CLASS),
2214		    /* MSG_INTL(MSG_HELP_EI_CLASS) */
2215		    ELFEDIT_I18NHDL(MSG_HELP_EI_CLASS),
2216		    opt_std, arg_ei_class },
2217
2218		/* ehdr:ei_data */
2219		{ cmd_ei_data, cpl_ei_data, name_ei_data,
2220		    /* MSG_INTL(MSG_DESC_EI_DATA) */
2221		    ELFEDIT_I18NHDL(MSG_DESC_EI_DATA),
2222		    /* MSG_INTL(MSG_HELP_EI_DATA) */
2223		    ELFEDIT_I18NHDL(MSG_HELP_EI_DATA),
2224		    opt_std, arg_ei_data },
2225
2226		/* ehdr:ei_version */
2227		{ cmd_ei_version, cpl_e_version, name_ei_version,
2228		    /* MSG_INTL(MSG_DESC_EI_VERSION) */
2229		    ELFEDIT_I18NHDL(MSG_DESC_EI_VERSION),
2230		    /* MSG_INTL(MSG_HELP_EI_VERSION) */
2231		    ELFEDIT_I18NHDL(MSG_HELP_EI_VERSION),
2232		    opt_std, arg_e_version },
2233
2234		/* ehdr:ei_osabi */
2235		{ cmd_ei_osabi, cpl_ei_osabi, name_ei_osabi,
2236		    /* MSG_INTL(MSG_DESC_EI_OSABI) */
2237		    ELFEDIT_I18NHDL(MSG_DESC_EI_OSABI),
2238		    /* MSG_INTL(MSG_HELP_EI_OSABI) */
2239		    ELFEDIT_I18NHDL(MSG_HELP_EI_OSABI),
2240		    opt_std, arg_ei_osabi },
2241
2242		/* ehdr:ei_abiversion */
2243		{ cmd_ei_abiversion, cpl_ei_abiversion, name_ei_abiversion,
2244		    /* MSG_INTL(MSG_DESC_EI_ABIVERSION) */
2245		    ELFEDIT_I18NHDL(MSG_DESC_EI_ABIVERSION),
2246		    /* MSG_INTL(MSG_HELP_EI_ABIVERSION) */
2247		    ELFEDIT_I18NHDL(MSG_HELP_EI_ABIVERSION),
2248		    opt_std, arg_ei_abiversion },
2249
2250		{ NULL }
2251	};
2252
2253	static elfedit_module_t module = {
2254	    ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
2255	    /* MSG_INTL(MSG_MOD_DESC) */
2256	    ELFEDIT_I18NHDL(MSG_MOD_DESC),
2257	    cmds, mod_i18nhdl_to_str };
2258
2259	return (&module);
2260}
2261