From d03712169b7a02e3a9b3c3a5c060395ed37b626e Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Mon, 24 Nov 2025 12:49:15 +0100 Subject: [PATCH] cmake: add support for libbacktrace, fix two build issues Also: - memdebug: fix symbol collision in unity builds. - memdebug: fix compiler warning by making a variable static. Follow-up to c77bed81a2e1325ffdebc223c27e3d1355147529 #19657 Closes #19666 --- .github/scripts/pyspelling.words | 1 + CMake/FindLibbacktrace.cmake | 52 ++++++++++++++++++++++++++++++++ CMakeLists.txt | 15 +++++++++ Makefile.am | 1 + docs/INSTALL-CMAKE.md | 3 ++ lib/curl_config.h.cmake | 3 ++ lib/memdebug.c | 9 +++--- 7 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 CMake/FindLibbacktrace.cmake diff --git a/.github/scripts/pyspelling.words b/.github/scripts/pyspelling.words index 5c96701cd0..984424200b 100644 --- a/.github/scripts/pyspelling.words +++ b/.github/scripts/pyspelling.words @@ -434,6 +434,7 @@ LDAPS ldaps LF LGTM +libbacktrace libbrotlidec libc libcurl diff --git a/CMake/FindLibbacktrace.cmake b/CMake/FindLibbacktrace.cmake new file mode 100644 index 0000000000..444c5f90fd --- /dev/null +++ b/CMake/FindLibbacktrace.cmake @@ -0,0 +1,52 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +# SPDX-License-Identifier: curl +# +########################################################################### +# Find the libbacktrace library +# +# Input variables: +# +# - `LIBBACKTRACE_INCLUDE_DIR`: Absolute path to libbacktrace include directory. +# - `LIBBACKTRACE_LIBRARY`: Absolute path to `libbacktrace` library. +# +# Result variables: +# +# - `LIBBACKTRACE_FOUND`: System has libbacktrace. +# - `LIBBACKTRACE_INCLUDE_DIRS`: The libbacktrace include directories. +# - `LIBBACKTRACE_LIBRARIES`: The libbacktrace library names. + +find_path(LIBBACKTRACE_INCLUDE_DIR NAMES "backtrace.h") +find_library(LIBBACKTRACE_LIBRARY NAMES "backtrace" "libbacktrace") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Libbacktrace + REQUIRED_VARS + LIBBACKTRACE_INCLUDE_DIR + LIBBACKTRACE_LIBRARY +) + +if(LIBBACKTRACE_FOUND) + set(LIBBACKTRACE_INCLUDE_DIRS ${LIBBACKTRACE_INCLUDE_DIR}) + set(LIBBACKTRACE_LIBRARIES ${LIBBACKTRACE_LIBRARY}) +endif() + +mark_as_advanced(LIBBACKTRACE_INCLUDE_DIR LIBBACKTRACE_LIBRARY) diff --git a/CMakeLists.txt b/CMakeLists.txt index 20336e097c..5d6e7ca3e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1421,6 +1421,21 @@ if(CURL_USE_GSSAPI) endif() endif() +# libbacktrace +option(CURL_USE_LIBBACKTRACE "Use libbacktrace. Requires build with TrackMemory and DWARF debug information." OFF) +if(CURL_USE_LIBBACKTRACE) + if(NOT ENABLE_CURLDEBUG) + message(FATAL_ERROR "libbacktrace requires TrackMemory enabled") + endif() + if(NOT CMAKE_BUILD_TYPE MATCHES "(Debug|RelWithDebInfo)") + message(FATAL_ERROR "libbacktrace requires debug information") + endif() + find_package(Libbacktrace REQUIRED) + list(APPEND CURL_LIBS ${LIBBACKTRACE_LIBRARIES}) + include_directories(SYSTEM ${LIBBACKTRACE_INCLUDE_DIRS}) + set(USE_BACKTRACE ON) +endif() + # libuv option(CURL_USE_LIBUV "Use libuv for event-based tests" OFF) if(CURL_USE_LIBUV) diff --git a/Makefile.am b/Makefile.am index 1ed54423e5..d289f33d57 100644 --- a/Makefile.am +++ b/Makefile.am @@ -37,6 +37,7 @@ CMAKE_DIST = \ CMake/FindGnuTLS.cmake \ CMake/FindGSS.cmake \ CMake/FindLDAP.cmake \ + CMake/FindLibbacktrace.cmake \ CMake/FindLibgsasl.cmake \ CMake/FindLibidn2.cmake \ CMake/FindLibpsl.cmake \ diff --git a/docs/INSTALL-CMAKE.md b/docs/INSTALL-CMAKE.md index bd9555b614..026db07628 100644 --- a/docs/INSTALL-CMAKE.md +++ b/docs/INSTALL-CMAKE.md @@ -355,6 +355,7 @@ Details via CMake - `CURL_USE_GNUTLS`: Enable GnuTLS for SSL/TLS. Default: `OFF` - `CURL_USE_GSASL`: Use libgsasl. Default: `OFF` - `CURL_USE_GSSAPI`: Use GSSAPI implementation. Default: `OFF` +- `CURL_USE_LIBBACKTRACE`: Use [libbacktrace](https://github.com/ianlancetaylor/libbacktrace). Requires build with TrackMemory and DWARF debug information. Default: `OFF` - `CURL_USE_LIBPSL`: Use libpsl. Default: `ON` - `CURL_USE_LIBSSH2`: Use libssh2. Default: `ON` - `CURL_USE_LIBSSH`: Use libssh. Default: `OFF` @@ -411,6 +412,8 @@ Details via CMake - `LDAP_INCLUDE_DIR`: Absolute path to LDAP include directory. - `LDAP_LIBRARY`: Absolute path to `ldap` library. - `LDAP_LBER_LIBRARY`: Absolute path to `lber` library. +- `LIBBACKTRACE_INCLUDE_DIR`: Absolute path to libbacktrace include directory (https://github.com/ianlancetaylor/libbacktrace). +- `LIBBACKTRACE_LIBRARY`: Absolute path to `libbacktrace` library. - `LIBGSASL_INCLUDE_DIR`: Absolute path to libgsasl include directory. - `LIBGSASL_LIBRARY`: Absolute path to `libgsasl` library. - `LIBIDN2_INCLUDE_DIR`: Absolute path to libidn2 include directory. diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake index acbb428575..37ec3d9a65 100644 --- a/lib/curl_config.h.cmake +++ b/lib/curl_config.h.cmake @@ -730,6 +730,9 @@ ${SIZEOF_TIME_T_CODE} /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UV_H 1 +/* if libbacktrace is in use */ +#cmakedefine USE_BACKTRACE 1 + /* Define to 1 if you do not want the OpenSSL configuration to be loaded automatically */ #cmakedefine CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 1 diff --git a/lib/memdebug.c b/lib/memdebug.c index cbda4a2be1..6ec292654f 100644 --- a/lib/memdebug.c +++ b/lib/memdebug.c @@ -63,7 +63,7 @@ static bool registered_cleanup = FALSE; /* atexit registered cleanup */ static bool memlimit = FALSE; /* enable memory limit */ static long memsize = 0; /* set number of mallocs allowed */ #ifdef USE_BACKTRACE -struct backtrace_state *btstate; +static struct backtrace_state *btstate; #endif /* LeakSantizier (LSAN) calls _exit() instead of exit() when a leak is detected @@ -81,7 +81,8 @@ static void curl_dbg_cleanup(void) curl_dbg_logfile = NULL; } #ifdef USE_BACKTRACE -static void error_callback(void *data, const char *message, int error_number) +static void error_bt_callback(void *data, const char *message, + int error_number) { (void)data; if(error_number == -1) @@ -102,7 +103,7 @@ static int full_callback(void *data, uintptr_t pc, const char *pathname, static void dump_bt(void) { - backtrace_full(btstate, 0, full_callback, error_callback, NULL); + backtrace_full(btstate, 0, full_callback, error_bt_callback, NULL); } #else #define dump_bt() /* nothing to do */ @@ -123,7 +124,7 @@ void curl_dbg_memdebug(const char *logname) #endif } #ifdef USE_BACKTRACE - btstate = backtrace_create_state(NULL, 0, error_callback, NULL); + btstate = backtrace_create_state(NULL, 0, error_bt_callback, NULL); #endif if(!registered_cleanup) registered_cleanup = !atexit(curl_dbg_cleanup); -- 2.47.3