1/* _Unwind_Frames_Extra with shadow stack for x86-64 and x86. 2 Copyright (C) 2017-2022 Free Software Foundation, Inc. 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 3, or (at your option) 9any later version. 10 11GCC is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16Under Section 7 of GPL version 3, you are granted additional 17permissions described in the GCC Runtime Library Exception, version 183.1, as published by the Free Software Foundation. 19 20You should have received a copy of the GNU General Public License and 21a copy of the GCC Runtime Library Exception along with this program; 22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23<http://www.gnu.org/licenses/>. */ 24 25#include <x86gprintrin.h> 26 27/* Unwind the shadow stack for EH. */ 28#undef _Unwind_Frames_Extra 29#define _Unwind_Frames_Extra(x) \ 30 do \ 31 { \ 32 _Unwind_Word ssp = _get_ssp (); \ 33 if (ssp != 0) \ 34 { \ 35 _Unwind_Word tmp = (x); \ 36 while (tmp > 255) \ 37 { \ 38 _inc_ssp (255); \ 39 tmp -= 255; \ 40 } \ 41 _inc_ssp (tmp); \ 42 } \ 43 } \ 44 while (0) 45 46/* Linux CET kernel places a restore token on shadow stack for signal 47 handler to enhance security. The restore token is 8 byte and aligned 48 to 8 bytes. It is usually transparent to user programs since kernel 49 will pop the restore token when signal handler returns. But when an 50 exception is thrown from a signal handler, now we need to pop the 51 restore token from shadow stack. For x86-64, we just need to treat 52 the signal frame as normal frame. For i386, we need to search for 53 the restore token to check if the original shadow stack is 8 byte 54 aligned. If the original shadow stack is 8 byte aligned, we just 55 need to pop 2 slots, one restore token, from shadow stack. Otherwise, 56 we need to pop 3 slots, one restore token + 4 byte padding, from 57 shadow stack. */ 58#ifndef __x86_64__ 59#undef _Unwind_Frames_Increment 60#define _Unwind_Frames_Increment(context, frames) \ 61 if (_Unwind_IsSignalFrame (context)) \ 62 do \ 63 { \ 64 _Unwind_Word ssp, prev_ssp, token; \ 65 ssp = _get_ssp (); \ 66 if (ssp != 0) \ 67 { \ 68 /* Align shadow stack pointer to the next \ 69 8 byte aligned boundary. */ \ 70 ssp = (ssp + 4) & ~7; \ 71 do \ 72 { \ 73 /* Look for a restore token. */ \ 74 token = (*(_Unwind_Word *) (ssp - 8)); \ 75 prev_ssp = token & ~7; \ 76 if (prev_ssp == ssp) \ 77 break; \ 78 ssp += 8; \ 79 } \ 80 while (1); \ 81 frames += (token & 0x4) ? 3 : 2; \ 82 } \ 83 } \ 84 while (0); \ 85 else \ 86 frames++; 87#endif 88