xref: /onnv-gate/usr/src/cmd/sgs/elfedit/modules/common/phdr.c (revision 5088:26c540f30cd3)
1*5088Sab196087 /*
2*5088Sab196087  * CDDL HEADER START
3*5088Sab196087  *
4*5088Sab196087  * The contents of this file are subject to the terms of the
5*5088Sab196087  * Common Development and Distribution License (the "License").
6*5088Sab196087  * You may not use this file except in compliance with the License.
7*5088Sab196087  *
8*5088Sab196087  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5088Sab196087  * or http://www.opensolaris.org/os/licensing.
10*5088Sab196087  * See the License for the specific language governing permissions
11*5088Sab196087  * and limitations under the License.
12*5088Sab196087  *
13*5088Sab196087  * When distributing Covered Code, include this CDDL HEADER in each
14*5088Sab196087  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5088Sab196087  * If applicable, add the following below this CDDL HEADER, with the
16*5088Sab196087  * fields enclosed by brackets "[]" replaced with your own identifying
17*5088Sab196087  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5088Sab196087  *
19*5088Sab196087  * CDDL HEADER END
20*5088Sab196087  */
21*5088Sab196087 
22*5088Sab196087 /*
23*5088Sab196087  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24*5088Sab196087  * Use is subject to license terms.
25*5088Sab196087  */
26*5088Sab196087 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5088Sab196087 
28*5088Sab196087 #include	<machdep.h>
29*5088Sab196087 #include	<elfedit.h>
30*5088Sab196087 #include	<strings.h>
31*5088Sab196087 #include	<conv.h>
32*5088Sab196087 #include	<debug.h>
33*5088Sab196087 #include	<phdr_msg.h>
34*5088Sab196087 
35*5088Sab196087 
36*5088Sab196087 /*
37*5088Sab196087  * Program headers
38*5088Sab196087  */
39*5088Sab196087 
40*5088Sab196087 
41*5088Sab196087 
42*5088Sab196087 /*
43*5088Sab196087  * This module uses shared code for several of the commands.
44*5088Sab196087  * It is sometimes necessary to know which specific command
45*5088Sab196087  * is active.
46*5088Sab196087  */
47*5088Sab196087 typedef enum {
48*5088Sab196087 	/* Dump command, used as module default to display dynamic section */
49*5088Sab196087 	PHDR_CMD_T_DUMP =	0,	/* phdr:dump */
50*5088Sab196087 
51*5088Sab196087 	/* Commands that correspond directly to program header fields */
52*5088Sab196087 	PHDR_CMD_T_P_TYPE =	1,	/* phdr:p_type */
53*5088Sab196087 	PHDR_CMD_T_P_OFFSET =	2,	/* phdr:p_offset */
54*5088Sab196087 	PHDR_CMD_T_P_VADDR =	3,	/* phdr:p_vaddr */
55*5088Sab196087 	PHDR_CMD_T_P_PADDR =	4,	/* phdr:p_paddr */
56*5088Sab196087 	PHDR_CMD_T_P_FILESZ =	5,	/* phdr:p_filesz */
57*5088Sab196087 	PHDR_CMD_T_P_MEMSZ =	6,	/* phdr:p_memsz */
58*5088Sab196087 	PHDR_CMD_T_P_FLAGS =	7,	/* phdr:p_flags */
59*5088Sab196087 	PHDR_CMD_T_P_ALIGN =	8,	/* phdr:p_align */
60*5088Sab196087 
61*5088Sab196087 	/* Commands that do not correspond directly to a specific phdr tag */
62*5088Sab196087 	PHDR_CMD_T_INTERP =	9,	/* phdr:interp */
63*5088Sab196087 	PHDR_CMD_T_DELETE =	10,	/* phdr:delete */
64*5088Sab196087 	PHDR_CMD_T_MOVE =	11	/* phdr:move */
65*5088Sab196087 } PHDR_CMD_T;
66*5088Sab196087 
67*5088Sab196087 
68*5088Sab196087 
69*5088Sab196087 /*
70*5088Sab196087  * The following type is ued by locate_interp() to return
71*5088Sab196087  * information about the interpreter program header.
72*5088Sab196087  */
73*5088Sab196087 typedef struct {
74*5088Sab196087 	Word			phndx;	/* Index of PT_INTERP header */
75*5088Sab196087 	Phdr			*phdr;		/* PT_INTERP header */
76*5088Sab196087 	elfedit_section_t	*sec;		/* Section containing string */
77*5088Sab196087 	Word			stroff;		/* Offset into string section */
78*5088Sab196087 	const char		*str;		/* Interpreter string */
79*5088Sab196087 } INTERP_STATE;
80*5088Sab196087 
81*5088Sab196087 
82*5088Sab196087 #ifndef _ELF64
83*5088Sab196087 /*
84*5088Sab196087  * We supply this function for the msg module
85*5088Sab196087  */
86*5088Sab196087 const char *
87*5088Sab196087 _phdr_msg(Msg mid)
88*5088Sab196087 {
89*5088Sab196087 	return (gettext(MSG_ORIG(mid)));
90*5088Sab196087 }
91*5088Sab196087 #endif
92*5088Sab196087 
93*5088Sab196087 
94*5088Sab196087 /*
95*5088Sab196087  * This function is supplied to elfedit through our elfedit_module_t
96*5088Sab196087  * definition. It translates the opaque elfedit_i18nhdl_t handles
97*5088Sab196087  * in our module interface into the actual strings for elfedit to
98*5088Sab196087  * use.
99*5088Sab196087  *
100*5088Sab196087  * note:
101*5088Sab196087  *	This module uses Msg codes for its i18n handle type.
102*5088Sab196087  *	So the translation is simply to use MSG_INTL() to turn
103*5088Sab196087  *	it into a string and return it.
104*5088Sab196087  */
105*5088Sab196087 static const char *
106*5088Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
107*5088Sab196087 {
108*5088Sab196087 	Msg msg = (Msg)hdl;
109*5088Sab196087 
110*5088Sab196087 	return (MSG_INTL(msg));
111*5088Sab196087 }
112*5088Sab196087 
113*5088Sab196087 
114*5088Sab196087 
115*5088Sab196087 /*
116*5088Sab196087  * The phdr_opt_t enum specifies a bit value for every optional
117*5088Sab196087  * argument allowed by a command in this module.
118*5088Sab196087  */
119*5088Sab196087 typedef enum {
120*5088Sab196087 	PHDR_OPT_F_AND =	1,	/* -and: AND (&) values to dest */
121*5088Sab196087 	PHDR_OPT_F_CMP =	2,	/* -cmp: Complement (~) values */
122*5088Sab196087 	PHDR_OPT_F_PHNDX =	4,	/* -phndx: Program header by index, */
123*5088Sab196087 					/*	not by name */
124*5088Sab196087 	PHDR_OPT_F_OR =		8	/* -or: OR (|) values to dest */
125*5088Sab196087 } phdr_opt_t;
126*5088Sab196087 
127*5088Sab196087 
128*5088Sab196087 /*
129*5088Sab196087  * A variable of type ARGSTATE is used by each command to maintain
130*5088Sab196087  * information about the section headers and related things. It is
131*5088Sab196087  * initialized by process_args(), and used by the other routines.
132*5088Sab196087  */
133*5088Sab196087 typedef struct {
134*5088Sab196087 	elfedit_obj_state_t	*obj_state;
135*5088Sab196087 	phdr_opt_t		optmask;   	/* Mask of options used */
136*5088Sab196087 	int			argc;		/* # of plain arguments */
137*5088Sab196087 	const char		**argv;		/* Plain arguments */
138*5088Sab196087 	int			ndx_set;	/* True if ndx is valid */
139*5088Sab196087 	Word			ndx;		/* Index of header if cmd */
140*5088Sab196087 						/*	accepts it */
141*5088Sab196087 	int			print_req;	/* Call is a print request */
142*5088Sab196087 } ARGSTATE;
143*5088Sab196087 
144*5088Sab196087 
145*5088Sab196087 /*
146*5088Sab196087  * Standard argument processing for phdr module
147*5088Sab196087  *
148*5088Sab196087  * entry
149*5088Sab196087  *	obj_state, argc, argv - Standard command arguments
150*5088Sab196087  *	optmask - Mask of allowed optional arguments.
151*5088Sab196087  *	cmd - PHDR_CMD_T_* value giving identify of caller
152*5088Sab196087  *	argstate - Address of ARGSTATE block to be initialized
153*5088Sab196087  *
154*5088Sab196087  * exit:
155*5088Sab196087  *	On success, *argstate is initialized. On error,
156*5088Sab196087  *	an error is issued and this routine does not return.
157*5088Sab196087  */
158*5088Sab196087 static void
159*5088Sab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
160*5088Sab196087     PHDR_CMD_T cmd, ARGSTATE *argstate)
161*5088Sab196087 {
162*5088Sab196087 	elfedit_getopt_state_t	getopt_state;
163*5088Sab196087 	elfedit_getopt_ret_t	*getopt_ret;
164*5088Sab196087 
165*5088Sab196087 	bzero(argstate, sizeof (*argstate));
166*5088Sab196087 	argstate->obj_state = obj_state;
167*5088Sab196087 
168*5088Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
169*5088Sab196087 
170*5088Sab196087 	/* Add each new option to the options mask */
171*5088Sab196087 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL)
172*5088Sab196087 		argstate->optmask |= getopt_ret->gor_idmask;
173*5088Sab196087 
174*5088Sab196087 	/* Are the right number of plain arguments present? */
175*5088Sab196087 	switch (cmd) {
176*5088Sab196087 	case PHDR_CMD_T_DUMP:
177*5088Sab196087 		if (argc > 1)
178*5088Sab196087 			elfedit_command_usage();
179*5088Sab196087 		argstate->print_req = 1;
180*5088Sab196087 		break;
181*5088Sab196087 	case PHDR_CMD_T_P_FLAGS:
182*5088Sab196087 		/* phdr:sh_flags allows an arbitrary number of arguments */
183*5088Sab196087 		argstate->print_req = (argc < 2);
184*5088Sab196087 		break;
185*5088Sab196087 	case PHDR_CMD_T_INTERP:
186*5088Sab196087 		if (argc > 1)
187*5088Sab196087 			elfedit_command_usage();
188*5088Sab196087 		argstate->print_req = (argc == 0);
189*5088Sab196087 		break;
190*5088Sab196087 	case PHDR_CMD_T_DELETE:
191*5088Sab196087 		if ((argc < 1) || (argc > 2))
192*5088Sab196087 			elfedit_command_usage();
193*5088Sab196087 		argstate->print_req = 0;
194*5088Sab196087 		break;
195*5088Sab196087 	case PHDR_CMD_T_MOVE:
196*5088Sab196087 		if ((argc < 2) || (argc > 3))
197*5088Sab196087 			elfedit_command_usage();
198*5088Sab196087 		argstate->print_req = 0;
199*5088Sab196087 		break;
200*5088Sab196087 
201*5088Sab196087 	default:
202*5088Sab196087 		/* The remaining commands accept 2 plain arguments */
203*5088Sab196087 		if (argc > 2)
204*5088Sab196087 			elfedit_command_usage();
205*5088Sab196087 		argstate->print_req = (argc < 2);
206*5088Sab196087 		break;
207*5088Sab196087 	}
208*5088Sab196087 
209*5088Sab196087 	/* Return the updated values of argc/argv */
210*5088Sab196087 	argstate->argc = argc;
211*5088Sab196087 	argstate->argv = argv;
212*5088Sab196087 
213*5088Sab196087 	argstate->ndx_set = 0;
214*5088Sab196087 	if ((argc > 0) && (cmd != PHDR_CMD_T_INTERP)) {
215*5088Sab196087 		/*
216*5088Sab196087 		 * If the -phndx option is present, the first argument is
217*5088Sab196087 		 * the index of the header to use. Otherwise, it is a
218*5088Sab196087 		 * name corresponding to its type, similar to the way
219*5088Sab196087 		 * elfdump works with its -N option.
220*5088Sab196087 		 */
221*5088Sab196087 		if (argstate->optmask & PHDR_OPT_F_PHNDX) {
222*5088Sab196087 			argstate->ndx = (Word) elfedit_atoui_range(
223*5088Sab196087 			    argstate->argv[0], MSG_ORIG(MSG_STR_ELEMENT), 0,
224*5088Sab196087 			    argstate->obj_state->os_phnum - 1, NULL);
225*5088Sab196087 			argstate->ndx_set = 1;
226*5088Sab196087 		} else {
227*5088Sab196087 			Conv_inv_buf_t inv_buf;
228*5088Sab196087 			Word		i;
229*5088Sab196087 			Phdr		*phdr;
230*5088Sab196087 
231*5088Sab196087 			argstate->ndx = (Word) elfedit_atoconst(
232*5088Sab196087 			    argstate->argv[0], ELFEDIT_CONST_PT);
233*5088Sab196087 			phdr = obj_state->os_phdr;
234*5088Sab196087 			for (i = 0; i < obj_state->os_phnum; i++, phdr++) {
235*5088Sab196087 				if (phdr->p_type == argstate->ndx) {
236*5088Sab196087 					argstate->ndx = i;
237*5088Sab196087 					argstate->ndx_set = 1;
238*5088Sab196087 					elfedit_msg(ELFEDIT_MSG_DEBUG,
239*5088Sab196087 					    MSG_INTL(MSG_DEBUG_PHDR),
240*5088Sab196087 					    EC_WORD(i), conv_phdr_type(
241*5088Sab196087 					    obj_state->os_ehdr->e_machine,
242*5088Sab196087 					    phdr->p_type, 0, &inv_buf));
243*5088Sab196087 					break;
244*5088Sab196087 				}
245*5088Sab196087 			}
246*5088Sab196087 			if (i == argstate->obj_state->os_phnum)
247*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_ERR,
248*5088Sab196087 				    MSG_INTL(MSG_ERR_NOPHDR), conv_phdr_type(
249*5088Sab196087 				    obj_state->os_ehdr->e_machine,
250*5088Sab196087 				    argstate->ndx, 0, &inv_buf));
251*5088Sab196087 		}
252*5088Sab196087 	}
253*5088Sab196087 
254*5088Sab196087 	/* If there may be an arbitrary amount of output, use a pager */
255*5088Sab196087 	if (argc == 0)
256*5088Sab196087 		elfedit_pager_init();
257*5088Sab196087 
258*5088Sab196087 }
259*5088Sab196087 
260*5088Sab196087 
261*5088Sab196087 
262*5088Sab196087 /*
263*5088Sab196087  * Locate the interpreter string for the object and related information
264*5088Sab196087  *
265*5088Sab196087  * entry:
266*5088Sab196087  *	obj_state - Object state
267*5088Sab196087  *	interp - NULL, or variable to be filled in with information
268*5088Sab196087  *		about the interpteter string.
269*5088Sab196087  */
270*5088Sab196087 static const char *
271*5088Sab196087 locate_interp(elfedit_obj_state_t *obj_state, INTERP_STATE *interp)
272*5088Sab196087 {
273*5088Sab196087 	INTERP_STATE		local_interp;
274*5088Sab196087 	elfedit_section_t	*strsec;	/* String table */
275*5088Sab196087 	size_t		phnum;		/* # of program headers */
276*5088Sab196087 	int		phndx;		/* Index of PT_INTERP program header */
277*5088Sab196087 	Phdr		*phdr;		/* Program header array */
278*5088Sab196087 	Word		i;
279*5088Sab196087 
280*5088Sab196087 	if (interp == NULL)
281*5088Sab196087 		interp = &local_interp;
282*5088Sab196087 
283*5088Sab196087 	/* Locate the PT_INTERP program header */
284*5088Sab196087 	phnum = obj_state->os_phnum;
285*5088Sab196087 	phdr = obj_state->os_phdr;
286*5088Sab196087 
287*5088Sab196087 	for (phndx = 0; phndx < phnum; phndx++) {
288*5088Sab196087 		if (phdr[phndx].p_type  == PT_INTERP) {
289*5088Sab196087 			interp->phndx = phndx;
290*5088Sab196087 			interp->phdr = phdr + phndx;
291*5088Sab196087 			break;
292*5088Sab196087 		}
293*5088Sab196087 	}
294*5088Sab196087 	/* If no PT_INTERP program header found, we cannot proceed */
295*5088Sab196087 	if (phndx == phnum)
296*5088Sab196087 		elfedit_elferr(obj_state->os_file,
297*5088Sab196087 		    MSG_INTL(MSG_ERR_NOINTERPPHDR));
298*5088Sab196087 
299*5088Sab196087 	/*
300*5088Sab196087 	 * Locate the section containing the interpteter string as well
301*5088Sab196087 	 * as the string itself.
302*5088Sab196087 	 *
303*5088Sab196087 	 * The program header contains a direct offset to the string, so
304*5088Sab196087 	 * we find the section by walking through the them looking for
305*5088Sab196087 	 * the one with a base and size that would contain the string.
306*5088Sab196087 	 * Note that this target section cannot be in a NOBITS section.
307*5088Sab196087 	 */
308*5088Sab196087 	for (i = 1; i < obj_state->os_shnum; i++) {
309*5088Sab196087 		strsec = &obj_state->os_secarr[i];
310*5088Sab196087 
311*5088Sab196087 		if ((strsec->sec_shdr->sh_type != SHT_NOBITS) &&
312*5088Sab196087 		    (interp->phdr->p_offset >= strsec->sec_shdr->sh_offset) &&
313*5088Sab196087 		    ((interp->phdr->p_offset + interp->phdr->p_filesz) <=
314*5088Sab196087 		    (strsec->sec_shdr->sh_offset +
315*5088Sab196087 		    strsec->sec_shdr->sh_size))) {
316*5088Sab196087 			interp->sec = strsec;
317*5088Sab196087 
318*5088Sab196087 			interp->stroff = interp->phdr->p_offset -
319*5088Sab196087 			    strsec->sec_shdr->sh_offset;
320*5088Sab196087 			interp->str = ((char *)strsec->sec_data->d_buf) +
321*5088Sab196087 			    interp->stroff;
322*5088Sab196087 			return (interp->str);
323*5088Sab196087 		}
324*5088Sab196087 	}
325*5088Sab196087 
326*5088Sab196087 	/*
327*5088Sab196087 	 * We don't expect to get here: If there is a PT_INTERP header,
328*5088Sab196087 	 * we fully expect the string to exist.
329*5088Sab196087 	 */
330*5088Sab196087 	elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOINTERPSEC));
331*5088Sab196087 	/*NOTREACHED*/
332*5088Sab196087 
333*5088Sab196087 	return (NULL);		/* For lint */
334*5088Sab196087 }
335*5088Sab196087 
336*5088Sab196087 /*
337*5088Sab196087  * Print program header values, taking the calling command, and output style
338*5088Sab196087  * into account.
339*5088Sab196087  *
340*5088Sab196087  * entry:
341*5088Sab196087  *	autoprint - If True, output is only produced if the elfedit
342*5088Sab196087  *		autoprint flag is set. If False, output is always produced.
343*5088Sab196087  *	cmd - PHDR_CMD_T_* value giving identify of caller
344*5088Sab196087  *	argstate - State block for section header array
345*5088Sab196087  *	ndx - Index of first program header to display
346*5088Sab196087  *	cnt - Number of program headers to display
347*5088Sab196087  */
348*5088Sab196087 static void
349*5088Sab196087 print_phdr(PHDR_CMD_T cmd, int autoprint, ARGSTATE *argstate)
350*5088Sab196087 {
351*5088Sab196087 	elfedit_outstyle_t	outstyle;
352*5088Sab196087 	Word			ndx, cnt;
353*5088Sab196087 
354*5088Sab196087 	if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))
355*5088Sab196087 		return;
356*5088Sab196087 
357*5088Sab196087 	if (argstate->ndx_set) {
358*5088Sab196087 		ndx = argstate->ndx;
359*5088Sab196087 		cnt = 1;
360*5088Sab196087 	} else {
361*5088Sab196087 		ndx = 0;
362*5088Sab196087 		cnt = argstate->obj_state->os_phnum;
363*5088Sab196087 	}
364*5088Sab196087 
365*5088Sab196087 	/*
366*5088Sab196087 	 * Pick an output style. phdr:dump is required to use the default
367*5088Sab196087 	 * style. The other commands use the current output style.
368*5088Sab196087 	 */
369*5088Sab196087 	outstyle = (cmd == PHDR_CMD_T_DUMP) ?
370*5088Sab196087 	    ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle();
371*5088Sab196087 
372*5088Sab196087 	/*
373*5088Sab196087 	 * If doing default output, use elfdump style where we
374*5088Sab196087 	 * show all program header attributes. In this case, the
375*5088Sab196087 	 * command that called us doesn't matter.
376*5088Sab196087 	 *
377*5088Sab196087 	 * Let PHDR_CMD_T_INTERP fall through: It isn't per-phdr like
378*5088Sab196087 	 * the other commands.
379*5088Sab196087 	 */
380*5088Sab196087 	if ((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) &&
381*5088Sab196087 	    (cmd != PHDR_CMD_T_INTERP)) {
382*5088Sab196087 		Half	mach = argstate->obj_state->os_ehdr->e_machine;
383*5088Sab196087 		Phdr	*phdr = argstate->obj_state->os_phdr + ndx;
384*5088Sab196087 
385*5088Sab196087 		for (; cnt--; ndx++, phdr++) {
386*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_NL));
387*5088Sab196087 			elfedit_printf(MSG_INTL(MSG_ELF_PHDR), EC_WORD(ndx));
388*5088Sab196087 			Elf_phdr(0, mach, phdr);
389*5088Sab196087 		}
390*5088Sab196087 		return;
391*5088Sab196087 	}
392*5088Sab196087 
393*5088Sab196087 	switch (cmd) {
394*5088Sab196087 	case PHDR_CMD_T_P_TYPE:
395*5088Sab196087 		for (; cnt--; ndx++) {
396*5088Sab196087 			Word p_type = argstate->obj_state->os_phdr[ndx].p_type;
397*5088Sab196087 			Conv_inv_buf_t inv_buf;
398*5088Sab196087 
399*5088Sab196087 			if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
400*5088Sab196087 				Half mach =
401*5088Sab196087 				    argstate->obj_state->os_ehdr->e_machine;
402*5088Sab196087 
403*5088Sab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
404*5088Sab196087 				    conv_phdr_type(mach, p_type, 0, &inv_buf));
405*5088Sab196087 			} else {
406*5088Sab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_X_NL),
407*5088Sab196087 				    EC_WORD(p_type));
408*5088Sab196087 			}
409*5088Sab196087 		}
410*5088Sab196087 		return;
411*5088Sab196087 
412*5088Sab196087 	case PHDR_CMD_T_P_OFFSET:
413*5088Sab196087 		for (; cnt--; ndx++)
414*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_FMT_LLX_NL),
415*5088Sab196087 			    EC_OFF(argstate->obj_state->os_phdr[ndx].p_offset));
416*5088Sab196087 		return;
417*5088Sab196087 
418*5088Sab196087 	case PHDR_CMD_T_P_VADDR:
419*5088Sab196087 		for (; cnt--; ndx++)
420*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_FMT_LLX_NL),
421*5088Sab196087 			    EC_ADDR(argstate->obj_state->os_phdr[ndx].p_vaddr));
422*5088Sab196087 		return;
423*5088Sab196087 
424*5088Sab196087 	case PHDR_CMD_T_P_PADDR:
425*5088Sab196087 		for (; cnt--; ndx++)
426*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_FMT_LLX_NL),
427*5088Sab196087 			    EC_ADDR(argstate->obj_state->os_phdr[ndx].p_paddr));
428*5088Sab196087 		return;
429*5088Sab196087 
430*5088Sab196087 	case PHDR_CMD_T_P_FILESZ:
431*5088Sab196087 		for (; cnt--; ndx++)
432*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_FMT_LLX_NL),
433*5088Sab196087 			    EC_XWORD(argstate->obj_state->
434*5088Sab196087 			    os_phdr[ndx].p_filesz));
435*5088Sab196087 		return;
436*5088Sab196087 
437*5088Sab196087 	case PHDR_CMD_T_P_MEMSZ:
438*5088Sab196087 		for (; cnt--; ndx++)
439*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_FMT_LLX_NL),
440*5088Sab196087 			    EC_XWORD(argstate->obj_state->
441*5088Sab196087 			    os_phdr[ndx].p_memsz));
442*5088Sab196087 		return;
443*5088Sab196087 
444*5088Sab196087 	case PHDR_CMD_T_P_FLAGS:
445*5088Sab196087 		for (; cnt--; ndx++) {
446*5088Sab196087 			Word p_flags =
447*5088Sab196087 			    argstate->obj_state->os_phdr[ndx].p_flags;
448*5088Sab196087 
449*5088Sab196087 			if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
450*5088Sab196087 				Conv_phdr_flags_buf_t phdr_flags_buf;
451*5088Sab196087 
452*5088Sab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
453*5088Sab196087 				    conv_phdr_flags(p_flags, CONV_FMT_NOBKT,
454*5088Sab196087 				    &phdr_flags_buf));
455*5088Sab196087 			} else {
456*5088Sab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_X_NL),
457*5088Sab196087 				    EC_WORD(p_flags));
458*5088Sab196087 			}
459*5088Sab196087 		}
460*5088Sab196087 		return;
461*5088Sab196087 
462*5088Sab196087 	case PHDR_CMD_T_P_ALIGN:
463*5088Sab196087 		for (; cnt--; ndx++)
464*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_FMT_LLX_NL),
465*5088Sab196087 			    EC_XWORD(argstate->obj_state->
466*5088Sab196087 			    os_phdr[ndx].p_align));
467*5088Sab196087 		return;
468*5088Sab196087 
469*5088Sab196087 	case PHDR_CMD_T_INTERP:
470*5088Sab196087 		{
471*5088Sab196087 			INTERP_STATE interp;
472*5088Sab196087 
473*5088Sab196087 			(void) locate_interp(argstate->obj_state, &interp);
474*5088Sab196087 			switch (outstyle) {
475*5088Sab196087 
476*5088Sab196087 			case ELFEDIT_OUTSTYLE_DEFAULT:
477*5088Sab196087 				elfedit_printf(MSG_INTL(MSG_FMT_ELF_INTERP),
478*5088Sab196087 				    interp.sec->sec_name, interp.str);
479*5088Sab196087 				break;
480*5088Sab196087 			case ELFEDIT_OUTSTYLE_SIMPLE:
481*5088Sab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
482*5088Sab196087 				    interp.str);
483*5088Sab196087 				break;
484*5088Sab196087 			case ELFEDIT_OUTSTYLE_NUM:
485*5088Sab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_U_NL),
486*5088Sab196087 				    EC_WORD(interp.stroff));
487*5088Sab196087 				break;
488*5088Sab196087 			}
489*5088Sab196087 		}
490*5088Sab196087 		return;
491*5088Sab196087 	}
492*5088Sab196087 }
493*5088Sab196087 
494*5088Sab196087 
495*5088Sab196087 /*
496*5088Sab196087  * Called from cmd_body() in the case where a plain argument
497*5088Sab196087  * is given to phdr:interp to change the interpreter.
498*5088Sab196087  */
499*5088Sab196087 static elfedit_cmdret_t
500*5088Sab196087 cmd_body_set_interp(ARGSTATE *argstate)
501*5088Sab196087 {
502*5088Sab196087 	elfedit_obj_state_t	*obj_state = argstate->obj_state;
503*5088Sab196087 	elfedit_section_t	*strsec;	/* String table */
504*5088Sab196087 	INTERP_STATE	interp;
505*5088Sab196087 	Word		numdyn;		/* # of elements in dyn arr */
506*5088Sab196087 	size_t		phnum;		/* # of program headers */
507*5088Sab196087 	Phdr		*phdr;		/* Program header array */
508*5088Sab196087 	Word		i, j;
509*5088Sab196087 	Word		str_offset;	/* Offset in strsec to new interp str */
510*5088Sab196087 	int		str_found = 0;	 /* True when we have new interp str */
511*5088Sab196087 	Word		str_size;	/* Size of new interp string + NULL */
512*5088Sab196087 
513*5088Sab196087 	phnum = obj_state->os_phnum;
514*5088Sab196087 	phdr = obj_state->os_phdr;
515*5088Sab196087 
516*5088Sab196087 	/* Locate the PT_INTERP program header */
517*5088Sab196087 	(void) locate_interp(obj_state, &interp);
518*5088Sab196087 	strsec = interp.sec;
519*5088Sab196087 	str_offset = interp.stroff;
520*5088Sab196087 
521*5088Sab196087 	/*
522*5088Sab196087 	 * If the given string is the same as the existing interpreter
523*5088Sab196087 	 * string, say so and return.
524*5088Sab196087 	 */
525*5088Sab196087 	if (strcmp(interp.str, argstate->argv[0]) == 0) {
526*5088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_OLDINTERPOK),
527*5088Sab196087 		    EC_WORD(strsec->sec_shndx), strsec->sec_name,
528*5088Sab196087 		    EC_WORD(str_offset), interp.str);
529*5088Sab196087 		return (ELFEDIT_CMDRET_NONE);
530*5088Sab196087 	}
531*5088Sab196087 
532*5088Sab196087 	/*
533*5088Sab196087 	 * An ELF PT_INTERP usually references its own special section
534*5088Sab196087 	 * instead of some other string table. The ELF ABI says that this
535*5088Sab196087 	 * section must be named ".interp". Hence, this is a rare case
536*5088Sab196087 	 * in which the name of a section can be taken as an indication
537*5088Sab196087 	 * of its contents. .interp is typically sized to just fit
538*5088Sab196087 	 * the original string, including its NULL termination. You can
539*5088Sab196087 	 * treat it as a string table with one string.
540*5088Sab196087 	 *
541*5088Sab196087 	 * Thanks to 'elfedit', it may be that we encounter a file where
542*5088Sab196087 	 * PT_INTERP does not reference the .interp section. This will happen
543*5088Sab196087 	 * if elfedit is used to change the interpreter to a string that is
544*5088Sab196087 	 * too big to fit in .interp, in which case we will use the
545*5088Sab196087 	 * .dynstr string table (That code is below, in this function).
546*5088Sab196087 	 *
547*5088Sab196087 	 * Given the above facts, our next step is to locate the .interp
548*5088Sab196087 	 * section and see if our new string will fit in it. Since we can't
549*5088Sab196087 	 * depend on PT_INTERP, we search the section headers to find a
550*5088Sab196087 	 * section whith the following characteristics:
551*5088Sab196087 	 *	- The name is ".interp".
552*5088Sab196087 	 *	- Section is allocable (SHF_ALLOC) and SHT_PROGBITS.
553*5088Sab196087 	 *	- It is not part of a writable segment.
554*5088Sab196087 	 * If we find such a section, and the new string fits, we will
555*5088Sab196087 	 * write it there.
556*5088Sab196087 	 */
557*5088Sab196087 	str_size = strlen(argstate->argv[0]) + 1;
558*5088Sab196087 	for (i = 1; i < obj_state->os_shnum; i++) {
559*5088Sab196087 		strsec = &obj_state->os_secarr[i];
560*5088Sab196087 		if ((strcmp(strsec->sec_name, MSG_ORIG(MSG_SEC_INTERP)) == 0) &&
561*5088Sab196087 		    (strsec->sec_shdr->sh_flags & SHF_ALLOC) &&
562*5088Sab196087 		    (strsec->sec_shdr->sh_type & SHT_PROGBITS)) {
563*5088Sab196087 			for (j = 0; j < phnum; j++) {
564*5088Sab196087 				Phdr *tphdr = &phdr[j];
565*5088Sab196087 				if ((strsec->sec_shdr->sh_offset >=
566*5088Sab196087 				    tphdr->p_offset) &&
567*5088Sab196087 				    ((strsec->sec_shdr->sh_offset +
568*5088Sab196087 				    strsec->sec_shdr->sh_size) <=
569*5088Sab196087 				    (tphdr->p_offset + tphdr->p_filesz)) &&
570*5088Sab196087 				    (tphdr->p_flags & PF_W)) {
571*5088Sab196087 					break;
572*5088Sab196087 				}
573*5088Sab196087 			}
574*5088Sab196087 			if ((j == phnum) &&
575*5088Sab196087 			    (str_size <= strsec->sec_shdr->sh_size)) {
576*5088Sab196087 				/* .interp section found, and has room */
577*5088Sab196087 				str_found = 1;
578*5088Sab196087 				str_offset = 0;
579*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
580*5088Sab196087 				    MSG_INTL(MSG_DEBUG_NEWISTR), EC_WORD(j),
581*5088Sab196087 				    strsec->sec_name, EC_WORD(str_offset),
582*5088Sab196087 				    argstate->argv[0]);
583*5088Sab196087 				/* Put new value in section */
584*5088Sab196087 				(void) strncpy((char *)strsec->sec_data->d_buf,
585*5088Sab196087 				    argstate->argv[0],
586*5088Sab196087 				    strsec->sec_shdr->sh_size);
587*5088Sab196087 				/* Set libelf dirty bit so change is flushed */
588*5088Sab196087 				elfedit_modified_data(strsec);
589*5088Sab196087 				break;
590*5088Sab196087 			} else {
591*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
592*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LNGISTR), EC_WORD(j),
593*5088Sab196087 				    strsec->sec_name, EC_WORD(str_offset),
594*5088Sab196087 				    EC_WORD(str_size),
595*5088Sab196087 				    EC_WORD(strsec->sec_shdr->sh_size),
596*5088Sab196087 				    argstate->argv[0]);
597*5088Sab196087 			}
598*5088Sab196087 		}
599*5088Sab196087 	}
600*5088Sab196087 
601*5088Sab196087 	/*
602*5088Sab196087 	 * If the above did not find a string within the .interp section,
603*5088Sab196087 	 * then we have a second option. If this ELF object has a dynamic
604*5088Sab196087 	 * section, then we are willing to use strings from within the
605*5088Sab196087 	 * associated .dynstr string table. And if there is reserved space
606*5088Sab196087 	 * in .dynstr (as reported by the DT_SUNW_STRPAD dynamic entry),
607*5088Sab196087 	 * then we are even willing to add a new string to .dynstr.
608*5088Sab196087 	 */
609*5088Sab196087 	if (!str_found) {
610*5088Sab196087 		elfedit_section_t	*dynsec;
611*5088Sab196087 		Dyn			*dyn;
612*5088Sab196087 
613*5088Sab196087 		dynsec = elfedit_sec_getdyn(obj_state, &dyn, &numdyn);
614*5088Sab196087 		strsec = elfedit_sec_getstr(obj_state,
615*5088Sab196087 		    dynsec->sec_shdr->sh_link);
616*5088Sab196087 
617*5088Sab196087 		/* Does string exist in the table already, or can we add it? */
618*5088Sab196087 		str_offset = elfedit_strtab_insert(obj_state, strsec,
619*5088Sab196087 		    dynsec, argstate->argv[0]);
620*5088Sab196087 	}
621*5088Sab196087 
622*5088Sab196087 
623*5088Sab196087 	/*
624*5088Sab196087 	 * If we are here, we know we have a replacement string, because
625*5088Sab196087 	 * the errors from checking .dynamic/.dynstr will not allow
626*5088Sab196087 	 * things to get here otherwise.
627*5088Sab196087 	 *
628*5088Sab196087 	 * The PT_INTERP program header references the string directly,
629*5088Sab196087 	 * so we add the section offset to the string offset.
630*5088Sab196087 	 */
631*5088Sab196087 	interp.phdr->p_offset = strsec->sec_shdr->sh_offset + str_offset;
632*5088Sab196087 	interp.phdr->p_filesz = str_size;
633*5088Sab196087 	elfedit_modified_phdr(obj_state);
634*5088Sab196087 	elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_SETPHINTERP),
635*5088Sab196087 	    EC_WORD(interp.phndx), EC_XWORD(interp.phdr->p_offset),
636*5088Sab196087 	    EC_XWORD(interp.phdr->p_filesz));
637*5088Sab196087 
638*5088Sab196087 	return (ELFEDIT_CMDRET_MOD);
639*5088Sab196087 }
640*5088Sab196087 
641*5088Sab196087 
642*5088Sab196087 /*
643*5088Sab196087  * Common body for the phdr: module commands. These commands
644*5088Sab196087  * share a large amount of common behavior, so it is convenient
645*5088Sab196087  * to centralize things and use the cmd argument to handle the
646*5088Sab196087  * small differences.
647*5088Sab196087  *
648*5088Sab196087  * entry:
649*5088Sab196087  *	cmd - One of the PHDR_CMD_T_* constants listed above, specifying
650*5088Sab196087  *		which command to implement.
651*5088Sab196087  *	obj_state, argc, argv - Standard command arguments
652*5088Sab196087  */
653*5088Sab196087 static elfedit_cmdret_t
654*5088Sab196087 cmd_body(PHDR_CMD_T cmd, elfedit_obj_state_t *obj_state,
655*5088Sab196087     int argc, const char *argv[])
656*5088Sab196087 {
657*5088Sab196087 	ARGSTATE		argstate;
658*5088Sab196087 	Phdr			*phdr;
659*5088Sab196087 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
660*5088Sab196087 	int			do_autoprint = 1;
661*5088Sab196087 
662*5088Sab196087 	process_args(obj_state, argc, argv, cmd, &argstate);
663*5088Sab196087 
664*5088Sab196087 	/* If this is a printing request, print and return */
665*5088Sab196087 	if (argstate.print_req) {
666*5088Sab196087 		print_phdr(cmd, 0, &argstate);
667*5088Sab196087 		return (ELFEDIT_CMDRET_NONE);
668*5088Sab196087 	}
669*5088Sab196087 
670*5088Sab196087 
671*5088Sab196087 	if (argstate.ndx_set)
672*5088Sab196087 		phdr = &argstate.obj_state->os_phdr[argstate.ndx];
673*5088Sab196087 
674*5088Sab196087 	switch (cmd) {
675*5088Sab196087 		/*
676*5088Sab196087 		 * PHDR_CMD_T_DUMP can't get here: It never has more than
677*5088Sab196087 		 * one argument, and is handled above.
678*5088Sab196087 		 */
679*5088Sab196087 
680*5088Sab196087 	case PHDR_CMD_T_P_TYPE:
681*5088Sab196087 		{
682*5088Sab196087 			Half mach = obj_state->os_ehdr->e_machine;
683*5088Sab196087 			Word p_type = elfedit_atoconst(argstate.argv[1],
684*5088Sab196087 			    ELFEDIT_CONST_PT);
685*5088Sab196087 			Conv_inv_buf_t inv_buf1, inv_buf2;
686*5088Sab196087 
687*5088Sab196087 			if (phdr->p_type == p_type) {
688*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
689*5088Sab196087 				    MSG_INTL(MSG_DEBUG_S_OK),
690*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_TYPE),
691*5088Sab196087 				    conv_phdr_type(mach, phdr->p_type,
692*5088Sab196087 				    0, &inv_buf1));
693*5088Sab196087 			} else {
694*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
695*5088Sab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
696*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_TYPE),
697*5088Sab196087 				    conv_phdr_type(mach, phdr->p_type, 0,
698*5088Sab196087 				    &inv_buf1),
699*5088Sab196087 				    conv_phdr_type(mach, p_type, 0, &inv_buf2));
700*5088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
701*5088Sab196087 				phdr->p_type = p_type;
702*5088Sab196087 			}
703*5088Sab196087 		}
704*5088Sab196087 		break;
705*5088Sab196087 
706*5088Sab196087 	case PHDR_CMD_T_P_OFFSET:
707*5088Sab196087 		{
708*5088Sab196087 			Off p_offset;
709*5088Sab196087 
710*5088Sab196087 			p_offset = elfedit_atoui(argstate.argv[1], NULL);
711*5088Sab196087 			if (phdr->p_offset == p_offset) {
712*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
713*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_OK),
714*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_OFFSET),
715*5088Sab196087 				    EC_XWORD(phdr->p_offset));
716*5088Sab196087 			} else {
717*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
718*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_CHG),
719*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_OFFSET),
720*5088Sab196087 				    EC_XWORD(phdr->p_offset),
721*5088Sab196087 				    EC_XWORD(p_offset));
722*5088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
723*5088Sab196087 				phdr->p_offset = p_offset;
724*5088Sab196087 			}
725*5088Sab196087 		}
726*5088Sab196087 		break;
727*5088Sab196087 
728*5088Sab196087 	case PHDR_CMD_T_P_VADDR:
729*5088Sab196087 		{
730*5088Sab196087 			Addr p_vaddr = elfedit_atoui(argstate.argv[1], NULL);
731*5088Sab196087 
732*5088Sab196087 			if (phdr->p_vaddr == p_vaddr) {
733*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
734*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_OK),
735*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_VADDR),
736*5088Sab196087 				    EC_ADDR(phdr->p_vaddr));
737*5088Sab196087 			} else {
738*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
739*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_CHG),
740*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_VADDR),
741*5088Sab196087 				    EC_ADDR(phdr->p_vaddr), EC_ADDR(p_vaddr));
742*5088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
743*5088Sab196087 				phdr->p_vaddr = p_vaddr;
744*5088Sab196087 			}
745*5088Sab196087 		}
746*5088Sab196087 		break;
747*5088Sab196087 
748*5088Sab196087 	case PHDR_CMD_T_P_PADDR:
749*5088Sab196087 		{
750*5088Sab196087 			Addr p_paddr = elfedit_atoui(argstate.argv[1], NULL);
751*5088Sab196087 
752*5088Sab196087 			if (phdr->p_paddr == p_paddr) {
753*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
754*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_OK),
755*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_PADDR),
756*5088Sab196087 				    EC_ADDR(phdr->p_paddr));
757*5088Sab196087 			} else {
758*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
759*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_CHG),
760*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_PADDR),
761*5088Sab196087 				    EC_ADDR(phdr->p_paddr), EC_ADDR(p_paddr));
762*5088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
763*5088Sab196087 				phdr->p_paddr = p_paddr;
764*5088Sab196087 			}
765*5088Sab196087 		}
766*5088Sab196087 		break;
767*5088Sab196087 
768*5088Sab196087 	case PHDR_CMD_T_P_FILESZ:
769*5088Sab196087 		{
770*5088Sab196087 			Xword p_filesz = elfedit_atoui(argstate.argv[1], NULL);
771*5088Sab196087 
772*5088Sab196087 			if (phdr->p_filesz == p_filesz) {
773*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
774*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_OK),
775*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_FILESZ),
776*5088Sab196087 				    EC_XWORD(phdr->p_filesz));
777*5088Sab196087 			} else {
778*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
779*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_CHG),
780*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_FILESZ),
781*5088Sab196087 				    EC_XWORD(phdr->p_filesz),
782*5088Sab196087 				    EC_XWORD(p_filesz));
783*5088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
784*5088Sab196087 				phdr->p_filesz = p_filesz;
785*5088Sab196087 			}
786*5088Sab196087 		}
787*5088Sab196087 		break;
788*5088Sab196087 
789*5088Sab196087 	case PHDR_CMD_T_P_MEMSZ:
790*5088Sab196087 		{
791*5088Sab196087 			Xword p_memsz = elfedit_atoui(argstate.argv[1], NULL);
792*5088Sab196087 
793*5088Sab196087 			if (phdr->p_memsz == p_memsz) {
794*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
795*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_OK),
796*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_MEMSZ),
797*5088Sab196087 				    EC_XWORD(phdr->p_memsz));
798*5088Sab196087 			} else {
799*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
800*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_CHG),
801*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_MEMSZ),
802*5088Sab196087 				    EC_XWORD(phdr->p_memsz),
803*5088Sab196087 				    EC_XWORD(p_memsz));
804*5088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
805*5088Sab196087 				phdr->p_memsz = p_memsz;
806*5088Sab196087 			}
807*5088Sab196087 		}
808*5088Sab196087 		break;
809*5088Sab196087 
810*5088Sab196087 	case PHDR_CMD_T_P_FLAGS:
811*5088Sab196087 		{
812*5088Sab196087 			Conv_phdr_flags_buf_t buf1, buf2;
813*5088Sab196087 			Word	p_flags = 0;
814*5088Sab196087 			int	i;
815*5088Sab196087 
816*5088Sab196087 						/* Collect the flag arguments */
817*5088Sab196087 			for (i = 1; i < argstate.argc; i++)
818*5088Sab196087 				p_flags |=
819*5088Sab196087 				    (Word) elfedit_atoconst(argstate.argv[i],
820*5088Sab196087 				    ELFEDIT_CONST_PF);
821*5088Sab196087 
822*5088Sab196087 			/* Complement the value? */
823*5088Sab196087 			if (argstate.optmask & PHDR_OPT_F_CMP)
824*5088Sab196087 				p_flags = ~p_flags;
825*5088Sab196087 
826*5088Sab196087 			/* Perform any requested bit operations */
827*5088Sab196087 			if (argstate.optmask & PHDR_OPT_F_AND)
828*5088Sab196087 				p_flags &= phdr->p_flags;
829*5088Sab196087 			else if (argstate.optmask & PHDR_OPT_F_OR)
830*5088Sab196087 				p_flags |= phdr->p_flags;
831*5088Sab196087 
832*5088Sab196087 			/* Set the value */
833*5088Sab196087 			if (phdr->p_flags == p_flags) {
834*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
835*5088Sab196087 				    MSG_INTL(MSG_DEBUG_S_OK),
836*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_FLAGS),
837*5088Sab196087 				    conv_phdr_flags(phdr->p_flags, 0, &buf1));
838*5088Sab196087 			} else {
839*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
840*5088Sab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
841*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_FLAGS),
842*5088Sab196087 				    conv_phdr_flags(phdr->p_flags, 0, &buf1),
843*5088Sab196087 				    conv_phdr_flags(p_flags, 0, &buf2));
844*5088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
845*5088Sab196087 				phdr->p_flags = p_flags;
846*5088Sab196087 			}
847*5088Sab196087 		}
848*5088Sab196087 		break;
849*5088Sab196087 
850*5088Sab196087 	case PHDR_CMD_T_P_ALIGN:
851*5088Sab196087 		{
852*5088Sab196087 			Xword p_align = elfedit_atoui(argstate.argv[1], NULL);
853*5088Sab196087 
854*5088Sab196087 			if (phdr->p_align == p_align) {
855*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
856*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_OK),
857*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_ALIGN),
858*5088Sab196087 				    EC_XWORD(phdr->p_align));
859*5088Sab196087 			} else {
860*5088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
861*5088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_CHG),
862*5088Sab196087 				    argstate.ndx, MSG_ORIG(MSG_CMD_P_ALIGN),
863*5088Sab196087 				    EC_XWORD(phdr->p_align),
864*5088Sab196087 				    EC_XWORD(p_align));
865*5088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
866*5088Sab196087 				phdr->p_align = p_align;
867*5088Sab196087 			}
868*5088Sab196087 		}
869*5088Sab196087 		break;
870*5088Sab196087 
871*5088Sab196087 	case PHDR_CMD_T_INTERP:
872*5088Sab196087 		ret = cmd_body_set_interp(&argstate);
873*5088Sab196087 		break;
874*5088Sab196087 
875*5088Sab196087 	case PHDR_CMD_T_DELETE:
876*5088Sab196087 		{
877*5088Sab196087 			Word cnt = (argstate.argc == 1) ? 1 :
878*5088Sab196087 			    (Word) elfedit_atoui_range(argstate.argv[1],
879*5088Sab196087 			    MSG_ORIG(MSG_STR_COUNT), 1,
880*5088Sab196087 			    obj_state->os_phnum - argstate.ndx, NULL);
881*5088Sab196087 
882*5088Sab196087 			elfedit_array_elts_delete(MSG_ORIG(MSG_MOD_NAME),
883*5088Sab196087 			    obj_state->os_phdr, sizeof (Phdr),
884*5088Sab196087 			    obj_state->os_phnum, argstate.ndx, cnt);
885*5088Sab196087 			do_autoprint = 0;
886*5088Sab196087 			ret = ELFEDIT_CMDRET_MOD;
887*5088Sab196087 		}
888*5088Sab196087 		break;
889*5088Sab196087 
890*5088Sab196087 	case PHDR_CMD_T_MOVE:
891*5088Sab196087 		{
892*5088Sab196087 			Phdr	save;
893*5088Sab196087 			Word	cnt;
894*5088Sab196087 			Word	dstndx;
895*5088Sab196087 
896*5088Sab196087 			do_autoprint = 0;
897*5088Sab196087 			dstndx = (Word)
898*5088Sab196087 			    elfedit_atoui_range(argstate.argv[1],
899*5088Sab196087 			    MSG_ORIG(MSG_STR_DST_INDEX), 0,
900*5088Sab196087 			    obj_state->os_phnum - 1, NULL);
901*5088Sab196087 			if (argstate.argc == 2) {
902*5088Sab196087 				cnt = 1;
903*5088Sab196087 			} else {
904*5088Sab196087 				cnt = (Word) elfedit_atoui_range(
905*5088Sab196087 				    argstate.argv[2], MSG_ORIG(MSG_STR_COUNT),
906*5088Sab196087 				    1, obj_state->os_phnum, NULL);
907*5088Sab196087 			}
908*5088Sab196087 			elfedit_array_elts_move(MSG_ORIG(MSG_MOD_NAME),
909*5088Sab196087 			    obj_state->os_phdr, sizeof (save),
910*5088Sab196087 			    obj_state->os_phnum, argstate.ndx, dstndx,
911*5088Sab196087 			    cnt, &save);
912*5088Sab196087 			ret = ELFEDIT_CMDRET_MOD;
913*5088Sab196087 		}
914*5088Sab196087 		break;
915*5088Sab196087 	}
916*5088Sab196087 
917*5088Sab196087 	/*
918*5088Sab196087 	 * If we modified the section header array, tell libelf.
919*5088Sab196087 	 */
920*5088Sab196087 	if (ret == ELFEDIT_CMDRET_MOD)
921*5088Sab196087 		elfedit_modified_phdr(obj_state);
922*5088Sab196087 
923*5088Sab196087 	/* Do autoprint */
924*5088Sab196087 	if (do_autoprint)
925*5088Sab196087 		print_phdr(cmd, 1, &argstate);
926*5088Sab196087 
927*5088Sab196087 	return (ret);
928*5088Sab196087 }
929*5088Sab196087 
930*5088Sab196087 
931*5088Sab196087 
932*5088Sab196087 /*
933*5088Sab196087  * Command completion functions for the various commands
934*5088Sab196087  */
935*5088Sab196087 
936*5088Sab196087 /*
937*5088Sab196087  * A number of the commands accept a PT_ constant as their first
938*5088Sab196087  * argument as long as the -phndx option is not used.
939*5088Sab196087  */
940*5088Sab196087 /*ARGSUSED*/
941*5088Sab196087 static void
942*5088Sab196087 cpl_1starg_pt(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
943*5088Sab196087     const char *argv[], int num_opt)
944*5088Sab196087 {
945*5088Sab196087 	int i;
946*5088Sab196087 
947*5088Sab196087 	for (i = 0; i < num_opt; i++)
948*5088Sab196087 		if (strcmp(MSG_ORIG(MSG_STR_MINUS_PHNDX), argv[i]) == 0)
949*5088Sab196087 			return;
950*5088Sab196087 
951*5088Sab196087 	if (argc == (num_opt + 1))
952*5088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_PT);
953*5088Sab196087 }
954*5088Sab196087 
955*5088Sab196087 /*ARGSUSED*/
956*5088Sab196087 static void
957*5088Sab196087 cpl_p_type(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
958*5088Sab196087     const char *argv[], int num_opt)
959*5088Sab196087 {
960*5088Sab196087 	/* The first argument follows the standard rules */
961*5088Sab196087 	cpl_1starg_pt(obj_state, cpldata, argc, argv, num_opt);
962*5088Sab196087 
963*5088Sab196087 	/* The second argument can be a PT_ value */
964*5088Sab196087 	if (argc == (num_opt + 2))
965*5088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_PT);
966*5088Sab196087 }
967*5088Sab196087 
968*5088Sab196087 
969*5088Sab196087 /*ARGSUSED*/
970*5088Sab196087 static void
971*5088Sab196087 cpl_p_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
972*5088Sab196087     const char *argv[], int num_opt)
973*5088Sab196087 {
974*5088Sab196087 	/* The first argument follows the standard rules */
975*5088Sab196087 	cpl_1starg_pt(obj_state, cpldata, argc, argv, num_opt);
976*5088Sab196087 
977*5088Sab196087 	/* The second and following arguments can be an PF_ value */
978*5088Sab196087 	if (argc >= (num_opt + 2))
979*5088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_PF);
980*5088Sab196087 }
981*5088Sab196087 
982*5088Sab196087 
983*5088Sab196087 
984*5088Sab196087 /*
985*5088Sab196087  * Implementation functions for the commands
986*5088Sab196087  */
987*5088Sab196087 static elfedit_cmdret_t
988*5088Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
989*5088Sab196087 {
990*5088Sab196087 	return (cmd_body(PHDR_CMD_T_DUMP, obj_state, argc, argv));
991*5088Sab196087 }
992*5088Sab196087 
993*5088Sab196087 static elfedit_cmdret_t
994*5088Sab196087 cmd_p_type(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
995*5088Sab196087 {
996*5088Sab196087 	return (cmd_body(PHDR_CMD_T_P_TYPE, obj_state, argc, argv));
997*5088Sab196087 }
998*5088Sab196087 
999*5088Sab196087 static elfedit_cmdret_t
1000*5088Sab196087 cmd_p_offset(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1001*5088Sab196087 {
1002*5088Sab196087 	return (cmd_body(PHDR_CMD_T_P_OFFSET, obj_state, argc, argv));
1003*5088Sab196087 }
1004*5088Sab196087 
1005*5088Sab196087 static elfedit_cmdret_t
1006*5088Sab196087 cmd_p_vaddr(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1007*5088Sab196087 {
1008*5088Sab196087 	return (cmd_body(PHDR_CMD_T_P_VADDR, obj_state, argc, argv));
1009*5088Sab196087 }
1010*5088Sab196087 
1011*5088Sab196087 static elfedit_cmdret_t
1012*5088Sab196087 cmd_p_paddr(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1013*5088Sab196087 {
1014*5088Sab196087 	return (cmd_body(PHDR_CMD_T_P_PADDR, obj_state, argc, argv));
1015*5088Sab196087 }
1016*5088Sab196087 
1017*5088Sab196087 static elfedit_cmdret_t
1018*5088Sab196087 cmd_p_filesz(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1019*5088Sab196087 {
1020*5088Sab196087 	return (cmd_body(PHDR_CMD_T_P_FILESZ, obj_state, argc, argv));
1021*5088Sab196087 }
1022*5088Sab196087 
1023*5088Sab196087 static elfedit_cmdret_t
1024*5088Sab196087 cmd_p_memsz(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1025*5088Sab196087 {
1026*5088Sab196087 	return (cmd_body(PHDR_CMD_T_P_MEMSZ, obj_state, argc, argv));
1027*5088Sab196087 }
1028*5088Sab196087 
1029*5088Sab196087 static elfedit_cmdret_t
1030*5088Sab196087 cmd_p_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1031*5088Sab196087 {
1032*5088Sab196087 	return (cmd_body(PHDR_CMD_T_P_FLAGS, obj_state, argc, argv));
1033*5088Sab196087 }
1034*5088Sab196087 
1035*5088Sab196087 static elfedit_cmdret_t
1036*5088Sab196087 cmd_p_align(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1037*5088Sab196087 {
1038*5088Sab196087 	return (cmd_body(PHDR_CMD_T_P_ALIGN, obj_state, argc, argv));
1039*5088Sab196087 }
1040*5088Sab196087 
1041*5088Sab196087 static elfedit_cmdret_t
1042*5088Sab196087 cmd_interp(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1043*5088Sab196087 {
1044*5088Sab196087 	return (cmd_body(PHDR_CMD_T_INTERP, obj_state, argc, argv));
1045*5088Sab196087 }
1046*5088Sab196087 
1047*5088Sab196087 static elfedit_cmdret_t
1048*5088Sab196087 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1049*5088Sab196087 {
1050*5088Sab196087 	return (cmd_body(PHDR_CMD_T_DELETE, obj_state, argc, argv));
1051*5088Sab196087 }
1052*5088Sab196087 
1053*5088Sab196087 static elfedit_cmdret_t
1054*5088Sab196087 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1055*5088Sab196087 {
1056*5088Sab196087 	return (cmd_body(PHDR_CMD_T_MOVE, obj_state, argc, argv));
1057*5088Sab196087 }
1058*5088Sab196087 
1059*5088Sab196087 
1060*5088Sab196087 /*ARGSUSED*/
1061*5088Sab196087 elfedit_module_t *
1062*5088Sab196087 elfedit_init(elfedit_module_version_t version)
1063*5088Sab196087 {
1064*5088Sab196087 	/* Multiple commands accept a standard set of options */
1065*5088Sab196087 	static elfedit_cmd_optarg_t opt_std[] = {
1066*5088Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
1067*5088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1068*5088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_PHNDX),
1069*5088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_PHNDX) */
1070*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_PHNDX), 0,
1071*5088Sab196087 		    PHDR_OPT_F_PHNDX, 0 },
1072*5088Sab196087 		{ NULL }
1073*5088Sab196087 	};
1074*5088Sab196087 
1075*5088Sab196087 	/* For commands that only accept -phndx */
1076*5088Sab196087 	static elfedit_cmd_optarg_t opt_minus_phndx[] = {
1077*5088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_PHNDX),
1078*5088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_PHNDX) */
1079*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_PHNDX), 0,
1080*5088Sab196087 		    PHDR_OPT_F_PHNDX, 0 },
1081*5088Sab196087 		{ NULL }
1082*5088Sab196087 	};
1083*5088Sab196087 
1084*5088Sab196087 
1085*5088Sab196087 	/* phdr:dump */
1086*5088Sab196087 	static const char *name_dump[] = {
1087*5088Sab196087 	    MSG_ORIG(MSG_CMD_DUMP),
1088*5088Sab196087 	    MSG_ORIG(MSG_STR_EMPTY),	/* "" makes this the default command */
1089*5088Sab196087 	    NULL
1090*5088Sab196087 	};
1091*5088Sab196087 	static elfedit_cmd_optarg_t arg_dump[] = {
1092*5088Sab196087 		{ MSG_ORIG(MSG_STR_ELEMENT),
1093*5088Sab196087 		    /* MSG_INTL(MSG_A1_ELEMENT) */
1094*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_ELEMENT),
1095*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1096*5088Sab196087 		{ NULL }
1097*5088Sab196087 	};
1098*5088Sab196087 
1099*5088Sab196087 	/* phdr:p_type */
1100*5088Sab196087 	static const char *name_p_type[] = { MSG_ORIG(MSG_CMD_P_TYPE), NULL };
1101*5088Sab196087 	static elfedit_cmd_optarg_t arg_p_type[] = {
1102*5088Sab196087 		{ MSG_ORIG(MSG_STR_ELEMENT),
1103*5088Sab196087 		    /* MSG_INTL(MSG_A1_ELEMENT) */
1104*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_ELEMENT),
1105*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1106*5088Sab196087 		{ MSG_ORIG(MSG_STR_TYPE),
1107*5088Sab196087 		    /* MSG_INTL(MSG_A2_P_TYPE_TYPE) */
1108*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_P_TYPE_TYPE),
1109*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1110*5088Sab196087 		{ NULL }
1111*5088Sab196087 	};
1112*5088Sab196087 
1113*5088Sab196087 	/* phdr:p_offset */
1114*5088Sab196087 	static const char *name_p_offset[] = { MSG_ORIG(MSG_CMD_P_OFFSET),
1115*5088Sab196087 	    NULL };
1116*5088Sab196087 	static elfedit_cmd_optarg_t arg_p_offset[] = {
1117*5088Sab196087 		{ MSG_ORIG(MSG_STR_ELEMENT),
1118*5088Sab196087 		    /* MSG_INTL(MSG_A1_ELEMENT) */
1119*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_ELEMENT),
1120*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1121*5088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
1122*5088Sab196087 		    /* MSG_INTL(MSG_A2_P_OFFSET_VALUE) */
1123*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_P_OFFSET_VALUE),
1124*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1125*5088Sab196087 		{ NULL }
1126*5088Sab196087 	};
1127*5088Sab196087 
1128*5088Sab196087 	/* phdr:p_vaddr */
1129*5088Sab196087 	static const char *name_p_vaddr[] = { MSG_ORIG(MSG_CMD_P_VADDR),
1130*5088Sab196087 	    NULL };
1131*5088Sab196087 	static elfedit_cmd_optarg_t arg_p_vaddr[] = {
1132*5088Sab196087 		{ MSG_ORIG(MSG_STR_ELEMENT),
1133*5088Sab196087 		    /* MSG_INTL(MSG_A1_ELEMENT) */
1134*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_ELEMENT),
1135*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1136*5088Sab196087 		{ MSG_ORIG(MSG_STR_ADDR),
1137*5088Sab196087 		    /* MSG_INTL(MSG_A2_P_VADDR_ADDR) */
1138*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_P_VADDR_ADDR),
1139*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1140*5088Sab196087 		{ NULL }
1141*5088Sab196087 	};
1142*5088Sab196087 
1143*5088Sab196087 	/* phdr:p_paddr */
1144*5088Sab196087 	static const char *name_p_paddr[] = { MSG_ORIG(MSG_CMD_P_PADDR),
1145*5088Sab196087 	    NULL };
1146*5088Sab196087 	static elfedit_cmd_optarg_t arg_p_paddr[] = {
1147*5088Sab196087 		{ MSG_ORIG(MSG_STR_ELEMENT),
1148*5088Sab196087 		    /* MSG_INTL(MSG_A1_ELEMENT) */
1149*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_ELEMENT),
1150*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1151*5088Sab196087 		{ MSG_ORIG(MSG_STR_ADDR),
1152*5088Sab196087 		    /* MSG_INTL(MSG_A2_P_PADDR_ADDR) */
1153*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_P_PADDR_ADDR),
1154*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1155*5088Sab196087 		{ NULL }
1156*5088Sab196087 	};
1157*5088Sab196087 
1158*5088Sab196087 	/* phdr:p_filesz */
1159*5088Sab196087 	static const char *name_p_filesz[] = { MSG_ORIG(MSG_CMD_P_FILESZ),
1160*5088Sab196087 	    NULL };
1161*5088Sab196087 	static elfedit_cmd_optarg_t arg_p_filesz[] = {
1162*5088Sab196087 	    /* MSG_INTL(MSG_A1_ELEMENT) */
1163*5088Sab196087 		{ MSG_ORIG(MSG_STR_ELEMENT), ELFEDIT_I18NHDL(MSG_A1_ELEMENT),
1164*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1165*5088Sab196087 		{ MSG_ORIG(MSG_STR_SIZE),
1166*5088Sab196087 		    /* MSG_INTL(MSG_A2_P_FILESZ_SIZE) */
1167*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_P_FILESZ_SIZE),
1168*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1169*5088Sab196087 		{ NULL }
1170*5088Sab196087 	};
1171*5088Sab196087 
1172*5088Sab196087 	/* phdr:p_memsz */
1173*5088Sab196087 	static const char *name_p_memsz[] = { MSG_ORIG(MSG_CMD_P_MEMSZ),
1174*5088Sab196087 	    NULL };
1175*5088Sab196087 	static elfedit_cmd_optarg_t arg_p_memsz[] = {
1176*5088Sab196087 		{ MSG_ORIG(MSG_STR_ELEMENT),
1177*5088Sab196087 		    /* MSG_INTL(MSG_A1_ELEMENT) */
1178*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_ELEMENT),
1179*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1180*5088Sab196087 		{ MSG_ORIG(MSG_STR_SIZE),
1181*5088Sab196087 		    /* MSG_INTL(MSG_A2_P_MEMSZ_SIZE) */
1182*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_P_MEMSZ_SIZE),
1183*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1184*5088Sab196087 		{ NULL }
1185*5088Sab196087 	};
1186*5088Sab196087 
1187*5088Sab196087 	/* shdr:p_flags */
1188*5088Sab196087 	static const char *name_p_flags[] = {
1189*5088Sab196087 	    MSG_ORIG(MSG_CMD_P_FLAGS), NULL };
1190*5088Sab196087 	static elfedit_cmd_optarg_t opt_p_flags[] = {
1191*5088Sab196087 		{ ELFEDIT_STDOA_OPT_AND, NULL,
1192*5088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, PHDR_OPT_F_AND, PHDR_OPT_F_OR },
1193*5088Sab196087 		{ ELFEDIT_STDOA_OPT_CMP, NULL,
1194*5088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, PHDR_OPT_F_CMP, 0 },
1195*5088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_PHNDX),
1196*5088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_PHNDX) */
1197*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_PHNDX), 0,
1198*5088Sab196087 		    PHDR_OPT_F_PHNDX, 0 },
1199*5088Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
1200*5088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1201*5088Sab196087 		{ ELFEDIT_STDOA_OPT_OR, NULL,
1202*5088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, PHDR_OPT_F_OR, PHDR_OPT_F_AND },
1203*5088Sab196087 		{ NULL }
1204*5088Sab196087 	};
1205*5088Sab196087 	static elfedit_cmd_optarg_t arg_p_flags[] = {
1206*5088Sab196087 		{ MSG_ORIG(MSG_STR_ELEMENT),
1207*5088Sab196087 		    /* MSG_INTL(MSG_A1_ELEMENT) */
1208*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_ELEMENT),
1209*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1210*5088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
1211*5088Sab196087 		    /* MSG_INTL(MSG_A2_P_FLAGS_VALUE) */
1212*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_P_FLAGS_VALUE),
1213*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
1214*5088Sab196087 		{ NULL }
1215*5088Sab196087 	};
1216*5088Sab196087 
1217*5088Sab196087 	/* phdr:p_align */
1218*5088Sab196087 	static const char *name_p_align[] = { MSG_ORIG(MSG_CMD_P_ALIGN),
1219*5088Sab196087 	    NULL };
1220*5088Sab196087 	static elfedit_cmd_optarg_t arg_p_align[] = {
1221*5088Sab196087 		{ MSG_ORIG(MSG_STR_ELEMENT),
1222*5088Sab196087 		    /* MSG_INTL(MSG_A1_ELEMENT) */
1223*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_ELEMENT),
1224*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1225*5088Sab196087 		{ MSG_ORIG(MSG_STR_ALIGN),
1226*5088Sab196087 		    /* MSG_INTL(MSG_A2_P_ALIGN_ALIGN) */
1227*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_P_ALIGN_ALIGN),
1228*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1229*5088Sab196087 		{ NULL }
1230*5088Sab196087 	};
1231*5088Sab196087 
1232*5088Sab196087 	/* phdr:interp */
1233*5088Sab196087 	static const char *name_interp[] = { MSG_ORIG(MSG_CMD_INTERP), NULL };
1234*5088Sab196087 	static elfedit_cmd_optarg_t opt_interp[] = {
1235*5088Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
1236*5088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1237*5088Sab196087 		{ NULL }
1238*5088Sab196087 	};
1239*5088Sab196087 	static elfedit_cmd_optarg_t arg_interp[] = {
1240*5088Sab196087 		{ MSG_ORIG(MSG_STR_NEWPATH),
1241*5088Sab196087 		    /* MSG_INTL(MSG_A1_INTERP_NEWPATH) */
1242*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_INTERP_NEWPATH),
1243*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1244*5088Sab196087 		{ NULL }
1245*5088Sab196087 	};
1246*5088Sab196087 
1247*5088Sab196087 	/* phdr:delete */
1248*5088Sab196087 	static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL };
1249*5088Sab196087 	static elfedit_cmd_optarg_t arg_delete[] = {
1250*5088Sab196087 		{ MSG_ORIG(MSG_STR_ELEMENT),
1251*5088Sab196087 		    /* MSG_INTL(MSG_A1_ELEMENT) */
1252*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_ELEMENT),
1253*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1254*5088Sab196087 		{ MSG_ORIG(MSG_STR_COUNT),
1255*5088Sab196087 		    /* MSG_INTL(MSG_A2_DELETE_COUNT) */
1256*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT),
1257*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1258*5088Sab196087 		{ NULL }
1259*5088Sab196087 	};
1260*5088Sab196087 
1261*5088Sab196087 	/* phdr:move */
1262*5088Sab196087 	static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL };
1263*5088Sab196087 	static elfedit_cmd_optarg_t arg_move[] = {
1264*5088Sab196087 		{ MSG_ORIG(MSG_STR_ELEMENT),
1265*5088Sab196087 		    /* MSG_INTL(MSG_A1_ELEMENT) */
1266*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_ELEMENT),
1267*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1268*5088Sab196087 		{ MSG_ORIG(MSG_STR_DST_INDEX),
1269*5088Sab196087 		    /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */
1270*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX),
1271*5088Sab196087 		    0 },
1272*5088Sab196087 		{ MSG_ORIG(MSG_STR_COUNT),
1273*5088Sab196087 		    /* MSG_INTL(MSG_A3_MOVE_COUNT) */
1274*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT),
1275*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
1276*5088Sab196087 		{ NULL }
1277*5088Sab196087 	};
1278*5088Sab196087 
1279*5088Sab196087 	static elfedit_cmd_t cmds[] = {
1280*5088Sab196087 		/* phdr:dump */
1281*5088Sab196087 		{ cmd_dump, cpl_1starg_pt, name_dump,
1282*5088Sab196087 		    /* MSG_INTL(MSG_DESC_DUMP) */
1283*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_DUMP),
1284*5088Sab196087 		    /* MSG_INTL(MSG_HELP_DUMP) */
1285*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_DUMP),
1286*5088Sab196087 		    opt_minus_phndx, arg_dump },
1287*5088Sab196087 
1288*5088Sab196087 		/* phdr:p_type */
1289*5088Sab196087 		{ cmd_p_type, cpl_p_type, name_p_type,
1290*5088Sab196087 		    /* MSG_INTL(MSG_DESC_P_TYPE) */
1291*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_P_TYPE),
1292*5088Sab196087 		    /* MSG_INTL(MSG_HELP_P_TYPE) */
1293*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_P_TYPE),
1294*5088Sab196087 		    opt_std, arg_p_type },
1295*5088Sab196087 
1296*5088Sab196087 		/* phdr:p_offset */
1297*5088Sab196087 		{ cmd_p_offset, cpl_1starg_pt, name_p_offset,
1298*5088Sab196087 		    /* MSG_INTL(MSG_DESC_P_OFFSET) */
1299*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_P_OFFSET),
1300*5088Sab196087 		    /* MSG_INTL(MSG_HELP_P_OFFSET) */
1301*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_P_OFFSET),
1302*5088Sab196087 		    opt_std, arg_p_offset },
1303*5088Sab196087 
1304*5088Sab196087 		/* phdr:p_vaddr */
1305*5088Sab196087 		{ cmd_p_vaddr, cpl_1starg_pt, name_p_vaddr,
1306*5088Sab196087 		    /* MSG_INTL(MSG_DESC_P_VADDR) */
1307*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_P_VADDR),
1308*5088Sab196087 		    /* MSG_INTL(MSG_HELP_P_VADDR) */
1309*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_P_VADDR),
1310*5088Sab196087 		    opt_std, arg_p_vaddr },
1311*5088Sab196087 
1312*5088Sab196087 		/* phdr:p_paddr */
1313*5088Sab196087 		{ cmd_p_paddr, cpl_1starg_pt, name_p_paddr,
1314*5088Sab196087 		    /* MSG_INTL(MSG_DESC_P_PADDR) */
1315*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_P_PADDR),
1316*5088Sab196087 		    /* MSG_INTL(MSG_HELP_P_PADDR) */
1317*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_P_PADDR),
1318*5088Sab196087 		    opt_std, arg_p_paddr },
1319*5088Sab196087 
1320*5088Sab196087 		/* phdr:p_filesz */
1321*5088Sab196087 		{ cmd_p_filesz, cpl_1starg_pt, name_p_filesz,
1322*5088Sab196087 		    /* MSG_INTL(MSG_DESC_P_FILESZ) */
1323*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_P_FILESZ),
1324*5088Sab196087 		    /* MSG_INTL(MSG_HELP_P_FILESZ) */
1325*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_P_FILESZ),
1326*5088Sab196087 		    opt_std, arg_p_filesz },
1327*5088Sab196087 
1328*5088Sab196087 		/* phdr:p_memsz */
1329*5088Sab196087 		{ cmd_p_memsz, cpl_1starg_pt, name_p_memsz,
1330*5088Sab196087 		    /* MSG_INTL(MSG_DESC_P_MEMSZ) */
1331*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_P_MEMSZ),
1332*5088Sab196087 		    /* MSG_INTL(MSG_HELP_P_MEMSZ) */
1333*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_P_MEMSZ),
1334*5088Sab196087 		    opt_std, arg_p_memsz },
1335*5088Sab196087 
1336*5088Sab196087 		/* phdr:p_flags */
1337*5088Sab196087 		{ cmd_p_flags, cpl_p_flags, name_p_flags,
1338*5088Sab196087 		    /* MSG_INTL(MSG_DESC_P_FLAGS) */
1339*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_P_FLAGS),
1340*5088Sab196087 		    /* MSG_INTL(MSG_HELP_P_FLAGS) */
1341*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_P_FLAGS),
1342*5088Sab196087 		    opt_p_flags, arg_p_flags },
1343*5088Sab196087 
1344*5088Sab196087 		/* phdr:p_align */
1345*5088Sab196087 		{ cmd_p_align, cpl_1starg_pt, name_p_align,
1346*5088Sab196087 		    /* MSG_INTL(MSG_DESC_P_ALIGN) */
1347*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_P_ALIGN),
1348*5088Sab196087 		    /* MSG_INTL(MSG_HELP_P_ALIGN) */
1349*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_P_ALIGN),
1350*5088Sab196087 		    opt_std, arg_p_align },
1351*5088Sab196087 
1352*5088Sab196087 		/* phdr:interp */
1353*5088Sab196087 		{ cmd_interp, NULL, name_interp,
1354*5088Sab196087 		    /* MSG_INTL(MSG_DESC_INTERP) */
1355*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_INTERP),
1356*5088Sab196087 		    /* MSG_INTL(MSG_HELP_INTERP) */
1357*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_INTERP),
1358*5088Sab196087 		    opt_interp, arg_interp },
1359*5088Sab196087 
1360*5088Sab196087 		/* phdr:delete */
1361*5088Sab196087 		{ cmd_delete, cpl_1starg_pt, name_delete,
1362*5088Sab196087 		    /* MSG_INTL(MSG_DESC_DELETE) */
1363*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_DELETE),
1364*5088Sab196087 		    /* MSG_INTL(MSG_HELP_DELETE) */
1365*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_DELETE),
1366*5088Sab196087 		    opt_minus_phndx, arg_delete },
1367*5088Sab196087 
1368*5088Sab196087 		/* phdr:move */
1369*5088Sab196087 		{ cmd_move, cpl_1starg_pt, name_move,
1370*5088Sab196087 		    /* MSG_INTL(MSG_DESC_MOVE) */
1371*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_MOVE),
1372*5088Sab196087 		    /* MSG_INTL(MSG_HELP_MOVE) */
1373*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_MOVE),
1374*5088Sab196087 		    opt_minus_phndx, arg_move },
1375*5088Sab196087 
1376*5088Sab196087 		{ NULL }
1377*5088Sab196087 	};
1378*5088Sab196087 
1379*5088Sab196087 	static elfedit_module_t module = {
1380*5088Sab196087 	    ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
1381*5088Sab196087 	    /* MSG_INTL(MSG_MOD_DESC) */
1382*5088Sab196087 	    ELFEDIT_I18NHDL(MSG_MOD_DESC),
1383*5088Sab196087 	    cmds, mod_i18nhdl_to_str };
1384*5088Sab196087 
1385*5088Sab196087 	return (&module);
1386*5088Sab196087 }
1387