* Fixed resize_section for ELF64

This commit is contained in:
Nibble 2009-04-08 00:47:40 +02:00
parent 5fc2e91777
commit 8744e9f86a
1 changed files with 71 additions and 57 deletions

View File

@ -363,7 +363,49 @@ 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], ".rela.plt")) {
if (!strcmp(&string[shdrp->sh_name], ".rel.plt")) {
ELF_(Rel) *rel, *relp;
rel = (ELF_(Rel) *)malloc(shdrp->sh_size);
if (rel == NULL) {
perror("malloc");
return 0;
}
if (lseek(bin->fd, shdrp->sh_offset, SEEK_SET) != shdrp->sh_offset) {
perror("lseek");
return 0;
}
if (read(bin->fd, rel, shdrp->sh_size) != shdrp->sh_size) {
perror("read");
return 0;
}
relp = rel;
for (j = 0; j < shdrp->sh_size; j += sizeof(ELF_(Rel)), 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_(Rel)), 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], ".rela.plt")) {
ELF_(Rela) *rel, *relp;
rel = (ELF_(Rela) *)malloc(shdrp->sh_size);
if (rel == NULL) {
@ -392,49 +434,7 @@ static u64 ELF_(get_import_addr)(ELF_(r_bin_elf_obj) *bin, int sym)
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");
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_(Rel)), 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_(Rel)), 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) {
!= relp->r_offset-bin->base_addr-got_offset) {
perror("lseek");
return 0;
}
@ -709,12 +709,12 @@ u64 ELF_(r_bin_elf_resize_section)(ELF_(r_bin_elf_obj) *bin, const char *name, u
ELF_(Phdr) *phdr = bin->phdr, *phdrp;
ELF_(Shdr) *shdr = bin->shdr, *shdrp;
const char *string = bin->string;
ELF_(Word) rsz_osize = 0, rsz_fsize;
ELF_(Word) rsz_size = (ELF_(Word)) size;
ELF_(Off) rsz_offset, new_offset;
ELF_(Addr) new_addr;
u64 off, delta = 0;
ELF_(Addr) new_addr, got_addr = 0;
u64 off, got_offset, delta = 0;
u64 rsz_osize = 0, rsz_fsize, rsz_size = size;
int i, j, done = 0;
int elf64 = (bin->ehdr.e_ident[EI_CLASS] == ELFCLASS64);
if (size == 0) {
printf("0 size section?\n");
@ -738,6 +738,14 @@ u64 ELF_(r_bin_elf_resize_section)(ELF_(r_bin_elf_obj) *bin, const char *name, u
printf("delta: %lld\n", delta);
/* rewrite rel's (imports) */
for (i = 0, shdrp = shdr; i < ehdr->e_shnum; i++, shdrp++) {
if (!strcmp(&string[shdrp->sh_name], ".got"))
got_addr = shdrp->sh_offset;
}
if (got_addr == 0) {
/* TODO: Unknown GOT address */
}
for (i = 0, shdrp = shdr; i < ehdr->e_shnum; i++, shdrp++) {
if (!strcmp(&string[shdrp->sh_name], ".rel.plt")) {
ELF_(Rel) *rel, *relp;
@ -752,11 +760,11 @@ u64 ELF_(r_bin_elf_resize_section)(ELF_(r_bin_elf_obj) *bin, const char *name, u
if (read(bin->fd, rel, shdrp->sh_size) != shdrp->sh_size)
perror("read");
got_offset = (rel->r_offset - bin->base_addr - got_addr) & ELF_GOTOFF_MASK;
for (j = 0, relp = rel; j < shdrp->sh_size; j += sizeof(ELF_(Rel)), 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) {
if (relp->r_offset - bin->base_addr - got_offset >= rsz_offset + rsz_osize) {
new_addr = (ELF_(Addr)) (relp->r_offset + delta);
off = shdrp->sh_offset + j;
@ -781,11 +789,11 @@ u64 ELF_(r_bin_elf_resize_section)(ELF_(r_bin_elf_obj) *bin, const char *name, u
if (read(bin->fd, rel, shdrp->sh_size) != shdrp->sh_size)
perror("read");
got_offset = (rel->r_offset - bin->base_addr - got_addr) & ELF_GOTOFF_MASK;
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) {
if (relp->r_offset - bin->base_addr - got_offset >= rsz_offset + rsz_osize) {
new_addr = (ELF_(Addr)) (relp->r_offset + delta);
off = shdrp->sh_offset + j;
@ -803,18 +811,24 @@ u64 ELF_(r_bin_elf_resize_section)(ELF_(r_bin_elf_obj) *bin, const char *name, u
/* rewrite section headers */
for (i = 0, shdrp = shdr; i < ehdr->e_shnum; i++, shdrp++)
if (!done && !strncmp(name, &string[shdrp->sh_name], ELF_NAME_LENGTH)) {
off = ehdr->e_shoff + i * sizeof(ELF_(Shdr)) + 3 * sizeof(ELF_(Word)) + sizeof(ELF_(Addr)) + sizeof(ELF_(Off));
if (elf64)
off = ehdr->e_shoff + i * sizeof(ELF_(Shdr)) + 2 * sizeof(ELF_(Word)) + sizeof(ELF_(Xword)) + sizeof(ELF_(Addr)) + sizeof(ELF_(Off));
else off = ehdr->e_shoff + i * sizeof(ELF_(Shdr)) + 3 * sizeof(ELF_(Word)) + sizeof(ELF_(Addr)) + sizeof(ELF_(Off));
if (lseek(bin->fd, off, SEEK_SET) < 0)
perror("lseek");
if (write(bin->fd, &rsz_size, sizeof(ELF_(Word))) != sizeof(ELF_(Word)))
perror("write (size)");
if (elf64) {
if (write(bin->fd, (ELF_(Word)*)&rsz_size, sizeof(ELF_(Word))) != sizeof(ELF_(Word)))
perror("write (size)");
} else if (write(bin->fd, (ELF_(Xword)*)&rsz_size, sizeof(ELF_(Xword))) != sizeof(ELF_(Xword)))
perror("write (size)");
done = 1;
} else if (shdrp->sh_offset >= rsz_offset + rsz_osize) {
new_offset = (ELF_(Off)) (shdrp->sh_offset + delta);
new_addr = (ELF_(Addr)) (shdrp->sh_addr ? shdrp->sh_addr + delta : 0);
off = ehdr->e_shoff + i * sizeof(ELF_(Shdr)) + 3 * sizeof(ELF_(Word));
if (elf64)
off = ehdr->e_shoff + i * sizeof(ELF_(Shdr)) + 2 * sizeof(ELF_(Word)) + sizeof(ELF_(Xword));
else off = ehdr->e_shoff + i * sizeof(ELF_(Shdr)) + 3 * sizeof(ELF_(Word));
if (lseek(bin->fd, off, SEEK_SET) < 0)
perror("lseek");