- 论坛徽章:
- 0
|
如何得到一个函数的代码长度
by wzt
1,如何得到一个elf文件的符号长度
相关信息请看:
http://www.whitecell.org/forums/viewthread.php?tid=298
2,我用的方法就是直接从elf文件中读取这个符号的数据结构。
1).建立elf文件的映象到内存,这样对elf文件的操作比较方便。
2).从elf头中读取section table header的相关信息。
3).从section table header中得到.shstrtab节的地址和大小。将其拷贝到一个内存缓冲区A中。
4).遍历节,根据sh_name在A中的偏移,得到节的名字,如果节名为.symtab或者.strtab,记录
他们的地址,偏移,如果是表的话,则计算表的大小。
5).将.strtab节拷贝到内存缓冲区B中。
6).遍厉符号表,根据st_name在B中的偏移,得到符号表的名字。如果是你要找的符号表,记录它
的相关信息即可。
3,具体代码如下:
/*
ELF Reader V 0.0.5 Show ELF Information
by wzt
*/
#include stdio.h>
#include string.h>
#include stdlib.h>
#include unistd.h>
#include fcntl.h>
#include elf.h>
#include sys/stat.h>
#include sys/mman.h>
#define BUFFER 1024
void usage(char *pro);
void info_elf(char *elf_file,char *function);
void usage(char *pro)
{
fprintf(stdout,"Relf V 0.0.5 by wzt\r\n");
fprintf(stdout,"\nusage:\r\n");
fprintf(stdout,"%s \r\n",pro);
exit(0);
}
void info_elf(char *elf_file,char *function)
{
Elf32_Ehdr *ehdr = NULL;
Elf32_Phdr *phdr = NULL;
Elf32_Shdr *shdr = NULL;
Elf32_Shdr *shstrtab = NULL;
Elf32_Sym *dynsym_ptr = NULL;
Elf32_Sym *symtab_ptr = NULL;
Elf32_Sym *dynstr_ptr = NULL;
char *Real_strtab = NULL;
char *dynstr = NULL;
char *strtab_ptr = NULL;
char buffer[BUFFER];
char dynstr_buffer[2048];
char strtab_buffer[4096];
int fd,i;
int phdr_len;
int shdr_len;
int symtab_off,symtab_num;
int dynsym_off,dynsym_size,dynsym_num;
int dynstr_off,dynstr_size;
int shstrtab_off,shstrtab_len,shstrtab_num;
unsigned int strtab_off,strtab_size;
fd = open(elf_file,O_RDWR);
if( fd == -1 ){
perror("elf_file");
exit(1);
}
if( fstat(fd,&stat) == -1 ){
perror("fstat");
exit(1);
}
ehdr = mmap(0, stat.st_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
if(ehdr == MAP_FAILED) {
perror("mmap ehdr");
goto err;
}
if(ehdr->e_ident[EI_MAG0] != 0x7f
|| ehdr->e_ident[EI_MAG1] != 'E'
|| ehdr->e_ident[EI_MAG2] != 'L'
|| ehdr->e_ident[EI_MAG3] != 'F'
|| ehdr->e_ident[EI_CLASS] != ELFCLASS32
|| ehdr->e_ident[EI_DATA] != ELFDATA2LSB
|| ehdr->e_ident[EI_VERSION] != EV_CURRENT
|| ehdr->e_type != ET_EXEC
|| ehdr->e_machine != EM_386
|| ehdr->e_version != EV_CURRENT
) {
printf("File type not supported\n");
goto err;
}
phdr = (Elf32_Phdr *)( (unsigned long)ehdr + ehdr->e_phoff );
shdr = (Elf32_Shdr *)( (unsigned long)ehdr + ehdr->e_shoff );
// 节名表所在的节在文件中的地址
shstrtab = &shdr[ehdr->e_shstrndx];
// 节名表在文件中的偏移
shstrtab_off = (unsigned int)shstrtab->sh_offset;
// 节名表的长度
shstrtab_len = shstrtab->sh_size;
// 节名表在内存中的实际地址
Real_strtab = (char *)( (unsigned long)ehdr + shstrtab_off );
printf("[+] .Shstrtab Size :%x,%d\n",shstrtab->sh_size,shstrtab->sh_name);
printf("[+] .Shstrtab Off: %x\n",shstrtab_off);
// 将节名表拷贝到缓冲区中
memcpy(buffer,Real_strtab,shstrtab_len + 1);
for(i = 0 ; i (int)ehdr->e_shnum ; i++){
if( strcmp(buffer + shdr.sh_name,".symtab") == 0 ){
symtab_off = (unsigned int)shdr.sh_offset;
symtab_num = (int )(shdr.sh_size / shdr.sh_entsize);
printf("[+] .Symtab Off : 0x%x num :%d\n",symtab_off,symtab_num);
}
if( strcmp(buffer + shdr.sh_name,".strtab") == 0){
strtab_off = (unsigned int)shdr.sh_offset;
strtab_size = (unsigned int)shdr.sh_size;
printf("[+] .Strtab Off : 0x%x num : %d\n",strtab_off,strtab_size);
}
}
// 将strtab节读到缓冲区中
strtab_ptr = (char *)( (unsigned long)ehdr + strtab_off );
memcpy(strtab_buffer,strtab_ptr,strtab_size + 1);
symtab_ptr = (Elf32_Sym *)( (unsigned long)ehdr + symtab_off );
for(i = 0; i symtab_num; i++){
if( !strcmp(strtab_buffer + symtab_ptr.st_name,function) ){
printf("[+] Found %s!\n",function);
printf("[+] Size :%d!\n", symtab_ptr.st_size);
break;
}
}
err:
if (ehdr)
munmap(ehdr, stat.st_size);
if (fd != -1)
close(fd);
}
int main(int argc,char **argv)
{
if( argc == 1 ){
usage(argv[0]);
}
info_elf(argv[1],argv[2]);
return 0;
}
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/15780/showart_206536.html |
|