Пример #1
0
void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
                                            const VTableLayout &VTLayout) {
  if (!LangOpts.Sanitize.has(SanitizerKind::CFIVCall) &&
      !LangOpts.Sanitize.has(SanitizerKind::CFINVCall) &&
      !LangOpts.Sanitize.has(SanitizerKind::CFIDerivedCast) &&
      !LangOpts.Sanitize.has(SanitizerKind::CFIUnrelatedCast))
    return;

  CharUnits PointerWidth =
      Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));

  typedef std::pair<const CXXRecordDecl *, unsigned> BSEntry;
  std::vector<BSEntry> BitsetEntries;
  // Create a bit set entry for each address point.
  for (auto &&AP : VTLayout.getAddressPoints()) {
    if (IsCFIBlacklistedRecord(AP.first.getBase()))
      continue;

    BitsetEntries.push_back(std::make_pair(AP.first.getBase(), AP.second));
  }

  // Sort the bit set entries for determinism.
  std::sort(BitsetEntries.begin(), BitsetEntries.end(),
            [this](const BSEntry &E1, const BSEntry &E2) {
    if (&E1 == &E2)
      return false;

    std::string S1;
    llvm::raw_string_ostream O1(S1);
    getCXXABI().getMangleContext().mangleTypeName(
        QualType(E1.first->getTypeForDecl(), 0), O1);
    O1.flush();

    std::string S2;
    llvm::raw_string_ostream O2(S2);
    getCXXABI().getMangleContext().mangleTypeName(
        QualType(E2.first->getTypeForDecl(), 0), O2);
    O2.flush();

    if (S1 < S2)
      return true;
    if (S1 != S2)
      return false;

    return E1.second < E2.second;
  });

  llvm::NamedMDNode *BitsetsMD =
      getModule().getOrInsertNamedMetadata("llvm.bitsets");
  for (auto BitsetEntry : BitsetEntries)
    CreateVTableBitSetEntry(BitsetsMD, VTable,
                            PointerWidth * BitsetEntry.second,
                            BitsetEntry.first);
}
Пример #2
0
void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
                                           const VTableLayout &VTLayout) {
  if (!getCodeGenOpts().LTOUnit)
    return;

  CharUnits PointerWidth =
      Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));

  typedef std::pair<const CXXRecordDecl *, unsigned> BSEntry;
  std::vector<BSEntry> BitsetEntries;
  // Create a bit set entry for each address point.
  for (auto &&AP : VTLayout.getAddressPoints())
    BitsetEntries.push_back(
        std::make_pair(AP.first.getBase(),
                       VTLayout.getVTableOffset(AP.second.VTableIndex) +
                           AP.second.AddressPointIndex));

  // Sort the bit set entries for determinism.
  std::sort(BitsetEntries.begin(), BitsetEntries.end(),
            [this](const BSEntry &E1, const BSEntry &E2) {
    if (&E1 == &E2)
      return false;

    std::string S1;
    llvm::raw_string_ostream O1(S1);
    getCXXABI().getMangleContext().mangleTypeName(
        QualType(E1.first->getTypeForDecl(), 0), O1);
    O1.flush();

    std::string S2;
    llvm::raw_string_ostream O2(S2);
    getCXXABI().getMangleContext().mangleTypeName(
        QualType(E2.first->getTypeForDecl(), 0), O2);
    O2.flush();

    if (S1 < S2)
      return true;
    if (S1 != S2)
      return false;

    return E1.second < E2.second;
  });

  for (auto BitsetEntry : BitsetEntries)
    AddVTableTypeMetadata(VTable, PointerWidth * BitsetEntry.second,
                          BitsetEntry.first);
}
Пример #3
0
void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
                                           const VTableLayout &VTLayout) {
  if (!getCodeGenOpts().LTOUnit)
    return;

  CharUnits PointerWidth =
      Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));

  typedef std::pair<const CXXRecordDecl *, unsigned> AddressPoint;
  std::vector<AddressPoint> AddressPoints;
  for (auto &&AP : VTLayout.getAddressPoints())
    AddressPoints.push_back(std::make_pair(
        AP.first.getBase(), VTLayout.getVTableOffset(AP.second.VTableIndex) +
                                AP.second.AddressPointIndex));

  // Sort the address points for determinism.
  llvm::sort(AddressPoints, [this](const AddressPoint &AP1,
                                   const AddressPoint &AP2) {
    if (&AP1 == &AP2)
      return false;

    std::string S1;
    llvm::raw_string_ostream O1(S1);
    getCXXABI().getMangleContext().mangleTypeName(
        QualType(AP1.first->getTypeForDecl(), 0), O1);
    O1.flush();

    std::string S2;
    llvm::raw_string_ostream O2(S2);
    getCXXABI().getMangleContext().mangleTypeName(
        QualType(AP2.first->getTypeForDecl(), 0), O2);
    O2.flush();

    if (S1 < S2)
      return true;
    if (S1 != S2)
      return false;

    return AP1.second < AP2.second;
  });

  ArrayRef<VTableComponent> Comps = VTLayout.vtable_components();
  for (auto AP : AddressPoints) {
    // Create type metadata for the address point.
    AddVTableTypeMetadata(VTable, PointerWidth * AP.second, AP.first);

    // The class associated with each address point could also potentially be
    // used for indirect calls via a member function pointer, so we need to
    // annotate the address of each function pointer with the appropriate member
    // function pointer type.
    for (unsigned I = 0; I != Comps.size(); ++I) {
      if (Comps[I].getKind() != VTableComponent::CK_FunctionPointer)
        continue;
      llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType(
          Context.getMemberPointerType(
              Comps[I].getFunctionDecl()->getType(),
              Context.getRecordType(AP.first).getTypePtr()));
      VTable->addTypeMetadata((PointerWidth * I).getQuantity(), MD);
    }
  }
}
Пример #4
0
void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
                                            const VTableLayout &VTLayout) {
  if (!LangOpts.Sanitize.has(SanitizerKind::CFIVCall) &&
      !LangOpts.Sanitize.has(SanitizerKind::CFINVCall) &&
      !LangOpts.Sanitize.has(SanitizerKind::CFIDerivedCast) &&
      !LangOpts.Sanitize.has(SanitizerKind::CFIUnrelatedCast))
    return;

  llvm::Metadata *VTableMD = llvm::ConstantAsMetadata::get(VTable);

  std::vector<llvm::MDTuple *> BitsetEntries;
  // Create a bit set entry for each address point.
  for (auto &&AP : VTLayout.getAddressPoints()) {
    // FIXME: Add blacklisting scheme.
    if (AP.first.getBase()->isInStdNamespace())
      continue;

    std::string OutName;
    llvm::raw_string_ostream Out(OutName);
    getCXXABI().getMangleContext().mangleCXXVTableBitSet(AP.first.getBase(),
                                                         Out);

    CharUnits PointerWidth =
        Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
    uint64_t AddrPointOffset = AP.second * PointerWidth.getQuantity();

    llvm::Metadata *BitsetOps[] = {
        llvm::MDString::get(getLLVMContext(), Out.str()),
        VTableMD,
        llvm::ConstantAsMetadata::get(
            llvm::ConstantInt::get(Int64Ty, AddrPointOffset))};
    llvm::MDTuple *BitsetEntry =
        llvm::MDTuple::get(getLLVMContext(), BitsetOps);
    BitsetEntries.push_back(BitsetEntry);
  }

  // Sort the bit set entries for determinism.
  std::sort(BitsetEntries.begin(), BitsetEntries.end(), [](llvm::MDTuple *T1,
                                                           llvm::MDTuple *T2) {
    if (T1 == T2)
      return false;

    StringRef S1 = cast<llvm::MDString>(T1->getOperand(0))->getString();
    StringRef S2 = cast<llvm::MDString>(T2->getOperand(0))->getString();
    if (S1 < S2)
      return true;
    if (S1 != S2)
      return false;

    uint64_t Offset1 = cast<llvm::ConstantInt>(
                           cast<llvm::ConstantAsMetadata>(T1->getOperand(2))
                               ->getValue())->getZExtValue();
    uint64_t Offset2 = cast<llvm::ConstantInt>(
                           cast<llvm::ConstantAsMetadata>(T2->getOperand(2))
                               ->getValue())->getZExtValue();
    assert(Offset1 != Offset2);
    return Offset1 < Offset2;
  });

  llvm::NamedMDNode *BitsetsMD =
      getModule().getOrInsertNamedMetadata("llvm.bitsets");
  for (auto BitsetEntry : BitsetEntries)
    BitsetsMD->addOperand(BitsetEntry);
}