llvm.org GIT mirror llvm / 2823147
SpecialCaseList: Add support for parsing multiple input files. Summary: This change allows users to create SpecialCaseList objects from multiple local files. This is needed to implement a proper support for -fsanitize-blacklist flag (allow users to specify multiple blacklists, in addition to default blacklist, see PR22431). DFSan can also benefit from this change, as DFSan instrumentation pass now accepts ABI-lists both from -fsanitize-blacklist= and -mllvm -dfsan-abilist flags. Go bindings are fixed accordingly. Test Plan: regression test suite Reviewers: pcc Subscribers: llvm-commits, axw, kcc Differential Revision: http://reviews.llvm.org/D7367 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228155 91177308-0d34-0410-b5e6-96231b3b80d8 Alexey Samsonov 4 years ago
8 changed file(s) with 128 addition(s) and 71 deletion(s). Raw diff Collapse all Expand all
3636 }
3737
3838 void LLVMAddDataFlowSanitizerPass(LLVMPassManagerRef PM,
39 const char *ABIListFile) {
40 unwrap(PM)->add(createDataFlowSanitizerPass(ABIListFile));
39 int ABIListFilesNum,
40 const char **ABIListFiles) {
41 std::vector ABIListFilesVec;
42 for (int i = 0; i != ABIListFilesNum; ++i) {
43 ABIListFilesVec.push_back(ABIListFiles[i]);
44 }
45 unwrap(PM)->add(createDataFlowSanitizerPass(ABIListFilesVec));
4146 }
2727 void LLVMAddAddressSanitizerModulePass(LLVMPassManagerRef PM);
2828 void LLVMAddThreadSanitizerPass(LLVMPassManagerRef PM);
2929 void LLVMAddMemorySanitizerPass(LLVMPassManagerRef PM);
30 void LLVMAddDataFlowSanitizerPass(LLVMPassManagerRef PM,
31 const char *ABIListFile);
30 void LLVMAddDataFlowSanitizerPass(LLVMPassManagerRef PM, int ABIListFilesNum,
31 const char **ABIListFiles);
3232
3333 #ifdef __cplusplus
3434 }
3535 C.LLVMAddMemorySanitizerPass(pm.C)
3636 }
3737
38 func (pm PassManager) AddDataFlowSanitizerPass(abilist string) {
39 cabilist := C.CString(abilist)
40 defer C.free(unsafe.Pointer(cabilist))
41 C.LLVMAddDataFlowSanitizerPass(pm.C, cabilist)
38 func (pm PassManager) AddDataFlowSanitizerPass(abilist []string) {
39 abiliststrs := make([]*C.char, len(abilist))
40 for i, arg := range abilist {
41 abiliststrs[i] = C.CString(arg)
42 defer C.free(unsafe.Pointer(abiliststrs[i]))
43 }
44 C.LLVMAddDataFlowSanitizerPass(pm.C, C.int(len(abilist)), &abiliststrs[0])
4245 }
4848 #define LLVM_SUPPORT_SPECIALCASELIST_H
4949
5050 #include "llvm/ADT/StringMap.h"
51 #include
52 #include
5153
5254 namespace llvm {
5355 class MemoryBuffer;
5658
5759 class SpecialCaseList {
5860 public:
59 /// Parses the special case list from a file. If Path is empty, returns
60 /// an empty special case list. On failure, returns 0 and writes an error
61 /// message to string.
62 static std::unique_ptr create(StringRef Path,
63 std::string &Error);
61 /// Parses the special case list entries from files. On failure, returns
62 /// 0 and writes an error message to string.
63 static std::unique_ptr
64 create(const std::vector &Paths, std::string &Error);
6465 /// Parses the special case list from a memory buffer. On failure, returns
6566 /// 0 and writes an error message to string.
6667 static std::unique_ptr create(const MemoryBuffer *MB,
67 std::string &Error);
68 /// Parses the special case list from a file. On failure, reports a fatal
69 /// error.
70 static std::unique_ptr createOrDie(StringRef Path);
68 std::string &Error);
69 /// Parses the special case list entries from files. On failure, reports a
70 /// fatal error.
71 static std::unique_ptr
72 createOrDie(const std::vector &Paths);
7173
7274 ~SpecialCaseList();
7375
8486 SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION;
8587
8688 struct Entry;
87 StringMap > Entries;
89 StringMap> Entries;
90 StringMap> Regexps;
91 bool IsCompiled;
8892
8993 SpecialCaseList();
9094 /// Parses just-constructed SpecialCaseList entries from a memory buffer.
9195 bool parse(const MemoryBuffer *MB, std::string &Error);
96 /// compile() should be called once, after parsing all the memory buffers.
97 void compile();
9298 };
9399
94100 } // namespace llvm
8585 FunctionPass *createThreadSanitizerPass();
8686
8787 // Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation
88 ModulePass *createDataFlowSanitizerPass(StringRef ABIListFile = StringRef(),
89 void *(*getArgTLS)() = nullptr,
90 void *(*getRetValTLS)() = nullptr);
88 ModulePass *createDataFlowSanitizerPass(
89 const std::vector &ABIListFiles = std::vector(),
90 void *(*getArgTLS)() = nullptr, void *(*getRetValTLS)() = nullptr);
9191
9292 // Insert SanitizerCoverage instrumentation.
9393 ModulePass *createSanitizerCoverageModulePass(int CoverageLevel);
9494
9595 #if defined(__GNUC__) && defined(__linux__) && !defined(ANDROID)
96 inline ModulePass *createDataFlowSanitizerPassForJIT(StringRef ABIListFile =
97 StringRef()) {
98 return createDataFlowSanitizerPass(ABIListFile, getDFSanArgTLSPtrForJIT,
96 inline ModulePass *createDataFlowSanitizerPassForJIT(
97 const std::vector &ABIListFiles = std::vector()) {
98 return createDataFlowSanitizerPass(ABIListFiles, getDFSanArgTLSPtrForJIT,
9999 getDFSanRetValTLSPtrForJIT);
100100 }
101101 #endif
4545 }
4646 };
4747
48 SpecialCaseList::SpecialCaseList() : Entries() {}
48 SpecialCaseList::SpecialCaseList() : Entries(), Regexps(), IsCompiled(false) {}
4949
50 std::unique_ptr SpecialCaseList::create(StringRef Path,
51 std::string &Error) {
52 if (Path.empty())
53 return std::unique_ptr(new SpecialCaseList());
54 ErrorOr> FileOrErr =
55 MemoryBuffer::getFile(Path);
56 if (std::error_code EC = FileOrErr.getError()) {
57 Error = (Twine("Can't open file '") + Path + "': " + EC.message()).str();
58 return nullptr;
50 std::unique_ptr
51 SpecialCaseList::create(const std::vector &Paths,
52 std::string &Error) {
53 std::unique_ptr SCL(new SpecialCaseList());
54 for (auto Path : Paths) {
55 ErrorOr> FileOrErr =
56 MemoryBuffer::getFile(Path);
57 if (std::error_code EC = FileOrErr.getError()) {
58 Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
59 return nullptr;
60 }
61 std::string ParseError;
62 if (!SCL->parse(FileOrErr.get().get(), ParseError)) {
63 Error = (Twine("error parsing file '") + Path + "': " + ParseError).str();
64 return nullptr;
65 }
5966 }
60 return create(FileOrErr.get().get(), Error);
67 SCL->compile();
68 return SCL;
6169 }
6270
6371 std::unique_ptr SpecialCaseList::create(const MemoryBuffer *MB,
6573 std::unique_ptr SCL(new SpecialCaseList());
6674 if (!SCL->parse(MB, Error))
6775 return nullptr;
76 SCL->compile();
6877 return SCL;
6978 }
7079
71 std::unique_ptr SpecialCaseList::createOrDie(StringRef Path) {
80 std::unique_ptr
81 SpecialCaseList::createOrDie(const std::vector &Paths) {
7282 std::string Error;
73 if (auto SCL = create(Path, Error))
83 if (auto SCL = create(Paths, Error))
7484 return SCL;
7585 report_fatal_error(Error);
7686 }
7989 // Iterate through each line in the blacklist file.
8090 SmallVector Lines;
8191 SplitString(MB->getBuffer(), Lines, "\n\r");
82 StringMap > Regexps;
83 assert(Entries.empty() &&
84 "parse() should be called on an empty SpecialCaseList");
8592 int LineNo = 1;
86 for (SmallVectorImpl::iterator I = Lines.begin(), E = Lines.end();
87 I != E; ++I, ++LineNo) {
93 for (auto I = Lines.begin(), E = Lines.end(); I != E; ++I, ++LineNo) {
8894 // Ignore empty lines and lines starting with "#"
8995 if (I->empty() || I->startswith("#"))
9096 continue;
9399 StringRef Prefix = SplitLine.first;
94100 if (SplitLine.second.empty()) {
95101 // Missing ':' in the line.
96 Error = (Twine("Malformed line ") + Twine(LineNo) + ": '" +
102 Error = (Twine("malformed line ") + Twine(LineNo) + ": '" +
97103 SplitLine.first + "'").str();
98104 return false;
99105 }
118124 Regex CheckRE(Regexp);
119125 std::string REError;
120126 if (!CheckRE.isValid(REError)) {
121 Error = (Twine("Malformed regex in line ") + Twine(LineNo) + ": '" +
127 Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" +
122128 SplitLine.second + "': " + REError).str();
123129 return false;
124130 }
128134 Regexps[Prefix][Category] += "|";
129135 Regexps[Prefix][Category] += "^" + Regexp + "$";
130136 }
137 return true;
138 }
131139
140 void SpecialCaseList::compile() {
141 assert(!IsCompiled && "compile() should only be called once");
132142 // Iterate through each of the prefixes, and create Regexs for them.
133 for (StringMap >::const_iterator I = Regexps.begin(),
134 E = Regexps.end();
143 for (StringMap>::const_iterator I = Regexps.begin(),
144 E = Regexps.end();
135145 I != E; ++I) {
136146 for (StringMap::const_iterator II = I->second.begin(),
137147 IE = I->second.end();
139149 Entries[I->getKey()][II->getKey()].RegEx.reset(new Regex(II->getValue()));
140150 }
141151 }
142 return true;
152 Regexps.clear();
153 IsCompiled = true;
143154 }
144155
145156 SpecialCaseList::~SpecialCaseList() {}
146157
147158 bool SpecialCaseList::inSection(StringRef Section, StringRef Query,
148159 StringRef Category) const {
160 assert(IsCompiled && "SpecialCaseList::compile() was not called!");
149161 StringMap >::const_iterator I = Entries.find(Section);
150162 if (I == Entries.end()) return false;
151163 StringMap::const_iterator II = I->second.find(Category);
8282 cl::desc("respect alignment requirements provided by input IR"), cl::Hidden,
8383 cl::init(false));
8484
85 // The ABI list file controls how shadow parameters are passed. The pass treats
85 // The ABI list files control how shadow parameters are passed. The pass treats
8686 // every function labelled "uninstrumented" in the ABI list file as conforming
8787 // to the "native" (i.e. unsanitized) ABI. Unless the ABI list contains
8888 // additional annotations for those functions, a call to one of those functions
8989 // will produce a warning message, as the labelling behaviour of the function is
9090 // unknown. The other supported annotations are "functional" and "discard",
9191 // which are described below under DataFlowSanitizer::WrapperKind.
92 static cl::opt ClABIListFile(
92 static cl::list ClABIListFiles(
9393 "dfsan-abilist",
9494 cl::desc("File listing native ABI functions and how the pass treats them"),
9595 cl::Hidden);
140140 std::unique_ptr SCL;
141141
142142 public:
143 DFSanABIList(std::unique_ptr SCL) : SCL(std::move(SCL)) {}
143 DFSanABIList() {}
144
145 void set(std::unique_ptr List) { SCL = std::move(List); }
144146
145147 /// Returns whether either this function or its source file are listed in the
146148 /// given category.
263265 Constant *getOrBuildTrampolineFunction(FunctionType *FT, StringRef FName);
264266
265267 public:
266 DataFlowSanitizer(StringRef ABIListFile = StringRef(),
267 void *(*getArgTLS)() = nullptr,
268 void *(*getRetValTLS)() = nullptr);
268 DataFlowSanitizer(
269 const std::vector &ABIListFiles = std::vector(),
270 void *(*getArgTLS)() = nullptr, void *(*getRetValTLS)() = nullptr);
269271 static char ID;
270272 bool doInitialization(Module &M) override;
271273 bool runOnModule(Module &M) override;
350352 INITIALIZE_PASS(DataFlowSanitizer, "dfsan",
351353 "DataFlowSanitizer: dynamic data flow analysis.", false, false)
352354
353 ModulePass *llvm::createDataFlowSanitizerPass(StringRef ABIListFile,
354 void *(*getArgTLS)(),
355 void *(*getRetValTLS)()) {
356 return new DataFlowSanitizer(ABIListFile, getArgTLS, getRetValTLS);
357 }
358
359 DataFlowSanitizer::DataFlowSanitizer(StringRef ABIListFile,
360 void *(*getArgTLS)(),
361 void *(*getRetValTLS)())
362 : ModulePass(ID), GetArgTLSPtr(getArgTLS), GetRetvalTLSPtr(getRetValTLS),
363 ABIList(SpecialCaseList::createOrDie(ABIListFile.empty() ? ClABIListFile
364 : ABIListFile)) {
355 ModulePass *
356 llvm::createDataFlowSanitizerPass(const std::vector &ABIListFiles,
357 void *(*getArgTLS)(),
358 void *(*getRetValTLS)()) {
359 return new DataFlowSanitizer(ABIListFiles, getArgTLS, getRetValTLS);
360 }
361
362 DataFlowSanitizer::DataFlowSanitizer(
363 const std::vector &ABIListFiles, void *(*getArgTLS)(),
364 void *(*getRetValTLS)())
365 : ModulePass(ID), GetArgTLSPtr(getArgTLS), GetRetvalTLSPtr(getRetValTLS) {
366 std::vector AllABIListFiles(std::move(ABIListFiles));
367 AllABIListFiles.insert(AllABIListFiles.end(), ClABIListFiles.begin(),
368 ClABIListFiles.end());
369 ABIList.set(SpecialCaseList::createOrDie(AllABIListFiles));
365370 }
366371
367372 FunctionType *DataFlowSanitizer::getArgsFunctionType(FunctionType *T) {
66 //
77 //===----------------------------------------------------------------------===//
88
9 #include "llvm/Support/FileSystem.h"
910 #include "llvm/Support/MemoryBuffer.h"
1011 #include "llvm/Support/SpecialCaseList.h"
1112 #include "gtest/gtest.h"
2829 assert(SCL);
2930 assert(Error == "");
3031 return SCL;
32 }
33
34 std::string makeSpecialCaseListFile(StringRef Contents) {
35 int FD;
36 SmallString<64> Path;
37 sys::fs::createTemporaryFile("SpecialCaseListTest", "temp", FD, Path);
38 raw_fd_ostream OF(FD, true, true);
39 OF << Contents;
40 OF.close();
41 return Path.str();
3142 }
3243 };
3344
8596 TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) {
8697 std::string Error;
8798 EXPECT_EQ(nullptr, makeSpecialCaseList("badline", Error));
88 EXPECT_EQ("Malformed line 1: 'badline'", Error);
99 EXPECT_EQ("malformed line 1: 'badline'", Error);
89100 EXPECT_EQ(nullptr, makeSpecialCaseList("src:bad[a-", Error));
90 EXPECT_EQ("Malformed regex in line 1: 'bad[a-': invalid character range",
101 EXPECT_EQ("malformed regex in line 1: 'bad[a-': invalid character range",
91102 Error);
92103 EXPECT_EQ(nullptr, makeSpecialCaseList("src:a.c\n"
93104 "fun:fun(a\n",
94105 Error));
95 EXPECT_EQ("Malformed regex in line 2: 'fun(a': parentheses not balanced",
106 EXPECT_EQ("malformed regex in line 2: 'fun(a': parentheses not balanced",
96107 Error);
97 EXPECT_EQ(nullptr, SpecialCaseList::create("unexisting", Error));
98 EXPECT_EQ(0U, Error.find("Can't open file 'unexisting':"));
108 std::vector Files(1, "unexisting");
109 EXPECT_EQ(nullptr, SpecialCaseList::create(Files, Error));
110 EXPECT_EQ(0U, Error.find("can't open file 'unexisting':"));
99111 }
100112
101113 TEST_F(SpecialCaseListTest, EmptySpecialCaseList) {
103115 EXPECT_FALSE(SCL->inSection("foo", "bar"));
104116 }
105117
118 TEST_F(SpecialCaseListTest, MultipleBlacklists) {
119 std::vector Files;
120 Files.push_back(makeSpecialCaseListFile("src:bar\n"
121 "src:*foo*\n"
122 "src:ban=init\n"));
123 Files.push_back(makeSpecialCaseListFile("src:baz\n"
124 "src:*fog*\n"));
125 auto SCL = SpecialCaseList::createOrDie(Files);
126 EXPECT_TRUE(SCL->inSection("src", "bar"));
127 EXPECT_TRUE(SCL->inSection("src", "baz"));
128 EXPECT_FALSE(SCL->inSection("src", "ban"));
129 EXPECT_TRUE(SCL->inSection("src", "ban", "init"));
130 EXPECT_TRUE(SCL->inSection("src", "tomfoolery"));
131 EXPECT_TRUE(SCL->inSection("src", "tomfoglery"));
106132 }
107133
108
134 }