I'm studying the ELF format right now. I have to code a simple nm fonction (without the options). I'm already printing on the output the symbol's value and the symbol's name.
Here's the nm output :
value type name
0000000000600e30 D __DTOR_END__
I have the same one, but without the 'type'. I am using the ELF64_Sym structure, as follow :
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;
I know that I have to use the st_info variable and this macro :
#define ELF64_ST_TYPE(info) ((info) & 0xf)
to get the symbol's type. But, the symbol type can be a macro as follow :
NAME VALUE
STT_NOTYPE 0
STT_OBJECT 1
STT_FUNC 2
STT_SECTION 3
STT_FILE 4
STT_LOPROC 13
STT_HIOPROC 15
And I would like to know is how can I get from these macros the letters printed by nm, example:
U, u, A, a, T, t, R, r, W, w
Ok I did some researchs and here's my function to get the correct character depending on the symbol. Feel free to add / edit some characters.
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;
}
I'm missing the s, n, p and i. I'm quite sure the 'R' is not good. I'll will edit this when I find it.
The ELF64_ST_TYPE
does not map directly into the letters that nm
prints.
In order to perform the mapping, you need to pay attention to both ELF64_ST_BIND
, and the section that the symbol refers to. For example:
bool weak = (ELF64_ST_BIND(sym) == STB_WEAK);
bool unresolved = (sym->st_shndx == SHN_UNDEF);
if (unresolved) {
printf(" %c ", weak ? 'w' : 'U');
}
For t
vs T
, you'll want to look at ELF64_ST_BIND(sym) == STB_LOCAL
or ELF64_ST_BIND(sym) == STB_GLOBAL
, and you'll want to find out whether the section referenced by st_shndx
is a "text" one (has SHF_EXECINSTR
in its flags).
P.S. As far as I know, there is no u
. If your nm
man page does list u
, I am curious to know what type of symbol that is.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With