scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 95d704d06828e99541170b8f5bfc97240d31b79d
parent 129b80feb976b22ba4eacaed59bd1c1f54804e1a
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sat, 30 Oct 2021 11:21:08 +0200

libmach: Add elf64getsym()

This function can be used to run over the full list of symbols
of a file and retrieve information for every one of them.

Diffstat:
Msrc/libmach/deps.mk | 3+++
Msrc/libmach/elf64/elf64.c | 1+
Asrc/libmach/elf64/elf64getsym.c | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/libmach/elf64/rules.mk | 1+
4 files changed, 117 insertions(+), 0 deletions(-)

diff --git a/src/libmach/deps.mk b/src/libmach/deps.mk @@ -59,6 +59,9 @@ elf64/elf64del.o: elf64/elf64.h elf64/elf64getsec.o: $(INCDIR)/scc/scc/mach.h elf64/elf64getsec.o: elf64/../libmach.h elf64/elf64getsec.o: elf64/elf64.h +elf64/elf64getsym.o: $(INCDIR)/scc/scc/mach.h +elf64/elf64getsym.o: elf64/../libmach.h +elf64/elf64getsym.o: elf64/elf64.h elf64/elf64new.o: $(INCDIR)/scc/scc/mach.h elf64/elf64new.o: elf64/../libmach.h elf64/elf64new.o: elf64/elf64.h diff --git a/src/libmach/elf64/elf64.c b/src/libmach/elf64/elf64.c @@ -15,6 +15,7 @@ struct objops elf64 = { .strip = NULL, .del = elf64del, .write = NULL, + .getsym = elf64getsym, .getsec = elf64getsec, .loadmap = NULL, }; diff --git a/src/libmach/elf64/elf64getsym.c b/src/libmach/elf64/elf64getsym.c @@ -0,0 +1,112 @@ +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/mach.h> + +#include "../libmach.h" +#include "elf64.h" + +static int +typeof(Elf64 *elf, Elf_Sym *ent, char *name) +{ + int c, bind; + unsigned long flags, type; + Elf_Shdr *shdr; + + switch (ent->st_shndx) { + case SHN_UNDEF: + c = 'U'; + break; + case SHN_ABS: + c = 'a'; + break; + case SHN_COMMON: + c = 'C'; + break; + case SHN_XINDEX: + abort(); + default: + shdr = &elf->shdr[ent->st_shndx]; + flags = shdr->sh_flags; + type = shdr->sh_type; + + if (flags & SHF_ALLOC) { + if (type == SHT_NOBITS) + c = 'b'; + else if (flags & SHF_WRITE) + c = 'd'; + else if (flags & SHF_EXECINSTR) + c = 't'; + else + c = 'r'; + } else if (strncmp(name, ".debug", 6) == 0) { + c = 'N'; + } else if (strcmp(name, ".comment") == 0) { + c = 'N'; + } else if (strcmp(name, ".line") == 0) { + c = 'N'; + } else if (strcmp(name, ".stab") == 0) { + c = 'N'; + } else { + c = '?'; + } + } + + if (ELF_ST_BIND(ent->st_info) != STB_LOCAL) + c = toupper(c); + + return c; +} + +static int +stypeof(Elf_Sym *ent) +{ + switch (ELF_ST_TYPE(ent->st_info)) { + case STT_OBJECT: + return SYMOBJECT; + case STT_FUNC: + return SYMFUNC; + case STT_SECTION: + return SYMSECTION; + case STT_FILE: + return SYMFILE; + case STT_COMMON: + return SYMCOMMON; + default: + case STT_NOTYPE: + return SYMNOTYPE; + } +} + +Symbol * +elf64getsym(Obj *obj, int *idx, Symbol *sym) +{ + int n = *idx; + Elf_Sym *ent; + Elf64 *elf = obj->data; + + if (n == 0) + n++; + + if (!elf->symtab || n >= elf->nsym) + return NULL; + ent = &elf->syms[n]; + + if (ELF_ST_TYPE(ent->st_info) == STT_SECTION) { + /* TODO: Implement XINDEX */ + Elf_Shdr *shdr = &elf->shdr[ent->st_shndx]; + sym->name = elf64str(obj, SEC_STRTBL, shdr->sh_name); + } else { + sym->name = elf64str(obj, SYM_STRTBL, ent->st_name); + } + + sym->type = typeof(elf, ent, sym->name); + sym->stype = stypeof(ent); + sym->value = ent->st_value; + sym->size = ent->st_size; + sym->index = *idx = n; + + return sym; +} diff --git a/src/libmach/elf64/rules.mk b/src/libmach/elf64/rules.mk @@ -5,3 +5,4 @@ ELF64_OBJS =\ elf64/elf64read.o\ elf64/elf64getsec.o\ elf64/elf64del.o\ + elf64/elf64getsym.o\