stable
This commit is contained in:
65
linker/riscv32_linker.c
Normal file
65
linker/riscv32_linker.c
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "header.h"
|
||||
|
||||
static u32_t text_addr = 0;
|
||||
#define FOREACH_PROGS(progs) for (rv32_prog_t **pprog = progs, *prog = *progs; \
|
||||
*pprog != NULL; prog = *(++pprog))
|
||||
int append(const void *key, void *value, void *context) {
|
||||
symtab_asm_t* symtab = (symtab_asm_t*) context;
|
||||
symasm_entry_t* entry = (symasm_entry_t*) key;
|
||||
u32_t* addr = (u32_t*) value;
|
||||
*addr += text_addr; // size to index
|
||||
salloc_alloc(16);
|
||||
if (entry->attr == GLOBAL) {
|
||||
symtab_asm_put(symtab, entry, *addr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
rv32_prog_t* link_rv32_prog(rv32_prog_t* progs[]) {
|
||||
symtab_asm_t symtab;
|
||||
init_symtab_asm(&symtab);
|
||||
|
||||
rv32_prog_t* exe = salloc_alloc(sizeof(rv32_prog_t));
|
||||
init_rv32_prog(exe, NULL);
|
||||
|
||||
FOREACH_PROGS(progs) {
|
||||
prog->text_base_address = text_addr;
|
||||
text_addr += prog->text.size;
|
||||
}
|
||||
exe->text.data = salloc_alloc(text_addr * sizeof(u32_t));
|
||||
exe->text.cap = text_addr;
|
||||
exe->text.size = text_addr;
|
||||
text_addr = 0;
|
||||
FOREACH_PROGS(progs) {
|
||||
rt_memcpy(exe->text.data + text_addr, prog->text.data, prog->text.size * sizeof(u32_t));
|
||||
// FIXME
|
||||
hashtable_foreach(&prog->symtab.symtab, append, &symtab);
|
||||
text_addr += prog->text.size;
|
||||
}
|
||||
|
||||
// find by self
|
||||
FOREACH_PROGS(progs) {
|
||||
for (int i = 0; i < prog->rinstrs.size; i++) {
|
||||
u32_t* paddr;
|
||||
u32_t addr;
|
||||
paddr = symtab_asm_get(&prog->symtab, &prog->rinstrs.data[i].target);
|
||||
if (paddr == NULL) {
|
||||
paddr = symtab_asm_get(&symtab, &prog->rinstrs.data[i].target);
|
||||
if (paddr == NULL) {
|
||||
LOG_FATAL("linker: %s not found", prog->rinstrs.data[i].target.name);
|
||||
}
|
||||
addr = *paddr;
|
||||
} else {
|
||||
addr = *paddr;
|
||||
// addr += prog->text_base_address;
|
||||
}
|
||||
// FIXME
|
||||
int cur_idx = prog->text_base_address + prog->rinstrs.data[i].address;
|
||||
prog->rinstrs.data[i].instr.imm += (addr - cur_idx) * sizeof(u32_t);
|
||||
emit_rv32_instr(exe, &prog->rinstrs.data[i].instr, cur_idx, NULL);
|
||||
|
||||
// symtab_get(&prog->symtab, &prog->rinstrs.data[i].target);
|
||||
}
|
||||
}
|
||||
return exe;
|
||||
}
|
||||
Reference in New Issue
Block a user