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