]> git.proxmox.com Git - mirror_frr.git/commitdiff
lib/xref: record log message format args
authorDavid Lamparter <equinox@diac24.net>
Sat, 13 Feb 2021 23:53:27 +0000 (00:53 +0100)
committerDavid Lamparter <equinox@diac24.net>
Tue, 23 Feb 2021 15:56:58 +0000 (16:56 +0100)
Apparently you can do `#__VA_ARGS__` and it actually does something
sensible, so here we go recording the format parameters for log messages
into the xref.

This allows some more checking in xrelfo.py, e.g. hints to use `%pFX`
and co.

Signed-off-by: David Lamparter <equinox@diac24.net>
lib/subdir.am
lib/zlog.h
python/xrefstructs.json
python/xrelfo.py

index 96d5fcba307f04fa49f8be24ff0b1c3eb65af01d..38d1a3f773dc83f8eab123dea8b73f9a9c83299e 100644 (file)
@@ -448,9 +448,15 @@ am__v_XRELFO_ = $(am__v_XRELFO_$(AM_DEFAULT_VERBOSITY))
 am__v_XRELFO_0 = @echo "  XRELFO  " $@;
 am__v_XRELFO_1 =
 
+if DEV_BUILD
+XRELFO_FLAGS = -Wlog-format -Wlog-args
+else
+XRELFO_FLAGS =
+endif
+
 SUFFIXES += .xref
 %.xref: % $(CLIPPY)
-       $(AM_V_XRELFO) $(CLIPPY) $(top_srcdir)/python/xrelfo.py -Wlog-format -o $@ $<
+       $(AM_V_XRELFO) $(CLIPPY) $(top_srcdir)/python/xrelfo.py $(XRELFO_FLAGS) -o $@ $<
 
 # dependencies added in python/makefile.py
 frr.xref:
index 3e86aa13459a52b9031d8434c79d0e2a501e4a3f..4fdb47bb9520822c92256382319374c2d96b6f25 100644 (file)
@@ -44,6 +44,7 @@ struct xref_logmsg {
        const char *fmtstring;
        uint32_t priority;
        uint32_t ec;
+       const char *args;
 };
 
 struct xrefdata_logmsg {
@@ -97,6 +98,7 @@ static inline void zlog_ref(const struct xref_logmsg *xref,
                        .xref = XREF_INIT(XREFT_LOGMSG, &_xrefdata, __func__), \
                        .fmtstring = (msg),                                    \
                        .priority = (prio),                                    \
+                       .args = (#__VA_ARGS__),                                \
                };                                                             \
                XREF_LINK(_xref.xref);                                         \
                zlog_ref(&_xref, (msg), ##__VA_ARGS__);                        \
@@ -122,6 +124,7 @@ static inline void zlog_ref(const struct xref_logmsg *xref,
                        .fmtstring = (msg),                                    \
                        .priority = (prio),                                    \
                        .ec = (ec_),                                           \
+                       .args = (#__VA_ARGS__),                                \
                };                                                             \
                XREF_LINK(_xref.xref);                                         \
                zlog_ref(&_xref, "[EC %u] " msg, ec_, ##__VA_ARGS__);          \
index 537afb87e629ebe8017c04a5f4c80302852e1a9a..e62c351bc9ff7bbd082d2fc54e98c95551d5cd0d 100644 (file)
         "offset": 44,
         "size": 4,
         "type": "uint32_t"
+      },
+      {
+        "name": "args",
+        "offset": 48,
+        "size": 8,
+        "type": "const char  *"
       }
     ]
   },
index b726d2895d5d128e4dc05ad8fd450beb78cb2afb..0ecd0085798f440e15f3a663984c4e2f9b49f624 100644 (file)
@@ -112,35 +112,60 @@ class XrefLogmsg(ELFDissectStruct, XrelfoJson):
     struct = 'xref_logmsg'
 
     def _warn_fmt(self, text):
-        yield ((self.xref.file, self.xref.line), '%s:%d: %s (in %s())\n' % (self.xref.file, self.xref.line, text, self.xref.func))
+        lines = text.split('\n')
+        yield ((self.xref.file, self.xref.line), '%s:%d: %s (in %s())%s\n' % (self.xref.file, self.xref.line, lines[0], self.xref.func, ''.join(['\n' + l for l in lines[1:]])))
 
-    regexes = [
+    fmt_regexes = [
         (re.compile(r'([\n\t]+)'), 'error: log message contains tab or newline'),
     #    (re.compile(r'^(\s+)'),   'warning: log message starts with whitespace'),
         (re.compile(r'^((?:warn(?:ing)?|error):\s*)', re.I), 'warning: log message starts with severity'),
     ]
+    arg_regexes = [
+    # the (?<![\?:] ) avoids warning for x ? inet_ntop(...) : "(bla)"
+        (re.compile(r'((?<![\?:] )inet_ntop\s*\(\s*(?:[AP]F_INET|2)\s*,)'),   'cleanup: replace inet_ntop(AF_INET, ...) with %pI4',  lambda s: True),
+        (re.compile(r'((?<![\?:] )inet_ntop\s*\(\s*(?:[AP]F_INET6|10)\s*,)'), 'cleanup: replace inet_ntop(AF_INET6, ...) with %pI6', lambda s: True),
+        (re.compile(r'((?<![\?:] )inet_ntoa)'),                               'cleanup: replace inet_ntoa(...) with %pI4',           lambda s: True),
+        (re.compile(r'((?<![\?:] )ipaddr2str)'),                              'cleanup: replace ipaddr2str(...) with %pIA',          lambda s: True),
+        (re.compile(r'((?<![\?:] )prefix2str)'),                              'cleanup: replace prefix2str(...) with %pFX',          lambda s: True),
+        (re.compile(r'((?<![\?:] )prefix_mac2str)'),                          'cleanup: replace prefix_mac2str(...) with %pEA',      lambda s: True),
+        (re.compile(r'((?<![\?:] )sockunion2str)'),                           'cleanup: replace sockunion2str(...) with %pSU',       lambda s: True),
+
+    #   (re.compile(r'^(\s*__(?:func|FUNCTION|PRETTY_FUNCTION)__\s*)'), 'error: debug message starts with __func__', lambda s: (s.priority & 7 == 7) ),
+    ]
 
     def check(self, wopt):
+        def fmt_msg(rex, itext):
+            if sys.stderr.isatty():
+                items = rex.split(itext)
+                out = []
+                for i, text in enumerate(items):
+                    if (i % 2) == 1:
+                        out.append('\033[41;37;1m%s\033[m' % repr(text)[1:-1])
+                    else:
+                        out.append(repr(text)[1:-1])
+
+                excerpt = ''.join(out)
+            else:
+                excerpt = repr(itext)[1:-1]
+            return excerpt
+
         if wopt.Wlog_format:
-            for rex, msg in self.regexes:
+            for rex, msg in self.fmt_regexes:
                 if not rex.search(self.fmtstring):
                     continue
 
-                if sys.stderr.isatty():
-                    items = rex.split(self.fmtstring)
-                    out = []
-                    for i, text in enumerate(items):
-                        if (i % 2) == 1:
-                            out.append('\033[41;37;1m%s\033[m' % repr(text)[1:-1])
-                        else:
-                            out.append(repr(text)[1:-1])
-
-                    excerpt = ''.join(out)
+                excerpt = fmt_msg(rex, self.fmtstring)
+                yield from self._warn_fmt('%s: "%s"' % (msg, excerpt))
 
-                else:
-                    excerpt = repr(self.fmtstring)[1:-1]
+        if wopt.Wlog_args:
+            for rex, msg, cond in self.arg_regexes:
+                if not cond(self):
+                    continue
+                if not rex.search(self.args):
+                    continue
 
-                yield from self._warn_fmt('%s: "%s"' % (msg, excerpt))
+                excerpt = fmt_msg(rex, self.args)
+                yield from self._warn_fmt('%s:\n\t"%s",\n\t%s' % (msg, repr(self.fmtstring)[1:-1], excerpt))
 
     def dump(self):
         print('%-60s %s%s %-25s [EC %d] %s' % (
@@ -154,6 +179,7 @@ class XrefLogmsg(ELFDissectStruct, XrelfoJson):
         if self.ec != 0:
             jsobj['ec'] = self.ec
         jsobj['fmtstring'] = self.fmtstring
+        jsobj['args'] = self.args
         jsobj['priority'] = self.priority & 7
         jsobj['type'] = 'logmsg'
         jsobj['binary'] = self._elfsect._elfwrap.orig_filename
@@ -330,6 +356,7 @@ def main():
     argp.add_argument('-o', dest='output', type=str, help='write JSON output')
     argp.add_argument('--out-by-file',     type=str, help='write by-file JSON output')
     argp.add_argument('-Wlog-format',      action='store_const', const=True)
+    argp.add_argument('-Wlog-args',        action='store_const', const=True)
     argp.add_argument('--profile',         action='store_const', const=True)
     argp.add_argument('binaries', metavar='BINARY', nargs='+', type=str, help='files to read (ELF files or libtool objects)')
     args = argp.parse_args()