summaryrefslogtreecommitdiff
path: root/mld/symtab.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--mld/symtab.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/mld/symtab.c b/mld/symtab.c
new file mode 100644
index 0000000..eca6dbe
--- /dev/null
+++ b/mld/symtab.c
@@ -0,0 +1,60 @@
+#include <elf.h>
+#include <merror.h>
+#include <stdlib.h>
+#include <melf.h>
+
+#include "link.h"
+
+#define SYMTAB_INIT_LEN 8
+
+int symtab_init(struct symbol_table *symtab)
+{
+ symtab->len = 1;
+ symtab->size = SYMTAB_INIT_LEN;
+ symtab->syms = malloc(sizeof(Elf32_Sym) * SYMTAB_INIT_LEN);
+
+ if (symtab->syms == NULL) {
+ PERROR("cannot alloc");
+ return M_ERROR;
+ }
+
+ symtab->syms[0] = (Elf32_Sym){0};
+
+ return M_SUCCESS;
+}
+
+void symtab_free(struct symbol_table *symtab)
+{
+ free(symtab->syms);
+}
+
+int symtab_push(struct symbol_table *symtab, const Elf32_Sym *sym)
+{
+ if (symtab->len >= symtab->size) {
+ size_t size = symtab->size *= 2;
+ void *new = realloc(symtab->syms, sizeof(Elf32_Sym) * size);
+ if (new == NULL) {
+ PERROR("cannot realloc");
+ return M_ERROR;
+ }
+ symtab->size = size;
+ symtab->syms = new;
+ }
+
+ symtab->syms[symtab->len++] = *sym;
+ return M_SUCCESS;
+}
+
+int symtab_get(struct symbol_table *symtab, Elf32_Sym **res, const char *name)
+{
+ for (size_t i = 0; i < symtab->len; i++) {
+ Elf32_Sym *sym = &symtab->syms[i];
+ const char *symname = symtab->strtab->data + B32(sym->st_name);
+ if (strcmp(name, symname) == 0) {
+ if (res != NULL)
+ *res = sym;
+ return M_SUCCESS;
+ }
+ }
+ return M_ERROR;
+}