shithub: scc

Download patch

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\