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 * 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 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