mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-04-01 12:43:47 +00:00
[libunwind][AIX] Fix up TOC register if unw_getcontext is called from a different module (#66549)
`unw_getcontext` saves the caller's registers in the context. However, if the caller of `unw_getcontext` is in a different module, the glue code of `unw_getcontext` sets the TOC register (r2) with the new TOC base and saves the original TOC register value in the stack frame. This causes the incorrect TOC value is used when the caller steps up frames, which fails libunwind LIT test case `unw_resume.pass.cpp`. This PR fixes the problem by using the original TOC register value saved in the stack if the caller is in a different module and enables `unw_resume.pass.cpp` on AIX.
This commit is contained in:
parent
a21d4abc89
commit
e25cd088a6
@ -305,9 +305,21 @@ 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.
|
||||
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)
|
||||
PPC64_STR(3)
|
||||
PPC64_STR(4)
|
||||
PPC64_STR(5)
|
||||
PPC64_STR(6)
|
||||
PPC64_STR(7)
|
||||
@ -547,9 +559,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 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:
|
||||
#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)
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user