summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.mk2
-rw-r--r--obj/modules/example/.gitignore0
-rw-r--r--src/bld/linker.C358
-rw-r--r--src/bld/makefile2
-rw-r--r--src/include/sys/vfs.h18
-rw-r--r--src/kernel/pagemgr.C6
-rw-r--r--src/makefile2
-rw-r--r--src/module.ld35
-rw-r--r--src/sys/init/init_main.C6
-rw-r--r--src/sys/vfs/vfs_main.C23
-rw-r--r--src/usr/example/example.C28
-rw-r--r--src/usr/example/makefile16
-rw-r--r--src/usr/makefile9
13 files changed, 488 insertions, 17 deletions
diff --git a/config.mk b/config.mk
index 5d2b2c028..14aefa449 100644
--- a/config.mk
+++ b/config.mk
@@ -21,7 +21,7 @@ ${OBJDIR}/%.o : %.c
${OBJDIR}/%.o : %.S
${CC} -c ${ASMFLAGS} $< -o $@ -Wa,-I${INCDIR}
-${OBJDIR}/%.so : ${OBJECTS} ${ROOTPATH}/src/module.ld
+${IMGDIR}/%.so : ${OBJECTS} ${ROOTPATH}/src/module.ld
${LD} -shared -z now --gc-sections ${LDFLAGS} $< \
-T ${ROOTPATH}/src/module.ld -o $@
diff --git a/obj/modules/example/.gitignore b/obj/modules/example/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/obj/modules/example/.gitignore
diff --git a/src/bld/linker.C b/src/bld/linker.C
index 59cbf6416..fda2059d4 100644
--- a/src/bld/linker.C
+++ b/src/bld/linker.C
@@ -3,34 +3,74 @@
#include <iostream>
#include <string>
#include <vector>
+#include <map>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
+#include <stdlib.h>
+#include <algorithm>
+
+#include <vfs.h>
using std::cout;
using std::endl;
using std::string;
using std::vector;
+using std::map;
+using std::for_each;
+using std::mem_fun_ref;
+using std::bind1st;
+
+struct Symbol
+{
+ string name;
+ uint8_t type;
+ uint64_t address;
+ uint64_t addend;
+
+ enum SymbolType
+ {
+ LOCAL = 0x01,
+ GLOBAL = 0x02,
+
+ UNRESOLVED = 0x04,
+
+ FUNCTION = 0x08,
+ VARIABLE = 0x10,
+
+ RELATIVE = 0x20,
+ };
+};
struct Section
{
string name;
size_t vma_offset;
size_t size;
-
+
bfd_byte* data;
};
struct Object
{
public:
+ string name;
bfd* image;
Section text;
Section data;
-
+ map<string, Symbol> symbols;
+ vector<Symbol> relocs;
+ long offset;
+
bool read_object(char* file);
bool write_object(FILE* file);
+ bool read_relocation();
+ bool perform_local_relocations(FILE* file);
+ bool perform_global_relocations(FILE* file);
+
+ uint64_t find_init_symbol();
+ uint64_t find_start_symbol();
};
vector<Object> objects;
@@ -59,16 +99,79 @@ int main(int argc, char** argv)
Object o;
if (o.read_object(argv[files]))
{
+ o.read_relocation();
objects.push_back(o);
+ cout << endl;
}
}
- for (vector<Object>::iterator i = objects.begin();
+ for_each(objects.begin(), objects.end(),
+ bind2nd(mem_fun_ref(&Object::write_object), output));
+ uint64_t last_address = ftell(output);
+
+ cout << "Local relocations..." << endl;
+ for_each(objects.begin(), objects.end(),
+ bind2nd(mem_fun_ref(&Object::perform_local_relocations), output));
+ cout << endl;
+
+ cout << "Global relocations..." << endl;
+ for_each(objects.begin(), objects.end(),
+ bind2nd(mem_fun_ref(&Object::perform_global_relocations), output));
+ cout << endl;
+
+ // Create module table.
+ uint64_t module_table_address =
+ objects[0].symbols[VFS_TOSTRING(VFS_MODULES)].address +
+ objects[0].offset + objects[0].data.vma_offset;
+
+ fseek(output, module_table_address, SEEK_SET);
+
+ if ((objects.size()-1) > VFS_MODULE_MAX)
+ {
+ cout << "Error: Too many modules." << endl;
+ return -1;
+ }
+
+ cout << "Updating module table... " << endl;
+ for (vector<Object>::iterator i = ++objects.begin();
i != objects.end();
++i)
{
- i->write_object(output);
+ string object_name = i->name;
+ object_name.erase(0, object_name.find_last_of("/")+1);
+
+ char obj_name[VFS_MODULE_NAME_MAX];
+ memset(obj_name, '\0', VFS_MODULE_NAME_MAX);
+ strncpy(obj_name, object_name.c_str(), VFS_MODULE_NAME_MAX-1);
+ fwrite(obj_name, VFS_MODULE_NAME_MAX, 1, output);
+
+ uint64_t init_symbol = i->find_init_symbol();
+ uint64_t start_symbol = i->find_start_symbol();
+
+ char data[sizeof(uint64_t)];
+
+ bfd_putb64(init_symbol, data);
+ fwrite(data, sizeof(uint64_t), 1, output);
+ bfd_putb64(start_symbol, data);
+ fwrite(data, sizeof(uint64_t), 1, output);
+
+ cout << "\tAdded module " << object_name << " with init at "
+ << std::hex << init_symbol << " and start at "
+ << start_symbol << endl;
}
+
+ cout << "Updating last address..." << std::hex;
+ uint64_t last_address_entry_address =
+ objects[0].symbols[VFS_TOSTRING(VFS_LAST_ADDRESS)].address +
+ objects[0].offset + objects[0].data.vma_offset;
+
+ fseek(output, last_address_entry_address, SEEK_SET);
+ char last_addr_data[sizeof(uint64_t)];
+ bfd_putb64(last_address, last_addr_data);
+ fwrite(last_addr_data, sizeof(uint64_t), 1, output);
+
+ cout << last_address << " to " << last_address_entry_address << endl;
+
return 0;
}
@@ -81,7 +184,8 @@ bool Object::read_object(char* file)
cout << "Unsupported file format: " << file << endl;
return false;
}
-
+
+ name = file;
cout << "File " << file << endl;
// Read sections.
@@ -115,8 +219,6 @@ bool Object::read_object(char* file)
image_section = image_section->next;
}
- cout << endl;
-
return true;
}
@@ -133,7 +235,7 @@ bool Object::write_object(FILE* file)
{
// Start outputing object at page boundary.
advance_to_page_align(file);
- long start_pos = ftell(file);
+ offset = ftell(file);
// Output TEXT section.
fseek(file, text.vma_offset, SEEK_CUR);
@@ -145,7 +247,7 @@ bool Object::write_object(FILE* file)
}
// Output DATA section.
- fseek(file, start_pos + data.vma_offset, SEEK_SET);
+ fseek(file, offset + data.vma_offset, SEEK_SET);
if (data.size != fwrite(data.data, 1, data.size, file))
{
int error = errno;
@@ -153,3 +255,241 @@ bool Object::write_object(FILE* file)
cout << strerror(error) << endl;
}
}
+
+bool Object::read_relocation()
+{
+ asymbol** syms = NULL;
+ long symbols = 0;
+ arelent** loc = NULL;
+ long locs = 0;
+
+ // Read symbol tables.
+ {
+ long symbol_size = bfd_get_dynamic_symtab_upper_bound(image);
+ if (0 < symbol_size)
+ {
+ syms = (asymbol**) malloc(symbol_size);
+ symbols = bfd_canonicalize_dynamic_symtab(image, syms);
+ }
+ }
+ if (0 >= symbols)
+ {
+ long symbol_size = bfd_get_symtab_upper_bound(image);
+ if (0 < symbol_size)
+ {
+ syms = (asymbol**) malloc(symbol_size);
+ symbols = bfd_canonicalize_symtab(image, syms);
+ }
+ }
+ if (0 >= symbols)
+ {
+ cout << "Couldn't find symbol table." << endl;
+ return false;
+ }
+ cout << "Symbols: " << std::dec << symbols << endl;
+ for (int i = 0; i < symbols; i++)
+ {
+ Symbol s;
+ s.name = syms[i]->name;
+ s.address = syms[i]->value;
+ s.type = 0;
+
+ cout << "\tSymbol: " << syms[i]->name << endl;
+ cout << "\t\tAddress: " << std::hex << syms[i]->value << endl;
+
+ // Determine symbol types.
+ if (syms[i]->flags & BSF_GLOBAL)
+ {
+ s.type |= Symbol::GLOBAL;
+ cout << "\t\tGLOBAL" << endl;
+ }
+ else if (syms[i]->flags & (BSF_LOCAL | BSF_WEAK))
+ {
+ s.type |= Symbol::LOCAL;
+ cout << "\t\tLOCAL" << endl;
+ }
+ else
+ {
+ s.type |= Symbol::UNRESOLVED;
+ cout << "\t\tUNDEFINED " << std::hex << syms[i]->flags << endl;
+ }
+
+ if (syms[i]->flags & BSF_FUNCTION)
+ {
+ s.type |= Symbol::FUNCTION;
+ cout << "\t\tFUNCTION" << endl;
+ }
+ else if (!(s.type & Symbol::UNRESOLVED))
+ {
+ s.type |= Symbol::VARIABLE;
+ cout << "\t\tVARIABLE" << endl;
+ }
+
+ // Add symbol to table.
+ if (!(s.type & Symbol::UNRESOLVED))
+ this->symbols[s.name] = s;
+ }
+
+ // Read relocations.
+ {
+ long loc_size = bfd_get_dynamic_reloc_upper_bound(image);
+ if (0 < loc_size)
+ {
+ loc = (arelent**) malloc(loc_size);
+ memset(loc, '\0', loc_size);
+ locs = bfd_canonicalize_dynamic_reloc(image, loc, syms);
+ }
+ }
+ if (0 >= locs)
+ {
+ goto cleanup;
+ }
+
+ cout << "Relocs: " << std::dec << locs << endl;
+ for (int i = 0; i < locs; i++)
+ {
+ Symbol s;
+
+ s.name = loc[i]->sym_ptr_ptr[0]->name;
+ s.address = loc[i]->address;
+ s.addend = loc[i]->addend;
+ if ((s.name == BFD_ABS_SECTION_NAME) ||
+ (this->symbols.find(s.name) != this->symbols.end()))
+ {
+ s.type = Symbol::RELATIVE;
+ }
+ else
+ {
+ s.type = Symbol::UNRESOLVED;
+ }
+ this->relocs.push_back(s);
+
+ cout << "\tSymbol: " << loc[i]->sym_ptr_ptr[0]->name;
+ cout << "\tAddress: " << std::hex << loc[i]->address << ", "
+ << loc[i]->addend << endl;
+ }
+
+cleanup:
+ if (NULL != loc)
+ free(loc);
+ if (NULL != syms)
+ free(syms);
+
+ return true;
+}
+
+bool Object::perform_local_relocations(FILE* file)
+{
+ cout << "File " << name << endl;
+
+ for(vector<Symbol>::iterator i = relocs.begin();
+ i != relocs.end();
+ ++i)
+ {
+ if (i->type & Symbol::UNRESOLVED)
+ continue;
+
+ cout << "\tSymbol: " << i->name << endl;
+
+ uint64_t relocation = i->addend + offset;
+ uint64_t address = 0;
+ char data[sizeof(uint64_t)];
+
+ fseek(file, offset + i->address, SEEK_SET);
+ fread(data, sizeof(uint64_t), 1, file);
+
+ address = bfd_getb64(data);
+ if (address != i->addend)
+ {
+ cout << "Expected " << i->addend << " found " << address << endl;
+ continue;
+ }
+
+ address = relocation;
+ bfd_putb64(address, data);
+
+ fseek(file, offset + i->address, SEEK_SET);
+ fwrite(data, sizeof(uint64_t), 1, file);
+
+ cout << "\tRelocated " << i->addend << " to "
+ << relocation << endl;
+ }
+}
+
+bool Object::perform_global_relocations(FILE* file)
+{
+ cout << "File " << name << endl;
+
+ for(vector<Symbol>::iterator i = relocs.begin();
+ i != relocs.end();
+ ++i)
+ {
+ if (!(i->type & Symbol::UNRESOLVED))
+ continue;
+
+ cout << "\tSymbol: " << i->name << endl;
+
+ char data[sizeof(uint64_t)*3];
+
+ for(vector<Object>::iterator j = objects.begin();
+ j != objects.end();
+ ++j)
+ {
+ if (j->symbols.find(i->name) != j->symbols.end())
+ {
+ Symbol s = j->symbols[i->name];
+ uint64_t symbol_addr =
+ j->offset + s.address + j->data.vma_offset;
+
+ if (s.type & Symbol::UNRESOLVED)
+ continue;
+ if (s.type & Symbol::LOCAL)
+ continue;
+ if (!(s.type & Symbol::GLOBAL))
+ continue;
+
+ if (s.type & Symbol::FUNCTION)
+ {
+ fseek(file, symbol_addr, SEEK_SET);
+ fread(data, sizeof(uint64_t), 3, file);
+
+ fseek(file, offset + i->address, SEEK_SET);
+ fwrite(data, sizeof(uint64_t), 3, file);
+
+ cout << "\tCopied relocation from " << std::hex
+ << symbol_addr << " to "
+ << offset + i->address << "." << endl;
+ }
+ else
+ {
+ bfd_putb64(symbol_addr, data);
+ fseek(file, offset + i->address, SEEK_SET);
+ fwrite(data, sizeof(uint64_t), 1, file);
+
+ cout << "\tRelocated from " << std::hex
+ << symbol_addr << " to "
+ << offset + i->address << "." << endl;
+ }
+ break;
+ }
+ }
+ }
+}
+
+uint64_t Object::find_init_symbol()
+{
+ if (symbols.find(VFS_TOSTRING(VFS_SYMBOL_INIT)) == symbols.end())
+ return 0;
+
+ return symbols[VFS_TOSTRING(VFS_SYMBOL_INIT)].address +
+ offset + data.vma_offset;
+}
+
+uint64_t Object::find_start_symbol()
+{
+ if (symbols.find(VFS_TOSTRING(VFS_SYMBOL_START)) == symbols.end())
+ return 0;
+
+ return symbols[VFS_TOSTRING(VFS_SYMBOL_START)].address +
+ offset + data.vma_offset;
+}
diff --git a/src/bld/makefile b/src/bld/makefile
index 37fd2e4b1..d80e2b533 100644
--- a/src/bld/makefile
+++ b/src/bld/makefile
@@ -1,5 +1,5 @@
linker: linker.C
- g++ -O3 linker.C -o linker -lbfd
+ g++ -O3 -g linker.C -o linker -lbfd -I../include/sys
all: linker
diff --git a/src/include/sys/vfs.h b/src/include/sys/vfs.h
index 579b9ba34..e596030fe 100644
--- a/src/include/sys/vfs.h
+++ b/src/include/sys/vfs.h
@@ -3,6 +3,13 @@
#include <stdint.h>
+#define VFS_MODULE_MAX 128
+#define VFS_MODULE_NAME_MAX 64
+#define VFS_SYMBOL_INIT _init
+#define VFS_SYMBOL_START _start
+#define VFS_STRINGIFY(X) #X
+#define VFS_TOSTRING(X) VFS_STRINGIFY(X)
+
#ifdef __cplusplus
extern "C"
{
@@ -19,6 +26,17 @@ enum VfsMessages
VFS_MSG_RESOLVE_MSGQ,
};
+struct VfsSystemModule
+{
+ const char module[VFS_MODULE_NAME_MAX];
+ void (*init)(void*);
+ void (*start)(void*);
+};
+
+extern VfsSystemModule VFS_MODULES[VFS_MODULE_MAX];
+extern uint64_t VFS_LAST_ADDRESS;
+
+
#ifdef __cplusplus
}
#endif
diff --git a/src/kernel/pagemgr.C b/src/kernel/pagemgr.C
index 022b642b0..2a92df206 100644
--- a/src/kernel/pagemgr.C
+++ b/src/kernel/pagemgr.C
@@ -1,6 +1,7 @@
#include <kernel/pagemgr.H>
#include <util/singleton.H>
#include <kernel/console.H>
+#include <sys/vfs.h>
void PageManager::init()
{
@@ -21,11 +22,8 @@ void PageManager::freePage(void* p, size_t n)
PageManager::PageManager()
{
- // NOTE: This will need to change once we support loading modules.
-
// Determine first page of un-allocated memory.
- extern void* end_load_address;
- uint64_t addr = (uint64_t)&end_load_address;
+ uint64_t addr = (uint64_t) VFS_LAST_ADDRESS;
if (0 != (addr % PAGESIZE))
addr = (addr - (addr % PAGESIZE)) + PAGESIZE;
diff --git a/src/makefile b/src/makefile
index 6045de28b..4117b7946 100644
--- a/src/makefile
+++ b/src/makefile
@@ -2,7 +2,7 @@ ROOTPATH = ..
IMGDIR = ${ROOTPATH}/img
OBJDIR = ${ROOTPATH}/obj/hbicore
-SUBDIRS = kernel.d lib.d libc++.d sys.d bld.d
+SUBDIRS = kernel.d lib.d libc++.d sys.d usr.d bld.d
IMAGES += ${IMGDIR}/hbicore.elf
IMAGES += ${IMGDIR}/hbicore.bin
diff --git a/src/module.ld b/src/module.ld
new file mode 100644
index 000000000..f94f97218
--- /dev/null
+++ b/src/module.ld
@@ -0,0 +1,35 @@
+SECTIONS
+{
+ .text : {
+ *(.text)
+ *(.text._*)
+ *(.rodata)
+ *(.rodata.*)
+ *(.glink)
+
+ . = ALIGN(0x8);
+ ctor_start_address = .;
+ *(.ctors)
+ ctor_end_address = .;
+ }
+
+ .data ALIGN(0x1000): {
+ *(.data)
+ *(.data.*)
+ *(.branch_lt)
+ *(.toc)
+ *(.opd)
+ *(.got)
+ *(.plt)
+ *(.bss)
+ *(.bss.*)
+ }
+
+ .rela : {
+ *(.rela.*)
+ }
+
+ /DISCARD/ : {
+ *(.dtors)
+ }
+}
diff --git a/src/sys/init/init_main.C b/src/sys/init/init_main.C
index 4be986ba7..72bfc64a8 100644
--- a/src/sys/init/init_main.C
+++ b/src/sys/init/init_main.C
@@ -25,7 +25,7 @@ void init_main(void* unused)
printk("Bringing up VFS...");
task_create(&vfs_main, NULL);
task_yield(); // TODO... add a barrier to ensure VFS is fully up.
-
+/*
uint64_t* mmio_addr = (uint64_t*) mmio_map((void*)0x800000000, 1);
printk("MMIO Access %llx\n", *mmio_addr);
@@ -49,4 +49,8 @@ void init_main(void* unused)
for (volatile int i = 0 ; i < 1000000; i++);
mutex_unlock(global_mutex);
}
+*/
+
+ while(1)
+ task_yield();
}
diff --git a/src/sys/vfs/vfs_main.C b/src/sys/vfs/vfs_main.C
index 6ba561eb2..481df1101 100644
--- a/src/sys/vfs/vfs_main.C
+++ b/src/sys/vfs/vfs_main.C
@@ -10,6 +10,8 @@ const char* VFS_ROOT = "/";
const char* VFS_ROOT_BIN = "/bin/";
const char* VFS_ROOT_DATA = "/data/";
const char* VFS_ROOT_MSG = "/msg/";
+VfsSystemModule VFS_MODULES[VFS_MODULE_MAX];
+uint64_t VFS_LAST_ADDRESS;
struct VfsPath
{
@@ -28,13 +30,34 @@ struct VfsEntry
VfsEntry* prev;
};
+void vfs_module_init()
+{
+ printk("Initializing modules.\n");
+
+ VfsSystemModule* module = &VFS_MODULES[0];
+ while ('\0' != module->module[0])
+ {
+ printk("\tIniting module %s...", module->module);
+ (module->init)(NULL);
+ printk("done.\n");
+
+ module++;
+ }
+
+ printk("Modules initialized.");
+}
+
void vfs_main(void* unused)
{
+ // Create message queue, register with kernel.
msg_q_t vfsMsgQ = msg_q_create();
msg_q_register(vfsMsgQ, VFS_ROOT);
printk("done.\n");
// TODO... barrier with init.
+
+ // Initalize modules.
+ vfs_module_init();
Util::Locked::List<VfsEntry, VfsEntry::key_type> vfsContents;
diff --git a/src/usr/example/example.C b/src/usr/example/example.C
new file mode 100644
index 000000000..18095ac5b
--- /dev/null
+++ b/src/usr/example/example.C
@@ -0,0 +1,28 @@
+#include <kernel/console.H>
+#include <sys/mutex.h>
+#include <sys/vfs.h>
+#include <sys/task.h>
+
+static mutex_t value = mutex_create();
+
+extern "C"
+void _init(void*)
+{
+ // Call default constructors for any static objects.
+ extern void (*ctor_start_address)();
+ extern void (*ctor_end_address)();
+ void(**ctors)() = &ctor_start_address;
+ while(ctors != &ctor_end_address)
+ {
+ (*ctors)();
+ ctors++;
+ }
+
+ printk("Here! %llx, %s\n", (uint64_t) value, VFS_ROOT);
+}
+
+extern "C"
+void _start(void*)
+{
+ task_end();
+}
diff --git a/src/usr/example/makefile b/src/usr/example/makefile
new file mode 100644
index 000000000..608aacc87
--- /dev/null
+++ b/src/usr/example/makefile
@@ -0,0 +1,16 @@
+ROOTPATH = ../../..
+OBJDIR = ${ROOTPATH}/obj/modules/example
+IMGDIR = ${ROOTPATH}/img
+EXTRACOMMONFLAGS = -fPIC
+
+OBJS = example.o
+OBJECTS = $(addprefix ${OBJDIR}/, ${OBJS})
+LIBS = libexample.so
+LIBRARIES = $(addprefix ${IMGDIR}/, ${LIBS})
+
+all: ${OBJECTS} ${LIBRARIES}
+
+clean:
+ (rm -f ${OBJECTS} ${LIBRARIES} )
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/makefile b/src/usr/makefile
new file mode 100644
index 000000000..e6907fe8c
--- /dev/null
+++ b/src/usr/makefile
@@ -0,0 +1,9 @@
+ROOTPATH = ../..
+
+SUBDIRS = example.d
+
+all: ${SUBDIRS}
+
+clean: $(patsubst %.d,%.clean, ${SUBDIRS})
+
+include ../../config.mk
OpenPOWER on IntegriCloud