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 /*
23*9273SAli.Bahrami@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
245088Sab196087 * Use is subject to license terms.
255088Sab196087 */
265088Sab196087
275088Sab196087 #include <stdlib.h>
285088Sab196087 #include <stdio.h>
295088Sab196087 #include <unistd.h>
305088Sab196087 #include <libintl.h>
316206Sab196087 #include <_machelf.h>
325088Sab196087 #include <libelf.h>
335088Sab196087 #include <link.h>
345088Sab196087 #include <strings.h>
355088Sab196087 #include <ctype.h>
365088Sab196087 #include "msg.h"
375088Sab196087 #include <elfedit.h>
385088Sab196087 #include <conv.h>
395088Sab196087 #include <sys/elf_SPARC.h>
405088Sab196087 #include <sys/elf_amd64.h>
415088Sab196087
425088Sab196087
435088Sab196087
445088Sab196087 /*
455088Sab196087 * ELFCLASS specific code that would otherwise be found in util.c
465088Sab196087 */
475088Sab196087
485088Sab196087
495088Sab196087
505088Sab196087
515088Sab196087 /*
525088Sab196087 * When you modify ELF constructs, you need to tell libelf that you've
535088Sab196087 * done so. Otherwise, the changes may not be flushed back to the
545088Sab196087 * output file.
555088Sab196087 *
565088Sab196087 * The elfedit_modified_*() functions exist to simplify the calls to
575088Sab196087 * the underlying elf_flag*() functions.
585088Sab196087 */
595088Sab196087 void
elfedit_modified_ehdr(elfedit_obj_state_t * obj_state)605088Sab196087 elfedit_modified_ehdr(elfedit_obj_state_t *obj_state)
615088Sab196087 {
625088Sab196087 (void) elf_flagehdr(obj_state->os_elf, ELF_C_SET, ELF_F_DIRTY);
635088Sab196087 }
645088Sab196087
655088Sab196087 void
elfedit_modified_phdr(elfedit_obj_state_t * obj_state)665088Sab196087 elfedit_modified_phdr(elfedit_obj_state_t *obj_state)
675088Sab196087 {
685088Sab196087 (void) elf_flagphdr(obj_state->os_elf, ELF_C_SET, ELF_F_DIRTY);
695088Sab196087 }
705088Sab196087
715088Sab196087 void
elfedit_modified_shdr(elfedit_section_t * s)725088Sab196087 elfedit_modified_shdr(elfedit_section_t *s)
735088Sab196087 {
745088Sab196087 (void) elf_flagshdr(s->sec_scn, ELF_C_SET, ELF_F_DIRTY);
755088Sab196087 }
765088Sab196087
775088Sab196087 void
elfedit_modified_data(elfedit_section_t * s)785088Sab196087 elfedit_modified_data(elfedit_section_t *s)
795088Sab196087 {
805088Sab196087 (void) elf_flagdata(s->sec_data, ELF_C_SET, ELF_F_DIRTY);
815088Sab196087 }
825088Sab196087
835088Sab196087
845088Sab196087
855088Sab196087 /*
865088Sab196087 * Prepare an elfedit_dyn_elt_t structure for use.
875088Sab196087 */
885088Sab196087 void
elfedit_dyn_elt_init(elfedit_dyn_elt_t * elt)895088Sab196087 elfedit_dyn_elt_init(elfedit_dyn_elt_t *elt)
905088Sab196087 {
915088Sab196087 elt->dn_seen = 0;
925088Sab196087 }
935088Sab196087
945088Sab196087 /*
955088Sab196087 * Given a dynamic section item, save it in the given elfedit_dyn_elt_t
965088Sab196087 * structure and mark that structure to show that it is present.
975088Sab196087 */
985088Sab196087 void
elfedit_dyn_elt_save(elfedit_dyn_elt_t * elt,Word ndx,Dyn * dyn)995088Sab196087 elfedit_dyn_elt_save(elfedit_dyn_elt_t *elt, Word ndx, Dyn *dyn)
1005088Sab196087 {
1015088Sab196087 elt->dn_seen = 1;
1025088Sab196087 elt->dn_ndx = ndx;
1035088Sab196087 elt->dn_dyn = *dyn;
1045088Sab196087 }
1055088Sab196087
1065088Sab196087
1075088Sab196087 /*
1085088Sab196087 * Return the index of the first section that has the given name.
1095088Sab196087 *
1105088Sab196087 * entry:
1115088Sab196087 * obj_state - Object state.
1125088Sab196087 * shnam - Name of desired section
1135088Sab196087 *
1145088Sab196087 * exit:
1155088Sab196087 * On success, returns the section index. On failure, an error
1165088Sab196087 * is issued, and this routine does not return to the caller.
1175088Sab196087 */
1185088Sab196087 Word
elfedit_name_to_shndx(elfedit_obj_state_t * obj_state,const char * shnam)1195088Sab196087 elfedit_name_to_shndx(elfedit_obj_state_t *obj_state, const char *shnam)
1205088Sab196087 {
1215088Sab196087 elfedit_section_t *sec = obj_state->os_secarr;
1225088Sab196087 Word ndx;
1235088Sab196087 Word shnum = obj_state->os_shnum;
1245088Sab196087
1255088Sab196087 for (ndx = 0; ndx < shnum; ndx++, sec++) {
1265088Sab196087 if (strcmp(shnam, sec->sec_name) == 0) {
1275088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
1285088Sab196087 MSG_INTL(MSG_DEBUG_SHNAM2NDX),
1295088Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name, shnam);
1305088Sab196087 return (ndx);
1315088Sab196087 }
1325088Sab196087 }
1335088Sab196087
1345088Sab196087 /* If didn't return in loop above, the name doesn't match */
1355088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSECNAM), shnam);
1365088Sab196087 /*NOTREACHED*/
1375088Sab196087 return (SHN_UNDEF);
1385088Sab196087 }
1395088Sab196087
1405088Sab196087
1415088Sab196087
1425088Sab196087 /*
1435088Sab196087 * Return the index of the first section that has the given type.
1445088Sab196087 *
1455088Sab196087 * entry:
1465088Sab196087 * obj_state - Object state.
1475088Sab196087 * shtype - Type of desired section
1485088Sab196087 *
1495088Sab196087 * exit:
1505088Sab196087 * On success, returns the section index. On failure, an error
1515088Sab196087 * is issued, and this routine does not return to the caller.
1525088Sab196087 */
1535088Sab196087 Word
elfedit_type_to_shndx(elfedit_obj_state_t * obj_state,Word shtype)1545088Sab196087 elfedit_type_to_shndx(elfedit_obj_state_t *obj_state, Word shtype)
1555088Sab196087 {
1565088Sab196087 Conv_inv_buf_t inv_buf;
1575088Sab196087 elfedit_section_t *sec = obj_state->os_secarr;
1585088Sab196087 Word ndx;
1595088Sab196087 Word shnum = obj_state->os_shnum;
1605088Sab196087
1615088Sab196087 for (ndx = 0; ndx < shnum; ndx++, sec++) {
1625088Sab196087 if (shtype == sec->sec_shdr->sh_type) {
1635088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
1645088Sab196087 MSG_INTL(MSG_DEBUG_SHNAM2NDX),
1655088Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name,
166*9273SAli.Bahrami@Sun.COM conv_sec_type(
167*9273SAli.Bahrami@Sun.COM obj_state->os_ehdr->e_ident[EI_OSABI],
168*9273SAli.Bahrami@Sun.COM obj_state->os_ehdr->e_machine,
1695088Sab196087 shtype, 0, &inv_buf));
1705088Sab196087 return (ndx);
1715088Sab196087 }
1725088Sab196087 }
1735088Sab196087
1745088Sab196087 /* If didn't return in loop above, the name doesn't match */
1755088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSECTYP),
176*9273SAli.Bahrami@Sun.COM conv_sec_type(obj_state->os_ehdr->e_ident[EI_OSABI],
177*9273SAli.Bahrami@Sun.COM obj_state->os_ehdr->e_machine, shtype, 0, &inv_buf));
1785088Sab196087 /*NOTREACHED*/
1795088Sab196087 return (SHN_UNDEF);
1805088Sab196087 }
1815088Sab196087
1825088Sab196087
1835088Sab196087
1845088Sab196087 /*
1855088Sab196087 * Locate the index of the first symbol that has the given name
1865088Sab196087 *
1875088Sab196087 * entry:
1885088Sab196087 * obj_state - Object state.
1895088Sab196087 * symsec - Symbol section
1905088Sab196087 * strsec = String section
1915088Sab196087 * name - String giving name of symbol to lookup
1925088Sab196087 * msg_type - ELFEDIT_MSG_ type code to use with message
1935088Sab196087 * issued if name does not exist in symbol table.
1945088Sab196087 * ret_symndx - Address of variable to receive index.
1955088Sab196087 *
1965088Sab196087 * exit:
1975088Sab196087 * On success, issues debug message, sets *ret_symndx, and returns
1985088Sab196087 * True (1).
1995088Sab196087 *
2005088Sab196087 * On failure, issues a message using msg_type to determine
2015088Sab196087 * the type of message sent. If the message does not take control away
2025088Sab196087 * from the caller, False (0) is returned.
2035088Sab196087 *
2045088Sab196087 * note:
2055088Sab196087 * Although the string table is referenced by the sh_link field of
2065088Sab196087 * the symbol table, we require the user to supply it rather than
2075088Sab196087 * look it up. The reason for this is that the caller will usually
2085088Sab196087 * have looked it up, and we wish to avoid multiple debug messages
2095088Sab196087 * from being issued to that effect.
2105088Sab196087 */
2115088Sab196087 int
elfedit_name_to_symndx(elfedit_section_t * symsec,elfedit_section_t * strsec,const char * name,elfedit_msg_t msg_type,Word * ret_symndx)2125088Sab196087 elfedit_name_to_symndx(elfedit_section_t *symsec, elfedit_section_t *strsec,
2135088Sab196087 const char *name, elfedit_msg_t msg_type, Word *ret_symndx)
2145088Sab196087
2155088Sab196087 {
2165088Sab196087 Sym *sym = (Sym *) symsec->sec_data->d_buf;
2175088Sab196087 Word cnt = symsec->sec_shdr->sh_size / symsec->sec_shdr->sh_entsize;
2185088Sab196087 Word ndx, offset;
2195088Sab196087 const char *curname;
2205088Sab196087
2215088Sab196087 for (ndx = 0; ndx < cnt; ndx++) {
2225088Sab196087 offset = sym[ndx].st_name;
2235088Sab196087
2245088Sab196087 curname = elfedit_offset_to_str(strsec, offset,
2255088Sab196087 ELFEDIT_MSG_ERR, 0);
2265088Sab196087 if (strcmp(curname, name) == 0) {
2275088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
2285088Sab196087 MSG_INTL(MSG_DEBUG_SYMNAM2NDX),
2295088Sab196087 EC_WORD(symsec->sec_shndx),
2305088Sab196087 symsec->sec_name, EC_WORD(ndx), name);
2315088Sab196087 *ret_symndx = ndx;
2325088Sab196087 return (1);
2335088Sab196087 }
2345088Sab196087 }
2355088Sab196087
2365088Sab196087 /* If didn't return in loop above, the name doesn't match */
2375088Sab196087 elfedit_msg(msg_type, MSG_INTL(MSG_ERR_NOSYM),
2385088Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name, name);
2395088Sab196087 /*NOTREACHED*/
2405088Sab196087 return (0); /* lint */
2415088Sab196087 }
2425088Sab196087
2435088Sab196087
2445088Sab196087 /*
2455088Sab196087 * Given a section index, turn it into a descriptive string.
2465088Sab196087 * - If it is one of the special reserved indexes, the
2475088Sab196087 * symbolic name is returned.
2485088Sab196087 * - If it is a regular section, in range for the file,
2495088Sab196087 * the name associated with the section is returned.
2505088Sab196087 * - Otherwise, the number is formatted as numeric ASCII.
2515088Sab196087 *
2525088Sab196087 * exit:
2535088Sab196087 * A pointer to the static buffer containing the name is
2545088Sab196087 * returned. This pointer is valid until the next call
2555088Sab196087 * to elfedit_shndx_to_name(), and which point it may
2565088Sab196087 * be overwritten.
2575088Sab196087 */
2585088Sab196087 const char *
elfedit_shndx_to_name(elfedit_obj_state_t * obj_state,Word shndx)2595088Sab196087 elfedit_shndx_to_name(elfedit_obj_state_t *obj_state, Word shndx)
2605088Sab196087 {
2615088Sab196087 /*
2625088Sab196087 * This routine can be called twice within a single C statement,
2635088Sab196087 * so we use alternating buffers on each call to allow this
2645088Sab196087 * without requiring the caller to supply a buffer (the size of
2655088Sab196087 * which they don't know).
2665088Sab196087 */
267*9273SAli.Bahrami@Sun.COM static Conv_inv_buf_t buf1, buf2;
268*9273SAli.Bahrami@Sun.COM static Conv_inv_buf_t *buf;
2695088Sab196087
2705088Sab196087 /*
2715088Sab196087 * If it is outside of the reserved area, and inside the
2725088Sab196087 * range of section indexes in the ELF file, then show
2735088Sab196087 * the section name.
2745088Sab196087 */
2755088Sab196087 if ((shndx < obj_state->os_shnum) &&
276*9273SAli.Bahrami@Sun.COM ((shndx < SHN_LORESERVE) || (shndx > SHN_HIRESERVE)) &&
277*9273SAli.Bahrami@Sun.COM (shndx != SHN_UNDEF))
2785088Sab196087 return (obj_state->os_secarr[shndx].sec_name);
2795088Sab196087
2805088Sab196087 /*
281*9273SAli.Bahrami@Sun.COM * Anything else is handled by libconv. It will return standard
282*9273SAli.Bahrami@Sun.COM * names for known items, or format as a number otherwise.
2835088Sab196087 */
284*9273SAli.Bahrami@Sun.COM buf = (buf == &buf1) ? &buf2 : &buf1; /* Switch buffers */
285*9273SAli.Bahrami@Sun.COM return (conv_sym_shndx(obj_state->os_ehdr->e_ident[EI_OSABI],
286*9273SAli.Bahrami@Sun.COM obj_state->os_ehdr->e_machine, shndx,
287*9273SAli.Bahrami@Sun.COM CONV_FMT_ALT_CF | CONV_FMT_DECIMAL, buf));
2885088Sab196087 }
2895088Sab196087
2905088Sab196087
2915088Sab196087 /*
2925892Sab196087 * Locate the arbitrary section specified by shndx for this object.
2935892Sab196087 *
2945892Sab196087 * exit:
2955892Sab196087 * Returns section descriptor on success. On failure, does not return.
2965892Sab196087 */
2975892Sab196087 elfedit_section_t *
elfedit_sec_get(elfedit_obj_state_t * obj_state,Word shndx)2985892Sab196087 elfedit_sec_get(elfedit_obj_state_t *obj_state, Word shndx)
2995892Sab196087 {
3005892Sab196087 elfedit_section_t *sec;
3015892Sab196087
3025892Sab196087 if ((shndx == 0) || (shndx >= obj_state->os_shnum))
3035892Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADSECNDX),
3045892Sab196087 EC_WORD(shndx), EC_WORD(obj_state->os_shnum - 1));
3055892Sab196087
3065892Sab196087 sec = &obj_state->os_secarr[shndx];
3075892Sab196087
3085892Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSEC),
3095892Sab196087 EC_WORD(shndx), sec->sec_name);
3105892Sab196087 return (sec);
3115892Sab196087 }
3125892Sab196087
3135892Sab196087
314*9273SAli.Bahrami@Sun.COM
315*9273SAli.Bahrami@Sun.COM /*
316*9273SAli.Bahrami@Sun.COM * Compare the a specified osabi with that of the current object.
317*9273SAli.Bahrami@Sun.COM *
318*9273SAli.Bahrami@Sun.COM * entry:
319*9273SAli.Bahrami@Sun.COM * obj_state - Object state for open object to query.
320*9273SAli.Bahrami@Sun.COM * issue_err - True if this routine should issue an error and
321*9273SAli.Bahrami@Sun.COM * not return to the caller if osabi is not native.
322*9273SAli.Bahrami@Sun.COM *
323*9273SAli.Bahrami@Sun.COM * exit:
324*9273SAli.Bahrami@Sun.COM * If current osabi is the one specified, True (1) is returned.
325*9273SAli.Bahrami@Sun.COM *
326*9273SAli.Bahrami@Sun.COM * Otherwise, if issue_err is True, an error is issued and this
327*9273SAli.Bahrami@Sun.COM * routine does not return to the caller. If issue_err is False,
328*9273SAli.Bahrami@Sun.COM * False (0) is returned.
329*9273SAli.Bahrami@Sun.COM *
330*9273SAli.Bahrami@Sun.COM * note:
331*9273SAli.Bahrami@Sun.COM * ELFOSABI_NONE is considered to be equivalent to ELFOSABI_SOLARIS.
332*9273SAli.Bahrami@Sun.COM */
333*9273SAli.Bahrami@Sun.COM int
elfedit_test_osabi(elfedit_obj_state_t * obj_state,uchar_t osabi,int issue_err)334*9273SAli.Bahrami@Sun.COM elfedit_test_osabi(elfedit_obj_state_t *obj_state, uchar_t osabi,
335*9273SAli.Bahrami@Sun.COM int issue_err)
336*9273SAli.Bahrami@Sun.COM {
337*9273SAli.Bahrami@Sun.COM uchar_t obj_osabi = obj_state->os_ehdr->e_ident[EI_OSABI];
338*9273SAli.Bahrami@Sun.COM Conv_inv_buf_t inv_buf;
339*9273SAli.Bahrami@Sun.COM
340*9273SAli.Bahrami@Sun.COM if (obj_osabi == ELFOSABI_NONE)
341*9273SAli.Bahrami@Sun.COM obj_osabi = ELFOSABI_SOLARIS;
342*9273SAli.Bahrami@Sun.COM
343*9273SAli.Bahrami@Sun.COM if (osabi == obj_osabi)
344*9273SAli.Bahrami@Sun.COM return (1);
345*9273SAli.Bahrami@Sun.COM
346*9273SAli.Bahrami@Sun.COM if (issue_err)
347*9273SAli.Bahrami@Sun.COM elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADOSABI),
348*9273SAli.Bahrami@Sun.COM conv_ehdr_osabi(osabi, 0, &inv_buf));
349*9273SAli.Bahrami@Sun.COM return (0);
350*9273SAli.Bahrami@Sun.COM }
351*9273SAli.Bahrami@Sun.COM
3525892Sab196087 /*
3535088Sab196087 * Locate the capabilities section for this object
3545088Sab196087 *
3555088Sab196087 * entry:
3565088Sab196087 * obj_state - Object state for open object to query.
3575088Sab196087 * cap - Address of variable to recieve pointer to capabilities
3585088Sab196087 * section data buffer.
3595088Sab196087 * num - Address of variable to receive number of items
3605088Sab196087 * referenced by cap.
3615088Sab196087 *
3625088Sab196087 * exit:
3635088Sab196087 * On success, returns section descriptor, and sets the
3645088Sab196087 * variables referenced by cap and num. On failure,
3655088Sab196087 * does not return.
3665088Sab196087 */
3675088Sab196087 elfedit_section_t *
elfedit_sec_getcap(elfedit_obj_state_t * obj_state,Cap ** cap,Word * num)3685088Sab196087 elfedit_sec_getcap(elfedit_obj_state_t *obj_state, Cap **cap, Word *num)
3695088Sab196087 {
3705088Sab196087 Word cnt;
3715088Sab196087 elfedit_section_t *cache;
3725088Sab196087
373*9273SAli.Bahrami@Sun.COM (void) elfedit_test_osabi(obj_state, ELFOSABI_SOLARIS, 1);
374*9273SAli.Bahrami@Sun.COM
3755088Sab196087 for (cnt = 1; cnt < obj_state->os_shnum; cnt++) {
3765088Sab196087 cache = &obj_state->os_secarr[cnt];
3775088Sab196087 if (cache->sec_shdr->sh_type == SHT_SUNW_cap) {
3785088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
3795088Sab196087 MSG_INTL(MSG_DEBUG_FNDCAP),
3805088Sab196087 EC_WORD(cnt), cache->sec_name);
3815088Sab196087 *cap = (Cap *) cache->sec_data->d_buf;
3825088Sab196087 *num = cache->sec_shdr->sh_size /
3835088Sab196087 cache->sec_shdr->sh_entsize;
3845088Sab196087 return (cache);
3855088Sab196087 }
3865088Sab196087 }
3875088Sab196087
3885088Sab196087 /* If here, this object has no capabilities section */
3895088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAP));
3905088Sab196087
3915088Sab196087 /*NOTREACHED*/
3925088Sab196087 return (NULL);
3935088Sab196087 }
3945088Sab196087
3955088Sab196087
3965088Sab196087 /*
3975088Sab196087 * Locate the dynamic section for this object
3985088Sab196087 *
3995088Sab196087 * entry:
4005088Sab196087 * obj_state - Object state for open object to query.
4015088Sab196087 * dyn - Address of variable to recieve pointer to dynamic
4025088Sab196087 * section data buffer.
4035088Sab196087 * numdyn - Address of variable to receive number of items
4045088Sab196087 * referenced by dyn.
4055088Sab196087 *
4065088Sab196087 * exit:
4075088Sab196087 * On success, returns section descriptor, and sets the
4085088Sab196087 * variables referenced by dyn and numdyn. On failure,
4095088Sab196087 * does not return.
4105088Sab196087 */
4115088Sab196087 elfedit_section_t *
elfedit_sec_getdyn(elfedit_obj_state_t * obj_state,Dyn ** dyn,Word * num)4125088Sab196087 elfedit_sec_getdyn(elfedit_obj_state_t *obj_state, Dyn **dyn, Word *num)
4135088Sab196087 {
4145088Sab196087 elfedit_section_t *cache;
4155088Sab196087
4165088Sab196087 if (obj_state->os_dynndx != SHN_UNDEF) {
4175088Sab196087 cache = &obj_state->os_secarr[obj_state->os_dynndx];
4185088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDDYN),
4195088Sab196087 EC_WORD(cache->sec_shndx), cache->sec_name);
4205088Sab196087 *dyn = (Dyn *) cache->sec_data->d_buf;
4215088Sab196087 *num = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize;
4225088Sab196087 return (cache);
4235088Sab196087 }
4245088Sab196087
4255088Sab196087 /* If here, this object has no dynamic section */
4265088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODYN));
4275088Sab196087
4285088Sab196087 /*NOTREACHED*/
4295088Sab196087 return (NULL);
4305088Sab196087 }
4315088Sab196087
4325088Sab196087
4335088Sab196087 /*
4345088Sab196087 * Locate the syminfo section for this object
4355088Sab196087 *
4365088Sab196087 * entry:
4375088Sab196087 * obj_state - Object state for open object to query.
4385088Sab196087 * syminfo - Address of variable to recieve pointer to syminfo
4395088Sab196087 * section data buffer.
4405088Sab196087 * num - Address of variable to receive number of items
4415088Sab196087 * referenced by syminfo.
4425088Sab196087 *
4435088Sab196087 * exit:
4445088Sab196087 * On success, returns section descriptor, and sets the
4455088Sab196087 * variables referenced by syminfo and num. On failure,
4465088Sab196087 * does not return.
4475088Sab196087 */
4485088Sab196087 elfedit_section_t *
elfedit_sec_getsyminfo(elfedit_obj_state_t * obj_state,Syminfo ** syminfo,Word * num)4495088Sab196087 elfedit_sec_getsyminfo(elfedit_obj_state_t *obj_state, Syminfo **syminfo,
4505088Sab196087 Word *num)
4515088Sab196087 {
4525088Sab196087 Word cnt;
4535088Sab196087 elfedit_section_t *cache;
4545088Sab196087
4555088Sab196087 for (cnt = 1; cnt < obj_state->os_shnum; cnt++) {
4565088Sab196087 cache = &obj_state->os_secarr[cnt];
4575088Sab196087 if (cache->sec_shdr->sh_type == SHT_SUNW_syminfo) {
4585088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
4595088Sab196087 MSG_INTL(MSG_DEBUG_FNDSYMINFO),
4605088Sab196087 EC_WORD(cnt), cache->sec_name);
4615088Sab196087 *syminfo = (Syminfo *) cache->sec_data->d_buf;
4625088Sab196087 *num = cache->sec_shdr->sh_size /
4635088Sab196087 cache->sec_shdr->sh_entsize;
4645088Sab196087 return (cache);
4655088Sab196087 }
4665088Sab196087 }
4675088Sab196087
4685088Sab196087 /* If here, this object has no syminfo section */
4695088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSYMINFO));
4705088Sab196087
4715088Sab196087 /*NOTREACHED*/
4725088Sab196087 return (NULL);
4735088Sab196087 }
4745088Sab196087
4755088Sab196087
4765088Sab196087 /*
4775088Sab196087 * Check the given section to see if it is a known symbol table type.
4785088Sab196087 *
4795088Sab196087 * entry:
480*9273SAli.Bahrami@Sun.COM * obj_state - Object state for open object to query.
4815088Sab196087 * sec - Section to check
4825088Sab196087 * issue_err - True if this routine should issue an error and
4835088Sab196087 * not return to the caller if sec is not a symbol table.
4845088Sab196087 * atoui_list - NULL, or address of variable to receive a pointer to
4855088Sab196087 * an array of elfedit_atoui_sym_t items describing the
4865088Sab196087 * type of symbol table found. This array is useful for
4875088Sab196087 * doing command completion.
4885088Sab196087 *
4895088Sab196087 * exit:
4905088Sab196087 * If sec is a symbol table:
4915088Sab196087 * - If atoui_list is non-NULL, *atoui_list is set to the
4925088Sab196087 * appropriate ELFEDIT_CONST_xx list of items.
4935088Sab196087 * - True (1) is returned
4945088Sab196087 * If sec is not a symbol table and issue_err is True:
4955088Sab196087 * - An error is issued, and this routine does not
4965088Sab196087 * return to the caller.
4975088Sab196087 * Otherwise:
4985088Sab196087 * - If atoui_list is non-NULL, *atoui_list is set to NULL.
4995088Sab196087 * - False (0) is returned
5005088Sab196087 */
5015088Sab196087 int
elfedit_sec_issymtab(elfedit_obj_state_t * obj_state,elfedit_section_t * sec,int issue_err,elfedit_atoui_sym_t ** atoui_list)502*9273SAli.Bahrami@Sun.COM elfedit_sec_issymtab(elfedit_obj_state_t *obj_state, elfedit_section_t *sec,
503*9273SAli.Bahrami@Sun.COM int issue_err, elfedit_atoui_sym_t **atoui_list)
5045088Sab196087 {
5055088Sab196087 elfedit_const_t const_type;
5065088Sab196087 int ret = 1;
5075088Sab196087
5085088Sab196087 /* Is the section a symbol table? */
5095088Sab196087 switch (sec->sec_shdr->sh_type) {
5105088Sab196087 case SHT_SYMTAB:
5115088Sab196087 const_type = ELFEDIT_CONST_SHT_SYMTAB;
5125088Sab196087 break;
5135088Sab196087 case SHT_DYNSYM:
5145088Sab196087 const_type = ELFEDIT_CONST_SHT_DYNSYM;
5155088Sab196087 break;
5165088Sab196087 case SHT_SUNW_LDYNSYM:
517*9273SAli.Bahrami@Sun.COM /*
518*9273SAli.Bahrami@Sun.COM * These sections are only known to be symbol tables
519*9273SAli.Bahrami@Sun.COM * if the osabi is Solaris.
520*9273SAli.Bahrami@Sun.COM */
521*9273SAli.Bahrami@Sun.COM if (elfedit_test_osabi(obj_state, ELFOSABI_SOLARIS, 0)) {
522*9273SAli.Bahrami@Sun.COM const_type = ELFEDIT_CONST_SHT_LDYNSYM;
523*9273SAli.Bahrami@Sun.COM break;
524*9273SAli.Bahrami@Sun.COM }
525*9273SAli.Bahrami@Sun.COM /*FALLTHROUGH*/
5265088Sab196087 default:
5275088Sab196087 if (issue_err)
5285088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR,
5295088Sab196087 MSG_INTL(MSG_ERR_NOTSYMTAB),
5305088Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name);
5315088Sab196087 ret = 0;
5325088Sab196087 break;
5335088Sab196087 }
5345088Sab196087
5355088Sab196087 if (atoui_list != NULL)
5365088Sab196087 *atoui_list = (ret == 0) ? NULL :
5375088Sab196087 elfedit_const_to_atoui(const_type);
5385088Sab196087
5395088Sab196087 return (ret);
5405088Sab196087 }
5415088Sab196087
5425088Sab196087
5435088Sab196087
5445088Sab196087 /*
5455088Sab196087 * Locate a symbol table section for this object
5465088Sab196087 *
5475088Sab196087 * entry:
5485088Sab196087 * obj_state - Object state for open object to query.
5495088Sab196087 * by_index - If True, we want to locate the section with the
5505088Sab196087 * section index given by index. If False, we return
5515088Sab196087 * the section with the name given by name.
5525088Sab196087 * index, name - Key to search for. See by_index.
5535088Sab196087 * sym - Address of variable to recieve pointer to symbol
5545088Sab196087 * section data buffer.
5555088Sab196087 * numsym - Address of variable to receive number of symbols
5565088Sab196087 * referenced by sym.
5575088Sab196087 * aux_info - Address of variable to receive pointer to the
5585088Sab196087 * elfedit_symtab_t struct that ties the symbol table and
5595088Sab196087 * its related auxiliary sections together. NULL if this
5605088Sab196087 * information is not required.
5615088Sab196087 *
5625088Sab196087 * exit:
5635088Sab196087 * On success, returns section descriptor, and sets the
5645088Sab196087 * variables referenced by sym, and numsym. On failure,
5655088Sab196087 * does not return.
5665088Sab196087 */
5675088Sab196087 elfedit_section_t *
elfedit_sec_getsymtab(elfedit_obj_state_t * obj_state,int by_index,Word index,const char * name,Sym ** sym,Word * num,elfedit_symtab_t ** aux_info)5685088Sab196087 elfedit_sec_getsymtab(elfedit_obj_state_t *obj_state, int by_index,
5695088Sab196087 Word index, const char *name, Sym **sym, Word *num,
5705088Sab196087 elfedit_symtab_t **aux_info)
5715088Sab196087 {
5725088Sab196087 Word ndx;
5735088Sab196087 elfedit_section_t *symsec = NULL;
5745088Sab196087 elfedit_symtab_t *symtab;
5755088Sab196087 const char *type_name;
5765088Sab196087
5775088Sab196087 /* If looking it up by index, make sure the index is in range */
5785088Sab196087 if (by_index && (index >= obj_state->os_shnum))
5795088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADSECNDX),
5805088Sab196087 EC_WORD(index), EC_WORD(obj_state->os_shnum - 1));
5815088Sab196087
5825088Sab196087 /*
5835088Sab196087 * Look at each known symbol table in turn until the desired
5845088Sab196087 * one is hit, or there are no more.
5855088Sab196087 */
5865088Sab196087 symtab = obj_state->os_symtab;
5875088Sab196087 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) {
5885088Sab196087 elfedit_section_t *s =
5895088Sab196087 &obj_state->os_secarr[symtab->symt_shndx];
5905088Sab196087
5915088Sab196087 if ((by_index && (symtab->symt_shndx == index)) ||
5925088Sab196087 (!by_index && (strcmp(s->sec_name, name) == 0))) {
5935088Sab196087 symsec = s;
5945088Sab196087 break;
5955088Sab196087 }
5965088Sab196087 }
5975088Sab196087
5985088Sab196087 /* Did we get a section? */
5995088Sab196087 if (symsec == NULL)
6005088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSYMTAB));
6015088Sab196087
6025088Sab196087 /* Got it. Report to the user and return the necessary data */
603*9273SAli.Bahrami@Sun.COM (void) elfedit_sec_issymtab(obj_state, symsec, 1, NULL);
6045088Sab196087 type_name = elfedit_atoconst_value_to_str(ELFEDIT_CONST_SHT_ALLSYMTAB,
6055088Sab196087 symsec->sec_shdr->sh_type, 1);
6065088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSYMTAB),
6075088Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name, type_name);
6085088Sab196087 *sym = (Sym *) symsec->sec_data->d_buf;
6095088Sab196087 *num = symsec->sec_shdr->sh_size / symsec->sec_shdr->sh_entsize;
6105088Sab196087 if (aux_info != NULL)
6115088Sab196087 *aux_info = symtab;
6125088Sab196087 return (symsec);
6135088Sab196087 }
6145088Sab196087
6155088Sab196087
6165088Sab196087
6175088Sab196087 /*
6185088Sab196087 * Locate the extended symbol index section associated with a symbol
6195088Sab196087 * table section.
6205088Sab196087 *
6215088Sab196087 * entry:
6225088Sab196087 * obj_state - Object state for open object to query.
6235088Sab196087 * symsec - Symbol table section for which extended index
6245088Sab196087 * index section is required.
6255088Sab196087 * xshndx - Address of variable to recieve pointer to section index
6265088Sab196087 * array data buffer.
6275088Sab196087 * numxshndx - Address of variable to receive number of indices
6285088Sab196087 * referenced by ndx.
6295088Sab196087 *
6305088Sab196087 * exit:
6315088Sab196087 * On success, returns extended index section descriptor, and sets the
6325088Sab196087 * variables referenced by xshndx, and numxshndx. On failure,
6335088Sab196087 * does not return.
6345088Sab196087 *
6355088Sab196087 * note:
6365088Sab196087 * Since the extended section index is found in the sec_xshndx field
6375088Sab196087 * of the elfedit_section_t, the caller may be tempted to bypass this
6385088Sab196087 * routine and access it directly. That temptation should be resisted,
6395088Sab196087 * as this routine performs useful error checking, and also handles
6405088Sab196087 * the issuing of the standard MSG_DEBUG messages.
6415088Sab196087 */
6425088Sab196087 elfedit_section_t *
elfedit_sec_getxshndx(elfedit_obj_state_t * obj_state,elfedit_section_t * symsec,Word ** xshndx,Word * num)6435088Sab196087 elfedit_sec_getxshndx(elfedit_obj_state_t *obj_state,
6445088Sab196087 elfedit_section_t *symsec, Word **xshndx, Word *num)
6455088Sab196087 {
6465088Sab196087 elfedit_section_t *xshndxsec;
6475088Sab196087 elfedit_symtab_t *symtab;
6485088Sab196087 Word ndx;
6495088Sab196087
6505088Sab196087 /* Sanity check: symsec must be a symbol table */
651*9273SAli.Bahrami@Sun.COM (void) elfedit_sec_issymtab(obj_state, symsec, 1, NULL);
6525088Sab196087
6535088Sab196087 symtab = obj_state->os_symtab;
6545088Sab196087 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++)
6555088Sab196087 if (symsec->sec_shndx == symtab->symt_shndx)
6565088Sab196087 break;
6575088Sab196087
6585088Sab196087 /*
6595088Sab196087 * Issue error if the symbol table lacks an extended index section.
6605088Sab196087 * The caller won't ask unless they encounter an SHN_XINDEX value,
6615088Sab196087 * in which case the lack of the index section denotes a corrupt
6625088Sab196087 * ELF file.
6635088Sab196087 */
6645088Sab196087 if ((ndx == obj_state->os_symtabnum) ||
6655088Sab196087 (symtab->symt_xshndx == SHN_UNDEF))
6665088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOXSHSEC),
6675088Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name);
6685088Sab196087
6695088Sab196087 /* Got it. Report to the user and return the necessary data */
6705088Sab196087 xshndxsec = &obj_state->os_secarr[symtab->symt_xshndx];
6715088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDXSHNDX),
6725088Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name,
6735088Sab196087 EC_WORD(xshndxsec->sec_shndx), xshndxsec->sec_name);
6745088Sab196087 *xshndx = (Word *) xshndxsec->sec_data->d_buf;
6755088Sab196087 *num = xshndxsec->sec_shdr->sh_size / xshndxsec->sec_shdr->sh_entsize;
6765088Sab196087 return (xshndxsec);
6775088Sab196087 }
6785088Sab196087
6795088Sab196087
6805088Sab196087
6815088Sab196087 /*
6825088Sab196087 * Locate the versym section associated with a symbol table section.
6835088Sab196087 *
6845088Sab196087 * entry:
6855088Sab196087 * obj_state - Object state for open object to query.
6865088Sab196087 * symsec - Symbol table section for which extended index
6875088Sab196087 * index section is required.
6885088Sab196087 * versym - Address of variable to recieve pointer to section index
6895088Sab196087 * array data buffer.
6905088Sab196087 * numversym - Address of variable to receive number of indices
6915088Sab196087 * referenced by ndx.
6925088Sab196087 *
6935088Sab196087 * exit:
6945088Sab196087 * On success, returns versym section descriptor, and sets the
6955088Sab196087 * variables referenced by versym, and numversym. On failure,
6965088Sab196087 * does not return.
6975088Sab196087 *
6985088Sab196087 * note:
6995088Sab196087 * Since the versym section index is found in the sec_versym field
7005088Sab196087 * of the elfedit_section_t, the caller may be tempted to bypass this
7015088Sab196087 * routine and access it directly. That temptation should be resisted,
7025088Sab196087 * as this routine performs useful error checking, and also handles
7035088Sab196087 * the issuing of the standard MSG_DEBUG messages.
7045088Sab196087 */
7055088Sab196087 elfedit_section_t *
elfedit_sec_getversym(elfedit_obj_state_t * obj_state,elfedit_section_t * symsec,Versym ** versym,Word * num)7065088Sab196087 elfedit_sec_getversym(elfedit_obj_state_t *obj_state,
7075088Sab196087 elfedit_section_t *symsec, Versym **versym, Word *num)
7085088Sab196087 {
7095088Sab196087 elfedit_section_t *versymsec;
7105088Sab196087 elfedit_symtab_t *symtab;
7115088Sab196087 Word ndx;
7125088Sab196087
7135088Sab196087 /* Sanity check: symsec must be a symbol table */
714*9273SAli.Bahrami@Sun.COM (void) elfedit_sec_issymtab(obj_state, symsec, 1, NULL);
7155088Sab196087
7165088Sab196087 symtab = obj_state->os_symtab;
7175088Sab196087 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++)
7185088Sab196087 if (symsec->sec_shndx == symtab->symt_shndx)
7195088Sab196087 break;
7205088Sab196087 /*
7215088Sab196087 * Issue error if the symbol table lacks a versym section.
7225088Sab196087 * The caller won't ask unless they see a non-null
7235088Sab196087 * aux.symtab.sec_versym, so this should not be a problem.
7245088Sab196087 */
7255088Sab196087 if ((ndx == obj_state->os_symtabnum) ||
7265088Sab196087 (symtab->symt_versym == SHN_UNDEF))
7275088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOVERSYMSEC),
7285088Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name);
7295088Sab196087
7305088Sab196087 /* Got it. Report to the user and return the necessary data */
7315088Sab196087 versymsec = &obj_state->os_secarr[symtab->symt_versym];
7325088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDVERSYM),
7335088Sab196087 EC_WORD(symsec->sec_shndx), symsec->sec_name,
7345088Sab196087 EC_WORD(versymsec->sec_shndx), versymsec->sec_name);
7355088Sab196087 *versym = (Versym *) versymsec->sec_data->d_buf;
7365088Sab196087 *num = versymsec->sec_shdr->sh_size / versymsec->sec_shdr->sh_entsize;
7375088Sab196087 return (versymsec);
7385088Sab196087 }
7395088Sab196087
7405088Sab196087
7415088Sab196087
7425088Sab196087 /*
7435088Sab196087 * Locate the string table specified by shndx for this object.
7445088Sab196087 *
7456225Sab196087 * entry:
7466225Sab196087 * obj_state - Object state.
7476225Sab196087 * shndx - Section index for string table section
7486225Sab196087 * allow_shflags - If False (0), only sections of type SHT_STRTAB
7496225Sab196087 * are accepted as being string tables, and any other type
7506225Sab196087 * will fail. If True (1), non-stringtable sections with
7516225Sab196087 * their SHF_STRINGS flag set are also accepted.
7526225Sab196087 *
7535088Sab196087 * exit:
7545088Sab196087 * Returns section descriptor on success. On failure, does not return.
7556225Sab196087 *
7566225Sab196087 * note:
7576225Sab196087 * At this time, we can only support SHF_STRINGS sections that
7586225Sab196087 * use single byte characters and which do not require alignment >1.
7596225Sab196087 * SHF_STRINGS sections that have multi-byte characters or alignment
7606225Sab196087 * are not currently supported and will draw an error even if
7616225Sab196087 * allow_shflags is True.
7625088Sab196087 */
7635088Sab196087 elfedit_section_t *
elfedit_sec_getstr(elfedit_obj_state_t * obj_state,Word shndx,int allow_shflags)7646225Sab196087 elfedit_sec_getstr(elfedit_obj_state_t *obj_state, Word shndx,
7656225Sab196087 int allow_shflags)
7665088Sab196087 {
7675088Sab196087 elfedit_section_t *strsec;
7685088Sab196087
7695088Sab196087 if ((shndx == 0) || (shndx >= obj_state->os_shnum))
7705088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_STRSHNDX),
7715892Sab196087 EC_WORD(shndx), EC_WORD(obj_state->os_shnum - 1));
7725088Sab196087
7735088Sab196087 strsec = &obj_state->os_secarr[shndx];
7746225Sab196087 if (strsec->sec_shdr->sh_type == SHT_STRTAB) {
7756225Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSTRTAB),
7766225Sab196087 EC_WORD(shndx), strsec->sec_name);
7776225Sab196087 } else if (allow_shflags &&
7786225Sab196087 ((strsec->sec_shdr->sh_flags & SHF_STRINGS) != 0) &&
7796225Sab196087 (strsec->sec_shdr->sh_entsize <= 1) &&
7806225Sab196087 (strsec->sec_shdr->sh_addralign <= 1)) {
7816225Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSTRTABFL),
7826225Sab196087 EC_WORD(shndx), strsec->sec_name);
7836225Sab196087 } else {
7845088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOTSTRSH),
7855088Sab196087 EC_WORD(shndx), strsec->sec_name);
7866225Sab196087 }
7875088Sab196087
7885088Sab196087 return (strsec);
7895088Sab196087 }
7905088Sab196087
7915088Sab196087
7925088Sab196087 /*
7935088Sab196087 * Returns the offset of the specified string from within
7945088Sab196087 * the given section.
7955088Sab196087 *
7965088Sab196087 * entry:
7975088Sab196087 * sec - Descriptor for section
7985088Sab196087 * tail_ign - If non-zero, the # of characters at the end of the
7995088Sab196087 * section that should be ignored and not searched.
8005088Sab196087 * str - String we are looking for.
8015088Sab196087 * ret_offset - Address of variable to receive result
8025088Sab196087 *
8035088Sab196087 * exit:
8045088Sab196087 * Returns 1 for success, and 0 for failure. If successful, *ret_offset
8055088Sab196087 * is set to the offset of the found string within the section.
8065088Sab196087 */
8075088Sab196087 int
elfedit_sec_findstr(elfedit_section_t * sec,Word tail_ign,const char * str,Word * ret_offset)8085088Sab196087 elfedit_sec_findstr(elfedit_section_t *sec, Word tail_ign,
8095088Sab196087 const char *str, Word *ret_offset)
8105088Sab196087 {
8115088Sab196087 int str_fch = *str; /* First character in str */
8125088Sab196087 Word len; /* # characters in table */
8135088Sab196087 char *s; /* ptr to strings within table */
8145088Sab196087 const char *tail; /* 1 past final character of table */
8155088Sab196087
8165088Sab196087
8175088Sab196087 /* Size of the section, minus the reserved part (if any) at the end */
8185088Sab196087 len = sec->sec_shdr->sh_size - tail_ign;
8195088Sab196087
8205088Sab196087 /*
8215088Sab196087 * Move through the section character by character looking for
8225088Sab196087 * a match. Moving character by character instead of skipping
8235088Sab196087 * from NULL terminated string to string allows us to use
8245088Sab196087 * the tails longer strings (i.e. we want "bar", and "foobar" exists).
8255088Sab196087 * We look at the first character manually before calling strcmp()
8265088Sab196087 * to lower the cost of this approach.
8275088Sab196087 */
8285088Sab196087 s = (char *)sec->sec_data->d_buf;
8295088Sab196087 tail = s + len;
8305088Sab196087 for (; s <= tail; s++) {
8315088Sab196087 if ((*s == str_fch) && (strcmp(s, str) == 0)) {
8325088Sab196087 *ret_offset = s - (char *)sec->sec_data->d_buf;
8335088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
8345088Sab196087 MSG_INTL(MSG_DEBUG_EXISTSTR),
8355088Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name,
8365088Sab196087 EC_WORD(*ret_offset), s);
8375088Sab196087 return (1);
8385088Sab196087 }
8395088Sab196087 }
8405088Sab196087
8415088Sab196087 /* Didn't find it. Report failure */
8425088Sab196087 return (0);
8435088Sab196087 }
8445088Sab196087
8455088Sab196087
8465088Sab196087 /*
8475088Sab196087 * Locate the DT_SUNW_STRPAD element of the given dynamic section if
8485088Sab196087 * it exists.
8495088Sab196087 *
8505088Sab196087 * entry:
851*9273SAli.Bahrami@Sun.COM * obj_state - Object state for open object to query.
8525088Sab196087 * dynsec - Dynamic section descriptor
8535088Sab196087 * dyn_strpad - Address of variable to receive the results.
8545088Sab196087 * The caller is responsible for calling elfedit_dyn_elt_init()
8555088Sab196087 * on this variable beforehand.
8565088Sab196087 *
8575088Sab196087 * exit:
8585088Sab196087 * The dynamic section is searched, and if a DT_SUNW_STRPAD element
8595088Sab196087 * is found, dyn_strpad is updated via elfedit_dyn_elt_save() to
8605088Sab196087 * reference it.
8615088Sab196087 *
8625088Sab196087 * Returns the final value of dyn_strpad->dn_seen.
8635088Sab196087 */
8645088Sab196087 int
elfedit_dynstr_getpad(elfedit_obj_state_t * obj_state,elfedit_section_t * dynsec,elfedit_dyn_elt_t * dyn_strpad)865*9273SAli.Bahrami@Sun.COM elfedit_dynstr_getpad(elfedit_obj_state_t *obj_state, elfedit_section_t *dynsec,
866*9273SAli.Bahrami@Sun.COM elfedit_dyn_elt_t *dyn_strpad)
8675088Sab196087 {
868*9273SAli.Bahrami@Sun.COM Word numdyn = dynsec->sec_shdr->sh_size / dynsec->sec_shdr->sh_entsize;
8695088Sab196087 Dyn *dyn = (Dyn *) dynsec->sec_data->d_buf;
870*9273SAli.Bahrami@Sun.COM Word i;
871*9273SAli.Bahrami@Sun.COM
872*9273SAli.Bahrami@Sun.COM /*
873*9273SAli.Bahrami@Sun.COM * DT_SUNW_STRPAD is specific to the Solaris OSABI.
874*9273SAli.Bahrami@Sun.COM * If the object is tagged otherwise, don't even look.
875*9273SAli.Bahrami@Sun.COM */
876*9273SAli.Bahrami@Sun.COM if (!elfedit_test_osabi(obj_state, ELFOSABI_SOLARIS, 0))
877*9273SAli.Bahrami@Sun.COM return (dyn_strpad->dn_seen);
8785088Sab196087
8795088Sab196087 /* Go through dynamic section tags and find the STRPAD entry */
8805088Sab196087 for (i = 0; i < numdyn; i++) {
8815088Sab196087 if (dyn[i].d_tag == DT_SUNW_STRPAD) {
8825088Sab196087 elfedit_dyn_elt_save(dyn_strpad, i, &dyn[i]);
8835088Sab196087 break;
8845088Sab196087 }
8855088Sab196087 }
8865088Sab196087
8875088Sab196087 return (dyn_strpad->dn_seen);
8885088Sab196087 }
8895088Sab196087
8905088Sab196087
8915088Sab196087
8925088Sab196087 /*
8935088Sab196087 * Given references to the dynamic section, its string table,
8945088Sab196087 * and the DT_SUNW_STRPAD entry of the dynamic section, returns
8955088Sab196087 * the offset of the specified string from within the given string table,
8965088Sab196087 * adding it if possible.
8975088Sab196087 *
8985088Sab196087 * entry:
8995088Sab196087 * dynsec - Dynamic section descriptor
9005088Sab196087 * strsec - Descriptor for string table assocated with dynamic section
9015088Sab196087 * dyn_strpad - DT_SUNW_STRPAD element from dynamic section
9025088Sab196087 * str - String we are looking for.
9035088Sab196087 *
9045088Sab196087 * exit:
9055088Sab196087 * On success, the offset of the given string within the string
9065088Sab196087 * table is returned. If the string does not exist within the table,
9075088Sab196087 * but there is a valid DT_SUNW_STRPAD reserved section, then we
9085088Sab196087 * add the string, and update the dynamic section STRPAD element
9095088Sab196087 * to reflect the space we use.
9105088Sab196087 *
9115088Sab196087 * This routine does not return on failure.
9125088Sab196087 */
9135088Sab196087 Word
elfedit_dynstr_insert(elfedit_section_t * dynsec,elfedit_section_t * strsec,elfedit_dyn_elt_t * dyn_strpad,const char * str)9145088Sab196087 elfedit_dynstr_insert(elfedit_section_t *dynsec, elfedit_section_t *strsec,
9155088Sab196087 elfedit_dyn_elt_t *dyn_strpad, const char *str)
9165088Sab196087 {
9175088Sab196087 Word ins_off; /* Table offset to 1st reserved byte */
9185088Sab196087 char *s; /* ptr to strings within table */
9195088Sab196087 Word len; /* Length of str inc. NULL byte */
9205088Sab196087 Word tail_ign; /* # reserved bytes at end of strtab */
9215088Sab196087
9225088Sab196087
9235088Sab196087 tail_ign = dyn_strpad->dn_seen ? dyn_strpad->dn_dyn.d_un.d_val : 0;
9245088Sab196087
9255088Sab196087 /* Does the string already existin the string table? */
9265088Sab196087 if (elfedit_sec_findstr(strsec, tail_ign, str, &len))
9275088Sab196087 return (len);
9285088Sab196087
9295088Sab196087 /*
9305088Sab196087 * The desired string does not already exist. Do we have
9315088Sab196087 * room to add it?
9325088Sab196087 */
9335088Sab196087 len = strlen(str) + 1;
9345088Sab196087 if (!dyn_strpad->dn_seen || (len > dyn_strpad->dn_dyn.d_un.d_val))
9355088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRPAD),
9365088Sab196087 EC_WORD(strsec->sec_shdr->sh_link),
9375088Sab196087 strsec->sec_name);
9385088Sab196087
9395088Sab196087
9405088Sab196087 /*
9415088Sab196087 * We will add the string at the first byte of the reserved NULL
9425088Sab196087 * area at the end. The DT_SUNW_STRPAD dynamic element gives us
9435088Sab196087 * the size of that reserved space.
9445088Sab196087 */
9455088Sab196087 ins_off = strsec->sec_shdr->sh_size - tail_ign;
9465088Sab196087 s = ((char *)strsec->sec_data->d_buf) + ins_off;
9475088Sab196087
9485088Sab196087 /* Announce the operation */
9495088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_ADDSTR),
9505088Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name,
9515088Sab196087 EC_WORD(ins_off), EC_WORD(len),
9525088Sab196087 EC_WORD(dyn_strpad->dn_dyn.d_un.d_val), str);
9535088Sab196087
9545088Sab196087 /*
9555088Sab196087 * Copy the string into the pad area at the end, and
9565088Sab196087 * mark the data area as dirty so libelf will flush our
9575088Sab196087 * changes to the string data.
9585088Sab196087 */
9595088Sab196087 (void) strncpy(s, str, dyn_strpad->dn_dyn.d_un.d_val);
9605088Sab196087 elfedit_modified_data(strsec);
9615088Sab196087
9625088Sab196087 /* Update the DT_STRPAD dynamic entry */
9635088Sab196087 dyn_strpad->dn_dyn.d_un.d_val -= len;
9645088Sab196087 ((Dyn *) dynsec->sec_data->d_buf)[dyn_strpad->dn_ndx] =
9655088Sab196087 dyn_strpad->dn_dyn;
9665088Sab196087 elfedit_modified_data(dynsec);
9675088Sab196087
9685088Sab196087 return (ins_off);
9695088Sab196087 }
9705088Sab196087
9715088Sab196087
9725088Sab196087 /*
9735088Sab196087 * Test to see if a call to elfedit_strtab_insert() will succeed.
9745088Sab196087 *
9755088Sab196087 * entry:
9765088Sab196087 * obj_state - Object state for open object to query.
9775088Sab196087 * strsec - Descriptor for string table
9785088Sab196087 * dynsec - NULL, or descriptor for dynamic section. Providing
9795088Sab196087 * a non-NULL value here will prevent elfedit_strtab_insert()
9805088Sab196087 * from looking it up, and the duplicate debug message that
9815088Sab196087 * would result.
9825088Sab196087 * str - String we are looking for.
9835088Sab196087 *
9845088Sab196087 * exit:
9855088Sab196087 * If the string exists within the string table, or if an attempt
9865088Sab196087 * to insert it will be successful, quietly return. Otherwise, throw
9875088Sab196087 * the error elfedit_strtab_insert() would throw under the
9885088Sab196087 * same circumstances.
9895088Sab196087 *
9905088Sab196087 */
9915088Sab196087 void
elfedit_strtab_insert_test(elfedit_obj_state_t * obj_state,elfedit_section_t * strsec,elfedit_section_t * dynsec,const char * str)9925088Sab196087 elfedit_strtab_insert_test(elfedit_obj_state_t *obj_state,
9935088Sab196087 elfedit_section_t *strsec, elfedit_section_t *dynsec, const char *str)
9945088Sab196087 {
9955088Sab196087 Word len; /* Length of str inc. NULL byte */
9965088Sab196087 int is_dynstr = 0;
9975088Sab196087 Word tail_ign = 0;
9985088Sab196087
9995088Sab196087
10005088Sab196087 /*
10015088Sab196087 * The dynstr is a special case, because we can add strings
10025088Sab196087 * to it under certain circumstances. So, we look for the
10035088Sab196087 * dynamic section, and if it exists, compare its sh_link to
10045088Sab196087 * the string section index. If they match, it is the dynstr,
10055088Sab196087 * and we use elfedit_dynstr_insert() to do the work.
10065088Sab196087 */
10075088Sab196087 if (dynsec == NULL) {
10085088Sab196087 if (obj_state->os_dynndx != SHN_UNDEF) {
10095088Sab196087 dynsec = &obj_state->os_secarr[obj_state->os_dynndx];
10105088Sab196087 if ((dynsec->sec_shdr->sh_type == SHT_DYNAMIC) &&
10115088Sab196087 (strsec->sec_shndx == dynsec->sec_shdr->sh_link)) {
10125088Sab196087 is_dynstr = 1;
10135088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
10145088Sab196087 MSG_INTL(MSG_DEBUG_FNDDYN),
10155088Sab196087 EC_WORD(dynsec->sec_shndx),
10165088Sab196087 dynsec->sec_name);
10175088Sab196087 }
10185088Sab196087 }
10195088Sab196087 } else {
10205088Sab196087 if (strsec->sec_shndx == dynsec->sec_shdr->sh_link)
10215088Sab196087 is_dynstr = 1;
10225088Sab196087 }
10235088Sab196087
10245088Sab196087
10255088Sab196087 if (is_dynstr) {
10265088Sab196087 elfedit_dyn_elt_t dyn_strpad;
10275088Sab196087
10285088Sab196087 /* Determine the size of the STRPAD area, if any */
10295088Sab196087 elfedit_dyn_elt_init(&dyn_strpad);
1030*9273SAli.Bahrami@Sun.COM if (elfedit_dynstr_getpad(obj_state, dynsec, &dyn_strpad) != 0)
10315088Sab196087 tail_ign = dyn_strpad.dn_dyn.d_un.d_val;
10325088Sab196087 }
10335088Sab196087
10345088Sab196087 /*
10355088Sab196087 * If the string is already in the string table, we
10365088Sab196087 * can't fail.
10375088Sab196087 */
10385088Sab196087 if (elfedit_sec_findstr(strsec, tail_ign, str, &len) != 0)
10395088Sab196087 return;
10405088Sab196087
10415088Sab196087 /*
10425088Sab196087 * It's not in the table, but if this is the dynstr, and
10435088Sab196087 * there is enough room, we will be able to add it.
10445088Sab196087 */
10455088Sab196087 if (is_dynstr && (tail_ign > strlen(str)))
10465088Sab196087 return;
10475088Sab196087
10485088Sab196087 /* Can't do it. Issue error */
10495088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRPAD),
10505088Sab196087 EC_WORD(strsec->sec_shdr->sh_link), strsec->sec_name);
10515088Sab196087 }
10525088Sab196087
10535088Sab196087
10545088Sab196087 /*
10555088Sab196087 * Returns the offset of the specified string from within
10565088Sab196087 * the given string table, adding it if possible.
10575088Sab196087 *
10585088Sab196087 * entry:
10595088Sab196087 * obj_state - Object state for open object to query.
10605088Sab196087 * strsec - Descriptor for string table
10615088Sab196087 * dynsec - NULL, or descriptor for dynamic section. Providing
10625088Sab196087 * a non-NULL value here will prevent elfedit_strtab_insert()
10635088Sab196087 * from looking it up, and the duplicate debug message that
10645088Sab196087 * would result.
10655088Sab196087 * str - String we are looking for.
10665088Sab196087 *
10675088Sab196087 * exit:
10685088Sab196087 * On success, the offset of the given string within the string
10695088Sab196087 * table is returned. If the string does not exist within the table,
10705088Sab196087 * and it is possible to add it, elfedit_strtab_insert() will
10715088Sab196087 * add the string, and then return the offset.
10725088Sab196087 *
10735088Sab196087 * If the string does not exist in the string table, and cannot
10745088Sab196087 * be added, this routine issues an error message and does not
10755088Sab196087 * return to the caller.
10765088Sab196087 */
10775088Sab196087 Word
elfedit_strtab_insert(elfedit_obj_state_t * obj_state,elfedit_section_t * strsec,elfedit_section_t * dynsec,const char * str)10785088Sab196087 elfedit_strtab_insert(elfedit_obj_state_t *obj_state, elfedit_section_t *strsec,
10795088Sab196087 elfedit_section_t *dynsec, const char *str)
10805088Sab196087 {
10815088Sab196087 Word len; /* Length of str inc. NULL byte */
10825088Sab196087 int is_dynstr = 0;
10835088Sab196087 elfedit_dyn_elt_t dyn_strpad;
10845088Sab196087
10855088Sab196087
10865088Sab196087 /*
10875088Sab196087 * The dynstr is a special case, because we can add strings
10885088Sab196087 * to it under certain circumstances. So, we look for the
10895088Sab196087 * dynamic section, and if it exists, compare its sh_link to
10905088Sab196087 * the string section index. If they match, it is the dynstr,
10915088Sab196087 * and we use elfedit_dynstr_insert() to do the work.
10925088Sab196087 */
10935088Sab196087 if (dynsec == NULL) {
10945088Sab196087 if (obj_state->os_dynndx != SHN_UNDEF) {
10955088Sab196087 dynsec = &obj_state->os_secarr[obj_state->os_dynndx];
10965088Sab196087 if ((dynsec->sec_shdr->sh_type == SHT_DYNAMIC) &&
10975088Sab196087 (strsec->sec_shndx == dynsec->sec_shdr->sh_link)) {
10985088Sab196087 is_dynstr = 1;
10995088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG,
11005088Sab196087 MSG_INTL(MSG_DEBUG_FNDDYN),
11015088Sab196087 EC_WORD(dynsec->sec_shndx),
11025088Sab196087 dynsec->sec_name);
11035088Sab196087 }
11045088Sab196087 }
11055088Sab196087 } else {
11065088Sab196087 if (strsec->sec_shndx == dynsec->sec_shdr->sh_link)
11075088Sab196087 is_dynstr = 1;
11085088Sab196087 }
11095088Sab196087
11105088Sab196087 if (is_dynstr) {
11115088Sab196087 elfedit_dyn_elt_init(&dyn_strpad);
1112*9273SAli.Bahrami@Sun.COM (void) elfedit_dynstr_getpad(obj_state, dynsec, &dyn_strpad);
11135088Sab196087 return (elfedit_dynstr_insert(dynsec, strsec,
11145088Sab196087 &dyn_strpad, str));
11155088Sab196087 }
11165088Sab196087
11175088Sab196087 /*
11185088Sab196087 * This is not the dynstr, so we are limited to strings that
11195088Sab196087 * already exist within it. Try to find one.
11205088Sab196087 */
11215088Sab196087 if (elfedit_sec_findstr(strsec, 0, str, &len))
11225088Sab196087 return (len);
11235088Sab196087
11245088Sab196087 /* Can't do it. Issue error */
11255088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRPAD),
11265088Sab196087 EC_WORD(strsec->sec_shdr->sh_link), strsec->sec_name);
11275088Sab196087 /*NOTREACHED*/
11285088Sab196087
11295088Sab196087 return (0);
11305088Sab196087 }
11315088Sab196087
11325088Sab196087
11335088Sab196087 /*
11345088Sab196087 * Return the string found at the given offset within the specified
11355088Sab196087 * string table.
11365088Sab196087 *
11375088Sab196087 * entry:
11385088Sab196087 * strsec - Section descriptor for string table section
11395088Sab196087 * offset - Offset of desired string in string table
11405088Sab196087 * msg_type - ELFEDIT_MSG_ type code to use with message
11415088Sab196087 * issued if offset is out of range for the symbol table.
11425088Sab196087 * debug_msg - True if should issue debug message for string found.
11435088Sab196087 *
11445088Sab196087 * exit:
11455088Sab196087 * If the offset is within the section, the string pointer
11465088Sab196087 * is returned. Otherwise an error is issued using msg_type
11475088Sab196087 * to determine the type of message. If this routine retains
11485088Sab196087 * control after the message is issued, a safe string is returned.
11495088Sab196087 */
11505088Sab196087 const char *
elfedit_offset_to_str(elfedit_section_t * strsec,Word offset,elfedit_msg_t msg_type,int debug_msg)11515088Sab196087 elfedit_offset_to_str(elfedit_section_t *strsec, Word offset,
11525088Sab196087 elfedit_msg_t msg_type, int debug_msg)
11535088Sab196087 {
11545088Sab196087 const char *str;
11555088Sab196087
11565088Sab196087 /* Make sure it is a string table section */
11575088Sab196087 if (strsec->sec_shdr->sh_type != SHT_STRTAB)
11585088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOTSTRSH),
11595088Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name);
11605088Sab196087
11615088Sab196087 /* Ensure the offset is in range */
11625088Sab196087 if (offset >= strsec->sec_data->d_size) {
11635088Sab196087 elfedit_msg(msg_type, MSG_INTL(MSG_ERR_BADSTROFF),
11645088Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name,
11655088Sab196087 EC_WORD(offset), EC_WORD(strsec->sec_data->d_size - 1));
11665088Sab196087 /*
11675088Sab196087 * If the msg_type is a type that returns, give the
11685088Sab196087 * user a safe string to use.
11695088Sab196087 */
11705088Sab196087 str = MSG_INTL(MSG_BADSYMOFFSETNAM);
11715088Sab196087 } else {
11725088Sab196087 /* Return the string */
11735088Sab196087 str = ((const char *)strsec->sec_data->d_buf) + offset;
11745088Sab196087 }
11755088Sab196087
11765088Sab196087 if (debug_msg)
11775088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSTR),
11785088Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name,
11795088Sab196087 EC_WORD(offset), str);
11805088Sab196087 return (str);
11815088Sab196087 }
11825088Sab196087
11835088Sab196087
11845088Sab196087 /*
11855088Sab196087 * Given a string table section, and a dynamic section entry
11865088Sab196087 * that supplies a string offset, return the string found at
11875088Sab196087 * the given offset. This routine is a convenience wrapper on
11885088Sab196087 * elfedit_offset_to_str().
11895088Sab196087 *
11905088Sab196087 * exit:
11915088Sab196087 * As per elfedit_offset_to_str().
11925088Sab196087 */
11935088Sab196087 const char *
elfedit_dyn_offset_to_str(elfedit_section_t * strsec,elfedit_dyn_elt_t * dynelt)11945088Sab196087 elfedit_dyn_offset_to_str(elfedit_section_t *strsec, elfedit_dyn_elt_t *dynelt)
11955088Sab196087 {
11965088Sab196087 return (elfedit_offset_to_str(strsec, dynelt->dn_dyn.d_un.d_val,
11975088Sab196087 ELFEDIT_MSG_ERR, 0));
11985088Sab196087 }
11995088Sab196087
12005088Sab196087
12015088Sab196087 /*
12025088Sab196087 * Given a section, fabricate a string for the form:
12035088Sab196087 *
12045088Sab196087 * "[#: name]"
12055088Sab196087 *
12065088Sab196087 * as used at the beginning of debug messages. A pointer to static
12075088Sab196087 * memory is returned, and is good until the next such call.
12085088Sab196087 */
12095088Sab196087 const char *
elfedit_sec_msgprefix(elfedit_section_t * sec)12105088Sab196087 elfedit_sec_msgprefix(elfedit_section_t *sec)
12115088Sab196087 {
12125088Sab196087 static char *buf;
12135088Sab196087 static size_t bufsize;
12145088Sab196087
12155088Sab196087 size_t need;
12165088Sab196087
12175088Sab196087 need = 64 + strlen(sec->sec_name);
12185088Sab196087 if (need > bufsize) {
12195088Sab196087 buf = elfedit_realloc(MSG_INTL(MSG_ALLOC_SECMSGPRE), buf, need);
12205088Sab196087 bufsize = need;
12215088Sab196087 }
12225088Sab196087
12235088Sab196087 (void) snprintf(buf, bufsize, MSG_ORIG(MSG_FMT_SECMSGPRE),
12245088Sab196087 EC_WORD(sec->sec_shndx), sec->sec_name);
12255088Sab196087
12265088Sab196087 return (buf);
12275088Sab196087 }
1228