summaryrefslogtreecommitdiff
path: root/linker/linker_main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linker/linker_main.cpp')
-rw-r--r--linker/linker_main.cpp39
1 files changed, 37 insertions, 2 deletions
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 98af54ac2..2a690e9a0 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -31,9 +31,10 @@
#include <link.h>
#include <sys/auxv.h>
+#include "linker.h"
+#include "linker_cfi.h"
#include "linker_debug.h"
#include "linker_debuggerd.h"
-#include "linker_cfi.h"
#include "linker_gdb_support.h"
#include "linker_globals.h"
#include "linker_phdr.h"
@@ -66,6 +67,8 @@ static void get_elf_base_from_phdr(const ElfW(Phdr)* phdr_table, size_t phdr_cou
static void set_bss_vma_name(soinfo* si);
+void __libc_init_mte(const void* phdr_start, size_t phdr_count, uintptr_t load_bias);
+
// These should be preserved static to avoid emitting
// RELATIVE relocations for the part of the code running
// before linker links itself.
@@ -297,6 +300,13 @@ static ExecutableInfo load_executable(const char* orig_path) {
return result;
}
+static void platform_properties_init() {
+#if defined(__aarch64__)
+ const unsigned long hwcap2 = getauxval(AT_HWCAP2);
+ g_platform_properties.bti_supported = (hwcap2 & HWCAP2_BTI) != 0;
+#endif
+}
+
static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load) {
ProtectedDataGuard guard;
@@ -311,6 +321,9 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load
// Initialize system properties
__system_properties_init(); // may use 'environ'
+ // Initialize platform properties.
+ platform_properties_init();
+
// Register the debuggerd signal handler.
linker_debuggerd_init();
@@ -381,6 +394,22 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load
solinker->set_realpath(interp);
init_link_map_head(*solinker);
+#if defined(__aarch64__)
+ if (exe_to_load == nullptr) {
+ // Kernel does not add PROT_BTI to executable pages of the loaded ELF.
+ // Apply appropriate protections here if it is needed.
+ auto note_gnu_property = GnuPropertySection(somain);
+ if (note_gnu_property.IsBTICompatible() &&
+ (phdr_table_protect_segments(somain->phdr, somain->phnum, somain->load_bias,
+ &note_gnu_property) < 0)) {
+ __linker_error("error: can't protect segments for \"%s\": %s", exe_info.path.c_str(),
+ strerror(errno));
+ }
+ }
+
+ __libc_init_mte(somain->phdr, somain->phnum, somain->load_bias);
+#endif
+
// Register the main executable and the linker upfront to have
// gdb aware of them before loading the rest of the dependency
// tree.
@@ -460,7 +489,6 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load
RTLD_GLOBAL,
nullptr,
true /* add_as_children */,
- true /* search_linked_namespaces */,
&namespaces)) {
__linker_cannot_link(g_argv[0]);
} else if (needed_libraries_count == 0) {
@@ -698,6 +726,13 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so)
// Initialize the linker's own global variables
tmp_linker_so.call_constructors();
+ // Setting the linker soinfo's soname can allocate heap memory, so delay it until here.
+ for (const ElfW(Dyn)* d = tmp_linker_so.dynamic; d->d_tag != DT_NULL; ++d) {
+ if (d->d_tag == DT_SONAME) {
+ tmp_linker_so.set_soname(tmp_linker_so.get_string(d->d_un.d_val));
+ }
+ }
+
// When the linker is run directly rather than acting as PT_INTERP, parse
// arguments and determine the executable to load. When it's instead acting
// as PT_INTERP, AT_ENTRY will refer to the loaded executable rather than the