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