From 9d3d75fecbf89ca526b95dd824b15a4d284e05c8 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Mon, 23 Sep 2024 10:13:38 -0400 Subject: [PATCH] fix local vs global symbol names, locals now are local --- mld/link.c | 29 ++++++++++++++--------- mld/link.h | 30 ++++++++++++++++++++++-- mld/obj.c | 3 ++- mld/symtab.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 108 insertions(+), 19 deletions(-) diff --git a/mld/link.c b/mld/link.c index 64cffe5..e9a886c 100644 --- a/mld/link.c +++ b/mld/link.c @@ -44,7 +44,7 @@ static int load_objects(struct linker *linker) // load obj file linker->obj_len++; - if (object_load(obj, path)) + if (object_load(obj, path, i+1)) return M_ERROR; skip_obj: } @@ -55,7 +55,7 @@ skip_obj: char *path = _STR(PREFIX) "/lib/mips/runtime.o"; struct object *obj = &linker->objects[linker->obj_len++]; - if (object_load(obj, path)) + if (object_load(obj, path, 0)) return M_ERROR; #undef _STR @@ -208,7 +208,7 @@ static int relocate_symbol(struct linker *linker, struct object *obj, new.st_shndx = B16(new_shndx); new.st_size = 0; - if (symtab_get(&linker->symtab, NULL, name) == M_SUCCESS) { + if (symtab_get(&linker->symtab, NULL, name, obj->index) == M_SUCCESS) { ERROR("cannot link doubly defiend symbol '%s'", name); return M_ERROR; } @@ -216,6 +216,9 @@ static int relocate_symbol(struct linker *linker, struct object *obj, if (symtab_push(&linker->symtab, &new)) return M_ERROR; + if (symtab_map_push(&linker->symtab_map, obj)) + return M_ERROR; + return M_SUCCESS; } @@ -380,12 +383,12 @@ static int relocate_instruction_rela(struct linker *linker, /// of this relocation in that segment part uint32_t off = B32(rel->r_offset); if (off > seg->size) { - ERROR("relocation in segment '%s' out of bounds", seg->name); + ERROR("invalid relocation in '%s'", seg->obj->name); return M_ERROR; } if (B32(rel->r_info) == 0) { - WARNING("skiping empty relocation entry"); + WARNING("skiping empty relocation entry in '%s'", seg->name); return M_SUCCESS; } @@ -397,22 +400,21 @@ static int relocate_instruction_rela(struct linker *linker, /// read the symbol from the relocation struct symbol_table *symtab = seg->reltab.symtab; if (idx >= symtab->len) { - ERROR("relocation in segment '%s', symbol index [%d] out of " - "bounds", seg->name, idx); + ERROR("invalid relocation in '%s'", seg->obj->name); return M_ERROR; } Elf32_Sym *sym = &symtab->syms[idx]; 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"); + ERROR("symbol name out of bounds in '%s'", seg->obj->name); 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"); + if (symtab_get(&linker->symtab, &new_sym, sym_name, seg->obj->index)) { + ERROR("symbol '%s' undefined", sym_name); return M_ERROR; } @@ -656,7 +658,7 @@ static int link_executable(struct linker *linker) ehdr->e_shstrndx = B16(linker->shstrtab_shidx); Elf32_Sym *entry = NULL; - if (symtab_get(&linker->symtab, &entry, "_start")) { + if (symtab_get(&linker->symtab, &entry, "_start", -1)) { ERROR("undefined symbol _start"); return M_ERROR; } @@ -681,6 +683,7 @@ static int linker_init(struct linker *linker, struct linker_arguments *args) linker->objects = NULL; linker->segments.size = 0; linker->symtab.syms = NULL; + linker->symtab_map.meta = NULL; linker->shstrtab.data = NULL; linker->strtab.data = NULL; linker->shdr = NULL; @@ -693,7 +696,10 @@ static int linker_init(struct linker *linker, struct linker_arguments *args) return M_ERROR; if (symtab_init(&linker->symtab)) return M_ERROR; + if (symtab_map_init(&linker->symtab_map)) + return M_ERROR; linker->symtab.strtab = &linker->strtab; + linker->symtab.map = &linker->symtab_map; return M_SUCCESS; } @@ -712,6 +718,7 @@ static void linker_free(struct linker *linker) strtab_free(&linker->shstrtab); strtab_free(&linker->strtab); symtab_free(&linker->symtab); + symtab_map_free(&linker->symtab_map); } int link_files(struct linker_arguments args) { diff --git a/mld/link.h b/mld/link.h index 9096975..6c3b714 100644 --- a/mld/link.h +++ b/mld/link.h @@ -39,6 +39,9 @@ struct linker; struct object; struct segment; +struct string_table; +struct symbol_table; +struct symbol_table_mapping; /// /// relocation table @@ -79,13 +82,35 @@ struct symbol_table { Elf32_Sym *syms; size_t len; size_t size; + + // mapping for global symbol table + // can be null + // (metadata for each symbol) + 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); int symtab_push(struct symbol_table *symtab, const Elf32_Sym *sym); -int symtab_get(struct symbol_table *symtab, Elf32_Sym **sym, const char *name); +int symtab_get(struct symbol_table *symtab, Elf32_Sym **sym, const char *name, + int32_t obj_idx); + +struct symbol_table_mapping { + uint32_t len; + uint32_t size; + struct object **meta; +}; + +int symtab_map_push(struct symbol_table_mapping *symtabm, struct object *seg); + +int symtab_map_init(struct symbol_table_mapping *symtabm); +void symtab_map_free(struct symbol_table_mapping *symtabm); /// /// segment @@ -211,7 +236,7 @@ struct object { struct symbol_table *symtabs; }; -int object_load(struct object *object, char *path); +int object_load(struct object *object, char *path, uint32_t index); void object_free(struct object *object); @@ -235,6 +260,7 @@ struct linker { struct string_table shstrtab; struct string_table strtab; struct symbol_table symtab; + struct symbol_table_mapping symtab_map; // output elf Elf32_Ehdr ehdr; diff --git a/mld/obj.c b/mld/obj.c index 9706371..b065316 100644 --- a/mld/obj.c +++ b/mld/obj.c @@ -276,7 +276,7 @@ static int map_file(struct object *obj, char *path) return M_SUCCESS; } -int object_load(struct object *object, char *path) +int object_load(struct object *object, char *path, uint32_t index) { current_file = path; @@ -286,6 +286,7 @@ int object_load(struct object *object, char *path) object->strtabs = NULL; object->mapped = NULL; object->name = path; + object->index = index; /** load the file */ if (map_file(object, path)) diff --git a/mld/symtab.c b/mld/symtab.c index eca6dbe..5abad2a 100644 --- a/mld/symtab.c +++ b/mld/symtab.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -19,6 +20,7 @@ int symtab_init(struct symbol_table *symtab) } symtab->syms[0] = (Elf32_Sym){0}; + symtab->map = NULL; return M_SUCCESS; } @@ -45,16 +47,69 @@ int symtab_push(struct symbol_table *symtab, const Elf32_Sym *sym) return M_SUCCESS; } -int symtab_get(struct symbol_table *symtab, Elf32_Sym **res, const char *name) +int symtab_get(struct symbol_table *symtab, Elf32_Sym **res, const char *name, + int32_t obj_idx) { for (size_t i = 0; i < symtab->len; i++) { Elf32_Sym *sym = &symtab->syms[i]; const char *symname = symtab->strtab->data + B32(sym->st_name); - if (strcmp(name, symname) == 0) { - if (res != NULL) - *res = sym; - return M_SUCCESS; + if (strcmp(name, symname) != 0) + continue; + + // only allow retrevial of local variables from the + // same object + if (sym->st_info >> 4 != STB_GLOBAL && symtab->map != NULL && + obj_idx >= 0) { + struct object *obj = symtab->map->meta[i]; + if (obj->index != (uint32_t)obj_idx) + continue; + } else if (obj_idx < 0 && sym->st_info >> 4 != STB_GLOBAL) { + // when obj_idx is -1, we only want to reutrn + // global symbols + continue; } + + if (res != NULL) + *res = sym; + return M_SUCCESS; } return M_ERROR; } + +int symtab_map_push(struct symbol_table_mapping *symtabm, struct object *meta) +{ + if (symtabm->len >= symtabm->size) { + uint32_t size = symtabm->size * 2; + void *new = realloc(symtabm->meta, + sizeof(struct object *) * size); + if (new == NULL) { + PERROR("cannot realloc"); + return M_ERROR; + } + symtabm->size = size; + symtabm->meta = new; + } + + symtabm->meta[symtabm->len++] = meta; + return M_SUCCESS; +} + +int symtab_map_init(struct symbol_table_mapping *symtabm) +{ + symtabm->len = 0; + symtabm->size = SYMTAB_INIT_LEN; + symtabm->meta = malloc(sizeof(struct object *) * symtabm->size); + + if (symtabm->meta == NULL) { + PERROR("cannot alloc"); + return M_ERROR; + } + + return M_SUCCESS; +} + + +void symtab_map_free(struct symbol_table_mapping *symtabm) +{ + free(symtabm->meta); +}