Commit 5581990e authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r352016:

------------------------------------------------------------------------
r352016 | phosek | 2019-01-24 04:04:42 +0100 (Thu, 24 Jan 2019) | 12 lines

[libunwind] Don't abort if encoutering invalid .eh_frame_hdr

Recent Linux kernel release has introduced a bug as part of the ORC
rollout where the vDSO has a valid .eh_frame section, but it's missing
the .eh_frame_hdr section and GNU_EH_FRAME segment has zero size. This
causes libunwind to abort which breaks programs that use libunwind.

The other unwinder implementation (libgcc, non-gnu) instead silently
bail out unless being compiled as debug. This change modifies libunwind
to use the same strategy.

Differential Revision: https://reviews.llvm.org/D57081
------------------------------------------------------------------------

llvm-svn: 353287
parent 35f4f2f7
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -534,11 +534,11 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
#endif
            cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
            cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
            EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
            found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
                *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
                hdrInfo);
            if (found_hdr)
              cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
            found_hdr = true;
          }
        }

+11 −5
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ public:
    uint8_t table_enc;
  };

  static void decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd,
  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,
@@ -53,12 +53,14 @@ private:
};

template <typename A>
void EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
                                    pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
  pint_t p = ehHdrStart;
  uint8_t version = addressSpace.get8(p++);
  if (version != 1)
    _LIBUNWIND_ABORT("Unsupported .eh_frame_hdr version");
  if (version != 1) {
    _LIBUNWIND_LOG0("Unsupported .eh_frame_hdr version");
    return false;
  }

  uint8_t eh_frame_ptr_enc = addressSpace.get8(p++);
  uint8_t fde_count_enc = addressSpace.get8(p++);
@@ -71,6 +73,8 @@ void EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
          ? 0
          : addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart);
  ehHdrInfo.table = p;

  return true;
}

template <typename A>
@@ -102,7 +106,9 @@ bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,
  pint_t ehHdrEnd = ehHdrStart + sectionLength;

  EHHeaderParser<A>::EHHeaderInfo hdrInfo;
  EHHeaderParser<A>::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd, hdrInfo);
  if (!EHHeaderParser<A>::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd,
                                      hdrInfo))
    return false;

  size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc);
  pint_t tableEntry;