1ad212f6fSab196087 /*
2ad212f6fSab196087 * CDDL HEADER START
3ad212f6fSab196087 *
4ad212f6fSab196087 * The contents of this file are subject to the terms of the
5ad212f6fSab196087 * Common Development and Distribution License (the "License").
6ad212f6fSab196087 * You may not use this file except in compliance with the License.
7ad212f6fSab196087 *
8ad212f6fSab196087 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9ad212f6fSab196087 * or http://www.opensolaris.org/os/licensing.
10ad212f6fSab196087 * See the License for the specific language governing permissions
11ad212f6fSab196087 * and limitations under the License.
12ad212f6fSab196087 *
13ad212f6fSab196087 * When distributing Covered Code, include this CDDL HEADER in each
14ad212f6fSab196087 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15ad212f6fSab196087 * If applicable, add the following below this CDDL HEADER, with the
16ad212f6fSab196087 * fields enclosed by brackets "[]" replaced with your own identifying
17ad212f6fSab196087 * information: Portions Copyright [yyyy] [name of copyright owner]
18ad212f6fSab196087 *
19ad212f6fSab196087 * CDDL HEADER END
20ad212f6fSab196087 */
21ad212f6fSab196087
22ad212f6fSab196087 /*
23*4f680cc6SAli Bahrami * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24ad212f6fSab196087 * Use is subject to license terms.
25ad212f6fSab196087 */
26ad212f6fSab196087
27ad212f6fSab196087 #include <stdio.h>
28ad212f6fSab196087 #include <ctype.h>
29ad212f6fSab196087 #include <unistd.h>
30ad212f6fSab196087 #include <elfedit.h>
31ad212f6fSab196087 #include <strings.h>
32ad212f6fSab196087 #include <debug.h>
33ad212f6fSab196087 #include <conv.h>
34ad212f6fSab196087 #include <str_msg.h>
35ad212f6fSab196087
36ad212f6fSab196087
37ad212f6fSab196087
38ad212f6fSab196087
39ad212f6fSab196087 #define MAXNDXSIZE 10
40ad212f6fSab196087
41ad212f6fSab196087
42ad212f6fSab196087
43ad212f6fSab196087 /*
44ad212f6fSab196087 * This module uses shared code for several of the commands.
45ad212f6fSab196087 * It is sometimes necessary to know which specific command
46ad212f6fSab196087 * is active.
47ad212f6fSab196087 */
48ad212f6fSab196087 typedef enum {
49ad212f6fSab196087 STR_CMD_T_DUMP = 0, /* str:dump */
50ad212f6fSab196087 STR_CMD_T_SET = 1, /* str:set */
51ad212f6fSab196087 STR_CMD_T_ADD = 2, /* str:add */
52ad212f6fSab196087 STR_CMD_T_ZERO = 3, /* str:zero */
53ad212f6fSab196087 } STR_CMD_T;
54ad212f6fSab196087
55ad212f6fSab196087
56ad212f6fSab196087
57ad212f6fSab196087 #ifndef _ELF64
58ad212f6fSab196087 /*
59ad212f6fSab196087 * We supply this function for the msg module. Only one copy is needed.
60ad212f6fSab196087 */
61ad212f6fSab196087 const char *
_str_msg(Msg mid)62ad212f6fSab196087 _str_msg(Msg mid)
63ad212f6fSab196087 {
64ad212f6fSab196087 return (gettext(MSG_ORIG(mid)));
65ad212f6fSab196087 }
66ad212f6fSab196087
67ad212f6fSab196087 #endif
68ad212f6fSab196087
69ad212f6fSab196087
70ad212f6fSab196087
71ad212f6fSab196087 /*
72ad212f6fSab196087 * This function is supplied to elfedit through our elfedit_module_t
73ad212f6fSab196087 * definition. It translates the opaque elfedit_i18nhdl_t handles
74ad212f6fSab196087 * in our module interface into the actual strings for elfedit to
75ad212f6fSab196087 * use.
76ad212f6fSab196087 *
77ad212f6fSab196087 * note:
78ad212f6fSab196087 * This module uses Msg codes for its i18n handle type.
79ad212f6fSab196087 * So the translation is simply to use MSG_INTL() to turn
80ad212f6fSab196087 * it into a string and return it.
81ad212f6fSab196087 */
82ad212f6fSab196087 static const char *
mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)83ad212f6fSab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
84ad212f6fSab196087 {
85ad212f6fSab196087 Msg msg = (Msg)hdl;
86ad212f6fSab196087
87ad212f6fSab196087 return (MSG_INTL(msg));
88ad212f6fSab196087 }
89ad212f6fSab196087
90ad212f6fSab196087
91ad212f6fSab196087
92ad212f6fSab196087 /*
93ad212f6fSab196087 * The sym_opt_t enum specifies a bit value for every optional
94ad212f6fSab196087 * argument allowed by a command in this module.
95ad212f6fSab196087 */
96ad212f6fSab196087 typedef enum {
97cce0e03bSab196087 STR_OPT_F_ANY = 1, /* -any: treat any sec. as strtab */
98cce0e03bSab196087 STR_OPT_F_END = 2, /* -end: zero to end of strtab */
99cce0e03bSab196087 STR_OPT_F_NOTERM = 4, /* -noterm: str:set won't term string */
100cce0e03bSab196087 STR_OPT_F_SHNAME = 8, /* -shnam name: section spec. by name */
101cce0e03bSab196087 STR_OPT_F_SHNDX = 16, /* -shndx ndx: strtab spec. by index */
102cce0e03bSab196087 STR_OPT_F_SHTYP = 32, /* -shtyp type: section spec. by type */
103cce0e03bSab196087 STR_OPT_F_STRNDX = 64, /* -strndx: String specified by index */
104ad212f6fSab196087 } str_opt_t;
105ad212f6fSab196087
106ad212f6fSab196087
107ad212f6fSab196087 /*
108ad212f6fSab196087 * A variable of type ARGSTATE is used by each command to maintain
109ad212f6fSab196087 * information about the string table section being used, and for any
110ad212f6fSab196087 * auxiliary sections that are related to it.
111ad212f6fSab196087 */
112ad212f6fSab196087 typedef struct {
113ad212f6fSab196087 elfedit_obj_state_t *obj_state;
114ad212f6fSab196087 str_opt_t optmask; /* Mask of options used */
115ad212f6fSab196087 int argc; /* # of plain arguments */
116ad212f6fSab196087 const char **argv; /* Plain arguments */
117ad212f6fSab196087
118ad212f6fSab196087 struct { /* String table */
119ad212f6fSab196087 elfedit_section_t *sec;
120ad212f6fSab196087 Word ndx; /* Table offset if (argc > 0) */
121ad212f6fSab196087 } str;
122ad212f6fSab196087 struct { /* Dynamic section */
123ad212f6fSab196087 elfedit_section_t *sec;
124ad212f6fSab196087 Dyn *data;
125ad212f6fSab196087 Word n;
126ad212f6fSab196087 elfedit_dyn_elt_t strpad;
127ad212f6fSab196087 } dyn;
128ad212f6fSab196087 } ARGSTATE;
129ad212f6fSab196087
130ad212f6fSab196087
131ad212f6fSab196087
132ad212f6fSab196087 /*
133cce0e03bSab196087 * Given an ELF SHT_ section type constant, shndx_to_strtab() returns
134ad212f6fSab196087 * one of the following
135ad212f6fSab196087 */
136ad212f6fSab196087
137ad212f6fSab196087 typedef enum {
138ad212f6fSab196087 SHTOSTR_NONE = 0, /* Type can't lead to a string table */
139ad212f6fSab196087 SHTOSTR_STRTAB = 1, /* type is SHT_STRTAB */
140ad212f6fSab196087 SHTOSTR_LINK_STRTAB = 2, /* sh_link for type yields strtab */
141ad212f6fSab196087 SHTOSTR_LINK_SYMTAB = 3, /* sh_link for type yields symtab */
14255ef6355Sab196087 SHTOSTR_SHF_STRINGS = 4, /* Not strtab, but SHF_STRINGS set */
143ad212f6fSab196087 } SHTOSTR_T;
144ad212f6fSab196087
14555ef6355Sab196087 static SHTOSTR_T
shtype_to_strtab(Word sh_type,Word sh_flags)14655ef6355Sab196087 shtype_to_strtab(Word sh_type, Word sh_flags)
147ad212f6fSab196087 {
14855ef6355Sab196087 /*
14955ef6355Sab196087 * A string table section always leads to itself. A
15055ef6355Sab196087 * non-string table that has it's SHF_STRINGS section flag
15155ef6355Sab196087 * set trumps anything else.
15255ef6355Sab196087 */
15355ef6355Sab196087 if (sh_type == SHT_STRTAB)
154ad212f6fSab196087 return (SHTOSTR_STRTAB);
15555ef6355Sab196087 if (sh_flags & SHF_STRINGS)
15655ef6355Sab196087 return (SHTOSTR_SHF_STRINGS);
157ad212f6fSab196087
15855ef6355Sab196087 /*
15955ef6355Sab196087 * Look at non-stringtable section types that can lead to
16055ef6355Sab196087 * string tables via sh_link.
16155ef6355Sab196087 */
16255ef6355Sab196087 switch (sh_type) {
163ad212f6fSab196087 /* These sections reference a string table via sh_link */
164ad212f6fSab196087 case SHT_DYNAMIC:
165ad212f6fSab196087 case SHT_SYMTAB:
166ad212f6fSab196087 case SHT_DYNSYM:
167ad212f6fSab196087 case SHT_SUNW_LDYNSYM:
168ad212f6fSab196087 case SHT_SUNW_verdef:
169ad212f6fSab196087 case SHT_SUNW_verneed:
170ad212f6fSab196087 return (SHTOSTR_LINK_STRTAB);
171ad212f6fSab196087
172ad212f6fSab196087 /*
173ad212f6fSab196087 * These sections reference a symbol table via sh_link.
174ad212f6fSab196087 * Symbol tables, in turn, reference a string table
175ad212f6fSab196087 * via their sh_link.
176ad212f6fSab196087 */
177ad212f6fSab196087 case SHT_HASH:
178ad212f6fSab196087 case SHT_REL:
179ad212f6fSab196087 case SHT_RELA:
180ad212f6fSab196087 case SHT_GROUP:
181ad212f6fSab196087 case SHT_SYMTAB_SHNDX:
182ad212f6fSab196087 case SHT_SUNW_move:
183ad212f6fSab196087 case SHT_SUNW_syminfo:
184ad212f6fSab196087 case SHT_SUNW_versym:
185ad212f6fSab196087 case SHT_SUNW_symsort:
186ad212f6fSab196087 case SHT_SUNW_tlssort:
187ad212f6fSab196087 return (SHTOSTR_LINK_SYMTAB);
188ad212f6fSab196087 }
189ad212f6fSab196087
190ad212f6fSab196087 /* Types that lead to string tables were caught above */
191ad212f6fSab196087 return (SHTOSTR_NONE);
192ad212f6fSab196087 }
193ad212f6fSab196087
194ad212f6fSab196087 /*
195ad212f6fSab196087 * Given a section index, attempt to convert it into an index
196ad212f6fSab196087 * to a string table section.
197ad212f6fSab196087 */
198ad212f6fSab196087 static Word
shndx_to_strtab(elfedit_obj_state_t * obj_state,Word ndx)199ad212f6fSab196087 shndx_to_strtab(elfedit_obj_state_t *obj_state, Word ndx)
200ad212f6fSab196087 {
201ad212f6fSab196087 /*
202ad212f6fSab196087 * Locate and validate the string table. In the case where
203ad212f6fSab196087 * a non-string table section is given that references a string
204ad212f6fSab196087 * table, we will use the referenced table.
205ad212f6fSab196087 */
206ad212f6fSab196087 if (ndx < obj_state->os_shnum) {
20755ef6355Sab196087 Shdr *shdr = obj_state->os_secarr[ndx].sec_shdr;
20855ef6355Sab196087
20955ef6355Sab196087 switch (shtype_to_strtab(shdr->sh_type, shdr->sh_flags)) {
210ad212f6fSab196087
211ad212f6fSab196087 /* Sections that reference a string table via sh_link */
212ad212f6fSab196087 case SHTOSTR_LINK_STRTAB:
21355ef6355Sab196087 ndx = shdr->sh_link;
214ad212f6fSab196087 break;
215ad212f6fSab196087
216ad212f6fSab196087 /*
217ad212f6fSab196087 * Sections that reference a symbol tabel via sh_link,
218ad212f6fSab196087 * which in turn reference a string table via their sh_link.
219ad212f6fSab196087 */
220ad212f6fSab196087 case SHTOSTR_LINK_SYMTAB:
22155ef6355Sab196087 ndx = shdr->sh_link;
222ad212f6fSab196087 if (ndx < obj_state->os_shnum)
223ad212f6fSab196087 ndx =
224ad212f6fSab196087 obj_state->os_secarr[ndx].sec_shdr->sh_link;
225ad212f6fSab196087 break;
226ad212f6fSab196087 }
227ad212f6fSab196087 }
228ad212f6fSab196087
229ad212f6fSab196087 return (ndx);
230ad212f6fSab196087 }
231ad212f6fSab196087
232ad212f6fSab196087
233ad212f6fSab196087
234ad212f6fSab196087 /*
235ad212f6fSab196087 * Standard argument processing for string table module
236ad212f6fSab196087 *
237ad212f6fSab196087 * entry
238ad212f6fSab196087 * obj_state, argc, argv - Standard command arguments
239ad212f6fSab196087 * optmask - Mask of allowed optional arguments.
240ad212f6fSab196087 * argstate - Address of ARGSTATE block to be initialized
241ad212f6fSab196087 *
242ad212f6fSab196087 * exit:
243ad212f6fSab196087 * On success, *argstate is initialized. On error,
244ad212f6fSab196087 * an error is issued and this routine does not return.
245ad212f6fSab196087 */
246ad212f6fSab196087 static void
process_args(elfedit_obj_state_t * obj_state,int argc,const char * argv[],STR_CMD_T cmd,ARGSTATE * argstate,int * print_only)247ad212f6fSab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
248ad212f6fSab196087 STR_CMD_T cmd, ARGSTATE *argstate, int *print_only)
249ad212f6fSab196087 {
250ad212f6fSab196087 elfedit_getopt_state_t getopt_state;
251ad212f6fSab196087 elfedit_getopt_ret_t *getopt_ret;
252ad212f6fSab196087 Word ndx;
253ad212f6fSab196087 int argc_ok;
254ad212f6fSab196087
255ad212f6fSab196087 bzero(argstate, sizeof (*argstate));
256ad212f6fSab196087 argstate->obj_state = obj_state;
257ad212f6fSab196087
258ad212f6fSab196087 /*
259ad212f6fSab196087 * By default, we use the section name string table pointed at
260ad212f6fSab196087 * by the ELF header.
261ad212f6fSab196087 */
262ad212f6fSab196087 ndx = obj_state->os_ehdr->e_shstrndx;
263ad212f6fSab196087
264ad212f6fSab196087 elfedit_getopt_init(&getopt_state, &argc, &argv);
265ad212f6fSab196087
266ad212f6fSab196087 /* Add each new option to the options mask */
267ad212f6fSab196087 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
268ad212f6fSab196087 argstate->optmask |= getopt_ret->gor_idmask;
269ad212f6fSab196087
270ad212f6fSab196087 switch (getopt_ret->gor_idmask) {
271ad212f6fSab196087 case STR_OPT_F_SHNAME: /* -shnam name */
272ad212f6fSab196087 ndx = elfedit_name_to_shndx(obj_state,
273ad212f6fSab196087 getopt_ret->gor_value);
274ad212f6fSab196087 break;
275ad212f6fSab196087
276ad212f6fSab196087 case STR_OPT_F_SHNDX: /* -shndx index */
277ad212f6fSab196087 ndx = elfedit_atoui(getopt_ret->gor_value, NULL);
278ad212f6fSab196087 break;
279ad212f6fSab196087
280ad212f6fSab196087 case STR_OPT_F_SHTYP: /* -shtyp type */
281ad212f6fSab196087 ndx = elfedit_type_to_shndx(obj_state,
282ad212f6fSab196087 elfedit_atoconst(getopt_ret->gor_value,
283ad212f6fSab196087 ELFEDIT_CONST_SHT));
284ad212f6fSab196087 break;
285ad212f6fSab196087 }
286ad212f6fSab196087 }
287ad212f6fSab196087
288ad212f6fSab196087 /*
289ad212f6fSab196087 * Usage error if there are the wrong number of plain arguments.
290ad212f6fSab196087 */
291ad212f6fSab196087 switch (cmd) {
292ad212f6fSab196087 case STR_CMD_T_DUMP:
293ad212f6fSab196087 argc_ok = (argc == 0) || (argc == 1);
294ad212f6fSab196087 *print_only = 1;
295ad212f6fSab196087 break;
296ad212f6fSab196087 case STR_CMD_T_SET:
297ad212f6fSab196087 argc_ok = (argc == 1) || (argc == 2);
298ad212f6fSab196087 *print_only = (argc == 1);
299ad212f6fSab196087 break;
300ad212f6fSab196087 case STR_CMD_T_ADD:
301ad212f6fSab196087 argc_ok = (argc == 1);
302ad212f6fSab196087 *print_only = 0;
303ad212f6fSab196087 break;
304ad212f6fSab196087 case STR_CMD_T_ZERO:
305ad212f6fSab196087 /*
306ad212f6fSab196087 * The second argument (count) and the -end option are
307ad212f6fSab196087 * mutally exclusive.
308ad212f6fSab196087 */
309ad212f6fSab196087 argc_ok = ((argc == 1) || (argc == 2)) &&
310ad212f6fSab196087 !((argc == 2) && (argstate->optmask & STR_OPT_F_END));
311ad212f6fSab196087 *print_only = 0;
312ad212f6fSab196087 break;
313ad212f6fSab196087 default:
314ad212f6fSab196087 argc_ok = 0; /* Unknown command? */
315ad212f6fSab196087 break;
316ad212f6fSab196087 }
317ad212f6fSab196087 if (!argc_ok)
318ad212f6fSab196087 elfedit_command_usage();
319ad212f6fSab196087
320ad212f6fSab196087 /* If there may be an arbitrary amount of output, use a pager */
321ad212f6fSab196087 if (argc == 0)
322ad212f6fSab196087 elfedit_pager_init();
323ad212f6fSab196087
324ad212f6fSab196087 /* Return the updated values of argc/argv */
325ad212f6fSab196087 argstate->argc = argc;
326ad212f6fSab196087 argstate->argv = argv;
327ad212f6fSab196087
328cce0e03bSab196087 if (argstate->optmask & STR_OPT_F_ANY) {
329cce0e03bSab196087 /* Take the arbitrary section */
330cce0e03bSab196087 argstate->str.sec = elfedit_sec_get(obj_state, ndx);
331cce0e03bSab196087
332cce0e03bSab196087 } else {
333ad212f6fSab196087 /*
334ad212f6fSab196087 * Locate and validate the string table. In the case where
335ad212f6fSab196087 * a non-string table section is given that references a string
336ad212f6fSab196087 * table, we will use the referenced table.
337ad212f6fSab196087 */
338ad212f6fSab196087 ndx = shndx_to_strtab(obj_state, ndx);
339ad212f6fSab196087
340ad212f6fSab196087 /*
341ad212f6fSab196087 * If ndx is a string table, the following will issue the
342ad212f6fSab196087 * proper debug messages. If it is out of range, or of any
343ad212f6fSab196087 * other type, an error is issued and it doesn't return.
344ad212f6fSab196087 */
34555ef6355Sab196087 argstate->str.sec = elfedit_sec_getstr(obj_state, ndx, 1);
346cce0e03bSab196087 }
347ad212f6fSab196087
348ad212f6fSab196087 /*
349ad212f6fSab196087 * If there is a dynamic section, check its sh_link to the
350ad212f6fSab196087 * string table index. If these match, then we have the
351ad212f6fSab196087 * dynamic string table. In that case, fetch the dynamic
352ad212f6fSab196087 * section and locate the DT_SUNW_STRPAD entry, causing
353ad212f6fSab196087 * debug messages to be issued.
354ad212f6fSab196087 */
355ad212f6fSab196087 argstate->dyn.sec = NULL;
356ad212f6fSab196087 elfedit_dyn_elt_init(&argstate->dyn.strpad);
357ad212f6fSab196087 if (obj_state->os_dynndx != SHN_UNDEF) {
358ad212f6fSab196087 elfedit_section_t *dynsec =
359ad212f6fSab196087 &obj_state->os_secarr[obj_state->os_dynndx];
360ad212f6fSab196087
361ad212f6fSab196087 if ((dynsec->sec_shdr->sh_type == SHT_DYNAMIC) &&
362ad212f6fSab196087 (argstate->str.sec->sec_shndx ==
363ad212f6fSab196087 dynsec->sec_shdr->sh_link)) {
364ad212f6fSab196087 argstate->dyn.sec = elfedit_sec_getdyn(obj_state,
365ad212f6fSab196087 &argstate->dyn.data, &argstate->dyn.n);
366*4f680cc6SAli Bahrami (void) elfedit_dynstr_getpad(obj_state, dynsec,
367ad212f6fSab196087 &argstate->dyn.strpad);
368ad212f6fSab196087
369ad212f6fSab196087 /*
370ad212f6fSab196087 * Does the pad value make sense?
371ad212f6fSab196087 * Issue debug message and ignore it if not.
372ad212f6fSab196087 */
373ad212f6fSab196087 if ((argstate->dyn.strpad.dn_seen != 0) &&
374ad212f6fSab196087 (argstate->dyn.strpad.dn_dyn.d_un.d_val >
375ad212f6fSab196087 argstate->str.sec->sec_data->d_size)) {
376ad212f6fSab196087 argstate->dyn.strpad.dn_seen = 0;
377ad212f6fSab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
378ad212f6fSab196087 MSG_INTL(MSG_DEBUG_BADSTRPAD),
379ad212f6fSab196087 EC_WORD(argstate->str.sec->sec_shndx),
380ad212f6fSab196087 argstate->str.sec->sec_name,
381ad212f6fSab196087 EC_XWORD(argstate->dyn.strpad.dn_dyn.
382ad212f6fSab196087 d_un.d_val),
383ad212f6fSab196087 EC_XWORD(argstate->str.sec->
384ad212f6fSab196087 sec_data->d_size));
385ad212f6fSab196087
386ad212f6fSab196087 }
387ad212f6fSab196087 }
388ad212f6fSab196087 }
389ad212f6fSab196087
390ad212f6fSab196087 /* Locate the string table offset if argument is present */
391ad212f6fSab196087 if ((argc > 0) && (cmd != STR_CMD_T_ADD)) {
392ad212f6fSab196087 /*
393ad212f6fSab196087 * If the -strndx option was specified, arg is an index
394ad212f6fSab196087 * into the string table. Otherwise it is a string
395ad212f6fSab196087 * to be looked up.
396ad212f6fSab196087 */
397ad212f6fSab196087 if (argstate->optmask & STR_OPT_F_STRNDX) {
398ad212f6fSab196087 argstate->str.ndx = (elfedit_atoui_range(argv[0],
399ad212f6fSab196087 MSG_ORIG(MSG_STR_STRING), 0,
400ad212f6fSab196087 argstate->str.sec->sec_data->d_size - 1, NULL));
401ad212f6fSab196087 } else {
402ad212f6fSab196087 if (elfedit_sec_findstr(argstate->str.sec, 0, argv[0],
403ad212f6fSab196087 &argstate->str.ndx) == 0)
404ad212f6fSab196087 elfedit_msg(ELFEDIT_MSG_ERR,
405ad212f6fSab196087 MSG_INTL(MSG_ERR_STRNOTFND),
406ad212f6fSab196087 EC_WORD(argstate->str.sec->sec_shndx),
407ad212f6fSab196087 argstate->str.sec->sec_name, argv[0]);
408ad212f6fSab196087 }
409ad212f6fSab196087 } else {
410ad212f6fSab196087 argstate->str.ndx = 0;
411ad212f6fSab196087 }
412ad212f6fSab196087 }
413ad212f6fSab196087
414ad212f6fSab196087
415ad212f6fSab196087
416ad212f6fSab196087 /*
417ad212f6fSab196087 * Print string table values, taking output style into account.
418ad212f6fSab196087 *
419ad212f6fSab196087 * entry:
420ad212f6fSab196087 * autoprint - If True, output is only produced if the elfedit
421ad212f6fSab196087 * autoprint flag is set. If False, output is always produced.
422ad212f6fSab196087 * argstate - State block for current symbol table.
423ad212f6fSab196087 */
424ad212f6fSab196087 static void
print_strtab(int autoprint,ARGSTATE * argstate)425ad212f6fSab196087 print_strtab(int autoprint, ARGSTATE *argstate)
426ad212f6fSab196087 {
427ad212f6fSab196087 char index[(MAXNDXSIZE * 2) + 4];
428ad212f6fSab196087 elfedit_outstyle_t outstyle;
429ad212f6fSab196087 const char *str, *limit, *tbl_limit;
430ad212f6fSab196087 Word ndx;
431ad212f6fSab196087
432ad212f6fSab196087
433ad212f6fSab196087 if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))
434ad212f6fSab196087 return;
435ad212f6fSab196087
436ad212f6fSab196087 outstyle = elfedit_outstyle();
437ad212f6fSab196087 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
438ad212f6fSab196087 elfedit_printf(MSG_INTL(MSG_FMT_STRTAB),
439ad212f6fSab196087 argstate->str.sec->sec_name);
440ad212f6fSab196087 if (argstate->dyn.strpad.dn_seen)
441ad212f6fSab196087 elfedit_printf(MSG_INTL(MSG_FMT_DYNSTRPAD),
442ad212f6fSab196087 EC_WORD(argstate->str.sec->sec_data->d_size -
443ad212f6fSab196087 argstate->dyn.strpad.dn_dyn.d_un.d_val),
444ad212f6fSab196087 EC_WORD(argstate->str.sec->sec_data->d_size - 1),
445ad212f6fSab196087 EC_WORD(argstate->dyn.strpad.dn_dyn.d_un.d_val));
446ad212f6fSab196087 elfedit_printf(MSG_INTL(MSG_FMT_DUMPTITLE));
447ad212f6fSab196087 }
448ad212f6fSab196087
449ad212f6fSab196087 str = argstate->str.sec->sec_data->d_buf;
450ad212f6fSab196087 tbl_limit = str + argstate->str.sec->sec_data->d_size;
451ad212f6fSab196087 ndx = argstate->str.ndx;
452ad212f6fSab196087 if (argstate->argc > 0) {
453ad212f6fSab196087 str += ndx;
454ad212f6fSab196087 /*
455ad212f6fSab196087 * If first byte is NULL and this is the default output style,
456ad212f6fSab196087 * then we want to display the range of NULL bytes, and we
457ad212f6fSab196087 * push limit out to the last one in the sequence. Otherwise,
458ad212f6fSab196087 * just display the string.
459ad212f6fSab196087 */
460ad212f6fSab196087 if ((*str == '\0') && (outstyle == ELFEDIT_OUTSTYLE_DEFAULT)) {
461ad212f6fSab196087 limit = str;
462ad212f6fSab196087 while (((limit + 1) < tbl_limit) &&
463ad212f6fSab196087 (*(limit + 1) == '\0'))
464ad212f6fSab196087 limit++;
465ad212f6fSab196087 } else {
466ad212f6fSab196087 limit = str + strlen(str) + 1;
467ad212f6fSab196087 }
468ad212f6fSab196087 } else {
469ad212f6fSab196087 /* Display the entire string table */
470ad212f6fSab196087 limit = tbl_limit;
471ad212f6fSab196087 }
472ad212f6fSab196087
473ad212f6fSab196087
474ad212f6fSab196087 while (str < limit) {
475ad212f6fSab196087 Word skip = strlen(str) + 1;
476ad212f6fSab196087 Word start_ndx;
477ad212f6fSab196087
478ad212f6fSab196087 if (outstyle != ELFEDIT_OUTSTYLE_DEFAULT) {
479ad212f6fSab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), str);
480ad212f6fSab196087 str += skip;
481ad212f6fSab196087 ndx += skip;
482ad212f6fSab196087 continue;
483ad212f6fSab196087 }
484ad212f6fSab196087
485ad212f6fSab196087 start_ndx = ndx;
486ad212f6fSab196087 if (*str == '\0')
487ad212f6fSab196087 while (((str + 1) < limit) && (*(str + 1) == '\0')) {
488ad212f6fSab196087 ndx++;
489ad212f6fSab196087 str++;
490ad212f6fSab196087 }
491ad212f6fSab196087
492ad212f6fSab196087 if (start_ndx != ndx) {
493ad212f6fSab196087 (void) snprintf(index, sizeof (index),
494ad212f6fSab196087 MSG_ORIG(MSG_FMT_INDEXRANGE),
495ad212f6fSab196087 EC_XWORD(start_ndx), EC_XWORD(ndx));
496ad212f6fSab196087 } else {
497ad212f6fSab196087 (void) snprintf(index, sizeof (index),
498ad212f6fSab196087 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(ndx));
499ad212f6fSab196087 }
500cce0e03bSab196087 elfedit_printf(MSG_ORIG(MSG_FMT_DUMPENTRY), index);
501cce0e03bSab196087 elfedit_write(MSG_ORIG(MSG_STR_DQUOTE), MSG_STR_DQUOTE_SIZE);
502cce0e03bSab196087 if (start_ndx == ndx)
503cce0e03bSab196087 elfedit_str_to_c_literal(str, elfedit_write);
504cce0e03bSab196087 elfedit_write(MSG_ORIG(MSG_STR_DQUOTENL),
505cce0e03bSab196087 MSG_STR_DQUOTENL_SIZE);
506ad212f6fSab196087 str += skip;
507ad212f6fSab196087 ndx += skip;
508ad212f6fSab196087 }
509ad212f6fSab196087 }
510ad212f6fSab196087
511ad212f6fSab196087
512ad212f6fSab196087 /*
513ad212f6fSab196087 * Command body for str:set, handling the case where the 3rd
514ad212f6fSab196087 * argument (new-str) is present.
515ad212f6fSab196087 */
516ad212f6fSab196087 static elfedit_cmdret_t
cmd_body_set(ARGSTATE * argstate)517ad212f6fSab196087 cmd_body_set(ARGSTATE *argstate)
518ad212f6fSab196087 {
519ad212f6fSab196087 elfedit_section_t *strsec = argstate->str.sec;
520ad212f6fSab196087 const char *newstr = argstate->argv[1];
521ad212f6fSab196087 Word ndx = argstate->str.ndx;
522ad212f6fSab196087 char *oldstr;
523ad212f6fSab196087 int i, len, ncp;
524ad212f6fSab196087
525ad212f6fSab196087 len = strlen(newstr);
526ad212f6fSab196087 ncp = len;
527ad212f6fSab196087 if (!(argstate->optmask & STR_OPT_F_NOTERM))
528ad212f6fSab196087 ncp++;
529ad212f6fSab196087
530ad212f6fSab196087 /* NULL string with no termination? Nothing to do */
531ad212f6fSab196087 if (ncp == 0)
532ad212f6fSab196087 return (ELFEDIT_CMDRET_NONE);
533ad212f6fSab196087
534ad212f6fSab196087 /* Does it fit? */
535ad212f6fSab196087 if ((ndx + ncp) > strsec->sec_data->d_size)
536ad212f6fSab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOFIT),
537ad212f6fSab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name,
538ad212f6fSab196087 EC_WORD(ndx), newstr);
539ad212f6fSab196087
540ad212f6fSab196087 /* Does it clobber the final NULL termination? */
541ad212f6fSab196087 if (((ndx + ncp) == strsec->sec_data->d_size) &&
542ad212f6fSab196087 (argstate->optmask & STR_OPT_F_NOTERM))
543ad212f6fSab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_FINALNULL),
544ad212f6fSab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name,
545ad212f6fSab196087 EC_WORD(ndx), newstr);
546ad212f6fSab196087
547ad212f6fSab196087 /*
548ad212f6fSab196087 * strtab[0] is always supposed to contain a NULL byte. You're not
549ad212f6fSab196087 * supposed to mess with it. We will carry out this operation,
550ad212f6fSab196087 * but with a debug message indicating that it is unorthodox.
551ad212f6fSab196087 */
552ad212f6fSab196087 if ((ndx == 0) && (*newstr != '\0'))
553ad212f6fSab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CHGSTR0),
554ad212f6fSab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name,
555ad212f6fSab196087 EC_WORD(ndx), newstr);
556ad212f6fSab196087
557ad212f6fSab196087 /* Does it alter the existing value? */
558ad212f6fSab196087 oldstr = ndx + (char *)strsec->sec_data->d_buf;
559ad212f6fSab196087 for (i = 0; i < ncp; i++)
560ad212f6fSab196087 if (newstr[i] != oldstr[i])
561ad212f6fSab196087 break;
562ad212f6fSab196087 if (i == ncp) { /* No change */
563ad212f6fSab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK),
564ad212f6fSab196087 strsec->sec_shndx, strsec->sec_name, ndx, newstr);
565ad212f6fSab196087 return (ELFEDIT_CMDRET_NONE);
566ad212f6fSab196087 }
567ad212f6fSab196087
568ad212f6fSab196087 /*
569ad212f6fSab196087 * If the new string is longer than the old one, then it will
570ad212f6fSab196087 * clobber the start of the following string. The resulting
571ad212f6fSab196087 * string table is perfectly legal, but issue a debug message
572ad212f6fSab196087 * letting the user know.
573ad212f6fSab196087 */
574ad212f6fSab196087 i = strlen(oldstr);
575ad212f6fSab196087 if (len > i)
576ad212f6fSab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_LONGSTR),
577ad212f6fSab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name,
578ad212f6fSab196087 EC_WORD(ndx), len, i);
579ad212f6fSab196087
580ad212f6fSab196087 /*
581ad212f6fSab196087 * If we have strayed into the reserved part of the dynstr, then
582ad212f6fSab196087 * update DT_SUNW_STRPAD.
583ad212f6fSab196087 */
584ad212f6fSab196087 if (argstate->dyn.strpad.dn_seen) {
585ad212f6fSab196087 elfedit_dyn_elt_t *strpad = &argstate->dyn.strpad;
586ad212f6fSab196087 Word new_pad_ndx = ndx + len + 1;
587ad212f6fSab196087 Word pad_ndx = argstate->str.sec->sec_data->d_size -
588ad212f6fSab196087 strpad->dn_dyn.d_un.d_val;
589ad212f6fSab196087
590ad212f6fSab196087 if (new_pad_ndx > pad_ndx) {
591ad212f6fSab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
592ad212f6fSab196087 MSG_INTL(MSG_DEBUG_ADDDYNSTR),
593ad212f6fSab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name,
594ad212f6fSab196087 EC_WORD(ndx), EC_WORD(new_pad_ndx - pad_ndx),
595ad212f6fSab196087 EC_WORD(strpad->dn_dyn.d_un.d_val),
596ad212f6fSab196087 newstr);
597ad212f6fSab196087
598ad212f6fSab196087 strpad->dn_dyn.d_un.d_val =
599ad212f6fSab196087 argstate->dyn.data[strpad->dn_ndx].d_un.d_val =
600ad212f6fSab196087 (argstate->str.sec->sec_data->d_size - new_pad_ndx);
601ad212f6fSab196087 elfedit_modified_data(argstate->dyn.sec);
602ad212f6fSab196087 }
603ad212f6fSab196087 }
604ad212f6fSab196087
605ad212f6fSab196087
606ad212f6fSab196087
607ad212f6fSab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG),
608ad212f6fSab196087 strsec->sec_shndx, strsec->sec_name, ndx, len, oldstr, newstr);
609ad212f6fSab196087 bcopy(newstr, oldstr, ncp);
610ad212f6fSab196087
611ad212f6fSab196087 return (ELFEDIT_CMDRET_MOD);
612ad212f6fSab196087 }
613ad212f6fSab196087
614ad212f6fSab196087
615ad212f6fSab196087 /*
616ad212f6fSab196087 * Command body for str:zero
617ad212f6fSab196087 */
618ad212f6fSab196087 static elfedit_cmdret_t
cmd_body_zero(ARGSTATE * argstate)619ad212f6fSab196087 cmd_body_zero(ARGSTATE *argstate)
620ad212f6fSab196087 {
621ad212f6fSab196087 elfedit_section_t *strsec = argstate->str.sec;
622ad212f6fSab196087 Word count;
623ad212f6fSab196087 Word ndx = argstate->str.ndx;
624ad212f6fSab196087 char *oldstr = ndx + (char *)strsec->sec_data->d_buf;
625ad212f6fSab196087 Word i;
626ad212f6fSab196087
627ad212f6fSab196087 /* How many bytes to zero? */
628ad212f6fSab196087 if (argstate->optmask & STR_OPT_F_END)
629ad212f6fSab196087 count = strsec->sec_data->d_size - argstate->str.ndx;
630ad212f6fSab196087 else if (argstate->argc == 2)
631ad212f6fSab196087 count = elfedit_atoui_range(argstate->argv[1],
632ad212f6fSab196087 MSG_ORIG(MSG_STR_COUNT), 0,
633ad212f6fSab196087 argstate->str.sec->sec_data->d_size - argstate->str.ndx,
634ad212f6fSab196087 NULL);
635ad212f6fSab196087 else
636ad212f6fSab196087 count = strlen(oldstr);
637ad212f6fSab196087
638ad212f6fSab196087 /* Does it alter the existing value? */
639ad212f6fSab196087 for (i = 0; i < count; i++)
640ad212f6fSab196087 if (oldstr[i] != '\0')
641ad212f6fSab196087 break;
642ad212f6fSab196087 if (i == count) { /* No change */
643ad212f6fSab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_Z_OK),
644ad212f6fSab196087 strsec->sec_shndx, strsec->sec_name, ndx);
645ad212f6fSab196087 return (ELFEDIT_CMDRET_NONE);
646ad212f6fSab196087 }
647ad212f6fSab196087
648ad212f6fSab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_Z_CHG),
649ad212f6fSab196087 strsec->sec_shndx, strsec->sec_name, ndx, count);
650ad212f6fSab196087 bzero(oldstr, count);
651ad212f6fSab196087
652ad212f6fSab196087 return (ELFEDIT_CMDRET_MOD);
653ad212f6fSab196087 }
654ad212f6fSab196087
655ad212f6fSab196087
656ad212f6fSab196087 /*
657ad212f6fSab196087 * Common body for the str: module commands.
658ad212f6fSab196087 *
659ad212f6fSab196087 * entry:
660ad212f6fSab196087 * cmd - One of the STR_CMD_T_* constants listed above, specifying
661ad212f6fSab196087 * which command to implement.
662ad212f6fSab196087 * obj_state, argc, argv - Standard command arguments
663ad212f6fSab196087 */
664ad212f6fSab196087 static elfedit_cmdret_t
cmd_body(STR_CMD_T cmd,elfedit_obj_state_t * obj_state,int argc,const char * argv[])665ad212f6fSab196087 cmd_body(STR_CMD_T cmd, elfedit_obj_state_t *obj_state,
666ad212f6fSab196087 int argc, const char *argv[])
667ad212f6fSab196087 {
668ad212f6fSab196087 ARGSTATE argstate;
669ad212f6fSab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE;
670ad212f6fSab196087 int print_only;
671ad212f6fSab196087
672ad212f6fSab196087 process_args(obj_state, argc, argv, cmd, &argstate, &print_only);
673ad212f6fSab196087
674ad212f6fSab196087 /*
675ad212f6fSab196087 * If this call call does not change data, display the current
676ad212f6fSab196087 * value(s) and return.
677ad212f6fSab196087 */
678ad212f6fSab196087 if (print_only) {
679ad212f6fSab196087 print_strtab(0, &argstate);
680ad212f6fSab196087 return (ELFEDIT_CMDRET_NONE);
681ad212f6fSab196087 }
682ad212f6fSab196087
683ad212f6fSab196087 switch (cmd) {
684ad212f6fSab196087 /* NOTE: STR_CMD_T_DUMP can't get here --- it's always print_only */
685ad212f6fSab196087
686ad212f6fSab196087 case STR_CMD_T_SET:
687ad212f6fSab196087 ret = cmd_body_set(&argstate);
688ad212f6fSab196087 break;
689ad212f6fSab196087
690ad212f6fSab196087 case STR_CMD_T_ADD:
691ad212f6fSab196087 argstate.str.ndx = elfedit_strtab_insert(obj_state,
692ad212f6fSab196087 argstate.str.sec, argstate.dyn.sec, argstate.argv[0]);
693ad212f6fSab196087 break;
694ad212f6fSab196087
695ad212f6fSab196087 case STR_CMD_T_ZERO:
696ad212f6fSab196087 ret = cmd_body_zero(&argstate);
697ad212f6fSab196087 break;
698ad212f6fSab196087 }
699ad212f6fSab196087
700ad212f6fSab196087 /*
701ad212f6fSab196087 * If we modified the strtab section, tell libelf.
702ad212f6fSab196087 */
703ad212f6fSab196087 if (ret == ELFEDIT_CMDRET_MOD)
704ad212f6fSab196087 elfedit_modified_data(argstate.str.sec);
705ad212f6fSab196087
706ad212f6fSab196087 /* Do autoprint */
707ad212f6fSab196087 print_strtab(1, &argstate);
708ad212f6fSab196087
709ad212f6fSab196087 return (ret);
710ad212f6fSab196087 }
711ad212f6fSab196087
712ad212f6fSab196087
713ad212f6fSab196087
714ad212f6fSab196087
715ad212f6fSab196087 /*
716ad212f6fSab196087 * Command completion functions for the various commands
717ad212f6fSab196087 */
718ad212f6fSab196087
719ad212f6fSab196087 static void
add_shtyp_match(Word sh_type,void * cpldata)720ad212f6fSab196087 add_shtyp_match(Word sh_type, void *cpldata)
721ad212f6fSab196087 {
722ad212f6fSab196087 char buf[128];
723ad212f6fSab196087 const char *s;
724ad212f6fSab196087 char *s2;
725ad212f6fSab196087
726ad212f6fSab196087 s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_SHT, sh_type, 0);
727ad212f6fSab196087 elfedit_cpl_match(cpldata, s, 1);
728ad212f6fSab196087
729ad212f6fSab196087 /*
730ad212f6fSab196087 * To get the informal tag names that are lowercase
731ad212f6fSab196087 * and lack the leading SHT_, we copy the string we
732ad212f6fSab196087 * have into a buffer and process it.
733ad212f6fSab196087 */
734ad212f6fSab196087 if (strlen(s) < 4)
735ad212f6fSab196087 return;
736ad212f6fSab196087 (void) strlcpy(buf, s + 4, sizeof (buf));
737ad212f6fSab196087 for (s2 = buf; *s2 != '\0'; s2++)
738ad212f6fSab196087 if (isupper(*s2))
739ad212f6fSab196087 *s2 = tolower(*s2);
740ad212f6fSab196087 elfedit_cpl_match(cpldata, buf, 1);
741ad212f6fSab196087 }
742ad212f6fSab196087
743ad212f6fSab196087 /*
744ad212f6fSab196087 * Handle filling in the values for -shnam, -shndx, and -shtyp options.
745ad212f6fSab196087 */
746ad212f6fSab196087 /*ARGSUSED*/
747ad212f6fSab196087 static void
cpl_sh_opt(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)748ad212f6fSab196087 cpl_sh_opt(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
749ad212f6fSab196087 const char *argv[], int num_opt)
750ad212f6fSab196087 {
751ad212f6fSab196087 enum { NAME, INDEX, TYPE } op;
752ad212f6fSab196087 elfedit_section_t *sec;
753ad212f6fSab196087 Word ndx;
754ad212f6fSab196087
755ad212f6fSab196087 if ((argc != num_opt) || (argc < 2))
756ad212f6fSab196087 return;
757ad212f6fSab196087
758ad212f6fSab196087 if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNAM)) == 0) {
759ad212f6fSab196087 op = NAME;
760ad212f6fSab196087 } else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0) {
761ad212f6fSab196087 op = INDEX;
762ad212f6fSab196087
763ad212f6fSab196087 } else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0) {
764ad212f6fSab196087 op = TYPE;
765ad212f6fSab196087
766ad212f6fSab196087 if (obj_state == NULL) { /* No object available */
767ad212f6fSab196087 elfedit_atoui_sym_t *atoui_sym;
768ad212f6fSab196087
769ad212f6fSab196087 atoui_sym = elfedit_const_to_atoui(ELFEDIT_CONST_SHT);
770ad212f6fSab196087 for (; atoui_sym->sym_name != NULL; atoui_sym++)
77155ef6355Sab196087 if (shtype_to_strtab(atoui_sym->sym_value, 0) !=
772ad212f6fSab196087 SHTOSTR_NONE)
773ad212f6fSab196087 elfedit_cpl_match(cpldata,
774ad212f6fSab196087 atoui_sym->sym_name, 1);
775ad212f6fSab196087 }
776ad212f6fSab196087 } else {
777ad212f6fSab196087 return;
778ad212f6fSab196087 }
779ad212f6fSab196087
780ad212f6fSab196087 if (obj_state == NULL) /* No object available */
781ad212f6fSab196087 return;
782ad212f6fSab196087
783ad212f6fSab196087 /*
784ad212f6fSab196087 * Loop over the section headers and supply command completion
785ad212f6fSab196087 * for the items in the file that can yield a string table.
786ad212f6fSab196087 */
787ad212f6fSab196087 sec = obj_state->os_secarr;
788ad212f6fSab196087 for (ndx = 0; ndx < obj_state->os_shnum; ndx++, sec++) {
78955ef6355Sab196087 Shdr *shdr = sec->sec_shdr;
79055ef6355Sab196087 SHTOSTR_T shtostr_type;
791ad212f6fSab196087
79255ef6355Sab196087 shtostr_type = shtype_to_strtab(shdr->sh_type, shdr->sh_flags);
79355ef6355Sab196087 if (shtostr_type == SHTOSTR_NONE)
794ad212f6fSab196087 continue;
795ad212f6fSab196087
796ad212f6fSab196087 switch (op) {
797ad212f6fSab196087 case NAME:
798ad212f6fSab196087 elfedit_cpl_match(cpldata, sec->sec_name, 0);
799ad212f6fSab196087 break;
800ad212f6fSab196087 case INDEX:
80155ef6355Sab196087 elfedit_cpl_ndx(cpldata, sec->sec_shndx);
802ad212f6fSab196087 break;
803ad212f6fSab196087 case TYPE:
80455ef6355Sab196087 if (shtostr_type != SHTOSTR_SHF_STRINGS)
80555ef6355Sab196087 add_shtyp_match(shdr->sh_type, cpldata);
806ad212f6fSab196087 break;
807ad212f6fSab196087 }
808ad212f6fSab196087 }
809ad212f6fSab196087 }
810ad212f6fSab196087
811ad212f6fSab196087
812ad212f6fSab196087 /*
813ad212f6fSab196087 * Most of the commands accept an -shXXX option for the string table
814ad212f6fSab196087 * and a string first argument. This routine examines which argument
815ad212f6fSab196087 * is being processed, and supplies completion for these items.
816ad212f6fSab196087 */
817ad212f6fSab196087 static void
cpl_sec_str(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)818ad212f6fSab196087 cpl_sec_str(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
819ad212f6fSab196087 const char *argv[], int num_opt)
820ad212f6fSab196087 {
821ad212f6fSab196087 const char *str, *limit;
822ad212f6fSab196087 elfedit_section_t *sec;
823ad212f6fSab196087 Word strtab_ndx;
824ad212f6fSab196087 Word ndx;
825ad212f6fSab196087
826ad212f6fSab196087 /* Handle -shXXX options */
827ad212f6fSab196087 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt);
828ad212f6fSab196087
829ad212f6fSab196087 /* Without object state, there's no data to work from */
830ad212f6fSab196087 if (obj_state == NULL)
831ad212f6fSab196087 return;
832ad212f6fSab196087
833ad212f6fSab196087 /* If not first plain arg, return */
834ad212f6fSab196087 if (argc != (num_opt + 1))
835ad212f6fSab196087 return;
836ad212f6fSab196087
837ad212f6fSab196087 /*
838ad212f6fSab196087 * Look at the options, looking for two things:
839ad212f6fSab196087 * 1) A -shXXX option specifying a section. If so, turn that
840ad212f6fSab196087 * into a section index if possible.
841ad212f6fSab196087 * 2) Was -strndx used? If so, we are looking at an integer
842ad212f6fSab196087 * value and have nothing to complete.
843ad212f6fSab196087 */
844ad212f6fSab196087 strtab_ndx = obj_state->os_ehdr->e_shstrndx;
845ad212f6fSab196087 for (ndx = 0; ndx < num_opt; ndx++) {
846ad212f6fSab196087 if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_STRNDX)) == 0)
847ad212f6fSab196087 return;
848ad212f6fSab196087
849ad212f6fSab196087 if ((ndx+1) < num_opt) {
850ad212f6fSab196087 if (strcmp(argv[ndx],
851ad212f6fSab196087 MSG_ORIG(MSG_STR_MINUS_SHNAM)) == 0) {
852ad212f6fSab196087 Word i;
853ad212f6fSab196087
854ad212f6fSab196087 for (i = 1; i < obj_state->os_shnum; i++)
855ad212f6fSab196087 if (strcmp(obj_state->os_secarr[i].
856ad212f6fSab196087 sec_name, argv[ndx+1]) == 0) {
857ad212f6fSab196087 strtab_ndx = i;
858ad212f6fSab196087 break;
859ad212f6fSab196087 }
860ad212f6fSab196087 } else if (strcmp(argv[ndx],
861ad212f6fSab196087 MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0) {
862ad212f6fSab196087 elfedit_atoui_t val;
863ad212f6fSab196087
864ad212f6fSab196087 if (elfedit_atoui2(argv[ndx+1], NULL,
865ad212f6fSab196087 &val) != 0)
866ad212f6fSab196087 strtab_ndx = val;
867ad212f6fSab196087 } else if (strcmp(argv[ndx],
868ad212f6fSab196087 MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0) {
869ad212f6fSab196087 elfedit_atoui_t sh_type;
870ad212f6fSab196087 Word i;
871ad212f6fSab196087
872ad212f6fSab196087 if (elfedit_atoconst2(argv[ndx+1],
873ad212f6fSab196087 ELFEDIT_CONST_SHT, &sh_type) == 0)
874ad212f6fSab196087 continue;
875ad212f6fSab196087 for (i = 1; i < obj_state->os_shnum; i++)
876ad212f6fSab196087 if (obj_state->os_secarr[i].sec_shdr->
877ad212f6fSab196087 sh_type == sh_type) {
878ad212f6fSab196087 strtab_ndx = i;
879ad212f6fSab196087 break;
880ad212f6fSab196087 }
881ad212f6fSab196087 }
882ad212f6fSab196087 }
883ad212f6fSab196087 }
884ad212f6fSab196087
885ad212f6fSab196087 /*
886ad212f6fSab196087 * Locate and validate the string table. In the case where
887ad212f6fSab196087 * a non-string table section is given that references a string
888ad212f6fSab196087 * table, we will use the referenced table.
889ad212f6fSab196087 */
890ad212f6fSab196087 strtab_ndx = shndx_to_strtab(obj_state, strtab_ndx);
891ad212f6fSab196087 if ((strtab_ndx >= obj_state->os_shnum) ||
892ad212f6fSab196087 (obj_state->os_secarr[strtab_ndx].sec_shdr->sh_type != SHT_STRTAB))
893ad212f6fSab196087 return;
894ad212f6fSab196087 sec = &obj_state->os_secarr[strtab_ndx];
895ad212f6fSab196087
896ad212f6fSab196087 str = sec->sec_data->d_buf;
897ad212f6fSab196087 limit = str + sec->sec_data->d_size;
898ad212f6fSab196087 while (str < limit) {
899ad212f6fSab196087 if (*str != '\0')
900ad212f6fSab196087 elfedit_cpl_match(cpldata, str, 0);
901ad212f6fSab196087 str += strlen(str) + 1;
902ad212f6fSab196087 }
903ad212f6fSab196087 }
904ad212f6fSab196087
905ad212f6fSab196087
906ad212f6fSab196087
907ad212f6fSab196087 /*
908ad212f6fSab196087 * Implementation functions for the commands
909ad212f6fSab196087 */
910ad212f6fSab196087 static elfedit_cmdret_t
cmd_dump(elfedit_obj_state_t * obj_state,int argc,const char * argv[])911ad212f6fSab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
912ad212f6fSab196087 {
913ad212f6fSab196087 return (cmd_body(STR_CMD_T_DUMP, obj_state, argc, argv));
914ad212f6fSab196087 }
915ad212f6fSab196087
916ad212f6fSab196087 static elfedit_cmdret_t
cmd_set(elfedit_obj_state_t * obj_state,int argc,const char * argv[])917ad212f6fSab196087 cmd_set(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
918ad212f6fSab196087 {
919ad212f6fSab196087 return (cmd_body(STR_CMD_T_SET, obj_state, argc, argv));
920ad212f6fSab196087 }
921ad212f6fSab196087
922ad212f6fSab196087 static elfedit_cmdret_t
cmd_add(elfedit_obj_state_t * obj_state,int argc,const char * argv[])923ad212f6fSab196087 cmd_add(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
924ad212f6fSab196087 {
925ad212f6fSab196087 return (cmd_body(STR_CMD_T_ADD, obj_state, argc, argv));
926ad212f6fSab196087 }
927ad212f6fSab196087
928ad212f6fSab196087 static elfedit_cmdret_t
cmd_zero(elfedit_obj_state_t * obj_state,int argc,const char * argv[])929ad212f6fSab196087 cmd_zero(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
930ad212f6fSab196087 {
931ad212f6fSab196087 return (cmd_body(STR_CMD_T_ZERO, obj_state, argc, argv));
932ad212f6fSab196087 }
933ad212f6fSab196087
934ad212f6fSab196087
935ad212f6fSab196087
936ad212f6fSab196087 /*ARGSUSED*/
937ad212f6fSab196087 elfedit_module_t *
elfedit_init(elfedit_module_version_t version)938ad212f6fSab196087 elfedit_init(elfedit_module_version_t version)
939ad212f6fSab196087 {
940ad212f6fSab196087 /* str:dump */
941ad212f6fSab196087 static const char *name_dump[] = {
942ad212f6fSab196087 MSG_ORIG(MSG_CMD_DUMP),
943ad212f6fSab196087 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */
944ad212f6fSab196087 NULL
945ad212f6fSab196087 };
946ad212f6fSab196087 static elfedit_cmd_optarg_t opt_dump[] = {
947cce0e03bSab196087 { MSG_ORIG(MSG_STR_MINUS_ANY),
948cce0e03bSab196087 /* MSG_INTL(MSG_OPTDESC_ANY) */
949cce0e03bSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_ANY), 0,
950cce0e03bSab196087 STR_OPT_F_ANY, 0 },
951ad212f6fSab196087 { ELFEDIT_STDOA_OPT_O, NULL,
952ad212f6fSab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
953ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_SHNAM),
954ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_SHNAM) */
955ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
956ad212f6fSab196087 STR_OPT_F_SHNAME, STR_OPT_F_SHNDX | STR_OPT_F_SHTYP },
957ad212f6fSab196087 { MSG_ORIG(MSG_STR_NAME), NULL, 0 },
958ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_SHNDX),
959ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_SHNDX) */
960ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
961ad212f6fSab196087 STR_OPT_F_SHNDX, STR_OPT_F_SHNAME | STR_OPT_F_SHTYP },
962ad212f6fSab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 },
963ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_SHTYP),
964ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_SHTYP) */
965ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
966ad212f6fSab196087 STR_OPT_F_SHTYP, STR_OPT_F_SHNAME | STR_OPT_F_SHNDX },
967ad212f6fSab196087 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 },
968ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_STRNDX),
969ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_STRNDX) */
970ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_STRNDX), 0,
971ad212f6fSab196087 STR_OPT_F_STRNDX, 0 },
972ad212f6fSab196087 { NULL }
973ad212f6fSab196087 };
974ad212f6fSab196087 static elfedit_cmd_optarg_t arg_dump[] = {
975ad212f6fSab196087 { MSG_ORIG(MSG_STR_STRING),
976ad212f6fSab196087 /* MSG_INTL(MSG_A1_STRING) */
977ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_A1_STRING),
978ad212f6fSab196087 ELFEDIT_CMDOA_F_OPT },
979ad212f6fSab196087 { NULL }
980ad212f6fSab196087 };
981ad212f6fSab196087
982ad212f6fSab196087 /* str:set */
983ad212f6fSab196087 static const char *name_set[] = {
984ad212f6fSab196087 MSG_ORIG(MSG_CMD_SET), NULL };
985ad212f6fSab196087 static elfedit_cmd_optarg_t opt_set[] = {
986cce0e03bSab196087 { MSG_ORIG(MSG_STR_MINUS_ANY),
987cce0e03bSab196087 /* MSG_INTL(MSG_OPTDESC_ANY) */
988cce0e03bSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_ANY), 0,
989cce0e03bSab196087 STR_OPT_F_ANY, 0 },
990ad212f6fSab196087 { ELFEDIT_STDOA_OPT_O, NULL,
991ad212f6fSab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
992ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_NOTERM),
993ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_NOTERM) */
994ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_NOTERM), 0,
995ad212f6fSab196087 STR_OPT_F_NOTERM, 0 },
996ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_SHNAM),
997ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_SHNAM) */
998ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
999ad212f6fSab196087 STR_OPT_F_SHNAME, STR_OPT_F_SHNDX | STR_OPT_F_SHTYP },
1000ad212f6fSab196087 { MSG_ORIG(MSG_STR_NAME), NULL, 0 },
1001ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_SHNDX),
1002ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_SHNDX) */
1003ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
1004ad212f6fSab196087 STR_OPT_F_SHNDX, STR_OPT_F_SHNAME | STR_OPT_F_SHTYP },
1005ad212f6fSab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 },
1006ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_SHTYP),
1007ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_SHTYP) */
1008ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
1009ad212f6fSab196087 STR_OPT_F_SHTYP, STR_OPT_F_SHNAME | STR_OPT_F_SHNDX },
1010ad212f6fSab196087 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 },
1011ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_STRNDX),
1012ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_STRNDX) */
1013ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_STRNDX), 0,
1014ad212f6fSab196087 STR_OPT_F_STRNDX, 0 },
1015ad212f6fSab196087 { NULL }
1016ad212f6fSab196087 };
1017ad212f6fSab196087 static elfedit_cmd_optarg_t arg_set[] = {
1018ad212f6fSab196087 { MSG_ORIG(MSG_STR_STRING),
1019ad212f6fSab196087 /* MSG_INTL(MSG_A1_STRING) */
1020ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_A1_STRING),
1021ad212f6fSab196087 0 },
1022ad212f6fSab196087 { MSG_ORIG(MSG_STR_NEWSTRING),
1023ad212f6fSab196087 /* MSG_INTL(MSG_A2_NEWSTRING) */
1024ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_A2_NEWSTRING),
1025ad212f6fSab196087 ELFEDIT_CMDOA_F_OPT },
1026ad212f6fSab196087 { NULL }
1027ad212f6fSab196087 };
1028ad212f6fSab196087
1029ad212f6fSab196087 /* str:add */
1030ad212f6fSab196087 static const char *name_add[] = {
1031ad212f6fSab196087 MSG_ORIG(MSG_CMD_ADD), NULL };
1032ad212f6fSab196087 static elfedit_cmd_optarg_t opt_add[] = {
1033ad212f6fSab196087 { ELFEDIT_STDOA_OPT_O, NULL,
1034ad212f6fSab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1035ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_SHNAM),
1036ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_SHNAM) */
1037ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
1038ad212f6fSab196087 STR_OPT_F_SHNAME, STR_OPT_F_SHNDX | STR_OPT_F_SHTYP },
1039ad212f6fSab196087 { MSG_ORIG(MSG_STR_NAME), NULL, 0 },
1040ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_SHNDX),
1041ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_SHNDX) */
1042ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
1043ad212f6fSab196087 STR_OPT_F_SHNDX, STR_OPT_F_SHNAME | STR_OPT_F_SHTYP },
1044ad212f6fSab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 },
1045ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_SHTYP),
1046ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_SHTYP) */
1047ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
1048ad212f6fSab196087 STR_OPT_F_SHTYP, STR_OPT_F_SHNAME | STR_OPT_F_SHNDX },
1049ad212f6fSab196087 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 },
1050ad212f6fSab196087 { NULL }
1051ad212f6fSab196087 };
1052ad212f6fSab196087 static elfedit_cmd_optarg_t arg_add[] = {
1053ad212f6fSab196087 { MSG_ORIG(MSG_STR_NEWSTRING),
1054ad212f6fSab196087 /* MSG_INTL(MSG_A1_NEWSTRING) */
1055ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_A1_NEWSTRING),
1056ad212f6fSab196087 0 },
1057ad212f6fSab196087 { NULL }
1058ad212f6fSab196087 };
1059ad212f6fSab196087
1060ad212f6fSab196087 /* str:zero */
1061ad212f6fSab196087 static const char *name_zero[] = {
1062ad212f6fSab196087 MSG_ORIG(MSG_CMD_ZERO), NULL };
1063ad212f6fSab196087 static elfedit_cmd_optarg_t opt_zero[] = {
1064cce0e03bSab196087 { MSG_ORIG(MSG_STR_MINUS_ANY),
1065cce0e03bSab196087 /* MSG_INTL(MSG_OPTDESC_ANY) */
1066cce0e03bSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_ANY), 0,
1067cce0e03bSab196087 STR_OPT_F_ANY, 0 },
1068ad212f6fSab196087 { ELFEDIT_STDOA_OPT_O, NULL,
1069ad212f6fSab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1070ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_SHNAM),
1071ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_SHNAM) */
1072ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
1073ad212f6fSab196087 STR_OPT_F_SHNAME, STR_OPT_F_SHNDX | STR_OPT_F_SHTYP },
1074ad212f6fSab196087 { MSG_ORIG(MSG_STR_NAME), NULL, 0 },
1075ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_SHNDX),
1076ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_SHNDX) */
1077ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
1078ad212f6fSab196087 STR_OPT_F_SHNDX, STR_OPT_F_SHNAME | STR_OPT_F_SHTYP },
1079ad212f6fSab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 },
1080ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_SHTYP),
1081ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_SHTYP) */
1082ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
1083ad212f6fSab196087 STR_OPT_F_SHTYP, STR_OPT_F_SHNAME | STR_OPT_F_SHNDX },
1084ad212f6fSab196087 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 },
1085ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_STRNDX),
1086ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_STRNDX) */
1087ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_STRNDX), 0,
1088ad212f6fSab196087 STR_OPT_F_STRNDX, 0 },
1089ad212f6fSab196087 { MSG_ORIG(MSG_STR_MINUS_END),
1090ad212f6fSab196087 /* MSG_INTL(MSG_OPTDESC_END) */
1091ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_END), 0,
1092ad212f6fSab196087 STR_OPT_F_END, 0 },
1093ad212f6fSab196087 { NULL }
1094ad212f6fSab196087 };
1095ad212f6fSab196087 static elfedit_cmd_optarg_t arg_zero[] = {
1096ad212f6fSab196087 { MSG_ORIG(MSG_STR_STRING),
1097ad212f6fSab196087 /* MSG_INTL(MSG_A1_STRING) */
1098ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_A1_STRING),
1099ad212f6fSab196087 0 },
1100ad212f6fSab196087 { MSG_ORIG(MSG_STR_COUNT),
1101ad212f6fSab196087 /* MSG_INTL(MSG_A2_COUNT) */
1102ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_A2_COUNT),
1103ad212f6fSab196087 ELFEDIT_CMDOA_F_OPT },
1104ad212f6fSab196087 { NULL }
1105ad212f6fSab196087 };
1106ad212f6fSab196087
1107ad212f6fSab196087
1108ad212f6fSab196087 static elfedit_cmd_t cmds[] = {
1109ad212f6fSab196087 /* str:dump */
1110ad212f6fSab196087 { cmd_dump, cpl_sec_str, name_dump,
1111ad212f6fSab196087 /* MSG_INTL(MSG_DESC_DUMP) */
1112ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_DESC_DUMP),
1113ad212f6fSab196087 /* MSG_INTL(MSG_HELP_DUMP) */
1114ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_HELP_DUMP),
1115ad212f6fSab196087 opt_dump, arg_dump },
1116ad212f6fSab196087
1117ad212f6fSab196087 /* str:set */
1118ad212f6fSab196087 { cmd_set, cpl_sec_str, name_set,
1119ad212f6fSab196087 /* MSG_INTL(MSG_DESC_SET) */
1120ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_DESC_SET),
1121ad212f6fSab196087 /* MSG_INTL(MSG_HELP_SET) */
1122ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_HELP_SET),
1123ad212f6fSab196087 opt_set, arg_set },
1124ad212f6fSab196087
1125ad212f6fSab196087 /* str:add */
1126ad212f6fSab196087 { cmd_add, cpl_sh_opt, name_add,
1127ad212f6fSab196087 /* MSG_INTL(MSG_DESC_ADD) */
1128ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_DESC_ADD),
1129ad212f6fSab196087 /* MSG_INTL(MSG_HELP_ADD) */
1130ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_HELP_ADD),
1131ad212f6fSab196087 opt_add, arg_add },
1132ad212f6fSab196087
1133ad212f6fSab196087 /* str:zero */
1134ad212f6fSab196087 { cmd_zero, cpl_sec_str, name_zero,
1135ad212f6fSab196087 /* MSG_INTL(MSG_DESC_ZERO) */
1136ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_DESC_ZERO),
1137ad212f6fSab196087 /* MSG_INTL(MSG_HELP_ZERO) */
1138ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_HELP_ZERO),
1139ad212f6fSab196087 opt_zero, arg_zero },
1140ad212f6fSab196087
1141ad212f6fSab196087 { NULL }
1142ad212f6fSab196087 };
1143ad212f6fSab196087
1144ad212f6fSab196087 static elfedit_module_t module = {
1145ad212f6fSab196087 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
1146ad212f6fSab196087 /* MSG_INTL(MSG_MOD_DESC) */
1147ad212f6fSab196087 ELFEDIT_I18NHDL(MSG_MOD_DESC),
1148ad212f6fSab196087 cmds, mod_i18nhdl_to_str };
1149ad212f6fSab196087
1150ad212f6fSab196087 return (&module);
1151ad212f6fSab196087 }
1152