1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <elfedit.h>
30 #include <sys/elf_SPARC.h>
31 #include <sys/elf_amd64.h>
32 #include <strings.h>
33 #include <debug.h>
34 #include <conv.h>
35 #include <shdr_msg.h>
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 SHDR_CMD_T_DUMP = 0, /* shdr:dump */
47
48 SHDR_CMD_T_SH_ADDR = 1, /* shdr:sh_addr */
49 SHDR_CMD_T_SH_ADDRALIGN = 2, /* shdr:sh_addralign */
50 SHDR_CMD_T_SH_ENTSIZE = 3, /* shdr:sh_entsize */
51 SHDR_CMD_T_SH_FLAGS = 4, /* shdr:sh_flags */
52 SHDR_CMD_T_SH_INFO = 5, /* shdr:sh_info */
53 SHDR_CMD_T_SH_LINK = 6, /* shdr:sh_link */
54 SHDR_CMD_T_SH_NAME = 7, /* shdr:sh_name */
55 SHDR_CMD_T_SH_OFFSET = 8, /* shdr:sh_offset */
56 SHDR_CMD_T_SH_SIZE = 9, /* shdr:sh_size */
57 SHDR_CMD_T_SH_TYPE = 10 /* shdr:sh_type */
58 } SHDR_CMD_T;
59
60
61
62 #ifndef _ELF64
63 /*
64 * We supply this function for the msg module. Only one copy is needed.
65 */
66 const char *
_shdr_msg(Msg mid)67 _shdr_msg(Msg mid)
68 {
69 return (gettext(MSG_ORIG(mid)));
70 }
71
72 #endif
73
74
75
76 /*
77 * This function is supplied to elfedit through our elfedit_module_t
78 * definition. It translates the opaque elfedit_i18nhdl_t handles
79 * in our module interface into the actual strings for elfedit to
80 * use.
81 *
82 * note:
83 * This module uses Msg codes for its i18n handle type.
84 * So the translation is simply to use MSG_INTL() to turn
85 * it into a string and return it.
86 */
87 static const char *
mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)88 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
89 {
90 Msg msg = (Msg)hdl;
91
92 return (MSG_INTL(msg));
93 }
94
95
96
97 /*
98 * The shdr_opt_t enum specifies a bit value for every optional
99 * argument allowed by a command in this module.
100 */
101 typedef enum {
102 SHDR_OPT_F_AND = 1, /* -and: AND (&) values to dest */
103 SHDR_OPT_F_CMP = 2, /* -cmp: Complement (~) values */
104 SHDR_OPT_F_NAMOFFSET = 4, /* -name_offset: Name arg is numeric */
105 /* ofset rather than string */
106 SHDR_OPT_F_OR = 8, /* -or: OR (|) values to dest */
107 SHDR_OPT_F_SHNDX = 16, /* -shndx: Section by index, not name */
108 SHDR_OPT_F_SHTYP = 32, /* -shtyp: Section by type, not name */
109 SHDR_OPT_F_VALUE_SHNAM = 64, /* -value_shnam: Value of sh_info or */
110 /* sh_link given as section name */
111 SHDR_OPT_F_VALUE_SHTYP = 128 /* -value_shtyp: Value of sh_info or */
112 /* sh_link given as section type */
113 } shdr_opt_t;
114
115
116 /*
117 * A variable of type ARGSTATE is used by each command to maintain
118 * information about the section headers and related things. It is
119 * initialized by process_args(), and used by the other routines.
120 */
121 typedef struct {
122 elfedit_obj_state_t *obj_state;
123 shdr_opt_t optmask; /* Mask of options used */
124 int argc; /* # of plain arguments */
125 const char **argv; /* Plain arguments */
126 } ARGSTATE;
127
128
129
130
131 /*
132 * Standard argument processing for shdr module
133 *
134 * entry
135 * obj_state, argc, argv - Standard command arguments
136 * optmask - Mask of allowed optional arguments.
137 * cmd - SHDR_CMD_T_* value giving identify of caller
138 * argstate - Address of ARGSTATE block to be initialized
139 *
140 * exit:
141 * On success, *argstate is initialized. On error,
142 * an error is issued and this routine does not return.
143 */
144 static void
process_args(elfedit_obj_state_t * obj_state,int argc,const char * argv[],SHDR_CMD_T cmd,ARGSTATE * argstate)145 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
146 SHDR_CMD_T cmd, ARGSTATE *argstate)
147 {
148 elfedit_getopt_state_t getopt_state;
149 elfedit_getopt_ret_t *getopt_ret;
150
151 bzero(argstate, sizeof (*argstate));
152 argstate->obj_state = obj_state;
153
154 elfedit_getopt_init(&getopt_state, &argc, &argv);
155
156 /* Add each new option to the options mask */
157 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL)
158 argstate->optmask |= getopt_ret->gor_idmask;
159
160 /* Are the right number of plain arguments present? */
161 switch (cmd) {
162 case SHDR_CMD_T_DUMP:
163 if (argc > 1)
164 elfedit_command_usage();
165 break;
166 case SHDR_CMD_T_SH_FLAGS:
167 /* shdr:sh_flags allows an arbitrary number of arguments */
168 break;
169 default:
170 /* The remaining commands accept 2 plain arguments */
171 if (argc > 2)
172 elfedit_command_usage();
173 break;
174 }
175
176 /* If there may be an arbitrary amount of output, use a pager */
177 if (argc == 0)
178 elfedit_pager_init();
179
180 /* Return the updated values of argc/argv */
181 argstate->argc = argc;
182 argstate->argv = argv;
183 }
184
185
186
187 /*
188 * Options for deciding which items print_shdr() displays.
189 */
190 typedef enum {
191 PRINT_SHDR_ALL, /* Print all shdr[ndx:ndx+cnt-1] */
192 PRINT_SHDR_TYPE, /* Print all shdr[ndx:ndx+cnt-1] with type */
193 /* of shdr[ndx] */
194 PRINT_SHDR_NAME, /* Print all shdr[ndx:ndx+cnt-1] with name */
195 /* of shdr[ndx] */
196 } PRINT_SHDR_T;
197
198 /*
199 * Print section header values, taking the calling command, and output style
200 * into account.
201 *
202 * entry:
203 * autoprint - If True, output is only produced if the elfedit
204 * autoprint flag is set. If False, output is always produced.
205 * cmd - SHDR_CMD_T_* value giving identify of caller
206 * argstate - State block for section header array
207 * ndx - Index of first section to display
208 * cnt - Number of sections to display
209 * print_type - Specifies which items are shown
210 */
211 static void
print_shdr(SHDR_CMD_T cmd,int autoprint,ARGSTATE * argstate,Word ndx,Word cnt,PRINT_SHDR_T print_type)212 print_shdr(SHDR_CMD_T cmd, int autoprint, ARGSTATE *argstate,
213 Word ndx, Word cnt, PRINT_SHDR_T print_type)
214 {
215 elfedit_outstyle_t outstyle;
216 Ehdr *ehdr = argstate->obj_state->os_ehdr;
217 uchar_t osabi = ehdr->e_ident[EI_OSABI];
218 Half mach = ehdr->e_machine;
219 elfedit_section_t *ref_sec = &argstate->obj_state->os_secarr[ndx];
220
221
222 if ((autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) ||
223 (cnt == 0))
224 return;
225
226 /*
227 * Pick an output style. shdr:dump is required to use the default
228 * style. The other commands use the current output style.
229 */
230 outstyle = (cmd == SHDR_CMD_T_DUMP) ?
231 ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle();
232
233 for (; cnt--; ndx++) {
234 elfedit_section_t *sec = &argstate->obj_state->os_secarr[ndx];
235 Shdr *shdr = sec->sec_shdr;
236
237 switch (print_type) {
238 case PRINT_SHDR_TYPE:
239 if (shdr->sh_type != ref_sec->sec_shdr->sh_type)
240 continue;
241 break;
242
243 case PRINT_SHDR_NAME:
244 if (strcmp(sec->sec_name, ref_sec->sec_name) != 0)
245 continue;
246 break;
247 }
248
249 /*
250 * If doing default output, use elfdump style where we
251 * show all section header attributes. In this case, the
252 * command that called us doesn't matter
253 */
254 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
255 elfedit_printf(MSG_ORIG(MSG_STR_NL));
256 elfedit_printf(MSG_INTL(MSG_ELF_SHDR), ndx,
257 sec->sec_name);
258 Elf_shdr(NULL, osabi, mach, sec->sec_shdr);
259 continue;
260 }
261
262 /* Non-default output is handled case by case */
263 switch (cmd) {
264 case SHDR_CMD_T_SH_ADDR:
265 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDHEXNL),
266 EC_XWORD(shdr->sh_addr));
267 break;
268
269 case SHDR_CMD_T_SH_ADDRALIGN:
270 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDHEXNL),
271 EC_XWORD(shdr->sh_addralign));
272 break;
273
274 case SHDR_CMD_T_SH_ENTSIZE:
275 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDHEXNL),
276 EC_XWORD(shdr->sh_entsize));
277 break;
278
279 case SHDR_CMD_T_SH_FLAGS:
280 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
281 Conv_sec_flags_buf_t sec_flags_buf;
282
283 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
284 conv_sec_flags(osabi, mach, shdr->sh_flags,
285 CONV_FMT_NOBKT, &sec_flags_buf));
286 } else {
287 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDHEXNL),
288 EC_XWORD(shdr->sh_flags));
289 }
290 break;
291
292 case SHDR_CMD_T_SH_INFO:
293 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL),
294 EC_WORD(shdr->sh_info));
295 break;
296
297 case SHDR_CMD_T_SH_LINK:
298 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL),
299 EC_WORD(shdr->sh_link));
300 break;
301
302 case SHDR_CMD_T_SH_NAME:
303 /*
304 * In simple output mode, we show the string. In
305 * numeric mode, we show the string table offset.
306 */
307 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
308 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
309 sec->sec_name);
310 } else {
311 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL),
312 EC_WORD(shdr->sh_name));
313 }
314 break;
315
316 case SHDR_CMD_T_SH_OFFSET:
317 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDHEXNL),
318 EC_XWORD(shdr->sh_offset));
319 break;
320
321 case SHDR_CMD_T_SH_SIZE:
322 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDHEXNL),
323 EC_XWORD(shdr->sh_size));
324 break;
325
326 case SHDR_CMD_T_SH_TYPE:
327 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
328 Conv_inv_buf_t inv_buf;
329
330 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
331 conv_sec_type(osabi, mach, shdr->sh_type, 0,
332 &inv_buf));
333 } else {
334 elfedit_printf(MSG_ORIG(MSG_FMT_WORDHEXNL),
335 EC_WORD(shdr->sh_type));
336 }
337 break;
338 }
339 }
340 }
341
342
343 /*
344 * Common body for the shdr: module commands. These commands
345 * share a large amount of common behavior, so it is convenient
346 * to centralize things and use the cmd argument to handle the
347 * small differences.
348 *
349 * entry:
350 * cmd - One of the SHDR_CMD_T_* constants listed above, specifying
351 * which command to implement.
352 * obj_state, argc, argv - Standard command arguments
353 */
354 static elfedit_cmdret_t
cmd_body(SHDR_CMD_T cmd,elfedit_obj_state_t * obj_state,int argc,const char * argv[])355 cmd_body(SHDR_CMD_T cmd, elfedit_obj_state_t *obj_state,
356 int argc, const char *argv[])
357 {
358 Ehdr *ehdr = obj_state->os_ehdr;
359 uchar_t osabi = ehdr->e_ident[EI_OSABI];
360 Half mach = ehdr->e_machine;
361 ARGSTATE argstate;
362 Word ndx;
363 elfedit_section_t *shdr_sec;
364 Shdr *shdr;
365 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE;
366 PRINT_SHDR_T print_type;
367
368 process_args(obj_state, argc, argv, cmd, &argstate);
369
370 /* If there are no arguments, dump the whole table and return */
371 if (argstate.argc == 0) {
372 print_shdr(cmd, 0, &argstate, 0, obj_state->os_shnum,
373 PRINT_SHDR_ALL);
374 return (ELFEDIT_CMDRET_NONE);
375 }
376
377 /*
378 * The first argument gives the section to use. This can be a
379 * name (default), section index, or section type, depending on
380 * the options used.
381 */
382 if (argstate.optmask & SHDR_OPT_F_SHNDX) {
383 ndx = elfedit_atoshndx(argstate.argv[0], obj_state->os_shnum);
384 print_type = PRINT_SHDR_ALL;
385 } else if (argstate.optmask & SHDR_OPT_F_SHTYP) {
386 ndx = elfedit_type_to_shndx(obj_state,
387 elfedit_atoconst(argstate.argv[0], ELFEDIT_CONST_SHT));
388 print_type = PRINT_SHDR_TYPE;
389 } else {
390 ndx = elfedit_name_to_shndx(obj_state, argstate.argv[0]);
391 print_type = PRINT_SHDR_NAME;
392 }
393
394 /* If there is a single argument, display that item and return */
395 if (argstate.argc == 1) {
396 Word cnt;
397
398 cnt = (print_type == PRINT_SHDR_ALL) ?
399 1 : obj_state->os_shnum - ndx;
400 print_shdr(cmd, 0, &argstate, ndx, cnt, print_type);
401 return (ELFEDIT_CMDRET_NONE);
402 }
403
404 /*
405 * Section [0] is supposed to be all zero unless extended sections
406 * are in force. Rather than setting extended values directly,
407 * it is expected to be handled by libelf. So, a direct change here
408 * is probably not what was intended.
409 */
410 if (ndx == 0)
411 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CHGSHDR0));
412
413 /* The second value is an integer giving a new value */
414 shdr_sec = &obj_state->os_secarr[ndx];
415 shdr = shdr_sec->sec_shdr;
416 switch (cmd) {
417 /*
418 * SHDR_CMD_T_DUMP can't get here: It never has more than
419 * one argument, and is handled above.
420 */
421
422 case SHDR_CMD_T_SH_ADDR:
423 {
424 Addr sh_addr = elfedit_atoui(argstate.argv[1], NULL);
425
426 if (shdr->sh_addr == sh_addr) {
427 elfedit_msg(ELFEDIT_MSG_DEBUG,
428 MSG_INTL(MSG_DEBUG_LLX_OK),
429 ndx, shdr_sec->sec_name,
430 MSG_ORIG(MSG_CMD_SH_ADDR),
431 EC_ADDR(shdr->sh_addr));
432 } else {
433 elfedit_msg(ELFEDIT_MSG_DEBUG,
434 MSG_INTL(MSG_DEBUG_LLX_CHG),
435 ndx, shdr_sec->sec_name,
436 MSG_ORIG(MSG_CMD_SH_ADDR),
437 EC_ADDR(shdr->sh_addr), EC_ADDR(sh_addr));
438 ret = ELFEDIT_CMDRET_MOD;
439 shdr->sh_addr = sh_addr;
440 }
441 }
442 break;
443
444 case SHDR_CMD_T_SH_ADDRALIGN:
445 {
446 Xword sh_addralign;
447
448 sh_addralign = elfedit_atoui(argstate.argv[1], NULL);
449 if (elfedit_bits_set(sh_addralign,
450 sizeof (sh_addralign)) > 1)
451 elfedit_msg(ELFEDIT_MSG_DEBUG,
452 MSG_INTL(MSG_DEBUG_ADDRALIGN),
453 argstate.argv[1]);
454 if (shdr->sh_addralign == sh_addralign) {
455 elfedit_msg(ELFEDIT_MSG_DEBUG,
456 MSG_INTL(MSG_DEBUG_LLX_OK),
457 ndx, shdr_sec->sec_name,
458 MSG_ORIG(MSG_CMD_SH_ADDRALIGN),
459 EC_XWORD(shdr->sh_addralign));
460 } else {
461 elfedit_msg(ELFEDIT_MSG_DEBUG,
462 MSG_INTL(MSG_DEBUG_LLX_CHG),
463 ndx, shdr_sec->sec_name,
464 MSG_ORIG(MSG_CMD_SH_ADDRALIGN),
465 EC_XWORD(shdr->sh_addralign),
466 EC_XWORD(sh_addralign));
467 ret = ELFEDIT_CMDRET_MOD;
468 shdr->sh_addralign = sh_addralign;
469 }
470 }
471 break;
472
473 case SHDR_CMD_T_SH_ENTSIZE:
474 {
475 Xword sh_entsize;
476
477 sh_entsize = elfedit_atoui(argstate.argv[1], NULL);
478 if (shdr->sh_entsize == sh_entsize) {
479 elfedit_msg(ELFEDIT_MSG_DEBUG,
480 MSG_INTL(MSG_DEBUG_LLX_OK),
481 ndx, shdr_sec->sec_name,
482 MSG_ORIG(MSG_CMD_SH_ENTSIZE),
483 EC_XWORD(shdr->sh_entsize));
484 } else {
485 elfedit_msg(ELFEDIT_MSG_DEBUG,
486 MSG_INTL(MSG_DEBUG_LLX_CHG),
487 ndx, shdr_sec->sec_name,
488 MSG_ORIG(MSG_CMD_SH_ENTSIZE),
489 EC_XWORD(shdr->sh_entsize),
490 EC_XWORD(sh_entsize));
491 ret = ELFEDIT_CMDRET_MOD;
492 shdr->sh_entsize = sh_entsize;
493 }
494 }
495 break;
496
497 case SHDR_CMD_T_SH_FLAGS:
498 {
499 Conv_sec_flags_buf_t buf1, buf2;
500 Word sh_flags = 0;
501 int i;
502
503 /* Collect the flag arguments */
504 for (i = 1; i < argstate.argc; i++)
505 sh_flags |=
506 (Word) elfedit_atoconst(argstate.argv[i],
507 ELFEDIT_CONST_SHF);
508
509 /* Complement the value? */
510 if (argstate.optmask & SHDR_OPT_F_CMP)
511 sh_flags = ~sh_flags;
512
513 /* Perform any requested bit operations */
514 if (argstate.optmask & SHDR_OPT_F_AND)
515 sh_flags &= shdr->sh_flags;
516 else if (argstate.optmask & SHDR_OPT_F_OR)
517 sh_flags |= shdr->sh_flags;
518
519 /* Set the value */
520 if (shdr->sh_flags == sh_flags) {
521 elfedit_msg(ELFEDIT_MSG_DEBUG,
522 MSG_INTL(MSG_DEBUG_S_OK),
523 ndx, shdr_sec->sec_name,
524 MSG_ORIG(MSG_CMD_SH_FLAGS),
525 conv_sec_flags(osabi, mach,
526 shdr->sh_flags, 0, &buf1));
527 } else {
528 elfedit_msg(ELFEDIT_MSG_DEBUG,
529 MSG_INTL(MSG_DEBUG_S_CHG),
530 ndx, shdr_sec->sec_name,
531 MSG_ORIG(MSG_CMD_SH_FLAGS),
532 conv_sec_flags(osabi, mach,
533 shdr->sh_flags, 0, &buf1),
534 conv_sec_flags(osabi, mach,
535 sh_flags, 0, &buf2));
536 ret = ELFEDIT_CMDRET_MOD;
537 shdr->sh_flags = sh_flags;
538 }
539 }
540 break;
541
542 case SHDR_CMD_T_SH_INFO:
543 {
544 Word sh_info;
545
546 if (argstate.optmask & SHDR_OPT_F_VALUE_SHNAM)
547 sh_info = elfedit_name_to_shndx(obj_state,
548 argstate.argv[1]);
549 else if (argstate.optmask & SHDR_OPT_F_VALUE_SHTYP)
550 sh_info = elfedit_type_to_shndx(obj_state,
551 elfedit_atoconst(argstate.argv[1],
552 ELFEDIT_CONST_SHT));
553 else
554 sh_info = elfedit_atoui(argstate.argv[1], NULL);
555
556 if (shdr->sh_info == sh_info) {
557 elfedit_msg(ELFEDIT_MSG_DEBUG,
558 MSG_INTL(MSG_DEBUG_D_OK),
559 ndx, shdr_sec->sec_name,
560 MSG_ORIG(MSG_CMD_SH_INFO),
561 EC_WORD(shdr->sh_info));
562 } else {
563 elfedit_msg(ELFEDIT_MSG_DEBUG,
564 MSG_INTL(MSG_DEBUG_D_CHG),
565 ndx, shdr_sec->sec_name,
566 MSG_ORIG(MSG_CMD_SH_INFO),
567 EC_WORD(shdr->sh_info), EC_WORD(sh_info));
568 ret = ELFEDIT_CMDRET_MOD;
569 shdr->sh_info = sh_info;
570 }
571 }
572 break;
573
574 case SHDR_CMD_T_SH_LINK:
575 {
576 Word sh_link;
577
578 if (argstate.optmask & SHDR_OPT_F_VALUE_SHNAM)
579 sh_link = elfedit_name_to_shndx(obj_state,
580 argstate.argv[1]);
581 else if (argstate.optmask & SHDR_OPT_F_VALUE_SHTYP)
582 sh_link = elfedit_type_to_shndx(obj_state,
583 elfedit_atoconst(argstate.argv[1],
584 ELFEDIT_CONST_SHT));
585 else
586 sh_link = elfedit_atoui(argstate.argv[1], NULL);
587
588 if (shdr->sh_link == sh_link) {
589 elfedit_msg(ELFEDIT_MSG_DEBUG,
590 MSG_INTL(MSG_DEBUG_D_OK),
591 ndx, shdr_sec->sec_name,
592 MSG_ORIG(MSG_CMD_SH_LINK),
593 EC_WORD(shdr->sh_link));
594 } else {
595 elfedit_msg(ELFEDIT_MSG_DEBUG,
596 MSG_INTL(MSG_DEBUG_D_CHG),
597 ndx, shdr_sec->sec_name,
598 MSG_ORIG(MSG_CMD_SH_LINK),
599 EC_WORD(shdr->sh_link), EC_WORD(sh_link));
600 ret = ELFEDIT_CMDRET_MOD;
601 shdr->sh_link = sh_link;
602 }
603 }
604 break;
605
606 case SHDR_CMD_T_SH_NAME:
607 {
608 elfedit_section_t *shstr_sec =
609 &obj_state->os_secarr[obj_state->os_shstrndx];
610 Word sh_name;
611
612 /*
613 * If -name_offset was specified, this is an offset
614 * into the string table. Otherwise it is a string
615 * we need to turn into an offset.
616 */
617 sh_name = (argstate.optmask & SHDR_OPT_F_NAMOFFSET) ?
618 elfedit_atoui(argstate.argv[1], NULL) :
619 elfedit_strtab_insert(obj_state,
620 shstr_sec, NULL, argstate.argv[1]);
621 if (shdr->sh_name == sh_name) {
622 elfedit_msg(ELFEDIT_MSG_DEBUG,
623 MSG_INTL(MSG_DEBUG_D_OK),
624 ndx, shdr_sec->sec_name,
625 MSG_ORIG(MSG_CMD_SH_NAME),
626 EC_WORD(shdr->sh_name));
627 } else {
628 /*
629 * The section name is cached, so we must
630 * also update that value. This call will
631 * warn if the offset is out of range, and
632 * will supply a safe string in that case.
633 */
634 shdr_sec->sec_name =
635 elfedit_offset_to_str(shstr_sec,
636 sh_name, ELFEDIT_MSG_DEBUG, 1);
637
638 elfedit_msg(ELFEDIT_MSG_DEBUG,
639 MSG_INTL(MSG_DEBUG_D_CHG),
640 ndx, shdr_sec->sec_name,
641 MSG_ORIG(MSG_CMD_SH_NAME),
642 EC_WORD(shdr->sh_name), EC_WORD(sh_name));
643 ret = ELFEDIT_CMDRET_MOD;
644 shdr->sh_name = sh_name;
645 }
646 }
647 break;
648
649 case SHDR_CMD_T_SH_OFFSET:
650 {
651 Off sh_offset;
652
653 sh_offset = elfedit_atoui(argstate.argv[1], NULL);
654 if (shdr->sh_offset == sh_offset) {
655 elfedit_msg(ELFEDIT_MSG_DEBUG,
656 MSG_INTL(MSG_DEBUG_LLX_OK),
657 ndx, shdr_sec->sec_name,
658 MSG_ORIG(MSG_CMD_SH_OFFSET),
659 EC_XWORD(shdr->sh_offset));
660 } else {
661 elfedit_msg(ELFEDIT_MSG_DEBUG,
662 MSG_INTL(MSG_DEBUG_LLX_CHG),
663 ndx, shdr_sec->sec_name,
664 MSG_ORIG(MSG_CMD_SH_OFFSET),
665 EC_XWORD(shdr->sh_offset),
666 EC_XWORD(sh_offset));
667 ret = ELFEDIT_CMDRET_MOD;
668 shdr->sh_offset = sh_offset;
669 }
670 }
671 break;
672
673 case SHDR_CMD_T_SH_SIZE:
674 {
675 Xword sh_size;
676
677 sh_size = elfedit_atoui(argstate.argv[1], NULL);
678 if (shdr->sh_size == sh_size) {
679 elfedit_msg(ELFEDIT_MSG_DEBUG,
680 MSG_INTL(MSG_DEBUG_LLX_OK),
681 ndx, shdr_sec->sec_name,
682 MSG_ORIG(MSG_CMD_SH_SIZE),
683 EC_XWORD(shdr->sh_size));
684 } else {
685 elfedit_msg(ELFEDIT_MSG_DEBUG,
686 MSG_INTL(MSG_DEBUG_LLX_CHG),
687 ndx, shdr_sec->sec_name,
688 MSG_ORIG(MSG_CMD_SH_SIZE),
689 EC_XWORD(shdr->sh_size),
690 EC_XWORD(sh_size));
691 ret = ELFEDIT_CMDRET_MOD;
692 shdr->sh_size = sh_size;
693 }
694 }
695 break;
696
697 case SHDR_CMD_T_SH_TYPE:
698 {
699 Word sh_type = elfedit_atoconst(argstate.argv[1],
700 ELFEDIT_CONST_SHT);
701 Conv_inv_buf_t inv_buf1, inv_buf2;
702
703 if (shdr->sh_type == sh_type) {
704 elfedit_msg(ELFEDIT_MSG_DEBUG,
705 MSG_INTL(MSG_DEBUG_S_OK),
706 ndx, shdr_sec->sec_name,
707 MSG_ORIG(MSG_CMD_SH_TYPE),
708 conv_sec_type(osabi, mach, shdr->sh_type,
709 0, &inv_buf1));
710 } else {
711 elfedit_msg(ELFEDIT_MSG_DEBUG,
712 MSG_INTL(MSG_DEBUG_S_CHG),
713 ndx, shdr_sec->sec_name,
714 MSG_ORIG(MSG_CMD_SH_TYPE),
715 conv_sec_type(osabi, mach, shdr->sh_type,
716 0, &inv_buf1),
717 conv_sec_type(osabi, mach, sh_type,
718 0, &inv_buf2));
719 ret = ELFEDIT_CMDRET_MOD;
720 shdr->sh_type = sh_type;
721 }
722 }
723 break;
724 }
725
726 /*
727 * If we modified the section header array, tell libelf.
728 */
729 if (ret == ELFEDIT_CMDRET_MOD)
730 elfedit_modified_shdr(shdr_sec);
731
732 /* Do autoprint */
733 print_shdr(cmd, 1, &argstate, ndx, 1, PRINT_SHDR_ALL);
734
735 return (ret);
736 }
737
738
739
740
741 /*
742 * Command completion functions for the various commands
743 */
744
745 /*
746 * All of the commands accept the same first argument (sec) that
747 * specifies the section. This argument can be a section name
748 * (default), section index, or section type, depending on the
749 * options used. This routine determines which case is current,
750 * and then supplies completion for the first argument.
751 */
752 static void
cpl_1starg_sec(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)753 cpl_1starg_sec(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
754 const char *argv[], int num_opt)
755 {
756 elfedit_section_t *sec;
757 enum { NAME, INDEX, TYPE } op;
758 Word ndx;
759
760 if (argc != (num_opt + 1))
761 return;
762
763 op = NAME;
764 for (ndx = 0; ndx < num_opt; ndx++) {
765 if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0)
766 op = INDEX;
767 else if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0)
768 op = TYPE;
769 }
770
771 switch (op) {
772 case NAME:
773 if (obj_state == NULL)
774 break;
775 sec = obj_state->os_secarr;
776 for (ndx = 0; ndx < obj_state->os_shnum; ndx++, sec++)
777 elfedit_cpl_match(cpldata, sec->sec_name, 0);
778 break;
779
780 case INDEX:
781 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHN);
782 break;
783
784 case TYPE:
785 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT);
786 break;
787 }
788 }
789
790
791 /*ARGSUSED*/
792 static void
cpl_sh_flags(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)793 cpl_sh_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
794 const char *argv[], int num_opt)
795 {
796 /* Handle -shXXX options */
797 cpl_1starg_sec(obj_state, cpldata, argc, argv, num_opt);
798
799 /* The second and following arguments can be an SHF_ value */
800 if (argc >= (num_opt + 2))
801 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHF);
802 }
803
804 /*
805 * For shdr:sh_info and shdr:sh_link: The value argument can be an
806 * integer, section name, or section type.
807 */
808 /*ARGSUSED*/
809 static void
cpl_sh_infolink(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)810 cpl_sh_infolink(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
811 const char *argv[], int num_opt)
812 {
813 elfedit_section_t *sec;
814 enum { NAME, INTVAL, TYPE } op;
815 Word ndx;
816
817 /* Handle -shXXX options */
818 cpl_1starg_sec(obj_state, cpldata, argc, argv, num_opt);
819
820 if (argc != (num_opt + 2))
821 return;
822
823 op = INTVAL;
824 for (ndx = 0; ndx < num_opt; ndx++) {
825 if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_VALUE_SHNAM)) == 0)
826 op = NAME;
827 else if (strcmp(argv[ndx],
828 MSG_ORIG(MSG_STR_MINUS_VALUE_SHTYP)) == 0)
829 op = TYPE;
830 }
831
832 switch (op) {
833 case NAME:
834 if (obj_state == NULL)
835 break;
836 sec = obj_state->os_secarr;
837 for (ndx = 0; ndx < obj_state->os_shnum; ndx++, sec++)
838 elfedit_cpl_match(cpldata, sec->sec_name, 0);
839 break;
840
841 case TYPE:
842 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT);
843 break;
844 }
845 }
846
847 /*ARGSUSED*/
848 static void
cpl_sh_type(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)849 cpl_sh_type(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
850 const char *argv[], int num_opt)
851 {
852 /* Handle -shXXX options */
853 cpl_1starg_sec(obj_state, cpldata, argc, argv, num_opt);
854
855 /* The second argument can be an SHT_ value */
856 if (argc == (num_opt + 2))
857 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT);
858 }
859
860
861
862 /*
863 * Implementation functions for the commands
864 */
865 static elfedit_cmdret_t
cmd_dump(elfedit_obj_state_t * obj_state,int argc,const char * argv[])866 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
867 {
868 return (cmd_body(SHDR_CMD_T_DUMP, obj_state, argc, argv));
869 }
870
871
872 static elfedit_cmdret_t
cmd_sh_addr(elfedit_obj_state_t * obj_state,int argc,const char * argv[])873 cmd_sh_addr(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
874 {
875 return (cmd_body(SHDR_CMD_T_SH_ADDR, obj_state, argc, argv));
876 }
877
878
879 static elfedit_cmdret_t
cmd_sh_addralign(elfedit_obj_state_t * obj_state,int argc,const char * argv[])880 cmd_sh_addralign(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
881 {
882 return (cmd_body(SHDR_CMD_T_SH_ADDRALIGN, obj_state, argc, argv));
883 }
884
885
886 static elfedit_cmdret_t
cmd_sh_entsize(elfedit_obj_state_t * obj_state,int argc,const char * argv[])887 cmd_sh_entsize(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
888 {
889 return (cmd_body(SHDR_CMD_T_SH_ENTSIZE, obj_state, argc, argv));
890 }
891
892 static elfedit_cmdret_t
cmd_sh_flags(elfedit_obj_state_t * obj_state,int argc,const char * argv[])893 cmd_sh_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
894 {
895 return (cmd_body(SHDR_CMD_T_SH_FLAGS, obj_state, argc, argv));
896 }
897
898 static elfedit_cmdret_t
cmd_sh_info(elfedit_obj_state_t * obj_state,int argc,const char * argv[])899 cmd_sh_info(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
900 {
901 return (cmd_body(SHDR_CMD_T_SH_INFO, obj_state, argc, argv));
902 }
903
904 static elfedit_cmdret_t
cmd_sh_link(elfedit_obj_state_t * obj_state,int argc,const char * argv[])905 cmd_sh_link(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
906 {
907 return (cmd_body(SHDR_CMD_T_SH_LINK, obj_state, argc, argv));
908 }
909
910 static elfedit_cmdret_t
cmd_sh_name(elfedit_obj_state_t * obj_state,int argc,const char * argv[])911 cmd_sh_name(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
912 {
913 return (cmd_body(SHDR_CMD_T_SH_NAME, obj_state, argc, argv));
914 }
915
916 static elfedit_cmdret_t
cmd_sh_offset(elfedit_obj_state_t * obj_state,int argc,const char * argv[])917 cmd_sh_offset(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
918 {
919 return (cmd_body(SHDR_CMD_T_SH_OFFSET, obj_state, argc, argv));
920 }
921
922 static elfedit_cmdret_t
cmd_sh_size(elfedit_obj_state_t * obj_state,int argc,const char * argv[])923 cmd_sh_size(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
924 {
925 return (cmd_body(SHDR_CMD_T_SH_SIZE, obj_state, argc, argv));
926 }
927
928 static elfedit_cmdret_t
cmd_sh_type(elfedit_obj_state_t * obj_state,int argc,const char * argv[])929 cmd_sh_type(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
930 {
931 return (cmd_body(SHDR_CMD_T_SH_TYPE, obj_state, argc, argv));
932 }
933
934
935
936 /*ARGSUSED*/
937 elfedit_module_t *
elfedit_init(elfedit_module_version_t version)938 elfedit_init(elfedit_module_version_t version)
939 {
940 /* Multiple commands accept only the standard set of options */
941 static elfedit_cmd_optarg_t opt_std[] = {
942 { ELFEDIT_STDOA_OPT_O, NULL,
943 ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
944 { MSG_ORIG(MSG_STR_MINUS_SHNDX),
945 /* MSG_INTL(MSG_OPTDESC_SHNDX) */
946 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), 0,
947 SHDR_OPT_F_SHNDX, SHDR_OPT_F_SHTYP },
948 { MSG_ORIG(MSG_STR_MINUS_SHTYP),
949 /* MSG_INTL(MSG_OPTDESC_SHTYP) */
950 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), 0,
951 SHDR_OPT_F_SHTYP, SHDR_OPT_F_SHNDX },
952 { NULL }
953 };
954
955 /*
956 * sh_info and sh_link accept the standard options above,
957 * plus -value_shnam and -value_shtyp.
958 */
959 static elfedit_cmd_optarg_t opt_infolink[] = {
960 { ELFEDIT_STDOA_OPT_O, NULL,
961 ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
962 { MSG_ORIG(MSG_STR_MINUS_SHNDX),
963 /* MSG_INTL(MSG_OPTDESC_SHNDX) */
964 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), 0,
965 SHDR_OPT_F_SHNDX, SHDR_OPT_F_SHTYP },
966 { MSG_ORIG(MSG_STR_MINUS_SHTYP),
967 /* MSG_INTL(MSG_OPTDESC_SHTYP) */
968 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), 0,
969 SHDR_OPT_F_SHTYP, SHDR_OPT_F_SHNDX },
970 { MSG_ORIG(MSG_STR_MINUS_VALUE_SHNAM),
971 /* MSG_INTL(MSG_OPTDESC_VALUE_SHNAM) */
972 ELFEDIT_I18NHDL(MSG_OPTDESC_VALUE_SHNAM), 0,
973 SHDR_OPT_F_VALUE_SHNAM, SHDR_OPT_F_VALUE_SHNAM },
974 { MSG_ORIG(MSG_STR_MINUS_VALUE_SHTYP),
975 /* MSG_INTL(MSG_OPTDESC_VALUE_SHTYP) */
976 ELFEDIT_I18NHDL(MSG_OPTDESC_VALUE_SHTYP), 0,
977 SHDR_OPT_F_VALUE_SHTYP, SHDR_OPT_F_VALUE_SHTYP },
978 { NULL }
979 };
980
981 /* shdr:sh_addr */
982 static const char *name_sh_addr[] = {
983 MSG_ORIG(MSG_CMD_SH_ADDR), NULL };
984 static elfedit_cmd_optarg_t arg_sh_addr[] = {
985 { MSG_ORIG(MSG_STR_SEC),
986 /* MSG_INTL(MSG_A1_SEC) */
987 ELFEDIT_I18NHDL(MSG_A1_SEC),
988 ELFEDIT_CMDOA_F_OPT },
989 { MSG_ORIG(MSG_STR_VALUE),
990 /* MSG_INTL(MSG_A2_DESC_SH_ADDR) */
991 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_ADDR),
992 ELFEDIT_CMDOA_F_OPT },
993 { NULL }
994 };
995
996 /* shdr:dump */
997 static const char *name_dump[] = {
998 MSG_ORIG(MSG_CMD_DUMP),
999 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */
1000 NULL
1001 };
1002 static elfedit_cmd_optarg_t opt_dump[] = {
1003 { MSG_ORIG(MSG_STR_MINUS_SHNDX),
1004 /* MSG_INTL(MSG_OPTDESC_SHNDX) */
1005 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), 0,
1006 SHDR_OPT_F_SHNDX, SHDR_OPT_F_SHTYP },
1007 { MSG_ORIG(MSG_STR_MINUS_SHTYP),
1008 /* MSG_INTL(MSG_OPTDESC_SHTYP) */
1009 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), 0,
1010 SHDR_OPT_F_SHTYP, SHDR_OPT_F_SHNDX },
1011 { NULL }
1012 };
1013 static elfedit_cmd_optarg_t arg_dump[] = {
1014 { MSG_ORIG(MSG_STR_SEC),
1015 /* MSG_INTL(MSG_A1_SEC) */
1016 ELFEDIT_I18NHDL(MSG_A1_SEC),
1017 ELFEDIT_CMDOA_F_OPT },
1018 { NULL }
1019 };
1020
1021 /* shdr:sh_addralign */
1022 static const char *name_sh_addralign[] = {
1023 MSG_ORIG(MSG_CMD_SH_ADDRALIGN), NULL };
1024 static elfedit_cmd_optarg_t arg_sh_addralign[] = {
1025 { MSG_ORIG(MSG_STR_SEC),
1026 /* MSG_INTL(MSG_A1_SEC) */
1027 ELFEDIT_I18NHDL(MSG_A1_SEC),
1028 ELFEDIT_CMDOA_F_OPT },
1029 { MSG_ORIG(MSG_STR_VALUE),
1030 /* MSG_INTL(MSG_A2_DESC_SH_ADDRALIGN) */
1031 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_ADDRALIGN),
1032 ELFEDIT_CMDOA_F_OPT },
1033 { NULL }
1034 };
1035
1036 /* shdr:sh_entsize */
1037 static const char *name_sh_entsize[] = {
1038 MSG_ORIG(MSG_CMD_SH_ENTSIZE), NULL };
1039 static elfedit_cmd_optarg_t arg_sh_entsize[] = {
1040 { MSG_ORIG(MSG_STR_SEC),
1041 /* MSG_INTL(MSG_A1_SEC) */
1042 ELFEDIT_I18NHDL(MSG_A1_SEC),
1043 ELFEDIT_CMDOA_F_OPT },
1044 { MSG_ORIG(MSG_STR_VALUE),
1045 /* MSG_INTL(MSG_A2_DESC_SH_ENTSIZE) */
1046 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_ENTSIZE),
1047 ELFEDIT_CMDOA_F_OPT },
1048 { NULL }
1049 };
1050
1051 /* shdr:sh_flags */
1052 static const char *name_sh_flags[] = {
1053 MSG_ORIG(MSG_CMD_SH_FLAGS), NULL };
1054 static elfedit_cmd_optarg_t opt_sh_flags[] = {
1055 { ELFEDIT_STDOA_OPT_AND, NULL,
1056 ELFEDIT_CMDOA_F_INHERIT, SHDR_OPT_F_AND, SHDR_OPT_F_OR },
1057 { ELFEDIT_STDOA_OPT_CMP, NULL,
1058 ELFEDIT_CMDOA_F_INHERIT, SHDR_OPT_F_CMP, 0 },
1059 { ELFEDIT_STDOA_OPT_O, NULL,
1060 ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1061 { ELFEDIT_STDOA_OPT_OR, NULL,
1062 ELFEDIT_CMDOA_F_INHERIT, SHDR_OPT_F_OR, SHDR_OPT_F_AND },
1063 { MSG_ORIG(MSG_STR_MINUS_SHNDX),
1064 /* MSG_INTL(MSG_OPTDESC_SHNDX) */
1065 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), 0,
1066 SHDR_OPT_F_SHNDX, SHDR_OPT_F_SHTYP },
1067 { MSG_ORIG(MSG_STR_MINUS_SHTYP),
1068 /* MSG_INTL(MSG_OPTDESC_SHTYP) */
1069 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), 0,
1070 SHDR_OPT_F_SHTYP, SHDR_OPT_F_SHNDX },
1071 { NULL }
1072 };
1073 static elfedit_cmd_optarg_t arg_sh_flags[] = {
1074 { MSG_ORIG(MSG_STR_SEC),
1075 /* MSG_INTL(MSG_A1_SEC) */
1076 ELFEDIT_I18NHDL(MSG_A1_SEC),
1077 ELFEDIT_CMDOA_F_OPT },
1078 { MSG_ORIG(MSG_STR_VALUE),
1079 /* MSG_INTL(MSG_A2_DESC_SH_FLAGS) */
1080 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_FLAGS),
1081 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
1082 { NULL }
1083 };
1084
1085 /* shdr:sh_info */
1086 static const char *name_sh_info[] = {
1087 MSG_ORIG(MSG_CMD_SH_INFO), NULL };
1088 static elfedit_cmd_optarg_t arg_sh_info[] = {
1089 { MSG_ORIG(MSG_STR_SEC),
1090 /* MSG_INTL(MSG_A1_SEC) */
1091 ELFEDIT_I18NHDL(MSG_A1_SEC),
1092 ELFEDIT_CMDOA_F_OPT },
1093 { MSG_ORIG(MSG_STR_VALUE),
1094 /* MSG_INTL(MSG_A2_DESC_SH_INFO) */
1095 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_INFO),
1096 ELFEDIT_CMDOA_F_OPT },
1097 { NULL }
1098 };
1099
1100 /* shdr:sh_link */
1101 static const char *name_sh_link[] = {
1102 MSG_ORIG(MSG_CMD_SH_LINK), NULL };
1103 static elfedit_cmd_optarg_t arg_sh_link[] = {
1104 { MSG_ORIG(MSG_STR_SEC),
1105 /* MSG_INTL(MSG_A1_SEC) */
1106 ELFEDIT_I18NHDL(MSG_A1_SEC),
1107 ELFEDIT_CMDOA_F_OPT },
1108 { MSG_ORIG(MSG_STR_VALUE),
1109 /* MSG_INTL(MSG_A2_DESC_SH_LINK) */
1110 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_LINK),
1111 ELFEDIT_CMDOA_F_OPT },
1112 { NULL }
1113 };
1114
1115 /* shdr:sh_name */
1116 static const char *name_sh_name[] = {
1117 MSG_ORIG(MSG_CMD_SH_NAME), NULL };
1118 static elfedit_cmd_optarg_t opt_sh_name[] = {
1119 { MSG_ORIG(MSG_STR_MINUS_NAME_OFFSET),
1120 /* MSG_INTL(MSG_OPTDESC_NAME_OFFSET) */
1121 ELFEDIT_I18NHDL(MSG_OPTDESC_NAME_OFFSET), 0,
1122 SHDR_OPT_F_NAMOFFSET, 0 },
1123 { ELFEDIT_STDOA_OPT_O, NULL,
1124 ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1125 { MSG_ORIG(MSG_STR_MINUS_SHNDX),
1126 /* MSG_INTL(MSG_OPTDESC_SHNDX) */
1127 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), 0,
1128 SHDR_OPT_F_SHNDX, SHDR_OPT_F_SHTYP },
1129 { MSG_ORIG(MSG_STR_MINUS_SHTYP),
1130 /* MSG_INTL(MSG_OPTDESC_SHTYP) */
1131 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), 0,
1132 SHDR_OPT_F_SHTYP, SHDR_OPT_F_SHNDX },
1133 { NULL }
1134 };
1135 static elfedit_cmd_optarg_t arg_sh_name[] = {
1136 { MSG_ORIG(MSG_STR_SEC),
1137 /* MSG_INTL(MSG_A1_SEC) */
1138 ELFEDIT_I18NHDL(MSG_A1_SEC),
1139 ELFEDIT_CMDOA_F_OPT },
1140 { MSG_ORIG(MSG_STR_NAME),
1141 /* MSG_INTL(MSG_A2_DESC_SH_NAME) */
1142 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_NAME),
1143 ELFEDIT_CMDOA_F_OPT },
1144 { NULL }
1145 };
1146
1147 /* shdr:sh_offset */
1148 static const char *name_sh_offset[] = {
1149 MSG_ORIG(MSG_CMD_SH_OFFSET), NULL };
1150 static elfedit_cmd_optarg_t arg_sh_offset[] = {
1151 { MSG_ORIG(MSG_STR_SEC),
1152 /* MSG_INTL(MSG_A1_SEC) */
1153 ELFEDIT_I18NHDL(MSG_A1_SEC),
1154 ELFEDIT_CMDOA_F_OPT },
1155 { MSG_ORIG(MSG_STR_VALUE),
1156 /* MSG_INTL(MSG_A2_DESC_SH_OFFSET) */
1157 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_OFFSET),
1158 ELFEDIT_CMDOA_F_OPT },
1159 { NULL }
1160 };
1161
1162 /* shdr:sh_size */
1163 static const char *name_sh_size[] = {
1164 MSG_ORIG(MSG_CMD_SH_SIZE), NULL };
1165 static elfedit_cmd_optarg_t arg_sh_size[] = {
1166 { MSG_ORIG(MSG_STR_SEC),
1167 /* MSG_INTL(MSG_A1_SEC) */
1168 ELFEDIT_I18NHDL(MSG_A1_SEC),
1169 ELFEDIT_CMDOA_F_OPT },
1170 { MSG_ORIG(MSG_STR_VALUE),
1171 /* MSG_INTL(MSG_A2_DESC_SH_SIZE) */
1172 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_SIZE),
1173 ELFEDIT_CMDOA_F_OPT },
1174 { NULL }
1175 };
1176
1177 /* shdr:sh_type */
1178 static const char *name_sh_type[] = {
1179 MSG_ORIG(MSG_CMD_SH_TYPE), NULL };
1180 static elfedit_cmd_optarg_t arg_sh_type[] = {
1181 { MSG_ORIG(MSG_STR_SEC),
1182 /* MSG_INTL(MSG_A1_SEC) */
1183 ELFEDIT_I18NHDL(MSG_A1_SEC),
1184 ELFEDIT_CMDOA_F_OPT },
1185 { MSG_ORIG(MSG_STR_VALUE),
1186 /* MSG_INTL(MSG_A2_DESC_SH_TYPE) */
1187 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_TYPE),
1188 ELFEDIT_CMDOA_F_OPT },
1189 { NULL }
1190 };
1191
1192 static elfedit_cmd_t cmds[] = {
1193 /* shdr:dump */
1194 { cmd_dump, cpl_1starg_sec, name_dump,
1195 /* MSG_INTL(MSG_DESC_DUMP) */
1196 ELFEDIT_I18NHDL(MSG_DESC_DUMP),
1197 /* MSG_INTL(MSG_HELP_DUMP) */
1198 ELFEDIT_I18NHDL(MSG_HELP_DUMP),
1199 opt_dump, arg_dump },
1200
1201 /* shdr:sh_addr */
1202 { cmd_sh_addr, cpl_1starg_sec, name_sh_addr,
1203 /* MSG_INTL(MSG_DESC_SH_ADDR) */
1204 ELFEDIT_I18NHDL(MSG_DESC_SH_ADDR),
1205 /* MSG_INTL(MSG_HELP_SH_ADDR) */
1206 ELFEDIT_I18NHDL(MSG_HELP_SH_ADDR),
1207 opt_std, arg_sh_addr },
1208
1209 /* shdr:sh_addralign */
1210 { cmd_sh_addralign, cpl_1starg_sec, name_sh_addralign,
1211 /* MSG_INTL(MSG_DESC_SH_ADDRALIGN) */
1212 ELFEDIT_I18NHDL(MSG_DESC_SH_ADDRALIGN),
1213 /* MSG_INTL(MSG_HELP_SH_ADDRALIGN) */
1214 ELFEDIT_I18NHDL(MSG_HELP_SH_ADDRALIGN),
1215 opt_std, arg_sh_addralign },
1216
1217 /* shdr:sh_entsize */
1218 { cmd_sh_entsize, cpl_1starg_sec, name_sh_entsize,
1219 /* MSG_INTL(MSG_DESC_SH_ENTSIZE) */
1220 ELFEDIT_I18NHDL(MSG_DESC_SH_ENTSIZE),
1221 /* MSG_INTL(MSG_HELP_SH_ENTSIZE) */
1222 ELFEDIT_I18NHDL(MSG_HELP_SH_ENTSIZE),
1223 opt_std, arg_sh_entsize },
1224
1225 /* shdr:sh_flags */
1226 { cmd_sh_flags, cpl_sh_flags, name_sh_flags,
1227 /* MSG_INTL(MSG_DESC_SH_FLAGS) */
1228 ELFEDIT_I18NHDL(MSG_DESC_SH_FLAGS),
1229 /* MSG_INTL(MSG_HELP_SH_FLAGS) */
1230 ELFEDIT_I18NHDL(MSG_HELP_SH_FLAGS),
1231 opt_sh_flags, arg_sh_flags },
1232
1233 /* shdr:sh_info */
1234 { cmd_sh_info, cpl_sh_infolink, name_sh_info,
1235 /* MSG_INTL(MSG_DESC_SH_INFO) */
1236 ELFEDIT_I18NHDL(MSG_DESC_SH_INFO),
1237 /* MSG_INTL(MSG_HELP_SH_INFO) */
1238 ELFEDIT_I18NHDL(MSG_HELP_SH_INFO),
1239 opt_infolink, arg_sh_info },
1240
1241 /* shdr:sh_link */
1242 { cmd_sh_link, cpl_sh_infolink, name_sh_link,
1243 /* MSG_INTL(MSG_DESC_SH_LINK) */
1244 ELFEDIT_I18NHDL(MSG_DESC_SH_LINK),
1245 /* MSG_INTL(MSG_HELP_SH_LINK) */
1246 ELFEDIT_I18NHDL(MSG_HELP_SH_LINK),
1247 opt_infolink, arg_sh_link },
1248
1249 /* shdr:sh_name */
1250 { cmd_sh_name, cpl_1starg_sec, name_sh_name,
1251 /* MSG_INTL(MSG_DESC_SH_NAME) */
1252 ELFEDIT_I18NHDL(MSG_DESC_SH_NAME),
1253 /* MSG_INTL(MSG_HELP_SH_NAME) */
1254 ELFEDIT_I18NHDL(MSG_HELP_SH_NAME),
1255 opt_sh_name, arg_sh_name },
1256
1257 /* shdr:sh_offset */
1258 { cmd_sh_offset, cpl_1starg_sec, name_sh_offset,
1259 /* MSG_INTL(MSG_DESC_SH_OFFSET) */
1260 ELFEDIT_I18NHDL(MSG_DESC_SH_OFFSET),
1261 /* MSG_INTL(MSG_HELP_SH_OFFSET) */
1262 ELFEDIT_I18NHDL(MSG_HELP_SH_OFFSET),
1263 opt_std, arg_sh_offset },
1264
1265 /* shdr:sh_size */
1266 { cmd_sh_size, cpl_1starg_sec, name_sh_size,
1267 /* MSG_INTL(MSG_DESC_SH_SIZE) */
1268 ELFEDIT_I18NHDL(MSG_DESC_SH_SIZE),
1269 /* MSG_INTL(MSG_HELP_SH_SIZE) */
1270 ELFEDIT_I18NHDL(MSG_HELP_SH_SIZE),
1271 opt_std, arg_sh_size },
1272
1273 /* shdr:sh_type */
1274 { cmd_sh_type, cpl_sh_type, name_sh_type,
1275 /* MSG_INTL(MSG_DESC_SH_TYPE) */
1276 ELFEDIT_I18NHDL(MSG_DESC_SH_TYPE),
1277 /* MSG_INTL(MSG_HELP_SH_TYPE) */
1278 ELFEDIT_I18NHDL(MSG_HELP_SH_TYPE),
1279 opt_std, arg_sh_type },
1280
1281 { NULL }
1282 };
1283
1284 static elfedit_module_t module = {
1285 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
1286 /* MSG_INTL(MSG_MOD_DESC) */
1287 ELFEDIT_I18NHDL(MSG_MOD_DESC),
1288 cmds, mod_i18nhdl_to_str };
1289
1290 return (&module);
1291 }
1292