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