diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_init_elf64.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_init_elf64.hpp deleted file mode 100644 index 33ef192..0000000 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_init_elf64.hpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2018-2019 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -/* -From musl include/elf.h - -Copyright © 2005-2014 Rich Felker, et al. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#pragma once -#include - -namespace ams::kern::init::Elf::Elf64 { - - /* Type declarations required to perform relocations */ - using Half = u16; - using Word = u32; - using Sword = s32; - using Xword = u64; - using SXword = s64; - - using Addr = u64; - using Off = u64; - - class Dyn { - private: - SXword tag; - union { - Xword value; - Addr ptr; - }; - public: - constexpr ALWAYS_INLINE SXword GetTag() const { - return this->tag; - } - - constexpr ALWAYS_INLINE Xword GetValue() const { - return this->value; - } - - constexpr ALWAYS_INLINE Addr GetPtr() const { - return this->ptr; - } - }; - - class Rel { - private: - Addr offset; - Xword info; - public: - constexpr ALWAYS_INLINE Addr GetOffset() const { - return this->offset; - } - - constexpr ALWAYS_INLINE Xword GetSym() const { - return this->info >> 32; - } - - constexpr ALWAYS_INLINE Xword GetType() const { - return this->info & 0xFFFFFFFF; - } - }; - - class Rela { - private: - Addr offset; - Xword info; - SXword addend; - public: - constexpr ALWAYS_INLINE Addr GetOffset() const { - return this->offset; - } - - constexpr ALWAYS_INLINE Xword GetSym() const { - return this->info >> 32; - } - - constexpr ALWAYS_INLINE Xword GetType() const { - return this->info & 0xFFFFFFFF; - } - - constexpr ALWAYS_INLINE SXword GetAddend() const { - return this->addend; - } - }; - - enum DynamicTag { - DT_NULL = 0, - DT_RELA = 7, - DT_RELAENT = 9, - DT_REL = 17, - DT_RELENT = 19, - - DT_RELACOUNT = 0x6ffffff9, - DT_RELCOUNT = 0x6ffffffa - }; - - enum RelocationType { - R_AARCH64_RELATIVE = 0x403, - }; - - /* API to apply relocations or call init array. */ - void ApplyRelocations(uintptr_t base_address, const Dyn *dynamic); - void CallInitArrayFuncs(uintptr_t init_array_start, uintptr_t init_array_end); - -} \ No newline at end of file diff --git a/libraries/libmesosphere/include/mesosphere/init/kern_init_elf.hpp b/libraries/libmesosphere/include/mesosphere/init/kern_init_elf.hpp index 2ee1e00..1e226cc 100644 --- a/libraries/libmesosphere/include/mesosphere/init/kern_init_elf.hpp +++ b/libraries/libmesosphere/include/mesosphere/init/kern_init_elf.hpp @@ -17,17 +17,25 @@ #include #ifdef ATMOSPHERE_ARCH_ARM64 - - #include "../arch/arm64/init/kern_init_elf64.hpp" - + #include "kern_init_elf64.hpp" #else - #error "Unknown Architecture" - #endif namespace ams::kern::init::Elf { - /* TODO: Anything we want inside this namespace? */ + #ifdef ATMOSPHERE_ARCH_ARM64 + using namespace ams::kern::init::Elf::Elf64; + + enum RelocationType { + R_ARCHITECTURE_RELATIVE = 0x403, /* Real name R_AARCH64_RELATIVE */ + }; + #else + #error "Unknown Architecture" + #endif + + /* API to apply relocations or call init array. */ + void ApplyRelocations(uintptr_t base_address, const Dyn *dynamic); + void CallInitArrayFuncs(uintptr_t init_array_start, uintptr_t init_array_end); } \ No newline at end of file diff --git a/libraries/libmesosphere/include/mesosphere/init/kern_init_elf64.hpp b/libraries/libmesosphere/include/mesosphere/init/kern_init_elf64.hpp new file mode 100644 index 0000000..84a0b25 --- /dev/null +++ b/libraries/libmesosphere/include/mesosphere/init/kern_init_elf64.hpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/* +From musl include/elf.h + +Copyright © 2005-2014 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#pragma once +#include + +namespace ams::kern::init::Elf::Elf64 { + + /* Type declarations required to perform relocations */ + using Half = u16; + using Word = u32; + using Sword = s32; + using Xword = u64; + using SXword = s64; + + using Addr = u64; + using Off = u64; + + class Dyn { + private: + SXword tag; + union { + Xword value; + Addr ptr; + }; + public: + constexpr ALWAYS_INLINE SXword GetTag() const { + return this->tag; + } + + constexpr ALWAYS_INLINE Xword GetValue() const { + return this->value; + } + + constexpr ALWAYS_INLINE Addr GetPtr() const { + return this->ptr; + } + }; + + class Rel { + private: + Addr offset; + Xword info; + public: + constexpr ALWAYS_INLINE Addr GetOffset() const { + return this->offset; + } + + constexpr ALWAYS_INLINE Xword GetSym() const { + return this->info >> 32; + } + + constexpr ALWAYS_INLINE Xword GetType() const { + return this->info & 0xFFFFFFFF; + } + }; + + class Rela { + private: + Addr offset; + Xword info; + SXword addend; + public: + constexpr ALWAYS_INLINE Addr GetOffset() const { + return this->offset; + } + + constexpr ALWAYS_INLINE Xword GetSym() const { + return this->info >> 32; + } + + constexpr ALWAYS_INLINE Xword GetType() const { + return this->info & 0xFFFFFFFF; + } + + constexpr ALWAYS_INLINE SXword GetAddend() const { + return this->addend; + } + }; + + enum DynamicTag { + DT_NULL = 0, + DT_RELA = 7, + DT_RELAENT = 9, + DT_REL = 17, + DT_RELENT = 19, + + DT_RELACOUNT = 0x6ffffff9, + DT_RELCOUNT = 0x6ffffffa + }; + +} diff --git a/libraries/libmesosphere/source/arch/arm64/init/kern_init_elf64.cpp b/libraries/libmesosphere/source/arch/arm64/init/kern_init_elf64.cpp deleted file mode 100644 index 6f84676..0000000 --- a/libraries/libmesosphere/source/arch/arm64/init/kern_init_elf64.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2018-2019 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include - -namespace ams::kern::init::Elf::Elf64 { - - /* API to apply relocations or call init array. */ - void ApplyRelocations(uintptr_t base_address, const Dyn *dynamic) { - uintptr_t dyn_rel = 0; - uintptr_t dyn_rela = 0; - uintptr_t rel_count = 0; - uintptr_t rela_count = 0; - uintptr_t rel_ent = 0; - uintptr_t rela_ent = 0; - - /* Iterate over all tags, identifying important extents. */ - for (const Dyn *cur_entry = dynamic; cur_entry->GetTag() != DT_NULL; cur_entry++) { - switch (cur_entry->GetTag()) { - case DT_REL: - dyn_rel = base_address + cur_entry->GetPtr(); - break; - case DT_RELA: - dyn_rela = base_address + cur_entry->GetPtr(); - break; - case DT_RELENT: - rel_ent = cur_entry->GetValue(); - break; - case DT_RELAENT: - rela_ent = cur_entry->GetValue(); - break; - case DT_RELCOUNT: - rel_count = cur_entry->GetValue(); - break; - case DT_RELACOUNT: - rela_count = cur_entry->GetValue(); - break; - } - } - - /* Apply all Rel relocations */ - for (size_t i = 0; i < rel_count; i++) { - const auto &rel = *reinterpret_cast(dyn_rel + rel_ent * i); - - /* Only allow R_AARCH64_RELATIVE relocations. */ - while (rel.GetType() != R_AARCH64_RELATIVE) { /* ... */ } - - /* Apply the relocation. */ - Elf64::Addr *target_address = reinterpret_cast(base_address + rel.GetOffset()); - *target_address += base_address; - } - - /* Apply all Rela relocations. */ - for (size_t i = 0; i < rela_count; i++) { - const auto &rela = *reinterpret_cast(dyn_rela + rela_ent * i); - - /* Only allow R_AARCH64_RELATIVE relocations. */ - while (rela.GetType() != R_AARCH64_RELATIVE) { /* ... */ } - - /* Apply the relocation. */ - Elf64::Addr *target_address = reinterpret_cast(base_address + rela.GetOffset()); - *target_address = base_address + rela.GetAddend(); - } - } - - void CallInitArrayFuncs(uintptr_t init_array_start, uintptr_t init_array_end) { - for (uintptr_t cur_entry = init_array_start; cur_entry < init_array_end; cur_entry += sizeof(void *)) { - (*(void (**)())(cur_entry))(); - } - } - -} \ No newline at end of file diff --git a/libraries/libmesosphere/source/init/kern_init_elf.cpp b/libraries/libmesosphere/source/init/kern_init_elf.cpp new file mode 100644 index 0000000..1eb6df6 --- /dev/null +++ b/libraries/libmesosphere/source/init/kern_init_elf.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include + +namespace ams::kern::init::Elf { + + /* API to apply relocations or call init array. */ + void ApplyRelocations(uintptr_t base_address, const Dyn *dynamic) { + uintptr_t dyn_rel = 0; + uintptr_t dyn_rela = 0; + uintptr_t rel_count = 0; + uintptr_t rela_count = 0; + uintptr_t rel_ent = 0; + uintptr_t rela_ent = 0; + + /* Iterate over all tags, identifying important extents. */ + for (const Dyn *cur_entry = dynamic; cur_entry->GetTag() != DT_NULL; cur_entry++) { + switch (cur_entry->GetTag()) { + case DT_REL: + dyn_rel = base_address + cur_entry->GetPtr(); + break; + case DT_RELA: + dyn_rela = base_address + cur_entry->GetPtr(); + break; + case DT_RELENT: + rel_ent = cur_entry->GetValue(); + break; + case DT_RELAENT: + rela_ent = cur_entry->GetValue(); + break; + case DT_RELCOUNT: + rel_count = cur_entry->GetValue(); + break; + case DT_RELACOUNT: + rela_count = cur_entry->GetValue(); + break; + } + } + + /* Apply all Rel relocations */ + for (size_t i = 0; i < rel_count; i++) { + const auto &rel = *reinterpret_cast(dyn_rel + rel_ent * i); + + /* Only allow architecture-specific relocations. */ + while (rel.GetType() != R_ARCHITECTURE_RELATIVE) { /* ... */ } + + /* Apply the relocation. */ + Elf::Addr *target_address = reinterpret_cast(base_address + rel.GetOffset()); + *target_address += base_address; + } + + /* Apply all Rela relocations. */ + for (size_t i = 0; i < rela_count; i++) { + const auto &rela = *reinterpret_cast(dyn_rela + rela_ent * i); + + /* Only allow architecture-specific relocations. */ + while (rela.GetType() != R_ARCHITECTURE_RELATIVE) { /* ... */ } + + /* Apply the relocation. */ + Elf::Addr *target_address = reinterpret_cast(base_address + rela.GetOffset()); + *target_address = base_address + rela.GetAddend(); + } + } + + void CallInitArrayFuncs(uintptr_t init_array_start, uintptr_t init_array_end) { + for (uintptr_t cur_entry = init_array_start; cur_entry < init_array_end; cur_entry += sizeof(void *)) { + (*(void (**)())(cur_entry))(); + } + } + +} \ No newline at end of file diff --git a/mesosphere/kernel_ldr/source/kern_init_loader.cpp b/mesosphere/kernel_ldr/source/kern_init_loader.cpp index f42e80f..7b7d5c5 100644 --- a/mesosphere/kernel_ldr/source/kern_init_loader.cpp +++ b/mesosphere/kernel_ldr/source/kern_init_loader.cpp @@ -320,14 +320,14 @@ std::memset(GetVoidPointer(virtual_base_address + bss_offset), 0, bss_end_offset - bss_offset); /* Apply relocations to the kernel. */ - const Elf::Elf64::Dyn *kernel_dynamic = reinterpret_cast(GetInteger(virtual_base_address) + dynamic_offset); - Elf::Elf64::ApplyRelocations(GetInteger(virtual_base_address), kernel_dynamic); + const Elf::Dyn *kernel_dynamic = reinterpret_cast(GetInteger(virtual_base_address) + dynamic_offset); + Elf::ApplyRelocations(GetInteger(virtual_base_address), kernel_dynamic); /* Reprotect .rodata as R-- */ ttbr1_table.Reprotect(virtual_base_address + ro_offset, ro_end_offset - ro_offset, KernelRwDataAttribute, KernelRoDataAttribute); /* Call the kernel's init array functions. */ - Elf::Elf64::CallInitArrayFuncs(GetInteger(virtual_base_address) + init_array_offset, GetInteger(virtual_base_address) + init_array_end_offset); + Elf::CallInitArrayFuncs(GetInteger(virtual_base_address) + init_array_offset, GetInteger(virtual_base_address) + init_array_end_offset); /* Return the difference between the random virtual base and the physical base. */ return GetInteger(virtual_base_address) - base_address; diff --git a/mesosphere/kernel_ldr/source/start.s b/mesosphere/kernel_ldr/source/start.s index f8aed3d..3812c3e 100644 --- a/mesosphere/kernel_ldr/source/start.s +++ b/mesosphere/kernel_ldr/source/start.s @@ -48,17 +48,17 @@ ldr x1, [x1, #0x18] /* .dynamic. */ add x1, x0, x1 - /* branch to ams::kern::init::Elf::Elf64::ApplyRelocations(uintptr_t, const ams::kern::init::Elf::Elf64::Dyn *); */ - bl _ZN3ams4kern4init3Elf5Elf6416ApplyRelocationsEmPKNS3_3DynE + /* branch to ams::kern::init::Elf::ApplyRelocations(uintptr_t, const ams::kern::init::Elf::Elf64::Dyn *); */ + bl _ZN3ams4kern4init3Elf16ApplyRelocationsEmPKNS2_5Elf643DynE - /* branch to ams::kern::init::Elf::Elf64::CallInitArrayFuncs(uintptr_t, uintptr_t) */ + /* branch to ams::kern::init::Elf::CallInitArrayFuncs(uintptr_t, uintptr_t) */ adr x2, _start adr x1, __external_references ldr x0, [x1, #0x20] /* init_array_start */ ldr x1, [x1, #0x28] /* init_array_end */ add x0, x0, x2 add x1, x1, x2 - bl _ZN3ams4kern4init3Elf5Elf6418CallInitArrayFuncsEmm + bl _ZN3ams4kern4init3Elf18CallInitArrayFuncsEmm /* Setup system registers, for detection of errors during init later. */ msr tpidr_el1, xzr /* Clear TPIDR_EL1 */