MINOR: debug: support passing an optional message in ABORT_NOW()

The ABORT_NOW() macro is not much used since we have BUG_ON(), but
there are situations where it makes sense, typically if the program
must always die regardless od DEBUG_STRICT, or if the condition must
always be evaluated (e.g. decompress something and check it).

It's not convenient not to have any hint about what happened there. But
providing too much info also results in wiping some registers, making
the trace less exploitable, so a compromise must be found.

What this patch does is to provide the support for an optional argument
to ABORT_NOW(). When an argument is passed (a string), then a message
will be emitted with the file name, line number, the message and a
trailing LF, before the stack dump and the crash. It should be used
reasonably, for example in functions that have multiple calls that need
to be more easily distinguished.
This commit is contained in:
Willy Tarreau 2024-02-05 16:16:08 +01:00
parent 73705ac701
commit d417863828

View File

@ -85,6 +85,23 @@ static inline __attribute((always_inline)) void ha_crash_now(void)
#endif // end of arch-specific ha_crash_now() definitions
/* ABORT_NOW() usually takes no argument and will cause the program to abort
* exactly where it is. We prefer to emit an invalid instruction to preserve
* all registers, but it may fall back to a regular abort depending on the
* platform. An optional argument can be a message string that will cause
* the emission of a message saying "ABORT at" followed by the file and line
* number then that message followed by a final line feed. This can be helpful
* in situations where the core cannot be retrieved for example. However it
* will definitely cause the loss of some registers, so should be avoided when
* not strictly necessary.
*/
#define ABORT_NOW(...) \
_ABORT_NOW(__FILE__, __LINE__, __VA_ARGS__)
#define _ABORT_NOW(file, line, ...) \
__ABORT_NOW(file, line, __VA_ARGS__)
#ifdef DEBUG_USE_ABORT
/* abort() is better recognized by code analysis tools */
@ -104,12 +121,22 @@ static __attribute__((noinline,noreturn,unused)) void abort_with_line(uint line)
abort();
}
#define ABORT_NOW() do { DUMP_TRACE(); abort_with_line(__LINE__); } while (0)
#define __ABORT_NOW(file, line, ...) do { \
if (sizeof("" __VA_ARGS__) > 1) \
complain(NULL, "\nABORT at " file ":" #line ": " __VA_ARGS__ "\n", 1); \
DUMP_TRACE(); \
abort_with_line(__LINE__); \
} while (0)
#else
/* More efficient than abort() because it does not mangle the
* stack and stops at the exact location we need.
*/
#define ABORT_NOW() do { DUMP_TRACE(); ha_crash_now(); } while (0)
#define __ABORT_NOW(file, line, ...) do { \
if (sizeof("" __VA_ARGS__) > 1) \
complain(NULL, "\nABORT at " file ":" #line ": " __VA_ARGS__ "\n", 1); \
DUMP_TRACE(); \
ha_crash_now(); \
} while (0)
#endif
/* This is the generic low-level macro dealing with conditional warnings and