diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2025-04-14 08:03:20 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2025-04-15 08:30:57 +0000 |
| commit | eb2144e822c56abb85860646d22d7ce4656fcdb1 (patch) | |
| tree | 7f1d897ee854cb0c5025121e2a8646ea0c72b48d /tools | |
| parent | 851253229c4963cf9144bc2c74b5001693172559 (diff) | |
tools/syz-declextract: extract ioctls declared with enums
Some ioctls are declared inconsistently using enums rather than macros.
Extract these as well.
Diffstat (limited to 'tools')
6 files changed, 109 insertions, 62 deletions
diff --git a/tools/syz-declextract/clangtool/declextract.cpp b/tools/syz-declextract/clangtool/declextract.cpp index 4be87b501..3b9769069 100644 --- a/tools/syz-declextract/clangtool/declextract.cpp +++ b/tools/syz-declextract/clangtool/declextract.cpp @@ -52,7 +52,8 @@ struct MacroDef { }; using MacroMap = std::unordered_map<std::string, MacroDef>; -struct MacroDesc { +// ConstDesc describes a macro or an enum value. +struct ConstDesc { std::string Name; std::string Value; SourceRange SourceRange; @@ -140,8 +141,9 @@ private: std::optional<QualType> getSizeofType(const Expr* E); int sizeofType(const Type* T); int alignofType(const Type* T); - void extractIoctl(const Expr* Cmd, const MacroDesc& Macro); - std::optional<MacroDesc> isMacroRef(const Expr* E); + void extractIoctl(const Expr* Cmd, const ConstDesc& Const); + std::optional<ConstDesc> isMacroOrEnum(const Expr* E); + ConstDesc constDesc(const Expr* E, const std::string& Str, const std::string& Value, const SourceRange& SourceRange); }; // PPCallbacksTracker records all macro definitions (name/value/source location). @@ -174,6 +176,18 @@ private: } }; +const Expr* removeCasts(const Expr* E) { + for (;;) { + if (auto* P = dyn_cast<ParenExpr>(E)) + E = P->getSubExpr(); + else if (auto* C = dyn_cast<CastExpr>(E)) + E = C->getSubExpr(); + else + break; + } + return E; +} + bool Extractor::handleBeginSource(CompilerInstance& CI) { Preprocessor& PP = CI.getPreprocessor(); PP.addPPCallbacks(std::make_unique<PPCallbacksTracker>(PP, Macros)); @@ -357,20 +371,27 @@ std::string Extractor::getDeclFileID(const Decl* Decl) { return file; } -std::optional<MacroDesc> Extractor::isMacroRef(const Expr* E) { +std::optional<ConstDesc> Extractor::isMacroOrEnum(const Expr* E) { if (!E) return {}; + if (auto* Enum = removeCasts(E)->getEnumConstantDecl()) + return constDesc(E, Enum->getNameAsString(), "", Enum->getSourceRange()); auto Range = Lexer::getAsCharRange(E->getSourceRange(), *SourceManager, Context->getLangOpts()); const std::string& Str = Lexer::getSourceText(Range, *SourceManager, Context->getLangOpts()).str(); auto MacroDef = Macros.find(Str); if (MacroDef == Macros.end()) return {}; + return constDesc(E, Str, MacroDef->second.Value, MacroDef->second.SourceRange); +} + +ConstDesc Extractor::constDesc(const Expr* E, const std::string& Str, const std::string& Value, + const SourceRange& SourceRange) { int64_t Val = evaluate(E); - emitConst(Str, Val, MacroDef->second.SourceRange.getBegin()); - return MacroDesc{ + emitConst(Str, Val, SourceRange.getBegin()); + return ConstDesc{ .Name = Str, - .Value = MacroDef->second.Value, - .SourceRange = MacroDef->second.SourceRange, + .Value = Value, + .SourceRange = SourceRange, .IntValue = Val, }; } @@ -597,18 +618,6 @@ std::string Extractor::getUniqueDeclName(const NamedDecl* Decl) { return Decl->getNameAsString() + "_" + getDeclFileID(Decl); } -const Expr* removeCasts(const Expr* E) { - for (;;) { - if (auto* P = dyn_cast<ParenExpr>(E)) - E = P->getSubExpr(); - else if (auto* C = dyn_cast<CastExpr>(E)) - E = C->getSubExpr(); - else - break; - } - return E; -} - bool isInterestingCall(const CallExpr* Call) { auto* CalleeDecl = Call->getDirectCallee(); // We don't handle indirect calls yet. @@ -677,8 +686,8 @@ struct FunctionAnalyzer : RecursiveASTVisitor<FunctionAnalyzer> { auto* Case = dyn_cast<CaseStmt>(C); if (!Case) continue; - auto LMacro = Extractor->isMacroRef(Case->getLHS()); - auto RMacro = Extractor->isMacroRef(Case->getRHS()); + auto LMacro = Extractor->isMacroOrEnum(Case->getLHS()); + auto RMacro = Extractor->isMacroOrEnum(Case->getRHS()); if (LMacro || RMacro) { IsInteresting = true; break; @@ -711,7 +720,7 @@ struct FunctionAnalyzer : RecursiveASTVisitor<FunctionAnalyzer> { // Otherwise it's a default case, for which we don't add any values. if (auto* Case = dyn_cast<CaseStmt>(C)) { int64_t LVal = Extractor->evaluate(Case->getLHS()); - auto LMacro = Extractor->isMacroRef(Case->getLHS()); + auto LMacro = Extractor->isMacroOrEnum(Case->getLHS()); if (LMacro) { Current->Values.push_back(LMacro->Name); Extractor->extractIoctl(Case->getLHS(), *LMacro); @@ -723,7 +732,7 @@ struct FunctionAnalyzer : RecursiveASTVisitor<FunctionAnalyzer> { // case FOO ... BAR: // Add all values in the range. int64_t RVal = Extractor->evaluate(Case->getRHS()); - auto RMacro = Extractor->isMacroRef(Case->getRHS()); + auto RMacro = Extractor->isMacroOrEnum(Case->getRHS()); for (int64_t V = LVal + 1; V <= RVal - (RMacro ? 1 : 0); V++) Current->Values.push_back(std::to_string(V)); if (RMacro) @@ -937,13 +946,13 @@ void Extractor::matchFileOps() { }); } -void Extractor::extractIoctl(const Expr* Cmd, const MacroDesc& Macro) { +void Extractor::extractIoctl(const Expr* Cmd, const ConstDesc& Const) { // This is old style ioctl defined directly via a number. // We can't infer anything about it. - if (Macro.Value.find("_IO") != 0) + if (Const.Value.find("_IO") != 0) return; FieldType Type; - auto Dir = _IOC_DIR(Macro.IntValue); + auto Dir = _IOC_DIR(Const.IntValue); if (Dir == _IOC_NONE) { Type = IntType{.ByteSize = 1, .IsConst = true}; } else if (std::optional<QualType> Arg = getSizeofType(Cmd)) { @@ -957,7 +966,7 @@ void Extractor::extractIoctl(const Expr* Cmd, const MacroDesc& Macro) { return; } Output.emit(Ioctl{ - .Name = Macro.Name, + .Name = Const.Name, .Type = std::move(Type), }); } diff --git a/tools/syz-declextract/testdata/file_operations.c b/tools/syz-declextract/testdata/file_operations.c index 136e608dd..0e62a6f16 100644 --- a/tools/syz-declextract/testdata/file_operations.c +++ b/tools/syz-declextract/testdata/file_operations.c @@ -5,6 +5,10 @@ #include "include/uapi/file_operations.h" #include "include/uapi/unused_ioctl.h" +enum { + FOO_IOCTL12 = _IOR('c', 12, int), +}; + static void foo_open() {} static void foo_read() {} static void foo_write() {} @@ -25,6 +29,9 @@ static void foo_ioctl(void* file, unsigned int cmd, unsigned long arg) { case FOO_IOCTL3: case FOO_IOCTL4: case FOO_IOCTL5: + case FOO_IOCTL10: + case FOO_IOCTL11: + case FOO_IOCTL12: } foo_ioctl2(cmd, arg); } diff --git a/tools/syz-declextract/testdata/file_operations.c.info b/tools/syz-declextract/testdata/file_operations.c.info index a6ad4f27b..d0adb11d8 100644 --- a/tools/syz-declextract/testdata/file_operations.c.info +++ b/tools/syz-declextract/testdata/file_operations.c.info @@ -4,11 +4,14 @@ FILEOP foo_write func:foo_write loc:0 coverage:0 access:unknown manual_desc:unkn FILEOP proc_open func:proc_open loc:0 coverage:0 access:unknown manual_desc:unknown auto_desc:false file:file_operations.c subsystem:kernel FILEOP proc_read func:proc_read loc:0 coverage:0 access:unknown manual_desc:unknown auto_desc:false file:file_operations.c subsystem:kernel FILEOP proc_write func:proc_write loc:0 coverage:0 access:unknown manual_desc:unknown auto_desc:false file:file_operations.c subsystem:kernel -IOCTL FOO_IOCTL1 func:foo_ioctl loc:10 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel -IOCTL FOO_IOCTL2 func:foo_ioctl loc:10 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel -IOCTL FOO_IOCTL3 func:foo_ioctl loc:10 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel -IOCTL FOO_IOCTL4 func:foo_ioctl loc:10 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel -IOCTL FOO_IOCTL5 func:foo_ioctl loc:10 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel +IOCTL FOO_IOCTL1 func:foo_ioctl loc:13 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel +IOCTL FOO_IOCTL10 func:foo_ioctl loc:13 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel +IOCTL FOO_IOCTL11 func:foo_ioctl loc:13 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel +IOCTL FOO_IOCTL12 func:foo_ioctl loc:13 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel +IOCTL FOO_IOCTL2 func:foo_ioctl loc:13 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel +IOCTL FOO_IOCTL3 func:foo_ioctl loc:13 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel +IOCTL FOO_IOCTL4 func:foo_ioctl loc:13 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel +IOCTL FOO_IOCTL5 func:foo_ioctl loc:13 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel IOCTL FOO_IOCTL6 func:foo_ioctl loc:8 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel IOCTL FOO_IOCTL7 func:foo_ioctl loc:8 coverage:0 access:unknown manual_desc:false auto_desc:true file:file_operations.c subsystem:kernel IOCTL UNUSED_IOCTL1 func:unused_ioctl loc:4 coverage:0 access:unknown manual_desc:false auto_desc:false file:file_operations.c subsystem:kernel diff --git a/tools/syz-declextract/testdata/file_operations.c.json b/tools/syz-declextract/testdata/file_operations.c.json index 734840160..0c1706767 100644 --- a/tools/syz-declextract/testdata/file_operations.c.json +++ b/tools/syz-declextract/testdata/file_operations.c.json @@ -27,8 +27,8 @@ { "name": "foo_ioctl", "file": "file_operations.c", - "start_line": 21, - "end_line": 30, + "start_line": 25, + "end_line": 37, "is_static": true, "scopes": [ { @@ -74,18 +74,21 @@ "FOO_IOCTL2", "FOO_IOCTL3", "FOO_IOCTL4", - "FOO_IOCTL5" + "FOO_IOCTL5", + "FOO_IOCTL10", + "FOO_IOCTL11", + "FOO_IOCTL12" ], - "start_line": 23, - "end_line": 28 + "start_line": 27, + "end_line": 35 } ] }, { "name": "foo_ioctl2", "file": "file_operations.c", - "start_line": 13, - "end_line": 19, + "start_line": 17, + "end_line": 23, "is_static": true, "scopes": [ { @@ -97,16 +100,16 @@ "FOO_IOCTL6", "FOO_IOCTL7" ], - "start_line": 15, - "end_line": 18 + "start_line": 19, + "end_line": 22 } ] }, { "name": "foo_mmap", "file": "file_operations.c", - "start_line": 11, - "end_line": 11, + "start_line": 15, + "end_line": 15, "is_static": true, "scopes": [ { @@ -117,8 +120,8 @@ { "name": "foo_open", "file": "file_operations.c", - "start_line": 8, - "end_line": 8, + "start_line": 12, + "end_line": 12, "is_static": true, "scopes": [ { @@ -129,8 +132,8 @@ { "name": "foo_read", "file": "file_operations.c", - "start_line": 9, - "end_line": 9, + "start_line": 13, + "end_line": 13, "is_static": true, "scopes": [ { @@ -141,8 +144,8 @@ { "name": "foo_write", "file": "file_operations.c", - "start_line": 10, - "end_line": 10, + "start_line": 14, + "end_line": 14, "is_static": true, "scopes": [ { @@ -165,8 +168,8 @@ { "name": "proc_ioctl", "file": "file_operations.c", - "start_line": 43, - "end_line": 43, + "start_line": 50, + "end_line": 50, "is_static": true, "scopes": [ { @@ -177,8 +180,8 @@ { "name": "proc_open", "file": "file_operations.c", - "start_line": 40, - "end_line": 40, + "start_line": 47, + "end_line": 47, "is_static": true, "scopes": [ { @@ -189,8 +192,8 @@ { "name": "proc_read", "file": "file_operations.c", - "start_line": 41, - "end_line": 41, + "start_line": 48, + "end_line": 48, "is_static": true, "scopes": [ { @@ -201,8 +204,8 @@ { "name": "proc_write", "file": "file_operations.c", - "start_line": 42, - "end_line": 42, + "start_line": 49, + "end_line": 49, "is_static": true, "scopes": [ { @@ -213,8 +216,8 @@ { "name": "unused_ioctl", "file": "file_operations.c", - "start_line": 59, - "end_line": 64, + "start_line": 66, + "end_line": 71, "is_static": true, "scopes": [ { @@ -226,8 +229,8 @@ "UNUSED_IOCTL1", "UNUSED_IOCTL2" ], - "start_line": 61, - "end_line": 63 + "start_line": 68, + "end_line": 70 } ] } @@ -239,6 +242,21 @@ "value": 25345 }, { + "name": "FOO_IOCTL10", + "filename": "include/uapi/file_operations.h", + "value": 2147771146 + }, + { + "name": "FOO_IOCTL11", + "filename": "include/uapi/file_operations.h", + "value": 2147771147 + }, + { + "name": "FOO_IOCTL12", + "filename": "file_operations.c", + "value": 2147771148 + }, + { "name": "FOO_IOCTL2", "filename": "include/uapi/file_operations.h", "value": 2147771138 diff --git a/tools/syz-declextract/testdata/file_operations.c.txt b/tools/syz-declextract/testdata/file_operations.c.txt index f37a386db..30743ffb9 100644 --- a/tools/syz-declextract/testdata/file_operations.c.txt +++ b/tools/syz-declextract/testdata/file_operations.c.txt @@ -15,6 +15,9 @@ read$auto_foo_file_operations(fd fd_foo_file_operations, buf ptr[out, array[int8 write$auto_foo_file_operations(fd fd_foo_file_operations, buf ptr[in, array[int8]], len bytesize[buf]) mmap$auto_foo_file_operations(addr vma, len len[addr], prot flags[mmap_prot], flags flags[mmap_flags], fd fd_foo_file_operations, offset fileoff) ioctl$auto_FOO_IOCTL1(fd fd_foo_file_operations, cmd const[FOO_IOCTL1], arg const[0]) +ioctl$auto_FOO_IOCTL10(fd fd_foo_file_operations, cmd const[FOO_IOCTL10], arg ptr[in, array[int8]]) +ioctl$auto_FOO_IOCTL11(fd fd_foo_file_operations, cmd const[FOO_IOCTL11], arg ptr[in, array[int8]]) +ioctl$auto_FOO_IOCTL12(fd fd_foo_file_operations, cmd const[FOO_IOCTL12], arg ptr[in, array[int8]]) ioctl$auto_FOO_IOCTL2(fd fd_foo_file_operations, cmd const[FOO_IOCTL2], arg ptr[in, int32]) ioctl$auto_FOO_IOCTL3(fd fd_foo_file_operations, cmd const[FOO_IOCTL3], arg ptr[in, foo_ioctl_arg$auto]) ioctl$auto_FOO_IOCTL4(fd fd_foo_file_operations, cmd const[FOO_IOCTL4], arg ptr[inout, foo_ioctl_arg$auto]) @@ -26,3 +29,5 @@ foo_ioctl_arg$auto { a int32 b int32 } + +define FOO_IOCTL12 2147771148 diff --git a/tools/syz-declextract/testdata/include/uapi/file_operations.h b/tools/syz-declextract/testdata/include/uapi/file_operations.h index f81d6886d..a4fa3a21e 100644 --- a/tools/syz-declextract/testdata/include/uapi/file_operations.h +++ b/tools/syz-declextract/testdata/include/uapi/file_operations.h @@ -13,6 +13,11 @@ #define FOO_IOCTL8 _IO('c', 8) #define FOO_IOCTL9 _IO('c', 9) +enum { + FOO_IOCTL10 = _IOR('c', 10, int), + FOO_IOCTL11 = _IOR('c', 11, int), +}; + struct foo_ioctl_arg { int a, b; }; |
