Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1462922
  • 博文数量: 267
  • 博客积分: 3010
  • 博客等级: 少校
  • 技术积分: 3089
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-05 17:09
个人简介

尊天命,尽人事

文章分类

全部博文(267)

文章存档

2017年(6)

2015年(4)

2014年(27)

2013年(52)

2012年(59)

2011年(120)

分类: LINUX

2014-01-02 19:35:06

ELF Section Header的结构还是要从/usr/include/elf.h中看。

typedef struct
{
  Elf32_Word sh_name; /* Section name (string tbl index) */
  Elf32_Word sh_type; /* Section type */
  Elf32_Word sh_flags; /* Section flags */
  Elf32_Addr sh_addr; /* Section virtual addr at execution */
  Elf32_Off sh_offset; /* Section file offset */
  Elf32_Word sh_size; /* Section size in bytes */
  Elf32_Word sh_link; /* Link to another section */
  Elf32_Word sh_info; /* Additional section information */
  Elf32_Word sh_addralign; /* Section alignment */
  Elf32_Word sh_entsize; /* Entry size if section holds table */
} Elf32_Shdr;
同样,可以算出来Elf32_Shdr的大小是40B。其结构中的各个元素数据类型在elf.h中同样可以找到,含义见注释。整个section header table就是一个数组,数组的每一个元素就是Elf32_Shdr。Elf32_Shdr仅仅是section的一个索引,包括一些属性信息,并不是 section本省。简单的介绍一下各个元素的含义。
sh_name: section name。不过其实sh_name中存放的是index,不是字符串,这一点从sh_name是定长应该能看出来,那么index又是什么意思 呢?index的含义是在string tabl总的第几个字节数。其实是这样的,所有的section name都存放在一个叫做string table的表中,index就是该section名字的第一个字符在表中的位置,名字一直到遇到一个'\0'为止结束。至于string table怎么找,还记得上一篇中提到的elf header中的e_shstrndx成员吗,它就指明了string table是在section header table中的第几个入口。
sh_offset:这个元素就指明了这个Elf32_Shdr描述的section在文件中的偏移量。
其他各个变量可以查询《Executable and Linkable Format(ELF)》这个文档。
为了检验程序输出结果的对错,我们与readelf这个命令的输出结果作比较。
下面编程序来输出文件的section信息。首先要找到section header table在文件中的位置,回忆一下,section header table的偏移量在elf header中的e_shoff中告诉了我们,所以,我们就知道了section header table在文件中的位置了,同样,我们在elf header中可以找到section header的大小及个数,这样我们用一个循环就可以输出出来每个section的信息了。


    fseek(fp, elfheader.e_shoff, SEEK_SET);
    shnum = elfheader.e_shnum;
    printf("Number of Section headers: %d\n\n", shnum);
    while(shnum != 0){
        fread(&shdr, sizeof(char), sizeof(shdr), fp);
        printf("sh_name : %d\n", shdr.sh_name);
        printf("sh_type : %#x\n", shdr.sh_type);
        printf("sh_flags : %d\n", shdr.sh_flags);
        printf("sh_addr : %#x\n", shdr.sh_addr);
        printf("sh_offset : %d\n", shdr.sh_offset);
        printf("sh_size : %d\n", shdr.sh_size);
        printf("sh_link : %d\n", shdr.sh_link);
        printf("sh_info : %d\n", shdr.sh_info);
        printf("sh_addralign : %d\n", shdr.sh_addralign);
        printf("sh_entsize : %d\n\n", shdr.sh_entsize);
        shnum--;
    }
输出的结果如下:
Number of Section headers: 34
sh_name : 0
sh_type : 0
sh_flags : 0
sh_addr : 0
sh_offset : 0
sh_size : 0
sh_link : 0
sh_info : 0
sh_addralign : 0
sh_entsize : 0
sh_name : 27
sh_type : 0x1
sh_flags : 2
sh_addr : 0x80480f4
sh_offset : 244
sh_size : 19
sh_link : 0
sh_info : 0
sh_addralign : 1
sh_entsize : 0
sh_name : 35
sh_type : 0x7
sh_flags : 2
sh_addr : 0x8048108
sh_offset : 264
sh_size : 32
sh_link : 0
sh_info : 0
sh_addralign : 4
sh_entsize : 0
...

观察上面的结果可以看到,sh_name并不是section的名字,而是一个数字。回忆前面提到的,sh_name存放的只是section name在string table的index。因此,为了输出section name我们必须先得到string table。string table的信息也在section header table中存放,只要我们得到了string table header的内容,就可以从里面的sh_offset知道string table的位置,从sh_size知道string table的大小。此时问题就成为如何找到string talbe header在section header table中的位置,即index.回忆前面讲到的,elf header中有一个变量e_shstrndx存放的就是string table header在section header中的index。此时整个思路已经明白了,即elfheader.e_shstrndx --> string table header --> string table。string table里面到底是什么呢?其实就是一些带'\0'的字符串。比如\0.bss\0.text\0\0,那么如果sh_name是1,则该 sh_name代表的是从string table中零开始的直到遇到\0为止的字符串,即.bss。整个程序如下:
    fseek(fp, elfheader.e_shoff + elfheader.e_shstrndx*elfheader.e_shentsize, SEEK_SET);
    fread(&strhdr, sizeof(char), sizeof(strhdr), fp);//get the string table header
    fseek(fp, strhdr.sh_offset, SEEK_SET);
    strtable = (unsigned char *)malloc(sizeof(unsigned char)*strhdr.sh_size);
    fread(strtable, sizeof(char), strhdr.sh_size, fp);
    fseek(fp, elfheader.e_shoff, SEEK_SET);
    shnum = elfheader.e_shnum;
    printf("Number of Section headers: %d\n\n", shnum);
    while(shnum != 0){
        fread(&shdr, sizeof(char), sizeof(shdr), fp);
        printf("sh_name : %s\n", strtable+shdr.sh_name);
        printf("sh_type : %#x\n", shdr.sh_type);
        printf("sh_flags : %d\n", shdr.sh_flags);
        printf("sh_addr : %#x\n", shdr.sh_addr);
        printf("sh_offset : %d\n", shdr.sh_offset);
        printf("sh_size : %d\n", shdr.sh_size);
        printf("sh_link : %d\n", shdr.sh_link);
        printf("sh_info : %d\n", shdr.sh_info);
        printf("sh_addralign : %d\n", shdr.sh_addralign);
        printf("sh_entsize : %d\n\n", shdr.sh_entsize);
        shnum--;
    }
程序的输出结果为:
Number of Section headers: 34
sh_name :
sh_type : 0
sh_flags : 0
sh_addr : 0
sh_offset : 0
sh_size : 0
sh_link : 0
sh_info : 0
sh_addralign : 0
sh_entsize : 0
sh_name : .interp
sh_type : 0x1
sh_flags : 2
sh_addr : 0x80480f4
sh_offset : 244
sh_size : 19
sh_link : 0
sh_info : 0
sh_addralign : 1
sh_entsize : 0
sh_name : .note.ABI-tag
sh_type : 0x7
sh_flags : 2
sh_addr : 0x8048108
sh_offset : 264
sh_size : 32
sh_link : 0
sh_info : 0
sh_addralign : 4
sh_entsize : 0
sh_name : .hash
sh_type : 0x5
sh_flags : 2
sh_addr : 0x8048128
sh_offset : 296
sh_size : 64
sh_link : 4
sh_info : 0
sh_addralign : 4
sh_entsize : 4
阅读(2836) | 评论(0) | 转发(0) |
0

上一篇:关于EMMC和SD卡

下一篇:gcc的几个妙用

给主人留下些什么吧!~~