summaryrefslogtreecommitdiff
path: root/masm/asm.c
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-10-04 19:41:10 -0400
committerFreya Murphy <freya@freyacat.org>2024-10-04 19:41:10 -0400
commit1c11a13ff33873bcc79d4597d31cd252d5c6c1ae (patch)
treea4321b97f5ad69d1a9b9d06dd629a4dc532758b0 /masm/asm.c
parentupdate msim usage (diff)
downloadmips-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.c645
1 files changed, 222 insertions, 423 deletions
diff --git a/masm/asm.c b/masm/asm.c
index 328ae16..619f9e5 100644
--- a/masm/asm.c
+++ b/masm/asm.c
@@ -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 = &sections[i];
+ if (elf_section_init(&sections[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);
}