From bb3f84250514d5990939e57b5d1ff8badc566033 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Tue, 12 Nov 2024 16:53:17 +0100 Subject: tools/syz-declextract: improve declaration name extraction Extracting declaration name is trickier than removing casts. If the initialized type is a union, then the expression may also contain InitListExpr and other nodes. Remove all of them in a more robust way. --- tools/syz-declextract/syz-declextract.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/syz-declextract/syz-declextract.cpp b/tools/syz-declextract/syz-declextract.cpp index 698bc1263..3c6c40a23 100644 --- a/tools/syz-declextract/syz-declextract.cpp +++ b/tools/syz-declextract/syz-declextract.cpp @@ -110,9 +110,21 @@ struct SyzRecordDecl { // If expression refers to some identifier, returns the identifier name. // Otherwise returns an empty string. // For example, if the expression is `function_name`, returns "function_name" string. -std::string getDeclName(const clang::Expr *expr) { - auto *decl = llvm::dyn_cast(expr->IgnoreCasts()); - return decl ? decl->getDecl()->getNameAsString() : ""; +std::string getDeclName(ASTContext &context, const clang::Expr *expr) { + if (!expr) { + return ""; + } + // The expression can be complex and include casts and e.g. InitListExpr, + // to remove all of these we match the first/any DeclRefExpr. + struct Matcher : MatchFinder::MatchCallback { + const DeclRefExpr *decl = nullptr; + void run(const MatchFinder::MatchResult &Result) override { decl = Result.Nodes.getNodeAs("decl"); } + }; + MatchFinder finder; + Matcher matcher; + finder.addMatcher(stmt(forEachDescendant(declRefExpr().bind("decl"))), &matcher); + finder.match(*expr, context); + return matcher.decl ? matcher.decl->getDecl()->getNameAsString() : ""; } bool endsWith(const std::string_view &str, const std::string_view end) { @@ -825,9 +837,9 @@ private: if (opsName != "small_ops") { policyDecl = init->getInit(opsMember["policy"])->getAsBuiltinConstantDeclRef(*context); } - std::string func = getDeclName(init->getInit(opsMember["doit"])); + std::string func = getDeclName(*context, init->getInit(opsMember["doit"])); if (func.empty()) - func = getDeclName(init->getInit(opsMember["dumpit"])); + func = getDeclName(*context, init->getInit(opsMember["dumpit"])); const Expr *flagsDecl = init->getInit(opsMember["flags"]); Expr::EvalResult flags; flagsDecl->EvaluateAsConstantExpr(flags, *context); @@ -912,6 +924,7 @@ public: private: void run(const MatchFinder::MatchResult &Result) override { + ASTContext *context = Result.Context; const auto *ioIssueDefs = Result.Nodes.getNodeAs("io_issue_defs"); if (!ioIssueDefs) { return; @@ -924,11 +937,11 @@ private: } for (const auto &[i, op] : elements) { const auto &init = llvm::dyn_cast(initList->getInit(i)); - std::string prep = getDeclName(init->getInit(fields["prep"])); + std::string prep = getDeclName(*context, init->getInit(fields["prep"])); if (prep == "io_eopnotsupp_prep") { continue; } - std::string issue = getDeclName(init->getInit(fields["issue"])); + std::string issue = getDeclName(*context, init->getInit(fields["issue"])); emitInterface("IOURING", op.name, op.name, issue, AccessUser); } } -- cgit mrf-deployment