summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2016-02-08 05:18:44 +0000
committerRui Ueyama <ruiu@google.com>2016-02-08 05:18:44 +0000
commitbe748c2033b39afbd559166d2209c1c712b896b3 (patch)
tree3e708668389fb5c17e03a71cd230e804a50d9535
parentb4fd8bb27ed60106f359264ae13137a9bc8f412b (diff)
downloadbcm5719-llvm-be748c2033b39afbd559166d2209c1c712b896b3.tar.gz
bcm5719-llvm-be748c2033b39afbd559166d2209c1c712b896b3.zip
ELF: Simplify getFdeEncoding.
I found that the handling of 'L' character in an augmentation string is wrong because 'L' means that the next byte is the length field. I could have fixed that by just skipping the next byte, but I decided to take a different approach. Teaching the linker about all the types of CIE internal records just to skip them is silly. And the code doing that is not actually executed now (that's why the bug did not cause any issue.) It is because the 'R' field, which we want to read, is always at beginning of the CIE. So I reduced the code dramatically by assuming that that's always the case. I want to see how it works in the wild. If it doesn't work, we can roll this back (with a fix for 'L'). http://reviews.llvm.org/D16939 llvm-svn: 260073
-rw-r--r--lld/ELF/OutputSections.cpp73
1 files changed, 15 insertions, 58 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 2f133d75e4b..b179c979930 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -881,34 +881,10 @@ static void skipLeb128(ArrayRef<uint8_t> &D) {
fatal("corrupted or unsupported CIE information");
}
-template <class ELFT> static unsigned getSizeForEncoding(unsigned Enc) {
- typedef typename ELFFile<ELFT>::uintX_t uintX_t;
- switch (Enc & 0x0f) {
- default:
- fatal("unknown FDE encoding");
- case dwarf::DW_EH_PE_absptr:
- case dwarf::DW_EH_PE_signed:
- return sizeof(uintX_t);
- 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;
- }
-}
-
template <class ELFT>
uint8_t EHOutputSection<ELFT>::getFdeEncoding(ArrayRef<uint8_t> D) {
- auto Check = [](bool C) {
- if (!C)
- fatal("corrupted or unsupported CIE information");
- };
-
- Check(D.size() >= 8);
+ if (D.size() < 8)
+ fatal("CIE too small");
D = D.slice(8);
uint8_t Version = readByte(D);
@@ -916,14 +892,16 @@ uint8_t EHOutputSection<ELFT>::getFdeEncoding(ArrayRef<uint8_t> D) {
fatal("FDE version 1 or 3 expected, but got " + Twine((unsigned)Version));
auto AugEnd = std::find(D.begin() + 1, D.end(), '\0');
- Check(AugEnd != D.end());
- ArrayRef<uint8_t> AugString(D.begin(), AugEnd - D.begin());
- D = D.slice(AugString.size() + 1);
+ if (AugEnd == D.end())
+ fatal("corrupted CIE");
+ StringRef Aug((char *)D.begin(), AugEnd - D.begin());
+ D = D.slice(Aug.size() + 1);
// Code alignment factor should always be 1 for .eh_frame.
if (readByte(D) != 1)
fatal("CIE code alignment must be 1");
- // Skip data alignment factor
+
+ // Skip data alignment factor.
skipLeb128(D);
// Skip the return address register. In CIE version 1 this is a single
@@ -933,34 +911,13 @@ uint8_t EHOutputSection<ELFT>::getFdeEncoding(ArrayRef<uint8_t> D) {
else
skipLeb128(D);
- while (!AugString.empty()) {
- switch (readByte(AugString)) {
- case 'z':
- skipLeb128(D);
- break;
- case 'R':
- return readByte(D);
- case 'P': {
- uint8_t Enc = readByte(D);
- if ((Enc & 0xf0) == dwarf::DW_EH_PE_aligned)
- fatal("DW_EH_PE_aligned encoding for address of a personality routine "
- "handler not supported");
- unsigned EncSize = getSizeForEncoding<ELFT>(Enc);
- Check(D.size() >= EncSize);
- D = D.slice(EncSize);
- break;
- }
- case 'S':
- case 'L':
- // L: Language Specific Data Area (LSDA) encoding
- // S: This CIE represents a stack frame for the invocation of a signal
- // handler
- break;
- default:
- fatal("unknown .eh_frame augmentation string value");
- }
- }
- return dwarf::DW_EH_PE_absptr;
+ // 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);
}
template <class ELFT>
OpenPOWER on IntegriCloud