My own elf programs.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
5.9 KiB

#include "ft_nm.h"
int is_32_section_init(t_elf32 *nm, int i) {
for (Elf32_Xword j = 0; j < nm->shdr[i].sh_size; j++) {
if (nm->ptr + nm->shdr[i].sh_offset + j != 0) return 1;
}
return 0;
}
char *get_32_name(t_elf32 *nm, int sym) {
if (nm->opts.a && ELF64_ST_TYPE(nm->symtab[sym].st_info) == STT_SECTION)
return nm->string_table + nm->shdr[nm->symtab[sym].st_shndx].sh_name;
else return nm->linked_symnames + nm->symtab[sym].st_name;
}
char get_32_type(t_elf32 *nm, int i) {
Elf32_Ehdr *ehdr = nm->ehdr;
Elf32_Sym sym = nm->symtab[i];
uint32_t bind = ELF32_ST_BIND(sym.st_info);
int is_global = bind == STB_GLOBAL;
if (sym.st_shndx == SHN_ABS) return is_global ? 'A' : bind == STB_WEAK ? 'W' : 'a';
if (sym.st_shndx == SHN_UNDEF) return bind == STB_WEAK ? 'w' : 'U';
char ret = "NDTDFDB "[ELF32_ST_TYPE(sym.st_info)];
if (ret == 'N') {
if (bind == STB_WEAK) return 'W';
if (is_32_section_init(nm, sym.st_shndx) || sym.st_value) ret = 'D';
}
if (ret == 'D') {
if (ehdr->e_ident[EI_OSABI] == ELFOSABI_FREEBSD && bind == STB_GNU_UNIQUE) ret = 'u';
else if (bind == STB_WEAK) return 'V'; // should be 'V' or 'W'
else if (is_sym_bss(nm->string_table + nm->shdr[sym.st_shndx].sh_name)) ret = 'B';
else if (sym.st_shndx == SHN_COMMON) ret = 'C';
else {
Elf32_Shdr shdr = nm->shdr[sym.st_shndx];
if (shdr.sh_type == SHT_NOBITS && !(shdr.sh_flags & SHF_EXECINSTR)) ret = 'B';
else if (!(shdr.sh_flags & SHF_WRITE)) {
if (shdr.sh_flags & SHF_EXECINSTR) ret = 'T';
else if (is_sec_read_only2(nm->string_table + shdr.sh_name))
return 't';
else if (is_sec_read_only(nm->string_table + shdr.sh_name) && sym.st_value == 0)
return 'n';
else if (is_sym_debug(nm->string_table + shdr.sh_name))
return 'N';
else if (is_sym_text2(nm->string_table + shdr.sh_name))
return 'a';
else ret = 'R';
}
}
} else if (ret == 'T')
if (bind == STB_WEAK) return 'W';
return is_global ? ret : tolower(ret);
}
void create_32_order_array(t_elf32 *nm, int symbol_num) {
for (int i = 0; i < symbol_num; i++) {
for (int j = i + 1; j < symbol_num; j++) {
int left = nm->ordered_sym_ids[i];
int right = nm->ordered_sym_ids[j];
char *l = get_32_name(nm, left);
char *r = get_32_name(nm, right);
int cmp = strcmp_ignored(l, r);
if ((nm->opts.r && (cmp < 0 || (!cmp && left < right))) ||
(!nm->opts.r && (cmp > 0 || (!cmp && left > right)))) {
int tmp = nm->ordered_sym_ids[i];
nm->ordered_sym_ids[i] = nm->ordered_sym_ids[j];
nm->ordered_sym_ids[j] = tmp;
}
}
}
}
int print_32_symtab(t_elf32 *nm) {
int sym_num = nm->symtab_end - nm->symtab;
for (int i = 0; i < sym_num; i++) {
int id = nm->opts.p == 0 ? nm->ordered_sym_ids[i] : i;
if (nm->sym_names[id] == NULL) continue;
if (nm->opts.a || nm->sym_types[id] == 'w' || nm->sym_types[id] == 'U' ||
(!nm->opts.u && ELF64_ST_TYPE(nm->symtab[id].st_info) != STT_FILE)) {
char type = nm->sym_types[id];
if (strlen(nm->sym_names[id]) == 0 && (!nm->opts.a || type == 'u' || type == 'U'))
continue;
if (type == 'U' || type == 'w') ft_printf("%8c", ' ');
else ft_printf("%08x", nm->symtab[id].st_value);
ft_printf(" %c", type);
char *name = get_32_name(nm, id);
ft_printf(" %s\n", name);
}
}
return (0);
}
int parse_32_symtab(t_elf32 *nm) {
Elf32_Shdr *shdr = &nm->shdr[nm->ehdr->e_shstrndx];
nm->string_table = (char *)(nm->ptr + shdr->sh_offset);
for (int i = 0; i < nm->ehdr->e_shnum; i++) {
if (nm->shdr[i].sh_type == SHT_SYMTAB ||
(nm->opts.D && nm->shdr[i].sh_type == SHT_DYNSYM)) {
nm->symtab = (Elf32_Sym *)(nm->ptr + nm->shdr[i].sh_offset);
nm->symtab_end = nm->symtab + (nm->shdr[i].sh_size / sizeof(Elf32_Sym));
int symbol_num = nm->shdr[i].sh_size / nm->shdr[i].sh_entsize;
nm->linked_symnames = (char *)(nm->ptr + nm->shdr[nm->shdr[i].sh_link].sh_offset);
nm->sym_names = malloc(sizeof(char *) * symbol_num);
nm->ordered_sym_ids = malloc(sizeof(int) * symbol_num);
nm->sym_types = malloc(sizeof(char) * symbol_num);
for (int j = 0; j < symbol_num; j++) {
nm->sym_types[j] = get_32_type(nm, j);
nm->sym_names[j] = get_32_name(nm, j);
nm->ordered_sym_ids[j] = j;
}
if (nm->opts.p == 0) create_32_order_array(nm, symbol_num);
print_32_symtab(nm);
free(nm->sym_names);
free(nm->sym_types);
free(nm->ordered_sym_ids);
return (i);
}
nm->symtab = NULL;
nm->symtab_end = NULL;
nm->sym_names = NULL;
nm->ordered_sym_ids = NULL;
}
return (0);
}
int ft_nm32(char *filename, int filesize, char *file, t_elf_opts opts) {
t_elf32 nm;
nm.file = filename;
nm.size = filesize;
nm.ptr = file;
nm.opts = opts;
nm.ehdr = (Elf32_Ehdr *)nm.ptr;
nm.shdr = (Elf32_Shdr *)(nm.ptr + nm.ehdr->e_shoff);
nm.name = malloc(nm.ehdr->e_shnum * sizeof(char *));
if (file[EI_DATA] != ET_REL && nm.ehdr->e_entry == 0) return -1;
if (nm.ehdr->e_shnum == 0) return -2;
if (nm.ehdr->e_shoff + nm.ehdr->e_shnum * nm.ehdr->e_shentsize > nm.size) return -3;
for (int i = 0; i < nm.ehdr->e_shnum; i++) nm.name[i] = &nm.string_table[nm.shdr[i].sh_name];
return parse_32_symtab(&nm) ? 0 : -2;
}