Skip to content

[libunwind] Tweak tests for musl support. #85097

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 10, 2024

Conversation

al45tair
Copy link
Contributor

We can't use dladdr() in the tests, because when we're statically linking with musl that function is a no-op.

Additionally, because musl disables emission of unwind information in its build, and because its signal trampolines don't include unwind information, tests that involve unwinding through a signal handler won't work and need to be disabled for musl.

rdar://123436891

We can't use `dladdr()` in the tests, because when we're statically
linking with musl that function is a no-op.

Additionally, because musl disables emission of unwind information
in its build, and because its signal trampolines don't include
unwind information, tests that involve unwinding through a signal
handler won't work and need to be disabled for musl.

rdar://123436891
@al45tair al45tair requested a review from a team as a code owner March 13, 2024 15:01
@al45tair
Copy link
Contributor Author

This is a cherry pick of swiftlang#8260.

@llvmbot
Copy link
Member

llvmbot commented Mar 13, 2024

@llvm/pr-subscribers-libunwind

Author: Alastair Houghton (al45tair)

Changes

We can't use dladdr() in the tests, because when we're statically linking with musl that function is a no-op.

Additionally, because musl disables emission of unwind information in its build, and because its signal trampolines don't include unwind information, tests that involve unwinding through a signal handler won't work and need to be disabled for musl.

rdar://123436891


Full diff: https://github.com/llvm/llvm-project/pull/85097.diff

4 Files Affected:

  • (modified) libunwind/test/floatregister.pass.cpp (+12-6)
  • (modified) libunwind/test/forceunwind.pass.cpp (+12-7)
  • (modified) libunwind/test/signal_unwind.pass.cpp (+19-7)
  • (modified) libunwind/test/unwind_leaffunction.pass.cpp (+18-6)
diff --git a/libunwind/test/floatregister.pass.cpp b/libunwind/test/floatregister.pass.cpp
index 64107e6d490b70b..e4657c63fd1adf3 100644
--- a/libunwind/test/floatregister.pass.cpp
+++ b/libunwind/test/floatregister.pass.cpp
@@ -11,20 +11,26 @@
 
 // Basic test for float registers number are accepted.
 
-#include <dlfcn.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unwind.h>
 
+// Using __attribute__((section("main_func"))) is Linux specific, but then
+// this entire test is marked as requiring Linux, so we should be good.
+//
+// We don't use dladdr() because on musl it's a no-op when statically linked.
+extern char __start_main_func;
+extern char __stop_main_func;
+
 _Unwind_Reason_Code frame_handler(struct _Unwind_Context *ctx, void *arg) {
   (void)arg;
-  Dl_info info = {0, 0, 0, 0};
 
-  // Unwind util the main is reached, above frames depend on the platform and
+  // Unwind until the main is reached, above frames depend on the platform and
   // architecture.
-  if (dladdr(reinterpret_cast<void *>(_Unwind_GetIP(ctx)), &info) &&
-      info.dli_sname && !strcmp("main", info.dli_sname))
+  uintptr_t ip = _Unwind_GetIP(ctx);
+  if (ip >= (uintptr_t)&__start_main_func && ip < (uintptr_t)&__stop_main_func) {
     _Exit(0);
+  }
 
   return _URC_NO_REASON;
 }
@@ -45,7 +51,7 @@ __attribute__((noinline)) void foo() {
   _Unwind_Backtrace(frame_handler, NULL);
 }
 
-int main() {
+__attribute__((section("main_func"))) int main() {
   foo();
   return -2;
 }
diff --git a/libunwind/test/forceunwind.pass.cpp b/libunwind/test/forceunwind.pass.cpp
index db499d8bc30894e..feb71fb769980c8 100644
--- a/libunwind/test/forceunwind.pass.cpp
+++ b/libunwind/test/forceunwind.pass.cpp
@@ -17,7 +17,6 @@
 
 #undef NDEBUG
 #include <assert.h>
-#include <dlfcn.h>
 #include <signal.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -27,6 +26,13 @@
 #include <unistd.h>
 #include <unwind.h>
 
+// Using __attribute__((section("main_func"))) is Linux specific, but then
+// this entire test is marked as requiring Linux, so we should be good.
+//
+// We don't use dladdr() because on musl it's a no-op when statically linked.
+extern char __start_main_func;
+extern char __stop_main_func;
+
 void foo();
 _Unwind_Exception ex;
 
@@ -41,14 +47,13 @@ _Unwind_Reason_Code stop(int version, _Unwind_Action actions,
   assert(exceptionObject == &ex);
   assert(stop_parameter == &foo);
 
-  Dl_info info = {0, 0, 0, 0};
-
-  // Unwind util the main is reached, above frames depend on the platform and
+  // Unwind until the main is reached, above frames depend on the platform and
   // architecture.
-  if (dladdr(reinterpret_cast<void *>(_Unwind_GetIP(context)), &info) &&
-      info.dli_sname && !strcmp("main", info.dli_sname)) {
+  uintptr_t ip = _Unwind_GetIP(context);
+  if (ip >= (uintptr_t)&__start_main_func && ip < (uintptr_t)&__stop_main_func) {
     _Exit(0);
   }
+
   return _URC_NO_REASON;
 }
 
@@ -66,7 +71,7 @@ __attribute__((noinline)) void foo() {
   _Unwind_ForcedUnwind(e, stop, (void *)&foo);
 }
 
-int main() {
+__attribute__((section("main_func"))) int main() {
   foo();
   return -2;
 }
diff --git a/libunwind/test/signal_unwind.pass.cpp b/libunwind/test/signal_unwind.pass.cpp
index 954a5d4ba3db10d..715299e7496efe7 100644
--- a/libunwind/test/signal_unwind.pass.cpp
+++ b/libunwind/test/signal_unwind.pass.cpp
@@ -8,14 +8,13 @@
 //===----------------------------------------------------------------------===//
 
 // Ensure that the unwinder can cope with the signal handler.
-// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+linux.*}}
+// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+}}linux-gnu
 
 // TODO: Figure out why this fails with Memory Sanitizer.
 // XFAIL: msan
 
 #undef NDEBUG
 #include <assert.h>
-#include <dlfcn.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -24,16 +23,29 @@
 #include <unistd.h>
 #include <unwind.h>
 
+// Note: this test fails on musl because:
+//
+//  (a) musl disables emission of unwind information for its build, and
+//  (b) musl's signal trampolines don't include unwind information
+//
+
+// Using __attribute__((section("main_func"))) is Linux specific, but then
+// this entire test is marked as requiring Linux, so we should be good.
+//
+// We don't use dladdr() because on musl it's a no-op when statically linked.
+extern char __start_main_func;
+extern char __stop_main_func;
+
 _Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) {
   (void)arg;
-  Dl_info info = { 0, 0, 0, 0 };
 
-  // Unwind util the main is reached, above frames depend on the platform and
+  // Unwind until the main is reached, above frames depend on the platform and
   // architecture.
-  if (dladdr(reinterpret_cast<void *>(_Unwind_GetIP(ctx)), &info) &&
-      info.dli_sname && !strcmp("main", info.dli_sname)) {
+  uintptr_t ip = _Unwind_GetIP(ctx);
+  if (ip >= (uintptr_t)&__start_main_func && ip < (uintptr_t)&__stop_main_func) {
     _Exit(0);
   }
+
   return _URC_NO_REASON;
 }
 
@@ -43,7 +55,7 @@ void signal_handler(int signum) {
   _Exit(-1);
 }
 
-int main(int, char**) {
+__attribute__((section("main_func"))) int main(int, char**) {
   signal(SIGUSR1, signal_handler);
   kill(getpid(), SIGUSR1);
   return -2;
diff --git a/libunwind/test/unwind_leaffunction.pass.cpp b/libunwind/test/unwind_leaffunction.pass.cpp
index 112a5968247a42d..5826ad2ba9533c3 100644
--- a/libunwind/test/unwind_leaffunction.pass.cpp
+++ b/libunwind/test/unwind_leaffunction.pass.cpp
@@ -8,14 +8,13 @@
 //===----------------------------------------------------------------------===//
 
 // Ensure that leaf function can be unwund.
-// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+linux.*}}
+// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+}}linux-gnu
 
 // TODO: Figure out why this fails with Memory Sanitizer.
 // XFAIL: msan
 
 #undef NDEBUG
 #include <assert.h>
-#include <dlfcn.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -24,16 +23,29 @@
 #include <unistd.h>
 #include <unwind.h>
 
+// Note: this test fails on musl because:
+//
+//  (a) musl disables emission of unwind information for its build, and
+//  (b) musl's signal trampolines don't include unwind information
+//
+
+// Using __attribute__((section("main_func"))) is Linux specific, but then
+// this entire test is marked as requiring Linux, so we should be good.
+//
+// We don't use dladdr() because on musl it's a no-op when statically linked.
+extern char __start_main_func;
+extern char __stop_main_func;
+
 _Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) {
   (void)arg;
-  Dl_info info = { 0, 0, 0, 0 };
 
   // Unwind until the main is reached, above frames depend on the platform and
   // architecture.
-  if (dladdr(reinterpret_cast<void *>(_Unwind_GetIP(ctx)), &info) &&
-      info.dli_sname && !strcmp("main", info.dli_sname)) {
+  uintptr_t ip = _Unwind_GetIP(ctx);
+  if (ip >= (uintptr_t)&__start_main_func && ip < (uintptr_t)&__stop_main_func) {
     _Exit(0);
   }
+
   return _URC_NO_REASON;
 }
 
@@ -56,7 +68,7 @@ __attribute__((noinline)) void crashing_leaf_func(int do_trap) {
     __builtin_trap();
 }
 
-int main(int, char**) {
+__attribute__((section("main_func"))) int main(int, char**) {
   signal(SIGTRAP, signal_handler);
   signal(SIGILL, signal_handler);
   crashing_leaf_func(1);

Copy link

github-actions bot commented Mar 13, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Tweak code formatting to keep clang-format happy.

rdar://123436891
Fix a couple of comments, and change to using `XFAIL` rather than explicitly
selecting only `linux-gnu`.

rdar://123436891
@al45tair al45tair requested a review from ldionne June 7, 2024 10:57
@al45tair
Copy link
Contributor Author

al45tair commented Jun 7, 2024

I don't have merge rights here, so someone else will need to hit the Merge button.

@ldionne ldionne merged commit fe1301b into llvm:main Jun 10, 2024
56 checks passed
Lukacma pushed a commit to Lukacma/llvm-project that referenced this pull request Jun 12, 2024
We can't use `dladdr()` in the tests, because when we're statically
linking with musl that function is a no-op.

Additionally, because musl disables emission of unwind information in
its build, and because its signal trampolines don't include unwind
information, tests that involve unwinding through a signal handler won't
work and need to be disabled for musl.

rdar://123436891
@HerrCai0907 HerrCai0907 mentioned this pull request Jun 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants