[compiler-rt] Don't use __libc_stack_end on ARM
authorIlya Leoshkevich <iii@linux.ibm.com>
Wed, 8 Apr 2020 12:25:20 +0000 (14:25 +0200)
committerIlya Leoshkevich <iii@linux.ibm.com>
Wed, 8 Apr 2020 12:25:59 +0000 (14:25 +0200)
Summary:
Commit b684c1a50f70 ("Add a `Symbolizer::GetEnvP()` method that allows
symbolizer implementations to customise the environment of the
symbolizer binary.") exposed a latent ARM issue, and that broke

http://lab.llvm.org:8011/builders/clang-cmake-thumbv7-full-sh

This coincided with breakage caused by my commit 5f5fb56c68e4
("[compiler-rt] Intercept the uname() function"), so I had to
investigate.

The issue is that GetArgsAndEnv does not work on ARM: there glibc's
_start overwrites argc value stored at __libc_start_end, breaking the
existing argv/envp parsing logic.

Fix by inferring argc from argv.

Reviewers: eugenis, vitalybuka

Reviewed By: eugenis

Subscribers: dberris, kristof.beyls, danielkiss, #sanitizers, delcypher

Tags: #sanitizers

Differential Revision: https://reviews.llvm.org/D77400

compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp

index 085b21a..15931e4 100644 (file)
@@ -606,7 +606,12 @@ static void GetArgsAndEnv(char ***argv, char ***envp) {
 #if !SANITIZER_GO
   if (&__libc_stack_end) {
     uptr* stack_end = (uptr*)__libc_stack_end;
-    int argc = *stack_end;
+    // Normally argc can be obtained from *stack_end, however, on ARM glibc's
+    // _start clobbers it:
+    // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/arm/start.S;hb=refs/heads/release/2.31/master#l75
+    // Do not special-case ARM and infer argc from argv everywhere.
+    int argc = 0;
+    while (stack_end[argc + 1]) argc++;
     *argv = (char**)(stack_end + 1);
     *envp = (char**)(stack_end + argc + 2);
   } else {