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

Sergey Matveev earthdok at google.com
Tue Oct 8 09:42:04 PDT 2013


Fixed in r192196


On Tue, Oct 8, 2013 at 8:29 PM, Sergey Matveev <earthdok at google.com> wrote:

> 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/60b4b3dd/attachment.html>


More information about the llvm-commits mailing list