xref: /onnv-gate/usr/src/cmd/sgs/elfedit/common/util_machelf.c (revision 9273:9a0603d78ad3)
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