Esempio n. 1
0
void EhFrame::moveInputFragments(EhFrame& pInFrame,
                                 CIE& pInCIE, CIE* pOutCIE)
{
  SectionData& in_sd = *pInFrame.getSectionData();
  SectionData::FragmentListType& in_frag_list = in_sd.getFragmentList();
  SectionData& out_sd = *getSectionData();
  SectionData::FragmentListType& out_frag_list = out_sd.getFragmentList();

  if (!pOutCIE) {
    // Newly inserted
    Fragment* frag = in_frag_list.remove(SectionData::iterator(pInCIE));
    out_frag_list.push_back(frag);
    frag->setParent(&out_sd);
    for (fde_iterator i = pInCIE.begin(), e = pInCIE.end(); i != e; ++i) {
      frag = in_frag_list.remove(SectionData::iterator(**i));
      out_frag_list.push_back(frag);
      frag->setParent(&out_sd);
    }
    return;
  }

  SectionData::iterator cur_iter(*pOutCIE);
  assert (cur_iter != out_frag_list.end());
  for (fde_iterator i = pInCIE.begin(), e = pInCIE.end(); i != e; ++i) {
    Fragment* frag = in_frag_list.remove(SectionData::iterator(**i));
    cur_iter = out_frag_list.insertAfter(cur_iter, frag);
    frag->setParent(&out_sd);
  }
}
Esempio n. 2
0
void EhFrame::setupAttributes(const LDSection* rel_sec)
{
  for (cie_iterator i = cie_begin(), e = cie_end(); i != e; ++i) {
    CIE* cie = *i;
    removeDiscardedFDE(*cie, rel_sec);

    if (cie->getPersonalityName().size() == 0) {
      // There's no personality data encoding inside augmentation string.
      cie->setMergeable();
    } else {
      if (!rel_sec) {
        // No relocation to eh_frame section
        assert (cie->getPersonalityName() != "" &&
                "PR name should be a symbol address or offset");
        continue;
      }
      const RelocData* reloc_data = rel_sec->getRelocData();
      for (RelocData::const_iterator ri = reloc_data->begin(),
           re = reloc_data->end(); ri != re; ++ri) {
        const Relocation& rel = *ri;
        if (rel.targetRef().getOutputOffset() == cie->getOffset() +
                                                 cie->getPersonalityOffset()) {
          cie->setMergeable();
          cie->setPersonalityName(rel.symInfo()->outSymbol()->name());
          cie->setRelocation(rel);
          break;
        }
      }

      assert (cie->getPersonalityName() != "" &&
              "PR name should be a symbol address or offset");
    }
  }
}
Esempio n. 3
0
void EhFrame::removeDiscardedFDE(CIE& pCIE, const LDSection* pRelocSect) {
  if (!pRelocSect)
    return;

  typedef std::vector<FDE*> FDERemoveList;
  FDERemoveList to_be_removed_fdes;
  const RelocData* reloc_data = pRelocSect->getRelocData();
  for (fde_iterator i = pCIE.begin(), e = pCIE.end(); i != e; ++i) {
    FDE& fde = **i;
    for (RelocData::const_iterator ri = reloc_data->begin(),
                                   re = reloc_data->end();
         ri != re;
         ++ri) {
      const Relocation& rel = *ri;
      if (rel.targetRef().getOutputOffset() ==
          fde.getOffset() + getDataStartOffset<32>()) {
        bool has_section = rel.symInfo()->outSymbol()->hasFragRef();
        if (!has_section)
          // The section was discarded, just ignore this FDE.
          // This may happen when redundant group section was read.
          to_be_removed_fdes.push_back(&fde);
        break;
      }
    }
  }

  for (FDERemoveList::iterator i = to_be_removed_fdes.begin(),
                               e = to_be_removed_fdes.end();
       i != e;
       ++i) {
    FDE& fde = **i;
    fde.getCIE().remove(fde);

    // FIXME: This traverses relocations from the beginning on each FDE, which
    // may cause performance degration. Actually relocations will be sequential
    // order, so we can bookkeep the previously found relocation for next use.
    // Note: We must ensure FDE order is ordered.
    for (RelocData::const_iterator ri = reloc_data->begin(),
                                   re = reloc_data->end();
         ri != re;) {
      Relocation& rel = const_cast<Relocation&>(*ri++);
      if (rel.targetRef().getOutputOffset() >= fde.getOffset() &&
          rel.targetRef().getOutputOffset() < fde.getOffset() + fde.size()) {
        const_cast<RelocData*>(reloc_data)->remove(rel);
      }
    }
  }
}
Esempio n. 4
0
void EhFrame::removeAndUpdateCIEForFDE(EhFrame& pInFrame, CIE& pInCIE,
                                       CIE& pOutCIE, const LDSection* rel_sect)
{
  // Make this relocation to be ignored.
  Relocation* rel = const_cast<Relocation*>(pInCIE.getRelocation());
  if (rel && rel_sect)
    const_cast<RelocData*>(rel_sect->getRelocData())->remove(*rel);

  // Update the CIE-pointed FDEs
  for (fde_iterator i = pInCIE.begin(), e = pInCIE.end(); i != e; ++i)
    (*i)->setCIE(pOutCIE);

  // We cannot know whether there are references to this fragment, so just
  // keep it in input fragment list instead of memory deallocation
  pInCIE.clearFDEs();
}
Esempio n. 5
0
void DWARFDebugFrame::parse(DataExtractor Data) {
  uint32_t Offset = 0;
  DenseMap<uint32_t, CIE *> CIEs;

  while (Data.isValidOffset(Offset)) {
    uint32_t StartOffset = Offset;

    auto ReportError = [StartOffset](const char *ErrorMsg) {
      std::string Str;
      raw_string_ostream OS(Str);
      OS << format(ErrorMsg, StartOffset);
      OS.flush();
      report_fatal_error(Str);
    };

    bool IsDWARF64 = false;
    uint64_t Length = Data.getU32(&Offset);
    uint64_t Id;

    if (Length == UINT32_MAX) {
      // DWARF-64 is distinguished by the first 32 bits of the initial length
      // field being 0xffffffff. Then, the next 64 bits are the actual entry
      // length.
      IsDWARF64 = true;
      Length = Data.getU64(&Offset);
    }

    // At this point, Offset points to the next field after Length.
    // Length is the structure size excluding itself. Compute an offset one
    // past the end of the structure (needed to know how many instructions to
    // read).
    // TODO: For honest DWARF64 support, DataExtractor will have to treat
    //       offset_ptr as uint64_t*
    uint32_t StartStructureOffset = Offset;
    uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);

    // The Id field's size depends on the DWARF format
    Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4);
    bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) ||
                  Id == DW_CIE_ID ||
                  (IsEH && !Id));

    if (IsCIE) {
      uint8_t Version = Data.getU8(&Offset);
      const char *Augmentation = Data.getCStr(&Offset);
      StringRef AugmentationString(Augmentation ? Augmentation : "");
      uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
                                          Data.getU8(&Offset);
      Data.setAddressSize(AddressSize);
      uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
      uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
      int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
      uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);

      // Parse the augmentation data for EH CIEs
      StringRef AugmentationData("");
      uint32_t FDEPointerEncoding = DW_EH_PE_omit;
      uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
      if (IsEH) {
        Optional<uint32_t> PersonalityEncoding;
        Optional<uint64_t> Personality;

        Optional<uint64_t> AugmentationLength;
        uint32_t StartAugmentationOffset;
        uint32_t EndAugmentationOffset;

        // Walk the augmentation string to get all the augmentation data.
        for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
          switch (AugmentationString[i]) {
            default:
              ReportError("Unknown augmentation character in entry at %lx");
            case 'L':
              LSDAPointerEncoding = Data.getU8(&Offset);
              break;
            case 'P': {
              if (Personality)
                ReportError("Duplicate personality in entry at %lx");
              PersonalityEncoding = Data.getU8(&Offset);
              Personality = readPointer(Data, Offset, *PersonalityEncoding);
              break;
            }
            case 'R':
              FDEPointerEncoding = Data.getU8(&Offset);
              break;
            case 'z':
              if (i)
                ReportError("'z' must be the first character at %lx");
              // Parse the augmentation length first.  We only parse it if
              // the string contains a 'z'.
              AugmentationLength = Data.getULEB128(&Offset);
              StartAugmentationOffset = Offset;
              EndAugmentationOffset = Offset +
                static_cast<uint32_t>(*AugmentationLength);
          }
        }

        if (AugmentationLength.hasValue()) {
          if (Offset != EndAugmentationOffset)
            ReportError("Parsing augmentation data at %lx failed");

          AugmentationData = Data.getData().slice(StartAugmentationOffset,
                                                  EndAugmentationOffset);
        }
      }

      auto Cie = make_unique<CIE>(StartOffset, Length, Version,
                                  AugmentationString, AddressSize,
                                  SegmentDescriptorSize, CodeAlignmentFactor,
                                  DataAlignmentFactor, ReturnAddressRegister,
                                  AugmentationData, FDEPointerEncoding,
                                  LSDAPointerEncoding);
      CIEs[StartOffset] = Cie.get();
      Entries.emplace_back(std::move(Cie));
    } else {
      // FDE
      uint64_t CIEPointer = Id;
      uint64_t InitialLocation = 0;
      uint64_t AddressRange = 0;
      CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];

      if (IsEH) {
        // The address size is encoded in the CIE we reference.
        if (!Cie)
          ReportError("Parsing FDE data at %lx failed due to missing CIE");

        InitialLocation = readPointer(Data, Offset,
                                      Cie->getFDEPointerEncoding());
        AddressRange = readPointer(Data, Offset,
                                   Cie->getFDEPointerEncoding());

        StringRef AugmentationString = Cie->getAugmentationString();
        if (!AugmentationString.empty()) {
          // Parse the augmentation length and data for this FDE.
          uint64_t AugmentationLength = Data.getULEB128(&Offset);

          uint32_t EndAugmentationOffset =
            Offset + static_cast<uint32_t>(AugmentationLength);

          // Decode the LSDA if the CIE augmentation string said we should.
          if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit)
            readPointer(Data, Offset, Cie->getLSDAPointerEncoding());

          if (Offset != EndAugmentationOffset)
            ReportError("Parsing augmentation data at %lx failed");
        }
      } else {
        InitialLocation = Data.getAddress(&Offset);
        AddressRange = Data.getAddress(&Offset);
      }

      Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
                                   InitialLocation, AddressRange,
                                   Cie));
    }

    Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);

    if (Offset != EndStructureOffset)
      ReportError("Parsing entry instructions at %lx failed");
  }
}