[compiler-rt] r189753 - [sanitizer_common] Add internal_clone().

Sergey Matveev earthdok at google.com
Tue Oct 8 09:29:55 PDT 2013


Apparently .cfi_undefined is not supported by clang 3.2. We only need the
CFI stuff when using the slow unwinder from under StopTheWorld (i.e. if
there's a crash in a StopTheWorld callback and we want to get the
backtrace). So the worst thing that can happen if we remove this line is us
not being able to get the backtrace to an internal crash. That said, I
tried removing all CFI directives from this function and it looks like the
unwinder still works, so I'll probably leave it at that.


On Sat, Oct 5, 2013 at 12:07 AM, Matt Arsenault
<Matthew.Arsenault at amd.com>wrote:

> This has been breaking the build for me for a while (I'm using the
> packaged clang 3.2 on Ubuntu 13.04):
>
> /home/marsenau/src/llvm/**projects/compiler-rt/lib/**
> sanitizer_common/sanitizer_**linux.cc:801:25: error: unknown directive
>                        ".cfi_undefined %%rip;\n"
>                         ^
> <inline asm>:8:1: note: instantiated into assembly here
> .cfi_undefined %rip;
> ^
> [ 14%] 1 error generated.
>
>
>
> On 09/02/2013 04:36 AM, Sergey Matveev wrote:
>
>> Author: smatveev
>> Date: Mon Sep  2 06:36:19 2013
>> New Revision: 189753
>>
>> URL: http://llvm.org/viewvc/llvm-**project?rev=189753&view=rev<http://llvm.org/viewvc/llvm-project?rev=189753&view=rev>
>> Log:
>> [sanitizer_common] Add internal_clone().
>>
>> Add a wrapper for the clone syscall for use in StopTheWorld. We
>> implement it only for x86_64, so stop building StopTheWorld for other
>> platforms
>> (no one uses it outside x86_64 anyway).
>>
>> See https://code.google.com/p/**address-sanitizer/issues/**detail?id=214<https://code.google.com/p/address-sanitizer/issues/detail?id=214>for why we
>> can't use the glibc clone() wrapper.
>>
>> Modified:
>>      compiler-rt/trunk/lib/**sanitizer_common/sanitizer_**linux.cc
>>      compiler-rt/trunk/lib/**sanitizer_common/sanitizer_**linux.h
>>      compiler-rt/trunk/lib/**sanitizer_common/sanitizer_**
>> stoptheworld_linux_libcdep.cc
>>      compiler-rt/trunk/lib/**sanitizer_common/tests/**
>> sanitizer_stoptheworld_test.cc
>>
>> Modified: compiler-rt/trunk/lib/**sanitizer_common/sanitizer_**linux.cc
>> URL: http://llvm.org/viewvc/llvm-**project/compiler-rt/trunk/lib/**
>> sanitizer_common/sanitizer_**linux.cc?rev=189753&r1=189752&**
>> r2=189753&view=diff<http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=189753&r1=189752&r2=189753&view=diff>
>> ==============================**==============================**
>> ==================
>> --- compiler-rt/trunk/lib/**sanitizer_common/sanitizer_**linux.cc
>> (original)
>> +++ compiler-rt/trunk/lib/**sanitizer_common/sanitizer_**linux.cc Mon
>> Sep  2 06:36:19 2013
>> @@ -679,6 +679,69 @@ void ForEachMappedRegion(link_map *map,
>>   }
>>   #endif
>>   +#if defined(__x86_64__)
>> +// We cannot use glibc's clone wrapper, because it messes with the child
>> +// task's TLS. It writes the PID and TID of the child task to its thread
>> +// descriptor, but in our case the child task shares the thread
>> descriptor with
>> +// the parent (because we don't know how to allocate a new thread
>> +// descriptor to keep glibc happy). So the stock version of clone(), when
>> +// used with CLONE_VM, would end up corrupting the parent's thread
>> descriptor.
>> +uptr internal_clone(int (*fn)(void *), void *child_stack, int flags,
>> void *arg,
>> +                    int *parent_tidptr, void *newtls, int *child_tidptr)
>> {
>> +  long long res;
>> +  if (!fn || !child_stack)
>> +    return -EINVAL;
>> +  CHECK_EQ(0, (uptr)child_stack % 16);
>> +  child_stack = (char *)child_stack - 2 * sizeof(void *);
>> +  ((void **)child_stack)[0] = (void *)(uptr)fn;
>> +  ((void **)child_stack)[1] = arg;
>> +  __asm__ __volatile__(
>> +                       /* %rax = syscall(%rax = __NR_clone,
>> +                        *                %rdi = flags,
>> +                        *                %rsi = child_stack,
>> +                        *                %rdx = parent_tidptr,
>> +                        *                %r8  = new_tls,
>> +                        *                %r10 = child_tidptr)
>> +                        */
>> +                       "movq   %6,%%r8\n"
>> +                       "movq   %7,%%r10\n"
>> +                       ".cfi_endproc\n"
>> +                       "syscall\n"
>> +
>> +                       /* if (%rax != 0)
>> +                        *   return;
>> +                        */
>> +                       "testq  %%rax,%%rax\n"
>> +                       "jnz    1f\n"
>> +
>> +                       /* In the child. Terminate unwind chain. */
>> +                       ".cfi_startproc\n"
>> +                       ".cfi_undefined %%rip;\n"
>> +                       "xorq   %%rbp,%%rbp\n"
>> +
>> +                       /* Call "fn(arg)". */
>> +                       "popq   %%rax\n"
>> +                       "popq   %%rdi\n"
>> +                       "call   *%%rax\n"
>> +
>> +                       /* Call _exit(%rax). */
>> +                       "movq   %%rax,%%rdi\n"
>> +                       "movq   %2,%%rax\n"
>> +                       "syscall\n"
>> +
>> +                       /* Return to parent. */
>> +                     "1:\n"
>> +                       : "=a" (res)
>> +                       : "a"(__NR_clone), "i"(__NR_exit),
>> +                         "S"(child_stack),
>> +                         "D"(flags),
>> +                         "d"(parent_tidptr),
>> +                         "r"(newtls),
>> +                         "r"(child_tidptr)
>> +                       : "rsp", "memory", "r8", "r10", "r11", "rcx");
>> +  return res;
>> +}
>> +#endif  // defined(__x86_64__)
>>   }  // namespace __sanitizer
>>     #endif  // SANITIZER_LINUX
>>
>> Modified: compiler-rt/trunk/lib/**sanitizer_common/sanitizer_**linux.h
>> URL: http://llvm.org/viewvc/llvm-**project/compiler-rt/trunk/lib/**
>> sanitizer_common/sanitizer_**linux.h?rev=189753&r1=189752&**
>> r2=189753&view=diff<http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h?rev=189753&r1=189752&r2=189753&view=diff>
>> ==============================**==============================**
>> ==================
>> --- compiler-rt/trunk/lib/**sanitizer_common/sanitizer_**linux.h
>> (original)
>> +++ compiler-rt/trunk/lib/**sanitizer_common/sanitizer_**linux.h Mon Sep
>>  2 06:36:19 2013
>> @@ -29,6 +29,10 @@ uptr internal_getdents(fd_t fd, struct l
>>   uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr
>> arg5);
>>   uptr internal_sigaltstack(const struct sigaltstack* ss,
>>                             struct sigaltstack* oss);
>> +#ifdef __x86_64__
>> +uptr internal_clone(int (*fn)(void *), void *child_stack, int flags,
>> void *arg,
>> +                    int *parent_tidptr, void *newtls, int *child_tidptr);
>> +#endif
>>     // This class reads thread IDs from /proc/<pid>/task using only
>> syscalls.
>>   class ThreadLister {
>>
>> Modified: compiler-rt/trunk/lib/**sanitizer_common/sanitizer_**
>> stoptheworld_linux_libcdep.cc
>> URL: http://llvm.org/viewvc/llvm-**project/compiler-rt/trunk/lib/**
>> sanitizer_common/sanitizer_**stoptheworld_linux_libcdep.cc?**
>> rev=189753&r1=189752&r2=**189753&view=diff<http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc?rev=189753&r1=189752&r2=189753&view=diff>
>> ==============================**==============================**
>> ==================
>> --- compiler-rt/trunk/lib/**sanitizer_common/sanitizer_**stoptheworld_linux_libcdep.cc
>> (original)
>> +++ compiler-rt/trunk/lib/**sanitizer_common/sanitizer_**stoptheworld_linux_libcdep.cc
>> Mon Sep  2 06:36:19 2013
>> @@ -14,12 +14,12 @@
>>       #include "sanitizer_platform.h"
>> -#if SANITIZER_LINUX
>> +#if SANITIZER_LINUX && defined(__x86_64__)
>>     #include "sanitizer_stoptheworld.h"
>>     #include <errno.h>
>> -#include <sched.h> // for clone
>> +#include <sched.h> // for CLONE_* definitions
>>   #include <stddef.h>
>>   #include <sys/prctl.h> // for PR_* definitions
>>   #include <sys/ptrace.h> // for PTRACE_* definitions
>> @@ -71,7 +71,6 @@
>>   // after it has exited. The following functions are used in this manner:
>>   // sigdelset()
>>   // sigprocmask()
>> -// clone()
>>     COMPILER_CHECK(sizeof(**SuspendedThreadID) == sizeof(pid_t));
>>   @@ -371,11 +370,14 @@ void StopTheWorld(**StopTheWorldCallback c
>>     // Block the execution of TracerThread until after we have set ptrace
>>     // permissions.
>>     tracer_thread_argument.mutex.**Lock();
>> -  pid_t tracer_pid = clone(TracerThread, tracer_stack.Bottom(),
>> -                           CLONE_VM | CLONE_FS | CLONE_FILES |
>> CLONE_UNTRACED,
>> -                           &tracer_thread_argument);
>> -  if (tracer_pid < 0) {
>> -    Report("Failed spawning a tracer thread (errno %d).\n", errno);
>> +  uptr tracer_pid = internal_clone(
>> +      TracerThread, tracer_stack.Bottom(),
>> +      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED,
>> +      &tracer_thread_argument, 0 /* parent_tidptr */, 0 /* newtls */, 0
>> +      /* child_tidptr */);
>> +  int local_errno = 0;
>> +  if (internal_iserror(tracer_pid, &local_errno)) {
>> +    Report("Failed spawning a tracer thread (errno %d).\n", local_errno);
>>       tracer_thread_argument.mutex.**Unlock();
>>     } else {
>>       // On some systems we have to explicitly declare that we want to be
>> traced
>> @@ -390,9 +392,8 @@ void StopTheWorld(**StopTheWorldCallback c
>>       // At this point, any signal will either be blocked or kill us, so
>> waitpid
>>       // should never return (and set errno) while the tracer thread is
>> alive.
>>       uptr waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL);
>> -    int wperrno;
>> -    if (internal_iserror(waitpid_**status, &wperrno))
>> -      Report("Waiting on the tracer thread failed (errno %d).\n",
>> wperrno);
>> +    if (internal_iserror(waitpid_**status, &local_errno))
>> +      Report("Waiting on the tracer thread failed (errno %d).\n",
>> local_errno);
>>     }
>>   }
>>   @@ -448,4 +449,4 @@ uptr SuspendedThreadsList::**RegisterCount
>>   }
>>   }  // namespace __sanitizer
>>   -#endif  // SANITIZER_LINUX
>> +#endif  // SANITIZER_LINUX && defined(__x86_64__)
>>
>> Modified: compiler-rt/trunk/lib/**sanitizer_common/tests/**
>> sanitizer_stoptheworld_test.cc
>> URL: http://llvm.org/viewvc/llvm-**project/compiler-rt/trunk/lib/**
>> sanitizer_common/tests/**sanitizer_stoptheworld_test.**
>> cc?rev=189753&r1=189752&r2=**189753&view=diff<http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc?rev=189753&r1=189752&r2=189753&view=diff>
>> ==============================**==============================**
>> ==================
>> --- compiler-rt/trunk/lib/**sanitizer_common/tests/**sanitizer_stoptheworld_test.cc
>> (original)
>> +++ compiler-rt/trunk/lib/**sanitizer_common/tests/**sanitizer_stoptheworld_test.cc
>> Mon Sep  2 06:36:19 2013
>> @@ -12,7 +12,7 @@
>>   //===-------------------------**------------------------------**
>> ---------------===//
>>     #include "sanitizer_common/sanitizer_**platform.h"
>> -#if SANITIZER_LINUX
>> +#if SANITIZER_LINUX && defined(__x86_64__)
>>     #include "sanitizer_common/sanitizer_**stoptheworld.h"
>>   #include "gtest/gtest.h"
>> @@ -191,4 +191,4 @@ TEST(StopTheWorld, SuspendThreadsAdvance
>>     }  // namespace __sanitizer
>>   -#endif  // SANITIZER_LINUX
>> +#endif  // SANITIZER_LINUX && defined(__x86_64__)
>>
>>
>> ______________________________**_________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/**mailman/listinfo/llvm-commits<http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits>
>>
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131008/b6c3bc5f/attachment.html>


More information about the llvm-commits mailing list