diff --git a/config.mk b/config.mk index 682002b..3f23d71 100644 --- a/config.mk +++ b/config.mk @@ -5,7 +5,7 @@ LD=cc CFLAGS += -pipe CFLAGS += -Wall -Wextra -pedantic -CFLAGS += -O3 -g +CFLAGS += -O0 -g # ======================== CONFIG OPTIONS == # diff --git a/include/mips32.h b/include/mips32.h index ce0e997..228e213 100644 --- a/include/mips32.h +++ b/include/mips32.h @@ -117,6 +117,7 @@ enum mips32_instruction_type { MIPS32_INS_SRLV, MIPS32_INS_SUB, MIPS32_INS_SUBU, + MIPS32_INS_SYSCALL, MIPS32_INS_OR, MIPS32_INS_ORI, MIPS32_INS_NOR, @@ -447,6 +448,10 @@ MIPS32_INS(SUB, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SUB) #define MIPS32_FUNCT_SUBU 0b100011 MIPS32_INS(SUBU, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SUBU) +/* SYSCALL - syscall */ +#define MIPS32_FUNCT_SYSCALL 0b001100 +MIPS32_INS(SYSCALL, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SYSCALL) + /* OR - or */ #define MIPS32_FUNCT_OR 0b100101 MIPS32_INS(OR, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_OR) @@ -478,11 +483,14 @@ enum mips32_directive_type { MIPS32_DIRECTIVE_HALF, MIPS32_DIRECTIVE_BYTE, MIPS32_DIRECTIVE_SECTION, + MIPS32_DIRECTIVE_EXTERN, + MIPS32_DIRECTIVE_GLOBL, }; /* mip32 directive */ struct mips32_directive { enum mips32_directive_type type; + uint32_t len; // used for words, halfs, bytes union { uint16_t align; uint16_t space; diff --git a/masm/asm.c b/masm/asm.c new file mode 100644 index 0000000..6e2a56c --- /dev/null +++ b/masm/asm.c @@ -0,0 +1,41 @@ +#include +#include + +#include "asm.h" + +int assembler_init(struct assembler *asm, const char *path) +{ + if (lexer_init(path, &asm->lexer)) + return M_ERROR; + + if (parser_init(&asm->lexer, &asm->parser)) { + lexer_free(&asm->lexer); + return M_ERROR; + } + + if (strtbl_init(&asm->shstr_tbl)) { + parser_free(&asm->parser); + lexer_free(&asm->lexer); + return M_ERROR; + } + + if (strtbl_init(&asm->str_tbl)) { + strtbl_free(&asm->shstr_tbl); + parser_free(&asm->parser); + lexer_free(&asm->lexer); + return M_ERROR; + } + + asm->meta = NULL; + + return M_SUCCESS; +} + +void assembler_free(struct assembler *asm) +{ + strtbl_free(&asm->str_tbl); + strtbl_free(&asm->shstr_tbl); + parser_free(&asm->parser); + lexer_free(&asm->lexer); + free(asm->meta); +} diff --git a/masm/asm.h b/masm/asm.h index 1bc7cf5..b8e6214 100644 --- a/masm/asm.h +++ b/masm/asm.h @@ -5,13 +5,16 @@ #include +#include "lex.h" +#include "parse.h" + struct str_table { - char *ptr; - size_t size; + char *ptr; + size_t size; }; /* initalize a string table */ -void strtbl_init(struct str_table *str_tbl); +int strtbl_init(struct str_table *str_tbl); /* free a string table */ void strtbl_free(struct str_table *str_tbl); @@ -22,11 +25,29 @@ int strtbl_get_str(struct str_table *str_tbl, const char *str, size_t *res); /* get or append a string into the string table */ int strtbl_write_str(struct str_table *str_tbl, const char *str, size_t *res); -struct assembler { - struct parser *parser; - struct str_table str_tbl; +struct section_meta { + void *reltbl; + uint32_t reltbl_len; + uint32_t reltbl_idx; // reltbl idx in shdr + uint32_t shdr_idx; // sec idx in shdr + uint32_t v_addr; }; +struct assembler { + struct lexer lexer; + struct parser parser; + struct str_table shstr_tbl; + struct str_table str_tbl; + + struct section_meta *meta; + size_t shstrtbl_idx; + size_t strtbl_idx; + size_t symtbl_idx; +}; + +int assembler_init(struct assembler *asm, const char *path); +void assembler_free(struct assembler *asm); + /* assemble a mips32 file*/ int assemble_file_mips32(char *path); diff --git a/masm/asm_mips32.c b/masm/asm_mips32.c index dcb81e5..deda214 100644 --- a/masm/asm_mips32.c +++ b/masm/asm_mips32.c @@ -14,352 +14,665 @@ extern char *current_file; -#define SHDR_SYMTBL 0 -#define SHDR_STRTBL 1 -#define SHDR_SECTIONS 2 - -static int parse_file(struct parser *parser) +static int handle_directive(struct assembler *asm, + struct mips32_directive *directive) { + switch (directive->type) { + case MIPS32_DIRECTIVE_SECTION: { + struct section_table *sec_tbl = &asm->parser.sec_tbl; + struct section *sec; + if (sectbl_get(sec_tbl, &sec, directive->name) + == M_SUCCESS) { + sec_tbl->current = sec; + break; + } + + if (sectbl_alloc(sec_tbl, &sec, directive->name)) + return M_ERROR; + + sec_tbl->current = sec; + break; + } + + case MIPS32_DIRECTIVE_ALIGN: { + asm->parser.sec_tbl.current->alignment = + 1 << directive->align; + break; + } + + case MIPS32_DIRECTIVE_SPACE: { + struct section_entry entry; + entry.type = ENT_NO_DATA; + entry.size = directive->space; + if (sec_push(asm->parser.sec_tbl.current, entry)) + return M_ERROR; + break; + } + + case MIPS32_DIRECTIVE_WORD: { + for (uint32_t i = 0; i < directive->len; i++) { + struct section_entry entry; + entry.type = ENT_WORD; + entry.word = directive->words[i]; + if (sec_push(asm->parser.sec_tbl.current, entry)) + return M_ERROR; + } + break; + } + + case MIPS32_DIRECTIVE_HALF: { + for (uint32_t i = 0; i < directive->len; i++) { + struct section_entry entry; + entry.type = ENT_HALF; + entry.half = directive->halfs[i]; + if (sec_push(asm->parser.sec_tbl.current, entry)) + return M_ERROR; + } + break; + } + + case MIPS32_DIRECTIVE_BYTE: { + for (uint32_t i = 0; i < directive->len; i++) { + struct section_entry entry; + entry.type = ENT_BYTE; + entry.byte = directive->bytes[i]; + if (sec_push(asm->parser.sec_tbl.current, entry)) + return M_ERROR; + } + break; + } + + case MIPS32_DIRECTIVE_EXTERN: { + struct symbol symbol; + if (symtbl_find(&asm->parser.sym_tbl, NULL, directive->name) + == M_SUCCESS) { + ERROR("cannot extern local symbol '%s'", + directive->name); + return M_ERROR; + } + + symbol = (struct symbol) { + .name = "", + .sec = asm->parser.sec_tbl.current, + .index = asm->parser.sec_tbl.current->count, + .flag = SYM_EXTERNAL, + }; + strcpy(symbol.name, directive->name); + + if (symtbl_push(&asm->parser.sym_tbl, symbol)) + return M_ERROR; + + break; + } + + case MIPS32_DIRECTIVE_GLOBL: { + struct symbol symbol; + if (symtbl_find(&asm->parser.sym_tbl, NULL, directive->name) + == M_SUCCESS) { + symbol.flag = SYM_GLOBAL; + break; + } + + symbol = (struct symbol) { + .name = "", + .sec = NULL, + .index = 0, + .flag = SYM_GLOBAL, + }; + strcpy(symbol.name, directive->name); + + if (symtbl_push(&asm->parser.sym_tbl, symbol)) + return M_ERROR; + + break; + } + } + + return M_SUCCESS; +} + +static int parse_file(struct assembler *asm) +{ + struct parser *parser = &asm->parser; + while (1) { struct expr expr; if (parser_next(parser, &expr)) { break; } - if (expr.type == EXPR_INS) - if (sectbl_push(&parser->sec_tbl, - parser->sec_tbl.current, expr.ins)) - return M_ERROR; + switch (expr.type) { + case EXPR_INS: + struct section_entry entry; + entry.type = ENT_INS; + entry.size = sizeof(struct mips32_instruction); + entry.ins = expr.ins; + if (sec_push(parser->sec_tbl.current, entry)) + return M_ERROR; + break; + + case EXPR_DIRECTIVE: + if (handle_directive(asm, &expr.directive.mips32)) + return M_ERROR; + break; + + case EXPR_CONSTANT: + case EXPR_LABEL: + // nothing needed to be done + break; + } + } + + struct section_meta *meta = malloc(sizeof(struct section_meta) * + parser->sec_tbl.count); + if (meta == NULL) { + ERROR("cannot alloc"); + return M_ERROR; } - for (uint32_t i = 0; i < parser->ref_tbl.count; i++) { - struct reference *ref = &parser->ref_tbl.references[i]; - struct symbol *sym; - struct mips32_instruction *ins; + asm->meta = meta; - if (symtbl_find(&parser->sym_tbl, &sym, ref->name)) { - ERROR("undefined symbol '%s'", ref->name); - return M_ERROR; - } + size_t ptr = 0; + for (uint32_t i = 0; i < parser->sec_tbl.count; i++) { + struct section *sec = &parser->sec_tbl.sections[i]; + meta[i].v_addr = ptr; + ptr += sec_size(sec); + } - ins = &ref->section->ins[ref->index].mips32; - - switch (ref->type) { - case REF_OFFESET: - ins->B_data.offset += sym->position - - (ref->section->start + ref->index); - break; - case REF_TARGET: - ins->J_data.target += sym->position; - break; - } - }; - - return M_SUCCESS; + return M_SUCCESS; } static int assemble_phdr(struct assembler *asm, Elf32_Phdr **res, - uint32_t *res2) + uint32_t *res2) { - struct parser *parser = asm->parser; - Elf32_Phdr *phdr = malloc(sizeof(Elf32_Phdr) * - parser->sec_tbl.count); - size_t ins_sz = sizeof(struct mips32_instruction); + struct parser *parser = &asm->parser; + Elf32_Phdr *phdr = malloc(sizeof(Elf32_Phdr) * + parser->sec_tbl.count); + if (phdr == NULL) { + ERROR("cannot alloc"); + return M_ERROR;; + } - if (phdr == NULL) { - ERROR("cannot alloc"); - return M_ERROR;; - } + for (uint32_t i = 0; i < parser->sec_tbl.count; i++) { + Elf32_Phdr *hdr = &phdr[i]; + struct section *sec = &parser->sec_tbl.sections[i]; + size_t size = sec_size(sec); + hdr->p_type = PT_LOAD; + hdr->p_flags = (sec->execute << 0) | + (sec->write << 1) | + (sec->read << 2); + hdr->p_offset = 0; + hdr->p_vaddr = 0; + hdr->p_paddr = 0; + hdr->p_filesz = size; + hdr->p_memsz = size; + hdr->p_align = sec->alignment; + } - for (uint32_t i = 0; i < parser->sec_tbl.count; i++) { - Elf32_Phdr *hdr = &phdr[i]; - struct section *sec = &parser->sec_tbl.sections[i]; - - hdr->p_type = PT_LOAD; - hdr->p_flags = PF_X | PF_W | PF_R; // FIXME: this is bad - hdr->p_offset = sec->start * ins_sz; - hdr->p_vaddr = sec->start * ins_sz; - hdr->p_paddr = 0x00; - hdr->p_filesz = sec->count * ins_sz; - hdr->p_memsz = sec->count * ins_sz; - hdr->p_align = sec->alignment; - } - - *res = phdr; - *res2 = parser->sec_tbl.count; - return M_SUCCESS; + *res = phdr; + *res2 = parser->sec_tbl.count; + return M_SUCCESS; } static int assemble_symtbl(struct assembler *asm, Elf32_Sym **res, - uint32_t *res2) + uint32_t *res2) { - Elf32_Sym *stbl = malloc(sizeof(Elf32_Sym) * asm->parser->sym_tbl - .count); + Elf32_Sym *stbl = malloc(sizeof(Elf32_Sym) * asm->parser.sym_tbl + .count); + size_t size = 0; - if (stbl == NULL) - return M_ERROR; + if (stbl == NULL) + return M_ERROR; - for (uint32_t i = 0; i < asm->parser->sym_tbl.count; i++) { - struct symbol *sym = &asm->parser->sym_tbl.symbols[i]; - size_t str_off; + for (uint32_t i = 0; i < asm->parser.sym_tbl.count; i++) { + struct symbol *sym = &asm->parser.sym_tbl.symbols[i]; + size_t str_off; + unsigned char bind; + unsigned char type = STT_NOTYPE; - if (strtbl_write_str(&asm->str_tbl, sym->name, &str_off)) { - free(stbl); - return M_ERROR; - } + if (strtbl_write_str(&asm->str_tbl, sym->name, &str_off)) { + free(stbl); + return M_ERROR; + } - int viz = STB_LOCAL; - switch (sym->flag) { - case SYM_LOCAL: - viz = STB_LOCAL; - break; - case SYM_GLOBAL: - case SYM_EXTERNAL: - viz = STB_GLOBAL; - break; - } + if (sym->flag != SYM_LOCAL) + bind = STB_LOCAL; + else + bind = STB_GLOBAL; - stbl[i] = (Elf32_Sym) { - .st_name = str_off, - .st_value = sym->position, - .st_size = 0, - .st_info = (unsigned char) - ELF32_ST_INFO(SYMINFO_BT_SELF, - SYMINFO_FLG_DIRECT), - .st_other = (unsigned char) - ELF32_ST_VISIBILITY(viz), - .st_shndx = 0, // FIXME: specify section - }; - }; + stbl[i] = (Elf32_Sym) { + .st_name = str_off, + .st_value = sym->index, + .st_size = 0, + .st_info = ELF32_ST_INFO(bind, type), + .st_other = ELF32_ST_VISIBILITY(STV_DEFAULT), + .st_shndx = asm->meta[sym->sec->index].shdr_idx, + }; + size = i + 1; + }; - *res = stbl; - *res2 = asm->parser->sym_tbl.count; + *res = stbl; + *res2 = size; - return M_SUCCESS; + return M_SUCCESS; +} + +static int assemble_reltbl_sec(struct assembler *asm, Elf32_Sym *symtbl, + uint32_t symtbl_len, struct section *sec) +{ + uint32_t len = 0; + + for (uint32_t i = 0; i < asm->parser.ref_tbl.count; i++) { + struct reference *ref = &asm->parser.ref_tbl.references[i]; + if (ref->section->index == sec->index) { + len++; + } + } + + if (len == 0) { + asm->meta[sec->index].reltbl = NULL; + return M_SUCCESS; + } + + Elf32_Rela *reltbl = malloc(sizeof(Elf32_Rela) * len); + + if (reltbl == NULL) { + ERROR("cannot alloc"); + return M_ERROR; + } + + for (uint32_t i = 0; i < asm->parser.ref_tbl.count; i++) { + struct reference *ref = &asm->parser.ref_tbl.references[i]; + struct mips32_instruction *ins = &ref->section-> + entries[ref->index].ins.mips32; + struct section_meta *meta = &asm->meta[ref->section->index]; + + if (ref->section->index != sec->index) { + continue; + } + + int32_t addend = 0; + unsigned char type = 0; + switch (ref->type) { + case REF_OFFESET: + addend = ins->B_data.offset; + type = R_MIPS_PC16; + break; + case REF_TARGET: + addend = ins->J_data.target; + type = R_MIPS_26; + break; + } + + int32_t symidx = -1; + + for (uint32_t i = 0; i < symtbl_len; i++) { + Elf32_Sym *sym = &symtbl[i]; + const char *str = &asm->str_tbl.ptr[sym->st_name]; + if (strcmp(ref->name, str) == 0) { + symidx = i; + break; + } + } + + if (symidx == -1) { + ERROR("undefined symbol '%s'", ref->name); + free(reltbl); + return M_ERROR; + } + + reltbl[i] = (Elf32_Rela) { + .r_info = ELF32_R_INFO(symidx, type), + .r_addend = addend, + .r_offset = meta->v_addr + + sec_index(ref->section, ref->index), + }; + }; + + asm->meta[sec->index].reltbl_len = len; + asm->meta[sec->index].reltbl = reltbl; + + return M_SUCCESS; +} + +static int assemble_reltbl(struct assembler *asm, Elf32_Sym *symtbl, + uint32_t symtbl_len) +{ + for (uint32_t i = 0; i < asm->parser.sec_tbl.count; i++) { + struct section *sec = &asm->parser.sec_tbl.sections[i]; + if (assemble_reltbl_sec(asm, symtbl, symtbl_len, sec)) + return M_ERROR; + } + + return M_SUCCESS; } static int assemble_shdr(struct assembler *asm, Elf32_Shdr **res, - uint32_t *res2) + uint32_t *res2) { - uint32_t entries = 2; // str table and sym tabel - entries += asm->parser->sec_tbl.count; // sections + uint32_t max_entries = 4; // symtab, strtab, shstrtab + max_entries += asm->parser.sec_tbl.count; // sections + max_entries += asm->parser.sec_tbl.count; // reltabs per section - Elf32_Shdr *shdr = malloc(sizeof(Elf32_Shdr) * entries); + Elf32_Shdr *shdr = malloc(sizeof(Elf32_Shdr) * max_entries); - size_t str_off; - if (strtbl_write_str(&asm->str_tbl, ".shsymtab", &str_off)) { - free(shdr); - return M_ERROR; - } + size_t str_off; + uint32_t count = 0; - // symbol table - shdr[SHDR_SYMTBL] = (Elf32_Shdr) { - .sh_name = str_off, - .sh_type = SHT_SYMTAB, - .sh_flags = 0, - .sh_addr = 0, - .sh_offset = 0, - .sh_size = 0, - .sh_link = 1, - .sh_info = 0, - .sh_addralign = 1, - .sh_entsize = sizeof(Elf32_Sym), - }; + // eeltables + for (uint32_t i = 0; i < asm->parser.sec_tbl.count; i++) { - if (strtbl_write_str(&asm->str_tbl, ".shstrtab", &str_off)) { - free(shdr); - return M_ERROR; - } + if (asm->meta[i].reltbl == NULL) + continue; - // string table - shdr[SHDR_STRTBL] = (Elf32_Shdr) { - .sh_name = str_off, - .sh_type = SHT_STRTAB, - .sh_flags = SHF_STRINGS, - .sh_addr = 0, - .sh_offset = 0, - .sh_size = 0, - .sh_link = 0, - .sh_info = 0, - .sh_addralign = 1, - .sh_entsize = 0, - }; + struct section *sec = &asm->parser.sec_tbl.sections[i]; + const char *prefix = ".reltab."; + char reltab_name[MAX_LEX_LENGTH + 8]; - // for each section - for (uint32_t i = 0; i < asm->parser->sec_tbl.count; i++) { - struct section *sec = &asm->parser->sec_tbl.sections[i]; - char name[MAX_LEX_LENGTH+1] = "."; - strcat(name, sec->name); - if (strtbl_write_str(&asm->str_tbl, name, &str_off)) { - free(shdr); - return M_ERROR; - } - shdr[i+SHDR_SECTIONS] = (Elf32_Shdr) { - .sh_name = str_off, - .sh_type = SHT_PROGBITS, - .sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR, - .sh_addr = 0, - .sh_offset = 0, - .sh_size = 0, - .sh_link = 0, - .sh_info = 0, - .sh_addralign = sec->alignment, - .sh_entsize = sizeof(struct mips32_instruction), + strcpy(reltab_name, prefix); + strcat(reltab_name, sec->name); + + if (strtbl_write_str(&asm->shstr_tbl, reltab_name, &str_off)) { + free(shdr); + return M_ERROR; + } + + asm->meta[i].reltbl_idx = count; + shdr[count++] = (Elf32_Shdr) { + .sh_name = str_off, + .sh_type = SHT_RELA, + .sh_flags = 0, + .sh_addr = 0, + .sh_offset = 0, + .sh_size = 0, + .sh_link = 0, + .sh_info = 0, + .sh_addralign = 1, + .sh_entsize = sizeof(Elf32_Rela), + }; + } + + // for each section + for (uint32_t i = 0; i < asm->parser.sec_tbl.count; i++) { + struct section *sec = &asm->parser.sec_tbl.sections[i]; + char name[MAX_LEX_LENGTH+1] = "."; + strcat(name, sec->name); + if (strtbl_write_str(&asm->shstr_tbl, name, &str_off)) { + free(shdr); + return M_ERROR; + } + asm->meta[i].shdr_idx = count; + if (asm->meta[i].reltbl != NULL) + shdr[asm->meta[i].reltbl_idx].sh_info = count; + shdr[count++] = (Elf32_Shdr){ + .sh_name = str_off, + .sh_type = SHT_PROGBITS, + .sh_flags = (sec->write << 0) | (sec->execute << 2) | + SHF_ALLOC, + .sh_addr = 0, + .sh_offset = 0, + .sh_size = 0, + .sh_link = 0, + .sh_info = 0, + .sh_addralign = sec->alignment, + .sh_entsize = sizeof(struct mips32_instruction), }; } - *res = shdr; - *res2 = entries; + // symbol table + if (strtbl_write_str(&asm->shstr_tbl, ".symtab", &str_off)) { + free(shdr); + return M_ERROR; + } - return M_SUCCESS; + asm->symtbl_idx = count; + shdr[count++] = (Elf32_Shdr) { + .sh_name = str_off, + .sh_type = SHT_SYMTAB, + .sh_flags = 0, + .sh_addr = 0, + .sh_offset = 0, + .sh_size = 0, + .sh_link = 1, + .sh_info = 0, + .sh_addralign = 1, + .sh_entsize = sizeof(Elf32_Sym), + }; + + // string table + if (strtbl_write_str(&asm->shstr_tbl, ".strtab", &str_off)) { + free(shdr); + return M_ERROR; + } + + asm->strtbl_idx = count; + shdr[count++] = (Elf32_Shdr) { + .sh_name = str_off, + .sh_type = SHT_STRTAB, + .sh_flags = SHF_STRINGS, + .sh_addr = 0, + .sh_offset = 0, + .sh_size = 0, + .sh_link = 0, + .sh_info = 0, + .sh_addralign = 1, + .sh_entsize = 0, + }; + + // sh string table + if (strtbl_write_str(&asm->shstr_tbl, ".shstrtab", &str_off)) { + free(shdr); + return M_ERROR; + } + + asm->shstrtbl_idx = count; + shdr[count++] = (Elf32_Shdr) { + .sh_name = str_off, + .sh_type = SHT_STRTAB, + .sh_flags = SHF_STRINGS, + .sh_addr = 0, + .sh_offset = 0, + .sh_size = 0, + .sh_link = 0, + .sh_info = 0, + .sh_addralign = 1, + .sh_entsize = 0, + }; + + for (uint32_t i = 0; i < asm->parser.sec_tbl.count; i++) { + if (asm->meta[i].reltbl == NULL) + continue; + shdr[asm->meta[i].reltbl_idx].sh_link = asm->symtbl_idx; + } + + *res = shdr; + *res2 = count; + + return M_SUCCESS; } static int assemble_file(struct assembler *asm) { - Elf32_Phdr *phdr; - Elf32_Shdr *shdr; - Elf32_Sym *symtbl; - uint32_t phdr_len; - uint32_t shdr_len; - uint32_t symtbl_len; + Elf32_Phdr *phdr; + Elf32_Shdr *shdr; + Elf32_Sym *symtbl; + uint32_t phdr_len; + uint32_t shdr_len; + uint32_t symtbl_len; - if (assemble_symtbl(asm, &symtbl, &symtbl_len)) - return M_ERROR; + if (assemble_symtbl(asm, &symtbl, &symtbl_len)) + return M_ERROR; - if (assemble_phdr(asm, &phdr, &phdr_len)) { - free(symtbl); - return M_ERROR; - } + if (assemble_reltbl(asm, symtbl, symtbl_len)) { + free(symtbl); + return M_ERROR; + }; - if (assemble_shdr(asm, &shdr, &shdr_len)) { - free(symtbl); - free(phdr); - return M_ERROR; - }; + if (assemble_phdr(asm, &phdr, &phdr_len)) { + free(symtbl); + return M_ERROR; + } - Elf32_Ehdr ehdr = { - .e_ident = { - [EI_MAG0] = ELFMAG0, - [EI_MAG1] = ELFMAG1, - [EI_MAG2] = ELFMAG2, - [EI_MAG3] = ELFMAG3, - [EI_CLASS] = ELFCLASS32, - [EI_DATA] = ELFDATA2LSB, - [EI_VERSION] = EV_CURRENT, - [EI_OSABI] = ELFOSABI_NONE, - [EI_ABIVERSION] = 0x00, - [EI_PAD] = 0x00, - }, - .e_type = ET_REL, - .e_machine = EM_MIPS, - .e_version = EV_CURRENT, - .e_entry = 0x00, - .e_phoff = 0x00, - .e_shoff = 0x00, - .e_flags = EF_MIPS_ARCH_32R6, - .e_ehsize = sizeof(Elf32_Ehdr), - .e_phentsize = sizeof(Elf32_Phdr), - .e_phnum = phdr_len, - .e_shentsize = sizeof(Elf32_Shdr), - .e_shnum = shdr_len, - .e_shstrndx = SHDR_STRTBL, - }; + if (assemble_shdr(asm, &shdr, &shdr_len)) { + free(symtbl); + free(phdr); + return M_ERROR; + }; - uint32_t ptr = 0; + Elf32_Ehdr ehdr = { + .e_ident = { + [EI_MAG0] = ELFMAG0, + [EI_MAG1] = ELFMAG1, + [EI_MAG2] = ELFMAG2, + [EI_MAG3] = ELFMAG3, + [EI_CLASS] = ELFCLASS32, + [EI_DATA] = ELFDATA2LSB, + [EI_VERSION] = EV_CURRENT, + [EI_OSABI] = ELFOSABI_NONE, + [EI_ABIVERSION] = 0x00, + [EI_PAD] = 0x00, + }, + .e_type = ET_REL, + .e_machine = EM_MIPS, + .e_version = EV_CURRENT, + .e_entry = 0x00, + .e_phoff = 0x00, + .e_shoff = 0x00, + .e_flags = EF_MIPS_ARCH_32R6, + .e_ehsize = sizeof(Elf32_Ehdr), + .e_phentsize = sizeof(Elf32_Phdr), + .e_phnum = phdr_len, + .e_shentsize = sizeof(Elf32_Shdr), + .e_shnum = shdr_len, + .e_shstrndx = asm->shstrtbl_idx, + }; - // we must now correct offets and sizes inside the ehdr, phdr, - // and shdr + uint32_t ptr = 0; - ptr += sizeof(Elf32_Ehdr); + // we must now correct offets and sizes inside the ehdr, phdr, + // and shdr + ptr += sizeof(Elf32_Ehdr); - // phdr - ehdr.e_phoff = ptr; - ptr += phdr_len * sizeof(Elf32_Phdr); + // phdr + ehdr.e_phoff = ptr; + ptr += phdr_len * sizeof(Elf32_Phdr); - // sections - for (uint32_t i = 0; i < asm->parser->sec_tbl.count; i++) { - phdr[i].p_offset = ptr; - phdr[i].p_vaddr = ptr; - shdr[i+SHDR_SECTIONS].sh_offset = ptr; - shdr[i+SHDR_SECTIONS].sh_size = phdr[i].p_filesz; - ptr += phdr[i].p_filesz; - } + // reltbls + for (uint32_t i = 0; i < asm->parser.sec_tbl.count; i++) { + if (asm->meta[i].reltbl == NULL) + continue; + int idx = asm->meta[i].reltbl_idx; + int len = asm->meta[i].reltbl_len; + shdr[idx].sh_offset = ptr; + shdr[idx].sh_size = len * sizeof(Elf32_Rela); + ptr += len * sizeof(Elf32_Rela); + } - // symtbl - shdr[SHDR_SYMTBL].sh_offset = ptr; - shdr[SHDR_SYMTBL].sh_size = symtbl_len * sizeof(Elf32_Sym); - ptr += symtbl_len * sizeof(Elf32_Sym); + // sections + for (uint32_t i = 0; i < asm->parser.sec_tbl.count; i++) { + int idx = asm->meta[i].shdr_idx; + phdr[i].p_offset = ptr; + phdr[i].p_vaddr = ptr; + phdr[i].p_paddr = ptr; + shdr[idx].sh_offset = ptr; + shdr[idx].sh_size = phdr[i].p_filesz; + shdr[idx].sh_addr = phdr[i].p_vaddr; + shdr[idx].sh_addralign = phdr[i].p_align; + ptr += phdr[i].p_filesz; + } - // strtbl - shdr[SHDR_STRTBL].sh_offset = ptr; - shdr[SHDR_STRTBL].sh_size = asm->str_tbl.size; - ptr += asm->str_tbl.size; + // symtbl + shdr[asm->symtbl_idx].sh_offset = ptr; + shdr[asm->symtbl_idx].sh_link = asm->strtbl_idx; + shdr[asm->symtbl_idx].sh_size = symtbl_len * sizeof(Elf32_Sym); + ptr += symtbl_len * sizeof(Elf32_Sym); - // shdr - ehdr.e_shoff = ptr; + // strtbl + shdr[asm->strtbl_idx].sh_offset = ptr; + shdr[asm->strtbl_idx].sh_size = asm->str_tbl.size; + ptr += asm->str_tbl.size; - FILE *out = fopen("out.o", "w"); + // shstrtbl + shdr[asm->shstrtbl_idx].sh_offset = ptr; + shdr[asm->shstrtbl_idx].sh_size = asm->shstr_tbl.size; + ptr += asm->shstr_tbl.size; - // ehdr - fwrite(&ehdr, sizeof(Elf32_Ehdr), 1, out); + // shdr + ehdr.e_shoff = ptr; - // phdr - fwrite(phdr, sizeof(Elf32_Phdr), phdr_len, out); + FILE *out = fopen("out.o", "w"); - // sections - for (uint32_t i = 0; i < asm->parser->sec_tbl.count; i++) { - struct section *sec = &asm->parser->sec_tbl.sections[i]; - for (uint32_t j = 0; j < sec->count; j++) { - struct mips32_instruction *ins = &sec->ins[j].mips32; - fwrite(ins, sizeof(struct mips32_instruction), - 1, out); - } - } + // ehdr + fwrite(&ehdr, sizeof(Elf32_Ehdr), 1, out); - // sym tbl - fwrite(symtbl, sizeof(Elf32_Sym), symtbl_len, out); + // phdr + fwrite(phdr, sizeof(Elf32_Phdr), phdr_len, out); - // str tbl - fwrite(asm->str_tbl.ptr, asm->str_tbl.size, 1, out); + // reltbls + for (uint32_t i = 0; i < asm->parser.sec_tbl.count; i++) { + if (asm->meta[i].reltbl == NULL) + continue; + void *ptr = asm->meta[i].reltbl; + int len = asm->meta[i].reltbl_len; + asm->meta[i].reltbl = NULL; + fwrite(ptr, sizeof(Elf32_Rela), len, out); + } - // shdr - fwrite(shdr, sizeof(Elf32_Shdr), shdr_len, out); + // sections + for (uint32_t i = 0; i < asm->parser.sec_tbl.count; i++) { + struct section *sec = &asm->parser.sec_tbl.sections[i]; + for (uint32_t j = 0; j < sec->count; j++) { + struct section_entry *entry = &sec->entries[j]; + size_t size = entry->size; + fwrite(&entry->data, size, 1, out); + while(size % sec->alignment) { + uint8_t zero = 0; + fwrite(&zero, 1, 1, out); + size++; + } + } + } - fclose(out); + // sym tbl + fwrite(symtbl, sizeof(Elf32_Sym), symtbl_len, out); - free(shdr); - free(phdr); - free(symtbl); + // str tbl + fwrite(asm->str_tbl.ptr, asm->str_tbl.size, 1, out); - return M_SUCCESS; + // shstr tbl + fwrite(asm->shstr_tbl.ptr, asm->shstr_tbl.size, 1, out); + + // shdr + fwrite(shdr, sizeof(Elf32_Shdr), shdr_len, out); + + // cleanip + fclose(out); + free(shdr); + free(phdr); + free(symtbl); + + return M_SUCCESS; } int assemble_file_mips32(char *path) { - struct lexer lexer; - struct parser parser; + struct assembler asm; + int res = M_SUCCESS; + current_file = path; - int res = M_SUCCESS; - if (lexer_init(current_file, &lexer)) + if (assembler_init(&asm, path)) return M_ERROR; - if (mips32_parser_init(&lexer, &parser)) - return M_ERROR; + mips32_parser_init(&asm.parser); - if (res == M_SUCCESS) - res = parse_file(&parser); + if (res == M_SUCCESS) + res = parse_file(&asm); - struct assembler assembler; - assembler.parser = &parser; - strtbl_init(&assembler.str_tbl); + if (res == M_SUCCESS) + res = assemble_file(&asm); - if (res == M_SUCCESS) - res = assemble_file(&assembler); + assembler_free(&asm); - strtbl_free(&assembler.str_tbl); - lexer_free(&lexer); - parser_free(&parser); - - return res; + return res; } diff --git a/masm/parse.c b/masm/parse.c index 9876311..9f8ddb1 100644 --- a/masm/parse.c +++ b/masm/parse.c @@ -105,23 +105,27 @@ static int parse_label(struct parser *parser, struct expr *expr) { struct token token; - struct symbol symbol; - uint32_t index; if (assert_token(parser, TOK_LABEL, &token)) return M_ERROR; strcpy(expr->text, token.text); - if (symtbl_find(&parser->sym_tbl, NULL, token.text) == M_SUCCESS) { + struct symbol *ref; + if (symtbl_find(&parser->sym_tbl, &ref, token.text) == M_SUCCESS) { + if (ref->flag == SYM_GLOBAL && ref->sec == NULL) { + ref->sec = parser->sec_tbl.current; + ref->index = parser->sec_tbl.current->count; + return M_SUCCESS; + } ERROR_POS(token, "redefined symbol '%s'", token.text); return M_ERROR; } - index = parser->sec_tbl.current->start + - parser->sec_tbl.current->count; + struct symbol symbol; symbol = (struct symbol) { .name = "", - .position = index, + .sec = parser->sec_tbl.current, + .index = parser->sec_tbl.current->count, .flag = SYM_LOCAL, }; strcpy(symbol.name, token.text); diff --git a/masm/parse.h b/masm/parse.h index 2aea0be..5f37052 100644 --- a/masm/parse.h +++ b/masm/parse.h @@ -18,7 +18,6 @@ enum expr_type { EXPR_INS, EXPR_DIRECTIVE, EXPR_CONSTANT, - EXPR_SEGMENT, EXPR_LABEL, }; @@ -44,7 +43,8 @@ enum symbol_flag { struct symbol { char name[MAX_LEX_LENGTH]; - uint32_t position; + uint32_t index; + struct section *sec; enum symbol_flag flag; }; @@ -62,13 +62,37 @@ int symtbl_push(struct symbol_table *sym_tbl, struct symbol sym); int symtbl_find(struct symbol_table *sym_tbl, struct symbol **sym, const char name[MAX_LEX_LENGTH]); +enum section_entry_type { + ENT_INS, + ENT_WORD, + ENT_HALF, + ENT_BYTE, + ENT_NO_DATA, +}; + +struct section_entry { + enum section_entry_type type; + size_t size; + + union { + char data; // to get memory address + union mips_instruction ins; + int32_t word; + int16_t half; + int8_t byte; + }; +}; + struct section { uint32_t count; uint32_t len; - uint32_t start; uint32_t alignment; - union mips_instruction *ins; + uint32_t index; // what index is my section char name[MAX_LEX_LENGTH]; + bool read; + bool write; + bool execute; + struct section_entry *entries; }; struct section_table { @@ -77,7 +101,6 @@ struct section_table { struct section *sections; struct section *current; char name[MAX_LEX_LENGTH]; - uint32_t total_ins; }; int sectbl_init(struct section_table *sec_tbl); @@ -85,10 +108,11 @@ void sectbl_free(struct section_table *sec_tbl); int sectbl_alloc(struct section_table *sec_tbl, struct section **sec, const char name[MAX_LEX_LENGTH]); -int sectbl_push(struct section_table *sec_tbl, struct section *section, - union mips_instruction ins); int sectbl_get(struct section_table *sec_tbl, struct section **sec, const char name[MAX_LEX_LENGTH]); +int sec_push(struct section *section, struct section_entry entry); +size_t sec_size(struct section *section); +size_t sec_index(struct section *section, uint32_t index); enum reference_type { REF_OFFESET, diff --git a/masm/parse_mips32.c b/masm/parse_mips32.c index 032f115..db7f346 100644 --- a/masm/parse_mips32.c +++ b/masm/parse_mips32.c @@ -14,50 +14,50 @@ /* each instruction has a given parse format * internal to the parser */ enum mips32_parse_format { - // register type: rs, rt, td - MIPS32_PARSE_R, - // register type: rs, rt - MIPS32_PARSE_R2, - // register type: rd - MIPS32_PARSE_RD, - // register type: rs - MIPS32_PARSE_RS, - // imeediate type: rs, rt, immd - MIPS32_PARSE_I, - // jump type: offset - MIPS32_PARSE_J, - // jump type: register - MIPS32_PARSE_JR, - // offset 16b type: offset - MIPS32_PARSE_O16, - // offset 26b type: offset - MIPS32_PARSE_O26, - // breanch equal type: rs, rt, offset - MIPS32_PARSE_BE, - // branch zero type: rs, offset - MIPS32_PARSE_BZ, - // store and load: rt, offset(base) - MIPS32_PARSE_SL, - // store and load immediate: rt, immediate - MIPS32_PARSE_SLI, - // shift: rd, rt, sa - MIPS32_PARSE_S, - // shift variable: rd, rt, rs - MIPS32_PARSE_SV, - // none: - MIPS32_PARSE_NONE, + // register type: rs, rt, td + MIPS32_PARSE_R, + // register type: rs, rt + MIPS32_PARSE_R2, + // register type: rd + MIPS32_PARSE_RD, + // register type: rs + MIPS32_PARSE_RS, + // imeediate type: rs, rt, immd + MIPS32_PARSE_I, + // jump type: offset + MIPS32_PARSE_J, + // jump type: register + MIPS32_PARSE_JR, + // offset 16b type: offset + MIPS32_PARSE_O16, + // offset 26b type: offset + MIPS32_PARSE_O26, + // breanch equal type: rs, rt, offset + MIPS32_PARSE_BE, + // branch zero type: rs, offset + MIPS32_PARSE_BZ, + // store and load: rt, offset(base) + MIPS32_PARSE_SL, + // store and load immediate: rt, immediate + MIPS32_PARSE_SLI, + // shift: rd, rt, sa + MIPS32_PARSE_S, + // shift variable: rd, rt, rs + MIPS32_PARSE_SV, + // none: + MIPS32_PARSE_NONE, }; #define FORMAT(ins, format) \ - [MIPS32_INS_##ins] = MIPS32_PARSE_##format, \ + [MIPS32_INS_##ins] = MIPS32_PARSE_##format, \ const enum mips32_parse_format mips32_parse_formats[] = { - FORMAT(ADD, R) - FORMAT(ADDI, I) + FORMAT(ADD, R) + FORMAT(ADDI, I) FORMAT(ADDIU, I) FORMAT(ADDU, R) - FORMAT(AND, R) - FORMAT(ANDI, I) + FORMAT(AND, R) + FORMAT(ANDI, I) FORMAT(BAL, O16) FORMAT(BALC, O26) FORMAT(BC, O26) @@ -94,34 +94,34 @@ const enum mips32_parse_format mips32_parse_formats[] = { FORMAT(LW, SL) FORMAT(LWL, SL) FORMAT(LWR, SL) - FORMAT(MFHI, RD) - FORMAT(MFLO, RD) - FORMAT(MTHI, RS) - FORMAT(MTLO, RS) - FORMAT(MULT, R2) - FORMAT(MULTU, R2) + FORMAT(MFHI, RD) + FORMAT(MFLO, RD) + FORMAT(MTHI, RS) + FORMAT(MTLO, RS) + FORMAT(MULT, R2) + FORMAT(MULTU, R2) FORMAT(SB, SL) FORMAT(SH, SL) FORMAT(SW, SL) FORMAT(SWL, SL) FORMAT(SLL, S) FORMAT(SLLV, SV) - FORMAT(SLT, R) - FORMAT(SLTI, I) - FORMAT(SLTIU, I) - FORMAT(SLTU, R) + FORMAT(SLT, R) + FORMAT(SLTI, I) + FORMAT(SLTIU, I) + FORMAT(SLTU, R) FORMAT(SRA, S) FORMAT(SRAV, SV) FORMAT(SRL, S) FORMAT(SRLV, SV) - FORMAT(SYSCALL, NONE) - FORMAT(OR, R) - FORMAT(ORI, I) - FORMAT(NOR, R) - FORMAT(SUB, R) - FORMAT(SUBU, R) - FORMAT(XOR, R) - FORMAT(XORI, I) + FORMAT(SYSCALL, NONE) + FORMAT(OR, R) + FORMAT(ORI, I) + FORMAT(NOR, R) + FORMAT(SUB, R) + FORMAT(SUBU, R) + FORMAT(XOR, R) + FORMAT(XORI, I) }; #undef FORMAT @@ -131,75 +131,75 @@ const enum mips32_parse_format mips32_parse_formats[] = { #define MAX26 67108864 static int get_reference(struct parser *parser, uint32_t *offset, - enum reference_type type) + enum reference_type type) { - struct token token; + struct token token; - if (next_token(parser, &token)) - return M_ERROR; + if (next_token(parser, &token)) + return M_ERROR; - if (token.type == TOK_NUMBER) { - *offset = token.number; - return M_SUCCESS; - } + if (token.type == TOK_NUMBER) { + *offset = token.number; + return M_SUCCESS; + } - if (token.type != TOK_IDENT) { - ERROR_POS(token, "unexpected token of type '%s'", - token_str(token.type)); - return M_ERROR; - } + if (token.type != TOK_IDENT) { + ERROR_POS(token, "unexpected token of type '%s'", + token_str(token.type)); + return M_ERROR; + } - struct reference reference = { - .section = parser->sec_tbl.current, - .index = parser->sec_tbl.current->count, - .type = type, - }; - strcpy(reference.name, token.text); + struct reference reference = { + .section = parser->sec_tbl.current, + .index = parser->sec_tbl.current->count, + .type = type, + }; + strcpy(reference.name, token.text); - if (reftbl_push(&parser->ref_tbl, reference)) - return M_ERROR; + if (reftbl_push(&parser->ref_tbl, reference)) + return M_ERROR; - *offset = 0; + *offset = 0; - return M_SUCCESS; + return M_SUCCESS; } static int get_offset(struct parser *parser, uint32_t *offset) { - return get_reference(parser, offset, REF_OFFESET); + return get_reference(parser, offset, REF_OFFESET); } static int get_target(struct parser *parser, uint32_t *offset) { - return get_reference(parser, offset, REF_TARGET); + return get_reference(parser, offset, REF_TARGET); } static int get_instruction(const char *ident, struct mips32_instruction *res) { - for (int i = 0; i < __MIPS32_INS_LEN; i++) { - struct mips32_instruction ins = - mips32_instructions[i]; - if (strcasecmp(ident, ins.name) == 0) { - if (res != NULL) - *res = ins; - return M_SUCCESS; - } - } - return M_ERROR; + for (int i = 0; i < __MIPS32_INS_LEN; i++) { + struct mips32_instruction ins = + mips32_instructions[i]; + if (strcasecmp(ident, ins.name) == 0) { + if (res != NULL) + *res = ins; + return M_SUCCESS; + } + } + return M_ERROR; } static int is_instruction(const char *ident) { - return get_instruction(ident, NULL); + return get_instruction(ident, NULL); } static int parse_register(struct parser *parser, enum mips32_register *reg) { - struct token token; - if (assert_token(parser, TOK_REG, &token)) - return M_ERROR; + struct token token; + if (assert_token(parser, TOK_REG, &token)) + return M_ERROR; - int len = strlen(token.text); + int len = strlen(token.text); int c0 = len > 0 ? token.text[0] : '\0', c1 = len > 1 ? token.text[1] : '\0', c2 = len > 2 ? token.text[2] : '\0', @@ -304,550 +304,569 @@ static int parse_register(struct parser *parser, enum mips32_register *reg) i += c1 - '0'; } if (i <= 31) { - *reg = i; - return M_SUCCESS; - } + *reg = i; + return M_SUCCESS; + } } - ERROR_POS(token, "unknown register $%s", token.text); + ERROR_POS(token, "unknown register $%s", token.text); return M_ERROR; } static int parse_instruction_r(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - // format: rs, rt, rd - enum mips32_register reg; + // format: rs, rt, rd + enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rd = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rd = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rs = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rt = reg; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_r2(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - // format: rs, rt - enum mips32_register reg; + // format: rs, rt + enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rs = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rt = reg; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_rs(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - // format: rs - enum mips32_register reg; + // format: rs + enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rs = reg; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_rd(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - // format: rd - enum mips32_register reg; + // format: rd + enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rd = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rd = reg; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_i(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - // format: rs, rt, immd - enum mips32_register reg; - struct token token; + // format: rs, rt, immd + enum mips32_register reg; + struct token token; - if (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->I_data.rt = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->I_data.rs = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (assert_token(parser, TOK_NUMBER, &token)) - return M_ERROR; + if (assert_token(parser, TOK_NUMBER, &token)) + return M_ERROR; - if (token.number >= MAX16) - return M_ERROR; - ins->I_data.immd = token.number; + if (token.number >= MAX16) + return M_ERROR; + ins->I_data.immd = token.number; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_offset(struct parser *parser, - uint32_t max, - struct mips32_instruction *ins) + uint32_t max, + struct mips32_instruction *ins) { - uint32_t n; - if (get_offset(parser, &n) || n > max) - return M_ERROR; + uint32_t n; + if (get_offset(parser, &n) || n > max) + return M_ERROR; - switch (max) { - case MAX26: - ins->J_data.target = n; - break; - case MAX16: - ins->B_data.offset = n; - break; - } + switch (max) { + case MAX26: + ins->J_data.target = n; + break; + case MAX16: + ins->B_data.offset = n; + break; + } - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_j(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - uint32_t n; - if (get_target(parser, &n) || n > MAX26) - return M_ERROR; - ins->J_data.target = n; + uint32_t n; + if (get_target(parser, &n) || n > MAX26) + return M_ERROR; + ins->J_data.target = n; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_jr(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - uint32_t n; - if (get_target(parser, &n) || n > MAX26) - return M_ERROR; - ins->J_data.target = n; + uint32_t n; + if (get_target(parser, &n) || n > MAX26) + return M_ERROR; + ins->J_data.target = n; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_branch_equal(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; + enum mips32_register reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rs = reg; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_branch(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - enum mips32_register reg; - uint32_t n; + enum mips32_register reg; + uint32_t n; - if (parse_register(parser, ®)) - return M_ERROR; - ins->B_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->B_data.rs = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (get_offset(parser, &n) || n > MAX16) - return M_ERROR; - ins->B_data.offset = n; + if (get_offset(parser, &n) || n > MAX16) + return M_ERROR; + ins->B_data.offset = n; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_sl(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - enum mips32_register reg; - uint32_t offset = 0; - struct token token; + enum mips32_register reg; + uint32_t offset = 0; + struct token token; - if (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->I_data.rt = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (peek_token(parser, &token)) - return M_ERROR; + if (peek_token(parser, &token)) + return M_ERROR; - if (token.type != TOK_LPAREN) - if (get_offset(parser, &offset)) - return M_ERROR; - ins->I_data.immd = offset; + if (token.type != TOK_LPAREN) + if (get_offset(parser, &offset)) + return M_ERROR; + ins->I_data.immd = offset; - if (peek_token(parser, &token)) - return M_ERROR; + if (peek_token(parser, &token)) + return M_ERROR; - if (token.type == TOK_NL) { - ins->I_data.rs = MIPS32_REG_ZERO; - return M_SUCCESS; - } + if (token.type == TOK_NL) { + ins->I_data.rs = MIPS32_REG_ZERO; + return M_SUCCESS; + } - if (assert_token(parser, TOK_LPAREN, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_LPAREN, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->I_data.rs = reg; - if (assert_token(parser, TOK_RPAREN, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_RPAREN, NULL)) + return M_ERROR; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_sli(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - enum mips32_register reg; - struct token token; + enum mips32_register reg; + struct token token; - if (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->I_data.rt = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (assert_token(parser, TOK_NUMBER, &token) || token.number > MAX16) - return M_ERROR; - ins->I_data.immd = token.number; + if (assert_token(parser, TOK_NUMBER, &token) || token.number > MAX16) + return M_ERROR; + ins->I_data.immd = token.number; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_s(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - enum mips32_register reg; - struct token token; + enum mips32_register reg; + struct token token; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rd = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rd = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rt = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (assert_token(parser, TOK_NUMBER, &token) || token.number > MAX5) - return M_ERROR; - ins->R_data.shamt = token.number; + if (assert_token(parser, TOK_NUMBER, &token) || token.number > MAX5) + return M_ERROR; + ins->R_data.shamt = token.number; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_sv(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - enum mips32_register reg; + enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rd = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rd = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rt = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rs = reg; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction(struct parser *parser, - union mips_instruction *ins, - struct token ident) + union mips_instruction *ins, + struct token ident) { - struct mips32_instruction instruction; - enum mips32_parse_format format; - int res = M_SUCCESS; + struct mips32_instruction instruction; + enum mips32_parse_format format; + int res = M_SUCCESS; - if (get_instruction(ident.text, &instruction)) { - ERROR_POS(ident, "unknown instruction '%s'", ident.text); - return M_ERROR; - } + if (get_instruction(ident.text, &instruction)) { + ERROR_POS(ident, "unknown instruction '%s'", ident.text); + return M_ERROR; + } - ins->mips32 = instruction; - format = mips32_parse_formats[instruction.type]; + ins->mips32 = instruction; + format = mips32_parse_formats[instruction.type]; - switch (format) { - case MIPS32_PARSE_R: - res = parse_instruction_r(parser, &ins->mips32); - break; - case MIPS32_PARSE_R2: - res = parse_instruction_r2(parser, &ins->mips32); - break; - case MIPS32_PARSE_RS: - res = parse_instruction_rs(parser, &ins->mips32); - break; - case MIPS32_PARSE_RD: - res = parse_instruction_rd(parser, &ins->mips32); - break; - case MIPS32_PARSE_I: - res = parse_instruction_i(parser, &ins->mips32); - break; - case MIPS32_PARSE_J: - res = parse_instruction_j(parser, &ins->mips32); - break; - case MIPS32_PARSE_JR: - res = parse_instruction_jr(parser, &ins->mips32); - break; - case MIPS32_PARSE_O16: - res = parse_instruction_offset(parser, MAX16, &ins->mips32); - break; - case MIPS32_PARSE_O26: - res = parse_instruction_offset(parser, MAX26, &ins->mips32); - break; - case MIPS32_PARSE_BE: - res = parse_instruction_branch_equal(parser, &ins->mips32); - break; - case MIPS32_PARSE_BZ: - res = parse_instruction_branch(parser, &ins->mips32); - break; - case MIPS32_PARSE_SL: - res = parse_instruction_sl(parser, &ins->mips32); - break; - case MIPS32_PARSE_SLI: - res = parse_instruction_sli(parser, &ins->mips32); - break; - case MIPS32_PARSE_S: - res = parse_instruction_s(parser, &ins->mips32); - break; - case MIPS32_PARSE_SV: - res = parse_instruction_sv(parser, &ins->mips32); - break; - case MIPS32_PARSE_NONE: - res = M_SUCCESS; - break; - } + switch (format) { + case MIPS32_PARSE_R: + res = parse_instruction_r(parser, &ins->mips32); + break; + case MIPS32_PARSE_R2: + res = parse_instruction_r2(parser, &ins->mips32); + break; + case MIPS32_PARSE_RS: + res = parse_instruction_rs(parser, &ins->mips32); + break; + case MIPS32_PARSE_RD: + res = parse_instruction_rd(parser, &ins->mips32); + break; + case MIPS32_PARSE_I: + res = parse_instruction_i(parser, &ins->mips32); + break; + case MIPS32_PARSE_J: + res = parse_instruction_j(parser, &ins->mips32); + break; + case MIPS32_PARSE_JR: + res = parse_instruction_jr(parser, &ins->mips32); + break; + case MIPS32_PARSE_O16: + res = parse_instruction_offset(parser, MAX16, &ins->mips32); + break; + case MIPS32_PARSE_O26: + res = parse_instruction_offset(parser, MAX26, &ins->mips32); + break; + case MIPS32_PARSE_BE: + res = parse_instruction_branch_equal(parser, &ins->mips32); + break; + case MIPS32_PARSE_BZ: + res = parse_instruction_branch(parser, &ins->mips32); + break; + case MIPS32_PARSE_SL: + res = parse_instruction_sl(parser, &ins->mips32); + break; + case MIPS32_PARSE_SLI: + res = parse_instruction_sli(parser, &ins->mips32); + break; + case MIPS32_PARSE_S: + res = parse_instruction_s(parser, &ins->mips32); + break; + case MIPS32_PARSE_SV: + res = parse_instruction_sv(parser, &ins->mips32); + break; + case MIPS32_PARSE_NONE: + res = M_SUCCESS; + break; + } - if (res == M_SUCCESS && assert_eol(parser)) - return M_ERROR; + if (res == M_SUCCESS && assert_eol(parser)) + return M_ERROR; - return res; + return res; } static int parse_directive_align(struct parser *parser, - struct mips32_directive *directive) + struct mips32_directive *directive) { - struct token token; - if (assert_token(parser, TOK_NUMBER, &token)) - return M_ERROR; + struct token token; + if (assert_token(parser, TOK_NUMBER, &token)) + return M_ERROR; - if (token.number < 0) { - ERROR_POS(token, "cannot align negative"); - return M_ERROR; - } + if (token.number < 0) { + ERROR_POS(token, "cannot align negative"); + return M_ERROR; + } - if (token.number > MAX16) { - ERROR_POS(token, "cannot align more than 65kb"); - return M_ERROR; - } + if (token.number > MAX16) { + ERROR_POS(token, "cannot align more than 65kb"); + return M_ERROR; + } - directive->type = MIPS32_DIRECTIVE_ALIGN; - directive->align = token.number; + directive->type = MIPS32_DIRECTIVE_ALIGN; + directive->align = token.number; - return M_SUCCESS; + return M_SUCCESS; } static int parse_directive_space(struct parser *parser, - struct mips32_directive *directive) + struct mips32_directive *directive) { - struct token token; - if (assert_token(parser, TOK_NUMBER, &token)) - return M_ERROR; + struct token token; + if (assert_token(parser, TOK_NUMBER, &token)) + return M_ERROR; - if (token.number < 0) { - ERROR_POS(token, "cannot reserve negative"); - return M_ERROR; - } + if (token.number < 0) { + ERROR_POS(token, "cannot reserve negative"); + return M_ERROR; + } - if (token.number > MAX16) { - ERROR_POS(token, "cannot reserve more than 65kb"); - return M_ERROR; - } + if (token.number > MAX16) { + ERROR_POS(token, "cannot reserve more than 65kb"); + return M_ERROR; + } - directive->type = MIPS32_DIRECTIVE_SPACE; - directive->space = token.number; + directive->type = MIPS32_DIRECTIVE_SPACE; + directive->space = token.number; - return M_SUCCESS; + return M_SUCCESS; } static int parse_directive_whb(struct parser *parser, - struct mips32_directive *directive, - enum mips32_directive_type type) + struct mips32_directive *directive, + enum mips32_directive_type type) { - struct token token; - uint32_t size = 0; - uint32_t len = 0; + struct token token; + uint32_t size = 0; + uint32_t len = 0; - switch (type) { - case MIPS32_DIRECTIVE_WORD: - size = UINT32_MAX; - break; - case MIPS32_DIRECTIVE_HALF: - size = UINT16_MAX; - break; - case MIPS32_DIRECTIVE_BYTE: - size = UINT8_MAX; - break; - default: - } + switch (type) { + case MIPS32_DIRECTIVE_WORD: + size = UINT32_MAX; + break; + case MIPS32_DIRECTIVE_HALF: + size = UINT16_MAX; + break; + case MIPS32_DIRECTIVE_BYTE: + size = UINT8_MAX; + break; + default: + } - directive->type = type; + directive->type = type; - while (1) { - if (assert_token(parser, TOK_NUMBER, &token)) - return M_ERROR; + while (1) { + if (assert_token(parser, TOK_NUMBER, &token)) + return M_ERROR; - if (len >= MAX_ARG_LENGTH) { - ERROR_POS(token, "directives cannot be longer than " - "%d arguments", MAX_ARG_LENGTH); - return M_ERROR; - } + if (len >= MAX_ARG_LENGTH) { + ERROR_POS(token, "directives cannot be longer than " + "%d arguments", MAX_ARG_LENGTH); + return M_ERROR; + } - if (token.number > size) { - ERROR_POS(token, "number cannot execede max size of: " - "%d", size); - return M_ERROR; - } + if (token.number > size) { + ERROR_POS(token, "number cannot execede max size of: " + "%d", size); + return M_ERROR; + } - switch (type) { - case MIPS32_DIRECTIVE_WORD: - directive->words[len++] = token.number; - break; - case MIPS32_DIRECTIVE_HALF: - directive->halfs[len++] = token.number; - break; - case MIPS32_DIRECTIVE_BYTE: - directive->bytes[len++] = token.number; - break; - default: - } + switch (type) { + case MIPS32_DIRECTIVE_WORD: + directive->words[len++] = token.number; - if (peek_token(parser, &token)) - return M_ERROR; + break; + case MIPS32_DIRECTIVE_HALF: + directive->halfs[len++] = token.number; + break; + case MIPS32_DIRECTIVE_BYTE: + directive->bytes[len++] = token.number; + break; + default: + } - if (token.type == TOK_COMMA) { - next_token(parser, NULL); - continue; - } + if (peek_token(parser, &token)) + return M_ERROR; - break; - } + if (token.type == TOK_COMMA) { + next_token(parser, NULL); + continue; + } - return M_SUCCESS; + break; + } + + directive->len = len; + + return M_SUCCESS; } -static int parse_section(struct parser *parser, - struct mips32_directive *directive, - char name[MAX_LEX_LENGTH]) +static int parse_directive_extern(struct parser *parser, + struct mips32_directive *directive) { - directive->type = MIPS32_DIRECTIVE_SECTION; - strcpy(directive->name, name); + struct token token; + if (assert_token(parser, TOK_IDENT, &token)) + return M_ERROR; - struct section *sec; - if (sectbl_get(&parser->sec_tbl, &sec, name) == M_SUCCESS) { - parser->sec_tbl.current = sec; - return M_SUCCESS; - } + directive->type = MIPS32_DIRECTIVE_EXTERN; + strcpy(directive->name, token.text); - if (sectbl_alloc(&parser->sec_tbl, &sec, name)) - return M_ERROR; + return M_SUCCESS; +} - parser->sec_tbl.current = sec; - return M_SUCCESS; +static int parse_directive_globl(struct parser *parser, + struct mips32_directive *directive) +{ + struct token token; + if (assert_token(parser, TOK_IDENT, &token)) + return M_ERROR; + + directive->type = MIPS32_DIRECTIVE_GLOBL; + strcpy(directive->name, token.text); + + return M_SUCCESS; +} + +static int parse_section(struct mips32_directive *directive, + char name[MAX_LEX_LENGTH]) +{ + directive->type = MIPS32_DIRECTIVE_SECTION; + strcpy(directive->name, name); + + return M_SUCCESS; } static int parse_directive(struct parser *parser, - union mips_directive *directive) + union mips_directive *directive) { - struct token token; - if (assert_token(parser, TOK_DIRECTIVE, &token)) - return M_ERROR; + struct token token; + if (assert_token(parser, TOK_DIRECTIVE, &token)) + return M_ERROR; - // .align n - if (strcmp(token.text, "align") == 0) - return parse_directive_align(parser, &directive->mips32); - else if (strcmp(token.text, "space") == 0) - return parse_directive_space(parser, &directive->mips32); - else if (strcmp(token.text, "word") == 0) - return parse_directive_whb(parser, &directive->mips32, - MIPS32_DIRECTIVE_WORD); - else if (strcmp(token.text, "half") == 0) - return parse_directive_whb(parser, &directive->mips32, - MIPS32_DIRECTIVE_HALF); - else if (strcmp(token.text, "byte") == 0) - return parse_directive_whb(parser, &directive->mips32, - MIPS32_DIRECTIVE_BYTE); - else - return parse_section(parser, &directive->mips32, token.text); + // .align n + if (strcmp(token.text, "align") == 0) + return parse_directive_align(parser, &directive->mips32); + else if (strcmp(token.text, "space") == 0) + return parse_directive_space(parser, &directive->mips32); + else if (strcmp(token.text, "word") == 0) + return parse_directive_whb(parser, &directive->mips32, + MIPS32_DIRECTIVE_WORD); + else if (strcmp(token.text, "half") == 0) + return parse_directive_whb(parser, &directive->mips32, + MIPS32_DIRECTIVE_HALF); + else if (strcmp(token.text, "byte") == 0) + return parse_directive_whb(parser, &directive->mips32, + MIPS32_DIRECTIVE_BYTE); + else if (strcmp(token.text, "extern") == 0) + return parse_directive_extern(parser, &directive->mips32); + else if (strcmp(token.text, "globl") == 0) + return parse_directive_globl(parser, &directive->mips32); + else + return parse_section(&directive->mips32, token.text); } -int mips32_parser_init(struct lexer *lexer, struct parser *parser) +void mips32_parser_init(struct parser *parser) { - if (parser_init(lexer, parser)) - return M_ERROR; - parser->parse_instruction = parse_instruction; - parser->is_instruction = is_instruction; - parser->parse_directive = parse_directive; - return M_SUCCESS; + parser->parse_instruction = parse_instruction; + parser->is_instruction = is_instruction; + parser->parse_directive = parse_directive; } void mips32_parser_free(struct parser *parser) { - parser_free(parser); + parser_free(parser); } diff --git a/masm/parse_mips32.h b/masm/parse_mips32.h index 6de154f..5262d68 100644 --- a/masm/parse_mips32.h +++ b/masm/parse_mips32.h @@ -5,8 +5,8 @@ #include "parse.h" -/* initzlize a mips32 parser*/ -int mips32_parser_init(struct lexer *lexer, struct parser *parser); +/* initzlize a mips32 parser vtable */ +void mips32_parser_init(struct parser *parser); /* free the mips32 parser */ void mips32_parser_free(struct parser *parser); diff --git a/masm/reftbl.c b/masm/reftbl.c index bdd1f07..198af83 100644 --- a/masm/reftbl.c +++ b/masm/reftbl.c @@ -12,13 +12,13 @@ int reftbl_init(struct reference_table *ref_tbl) { ref_tbl->len = RELTBL_INIT_LEN; ref_tbl->count = 0; - ref_tbl->references = malloc(sizeof(struct reference) * + ref_tbl->references = malloc(sizeof(struct reference) * RELTBL_INIT_LEN); - if (ref_tbl->references == NULL) { - ERROR("cannot alloc"); - return M_ERROR; - } + if (ref_tbl->references == NULL) { + ERROR("cannot alloc"); + return M_ERROR; + } return M_SUCCESS; } diff --git a/masm/sectbl.c b/masm/sectbl.c index f568a6f..6eafc60 100644 --- a/masm/sectbl.c +++ b/masm/sectbl.c @@ -13,13 +13,12 @@ int sectbl_init(struct section_table *sec_tbl) { sec_tbl->len = SECTBL_INIT_LEN; sec_tbl->count = 0; - sec_tbl->total_ins = 0; - sec_tbl->sections = malloc(sizeof(struct section) * SECTBL_INIT_LEN); + sec_tbl->sections = malloc(sizeof(struct section) * SECTBL_INIT_LEN); - if (sec_tbl->sections == NULL) { - ERROR("cannot alloc"); - return M_ERROR; - } + if (sec_tbl->sections == NULL) { + ERROR("cannot alloc"); + return M_ERROR; + } if (sectbl_alloc(sec_tbl, &sec_tbl->current, inital_section)) return M_ERROR; @@ -30,11 +29,26 @@ int sectbl_init(struct section_table *sec_tbl) void sectbl_free(struct section_table *sec_tbl) { for (uint32_t i = 0; i < sec_tbl->count; i++) { - free(sec_tbl->sections[i].ins); + free(sec_tbl->sections[i].entries); } free(sec_tbl->sections); } +struct section_settings { + const char *name; + bool read; + bool write; + bool execute; + uint32_t align; +}; + +static struct section_settings default_section_settings[] = { + {"data", true, true, false, 1}, + {"bss", true, true, false, 1}, + {"rodata", true, false, false, 1}, + {"text", true, false, true, 4}, +}; + int sectbl_alloc(struct section_table *sec_tbl, struct section **sec, const char name[MAX_LEX_LENGTH]) { @@ -50,50 +64,46 @@ int sectbl_alloc(struct section_table *sec_tbl, struct section **sec, } struct section *temp; - temp = &sec_tbl->sections[sec_tbl->count++]; + temp = &sec_tbl->sections[sec_tbl->count]; strcpy(temp->name,name); temp->count = 0; temp->len = SECTBL_INIT_LEN; - temp->start = sec_tbl->total_ins; temp->alignment = 1; - temp->ins = malloc(sizeof(union mips_instruction) * SECTBL_INIT_LEN); + temp->read = true; + temp->write = true; + temp->execute = false; + temp->index = sec_tbl->count; + temp->entries = malloc(sizeof(struct section_entry) * SECTBL_INIT_LEN); - if (temp->ins == NULL) { + for (int i = 0; i < 4; i++) { + struct section_settings *set = &default_section_settings[i]; + if (strcmp(set->name, name) == 0) { + temp->read = set->read; + temp->write = set->write; + temp->execute = set->execute; + temp->alignment = set->align; + break; + } + } + + if (temp->entries == NULL) { ERROR("cannot alloc"); return M_ERROR; } + sec_tbl->count++; + *sec = temp; return M_SUCCESS; } -int sectbl_push(struct section_table *sec_tbl, struct section *section, - union mips_instruction ins) -{ - if (section->count >= section->len) { - section->len *= 2; - section->ins = realloc(section->ins, - sizeof(union mips_instruction) * section->len); - - if (section->ins == NULL) { - ERROR("cannot realloc"); - return M_ERROR; - } - } - - section->ins[section->count++] = ins; - sec_tbl->total_ins++; - - return M_SUCCESS; -} - int sectbl_get(struct section_table *sec_tbl, struct section **sec, const char name[MAX_LEX_LENGTH]) { for (uint32_t i = 0; i < sec_tbl->count; i++) { struct section *temp = &sec_tbl->sections[i]; if (strcmp(name, temp->name) == 0) { - if (sec != NULL) + if (sec != NULL) *sec = temp; return M_SUCCESS; } @@ -101,3 +111,49 @@ int sectbl_get(struct section_table *sec_tbl, struct section **sec, return M_ERROR; } + +int sec_push(struct section *section, struct section_entry entry) +{ + if (section->count >= section->len) { + section->len *= 2; + void *new = realloc(section->entries, + sizeof(struct section_entry) * section->len); + + if (new == NULL) { + ERROR("cannot realloc"); + return M_ERROR; + } + + section->entries = new; + } + + section->entries[section->count++] = entry; + + return M_SUCCESS; +} + +size_t sec_size(struct section *sec) +{ + size_t n = 0; + for (uint32_t i = 0; i < sec->count; i++) { + size_t t = sec->entries[i].size; + size_t m = t % sec->alignment; + if (m) + t += sec->alignment - m; + n += t; + } + return n; +} + +size_t sec_index(struct section *sec, uint32_t idx) +{ + size_t n = 0; + for (uint32_t i = 0; i < idx; i++) { + size_t t = sec->entries[i].size; + size_t m = t % sec->alignment; + if (m) + t += sec->alignment - m; + n += t; + } + return n; +} diff --git a/masm/strtbl.c b/masm/strtbl.c index b01bb92..7bdbbea 100644 --- a/masm/strtbl.c +++ b/masm/strtbl.c @@ -6,44 +6,49 @@ int strtbl_get_str(struct str_table *str_tbl, const char *str, size_t *res) { - for (size_t i = 0; i < str_tbl->size; i ++) { - if (strcmp(str_tbl->ptr + i, str) == 0) { - if (res != NULL) - *res = i; - return M_SUCCESS; - } - } + for (size_t i = 0; i < str_tbl->size; i ++) { + if (strcmp(str_tbl->ptr + i, str) == 0) { + if (res != NULL) + *res = i; + return M_SUCCESS; + } + } - return M_ERROR; + return M_ERROR; } int strtbl_write_str(struct str_table *str_tbl, const char *str, size_t *res) { - if (strtbl_get_str(str_tbl, str, res) == M_SUCCESS) - return M_SUCCESS; + if (strtbl_get_str(str_tbl, str, res) == M_SUCCESS) + return M_SUCCESS; - size_t len = strlen(str); - char *new = realloc(str_tbl->ptr, str_tbl->size + len + 1); - if (new == NULL) - return M_ERROR; - str_tbl->ptr = new; - memcpy(str_tbl->ptr + str_tbl->size, str, len + 1); + size_t len = strlen(str); + char *new = realloc(str_tbl->ptr, str_tbl->size + len + 1); + if (new == NULL) + return M_ERROR; + str_tbl->ptr = new; + memcpy(str_tbl->ptr + str_tbl->size, str, len + 1); - if (res != NULL) - *res = str_tbl->size; + if (res != NULL) + *res = str_tbl->size; - str_tbl->size += len + 1; - return M_SUCCESS; + str_tbl->size += len + 1; + return M_SUCCESS; } -void strtbl_init(struct str_table *str_tbl) +int strtbl_init(struct str_table *str_tbl) { - str_tbl->size = 1; - str_tbl->ptr = malloc(1); - *str_tbl->ptr = '\0'; + str_tbl->size = 1; + str_tbl->ptr = malloc(1); + if (str_tbl->ptr == NULL) { + ERROR("cannot alloc"); + return M_ERROR; + } + *str_tbl->ptr = '\0'; + return M_SUCCESS; } void strtbl_free(struct str_table *str_tbl) { - free(str_tbl->ptr); + free(str_tbl->ptr); } diff --git a/masm/test.asm b/masm/test.asm index c3b61fb..1820b62 100644 --- a/masm/test.asm +++ b/masm/test.asm @@ -1,6 +1,9 @@ .text .align 2 +.globl main +.extern test2 + main: add $zero,$t7,$t7 xori $a0, $v1, 69 @@ -19,4 +22,4 @@ test: mfhi $s0 mtlo $s7 - j test + j test2