diff options
Diffstat (limited to '')
| -rw-r--r-- | masm/asm/elf32.c (renamed from masm/asm.c) | 132 |
1 files changed, 75 insertions, 57 deletions
diff --git a/masm/asm.c b/masm/asm/elf32.c index 8cbc439..e454273 100644 --- a/masm/asm.c +++ b/masm/asm/elf32.c @@ -1,15 +1,11 @@ #include <merror.h> -#include <netinet/in.h> -#include <stdio.h> #include <stdlib.h> #include <elf.h> -#include <string.h> -#include <stddef.h> #include <melf.h> -#include "asm.h" -#include "gen.h" -#include "tab.h" +#include "../tab.h" +#include "../masm.h" +#include "elf32.h" extern char *current_file; @@ -83,10 +79,10 @@ static void elf_section_free(struct elf_section *sec) free(sec->reltab); } -static int asm_init_sections(struct assembler *assembler) +static int asm_init_sections(struct elf_assembler *assembler) { - struct section *sections = assembler->gen.sections; - uint32_t len = assembler->gen.sections_len; + struct section *sections = assembler->gen->sections; + uint32_t len = assembler->gen->sections_len; struct elf_section *elftab = malloc(sizeof(struct elf_section) * len); if (elftab == NULL) { @@ -121,8 +117,8 @@ static int elf_sym_bind(enum symbol_type ty) { return STB_GLOBAL; } -static int asm_init_symtab(struct assembler *assembler) { - struct symbol_table *symtab = &assembler->gen.symtab; +static int asm_init_symtab(struct elf_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) { @@ -146,6 +142,17 @@ static int asm_init_symtab(struct assembler *assembler) { return M_ERROR; } + // check if symbol is undefined + if (sym->secidx == SYM_SEC_STUB) { + if (sym->type == SYM_LOCAL && + assembler->args->extern_undefined == false) { + ERROR("undefined symbol %s", sym->name.str); + return M_ERROR; + } + sym->secidx = 0; + bind = STB_GLOBAL; + } + elftab[i+1] = (Elf32_Sym) { .st_name = B32(str_off), .st_info = ELF32_ST_INFO(bind, type), @@ -162,18 +169,7 @@ static int asm_init_symtab(struct assembler *assembler) { return M_SUCCESS; } -static int parse_file(struct assembler *assembler) -{ - 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; -} - -static int assemble_shdr(struct assembler *assembler, Elf32_Shdr **res, +static int assemble_shdr(struct elf_assembler *assembler, Elf32_Shdr **res, uint32_t *res2) { uint32_t max_entries = 0; @@ -337,7 +333,7 @@ static int assemble_shdr(struct assembler *assembler, Elf32_Shdr **res, return M_SUCCESS; } -static void update_offsets(struct assembler *assembler, Elf32_Ehdr *ehdr) +static void update_offsets(struct elf_assembler *assembler, Elf32_Ehdr *ehdr) { Elf32_Shdr *shdr = (Elf32_Shdr *) assembler->shdr; uint32_t ptr = 0; @@ -402,7 +398,7 @@ static void update_offsets(struct assembler *assembler, Elf32_Ehdr *ehdr) ehdr->e_shoff = B32(ptr); } -static int write_file(struct assembler *assembler, Elf32_Ehdr *ehdr, +static int write_file(struct elf_assembler *assembler, Elf32_Ehdr *ehdr, const char *path) { FILE *out = fopen(path, "w"); @@ -453,11 +449,11 @@ static int write_file(struct assembler *assembler, Elf32_Ehdr *ehdr, return M_SUCCESS; } -static void update_sym_shndx(struct assembler *assembler) +static void update_sym_shndx(struct elf_assembler *assembler) { 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]; + struct symbol *sym = &assembler->gen->symtab.symbols[i - 1]; // get shindx int shindx = 0; @@ -470,14 +466,42 @@ static void update_sym_shndx(struct assembler *assembler) } } -static int assemble_elf(struct assembler *assembler, const char *out) +static int assemble_elf(struct elf_assembler *assembler, const char *out) { + if (asm_init_sections(assembler)) + return M_ERROR; + + if (asm_init_symtab(assembler)) + return M_ERROR; + if (assemble_shdr(assembler, &assembler->shdr, &assembler->shdr_len)) return M_ERROR; + // get ehdr flags + uint32_t flags = EF_MIPS_NAN2008; + switch (assembler->args->isa) { + case ISA_MIPS1: + flags |= EF_MIPS_ARCH_1; + break; + case ISA_MIPS32R2: + flags |= EF_MIPS_ARCH_32R2; + break; + case ISA_MIPS32R6: + flags |= EF_MIPS_ARCH_32R6; + break; + } + switch (assembler->args->abi) { + case ABI_O32: + flags |= EF_MIPS_ABI_O32; + break; + case ABI_NONE: + break; + } + Elf32_Ehdr ehdr = MIPS_ELF_EHDR; ehdr.e_shnum = B16(assembler->shdr_len); ehdr.e_shstrndx = B16(assembler->shstrtab_shidx); + ehdr.e_flags = B32(flags); update_offsets(assembler, &ehdr); update_sym_shndx(assembler); @@ -487,41 +511,20 @@ static int assemble_elf(struct assembler *assembler, const char *out) return M_SUCCESS; } -int assemble_file(struct assembler_arguments args) +static int assembler_init(struct elf_assembler *assembler, + struct generator *gen, + struct arguments *args) { - struct assembler assembler; - int res = M_SUCCESS; - - current_file = args.in_file; - - if (assembler_init(&assembler, args.in_file)) - return M_ERROR; - - if (res == M_SUCCESS) - res = parse_file(&assembler); - - if (res == M_SUCCESS) - res = assemble_elf(&assembler, args.out_file); + assembler->args = args; + assembler->gen = gen; - assembler_free(&assembler); - - return res; -} - -int assembler_init(struct assembler *assembler, const char *path) -{ 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 (generator_init(path, &assembler->gen)) - return M_ERROR; - if (strtab_init(&assembler->shstrtab)) return M_ERROR; @@ -531,7 +534,7 @@ int assembler_init(struct assembler *assembler, const char *path) return M_SUCCESS; } -void assembler_free(struct assembler *assembler) +static void assembler_free(struct elf_assembler *assembler) { if (assembler->shdr) free(assembler->shdr); @@ -545,5 +548,20 @@ void assembler_free(struct assembler *assembler) strtab_free(&assembler->strtab); strtab_free(&assembler->shstrtab); - generator_free(&assembler->gen); } + +int assemble_elf32(struct generator *gen, struct arguments *args) +{ + struct elf_assembler assembler; + int res = M_SUCCESS; + current_file = args->in_file; + + if (assembler_init(&assembler, gen, args)) + return M_ERROR; + + res = assemble_elf(&assembler, args->out_file); + assembler_free(&assembler); + + return res; +} + |