我正在研究ELF格式。我必须编写一个简单的nm函数(没有选项)。 我已经在输出上打印了符号的值和符号的名称。
这是nm输出:
value type name
0000000000600e30 D __DTOR_END__
我有同一个,但没有'类型'。我正在使用ELF64_Sym结构,如下所示:
typedef struct {
Elf64_Word st_name;
unsigned char st_info;
unsigned char st_other;
Elf64_Half st_shndx;
Elf64_Addr st_value;
Elf64_Xword st_size;
} Elf64_Sym;
我知道我必须使用st_info变量和这个宏:
#define ELF64_ST_TYPE(info) ((info) & 0xf)
获取符号的类型。但是,符号类型可以是一个宏,如下所示:
NAME VALUE
STT_NOTYPE 0
STT_OBJECT 1
STT_FUNC 2
STT_SECTION 3
STT_FILE 4
STT_LOPROC 13
STT_HIOPROC 15
我想知道如何从这些宏中获取由nm打印的字母,例如:
U, u, A, a, T, t, R, r, W, w
答案 0 :(得分:7)
好的,我做了一些研究,这是我的功能,根据符号得到正确的字符。随意添加/编辑一些字符。
char print_type(Elf64_Sym sym, Elf64_Shdr *shdr)
{
char c;
if (ELF64_ST_BIND(sym.st_info) == STB_GNU_UNIQUE)
c = 'u';
else if (ELF64_ST_BIND(sym.st_info) == STB_WEAK)
{
c = 'W';
if (sym.st_shndx == SHN_UNDEF)
c = 'w';
}
else if (ELF64_ST_BIND(sym.st_info) == STB_WEAK && ELF64_ST_TYPE(sym.st_info) == STT_OBJECT)
{
c = 'V';
if (sym.st_shndx == SHN_UNDEF)
c = 'v';
}
else if (sym.st_shndx == SHN_UNDEF)
c = 'U';
else if (sym.st_shndx == SHN_ABS)
c = 'A';
else if (sym.st_shndx == SHN_COMMON)
c = 'C';
else if (shdr[sym.st_shndx].sh_type == SHT_NOBITS
&& shdr[sym.st_shndx].sh_flags == (SHF_ALLOC | SHF_WRITE))
c = 'B';
else if (shdr[sym.st_shndx].sh_type == SHT_PROGBITS
&& shdr[sym.st_shndx].sh_flags == SHF_ALLOC)
c = 'R';
else if (shdr[sym.st_shndx].sh_type == SHT_PROGBITS
&& shdr[sym.st_shndx].sh_flags == (SHF_ALLOC | SHF_WRITE))
c = 'D';
else if (shdr[sym.st_shndx].sh_type == SHT_PROGBITS
&& shdr[sym.st_shndx].sh_flags == (SHF_ALLOC | SHF_EXECINSTR))
c = 'T';
else if (shdr[sym.st_shndx].sh_type == SHT_DYNAMIC)
c = 'D';
else
c = '?';
if (ELF64_ST_BIND(sym.st_info) == STB_LOCAL && c != '?')
c += 32;
return c;
}
我错过了s,n,p和i。 我很确定'R'不好。当我找到它时,我会编辑它。
答案 1 :(得分:3)
ELF64_ST_TYPE
将不直接映射到nm
打印的字母。
为了执行映射,您需要注意符号所引用的部分ELF64_ST_BIND
,和。例如:
bool weak = (ELF64_ST_BIND(sym) == STB_WEAK);
bool unresolved = (sym->st_shndx == SHN_UNDEF);
if (unresolved) {
printf(" %c ", weak ? 'w' : 'U');
}
对于t
vs T
,您需要查看ELF64_ST_BIND(sym) == STB_LOCAL
或ELF64_ST_BIND(sym) == STB_GLOBAL
,和您想了解的内容st_shndx
引用的部分是否为“文本”部分(其标记中包含SHF_EXECINSTR
)。
P.S。据我所知,没有u
。如果您的nm
手册页确实列出了u
,我很想知道它是什么类型的符号。