-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
[libunwind] Add GCS support for AArch64 #99335
Changes from 3 commits
e0f7186
c9f7373
bb7ade6
c776eaf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,7 +44,7 @@ | |
// _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we | ||
// directly jump to __libunwind_Registers_x86/x86_64_jumpto instead of using | ||
// a regular function call to avoid pushing to CET shadow stack again. | ||
#if !defined(_LIBUNWIND_USE_CET) | ||
#if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS) | ||
#define __unw_phase2_resume(cursor, fn) \ | ||
do { \ | ||
(void)fn; \ | ||
|
@@ -72,6 +72,19 @@ | |
__asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext), \ | ||
"d"(cetJumpAddress)); \ | ||
} while (0) | ||
#elif defined(_LIBUNWIND_TARGET_AARCH64) | ||
#define __cet_ss_step_size 8 | ||
#define __unw_phase2_resume(cursor, fn) \ | ||
do { \ | ||
_LIBUNWIND_POP_CET_SSP((fn)); \ | ||
void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ | ||
void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ | ||
__asm__ volatile("mov x0, %0\n\t" \ | ||
"br %1\n\t" \ | ||
: \ | ||
: "r"(cetRegContext), "r"(cetJumpAddress) \ | ||
: "x0"); \ | ||
} while (0) | ||
#endif | ||
|
||
static _Unwind_Reason_Code | ||
|
@@ -170,6 +183,10 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except | |
} | ||
extern int __unw_step_stage2(unw_cursor_t *); | ||
|
||
#if defined(_LIBUNWIND_USE_GCS) | ||
// Enable the GCS target feature to permit GCS instructions to be used. | ||
__attribute__((target("gcs"))) | ||
#endif | ||
static _Unwind_Reason_Code | ||
unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { | ||
__unw_init_local(cursor, uc); | ||
|
@@ -180,8 +197,13 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except | |
// uc is initialized by __unw_getcontext in the parent frame. The first stack | ||
// frame walked is unwind_phase2. | ||
unsigned framesWalked = 1; | ||
#ifdef _LIBUNWIND_USE_CET | ||
#if defined(_LIBUNWIND_USE_CET) | ||
unsigned long shadowStackTop = _get_ssp(); | ||
#elif defined(_LIBUNWIND_USE_GCS) | ||
unsigned long shadowStackTop = 0; | ||
if (__chkfeat(_CHKFEAT_GCS)) { | ||
shadowStackTop = (unsigned long)__gcspr(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the brace can be dropped |
||
} | ||
#endif | ||
// Walk each frame until we reach where search phase said to stop. | ||
while (true) { | ||
|
@@ -238,7 +260,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except | |
// against return address stored in CET shadow stack, if the 2 addresses don't | ||
// match, it means return address in normal stack has been corrupted, we return | ||
// _URC_FATAL_PHASE2_ERROR. | ||
#ifdef _LIBUNWIND_USE_CET | ||
#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS) | ||
if (shadowStackTop != 0) { | ||
unw_word_t retInNormalStack; | ||
__unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack); | ||
|
@@ -306,6 +328,10 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except | |
return _URC_FATAL_PHASE2_ERROR; | ||
} | ||
|
||
#if defined(_LIBUNWIND_USE_GCS) | ||
// Enable the GCS target feature to permit GCS instructions to be used. | ||
__attribute__((target("gcs"))) | ||
#endif | ||
static _Unwind_Reason_Code | ||
unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, | ||
_Unwind_Exception *exception_object, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -680,7 +680,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) | |
ldr x16, [x0, #0x0F8] | ||
ldp x0, x1, [x0, #0x000] // restore x0,x1 | ||
mov sp,x16 // restore sp | ||
ret x30 // jump to pc | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the application is compiled with BTI then There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes you're right, and actually the way I've adjusted __unw_phase2_resume also means we need to change the BTI instruction in __libunwind_Registers_arm64_jumpto to BTI JC. I'll fix this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #102322 should fix this |
||
br x30 // jump to pc | ||
|
||
#elif defined(__arm__) && !defined(__APPLE__) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be useful to elaborate what instructions need to use the GCS version.