2013-03-12 64 views
3

我想獲得偏移量和精靈文件的每個部分的數據。 我已經有部分的名稱與此代碼:獲取精靈節偏移

#include <elf.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/mman.h> 

int filesize(int fd) 
{ 
    return (lseek(fd, 0, SEEK_END)); 
} 

void print_section(Elf64_Shdr *shdr, char *strTab, int shNum) 
{ 
    int i; 

    for(i = 0; i < shNum; i++) 
    printf("%02d: %s\n", i, &strTab[shdr[i].sh_name]); 
} 

int main(int ac, char **av) 
{ 
    void *data; 
    Elf64_Ehdr *elf; 
    Elf64_Shdr *shdr; 
    int  fd; 
    char  *strtab; 

    fd = open(av[1], O_RDONLY); 
    data = mmap(NULL, filesize(fd), PROT_READ, MAP_SHARED, fd, 0); 
    elf = (Elf64_Ehdr *) data; 
    shdr = (Elf64_Shdr *) (data + elf->e_shoff); 
    strtab = (char *)(data + shdr[elf->e_shstrndx].sh_offset); 
    print_section(shdr, strtab, elf->e_shnum); 
    close(fd); 
    return 0; 
} 

但我不能找到一個辦法讓每一個部分的任何數據,也沒有他們的起始偏移量。 感謝您的幫助

回答

5

我認爲你可以使用sh_offsetshdr[i].sh_size

void print_section(Elf64_Shdr *shdr, char *strTab, int shNum, uint8_t *data) 
{ 
    int i; 

    for(i = 0; i < shNum; i++) { 
    size_t k; 
    printf("%02d: %s Offset %lx\n", i, &strTab[shdr[i].sh_name], 
     shdr[i].sh_offset); 
    for (k = shdr[i].sh_offset; k < shdr[i].sh_offset + shdr[i].sh_size; k++) { 
     printf("%x", data[k]); 
    } 
    printf("\n"); 
    for (k = shdr[i].sh_offset; k < shdr[i].sh_offset + shdr[i].sh_size; k++) { 
     printf("%c", data[k]); 
    } 
    printf("\n"); 
    } 
} 

,並調用它是這樣的:

print_section(shdr, strtab, elf->e_shnum, (uint8_t*)data); 

一種方式來獲得虛擬地址(偏移量):

Elf64_Phdr *ph = (Elf64_Phdr *) ((uint8_t *) data + elf->e_phoff); 
printf("Virtual address offset: %lx\n", ph->p_vaddr - elf->e_phoff); 
+0

謝謝,它的工作原理!但只是另一個問題。當我在程序中使用objdump -s時,我得到一個起始地址; 400200.但在我的只有200,我應該從結構中增加400200?這些偏移之間有什麼區別?謝謝 – 2013-03-12 04:35:02

+0

更新了答案 – perreal 2013-03-12 05:13:34

+0

0x400000是x86_64平臺上的默認值,請看這裏:http://stackoverflow.com/questions/14314021/why-linux-gnu-linker-chose-address-0x400000 – evildead 2015-07-10 20:07:56