summaryrefslogtreecommitdiff
path: root/mld
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-09-23 10:13:38 -0400
committerFreya Murphy <freya@freyacat.org>2024-09-23 10:13:38 -0400
commit9d3d75fecbf89ca526b95dd824b15a4d284e05c8 (patch)
tree969c28f4090595853a9ad863bb3812020b5aecaf /mld
parentupdate readme (diff)
downloadmips-9d3d75fecbf89ca526b95dd824b15a4d284e05c8.tar.gz
mips-9d3d75fecbf89ca526b95dd824b15a4d284e05c8.tar.bz2
mips-9d3d75fecbf89ca526b95dd824b15a4d284e05c8.zip
fix local vs global symbol names, locals now are local
Diffstat (limited to 'mld')
-rw-r--r--mld/link.c29
-rw-r--r--mld/link.h30
-rw-r--r--mld/obj.c3
-rw-r--r--mld/symtab.c65
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 <elf.h>
#include <merror.h>
+#include <stdio.h>
#include <stdlib.h>
#include <melf.h>
@@ -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);
+}