Print this page
Append to the string and symbol tables by allocating a new data
descriptor, rather than copying and extending the buffers returned by
libelf.

*** 22,32 **** /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ ! #pragma ident "%Z%%M% %I% %E% SMI" #define ELF_TARGET_ALL #include <elf.h> #include <sys/types.h> --- 22,34 ---- /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ ! /* ! * Copyright (c) 2013 by Delphix. All rights reserved. ! */ #define ELF_TARGET_ALL #include <elf.h> #include <sys/types.h>
*** 1028,1037 **** --- 1030,1041 ---- uint32_t off, eclass, emachine1, emachine2; size_t symsize, nsym, isym, istr, len; key_t objkey; dt_link_pair_t *pair, *bufs = NULL; dt_strtab_t *strtab; + Elf_Data *data_newsym, *data_newstr; + size_t newsym = 0; if ((fd = open64(obj, O_RDWR)) == -1) { return (dt_link_error(dtp, elf, fd, bufs, "failed to open %s: %s", obj, strerror(errno))); }
*** 1260,1300 **** dt_strtab_destroy(strtab); if ((pair = dt_alloc(dtp, sizeof (*pair))) == NULL) goto err; ! if ((pair->dlp_str = dt_alloc(dtp, data_str->d_size + ! len)) == NULL) { dt_free(dtp, pair); goto err; } ! if ((pair->dlp_sym = dt_alloc(dtp, data_sym->d_size + ! nsym * symsize)) == NULL) { dt_free(dtp, pair->dlp_str); dt_free(dtp, pair); goto err; } pair->dlp_next = bufs; bufs = pair; ! bcopy(data_str->d_buf, pair->dlp_str, data_str->d_size); ! data_str->d_buf = pair->dlp_str; ! data_str->d_size += len; ! (void) elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY); ! ! shdr_str.sh_size += len; ! (void) gelf_update_shdr(scn_str, &shdr_str); ! ! bcopy(data_sym->d_buf, pair->dlp_sym, data_sym->d_size); ! data_sym->d_buf = pair->dlp_sym; ! data_sym->d_size += nsym * symsize; ! (void) elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY); ! shdr_sym.sh_size += nsym * symsize; ! (void) gelf_update_shdr(scn_sym, &shdr_sym); nsym += isym; } else { dt_strtab_destroy(strtab); } --- 1264,1297 ---- dt_strtab_destroy(strtab); if ((pair = dt_alloc(dtp, sizeof (*pair))) == NULL) goto err; ! if ((pair->dlp_str = dt_alloc(dtp, len)) == NULL) { dt_free(dtp, pair); goto err; } ! if ((pair->dlp_sym = ! dt_alloc(dtp, nsym * symsize)) == NULL) { dt_free(dtp, pair->dlp_str); dt_free(dtp, pair); goto err; } pair->dlp_next = bufs; bufs = pair; ! if ((data_newstr = elf_newdata(scn_str)) == NULL) ! goto err; ! data_newstr->d_size = len; ! data_newstr->d_buf = pair->dlp_str; ! if ((data_newsym = elf_newdata(scn_sym)) == NULL) ! goto err; ! data_newsym->d_size = nsym * symsize; ! data_newsym->d_buf = pair->dlp_sym; nsym += isym; } else { dt_strtab_destroy(strtab); }
*** 1355,1370 **** bcopy(s, pname, p - s); pname[p - s] = '\0'; p = strhyphenate(p + 3); /* strlen("___") */ ! if (dt_symtab_lookup(data_sym, isym, rela.r_offset, ! shdr_rel.sh_info, &fsym) != 0) goto err; ! ! if (fsym.st_name > data_str->d_size) goto err; assert(GELF_ST_TYPE(fsym.st_info) == STT_FUNC); /* * If a NULL relocation name is passed to --- 1352,1376 ---- bcopy(s, pname, p - s); pname[p - s] = '\0'; p = strhyphenate(p + 3); /* strlen("___") */ ! if (dt_symtab_lookup(data_newsym, newsym, ! rela.r_offset, shdr_rel.sh_info, &fsym) == 0) { ! if (fsym.st_name >= data_str->d_size + ! data_newstr->d_size) goto err; ! s = (char *)data_newstr->d_buf + ! fsym.st_name - data_str->d_size; ! } else if (dt_symtab_lookup(data_sym, isym, ! rela.r_offset, shdr_rel.sh_info, &fsym) == 0) { ! if (fsym.st_name >= data_str->d_size) goto err; + s = (char *)data_str->d_buf + fsym.st_name; + } else { + goto err; + } assert(GELF_ST_TYPE(fsym.st_info) == STT_FUNC); /* * If a NULL relocation name is passed to
*** 1373,1398 **** * name if the symbol is locally scoped; the function * name may need to change if we've found the global * alias for the locally scoped symbol (we prefer * global symbols to locals in dt_symtab_lookup()). */ - s = (char *)data_str->d_buf + fsym.st_name; r = NULL; if (GELF_ST_BIND(fsym.st_info) == STB_LOCAL) { dsym = fsym; dsym.st_name = istr; dsym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC); dsym.st_other = ELF64_ST_VISIBILITY(STV_ELIMINATE); ! (void) gelf_update_sym(data_sym, isym, &dsym); ! r = (char *)data_str->d_buf + istr; istr += 1 + sprintf(r, dt_symfmt, dt_symprefix, objkey, s); isym++; assert(isym <= nsym); } else if (strncmp(s, dt_symprefix, strlen(dt_symprefix)) == 0) { r = s; --- 1379,1406 ---- * name if the symbol is locally scoped; the function * name may need to change if we've found the global * alias for the locally scoped symbol (we prefer * global symbols to locals in dt_symtab_lookup()). */ r = NULL; if (GELF_ST_BIND(fsym.st_info) == STB_LOCAL) { dsym = fsym; dsym.st_name = istr; dsym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC); dsym.st_other = ELF64_ST_VISIBILITY(STV_ELIMINATE); ! (void)gelf_update_sym(data_newsym, newsym, ! &dsym); ! r = (char *)data_newstr->d_buf + ! (istr - data_str->d_size); istr += 1 + sprintf(r, dt_symfmt, dt_symprefix, objkey, s); isym++; + newsym++; assert(isym <= nsym); } else if (strncmp(s, dt_symprefix, strlen(dt_symprefix)) == 0) { r = s;