1d29b2c44Sab /*
2d29b2c44Sab * CDDL HEADER START
3d29b2c44Sab *
4d29b2c44Sab * The contents of this file are subject to the terms of the
5d29b2c44Sab * Common Development and Distribution License (the "License").
6d29b2c44Sab * You may not use this file except in compliance with the License.
7d29b2c44Sab *
8d29b2c44Sab * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d29b2c44Sab * or http://www.opensolaris.org/os/licensing.
10d29b2c44Sab * See the License for the specific language governing permissions
11d29b2c44Sab * and limitations under the License.
12d29b2c44Sab *
13d29b2c44Sab * When distributing Covered Code, include this CDDL HEADER in each
14d29b2c44Sab * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d29b2c44Sab * If applicable, add the following below this CDDL HEADER, with the
16d29b2c44Sab * fields enclosed by brackets "[]" replaced with your own identifying
17d29b2c44Sab * information: Portions Copyright [yyyy] [name of copyright owner]
18d29b2c44Sab *
19d29b2c44Sab * CDDL HEADER END
20d29b2c44Sab */
21d29b2c44Sab
22d29b2c44Sab /*
2308278a5eSRod Evans * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24d29b2c44Sab * Use is subject to license terms.
25d29b2c44Sab */
26d29b2c44Sab
27d29b2c44Sab #include <ctype.h>
28d29b2c44Sab #include <elfedit.h>
29d29b2c44Sab #include <sys/elf_SPARC.h>
30d29b2c44Sab #include <strings.h>
31d29b2c44Sab #include <debug.h>
32d29b2c44Sab #include <conv.h>
33d29b2c44Sab #include <dyn_msg.h>
34d29b2c44Sab
35d29b2c44Sab
36d29b2c44Sab /*
37d29b2c44Sab * Dynamic section
38d29b2c44Sab */
39d29b2c44Sab
40d29b2c44Sab /*
41d29b2c44Sab * This module uses shared code for several of the commands.
42d29b2c44Sab * It is sometimes necessary to know which specific command
43d29b2c44Sab * is active.
44d29b2c44Sab */
45d29b2c44Sab typedef enum {
46d29b2c44Sab /* Dump command, used as module default to display dynamic section */
47d29b2c44Sab DYN_CMD_T_DUMP = 0, /* dyn:dump */
48d29b2c44Sab
49d29b2c44Sab /* Commands that do not correspond directly to a specific DT tag */
50d29b2c44Sab DYN_CMD_T_TAG = 1, /* dyn:tag */
51d29b2c44Sab DYN_CMD_T_VALUE = 2, /* dyn:value */
52d29b2c44Sab DYN_CMD_T_DELETE = 3, /* dyn:delete */
53d29b2c44Sab DYN_CMD_T_MOVE = 4, /* dyn:shift */
54d29b2c44Sab
55d29b2c44Sab /* Commands that embody tag specific knowledge */
56d29b2c44Sab DYN_CMD_T_RUNPATH = 5, /* dyn:runpath/rpath */
57d29b2c44Sab DYN_CMD_T_POSFLAG1 = 6, /* dyn:posflag1 */
58d29b2c44Sab DYN_CMD_T_FLAGS = 7, /* dyn:flags */
59d29b2c44Sab DYN_CMD_T_FLAGS1 = 8, /* dyn:flags1 */
60d29b2c44Sab DYN_CMD_T_FEATURE1 = 9, /* dyn:feature1 */
61ba2be530Sab DYN_CMD_T_CHECKSUM = 10, /* dyn:checksum */
62ba2be530Sab DYN_CMD_T_SUNW_LDMACH = 11 /* dyn:sunw_ldmach */
63d29b2c44Sab } DYN_CMD_T;
64d29b2c44Sab
65d29b2c44Sab
66d29b2c44Sab
67d29b2c44Sab #ifndef _ELF64
68d29b2c44Sab /*
69d29b2c44Sab * We supply this function for the msg module
70d29b2c44Sab */
71d29b2c44Sab const char *
_dyn_msg(Msg mid)72d29b2c44Sab _dyn_msg(Msg mid)
73d29b2c44Sab {
74d29b2c44Sab return (gettext(MSG_ORIG(mid)));
75d29b2c44Sab }
76d29b2c44Sab #endif
77d29b2c44Sab
78d29b2c44Sab
79d29b2c44Sab /*
80d29b2c44Sab * This function is supplied to elfedit through our elfedit_module_t
81d29b2c44Sab * definition. It translates the opaque elfedit_i18nhdl_t handles
82d29b2c44Sab * in our module interface into the actual strings for elfedit to
83d29b2c44Sab * use.
84d29b2c44Sab *
85d29b2c44Sab * note:
86d29b2c44Sab * This module uses Msg codes for its i18n handle type.
87d29b2c44Sab * So the translation is simply to use MSG_INTL() to turn
88d29b2c44Sab * it into a string and return it.
89d29b2c44Sab */
90d29b2c44Sab static const char *
mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)91d29b2c44Sab mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
92d29b2c44Sab {
93d29b2c44Sab Msg msg = (Msg)hdl;
94d29b2c44Sab
95d29b2c44Sab return (MSG_INTL(msg));
96d29b2c44Sab }
97d29b2c44Sab
98d29b2c44Sab
99d29b2c44Sab
100d29b2c44Sab /*
101d29b2c44Sab * The dyn_opt_t enum specifies a bit value for every optional
102d29b2c44Sab * argument allowed by a command in this module.
103d29b2c44Sab */
104d29b2c44Sab typedef enum {
105d29b2c44Sab DYN_OPT_F_ADD = 1, /* -add: Add new elt rather than */
106d29b2c44Sab /* modifying an existing one */
107d29b2c44Sab DYN_OPT_F_AND = 2, /* -and: AND (&) values to dest */
108d29b2c44Sab DYN_OPT_F_CMP = 4, /* -cmp: Complement (~) values */
10955ef6355Sab DYN_OPT_F_DYNNDX_ELT = 8, /* -dynndx: 1st plain arg is tag */
11055ef6355Sab /* index, not name */
11155ef6355Sab DYN_OPT_F_DYNNDX_VAL = 16, /* -dynndx ndx: Index is value to */
11255ef6355Sab /* option rather than 1st plain */
11355ef6355Sab /* arg. Used for dyn:posflag1 */
11455ef6355Sab DYN_OPT_F_NEEDED = 32, /* -needed str: Locate DT_POSFLAG_1 */
11555ef6355Sab /* relative to DT_NEEDED element */
11655ef6355Sab DYN_OPT_F_OR = 64, /* -or: OR (|) values to dest */
11755ef6355Sab DYN_OPT_F_STRVAL = 128 /* -s: value is string, not integer */
118d29b2c44Sab } dyn_opt_t;
119d29b2c44Sab
120d29b2c44Sab
121d29b2c44Sab /*
122d29b2c44Sab * A variable of type ARGSTATE is used by each command to maintain
123d29b2c44Sab * information about the arguments and related things. It is
124d29b2c44Sab * initialized by process_args(), and used by the other routines.
125d29b2c44Sab */
126d29b2c44Sab typedef struct {
127d29b2c44Sab elfedit_obj_state_t *obj_state;
128d29b2c44Sab elfedit_section_t *strsec; /* Dynamic string table ref */
129d29b2c44Sab struct {
130d29b2c44Sab elfedit_section_t *sec; /* Dynamic section reference */
131d29b2c44Sab Dyn *data; /* Start dynamic section data */
132d29b2c44Sab Word num; /* # dynamic elts */
133d29b2c44Sab Word null_ndx; /* Index of first DT_NULL */
134d29b2c44Sab Word num_null_ndx; /* # of DT_NULL elements */
135d29b2c44Sab } dyn;
136*9320f495SToomas Soome dyn_opt_t optmask; /* Mask of options used */
137d29b2c44Sab int argc; /* # of plain arguments */
138d29b2c44Sab const char **argv; /* Plain arguments */
13955ef6355Sab const char *dyn_elt_str; /* Value string for */
14055ef6355Sab /* DYN_OPT_F_DYNNDX_VAL */
14155ef6355Sab /* or DYN_OPT_F_NEEDED */
142d29b2c44Sab } ARGSTATE;
143d29b2c44Sab
144d29b2c44Sab
145d29b2c44Sab
146d29b2c44Sab /*
147d29b2c44Sab * Set argstate null_ndx field for current dynamic area
148d29b2c44Sab */
149d29b2c44Sab static void
set_null_ndx(ARGSTATE * argstate)150d29b2c44Sab set_null_ndx(ARGSTATE *argstate)
151d29b2c44Sab {
152d29b2c44Sab Word num, null_ndx;
153d29b2c44Sab
154d29b2c44Sab num = argstate->dyn.num;
155d29b2c44Sab argstate->dyn.num_null_ndx = 0;
156d29b2c44Sab for (null_ndx = 0; null_ndx < num; null_ndx++)
157d29b2c44Sab if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) {
158d29b2c44Sab argstate->dyn.num_null_ndx++;
159d29b2c44Sab break;
160d29b2c44Sab }
161d29b2c44Sab argstate->dyn.null_ndx = null_ndx;
162d29b2c44Sab
163d29b2c44Sab /* Count the number of remaining DT_NULL items */
164d29b2c44Sab for (; null_ndx < num; null_ndx++)
165d29b2c44Sab if (argstate->dyn.data[null_ndx].d_tag == DT_NULL)
166d29b2c44Sab argstate->dyn.num_null_ndx++;
167d29b2c44Sab }
168d29b2c44Sab
169d29b2c44Sab
170d29b2c44Sab /*
171d29b2c44Sab * Convert the first available DT_NULL slot in the dynamic section
172d29b2c44Sab * into something else.
173d29b2c44Sab *
174d29b2c44Sab * entry:
175d29b2c44Sab * argstate - Argument state block
176d29b2c44Sab * d_tag, d_val - Values to be set in new element
177d29b2c44Sab *
178d29b2c44Sab * exit:
179d29b2c44Sab * If an extra DT_NULL slot is available, a debug message is
180d29b2c44Sab * issued, the slot is converted to its new use, and the argstate
181d29b2c44Sab * block state related to DT_NULL slots is updated.
182d29b2c44Sab *
183d29b2c44Sab * if no extra DT_NULL slot is present, an error is issued and
184d29b2c44Sab * this routine does not return to the caller.
185d29b2c44Sab */
186d29b2c44Sab static Word
convert_dt_null(ARGSTATE * argstate,Xword d_tag,Xword d_val)1874f680cc6SAli Bahrami convert_dt_null(ARGSTATE *argstate, Xword d_tag, Xword d_val)
188d29b2c44Sab {
189d29b2c44Sab Conv_inv_buf_t inv_buf;
190d29b2c44Sab Word ndx;
191d29b2c44Sab Dyn *dyn;
1924f680cc6SAli Bahrami Ehdr *ehdr;
193d29b2c44Sab
194d29b2c44Sab /* If we lack an extra element, we can't continue */
195d29b2c44Sab if (argstate->dyn.num_null_ndx <= 1)
196d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL),
197d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx),
198d29b2c44Sab argstate->dyn.sec->sec_name);
199d29b2c44Sab
2004f680cc6SAli Bahrami ehdr = argstate->obj_state->os_ehdr;
201d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CONVNULL),
202d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), argstate->dyn.sec->sec_name,
203d29b2c44Sab EC_WORD(argstate->dyn.null_ndx), conv_dyn_tag(d_tag,
2044f680cc6SAli Bahrami ehdr->e_ident[EI_OSABI], ehdr->e_machine, 0, &inv_buf));
205d29b2c44Sab
206d29b2c44Sab ndx = argstate->dyn.null_ndx;
207d29b2c44Sab dyn = &argstate->dyn.data[ndx];
208d29b2c44Sab dyn->d_tag = d_tag;
209d29b2c44Sab dyn->d_un.d_val = d_val;
210d29b2c44Sab
211d29b2c44Sab /* Recompute the DT_NULL situation */
212d29b2c44Sab set_null_ndx(argstate);
213d29b2c44Sab
214d29b2c44Sab return (ndx);
215d29b2c44Sab }
216d29b2c44Sab
217d29b2c44Sab
218d29b2c44Sab /*
219d29b2c44Sab * Standard argument processing for dyn module
220d29b2c44Sab *
221d29b2c44Sab * entry
222d29b2c44Sab * obj_state, argc, argv - Standard command arguments
223d29b2c44Sab * argstate - Address of ARGSTATE block to be initialized
224d29b2c44Sab *
225d29b2c44Sab * exit:
226d29b2c44Sab * On success, *argstate is initialized. On error,
227d29b2c44Sab * an error is issued and this routine does not return.
228d29b2c44Sab */
229d29b2c44Sab static void
process_args(elfedit_obj_state_t * obj_state,int argc,const char * argv[],ARGSTATE * argstate)230d29b2c44Sab process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
231d29b2c44Sab ARGSTATE *argstate)
232d29b2c44Sab {
233d29b2c44Sab elfedit_getopt_state_t getopt_state;
234d29b2c44Sab elfedit_getopt_ret_t *getopt_ret;
235d29b2c44Sab
236d29b2c44Sab bzero(argstate, sizeof (*argstate));
237d29b2c44Sab argstate->obj_state = obj_state;
238d29b2c44Sab
239d29b2c44Sab elfedit_getopt_init(&getopt_state, &argc, &argv);
240d29b2c44Sab
241d29b2c44Sab /* Add each new option to the options mask */
24255ef6355Sab while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
243d29b2c44Sab argstate->optmask |= getopt_ret->gor_idmask;
24455ef6355Sab switch (getopt_ret->gor_idmask) {
24555ef6355Sab case DYN_OPT_F_DYNNDX_VAL:
24655ef6355Sab case DYN_OPT_F_NEEDED:
24755ef6355Sab argstate->dyn_elt_str = getopt_ret->gor_value;
24855ef6355Sab break;
24955ef6355Sab }
25055ef6355Sab }
251d29b2c44Sab
252d29b2c44Sab /* If there may be an arbitrary amount of output, use a pager */
253d29b2c44Sab if (argc == 0)
254d29b2c44Sab elfedit_pager_init();
255d29b2c44Sab
256d29b2c44Sab /* Return the updated values of argc/argv */
257d29b2c44Sab argstate->argc = argc;
258d29b2c44Sab argstate->argv = argv;
259d29b2c44Sab
260d29b2c44Sab /* Locate the dynamic section, and the assocated string table */
261d29b2c44Sab argstate->dyn.sec = elfedit_sec_getdyn(obj_state, &argstate->dyn.data,
262d29b2c44Sab &argstate->dyn.num);
263d29b2c44Sab argstate->strsec = elfedit_sec_getstr(obj_state,
26455ef6355Sab argstate->dyn.sec->sec_shdr->sh_link, 0);
265d29b2c44Sab
266d29b2c44Sab /* Index of first DT_NULL */
267d29b2c44Sab set_null_ndx(argstate);
268d29b2c44Sab }
269d29b2c44Sab
270d29b2c44Sab /*
271d29b2c44Sab * Print ELF header values, taking the calling command, and output style
272d29b2c44Sab * into account.
273d29b2c44Sab *
274d29b2c44Sab * entry:
275d29b2c44Sab * cmd - DYN_CMD_T_* value giving identify of caller
276d29b2c44Sab * autoprint - If True, output is only produced if the elfedit
277d29b2c44Sab * autoprint flag is set. If False, output is always produced.
278d29b2c44Sab * argstate - Argument state block
279d29b2c44Sab * print_type - Specifies which dynamic elements to display.
2804f680cc6SAli Bahrami * arg - If print_type is PRINT_DYN_T_NDX, displays the index specified.
281d29b2c44Sab * Otherwise ignored.
282d29b2c44Sab */
283d29b2c44Sab typedef enum {
284d29b2c44Sab PRINT_DYN_T_ALL = 0, /* Show all indexes */
285d29b2c44Sab PRINT_DYN_T_NDX = 1, /* Show dynamic[arg] only */
286d29b2c44Sab PRINT_DYN_T_TAG = 2, /* Show all elts with tag type */
287d29b2c44Sab /* given by arg */
288d29b2c44Sab PRINT_DYN_T_RUNPATH = 3 /* Show all runpath/rpath elts */
289d29b2c44Sab
290d29b2c44Sab } PRINT_DYN_T;
291d29b2c44Sab
292d29b2c44Sab static void
print_dyn(DYN_CMD_T cmd,int autoprint,ARGSTATE * argstate,PRINT_DYN_T print_type,Word arg)293d29b2c44Sab print_dyn(DYN_CMD_T cmd, int autoprint, ARGSTATE *argstate,
294d29b2c44Sab PRINT_DYN_T print_type, Word arg)
295d29b2c44Sab {
296d29b2c44Sab elfedit_outstyle_t outstyle;
297d29b2c44Sab Conv_fmt_flags_t flags_fmt_flags;
298c6c9aed4Sab Word end_ndx, ndx, printed = 0;
299d29b2c44Sab Dyn *dyn;
300d29b2c44Sab int header_done = 0;
301d29b2c44Sab Xword last_d_val;
30255ef6355Sab int one_shot;
3034f680cc6SAli Bahrami int osabi_solaris;
304d29b2c44Sab
305d29b2c44Sab if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))
306d29b2c44Sab return;
307d29b2c44Sab
3084f680cc6SAli Bahrami osabi_solaris =
3094f680cc6SAli Bahrami elfedit_test_osabi(argstate->obj_state, ELFOSABI_SOLARIS, 0);
3104f680cc6SAli Bahrami
311d29b2c44Sab /*
312d29b2c44Sab * Pick an output style. dyn:dump is required to use the default
313d29b2c44Sab * style. The other commands use the current output style.
314d29b2c44Sab */
315d29b2c44Sab outstyle = (cmd == DYN_CMD_T_DUMP) ?
316d29b2c44Sab ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle();
317d29b2c44Sab
318d29b2c44Sab /*
319d29b2c44Sab * When using the simple output style, omit the
320d29b2c44Sab * brackets from around the values.
321d29b2c44Sab */
322d29b2c44Sab flags_fmt_flags = (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) ?
323d29b2c44Sab CONV_FMT_NOBKT : 0;
324d29b2c44Sab
325c6c9aed4Sab /* Starting index */
326d29b2c44Sab if (print_type == PRINT_DYN_T_NDX) {
327d29b2c44Sab if (arg >= argstate->dyn.num)
328d29b2c44Sab return; /* Out of range */
329d29b2c44Sab ndx = arg;
330d29b2c44Sab } else {
331d29b2c44Sab ndx = 0;
332d29b2c44Sab }
333d29b2c44Sab
33455ef6355Sab /*
33555ef6355Sab * one_shot is used by positional elements (e.g. DT_POSFLAG_1)
33655ef6355Sab * to get the item following them to be shown even if they
33755ef6355Sab * are not of the desired tag type or the count of elements
33855ef6355Sab * to be displayed is only 1.
33955ef6355Sab */
34055ef6355Sab one_shot = 0;
34155ef6355Sab
342d29b2c44Sab dyn = &argstate->dyn.data[ndx];
343c6c9aed4Sab
344c6c9aed4Sab /*
345c6c9aed4Sab * Loop predicate explanation:
346c6c9aed4Sab * Normally, we want to iterate from the starting index
347c6c9aed4Sab * to the end. However, in the case of PRINT_DYN_T_NDX, we
348c6c9aed4Sab * only want to display one item (ndx == arg) and then quit,
349c6c9aed4Sab * with the exception that if we've been through the loop
350c6c9aed4Sab * and encountered a one_shot situation, we want to continue
351c6c9aed4Sab * iterating until the one-shot situation is cleared.
352c6c9aed4Sab */
353c6c9aed4Sab for (; (ndx < argstate->dyn.num) &&
354c6c9aed4Sab ((print_type != PRINT_DYN_T_NDX) || ((ndx == arg) || one_shot));
355c6c9aed4Sab dyn++, ndx++) {
356d29b2c44Sab union {
357ba2be530Sab Conv_inv_buf_t inv;
358d29b2c44Sab Conv_dyn_flag_buf_t flag;
359d29b2c44Sab Conv_dyn_flag1_buf_t flag1;
360d29b2c44Sab Conv_dyn_posflag1_buf_t posflag1;
361d29b2c44Sab Conv_dyn_feature1_buf_t feature1;
362d29b2c44Sab } c_buf;
363d29b2c44Sab const char *name;
364d29b2c44Sab
36555ef6355Sab if (one_shot) {
36655ef6355Sab one_shot = 0;
36755ef6355Sab } else {
36855ef6355Sab /*
36955ef6355Sab * If we are only displaying certain tag types and
37055ef6355Sab * this isn't one of those, move on to next element.
37155ef6355Sab */
37255ef6355Sab switch (print_type) {
37355ef6355Sab case PRINT_DYN_T_TAG:
37455ef6355Sab if (dyn->d_tag != arg)
37555ef6355Sab continue;
37655ef6355Sab break;
37755ef6355Sab case PRINT_DYN_T_RUNPATH:
37855ef6355Sab if ((dyn->d_tag != DT_RPATH) &&
37955ef6355Sab (dyn->d_tag != DT_RUNPATH))
38055ef6355Sab continue;
38155ef6355Sab break;
38255ef6355Sab }
383d29b2c44Sab }
384d29b2c44Sab
385d29b2c44Sab /*
386d29b2c44Sab * Print the information numerically, and if possible
387d29b2c44Sab * as a string.
388d29b2c44Sab */
389d29b2c44Sab name = NULL;
390d29b2c44Sab switch (dyn->d_tag) {
391d29b2c44Sab case DT_NULL:
392d29b2c44Sab if (!((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) &&
393d29b2c44Sab (print_type == PRINT_DYN_T_ALL) &&
394d29b2c44Sab (dyn->d_un.d_val == 0)))
395d29b2c44Sab break;
396d29b2c44Sab end_ndx = ndx;
397d29b2c44Sab /*
398d29b2c44Sab * Special case: DT_NULLs can come in groups
399d29b2c44Sab * that we prefer to reduce to a single line.
400d29b2c44Sab */
401d29b2c44Sab while ((end_ndx < (argstate->dyn.num - 1)) &&
402d29b2c44Sab ((dyn + 1)->d_tag == DT_NULL) &&
403d29b2c44Sab ((dyn + 1)->d_un.d_val == 0)) {
404d29b2c44Sab dyn++;
405d29b2c44Sab end_ndx++;
406d29b2c44Sab }
407d29b2c44Sab if (header_done == 0) {
408d29b2c44Sab header_done = 1;
409d29b2c44Sab Elf_dyn_title(0);
410d29b2c44Sab }
411d29b2c44Sab Elf_dyn_null_entry(0, dyn, ndx, end_ndx);
412d29b2c44Sab ndx = end_ndx;
413d29b2c44Sab printed = 1;
414d29b2c44Sab last_d_val = dyn->d_un.d_val;
415d29b2c44Sab continue;
416d29b2c44Sab
417d29b2c44Sab /*
418d29b2c44Sab * Print the information numerically, and if possible
419d29b2c44Sab * as a string.
420d29b2c44Sab */
421d29b2c44Sab case DT_NEEDED:
422d29b2c44Sab case DT_SONAME:
423d29b2c44Sab case DT_FILTER:
424d29b2c44Sab case DT_AUXILIARY:
425d29b2c44Sab case DT_CONFIG:
426d29b2c44Sab case DT_RPATH:
427d29b2c44Sab case DT_RUNPATH:
428d29b2c44Sab case DT_USED:
429d29b2c44Sab case DT_DEPAUDIT:
430d29b2c44Sab case DT_AUDIT:
431d29b2c44Sab name = elfedit_offset_to_str(argstate->strsec,
432d29b2c44Sab dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
433d29b2c44Sab break;
4344f680cc6SAli Bahrami case DT_SUNW_AUXILIARY:
4354f680cc6SAli Bahrami case DT_SUNW_FILTER:
4364f680cc6SAli Bahrami if (osabi_solaris)
4374f680cc6SAli Bahrami name = elfedit_offset_to_str(argstate->strsec,
4384f680cc6SAli Bahrami dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
4394f680cc6SAli Bahrami break;
440d29b2c44Sab
441d29b2c44Sab case DT_FLAGS:
442d29b2c44Sab name = conv_dyn_flag(dyn->d_un.d_val,
443d29b2c44Sab flags_fmt_flags, &c_buf.flag);
444d29b2c44Sab break;
445d29b2c44Sab case DT_FLAGS_1:
446d29b2c44Sab name = conv_dyn_flag1(dyn->d_un.d_val,
447d29b2c44Sab flags_fmt_flags, &c_buf.flag1);
448d29b2c44Sab break;
449d29b2c44Sab case DT_POSFLAG_1:
45055ef6355Sab /*
45155ef6355Sab * If this is dyn:posflag1, and the print_type
45255ef6355Sab * is PRINT_DYN_T_TAG, and the -needed option is
45355ef6355Sab * used, then don't show any DT_POSFLAG_1 elements
45455ef6355Sab * that are not followed by a DT_NEEDED element
45555ef6355Sab * that matches the -needed string.
45655ef6355Sab */
45755ef6355Sab if ((cmd == DYN_CMD_T_POSFLAG1) &&
45855ef6355Sab (print_type == PRINT_DYN_T_TAG) &&
45955ef6355Sab ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) &&
46055ef6355Sab ((ndx + 1) < argstate->dyn.num)) {
46155ef6355Sab Dyn *dyn1 = &argstate->dyn.data[ndx + 1];
46255ef6355Sab
46355ef6355Sab if (dyn1->d_tag != DT_NEEDED)
46455ef6355Sab continue;
46555ef6355Sab name = elfedit_offset_to_str(argstate->strsec,
46655ef6355Sab dyn1->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
46755ef6355Sab if (strncmp(name, argstate->dyn_elt_str,
46855ef6355Sab strlen(argstate->dyn_elt_str)) != 0)
46955ef6355Sab continue;
47055ef6355Sab }
47155ef6355Sab
472d29b2c44Sab name = conv_dyn_posflag1(dyn->d_un.d_val,
473d29b2c44Sab flags_fmt_flags, &c_buf.posflag1);
47455ef6355Sab /*
47555ef6355Sab * DT_POSFLAG_1 is a positional element that affects
47655ef6355Sab * the following item. If using the default output
47755ef6355Sab * style, then show the following item as well.
47855ef6355Sab */
47955ef6355Sab one_shot = (outstyle == ELFEDIT_OUTSTYLE_DEFAULT);
480d29b2c44Sab break;
481d29b2c44Sab case DT_FEATURE_1:
482d29b2c44Sab name = conv_dyn_feature1(dyn->d_un.d_val,
483d29b2c44Sab flags_fmt_flags, &c_buf.feature1);
484d29b2c44Sab break;
485d29b2c44Sab case DT_DEPRECATED_SPARC_REGISTER:
486d29b2c44Sab name = MSG_INTL(MSG_STR_DEPRECATED);
487d29b2c44Sab break;
488ba2be530Sab case DT_SUNW_LDMACH:
4894f680cc6SAli Bahrami if (osabi_solaris)
4904f680cc6SAli Bahrami name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0,
4914f680cc6SAli Bahrami &c_buf.inv);
492ba2be530Sab break;
493d29b2c44Sab }
494d29b2c44Sab
495d29b2c44Sab if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
4964f680cc6SAli Bahrami Ehdr *ehdr;
4974f680cc6SAli Bahrami
498d29b2c44Sab if (header_done == 0) {
499d29b2c44Sab header_done = 1;
500d29b2c44Sab Elf_dyn_title(0);
501d29b2c44Sab }
502d29b2c44Sab if (name == NULL)
503d29b2c44Sab name = MSG_ORIG(MSG_STR_EMPTY);
5044f680cc6SAli Bahrami ehdr = argstate->obj_state->os_ehdr;
505d29b2c44Sab Elf_dyn_entry(0, dyn, ndx, name,
5064f680cc6SAli Bahrami ehdr->e_ident[EI_OSABI], ehdr->e_machine);
507d29b2c44Sab } else {
508d29b2c44Sab /*
509d29b2c44Sab * In simple or numeric mode under a print type
510d29b2c44Sab * that is based on tag type rather than on index,
5115c02782fSAli Bahrami * if there are more than one qualifying tag, we
5125c02782fSAli Bahrami * want to skip printing redundant information.
513d29b2c44Sab */
514d29b2c44Sab switch (print_type) {
515d29b2c44Sab case PRINT_DYN_T_TAG:
5165c02782fSAli Bahrami switch (dyn->d_tag) {
5175c02782fSAli Bahrami case DT_NEEDED:
5185c02782fSAli Bahrami /* Multiple NEEDED entries are normal */
5195c02782fSAli Bahrami break;
5205c02782fSAli Bahrami case DT_POSFLAG_1:
5215c02782fSAli Bahrami /*
5225c02782fSAli Bahrami * Positional flags don't count,
5235c02782fSAli Bahrami * because each one affects a different
5245c02782fSAli Bahrami * item. Don't skip those even if they
5255c02782fSAli Bahrami * have duplicate values.
5265c02782fSAli Bahrami */
5275c02782fSAli Bahrami break;
5285c02782fSAli Bahrami default:
5295c02782fSAli Bahrami /*
5305c02782fSAli Bahrami * Anything else: If we've already
5315c02782fSAli Bahrami * printed this value, don't print
5325c02782fSAli Bahrami * it again.
5335c02782fSAli Bahrami */
5345c02782fSAli Bahrami if (printed &&
5355c02782fSAli Bahrami (last_d_val == dyn->d_un.d_val))
5365c02782fSAli Bahrami continue;
5375c02782fSAli Bahrami }
53855ef6355Sab break;
539d29b2c44Sab case PRINT_DYN_T_RUNPATH:
5405c02782fSAli Bahrami /*
5415c02782fSAli Bahrami * If we've already printed this value,
5425c02782fSAli Bahrami * don't print it again. This commonly
5435c02782fSAli Bahrami * happens when both DT_RPATH and DT_RUNPATH
5445c02782fSAli Bahrami * are present with the same value.
5455c02782fSAli Bahrami */
546d29b2c44Sab if (printed && (last_d_val == dyn->d_un.d_val))
547d29b2c44Sab continue;
54855ef6355Sab break;
549d29b2c44Sab }
550d29b2c44Sab
551d29b2c44Sab if ((name != NULL) &&
552d29b2c44Sab (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)) {
553d29b2c44Sab elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), name);
554d29b2c44Sab } else {
555d29b2c44Sab elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL),
55608278a5eSRod Evans EC_XWORD(dyn->d_un.d_val));
557d29b2c44Sab }
558d29b2c44Sab }
559d29b2c44Sab printed = 1;
560d29b2c44Sab last_d_val = dyn->d_un.d_val;
561d29b2c44Sab }
562d29b2c44Sab
563d29b2c44Sab /*
564d29b2c44Sab * If nothing was output under the print types that are
565d29b2c44Sab * based on tag type, issue an error saying it doesn't exist.
566d29b2c44Sab */
567d29b2c44Sab if (!printed) {
568d29b2c44Sab if (print_type == PRINT_DYN_T_TAG) {
5694f680cc6SAli Bahrami Conv_inv_buf_t inv_buf;
5704f680cc6SAli Bahrami Ehdr *ehdr = argstate->obj_state->os_ehdr;
571d29b2c44Sab
572d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR,
573d29b2c44Sab MSG_INTL(MSG_ERR_NODYNELT),
574d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx),
575d29b2c44Sab argstate->dyn.sec->sec_name, conv_dyn_tag(arg,
5764f680cc6SAli Bahrami ehdr->e_ident[EI_OSABI], ehdr->e_machine,
577d29b2c44Sab 0, &inv_buf));
578d29b2c44Sab }
579d29b2c44Sab
580d29b2c44Sab if (print_type == PRINT_DYN_T_RUNPATH)
581d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR,
582d29b2c44Sab MSG_INTL(MSG_ERR_NORUNPATH),
583d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx),
584d29b2c44Sab argstate->dyn.sec->sec_name);
585d29b2c44Sab }
586d29b2c44Sab }
587d29b2c44Sab
588d29b2c44Sab
589d29b2c44Sab /*
59055ef6355Sab * Determine the index(s) of the dynamic element(s) to be displayed and/or
59155ef6355Sab * manipulated.
592d29b2c44Sab *
593d29b2c44Sab * entry:
594d29b2c44Sab * argstate - Argument state block
59555ef6355Sab * arg - If the command being called accepts a first plain argument
59655ef6355Sab * named 'elt' which is used to specify the dynamic element,
59755ef6355Sab * arg is the value of argv[0] for that command. If the
59855ef6355Sab * command does not accept an 'elt' argument and instead
59955ef6355Sab * implicitly assumes a tag type, arg is the constant string
60055ef6355Sab * for that type (e.g. "DT_POSFLAG_1").
601d29b2c44Sab * print_request - True if the command is to print the current
602d29b2c44Sab * value(s) and return without changing anything.
603d29b2c44Sab * print_type - Address of variable containing PRINT_DYN_T_
604d29b2c44Sab * code specifying how the elements will be displayed.
605d29b2c44Sab *
606d29b2c44Sab * exit:
60755ef6355Sab * If print_request is False: This routine always returns the index
60855ef6355Sab * of a single dynamic element. *print_type is set to PRINT_DYN_T_NDX.
60955ef6355Sab * The 'elt' argument as well as any modifier options (-dynndx, -needed)
61055ef6355Sab * are examined to determine this index. If there are no modifier options,
61155ef6355Sab * the dynamic section contains no element of the desired type, and there
61255ef6355Sab * is an extra DT_NULL element in the section, then a new element of
61355ef6355Sab * the desired type is created and its index returned. Otherwise an
61455ef6355Sab * error is issued.
615d29b2c44Sab *
61655ef6355Sab * If print_request is True: If a modifier (-dynndx, -needed) was used,
61755ef6355Sab * *print_type is set to PRINT_DYN_T_NDX and the index of the
61855ef6355Sab * corresponding single dynamic element is returned. If no modifier
61955ef6355Sab * was used, *print_type is set to PRINT_DYN_T_TAG, and the tag
62055ef6355Sab * type code is returned.
621d29b2c44Sab */
622d29b2c44Sab static Word
arg_to_index(ARGSTATE * argstate,const char * arg,int print_request,PRINT_DYN_T * print_type)62355ef6355Sab arg_to_index(ARGSTATE *argstate, const char *arg,
624d29b2c44Sab int print_request, PRINT_DYN_T *print_type)
625d29b2c44Sab {
6264f680cc6SAli Bahrami Word ndx;
6274f680cc6SAli Bahrami Xword dt_value;
62855ef6355Sab Dyn *dyn;
629d29b2c44Sab
630d29b2c44Sab
631d29b2c44Sab /* Assume we are returning an index, alter as needed below */
632d29b2c44Sab *print_type = PRINT_DYN_T_NDX;
633d29b2c44Sab
63455ef6355Sab /*
63555ef6355Sab * All the commands that accept the DYN_OPT_F_DYNNDX_ELT form
63655ef6355Sab * of -dynndx require a plain argument named 'elt' as their first
63755ef6355Sab * argument. -dynndx is a modifier that means that 'elt' is a
63855ef6355Sab * simple numeric section index. Routines that accept this form
63955ef6355Sab * of -dynndx are willing to handle any tag type, so all we need
64055ef6355Sab * to check is that the value is in range.
64155ef6355Sab */
64255ef6355Sab if ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0)
64355ef6355Sab return ((Word) elfedit_atoui_range(arg, MSG_ORIG(MSG_STR_ELT),
64455ef6355Sab 0, argstate->dyn.num - 1, NULL));
645d29b2c44Sab
64655ef6355Sab /* arg is a DT_ tag type, not a numeric index */
647d29b2c44Sab dt_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_DT);
648d29b2c44Sab
64955ef6355Sab /*
65055ef6355Sab * Commands that accept the DYN_OPT_F_DYNNDX_VAL form of
65155ef6355Sab * dynndx do not accept the 'elt' argument. The index is a
65255ef6355Sab * value that follows the option, and was saved in argstate by
65355ef6355Sab * process_args(). Routines that accept this form of -dynndx
65455ef6355Sab * require the specified element to have a specific tag type,
65555ef6355Sab * so we test for this as well as for the index being in range.
65655ef6355Sab */
65755ef6355Sab if ((argstate->optmask & DYN_OPT_F_DYNNDX_VAL) != 0) {
65855ef6355Sab ndx = ((Word) elfedit_atoui_range(argstate->dyn_elt_str,
65955ef6355Sab MSG_ORIG(MSG_STR_INDEX), 0, argstate->dyn.num - 1, NULL));
66055ef6355Sab if (argstate->dyn.data[ndx].d_tag != dt_value) {
6614f680cc6SAli Bahrami Ehdr *ehdr = argstate->obj_state->os_ehdr;
6624f680cc6SAli Bahrami uchar_t osabi = ehdr->e_ident[EI_OSABI];
6634f680cc6SAli Bahrami Half mach = ehdr->e_machine;
66455ef6355Sab Conv_inv_buf_t is, want;
66555ef6355Sab
66655ef6355Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_WRONGTAG),
66755ef6355Sab EC_WORD(argstate->dyn.sec->sec_shndx),
66855ef6355Sab argstate->dyn.sec->sec_name, ndx,
6694f680cc6SAli Bahrami conv_dyn_tag(dt_value, osabi, mach, 0, &want),
6704f680cc6SAli Bahrami conv_dyn_tag(argstate->dyn.data[ndx].d_tag,
6714f680cc6SAli Bahrami osabi, mach, 0, &is));
67255ef6355Sab }
67355ef6355Sab return (ndx);
67455ef6355Sab }
67555ef6355Sab
676d29b2c44Sab /*
677d29b2c44Sab * If this is a printing request, then we let print_dyn() show
678d29b2c44Sab * all the items with this tag type.
679d29b2c44Sab */
680d29b2c44Sab if (print_request) {
681d29b2c44Sab *print_type = PRINT_DYN_T_TAG;
682d29b2c44Sab return (dt_value);
683d29b2c44Sab }
684d29b2c44Sab
68555ef6355Sab /*
68655ef6355Sab * Commands that accept -needed are looking for the dt_value element
68755ef6355Sab * (usually DT_POSFLAG_1) that immediately preceeds the DT_NEEDED
68855ef6355Sab * element with the string given by argstate->dyn_elt_str.
68955ef6355Sab */
69055ef6355Sab if ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) {
69155ef6355Sab Word retndx = argstate->dyn.num; /* Out of range value */
69255ef6355Sab const char *name;
69355ef6355Sab size_t len;
69455ef6355Sab
69555ef6355Sab len = strlen(argstate->dyn_elt_str);
69655ef6355Sab for (ndx = 0, dyn = argstate->dyn.data;
69755ef6355Sab ndx < argstate->dyn.num; dyn++, ndx++) {
69855ef6355Sab /*
69955ef6355Sab * If the immediately preceeding item has the
70055ef6355Sab * tag type we're looking for, and the current item
70155ef6355Sab * is a DT_NEEDED with a string that matches,
70255ef6355Sab * then the preceeding item is the one we want.
70355ef6355Sab */
70455ef6355Sab if ((dyn->d_tag == DT_NEEDED) &&
70555ef6355Sab (ndx > 0) && (retndx == (ndx - 1))) {
70655ef6355Sab name = elfedit_offset_to_str(argstate->strsec,
70755ef6355Sab dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
70855ef6355Sab
70955ef6355Sab if (strncmp(name,
71055ef6355Sab argstate->dyn_elt_str, len) == 0)
71155ef6355Sab return (retndx);
71255ef6355Sab continue;
71355ef6355Sab }
71455ef6355Sab
71555ef6355Sab /*
71655ef6355Sab * If the current item has the tag type we're
71755ef6355Sab * looking for, make it our current candidate.
71855ef6355Sab * If the next item is a DT_NEEDED with the right
71955ef6355Sab * string value, we'll use it then.
72055ef6355Sab */
72155ef6355Sab if (dyn->d_tag == dt_value)
72255ef6355Sab retndx = ndx;
72355ef6355Sab }
72455ef6355Sab
72555ef6355Sab /* If we get here, no matching DT_NEEDED was found */
72655ef6355Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEDNOMATCH),
72755ef6355Sab EC_WORD(argstate->dyn.sec->sec_shndx),
72855ef6355Sab argstate->dyn.sec->sec_name, argstate->dyn_elt_str);
72955ef6355Sab }
73055ef6355Sab
731d29b2c44Sab /* Locate the first entry with the given tag type */
732d29b2c44Sab for (ndx = 0; ndx < argstate->dyn.num; ndx++) {
733d29b2c44Sab if (argstate->dyn.data[ndx].d_tag == dt_value) {
734d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG,
735d29b2c44Sab MSG_INTL(MSG_DEBUG_DT2NDX),
736d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx),
737d29b2c44Sab argstate->dyn.sec->sec_name, EC_WORD(ndx), arg);
738d29b2c44Sab return (ndx);
739d29b2c44Sab }
740d29b2c44Sab }
741d29b2c44Sab
742d29b2c44Sab /* Not found. Can we create one? */
743d29b2c44Sab if (argstate->dyn.num_null_ndx > 1)
744d29b2c44Sab return (convert_dt_null(argstate, dt_value, 0));
745d29b2c44Sab
746d29b2c44Sab /* No room to create one, so we're out of options and must fail */
747d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODTELT),
748d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx),
749d29b2c44Sab argstate->dyn.sec->sec_name, arg);
750d29b2c44Sab
751d29b2c44Sab /*NOTREACHED*/
752d29b2c44Sab return (0); /* For lint */
753d29b2c44Sab }
754d29b2c44Sab
755d29b2c44Sab
756d29b2c44Sab /*
757d29b2c44Sab * Called by cmd_body() for dyn:value. Implements the core functionality
758d29b2c44Sab * for that command.
759d29b2c44Sab *
760d29b2c44Sab * This routine expects that both the index and value arguments are
761d29b2c44Sab * present.
762d29b2c44Sab */
763d29b2c44Sab static elfedit_cmdret_t
cmd_body_value(ARGSTATE * argstate,Word * ret_ndx)764d29b2c44Sab cmd_body_value(ARGSTATE *argstate, Word *ret_ndx)
765d29b2c44Sab {
766d29b2c44Sab elfedit_section_t *dynsec = argstate->dyn.sec;
767d29b2c44Sab elfedit_section_t *strsec = argstate->strsec;
768d29b2c44Sab elfedit_dyn_elt_t strpad_elt;
769d29b2c44Sab Word i;
770d29b2c44Sab Dyn *dyn = argstate->dyn.data;
771d29b2c44Sab Word numdyn = argstate->dyn.num;
77255ef6355Sab int minus_add, minus_s, minus_dynndx;
7734f680cc6SAli Bahrami Word tmp_val;
7744f680cc6SAli Bahrami Xword arg1, arg2;
775d29b2c44Sab int arg2_known = 1;
776d29b2c44Sab
77755ef6355Sab minus_add = ((argstate->optmask & DYN_OPT_F_ADD) != 0);
77855ef6355Sab minus_s = ((argstate->optmask & DYN_OPT_F_STRVAL) != 0);
77955ef6355Sab minus_dynndx = ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0);
780d29b2c44Sab
781d29b2c44Sab elfedit_dyn_elt_init(&strpad_elt);
782d29b2c44Sab
783d29b2c44Sab /*
784d29b2c44Sab * The first argument is an index if -dynndx is used, and is a
785d29b2c44Sab * tag value otherwise.
786d29b2c44Sab */
787d29b2c44Sab arg1 = minus_dynndx ?
788d29b2c44Sab elfedit_atoui_range(argstate->argv[0], MSG_ORIG(MSG_STR_ELT),
789d29b2c44Sab 0, numdyn - 1, NULL) :
790d29b2c44Sab elfedit_atoconst(argstate->argv[0], ELFEDIT_CONST_DT);
791d29b2c44Sab
792d29b2c44Sab if (minus_s) {
793d29b2c44Sab /*
794d29b2c44Sab * Don't allow the user to specify -s when manipulating a
795d29b2c44Sab * DT_SUNW_STRPAD element. Since DT_SUNW_STRPAD is used to
796d29b2c44Sab * manage the extra space used for strings, this would break
797d29b2c44Sab * our ability to add the string.
798d29b2c44Sab */
799d29b2c44Sab if ((!minus_dynndx && (arg1 == DT_SUNW_STRPAD)) ||
800d29b2c44Sab (minus_dynndx && (dyn[arg1].d_tag == DT_SUNW_STRPAD)))
801d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR,
802d29b2c44Sab MSG_INTL(MSG_ERR_STRPADSTRVAL),
803d29b2c44Sab EC_WORD(dynsec->sec_shndx), dynsec->sec_name);
804d29b2c44Sab
805d29b2c44Sab /* Locate DT_SUNW_STRPAD element if present */
806d29b2c44Sab strpad_elt.dn_dyn.d_un.d_val = 0;
8074f680cc6SAli Bahrami (void) elfedit_dynstr_getpad(argstate->obj_state,
8084f680cc6SAli Bahrami argstate->dyn.sec, &strpad_elt);
809d29b2c44Sab
810d29b2c44Sab /*
811d29b2c44Sab * Look up the string: If the user specified the -dynndx
812d29b2c44Sab * -option, then we will insert it if possible, and
813d29b2c44Sab * fail with an error if not. However, if they did not
814d29b2c44Sab * specify -dynndx, we want to look up the string if it is
815d29b2c44Sab * already there, but defer the insertion. The reason for
816d29b2c44Sab * this is that we may have to grab an unused DT_NULL element
817d29b2c44Sab * below, and if there are none available, we won't want
818d29b2c44Sab * to have modified the string table.
819d29b2c44Sab *
820d29b2c44Sab * This isn't a problem, because if the string isn't
821d29b2c44Sab * in the string table, it can't be used by a dynamic element.
822d29b2c44Sab * Hence, we don't need to insert it to know that there is
823d29b2c44Sab * no match.
824d29b2c44Sab */
825d29b2c44Sab if (minus_dynndx == 0) {
826d29b2c44Sab if (elfedit_sec_findstr(strsec,
827d29b2c44Sab strpad_elt.dn_dyn.d_un.d_val, argstate->argv[1],
828d29b2c44Sab &tmp_val) == 0) {
829d29b2c44Sab arg2_known = 0;
830d29b2c44Sab } else {
831d29b2c44Sab arg2 = tmp_val;
832d29b2c44Sab }
833d29b2c44Sab } else {
834d29b2c44Sab arg2 = elfedit_dynstr_insert(dynsec, strsec,
835d29b2c44Sab &strpad_elt, argstate->argv[1]);
836d29b2c44Sab }
837d29b2c44Sab } else { /* Argument 2 is an integer */
838d29b2c44Sab arg2 = elfedit_atoui(argstate->argv[1], NULL);
839d29b2c44Sab }
840d29b2c44Sab
841d29b2c44Sab
842d29b2c44Sab if (!minus_dynndx && !(minus_add && !arg2_known)) {
843d29b2c44Sab /*
844d29b2c44Sab * Search the dynamic section and see if an item with the
845d29b2c44Sab * specified tag value already exists. We can reduce this
846d29b2c44Sab * to a simple update of an existing value if -add is not
847d29b2c44Sab * specified or the existing d_un value matches the new one.
848d29b2c44Sab *
849d29b2c44Sab * In either of these cases, we will change arg1 to be the
850d29b2c44Sab * index, and set minus_dynndx, causing the simple update to
851d29b2c44Sab * happen immediately below.
852d29b2c44Sab */
853d29b2c44Sab for (i = 0; i < numdyn; i++) {
854d29b2c44Sab if ((dyn[i].d_tag == arg1) &&
855d29b2c44Sab (!minus_add || (dyn[i].d_un.d_val == arg2))) {
856d29b2c44Sab arg1 = i;
857d29b2c44Sab minus_dynndx = 1;
858d29b2c44Sab break;
859d29b2c44Sab }
860d29b2c44Sab }
861d29b2c44Sab }
862d29b2c44Sab
863d29b2c44Sab /*
864d29b2c44Sab * If -dynndx is used, then this is a relatively simple
865d29b2c44Sab * operation, as we simply write over the specified index.
866d29b2c44Sab */
867d29b2c44Sab if (minus_dynndx) {
868d29b2c44Sab /*
869d29b2c44Sab * If we held back from inserting a new string into
870d29b2c44Sab * the dynstr above, we insert it now, because we
871d29b2c44Sab * have a slot in the dynamic section, and we need
872d29b2c44Sab * the string offset ot finish.
873d29b2c44Sab */
874d29b2c44Sab if (!arg2_known)
875d29b2c44Sab arg2 = elfedit_dynstr_insert(dynsec, strsec,
876d29b2c44Sab &strpad_elt, argstate->argv[1]);
877d29b2c44Sab
878d29b2c44Sab *ret_ndx = arg1;
879d29b2c44Sab if (dyn[arg1].d_un.d_val == arg2) {
880d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG,
881d29b2c44Sab MSG_INTL(MSG_DEBUG_X_OK),
882d29b2c44Sab dynsec->sec_shndx, dynsec->sec_name,
883d29b2c44Sab EC_WORD(arg1), EC_XWORD(arg2));
884d29b2c44Sab return (ELFEDIT_CMDRET_NONE);
885d29b2c44Sab } else {
886d29b2c44Sab /* Warn if setting DT_NULL value to non-zero */
887d29b2c44Sab if ((dyn[arg1].d_tag == DT_NULL) && (arg2 != 0))
888d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG,
889d29b2c44Sab MSG_INTL(MSG_DEBUG_DTNULLVALUE),
890d29b2c44Sab dynsec->sec_shndx, dynsec->sec_name,
891d29b2c44Sab EC_WORD(arg1), EC_XWORD(arg2));
892d29b2c44Sab
893d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG,
894d29b2c44Sab MSG_INTL(MSG_DEBUG_X_CHG),
895d29b2c44Sab dynsec->sec_shndx, dynsec->sec_name,
896d29b2c44Sab EC_WORD(arg1), EC_XWORD(dyn[arg1].d_un.d_val),
897