最近,我一直在玩ELF格式的文件。我试图解决一个问题:
给出
eip
,在ELF可执行文件中打印函数的名称
我可以使用符号表和字符串表来做到这一点。由于我只需要处理类型为STT_FUNC
的那些符号,因此我编写了以下程序:
for (i = 0; i < nr_symtab_entry; ++i) {
if ((symtab[i].st_info == STT_FUNC) &&
eip < symtab[i].st_value + symtab[i].st_size &&
eip >= symtab[i].st_value) {
strcpy(funcName, strtab + symtab[i].st_name);
}
}
其中symtab
是符号表,strtab
是字符串表。
但是经过几次测试,我意识到上面的程序是错误的。经过几次试验,我将其更改为:
for (i = 0; i < nr_symtab_entry; ++i) {
if ((symtab[i].st_info & STT_FUNC) &&
eip < symtab[i].st_value + symtab[i].st_size &&
eip >= symtab[i].st_value) {
strcpy(funcName, strtab + symtab[i].st_name);
}
}
然后它起作用了!但是当我man elf
时,手册告诉我:
st_info 该成员指定符号的类型和绑定属性
它没有提到它是否是位标志。然后,我遇到了一个问题,该问题需要我检查某个段是否为PT_LOAD
。同样,手册也没有指定它是否是位标志。所以我来这里寻求帮助--- PT_LOAD
还是一个标志吗?是不是像ELF文件中的每个符号常量一样,都有位标记?
似乎st_info
可以由特定的宏解释。但是p_type
呢?
答案 0 :(得分:2)
使用:
if (ELF32_ST_TYPE(symtab[i].st_info) == STT_FUNC && ...
例如内核在linux kernel/module.c中所做的事情。
ELF32_ST_TYPE用于从st_info中提取符号的类型。我找不到任何位置的符号列表,但在elf.h中检查#define ELF32_ST_TYPE(info) ((info) & 0xf)
及其定义后,我可以确定ELF32_ST_TYPE(st_info)
等于以下宏之一:
#define STT_NOTYPE 0
#define STT_OBJECT 1
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
#define STT_COMMON 5
#define STT_TLS 6
在man elf
中是:
有一些用于打包和解包绑定的宏, 输入字段:
ELF32_ST_BIND(信息),ELF64_ST_BIND(信息)
从st_info值中提取绑定。ELF32_ST_TYPE(信息),ELF64_ST_TYPE(信息)
从st_info值中提取类型。ELF32_ST_INFO(绑定,类型),ELF64_ST_INFO(绑定,类型)
将绑定和类型转换为st_info值。