【问题标题】:How to display the symbol's type like the nm command?如何像 nm 命令一样显示符号的类型?
【发布时间】:2013-02-19 22:41:12
【问题描述】:

我现在正在研究 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

【问题讨论】:

标签: c unix command elf nm


【解决方案1】:

好的,我做了一些研究,这是我根据符号获取正确字符的函数。随意添加/编辑一些字符。

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'不好。当我找到它时,我会编辑它。

【讨论】:

    【解决方案2】:

    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');
    }
    

    对于tT,您需要查看ELF64_ST_BIND(sym) == STB_LOCALELF64_ST_BIND(sym) == STB_GLOBAL并且您需要了解st_shndx 引用的部分是否是一个“文本”(在其标志中有SHF_EXECINSTR)。

    附:据我所知,没有u。如果您的 nm 手册页确实列出了 u,我很想知道这是什么类型的符号。

    【讨论】:

    • 谢谢,这是我需要做的。我正在使用 ELF64_ST_BIND 宏来确定符号是本地还是全局(MIN 或 MAJ),然后使用节类型和节标志我得到一些字符,例如 B、D、T。但是还有更多字符找到!我将继续并发布所有结果。这是包含所有字符的 nm 人:linux.die.net/man/1/nm
    • @JérémieCharrier 啊,我忘了:uELF64_ST_BIND(sym) == STB_GNU_UNIQUE
    猜你喜欢
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-26
    相关资源
    最近更新 更多