diff --git a/config.mk b/config.mk index dcc3bcf..2eb7541 100644 --- a/config.mk +++ b/config.mk @@ -12,12 +12,11 @@ PREFIX=/usr/local # ======================== CONFIG OPTIONS == # -# MAX LEX LENGTH -# Specifies how long a ident, register, -# instruction name, or any type of variable -# length text can be inside the lexer +# MAX EXT LENGTH +# Specifies how long a stirng extension in a +# shdr entry name can be. # -# CFLAGS+= -DMAX_LEX_LENGTH=24 +# CFLAGS+= -DMAX_EXT_LENGTH=48 # # # MAX_ARG_LENGTH diff --git a/include/melf.h b/include/melf.h index e7311cd..a1c88c2 100644 --- a/include/melf.h +++ b/include/melf.h @@ -32,7 +32,7 @@ static const Elf32_Ehdr MIPS_ELF_EHDR = .e_machine = B16(EM_MIPS), .e_version = B32(EV_CURRENT), .e_entry = 0x00, - .e_flags = 0x00, // B32(EF_MIPS_ARCH_32R6), + .e_flags = B32(EF_MIPS_ARCH_32R6 | EF_MIPS_NAN2008 | EF_MIPS_ABI_O32), .e_ehsize = B16(sizeof(Elf32_Ehdr)), .e_phentsize = B16(sizeof(Elf32_Phdr)), .e_shentsize = B16(sizeof(Elf32_Shdr)), diff --git a/include/mlimits.h b/include/mlimits.h index 12318be..db07c64 100644 --- a/include/mlimits.h +++ b/include/mlimits.h @@ -3,12 +3,11 @@ #ifndef __MLIMITS_H__ #define __MLIMITS_H__ -/* Specifies how long a ident, register, - * instruction name, or any type of variable - * length text can be inside the lexer. +/* Specifies how long a stirng extension in a + * shdr entry name can be. */ -#ifndef MAX_LEX_LENGTH -#define MAX_LEX_LENGTH 24 +#ifndef MAX_EXT_LENGTH +#define MAX_EXT_LENGTH 48 #endif /* Specifices how many max arguments a diff --git a/masm/asm.c b/masm/asm.c index 619f9e5..8cbc439 100644 --- a/masm/asm.c +++ b/masm/asm.c @@ -9,7 +9,6 @@ #include "asm.h" #include "gen.h" -#include "mlimits.h" #include "tab.h" extern char *current_file; @@ -202,14 +201,14 @@ static int assemble_shdr(struct assembler *assembler, Elf32_Shdr **res, 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)]; + char reltab_name[MAX_EXT_LENGTH + strlen(prefix)]; if (sec->reltab_len == 0) continue; strcpy(reltab_name, prefix); strncat(reltab_name, sec->data->name.str, - MAX_LEX_LENGTH - strlen(prefix)); + MAX_EXT_LENGTH - strlen(prefix)); if (strtab_write_str(&assembler->shstrtab, reltab_name, &str_off)) { diff --git a/mld/link.c b/mld/link.c index dd3fcc6..2abc990 100644 --- a/mld/link.c +++ b/mld/link.c @@ -47,6 +47,7 @@ static int load_objects(struct linker *linker) skip_obj: } + // load runtime object if not set to be freestanding if (linker->args->freestanding == false) { #define _STR(x) _STR2(x) #define _STR2(x) #x @@ -69,6 +70,9 @@ skip_obj: */ static int relocate_segment_name(struct linker *linker, const char *name) { + // find each segment with the provided segment name, + // and then relocate them + for (size_t i = 0; i < linker->obj_len; i++) { struct object *obj = &linker->objects[i]; for (size_t j = 0; j < obj->segment_len; j++) { @@ -122,6 +126,7 @@ static int relocate_segment_name(struct linker *linker, const char *name) M_SUCCESS) { if (segtab_ent_push(ent, seg)) return M_ERROR; + // otherwise create a new segment table entry } else { // update vaddr to be page aligned uint32_t m = seg->new_vaddr % SEC_ALIGN; @@ -134,7 +139,7 @@ static int relocate_segment_name(struct linker *linker, const char *name) linker->data_vaddr += add; } - // else create a new segment + // create a new segment if (segtab_push(&linker->segments, NULL, seg)) return M_ERROR; } @@ -146,6 +151,9 @@ static int relocate_segment_name(struct linker *linker, const char *name) static int relocate_segments(struct linker *linker) { + // for each object, find each different + // unique segment name + for (size_t i = 0; i < linker->obj_len; i++) { struct object *obj = &linker->objects[i]; for (size_t j = 0; j < obj->segment_len; j++) { @@ -154,6 +162,9 @@ static int relocate_segments(struct linker *linker) // check if the segment has already been relocated if (seg->new_vaddr != 0) continue; + + // relocate each segment with that segment + // name if(relocate_segment_name(linker, seg->name)) return M_ERROR; } @@ -165,6 +176,14 @@ static int relocate_segments(struct linker *linker) static int relocate_symbol(struct linker *linker, struct object *obj, struct symbol_table *symtab, const Elf32_Sym *sym) { + // given the symbol and the object its in + // 1. make sure the symbol is valid + // 2. get the segment in the object that the symbol is in + // 3. get tthe segment table entry that the segment is also + // in. This allows us to get the offset into the segment_table + // 4. the new shndx is the offset + 1 (since segments start at + // shndx 1 + size_t shndx = B16(sym->st_shndx); if (shndx == 0 || shndx == SHN_ABS) return M_SUCCESS; // ignore this symbol @@ -177,11 +196,15 @@ static int relocate_symbol(struct linker *linker, struct object *obj, return M_ERROR; } + // make sure the symbol name is + // in bounds if (B32(sym->st_name) >= symtab->strtab->len) { ERROR("symbol name out of bounds"); return M_ERROR; } + // find the segment that this symbol + // is contained in struct segment *sec = NULL; for (size_t i = 0; i < obj->phdr_len; i++) { if (obj->phdr_to_shdr_mapping[i] == shndx) { @@ -245,13 +268,17 @@ static int relocate_symbol(struct linker *linker, struct object *obj, static int relocate_symbols(struct linker *linker) { + // relocate in each object for (size_t i = 0; i < linker->obj_len; i++) { struct object *obj = &linker->objects[i]; + // look though each shdr entry and find + // any symbol tables for (size_t j = 0; j < obj->shdr_len; j++) { struct symbol_table *symtab = &obj->symtabs[j]; if (symtab->len < 1) continue; + // for each symbol in the table, relocate it for (size_t k = 0; k < symtab->len; k++) { const Elf32_Sym *sym = &symtab->syms[k]; if (relocate_symbol(linker, obj, symtab, sym)) diff --git a/mld/link.h b/mld/link.h index 3c9ca42..ef3a4af 100644 --- a/mld/link.h +++ b/mld/link.h @@ -92,11 +92,6 @@ struct symbol_table { struct symbol_table_mapping *map; }; -/// -/// symbol table map -/// (metadata for each symbol) -/// - int symtab_init(struct symbol_table *symtab); void symtab_free(struct symbol_table *symtab); @@ -104,6 +99,13 @@ int symtab_push(struct symbol_table *symtab, const Elf32_Sym *sym); int symtab_get(struct symbol_table *symtab, Elf32_Sym **sym, const char *name, int32_t obj_idx); +/// +/// symbol table map +/// (metadata for each symbol) +/// stores each object that a symbol +/// is in +/// + struct symbol_table_mapping { uint32_t len; uint32_t size; @@ -163,6 +165,9 @@ int segment_load(struct object *object, struct segment *segment, size_t index); /// /// segment table +/// holds each segment that +/// share the same name +/// (i.e. all .text segments) /// struct segment_table_entry { @@ -172,6 +177,7 @@ struct segment_table_entry { uint32_t off; uint32_t vaddr; // weak segment pointers. we do not own these!!! + // (but we own the array) struct segment **parts; }; @@ -181,9 +187,10 @@ void segtab_ent_free(struct segment_table_entry *ent); int segtab_ent_push(struct segment_table_entry *ent, struct segment *seg); uint32_t segtab_ent_size(struct segment_table_entry *ent); -// holds each segment by name -// and all the segment parts from each of the -// object files +/// +/// segment table +/// holds each segment table entry by name +/// struct segment_table { uint32_t len; uint32_t size; @@ -215,14 +222,16 @@ struct object { Elf32_Ehdr *ehdr; // section header table - Elf32_Shdr *shdr; + Elf32_Shdr *shdr; // weak size_t shdr_len; // program table - Elf32_Phdr *phdr; + Elf32_Phdr *phdr; // owned size_t phdr_len; // phdr <=> shdr mappings + // need a way to find any assoiciated + // phdr with a shdr, and also reverse uint32_t *phdr_to_shdr_mapping; // object meta