15088Sab196087 /* 25088Sab196087 * CDDL HEADER START 35088Sab196087 * 45088Sab196087 * The contents of this file are subject to the terms of the 55088Sab196087 * Common Development and Distribution License (the "License"). 65088Sab196087 * You may not use this file except in compliance with the License. 75088Sab196087 * 85088Sab196087 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95088Sab196087 * or http://www.opensolaris.org/os/licensing. 105088Sab196087 * See the License for the specific language governing permissions 115088Sab196087 * and limitations under the License. 125088Sab196087 * 135088Sab196087 * When distributing Covered Code, include this CDDL HEADER in each 145088Sab196087 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155088Sab196087 * If applicable, add the following below this CDDL HEADER, with the 165088Sab196087 * fields enclosed by brackets "[]" replaced with your own identifying 175088Sab196087 * information: Portions Copyright [yyyy] [name of copyright owner] 185088Sab196087 * 195088Sab196087 * CDDL HEADER END 205088Sab196087 */ 215088Sab196087 225088Sab196087 /* 235892Sab196087 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 245088Sab196087 * Use is subject to license terms. 255088Sab196087 */ 265088Sab196087 #pragma ident "%Z%%M% %I% %E% SMI" 275088Sab196087 285088Sab196087 #include <stdlib.h> 295088Sab196087 #include <stdio.h> 305088Sab196087 #include <unistd.h> 315088Sab196087 #include <libintl.h> 32*6206Sab196087 #include <_machelf.h> 335088Sab196087 #include <libelf.h> 345088Sab196087 #include <link.h> 355088Sab196087 #include <strings.h> 365088Sab196087 #include <ctype.h> 375088Sab196087 #include "msg.h" 385088Sab196087 #include <elfedit.h> 395088Sab196087 #include <conv.h> 405088Sab196087 #include <sys/elf_SPARC.h> 415088Sab196087 #include <sys/elf_amd64.h> 425088Sab196087 435088Sab196087 445088Sab196087 455088Sab196087 /* 465088Sab196087 * ELFCLASS specific code that would otherwise be found in util.c 475088Sab196087 */ 485088Sab196087 495088Sab196087 505088Sab196087 515088Sab196087 525088Sab196087 /* 535088Sab196087 * When you modify ELF constructs, you need to tell libelf that you've 545088Sab196087 * done so. Otherwise, the changes may not be flushed back to the 555088Sab196087 * output file. 565088Sab196087 * 575088Sab196087 * The elfedit_modified_*() functions exist to simplify the calls to 585088Sab196087 * the underlying elf_flag*() functions. 595088Sab196087 */ 605088Sab196087 void 615088Sab196087 elfedit_modified_ehdr(elfedit_obj_state_t *obj_state) 625088Sab196087 { 635088Sab196087 (void) elf_flagehdr(obj_state->os_elf, ELF_C_SET, ELF_F_DIRTY); 645088Sab196087 } 655088Sab196087 665088Sab196087 void 675088Sab196087 elfedit_modified_phdr(elfedit_obj_state_t *obj_state) 685088Sab196087 { 695088Sab196087 (void) elf_flagphdr(obj_state->os_elf, ELF_C_SET, ELF_F_DIRTY); 705088Sab196087 } 715088Sab196087 725088Sab196087 void 735088Sab196087 elfedit_modified_shdr(elfedit_section_t *s) 745088Sab196087 { 755088Sab196087 (void) elf_flagshdr(s->sec_scn, ELF_C_SET, ELF_F_DIRTY); 765088Sab196087 } 775088Sab196087 785088Sab196087 void 795088Sab196087 elfedit_modified_data(elfedit_section_t *s) 805088Sab196087 { 815088Sab196087 (void) elf_flagdata(s->sec_data, ELF_C_SET, ELF_F_DIRTY); 825088Sab196087 } 835088Sab196087 845088Sab196087 855088Sab196087 865088Sab196087 /* 875088Sab196087 * Prepare an elfedit_dyn_elt_t structure for use. 885088Sab196087 */ 895088Sab196087 void 905088Sab196087 elfedit_dyn_elt_init(elfedit_dyn_elt_t *elt) 915088Sab196087 { 925088Sab196087 elt->dn_seen = 0; 935088Sab196087 } 945088Sab196087 955088Sab196087 /* 965088Sab196087 * Given a dynamic section item, save it in the given elfedit_dyn_elt_t 975088Sab196087 * structure and mark that structure to show that it is present. 985088Sab196087 */ 995088Sab196087 void 1005088Sab196087 elfedit_dyn_elt_save(elfedit_dyn_elt_t *elt, Word ndx, Dyn *dyn) 1015088Sab196087 { 1025088Sab196087 elt->dn_seen = 1; 1035088Sab196087 elt->dn_ndx = ndx; 1045088Sab196087 elt->dn_dyn = *dyn; 1055088Sab196087 } 1065088Sab196087 1075088Sab196087 1085088Sab196087 /* 1095088Sab196087 * Return the index of the first section that has the given name. 1105088Sab196087 * 1115088Sab196087 * entry: 1125088Sab196087 * obj_state - Object state. 1135088Sab196087 * shnam - Name of desired section 1145088Sab196087 * 1155088Sab196087 * exit: 1165088Sab196087 * On success, returns the section index. On failure, an error 1175088Sab196087 * is issued, and this routine does not return to the caller. 1185088Sab196087 */ 1195088Sab196087 Word 1205088Sab196087 elfedit_name_to_shndx(elfedit_obj_state_t *obj_state, const char *shnam) 1215088Sab196087 { 1225088Sab196087 elfedit_section_t *sec = obj_state->os_secarr; 1235088Sab196087 Word ndx; 1245088Sab196087 Word shnum = obj_state->os_shnum; 1255088Sab196087 1265088Sab196087 for (ndx = 0; ndx < shnum; ndx++, sec++) { 1275088Sab196087 if (strcmp(shnam, sec->sec_name) == 0) { 1285088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 1295088Sab196087 MSG_INTL(MSG_DEBUG_SHNAM2NDX), 1305088Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name, shnam); 1315088Sab196087 return (ndx); 1325088Sab196087 } 1335088Sab196087 } 1345088Sab196087 1355088Sab196087 /* If didn't return in loop above, the name doesn't match */ 1365088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSECNAM), shnam); 1375088Sab196087 /*NOTREACHED*/ 1385088Sab196087 return (SHN_UNDEF); 1395088Sab196087 } 1405088Sab196087 1415088Sab196087 1425088Sab196087 1435088Sab196087 /* 1445088Sab196087 * Return the index of the first section that has the given type. 1455088Sab196087 * 1465088Sab196087 * entry: 1475088Sab196087 * obj_state - Object state. 1485088Sab196087 * shtype - Type of desired section 1495088Sab196087 * 1505088Sab196087 * exit: 1515088Sab196087 * On success, returns the section index. On failure, an error 1525088Sab196087 * is issued, and this routine does not return to the caller. 1535088Sab196087 */ 1545088Sab196087 Word 1555088Sab196087 elfedit_type_to_shndx(elfedit_obj_state_t *obj_state, Word shtype) 1565088Sab196087 { 1575088Sab196087 Conv_inv_buf_t inv_buf; 1585088Sab196087 elfedit_section_t *sec = obj_state->os_secarr; 1595088Sab196087 Word ndx; 1605088Sab196087 Word shnum = obj_state->os_shnum; 1615088Sab196087 1625088Sab196087 for (ndx = 0; ndx < shnum; ndx++, sec++) { 1635088Sab196087 if (shtype == sec->sec_shdr->sh_type) { 1645088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 1655088Sab196087 MSG_INTL(MSG_DEBUG_SHNAM2NDX), 1665088Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name, 1675088Sab196087 conv_sec_type(obj_state->os_ehdr->e_machine, 1685088Sab196087 shtype, 0, &inv_buf)); 1695088Sab196087 return (ndx); 1705088Sab196087 } 1715088Sab196087 } 1725088Sab196087 1735088Sab196087 /* If didn't return in loop above, the name doesn't match */ 1745088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSECTYP), 1755088Sab196087 conv_sec_type(obj_state->os_ehdr->e_machine, shtype, 0, &inv_buf)); 1765088Sab196087 /*NOTREACHED*/ 1775088Sab196087 return (SHN_UNDEF); 1785088Sab196087 } 1795088Sab196087 1805088Sab196087 1815088Sab196087 1825088Sab196087 /* 1835088Sab196087 * Locate the index of the first symbol that has the given name 1845088Sab196087 * 1855088Sab196087 * entry: 1865088Sab196087 * obj_state - Object state. 1875088Sab196087 * symsec - Symbol section 1885088Sab196087 * strsec = String section 1895088Sab196087 * name - String giving name of symbol to lookup 1905088Sab196087 * msg_type - ELFEDIT_MSG_ type code to use with message 1915088Sab196087 * issued if name does not exist in symbol table. 1925088Sab196087 * ret_symndx - Address of variable to receive index. 1935088Sab196087 * 1945088Sab196087 * exit: 1955088Sab196087 * On success, issues debug message, sets *ret_symndx, and returns 1965088Sab196087 * True (1). 1975088Sab196087 * 1985088Sab196087 * On failure, issues a message using msg_type to determine 1995088Sab196087 * the type of message sent. If the message does not take control away 2005088Sab196087 * from the caller, False (0) is returned. 2015088Sab196087 * 2025088Sab196087 * note: 2035088Sab196087 * Although the string table is referenced by the sh_link field of 2045088Sab196087 * the symbol table, we require the user to supply it rather than 2055088Sab196087 * look it up. The reason for this is that the caller will usually 2065088Sab196087 * have looked it up, and we wish to avoid multiple debug messages 2075088Sab196087 * from being issued to that effect. 2085088Sab196087 */ 2095088Sab196087 int 2105088Sab196087 elfedit_name_to_symndx(elfedit_section_t *symsec, elfedit_section_t *strsec, 2115088Sab196087 const char *name, elfedit_msg_t msg_type, Word *ret_symndx) 2125088Sab196087 2135088Sab196087 { 2145088Sab196087 Sym *sym = (Sym *) symsec->sec_data->d_buf; 2155088Sab196087 Word cnt = symsec->sec_shdr->sh_size / symsec->sec_shdr->sh_entsize; 2165088Sab196087 Word ndx, offset; 2175088Sab196087 const char *curname; 2185088Sab196087 2195088Sab196087 for (ndx = 0; ndx < cnt; ndx++) { 2205088Sab196087 offset = sym[ndx].st_name; 2215088Sab196087 2225088Sab196087 curname = elfedit_offset_to_str(strsec, offset, 2235088Sab196087 ELFEDIT_MSG_ERR, 0); 2245088Sab196087 if (strcmp(curname, name) == 0) { 2255088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 2265088Sab196087 MSG_INTL(MSG_DEBUG_SYMNAM2NDX), 2275088Sab196087 EC_WORD(symsec->sec_shndx), 2285088Sab196087 symsec->sec_name, EC_WORD(ndx), name); 2295088Sab196087 *ret_symndx = ndx; 2305088Sab196087 return (1); 2315088Sab196087 } 2325088Sab196087 } 2335088Sab196087 2345088Sab196087 /* If didn't return in loop above, the name doesn't match */ 2355088Sab196087 elfedit_msg(msg_type, MSG_INTL(MSG_ERR_NOSYM), 2365088Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name, name); 2375088Sab196087 /*NOTREACHED*/ 2385088Sab196087 return (0); /* lint */ 2395088Sab196087 } 2405088Sab196087 2415088Sab196087 2425088Sab196087 /* 2435088Sab196087 * Given a section index, turn it into a descriptive string. 2445088Sab196087 * - If it is one of the special reserved indexes, the 2455088Sab196087 * symbolic name is returned. 2465088Sab196087 * - If it is a regular section, in range for the file, 2475088Sab196087 * the name associated with the section is returned. 2485088Sab196087 * - Otherwise, the number is formatted as numeric ASCII. 2495088Sab196087 * 2505088Sab196087 * exit: 2515088Sab196087 * A pointer to the static buffer containing the name is 2525088Sab196087 * returned. This pointer is valid until the next call 2535088Sab196087 * to elfedit_shndx_to_name(), and which point it may 2545088Sab196087 * be overwritten. 2555088Sab196087 */ 2565088Sab196087 const char * 2575088Sab196087 elfedit_shndx_to_name(elfedit_obj_state_t *obj_state, Word shndx) 2585088Sab196087 { 2595088Sab196087 /* 2605088Sab196087 * This routine can be called twice within a single C statement, 2615088Sab196087 * so we use alternating buffers on each call to allow this 2625088Sab196087 * without requiring the caller to supply a buffer (the size of 2635088Sab196087 * which they don't know). 2645088Sab196087 */ 2655088Sab196087 static char buf1[64], buf2[64]; 2665088Sab196087 static char *buf; 2675088Sab196087 2685088Sab196087 if ((obj_state->os_ehdr->e_machine == EM_AMD64) && 2695088Sab196087 (shndx == SHN_AMD64_LCOMMON)) 2705088Sab196087 return (MSG_ORIG(MSG_SHN_AMD64_LCOMMON)); 2715088Sab196087 2725088Sab196087 switch (shndx) { 2735088Sab196087 case SHN_UNDEF: 2745088Sab196087 return (MSG_ORIG(MSG_SHN_UNDEF)); 2755088Sab196087 case SHN_SUNW_IGNORE: 2765088Sab196087 return (MSG_ORIG(MSG_SHN_SUNW_IGNORE)); 2775088Sab196087 case SHN_BEFORE: 2785088Sab196087 return (MSG_ORIG(MSG_SHN_BEFORE)); 2795088Sab196087 case SHN_AFTER: 2805088Sab196087 return (MSG_ORIG(MSG_SHN_AFTER)); 2815088Sab196087 case SHN_AMD64_LCOMMON: 2825088Sab196087 if (obj_state->os_ehdr->e_machine == EM_AMD64) 2835088Sab196087 return (MSG_ORIG(MSG_SHN_AMD64_LCOMMON)); 2845088Sab196087 break; 2855088Sab196087 case SHN_ABS: 2865088Sab196087 return (MSG_ORIG(MSG_SHN_ABS)); 2875088Sab196087 case SHN_COMMON: 2885088Sab196087 return (MSG_ORIG(MSG_SHN_COMMON)); 2895088Sab196087 case SHN_XINDEX: 2905088Sab196087 return (MSG_ORIG(MSG_SHN_XINDEX)); 2915088Sab196087 } 2925088Sab196087 2935088Sab196087 2945088Sab196087 /* 2955088Sab196087 * If it is outside of the reserved area, and inside the 2965088Sab196087 * range of section indexes in the ELF file, then show 2975088Sab196087 * the section name. 2985088Sab196087 */ 2995088Sab196087 if ((shndx < obj_state->os_shnum) && 3005088Sab196087 ((shndx < SHN_LORESERVE) || (shndx > SHN_HIRESERVE))) 3015088Sab196087 return (obj_state->os_secarr[shndx].sec_name); 3025088Sab196087 3035088Sab196087 /* Switch buffers */ 3045088Sab196087 buf = (buf == buf1) ? buf2 : buf1; 3055088Sab196087 3065088Sab196087 /* 3075088Sab196087 * If we haven't identified it by now, format the 3085088Sab196087 * number in a static buffer and return that. 3095088Sab196087 */ 3105088Sab196087 (void) snprintf(buf, sizeof (buf1), 3115088Sab196087 MSG_ORIG(MSG_FMT_WORDVAL), shndx); 3125088Sab196087 return (buf); 3135088Sab196087 } 3145088Sab196087 3155088Sab196087 3165088Sab196087 /* 3175892Sab196087 * Locate the arbitrary section specified by shndx for this object. 3185892Sab196087 * 3195892Sab196087 * exit: 3205892Sab196087 * Returns section descriptor on success. On failure, does not return. 3215892Sab196087 */ 3225892Sab196087 elfedit_section_t * 3235892Sab196087 elfedit_sec_get(elfedit_obj_state_t *obj_state, Word shndx) 3245892Sab196087 { 3255892Sab196087 elfedit_section_t *sec; 3265892Sab196087 3275892Sab196087 if ((shndx == 0) || (shndx >= obj_state->os_shnum)) 3285892Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADSECNDX), 3295892Sab196087 EC_WORD(shndx), EC_WORD(obj_state->os_shnum - 1)); 3305892Sab196087 3315892Sab196087 sec = &obj_state->os_secarr[shndx]; 3325892Sab196087 3335892Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSEC), 3345892Sab196087 EC_WORD(shndx), sec->sec_name); 3355892Sab196087 return (sec); 3365892Sab196087 } 3375892Sab196087 3385892Sab196087 3395892Sab196087 /* 3405088Sab196087 * Locate the capabilities section for this object 3415088Sab196087 * 3425088Sab196087 * entry: 3435088Sab196087 * obj_state - Object state for open object to query. 3445088Sab196087 * cap - Address of variable to recieve pointer to capabilities 3455088Sab196087 * section data buffer. 3465088Sab196087 * num - Address of variable to receive number of items 3475088Sab196087 * referenced by cap. 3485088Sab196087 * 3495088Sab196087 * exit: 3505088Sab196087 * On success, returns section descriptor, and sets the 3515088Sab196087 * variables referenced by cap and num. On failure, 3525088Sab196087 * does not return. 3535088Sab196087 */ 3545088Sab196087 elfedit_section_t * 3555088Sab196087 elfedit_sec_getcap(elfedit_obj_state_t *obj_state, Cap **cap, Word *num) 3565088Sab196087 { 3575088Sab196087 Word cnt; 3585088Sab196087 elfedit_section_t *cache; 3595088Sab196087 3605088Sab196087 for (cnt = 1; cnt < obj_state->os_shnum; cnt++) { 3615088Sab196087 cache = &obj_state->os_secarr[cnt]; 3625088Sab196087 if (cache->sec_shdr->sh_type == SHT_SUNW_cap) { 3635088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 3645088Sab196087 MSG_INTL(MSG_DEBUG_FNDCAP), 3655088Sab196087 EC_WORD(cnt), cache->sec_name); 3665088Sab196087 *cap = (Cap *) cache->sec_data->d_buf; 3675088Sab196087 *num = cache->sec_shdr->sh_size / 3685088Sab196087 cache->sec_shdr->sh_entsize; 3695088Sab196087 return (cache); 3705088Sab196087 } 3715088Sab196087 } 3725088Sab196087 3735088Sab196087 /* If here, this object has no capabilities section */ 3745088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAP)); 3755088Sab196087 3765088Sab196087 /*NOTREACHED*/ 3775088Sab196087 return (NULL); 3785088Sab196087 } 3795088Sab196087 3805088Sab196087 3815088Sab196087 /* 3825088Sab196087 * Locate the dynamic section for this object 3835088Sab196087 * 3845088Sab196087 * entry: 3855088Sab196087 * obj_state - Object state for open object to query. 3865088Sab196087 * dyn - Address of variable to recieve pointer to dynamic 3875088Sab196087 * section data buffer. 3885088Sab196087 * numdyn - Address of variable to receive number of items 3895088Sab196087 * referenced by dyn. 3905088Sab196087 * 3915088Sab196087 * exit: 3925088Sab196087 * On success, returns section descriptor, and sets the 3935088Sab196087 * variables referenced by dyn and numdyn. On failure, 3945088Sab196087 * does not return. 3955088Sab196087 */ 3965088Sab196087 elfedit_section_t * 3975088Sab196087 elfedit_sec_getdyn(elfedit_obj_state_t *obj_state, Dyn **dyn, Word *num) 3985088Sab196087 { 3995088Sab196087 elfedit_section_t *cache; 4005088Sab196087 4015088Sab196087 if (obj_state->os_dynndx != SHN_UNDEF) { 4025088Sab196087 cache = &obj_state->os_secarr[obj_state->os_dynndx]; 4035088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDDYN), 4045088Sab196087 EC_WORD(cache->sec_shndx), cache->sec_name); 4055088Sab196087 *dyn = (Dyn *) cache->sec_data->d_buf; 4065088Sab196087 *num = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize; 4075088Sab196087 return (cache); 4085088Sab196087 } 4095088Sab196087 4105088Sab196087 /* If here, this object has no dynamic section */ 4115088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODYN)); 4125088Sab196087 4135088Sab196087 /*NOTREACHED*/ 4145088Sab196087 return (NULL); 4155088Sab196087 } 4165088Sab196087 4175088Sab196087 4185088Sab196087 /* 4195088Sab196087 * Locate the syminfo section for this object 4205088Sab196087 * 4215088Sab196087 * entry: 4225088Sab196087 * obj_state - Object state for open object to query. 4235088Sab196087 * syminfo - Address of variable to recieve pointer to syminfo 4245088Sab196087 * section data buffer. 4255088Sab196087 * num - Address of variable to receive number of items 4265088Sab196087 * referenced by syminfo. 4275088Sab196087 * 4285088Sab196087 * exit: 4295088Sab196087 * On success, returns section descriptor, and sets the 4305088Sab196087 * variables referenced by syminfo and num. On failure, 4315088Sab196087 * does not return. 4325088Sab196087 */ 4335088Sab196087 elfedit_section_t * 4345088Sab196087 elfedit_sec_getsyminfo(elfedit_obj_state_t *obj_state, Syminfo **syminfo, 4355088Sab196087 Word *num) 4365088Sab196087 { 4375088Sab196087 Word cnt; 4385088Sab196087 elfedit_section_t *cache; 4395088Sab196087 4405088Sab196087 for (cnt = 1; cnt < obj_state->os_shnum; cnt++) { 4415088Sab196087 cache = &obj_state->os_secarr[cnt]; 4425088Sab196087 if (cache->sec_shdr->sh_type == SHT_SUNW_syminfo) { 4435088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 4445088Sab196087 MSG_INTL(MSG_DEBUG_FNDSYMINFO), 4455088Sab196087 EC_WORD(cnt), cache->sec_name); 4465088Sab196087 *syminfo = (Syminfo *) cache->sec_data->d_buf; 4475088Sab196087 *num = cache->sec_shdr->sh_size / 4485088Sab196087 cache->sec_shdr->sh_entsize; 4495088Sab196087 return (cache); 4505088Sab196087 } 4515088Sab196087 } 4525088Sab196087 4535088Sab196087 /* If here, this object has no syminfo section */ 4545088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSYMINFO)); 4555088Sab196087 4565088Sab196087 /*NOTREACHED*/ 4575088Sab196087 return (NULL); 4585088Sab196087 } 4595088Sab196087 4605088Sab196087 4615088Sab196087 /* 4625088Sab196087 * Check the given section to see if it is a known symbol table type. 4635088Sab196087 * 4645088Sab196087 * entry: 4655088Sab196087 * sec - Section to check 4665088Sab196087 * issue_err - True if this routine should issue an error and 4675088Sab196087 * not return to the caller if sec is not a symbol table. 4685088Sab196087 * atoui_list - NULL, or address of variable to receive a pointer to 4695088Sab196087 * an array of elfedit_atoui_sym_t items describing the 4705088Sab196087 * type of symbol table found. This array is useful for 4715088Sab196087 * doing command completion. 4725088Sab196087 * 4735088Sab196087 * exit: 4745088Sab196087 * If sec is a symbol table: 4755088Sab196087 * - If atoui_list is non-NULL, *atoui_list is set to the 4765088Sab196087 * appropriate ELFEDIT_CONST_xx list of items. 4775088Sab196087 * - True (1) is returned 4785088Sab196087 * If sec is not a symbol table and issue_err is True: 4795088Sab196087 * - An error is issued, and this routine does not 4805088Sab196087 * return to the caller. 4815088Sab196087 * Otherwise: 4825088Sab196087 * - If atoui_list is non-NULL, *atoui_list is set to NULL. 4835088Sab196087 * - False (0) is returned 4845088Sab196087 */ 4855088Sab196087 int 4865088Sab196087 elfedit_sec_issymtab(elfedit_section_t *sec, int issue_err, 4875088Sab196087 elfedit_atoui_sym_t **atoui_list) 4885088Sab196087 { 4895088Sab196087 elfedit_const_t const_type; 4905088Sab196087 int ret = 1; 4915088Sab196087 4925088Sab196087 /* Is the section a symbol table? */ 4935088Sab196087 switch (sec->sec_shdr->sh_type) { 4945088Sab196087 case SHT_SYMTAB: 4955088Sab196087 const_type = ELFEDIT_CONST_SHT_SYMTAB; 4965088Sab196087 break; 4975088Sab196087 case SHT_DYNSYM: 4985088Sab196087 const_type = ELFEDIT_CONST_SHT_DYNSYM; 4995088Sab196087 break; 5005088Sab196087 case SHT_SUNW_LDYNSYM: 5015088Sab196087 const_type = ELFEDIT_CONST_SHT_LDYNSYM; 5025088Sab196087 break; 5035088Sab196087 default: 5045088Sab196087 if (issue_err) 5055088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 5065088Sab196087 MSG_INTL(MSG_ERR_NOTSYMTAB), 5075088Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name); 5085088Sab196087 ret = 0; 5095088Sab196087 break; 5105088Sab196087 } 5115088Sab196087 5125088Sab196087 if (atoui_list != NULL) 5135088Sab196087 *atoui_list = (ret == 0) ? NULL : 5145088Sab196087 elfedit_const_to_atoui(const_type); 5155088Sab196087 5165088Sab196087 return (ret); 5175088Sab196087 } 5185088Sab196087 5195088Sab196087 5205088Sab196087 5215088Sab196087 /* 5225088Sab196087 * Locate a symbol table section for this object 5235088Sab196087 * 5245088Sab196087 * entry: 5255088Sab196087 * obj_state - Object state for open object to query. 5265088Sab196087 * by_index - If True, we want to locate the section with the 5275088Sab196087 * section index given by index. If False, we return 5285088Sab196087 * the section with the name given by name. 5295088Sab196087 * index, name - Key to search for. See by_index. 5305088Sab196087 * sym - Address of variable to recieve pointer to symbol 5315088Sab196087 * section data buffer. 5325088Sab196087 * numsym - Address of variable to receive number of symbols 5335088Sab196087 * referenced by sym. 5345088Sab196087 * aux_info - Address of variable to receive pointer to the 5355088Sab196087 * elfedit_symtab_t struct that ties the symbol table and 5365088Sab196087 * its related auxiliary sections together. NULL if this 5375088Sab196087 * information is not required. 5385088Sab196087 * 5395088Sab196087 * exit: 5405088Sab196087 * On success, returns section descriptor, and sets the 5415088Sab196087 * variables referenced by sym, and numsym. On failure, 5425088Sab196087 * does not return. 5435088Sab196087 */ 5445088Sab196087 elfedit_section_t * 5455088Sab196087 elfedit_sec_getsymtab(elfedit_obj_state_t *obj_state, int by_index, 5465088Sab196087 Word index, const char *name, Sym **sym, Word *num, 5475088Sab196087 elfedit_symtab_t **aux_info) 5485088Sab196087 { 5495088Sab196087 Word ndx; 5505088Sab196087 elfedit_section_t *symsec = NULL; 5515088Sab196087 elfedit_symtab_t *symtab; 5525088Sab196087 const char *type_name; 5535088Sab196087 5545088Sab196087 /* If looking it up by index, make sure the index is in range */ 5555088Sab196087 if (by_index && (index >= obj_state->os_shnum)) 5565088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADSECNDX), 5575088Sab196087 EC_WORD(index), EC_WORD(obj_state->os_shnum - 1)); 5585088Sab196087 5595088Sab196087 /* 5605088Sab196087 * Look at each known symbol table in turn until the desired 5615088Sab196087 * one is hit, or there are no more. 5625088Sab196087 */ 5635088Sab196087 symtab = obj_state->os_symtab; 5645088Sab196087 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) { 5655088Sab196087 elfedit_section_t *s = 5665088Sab196087 &obj_state->os_secarr[symtab->symt_shndx]; 5675088Sab196087 5685088Sab196087 if ((by_index && (symtab->symt_shndx == index)) || 5695088Sab196087 (!by_index && (strcmp(s->sec_name, name) == 0))) { 5705088Sab196087 symsec = s; 5715088Sab196087 break; 5725088Sab196087 } 5735088Sab196087 } 5745088Sab196087 5755088Sab196087 /* Did we get a section? */ 5765088Sab196087 if (symsec == NULL) 5775088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSYMTAB)); 5785088Sab196087 5795088Sab196087 /* Got it. Report to the user and return the necessary data */ 5805088Sab196087 (void) elfedit_sec_issymtab(symsec, 1, NULL); 5815088Sab196087 type_name = elfedit_atoconst_value_to_str(ELFEDIT_CONST_SHT_ALLSYMTAB, 5825088Sab196087 symsec->sec_shdr->sh_type, 1); 5835088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSYMTAB), 5845088Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name, type_name); 5855088Sab196087 *sym = (Sym *) symsec->sec_data->d_buf; 5865088Sab196087 *num = symsec->sec_shdr->sh_size / symsec->sec_shdr->sh_entsize; 5875088Sab196087 if (aux_info != NULL) 5885088Sab196087 *aux_info = symtab; 5895088Sab196087 return (symsec); 5905088Sab196087 } 5915088Sab196087 5925088Sab196087 5935088Sab196087 5945088Sab196087 /* 5955088Sab196087 * Locate the extended symbol index section associated with a symbol 5965088Sab196087 * table section. 5975088Sab196087 * 5985088Sab196087 * entry: 5995088Sab196087 * obj_state - Object state for open object to query. 6005088Sab196087 * symsec - Symbol table section for which extended index 6015088Sab196087 * index section is required. 6025088Sab196087 * xshndx - Address of variable to recieve pointer to section index 6035088Sab196087 * array data buffer. 6045088Sab196087 * numxshndx - Address of variable to receive number of indices 6055088Sab196087 * referenced by ndx. 6065088Sab196087 * 6075088Sab196087 * exit: 6085088Sab196087 * On success, returns extended index section descriptor, and sets the 6095088Sab196087 * variables referenced by xshndx, and numxshndx. On failure, 6105088Sab196087 * does not return. 6115088Sab196087 * 6125088Sab196087 * note: 6135088Sab196087 * Since the extended section index is found in the sec_xshndx field 6145088Sab196087 * of the elfedit_section_t, the caller may be tempted to bypass this 6155088Sab196087 * routine and access it directly. That temptation should be resisted, 6165088Sab196087 * as this routine performs useful error checking, and also handles 6175088Sab196087 * the issuing of the standard MSG_DEBUG messages. 6185088Sab196087 */ 6195088Sab196087 elfedit_section_t * 6205088Sab196087 elfedit_sec_getxshndx(elfedit_obj_state_t *obj_state, 6215088Sab196087 elfedit_section_t *symsec, Word **xshndx, Word *num) 6225088Sab196087 { 6235088Sab196087 elfedit_section_t *xshndxsec; 6245088Sab196087 elfedit_symtab_t *symtab; 6255088Sab196087 Word ndx; 6265088Sab196087 6275088Sab196087 /* Sanity check: symsec must be a symbol table */ 6285088Sab196087 (void) elfedit_sec_issymtab(symsec, 1, NULL); 6295088Sab196087 6305088Sab196087 symtab = obj_state->os_symtab; 6315088Sab196087 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) 6325088Sab196087 if (symsec->sec_shndx == symtab->symt_shndx) 6335088Sab196087 break; 6345088Sab196087 6355088Sab196087 /* 6365088Sab196087 * Issue error if the symbol table lacks an extended index section. 6375088Sab196087 * The caller won't ask unless they encounter an SHN_XINDEX value, 6385088Sab196087 * in which case the lack of the index section denotes a corrupt 6395088Sab196087 * ELF file. 6405088Sab196087 */ 6415088Sab196087 if ((ndx == obj_state->os_symtabnum) || 6425088Sab196087 (symtab->symt_xshndx == SHN_UNDEF)) 6435088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOXSHSEC), 6445088Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name); 6455088Sab196087 6465088Sab196087 /* Got it. Report to the user and return the necessary data */ 6475088Sab196087 xshndxsec = &obj_state->os_secarr[symtab->symt_xshndx]; 6485088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDXSHNDX), 6495088Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name, 6505088Sab196087 EC_WORD(xshndxsec->sec_shndx), xshndxsec->sec_name); 6515088Sab196087 *xshndx = (Word *) xshndxsec->sec_data->d_buf; 6525088Sab196087 *num = xshndxsec->sec_shdr->sh_size / xshndxsec->sec_shdr->sh_entsize; 6535088Sab196087 return (xshndxsec); 6545088Sab196087 } 6555088Sab196087 6565088Sab196087 6575088Sab196087 6585088Sab196087 /* 6595088Sab196087 * Locate the versym section associated with a symbol table section. 6605088Sab196087 * 6615088Sab196087 * entry: 6625088Sab196087 * obj_state - Object state for open object to query. 6635088Sab196087 * symsec - Symbol table section for which extended index 6645088Sab196087 * index section is required. 6655088Sab196087 * versym - Address of variable to recieve pointer to section index 6665088Sab196087 * array data buffer. 6675088Sab196087 * numversym - Address of variable to receive number of indices 6685088Sab196087 * referenced by ndx. 6695088Sab196087 * 6705088Sab196087 * exit: 6715088Sab196087 * On success, returns versym section descriptor, and sets the 6725088Sab196087 * variables referenced by versym, and numversym. On failure, 6735088Sab196087 * does not return. 6745088Sab196087 * 6755088Sab196087 * note: 6765088Sab196087 * Since the versym section index is found in the sec_versym field 6775088Sab196087 * of the elfedit_section_t, the caller may be tempted to bypass this 6785088Sab196087 * routine and access it directly. That temptation should be resisted, 6795088Sab196087 * as this routine performs useful error checking, and also handles 6805088Sab196087 * the issuing of the standard MSG_DEBUG messages. 6815088Sab196087 */ 6825088Sab196087 elfedit_section_t * 6835088Sab196087 elfedit_sec_getversym(elfedit_obj_state_t *obj_state, 6845088Sab196087 elfedit_section_t *symsec, Versym **versym, Word *num) 6855088Sab196087 { 6865088Sab196087 elfedit_section_t *versymsec; 6875088Sab196087 elfedit_symtab_t *symtab; 6885088Sab196087 Word ndx; 6895088Sab196087 6905088Sab196087 /* Sanity check: symsec must be a symbol table */ 6915088Sab196087 (void) elfedit_sec_issymtab(symsec, 1, NULL); 6925088Sab196087 6935088Sab196087 symtab = obj_state->os_symtab; 6945088Sab196087 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) 6955088Sab196087 if (symsec->sec_shndx == symtab->symt_shndx) 6965088Sab196087 break; 6975088Sab196087 /* 6985088Sab196087 * Issue error if the symbol table lacks a versym section. 6995088Sab196087 * The caller won't ask unless they see a non-null 7005088Sab196087 * aux.symtab.sec_versym, so this should not be a problem. 7015088Sab196087 */ 7025088Sab196087 if ((ndx == obj_state->os_symtabnum) || 7035088Sab196087 (symtab->symt_versym == SHN_UNDEF)) 7045088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOVERSYMSEC), 7055088Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name); 7065088Sab196087 7075088Sab196087 /* Got it. Report to the user and return the necessary data */ 7085088Sab196087 versymsec = &obj_state->os_secarr[symtab->symt_versym]; 7095088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDVERSYM), 7105088Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name, 7115088Sab196087 EC_WORD(versymsec->sec_shndx), versymsec->sec_name); 7125088Sab196087 *versym = (Versym *) versymsec->sec_data->d_buf; 7135088Sab196087 *num = versymsec->sec_shdr->sh_size / versymsec->sec_shdr->sh_entsize; 7145088Sab196087 return (versymsec); 7155088Sab196087 } 7165088Sab196087 7175088Sab196087 7185088Sab196087 7195088Sab196087 /* 7205088Sab196087 * Locate the string table specified by shndx for this object. 7215088Sab196087 * 7225088Sab196087 * exit: 7235088Sab196087 * Returns section descriptor on success. On failure, does not return. 7245088Sab196087 */ 7255088Sab196087 elfedit_section_t * 7265088Sab196087 elfedit_sec_getstr(elfedit_obj_state_t *obj_state, Word shndx) 7275088Sab196087 { 7285088Sab196087 elfedit_section_t *strsec; 7295088Sab196087 7305088Sab196087 if ((shndx == 0) || (shndx >= obj_state->os_shnum)) 7315088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_STRSHNDX), 7325892Sab196087 EC_WORD(shndx), EC_WORD(obj_state->os_shnum - 1)); 7335088Sab196087 7345088Sab196087 strsec = &obj_state->os_secarr[shndx]; 7355088Sab196087 if (strsec->sec_shdr->sh_type != SHT_STRTAB) 7365088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOTSTRSH), 7375088Sab196087 EC_WORD(shndx), strsec->sec_name); 7385088Sab196087 7395088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSTRTAB), 7405088Sab196087 EC_WORD(shndx), strsec->sec_name); 7415088Sab196087 return (strsec); 7425088Sab196087 } 7435088Sab196087 7445088Sab196087 7455088Sab196087 /* 7465088Sab196087 * Returns the offset of the specified string from within 7475088Sab196087 * the given section. 7485088Sab196087 * 7495088Sab196087 * entry: 7505088Sab196087 * sec - Descriptor for section 7515088Sab196087 * tail_ign - If non-zero, the # of characters at the end of the 7525088Sab196087 * section that should be ignored and not searched. 7535088Sab196087 * str - String we are looking for. 7545088Sab196087 * ret_offset - Address of variable to receive result 7555088Sab196087 * 7565088Sab196087 * exit: 7575088Sab196087 * Returns 1 for success, and 0 for failure. If successful, *ret_offset 7585088Sab196087 * is set to the offset of the found string within the section. 7595088Sab196087 */ 7605088Sab196087 int 7615088Sab196087 elfedit_sec_findstr(elfedit_section_t *sec, Word tail_ign, 7625088Sab196087 const char *str, Word *ret_offset) 7635088Sab196087 { 7645088Sab196087 int str_fch = *str; /* First character in str */ 7655088Sab196087 Word len; /* # characters in table */ 7665088Sab196087 char *s; /* ptr to strings within table */ 7675088Sab196087 const char *tail; /* 1 past final character of table */ 7685088Sab196087 7695088Sab196087 7705088Sab196087 /* Size of the section, minus the reserved part (if any) at the end */ 7715088Sab196087 len = sec->sec_shdr->sh_size - tail_ign; 7725088Sab196087 7735088Sab196087 /* 7745088Sab196087 * Move through the section character by character looking for 7755088Sab196087 * a match. Moving character by character instead of skipping 7765088Sab196087 * from NULL terminated string to string allows us to use 7775088Sab196087 * the tails longer strings (i.e. we want "bar", and "foobar" exists). 7785088Sab196087 * We look at the first character manually before calling strcmp() 7795088Sab196087 * to lower the cost of this approach. 7805088Sab196087 */ 7815088Sab196087 s = (char *)sec->sec_data->d_buf; 7825088Sab196087 tail = s + len; 7835088Sab196087 for (; s <= tail; s++) { 7845088Sab196087 if ((*s == str_fch) && (strcmp(s, str) == 0)) { 7855088Sab196087 *ret_offset = s - (char *)sec->sec_data->d_buf; 7865088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 7875088Sab196087 MSG_INTL(MSG_DEBUG_EXISTSTR), 7885088Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name, 7895088Sab196087 EC_WORD(*ret_offset), s); 7905088Sab196087 return (1); 7915088Sab196087 } 7925088Sab196087 } 7935088Sab196087 7945088Sab196087 /* Didn't find it. Report failure */ 7955088Sab196087 return (0); 7965088Sab196087 } 7975088Sab196087 7985088Sab196087 7995088Sab196087 /* 8005088Sab196087 * Locate the DT_SUNW_STRPAD element of the given dynamic section if 8015088Sab196087 * it exists. 8025088Sab196087 * 8035088Sab196087 * entry: 8045088Sab196087 * dynsec - Dynamic section descriptor 8055088Sab196087 * dyn_strpad - Address of variable to receive the results. 8065088Sab196087 * The caller is responsible for calling elfedit_dyn_elt_init() 8075088Sab196087 * on this variable beforehand. 8085088Sab196087 * 8095088Sab196087 * exit: 8105088Sab196087 * The dynamic section is searched, and if a DT_SUNW_STRPAD element 8115088Sab196087 * is found, dyn_strpad is updated via elfedit_dyn_elt_save() to 8125088Sab196087 * reference it. 8135088Sab196087 * 8145088Sab196087 * Returns the final value of dyn_strpad->dn_seen. 8155088Sab196087 */ 8165088Sab196087 int 8175088Sab196087 elfedit_dynstr_getpad(elfedit_section_t *dynsec, elfedit_dyn_elt_t *dyn_strpad) 8185088Sab196087 { 8195088Sab196087 Dyn *dyn = (Dyn *) dynsec->sec_data->d_buf; 8205088Sab196087 Word numdyn = dynsec->sec_shdr->sh_size / dynsec->sec_shdr->sh_entsize; 8215088Sab196087 Word i; 8225088Sab196087 8235088Sab196087 /* Go through dynamic section tags and find the STRPAD entry */ 8245088Sab196087 for (i = 0; i < numdyn; i++) { 8255088Sab196087 if (dyn[i].d_tag == DT_SUNW_STRPAD) { 8265088Sab196087 elfedit_dyn_elt_save(dyn_strpad, i, &dyn[i]); 8275088Sab196087 break; 8285088Sab196087 } 8295088Sab196087 } 8305088Sab196087 8315088Sab196087 return (dyn_strpad->dn_seen); 8325088Sab196087 } 8335088Sab196087 8345088Sab196087 8355088Sab196087 8365088Sab196087 /* 8375088Sab196087 * Given references to the dynamic section, its string table, 8385088Sab196087 * and the DT_SUNW_STRPAD entry of the dynamic section, returns 8395088Sab196087 * the offset of the specified string from within the given string table, 8405088Sab196087 * adding it if possible. 8415088Sab196087 * 8425088Sab196087 * entry: 8435088Sab196087 * dynsec - Dynamic section descriptor 8445088Sab196087 * strsec - Descriptor for string table assocated with dynamic section 8455088Sab196087 * dyn_strpad - DT_SUNW_STRPAD element from dynamic section 8465088Sab196087 * str - String we are looking for. 8475088Sab196087 * 8485088Sab196087 * exit: 8495088Sab196087 * On success, the offset of the given string within the string 8505088Sab196087 * table is returned. If the string does not exist within the table, 8515088Sab196087 * but there is a valid DT_SUNW_STRPAD reserved section, then we 8525088Sab196087 * add the string, and update the dynamic section STRPAD element 8535088Sab196087 * to reflect the space we use. 8545088Sab196087 * 8555088Sab196087 * This routine does not return on failure. 8565088Sab196087 */ 8575088Sab196087 Word 8585088Sab196087 elfedit_dynstr_insert(elfedit_section_t *dynsec, elfedit_section_t *strsec, 8595088Sab196087 elfedit_dyn_elt_t *dyn_strpad, const char *str) 8605088Sab196087 { 8615088Sab196087 Word ins_off; /* Table offset to 1st reserved byte */ 8625088Sab196087 char *s; /* ptr to strings within table */ 8635088Sab196087 Word len; /* Length of str inc. NULL byte */ 8645088Sab196087 Word tail_ign; /* # reserved bytes at end of strtab */ 8655088Sab196087 8665088Sab196087 8675088Sab196087 tail_ign = dyn_strpad->dn_seen ? dyn_strpad->dn_dyn.d_un.d_val : 0; 8685088Sab196087 8695088Sab196087 /* Does the string already existin the string table? */ 8705088Sab196087 if (elfedit_sec_findstr(strsec, tail_ign, str, &len)) 8715088Sab196087 return (len); 8725088Sab196087 8735088Sab196087 /* 8745088Sab196087 * The desired string does not already exist. Do we have 8755088Sab196087 * room to add it? 8765088Sab196087 */ 8775088Sab196087 len = strlen(str) + 1; 8785088Sab196087 if (!dyn_strpad->dn_seen || (len > dyn_strpad->dn_dyn.d_un.d_val)) 8795088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRPAD), 8805088Sab196087 EC_WORD(strsec->sec_shdr->sh_link), 8815088Sab196087 strsec->sec_name); 8825088Sab196087 8835088Sab196087 8845088Sab196087 /* 8855088Sab196087 * We will add the string at the first byte of the reserved NULL 8865088Sab196087 * area at the end. The DT_SUNW_STRPAD dynamic element gives us 8875088Sab196087 * the size of that reserved space. 8885088Sab196087 */ 8895088Sab196087 ins_off = strsec->sec_shdr->sh_size - tail_ign; 8905088Sab196087 s = ((char *)strsec->sec_data->d_buf) + ins_off; 8915088Sab196087 8925088Sab196087 /* Announce the operation */ 8935088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_ADDSTR), 8945088Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name, 8955088Sab196087 EC_WORD(ins_off), EC_WORD(len), 8965088Sab196087 EC_WORD(dyn_strpad->dn_dyn.d_un.d_val), str); 8975088Sab196087 8985088Sab196087 /* 8995088Sab196087 * Copy the string into the pad area at the end, and 9005088Sab196087 * mark the data area as dirty so libelf will flush our 9015088Sab196087 * changes to the string data. 9025088Sab196087 */ 9035088Sab196087 (void) strncpy(s, str, dyn_strpad->dn_dyn.d_un.d_val); 9045088Sab196087 elfedit_modified_data(strsec); 9055088Sab196087 9065088Sab196087 /* Update the DT_STRPAD dynamic entry */ 9075088Sab196087 dyn_strpad->dn_dyn.d_un.d_val -= len; 9085088Sab196087 ((Dyn *) dynsec->sec_data->d_buf)[dyn_strpad->dn_ndx] = 9095088Sab196087 dyn_strpad->dn_dyn; 9105088Sab196087 elfedit_modified_data(dynsec); 9115088Sab196087 9125088Sab196087 return (ins_off); 9135088Sab196087 } 9145088Sab196087 9155088Sab196087 9165088Sab196087 /* 9175088Sab196087 * Test to see if a call to elfedit_strtab_insert() will succeed. 9185088Sab196087 * 9195088Sab196087 * entry: 9205088Sab196087 * obj_state - Object state for open object to query. 9215088Sab196087 * strsec - Descriptor for string table 9225088Sab196087 * dynsec - NULL, or descriptor for dynamic section. Providing 9235088Sab196087 * a non-NULL value here will prevent elfedit_strtab_insert() 9245088Sab196087 * from looking it up, and the duplicate debug message that 9255088Sab196087 * would result. 9265088Sab196087 * str - String we are looking for. 9275088Sab196087 * 9285088Sab196087 * exit: 9295088Sab196087 * If the string exists within the string table, or if an attempt 9305088Sab196087 * to insert it will be successful, quietly return. Otherwise, throw 9315088Sab196087 * the error elfedit_strtab_insert() would throw under the 9325088Sab196087 * same circumstances. 9335088Sab196087 * 9345088Sab196087 */ 9355088Sab196087 void 9365088Sab196087 elfedit_strtab_insert_test(elfedit_obj_state_t *obj_state, 9375088Sab196087 elfedit_section_t *strsec, elfedit_section_t *dynsec, const char *str) 9385088Sab196087 { 9395088Sab196087 Word len; /* Length of str inc. NULL byte */ 9405088Sab196087 int is_dynstr = 0; 9415088Sab196087 Word tail_ign = 0; 9425088Sab196087 9435088Sab196087 9445088Sab196087 /* 9455088Sab196087 * The dynstr is a special case, because we can add strings 9465088Sab196087 * to it under certain circumstances. So, we look for the 9475088Sab196087 * dynamic section, and if it exists, compare its sh_link to 9485088Sab196087 * the string section index. If they match, it is the dynstr, 9495088Sab196087 * and we use elfedit_dynstr_insert() to do the work. 9505088Sab196087 */ 9515088Sab196087 if (dynsec == NULL) { 9525088Sab196087 if (obj_state->os_dynndx != SHN_UNDEF) { 9535088Sab196087 dynsec = &obj_state->os_secarr[obj_state->os_dynndx]; 9545088Sab196087 if ((dynsec->sec_shdr->sh_type == SHT_DYNAMIC) && 9555088Sab196087 (strsec->sec_shndx == dynsec->sec_shdr->sh_link)) { 9565088Sab196087 is_dynstr = 1; 9575088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 9585088Sab196087 MSG_INTL(MSG_DEBUG_FNDDYN), 9595088Sab196087 EC_WORD(dynsec->sec_shndx), 9605088Sab196087 dynsec->sec_name); 9615088Sab196087 } 9625088Sab196087 } 9635088Sab196087 } else { 9645088Sab196087 if (strsec->sec_shndx == dynsec->sec_shdr->sh_link) 9655088Sab196087 is_dynstr = 1; 9665088Sab196087 } 9675088Sab196087 9685088Sab196087 9695088Sab196087 if (is_dynstr) { 9705088Sab196087 elfedit_dyn_elt_t dyn_strpad; 9715088Sab196087 9725088Sab196087 /* Determine the size of the STRPAD area, if any */ 9735088Sab196087 elfedit_dyn_elt_init(&dyn_strpad); 9745088Sab196087 if (elfedit_dynstr_getpad(dynsec, &dyn_strpad) != 0) 9755088Sab196087 tail_ign = dyn_strpad.dn_dyn.d_un.d_val; 9765088Sab196087 } 9775088Sab196087 9785088Sab196087 /* 9795088Sab196087 * If the string is already in the string table, we 9805088Sab196087 * can't fail. 9815088Sab196087 */ 9825088Sab196087 if (elfedit_sec_findstr(strsec, tail_ign, str, &len) != 0) 9835088Sab196087 return; 9845088Sab196087 9855088Sab196087 /* 9865088Sab196087 * It's not in the table, but if this is the dynstr, and 9875088Sab196087 * there is enough room, we will be able to add it. 9885088Sab196087 */ 9895088Sab196087 if (is_dynstr && (tail_ign > strlen(str))) 9905088Sab196087 return; 9915088Sab196087 9925088Sab196087 /* Can't do it. Issue error */ 9935088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRPAD), 9945088Sab196087 EC_WORD(strsec->sec_shdr->sh_link), strsec->sec_name); 9955088Sab196087 } 9965088Sab196087 9975088Sab196087 9985088Sab196087 /* 9995088Sab196087 * Returns the offset of the specified string from within 10005088Sab196087 * the given string table, adding it if possible. 10015088Sab196087 * 10025088Sab196087 * entry: 10035088Sab196087 * obj_state - Object state for open object to query. 10045088Sab196087 * strsec - Descriptor for string table 10055088Sab196087 * dynsec - NULL, or descriptor for dynamic section. Providing 10065088Sab196087 * a non-NULL value here will prevent elfedit_strtab_insert() 10075088Sab196087 * from looking it up, and the duplicate debug message that 10085088Sab196087 * would result. 10095088Sab196087 * str - String we are looking for. 10105088Sab196087 * 10115088Sab196087 * exit: 10125088Sab196087 * On success, the offset of the given string within the string 10135088Sab196087 * table is returned. If the string does not exist within the table, 10145088Sab196087 * and it is possible to add it, elfedit_strtab_insert() will 10155088Sab196087 * add the string, and then return the offset. 10165088Sab196087 * 10175088Sab196087 * If the string does not exist in the string table, and cannot 10185088Sab196087 * be added, this routine issues an error message and does not 10195088Sab196087 * return to the caller. 10205088Sab196087 */ 10215088Sab196087 Word 10225088Sab196087 elfedit_strtab_insert(elfedit_obj_state_t *obj_state, elfedit_section_t *strsec, 10235088Sab196087 elfedit_section_t *dynsec, const char *str) 10245088Sab196087 { 10255088Sab196087 Word len; /* Length of str inc. NULL byte */ 10265088Sab196087 int is_dynstr = 0; 10275088Sab196087 elfedit_dyn_elt_t dyn_strpad; 10285088Sab196087 10295088Sab196087 10305088Sab196087 /* 10315088Sab196087 * The dynstr is a special case, because we can add strings 10325088Sab196087 * to it under certain circumstances. So, we look for the 10335088Sab196087 * dynamic section, and if it exists, compare its sh_link to 10345088Sab196087 * the string section index. If they match, it is the dynstr, 10355088Sab196087 * and we use elfedit_dynstr_insert() to do the work. 10365088Sab196087 */ 10375088Sab196087 if (dynsec == NULL) { 10385088Sab196087 if (obj_state->os_dynndx != SHN_UNDEF) { 10395088Sab196087 dynsec = &obj_state->os_secarr[obj_state->os_dynndx]; 10405088Sab196087 if ((dynsec->sec_shdr->sh_type == SHT_DYNAMIC) && 10415088Sab196087 (strsec->sec_shndx == dynsec->sec_shdr->sh_link)) { 10425088Sab196087 is_dynstr = 1; 10435088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 10445088Sab196087 MSG_INTL(MSG_DEBUG_FNDDYN), 10455088Sab196087 EC_WORD(dynsec->sec_shndx), 10465088Sab196087 dynsec->sec_name); 10475088Sab196087 } 10485088Sab196087 } 10495088Sab196087 } else { 10505088Sab196087 if (strsec->sec_shndx == dynsec->sec_shdr->sh_link) 10515088Sab196087 is_dynstr = 1; 10525088Sab196087 } 10535088Sab196087 10545088Sab196087 if (is_dynstr) { 10555088Sab196087 elfedit_dyn_elt_init(&dyn_strpad); 10565088Sab196087 (void) elfedit_dynstr_getpad(dynsec, &dyn_strpad); 10575088Sab196087 return (elfedit_dynstr_insert(dynsec, strsec, 10585088Sab196087 &dyn_strpad, str)); 10595088Sab196087 } 10605088Sab196087 10615088Sab196087 /* 10625088Sab196087 * This is not the dynstr, so we are limited to strings that 10635088Sab196087 * already exist within it. Try to find one. 10645088Sab196087 */ 10655088Sab196087 if (elfedit_sec_findstr(strsec, 0, str, &len)) 10665088Sab196087 return (len); 10675088Sab196087 10685088Sab196087 /* Can't do it. Issue error */ 10695088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRPAD), 10705088Sab196087 EC_WORD(strsec->sec_shdr->sh_link), strsec->sec_name); 10715088Sab196087 /*NOTREACHED*/ 10725088Sab196087 10735088Sab196087 return (0); 10745088Sab196087 } 10755088Sab196087 10765088Sab196087 10775088Sab196087 /* 10785088Sab196087 * Return the string found at the given offset within the specified 10795088Sab196087 * string table. 10805088Sab196087 * 10815088Sab196087 * entry: 10825088Sab196087 * strsec - Section descriptor for string table section 10835088Sab196087 * offset - Offset of desired string in string table 10845088Sab196087 * msg_type - ELFEDIT_MSG_ type code to use with message 10855088Sab196087 * issued if offset is out of range for the symbol table. 10865088Sab196087 * debug_msg - True if should issue debug message for string found. 10875088Sab196087 * 10885088Sab196087 * exit: 10895088Sab196087 * If the offset is within the section, the string pointer 10905088Sab196087 * is returned. Otherwise an error is issued using msg_type 10915088Sab196087 * to determine the type of message. If this routine retains 10925088Sab196087 * control after the message is issued, a safe string is returned. 10935088Sab196087 */ 10945088Sab196087 const char * 10955088Sab196087 elfedit_offset_to_str(elfedit_section_t *strsec, Word offset, 10965088Sab196087 elfedit_msg_t msg_type, int debug_msg) 10975088Sab196087 { 10985088Sab196087 const char *str; 10995088Sab196087 11005088Sab196087 /* Make sure it is a string table section */ 11015088Sab196087 if (strsec->sec_shdr->sh_type != SHT_STRTAB) 11025088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOTSTRSH), 11035088Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name); 11045088Sab196087 11055088Sab196087 /* Ensure the offset is in range */ 11065088Sab196087 if (offset >= strsec->sec_data->d_size) { 11075088Sab196087 elfedit_msg(msg_type, MSG_INTL(MSG_ERR_BADSTROFF), 11085088Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name, 11095088Sab196087 EC_WORD(offset), EC_WORD(strsec->sec_data->d_size - 1)); 11105088Sab196087 /* 11115088Sab196087 * If the msg_type is a type that returns, give the 11125088Sab196087 * user a safe string to use. 11135088Sab196087 */ 11145088Sab196087 str = MSG_INTL(MSG_BADSYMOFFSETNAM); 11155088Sab196087 } else { 11165088Sab196087 /* Return the string */ 11175088Sab196087 str = ((const char *)strsec->sec_data->d_buf) + offset; 11185088Sab196087 } 11195088Sab196087 11205088Sab196087 if (debug_msg) 11215088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSTR), 11225088Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name, 11235088Sab196087 EC_WORD(offset), str); 11245088Sab196087 return (str); 11255088Sab196087 } 11265088Sab196087 11275088Sab196087 11285088Sab196087 /* 11295088Sab196087 * Given a string table section, and a dynamic section entry 11305088Sab196087 * that supplies a string offset, return the string found at 11315088Sab196087 * the given offset. This routine is a convenience wrapper on 11325088Sab196087 * elfedit_offset_to_str(). 11335088Sab196087 * 11345088Sab196087 * exit: 11355088Sab196087 * As per elfedit_offset_to_str(). 11365088Sab196087 */ 11375088Sab196087 const char * 11385088Sab196087 elfedit_dyn_offset_to_str(elfedit_section_t *strsec, elfedit_dyn_elt_t *dynelt) 11395088Sab196087 { 11405088Sab196087 return (elfedit_offset_to_str(strsec, dynelt->dn_dyn.d_un.d_val, 11415088Sab196087 ELFEDIT_MSG_ERR, 0)); 11425088Sab196087 } 11435088Sab196087 11445088Sab196087 11455088Sab196087 /* 11465088Sab196087 * Given a section, fabricate a string for the form: 11475088Sab196087 * 11485088Sab196087 * "[#: name]" 11495088Sab196087 * 11505088Sab196087 * as used at the beginning of debug messages. A pointer to static 11515088Sab196087 * memory is returned, and is good until the next such call. 11525088Sab196087 */ 11535088Sab196087 const char * 11545088Sab196087 elfedit_sec_msgprefix(elfedit_section_t *sec) 11555088Sab196087 { 11565088Sab196087 static char *buf; 11575088Sab196087 static size_t bufsize; 11585088Sab196087 11595088Sab196087 size_t need; 11605088Sab196087 11615088Sab196087 need = 64 + strlen(sec->sec_name); 11625088Sab196087 if (need > bufsize) { 11635088Sab196087 buf = elfedit_realloc(MSG_INTL(MSG_ALLOC_SECMSGPRE), buf, need); 11645088Sab196087 bufsize = need; 11655088Sab196087 } 11665088Sab196087 11675088Sab196087 (void) snprintf(buf, bufsize, MSG_ORIG(MSG_FMT_SECMSGPRE), 11685088Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name); 11695088Sab196087 11705088Sab196087 return (buf); 11715088Sab196087 } 1172