summaryrefslogtreecommitdiff
path: root/linker/linker_main.cpp
diff options
context:
space:
mode:
authorRyan Prichard <rprichard@google.com>2019-11-05 14:19:18 -0800
committerRyan Prichard <rprichard@google.com>2019-11-05 14:56:09 -0800
commit94a8e859edbd6b470699210eea8712e75fd97f79 (patch)
tree373eb2fb8139055d2f628fb9488d37941dabfbd6 /linker/linker_main.cpp
parent249757bae2b45c845feddee2ba9f794a54d8ea14 (diff)
linker: avoid -O0 memset while clearing temp_tcb
With -O0, on arm64, Clang uses memset for this declaration: bionic_tcb temp_tcb = {}; arm64 doesn't currently have an ifunc for memset, but if it did, then this line would crash when the linker is compiled with -O0. It looks like other architectures would only use a memset call if the bionic_tcb struct were larger. Avoid memset by using a custom memclr function that the compiler optimizes into something efficient. Also add __attribute__((uninitialized)) to ensure that -ftrivial-auto-var-init does not generate a call to memset. See this change[1] in build/soong. [1] If085ec53c619e2cebc86ca23f7039298160d99ae Test: build linker with -O0, linker[64] --help works Bug: none Change-Id: I0df8065a362646de4fa021cae63a7d68ca3966b6
Diffstat (limited to 'linker/linker_main.cpp')
-rw-r--r--linker/linker_main.cpp10
1 files changed, 9 insertions, 1 deletions
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 264923f1d..8ba947f31 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -593,6 +593,13 @@ static void call_ifunc_resolvers(ElfW(Addr) load_bias) {
}
#endif
+// Usable before ifunc resolvers have been called. This function is compiled with -ffreestanding.
+static void linker_memclr(void* dst, size_t cnt) {
+ for (size_t i = 0; i < cnt; ++i) {
+ reinterpret_cast<char*>(dst)[i] = '\0';
+ }
+}
+
// Detect an attempt to run the linker on itself. e.g.:
// /system/bin/linker64 /system/bin/linker64
// Use priority-1 to run this constructor before other constructors.
@@ -626,7 +633,8 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& linker_so);
extern "C" ElfW(Addr) __linker_init(void* raw_args) {
// Initialize TLS early so system calls and errno work.
KernelArgumentBlock args(raw_args);
- bionic_tcb temp_tcb = {};
+ bionic_tcb temp_tcb __attribute__((uninitialized));
+ linker_memclr(&temp_tcb, sizeof(temp_tcb));
__libc_init_main_thread_early(args, &temp_tcb);
// When the linker is run by itself (rather than as an interpreter for