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