]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: debug: make a pair of __BUG_ON() for modern and obsolete linkers
authorWilly Tarreau <w@1wt.eu>
Tue, 11 Aug 2026 07:43:13 +0000 (09:43 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 13 Aug 2026 15:43:30 +0000 (17:43 +0200)
The _BUG_ON() and _BUG_ON_ONCE() calls used to systematically call
__DBG_COUNT() first, then to call __BUG_ON(). Let's have a variant of
__BUG_ON() for each linker mode, that is merged with __DBG_COUNT().
The modern linker one now performs both the counting and processing
of the event at once.

For now the "once" aspect is still dependent on the expression-local
counter so that the code is exactly the same as before. The code size
didn't change.

include/haproxy/bug.h

index 644d05cf57533857363c0baa0dbba0a6abc047b1..585658288e573f6f9a9d40854b669d54495e418e 100644 (file)
@@ -345,6 +345,39 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt  HA_SECTION_S
        } while (0)
 
 
+/* This is called by _BUG_ON() and _BUG_ON_ONCE() to count and handle the event. */
+#define __BUG_ON(_cond, _file, _line, _type, _details, ...) {                  \
+               static struct debug_count __dbg_cnt_##_line HA_SECTION("dbg_cnt") \
+               __attribute__((__used__,__aligned__(sizeof(void*)))) = {        \
+                       .file = _file,                                          \
+                       .func = __func__,                                       \
+                       .line = _line,                                          \
+                       .type = _type,                                          \
+                       .desc = (sizeof("" #_cond) > 1) ?                       \
+                                 (sizeof("" __VA_ARGS__) > 1) ?                \
+                                 "" #_cond "\x1e" __VA_ARGS__ :                \
+                                 "" #_cond :                                   \
+                               "" __VA_ARGS__,                                 \
+                       .count = 0,                                             \
+               };                                                              \
+               HA_WEAK(__start_dbg_cnt);                                       \
+               HA_WEAK(__stop_dbg_cnt);                                        \
+               _HA_ATOMIC_INC(&__dbg_cnt_##_line.count);                       \
+               if (_type != DBG_BUG_ONCE ||                                    \
+                   ({ static int __match_count_##_line;                        \
+                      !_HA_ATOMIC_FETCH_ADD(&__match_count_##_line, 1); })) {  \
+                       const char *msg =                                       \
+                               (sizeof("" __VA_ARGS__) > 1) ?                  \
+                                       "\"" #_cond "\" matched at " _file ":" #_line "\x1e" __VA_ARGS__ : \
+                                       "\"" #_cond "\" matched at " _file ":" #_line;  \
+                       complain(_details, msg);                                \
+                       if (_details & DBG_DET_FAT_FATL)                        \
+                               ABORT_NOW();                                    \
+                       else if (_details & DBG_DET_FAT_WARN)                   \
+                               ha_backtrace_to_stderr(0);                      \
+               }                                                               \
+       }
+
 /* Matrix for DEBUG_COUNTERS:
  *    0 : only BUG_ON() and CHECK_IF() are reported (super rare)
  *    1 : COUNT_GLITCH() are also reported (rare)
@@ -387,6 +420,24 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt  HA_SECTION_S
 # define _COUNT_IF(cond, file, line, ...) DISGUISE(unlikely(cond) ? 1 : 0)
 # define _COUNT_GLITCH(file, line, ...) do { } while (0)
 
+/* This is called by _BUG_ON() and _BUG_ON_ONCE() to handle the event. */
+#define __BUG_ON(cond, file, line, type, details, ...) {               \
+               const char *msg;                                        \
+               if (sizeof("" __VA_ARGS__) > 1)                         \
+                       msg = "\"" #cond "\" matched at " file ":" #line "\x1e" __VA_ARGS__; \
+               else                                                    \
+                       msg = "\"" #cond "\" matched at " file ":" #line; \
+               if (type != DBG_BUG_ONCE ||                             \
+                   ({ static int __match_count_##line;                 \
+                      !_HA_ATOMIC_FETCH_ADD(&__match_count_##line, 1); })) { \
+                       complain(details, msg);                         \
+                       if (details & DBG_DET_FAT_FATL)                 \
+                               ABORT_NOW();                            \
+                       else if (details & DBG_DET_FAT_WARN)            \
+                               ha_backtrace_to_stderr(0);              \
+               }                                                       \
+       }
+
 #endif /* USE_OBSOLETE_LINKER  */
 
 /* reports a glitch for current file and line, optionally with an explanation */
@@ -404,29 +455,10 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt  HA_SECTION_S
  */
 #define _BUG_ON(cond, file, line, details, ...)                                        \
        (void)(unlikely(cond) ? ({                                              \
-               __DBG_COUNT(cond, file, line, DBG_BUG, __VA_ARGS__);            \
                __BUG_ON(cond, file, line, DBG_BUG, details, __VA_ARGS__);      \
                1; /* let's return the true condition */                        \
        }) : 0)
 
-/* This is called by _BUG_ON() and _BUG_ON_ONCE() to handle the event. */
-#define __BUG_ON(cond, file, line, type, details, ...) {               \
-               const char *msg;                                        \
-               if (sizeof("" __VA_ARGS__) > 1)                         \
-                       msg = "\"" #cond "\" matched at " file ":" #line "\x1e" __VA_ARGS__; \
-               else                                                    \
-                       msg = "\"" #cond "\" matched at " file ":" #line; \
-               if (type != DBG_BUG_ONCE ||                             \
-                   ({ static int __match_count_##line;                 \
-                      !_HA_ATOMIC_FETCH_ADD(&__match_count_##line, 1); })) { \
-                       complain(details, msg);                         \
-                       if (details & DBG_DET_FAT_FATL)                 \
-                               ABORT_NOW();                            \
-                       else if (details & DBG_DET_FAT_WARN)            \
-                               ha_backtrace_to_stderr(0);              \
-               }                                                       \
-       }
-
 /* This one is equivalent except that it only emits the message once by
  * maintaining a static counter. This may be used with warnings to detect
  * certain unexpected conditions in field. Later on, in cores it will be
@@ -434,7 +466,6 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt  HA_SECTION_S
  */
 #define _BUG_ON_ONCE(cond, file, line, details, ...)                           \
        (void)(unlikely(cond) ? ({                                              \
-               __DBG_COUNT(cond, file, line, DBG_BUG_ONCE, __VA_ARGS__);       \
                __BUG_ON(cond, file, line, DBG_BUG_ONCE, details, __VA_ARGS__); \
                1; /* let's return the true condition */                        \
        }) : 0)