ref: 95d704d06828e99541170b8f5bfc97240d31b79d
parent: 129b80feb976b22ba4eacaed59bd1c1f54804e1a
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sat Oct 30 07:21:08 EDT 2021
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.
--- a/src/libmach/deps.mk
+++ b/src/libmach/deps.mk
@@ -59,6 +59,9 @@
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
--- a/src/libmach/elf64/elf64.c
+++ b/src/libmach/elf64/elf64.c
@@ -15,6 +15,7 @@
.strip = NULL,
.del = elf64del,
.write = NULL,
+ .getsym = elf64getsym,
.getsec = elf64getsec,
.loadmap = NULL,
};
--- /dev/null
+++ b/src/libmach/elf64/elf64getsym.c
@@ -1,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;
+}
--- a/src/libmach/elf64/rules.mk
+++ b/src/libmach/elf64/rules.mk
@@ -5,3 +5,4 @@
elf64/elf64read.o\
elf64/elf64getsec.o\
elf64/elf64del.o\
+ elf64/elf64getsym.o\