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