[lld] r260294 - ELF: Add .eh_frame 'P', 'R' and 'L' augmentation characters.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 9 13:41:02 PST 2016
Author: ruiu
Date: Tue Feb 9 15:41:01 2016
New Revision: 260294
URL: http://llvm.org/viewvc/llvm-project?rev=260294&view=rev
Log:
ELF: Add .eh_frame 'P', 'R' and 'L' augmentation characters.
This basically reverts commit r260073 because it is found that
augmentation strings don't always start with "zR". It is reported
as https://llvm.org/bugs/show_bug.cgi?id=26541.
Modified:
lld/trunk/ELF/OutputSections.cpp
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=260294&r1=260293&r2=260294&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Tue Feb 9 15:41:01 2016
@@ -881,6 +881,34 @@ static void skipLeb128(ArrayRef<uint8_t>
fatal("corrupted or unsupported CIE information");
}
+template <class ELFT> static size_t getAugPSize(unsigned Enc) {
+ switch (Enc & 0x0f) {
+ case dwarf::DW_EH_PE_absptr:
+ case dwarf::DW_EH_PE_signed:
+ return ELFT::Is64Bits ? 8 : 4;
+ case dwarf::DW_EH_PE_udata2:
+ case dwarf::DW_EH_PE_sdata2:
+ return 2;
+ case dwarf::DW_EH_PE_udata4:
+ case dwarf::DW_EH_PE_sdata4:
+ return 4;
+ case dwarf::DW_EH_PE_udata8:
+ case dwarf::DW_EH_PE_sdata8:
+ return 8;
+ }
+ fatal("unknown FDE encoding");
+}
+
+template <class ELFT> static void skipAugP(ArrayRef<uint8_t> &D) {
+ uint8_t Enc = readByte(D);
+ if ((Enc & 0xf0) == dwarf::DW_EH_PE_aligned)
+ fatal("DW_EH_PE_aligned encoding is not supported");
+ size_t Size = getAugPSize<ELFT>(Enc);
+ if (Size < D.size())
+ fatal("corrupted CIE");
+ D = D.slice(Size);
+}
+
template <class ELFT>
uint8_t EHOutputSection<ELFT>::getFdeEncoding(ArrayRef<uint8_t> D) {
if (D.size() < 8)
@@ -911,13 +939,26 @@ uint8_t EHOutputSection<ELFT>::getFdeEnc
else
skipLeb128(D);
- // We assume that the augmentation string always starts with 'z'
- // (which specifies the size of the CIE field) and 'R' (which
- // specifies the FDE encoding.)
- if (!Aug.startswith("zR"))
- fatal("unknown .eh_frame augmentation string: " + Aug);
- skipLeb128(D);
- return readByte(D);
+ // We only care about an 'R' value, but other records may precede an 'R'
+ // record. Records are not in TLV (type-length-value) format, so we need
+ // to teach the linker how to skip records for each type.
+ for (; !Aug.empty(); Aug = Aug.substr(1)) {
+ switch (Aug[0]) {
+ case 'z':
+ skipLeb128(D);
+ break;
+ case 'R':
+ return readByte(D);
+ case 'P':
+ skipAugP<ELFT>(D);
+ break;
+ case 'L':
+ break;
+ default:
+ fatal("unknown .eh_frame augmentation string: " + Aug);
+ }
+ }
+ return dwarf::DW_EH_PE_absptr;
}
template <class ELFT>
More information about the llvm-commits
mailing list