#include "sym.h" #include "header.h" #include "link.h" #include #include #include #include void sym_destroy(Sym* sym) { free(sym->ident); } void sym_table_construct(SymTable* table) { const size_t syms_capacity = 16; *table = (SymTable) { .syms = malloc(sizeof(SymTable) * syms_capacity), .syms_capacity = syms_capacity, .syms_size = 0, }; } void sym_table_destroy(SymTable* table) { for (size_t i = 0; i < table->syms_size; ++i) { sym_destroy(&table->syms[i]); } free(table->syms); } Sym* sym_table_find(SymTable* table, const char* ident) { for (size_t i = 0; i < table->syms_size; ++i) { Sym* sym = &table->syms[i]; if (strcmp(sym->ident, ident) == 0) { return sym; } } return NULL; } static inline void sym_table_add(SymTable* table, char* ident, const char* filename, uint16_t offset, bool resolved) { if (table->syms_size + 1 > table->syms_capacity) { table->syms_capacity *= 2; table->syms = realloc(table->syms, sizeof(SymTable) * table->syms_capacity); } table->syms[table->syms_size++] = (Sym) { ident, filename, offset, resolved }; } void sym_table_add_unresolved( SymTable* table, char* ident, const char* filename) { sym_table_add(table, ident, filename, 0, false); } void sym_table_add_resolved( SymTable* table, char* ident, const char* filename, uint16_t offset) { sym_table_add(table, ident, filename, offset, true); } int sym_table_walk_header( SymTable* syms, Header* header, uint16_t offset, const char* input_filename) { for (size_t i = 0; i < header->global_syms_size; ++i) { const HeaderGlobalSym* global_sym = &header->global_syms[i]; Sym* sym = sym_table_find(syms, global_sym->ident); if (!sym) { sym_table_add_resolved(syms, link_strdup(global_sym->ident), input_filename, offset + global_sym->offset); } else if (!sym->resolved) { sym->offset = offset + global_sym->offset; sym->resolved = true; } else { fprintf(stderr, "error: duplicate symbol '%s' defined in %s\n", global_sym->ident, input_filename); fprintf(stderr, "info: symbol '%s' originally defined in %s\n", sym->ident, sym->filename); return -1; } } for (size_t i = 0; i < header->extern_syms_size; ++i) { const HeaderExternSym* extern_sym = &header->extern_syms[i]; Sym* sym = sym_table_find(syms, extern_sym->ident); if (!sym) { sym_table_add_unresolved( syms, link_strdup(extern_sym->ident), input_filename); } } return 0; }