[libunwind] [libunwind][AIX] Fix up TOC register if unw_getcontext is called from a different module (PR #66549)

via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 18 09:51:58 PDT 2023


https://github.com/xingxue-ibm updated https://github.com/llvm/llvm-project/pull/66549

>From d42f6f35b8a4f3750b151f29951b215889d2c3e4 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Fri, 15 Sep 2023 16:09:43 -0400
Subject: [PATCH 1/2] The TOC register (r2) was changed by the glue code if
 unw_getcontext is called from a different module. Fix it up by using the
 original TOC register saved in the stack frame.

---
 libunwind/src/UnwindRegistersSave.S | 29 +++++++++++++++++++++++++++--
 libunwind/test/unw_resume.pass.cpp  |  3 ---
 2 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S
index 58ffd1b9e1fb35a..f47b38ff848f729 100644
--- a/libunwind/src/UnwindRegistersSave.S
+++ b/libunwind/src/UnwindRegistersSave.S
@@ -305,9 +305,22 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   mflr  0
   std   0, PPC64_OFFS_SRR0(3) // store lr as ssr0
   PPC64_STR(1)
+  PPC64_STR(4)      // Save r4 first since it will be used for fixing r2.
+#if defined(_AIX)
+  // The TOC register (r2) was changed by the glue code if unw_getcontext
+  // is called from a different module. Save the original TOC register
+  // in the context if this is the case.
+  mflr  4
+  lwz   4, 0(4)     // Get the first instruction at the return address.
+  lis   0, 0xe841   // Is it reloading the TOC register "ld 2,40(1)"?
+  ori   0, 0, 0x28
+  cmpw  0, 0, 4
+  bne   0, LnoR2Fix // No need to fix up r2 if it is not.
+  ld    2, 40(1)    // Use the saved TOC register in the stack.
+LnoR2Fix:
+#endif
   PPC64_STR(2)
   PPC64_STR(3)
-  PPC64_STR(4)
   PPC64_STR(5)
   PPC64_STR(6)
   PPC64_STR(7)
@@ -547,9 +560,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   mflr    0
   stw     0,   0(3) // store lr as ssr0
   stw     1,  12(3)
+  stw     4,  24(3) // Save r4 first since it will be used for fixing r2.
+#if defined(_AIX)
+  // The TOC register (r2) was changed by the glue code if unw_getcontext
+  // is called from a different module. Save the original TOC register
+  // in the context if this is the case.
+  mflr    4
+  lwz     4,  0(4)      // Get the instruction at the return address.
+  xoris   4,  4, 0x8041 // Is it reloading the TOC register "lwz r2,20(r1)"?
+  cmplwi  4,  0x14
+  bne     0,  LnoR2Fix  // No need to fix up r2 if it is not.
+  lwz     2,  20(1)     // Use the saved TOC register in the stack.
+LnoR2Fix:
+#endif
   stw     2,  16(3)
   stw     3,  20(3)
-  stw     4,  24(3)
   stw     5,  28(3)
   stw     6,  32(3)
   stw     7,  36(3)
diff --git a/libunwind/test/unw_resume.pass.cpp b/libunwind/test/unw_resume.pass.cpp
index 76273e4a8ef0a71..08e8d4edeaf2927 100644
--- a/libunwind/test/unw_resume.pass.cpp
+++ b/libunwind/test/unw_resume.pass.cpp
@@ -10,9 +10,6 @@
 // Ensure that unw_resume() resumes execution at the stack frame identified by
 // cursor.
 
-// TODO: Investigate this failure on AIX system.
-// XFAIL: target={{.*}}-aix{{.*}}
-
 // TODO: Figure out why this fails with Memory Sanitizer.
 // XFAIL: msan
 

>From b9b6bed9a3658627b3d93a22043edb1da40134f2 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Mon, 18 Sep 2023 12:47:07 -0400
Subject: [PATCH 2/2] Addressed comment. - use the same code for 32- and 64-bit
 comparison.

---
 libunwind/src/UnwindRegistersSave.S | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S
index f47b38ff848f729..5534d1734b6ba7b 100644
--- a/libunwind/src/UnwindRegistersSave.S
+++ b/libunwind/src/UnwindRegistersSave.S
@@ -305,18 +305,17 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   mflr  0
   std   0, PPC64_OFFS_SRR0(3) // store lr as ssr0
   PPC64_STR(1)
-  PPC64_STR(4)      // Save r4 first since it will be used for fixing r2.
+  PPC64_STR(4)        // Save r4 first since it will be used for fixing r2.
 #if defined(_AIX)
   // The TOC register (r2) was changed by the glue code if unw_getcontext
   // is called from a different module. Save the original TOC register
   // in the context if this is the case.
-  mflr  4
-  lwz   4, 0(4)     // Get the first instruction at the return address.
-  lis   0, 0xe841   // Is it reloading the TOC register "ld 2,40(1)"?
-  ori   0, 0, 0x28
-  cmpw  0, 0, 4
-  bne   0, LnoR2Fix // No need to fix up r2 if it is not.
-  ld    2, 40(1)    // Use the saved TOC register in the stack.
+  mflr   4
+  lwz    4, 0(4)      // Get the first instruction at the return address.
+  xoris  0, 4, 0xe841 // Is it reloading the TOC register "ld 2,40(1)"?
+  cmplwi 0, 0x28
+  bne    0, LnoR2Fix  // No need to fix up r2 if it is not.
+  ld     2, 40(1)     // Use the saved TOC register in the stack.
 LnoR2Fix:
 #endif
   PPC64_STR(2)
@@ -566,9 +565,9 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
   // is called from a different module. Save the original TOC register
   // in the context if this is the case.
   mflr    4
-  lwz     4,  0(4)      // Get the instruction at the return address.
-  xoris   4,  4, 0x8041 // Is it reloading the TOC register "lwz r2,20(r1)"?
-  cmplwi  4,  0x14
+  lwz     4,   0(4)     // Get the instruction at the return address.
+  xoris   0,  4, 0x8041 // Is it reloading the TOC register "ld 2,40(1)"?
+  cmplwi  0,  0x14
   bne     0,  LnoR2Fix  // No need to fix up r2 if it is not.
   lwz     2,  20(1)     // Use the saved TOC register in the stack.
 LnoR2Fix:



More information about the cfe-commits mailing list