summaryrefslogtreecommitdiff
path: root/masm/symtab.c
blob: c6f9aac0eea00bd788e353ffb53c4e89a1204955 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <elf.h>
#include <merror.h>
#include <netinet/in.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "asm.h"

#define SYMTBL_INIT_LEN 24

int symtab_init(struct symbol_table *symtab)
{
        symtab->size = SYMTBL_INIT_LEN;
        symtab->len = 0;
        symtab->symbols = malloc(sizeof(Elf32_Sym) * SYMTBL_INIT_LEN);
        symtab->sections = malloc(sizeof(ssize_t) * SYMTBL_INIT_LEN);

        if (symtab->symbols == NULL || symtab->sections == NULL) {
                ERROR("cannot alloc");
                return M_ERROR;
        }

        Elf32_Sym null = {0};
        if (symtab_push(symtab, null, -1))
                return M_ERROR;

        return M_SUCCESS;
}

void symtab_free(struct symbol_table *symtab)
{
        free(symtab->symbols);
        free(symtab->sections);
}

int symtab_push(struct symbol_table *symtab, Elf32_Sym sym, ssize_t sec_idx)
{
        if (symtab->len >= symtab->size) {
                symtab->size *= 2;
                symtab->symbols = realloc(symtab->symbols,
                                        sizeof(Elf32_Sym) * symtab->size);
                symtab->sections = realloc(symtab->sections,
                                        sizeof(ssize_t) * symtab->size);
                if (symtab->symbols == NULL || symtab->sections == NULL) {
                        ERROR("cannot realloc");
                        return M_ERROR;
                }
        }

        symtab->symbols[symtab->len] = sym;
        symtab->sections[symtab->len++] = sec_idx;
        return M_SUCCESS;
}

int symtab_find(struct symbol_table *symtab, Elf32_Sym **ptr,
                size_t *idx, const char name[MAX_LEX_LENGTH])
{
        for (uint32_t i = 0; i < symtab->len; i++) {
                Elf32_Sym *sym = &symtab->symbols[i];
                const char *str = &symtab->strtab->ptr[ntohl(sym->st_name)];
                if (strcmp(str, name) == 0) {
                        if (ptr != NULL)
                                *ptr = sym;

                        ptrdiff_t diff = sym - symtab->symbols;
                        if (idx != NULL)
                                *idx = diff;

                        return M_SUCCESS;
                }
        }
        return M_ERROR;
}