[lld] r260073 - ELF: Simplify getFdeEncoding.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 7 21:18:44 PST 2016


Author: ruiu
Date: Sun Feb  7 23:18:44 2016
New Revision: 260073

URL: http://llvm.org/viewvc/llvm-project?rev=260073&view=rev
Log:
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

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=260073&r1=260072&r2=260073&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Sun Feb  7 23:18:44 2016
@@ -881,34 +881,10 @@ static void skipLeb128(ArrayRef<uint8_t>
   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>::getFdeEnc
     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>::getFdeEnc
   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>




More information about the llvm-commits mailing list