aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorPimyn Girgis <bemenboshra2001@gmail.com>2024-09-04 10:22:56 +0000
committerAleksandr Nogikh <nogikh@google.com>2024-09-09 13:14:54 +0000
commit37f6c627c0e515d3c1bc57da1e15ddf208f5a23b (patch)
treef4451d64dd6baeaf33bb9af726b3e9e41739a556 /tools
parent073f8be214232113bbf75d16a9bb0372beee85b9 (diff)
tools/syz-declextract: restructuring for clang tool
Split the Matcher into two classes for system calls and netlinks. Made the system call extraction more robust by avoiding using constants and extracting their values instead.
Diffstat (limited to 'tools')
-rw-r--r--tools/syz-declextract/syz-declextract.cpp142
1 files changed, 78 insertions, 64 deletions
diff --git a/tools/syz-declextract/syz-declextract.cpp b/tools/syz-declextract/syz-declextract.cpp
index 66ce053a9..60506f79a 100644
--- a/tools/syz-declextract/syz-declextract.cpp
+++ b/tools/syz-declextract/syz-declextract.cpp
@@ -68,7 +68,63 @@ public:
}
};
-class Matcher : public MatchFinder::MatchCallback {
+class SyscallMatcher : public MatchFinder::MatchCallback {
+private:
+ const std::string getSyzType(const std::string &type) { return "intptr"; }
+ const std::string swapIfReservedKeyword(const std::string &word) {
+ if (word == "resource")
+ return "rsrc";
+ return word;
+ }
+ unsigned int nameIndex{0}, argcIndex{0}, typesIndex{0}, argsIndex{0};
+ bool isInitialized{false};
+ llvm::ArrayRef<Expr *> getVarDeclInitList(Expr *init, const ASTContext *context) {
+ return llvm::dyn_cast<InitListExpr>(
+ llvm::dyn_cast<VarDecl>(init->getAsBuiltinConstantDeclRef(*context)->getUnderlyingDecl())->getInit())
+ ->inits();
+ }
+
+ std::vector<Param> getArgs(Expr *types, Expr *names, int argc, ASTContext *context) {
+ std::vector<Param> args(argc);
+ if (argc) {
+ int i = 0;
+ for (const auto *type : getVarDeclInitList(types, context)) { // get parameter types.
+ args[i++].type = std::move(*type->tryEvaluateString(*context));
+ }
+
+ i = 0;
+ for (const auto *name : getVarDeclInitList(names, context)) { // get parameter names
+ args[i++].name = std::move(*name->tryEvaluateString(*context));
+ }
+ }
+ return args;
+ }
+
+public:
+ void virtual run(const MatchFinder::MatchResult &Result) override {
+ ASTContext *context = Result.Context;
+ const auto *initList = Result.Nodes.getNodeAs<InitListExpr>("initList");
+ if (!isInitialized) {
+ argcIndex = Result.Nodes.getNodeAs<FieldDecl>("nb_args")->getFieldIndex();
+ typesIndex = Result.Nodes.getNodeAs<FieldDecl>("types")->getFieldIndex();
+ argsIndex = Result.Nodes.getNodeAs<FieldDecl>("args")->getFieldIndex();
+ nameIndex = Result.Nodes.getNodeAs<FieldDecl>("name")->getFieldIndex();
+ }
+ // values contains the initializer list for the struct `syscall_metadata`
+ auto values = initList->inits();
+ int argc = values[argcIndex]->getIntegerConstantExpr(*context)->getSExtValue();
+
+ printf("%s$auto(", values[nameIndex]->tryEvaluateString(*context)->c_str() + 4); // name
+ const char *sep = "";
+ for (const auto &arg : getArgs(values[typesIndex], values[argsIndex], argc, context)) {
+ printf("%s%s %s", sep, swapIfReservedKeyword(arg.name).c_str(), getSyzType(arg.type).c_str());
+ sep = ", ";
+ }
+ puts(") (automatic)");
+ }
+};
+
+class NetlinkPolicyMatcher : public MatchFinder::MatchCallback {
private:
const std::string nlaToSyz(const Expr *const policyType) {
// NOTE:This check is for when the policy is missing the field `type`.
@@ -114,59 +170,9 @@ private:
fprintf(stderr, "Unsupported netlink type %s\n", type.c_str());
exit(1);
}
- const std::string getSyzType(const std::string &type) { return "intptr"; }
- const std::string swapIfReservedKeyword(const std::string &word) {
- if (word == "resource")
- return "rsrc";
- return word;
- }
-
- void syscall(const MatchFinder::MatchResult &Result) {
- ASTContext *context = Result.Context;
- const auto *varDecl = Result.Nodes.getNodeAs<VarDecl>("syscall");
- if (!varDecl || !varDecl->getInit())
- return;
-
- // values contains the initializer list for the struct `syscall_metadata`
- auto values = llvm::dyn_cast<InitListExpr>(varDecl->getInit())->inits();
- if (values.empty())
- return;
-
- int argc = *values[2]->getIntegerConstantExpr(*context)->getRawData();
-
- std::vector<Param> args(argc);
- if (argc) {
- int i = 0;
- for (const auto *type : // get parameter types
- llvm::dyn_cast<InitListExpr>(
- llvm::dyn_cast<VarDecl>(values[3]->getAsBuiltinConstantDeclRef(*context)->getUnderlyingDecl())
- ->getInit())
- ->inits()) {
- args[i++].type = std::move(*type->tryEvaluateString(*context));
- }
-
- i = 0;
- for (const auto *name : // get parameter names
- llvm::dyn_cast<InitListExpr>(
- llvm::dyn_cast<VarDecl>(values[4]->getAsBuiltinConstantDeclRef(*context)->getUnderlyingDecl())
- ->getInit())
- ->inits()) {
- args[i++].name = std::move(*name->tryEvaluateString(*context));
- }
- }
-
- printf("%s$auto(", values[0]->tryEvaluateString(*context)->c_str() + 4); // name
- const char *sep = "";
- for (const auto &arg : args) {
- printf("%s%s %s", sep, swapIfReservedKeyword(arg.name).c_str(), getSyzType(arg.type).c_str());
- sep = ", ";
- }
- puts(") (automatic)");
- }
void netlink(const MatchFinder::MatchResult &Result) {
ASTContext *context = Result.Context;
- std::string output;
const auto *netlinkDecl = Result.Nodes.getNodeAs<VarDecl>("netlink");
if (!netlinkDecl) {
return;
@@ -279,17 +285,16 @@ private:
void genlFamily(const MatchFinder::MatchResult &Result) {
ASTContext *context = Result.Context;
- const auto *genlFamily = Result.Nodes.getNodeAs<RecordDecl>("genl_family");
- if (!genlFamily) {
- return;
- }
- for (const auto &field : genlFamily->fields()) {
- genlFamilyMember[field->getNameAsString()] = field->getFieldIndex();
- }
const auto *genlFamilyInit = Result.Nodes.getNodeAs<InitListExpr>("genl_family_init");
if (!genlFamilyInit) {
return;
}
+ if (genlFamilyMember.empty()) {
+ const auto *genlFamily = Result.Nodes.getNodeAs<RecordDecl>("genl_family");
+ for (const auto &field : genlFamily->fields()) {
+ genlFamilyMember[field->getNameAsString()] = field->getFieldIndex();
+ }
+ }
auto name = llvm::dyn_cast<StringLiteral>(genlFamilyInit->getInit(genlFamilyMember["name"]))->getString().str();
std::replace(name.begin(), name.end(), '.', '_'); // Illegal character.
@@ -332,7 +337,6 @@ private:
public:
virtual void run(const MatchFinder::MatchResult &Result) override {
- syscall(Result);
netlink(Result);
genlFamily(Result);
};
@@ -350,22 +354,32 @@ int main(int argc, const char **argv) {
clang::tooling::CommonOptionsParser &OptionsParser = ExpectedParser.get();
clang::tooling::ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());
- Matcher Printer;
+ NetlinkPolicyMatcher NetlinkPolicyMatcher;
+ SyscallMatcher SyscallMatcher;
MatchFinder Finder;
+
Finder.addMatcher(
- varDecl(isExpandedFromMacro("SYSCALL_METADATA"), hasType(recordDecl(hasName("syscall_metadata"))), isDefinition())
+ varDecl(
+ isExpandedFromMacro("SYSCALL_METADATA"),
+ hasType(recordDecl(hasName("syscall_metadata"), has(fieldDecl(hasName("nb_args")).bind("nb_args")),
+ has(fieldDecl(hasName("types")).bind("types")),
+ has(fieldDecl(hasName("name")).bind("name")), has(fieldDecl(hasName("args")).bind("args")))
+ .bind("syscall_metadata")),
+ has(initListExpr().bind("initList")))
.bind("syscall"),
- &Printer);
+ &SyscallMatcher);
+
Finder.addMatcher(varDecl(hasType(constantArrayType(hasElementType(hasDeclaration(
recordDecl(hasName("nla_policy")).bind("nla_policy"))))
.bind("nla_policy_array")),
isDefinition())
.bind("netlink"),
- &Printer);
+ &NetlinkPolicyMatcher);
+
Finder.addMatcher(varDecl(hasType(recordDecl(hasName("genl_family")).bind("genl_family")),
has(initListExpr().bind("genl_family_init")))
.bind("genl_family_decl"),
- &Printer);
+ &NetlinkPolicyMatcher);
return Tool.run(clang::tooling::newFrontendActionFactory(&Finder).get());
}