<div dir="ltr">Fixed in r192196</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Oct 8, 2013 at 8:29 PM, Sergey Matveev <span dir="ltr"><<a href="mailto:earthdok@google.com" target="_blank">earthdok@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">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.</div>
<div class="HOEnZb"><div class="h5">
<div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Oct 5, 2013 at 12:07 AM, Matt Arsenault <span dir="ltr"><<a href="mailto:Matthew.Arsenault@amd.com" target="_blank">Matthew.Arsenault@amd.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This has been breaking the build for me for a while (I'm using the packaged clang 3.2 on Ubuntu 13.04):<br>
<br>
/home/marsenau/src/llvm/<u></u>projects/compiler-rt/lib/<u></u>sanitizer_common/sanitizer_<u></u>linux.cc:801:25: error: unknown directive<br>
                       ".cfi_undefined %%rip;\n"<br>
                        ^<br>
<inline asm>:8:1: note: instantiated into assembly here<br>
.cfi_undefined %rip;<br>
^<br>
[ 14%] 1 error generated.<div><div><br>
<br>
<br>
On 09/02/2013 04:36 AM, Sergey Matveev wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: smatveev<br>
Date: Mon Sep  2 06:36:19 2013<br>
New Revision: 189753<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=189753&view=rev" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project?rev=189753&view=rev</a><br>
Log:<br>
[sanitizer_common] Add internal_clone().<br>
<br>
Add a wrapper for the clone syscall for use in StopTheWorld. We<br>
implement it only for x86_64, so stop building StopTheWorld for other platforms<br>
(no one uses it outside x86_64 anyway).<br>
<br>
See <a href="https://code.google.com/p/address-sanitizer/issues/detail?id=214" target="_blank">https://code.google.com/p/<u></u>address-sanitizer/issues/<u></u>detail?id=214</a> for why we<br>
can't use the glibc clone() wrapper.<br>
<br>
Modified:<br>
     compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>linux.cc<br>
     compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>linux.h<br>
     compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>stoptheworld_linux_libcdep.cc<br>
     compiler-rt/trunk/lib/<u></u>sanitizer_common/tests/<u></u>sanitizer_stoptheworld_test.cc<br>
<br>
Modified: compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>linux.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=189753&r1=189752&r2=189753&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>linux.cc?rev=189753&r1=189752&<u></u>r2=189753&view=diff</a><br>


==============================<u></u>==============================<u></u>==================<br>
--- compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>linux.cc (original)<br>
+++ compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>linux.cc Mon Sep  2 06:36:19 2013<br>
@@ -679,6 +679,69 @@ void ForEachMappedRegion(link_map *map,<br>
  }<br>
  #endif<br>
  +#if defined(__x86_64__)<br>
+// We cannot use glibc's clone wrapper, because it messes with the child<br>
+// task's TLS. It writes the PID and TID of the child task to its thread<br>
+// descriptor, but in our case the child task shares the thread descriptor with<br>
+// the parent (because we don't know how to allocate a new thread<br>
+// descriptor to keep glibc happy). So the stock version of clone(), when<br>
+// used with CLONE_VM, would end up corrupting the parent's thread descriptor.<br>
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,<br>
+                    int *parent_tidptr, void *newtls, int *child_tidptr) {<br>
+  long long res;<br>
+  if (!fn || !child_stack)<br>
+    return -EINVAL;<br>
+  CHECK_EQ(0, (uptr)child_stack % 16);<br>
+  child_stack = (char *)child_stack - 2 * sizeof(void *);<br>
+  ((void **)child_stack)[0] = (void *)(uptr)fn;<br>
+  ((void **)child_stack)[1] = arg;<br>
+  __asm__ __volatile__(<br>
+                       /* %rax = syscall(%rax = __NR_clone,<br>
+                        *                %rdi = flags,<br>
+                        *                %rsi = child_stack,<br>
+                        *                %rdx = parent_tidptr,<br>
+                        *                %r8  = new_tls,<br>
+                        *                %r10 = child_tidptr)<br>
+                        */<br>
+                       "movq   %6,%%r8\n"<br>
+                       "movq   %7,%%r10\n"<br>
+                       ".cfi_endproc\n"<br>
+                       "syscall\n"<br>
+<br>
+                       /* if (%rax != 0)<br>
+                        *   return;<br>
+                        */<br>
+                       "testq  %%rax,%%rax\n"<br>
+                       "jnz    1f\n"<br>
+<br>
+                       /* In the child. Terminate unwind chain. */<br>
+                       ".cfi_startproc\n"<br>
+                       ".cfi_undefined %%rip;\n"<br>
+                       "xorq   %%rbp,%%rbp\n"<br>
+<br>
+                       /* Call "fn(arg)". */<br>
+                       "popq   %%rax\n"<br>
+                       "popq   %%rdi\n"<br>
+                       "call   *%%rax\n"<br>
+<br>
+                       /* Call _exit(%rax). */<br>
+                       "movq   %%rax,%%rdi\n"<br>
+                       "movq   %2,%%rax\n"<br>
+                       "syscall\n"<br>
+<br>
+                       /* Return to parent. */<br>
+                     "1:\n"<br>
+                       : "=a" (res)<br>
+                       : "a"(__NR_clone), "i"(__NR_exit),<br>
+                         "S"(child_stack),<br>
+                         "D"(flags),<br>
+                         "d"(parent_tidptr),<br>
+                         "r"(newtls),<br>
+                         "r"(child_tidptr)<br>
+                       : "rsp", "memory", "r8", "r10", "r11", "rcx");<br>
+  return res;<br>
+}<br>
+#endif  // defined(__x86_64__)<br>
  }  // namespace __sanitizer<br>
    #endif  // SANITIZER_LINUX<br>
<br>
Modified: compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>linux.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h?rev=189753&r1=189752&r2=189753&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>linux.h?rev=189753&r1=189752&<u></u>r2=189753&view=diff</a><br>


==============================<u></u>==============================<u></u>==================<br>
--- compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>linux.h (original)<br>
+++ compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>linux.h Mon Sep  2 06:36:19 2013<br>
@@ -29,6 +29,10 @@ uptr internal_getdents(fd_t fd, struct l<br>
  uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);<br>
  uptr internal_sigaltstack(const struct sigaltstack* ss,<br>
                            struct sigaltstack* oss);<br>
+#ifdef __x86_64__<br>
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,<br>
+                    int *parent_tidptr, void *newtls, int *child_tidptr);<br>
+#endif<br>
    // This class reads thread IDs from /proc/<pid>/task using only syscalls.<br>
  class ThreadLister {<br>
<br>
Modified: compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>stoptheworld_linux_libcdep.cc<br>
URL: <a href="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" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>stoptheworld_linux_libcdep.cc?<u></u>rev=189753&r1=189752&r2=<u></u>189753&view=diff</a><br>


==============================<u></u>==============================<u></u>==================<br>
--- compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>stoptheworld_linux_libcdep.cc (original)<br>
+++ compiler-rt/trunk/lib/<u></u>sanitizer_common/sanitizer_<u></u>stoptheworld_linux_libcdep.cc Mon Sep  2 06:36:19 2013<br>
@@ -14,12 +14,12 @@<br>
      #include "sanitizer_platform.h"<br>
-#if SANITIZER_LINUX<br>
+#if SANITIZER_LINUX && defined(__x86_64__)<br>
    #include "sanitizer_stoptheworld.h"<br>
    #include <errno.h><br>
-#include <sched.h> // for clone<br>
+#include <sched.h> // for CLONE_* definitions<br>
  #include <stddef.h><br>
  #include <sys/prctl.h> // for PR_* definitions<br>
  #include <sys/ptrace.h> // for PTRACE_* definitions<br>
@@ -71,7 +71,6 @@<br>
  // after it has exited. The following functions are used in this manner:<br>
  // sigdelset()<br>
  // sigprocmask()<br>
-// clone()<br>
    COMPILER_CHECK(sizeof(<u></u>SuspendedThreadID) == sizeof(pid_t));<br>
  @@ -371,11 +370,14 @@ void StopTheWorld(<u></u>StopTheWorldCallback c<br>
    // Block the execution of TracerThread until after we have set ptrace<br>
    // permissions.<br>
    tracer_thread_argument.mutex.<u></u>Lock();<br>
-  pid_t tracer_pid = clone(TracerThread, tracer_stack.Bottom(),<br>
-                           CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED,<br>
-                           &tracer_thread_argument);<br>
-  if (tracer_pid < 0) {<br>
-    Report("Failed spawning a tracer thread (errno %d).\n", errno);<br>
+  uptr tracer_pid = internal_clone(<br>
+      TracerThread, tracer_stack.Bottom(),<br>
+      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED,<br>
+      &tracer_thread_argument, 0 /* parent_tidptr */, 0 /* newtls */, 0<br>
+      /* child_tidptr */);<br>
+  int local_errno = 0;<br>
+  if (internal_iserror(tracer_pid, &local_errno)) {<br>
+    Report("Failed spawning a tracer thread (errno %d).\n", local_errno);<br>
      tracer_thread_argument.mutex.<u></u>Unlock();<br>
    } else {<br>
      // On some systems we have to explicitly declare that we want to be traced<br>
@@ -390,9 +392,8 @@ void StopTheWorld(<u></u>StopTheWorldCallback c<br>
      // At this point, any signal will either be blocked or kill us, so waitpid<br>
      // should never return (and set errno) while the tracer thread is alive.<br>
      uptr waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL);<br>
-    int wperrno;<br>
-    if (internal_iserror(waitpid_<u></u>status, &wperrno))<br>
-      Report("Waiting on the tracer thread failed (errno %d).\n", wperrno);<br>
+    if (internal_iserror(waitpid_<u></u>status, &local_errno))<br>
+      Report("Waiting on the tracer thread failed (errno %d).\n", local_errno);<br>
    }<br>
  }<br>
  @@ -448,4 +449,4 @@ uptr SuspendedThreadsList::<u></u>RegisterCount<br>
  }<br>
  }  // namespace __sanitizer<br>
  -#endif  // SANITIZER_LINUX<br>
+#endif  // SANITIZER_LINUX && defined(__x86_64__)<br>
<br>
Modified: compiler-rt/trunk/lib/<u></u>sanitizer_common/tests/<u></u>sanitizer_stoptheworld_test.cc<br>
URL: <a href="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" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/compiler-rt/trunk/lib/<u></u>sanitizer_common/tests/<u></u>sanitizer_stoptheworld_test.<u></u>cc?rev=189753&r1=189752&r2=<u></u>189753&view=diff</a><br>


==============================<u></u>==============================<u></u>==================<br>
--- compiler-rt/trunk/lib/<u></u>sanitizer_common/tests/<u></u>sanitizer_stoptheworld_test.cc (original)<br>
+++ compiler-rt/trunk/lib/<u></u>sanitizer_common/tests/<u></u>sanitizer_stoptheworld_test.cc Mon Sep  2 06:36:19 2013<br>
@@ -12,7 +12,7 @@<br>
  //===-------------------------<u></u>------------------------------<u></u>---------------===//<br>
    #include "sanitizer_common/sanitizer_<u></u>platform.h"<br>
-#if SANITIZER_LINUX<br>
+#if SANITIZER_LINUX && defined(__x86_64__)<br>
    #include "sanitizer_common/sanitizer_<u></u>stoptheworld.h"<br>
  #include "gtest/gtest.h"<br>
@@ -191,4 +191,4 @@ TEST(StopTheWorld, SuspendThreadsAdvance<br>
    }  // namespace __sanitizer<br>
  -#endif  // SANITIZER_LINUX<br>
+#endif  // SANITIZER_LINUX && defined(__x86_64__)<br>
<br>
<br>
______________________________<u></u>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/llvm-commits</a><br>
<br>
</blockquote>
<br>
<br>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>