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