* r_bin_elf

- Fixed "imports bug" in ELF64
    (needs more love ;)
  - More fixups in section_resize for ELF64
This commit is contained in:
Nibble 2009-04-07 22:46:36 +02:00
parent c5303272d9
commit 5fc2e91777
2 changed files with 117 additions and 16 deletions

View file

@ -347,7 +347,6 @@ static u64 ELF_(get_import_addr)(ELF_(r_bin_elf_obj) *bin, int sym)
{
ELF_(Ehdr) *ehdr = &bin->ehdr;
ELF_(Shdr) *shdr = bin->shdr, *shdrp;
ELF_(Rel) *rel, *relp;
ELF_(Addr) plt_sym_addr, got_addr = 0;
const char *string = bin->string;
int i, j;
@ -364,7 +363,50 @@ static u64 ELF_(get_import_addr)(ELF_(r_bin_elf_obj) *bin, int sym)
shdrp = shdr;
for (i = 0; i < ehdr->e_shnum; i++, shdrp++) {
if (!strcmp(&string[shdrp->sh_name], ".rel.plt")) {
if (!strcmp(&string[shdrp->sh_name], ".rela.plt")) {
ELF_(Rela) *rel, *relp;
rel = (ELF_(Rela) *)malloc(shdrp->sh_size);
if (rel == NULL) {
perror("malloc");
return -1;
}
if (lseek(bin->fd, shdrp->sh_offset, SEEK_SET) != shdrp->sh_offset) {
perror("lseek");
return -1;
}
if (read(bin->fd, rel, shdrp->sh_size) != shdrp->sh_size) {
perror("read");
return -1;
}
relp = rel;
for (j = 0; j < shdrp->sh_size; j += sizeof(ELF_(Rela)), relp++) {
ELF_(aux_swap_endian)((u8*)&(relp->r_offset), sizeof(ELF_(Addr)));
ELF_(aux_swap_endian)((u8*)&(relp->r_info), sizeof(ELF_(Word)));
}
got_offset = (rel->r_offset - bin->base_addr - got_addr) & ELF_GOTOFF_MASK;
relp = rel;
for (j = 0; j < shdrp->sh_size; j += sizeof(ELF_(Rela)), relp++) {
if (ELF_R_SYM(relp->r_info) == sym) {
if (lseek(bin->fd, relp->r_offset-bin->base_addr-got_offset, SEEK_SET)
!= relp->r_offset-bin->base_addr-got_offset) {
perror("lseek");
return 0;
}
if (read(bin->fd, &plt_sym_addr, sizeof(ELF_(Addr))) != sizeof(ELF_(Addr))) {
perror("read");
return 0;
}
return plt_sym_addr-6;
}
}
} else if (!strcmp(&string[shdrp->sh_name], ".rel.plt")) {
ELF_(Rel) *rel, *relp;
rel = (ELF_(Rel) *)malloc(shdrp->sh_size);
if (rel == NULL) {
perror("malloc");
@ -388,19 +430,18 @@ static u64 ELF_(get_import_addr)(ELF_(r_bin_elf_obj) *bin, int sym)
}
got_offset = (rel->r_offset - bin->base_addr - got_addr) & ELF_GOTOFF_MASK;
relp = rel;
for (j = 0; j < shdrp->sh_size; j += sizeof(ELF_(Rel)), relp++) {
if (ELF32_R_SYM(relp->r_info) == sym) {
if (ELF_R_SYM(relp->r_info) == sym) {
if (lseek(bin->fd, relp->r_offset-bin->base_addr-got_offset, SEEK_SET)
!= relp->r_offset-bin->base_addr-got_offset) {
perror("lseek");
return -1;
return 0;
}
if (read(bin->fd, &plt_sym_addr, sizeof(ELF_(Addr))) != sizeof(ELF_(Addr))) {
perror("read");
return -1;
return 0;
}
return plt_sym_addr-6;
@ -667,7 +708,6 @@ u64 ELF_(r_bin_elf_resize_section)(ELF_(r_bin_elf_obj) *bin, const char *name, u
ELF_(Ehdr) *ehdr = &bin->ehdr;
ELF_(Phdr) *phdr = bin->phdr, *phdrp;
ELF_(Shdr) *shdr = bin->shdr, *shdrp;
ELF_(Rel) *rel, *relp;
const char *string = bin->string;
ELF_(Word) rsz_osize = 0, rsz_fsize;
ELF_(Word) rsz_size = (ELF_(Word)) size;
@ -700,6 +740,7 @@ u64 ELF_(r_bin_elf_resize_section)(ELF_(r_bin_elf_obj) *bin, const char *name, u
/* rewrite rel's (imports) */
for (i = 0, shdrp = shdr; i < ehdr->e_shnum; i++, shdrp++) {
if (!strcmp(&string[shdrp->sh_name], ".rel.plt")) {
ELF_(Rel) *rel, *relp;
rel = (ELF_(Rel) *)malloc(shdrp->sh_size);
if (rel == NULL) {
perror("malloc");
@ -726,6 +767,36 @@ u64 ELF_(r_bin_elf_resize_section)(ELF_(r_bin_elf_obj) *bin, const char *name, u
}
}
free(rel);
break;
} else if (!strcmp(&string[shdrp->sh_name], ".rela.plt")) {
ELF_(Rela) *rel, *relp;
rel = (ELF_(Rela) *)malloc(shdrp->sh_size);
if (rel == NULL) {
perror("malloc");
return -1;
}
if (lseek(bin->fd, shdrp->sh_offset, SEEK_SET) < 0)
perror("lseek");
if (read(bin->fd, rel, shdrp->sh_size) != shdrp->sh_size)
perror("read");
for (j = 0, relp = rel; j < shdrp->sh_size; j += sizeof(ELF_(Rela)), relp++) {
ELF_(aux_swap_endian)((u8*)&(relp->r_offset), sizeof(ELF_(Addr)));
ELF_(aux_swap_endian)((u8*)&(relp->r_info), sizeof(ELF_(Word)));
/* rewrite relp->r_offset */
if (relp->r_offset - bin->base_addr >= rsz_offset + rsz_osize) {
new_addr = (ELF_(Addr)) (relp->r_offset + delta);
off = shdrp->sh_offset + j;
if (lseek(bin->fd, off, SEEK_SET) < 0)
perror("lseek");
if (write(bin->fd, &new_addr, sizeof(ELF_(Addr))) != sizeof(ELF_(Addr)))
perror("write (off)");
}
}
free(rel);
break;
}
}
@ -921,7 +992,7 @@ int ELF_(r_bin_elf_get_imports)(ELF_(r_bin_elf_obj) *bin, r_bin_elf_import *impo
for (j = 0, k = 0; j < shdrp->sh_size; j += sizeof(ELF_(Sym)), k++, symp++) {
if (k == 0)
continue;
if (symp->st_shndx == STN_UNDEF && ELF32_ST_BIND(symp->st_info) != STB_WEAK) {
if (symp->st_shndx == STN_UNDEF && ELF_ST_BIND(symp->st_info) != STB_WEAK) {
memcpy(importp->name, &string[symp->st_name], ELF_NAME_LENGTH);
importp->name[ELF_NAME_LENGTH-1] = '\0';
if (symp->st_value)
@ -931,7 +1002,7 @@ int ELF_(r_bin_elf_get_imports)(ELF_(r_bin_elf_obj) *bin, r_bin_elf_import *impo
if (importp->offset >= bin->base_addr)
importp->offset -= bin->base_addr;
switch (ELF32_ST_BIND(symp->st_info)) {
switch (ELF_ST_BIND(symp->st_info)) {
case STB_LOCAL: snprintf(importp->bind, ELF_NAME_LENGTH, "LOCAL"); break;
case STB_GLOBAL: snprintf(importp->bind, ELF_NAME_LENGTH, "GLOBAL"); break;
case STB_NUM: snprintf(importp->bind, ELF_NAME_LENGTH, "NUM"); break;
@ -941,7 +1012,7 @@ int ELF_(r_bin_elf_get_imports)(ELF_(r_bin_elf_obj) *bin, r_bin_elf_import *impo
case STB_HIPROC: snprintf(importp->bind, ELF_NAME_LENGTH, "HIPROC"); break;
default: snprintf(importp->bind, ELF_NAME_LENGTH, "UNKNOWN");
}
switch (ELF32_ST_TYPE(symp->st_info)) {
switch (ELF_ST_TYPE(symp->st_info)) {
case STT_NOTYPE: snprintf(importp->type, ELF_NAME_LENGTH, "NOTYPE"); break;
case STT_OBJECT: snprintf(importp->type, ELF_NAME_LENGTH, "OBJECT"); break;
case STT_FUNC: snprintf(importp->type, ELF_NAME_LENGTH, "FUNC"); break;
@ -995,7 +1066,7 @@ int ELF_(r_bin_elf_get_imports_count)(ELF_(r_bin_elf_obj) *bin)
for (j = 0, k = 0; j < shdrp->sh_size; j += sizeof(ELF_(Sym)), k++, symp++) {
if (k == 0)
continue;
if (symp->st_shndx == STN_UNDEF && ELF32_ST_BIND(symp->st_info) != STB_WEAK) {
if (symp->st_shndx == STN_UNDEF && ELF_ST_BIND(symp->st_info) != STB_WEAK) {
ctr++;
}
}
@ -1072,14 +1143,14 @@ int ELF_(r_bin_elf_get_symbols)(ELF_(r_bin_elf_obj) *bin, r_bin_elf_symbol *symb
for (j = 0, k = 0; j < shdrp->sh_size; j += sizeof(ELF_(Sym)), k++, symp++) {
if (k == 0)
continue;
if (symp->st_shndx != STN_UNDEF && ELF32_ST_TYPE(symp->st_info) != STT_SECTION && ELF32_ST_BIND(symp->st_info) != STB_WEAK) {
if (symp->st_shndx != STN_UNDEF && ELF_ST_TYPE(symp->st_info) != STT_SECTION && ELF_ST_BIND(symp->st_info) != STB_WEAK) {
symbolp->size = (u64)symp->st_size;
memcpy(symbolp->name, &string[symp->st_name], ELF_NAME_LENGTH);
symbolp->name[ELF_NAME_LENGTH-1] = '\0';
symbolp->offset = (u64)symp->st_value + sym_offset;
if (symbolp->offset >= bin->base_addr)
symbolp->offset -= bin->base_addr;
switch (ELF32_ST_BIND(symp->st_info)) {
switch (ELF_ST_BIND(symp->st_info)) {
case STB_LOCAL: snprintf(symbolp->bind, ELF_NAME_LENGTH, "LOCAL"); break;
case STB_GLOBAL: snprintf(symbolp->bind, ELF_NAME_LENGTH, "GLOBAL"); break;
case STB_NUM: snprintf(symbolp->bind, ELF_NAME_LENGTH, "NUM"); break;
@ -1089,7 +1160,7 @@ int ELF_(r_bin_elf_get_symbols)(ELF_(r_bin_elf_obj) *bin, r_bin_elf_symbol *symb
case STB_HIPROC: snprintf(symbolp->bind, ELF_NAME_LENGTH, "HIPROC"); break;
default: snprintf(symbolp->bind, ELF_NAME_LENGTH, "UNKNOWN");
}
switch (ELF32_ST_TYPE(symp->st_info)) {
switch (ELF_ST_TYPE(symp->st_info)) {
case STT_NOTYPE: snprintf(symbolp->type, ELF_NAME_LENGTH, "NOTYPE"); break;
case STT_OBJECT: snprintf(symbolp->type, ELF_NAME_LENGTH, "OBJECT"); break;
case STT_FUNC: snprintf(symbolp->type, ELF_NAME_LENGTH, "FUNC"); break;
@ -1144,7 +1215,7 @@ int ELF_(r_bin_elf_get_symbols_count)(ELF_(r_bin_elf_obj) *bin)
for (j = 0, k = 0; j < shdrp->sh_size; j += sizeof(ELF_(Sym)), k++, symp++) {
if (k == 0)
continue;
if (symp->st_shndx != STN_UNDEF && ELF32_ST_TYPE(symp->st_info) != STT_SECTION && ELF32_ST_BIND(symp->st_info) != STB_WEAK)
if (symp->st_shndx != STN_UNDEF && ELF_ST_TYPE(symp->st_info) != STT_SECTION && ELF_ST_BIND(symp->st_info) != STB_WEAK)
ctr++;
}
}

View file

@ -18,11 +18,41 @@
02111-1307 USA. */
#undef ELF_
#undef ELF_ST_BIND
#undef ELF_ST_TYPE
#undef ELF_ST_INFO
#undef ELF_ST_VISIBILITY
#undef ELF_ST_R_SYM
#undef ELF_R_TYPE
#undef ELF_R_INFO
#undef ELF_M_SYM
#undef ELF_M_SIZE
#undef ELF_M_INFO
#ifdef R_BIN_ELF64
#define ELF_(name) Elf64_##name
#define ELF_(name) Elf64_##name
#define ELF_ST_BIND ELF64_ST_BIND
#define ELF_ST_TYPE ELF64_ST_TYPE
#define ELF_ST_INFO ELF64_ST_INFO
#define ELF_ST_VISIBILITY ELF64_ST_VISIBILITY
#define ELF_R_SYM ELF64_R_SYM
#define ELF_R_TYPE ELF64_R_TYPE
#define ELF_R_INFO ELF64_R_INFO
#define ELF_M_SYM ELF64_M_SYM
#define ELF_M_SIZE ELF64_M_SIZE
#define ELF_M_INFO ELF64_M_INFO
#else
#define ELF_(name) Elf32_##name
#define ELF_ST_BIND ELF32_ST_BIND
#define ELF_ST_TYPE ELF32_ST_TYPE
#define ELF_ST_INFO ELF32_ST_INFO
#define ELF_ST_VISIBILITY ELF32_ST_VISIBILITY
#define ELF_R_SYM ELF32_R_SYM
#define ELF_R_TYPE ELF32_R_TYPE
#define ELF_R_INFO ELF32_R_INFO
#define ELF_M_SYM ELF32_M_SYM
#define ELF_M_SIZE ELF32_M_SIZE
#define ELF_M_INFO ELF32_M_INFO
#endif
#ifndef _INCLUDE_ELF_SPECS_H