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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
39 #include <sys/elf_SPARC.h>
40 #include <sys/elf_amd64.h>
45 * ELFCLASS specific code that would otherwise be found in util.c
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
56 * The elfedit_modified_*() functions exist to simplify the calls to
57 * the underlying elf_flag*() functions.
60 elfedit_modified_ehdr(elfedit_obj_state_t
*obj_state
)
62 (void) elf_flagehdr(obj_state
->os_elf
, ELF_C_SET
, ELF_F_DIRTY
);
66 elfedit_modified_phdr(elfedit_obj_state_t
*obj_state
)
68 (void) elf_flagphdr(obj_state
->os_elf
, ELF_C_SET
, ELF_F_DIRTY
);
72 elfedit_modified_shdr(elfedit_section_t
*s
)
74 (void) elf_flagshdr(s
->sec_scn
, ELF_C_SET
, ELF_F_DIRTY
);
78 elfedit_modified_data(elfedit_section_t
*s
)
80 (void) elf_flagdata(s
->sec_data
, ELF_C_SET
, ELF_F_DIRTY
);
86 * Prepare an elfedit_dyn_elt_t structure for use.
89 elfedit_dyn_elt_init(elfedit_dyn_elt_t
*elt
)
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.
99 elfedit_dyn_elt_save(elfedit_dyn_elt_t
*elt
, Word ndx
, Dyn
*dyn
)
108 * Return the index of the first section that has the given name.
111 * obj_state - Object state.
112 * shnam - Name of desired section
115 * On success, returns the section index. On failure, an error
116 * is issued, and this routine does not return to the caller.
119 elfedit_name_to_shndx(elfedit_obj_state_t
*obj_state
, const char *shnam
)
121 elfedit_section_t
*sec
= obj_state
->os_secarr
;
123 Word shnum
= obj_state
->os_shnum
;
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
);
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
);
143 * Return the index of the first section that has the given type.
146 * obj_state - Object state.
147 * shtype - Type of desired section
150 * On success, returns the section index. On failure, an error
151 * is issued, and this routine does not return to the caller.
154 elfedit_type_to_shndx(elfedit_obj_state_t
*obj_state
, Word shtype
)
156 Conv_inv_buf_t inv_buf
;
157 elfedit_section_t
*sec
= obj_state
->os_secarr
;
159 Word shnum
= obj_state
->os_shnum
;
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
,
167 obj_state
->os_ehdr
->e_ident
[EI_OSABI
],
168 obj_state
->os_ehdr
->e_machine
,
169 shtype
, 0, &inv_buf
));
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
));
185 * Locate the index of the first symbol that has the given name
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.
197 * On success, issues debug message, sets *ret_symndx, and returns
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.
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.
212 elfedit_name_to_symndx(elfedit_section_t
*symsec
, elfedit_section_t
*strsec
,
213 const char *name
, elfedit_msg_t msg_type
, Word
*ret_symndx
)
216 Sym
*sym
= (Sym
*) symsec
->sec_data
->d_buf
;
217 Word cnt
= symsec
->sec_shdr
->sh_size
/ symsec
->sec_shdr
->sh_entsize
;
221 for (ndx
= 0; ndx
< cnt
; ndx
++) {
222 offset
= sym
[ndx
].st_name
;
224 curname
= elfedit_offset_to_str(strsec
, offset
,
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
);
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
);
240 return (0); /* lint */
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.
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
259 elfedit_shndx_to_name(elfedit_obj_state_t
*obj_state
, Word shndx
)
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).
267 static Conv_inv_buf_t buf1
, buf2
;
268 static Conv_inv_buf_t
*buf
;
271 * If it is outside of the reserved area, and inside the
272 * range of section indexes in the ELF file, then show
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
);
281 * Anything else is handled by libconv. It will return standard
282 * names for known items, or format as a number otherwise.
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
));
292 * Locate the arbitrary section specified by shndx for this object.
295 * Returns section descriptor on success. On failure, does not return.
298 elfedit_sec_get(elfedit_obj_state_t
*obj_state
, Word shndx
)
300 elfedit_section_t
*sec
;
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));
306 sec
= &obj_state
->os_secarr
[shndx
];
308 elfedit_msg(ELFEDIT_MSG_DEBUG
, MSG_INTL(MSG_DEBUG_FNDSEC
),
309 EC_WORD(shndx
), sec
->sec_name
);
316 * Compare the a specified osabi with that of the current object.
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.
324 * If current osabi is the one specified, True (1) is returned.
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.
331 * ELFOSABI_NONE is considered to be equivalent to ELFOSABI_SOLARIS.
334 elfedit_test_osabi(elfedit_obj_state_t
*obj_state
, uchar_t osabi
,
337 uchar_t obj_osabi
= obj_state
->os_ehdr
->e_ident
[EI_OSABI
];
338 Conv_inv_buf_t inv_buf
;
340 if (obj_osabi
== ELFOSABI_NONE
)
341 obj_osabi
= ELFOSABI_SOLARIS
;
343 if (osabi
== obj_osabi
)
347 elfedit_msg(ELFEDIT_MSG_ERR
, MSG_INTL(MSG_ERR_BADOSABI
),
348 conv_ehdr_osabi(osabi
, 0, &inv_buf
));
353 * Locate the capabilities section for this object
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
363 * On success, returns section descriptor, and sets the
364 * variables referenced by cap and num. On failure,
368 elfedit_sec_getcap(elfedit_obj_state_t
*obj_state
, Cap
**cap
, Word
*num
)
371 elfedit_section_t
*cache
;
373 (void) elfedit_test_osabi(obj_state
, ELFOSABI_SOLARIS
, 1);
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
;
388 /* If here, this object has no capabilities section */
389 elfedit_msg(ELFEDIT_MSG_ERR
, MSG_INTL(MSG_ERR_NOCAP
));
397 * Locate the dynamic section for this object
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
407 * On success, returns section descriptor, and sets the
408 * variables referenced by dyn and numdyn. On failure,
412 elfedit_sec_getdyn(elfedit_obj_state_t
*obj_state
, Dyn
**dyn
, Word
*num
)
414 elfedit_section_t
*cache
;
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
;
425 /* If here, this object has no dynamic section */
426 elfedit_msg(ELFEDIT_MSG_ERR
, MSG_INTL(MSG_ERR_NODYN
));
434 * Locate the syminfo section for this object
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.
444 * On success, returns section descriptor, and sets the
445 * variables referenced by syminfo and num. On failure,
449 elfedit_sec_getsyminfo(elfedit_obj_state_t
*obj_state
, Syminfo
**syminfo
,
453 elfedit_section_t
*cache
;
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
;
468 /* If here, this object has no syminfo section */
469 elfedit_msg(ELFEDIT_MSG_ERR
, MSG_INTL(MSG_ERR_NOSYMINFO
));
477 * Check the given section to see if it is a known symbol table type.
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.
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.
498 * - If atoui_list is non-NULL, *atoui_list is set to NULL.
499 * - False (0) is returned
502 elfedit_sec_issymtab(elfedit_obj_state_t
*obj_state
, elfedit_section_t
*sec
,
503 int issue_err
, elfedit_atoui_sym_t
**atoui_list
)
505 elfedit_const_t const_type
;
508 /* Is the section a symbol table? */
509 switch (sec
->sec_shdr
->sh_type
) {
511 const_type
= ELFEDIT_CONST_SHT_SYMTAB
;
514 const_type
= ELFEDIT_CONST_SHT_DYNSYM
;
516 case SHT_SUNW_LDYNSYM
:
518 * These sections are only known to be symbol tables
519 * if the osabi is Solaris.
521 if (elfedit_test_osabi(obj_state
, ELFOSABI_SOLARIS
, 0)) {
522 const_type
= ELFEDIT_CONST_SHT_LDYNSYM
;
528 elfedit_msg(ELFEDIT_MSG_ERR
,
529 MSG_INTL(MSG_ERR_NOTSYMTAB
),
530 EC_WORD(sec
->sec_shndx
), sec
->sec_name
);
535 if (atoui_list
!= NULL
)
536 *atoui_list
= (ret
== 0) ? NULL
:
537 elfedit_const_to_atoui(const_type
);
545 * Locate a symbol table section for this object
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
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.
563 * On success, returns section descriptor, and sets the
564 * variables referenced by sym, and numsym. On failure,
568 elfedit_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
)
573 elfedit_section_t
*symsec
= NULL
;
574 elfedit_symtab_t
*symtab
;
575 const char *type_name
;
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));
583 * Look at each known symbol table in turn until the desired
584 * one is hit, or there are no more.
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
];
591 if ((by_index
&& (symtab
->symt_shndx
== index
)) ||
592 (!by_index
&& (strcmp(s
->sec_name
, name
) == 0))) {
598 /* Did we get a section? */
600 elfedit_msg(ELFEDIT_MSG_ERR
, MSG_INTL(MSG_ERR_NOSYMTAB
));
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
)
618 * Locate the extended symbol index section associated with a symbol
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
627 * numxshndx - Address of variable to receive number of indices
631 * On success, returns extended index section descriptor, and sets the
632 * variables referenced by xshndx, and numxshndx. On failure,
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.
643 elfedit_sec_getxshndx(elfedit_obj_state_t
*obj_state
,
644 elfedit_section_t
*symsec
, Word
**xshndx
, Word
*num
)
646 elfedit_section_t
*xshndxsec
;
647 elfedit_symtab_t
*symtab
;
650 /* Sanity check: symsec must be a symbol table */
651 (void) elfedit_sec_issymtab(obj_state
, symsec
, 1, NULL
);
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
)
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
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
);
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
;
682 * Locate the versym section associated with a symbol table section.
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
690 * numversym - Address of variable to receive number of indices
694 * On success, returns versym section descriptor, and sets the
695 * variables referenced by versym, and numversym. On failure,
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.
706 elfedit_sec_getversym(elfedit_obj_state_t
*obj_state
,
707 elfedit_section_t
*symsec
, Versym
**versym
, Word
*num
)
709 elfedit_section_t
*versymsec
;
710 elfedit_symtab_t
*symtab
;
713 /* Sanity check: symsec must be a symbol table */
714 (void) elfedit_sec_issymtab(obj_state
, symsec
, 1, NULL
);
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
)
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.
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
);
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
;
743 * Locate the string table specified by shndx for this object.
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.
754 * Returns section descriptor on success. On failure, does not return.
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.
764 elfedit_sec_getstr(elfedit_obj_state_t
*obj_state
, Word shndx
,
767 elfedit_section_t
*strsec
;
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));
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
);
784 elfedit_msg(ELFEDIT_MSG_ERR
, MSG_INTL(MSG_ERR_NOTSTRSH
),
785 EC_WORD(shndx
), strsec
->sec_name
);
793 * Returns the offset of the specified string from within
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
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.
808 elfedit_sec_findstr(elfedit_section_t
*sec
, Word tail_ign
,
809 const char *str
, Word
*ret_offset
)
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 */
817 /* Size of the section, minus the reserved part (if any) at the end */
818 len
= sec
->sec_shdr
->sh_size
- tail_ign
;
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.
828 s
= (char *)sec
->sec_data
->d_buf
;
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
);
841 /* Didn't find it. Report failure */
847 * Locate the DT_SUNW_STRPAD element of the given dynamic section if
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.
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
862 * Returns the final value of dyn_strpad->dn_seen.
865 elfedit_dynstr_getpad(elfedit_obj_state_t
*obj_state
, elfedit_section_t
*dynsec
,
866 elfedit_dyn_elt_t
*dyn_strpad
)
868 Word numdyn
= dynsec
->sec_shdr
->sh_size
/ dynsec
->sec_shdr
->sh_entsize
;
869 Dyn
*dyn
= (Dyn
*) dynsec
->sec_data
->d_buf
;
873 * DT_SUNW_STRPAD is specific to the Solaris OSABI.
874 * If the object is tagged otherwise, don't even look.
876 if (!elfedit_test_osabi(obj_state
, ELFOSABI_SOLARIS
, 0))
877 return (dyn_strpad
->dn_seen
);
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
]);
887 return (dyn_strpad
->dn_seen
);
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.
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.
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.
911 * This routine does not return on failure.
914 elfedit_dynstr_insert(elfedit_section_t
*dynsec
, elfedit_section_t
*strsec
,
915 elfedit_dyn_elt_t
*dyn_strpad
, const char *str
)
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 */
923 tail_ign
= dyn_strpad
->dn_seen
? dyn_strpad
->dn_dyn
.d_un
.d_val
: 0;
925 /* Does the string already existin the string table? */
926 if (elfedit_sec_findstr(strsec
, tail_ign
, str
, &len
))
930 * The desired string does not already exist. Do we have
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
),
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.
945 ins_off
= strsec
->sec_shdr
->sh_size
- tail_ign
;
946 s
= ((char *)strsec
->sec_data
->d_buf
) + ins_off
;
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
);
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.
959 (void) strncpy(s
, str
, dyn_strpad
->dn_dyn
.d_un
.d_val
);
960 elfedit_modified_data(strsec
);
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
] =
966 elfedit_modified_data(dynsec
);
973 * Test to see if a call to elfedit_strtab_insert() will succeed.
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
982 * str - String we are looking for.
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.
992 elfedit_strtab_insert_test(elfedit_obj_state_t
*obj_state
,
993 elfedit_section_t
*strsec
, elfedit_section_t
*dynsec
, const char *str
)
995 Word len
; /* Length of str inc. NULL byte */
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.
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
)) {
1013 elfedit_msg(ELFEDIT_MSG_DEBUG
,
1014 MSG_INTL(MSG_DEBUG_FNDDYN
),
1015 EC_WORD(dynsec
->sec_shndx
),
1020 if (strsec
->sec_shndx
== dynsec
->sec_shdr
->sh_link
)
1026 elfedit_dyn_elt_t dyn_strpad
;
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
;
1035 * If the string is already in the string table, we
1038 if (elfedit_sec_findstr(strsec
, tail_ign
, str
, &len
) != 0)
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.
1045 if (is_dynstr
&& (tail_ign
> strlen(str
)))
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
);
1055 * Returns the offset of the specified string from within
1056 * the given string table, adding it if possible.
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
1065 * str - String we are looking for.
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.
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.
1078 elfedit_strtab_insert(elfedit_obj_state_t
*obj_state
, elfedit_section_t
*strsec
,
1079 elfedit_section_t
*dynsec
, const char *str
)
1081 Word len
; /* Length of str inc. NULL byte */
1083 elfedit_dyn_elt_t dyn_strpad
;
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.
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
)) {
1099 elfedit_msg(ELFEDIT_MSG_DEBUG
,
1100 MSG_INTL(MSG_DEBUG_FNDDYN
),
1101 EC_WORD(dynsec
->sec_shndx
),
1106 if (strsec
->sec_shndx
== dynsec
->sec_shdr
->sh_link
)
1111 elfedit_dyn_elt_init(&dyn_strpad
);
1112 (void) elfedit_dynstr_getpad(obj_state
, dynsec
, &dyn_strpad
);
1113 return (elfedit_dynstr_insert(dynsec
, strsec
,
1118 * This is not the dynstr, so we are limited to strings that
1119 * already exist within it. Try to find one.
1121 if (elfedit_sec_findstr(strsec
, 0, str
, &len
))
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
);
1134 * Return the string found at the given offset within the specified
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.
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.
1151 elfedit_offset_to_str(elfedit_section_t
*strsec
, Word offset
,
1152 elfedit_msg_t msg_type
, int debug_msg
)
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
);
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));
1167 * If the msg_type is a type that returns, give the
1168 * user a safe string to use.
1170 str
= MSG_INTL(MSG_BADSYMOFFSETNAM
);
1172 /* Return the string */
1173 str
= ((const char *)strsec
->sec_data
->d_buf
) + offset
;
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
);
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().
1191 * As per elfedit_offset_to_str().
1194 elfedit_dyn_offset_to_str(elfedit_section_t
*strsec
, elfedit_dyn_elt_t
*dynelt
)
1196 return (elfedit_offset_to_str(strsec
, dynelt
->dn_dyn
.d_un
.d_val
,
1197 ELFEDIT_MSG_ERR
, 0));
1202 * Given a section, fabricate a string for the form:
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.
1210 elfedit_sec_msgprefix(elfedit_section_t
*sec
)
1213 static size_t bufsize
;
1217 need
= 64 + strlen(sec
->sec_name
);
1218 if (need
> bufsize
) {
1219 buf
= elfedit_realloc(MSG_INTL(MSG_ALLOC_SECMSGPRE
), buf
, need
);
1223 (void) snprintf(buf
, bufsize
, MSG_ORIG(MSG_FMT_SECMSGPRE
),
1224 EC_WORD(sec
->sec_shndx
), sec
->sec_name
);