1d29b2c44Sab196087 /*
2d29b2c44Sab196087 * CDDL HEADER START
3d29b2c44Sab196087 *
4d29b2c44Sab196087 * The contents of this file are subject to the terms of the
5d29b2c44Sab196087 * Common Development and Distribution License (the "License").
6d29b2c44Sab196087 * You may not use this file except in compliance with the License.
7d29b2c44Sab196087 *
8d29b2c44Sab196087 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d29b2c44Sab196087 * or http://www.opensolaris.org/os/licensing.
10d29b2c44Sab196087 * See the License for the specific language governing permissions
11d29b2c44Sab196087 * and limitations under the License.
12d29b2c44Sab196087 *
13d29b2c44Sab196087 * When distributing Covered Code, include this CDDL HEADER in each
14d29b2c44Sab196087 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d29b2c44Sab196087 * If applicable, add the following below this CDDL HEADER, with the
16d29b2c44Sab196087 * fields enclosed by brackets "[]" replaced with your own identifying
17d29b2c44Sab196087 * information: Portions Copyright [yyyy] [name of copyright owner]
18d29b2c44Sab196087 *
19d29b2c44Sab196087 * CDDL HEADER END
20d29b2c44Sab196087 */
21d29b2c44Sab196087
22d29b2c44Sab196087 /*
2362b628a6SAli Bahrami * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24d29b2c44Sab196087 * Use is subject to license terms.
25*0c3ebc9eSAndy Fiddaman * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
26d29b2c44Sab196087 */
27d29b2c44Sab196087
28d29b2c44Sab196087 /*
29d29b2c44Sab196087 * ELFCLASS specific code for elfedit, built once for each class
30d29b2c44Sab196087 */
31d29b2c44Sab196087 #include <stdlib.h>
32d29b2c44Sab196087 #include <stdio.h>
33d29b2c44Sab196087 #include <unistd.h>
34ba2be530Sab196087 #include <_machelf.h>
35d29b2c44Sab196087 #include <libelf.h>
36d29b2c44Sab196087 #include <strings.h>
37d29b2c44Sab196087 #include <sgs.h>
38d29b2c44Sab196087 #include "msg.h"
39d29b2c44Sab196087 #include "_elfedit.h"
40d29b2c44Sab196087
41d29b2c44Sab196087
42d29b2c44Sab196087
43d29b2c44Sab196087 /*
44d29b2c44Sab196087 * Look up the elfedit_symtab_t that corresponds to the symbol table
45d29b2c44Sab196087 * referenced by the sh_link field of the given auxiliary section.
46d29b2c44Sab196087 *
47d29b2c44Sab196087 * entry:
48d29b2c44Sab196087 * obj_state - Partially constructed object state from
49d29b2c44Sab196087 * elfedit_init_obj_state().
50d29b2c44Sab196087 * auxsec - Section that is associated with the symbol table section
51d29b2c44Sab196087 *
52d29b2c44Sab196087 * exit:
53d29b2c44Sab196087 * Returns the pointer to the elfedit_symtab_t entry that is
54d29b2c44Sab196087 * referenced by the auxiliary section. If not found,
55d29b2c44Sab196087 * outputs a debug message, and returns NULL.
56d29b2c44Sab196087 */
57d29b2c44Sab196087 static elfedit_symtab_t *
get_symtab(elfedit_obj_state_t * obj_state,elfedit_section_t * auxsec)58d29b2c44Sab196087 get_symtab(elfedit_obj_state_t *obj_state, elfedit_section_t *auxsec)
59d29b2c44Sab196087 {
60d29b2c44Sab196087 elfedit_symtab_t *symtab = obj_state->os_symtab;
61d29b2c44Sab196087 Word sh_link = auxsec->sec_shdr->sh_link;
62d29b2c44Sab196087 Word i;
63d29b2c44Sab196087
64d29b2c44Sab196087 for (i = 0; i < obj_state->os_symtabnum; i++, symtab++)
65d29b2c44Sab196087 if (symtab->symt_shndx == sh_link)
66d29b2c44Sab196087 return (symtab);
67d29b2c44Sab196087
68d29b2c44Sab196087 /*
69d29b2c44Sab196087 * If we don't return above, it doesn't reference a valid
70d29b2c44Sab196087 * symbol table. Issue warning.
71d29b2c44Sab196087 */
72d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_AUX_LINK),
73d29b2c44Sab196087 EC_WORD(auxsec->sec_shndx), auxsec->sec_name,
74d29b2c44Sab196087 EC_WORD(sh_link));
75d29b2c44Sab196087
76d29b2c44Sab196087 return (NULL);
77d29b2c44Sab196087 }
78d29b2c44Sab196087
79d29b2c44Sab196087
80d29b2c44Sab196087 /*
81d29b2c44Sab196087 * Fill in state.elf.obj_state with a a dynamically allocated
82d29b2c44Sab196087 * elfedit_obj_state_t struct of the appropriate ELFCLASS.
83d29b2c44Sab196087 * This pre-chewed form is fed to each command, reducing the amount
84d29b2c44Sab196087 * of ELF boilerplate code each command needs to contain.
85d29b2c44Sab196087 *
86d29b2c44Sab196087 * entry:
87d29b2c44Sab196087 * file - Name of file to process
88d29b2c44Sab196087 * fd - Descriptor of open file which has been successfully
89d29b2c44Sab196087 * processed by elf_begin().
90d29b2c44Sab196087 * elf - Elf handle returned by elf_begin
91d29b2c44Sab196087 *
92d29b2c44Sab196087 * exit:
93d29b2c44Sab196087 * An elfedit_obj_state_t struct of the appropriate ELFCLASS has
94d29b2c44Sab196087 * been dynamically allocated, and state.elf.obj_state references it.
95d29b2c44Sab196087 * On failure, this routine does not return to the caller.
96d29b2c44Sab196087 *
97d29b2c44Sab196087 * note: The resulting elfedit_obj_state_t is allocated from a single
98d29b2c44Sab196087 * piece of memory, such that a single call to free() suffices
99d29b2c44Sab196087 * to release it as well as any memory it references.
100d29b2c44Sab196087 */
101d29b2c44Sab196087 #ifdef _ELF64
102d29b2c44Sab196087 void
elfedit64_init_obj_state(const char * file,int fd,Elf * elf)103d29b2c44Sab196087 elfedit64_init_obj_state(const char *file, int fd, Elf *elf)
104d29b2c44Sab196087 #else
105d29b2c44Sab196087 void
106d29b2c44Sab196087 elfedit32_init_obj_state(const char *file, int fd, Elf *elf)
107d29b2c44Sab196087 #endif
108d29b2c44Sab196087 {
109d29b2c44Sab196087 #define INITIAL_SYMTABNDX_ALLOC 5
110d29b2c44Sab196087
111d29b2c44Sab196087 /*
11262b628a6SAli Bahrami * These macros are used to call functions from libelf.
11362b628a6SAli Bahrami *
11462b628a6SAli Bahrami * LIBELF_FAIL encapsulates the common way in which we handle
11562b628a6SAli Bahrami * all of these errors: libelf_fail_name is set and execution
11662b628a6SAli Bahrami * jumps to the libelf_failure label for handling.
11762b628a6SAli Bahrami *
11862b628a6SAli Bahrami * LIBELF is used for the common case in which the function returns
11962b628a6SAli Bahrami * NULL for failure and something else for success.
120d29b2c44Sab196087 */
12162b628a6SAli Bahrami #define LIBELF_FAIL(_name) { libelf_fail_name = _name; goto libelf_failure; }
122d29b2c44Sab196087 #define LIBELF(_libelf_expr, _name) \
12362b628a6SAli Bahrami if ((_libelf_expr) == NULL) \
12462b628a6SAli Bahrami LIBELF_FAIL(_name)
125d29b2c44Sab196087
126d29b2c44Sab196087 const char *libelf_fail_name; /* Used for LIBELF errors */
127d29b2c44Sab196087
128d29b2c44Sab196087 Elf_Scn *scn;
129d29b2c44Sab196087 Elf_Data *data;
130d29b2c44Sab196087 uint_t ndx;
131d29b2c44Sab196087 size_t len, os_size, secarr_size;
132d29b2c44Sab196087 char *names = 0;
133d29b2c44Sab196087 size_t names_len;
134d29b2c44Sab196087 elfedit_section_t *_cache;
135d29b2c44Sab196087 elfedit_obj_state_t tstate;
136d29b2c44Sab196087 elfedit_obj_state_t *obj_state = NULL;
137d29b2c44Sab196087 Word *symtabndx = NULL;
138d29b2c44Sab196087 Word symtabndx_size = 0;
139d29b2c44Sab196087 elfedit_symtab_t *symtab;
140d29b2c44Sab196087
141d29b2c44Sab196087 tstate.os_file = file;
142d29b2c44Sab196087 tstate.os_fd = fd;
143d29b2c44Sab196087 tstate.os_elf = elf;
144d29b2c44Sab196087 tstate.os_dynndx = SHN_UNDEF;
145d29b2c44Sab196087 tstate.os_symtabnum = 0;
146d29b2c44Sab196087
147d29b2c44Sab196087 LIBELF(tstate.os_ehdr = elf_getehdr(tstate.os_elf),
148d29b2c44Sab196087 MSG_ORIG(MSG_ELF_GETEHDR))
149d29b2c44Sab196087
150d29b2c44Sab196087 /* Program header array count and address */
15162b628a6SAli Bahrami if (elf_getphdrnum(tstate.os_elf, &tstate.os_phnum) == -1)
15262b628a6SAli Bahrami LIBELF_FAIL(MSG_ORIG(MSG_ELF_GETPHDRNUM))
153d29b2c44Sab196087 if (tstate.os_phnum > 0) {
154d29b2c44Sab196087 LIBELF((tstate.os_phdr = elf_getphdr(tstate.os_elf)),
155d29b2c44Sab196087 MSG_ORIG(MSG_ELF_GETPHDR))
156d29b2c44Sab196087 } else {
157d29b2c44Sab196087 tstate.os_phdr = NULL;
158d29b2c44Sab196087 }
159d29b2c44Sab196087
16062b628a6SAli Bahrami if (elf_getshdrnum(tstate.os_elf, &tstate.os_shnum) == -1)
16162b628a6SAli Bahrami LIBELF_FAIL(MSG_ORIG(MSG_ELF_GETSHDRNUM))
162d29b2c44Sab196087
163d29b2c44Sab196087 /*
164d29b2c44Sab196087 * Obtain the .shstrtab data buffer to provide the required section
165d29b2c44Sab196087 * name strings.
166d29b2c44Sab196087 */
16762b628a6SAli Bahrami if (elf_getshdrstrndx(tstate.os_elf, &tstate.os_shstrndx) == -1)
16862b628a6SAli Bahrami LIBELF_FAIL(MSG_ORIG(MSG_ELF_GETSHDRSTRNDX))
169d29b2c44Sab196087 LIBELF((scn = elf_getscn(tstate.os_elf, tstate.os_shstrndx)),
170d29b2c44Sab196087 MSG_ORIG(MSG_ELF_GETSCN))
171d29b2c44Sab196087 LIBELF((data = elf_getdata(scn, NULL)), MSG_ORIG(MSG_ELF_GETDATA))
172d29b2c44Sab196087 names = data->d_buf;
173d29b2c44Sab196087 names_len = (names == NULL) ? 0 : data->d_size;
174d29b2c44Sab196087
175d29b2c44Sab196087 /*
176d29b2c44Sab196087 * Count the number of symbol tables and capture their indexes.
177d29b2c44Sab196087 * Find the dynamic section.
178d29b2c44Sab196087 */
179d29b2c44Sab196087 for (ndx = 1, scn = NULL; scn = elf_nextscn(tstate.os_elf, scn);
180d29b2c44Sab196087 ndx++) {
181d29b2c44Sab196087 Shdr *shdr;
182d29b2c44Sab196087
183d29b2c44Sab196087 LIBELF(shdr = elf_getshdr(scn), MSG_ORIG(MSG_ELF_GETSHDR));
184d29b2c44Sab196087
185d29b2c44Sab196087 switch (shdr->sh_type) {
186d29b2c44Sab196087 case SHT_DYNAMIC:
187d29b2c44Sab196087 /* Save index of dynamic section for use below */
188d29b2c44Sab196087 tstate.os_dynndx = ndx;
189d29b2c44Sab196087 break;
190d29b2c44Sab196087
191d29b2c44Sab196087 case SHT_SYMTAB:
192d29b2c44Sab196087 case SHT_DYNSYM:
193d29b2c44Sab196087 case SHT_SUNW_LDYNSYM:
194d29b2c44Sab196087 if (symtabndx_size <= tstate.os_symtabnum) {
195d29b2c44Sab196087 symtabndx_size = (symtabndx_size == 0) ?
196d29b2c44Sab196087 INITIAL_SYMTABNDX_ALLOC :
197d29b2c44Sab196087 (symtabndx_size * 2);
198d29b2c44Sab196087 symtabndx = elfedit_realloc(
199d29b2c44Sab196087 MSG_INTL(MSG_ALLOC_SYMTABOS), symtabndx,
200d29b2c44Sab196087 symtabndx_size * sizeof (symtabndx[0]));
201d29b2c44Sab196087 }
202d29b2c44Sab196087 symtabndx[tstate.os_symtabnum++] = ndx;
203d29b2c44Sab196087 break;
204d29b2c44Sab196087 }
205d29b2c44Sab196087 }
206d29b2c44Sab196087
207d29b2c44Sab196087 /*
208d29b2c44Sab196087 * Allocate space to hold the state. We allocate space for everything
209d29b2c44Sab196087 * in one chunk to make releasing it easy:
210d29b2c44Sab196087 * (1) elfedit_obj_state_t struct
211d29b2c44Sab196087 * (2) The array of elfedit_section_t items referenced from
212d29b2c44Sab196087 * the elfedit_obj_state_t struct.
213d29b2c44Sab196087 * (3) The array of elfedit_symtab_t items referenced from
214d29b2c44Sab196087 * the elfedit_obj_state_t struct.
215d29b2c44Sab196087 * (4) The file name.
216d29b2c44Sab196087 *
217d29b2c44Sab196087 * Note that we round up the size of (1) and (2) to a double boundary
218d29b2c44Sab196087 * to ensure proper alignment of (2) and (3). (4) can align on any
219d29b2c44Sab196087 * boundary.
220d29b2c44Sab196087 */
221d29b2c44Sab196087 os_size = S_DROUND(sizeof (tstate));
222d29b2c44Sab196087 secarr_size = (tstate.os_shnum * sizeof (elfedit_section_t));
223d29b2c44Sab196087 secarr_size = S_DROUND(secarr_size);
224d29b2c44Sab196087 len = strlen(tstate.os_file) + 1;
225d29b2c44Sab196087 obj_state = elfedit_malloc(MSG_INTL(MSG_ALLOC_OBJSTATE),
226d29b2c44Sab196087 os_size + secarr_size +
227d29b2c44Sab196087 (tstate.os_symtabnum * sizeof (elfedit_symtab_t)) + len);
228d29b2c44Sab196087 *obj_state = tstate;
229d29b2c44Sab196087
230d29b2c44Sab196087 /*LINTED E_BAD_PTR_CAST_ALIGN*/
231d29b2c44Sab196087 obj_state->os_secarr = (elfedit_section_t *)
232d29b2c44Sab196087 ((char *)obj_state + os_size);
233*0c3ebc9eSAndy Fiddaman if (obj_state->os_symtabnum == 0) {
234d29b2c44Sab196087 obj_state->os_symtab = NULL;
235*0c3ebc9eSAndy Fiddaman } else {
236d29b2c44Sab196087 /*LINTED E_BAD_PTR_CAST_ALIGN*/
237d29b2c44Sab196087 obj_state->os_symtab = (elfedit_symtab_t *)
238d29b2c44Sab196087 ((char *)obj_state->os_secarr + secarr_size);
239d29b2c44Sab196087 obj_state->os_file =
240d29b2c44Sab196087 (char *)(obj_state->os_symtab + tstate.os_symtabnum);
241d29b2c44Sab196087 (void) strncpy((char *)obj_state->os_file, tstate.os_file, len);
242*0c3ebc9eSAndy Fiddaman }
243d29b2c44Sab196087
244d29b2c44Sab196087 /*
245d29b2c44Sab196087 * Fill in obj_state->os_secarr with information for each section.
246d29b2c44Sab196087 * At the same time, fill in obj_state->os_symtab with the symbol
247d29b2c44Sab196087 * table related data.
248d29b2c44Sab196087 */
249d29b2c44Sab196087 bzero(obj_state->os_secarr, sizeof (obj_state->os_secarr[0]));
250d29b2c44Sab196087 _cache = obj_state->os_secarr;
251d29b2c44Sab196087 LIBELF(scn = elf_getscn(tstate.os_elf, 0),
252d29b2c44Sab196087 MSG_ORIG(MSG_ELF_GETSCN));
253d29b2c44Sab196087 _cache->sec_scn = scn;
254d29b2c44Sab196087 LIBELF(_cache->sec_shdr = elf_getshdr(scn), MSG_ORIG(MSG_ELF_GETSHDR));
255d29b2c44Sab196087 _cache->sec_name = (_cache->sec_shdr->sh_name < names_len) ?
256d29b2c44Sab196087 (names + _cache->sec_shdr->sh_name) : MSG_INTL(MSG_UNKNOWNSECNAM);
257d29b2c44Sab196087 _cache++;
258d29b2c44Sab196087
259d29b2c44Sab196087 if (obj_state->os_symtab != NULL) {
260d29b2c44Sab196087 bzero(obj_state->os_symtab,
261d29b2c44Sab196087 sizeof (obj_state->os_symtab[0]) * obj_state->os_symtabnum);
262d29b2c44Sab196087 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++)
263d29b2c44Sab196087 obj_state->os_symtab[ndx].symt_shndx = symtabndx[ndx];
264d29b2c44Sab196087 free(symtabndx);
265d29b2c44Sab196087 }
266d29b2c44Sab196087
267d29b2c44Sab196087 for (ndx = 1, scn = NULL; scn = elf_nextscn(tstate.os_elf, scn);
268d29b2c44Sab196087 ndx++, _cache++) {
269d29b2c44Sab196087 _cache->sec_shndx = ndx;
270d29b2c44Sab196087 _cache->sec_scn = scn;
271d29b2c44Sab196087 LIBELF(_cache->sec_shdr = elf_getshdr(scn),
272d29b2c44Sab196087 MSG_ORIG(MSG_ELF_GETSHDR))
273d29b2c44Sab196087 _cache->sec_data = elf_getdata(scn, NULL);
274d29b2c44Sab196087 _cache->sec_name = (_cache->sec_shdr->sh_name < names_len) ?
275d29b2c44Sab196087 (names + _cache->sec_shdr->sh_name) :
276d29b2c44Sab196087 MSG_INTL(MSG_UNKNOWNSECNAM);
277d29b2c44Sab196087
278d29b2c44Sab196087 switch (_cache->sec_shdr->sh_type) {
279d29b2c44Sab196087 case SHT_SYMTAB_SHNDX:
280d29b2c44Sab196087 symtab = get_symtab(obj_state, _cache);
281d29b2c44Sab196087 symtab->symt_xshndx = ndx;
282d29b2c44Sab196087 break;
283d29b2c44Sab196087
284d29b2c44Sab196087 case SHT_SUNW_syminfo:
285d29b2c44Sab196087 symtab = get_symtab(obj_state, _cache);
286d29b2c44Sab196087 symtab->symt_syminfo = ndx;
287d29b2c44Sab196087 break;
288d29b2c44Sab196087
289d29b2c44Sab196087 case SHT_SUNW_versym:
290d29b2c44Sab196087 symtab = get_symtab(obj_state, _cache);
291d29b2c44Sab196087 symtab->symt_versym = ndx;
292d29b2c44Sab196087 break;
293d29b2c44Sab196087 }
294d29b2c44Sab196087 }
295d29b2c44Sab196087
296d29b2c44Sab196087 /*
297d29b2c44Sab196087 * Sanity check the symbol tables, and discard any auxiliary
298d29b2c44Sab196087 * sections without enough elements.
299d29b2c44Sab196087 */
300d29b2c44Sab196087 symtab = obj_state->os_symtab;
301d29b2c44Sab196087 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) {
302d29b2c44Sab196087 elfedit_section_t *symsec;
303d29b2c44Sab196087 Word symsec_cnt, aux_cnt;
304d29b2c44Sab196087
305d29b2c44Sab196087 symsec = &obj_state->os_secarr[symtab->symt_shndx];
306d29b2c44Sab196087 symsec_cnt = symsec->sec_shdr->sh_size / sizeof (Sym);
307d29b2c44Sab196087
308d29b2c44Sab196087 /* Extended section indexes */
309d29b2c44Sab196087 if (symtab->symt_xshndx != SHN_UNDEF) {
310d29b2c44Sab196087 _cache = &obj_state->os_secarr[symtab->symt_xshndx];
311d29b2c44Sab196087 aux_cnt = _cache->sec_shdr->sh_size / sizeof (Word);
312d29b2c44Sab196087 if (symsec_cnt > aux_cnt)
313d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
314d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_AUX_SIZE),
315d29b2c44Sab196087 EC_WORD(ndx), _cache->sec_name,
316d29b2c44Sab196087 EC_WORD(aux_cnt),
317d29b2c44Sab196087 EC_WORD(symsec->sec_shndx),
318d29b2c44Sab196087 symsec->sec_name, EC_WORD(aux_cnt));
319d29b2c44Sab196087 }
320d29b2c44Sab196087
321d29b2c44Sab196087 /* Syminfo */
322d29b2c44Sab196087 if (symtab->symt_syminfo != SHN_UNDEF) {
323d29b2c44Sab196087 _cache = &obj_state->os_secarr[symtab->symt_syminfo];
324d29b2c44Sab196087 aux_cnt = _cache->sec_shdr->sh_size / sizeof (Syminfo);
325d29b2c44Sab196087 if (symsec_cnt > aux_cnt)
326d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
327d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_AUX_SIZE),
328d29b2c44Sab196087 EC_WORD(ndx), _cache->sec_name,
329d29b2c44Sab196087 EC_WORD(aux_cnt),
330d29b2c44Sab196087 EC_WORD(symsec->sec_shndx),
331d29b2c44Sab196087 symsec->sec_name, EC_WORD(aux_cnt));
332d29b2c44Sab196087 }
333d29b2c44Sab196087
334d29b2c44Sab196087 /* Versym */
335d29b2c44Sab196087 if (symtab->symt_versym != SHN_UNDEF) {
336d29b2c44Sab196087 _cache = &obj_state->os_secarr[symtab->symt_versym];
337d29b2c44Sab196087 aux_cnt = _cache->sec_shdr->sh_size / sizeof (Versym);
338d29b2c44Sab196087 if (symsec_cnt > aux_cnt)
339d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
340d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_AUX_SIZE),
341d29b2c44Sab196087 EC_WORD(ndx), _cache->sec_name,
342d29b2c44Sab196087 EC_WORD(aux_cnt),
343d29b2c44Sab196087 EC_WORD(symsec->sec_shndx),
344d29b2c44Sab196087 symsec->sec_name, EC_WORD(aux_cnt));
345d29b2c44Sab196087 }
346d29b2c44Sab196087 }
347d29b2c44Sab196087
348d29b2c44Sab196087 /*
349d29b2c44Sab196087 * If this object has a dynsym section with a FLAGS_1 field,
350d29b2c44Sab196087 * then set the DF_1_EDITED bit. elfedit allows changes that
351d29b2c44Sab196087 * can break the resulting program, so knowing that a file was
352d29b2c44Sab196087 * edited can be helpful when encountering a core file or other
353d29b2c44Sab196087 * unexpected failure in the field. A single bit can't tell you
354d29b2c44Sab196087 * what was changed, but it will alert you to the possibility that
355d29b2c44Sab196087 * some additional questions might be in order.
356d29b2c44Sab196087 */
357d29b2c44Sab196087 if (obj_state->os_dynndx != SHN_UNDEF) {
358d29b2c44Sab196087 Word i;
359d29b2c44Sab196087 Word numdyn;
360d29b2c44Sab196087 elfedit_section_t *dynsec;
361d29b2c44Sab196087 elfedit_dyn_elt_t flags_1_elt;
362d29b2c44Sab196087 elfedit_dyn_elt_t null_elt;
363d29b2c44Sab196087 Dyn *dyn;
364d29b2c44Sab196087
365d29b2c44Sab196087 dynsec = &obj_state->os_secarr[obj_state->os_dynndx];
366d29b2c44Sab196087 dyn = (Dyn *) dynsec->sec_data->d_buf;
367d29b2c44Sab196087 numdyn = dynsec->sec_shdr->sh_size /
368d29b2c44Sab196087 dynsec->sec_shdr->sh_entsize;
369d29b2c44Sab196087 elfedit_dyn_elt_init(&flags_1_elt);
370d29b2c44Sab196087 elfedit_dyn_elt_init(&null_elt);
371d29b2c44Sab196087 for (i = 0; i < numdyn; i++) {
372d29b2c44Sab196087
373d29b2c44Sab196087 switch (dyn[i].d_tag) {
374d29b2c44Sab196087 case DT_NULL:
375d29b2c44Sab196087 /*
376d29b2c44Sab196087 * Remember state of the first DT_NULL. If there
377d29b2c44Sab196087 * are more than one (i.e. the first one is not
378d29b2c44Sab196087 * in the final spot), and there is no flags1,
379d29b2c44Sab196087 * then we will turn the first one into a
380d29b2c44Sab196087 * DT_FLAGS_1.
381d29b2c44Sab196087 */
382d29b2c44Sab196087 if (!null_elt.dn_seen)
383d29b2c44Sab196087 elfedit_dyn_elt_save(&null_elt, i,
384d29b2c44Sab196087 &dyn[i]);
385d29b2c44Sab196087 break;
386d29b2c44Sab196087
387d29b2c44Sab196087 case DT_FLAGS_1:
388d29b2c44Sab196087 elfedit_dyn_elt_save(&flags_1_elt, i, &dyn[i]);
389d29b2c44Sab196087 break;
390d29b2c44Sab196087 }
391d29b2c44Sab196087 }
392d29b2c44Sab196087 /* If don't have a flags1 field, can we make one from a NULL? */
393d29b2c44Sab196087 if (!flags_1_elt.dn_seen && null_elt.dn_seen &&
394d29b2c44Sab196087 (null_elt.dn_ndx < (numdyn - 1))) {
395d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
396d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_NULL2DYNFL1),
397d29b2c44Sab196087 EC_WORD(obj_state->os_dynndx),
398d29b2c44Sab196087 dynsec->sec_name, EC_WORD(null_elt.dn_ndx));
399d29b2c44Sab196087 flags_1_elt.dn_seen = 1;
400d29b2c44Sab196087 flags_1_elt.dn_ndx = null_elt.dn_ndx;
401d29b2c44Sab196087 flags_1_elt.dn_dyn.d_tag = DT_FLAGS_1;
402d29b2c44Sab196087 flags_1_elt.dn_dyn.d_un.d_val = 0;
403d29b2c44Sab196087 }
404d29b2c44Sab196087 /*
405d29b2c44Sab196087 * If there is a flags 1 field, add the edit flag if
406d29b2c44Sab196087 * it is not present, and report it's presence otherwise.
407d29b2c44Sab196087 */
408d29b2c44Sab196087 if (flags_1_elt.dn_seen) {
409d29b2c44Sab196087 if (flags_1_elt.dn_dyn.d_un.d_val & DF_1_EDITED) {
410d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
411d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_SEEDYNFLG),
412d29b2c44Sab196087 EC_WORD(obj_state->os_dynndx),
413d29b2c44Sab196087 dynsec->sec_name,
414d29b2c44Sab196087 EC_WORD(flags_1_elt.dn_ndx));
415d29b2c44Sab196087 } else {
416d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
417d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_ADDDYNFLG),
418d29b2c44Sab196087 EC_WORD(obj_state->os_dynndx),
419d29b2c44Sab196087 dynsec->sec_name,
420d29b2c44Sab196087 EC_WORD(flags_1_elt.dn_ndx));
421d29b2c44Sab196087 flags_1_elt.dn_dyn.d_un.d_val |= DF_1_EDITED;
422d29b2c44Sab196087 dyn[flags_1_elt.dn_ndx] = flags_1_elt.dn_dyn;
423d29b2c44Sab196087 elfedit_modified_data(dynsec);
424d29b2c44Sab196087 }
425d29b2c44Sab196087 }
426d29b2c44Sab196087 }
427d29b2c44Sab196087
428d29b2c44Sab196087 #ifdef _ELF64
429d29b2c44Sab196087 state.elf.obj_state.s64 = obj_state;
430d29b2c44Sab196087 #else
431d29b2c44Sab196087 state.elf.obj_state.s32 = obj_state;
432d29b2c44Sab196087 #endif
433d29b2c44Sab196087 return;
434d29b2c44Sab196087
435d29b2c44Sab196087 libelf_failure:
436d29b2c44Sab196087 /*
437d29b2c44Sab196087 * Control comes here if there is an error with LIBELF.
438d29b2c44Sab196087 *
439d29b2c44Sab196087 * entry:
440d29b2c44Sab196087 * libelf_fail_name - Name of failing libelf function
441d29b2c44Sab196087 * tstate.os_file - Name of ELF file being processed
442d29b2c44Sab196087 * tstate.os_fd - Descriptor of open ELF file
443d29b2c44Sab196087 *
444d29b2c44Sab196087 * exit:
445d29b2c44Sab196087 * - dynamic memory is released if necessary
446d29b2c44Sab196087 * - The error issued
447d29b2c44Sab196087 */
448d29b2c44Sab196087 if (obj_state != NULL)
449d29b2c44Sab196087 free(obj_state);
450d29b2c44Sab196087 (void) close(tstate.os_fd);
451d29b2c44Sab196087 elfedit_elferr(tstate.os_file, libelf_fail_name);
452d29b2c44Sab196087 #undef INITIAL_SYMTABNDX_ALLOC
45362b628a6SAli Bahrami #undef LIBELF_FAIL
45462b628a6SAli Bahrami #undef LIBELF
455d29b2c44Sab196087 }
456