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;