Compare commits
No commits in common. "9a3ccc2fc13150af418d4fbee266fd593891ec45" and "0eec2bf24de9f6dd1af82afe0544539c0962958a" have entirely different histories.
9a3ccc2fc1
...
0eec2bf24d
5 changed files with 19 additions and 109 deletions
|
@ -6,7 +6,6 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
.extern main
|
.extern main
|
||||||
.globl _start
|
|
||||||
|
|
||||||
.stack
|
.stack
|
||||||
.align 2
|
.align 2
|
||||||
|
|
29
mld/link.c
29
mld/link.c
|
@ -44,7 +44,7 @@ static int load_objects(struct linker *linker)
|
||||||
|
|
||||||
// load obj file
|
// load obj file
|
||||||
linker->obj_len++;
|
linker->obj_len++;
|
||||||
if (object_load(obj, path, i+1))
|
if (object_load(obj, path))
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
skip_obj:
|
skip_obj:
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ skip_obj:
|
||||||
|
|
||||||
char *path = _STR(PREFIX) "/lib/mips/runtime.o";
|
char *path = _STR(PREFIX) "/lib/mips/runtime.o";
|
||||||
struct object *obj = &linker->objects[linker->obj_len++];
|
struct object *obj = &linker->objects[linker->obj_len++];
|
||||||
if (object_load(obj, path, 0))
|
if (object_load(obj, path))
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
|
|
||||||
#undef _STR
|
#undef _STR
|
||||||
|
@ -208,7 +208,7 @@ static int relocate_symbol(struct linker *linker, struct object *obj,
|
||||||
new.st_shndx = B16(new_shndx);
|
new.st_shndx = B16(new_shndx);
|
||||||
new.st_size = 0;
|
new.st_size = 0;
|
||||||
|
|
||||||
if (symtab_get(&linker->symtab, NULL, name, obj->index) == M_SUCCESS) {
|
if (symtab_get(&linker->symtab, NULL, name) == M_SUCCESS) {
|
||||||
ERROR("cannot link doubly defiend symbol '%s'", name);
|
ERROR("cannot link doubly defiend symbol '%s'", name);
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -216,9 +216,6 @@ static int relocate_symbol(struct linker *linker, struct object *obj,
|
||||||
if (symtab_push(&linker->symtab, &new))
|
if (symtab_push(&linker->symtab, &new))
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
|
|
||||||
if (symtab_map_push(&linker->symtab_map, obj))
|
|
||||||
return M_ERROR;
|
|
||||||
|
|
||||||
return M_SUCCESS;
|
return M_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,12 +380,12 @@ static int relocate_instruction_rela(struct linker *linker,
|
||||||
/// of this relocation in that segment part
|
/// of this relocation in that segment part
|
||||||
uint32_t off = B32(rel->r_offset);
|
uint32_t off = B32(rel->r_offset);
|
||||||
if (off > seg->size) {
|
if (off > seg->size) {
|
||||||
ERROR("invalid relocation in '%s'", seg->obj->name);
|
ERROR("relocation in segment '%s' out of bounds", seg->name);
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (B32(rel->r_info) == 0) {
|
if (B32(rel->r_info) == 0) {
|
||||||
WARNING("skiping empty relocation entry in '%s'", seg->name);
|
WARNING("skiping empty relocation entry");
|
||||||
return M_SUCCESS;
|
return M_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,21 +397,22 @@ static int relocate_instruction_rela(struct linker *linker,
|
||||||
/// read the symbol from the relocation
|
/// read the symbol from the relocation
|
||||||
struct symbol_table *symtab = seg->reltab.symtab;
|
struct symbol_table *symtab = seg->reltab.symtab;
|
||||||
if (idx >= symtab->len) {
|
if (idx >= symtab->len) {
|
||||||
ERROR("invalid relocation in '%s'", seg->obj->name);
|
ERROR("relocation in segment '%s', symbol index [%d] out of "
|
||||||
|
"bounds", seg->name, idx);
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
}
|
}
|
||||||
Elf32_Sym *sym = &symtab->syms[idx];
|
Elf32_Sym *sym = &symtab->syms[idx];
|
||||||
|
|
||||||
char const *sym_name = 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) {
|
if (B32(sym->st_name) >= symtab->strtab->len) {
|
||||||
ERROR("symbol name out of bounds in '%s'", seg->obj->name);
|
ERROR("relocation symbol name out of bounds");
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the new sym for the new vaddr
|
// get the new sym for the new vaddr
|
||||||
Elf32_Sym *new_sym = NULL;
|
Elf32_Sym *new_sym = NULL;
|
||||||
if (symtab_get(&linker->symtab, &new_sym, sym_name, seg->obj->index)) {
|
if (symtab_get(&linker->symtab, &new_sym, sym_name)) {
|
||||||
ERROR("symbol '%s' undefined", sym_name);
|
ERROR("relocation symbol not found");
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,7 +656,7 @@ static int link_executable(struct linker *linker)
|
||||||
ehdr->e_shstrndx = B16(linker->shstrtab_shidx);
|
ehdr->e_shstrndx = B16(linker->shstrtab_shidx);
|
||||||
|
|
||||||
Elf32_Sym *entry = NULL;
|
Elf32_Sym *entry = NULL;
|
||||||
if (symtab_get(&linker->symtab, &entry, "_start", -1)) {
|
if (symtab_get(&linker->symtab, &entry, "_start")) {
|
||||||
ERROR("undefined symbol _start");
|
ERROR("undefined symbol _start");
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -683,7 +681,6 @@ static int linker_init(struct linker *linker, struct linker_arguments *args)
|
||||||
linker->objects = NULL;
|
linker->objects = NULL;
|
||||||
linker->segments.size = 0;
|
linker->segments.size = 0;
|
||||||
linker->symtab.syms = NULL;
|
linker->symtab.syms = NULL;
|
||||||
linker->symtab_map.meta = NULL;
|
|
||||||
linker->shstrtab.data = NULL;
|
linker->shstrtab.data = NULL;
|
||||||
linker->strtab.data = NULL;
|
linker->strtab.data = NULL;
|
||||||
linker->shdr = NULL;
|
linker->shdr = NULL;
|
||||||
|
@ -696,10 +693,7 @@ static int linker_init(struct linker *linker, struct linker_arguments *args)
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
if (symtab_init(&linker->symtab))
|
if (symtab_init(&linker->symtab))
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
if (symtab_map_init(&linker->symtab_map))
|
|
||||||
return M_ERROR;
|
|
||||||
linker->symtab.strtab = &linker->strtab;
|
linker->symtab.strtab = &linker->strtab;
|
||||||
linker->symtab.map = &linker->symtab_map;
|
|
||||||
return M_SUCCESS;
|
return M_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -718,7 +712,6 @@ static void linker_free(struct linker *linker)
|
||||||
strtab_free(&linker->shstrtab);
|
strtab_free(&linker->shstrtab);
|
||||||
strtab_free(&linker->strtab);
|
strtab_free(&linker->strtab);
|
||||||
symtab_free(&linker->symtab);
|
symtab_free(&linker->symtab);
|
||||||
symtab_map_free(&linker->symtab_map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int link_files(struct linker_arguments args) {
|
int link_files(struct linker_arguments args) {
|
||||||
|
|
30
mld/link.h
30
mld/link.h
|
@ -39,9 +39,6 @@
|
||||||
struct linker;
|
struct linker;
|
||||||
struct object;
|
struct object;
|
||||||
struct segment;
|
struct segment;
|
||||||
struct string_table;
|
|
||||||
struct symbol_table;
|
|
||||||
struct symbol_table_mapping;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// relocation table
|
/// relocation table
|
||||||
|
@ -82,35 +79,13 @@ struct symbol_table {
|
||||||
Elf32_Sym *syms;
|
Elf32_Sym *syms;
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t size;
|
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);
|
int symtab_init(struct symbol_table *symtab);
|
||||||
void symtab_free(struct symbol_table *symtab);
|
void symtab_free(struct symbol_table *symtab);
|
||||||
|
|
||||||
int symtab_push(struct symbol_table *symtab, const Elf32_Sym *sym);
|
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
|
/// segment
|
||||||
|
@ -236,7 +211,7 @@ struct object {
|
||||||
struct symbol_table *symtabs;
|
struct symbol_table *symtabs;
|
||||||
};
|
};
|
||||||
|
|
||||||
int object_load(struct object *object, char *path, uint32_t index);
|
int object_load(struct object *object, char *path);
|
||||||
|
|
||||||
void object_free(struct object *object);
|
void object_free(struct object *object);
|
||||||
|
|
||||||
|
@ -260,7 +235,6 @@ struct linker {
|
||||||
struct string_table shstrtab;
|
struct string_table shstrtab;
|
||||||
struct string_table strtab;
|
struct string_table strtab;
|
||||||
struct symbol_table symtab;
|
struct symbol_table symtab;
|
||||||
struct symbol_table_mapping symtab_map;
|
|
||||||
|
|
||||||
// output elf
|
// output elf
|
||||||
Elf32_Ehdr ehdr;
|
Elf32_Ehdr ehdr;
|
||||||
|
|
|
@ -276,7 +276,7 @@ static int map_file(struct object *obj, char *path)
|
||||||
return M_SUCCESS;
|
return M_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int object_load(struct object *object, char *path, uint32_t index)
|
int object_load(struct object *object, char *path)
|
||||||
{
|
{
|
||||||
current_file = path;
|
current_file = path;
|
||||||
|
|
||||||
|
@ -286,7 +286,6 @@ int object_load(struct object *object, char *path, uint32_t index)
|
||||||
object->strtabs = NULL;
|
object->strtabs = NULL;
|
||||||
object->mapped = NULL;
|
object->mapped = NULL;
|
||||||
object->name = path;
|
object->name = path;
|
||||||
object->index = index;
|
|
||||||
|
|
||||||
/** load the file */
|
/** load the file */
|
||||||
if (map_file(object, path))
|
if (map_file(object, path))
|
||||||
|
|
61
mld/symtab.c
61
mld/symtab.c
|
@ -1,6 +1,5 @@
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <merror.h>
|
#include <merror.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <melf.h>
|
#include <melf.h>
|
||||||
|
|
||||||
|
@ -20,7 +19,6 @@ int symtab_init(struct symbol_table *symtab)
|
||||||
}
|
}
|
||||||
|
|
||||||
symtab->syms[0] = (Elf32_Sym){0};
|
symtab->syms[0] = (Elf32_Sym){0};
|
||||||
symtab->map = NULL;
|
|
||||||
|
|
||||||
return M_SUCCESS;
|
return M_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -47,69 +45,16 @@ int symtab_push(struct symbol_table *symtab, const Elf32_Sym *sym)
|
||||||
return M_SUCCESS;
|
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++) {
|
for (size_t i = 0; i < symtab->len; i++) {
|
||||||
Elf32_Sym *sym = &symtab->syms[i];
|
Elf32_Sym *sym = &symtab->syms[i];
|
||||||
const char *symname = symtab->strtab->data + B32(sym->st_name);
|
const char *symname = symtab->strtab->data + B32(sym->st_name);
|
||||||
if (strcmp(name, symname) != 0)
|
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)
|
if (res != NULL)
|
||||||
*res = sym;
|
*res = sym;
|
||||||
return M_SUCCESS;
|
return M_SUCCESS;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return M_ERROR;
|
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);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue