Skip to content

Update libunwind to LLVM 18.1.2 #21607

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

Merged
merged 2 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion system/lib/libunwind/include/__libunwind_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
# if defined(__linux__)
# define _LIBUNWIND_TARGET_LINUX 1
# endif
# if defined(__HAIKU__)
# define _LIBUNWIND_TARGET_HAIKU 1
# endif
# if defined(__i386__)
# define _LIBUNWIND_TARGET_I386
# define _LIBUNWIND_CONTEXT_SIZE 8
Expand Down Expand Up @@ -196,7 +199,7 @@
# define _LIBUNWIND_TARGET_RISCV 1
# define _LIBUNWIND_TARGET_VE 1
# define _LIBUNWIND_TARGET_S390X 1
#define _LIBUNWIND_TARGET_LOONGARCH 1
# define _LIBUNWIND_TARGET_LOONGARCH 1
# define _LIBUNWIND_CONTEXT_SIZE 167
# define _LIBUNWIND_CURSOR_SIZE 204
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
Expand Down
3 changes: 3 additions & 0 deletions system/lib/libunwind/include/libunwind.h
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,9 @@ enum {
UNW_MIPS_F29 = 61,
UNW_MIPS_F30 = 62,
UNW_MIPS_F31 = 63,
// HI,LO have been dropped since r6, we keep them here.
// So, when we add DSP/MSA etc, we can use the same register indexes
// for r6 and pre-r6.
UNW_MIPS_HI = 64,
UNW_MIPS_LO = 65,
};
Expand Down
80 changes: 40 additions & 40 deletions system/lib/libunwind/include/mach-o/compact_unwind_encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ enum {
// are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries.
// Each entry contains which register to restore.
// UNWIND_X86_MODE_STACK_IMMD:
// A "frameless" (EBP not used as frame pointer) function with a small
// A "frameless" (EBP not used as frame pointer) function with a small
// constant stack size. To return, a constant (encoded in the compact
// unwind encoding) is added to the ESP. Then the return is done by
// popping the stack into the pc.
Expand All @@ -119,16 +119,16 @@ enum {
// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
// saved and their order.
// UNWIND_X86_MODE_STACK_IND:
// A "frameless" (EBP not used as frame pointer) function large constant
// A "frameless" (EBP not used as frame pointer) function large constant
// stack size. This case is like the previous, except the stack size is too
// large to encode in the compact unwind encoding. Instead it requires that
// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact
// large to encode in the compact unwind encoding. Instead it requires that
// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact
// encoding contains the offset to the nnnnnnnn value in the function in
// UNWIND_X86_FRAMELESS_STACK_SIZE.
// UNWIND_X86_FRAMELESS_STACK_SIZE.
// UNWIND_X86_MODE_DWARF:
// No compact unwind encoding is available. Instead the low 24-bits of the
// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
// This mode is never used in object files. It is only generated by the
// This mode is never used in object files. It is only generated by the
// linker in final linked images which have only DWARF unwind info for a
// function.
//
Expand Down Expand Up @@ -233,36 +233,36 @@ enum {
// For x86_64 there are four modes for the compact unwind encoding:
// UNWIND_X86_64_MODE_RBP_FRAME:
// RBP based frame where RBP is push on stack immediately after return address,
// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current
// EPB value, then RBP is restored by popping off the stack, and the return
// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current
// EPB value, then RBP is restored by popping off the stack, and the return
// is done by popping the stack once more into the pc.
// All non-volatile registers that need to be restored must have been saved
// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8
// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8
// is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved
// are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries.
// Each entry contains which register to restore.
// Each entry contains which register to restore.
// UNWIND_X86_64_MODE_STACK_IMMD:
// A "frameless" (RBP not used as frame pointer) function with a small
// constant stack size. To return, a constant (encoded in the compact
// unwind encoding) is added to the RSP. Then the return is done by
// A "frameless" (RBP not used as frame pointer) function with a small
// constant stack size. To return, a constant (encoded in the compact
// unwind encoding) is added to the RSP. Then the return is done by
// popping the stack into the pc.
// All non-volatile registers that need to be restored must have been saved
// on the stack immediately after the return address. The stack_size/8 is
// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048).
// The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT.
// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
// saved and their order.
// saved and their order.
// UNWIND_X86_64_MODE_STACK_IND:
// A "frameless" (RBP not used as frame pointer) function large constant
// A "frameless" (RBP not used as frame pointer) function large constant
// stack size. This case is like the previous, except the stack size is too
// large to encode in the compact unwind encoding. Instead it requires that
// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact
// large to encode in the compact unwind encoding. Instead it requires that
// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact
// encoding contains the offset to the nnnnnnnn value in the function in
// UNWIND_X86_64_FRAMELESS_STACK_SIZE.
// UNWIND_X86_64_FRAMELESS_STACK_SIZE.
// UNWIND_X86_64_MODE_DWARF:
// No compact unwind encoding is available. Instead the low 24-bits of the
// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
// This mode is never used in object files. It is only generated by the
// This mode is never used in object files. It is only generated by the
// linker in final linked images which have only DWARF unwind info for a
// function.
//
Expand Down Expand Up @@ -307,20 +307,20 @@ enum {
// This is a standard arm64 prolog where FP/LR are immediately pushed on the
// stack, then SP is copied to FP. If there are any non-volatile registers
// saved, then are copied into the stack frame in pairs in a contiguous
// range right below the saved FP/LR pair. Any subset of the five X pairs
// range right below the saved FP/LR pair. Any subset of the five X pairs
// and four D pairs can be saved, but the memory layout must be in register
// number order.
// number order.
// UNWIND_ARM64_MODE_FRAMELESS:
// A "frameless" leaf function, where FP/LR are not saved. The return address
// A "frameless" leaf function, where FP/LR are not saved. The return address
// remains in LR throughout the function. If any non-volatile registers
// are saved, they must be pushed onto the stack before any stack space is
// allocated for local variables. The stack sized (including any saved
// non-volatile registers) divided by 16 is encoded in the bits
// non-volatile registers) divided by 16 is encoded in the bits
// UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK.
// UNWIND_ARM64_MODE_DWARF:
// No compact unwind encoding is available. Instead the low 24-bits of the
// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
// This mode is never used in object files. It is only generated by the
// This mode is never used in object files. It is only generated by the
// linker in final linked images which have only DWARF unwind info for a
// function.
//
Expand All @@ -337,19 +337,19 @@ enum {

//
// A compiler can generated compact unwind information for a function by adding
// a "row" to the __LD,__compact_unwind section. This section has the
// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers.
// It is removed by the new linker, so never ends up in final executables.
// This section is a table, initially with one row per function (that needs
// a "row" to the __LD,__compact_unwind section. This section has the
// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers.
// It is removed by the new linker, so never ends up in final executables.
// This section is a table, initially with one row per function (that needs
// unwind info). The table columns and some conceptual entries are:
//
// range-start pointer to start of function/range
// range-length
// compact-unwind-encoding 32-bit encoding
// range-length
// compact-unwind-encoding 32-bit encoding
// personality-function or zero if no personality function
// lsda or zero if no LSDA data
//
// The length and encoding fields are 32-bits. The other are all pointer sized.
// The length and encoding fields are 32-bits. The other are all pointer sized.
//
// In x86_64 assembly, these entry would look like:
//
Expand All @@ -372,23 +372,23 @@ enum {
// .quad except_tab1
//
//
// Notes: There is no need for any labels in the the __compact_unwind section.
// The use of the .set directive is to force the evaluation of the
// Notes: There is no need for any labels in the __compact_unwind section.
// The use of the .set directive is to force the evaluation of the
// range-length at assembly time, instead of generating relocations.
//
// To support future compiler optimizations where which non-volatile registers
// To support future compiler optimizations where which non-volatile registers
// are saved changes within a function (e.g. delay saving non-volatiles until
// necessary), there can by multiple lines in the __compact_unwind table for one
// function, each with a different (non-overlapping) range and each with
// different compact unwind encodings that correspond to the non-volatiles
// function, each with a different (non-overlapping) range and each with
// different compact unwind encodings that correspond to the non-volatiles
// saved at that range of the function.
//
// If a particular function is so wacky that there is no compact unwind way
// to encode it, then the compiler can emit traditional DWARF unwind info.
// to encode it, then the compiler can emit traditional DWARF unwind info.
// The runtime will use which ever is available.
//
// Runtime support for compact unwind encodings are only available on 10.6
// and later. So, the compiler should not generate it when targeting pre-10.6.
// Runtime support for compact unwind encodings are only available on 10.6
// and later. So, the compiler should not generate it when targeting pre-10.6.



Expand All @@ -402,7 +402,7 @@ enum {
//
// The __TEXT,__unwind_info section is laid out for an efficient two level lookup.
// The header of the section contains a coarse index that maps function address
// to the page (4096 byte block) containing the unwind info for that function.
// to the page (4096 byte block) containing the unwind info for that function.
//

#define UNWIND_SECTION_VERSION 1
Expand Down
7 changes: 4 additions & 3 deletions system/lib/libunwind/src/AddressSpace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,8 +414,8 @@ static bool checkForUnwindInfoSegment(const Elf_Phdr *phdr, size_t image_base,
cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
if (EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
*cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
hdrInfo)) {
*cbdata->addressSpace, eh_frame_hdr_start,
eh_frame_hdr_start + phdr->p_memsz, hdrInfo)) {
// .eh_frame_hdr records the start of .eh_frame, but not its size.
// Rely on a zero terminator to find the end of the section.
cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
Expand Down Expand Up @@ -638,7 +638,8 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
info.dwarf_index_section_length = SIZE_MAX;
EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
if (!EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
*this, info.dwarf_index_section, info.dwarf_index_section_length,
*this, info.dwarf_index_section,
info.dwarf_index_section + info.dwarf_index_section_length,
hdrInfo)) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion system/lib/libunwind/src/DwarfInstructions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class DwarfInstructions {
return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
prolog.cfaRegisterOffset);
if (prolog.cfaExpression != 0)
return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
registers, 0);
assert(0 && "getCFA(): unknown location");
__builtin_unreachable();
Expand Down
13 changes: 13 additions & 0 deletions system/lib/libunwind/src/EHHeaderParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,19 @@ template <typename A>
bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
pint_t p = ehHdrStart;

// Ensure that we don't read data beyond the end of .eh_frame_hdr
if (ehHdrEnd - ehHdrStart < 4) {
// Don't print a message for an empty .eh_frame_hdr (this can happen if
// the linker script defines symbols for it even in the empty case).
if (ehHdrEnd == ehHdrStart)
return false;
_LIBUNWIND_LOG("unsupported .eh_frame_hdr at %" PRIx64
": need at least 4 bytes of data but only got %zd",
static_cast<uint64_t>(ehHdrStart),
static_cast<size_t>(ehHdrEnd - ehHdrStart));
return false;
}
uint8_t version = addressSpace.get8(p++);
if (version != 1) {
_LIBUNWIND_LOG("unsupported .eh_frame_hdr version: %" PRIu8 " at %" PRIx64,
Expand Down
6 changes: 3 additions & 3 deletions system/lib/libunwind/src/FrameHeaderCache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@

class _LIBUNWIND_HIDDEN FrameHeaderCache {
struct CacheEntry {
uintptr_t LowPC() { return Info.dso_base; };
uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; };
uintptr_t LowPC() { return Info.dso_base; }
uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; }
UnwindInfoSections Info;
CacheEntry *Next;
};
Expand All @@ -41,7 +41,7 @@ class _LIBUNWIND_HIDDEN FrameHeaderCache {

// Can't depend on the C++ standard library in libunwind, so use an array to
// allocate the entries, and two linked lists for ordering unused and recently
// used entries. FIXME: Would the the extra memory for a doubly-linked list
// used entries. FIXME: Would the extra memory for a doubly-linked list
// be better than the runtime cost of traversing a very short singly-linked
// list on a cache miss? The entries themselves are all small and consecutive,
// so unlikely to cause page faults when following the pointers. The memory
Expand Down
20 changes: 18 additions & 2 deletions system/lib/libunwind/src/Registers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,8 @@ class _LIBUNWIND_HIDDEN Registers_ppc {
void setIP(uint32_t value) { _registers.__srr0 = value; }
uint64_t getCR() const { return _registers.__cr; }
void setCR(uint32_t value) { _registers.__cr = value; }
uint64_t getLR() const { return _registers.__lr; }
void setLR(uint32_t value) { _registers.__lr = value; }

private:
struct ppc_thread_state_t {
Expand Down Expand Up @@ -1189,6 +1191,8 @@ class _LIBUNWIND_HIDDEN Registers_ppc64 {
void setIP(uint64_t value) { _registers.__srr0 = value; }
uint64_t getCR() const { return _registers.__cr; }
void setCR(uint64_t value) { _registers.__cr = value; }
uint64_t getLR() const { return _registers.__lr; }
void setLR(uint64_t value) { _registers.__lr = value; }

private:
struct ppc64_thread_state_t {
Expand Down Expand Up @@ -2869,7 +2873,7 @@ inline bool Registers_mips_o32::validRegister(int regNum) const {
return false;
if (regNum <= UNW_MIPS_R31)
return true;
#if __mips_isa_rev != 6
#if __mips_isa_rev < 6
if (regNum == UNW_MIPS_HI)
return true;
if (regNum == UNW_MIPS_LO)
Expand Down Expand Up @@ -2903,10 +2907,12 @@ inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
return _registers.__pc;
case UNW_REG_SP:
return _registers.__r[29];
#if __mips_isa_rev < 6
case UNW_MIPS_HI:
return _registers.__hi;
case UNW_MIPS_LO:
return _registers.__lo;
#endif
}
_LIBUNWIND_ABORT("unsupported mips_o32 register");
}
Expand Down Expand Up @@ -2936,11 +2942,13 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
case UNW_REG_SP:
_registers.__r[29] = value;
return;
#if __mips_isa_rev < 6
case UNW_MIPS_HI:
_registers.__hi = value;
return;
case UNW_MIPS_LO:
_registers.__lo = value;
#endif
return;
}
_LIBUNWIND_ABORT("unsupported mips_o32 register");
Expand Down Expand Up @@ -3120,10 +3128,12 @@ inline const char *Registers_mips_o32::getRegisterName(int regNum) {
return "$f30";
case UNW_MIPS_F31:
return "$f31";
#if __mips_isa_rev < 6
case UNW_MIPS_HI:
return "$hi";
case UNW_MIPS_LO:
return "$lo";
#endif
default:
return "unknown register";
}
Expand Down Expand Up @@ -3193,7 +3203,7 @@ inline bool Registers_mips_newabi::validRegister(int regNum) const {
return false;
if (regNum <= UNW_MIPS_R31)
return true;
#if __mips_isa_rev != 6
#if __mips_isa_rev < 6
if (regNum == UNW_MIPS_HI)
return true;
if (regNum == UNW_MIPS_LO)
Expand All @@ -3212,10 +3222,12 @@ inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
return _registers.__pc;
case UNW_REG_SP:
return _registers.__r[29];
#if __mips_isa_rev < 6
case UNW_MIPS_HI:
return _registers.__hi;
case UNW_MIPS_LO:
return _registers.__lo;
#endif
}
_LIBUNWIND_ABORT("unsupported mips_newabi register");
}
Expand All @@ -3233,12 +3245,14 @@ inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
case UNW_REG_SP:
_registers.__r[29] = value;
return;
#if __mips_isa_rev < 6
case UNW_MIPS_HI:
_registers.__hi = value;
return;
case UNW_MIPS_LO:
_registers.__lo = value;
return;
#endif
}
_LIBUNWIND_ABORT("unsupported mips_newabi register");
}
Expand Down Expand Up @@ -3417,10 +3431,12 @@ inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
return "$f30";
case UNW_MIPS_F31:
return "$f31";
#if __mips_isa_rev < 6
case UNW_MIPS_HI:
return "$hi";
case UNW_MIPS_LO:
return "$lo";
#endif
default:
return "unknown register";
}
Expand Down
Loading