diff --git a/repos/base-hw/mk/spec/hw_riscv.mk b/repos/base-hw/mk/spec/hw_riscv.mk index 81180a2da5..1c3ece6624 100644 --- a/repos/base-hw/mk/spec/hw_riscv.mk +++ b/repos/base-hw/mk/spec/hw_riscv.mk @@ -1,6 +1,6 @@ SPECS += hw riscv platform_riscv 64bit -LD_TEXT_ADDR ?= 0x1000 +LD_TEXT_ADDR ?= 0x1000000 CORE_LD_TEXT_ADDR = 0x200 NR_OF_CPUS = 1 REP_INC_DIR += include/spec/riscv diff --git a/repos/base-hw/src/core/spec/riscv/kernel/thread.cc b/repos/base-hw/src/core/spec/riscv/kernel/thread.cc index fc96d4ce68..b17f29cad0 100644 --- a/repos/base-hw/src/core/spec/riscv/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/riscv/kernel/thread.cc @@ -35,8 +35,8 @@ void Thread::exception(unsigned const cpu) _mmu_exception(); break; default: - PWRN("%s -> %s: unhandled exception %lu at ip=%lx", - pd_label(), label(), cpu_exception, ip); + PWRN("%s -> %s: unhandled exception %lu at ip=%lx addr=%lx", + pd_label(), label(), cpu_exception, ip, Cpu::sbadaddr()); _stop(); } } diff --git a/repos/base/lib/mk/spec/riscv/ld.mk b/repos/base/lib/mk/spec/riscv/ld.mk new file mode 100644 index 0000000000..fd72cc99b3 --- /dev/null +++ b/repos/base/lib/mk/spec/riscv/ld.mk @@ -0,0 +1,6 @@ +REQUIRES = riscv + +include $(REP_DIR)/lib/mk/ldso.inc + +INC_DIR += $(DIR)/spec/riscv +vpath %.s $(DIR)/spec/riscv diff --git a/repos/base/src/lib/ldso/include/dynamic_generic.h b/repos/base/src/lib/ldso/include/dynamic_generic.h new file mode 100644 index 0000000000..265b16a3d1 --- /dev/null +++ b/repos/base/src/lib/ldso/include/dynamic_generic.h @@ -0,0 +1,49 @@ +/** + * \brief Generic dynamic section address handling + * \author Sebastian Sumpf + * \date 2016-02-17 + */ + +/* + * Copyright (C) 2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__DYNAMIC_GENERIC_H_ +#define _INCLUDE__DYNAMIC_GENERIC_H_ + +extern const unsigned long _GLOBAL_OFFSET_TABLE_[] __attribute__((visibility("hidden"))); +extern unsigned long _DYNAMIC[] __attribute__((visibility("hidden"))); + +namespace Linker { + + /** + * Address of .dynamic section in GOT + */ + static inline unsigned long dynamic_address_got() + { + return _GLOBAL_OFFSET_TABLE_[0]; + } + + /** + * Address of .dynamic section from symbol + */ + static inline unsigned long dynamic_address() + { + return (unsigned long)&_DYNAMIC; + } + + /** + * Return the run-time load address of the shared object. + */ + static inline unsigned long relocation_address(void) + { + return dynamic_address() < dynamic_address_got() ? + dynamic_address_got() - dynamic_address() : + dynamic_address() - dynamic_address_got(); + } +} + +#endif /* _INCLUDE__DYNAMIC_GENERIC_H_ */ diff --git a/repos/base/src/lib/ldso/include/elf.h b/repos/base/src/lib/ldso/include/elf.h index 8df92968b8..73cb934462 100644 --- a/repos/base/src/lib/ldso/include/elf.h +++ b/repos/base/src/lib/ldso/include/elf.h @@ -445,7 +445,7 @@ namespace Linker { /** * Define bit-width independent types */ -#ifdef __x86_64__ +#ifdef _LP64 namespace Elf = Linker::Elf64; #define ELFCLASS ELFCLASS64 #define EFMT "%llx" diff --git a/repos/base/src/lib/ldso/include/linker.h b/repos/base/src/lib/ldso/include/linker.h index f0f7e2f84a..2507de1e66 100644 --- a/repos/base/src/lib/ldso/include/linker.h +++ b/repos/base/src/lib/ldso/include/linker.h @@ -34,9 +34,6 @@ constexpr bool verbose_exception = false; constexpr bool verbose_shared = false; constexpr bool verbose_loading = false; - -extern const unsigned long _GLOBAL_OFFSET_TABLE_[] __attribute__((visibility("hidden"))); -extern unsigned long _DYNAMIC[] __attribute__((visibility("hidden"))); extern Elf::Addr etext; /** @@ -131,32 +128,6 @@ namespace Linker { */ constexpr char const *binary_name() { return "binary"; } constexpr char const *linker_name() { return "ld.lib.so"; } - - /** - * Address of .dynamic section in GOT - */ - static inline unsigned long dynamic_address_got() - { - return _GLOBAL_OFFSET_TABLE_[0]; - } - - /** - * Address of .dynamic section from symbol - */ - static inline unsigned long dynamic_address() - { - return (unsigned long)&_DYNAMIC; - } - - /** - * Return the run-time load address of the shared object. - */ - static inline unsigned long relocation_address(void) - { - return dynamic_address() < dynamic_address_got() ? - dynamic_address_got() - dynamic_address() : - dynamic_address() - dynamic_address_got(); - } } diff --git a/repos/base/src/lib/ldso/spec/arm/relocation.h b/repos/base/src/lib/ldso/spec/arm/relocation.h index 32f4055cd0..26cbc54b21 100644 --- a/repos/base/src/lib/ldso/spec/arm/relocation.h +++ b/repos/base/src/lib/ldso/spec/arm/relocation.h @@ -15,6 +15,7 @@ #define _LIB__LDSO__SPEC__ARM__RELOCATION_H_ #include +#include namespace Linker { enum Reloc_types { diff --git a/repos/base/src/lib/ldso/spec/riscv/jmp_slot.s b/repos/base/src/lib/ldso/spec/riscv/jmp_slot.s new file mode 100644 index 0000000000..a811a76962 --- /dev/null +++ b/repos/base/src/lib/ldso/spec/riscv/jmp_slot.s @@ -0,0 +1,23 @@ +/** + * \brief Jump slot entry code for RISC-V + * \author Sebastian Sumpf + * \date 2015-09-07 + */ + +/* + * Copyright (C) 2015-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +.text +.globl _jmp_slot +.type _jmp_slot,%function +/* + * stack[0] = RA + * ip = &GOT[n+3] + * lr = &GOT[2] + */ +_jmp_slot: + jal jmp_slot diff --git a/repos/base/src/lib/ldso/spec/riscv/relocation.h b/repos/base/src/lib/ldso/spec/riscv/relocation.h new file mode 100644 index 0000000000..435345ea4c --- /dev/null +++ b/repos/base/src/lib/ldso/spec/riscv/relocation.h @@ -0,0 +1,111 @@ +/** + * \brief RISC-V 64 specific relocations + * \author Sebastian Sumpf + * \date 2015-09-07 + */ + +/* + * Copyright (C) 2015-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__RISCV_64__RELOCATION_H_ +#define _INCLUDE__RISCV_64__RELOCATION_H_ + +#include + +namespace Linker { + + inline unsigned long dynamic_address() + { + unsigned long addr; + asm volatile ("lla %0, _DYNAMIC" : "=r"(addr)); + return addr; + } + + inline unsigned long relocation_address(void) { return 0; } + +/** + * Relocation types + */ + enum Reloc_types { + R_64 = 2, /* add 64 bit symbol valu with addend */ + R_RELATIVE = 3, /* add load addr of shared object */ + R_JMPSLOT = 5, /* jump slot */ + }; + + class Reloc_non_plt; + + typedef Reloc_plt_generic Reloc_plt; + typedef Reloc_jmpslot_generic Reloc_jmpslot; + typedef Reloc_bind_now_generic Reloc_bind_now; +}; + +class Linker::Reloc_non_plt : public Reloc_non_plt_generic +{ + private: + /** + * Relative relocation (reloc base + addend) + */ + void _relative(Elf::Rela const *rel, Elf::Addr *addr) + { + *addr = _dep->obj->reloc_base() + rel->addend; + } + + /** + * GOT entry to data address or 64 bit symbol (addend = true), + * (reloc base of containing ojbect + symbol value (+ addend) + */ + void _glob_dat_64(Elf::Rela const *rel, Elf::Addr *addr, bool addend) + { + Elf::Addr reloc_base; + Elf::Sym const *sym; + + if (!(sym = lookup_symbol(rel->sym(), _dep, &reloc_base))) + return; + + *addr = reloc_base + sym->st_value + (addend ? rel->addend : 0); + if (verbose_reloc(_dep)) + PDBG("GLOB DAT %p -> %llx r %llx v %llx", addr, *addr, reloc_base, + sym->st_value); + } + + public: + + Reloc_non_plt(Dependency const *dep, Elf::Rela const *rel, unsigned long size) + : Reloc_non_plt_generic(dep) + { + Elf::Rela const *end = rel + (size / sizeof(Elf::Rela)); + + for (; rel < end; rel++) { + Elf::Addr *addr = (Elf::Addr *)(_dep->obj->reloc_base() + rel->offset); + + if (verbose_reloc(_dep)) + PDBG("reloc: %p type: %u", rel, rel->type()); + + switch(rel->type()) { + case R_JMPSLOT: _glob_dat_64(rel, addr, false); break; + case R_64: _glob_dat_64(rel, addr, true); break; + case R_RELATIVE: _relative(rel, addr); break; + + default: + if (!_dep->obj->is_linker()) { + PWRN("LD: Unkown relocation %u", rel->type()); + throw Incompatible(); + } + break; + } + } + } + + Reloc_non_plt(Dependency const *dep, Elf::Rel const *, unsigned long, bool) + : Reloc_non_plt_generic(dep) + { + PERR("LD: DT_REL not supported"); + throw Incompatible(); + } +}; + +#endif /* _INCLUDE__RISCV_64__RELOCATION_H_ */ diff --git a/repos/base/src/lib/ldso/spec/x86_32/relocation.h b/repos/base/src/lib/ldso/spec/x86_32/relocation.h index c58f93a8a6..97d1d2e741 100644 --- a/repos/base/src/lib/ldso/spec/x86_32/relocation.h +++ b/repos/base/src/lib/ldso/spec/x86_32/relocation.h @@ -15,6 +15,7 @@ #define _LIB__LDSO__SPEC__X86_32__RELOCATION_H_ #include +#include namespace Linker { diff --git a/repos/base/src/lib/ldso/spec/x86_64/relocation.h b/repos/base/src/lib/ldso/spec/x86_64/relocation.h index 20abf060cd..dc49fea9e0 100644 --- a/repos/base/src/lib/ldso/spec/x86_64/relocation.h +++ b/repos/base/src/lib/ldso/spec/x86_64/relocation.h @@ -15,6 +15,7 @@ #define _LIB__LDSO__SPEC__X86_64__RELOCATION_H_ #include +#include namespace Linker { diff --git a/repos/libports/src/test/ldso/lib_1.cc b/repos/libports/src/test/ldso/lib_1.cc index c3a5f25302..3ffd76ea8a 100644 --- a/repos/libports/src/test/ldso/lib_1.cc +++ b/repos/libports/src/test/ldso/lib_1.cc @@ -116,6 +116,8 @@ static void lib_1_attr_destructor_2() { printf("%s %x\n", __func__, --lib_1_pod static void exception() { throw 666; } void lib_1_exception() { throw Genode::Rm_session::Region_conflict(); } +void lib_1_good() { } + void lib_1_test() {