diff options
Diffstat (limited to '')
-rw-r--r-- | mld/link.c | 29 |
1 files changed, 28 insertions, 1 deletions
@@ -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)) |