Compare commits
No commits in common. "0eec2bf24de9f6dd1af82afe0544539c0962958a" and "fff0444f6c9f666e5956dd9a7f7f2443d6d3d58f" have entirely different histories.
0eec2bf24d
...
fff0444f6c
16 changed files with 32 additions and 145 deletions
31
Makefile
31
Makefile
|
@ -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
|
11
README.md
11
README.md
|
@ -6,17 +6,6 @@ a full mips r2000 toolchain with a assembler and linker
|
|||
|
||||
outputs MIPS32r6 ELF32 Big Endian executables
|
||||
|
||||
##### installing
|
||||
```bash
|
||||
$ make build
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
##### uninstalling
|
||||
```bash
|
||||
$ sudo make uninstall
|
||||
```
|
||||
|
||||
#### masm
|
||||
|
||||
the assembler
|
||||
|
|
|
@ -5,4 +5,3 @@
|
|||
-pedantic
|
||||
-Wno-gnu-binary-literal
|
||||
-Iinclude
|
||||
-DPREFIX=/usr/local
|
||||
|
|
|
@ -8,8 +8,6 @@ CFLAGS += -Wall -Wextra -pedantic
|
|||
CFLAGS += -Wno-initializer-overrides
|
||||
CFLAGS += -O0 -g
|
||||
|
||||
PREFIX=/usr/local
|
||||
|
||||
# ======================== CONFIG OPTIONS ==
|
||||
#
|
||||
# MAX LEX LENGTH
|
||||
|
|
|
@ -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
|
|
@ -4,6 +4,4 @@ SRC=.
|
|||
BIN=../bin/mld
|
||||
OUT=mld
|
||||
|
||||
CFLAGS += -DPREFIX=$(PREFIX)
|
||||
|
||||
include ../makefile.mk
|
||||
|
|
61
mld/link.c
61
mld/link.c
|
@ -16,11 +16,8 @@
|
|||
|
||||
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) *
|
||||
max_entries);
|
||||
linker->args->in_count);
|
||||
linker->obj_len = 0;
|
||||
|
||||
if (linker->objects == NULL) {
|
||||
|
@ -49,19 +46,6 @@ static int load_objects(struct linker *linker)
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -177,7 +161,7 @@ static int relocate_symbol(struct linker *linker, struct object *obj,
|
|||
struct segment *sec = NULL;
|
||||
for (size_t i = 0; i < obj->phdr_len; i++) {
|
||||
Elf32_Phdr *temp = &obj->phdr[i];
|
||||
if (PHDR_SHDR_MATCH(temp, shdr)) {
|
||||
if (shdr->sh_offset == temp->p_offset) {
|
||||
sec = &obj->segments[i];
|
||||
break;
|
||||
}
|
||||
|
@ -402,22 +386,30 @@ static int relocate_instruction_rela(struct linker *linker,
|
|||
return M_ERROR;
|
||||
}
|
||||
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) {
|
||||
ERROR("relocation symbol name out of bounds");
|
||||
return M_ERROR;
|
||||
}
|
||||
|
||||
// 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");
|
||||
|
||||
/// get the section header that the symbol is related to
|
||||
Elf32_Shdr *shdr = NULL;
|
||||
if (B16(sym->st_shndx) >= seg->obj->shdr_len) {
|
||||
ERROR("shndx index [%d] out of bounds", B16(sym->st_shndx));
|
||||
return M_ERROR;
|
||||
}
|
||||
shdr = &seg->obj->shdr[B16(sym->st_shndx)];
|
||||
|
||||
/// 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];
|
||||
|
||||
union mips_instruction_data ins;
|
||||
|
@ -470,7 +462,7 @@ static int relocate_instruction_rela(struct linker *linker,
|
|||
*ins_raw = B32(ins.raw);
|
||||
|
||||
if (warn)
|
||||
WARNING("truncating relocation for symbol '%s'", sym_name);
|
||||
WARNING("truncating relocation for symbol '%s'", symname);
|
||||
|
||||
return M_SUCCESS;
|
||||
|
||||
|
@ -655,15 +647,6 @@ static int link_executable(struct linker *linker)
|
|||
ehdr->e_shnum = B16(linker->shdr_len);
|
||||
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);
|
||||
|
||||
if (write_file(linker))
|
||||
|
|
|
@ -26,11 +26,6 @@
|
|||
#define ADDR_CHK(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
|
||||
#define TEXT_VADDR_MIN 0x00400000
|
||||
#define DATA_VADDR_MIN 0x10000000
|
||||
|
@ -124,8 +119,6 @@ struct segment {
|
|||
|
||||
// object im related to
|
||||
struct object *obj;
|
||||
// segment table entry im related to
|
||||
struct segment_table_entry *ent;
|
||||
|
||||
// relocation table
|
||||
struct relocation_table reltab;
|
||||
|
@ -259,7 +252,6 @@ struct linker_arguments {
|
|||
char **in_files;
|
||||
int in_count;
|
||||
char *out_file;
|
||||
bool freestanding;
|
||||
};
|
||||
|
||||
/* link object files */
|
||||
|
|
|
@ -10,7 +10,6 @@ void help(void) {
|
|||
printf("options:\n");
|
||||
printf("\t-h\t\tprints this help message\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) {
|
||||
|
@ -19,12 +18,11 @@ int main(int argc, char **argv) {
|
|||
.in_files = NULL,
|
||||
.in_count = 0,
|
||||
.out_file = "a.out",
|
||||
.freestanding = false,
|
||||
};
|
||||
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "ho:f")) != 1) {
|
||||
while ((c = getopt(argc, argv, "ho:")) != 1) {
|
||||
switch(c) {
|
||||
case 'h':
|
||||
help();
|
||||
|
@ -32,9 +30,6 @@ int main(int argc, char **argv) {
|
|||
case 'o':
|
||||
args.out_file = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
args.freestanding = true;
|
||||
break;
|
||||
case '?':
|
||||
return M_ERROR;
|
||||
default:
|
||||
|
|
|
@ -31,9 +31,10 @@ static int load_shdr(struct object *obj, struct segment *seg, size_t index)
|
|||
Elf32_Shdr *hdr = &obj->shdr[i];
|
||||
|
||||
// find shdr that matches the offset in phdr
|
||||
if (!PHDR_SHDR_MATCH(seg->phdr, hdr))
|
||||
if (seg->phdr->p_offset != hdr->sh_offset)
|
||||
continue;
|
||||
|
||||
|
||||
// get name
|
||||
uint32_t name = B32(hdr->sh_name);
|
||||
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];
|
||||
|
||||
if (seg->phdr->p_filesz != hdr->sh_size) {
|
||||
ERROR("segment phdr and shdr file sizes to not match");
|
||||
return M_ERROR;
|
||||
}
|
||||
|
||||
// map bytes
|
||||
uint32_t len = B32(hdr->sh_size);
|
||||
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->obj = obj;
|
||||
seg->ent = NULL;
|
||||
|
||||
return M_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -136,8 +136,6 @@ int segtab_ent_push(struct segment_table_entry *ent, struct segment *seg)
|
|||
}
|
||||
|
||||
ent->parts[ent->len++] = seg;
|
||||
seg->ent = ent;
|
||||
|
||||
return M_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
include ../config.mk
|
||||
|
||||
SRC=.
|
||||
BIN=../bin/msim
|
||||
OUT=msim
|
||||
|
||||
include ../makefile.mk
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
int main(void) {
|
||||
// NOT YET IMPLEMENTED
|
||||
return 1;
|
||||
}
|
|
@ -18,6 +18,7 @@ null:
|
|||
.text
|
||||
.align 2
|
||||
.globl main
|
||||
.globl _start
|
||||
|
||||
# init the heap
|
||||
heap_init:
|
||||
|
@ -203,6 +204,7 @@ realloc_free:
|
|||
jr $ra
|
||||
|
||||
|
||||
_start:
|
||||
main:
|
||||
# push return address
|
||||
addi $sp, $sp, -4
|
||||
|
|
BIN
test/mld/test.o
BIN
test/mld/test.o
Binary file not shown.
BIN
test/msim/test
BIN
test/msim/test
Binary file not shown.
Loading…
Reference in a new issue