[libunwind] [libunwind] Tweak tests for musl support. (PR #85097)

Alastair Houghton via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 6 07:22:12 PDT 2024


https://github.com/al45tair updated https://github.com/llvm/llvm-project/pull/85097

>From 6808d20b198bba4f2e062094b89cfc13eac49f85 Mon Sep 17 00:00:00 2001
From: Alastair Houghton <ahoughton at apple.com>
Date: Thu, 22 Feb 2024 11:59:24 +0000
Subject: [PATCH 1/3] [libunwind] Tweak tests for musl support.

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
---
 libunwind/test/floatregister.pass.cpp       | 18 +++++++++-----
 libunwind/test/forceunwind.pass.cpp         | 19 +++++++++------
 libunwind/test/signal_unwind.pass.cpp       | 26 +++++++++++++++------
 libunwind/test/unwind_leaffunction.pass.cpp | 24 ++++++++++++++-----
 4 files changed, 61 insertions(+), 26 deletions(-)

diff --git a/libunwind/test/floatregister.pass.cpp b/libunwind/test/floatregister.pass.cpp
index 64107e6d490b7..e4657c63fd1ad 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 db499d8bc3089..feb71fb769980 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 954a5d4ba3db1..715299e7496ef 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 112a5968247a4..5826ad2ba9533 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);

>From 55b96e8d4d4e6a03361d0389986f95ea37ba86a9 Mon Sep 17 00:00:00 2001
From: Alastair Houghton <ahoughton at apple.com>
Date: Wed, 13 Mar 2024 16:07:41 +0000
Subject: [PATCH 2/3] [libunwind] Tweak formatting slightly.

Tweak code formatting to keep clang-format happy.

rdar://123436891
---
 libunwind/test/floatregister.pass.cpp       | 3 ++-
 libunwind/test/forceunwind.pass.cpp         | 3 ++-
 libunwind/test/signal_unwind.pass.cpp       | 5 +++--
 libunwind/test/unwind_leaffunction.pass.cpp | 5 +++--
 4 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/libunwind/test/floatregister.pass.cpp b/libunwind/test/floatregister.pass.cpp
index e4657c63fd1ad..fb822363d4e7f 100644
--- a/libunwind/test/floatregister.pass.cpp
+++ b/libunwind/test/floatregister.pass.cpp
@@ -28,7 +28,8 @@ _Unwind_Reason_Code frame_handler(struct _Unwind_Context *ctx, void *arg) {
   // Unwind until the main is reached, above frames depend on the platform and
   // architecture.
   uintptr_t ip = _Unwind_GetIP(ctx);
-  if (ip >= (uintptr_t)&__start_main_func && ip < (uintptr_t)&__stop_main_func) {
+  if (ip >= (uintptr_t)&__start_main_func &&
+      ip < (uintptr_t)&__stop_main_func) {
     _Exit(0);
   }
 
diff --git a/libunwind/test/forceunwind.pass.cpp b/libunwind/test/forceunwind.pass.cpp
index feb71fb769980..344034e1ea5f5 100644
--- a/libunwind/test/forceunwind.pass.cpp
+++ b/libunwind/test/forceunwind.pass.cpp
@@ -50,7 +50,8 @@ _Unwind_Reason_Code stop(int version, _Unwind_Action actions,
   // Unwind until the main is reached, above frames depend on the platform and
   // architecture.
   uintptr_t ip = _Unwind_GetIP(context);
-  if (ip >= (uintptr_t)&__start_main_func && ip < (uintptr_t)&__stop_main_func) {
+  if (ip >= (uintptr_t)&__start_main_func &&
+      ip < (uintptr_t)&__stop_main_func) {
     _Exit(0);
   }
 
diff --git a/libunwind/test/signal_unwind.pass.cpp b/libunwind/test/signal_unwind.pass.cpp
index 715299e7496ef..beb1514fb2eb8 100644
--- a/libunwind/test/signal_unwind.pass.cpp
+++ b/libunwind/test/signal_unwind.pass.cpp
@@ -42,7 +42,8 @@ _Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) {
   // Unwind until the main is reached, above frames depend on the platform and
   // architecture.
   uintptr_t ip = _Unwind_GetIP(ctx);
-  if (ip >= (uintptr_t)&__start_main_func && ip < (uintptr_t)&__stop_main_func) {
+  if (ip >= (uintptr_t)&__start_main_func &&
+      ip < (uintptr_t)&__stop_main_func) {
     _Exit(0);
   }
 
@@ -55,7 +56,7 @@ void signal_handler(int signum) {
   _Exit(-1);
 }
 
-__attribute__((section("main_func"))) 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 5826ad2ba9533..7415441f506f5 100644
--- a/libunwind/test/unwind_leaffunction.pass.cpp
+++ b/libunwind/test/unwind_leaffunction.pass.cpp
@@ -42,7 +42,8 @@ _Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) {
   // Unwind until the main is reached, above frames depend on the platform and
   // architecture.
   uintptr_t ip = _Unwind_GetIP(ctx);
-  if (ip >= (uintptr_t)&__start_main_func && ip < (uintptr_t)&__stop_main_func) {
+  if (ip >= (uintptr_t)&__start_main_func &&
+      ip < (uintptr_t)&__stop_main_func) {
     _Exit(0);
   }
 
@@ -68,7 +69,7 @@ __attribute__((noinline)) void crashing_leaf_func(int do_trap) {
     __builtin_trap();
 }
 
-__attribute__((section("main_func"))) int main(int, char**) {
+__attribute__((section("main_func"))) int main(int, char **) {
   signal(SIGTRAP, signal_handler);
   signal(SIGILL, signal_handler);
   crashing_leaf_func(1);

>From 70b9619c998ec2bb8824b7998e5944ea15e43f32 Mon Sep 17 00:00:00 2001
From: Alastair Houghton <ahoughton at apple.com>
Date: Thu, 6 Jun 2024 15:20:58 +0100
Subject: [PATCH 3/3] [libunwind] Fix nits from review.

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

rdar://123436891
---
 libunwind/test/floatregister.pass.cpp       |  2 +-
 libunwind/test/signal_unwind.pass.cpp       | 17 +++++++++--------
 libunwind/test/unwind_leaffunction.pass.cpp | 17 +++++++++--------
 3 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/libunwind/test/floatregister.pass.cpp b/libunwind/test/floatregister.pass.cpp
index fb822363d4e7f..ce4481bdf8287 100644
--- a/libunwind/test/floatregister.pass.cpp
+++ b/libunwind/test/floatregister.pass.cpp
@@ -15,7 +15,7 @@
 #include <string.h>
 #include <unwind.h>
 
-// Using __attribute__((section("main_func"))) is Linux specific, but then
+// Using __attribute__((section("main_func"))) is ELF 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.
diff --git a/libunwind/test/signal_unwind.pass.cpp b/libunwind/test/signal_unwind.pass.cpp
index beb1514fb2eb8..1c1566415a4d4 100644
--- a/libunwind/test/signal_unwind.pass.cpp
+++ b/libunwind/test/signal_unwind.pass.cpp
@@ -8,11 +8,18 @@
 //===----------------------------------------------------------------------===//
 
 // Ensure that the unwinder can cope with the signal handler.
-// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+}}linux-gnu
+// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+linux.*}}
 
 // TODO: Figure out why this fails with Memory Sanitizer.
 // XFAIL: msan
 
+// 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
+//
+// XFAIL: target={{.*}}-musl
+
 #undef NDEBUG
 #include <assert.h>
 #include <signal.h>
@@ -23,13 +30,7 @@
 #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
+// Using __attribute__((section("main_func"))) is ELF 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.
diff --git a/libunwind/test/unwind_leaffunction.pass.cpp b/libunwind/test/unwind_leaffunction.pass.cpp
index 7415441f506f5..98de7dc43260c 100644
--- a/libunwind/test/unwind_leaffunction.pass.cpp
+++ b/libunwind/test/unwind_leaffunction.pass.cpp
@@ -8,11 +8,18 @@
 //===----------------------------------------------------------------------===//
 
 // Ensure that leaf function can be unwund.
-// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+}}linux-gnu
+// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+linux.*}}
 
 // TODO: Figure out why this fails with Memory Sanitizer.
 // XFAIL: msan
 
+// 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
+//
+// XFAIL: target={{.*}}-musl
+
 #undef NDEBUG
 #include <assert.h>
 #include <signal.h>
@@ -23,13 +30,7 @@
 #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
+// Using __attribute__((section("main_func"))) is ELF 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.



More information about the cfe-commits mailing list