uh hi
This commit is contained in:
parent
2ed2758216
commit
6ec6d858b5
1 changed files with 0 additions and 363 deletions
363
masm/:
363
masm/:
|
@ -1,363 +0,0 @@
|
||||||
#include <merror.h>
|
|
||||||
#include <mips.h>
|
|
||||||
#include <mips32.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "asm.h"
|
|
||||||
#include "mlimits.h"
|
|
||||||
#include "parse.h"
|
|
||||||
#include "parse_mips32.h"
|
|
||||||
|
|
||||||
extern char *current_file;
|
|
||||||
|
|
||||||
#define SHDR_STRTBL 0
|
|
||||||
#define SHDR_SYMTBL 1
|
|
||||||
#define SHDR_SECTIONS 2
|
|
||||||
|
|
||||||
static int parse_file(struct parser *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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (symtbl_find(&parser->sym_tbl, &sym, ref->name)) {
|
|
||||||
ERROR("undefined symbol '%s'", ref->name);
|
|
||||||
return M_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int assemble_phdr(struct assembler *asm, Elf32_Phdr **res,
|
|
||||||
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);
|
|
||||||
|
|
||||||
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];
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int assemble_symtbl(struct assembler *asm, Elf32_Sym **res,
|
|
||||||
uint32_t *res2)
|
|
||||||
{
|
|
||||||
Elf32_Sym *stbl = malloc(sizeof(Elf32_Sym) * asm->parser->sym_tbl
|
|
||||||
.count);
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
*res = stbl;
|
|
||||||
*res2 = asm->parser->sym_tbl.count;
|
|
||||||
|
|
||||||
return M_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int assemble_shdr(struct assembler *asm, Elf32_Shdr **res,
|
|
||||||
uint32_t *res2)
|
|
||||||
{
|
|
||||||
uint32_t entries = 2; // str table and sym tabel
|
|
||||||
entries += asm->parser->sec_tbl.count; // sections
|
|
||||||
|
|
||||||
Elf32_Shdr *shdr = malloc(sizeof(Elf32_Shdr) * entries);
|
|
||||||
|
|
||||||
size_t str_off;
|
|
||||||
if (strtbl_write_str(&asm->str_tbl, ".shstrtab", &str_off)) {
|
|
||||||
free(shdr);
|
|
||||||
return M_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (strtbl_write_str(&asm->str_tbl, ".shsymtab", &str_off)) {
|
|
||||||
free(shdr);
|
|
||||||
return M_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 = 0,
|
|
||||||
.sh_info = 0,
|
|
||||||
.sh_addralign = 1,
|
|
||||||
.sh_entsize = sizeof(Elf32_Sym),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
*res = shdr;
|
|
||||||
*res2 = entries;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (assemble_symtbl(asm, &symtbl, &symtbl_len))
|
|
||||||
return M_ERROR;
|
|
||||||
|
|
||||||
if (assemble_phdr(asm, &phdr, &phdr_len)) {
|
|
||||||
free(symtbl);
|
|
||||||
return M_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (assemble_shdr(asm, &shdr, &shdr_len)) {
|
|
||||||
free(symtbl);
|
|
||||||
free(phdr);
|
|
||||||
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_STANDALONE,
|
|
||||||
[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 = 0x20,
|
|
||||||
.e_phnum = phdr_len,
|
|
||||||
.e_shentsize = 0x28,
|
|
||||||
.e_shnum = shdr_len,
|
|
||||||
.e_shstrndx = 0x00, // str table is always inx 0
|
|
||||||
};
|
|
||||||
|
|
||||||
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 = 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// strtbl
|
|
||||||
shdr[SHDR_STRTBL].sh_offset = ptr;
|
|
||||||
shdr[SHDR_STRTBL].sh_size = asm->str_tbl.size;
|
|
||||||
ptr += asm->str_tbl.size;
|
|
||||||
|
|
||||||
// symtbl
|
|
||||||
ehdr.e_shoff = ptr;
|
|
||||||
shdr[SHDR_SYMTBL].sh_offset = ptr;
|
|
||||||
shdr[SHDR_SYMTBL].sh_size = symtbl_len * sizeof(Elf32_Sym);
|
|
||||||
ptr += symtbl_len * sizeof(Elf32_Sym);
|
|
||||||
|
|
||||||
FILE *out = fopen("/home/freya/out.o", "w");
|
|
||||||
|
|
||||||
// ehdr
|
|
||||||
fwrite(&ehdr, sizeof(Elf32_Ehdr), 1, out);
|
|
||||||
|
|
||||||
// phdr
|
|
||||||
fwrite(phdr, sizeof(Elf32_Phdr), phdr_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 mips32_instruction *ins = &sec->ins[j].mips32;
|
|
||||||
fwrite(ins, sizeof(struct mips32_instruction),
|
|
||||||
1, out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// str tbl
|
|
||||||
fwrite(asm->str_tbl.ptr, asm->str_tbl.size, 1, out);
|
|
||||||
|
|
||||||
// sym tbl
|
|
||||||
fwrite(symtbl, sizeof(Elf32_Sym), symtbl_len, out);
|
|
||||||
|
|
||||||
// shdr
|
|
||||||
fwrite(shdr, sizeof(Elf32_Shdr), shdr_len, out);
|
|
||||||
|
|
||||||
fclose(out);
|
|
||||||
|
|
||||||
free(shdr);
|
|
||||||
free(phdr);
|
|
||||||
free(symtbl);
|
|
||||||
|
|
||||||
return M_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int assemble_file_mips32(char *path)
|
|
||||||
{
|
|
||||||
struct lexer lexer;
|
|
||||||
struct parser parser;
|
|
||||||
current_file = path;
|
|
||||||
int res = M_SUCCESS;
|
|
||||||
|
|
||||||
if (lexer_init(current_file, &lexer))
|
|
||||||
return M_ERROR;
|
|
||||||
|
|
||||||
if (mips32_parser_init(&lexer, &parser))
|
|
||||||
return M_ERROR;
|
|
||||||
|
|
||||||
if (res == M_SUCCESS)
|
|
||||||
res = parse_file(&parser);
|
|
||||||
|
|
||||||
struct assembler assembler;
|
|
||||||
assembler.parser = &parser;
|
|
||||||
strtbl_init(&assembler.str_tbl);
|
|
||||||
|
|
||||||
if (res == M_SUCCESS)
|
|
||||||
res = assemble_file(&assembler);
|
|
||||||
|
|
||||||
strtbl_free(&assembler.str_tbl);
|
|
||||||
lexer_free(&lexer);
|
|
||||||
parser_free(&parser);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
Loading…
Reference in a new issue