m4_include([m4/ax_check_compile_flag.m4])
m4_include([m4/ax_check_openssl.m4])
+m4_include([m4/ax_gcc_func_attribute.m4])
m4_include([m4/ax_posix_shell.m4])
m4_include([m4/ax_pthread.m4])
m4_include([m4/ax_restore_flags.m4])
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
#undef HAVE_FSEEKO
+/* Define to 1 if the system has the `constructor' function attribute */
+#undef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
+
+/* Define to 1 if the system has the `destructor' function attribute */
+#undef HAVE_FUNC_ATTRIBUTE_DESTRUCTOR
+
/* Build with GeoIP2 support */
#undef HAVE_GEOIP2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking contributed DLZ drivers" >&5
$as_echo_n "checking contributed DLZ drivers... " >&6; }
+#
+# Support for constructor and destructor attributes
+#
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__((constructor))" >&5
+$as_echo_n "checking for __attribute__((constructor))... " >&6; }
+if ${ax_cv_have_func_attribute_constructor+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+ int foo( void ) __attribute__((constructor));
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ if test -s conftest.err; then :
+ ax_cv_have_func_attribute_constructor=no
+else
+ ax_cv_have_func_attribute_constructor=yes
+fi
+else
+ ax_cv_have_func_attribute_constructor=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_have_func_attribute_constructor" >&5
+$as_echo "$ax_cv_have_func_attribute_constructor" >&6; }
+
+ if test yes = $ax_cv_have_func_attribute_constructor; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__((destructor))" >&5
+$as_echo_n "checking for __attribute__((destructor))... " >&6; }
+if ${ax_cv_have_func_attribute_destructor+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+ int foo( void ) __attribute__((destructor));
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ if test -s conftest.err; then :
+ ax_cv_have_func_attribute_destructor=no
+else
+ ax_cv_have_func_attribute_destructor=yes
+fi
+else
+ ax_cv_have_func_attribute_destructor=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_have_func_attribute_destructor" >&5
+$as_echo "$ax_cv_have_func_attribute_destructor" >&6; }
+
+ if test yes = $ax_cv_have_func_attribute_destructor; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_FUNC_ATTRIBUTE_DESTRUCTOR 1
+_ACEOF
+
+fi
+
+
+
+
if test -n "$CONTRIB_DLZ"
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
sinclude(contrib/dlz/config.dlz.in)
AC_MSG_CHECKING(contributed DLZ drivers)
+#
+# Support for constructor and destructor attributes
+#
+AX_GCC_FUNC_ATTRIBUTE([constructor])
+AX_GCC_FUNC_ATTRIBUTE([destructor])
+
if test -n "$CONTRIB_DLZ"
then
AC_MSG_RESULT(yes)
dst__openssl_init(const char *engine) {
isc_result_t result = ISC_R_SUCCESS;
- isc_tls_initialize();
-
enable_fips_mode();
#if !defined(OPENSSL_NO_ENGINE)
}
e = NULL;
#endif /* if !defined(OPENSSL_NO_ENGINE) */
- isc_tls_destroy();
}
static isc_result_t
typedef struct ssl_ctx_st isc_tlsctx_t;
-void
-isc_tls_initialize(void);
-
-void
-isc_tls_destroy(void);
-
void
isc_tlsctx_free(isc_tlsctx_t **ctpx);
/*%
#define ISC_NONSTRING
#endif /* __GNUC__ */
+#if HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR && HAVE_FUNC_ATTRIBUTE_DESTRUCTOR
+#define ISC_CONSTRUCTOR(priority) __attribute__((constructor(priority)))
+#define ISC_DESTRUCTOR(priority) __attribute__((destructor(priority)))
+#elif WIN32
+#define ISC_CONSTRUCTOR(priority)
+#define ISC_DESTRUCTOR(priority)
+#else
+#error Either __attribute__((constructor|destructor))__ or DllMain support needed to compile BIND 9.
+#endif
+
/*%
* The opposite: silent warnings about stored values which are never read.
*/
#include <isc/bind9.h>
#include <isc/lib.h>
+#include <isc/mem.h>
+#include <isc/tls.h>
+#include <isc/util.h>
+
+#include "mem_p.h"
+#include "tls_p.h"
/***
*** Functions
isc_lib_register(void) {
isc_bind9 = false;
}
+
+void
+isc__initialize(void) ISC_CONSTRUCTOR(101);
+void
+isc__shutdown(void) ISC_DESTRUCTOR(101);
+
+void
+isc__initialize(void) {
+ isc__mem_initialize();
+ isc__tls_initialize();
+}
+
+void
+isc__shutdown(void) {
+ isc__tls_shutdown();
+ isc__mem_shutdown();
+}
static ISC_LIST(isc__mem_t) contexts;
-static isc_once_t once = ISC_ONCE_INIT;
+static isc_once_t init_once = ISC_ONCE_INIT;
+static isc_once_t shut_once = ISC_ONCE_INIT;
static isc_mutex_t contextslock;
/*%
}
static void
-initialize_action(void) {
+mem_initialize(void) {
isc_mutex_init(&contextslock);
ISC_LIST_INIT(contexts);
totallost = 0;
}
+void
+isc__mem_initialize(void) {
+ RUNTIME_CHECK(isc_once_do(&init_once, mem_initialize) == ISC_R_SUCCESS);
+}
+
+static void
+mem_shutdown(void) {
+ isc__mem_checkdestroyed();
+
+ isc_mutex_destroy(&contextslock);
+}
+
+void
+isc__mem_shutdown(void) {
+ RUNTIME_CHECK(isc_once_do(&shut_once, mem_shutdown) == ISC_R_SUCCESS);
+}
+
static void
mem_create(isc_mem_t **ctxp, unsigned int flags) {
REQUIRE(ctxp != NULL && *ctxp == NULL);
STATIC_ASSERT((ALIGNMENT_SIZE & (ALIGNMENT_SIZE - 1)) == 0,
"wrong alignment size");
- RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
-
ctx = (default_memalloc)(sizeof(*ctx));
isc_mutex_init(&ctx->lock);
fflush(file);
}
+static atomic_uintptr_t checkdestroyed = ATOMIC_VAR_INIT(0);
+
void
isc_mem_checkdestroyed(FILE *file) {
-#if !ISC_MEM_TRACKLINES
- UNUSED(file);
-#endif /* if !ISC_MEM_TRACKLINES */
+ atomic_store_release(&checkdestroyed, (uintptr_t)file);
+}
- RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+void
+isc__mem_checkdestroyed(void) {
+ FILE *file = (FILE *)atomic_load_acquire(&checkdestroyed);
+
+ if (file == NULL) {
+ return;
+ }
LOCK(&contextslock);
if (!ISC_LIST_EMPTY(contexts)) {
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "contexts"));
- RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
-
LOCK(&contextslock);
lost = totallost;
for (ctx = ISC_LIST_HEAD(contexts); ctx != NULL;
json_object *memobj = (json_object *)memobj0;
memset(&summary, 0, sizeof(summary));
- RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
ctxarray = json_object_new_array();
CHECKMEM(ctxarray);
* information regarding copyright ownership.
*/
-#ifndef ISC_MEM_P_H
-#define ISC_MEM_P_H
+#pragma once
+
+#include <stdio.h>
+
+#include <isc/mem.h>
/*! \file */
* a single memory context.
*/
-#endif /* ISC_MEM_P_H */
+void
+isc__mem_checkdestroyed(void);
+
+void
+isc__mem_initialize(void);
+
+void
+isc__mem_shutdown(void);
isc__nm_winsock_initialize();
#endif /* WIN32 */
- isc_tls_initialize();
-
mgr = isc_mem_get(mctx, sizeof(*mgr));
*mgr = (isc_nm_t){ .nworkers = workers };
mgr->nworkers * sizeof(isc__networker_t));
isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
- isc_tls_destroy();
-
#ifdef WIN32
isc__nm_winsock_destroy();
#endif /* WIN32 */
REQUIRE(VALID_NM(mgr));
REQUIRE(local != NULL);
REQUIRE(peer != NULL);
+ REQUIRE(sslctx != NULL);
sa_family = peer->addr.type.sa.sa_family;
csock->tls.state = TLS_STATE_NONE;
csock->tls.ssl = SSL_new(ssock->tls.ctx);
+
+ if (csock->tls.ssl == NULL) {
+ char errbuf[256];
+ unsigned long err = ERR_get_error();
+
+ ERR_error_string_n(err, errbuf, sizeof(errbuf));
+ fprintf(stderr, "%s:SSL_new(%p) -> %s\n", __func__,
+ ssock->tls.ctx, errbuf);
+ }
+
RUNTIME_CHECK(csock->tls.ssl != NULL);
r = BIO_new_bio_pair(&csock->tls.ssl_wbio, TLS_BUF_SIZE,
int tlsdns_listen_sock = -1;
isc_nm_t **nm = NULL;
- isc_tlsctx_createserver(NULL, NULL, &tlsdns_listen_ctx);
- isc_tlsctx_createclient(&tlsdns_connect_ctx);
+ if (isc_tlsctx_createserver(NULL, NULL, &tlsdns_listen_ctx) !=
+ ISC_R_SUCCESS) {
+ return (-1);
+ }
+ if (isc_tlsctx_createclient(&tlsdns_connect_ctx) != ISC_R_SUCCESS) {
+ return (-1);
+ }
tlsdns_listen_addr = (isc_sockaddr_t){ .length = 0 };
tlsdns_listen_sock = setup_ephemeral_port(&tlsdns_listen_addr,
#include <isc/util.h>
#include "openssl_shim.h"
+#include "tls_p.h"
static isc_once_t init_once = ISC_ONCE_INIT;
static isc_once_t shut_once = ISC_ONCE_INIT;
static atomic_bool init_done = ATOMIC_VAR_INIT(false);
static atomic_bool shut_done = ATOMIC_VAR_INIT(false);
-static isc_mem_t *isc__tls_mctx = NULL;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
static isc_mutex_t *locks = NULL;
}
#endif
-#if 0
-static void *
-isc__tls_malloc(size_t size, const char *file, int line) {
- UNUSED(file);
- UNUSED(line);
-
- return (isc_mem_allocate(isc__tls_mctx, size));
-}
-
-static void *
-isc__tls_realloc(void *ptr, size_t size, const char *file, int line) {
- UNUSED(file);
- UNUSED(line);
-
- return (isc__mem_reallocate(isc__tls_mctx, ptr, size));
-}
-
-static void
-isc__tls_free(void *ptr, const char *file, int line) {
- UNUSED(file);
- UNUSED(line);
-
- if (ptr == NULL) {
- return;
- }
-
- isc__mem_free(isc__tls_mctx, ptr);
-}
-#endif
-
static void
-isc__tls_initialize(void) {
+tls_initialize(void) {
REQUIRE(!atomic_load(&init_done));
- isc_mem_create(&isc__tls_mctx);
- /* isc_mem_setdestroycheck(isc__tls_mctx, false); */
-
- /* REQUIRE(CRYPTO_set_mem_functions(isc__tls_malloc, isc__tls_realloc,
- * isc__tls_free) == 1); */
-
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
RUNTIME_CHECK(OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN |
OPENSSL_INIT_LOAD_CONFIG,
NULL) == 1);
#else
nlocks = CRYPTO_num_locks();
- locks = isc_mem_get(isc__tls_mctx, nlocks * sizeof(locks[0]));
+ /*
+ * We can't use isc_mem API here, because it's called too
+ * early and when the isc_mem_debugging flags are changed
+ * later and ISC_MEM_DEBUGSIZE or ISC_MEM_DEBUGCTX flags are
+ * added, neither isc_mem_put() nor isc_mem_free() can be used
+ * to free up the memory allocated here because the flags were
+ * not set when calling isc_mem_get() or isc_mem_allocate()
+ * here.
+ *
+ * Actually, since this is a single allocation at library load
+ * and deallocation at library unload, using the standard
+ * allocator without the tracking is fine for this purpose.
+ */
+ locks = calloc(nlocks, sizeof(locks[0]));
isc_mutexblock_init(locks, nlocks);
CRYPTO_set_locking_callback(isc__tls_lock_callback);
CRYPTO_THREADID_set_callback(isc__tls_set_thread_id);
"seeded' message in the OpenSSL FAQ)");
}
- atomic_compare_exchange_strong(&init_done, &(bool){ false }, true);
+ REQUIRE(atomic_compare_exchange_strong(&init_done, &(bool){ false },
+ true));
}
void
-isc_tls_initialize(void) {
- isc_result_t result = isc_once_do(&init_once, isc__tls_initialize);
+isc__tls_initialize(void) {
+ isc_result_t result = isc_once_do(&init_once, tls_initialize);
REQUIRE(result == ISC_R_SUCCESS);
REQUIRE(atomic_load(&init_done));
}
static void
-isc__tls_destroy(void) {
+tls_shutdown(void) {
REQUIRE(atomic_load(&init_done));
REQUIRE(!atomic_load(&shut_done));
+
#if OPENSSL_VERSION_NUMBER < 0x10100000L
CONF_modules_unload(1);
CRYPTO_set_locking_callback(NULL);
- /* REQUIRE(CRYPTO_set_mem_functions(OPENSSL_malloc, OPENSSL_realloc,
- * OPENSSL_free) == 1); */
-
if (locks != NULL) {
- INSIST(isc__tls_mctx != NULL);
isc_mutexblock_destroy(locks, nlocks);
- isc_mem_put(isc__tls_mctx, locks, nlocks * sizeof(locks[0]));
+ free(locks);
locks = NULL;
}
#endif
- isc_mem_detach(&isc__tls_mctx);
- atomic_compare_exchange_strong(&shut_done, &(bool){ false }, true);
+ REQUIRE(atomic_compare_exchange_strong(&shut_done, &(bool){ false },
+ true));
}
void
-isc_tls_destroy(void) {
- isc_result_t result = isc_once_do(&shut_once, isc__tls_destroy);
+isc__tls_shutdown(void) {
+ isc_result_t result = isc_once_do(&shut_once, tls_shutdown);
REQUIRE(result == ISC_R_SUCCESS);
REQUIRE(atomic_load(&shut_done));
}
REQUIRE(ctxp != NULL && *ctxp == NULL);
- isc_tls_initialize();
-
method = TLS_client_method();
if (method == NULL) {
goto ssl_error;
REQUIRE(ctxp != NULL && *ctxp == NULL);
- isc_tls_initialize();
-
if (ephemeral) {
INSIST(keyfile == NULL);
INSIST(certfile == NULL);
isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_NETMGR,
ISC_LOG_ERROR, "Error initializing TLS context: %s",
errbuf);
+
if (ctx != NULL) {
SSL_CTX_free(ctx);
}
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+void
+isc__tls_initialize(void);
+
+void
+isc__tls_shutdown(void);
#include <stdio.h>
#include <windows.h>
+#include <isc/mem.h>
+#include <isc/tls.h>
+#include <isc/util.h>
+
+#include "mem_p.h"
+#include "tls_p.h"
+
/*
* Called when we enter the DLL
*/
* Disable DllMain() invocation on Thread creation/destruction
*/
DisableThreadLibraryCalls(hinstDLL);
+ isc__mem_initialize();
+ isc__tls_initialize();
break;
/*
* termination or a call to FreeLibrary.
*/
case DLL_PROCESS_DETACH:
+ isc__tls_shutdown();
+ isc__mem_shutdown();
break;
case DLL_THREAD_ATTACH:
* disabled.
*/
INSIST(0);
+ ISC_UNREACHABLE();
break;
default:
isc_md_type_get_size
isc_md_type_get_block_size
isc_md
+isc__mem_checkdestroyed
+isc__mem_initialize
+isc__mem_shutdown
isc_mem_attach
isc_mem_checkdestroyed
isc_mem_create
isc_timermgr_createinctx
isc_timermgr_destroy
isc_timermgr_poke
-isc_tls_initialize
-isc_tls_destroy
+isc__tls_initialize
+isc__tls_shutdown
isc_tlsctx_createclient
isc_tlsctx_createserver
isc_tlsctx_free
--- /dev/null
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_gcc_func_attribute.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_GCC_FUNC_ATTRIBUTE(ATTRIBUTE)
+#
+# DESCRIPTION
+#
+# This macro checks if the compiler supports one of GCC's function
+# attributes; many other compilers also provide function attributes with
+# the same syntax. Compiler warnings are used to detect supported
+# attributes as unsupported ones are ignored by default so quieting
+# warnings when using this macro will yield false positives.
+#
+# The ATTRIBUTE parameter holds the name of the attribute to be checked.
+#
+# If ATTRIBUTE is supported define HAVE_FUNC_ATTRIBUTE_<ATTRIBUTE>.
+#
+# The macro caches its result in the ax_cv_have_func_attribute_<attribute>
+# variable.
+#
+# The macro currently supports the following function attributes:
+#
+# alias
+# aligned
+# alloc_size
+# always_inline
+# artificial
+# cold
+# const
+# constructor
+# constructor_priority for constructor attribute with priority
+# deprecated
+# destructor
+# dllexport
+# dllimport
+# error
+# externally_visible
+# fallthrough
+# flatten
+# format
+# format_arg
+# gnu_format
+# gnu_inline
+# hot
+# ifunc
+# leaf
+# malloc
+# noclone
+# noinline
+# nonnull
+# noreturn
+# nothrow
+# optimize
+# pure
+# sentinel
+# sentinel_position
+# unused
+# used
+# visibility
+# warning
+# warn_unused_result
+# weak
+# weakref
+#
+# Unsupported function attributes will be tested with a prototype
+# returning an int and not accepting any arguments and the result of the
+# check might be wrong or meaningless so use with care.
+#
+# LICENSE
+#
+# Copyright (c) 2013 Gabriele Svelto <gabriele.svelto@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 10
+
+AC_DEFUN([AX_GCC_FUNC_ATTRIBUTE], [
+ AS_VAR_PUSHDEF([ac_var], [ax_cv_have_func_attribute_$1])
+
+ AC_CACHE_CHECK([for __attribute__(($1))], [ac_var], [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([
+ m4_case([$1],
+ [alias], [
+ int foo( void ) { return 0; }
+ int bar( void ) __attribute__(($1("foo")));
+ ],
+ [aligned], [
+ int foo( void ) __attribute__(($1(32)));
+ ],
+ [alloc_size], [
+ void *foo(int a) __attribute__(($1(1)));
+ ],
+ [always_inline], [
+ inline __attribute__(($1)) int foo( void ) { return 0; }
+ ],
+ [artificial], [
+ inline __attribute__(($1)) int foo( void ) { return 0; }
+ ],
+ [cold], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [const], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [constructor_priority], [
+ int foo( void ) __attribute__((__constructor__(65535/2)));
+ ],
+ [constructor], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [deprecated], [
+ int foo( void ) __attribute__(($1("")));
+ ],
+ [destructor], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [dllexport], [
+ __attribute__(($1)) int foo( void ) { return 0; }
+ ],
+ [dllimport], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [error], [
+ int foo( void ) __attribute__(($1("")));
+ ],
+ [externally_visible], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [fallthrough], [
+ int foo( void ) {switch (0) { case 1: __attribute__(($1)); case 2: break ; }};
+ ],
+ [flatten], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [format], [
+ int foo(const char *p, ...) __attribute__(($1(printf, 1, 2)));
+ ],
+ [gnu_format], [
+ int foo(const char *p, ...) __attribute__((format(gnu_printf, 1, 2)));
+ ],
+ [format_arg], [
+ char *foo(const char *p) __attribute__(($1(1)));
+ ],
+ [gnu_inline], [
+ inline __attribute__(($1)) int foo( void ) { return 0; }
+ ],
+ [hot], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [ifunc], [
+ int my_foo( void ) { return 0; }
+ static int (*resolve_foo(void))(void) { return my_foo; }
+ int foo( void ) __attribute__(($1("resolve_foo")));
+ ],
+ [leaf], [
+ __attribute__(($1)) int foo( void ) { return 0; }
+ ],
+ [malloc], [
+ void *foo( void ) __attribute__(($1));
+ ],
+ [noclone], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [noinline], [
+ __attribute__(($1)) int foo( void ) { return 0; }
+ ],
+ [nonnull], [
+ int foo(char *p) __attribute__(($1(1)));
+ ],
+ [noreturn], [
+ void foo( void ) __attribute__(($1));
+ ],
+ [nothrow], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [optimize], [
+ __attribute__(($1(3))) int foo( void ) { return 0; }
+ ],
+ [pure], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [sentinel], [
+ int foo(void *p, ...) __attribute__(($1));
+ ],
+ [sentinel_position], [
+ int foo(void *p, ...) __attribute__(($1(1)));
+ ],
+ [returns_nonnull], [
+ void *foo( void ) __attribute__(($1));
+ ],
+ [unused], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [used], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [visibility], [
+ int foo_def( void ) __attribute__(($1("default")));
+ int foo_hid( void ) __attribute__(($1("hidden")));
+ int foo_int( void ) __attribute__(($1("internal")));
+ int foo_pro( void ) __attribute__(($1("protected")));
+ ],
+ [warning], [
+ int foo( void ) __attribute__(($1("")));
+ ],
+ [warn_unused_result], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [weak], [
+ int foo( void ) __attribute__(($1));
+ ],
+ [weakref], [
+ static int foo( void ) { return 0; }
+ static int bar( void ) __attribute__(($1("foo")));
+ ],
+ [
+ m4_warn([syntax], [Unsupported attribute $1, the test may fail])
+ int foo( void ) __attribute__(($1));
+ ]
+ )], [])
+ ],
+ dnl GCC doesn't exit with an error if an unknown attribute is
+ dnl provided but only outputs a warning, so accept the attribute
+ dnl only if no warning were issued.
+ [AS_IF([test -s conftest.err],
+ [AS_VAR_SET([ac_var], [no])],
+ [AS_VAR_SET([ac_var], [yes])])],
+ [AS_VAR_SET([ac_var], [no])])
+ ])
+
+ AS_IF([test yes = AS_VAR_GET([ac_var])],
+ [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_FUNC_ATTRIBUTE_$1), 1,
+ [Define to 1 if the system has the `$1' function attribute])], [])
+
+ AS_VAR_POPDEF([ac_var])
+])
./lib/isc/timer.c C 1998,1999,2000,2001,2002,2004,2005,2007,2008,2009,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
./lib/isc/timer_p.h C 2000,2001,2004,2005,2007,2009,2016,2017,2018,2019,2020,2021
./lib/isc/tls.c C 2021
+./lib/isc/tls_p.h C 2021
./lib/isc/tm.c C 2014,2016,2018,2019,2020,2021
./lib/isc/unix/dir.c C 1999,2000,2001,2004,2005,2007,2008,2009,2011,2012,2016,2017,2018,2019,2020,2021
./lib/isc/unix/errno.c C 2016,2018,2019,2020,2021