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