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 /* 23*4f680cc6SAli Bahrami * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24d29b2c44Sab196087 * Use is subject to license terms. 25d29b2c44Sab196087 */ 26d29b2c44Sab196087 27d29b2c44Sab196087 #include <stdlib.h> 28d29b2c44Sab196087 #include <stdio.h> 29d29b2c44Sab196087 #include <unistd.h> 30d29b2c44Sab196087 #include <libintl.h> 31ba2be530Sab196087 #include <_machelf.h> 32d29b2c44Sab196087 #include <libelf.h> 33d29b2c44Sab196087 #include <link.h> 34d29b2c44Sab196087 #include <strings.h> 35d29b2c44Sab196087 #include <ctype.h> 36d29b2c44Sab196087 #include "msg.h" 37d29b2c44Sab196087 #include <elfedit.h> 38d29b2c44Sab196087 #include <conv.h> 39d29b2c44Sab196087 #include <sys/elf_SPARC.h> 40d29b2c44Sab196087 #include <sys/elf_amd64.h> 41d29b2c44Sab196087 42d29b2c44Sab196087 43d29b2c44Sab196087 44d29b2c44Sab196087 /* 45d29b2c44Sab196087 * ELFCLASS specific code that would otherwise be found in util.c 46d29b2c44Sab196087 */ 47d29b2c44Sab196087 48d29b2c44Sab196087 49d29b2c44Sab196087 50d29b2c44Sab196087 51d29b2c44Sab196087 /* 52d29b2c44Sab196087 * When you modify ELF constructs, you need to tell libelf that you've 53d29b2c44Sab196087 * done so. Otherwise, the changes may not be flushed back to the 54d29b2c44Sab196087 * output file. 55d29b2c44Sab196087 * 56d29b2c44Sab196087 * The elfedit_modified_*() functions exist to simplify the calls to 57d29b2c44Sab196087 * the underlying elf_flag*() functions. 58d29b2c44Sab196087 */ 59d29b2c44Sab196087 void 60d29b2c44Sab196087 elfedit_modified_ehdr(elfedit_obj_state_t *obj_state) 61d29b2c44Sab196087 { 62d29b2c44Sab196087 (void) elf_flagehdr(obj_state->os_elf, ELF_C_SET, ELF_F_DIRTY); 63d29b2c44Sab196087 } 64d29b2c44Sab196087 65d29b2c44Sab196087 void 66d29b2c44Sab196087 elfedit_modified_phdr(elfedit_obj_state_t *obj_state) 67d29b2c44Sab196087 { 68d29b2c44Sab196087 (void) elf_flagphdr(obj_state->os_elf, ELF_C_SET, ELF_F_DIRTY); 69d29b2c44Sab196087 } 70d29b2c44Sab196087 71d29b2c44Sab196087 void 72d29b2c44Sab196087 elfedit_modified_shdr(elfedit_section_t *s) 73d29b2c44Sab196087 { 74d29b2c44Sab196087 (void) elf_flagshdr(s->sec_scn, ELF_C_SET, ELF_F_DIRTY); 75d29b2c44Sab196087 } 76d29b2c44Sab196087 77d29b2c44Sab196087 void 78d29b2c44Sab196087 elfedit_modified_data(elfedit_section_t *s) 79d29b2c44Sab196087 { 80d29b2c44Sab196087 (void) elf_flagdata(s->sec_data, ELF_C_SET, ELF_F_DIRTY); 81d29b2c44Sab196087 } 82d29b2c44Sab196087 83d29b2c44Sab196087 84d29b2c44Sab196087 85d29b2c44Sab196087 /* 86d29b2c44Sab196087 * Prepare an elfedit_dyn_elt_t structure for use. 87d29b2c44Sab196087 */ 88d29b2c44Sab196087 void 89d29b2c44Sab196087 elfedit_dyn_elt_init(elfedit_dyn_elt_t *elt) 90d29b2c44Sab196087 { 91d29b2c44Sab196087 elt->dn_seen = 0; 92d29b2c44Sab196087 } 93d29b2c44Sab196087 94d29b2c44Sab196087 /* 95d29b2c44Sab196087 * Given a dynamic section item, save it in the given elfedit_dyn_elt_t 96d29b2c44Sab196087 * structure and mark that structure to show that it is present. 97d29b2c44Sab196087 */ 98d29b2c44Sab196087 void 99d29b2c44Sab196087 elfedit_dyn_elt_save(elfedit_dyn_elt_t *elt, Word ndx, Dyn *dyn) 100d29b2c44Sab196087 { 101d29b2c44Sab196087 elt->dn_seen = 1; 102d29b2c44Sab196087 elt->dn_ndx = ndx; 103d29b2c44Sab196087 elt->dn_dyn = *dyn; 104d29b2c44Sab196087 } 105d29b2c44Sab196087 106d29b2c44Sab196087 107d29b2c44Sab196087 /* 108d29b2c44Sab196087 * Return the index of the first section that has the given name. 109d29b2c44Sab196087 * 110d29b2c44Sab196087 * entry: 111d29b2c44Sab196087 * obj_state - Object state. 112d29b2c44Sab196087 * shnam - Name of desired section 113d29b2c44Sab196087 * 114d29b2c44Sab196087 * exit: 115d29b2c44Sab196087 * On success, returns the section index. On failure, an error 116d29b2c44Sab196087 * is issued, and this routine does not return to the caller. 117d29b2c44Sab196087 */ 118d29b2c44Sab196087 Word 119d29b2c44Sab196087 elfedit_name_to_shndx(elfedit_obj_state_t *obj_state, const char *shnam) 120d29b2c44Sab196087 { 121d29b2c44Sab196087 elfedit_section_t *sec = obj_state->os_secarr; 122d29b2c44Sab196087 Word ndx; 123d29b2c44Sab196087 Word shnum = obj_state->os_shnum; 124d29b2c44Sab196087 125d29b2c44Sab196087 for (ndx = 0; ndx < shnum; ndx++, sec++) { 126d29b2c44Sab196087 if (strcmp(shnam, sec->sec_name) == 0) { 127d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 128d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_SHNAM2NDX), 129d29b2c44Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name, shnam); 130d29b2c44Sab196087 return (ndx); 131d29b2c44Sab196087 } 132d29b2c44Sab196087 } 133d29b2c44Sab196087 134d29b2c44Sab196087 /* If didn't return in loop above, the name doesn't match */ 135d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSECNAM), shnam); 136d29b2c44Sab196087 /*NOTREACHED*/ 137d29b2c44Sab196087 return (SHN_UNDEF); 138d29b2c44Sab196087 } 139d29b2c44Sab196087 140d29b2c44Sab196087 141d29b2c44Sab196087 142d29b2c44Sab196087 /* 143d29b2c44Sab196087 * Return the index of the first section that has the given type. 144d29b2c44Sab196087 * 145d29b2c44Sab196087 * entry: 146d29b2c44Sab196087 * obj_state - Object state. 147d29b2c44Sab196087 * shtype - Type of desired section 148d29b2c44Sab196087 * 149d29b2c44Sab196087 * exit: 150d29b2c44Sab196087 * On success, returns the section index. On failure, an error 151d29b2c44Sab196087 * is issued, and this routine does not return to the caller. 152d29b2c44Sab196087 */ 153d29b2c44Sab196087 Word 154d29b2c44Sab196087 elfedit_type_to_shndx(elfedit_obj_state_t *obj_state, Word shtype) 155d29b2c44Sab196087 { 156d29b2c44Sab196087 Conv_inv_buf_t inv_buf; 157d29b2c44Sab196087 elfedit_section_t *sec = obj_state->os_secarr; 158d29b2c44Sab196087 Word ndx; 159d29b2c44Sab196087 Word shnum = obj_state->os_shnum; 160d29b2c44Sab196087 161d29b2c44Sab196087 for (ndx = 0; ndx < shnum; ndx++, sec++) { 162d29b2c44Sab196087 if (shtype == sec->sec_shdr->sh_type) { 163d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 164d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_SHNAM2NDX), 165d29b2c44Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name, 166*4f680cc6SAli Bahrami conv_sec_type( 167*4f680cc6SAli Bahrami obj_state->os_ehdr->e_ident[EI_OSABI], 168*4f680cc6SAli Bahrami obj_state->os_ehdr->e_machine, 169d29b2c44Sab196087 shtype, 0, &inv_buf)); 170d29b2c44Sab196087 return (ndx); 171d29b2c44Sab196087 } 172d29b2c44Sab196087 } 173d29b2c44Sab196087 174d29b2c44Sab196087 /* If didn't return in loop above, the name doesn't match */ 175d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSECTYP), 176*4f680cc6SAli Bahrami conv_sec_type(obj_state->os_ehdr->e_ident[EI_OSABI], 177*4f680cc6SAli Bahrami obj_state->os_ehdr->e_machine, shtype, 0, &inv_buf)); 178d29b2c44Sab196087 /*NOTREACHED*/ 179d29b2c44Sab196087 return (SHN_UNDEF); 180d29b2c44Sab196087 } 181d29b2c44Sab196087 182d29b2c44Sab196087 183d29b2c44Sab196087 184d29b2c44Sab196087 /* 185d29b2c44Sab196087 * Locate the index of the first symbol that has the given name 186d29b2c44Sab196087 * 187d29b2c44Sab196087 * entry: 188d29b2c44Sab196087 * obj_state - Object state. 189d29b2c44Sab196087 * symsec - Symbol section 190d29b2c44Sab196087 * strsec = String section 191d29b2c44Sab196087 * name - String giving name of symbol to lookup 192d29b2c44Sab196087 * msg_type - ELFEDIT_MSG_ type code to use with message 193d29b2c44Sab196087 * issued if name does not exist in symbol table. 194d29b2c44Sab196087 * ret_symndx - Address of variable to receive index. 195d29b2c44Sab196087 * 196d29b2c44Sab196087 * exit: 197d29b2c44Sab196087 * On success, issues debug message, sets *ret_symndx, and returns 198d29b2c44Sab196087 * True (1). 199d29b2c44Sab196087 * 200d29b2c44Sab196087 * On failure, issues a message using msg_type to determine 201d29b2c44Sab196087 * the type of message sent. If the message does not take control away 202d29b2c44Sab196087 * from the caller, False (0) is returned. 203d29b2c44Sab196087 * 204d29b2c44Sab196087 * note: 205d29b2c44Sab196087 * Although the string table is referenced by the sh_link field of 206d29b2c44Sab196087 * the symbol table, we require the user to supply it rather than 207d29b2c44Sab196087 * look it up. The reason for this is that the caller will usually 208d29b2c44Sab196087 * have looked it up, and we wish to avoid multiple debug messages 209d29b2c44Sab196087 * from being issued to that effect. 210d29b2c44Sab196087 */ 211d29b2c44Sab196087 int 212d29b2c44Sab196087 elfedit_name_to_symndx(elfedit_section_t *symsec, elfedit_section_t *strsec, 213d29b2c44Sab196087 const char *name, elfedit_msg_t msg_type, Word *ret_symndx) 214d29b2c44Sab196087 215d29b2c44Sab196087 { 216d29b2c44Sab196087 Sym *sym = (Sym *) symsec->sec_data->d_buf; 217d29b2c44Sab196087 Word cnt = symsec->sec_shdr->sh_size / symsec->sec_shdr->sh_entsize; 218d29b2c44Sab196087 Word ndx, offset; 219d29b2c44Sab196087 const char *curname; 220d29b2c44Sab196087 221d29b2c44Sab196087 for (ndx = 0; ndx < cnt; ndx++) { 222d29b2c44Sab196087 offset = sym[ndx].st_name; 223d29b2c44Sab196087 224d29b2c44Sab196087 curname = elfedit_offset_to_str(strsec, offset, 225d29b2c44Sab196087 ELFEDIT_MSG_ERR, 0); 226d29b2c44Sab196087 if (strcmp(curname, name) == 0) { 227d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 228d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_SYMNAM2NDX), 229d29b2c44Sab196087 EC_WORD(symsec->sec_shndx), 230d29b2c44Sab196087 symsec->sec_name, EC_WORD(ndx), name); 231d29b2c44Sab196087 *ret_symndx = ndx; 232d29b2c44Sab196087 return (1); 233d29b2c44Sab196087 } 234d29b2c44Sab196087 } 235d29b2c44Sab196087 236d29b2c44Sab196087 /* If didn't return in loop above, the name doesn't match */ 237d29b2c44Sab196087 elfedit_msg(msg_type, MSG_INTL(MSG_ERR_NOSYM), 238d29b2c44Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name, name); 239d29b2c44Sab196087 /*NOTREACHED*/ 240d29b2c44Sab196087 return (0); /* lint */ 241d29b2c44Sab196087 } 242d29b2c44Sab196087 243d29b2c44Sab196087 244d29b2c44Sab196087 /* 245d29b2c44Sab196087 * Given a section index, turn it into a descriptive string. 246d29b2c44Sab196087 * - If it is one of the special reserved indexes, the 247d29b2c44Sab196087 * symbolic name is returned. 248d29b2c44Sab196087 * - If it is a regular section, in range for the file, 249d29b2c44Sab196087 * the name associated with the section is returned. 250d29b2c44Sab196087 * - Otherwise, the number is formatted as numeric ASCII. 251d29b2c44Sab196087 * 252d29b2c44Sab196087 * exit: 253d29b2c44Sab196087 * A pointer to the static buffer containing the name is 254d29b2c44Sab196087 * returned. This pointer is valid until the next call 255d29b2c44Sab196087 * to elfedit_shndx_to_name(), and which point it may 256d29b2c44Sab196087 * be overwritten. 257d29b2c44Sab196087 */ 258d29b2c44Sab196087 const char * 259d29b2c44Sab196087 elfedit_shndx_to_name(elfedit_obj_state_t *obj_state, Word shndx) 260d29b2c44Sab196087 { 261d29b2c44Sab196087 /* 262d29b2c44Sab196087 * This routine can be called twice within a single C statement, 263d29b2c44Sab196087 * so we use alternating buffers on each call to allow this 264d29b2c44Sab196087 * without requiring the caller to supply a buffer (the size of 265d29b2c44Sab196087 * which they don't know). 266d29b2c44Sab196087 */ 267*4f680cc6SAli Bahrami static Conv_inv_buf_t buf1, buf2; 268*4f680cc6SAli Bahrami static Conv_inv_buf_t *buf; 269d29b2c44Sab196087 270d29b2c44Sab196087 /* 271d29b2c44Sab196087 * If it is outside of the reserved area, and inside the 272d29b2c44Sab196087 * range of section indexes in the ELF file, then show 273d29b2c44Sab196087 * the section name. 274d29b2c44Sab196087 */ 275d29b2c44Sab196087 if ((shndx < obj_state->os_shnum) && 276*4f680cc6SAli Bahrami ((shndx < SHN_LORESERVE) || (shndx > SHN_HIRESERVE)) && 277*4f680cc6SAli Bahrami (shndx != SHN_UNDEF)) 278d29b2c44Sab196087 return (obj_state->os_secarr[shndx].sec_name); 279d29b2c44Sab196087 280d29b2c44Sab196087 /* 281*4f680cc6SAli Bahrami * Anything else is handled by libconv. It will return standard 282*4f680cc6SAli Bahrami * names for known items, or format as a number otherwise. 283d29b2c44Sab196087 */ 284*4f680cc6SAli Bahrami buf = (buf == &buf1) ? &buf2 : &buf1; /* Switch buffers */ 285*4f680cc6SAli Bahrami return (conv_sym_shndx(obj_state->os_ehdr->e_ident[EI_OSABI], 286*4f680cc6SAli Bahrami obj_state->os_ehdr->e_machine, shndx, 287*4f680cc6SAli Bahrami CONV_FMT_ALT_CF | CONV_FMT_DECIMAL, buf)); 288d29b2c44Sab196087 } 289d29b2c44Sab196087 290d29b2c44Sab196087 291d29b2c44Sab196087 /* 292cce0e03bSab196087 * Locate the arbitrary section specified by shndx for this object. 293cce0e03bSab196087 * 294cce0e03bSab196087 * exit: 295cce0e03bSab196087 * Returns section descriptor on success. On failure, does not return. 296cce0e03bSab196087 */ 297cce0e03bSab196087 elfedit_section_t * 298cce0e03bSab196087 elfedit_sec_get(elfedit_obj_state_t *obj_state, Word shndx) 299cce0e03bSab196087 { 300cce0e03bSab196087 elfedit_section_t *sec; 301cce0e03bSab196087 302cce0e03bSab196087 if ((shndx == 0) || (shndx >= obj_state->os_shnum)) 303cce0e03bSab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADSECNDX), 304cce0e03bSab196087 EC_WORD(shndx), EC_WORD(obj_state->os_shnum - 1)); 305cce0e03bSab196087 306cce0e03bSab196087 sec = &obj_state->os_secarr[shndx]; 307cce0e03bSab196087 308cce0e03bSab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSEC), 309cce0e03bSab196087 EC_WORD(shndx), sec->sec_name); 310cce0e03bSab196087 return (sec); 311cce0e03bSab196087 } 312cce0e03bSab196087 313cce0e03bSab196087 314*4f680cc6SAli Bahrami 315*4f680cc6SAli Bahrami /* 316*4f680cc6SAli Bahrami * Compare the a specified osabi with that of the current object. 317*4f680cc6SAli Bahrami * 318*4f680cc6SAli Bahrami * entry: 319*4f680cc6SAli Bahrami * obj_state - Object state for open object to query. 320*4f680cc6SAli Bahrami * issue_err - True if this routine should issue an error and 321*4f680cc6SAli Bahrami * not return to the caller if osabi is not native. 322*4f680cc6SAli Bahrami * 323*4f680cc6SAli Bahrami * exit: 324*4f680cc6SAli Bahrami * If current osabi is the one specified, True (1) is returned. 325*4f680cc6SAli Bahrami * 326*4f680cc6SAli Bahrami * Otherwise, if issue_err is True, an error is issued and this 327*4f680cc6SAli Bahrami * routine does not return to the caller. If issue_err is False, 328*4f680cc6SAli Bahrami * False (0) is returned. 329*4f680cc6SAli Bahrami * 330*4f680cc6SAli Bahrami * note: 331*4f680cc6SAli Bahrami * ELFOSABI_NONE is considered to be equivalent to ELFOSABI_SOLARIS. 332*4f680cc6SAli Bahrami */ 333*4f680cc6SAli Bahrami int 334*4f680cc6SAli Bahrami elfedit_test_osabi(elfedit_obj_state_t *obj_state, uchar_t osabi, 335*4f680cc6SAli Bahrami int issue_err) 336*4f680cc6SAli Bahrami { 337*4f680cc6SAli Bahrami uchar_t obj_osabi = obj_state->os_ehdr->e_ident[EI_OSABI]; 338*4f680cc6SAli Bahrami Conv_inv_buf_t inv_buf; 339*4f680cc6SAli Bahrami 340*4f680cc6SAli Bahrami if (obj_osabi == ELFOSABI_NONE) 341*4f680cc6SAli Bahrami obj_osabi = ELFOSABI_SOLARIS; 342*4f680cc6SAli Bahrami 343*4f680cc6SAli Bahrami if (osabi == obj_osabi) 344*4f680cc6SAli Bahrami return (1); 345*4f680cc6SAli Bahrami 346*4f680cc6SAli Bahrami if (issue_err) 347*4f680cc6SAli Bahrami elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADOSABI), 348*4f680cc6SAli Bahrami conv_ehdr_osabi(osabi, 0, &inv_buf)); 349*4f680cc6SAli Bahrami return (0); 350*4f680cc6SAli Bahrami } 351*4f680cc6SAli Bahrami 352cce0e03bSab196087 /* 353d29b2c44Sab196087 * Locate the capabilities section for this object 354d29b2c44Sab196087 * 355d29b2c44Sab196087 * entry: 356d29b2c44Sab196087 * obj_state - Object state for open object to query. 357d29b2c44Sab196087 * cap - Address of variable to recieve pointer to capabilities 358d29b2c44Sab196087 * section data buffer. 359d29b2c44Sab196087 * num - Address of variable to receive number of items 360d29b2c44Sab196087 * referenced by cap. 361d29b2c44Sab196087 * 362d29b2c44Sab196087 * exit: 363d29b2c44Sab196087 * On success, returns section descriptor, and sets the 364d29b2c44Sab196087 * variables referenced by cap and num. On failure, 365d29b2c44Sab196087 * does not return. 366d29b2c44Sab196087 */ 367d29b2c44Sab196087 elfedit_section_t * 368d29b2c44Sab196087 elfedit_sec_getcap(elfedit_obj_state_t *obj_state, Cap **cap, Word *num) 369d29b2c44Sab196087 { 370d29b2c44Sab196087 Word cnt; 371d29b2c44Sab196087 elfedit_section_t *cache; 372d29b2c44Sab196087 373*4f680cc6SAli Bahrami (void) elfedit_test_osabi(obj_state, ELFOSABI_SOLARIS, 1); 374*4f680cc6SAli Bahrami 375d29b2c44Sab196087 for (cnt = 1; cnt < obj_state->os_shnum; cnt++) { 376d29b2c44Sab196087 cache = &obj_state->os_secarr[cnt]; 377d29b2c44Sab196087 if (cache->sec_shdr->sh_type == SHT_SUNW_cap) { 378d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 379d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_FNDCAP), 380d29b2c44Sab196087 EC_WORD(cnt), cache->sec_name); 381d29b2c44Sab196087 *cap = (Cap *) cache->sec_data->d_buf; 382d29b2c44Sab196087 *num = cache->sec_shdr->sh_size / 383d29b2c44Sab196087 cache->sec_shdr->sh_entsize; 384d29b2c44Sab196087 return (cache); 385d29b2c44Sab196087 } 386d29b2c44Sab196087 } 387d29b2c44Sab196087 388d29b2c44Sab196087 /* If here, this object has no capabilities section */ 389d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAP)); 390d29b2c44Sab196087 391d29b2c44Sab196087 /*NOTREACHED*/ 392d29b2c44Sab196087 return (NULL); 393d29b2c44Sab196087 } 394d29b2c44Sab196087 395d29b2c44Sab196087 396d29b2c44Sab196087 /* 397d29b2c44Sab196087 * Locate the dynamic section for this object 398d29b2c44Sab196087 * 399d29b2c44Sab196087 * entry: 400d29b2c44Sab196087 * obj_state - Object state for open object to query. 401d29b2c44Sab196087 * dyn - Address of variable to recieve pointer to dynamic 402d29b2c44Sab196087 * section data buffer. 403d29b2c44Sab196087 * numdyn - Address of variable to receive number of items 404d29b2c44Sab196087 * referenced by dyn. 405d29b2c44Sab196087 * 406d29b2c44Sab196087 * exit: 407d29b2c44Sab196087 * On success, returns section descriptor, and sets the 408d29b2c44Sab196087 * variables referenced by dyn and numdyn. On failure, 409d29b2c44Sab196087 * does not return. 410d29b2c44Sab196087 */ 411d29b2c44Sab196087 elfedit_section_t * 412d29b2c44Sab196087 elfedit_sec_getdyn(elfedit_obj_state_t *obj_state, Dyn **dyn, Word *num) 413d29b2c44Sab196087 { 414d29b2c44Sab196087 elfedit_section_t *cache; 415d29b2c44Sab196087 416d29b2c44Sab196087 if (obj_state->os_dynndx != SHN_UNDEF) { 417d29b2c44Sab196087 cache = &obj_state->os_secarr[obj_state->os_dynndx]; 418d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDDYN), 419d29b2c44Sab196087 EC_WORD(cache->sec_shndx), cache->sec_name); 420d29b2c44Sab196087 *dyn = (Dyn *) cache->sec_data->d_buf; 421d29b2c44Sab196087 *num = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize; 422d29b2c44Sab196087 return (cache); 423d29b2c44Sab196087 } 424d29b2c44Sab196087 425d29b2c44Sab196087 /* If here, this object has no dynamic section */ 426d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODYN)); 427d29b2c44Sab196087 428d29b2c44Sab196087 /*NOTREACHED*/ 429d29b2c44Sab196087 return (NULL); 430d29b2c44Sab196087 } 431d29b2c44Sab196087 432d29b2c44Sab196087 433d29b2c44Sab196087 /* 434d29b2c44Sab196087 * Locate the syminfo section for this object 435d29b2c44Sab196087 * 436d29b2c44Sab196087 * entry: 437d29b2c44Sab196087 * obj_state - Object state for open object to query. 438d29b2c44Sab196087 * syminfo - Address of variable to recieve pointer to syminfo 439d29b2c44Sab196087 * section data buffer. 440d29b2c44Sab196087 * num - Address of variable to receive number of items 441d29b2c44Sab196087 * referenced by syminfo. 442d29b2c44Sab196087 * 443d29b2c44Sab196087 * exit: 444d29b2c44Sab196087 * On success, returns section descriptor, and sets the 445d29b2c44Sab196087 * variables referenced by syminfo and num. On failure, 446d29b2c44Sab196087 * does not return. 447d29b2c44Sab196087 */ 448d29b2c44Sab196087 elfedit_section_t * 449d29b2c44Sab196087 elfedit_sec_getsyminfo(elfedit_obj_state_t *obj_state, Syminfo **syminfo, 450d29b2c44Sab196087 Word *num) 451d29b2c44Sab196087 { 452d29b2c44Sab196087 Word cnt; 453d29b2c44Sab196087 elfedit_section_t *cache; 454d29b2c44Sab196087 455d29b2c44Sab196087 for (cnt = 1; cnt < obj_state->os_shnum; cnt++) { 456d29b2c44Sab196087 cache = &obj_state->os_secarr[cnt]; 457d29b2c44Sab196087 if (cache->sec_shdr->sh_type == SHT_SUNW_syminfo) { 458d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 459d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_FNDSYMINFO), 460d29b2c44Sab196087 EC_WORD(cnt), cache->sec_name); 461d29b2c44Sab196087 *syminfo = (Syminfo *) cache->sec_data->d_buf; 462d29b2c44Sab196087 *num = cache->sec_shdr->sh_size / 463d29b2c44Sab196087 cache->sec_shdr->sh_entsize; 464d29b2c44Sab196087 return (cache); 465d29b2c44Sab196087 } 466d29b2c44Sab196087 } 467d29b2c44Sab196087 468d29b2c44Sab196087 /* If here, this object has no syminfo section */ 469d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSYMINFO)); 470d29b2c44Sab196087 471d29b2c44Sab196087 /*NOTREACHED*/ 472d29b2c44Sab196087 return (NULL); 473d29b2c44Sab196087 } 474d29b2c44Sab196087 475d29b2c44Sab196087 476d29b2c44Sab196087 /* 477d29b2c44Sab196087 * Check the given section to see if it is a known symbol table type. 478d29b2c44Sab196087 * 479d29b2c44Sab196087 * entry: 480*4f680cc6SAli Bahrami * obj_state - Object state for open object to query. 481d29b2c44Sab196087 * sec - Section to check 482d29b2c44Sab196087 * issue_err - True if this routine should issue an error and 483d29b2c44Sab196087 * not return to the caller if sec is not a symbol table. 484d29b2c44Sab196087 * atoui_list - NULL, or address of variable to receive a pointer to 485d29b2c44Sab196087 * an array of elfedit_atoui_sym_t items describing the 486d29b2c44Sab196087 * type of symbol table found. This array is useful for 487d29b2c44Sab196087 * doing command completion. 488d29b2c44Sab196087 * 489d29b2c44Sab196087 * exit: 490d29b2c44Sab196087 * If sec is a symbol table: 491d29b2c44Sab196087 * - If atoui_list is non-NULL, *atoui_list is set to the 492d29b2c44Sab196087 * appropriate ELFEDIT_CONST_xx list of items. 493d29b2c44Sab196087 * - True (1) is returned 494d29b2c44Sab196087 * If sec is not a symbol table and issue_err is True: 495d29b2c44Sab196087 * - An error is issued, and this routine does not 496d29b2c44Sab196087 * return to the caller. 497d29b2c44Sab196087 * Otherwise: 498d29b2c44Sab196087 * - If atoui_list is non-NULL, *atoui_list is set to NULL. 499d29b2c44Sab196087 * - False (0) is returned 500d29b2c44Sab196087 */ 501d29b2c44Sab196087 int 502*4f680cc6SAli Bahrami elfedit_sec_issymtab(elfedit_obj_state_t *obj_state, elfedit_section_t *sec, 503*4f680cc6SAli Bahrami int issue_err, elfedit_atoui_sym_t **atoui_list) 504d29b2c44Sab196087 { 505d29b2c44Sab196087 elfedit_const_t const_type; 506d29b2c44Sab196087 int ret = 1; 507d29b2c44Sab196087 508d29b2c44Sab196087 /* Is the section a symbol table? */ 509d29b2c44Sab196087 switch (sec->sec_shdr->sh_type) { 510d29b2c44Sab196087 case SHT_SYMTAB: 511d29b2c44Sab196087 const_type = ELFEDIT_CONST_SHT_SYMTAB; 512d29b2c44Sab196087 break; 513d29b2c44Sab196087 case SHT_DYNSYM: 514d29b2c44Sab196087 const_type = ELFEDIT_CONST_SHT_DYNSYM; 515d29b2c44Sab196087 break; 516d29b2c44Sab196087 case SHT_SUNW_LDYNSYM: 517*4f680cc6SAli Bahrami /* 518*4f680cc6SAli Bahrami * These sections are only known to be symbol tables 519*4f680cc6SAli Bahrami * if the osabi is Solaris. 520*4f680cc6SAli Bahrami */ 521*4f680cc6SAli Bahrami if (elfedit_test_osabi(obj_state, ELFOSABI_SOLARIS, 0)) { 522d29b2c44Sab196087 const_type = ELFEDIT_CONST_SHT_LDYNSYM; 523d29b2c44Sab196087 break; 524*4f680cc6SAli Bahrami } 525*4f680cc6SAli Bahrami /*FALLTHROUGH*/ 526d29b2c44Sab196087 default: 527d29b2c44Sab196087 if (issue_err) 528d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 529d29b2c44Sab196087 MSG_INTL(MSG_ERR_NOTSYMTAB), 530d29b2c44Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name); 531d29b2c44Sab196087 ret = 0; 532d29b2c44Sab196087 break; 533d29b2c44Sab196087 } 534d29b2c44Sab196087 535d29b2c44Sab196087 if (atoui_list != NULL) 536d29b2c44Sab196087 *atoui_list = (ret == 0) ? NULL : 537d29b2c44Sab196087 elfedit_const_to_atoui(const_type); 538d29b2c44Sab196087 539d29b2c44Sab196087 return (ret); 540d29b2c44Sab196087 } 541d29b2c44Sab196087 542d29b2c44Sab196087 543d29b2c44Sab196087 544d29b2c44Sab196087 /* 545d29b2c44Sab196087 * Locate a symbol table section for this object 546d29b2c44Sab196087 * 547d29b2c44Sab196087 * entry: 548d29b2c44Sab196087 * obj_state - Object state for open object to query. 549d29b2c44Sab196087 * by_index - If True, we want to locate the section with the 550d29b2c44Sab196087 * section index given by index. If False, we return 551d29b2c44Sab196087 * the section with the name given by name. 552d29b2c44Sab196087 * index, name - Key to search for. See by_index. 553d29b2c44Sab196087 * sym - Address of variable to recieve pointer to symbol 554d29b2c44Sab196087 * section data buffer. 555d29b2c44Sab196087 * numsym - Address of variable to receive number of symbols 556d29b2c44Sab196087 * referenced by sym. 557d29b2c44Sab196087 * aux_info - Address of variable to receive pointer to the 558d29b2c44Sab196087 * elfedit_symtab_t struct that ties the symbol table and 559d29b2c44Sab196087 * its related auxiliary sections together. NULL if this 560d29b2c44Sab196087 * information is not required. 561d29b2c44Sab196087 * 562d29b2c44Sab196087 * exit: 563d29b2c44Sab196087 * On success, returns section descriptor, and sets the 564d29b2c44Sab196087 * variables referenced by sym, and numsym. On failure, 565d29b2c44Sab196087 * does not return. 566d29b2c44Sab196087 */ 567d29b2c44Sab196087 elfedit_section_t * 568d29b2c44Sab196087 elfedit_sec_getsymtab(elfedit_obj_state_t *obj_state, int by_index, 569d29b2c44Sab196087 Word index, const char *name, Sym **sym, Word *num, 570d29b2c44Sab196087 elfedit_symtab_t **aux_info) 571d29b2c44Sab196087 { 572d29b2c44Sab196087 Word ndx; 573d29b2c44Sab196087 elfedit_section_t *symsec = NULL; 574d29b2c44Sab196087 elfedit_symtab_t *symtab; 575d29b2c44Sab196087 const char *type_name; 576d29b2c44Sab196087 577d29b2c44Sab196087 /* If looking it up by index, make sure the index is in range */ 578d29b2c44Sab196087 if (by_index && (index >= obj_state->os_shnum)) 579d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADSECNDX), 580d29b2c44Sab196087 EC_WORD(index), EC_WORD(obj_state->os_shnum - 1)); 581d29b2c44Sab196087 582d29b2c44Sab196087 /* 583d29b2c44Sab196087 * Look at each known symbol table in turn until the desired 584d29b2c44Sab196087 * one is hit, or there are no more. 585d29b2c44Sab196087 */ 586d29b2c44Sab196087 symtab = obj_state->os_symtab; 587d29b2c44Sab196087 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) { 588d29b2c44Sab196087 elfedit_section_t *s = 589d29b2c44Sab196087 &obj_state->os_secarr[symtab->symt_shndx]; 590d29b2c44Sab196087 591d29b2c44Sab196087 if ((by_index && (symtab->symt_shndx == index)) || 592d29b2c44Sab196087 (!by_index && (strcmp(s->sec_name, name) == 0))) { 593d29b2c44Sab196087 symsec = s; 594d29b2c44Sab196087 break; 595d29b2c44Sab196087 } 596d29b2c44Sab196087 } 597d29b2c44Sab196087 598d29b2c44Sab196087 /* Did we get a section? */ 599d29b2c44Sab196087 if (symsec == NULL) 600d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSYMTAB)); 601d29b2c44Sab196087 602d29b2c44Sab196087 /* Got it. Report to the user and return the necessary data */ 603*4f680cc6SAli Bahrami (void) elfedit_sec_issymtab(obj_state, symsec, 1, NULL); 604d29b2c44Sab196087 type_name = elfedit_atoconst_value_to_str(ELFEDIT_CONST_SHT_ALLSYMTAB, 605d29b2c44Sab196087 symsec->sec_shdr->sh_type, 1); 606d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSYMTAB), 607d29b2c44Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name, type_name); 608d29b2c44Sab196087 *sym = (Sym *) symsec->sec_data->d_buf; 609d29b2c44Sab196087 *num = symsec->sec_shdr->sh_size / symsec->sec_shdr->sh_entsize; 610d29b2c44Sab196087 if (aux_info != NULL) 611d29b2c44Sab196087 *aux_info = symtab; 612d29b2c44Sab196087 return (symsec); 613d29b2c44Sab196087 } 614d29b2c44Sab196087 615d29b2c44Sab196087 616d29b2c44Sab196087 617d29b2c44Sab196087 /* 618d29b2c44Sab196087 * Locate the extended symbol index section associated with a symbol 619d29b2c44Sab196087 * table section. 620d29b2c44Sab196087 * 621d29b2c44Sab196087 * entry: 622d29b2c44Sab196087 * obj_state - Object state for open object to query. 623d29b2c44Sab196087 * symsec - Symbol table section for which extended index 624d29b2c44Sab196087 * index section is required. 625d29b2c44Sab196087 * xshndx - Address of variable to recieve pointer to section index 626d29b2c44Sab196087 * array data buffer. 627d29b2c44Sab196087 * numxshndx - Address of variable to receive number of indices 628d29b2c44Sab196087 * referenced by ndx. 629d29b2c44Sab196087 * 630d29b2c44Sab196087 * exit: 631d29b2c44Sab196087 * On success, returns extended index section descriptor, and sets the 632d29b2c44Sab196087 * variables referenced by xshndx, and numxshndx. On failure, 633d29b2c44Sab196087 * does not return. 634d29b2c44Sab196087 * 635d29b2c44Sab196087 * note: 636d29b2c44Sab196087 * Since the extended section index is found in the sec_xshndx field 637d29b2c44Sab196087 * of the elfedit_section_t, the caller may be tempted to bypass this 638d29b2c44Sab196087 * routine and access it directly. That temptation should be resisted, 639d29b2c44Sab196087 * as this routine performs useful error checking, and also handles 640d29b2c44Sab196087 * the issuing of the standard MSG_DEBUG messages. 641d29b2c44Sab196087 */ 642d29b2c44Sab196087 elfedit_section_t * 643d29b2c44Sab196087 elfedit_sec_getxshndx(elfedit_obj_state_t *obj_state, 644d29b2c44Sab196087 elfedit_section_t *symsec, Word **xshndx, Word *num) 645d29b2c44Sab196087 { 646d29b2c44Sab196087 elfedit_section_t *xshndxsec; 647d29b2c44Sab196087 elfedit_symtab_t *symtab; 648d29b2c44Sab196087 Word ndx; 649d29b2c44Sab196087 650d29b2c44Sab196087 /* Sanity check: symsec must be a symbol table */ 651*4f680cc6SAli Bahrami (void) elfedit_sec_issymtab(obj_state, symsec, 1, NULL); 652d29b2c44Sab196087 653d29b2c44Sab196087 symtab = obj_state->os_symtab; 654d29b2c44Sab196087 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) 655d29b2c44Sab196087 if (symsec->sec_shndx == symtab->symt_shndx) 656d29b2c44Sab196087 break; 657d29b2c44Sab196087 658d29b2c44Sab196087 /* 659d29b2c44Sab196087 * Issue error if the symbol table lacks an extended index section. 660d29b2c44Sab196087 * The caller won't ask unless they encounter an SHN_XINDEX value, 661d29b2c44Sab196087 * in which case the lack of the index section denotes a corrupt 662d29b2c44Sab196087 * ELF file. 663d29b2c44Sab196087 */ 664d29b2c44Sab196087 if ((ndx == obj_state->os_symtabnum) || 665d29b2c44Sab196087 (symtab->symt_xshndx == SHN_UNDEF)) 666d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOXSHSEC), 667d29b2c44Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name); 668d29b2c44Sab196087 669d29b2c44Sab196087 /* Got it. Report to the user and return the necessary data */ 670d29b2c44Sab196087 xshndxsec = &obj_state->os_secarr[symtab->symt_xshndx]; 671d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDXSHNDX), 672d29b2c44Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name, 673d29b2c44Sab196087 EC_WORD(xshndxsec->sec_shndx), xshndxsec->sec_name); 674d29b2c44Sab196087 *xshndx = (Word *) xshndxsec->sec_data->d_buf; 675d29b2c44Sab196087 *num = xshndxsec->sec_shdr->sh_size / xshndxsec->sec_shdr->sh_entsize; 676d29b2c44Sab196087 return (xshndxsec); 677d29b2c44Sab196087 } 678d29b2c44Sab196087 679d29b2c44Sab196087 680d29b2c44Sab196087 681d29b2c44Sab196087 /* 682d29b2c44Sab196087 * Locate the versym section associated with a symbol table section. 683d29b2c44Sab196087 * 684d29b2c44Sab196087 * entry: 685d29b2c44Sab196087 * obj_state - Object state for open object to query. 686d29b2c44Sab196087 * symsec - Symbol table section for which extended index 687d29b2c44Sab196087 * index section is required. 688d29b2c44Sab196087 * versym - Address of variable to recieve pointer to section index 689d29b2c44Sab196087 * array data buffer. 690d29b2c44Sab196087 * numversym - Address of variable to receive number of indices 691d29b2c44Sab196087 * referenced by ndx. 692d29b2c44Sab196087 * 693d29b2c44Sab196087 * exit: 694d29b2c44Sab196087 * On success, returns versym section descriptor, and sets the 695d29b2c44Sab196087 * variables referenced by versym, and numversym. On failure, 696d29b2c44Sab196087 * does not return. 697d29b2c44Sab196087 * 698d29b2c44Sab196087 * note: 699d29b2c44Sab196087 * Since the versym section index is found in the sec_versym field 700d29b2c44Sab196087 * of the elfedit_section_t, the caller may be tempted to bypass this 701d29b2c44Sab196087 * routine and access it directly. That temptation should be resisted, 702d29b2c44Sab196087 * as this routine performs useful error checking, and also handles 703d29b2c44Sab196087 * the issuing of the standard MSG_DEBUG messages. 704d29b2c44Sab196087 */ 705d29b2c44Sab196087 elfedit_section_t * 706d29b2c44Sab196087 elfedit_sec_getversym(elfedit_obj_state_t *obj_state, 707d29b2c44Sab196087 elfedit_section_t *symsec, Versym **versym, Word *num) 708d29b2c44Sab196087 { 709d29b2c44Sab196087 elfedit_section_t *versymsec; 710d29b2c44Sab196087 elfedit_symtab_t *symtab; 711d29b2c44Sab196087 Word ndx; 712d29b2c44Sab196087 713d29b2c44Sab196087 /* Sanity check: symsec must be a symbol table */ 714*4f680cc6SAli Bahrami (void) elfedit_sec_issymtab(obj_state, symsec, 1, NULL); 715d29b2c44Sab196087 716d29b2c44Sab196087 symtab = obj_state->os_symtab; 717d29b2c44Sab196087 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) 718d29b2c44Sab196087 if (symsec->sec_shndx == symtab->symt_shndx) 719d29b2c44Sab196087 break; 720d29b2c44Sab196087 /* 721d29b2c44Sab196087 * Issue error if the symbol table lacks a versym section. 722d29b2c44Sab196087 * The caller won't ask unless they see a non-null 723d29b2c44Sab196087 * aux.symtab.sec_versym, so this should not be a problem. 724d29b2c44Sab196087 */ 725d29b2c44Sab196087 if ((ndx == obj_state->os_symtabnum) || 726d29b2c44Sab196087 (symtab->symt_versym == SHN_UNDEF)) 727d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOVERSYMSEC), 728d29b2c44Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name); 729d29b2c44Sab196087 730d29b2c44Sab196087 /* Got it. Report to the user and return the necessary data */ 731d29b2c44Sab196087 versymsec = &obj_state->os_secarr[symtab->symt_versym]; 732d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDVERSYM), 733d29b2c44Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name, 734d29b2c44Sab196087 EC_WORD(versymsec->sec_shndx), versymsec->sec_name); 735d29b2c44Sab196087 *versym = (Versym *) versymsec->sec_data->d_buf; 736d29b2c44Sab196087 *num = versymsec->sec_shdr->sh_size / versymsec->sec_shdr->sh_entsize; 737d29b2c44Sab196087 return (versymsec); 738d29b2c44Sab196087 } 739d29b2c44Sab196087 740d29b2c44Sab196087 741d29b2c44Sab196087 742d29b2c44Sab196087 /* 743d29b2c44Sab196087 * Locate the string table specified by shndx for this object. 744d29b2c44Sab196087 * 74555ef6355Sab196087 * entry: 74655ef6355Sab196087 * obj_state - Object state. 74755ef6355Sab196087 * shndx - Section index for string table section 74855ef6355Sab196087 * allow_shflags - If False (0), only sections of type SHT_STRTAB 74955ef6355Sab196087 * are accepted as being string tables, and any other type 75055ef6355Sab196087 * will fail. If True (1), non-stringtable sections with 75155ef6355Sab196087 * their SHF_STRINGS flag set are also accepted. 75255ef6355Sab196087 * 753d29b2c44Sab196087 * exit: 754d29b2c44Sab196087 * Returns section descriptor on success. On failure, does not return. 75555ef6355Sab196087 * 75655ef6355Sab196087 * note: 75755ef6355Sab196087 * At this time, we can only support SHF_STRINGS sections that 75855ef6355Sab196087 * use single byte characters and which do not require alignment >1. 75955ef6355Sab196087 * SHF_STRINGS sections that have multi-byte characters or alignment 76055ef6355Sab196087 * are not currently supported and will draw an error even if 76155ef6355Sab196087 * allow_shflags is True. 762d29b2c44Sab196087 */ 763d29b2c44Sab196087 elfedit_section_t * 76455ef6355Sab196087 elfedit_sec_getstr(elfedit_obj_state_t *obj_state, Word shndx, 76555ef6355Sab196087 int allow_shflags) 766d29b2c44Sab196087 { 767d29b2c44Sab196087 elfedit_section_t *strsec; 768d29b2c44Sab196087 769d29b2c44Sab196087 if ((shndx == 0) || (shndx >= obj_state->os_shnum)) 770d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_STRSHNDX), 771cce0e03bSab196087 EC_WORD(shndx), EC_WORD(obj_state->os_shnum - 1)); 772d29b2c44Sab196087 773d29b2c44Sab196087 strsec = &obj_state->os_secarr[shndx]; 77455ef6355Sab196087 if (strsec->sec_shdr->sh_type == SHT_STRTAB) { 775d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSTRTAB), 776d29b2c44Sab196087 EC_WORD(shndx), strsec->sec_name); 77755ef6355Sab196087 } else if (allow_shflags && 77855ef6355Sab196087 ((strsec->sec_shdr->sh_flags & SHF_STRINGS) != 0) && 77955ef6355Sab196087 (strsec->sec_shdr->sh_entsize <= 1) && 78055ef6355Sab196087 (strsec->sec_shdr->sh_addralign <= 1)) { 78155ef6355Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSTRTABFL), 78255ef6355Sab196087 EC_WORD(shndx), strsec->sec_name); 78355ef6355Sab196087 } else { 78455ef6355Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOTSTRSH), 78555ef6355Sab196087 EC_WORD(shndx), strsec->sec_name); 78655ef6355Sab196087 } 78755ef6355Sab196087 788d29b2c44Sab196087 return (strsec); 789d29b2c44Sab196087 } 790d29b2c44Sab196087 791d29b2c44Sab196087 792d29b2c44Sab196087 /* 793d29b2c44Sab196087 * Returns the offset of the specified string from within 794d29b2c44Sab196087 * the given section. 795d29b2c44Sab196087 * 796d29b2c44Sab196087 * entry: 797d29b2c44Sab196087 * sec - Descriptor for section 798d29b2c44Sab196087 * tail_ign - If non-zero, the # of characters at the end of the 799d29b2c44Sab196087 * section that should be ignored and not searched. 800d29b2c44Sab196087 * str - String we are looking for. 801d29b2c44Sab196087 * ret_offset - Address of variable to receive result 802d29b2c44Sab196087 * 803d29b2c44Sab196087 * exit: 804d29b2c44Sab196087 * Returns 1 for success, and 0 for failure. If successful, *ret_offset 805d29b2c44Sab196087 * is set to the offset of the found string within the section. 806d29b2c44Sab196087 */ 807d29b2c44Sab196087 int 808d29b2c44Sab196087 elfedit_sec_findstr(elfedit_section_t *sec, Word tail_ign, 809d29b2c44Sab196087 const char *str, Word *ret_offset) 810d29b2c44Sab196087 { 811d29b2c44Sab196087 int str_fch = *str; /* First character in str */ 812d29b2c44Sab196087 Word len; /* # characters in table */ 813d29b2c44Sab196087 char *s; /* ptr to strings within table */ 814d29b2c44Sab196087 const char *tail; /* 1 past final character of table */ 815d29b2c44Sab196087 816d29b2c44Sab196087 817d29b2c44Sab196087 /* Size of the section, minus the reserved part (if any) at the end */ 818d29b2c44Sab196087 len = sec->sec_shdr->sh_size - tail_ign; 819d29b2c44Sab196087 820d29b2c44Sab196087 /* 821d29b2c44Sab196087 * Move through the section character by character looking for 822d29b2c44Sab196087 * a match. Moving character by character instead of skipping 823d29b2c44Sab196087 * from NULL terminated string to string allows us to use 824d29b2c44Sab196087 * the tails longer strings (i.e. we want "bar", and "foobar" exists). 825d29b2c44Sab196087 * We look at the first character manually before calling strcmp() 826d29b2c44Sab196087 * to lower the cost of this approach. 827d29b2c44Sab196087 */ 828d29b2c44Sab196087 s = (char *)sec->sec_data->d_buf; 829d29b2c44Sab196087 tail = s + len; 830d29b2c44Sab196087 for (; s <= tail; s++) { 831d29b2c44Sab196087 if ((*s == str_fch) && (strcmp(s, str) == 0)) { 832d29b2c44Sab196087 *ret_offset = s - (char *)sec->sec_data->d_buf; 833d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 834d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_EXISTSTR), 835d29b2c44Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name, 836d29b2c44Sab196087 EC_WORD(*ret_offset), s); 837d29b2c44Sab196087 return (1); 838d29b2c44Sab196087 } 839d29b2c44Sab196087 } 840d29b2c44Sab196087 841d29b2c44Sab196087 /* Didn't find it. Report failure */ 842d29b2c44Sab196087 return (0); 843d29b2c44Sab196087 } 844d29b2c44Sab196087 845d29b2c44Sab196087 846d29b2c44Sab196087 /* 847d29b2c44Sab196087 * Locate the DT_SUNW_STRPAD element of the given dynamic section if 848d29b2c44Sab196087 * it exists. 849d29b2c44Sab196087 * 850d29b2c44Sab196087 * entry: 851*4f680cc6SAli Bahrami * obj_state - Object state for open object to query. 852d29b2c44Sab196087 * dynsec - Dynamic section descriptor 853d29b2c44Sab196087 * dyn_strpad - Address of variable to receive the results. 854d29b2c44Sab196087 * The caller is responsible for calling elfedit_dyn_elt_init() 855d29b2c44Sab196087 * on this variable beforehand. 856d29b2c44Sab196087 * 857d29b2c44Sab196087 * exit: 858d29b2c44Sab196087 * The dynamic section is searched, and if a DT_SUNW_STRPAD element 859d29b2c44Sab196087 * is found, dyn_strpad is updated via elfedit_dyn_elt_save() to 860d29b2c44Sab196087 * reference it. 861d29b2c44Sab196087 * 862d29b2c44Sab196087 * Returns the final value of dyn_strpad->dn_seen. 863d29b2c44Sab196087 */ 864d29b2c44Sab196087 int 865*4f680cc6SAli Bahrami elfedit_dynstr_getpad(elfedit_obj_state_t *obj_state, elfedit_section_t *dynsec, 866*4f680cc6SAli Bahrami elfedit_dyn_elt_t *dyn_strpad) 867d29b2c44Sab196087 { 868d29b2c44Sab196087 Word numdyn = dynsec->sec_shdr->sh_size / dynsec->sec_shdr->sh_entsize; 869*4f680cc6SAli Bahrami Dyn *dyn = (Dyn *) dynsec->sec_data->d_buf; 870d29b2c44Sab196087 Word i; 871d29b2c44Sab196087 872*4f680cc6SAli Bahrami /* 873*4f680cc6SAli Bahrami * DT_SUNW_STRPAD is specific to the Solaris OSABI. 874*4f680cc6SAli Bahrami * If the object is tagged otherwise, don't even look. 875*4f680cc6SAli Bahrami */ 876*4f680cc6SAli Bahrami if (!elfedit_test_osabi(obj_state, ELFOSABI_SOLARIS, 0)) 877*4f680cc6SAli Bahrami return (dyn_strpad->dn_seen); 878*4f680cc6SAli Bahrami 879d29b2c44Sab196087 /* Go through dynamic section tags and find the STRPAD entry */ 880d29b2c44Sab196087 for (i = 0; i < numdyn; i++) { 881d29b2c44Sab196087 if (dyn[i].d_tag == DT_SUNW_STRPAD) { 882d29b2c44Sab196087 elfedit_dyn_elt_save(dyn_strpad, i, &dyn[i]); 883d29b2c44Sab196087 break; 884d29b2c44Sab196087 } 885d29b2c44Sab196087 } 886d29b2c44Sab196087 887d29b2c44Sab196087 return (dyn_strpad->dn_seen); 888d29b2c44Sab196087 } 889d29b2c44Sab196087 890d29b2c44Sab196087 891d29b2c44Sab196087 892d29b2c44Sab196087 /* 893d29b2c44Sab196087 * Given references to the dynamic section, its string table, 894d29b2c44Sab196087 * and the DT_SUNW_STRPAD entry of the dynamic section, returns 895d29b2c44Sab196087 * the offset of the specified string from within the given string table, 896d29b2c44Sab196087 * adding it if possible. 897d29b2c44Sab196087 * 898d29b2c44Sab196087 * entry: 899d29b2c44Sab196087 * dynsec - Dynamic section descriptor 900d29b2c44Sab196087 * strsec - Descriptor for string table assocated with dynamic section 901d29b2c44Sab196087 * dyn_strpad - DT_SUNW_STRPAD element from dynamic section 902d29b2c44Sab196087 * str - String we are looking for. 903d29b2c44Sab196087 * 904d29b2c44Sab196087 * exit: 905d29b2c44Sab196087 * On success, the offset of the given string within the string 906d29b2c44Sab196087 * table is returned. If the string does not exist within the table, 907d29b2c44Sab196087 * but there is a valid DT_SUNW_STRPAD reserved section, then we 908d29b2c44Sab196087 * add the string, and update the dynamic section STRPAD element 909d29b2c44Sab196087 * to reflect the space we use. 910d29b2c44Sab196087 * 911d29b2c44Sab196087 * This routine does not return on failure. 912d29b2c44Sab196087 */ 913d29b2c44Sab196087 Word 914d29b2c44Sab196087 elfedit_dynstr_insert(elfedit_section_t *dynsec, elfedit_section_t *strsec, 915d29b2c44Sab196087 elfedit_dyn_elt_t *dyn_strpad, const char *str) 916d29b2c44Sab196087 { 917d29b2c44Sab196087 Word ins_off; /* Table offset to 1st reserved byte */ 918d29b2c44Sab196087 char *s; /* ptr to strings within table */ 919d29b2c44Sab196087 Word len; /* Length of str inc. NULL byte */ 920d29b2c44Sab196087 Word tail_ign; /* # reserved bytes at end of strtab */ 921d29b2c44Sab196087 922d29b2c44Sab196087 923d29b2c44Sab196087 tail_ign = dyn_strpad->dn_seen ? dyn_strpad->dn_dyn.d_un.d_val : 0; 924d29b2c44Sab196087 925d29b2c44Sab196087 /* Does the string already existin the string table? */ 926d29b2c44Sab196087 if (elfedit_sec_findstr(strsec, tail_ign, str, &len)) 927d29b2c44Sab196087 return (len); 928d29b2c44Sab196087 929d29b2c44Sab196087 /* 930d29b2c44Sab196087 * The desired string does not already exist. Do we have 931d29b2c44Sab196087 * room to add it? 932d29b2c44Sab196087 */ 933d29b2c44Sab196087 len = strlen(str) + 1; 934d29b2c44Sab196087 if (!dyn_strpad->dn_seen || (len > dyn_strpad->dn_dyn.d_un.d_val)) 935d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRPAD), 936d29b2c44Sab196087 EC_WORD(strsec->sec_shdr->sh_link), 937d29b2c44Sab196087 strsec->sec_name); 938d29b2c44Sab196087 939d29b2c44Sab196087 940d29b2c44Sab196087 /* 941d29b2c44Sab196087 * We will add the string at the first byte of the reserved NULL 942d29b2c44Sab196087 * area at the end. The DT_SUNW_STRPAD dynamic element gives us 943d29b2c44Sab196087 * the size of that reserved space. 944d29b2c44Sab196087 */ 945d29b2c44Sab196087 ins_off = strsec->sec_shdr->sh_size - tail_ign; 946d29b2c44Sab196087 s = ((char *)strsec->sec_data->d_buf) + ins_off; 947d29b2c44Sab196087 948d29b2c44Sab196087 /* Announce the operation */ 949d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_ADDSTR), 950d29b2c44Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name, 951d29b2c44Sab196087 EC_WORD(ins_off), EC_WORD(len), 952d29b2c44Sab196087 EC_WORD(dyn_strpad->dn_dyn.d_un.d_val), str); 953d29b2c44Sab196087 954d29b2c44Sab196087 /* 955d29b2c44Sab196087 * Copy the string into the pad area at the end, and 956d29b2c44Sab196087 * mark the data area as dirty so libelf will flush our 957d29b2c44Sab196087 * changes to the string data. 958d29b2c44Sab196087 */ 959d29b2c44Sab196087 (void) strncpy(s, str, dyn_strpad->dn_dyn.d_un.d_val); 960d29b2c44Sab196087 elfedit_modified_data(strsec); 961d29b2c44Sab196087 962d29b2c44Sab196087 /* Update the DT_STRPAD dynamic entry */ 963d29b2c44Sab196087 dyn_strpad->dn_dyn.d_un.d_val -= len; 964d29b2c44Sab196087 ((Dyn *) dynsec->sec_data->d_buf)[dyn_strpad->dn_ndx] = 965d29b2c44Sab196087 dyn_strpad->dn_dyn; 966d29b2c44Sab196087 elfedit_modified_data(dynsec); 967d29b2c44Sab196087 968d29b2c44Sab196087 return (ins_off); 969d29b2c44Sab196087 } 970d29b2c44Sab196087 971d29b2c44Sab196087 972d29b2c44Sab196087 /* 973d29b2c44Sab196087 * Test to see if a call to elfedit_strtab_insert() will succeed. 974d29b2c44Sab196087 * 975d29b2c44Sab196087 * entry: 976d29b2c44Sab196087 * obj_state - Object state for open object to query. 977d29b2c44Sab196087 * strsec - Descriptor for string table 978d29b2c44Sab196087 * dynsec - NULL, or descriptor for dynamic section. Providing 979d29b2c44Sab196087 * a non-NULL value here will prevent elfedit_strtab_insert() 980d29b2c44Sab196087 * from looking it up, and the duplicate debug message that 981d29b2c44Sab196087 * would result. 982d29b2c44Sab196087 * str - String we are looking for. 983d29b2c44Sab196087 * 984d29b2c44Sab196087 * exit: 985d29b2c44Sab196087 * If the string exists within the string table, or if an attempt 986d29b2c44Sab196087 * to insert it will be successful, quietly return. Otherwise, throw 987d29b2c44Sab196087 * the error elfedit_strtab_insert() would throw under the 988d29b2c44Sab196087 * same circumstances. 989d29b2c44Sab196087 * 990d29b2c44Sab196087 */ 991d29b2c44Sab196087 void 992d29b2c44Sab196087 elfedit_strtab_insert_test(elfedit_obj_state_t *obj_state, 993d29b2c44Sab196087 elfedit_section_t *strsec, elfedit_section_t *dynsec, const char *str) 994d29b2c44Sab196087 { 995d29b2c44Sab196087 Word len; /* Length of str inc. NULL byte */ 996d29b2c44Sab196087 int is_dynstr = 0; 997d29b2c44Sab196087 Word tail_ign = 0; 998d29b2c44Sab196087 999d29b2c44Sab196087 1000d29b2c44Sab196087 /* 1001d29b2c44Sab196087 * The dynstr is a special case, because we can add strings 1002d29b2c44Sab196087 * to it under certain circumstances. So, we look for the 1003d29b2c44Sab196087 * dynamic section, and if it exists, compare its sh_link to 1004d29b2c44Sab196087 * the string section index. If they match, it is the dynstr, 1005d29b2c44Sab196087 * and we use elfedit_dynstr_insert() to do the work. 1006d29b2c44Sab196087 */ 1007d29b2c44Sab196087 if (dynsec == NULL) { 1008d29b2c44Sab196087 if (obj_state->os_dynndx != SHN_UNDEF) { 1009d29b2c44Sab196087 dynsec = &obj_state->os_secarr[obj_state->os_dynndx]; 1010d29b2c44Sab196087 if ((dynsec->sec_shdr->sh_type == SHT_DYNAMIC) && 1011d29b2c44Sab196087 (strsec->sec_shndx == dynsec->sec_shdr->sh_link)) { 1012d29b2c44Sab196087 is_dynstr = 1; 1013d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 1014d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_FNDDYN), 1015d29b2c44Sab196087 EC_WORD(dynsec->sec_shndx), 1016d29b2c44Sab196087 dynsec->sec_name); 1017d29b2c44Sab196087 } 1018d29b2c44Sab196087 } 1019d29b2c44Sab196087 } else { 1020d29b2c44Sab196087 if (strsec->sec_shndx == dynsec->sec_shdr->sh_link) 1021d29b2c44Sab196087 is_dynstr = 1; 1022d29b2c44Sab196087 } 1023d29b2c44Sab196087 1024d29b2c44Sab196087 1025d29b2c44Sab196087 if (is_dynstr) { 1026d29b2c44Sab196087 elfedit_dyn_elt_t dyn_strpad; 1027d29b2c44Sab196087 1028d29b2c44Sab196087 /* Determine the size of the STRPAD area, if any */ 1029d29b2c44Sab196087 elfedit_dyn_elt_init(&dyn_strpad); 1030*4f680cc6SAli Bahrami if (elfedit_dynstr_getpad(obj_state, dynsec, &dyn_strpad) != 0) 1031d29b2c44Sab196087 tail_ign = dyn_strpad.dn_dyn.d_un.d_val; 1032d29b2c44Sab196087 } 1033d29b2c44Sab196087 1034d29b2c44Sab196087 /* 1035d29b2c44Sab196087 * If the string is already in the string table, we 1036d29b2c44Sab196087 * can't fail. 1037d29b2c44Sab196087 */ 1038d29b2c44Sab196087 if (elfedit_sec_findstr(strsec, tail_ign, str, &len) != 0) 1039d29b2c44Sab196087 return; 1040d29b2c44Sab196087 1041d29b2c44Sab196087 /* 1042d29b2c44Sab196087 * It's not in the table, but if this is the dynstr, and 1043d29b2c44Sab196087 * there is enough room, we will be able to add it. 1044d29b2c44Sab196087 */ 1045d29b2c44Sab196087 if (is_dynstr && (tail_ign > strlen(str))) 1046d29b2c44Sab196087 return; 1047d29b2c44Sab196087 1048d29b2c44Sab196087 /* Can't do it. Issue error */ 1049d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRPAD), 1050d29b2c44Sab196087 EC_WORD(strsec->sec_shdr->sh_link), strsec->sec_name); 1051d29b2c44Sab196087 } 1052d29b2c44Sab196087 1053d29b2c44Sab196087 1054d29b2c44Sab196087 /* 1055d29b2c44Sab196087 * Returns the offset of the specified string from within 1056d29b2c44Sab196087 * the given string table, adding it if possible. 1057d29b2c44Sab196087 * 1058d29b2c44Sab196087 * entry: 1059d29b2c44Sab196087 * obj_state - Object state for open object to query. 1060d29b2c44Sab196087 * strsec - Descriptor for string table 1061d29b2c44Sab196087 * dynsec - NULL, or descriptor for dynamic section. Providing 1062d29b2c44Sab196087 * a non-NULL value here will prevent elfedit_strtab_insert() 1063d29b2c44Sab196087 * from looking it up, and the duplicate debug message that 1064d29b2c44Sab196087 * would result. 1065d29b2c44Sab196087 * str - String we are looking for. 1066d29b2c44Sab196087 * 1067d29b2c44Sab196087 * exit: 1068d29b2c44Sab196087 * On success, the offset of the given string within the string 1069d29b2c44Sab196087 * table is returned. If the string does not exist within the table, 1070d29b2c44Sab196087 * and it is possible to add it, elfedit_strtab_insert() will 1071d29b2c44Sab196087 * add the string, and then return the offset. 1072d29b2c44Sab196087 * 1073d29b2c44Sab196087 * If the string does not exist in the string table, and cannot 1074d29b2c44Sab196087 * be added, this routine issues an error message and does not 1075d29b2c44Sab196087 * return to the caller. 1076d29b2c44Sab196087 */ 1077d29b2c44Sab196087 Word 1078d29b2c44Sab196087 elfedit_strtab_insert(elfedit_obj_state_t *obj_state, elfedit_section_t *strsec, 1079d29b2c44Sab196087 elfedit_section_t *dynsec, const char *str) 1080d29b2c44Sab196087 { 1081d29b2c44Sab196087 Word len; /* Length of str inc. NULL byte */ 1082d29b2c44Sab196087 int is_dynstr = 0; 1083d29b2c44Sab196087 elfedit_dyn_elt_t dyn_strpad; 1084d29b2c44Sab196087 1085d29b2c44Sab196087 1086d29b2c44Sab196087 /* 1087d29b2c44Sab196087 * The dynstr is a special case, because we can add strings 1088d29b2c44Sab196087 * to it under certain circumstances. So, we look for the 1089d29b2c44Sab196087 * dynamic section, and if it exists, compare its sh_link to 1090d29b2c44Sab196087 * the string section index. If they match, it is the dynstr, 1091d29b2c44Sab196087 * and we use elfedit_dynstr_insert() to do the work. 1092d29b2c44Sab196087 */ 1093d29b2c44Sab196087 if (dynsec == NULL) { 1094d29b2c44Sab196087 if (obj_state->os_dynndx != SHN_UNDEF) { 1095d29b2c44Sab196087 dynsec = &obj_state->os_secarr[obj_state->os_dynndx]; 1096d29b2c44Sab196087 if ((dynsec->sec_shdr->sh_type == SHT_DYNAMIC) && 1097d29b2c44Sab196087 (strsec->sec_shndx == dynsec->sec_shdr->sh_link)) { 1098d29b2c44Sab196087 is_dynstr = 1; 1099d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 1100d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_FNDDYN), 1101d29b2c44Sab196087 EC_WORD(dynsec->sec_shndx), 1102d29b2c44Sab196087 dynsec->sec_name); 1103d29b2c44Sab196087 } 1104d29b2c44Sab196087 } 1105d29b2c44Sab196087 } else { 1106d29b2c44Sab196087 if (strsec->sec_shndx == dynsec->sec_shdr->sh_link) 1107d29b2c44Sab196087 is_dynstr = 1; 1108d29b2c44Sab196087 } 1109d29b2c44Sab196087 1110d29b2c44Sab196087 if (is_dynstr) { 1111d29b2c44Sab196087 elfedit_dyn_elt_init(&dyn_strpad); 1112*4f680cc6SAli Bahrami (void) elfedit_dynstr_getpad(obj_state, dynsec, &dyn_strpad); 1113d29b2c44Sab196087 return (elfedit_dynstr_insert(dynsec, strsec, 1114d29b2c44Sab196087 &dyn_strpad, str)); 1115d29b2c44Sab196087 } 1116d29b2c44Sab196087 1117d29b2c44Sab196087 /* 1118d29b2c44Sab196087 * This is not the dynstr, so we are limited to strings that 1119d29b2c44Sab196087 * already exist within it. Try to find one. 1120d29b2c44Sab196087 */ 1121d29b2c44Sab196087 if (elfedit_sec_findstr(strsec, 0, str, &len)) 1122d29b2c44Sab196087 return (len); 1123d29b2c44Sab196087 1124d29b2c44Sab196087 /* Can't do it. Issue error */ 1125d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRPAD), 1126d29b2c44Sab196087 EC_WORD(strsec->sec_shdr->sh_link), strsec->sec_name); 1127d29b2c44Sab196087 /*NOTREACHED*/ 1128d29b2c44Sab196087 1129d29b2c44Sab196087 return (0); 1130d29b2c44Sab196087 } 1131d29b2c44Sab196087 1132d29b2c44Sab196087 1133d29b2c44Sab196087 /* 1134d29b2c44Sab196087 * Return the string found at the given offset within the specified 1135d29b2c44Sab196087 * string table. 1136d29b2c44Sab196087 * 1137d29b2c44Sab196087 * entry: 1138d29b2c44Sab196087 * strsec - Section descriptor for string table section 1139d29b2c44Sab196087 * offset - Offset of desired string in string table 1140d29b2c44Sab196087 * msg_type - ELFEDIT_MSG_ type code to use with message 1141d29b2c44Sab196087 * issued if offset is out of range for the symbol table. 1142d29b2c44Sab196087 * debug_msg - True if should issue debug message for string found. 1143d29b2c44Sab196087 * 1144d29b2c44Sab196087 * exit: 1145d29b2c44Sab196087 * If the offset is within the section, the string pointer 1146d29b2c44Sab196087 * is returned. Otherwise an error is issued using msg_type 1147d29b2c44Sab196087 * to determine the type of message. If this routine retains 1148d29b2c44Sab196087 * control after the message is issued, a safe string is returned. 1149d29b2c44Sab196087 */ 1150d29b2c44Sab196087 const char * 1151d29b2c44Sab196087 elfedit_offset_to_str(elfedit_section_t *strsec, Word offset, 1152d29b2c44Sab196087 elfedit_msg_t msg_type, int debug_msg) 1153d29b2c44Sab196087 { 1154d29b2c44Sab196087 const char *str; 1155d29b2c44Sab196087 1156d29b2c44Sab196087 /* Make sure it is a string table section */ 1157d29b2c44Sab196087 if (strsec->sec_shdr->sh_type != SHT_STRTAB) 1158d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOTSTRSH), 1159d29b2c44Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name); 1160d29b2c44Sab196087 1161d29b2c44Sab196087 /* Ensure the offset is in range */ 1162d29b2c44Sab196087 if (offset >= strsec->sec_data->d_size) { 1163d29b2c44Sab196087 elfedit_msg(msg_type, MSG_INTL(MSG_ERR_BADSTROFF), 1164d29b2c44Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name, 1165d29b2c44Sab196087 EC_WORD(offset), EC_WORD(strsec->sec_data->d_size - 1)); 1166d29b2c44Sab196087 /* 1167d29b2c44Sab196087 * If the msg_type is a type that returns, give the 1168d29b2c44Sab196087 * user a safe string to use. 1169d29b2c44Sab196087 */ 1170d29b2c44Sab196087 str = MSG_INTL(MSG_BADSYMOFFSETNAM); 1171d29b2c44Sab196087 } else { 1172d29b2c44Sab196087 /* Return the string */ 1173d29b2c44Sab196087 str = ((const char *)strsec->sec_data->d_buf) + offset; 1174d29b2c44Sab196087 } 1175d29b2c44Sab196087 1176d29b2c44Sab196087 if (debug_msg) 1177d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSTR), 1178d29b2c44Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name, 1179d29b2c44Sab196087 EC_WORD(offset), str); 1180d29b2c44Sab196087 return (str); 1181d29b2c44Sab196087 } 1182d29b2c44Sab196087 1183d29b2c44Sab196087 1184d29b2c44Sab196087 /* 1185d29b2c44Sab196087 * Given a string table section, and a dynamic section entry 1186d29b2c44Sab196087 * that supplies a string offset, return the string found at 1187d29b2c44Sab196087 * the given offset. This routine is a convenience wrapper on 1188d29b2c44Sab196087 * elfedit_offset_to_str(). 1189d29b2c44Sab196087 * 1190d29b2c44Sab196087 * exit: 1191d29b2c44Sab196087 * As per elfedit_offset_to_str(). 1192d29b2c44Sab196087 */ 1193d29b2c44Sab196087 const char * 1194d29b2c44Sab196087 elfedit_dyn_offset_to_str(elfedit_section_t *strsec, elfedit_dyn_elt_t *dynelt) 1195d29b2c44Sab196087 { 1196d29b2c44Sab196087 return (elfedit_offset_to_str(strsec, dynelt->dn_dyn.d_un.d_val, 1197d29b2c44Sab196087 ELFEDIT_MSG_ERR, 0)); 1198d29b2c44Sab196087 } 1199d29b2c44Sab196087 1200d29b2c44Sab196087 1201d29b2c44Sab196087 /* 1202d29b2c44Sab196087 * Given a section, fabricate a string for the form: 1203d29b2c44Sab196087 * 1204d29b2c44Sab196087 * "[#: name]" 1205d29b2c44Sab196087 * 1206d29b2c44Sab196087 * as used at the beginning of debug messages. A pointer to static 1207d29b2c44Sab196087 * memory is returned, and is good until the next such call. 1208d29b2c44Sab196087 */ 1209d29b2c44Sab196087 const char * 1210d29b2c44Sab196087 elfedit_sec_msgprefix(elfedit_section_t *sec) 1211d29b2c44Sab196087 { 1212d29b2c44Sab196087 static char *buf; 1213d29b2c44Sab196087 static size_t bufsize; 1214d29b2c44Sab196087 1215d29b2c44Sab196087 size_t need; 1216d29b2c44Sab196087 1217d29b2c44Sab196087 need = 64 + strlen(sec->sec_name); 1218d29b2c44Sab196087 if (need > bufsize) { 1219d29b2c44Sab196087 buf = elfedit_realloc(MSG_INTL(MSG_ALLOC_SECMSGPRE), buf, need); 1220d29b2c44Sab196087 bufsize = need; 1221d29b2c44Sab196087 } 1222d29b2c44Sab196087 1223d29b2c44Sab196087 (void) snprintf(buf, bufsize, MSG_ORIG(MSG_FMT_SECMSGPRE), 1224d29b2c44Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name); 1225d29b2c44Sab196087 1226d29b2c44Sab196087 return (buf); 1227d29b2c44Sab196087 } 1228