diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp index 63f9cb367ec0..52477b16b355 100644 --- a/libunwind/src/AddressSpace.hpp +++ b/libunwind/src/AddressSpace.hpp @@ -202,10 +202,15 @@ public: pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, pint_t datarelBase = 0, pint_t *resultAddr = nullptr); - bool findFunctionName(pint_t addr, char *buf, size_t bufLen, - unw_word_t *offset); - bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); - bool findOtherFDE(pint_t targetAddr, pint_t &fde); + template + bool findFunctionName(typename R::link_hardened_reg_arg_t addr, char *buf, + size_t bufLen, unw_word_t *offset); + template + bool findUnwindSections(typename R::link_hardened_reg_arg_t targetAddr, + UnwindInfoSections &info); + template + bool findOtherFDE(typename R::link_hardened_reg_arg_t targetAddr, + pint_t &fde); static LocalAddressSpace sThisAddressSpace; }; @@ -497,9 +502,9 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, #endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) - -inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, - UnwindInfoSections &info) { +template +inline bool LocalAddressSpace::findUnwindSections( + typename R::link_hardened_reg_arg_t targetAddr, UnwindInfoSections &info) { #ifdef __APPLE__ dyld_unwind_sections dyldInfo; if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { @@ -669,16 +674,21 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, return false; } -inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { +template +inline bool +LocalAddressSpace::findOtherFDE(typename R::link_hardened_reg_arg_t targetAddr, + pint_t &fde) { // TO DO: if OS has way to dynamically register FDEs, check that. (void)targetAddr; (void)fde; return false; } -inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, - size_t bufLen, - unw_word_t *offset) { +template +inline bool +LocalAddressSpace::findFunctionName(typename R::link_hardened_reg_arg_t addr, + char *buf, size_t bufLen, + unw_word_t *offset) { #if _LIBUNWIND_USE_DLADDR Dl_info dyldInfo; if (dladdr((void *)addr, &dyldInfo)) { diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp index d2822e8be29e..165c4a99e9a9 100644 --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -33,7 +33,8 @@ public: typedef typename A::pint_t pint_t; typedef typename A::sint_t sint_t; - static int stepWithDwarf(A &addressSpace, const typename R::link_reg_t &pc, + static int stepWithDwarf(A &addressSpace, + typename R::link_hardened_reg_arg_t pc, pint_t fdeStart, R ®isters, bool &isSignalFrame, bool stage2); @@ -208,17 +209,16 @@ bool DwarfInstructions::isReturnAddressSignedWithPC(A &addressSpace, #endif template -int DwarfInstructions::stepWithDwarf(A &addressSpace, - const typename R::link_reg_t &pc, - pint_t fdeStart, R ®isters, - bool &isSignalFrame, bool stage2) { +int DwarfInstructions::stepWithDwarf( + A &addressSpace, typename R::link_hardened_reg_arg_t pc, pint_t fdeStart, + R ®isters, bool &isSignalFrame, bool stage2) { FDE_Info fdeInfo; CIE_Info cieInfo; if (CFI_Parser::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL) { PrologInfo prolog; - if (CFI_Parser::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, - R::getArch(), &prolog)) { + if (CFI_Parser::template parseFDEInstructions( + addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) { // get pointer to cfa (architecture specific) pint_t cfa = getCFA(addressSpace, prolog, registers); diff --git a/libunwind/src/DwarfParser.hpp b/libunwind/src/DwarfParser.hpp index 2b04ae2831f9..22de49023cb4 100644 --- a/libunwind/src/DwarfParser.hpp +++ b/libunwind/src/DwarfParser.hpp @@ -160,14 +160,17 @@ public: } }; - static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, - size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, - CIE_Info *cieInfo); + template + static bool findFDE(A &addressSpace, typename R::link_hardened_reg_arg_t pc, + pint_t ehSectionStart, size_t sectionLength, + pint_t fdeHint, FDE_Info *fdeInfo, CIE_Info *cieInfo); static const char *decodeFDE(A &addressSpace, pint_t fdeStart, FDE_Info *fdeInfo, CIE_Info *cieInfo, bool useCIEInfo = false); + template static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, - const CIE_Info &cieInfo, pint_t upToPC, + const CIE_Info &cieInfo, + typename R::link_hardened_reg_arg_t upToPC, int arch, PrologInfo *results); static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); @@ -239,9 +242,12 @@ const char *CFI_Parser::decodeFDE(A &addressSpace, pint_t fdeStart, /// Scan an eh_frame section to find an FDE for a pc template -bool CFI_Parser::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, - size_t sectionLength, pint_t fdeHint, - FDE_Info *fdeInfo, CIE_Info *cieInfo) { +template +bool CFI_Parser::findFDE(A &addressSpace, + typename R::link_hardened_reg_arg_t pc, + pint_t ehSectionStart, size_t sectionLength, + pint_t fdeHint, FDE_Info *fdeInfo, + CIE_Info *cieInfo) { //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; const pint_t ehSectionEnd = (sectionLength == SIZE_MAX) @@ -451,10 +457,10 @@ const char *CFI_Parser::parseCIE(A &addressSpace, pint_t cie, /// "run" the DWARF instructions and create the abstract PrologInfo for an FDE template -bool CFI_Parser::parseFDEInstructions(A &addressSpace, - const FDE_Info &fdeInfo, - const CIE_Info &cieInfo, pint_t upToPC, - int arch, PrologInfo *results) { +template +bool CFI_Parser::parseFDEInstructions( + A &addressSpace, const FDE_Info &fdeInfo, const CIE_Info &cieInfo, + typename R::link_hardened_reg_arg_t upToPC, int arch, PrologInfo *results) { // Alloca is used for the allocation of the rememberStack entries. It removes // the dependency on new/malloc but the below for loop can not be refactored // into functions. Entry could be saved during the processing of a CIE and diff --git a/libunwind/src/EHHeaderParser.hpp b/libunwind/src/EHHeaderParser.hpp index 0662a1321e2c..b5d927027f64 100644 --- a/libunwind/src/EHHeaderParser.hpp +++ b/libunwind/src/EHHeaderParser.hpp @@ -37,8 +37,9 @@ public: static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo); - static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, - uint32_t sectionLength, + template + static bool findFDE(A &addressSpace, typename R::link_hardened_reg_arg_t pc, + pint_t ehHdrStart, uint32_t sectionLength, typename CFI_Parser::FDE_Info *fdeInfo, typename CFI_Parser::CIE_Info *cieInfo); @@ -112,8 +113,10 @@ bool EHHeaderParser::decodeTableEntry( } template -bool EHHeaderParser::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, - uint32_t sectionLength, +template +bool EHHeaderParser::findFDE(A &addressSpace, + typename R::link_hardened_reg_arg_t pc, + pint_t ehHdrStart, uint32_t sectionLength, typename CFI_Parser::FDE_Info *fdeInfo, typename CFI_Parser::CIE_Info *cieInfo) { pint_t ehHdrEnd = ehHdrStart + sectionLength; diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp index 45a2b0921ea3..474b17461bf7 100644 --- a/libunwind/src/Registers.hpp +++ b/libunwind/src/Registers.hpp @@ -68,6 +68,7 @@ public: typedef uint32_t reg_t; typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint32_t getRegister(int num) const; @@ -289,6 +290,7 @@ public: typedef uint64_t reg_t; typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint64_t getRegister(int num) const; @@ -611,6 +613,7 @@ public: typedef uint32_t reg_t; typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint32_t getRegister(int num) const; @@ -1186,6 +1189,7 @@ public: typedef uint64_t reg_t; typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint64_t getRegister(int num) const; @@ -1852,6 +1856,14 @@ public: typedef uint64_t reg_t; typedef uint64_t __ptrauth_unwind_registers_arm64_link_reg link_reg_t; + // Use `link_hardened_reg_arg_t` to pass values of `link_reg_t` type as + // function arguments. We need to use a const l-value reference to keep + // signature of `__ptrauth`-qualified values of `link_reg_t` type on AArch64 + // PAuth-enabled ABI intact. Passing the raw pointer by value would cause + // authentication on the caller side and make the pointer prone to + // substitution if spilled to the stack in the callee. + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); @@ -2257,6 +2269,7 @@ public: typedef uint32_t reg_t; typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint32_t getRegister(int num) const; @@ -2765,6 +2778,7 @@ public: typedef uint32_t reg_t; typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint32_t getRegister(int num) const; @@ -2967,6 +2981,7 @@ public: typedef uint32_t reg_t; typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint32_t getRegister(int num) const; @@ -3305,6 +3320,7 @@ public: typedef uint64_t reg_t; typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint64_t getRegister(int num) const; @@ -3611,6 +3627,7 @@ public: typedef uint32_t reg_t; typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint32_t getRegister(int num) const; @@ -3800,6 +3817,7 @@ public: typedef uint64_t reg_t; typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint64_t getRegister(int num) const; @@ -3988,6 +4006,7 @@ public: typedef uint32_t reg_t; typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint32_t getRegister(int num) const; @@ -4206,6 +4225,7 @@ public: typedef ::libunwind::reg_t reg_t; typedef ::libunwind::reg_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; reg_t getRegister(int num) const; @@ -4506,6 +4526,7 @@ public: typedef uint64_t reg_t; typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint64_t getRegister(int num) const; @@ -4952,6 +4973,7 @@ public: typedef uint64_t reg_t; typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint64_t getRegister(int num) const; @@ -5243,6 +5265,7 @@ public: typedef uint64_t reg_t; typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint64_t getRegister(int num) const; diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index afa0cae79037..5838dbcaa998 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -121,7 +121,9 @@ class _LIBUNWIND_HIDDEN DwarfFDECache { typedef typename A::pint_t pint_t; public: static constexpr pint_t kSearchAll = static_cast(-1); - static pint_t findFDE(pint_t mh, pint_t pc); + template + static pint_t findFDE(pint_t mh, typename R::link_hardened_reg_arg_t pc); + static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); static void removeAllIn(pint_t mh); static void iterateCacheEntries(void (*func)(unw_word_t ip_start, @@ -174,8 +176,9 @@ bool DwarfFDECache::_registeredForDyldUnloads = false; #endif template -typename DwarfFDECache::pint_t DwarfFDECache::findFDE(pint_t mh, - pint_t pc) { +template +typename DwarfFDECache::pint_t +DwarfFDECache::findFDE(pint_t mh, typename R::link_hardened_reg_arg_t pc) { pint_t result = 0; _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); for (entry *p = _buffer; p < _bufferUsed; ++p) { @@ -1060,8 +1063,9 @@ private: #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) bool getInfoFromFdeCie(const typename CFI_Parser::FDE_Info &fdeInfo, const typename CFI_Parser::CIE_Info &cieInfo, - pint_t pc, uintptr_t dso_base); - bool getInfoFromDwarfSection(const typename R::link_reg_t &pc, + typename R::link_hardened_reg_arg_t pc, + uintptr_t dso_base); + bool getInfoFromDwarfSection(typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections §s, uint32_t fdeSectionOffsetHint = 0); int stepWithDwarfFDE(bool stage2) { @@ -1079,7 +1083,7 @@ private: #endif #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - bool getInfoFromCompactEncodingSection(const typename R::link_reg_t &pc, + bool getInfoFromCompactEncodingSection(typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections §s); int stepWithCompactEncoding(bool stage2 = false) { #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) @@ -1730,11 +1734,11 @@ bool UnwindCursor::getInfoFromEHABISection( template bool UnwindCursor::getInfoFromFdeCie( const typename CFI_Parser::FDE_Info &fdeInfo, - const typename CFI_Parser::CIE_Info &cieInfo, pint_t pc, - uintptr_t dso_base) { + const typename CFI_Parser::CIE_Info &cieInfo, + typename R::link_hardened_reg_arg_t pc, uintptr_t dso_base) { typename CFI_Parser::PrologInfo prolog; - if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, - R::getArch(), &prolog)) { + if (CFI_Parser::template parseFDEInstructions( + _addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) { // Save off parsed FDE info _info.start_ip = fdeInfo.pcStart; _info.end_ip = fdeInfo.pcEnd; @@ -1755,7 +1759,7 @@ bool UnwindCursor::getInfoFromFdeCie( template bool UnwindCursor::getInfoFromDwarfSection( - const typename R::link_reg_t &pc, const UnwindInfoSections §s, + typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections §s, uint32_t fdeSectionOffsetHint) { typename CFI_Parser::FDE_Info fdeInfo; typename CFI_Parser::CIE_Info cieInfo; @@ -1763,34 +1767,33 @@ bool UnwindCursor::getInfoFromDwarfSection( bool foundInCache = false; // If compact encoding table gave offset into dwarf section, go directly there if (fdeSectionOffsetHint != 0) { - foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - sects.dwarf_section_length, - sects.dwarf_section + fdeSectionOffsetHint, - &fdeInfo, &cieInfo); + foundFDE = CFI_Parser::template findFDE( + _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, + sects.dwarf_section + fdeSectionOffsetHint, &fdeInfo, &cieInfo); } #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) if (!foundFDE && (sects.dwarf_index_section != 0)) { - foundFDE = EHHeaderParser::findFDE( + foundFDE = EHHeaderParser::template findFDE( _addressSpace, pc, sects.dwarf_index_section, (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo); } #endif if (!foundFDE) { // otherwise, search cache of previously found FDEs. - pint_t cachedFDE = DwarfFDECache::findFDE(sects.dso_base, pc); + pint_t cachedFDE = + DwarfFDECache::template findFDE(sects.dso_base, pc); if (cachedFDE != 0) { - foundFDE = - CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - sects.dwarf_section_length, - cachedFDE, &fdeInfo, &cieInfo); + foundFDE = CFI_Parser::template findFDE( + _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, + cachedFDE, &fdeInfo, &cieInfo); foundInCache = foundFDE; } } if (!foundFDE) { // Still not found, do full scan of __eh_frame section. - foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - sects.dwarf_section_length, 0, - &fdeInfo, &cieInfo); + foundFDE = CFI_Parser::template findFDE( + _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, 0, + &fdeInfo, &cieInfo); } if (foundFDE) { if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) { @@ -1815,7 +1818,7 @@ bool UnwindCursor::getInfoFromDwarfSection( #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) template bool UnwindCursor::getInfoFromCompactEncodingSection( - const typename R::link_reg_t &pc, const UnwindInfoSections §s) { + typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections §s) { const bool log = false; if (log) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n", @@ -2773,7 +2776,7 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { // Ask address space object to find unwind sections for this pc. UnwindInfoSections sects; - if (_addressSpace.findUnwindSections(pc, sects)) { + if (_addressSpace.template findUnwindSections(pc, sects)) { #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) // If there is a compact unwind encoding table, look there first. if (sects.compact_unwind_section != 0) { @@ -2829,8 +2832,8 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) // There is no static unwind info for this pc. Look to see if an FDE was // dynamically registered for it. - pint_t cachedFDE = DwarfFDECache::findFDE(DwarfFDECache::kSearchAll, - pc); + pint_t cachedFDE = + DwarfFDECache::template findFDE(DwarfFDECache::kSearchAll, pc); if (cachedFDE != 0) { typename CFI_Parser::FDE_Info fdeInfo; typename CFI_Parser::CIE_Info cieInfo; @@ -2842,7 +2845,7 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { // Lastly, ask AddressSpace object about platform specific ways to locate // other FDEs. pint_t fde; - if (_addressSpace.findOtherFDE(pc, fde)) { + if (_addressSpace.template findOtherFDE(pc, fde)) { typename CFI_Parser::FDE_Info fdeInfo; typename CFI_Parser::CIE_Info cieInfo; if (!CFI_Parser::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) { @@ -3312,7 +3315,7 @@ bool UnwindCursor::getFunctionName(char *buf, size_t bufLen, #else typename R::link_reg_t pc = this->getReg(UNW_REG_IP); #endif - return _addressSpace.findFunctionName(pc, buf, bufLen, offset); + return _addressSpace.template findFunctionName(pc, buf, bufLen, offset); } #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)