Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
[cfi] CFI-ICall for ThinLTO.
Browse files Browse the repository at this point in the history
Implement ControlFlowIntegrity for indirect function calls in ThinLTO.
Design follows the RFC in llvm-dev, see
https://groups.google.com/d/msg/llvm-dev/MgUlaphu4Qc/kywu0AqjAQAJ

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305533 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
eugenis committed Jun 16, 2017
1 parent 68e216b commit 3184f8d
Show file tree
Hide file tree
Showing 17 changed files with 494 additions and 32 deletions.
7 changes: 7 additions & 0 deletions include/llvm/Analysis/TypeMetadataUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@

namespace llvm {

/// The type of CFI jumptable needed for a function.
enum CfiFunctionLinkage {
CFL_Definition = 0,
CFL_Declaration = 1,
CFL_WeakDeclaration = 2
};

/// A call site that could be devirtualized.
struct DevirtCallSite {
/// The offset from the address point to the virtual function.
Expand Down
4 changes: 4 additions & 0 deletions include/llvm/Bitcode/BitcodeWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ namespace llvm {
void writeModule(const Module *M, bool ShouldPreserveUseListOrder = false,
const ModuleSummaryIndex *Index = nullptr,
bool GenerateHash = false, ModuleHash *ModHash = nullptr);

void writeIndex(
const ModuleSummaryIndex *Index,
const std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex);
};

/// \brief Write the specified module to the specified raw output stream.
Expand Down
8 changes: 8 additions & 0 deletions include/llvm/Bitcode/LLVMBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,14 @@ enum GlobalValueSummarySymtabCodes {
// summaries, but it can also appear in per-module summaries for PGO data.
// [valueid, guid]
FS_VALUE_GUID = 16,
// The list of local functions with CFI jump tables. Function names are
// strings in strtab.
// [n * name]
FS_CFI_FUNCTION_DEFS = 17,
// The list of external functions with CFI jump tables. Function names are
// strings in strtab.
// [n * name]
FS_CFI_FUNCTION_DECLS = 18,
};

enum MetadataCodes {
Expand Down
10 changes: 10 additions & 0 deletions include/llvm/IR/ModuleSummaryIndex.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <cstdint>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
Expand Down Expand Up @@ -542,6 +543,9 @@ class ModuleSummaryIndex {
/// considered live.
bool WithGlobalValueDeadStripping = false;

std::set<std::string> CfiFunctionDefs;
std::set<std::string> CfiFunctionDecls;

// YAML I/O support.
friend yaml::MappingTraits<ModuleSummaryIndex>;

Expand Down Expand Up @@ -593,6 +597,12 @@ class ModuleSummaryIndex {
return I == OidGuidMap.end() ? 0 : I->second;
}

std::set<std::string> &cfiFunctionDefs() { return CfiFunctionDefs; }
const std::set<std::string> &cfiFunctionDefs() const { return CfiFunctionDefs; }

std::set<std::string> &cfiFunctionDecls() { return CfiFunctionDecls; }
const std::set<std::string> &cfiFunctionDecls() const { return CfiFunctionDecls; }

/// Add a global value summary for a value of the given name.
void addGlobalValueSummary(StringRef ValueName,
std::unique_ptr<GlobalValueSummary> Summary) {
Expand Down
18 changes: 18 additions & 0 deletions include/llvm/IR/ModuleSummaryIndexYAML.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ template <> struct MappingTraits<FunctionSummaryYaml> {

LLVM_YAML_IS_STRING_MAP(TypeIdSummary)
LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummaryYaml)
LLVM_YAML_IS_SEQUENCE_VECTOR(std::string)

namespace llvm {
namespace yaml {
Expand Down Expand Up @@ -240,6 +241,23 @@ template <> struct MappingTraits<ModuleSummaryIndex> {
io.mapOptional("TypeIdMap", index.TypeIdMap);
io.mapOptional("WithGlobalValueDeadStripping",
index.WithGlobalValueDeadStripping);

if (io.outputting()) {
std::vector<std::string> CfiFunctionDefs(index.CfiFunctionDefs.begin(),
index.CfiFunctionDefs.end());
io.mapOptional("CfiFunctionDefs", CfiFunctionDefs);
std::vector<std::string> CfiFunctionDecls(index.CfiFunctionDecls.begin(),
index.CfiFunctionDecls.end());
io.mapOptional("CfiFunctionDecls", CfiFunctionDecls);
} else {
std::vector<std::string> CfiFunctionDefs;
io.mapOptional("CfiFunctionDefs", CfiFunctionDefs);
index.CfiFunctionDefs = {CfiFunctionDefs.begin(), CfiFunctionDefs.end()};
std::vector<std::string> CfiFunctionDecls;
io.mapOptional("CfiFunctionDecls", CfiFunctionDecls);
index.CfiFunctionDecls = {CfiFunctionDecls.begin(),
CfiFunctionDecls.end()};
}
}
};

Expand Down
12 changes: 12 additions & 0 deletions lib/Bitcode/Reader/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5252,6 +5252,18 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
{{Record[0], Record[1]}, {Record.begin() + 2, Record.end()}});
break;
}
case bitc::FS_CFI_FUNCTION_DEFS: {
std::set<std::string> &CfiFunctionDefs = TheIndex.cfiFunctionDefs();
for (unsigned I = 0; I != Record.size(); I += 2)
CfiFunctionDefs.insert({Strtab.data() + Record[I], Record[I+1]});
break;
}
case bitc::FS_CFI_FUNCTION_DECLS: {
std::set<std::string> &CfiFunctionDecls = TheIndex.cfiFunctionDecls();
for (unsigned I = 0; I != Record.size(); I += 2)
CfiFunctionDecls.insert({Strtab.data() + Record[I], Record[I+1]});
break;
}
}
}
llvm_unreachable("Exit infinite loop");
Expand Down
50 changes: 38 additions & 12 deletions lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,13 @@ class BitcodeWriterBase {
/// The stream created and owned by the client.
BitstreamWriter &Stream;

StringTableBuilder &StrtabBuilder;

public:
/// Constructs a BitcodeWriterBase object that writes to the provided
/// \p Stream.
BitcodeWriterBase(BitstreamWriter &Stream) : Stream(Stream) {}
BitcodeWriterBase(BitstreamWriter &Stream, StringTableBuilder &StrtabBuilder)
: Stream(Stream), StrtabBuilder(StrtabBuilder) {}

protected:
void writeBitcodeHeader();
Expand All @@ -97,8 +100,6 @@ class ModuleBitcodeWriter : public BitcodeWriterBase {
/// Pointer to the buffer allocated by caller for bitcode writing.
const SmallVectorImpl<char> &Buffer;

StringTableBuilder &StrtabBuilder;

/// The Module to write to bitcode.
const Module &M;

Expand Down Expand Up @@ -142,8 +143,8 @@ class ModuleBitcodeWriter : public BitcodeWriterBase {
BitstreamWriter &Stream, bool ShouldPreserveUseListOrder,
const ModuleSummaryIndex *Index, bool GenerateHash,
ModuleHash *ModHash = nullptr)
: BitcodeWriterBase(Stream), Buffer(Buffer), StrtabBuilder(StrtabBuilder),
M(*M), VE(*M, ShouldPreserveUseListOrder), Index(Index),
: BitcodeWriterBase(Stream, StrtabBuilder), Buffer(Buffer), M(*M),
VE(*M, ShouldPreserveUseListOrder), Index(Index),
GenerateHash(GenerateHash), ModHash(ModHash),
BitcodeStartBit(Stream.GetCurrentBitNo()) {
// Assign ValueIds to any callee values in the index that came from
Expand Down Expand Up @@ -331,10 +332,11 @@ class IndexBitcodeWriter : public BitcodeWriterBase {
/// Constructs a IndexBitcodeWriter object for the given combined index,
/// writing to the provided \p Buffer. When writing a subset of the index
/// for a distributed backend, provide a \p ModuleToSummariesForIndex map.
IndexBitcodeWriter(BitstreamWriter &Stream, const ModuleSummaryIndex &Index,
IndexBitcodeWriter(BitstreamWriter &Stream, StringTableBuilder &StrtabBuilder,
const ModuleSummaryIndex &Index,
const std::map<std::string, GVSummaryMapTy>
*ModuleToSummariesForIndex = nullptr)
: BitcodeWriterBase(Stream), Index(Index),
: BitcodeWriterBase(Stream, StrtabBuilder), Index(Index),
ModuleToSummariesForIndex(ModuleToSummariesForIndex) {
// Assign unique value ids to all summaries to be written, for use
// in writing out the call graph edges. Save the mapping from GUID
Expand Down Expand Up @@ -3595,6 +3597,24 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
MaybeEmitOriginalName(*AS);
}

if (!Index.cfiFunctionDefs().empty()) {
for (auto &S : Index.cfiFunctionDefs()) {
NameVals.push_back(StrtabBuilder.add(S));
NameVals.push_back(S.size());
}
Stream.EmitRecord(bitc::FS_CFI_FUNCTION_DEFS, NameVals);
NameVals.clear();
}

if (!Index.cfiFunctionDecls().empty()) {
for (auto &S : Index.cfiFunctionDecls()) {
NameVals.push_back(StrtabBuilder.add(S));
NameVals.push_back(S.size());
}
Stream.EmitRecord(bitc::FS_CFI_FUNCTION_DECLS, NameVals);
NameVals.clear();
}

Stream.ExitBlock();
}

Expand Down Expand Up @@ -3829,6 +3849,14 @@ void BitcodeWriter::writeModule(const Module *M,
ModuleWriter.write();
}

void BitcodeWriter::writeIndex(
const ModuleSummaryIndex *Index,
const std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex) {
IndexBitcodeWriter IndexWriter(*Stream, StrtabBuilder, *Index,
ModuleToSummariesForIndex);
IndexWriter.write();
}

/// WriteBitcodeToFile - Write the specified module to the specified output
/// stream.
void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out,
Expand Down Expand Up @@ -3880,11 +3908,9 @@ void llvm::WriteIndexToFile(
SmallVector<char, 0> Buffer;
Buffer.reserve(256 * 1024);

BitstreamWriter Stream(Buffer);
writeBitcodeHeader(Stream);

IndexBitcodeWriter IndexWriter(Stream, Index, ModuleToSummariesForIndex);
IndexWriter.write();
BitcodeWriter Writer(Buffer);
Writer.writeIndex(&Index, ModuleToSummariesForIndex);
Writer.writeStrtab();

Out.write((char *)&Buffer.front(), Buffer.size());
}
7 changes: 5 additions & 2 deletions lib/IR/ModuleSummaryIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ ModuleSummaryIndex::getGlobalValueSummary(uint64_t ValueGUID,
bool ModuleSummaryIndex::isGUIDLive(GlobalValue::GUID GUID) const {
auto VI = getValueInfo(GUID);
if (!VI)
return false;
for (auto &I : VI.getSummaryList())
return true;
const auto &SummaryList = VI.getSummaryList();
if (SummaryList.empty())
return true;
for (auto &I : SummaryList)
if (isGlobalValueLive(I.get()))
return true;
return false;
Expand Down
11 changes: 11 additions & 0 deletions lib/Transforms/IPO/CrossDSOCFI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,17 @@ void CrossDSOCFI::buildCFICheck(Module &M) {
}
}

NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions");
if (CfiFunctionsMD) {
for (auto Func : CfiFunctionsMD->operands()) {
assert(Func->getNumOperands() >= 2);
for (unsigned I = 2; I < Func->getNumOperands(); ++I)
if (ConstantInt *TypeId =
extractNumericTypeId(cast<MDNode>(Func->getOperand(I).get())))
TypeIds.insert(TypeId->getZExtValue());
}
}

LLVMContext &Ctx = M.getContext();
Constant *C = M.getOrInsertFunction(
"__cfi_check", Type::getVoidTy(Ctx), Type::getInt64Ty(Ctx),
Expand Down
Loading

0 comments on commit 3184f8d

Please sign in to comment.