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