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