diff options
author | Freya Murphy <freya@freyacat.org> | 2024-10-04 19:41:10 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2024-10-04 19:41:10 -0400 |
commit | 1c11a13ff33873bcc79d4597d31cd252d5c6c1ae (patch) | |
tree | a4321b97f5ad69d1a9b9d06dd629a4dc532758b0 /masm/asm.c | |
parent | update msim usage (diff) | |
download | mips-1c11a13ff33873bcc79d4597d31cd252d5c6c1ae.tar.gz mips-1c11a13ff33873bcc79d4597d31cd252d5c6c1ae.tar.bz2 mips-1c11a13ff33873bcc79d4597d31cd252d5c6c1ae.zip |
refactor masm to add codegen step
Diffstat (limited to 'masm/asm.c')
-rw-r--r-- | masm/asm.c | 645 |
1 files changed, 222 insertions, 423 deletions
@@ -1,5 +1,4 @@ #include <merror.h> -#include <mips.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> @@ -9,8 +8,9 @@ #include <melf.h> #include "asm.h" +#include "gen.h" #include "mlimits.h" -#include "parse.h" +#include "tab.h" extern char *current_file; @@ -19,325 +19,158 @@ extern char *current_file; #define SEC_ALIGN 0x1000 -static int create_symbol(struct assembler *assembler, - const char name[MAX_LEX_LENGTH], - ssize_t section_idx, - size_t section_offset, - unsigned char bind) -{ - size_t str_off; - if (strtab_write_str(&assembler->strtab, name, &str_off)) - return M_ERROR; +static int elf_rel_type(enum reference_type ty) { + switch (ty) { + case REF_NONE: + return R_MIPS_NONE; + case REF_MIPS_16: + return R_MIPS_16; + case REF_MIPS_26: + return R_MIPS_26; + case REF_MIPS_PC16: + return R_MIPS_PC16; + case REF_MIPS_LO16: + return R_MIPS_LO16; + case REF_MIPS_HI16: + return R_MIPS_HI16; + } - Elf32_Sym symbol = { - .st_name = B32(str_off), - .st_value = B32(section_offset), - .st_size = 0, - .st_info = ELF32_ST_INFO(bind, STT_NOTYPE), - .st_other = ELF32_ST_VISIBILITY(STV_DEFAULT), - .st_shndx = B16(section_idx), - }; + return R_MIPS_NONE; +} - // dont put magic flag values inside symbol, only real indexes - if (section_idx < 0) - symbol.st_shndx = 0; +static int elf_section_init_reltab(struct section *sec, + struct elf_section *elf_sec) +{ + Elf32_Rel *reltab = malloc(sizeof(Elf32_Rel) * + sec->reftab.len); - if (symtab_push(&assembler->symtab, symbol, section_idx)) + if (reltab == NULL) { + PERROR("cannot alloc"); return M_ERROR; + } + for (uint32_t i = 0; i < sec->reftab.len; i++) { + Elf32_Rel *rel = &reltab[i]; + struct reference *ref = &sec->reftab.references[i]; + rel->r_offset = B32(ref->offset); + int sym = ref->symbol->tabidx + 1; + int type = elf_rel_type(ref->type); + rel->r_info = B32(ELF32_R_INFO(sym, type)); + } + + elf_sec->reltab_len = sec->reftab.len; + elf_sec->reltab = reltab; return M_SUCCESS; } -static int find_symbol_or_stub(struct assembler *assembler, - const char name[MAX_LEX_LENGTH], - Elf32_Sym **res, - size_t *res2) +static int elf_section_init(struct section *sec, struct elf_section *elf_sec) { - if (symtab_find(&assembler->symtab, res, res2, name) == M_SUCCESS) - return M_SUCCESS; + elf_sec->data = sec; + elf_sec->shdr_idx = 0; // dont know yet + elf_sec->reltab_shidx = 0; // dont know yet + elf_sec->reltab_len = sec->reftab.len; + elf_sec->reltab = NULL; - if (create_symbol(assembler, name, SYMSEC_STUB, 0, STB_LOCAL)) + if (sec->reftab.len && elf_section_init_reltab(sec, elf_sec)) return M_ERROR; - size_t idx = assembler->symtab.len - 1; - - if (res != NULL) - *res = &assembler->symtab.symbols[idx]; - if (res2 != NULL) - *res2 = idx; - return M_SUCCESS; } -static int handle_directive(struct assembler *assembler, - struct mips_directive *directive) +/* free an elf section */ +static void elf_section_free(struct elf_section *sec) { - switch (directive->type) { - case MIPS_DIRECTIVE_SECTION: { - struct section_table *sec_tbl = &assembler->sectab; - struct section *sec; - if (sectab_get(sec_tbl, &sec, directive->name) - == M_SUCCESS) { - sec_tbl->current = sec; - break; - } - - if (sectab_alloc(sec_tbl, &sec, directive->name)) - return M_ERROR; - - sec_tbl->current = sec; - break; - } - - case MIPS_DIRECTIVE_ALIGN: { - assembler->sectab.current->alignment = - 1 << directive->align; - if (assembler->sectab.current->alignment == 0) { - ERROR("cannot align to zero"); - return M_ERROR; - } - break; - } - - case MIPS_DIRECTIVE_SPACE: { - struct section_entry entry; - entry.type = ENT_NO_DATA; - entry.size = directive->space; - if (sec_push(assembler->sectab.current, entry)) - return M_ERROR; - break; - } - - case MIPS_DIRECTIVE_WORD: { - for (uint32_t i = 0; i < directive->len; i++) { - struct section_entry entry; - entry.type = ENT_WORD; - entry.word = directive->words[i]; - entry.size = sizeof(uint32_t); - if (sec_push(assembler->sectab.current, - entry)) - return M_ERROR; - } - break; - } + if (sec->reltab != NULL) + free(sec->reltab); +} - case MIPS_DIRECTIVE_HALF: { - for (uint32_t i = 0; i < directive->len; i++) { - struct section_entry entry; - entry.type = ENT_HALF; - entry.half = directive->halfs[i]; - entry.size = sizeof(uint16_t); - if (sec_push(assembler->sectab.current, - entry)) - return M_ERROR; - } - break; - } +static int asm_init_sections(struct assembler *assembler) +{ + struct section *sections = assembler->gen.sections; + uint32_t len = assembler->gen.sections_len; - case MIPS_DIRECTIVE_BYTE: { - for (uint32_t i = 0; i < directive->len; i++) { - struct section_entry entry; - entry.type = ENT_BYTE; - entry.byte = directive->bytes[i]; - entry.size = sizeof(uint8_t); - if (sec_push(assembler->sectab.current, - entry)) - return M_ERROR; - } - break; + struct elf_section *elftab = malloc(sizeof(struct elf_section) * len); + if (elftab == NULL) { + PERROR("cannot alloc"); + return M_ERROR; } - case MIPS_DIRECTIVE_EXTERN: { - if (symtab_find(&assembler->symtab, NULL, NULL, - directive->name) == M_SUCCESS) { - ERROR("cannot extern local symbol '%s'", - directive->name); + for (uint32_t i = 0; i < len; i++) { + struct elf_section *elfsec = &elftab[i]; + elfsec->data = §ions[i]; + if (elf_section_init(§ions[i], elfsec)) { + free(elftab); return M_ERROR; } - - if (create_symbol(assembler, directive->name, SYMSEC_EXTERN, 0, - STB_GLOBAL)) - return M_ERROR; - - break; - } - - case MIPS_DIRECTIVE_GLOBL: { - Elf32_Sym *sym; - if (symtab_find(&assembler->symtab, &sym, NULL, - directive->name) == M_SUCCESS) { - sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE); - break; - } - - if (create_symbol(assembler, directive->name, SYMSEC_STUB, 0, - STB_GLOBAL)) - return M_ERROR; - - break; } - case MIPS_DIRECTIVE_ASCII: { - struct section_entry entry; - entry.type = ENT_STR; - entry.size = strlen(directive->name); - memcpy(entry.str, directive->name, entry.size); - if (sec_push(assembler->sectab.current, entry)) - return M_ERROR; - break; - } - - case MIPS_DIRECTIVE_ASCIIZ: { - struct section_entry entry; - entry.type = ENT_STR; - entry.size = strlen(directive->name) + 1; - memcpy(entry.str, directive->name, entry.size); - if (sec_push(assembler->sectab.current, entry)) - return M_ERROR; - break; - } - } - - return M_SUCCESS; + assembler->sections = elftab; + assembler->section_len = len; + return M_SUCCESS; } -static int handle_label(struct assembler *assembler, - const char name[MAX_LEX_LENGTH]) -{ - struct section *cur = assembler->sectab.current; - - Elf32_Sym *ref; - size_t symidx; - - if (symtab_find(&assembler->symtab, &ref, &symidx, name) == M_SUCCESS) { - ssize_t *sec = &assembler->symtab.sections[symidx]; - - // check if the symbol is acutally jus a stub, if so - // we need to update it - if (*sec == SYMSEC_STUB) { - *sec = cur->index; - ref->st_value = B32(sec_size(cur)); - return M_SUCCESS; - } - - ERROR("redefined symbol '%s'", name); - return M_ERROR; +static int elf_sym_bind(enum symbol_type ty) { + switch (ty) { + case SYM_LOCAL: + return STB_LOCAL; + case SYM_GLOBAL: + return STB_GLOBAL; + case SYM_EXTERN: + return STB_GLOBAL; } - if (create_symbol(assembler, name, cur->index, sec_size(cur), - STB_LOCAL)) - return M_ERROR; - - return M_SUCCESS; + return STB_GLOBAL; } -static int handle_ins(struct assembler *assembler, - struct ins_expr *expr) -{ - struct section *sec = assembler->sectab.current; - size_t secidx = sec->len; - - for (size_t i = 0; i < expr->ins_len; i++) { - union mips_instruction_data *ins = - &expr->ins[i].data; - struct reference *ref = - &expr->ref[i]; - struct section_entry entry; - - entry.type = ENT_INS; - entry.size = sizeof(union mips_instruction_data); - entry.ins = B32(ins->raw); +static int asm_init_symtab(struct assembler *assembler) { + struct symbol_table *symtab = &assembler->gen.symtab; + size_t len = symtab->len + 1; + Elf32_Sym *elftab = malloc(sizeof(Elf32_Sym) * len); + if (elftab == NULL) { + PERROR("cannot alloc"); + } - if (sec_push(sec, entry)) - return M_ERROR; + // add null entry + elftab[0] = (Elf32_Sym) {0}; - if (ref->type == R_MIPS_NONE) - continue; + // add rest of the entries + for (uint32_t i = 0; i < symtab->len; i++) { + struct symbol *sym = &symtab->symbols[i]; + int bind = elf_sym_bind(sym->type); + int type = STT_NOTYPE; - size_t symidx; - if (find_symbol_or_stub(assembler, ref->name, NULL, &symidx)) + // get name + size_t str_off; + if (strtab_write_str(&assembler->strtab, sym->name.str, + &str_off)) { + free(elftab); return M_ERROR; + } - Elf32_Rela rel = { - .r_info = B32(ELF32_R_INFO(symidx, ref->type)), - .r_addend = B32(ref->addend), - .r_offset = B32(sec_index(sec, secidx + i)), + elftab[i+1] = (Elf32_Sym) { + .st_name = B32(str_off), + .st_info = ELF32_ST_INFO(bind, type), + .st_size = 0, + .st_other = 0, + .st_value = B32(sym->offset), + .st_shndx = 0, }; - - if (reltab_push(&sec->reltab, rel)) - return M_ERROR; } - return M_SUCCESS; -} - -static int parse_file(struct assembler *assembler) -{ - struct parser *parser = &assembler->parser; - - while (1) { - struct expr expr; - int res = parser_next(parser, &expr); - - if (res == M_ERROR) - return M_ERROR; - - if (res == M_EOF) - return M_SUCCESS; - - switch (expr.type) { - case EXPR_INS: - if (handle_ins(assembler, &expr.ins)) - return M_ERROR; - break; - case EXPR_DIRECTIVE: - if (handle_directive(assembler, - &expr.directive)) - return M_ERROR; - break; - - case EXPR_LABEL: - if (handle_label(assembler, expr.label)) - return M_ERROR; - break; - - case EXPR_CONSTANT: - break; - } - } + assembler->symbols = elftab; + assembler->symtab_len = len; return M_SUCCESS; } -static int assemble_phdr(struct assembler *assembler, Elf32_Phdr **res, - uint32_t *res2) +static int parse_file(struct assembler *assembler) { - Elf32_Phdr *phdr = malloc(sizeof(Elf32_Phdr) * - assembler->sectab.len); - if (phdr == NULL) { - PERROR("cannot alloc"); - return M_ERROR;; - } - - for (uint32_t i = 0; i < assembler->sectab.len; i++) { - Elf32_Phdr *hdr = &phdr[i]; - struct section *sec = &assembler->sectab.sections[i]; - size_t size = sec_size(sec); - hdr->p_type = B32(PT_LOAD); - hdr->p_flags = B32( - (sec->execute << 0) | - (sec->write << 1) | - (sec->read << 2)); - hdr->p_offset = 0; - hdr->p_vaddr = 0; - hdr->p_paddr = 0; - hdr->p_filesz = B32(size); - hdr->p_memsz = B32(size); - hdr->p_align = B32(SEC_ALIGN); - } - - *res = phdr; - *res2 = assembler->sectab.len; + if (generate_mips32r6(&assembler->gen)) + return M_ERROR; + if (asm_init_sections(assembler)) + return M_ERROR; + if (asm_init_symtab(assembler)) + return M_ERROR; return M_SUCCESS; } @@ -349,8 +182,8 @@ static int assemble_shdr(struct assembler *assembler, Elf32_Shdr **res, max_entries += 1; // symtab max_entries += 1; // strtab max_entries += 1; // shtrtab - max_entries += assembler->sectab.len; // sections - max_entries += assembler->sectab.len; // reltabs per section + max_entries += assembler->section_len; // sections + max_entries += assembler->section_len; // reltabs per section Elf32_Shdr *shdr = malloc(sizeof(Elf32_Shdr) * max_entries); @@ -366,16 +199,17 @@ static int assemble_shdr(struct assembler *assembler, Elf32_Shdr **res, shdr[count++] = (Elf32_Shdr) {0}; // reltables - for (uint32_t i = 0; i < assembler->sectab.len; i++) { - struct section *sec = &assembler->sectab.sections[i]; - const char *prefix = ".reltab."; - char reltab_name[MAX_LEX_LENGTH + 8]; + for (uint32_t i = 0; i < assembler->section_len; i++) { + struct elf_section *sec = &assembler->sections[i]; + const char *prefix = ".reltab"; + char reltab_name[MAX_LEX_LENGTH + strlen(prefix)]; - if (sec->reltab.len == 0) + if (sec->reltab_len == 0) continue; strcpy(reltab_name, prefix); - strcat(reltab_name, sec->name); + strncat(reltab_name, sec->data->name.str, + MAX_LEX_LENGTH - strlen(prefix)); if (strtab_write_str(&assembler->shstrtab, reltab_name, &str_off)) { @@ -386,7 +220,7 @@ static int assemble_shdr(struct assembler *assembler, Elf32_Shdr **res, sec->reltab_shidx = count; shdr[count++] = (Elf32_Shdr) { .sh_name = B32(str_off), - .sh_type = B32(SHT_RELA), + .sh_type = B32(SHT_REL), .sh_flags = 0, .sh_addr = 0, .sh_offset = 0, @@ -394,41 +228,41 @@ static int assemble_shdr(struct assembler *assembler, Elf32_Shdr **res, .sh_link = 0, .sh_info = 0, .sh_addralign = B32(1), - .sh_entsize = B32(sizeof(Elf32_Rela)), + .sh_entsize = B32(sizeof(Elf32_Rel)), }; } // for each section - for (uint32_t i = 0; i < assembler->sectab.len; i++) { - struct section *sec = &assembler->sectab.sections[i]; - char name[MAX_LEX_LENGTH+1] = "."; + for (uint32_t i = 0; i < assembler->section_len; i++) { + struct elf_section *sec = &assembler->sections[i]; + const char *name = sec->data->name.str; - strcat(name, sec->name); if (strtab_write_str(&assembler->shstrtab, name, &str_off)) { free(shdr); return M_ERROR; } sec->shdr_idx = count; - if (sec->reltab.len != 0) + if (sec->reltab_len != 0) shdr[sec->reltab_shidx].sh_info = B32(count); - shdr[count++] = (Elf32_Shdr){ - .sh_name = B32(str_off), - .sh_type = B32(SHT_PROGBITS), - .sh_flags = B32( - (sec->write << 0) | - (sec->execute << 2) | + shdr[count++] = (Elf32_Shdr){ + .sh_name = B32(str_off), + .sh_type = B32(sec->data->execute ? + SHT_PROGBITS : SHT_NOBITS), + .sh_flags = B32( + (sec->data->write << 0) | + (sec->data->execute << 2) | SHF_ALLOC), - .sh_addr = 0, - .sh_offset = 0, - .sh_size = 0, - .sh_link = 0, - .sh_info = 0, - .sh_addralign = B32(sec->alignment), - .sh_entsize = 0, - }; - } + .sh_addr = 0, + .sh_offset = 0, + .sh_size = 0, + .sh_link = 0, + .sh_info = 0, + .sh_addralign = B32(SEC_ALIGN), + .sh_entsize = 0, + }; + } // symbol table if (strtab_write_str(&assembler->shstrtab, ".symtab", &str_off)) { @@ -490,9 +324,9 @@ static int assemble_shdr(struct assembler *assembler, Elf32_Shdr **res, .sh_entsize = 0, }; - for (uint32_t i = 0; i < assembler->sectab.len; i++) { - struct section *sec = &assembler->sectab.sections[i]; - if (sec->reltab.len == 0) + for (uint32_t i = 0; i < assembler->section_len; i++) { + struct elf_section *sec = &assembler->sections[i]; + if (sec->reltab_len == 0) continue; shdr[sec->reltab_shidx].sh_link = B32(assembler->symtab_shidx); @@ -507,61 +341,53 @@ static int assemble_shdr(struct assembler *assembler, Elf32_Shdr **res, static void update_offsets(struct assembler *assembler, Elf32_Ehdr *ehdr) { Elf32_Shdr *shdr = (Elf32_Shdr *) assembler->shdr; - Elf32_Phdr *phdr = (Elf32_Phdr *) assembler->phdr; uint32_t ptr = 0; // we must now correct offets and sizes inside the ehdr, phdr, // and shdr ptr += sizeof(Elf32_Ehdr); - // phdr - ehdr->e_phoff = B32(ptr); - ptr += assembler->phdr_len * sizeof(Elf32_Phdr); - // reltbls - for (uint32_t i = 0; i < assembler->sectab.len; i++) { - struct section *sec = &assembler->sectab.sections[i]; - if (sec->reltab.len == 0) + for (uint32_t i = 0; i < assembler->section_len; i++) { + struct elf_section *sec = &assembler->sections[i]; + if (sec->reltab_len == 0) continue; int idx = sec->reltab_shidx; - int len = sec->reltab.len; + int len = sec->reltab_len; shdr[idx].sh_offset = B32(ptr); - shdr[idx].sh_size = B32(len * sizeof(Elf32_Rela)); - ptr += len * sizeof(Elf32_Rela); - } - - // section padding - { - uint32_t mod = ptr % SEC_ALIGN; - if (mod != 0) - assembler->secalign = (SEC_ALIGN - mod); - else - assembler->secalign = 0; - ptr += assembler->secalign; + shdr[idx].sh_size = B32(len * sizeof(Elf32_Rel)); + ptr += len * sizeof(Elf32_Rel); } // sections size_t v_addr = 0; - for (uint32_t i = 0; i < assembler->sectab.len; i++) { - struct section *sec = &assembler->sectab.sections[i]; + for (uint32_t i = 0; i < assembler->section_len; i++) { + + size_t pad = v_addr % SEC_ALIGN; + if (pad) + pad = SEC_ALIGN - pad; + v_addr += pad; + + struct elf_section *sec = &assembler->sections[i]; uint32_t idx = sec->shdr_idx; - uint32_t size = ntohl(phdr[i].p_filesz); - phdr[i].p_offset = B32(ptr); - phdr[i].p_vaddr = B32(v_addr); - phdr[i].p_paddr = B32(v_addr); + uint32_t size = sec->data->len; shdr[idx].sh_offset = B32(ptr); - shdr[idx].sh_size = phdr[i].p_filesz; - shdr[idx].sh_addr = phdr[i].p_vaddr; + shdr[idx].sh_size = B32(size); + shdr[idx].sh_addr = B32(v_addr); v_addr += size; ptr += size; } // symtab - shdr[assembler->symtab_shidx].sh_offset = B32(ptr); - shdr[assembler->symtab_shidx].sh_link = B32(assembler->strtab_shidx); - shdr[assembler->symtab_shidx].sh_size = - B32(assembler->symtab.len * sizeof(Elf32_Sym)); - ptr += assembler->symtab.len * sizeof(Elf32_Sym); + { + uint32_t len = assembler->symtab_len; + uint32_t size = len * sizeof(Elf32_Sym); + shdr[assembler->symtab_shidx].sh_offset = B32(ptr); + shdr[assembler->symtab_shidx].sh_link = + B32(assembler->strtab_shidx); + shdr[assembler->symtab_shidx].sh_size = B32(size); + ptr += size; + } // strtab shdr[assembler->strtab_shidx].sh_offset = B32(ptr); @@ -573,24 +399,10 @@ static void update_offsets(struct assembler *assembler, Elf32_Ehdr *ehdr) shdr[assembler->shstrtab_shidx].sh_size = B32(assembler->shstrtab.size); ptr += assembler->shstrtab.size; - // shdr ehdr->e_shoff = B32(ptr); } -static void update_sym_shindx(struct assembler *assembler) -{ - for (size_t i = 0; i < assembler->symtab.len; i++) { - Elf32_Sym *sym = &assembler->symtab.symbols[i]; - ssize_t sec = assembler->symtab.sections[i]; - - if (sec >= 0) { - sym->st_shndx = B16(assembler-> - sectab.sections[sec].shdr_idx); - } - } -} - static int write_file(struct assembler *assembler, Elf32_Ehdr *ehdr, const char *path) { @@ -605,80 +417,70 @@ static int write_file(struct assembler *assembler, Elf32_Ehdr *ehdr, // ehdr fwrite(ehdr, sizeof(Elf32_Ehdr), 1, out); - // phdr - fwrite(assembler->phdr, sizeof(Elf32_Phdr), assembler->phdr_len, out); - // reltbls - for (uint32_t i = 0; i < assembler->sectab.len; i++) { - struct section *sec = &assembler->sectab.sections[i]; - if (sec->reltab.len == 0) + for (uint32_t i = 0; i < assembler->section_len; i++) { + struct elf_section *sec = &assembler->sections[i]; + void *ptr = sec->reltab; + int len = sec->reltab_len; + if (len < 1) continue; - void *ptr = sec->reltab.data; - int len = sec->reltab.len; - fwrite(ptr, sizeof(Elf32_Rela), len, out); - } - - // section padding - for (uint32_t i = 0; i < assembler->secalign; i++) { - uint8_t zero = 0; - fwrite(&zero, 1, 1, out); + fwrite(ptr, sizeof(Elf32_Rel), len, out); } // sections - for (uint32_t i = 0; i < assembler->sectab.len; i++) { - struct section *sec = &assembler->sectab.sections[i]; - for (uint32_t j = 0; j < sec->len; j++) { - struct section_entry *entry = &sec->entries[j]; - size_t size = entry->size; - size_t zeros = size % sec->alignment;; - if (entry->type != ENT_NO_DATA) - fwrite(&entry->data, size, 1, out); - else - zeros += size; - while(zeros) { - fputc(0, out); - zeros--; - } - } + for (uint32_t i = 0; i < assembler->section_len; i++) { + struct elf_section *sec = &assembler->sections[i]; + void *ptr = sec->data->data; + size_t size = sec->data->len; + fwrite(ptr, 1, size, out); } // sym tbl - fwrite(assembler->symtab.symbols, sizeof(Elf32_Sym), - assembler->symtab.len, out); + fwrite(assembler->symbols, sizeof(Elf32_Sym), assembler->symtab_len, + out); // str tbl - fwrite(assembler->strtab.ptr, assembler->strtab.size, 1, out); + fwrite(assembler->strtab.ptr, 1, assembler->strtab.size, out); // shstr tbl - fwrite(assembler->shstrtab.ptr, assembler->shstrtab.size, 1, out); + fwrite(assembler->shstrtab.ptr, 1, assembler->shstrtab.size, out); // shdr fwrite(assembler->shdr, sizeof(Elf32_Shdr), assembler->shdr_len, out); + // close fclose(out); return M_SUCCESS; } -static int assemble_elf(struct assembler *assembler, const char *out) +static void update_sym_shndx(struct assembler *assembler) { - if (assemble_phdr(assembler, (Elf32_Phdr **) &assembler->phdr, - &assembler->phdr_len)) { - return M_ERROR; + for (uint32_t i = 1; i < assembler->symtab_len; i++) { + Elf32_Sym *esym = &assembler->symbols[i]; + struct symbol *sym = &assembler->gen.symtab.symbols[i - 1]; + + // get shindx + int shindx = 0; + if (sym->secidx != SYM_SEC_STUB) + shindx = assembler->sections[sym->secidx].shdr_idx; + else if (sym->type == SYM_EXTERN) + shindx = 0; + + esym->st_shndx = B16(shindx); } +} - if (assemble_shdr(assembler, (Elf32_Shdr **) &assembler->shdr, - &assembler->shdr_len)) { +static int assemble_elf(struct assembler *assembler, const char *out) +{ + if (assemble_shdr(assembler, &assembler->shdr, &assembler->shdr_len)) return M_ERROR; - }; Elf32_Ehdr ehdr = MIPS_ELF_EHDR; - ehdr.e_phnum = B16(assembler->phdr_len); ehdr.e_shnum = B16(assembler->shdr_len); ehdr.e_shstrndx = B16(assembler->shstrtab_shidx); - update_offsets(assembler, &ehdr); - update_sym_shindx(assembler); + update_sym_shndx(assembler); if (write_file(assembler, &ehdr, out)) return M_ERROR; @@ -709,10 +511,16 @@ int assemble_file(struct assembler_arguments args) int assembler_init(struct assembler *assembler, const char *path) { - if (lexer_init(path, &assembler->lexer)) - return M_ERROR; + assembler->shdr = NULL; + assembler->symbols = NULL; + assembler->sections = NULL; + assembler->strtab.ptr = NULL; + assembler->shstrtab.ptr = NULL; + assembler->gen.sections = NULL; + assembler->gen.symtab.symbols = NULL; + assembler->section_len = 0; - if (parser_init(&assembler->lexer, &assembler->parser)) + if (generator_init(path, &assembler->gen)) return M_ERROR; if (strtab_init(&assembler->shstrtab)) @@ -721,31 +529,22 @@ int assembler_init(struct assembler *assembler, const char *path) if (strtab_init(&assembler->strtab)) return M_ERROR; - if (symtab_init(&assembler->symtab)) - return M_ERROR; - - if (sectab_init(&assembler->sectab)) - return M_ERROR; - - assembler->symtab.strtab = &assembler->strtab; - assembler->phdr = NULL; - assembler->shdr = NULL; - return M_SUCCESS; } void assembler_free(struct assembler *assembler) { - if (assembler->phdr) - free(assembler->phdr); if (assembler->shdr) free(assembler->shdr); + if (assembler->symbols) + free(assembler->symbols); + if (assembler->sections) { + for (uint32_t i = 0; i < assembler->section_len; i++) + elf_section_free(&assembler->sections[i]); + free(assembler->sections); + } - sectab_free(&assembler->sectab); - symtab_free(&assembler->symtab); strtab_free(&assembler->strtab); strtab_free(&assembler->shstrtab); - - parser_free(&assembler->parser); - lexer_free(&assembler->lexer); + generator_free(&assembler->gen); } |