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