Compare commits

..

No commits in common. "0eec2bf24de9f6dd1af82afe0544539c0962958a" and "fff0444f6c9f666e5956dd9a7f7f2443d6d3d58f" have entirely different histories.

16 changed files with 32 additions and 145 deletions

View file

@ -1,31 +0,0 @@
include config.mk
.PHONY: build clean install uninstall masm mld msim
build: masm mld msim
./bin/masm/masm -o ./bin/runtime.o ./lib/runtime.asm
clean:
rm -fr ./bin
install:
install -m 755 -D -t $(PREFIX)/bin ./bin/masm/masm
install -m 755 -D -t $(PREFIX)/bin ./bin/mld/mld
install -m 755 -D -t $(PREFIX)/bin ./bin/msim/msim
install -m 444 -D -t $(PREFIX)/lib/mips ./bin/runtime.o
uninstall:
rm $(PREFIX)/bin/masm
rm $(PREFIX)/bin/mld
rm $(PREFIX)/bin/msim
rm $(PREFIX)/lib/mips/runtime.o
rmdir $(PREFIX)/lib/mips
masm:
make -C ./masm build
mld:
make -C ./mld build
msim:
make -C ./msim build

View file

@ -6,17 +6,6 @@ a full mips r2000 toolchain with a assembler and linker
outputs MIPS32r6 ELF32 Big Endian executables outputs MIPS32r6 ELF32 Big Endian executables
##### installing
```bash
$ make build
$ sudo make install
```
##### uninstalling
```bash
$ sudo make uninstall
```
#### masm #### masm
the assembler the assembler

View file

@ -5,4 +5,3 @@
-pedantic -pedantic
-Wno-gnu-binary-literal -Wno-gnu-binary-literal
-Iinclude -Iinclude
-DPREFIX=/usr/local

View file

@ -8,8 +8,6 @@ CFLAGS += -Wall -Wextra -pedantic
CFLAGS += -Wno-initializer-overrides CFLAGS += -Wno-initializer-overrides
CFLAGS += -O0 -g CFLAGS += -O0 -g
PREFIX=/usr/local
# ======================== CONFIG OPTIONS == # ======================== CONFIG OPTIONS ==
# #
# MAX LEX LENGTH # MAX LEX LENGTH

View file

@ -1,29 +0,0 @@
#
# MIPS32r6 ASSEMBLY RUNTIME
# - sets up the stack
# - calls main
# - exits
#
.extern main
.stack
.align 2
.space 4096
__mips_stack:
.text
.align 2
_start:
# setup stack
la $sp, __mips_stack
# call main
jal main
# exit
move $a0, $v0
li $v0, 1
syscall

View file

@ -4,6 +4,4 @@ SRC=.
BIN=../bin/mld BIN=../bin/mld
OUT=mld OUT=mld
CFLAGS += -DPREFIX=$(PREFIX)
include ../makefile.mk include ../makefile.mk

View file

@ -16,11 +16,8 @@
static int load_objects(struct linker *linker) static int load_objects(struct linker *linker)
{ {
int max_entries = linker->args->in_count + 1;
// 1 needed for the runtime
linker->objects = malloc(sizeof(struct object) * linker->objects = malloc(sizeof(struct object) *
max_entries); linker->args->in_count);
linker->obj_len = 0; linker->obj_len = 0;
if (linker->objects == NULL) { if (linker->objects == NULL) {
@ -49,19 +46,6 @@ static int load_objects(struct linker *linker)
skip_obj: skip_obj:
} }
if (linker->args->freestanding == false) {
#define _STR(x) _STR2(x)
#define _STR2(x) #x
char *path = _STR(PREFIX) "/lib/mips/runtime.o";
struct object *obj = &linker->objects[linker->obj_len++];
if (object_load(obj, path))
return M_ERROR;
#undef _STR
#undef _STR2
}
return M_SUCCESS; return M_SUCCESS;
} }
@ -177,7 +161,7 @@ static int relocate_symbol(struct linker *linker, struct object *obj,
struct segment *sec = NULL; struct segment *sec = NULL;
for (size_t i = 0; i < obj->phdr_len; i++) { for (size_t i = 0; i < obj->phdr_len; i++) {
Elf32_Phdr *temp = &obj->phdr[i]; Elf32_Phdr *temp = &obj->phdr[i];
if (PHDR_SHDR_MATCH(temp, shdr)) { if (shdr->sh_offset == temp->p_offset) {
sec = &obj->segments[i]; sec = &obj->segments[i];
break; break;
} }
@ -402,22 +386,30 @@ static int relocate_instruction_rela(struct linker *linker,
return M_ERROR; return M_ERROR;
} }
Elf32_Sym *sym = &symtab->syms[idx]; Elf32_Sym *sym = &symtab->syms[idx];
const char *symname = symtab->strtab->data + B32(sym->st_name);
char const *sym_name = symtab->strtab->data + B32(sym->st_name);
if (B32(sym->st_name) >= symtab->strtab->len) { /// get the section header that the symbol is related to
ERROR("relocation symbol name out of bounds"); Elf32_Shdr *shdr = NULL;
return M_ERROR; if (B16(sym->st_shndx) >= seg->obj->shdr_len) {
} ERROR("shndx index [%d] out of bounds", B16(sym->st_shndx));
// get the new sym for the new vaddr
Elf32_Sym *new_sym = NULL;
if (symtab_get(&linker->symtab, &new_sym, sym_name)) {
ERROR("relocation symbol not found");
return M_ERROR; return M_ERROR;
} }
shdr = &seg->obj->shdr[B16(sym->st_shndx)];
/// get the segment that the symbol is in /// get the segment that the symbol is in
uint32_t sym_vaddr = B32(new_sym->st_value); struct segment_table_entry *ent;
const char *segname = seg->obj->shstrtab->data + B32(shdr->sh_name);
if (B32(shdr->sh_name) >= seg->obj->shstrtab->len) {
ERROR("relocation segment name out of bounds");
return M_ERROR;
}
if (segtab_get(&linker->segments, &ent, segname)) {
ERROR("could not locate segment for relocation");
return M_ERROR;
}
uint32_t sym_vaddr = B32(sym->st_value) + ent->vaddr;
uint32_t *ins_raw = (uint32_t *) &seg->bytes[off]; uint32_t *ins_raw = (uint32_t *) &seg->bytes[off];
union mips_instruction_data ins; union mips_instruction_data ins;
@ -470,7 +462,7 @@ static int relocate_instruction_rela(struct linker *linker,
*ins_raw = B32(ins.raw); *ins_raw = B32(ins.raw);
if (warn) if (warn)
WARNING("truncating relocation for symbol '%s'", sym_name); WARNING("truncating relocation for symbol '%s'", symname);
return M_SUCCESS; return M_SUCCESS;
@ -655,15 +647,6 @@ static int link_executable(struct linker *linker)
ehdr->e_shnum = B16(linker->shdr_len); ehdr->e_shnum = B16(linker->shdr_len);
ehdr->e_shstrndx = B16(linker->shstrtab_shidx); ehdr->e_shstrndx = B16(linker->shstrtab_shidx);
Elf32_Sym *entry = NULL;
if (symtab_get(&linker->symtab, &entry, "_start")) {
ERROR("undefined symbol _start");
return M_ERROR;
}
// BE to BE, no endiness conversion needed
ehdr->e_entry = entry->st_value;
update_offsets(linker); update_offsets(linker);
if (write_file(linker)) if (write_file(linker))

View file

@ -26,11 +26,6 @@
#define ADDR_CHK(lnk_f, seg_f, max) \ #define ADDR_CHK(lnk_f, seg_f, max) \
((lnk_f) > max - (seg_f) || (lnk_f) + (seg_f) > max) ((lnk_f) > max - (seg_f) || (lnk_f) + (seg_f) > max)
// checks if a phdr and shdr are matches
#define PHDR_SHDR_MATCH(phdr, shdr) ( \
((phdr)->p_offset == (shdr)->sh_offset) && \
((phdr)->p_filesz == (shdr)->sh_size)) \
// start addresses for each tyoe of segment // start addresses for each tyoe of segment
#define TEXT_VADDR_MIN 0x00400000 #define TEXT_VADDR_MIN 0x00400000
#define DATA_VADDR_MIN 0x10000000 #define DATA_VADDR_MIN 0x10000000
@ -124,8 +119,6 @@ struct segment {
// object im related to // object im related to
struct object *obj; struct object *obj;
// segment table entry im related to
struct segment_table_entry *ent;
// relocation table // relocation table
struct relocation_table reltab; struct relocation_table reltab;
@ -259,7 +252,6 @@ struct linker_arguments {
char **in_files; char **in_files;
int in_count; int in_count;
char *out_file; char *out_file;
bool freestanding;
}; };
/* link object files */ /* link object files */

View file

@ -10,7 +10,6 @@ void help(void) {
printf("options:\n"); printf("options:\n");
printf("\t-h\t\tprints this help message\n"); printf("\t-h\t\tprints this help message\n");
printf("\t-o <output>\tselect a output file destination\n"); printf("\t-o <output>\tselect a output file destination\n");
printf("\t-f\t\tmake this binary freestanding (no runtime)\n");
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -19,12 +18,11 @@ int main(int argc, char **argv) {
.in_files = NULL, .in_files = NULL,
.in_count = 0, .in_count = 0,
.out_file = "a.out", .out_file = "a.out",
.freestanding = false,
}; };
int c; int c;
while ((c = getopt(argc, argv, "ho:f")) != 1) { while ((c = getopt(argc, argv, "ho:")) != 1) {
switch(c) { switch(c) {
case 'h': case 'h':
help(); help();
@ -32,9 +30,6 @@ int main(int argc, char **argv) {
case 'o': case 'o':
args.out_file = optarg; args.out_file = optarg;
break; break;
case 'f':
args.freestanding = true;
break;
case '?': case '?':
return M_ERROR; return M_ERROR;
default: default:

View file

@ -31,9 +31,10 @@ static int load_shdr(struct object *obj, struct segment *seg, size_t index)
Elf32_Shdr *hdr = &obj->shdr[i]; Elf32_Shdr *hdr = &obj->shdr[i];
// find shdr that matches the offset in phdr // find shdr that matches the offset in phdr
if (!PHDR_SHDR_MATCH(seg->phdr, hdr)) if (seg->phdr->p_offset != hdr->sh_offset)
continue; continue;
// get name // get name
uint32_t name = B32(hdr->sh_name); uint32_t name = B32(hdr->sh_name);
if (name >= obj->shstrtab->len) { if (name >= obj->shstrtab->len) {
@ -42,6 +43,11 @@ static int load_shdr(struct object *obj, struct segment *seg, size_t index)
} }
seg->name = &obj->shstrtab->data[name]; seg->name = &obj->shstrtab->data[name];
if (seg->phdr->p_filesz != hdr->sh_size) {
ERROR("segment phdr and shdr file sizes to not match");
return M_ERROR;
}
// map bytes // map bytes
uint32_t len = B32(hdr->sh_size); uint32_t len = B32(hdr->sh_size);
uint32_t off = B32(hdr->sh_offset); uint32_t off = B32(hdr->sh_offset);
@ -148,7 +154,6 @@ int segment_load(struct object *obj, struct segment *seg, size_t index)
seg->align = B32(seg->phdr->p_align); seg->align = B32(seg->phdr->p_align);
seg->obj = obj; seg->obj = obj;
seg->ent = NULL;
return M_SUCCESS; return M_SUCCESS;
} }

View file

@ -136,8 +136,6 @@ int segtab_ent_push(struct segment_table_entry *ent, struct segment *seg)
} }
ent->parts[ent->len++] = seg; ent->parts[ent->len++] = seg;
seg->ent = ent;
return M_SUCCESS; return M_SUCCESS;
} }

View file

@ -1,7 +0,0 @@
include ../config.mk
SRC=.
BIN=../bin/msim
OUT=msim
include ../makefile.mk

View file

@ -1,5 +0,0 @@
int main(void) {
// NOT YET IMPLEMENTED
return 1;
}

View file

@ -18,6 +18,7 @@ null:
.text .text
.align 2 .align 2
.globl main .globl main
.globl _start
# init the heap # init the heap
heap_init: heap_init:
@ -203,6 +204,7 @@ realloc_free:
jr $ra jr $ra
_start:
main: main:
# push return address # push return address
addi $sp, $sp, -4 addi $sp, $sp, -4

Binary file not shown.

Binary file not shown.