7e1ffc
diff --color -ruNp a/configure.ac b/configure.ac
7e1ffc
--- a/configure.ac	2022-05-27 09:17:26.000000000 +0200
7e1ffc
+++ b/configure.ac	2022-12-15 11:00:18.830698584 +0100
7e1ffc
@@ -619,6 +619,8 @@ if [ test "$enable_fips" = "yes" ];then
7e1ffc
     if test "x$fips_module_version" != xnone; then
7e1ffc
        AC_DEFINE_UNQUOTED([FIPS_MODULE_VERSION], ["$fips_module_version"], [The FIPS140 module version])
7e1ffc
     fi
7e1ffc
+
7e1ffc
+    AC_CHECK_FUNCS(dl_iterate_phdr)
7e1ffc
   else
7e1ffc
     enable_fips=no
7e1ffc
     AC_MSG_WARN([[
7e1ffc
diff --color -ruNp a/lib/fips.c b/lib/fips.c
7e1ffc
--- a/lib/fips.c	2022-12-15 10:59:57.460279029 +0100
7e1ffc
+++ b/lib/fips.c	2022-12-15 11:00:18.831698604 +0100
7e1ffc
@@ -23,9 +23,11 @@
7e1ffc
 #include <gnutls/gnutls.h>
7e1ffc
 #include <gnutls/crypto.h>
7e1ffc
 #include <unistd.h>
7e1ffc
+#include "dirname.h"
7e1ffc
 #include "errors.h"
7e1ffc
 #include "file.h"
7e1ffc
 #include "inih/ini.h"
7e1ffc
+#include "str.h"
7e1ffc
 #include <fips.h>
7e1ffc
 #include <gnutls/self-test.h>
7e1ffc
 #include <stdio.h>
7e1ffc
@@ -34,6 +36,10 @@
7e1ffc
 
7e1ffc
 #include "gthreads.h"
7e1ffc
 
7e1ffc
+#ifdef HAVE_DL_ITERATE_PHDR
7e1ffc
+#include <link.h>
7e1ffc
+#endif
7e1ffc
+
7e1ffc
 unsigned int _gnutls_lib_state = LIB_STATE_POWERON;
7e1ffc
 
7e1ffc
 struct gnutls_fips140_context_st {
7e1ffc
@@ -153,7 +159,6 @@ void _gnutls_fips_mode_reset_zombie(void
7e1ffc
 
7e1ffc
 #define HMAC_SIZE 32
7e1ffc
 #define HMAC_ALGO GNUTLS_MAC_SHA256
7e1ffc
-#define HMAC_FILE_NAME ".gnutls.hmac"
7e1ffc
 #define HMAC_FORMAT_VERSION 1
7e1ffc
 
7e1ffc
 struct hmac_entry
7e1ffc
@@ -162,51 +167,32 @@ struct hmac_entry
7e1ffc
 	uint8_t hmac[HMAC_SIZE];
7e1ffc
 };
7e1ffc
 
7e1ffc
-typedef struct
7e1ffc
+struct hmac_file
7e1ffc
 {
7e1ffc
 	int version;
7e1ffc
 	struct hmac_entry gnutls;
7e1ffc
 	struct hmac_entry nettle;
7e1ffc
 	struct hmac_entry hogweed;
7e1ffc
 	struct hmac_entry gmp;
7e1ffc
-} hmac_file;
7e1ffc
+};
7e1ffc
 
7e1ffc
-static int get_library_path(const char* lib, const char* symbol, char* path, size_t path_size)
7e1ffc
+struct lib_paths
7e1ffc
 {
7e1ffc
-	int ret;
7e1ffc
-	void *dl, *sym;
7e1ffc
-	Dl_info info;
7e1ffc
-
7e1ffc
-	dl = dlopen(lib, RTLD_LAZY);
7e1ffc
-	if (dl == NULL)
7e1ffc
-		return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
7e1ffc
-
7e1ffc
-	sym = dlsym(dl, symbol);
7e1ffc
-	if (sym == NULL) {
7e1ffc
-		ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
7e1ffc
-		goto cleanup;
7e1ffc
-	}
7e1ffc
-
7e1ffc
-	ret = dladdr(sym, &info;;
7e1ffc
-	if (ret == 0) {
7e1ffc
-		ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
7e1ffc
-		goto cleanup;
7e1ffc
-	}
7e1ffc
-
7e1ffc
-	ret = snprintf(path, path_size, "%s", info.dli_fname);
7e1ffc
-	if ((size_t)ret >= path_size) {
7e1ffc
-		ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
7e1ffc
-		goto cleanup;
7e1ffc
-	}
7e1ffc
-
7e1ffc
-	ret = 0;
7e1ffc
-cleanup:
7e1ffc
-	dlclose(dl);
7e1ffc
-	return ret;
7e1ffc
-}
7e1ffc
+	char gnutls[GNUTLS_PATH_MAX];
7e1ffc
+	char nettle[GNUTLS_PATH_MAX];
7e1ffc
+	char hogweed[GNUTLS_PATH_MAX];
7e1ffc
+	char gmp[GNUTLS_PATH_MAX];
7e1ffc
+};
7e1ffc
 
7e1ffc
-/* Parses hmac data and copies hex value into dest.
7e1ffc
+/*
7e1ffc
+ * get_hmac:
7e1ffc
+ * @dest: buffer for the hex value
7e1ffc
+ * @value: hmac value
7e1ffc
+ *
7e1ffc
+ * Parses hmac data and copies hex value into dest.
7e1ffc
  * dest must point to at least HMAC_SIZE amount of memory
7e1ffc
+ *
7e1ffc
+ * Returns: 0 on success, a negative error code otherwise
7e1ffc
  */
7e1ffc
 static int get_hmac(uint8_t *dest, const char *value)
7e1ffc
 {
7e1ffc
@@ -245,7 +231,7 @@ lib_handler(struct hmac_entry *entry,
7e1ffc
 
7e1ffc
 static int handler(void *user, const char *section, const char *name, const char *value)
7e1ffc
 {
7e1ffc
-	hmac_file *p = (hmac_file *)user;
7e1ffc
+	struct hmac_file *p = (struct hmac_file *)user;
7e1ffc
 
7e1ffc
 	if (!strcmp(section, "global")) {
7e1ffc
 		if (!strcmp(name, "format-version")) {
7e1ffc
@@ -267,24 +253,29 @@ static int handler(void *user, const cha
7e1ffc
 	return 1;
7e1ffc
 }
7e1ffc
 
7e1ffc
-static int get_hmac_path(char *mac_file, size_t mac_file_size)
7e1ffc
+/*
7e1ffc
+ * get_hmac_path:
7e1ffc
+ * @mac_file: buffer where the hmac file path will be written to
7e1ffc
+ * @mac_file_size: size of the mac_file buffer
7e1ffc
+ * @gnutls_path: path to the gnutls library, used to deduce hmac file path
7e1ffc
+ * 
7e1ffc
+ * Deduces hmac file path from the gnutls library path.
7e1ffc
+ *
7e1ffc
+ * Returns: 0 on success, a negative error code otherwise
7e1ffc
+ */
7e1ffc
+static int get_hmac_path(char *mac_file, size_t mac_file_size, const char *gnutls_path)
7e1ffc
 {
7e1ffc
 	int ret;
7e1ffc
 	char *p;
7e1ffc
-	char file[GNUTLS_PATH_MAX];
7e1ffc
 
7e1ffc
-	ret = get_library_path(GNUTLS_LIBRARY_NAME, "gnutls_global_init",
7e1ffc
-			       file, sizeof(file));
7e1ffc
-	if (ret < 0)
7e1ffc
-		return ret;
7e1ffc
-
7e1ffc
-	p = strrchr(file, '/');
7e1ffc
+	p = strrchr(gnutls_path, '/');
7e1ffc
 
7e1ffc
 	if (p == NULL)
7e1ffc
-		ret = snprintf(mac_file, mac_file_size, HMAC_FILE_NAME);
7e1ffc
+		ret = snprintf(mac_file, mac_file_size, ".%s.hmac", gnutls_path);
7e1ffc
 	else
7e1ffc
-		ret = snprintf(mac_file, mac_file_size,
7e1ffc
-			       "%.*s/"HMAC_FILE_NAME, (int)(p - file), file);
7e1ffc
+		ret = snprintf(mac_file, mac_file_size, "%.*s/.%s.hmac",
7e1ffc
+			       (int)(p - gnutls_path), gnutls_path, p + 1);
7e1ffc
+
7e1ffc
 	if ((size_t)ret >= mac_file_size)
7e1ffc
 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
7e1ffc
 
7e1ffc
@@ -293,10 +284,11 @@ static int get_hmac_path(char *mac_file,
7e1ffc
 		return GNUTLS_E_SUCCESS;
7e1ffc
 
7e1ffc
 	if (p == NULL)
7e1ffc
-		ret = snprintf(mac_file, mac_file_size, "fipscheck/"HMAC_FILE_NAME);
7e1ffc
+		ret = snprintf(mac_file, mac_file_size, "fipscheck/.%s.hmac", gnutls_path);
7e1ffc
 	else
7e1ffc
-		ret = snprintf(mac_file, mac_file_size,
7e1ffc
-			       "%.*s/fipscheck/"HMAC_FILE_NAME, (int)(p - file), file);
7e1ffc
+		ret = snprintf(mac_file, mac_file_size, "%.*s/fipscheck/.%s.hmac",
7e1ffc
+			       (int)(p - gnutls_path), gnutls_path, p + 1);
7e1ffc
+
7e1ffc
 	if ((size_t)ret >= mac_file_size)
7e1ffc
 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
7e1ffc
 
7e1ffc
@@ -307,51 +299,52 @@ static int get_hmac_path(char *mac_file,
7e1ffc
 	return GNUTLS_E_FILE_ERROR;
7e1ffc
 }
7e1ffc
 
7e1ffc
-static int load_hmac_file(hmac_file *p)
7e1ffc
+/*
7e1ffc
+ * load_hmac_file:
7e1ffc
+ * @hmac_file: hmac file structure
7e1ffc
+ * @hmac_path: path to the hmac file
7e1ffc
+ *
7e1ffc
+ * Loads the hmac file into the hmac file structure.
7e1ffc
+ *
7e1ffc
+ * Returns: 0 on success, a negative error code otherwise
7e1ffc
+ */
7e1ffc
+static int load_hmac_file(struct hmac_file *hmac_file, const char *hmac_path)
7e1ffc
 {
7e1ffc
 	int ret;
7e1ffc
 	FILE *stream;
7e1ffc
-	char hmac_path[GNUTLS_PATH_MAX];
7e1ffc
-
7e1ffc
-	ret = get_hmac_path(hmac_path, sizeof(hmac_path));
7e1ffc
-	if (ret < 0)
7e1ffc
-		return gnutls_assert_val(ret);
7e1ffc
 
7e1ffc
 	stream = fopen(hmac_path, "r");
7e1ffc
 	if (stream == NULL)
7e1ffc
 		return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
7e1ffc
 
7e1ffc
-	gnutls_memset(p, 0, sizeof(*p));
7e1ffc
-	ret = ini_parse_file(stream, handler, p);
7e1ffc
+	gnutls_memset(hmac_file, 0, sizeof(*hmac_file));
7e1ffc
+	ret = ini_parse_file(stream, handler, hmac_file);
7e1ffc
 	fclose(stream);
7e1ffc
 	if (ret < 0)
7e1ffc
 		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
7e1ffc
 
7e1ffc
-	if (p->version != HMAC_FORMAT_VERSION)
7e1ffc
+	if (hmac_file->version != HMAC_FORMAT_VERSION)
7e1ffc
 		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
7e1ffc
 
7e1ffc
 	return 0;
7e1ffc
 }
7e1ffc
 
7e1ffc
-/* Run an HMAC using the key above on the library binary data.
7e1ffc
- * Returns 0 on success and negative value on error.
7e1ffc
+/*
7e1ffc
+ * check_lib_hmac:
7e1ffc
+ * @entry: hmac file entry
7e1ffc
+ * @path: path to the library which hmac should be compared
7e1ffc
+ *
7e1ffc
+ * Verify that HMAC from hmac file entry matches HMAC of given library.
7e1ffc
+ *
7e1ffc
+ * Returns: 0 on successful HMAC verification, a negative error code otherwise
7e1ffc
  */
7e1ffc
-static int check_lib_hmac(struct hmac_entry *entry,
7e1ffc
-			  const char *lib, const char *sym)
7e1ffc
+static int check_lib_hmac(struct hmac_entry *entry, const char *path)
7e1ffc
 {
7e1ffc
 	int ret;
7e1ffc
 	unsigned prev;
7e1ffc
-	char path[GNUTLS_PATH_MAX];
7e1ffc
 	uint8_t hmac[HMAC_SIZE];
7e1ffc
 	gnutls_datum_t data;
7e1ffc
 
7e1ffc
-	ret = get_library_path(lib, sym, path, sizeof(path));
7e1ffc
-	if (ret < 0) {
7e1ffc
-		_gnutls_debug_log("Could not get lib path for %s: %s\n",
7e1ffc
-				  lib, gnutls_strerror(ret));
7e1ffc
-		return gnutls_assert_val(ret);
7e1ffc
-	}
7e1ffc
-
7e1ffc
 	_gnutls_debug_log("Loading: %s\n", path);
7e1ffc
 	ret = gnutls_load_file(path, &data);
7e1ffc
 	if (ret < 0) {
7e1ffc
@@ -382,28 +375,99 @@ static int check_lib_hmac(struct hmac_en
7e1ffc
 	return 0;
7e1ffc
 }
7e1ffc
 
7e1ffc
+#ifdef HAVE_DL_ITERATE_PHDR
7e1ffc
+
7e1ffc
+static int callback(struct dl_phdr_info *info, size_t size, void *data)
7e1ffc
+{
7e1ffc
+	const char *path = info->dlpi_name;
7e1ffc
+	const char *soname = last_component(path);
7e1ffc
+	struct lib_paths *paths = (struct lib_paths *)data;
7e1ffc
+
7e1ffc
+	if (!strcmp(soname, GNUTLS_LIBRARY_SONAME))
7e1ffc
+		_gnutls_str_cpy(paths->gnutls, GNUTLS_PATH_MAX, path);
7e1ffc
+	else if (!strcmp(soname, NETTLE_LIBRARY_SONAME))
7e1ffc
+		_gnutls_str_cpy(paths->nettle, GNUTLS_PATH_MAX, path);
7e1ffc
+	else if (!strcmp(soname, HOGWEED_LIBRARY_SONAME))
7e1ffc
+		_gnutls_str_cpy(paths->hogweed, GNUTLS_PATH_MAX, path);
7e1ffc
+	else if (!strcmp(soname, GMP_LIBRARY_SONAME))
7e1ffc
+		_gnutls_str_cpy(paths->gmp, GNUTLS_PATH_MAX, path);
7e1ffc
+	return 0;
7e1ffc
+}
7e1ffc
+
7e1ffc
+static int load_lib_paths(struct lib_paths *paths)
7e1ffc
+{
7e1ffc
+	memset(paths, 0, sizeof(*paths));
7e1ffc
+	dl_iterate_phdr(callback, paths);
7e1ffc
+	
7e1ffc
+	if (paths->gnutls[0] == '\0') {
7e1ffc
+		_gnutls_debug_log("Gnutls library path was not found\n");
7e1ffc
+		return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
7e1ffc
+	}
7e1ffc
+	if (paths->nettle[0] == '\0') {
7e1ffc
+		_gnutls_debug_log("Nettle library path was not found\n");
7e1ffc
+		return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
7e1ffc
+	}
7e1ffc
+	if (paths->hogweed[0] == '\0') {
7e1ffc
+		_gnutls_debug_log("Hogweed library path was not found\n");
7e1ffc
+		return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
7e1ffc
+	}
7e1ffc
+	if (paths->gmp[0] == '\0') {
7e1ffc
+		_gnutls_debug_log("Gmp library path was not found\n");
7e1ffc
+		return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
7e1ffc
+	}
7e1ffc
+
7e1ffc
+	return GNUTLS_E_SUCCESS;
7e1ffc
+}
7e1ffc
+
7e1ffc
+#else
7e1ffc
+
7e1ffc
+static int load_lib_paths(struct lib_paths *paths)
7e1ffc
+{
7e1ffc
+	(void)paths;
7e1ffc
+	_gnutls_debug_log("Function dl_iterate_phdr is missing\n");
7e1ffc
+	return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
7e1ffc
+}
7e1ffc
+
7e1ffc
+#endif /* HAVE_DL_ITERATE_PHDR */
7e1ffc
+
7e1ffc
 static int check_binary_integrity(void)
7e1ffc
 {
7e1ffc
 	int ret;
7e1ffc
-	hmac_file file;
7e1ffc
+	struct lib_paths paths;
7e1ffc
+	struct hmac_file hmac;
7e1ffc
+	char hmac_path[GNUTLS_PATH_MAX];
7e1ffc
+
7e1ffc
+	ret = load_lib_paths(&paths);
7e1ffc
+	if (ret < 0) {
7e1ffc
+		_gnutls_debug_log("Could not load library paths: %s\n",
7e1ffc
+				  gnutls_strerror(ret));
7e1ffc
+		return ret;
7e1ffc
+	}
7e1ffc
+
7e1ffc
+	ret = get_hmac_path(hmac_path, sizeof(hmac_path), paths.gnutls);
7e1ffc
+	if (ret < 0) {
7e1ffc
+		_gnutls_debug_log("Could not get hmac file path: %s\n",
7e1ffc
+				  gnutls_strerror(ret));
7e1ffc
+		return ret;
7e1ffc
+	}
7e1ffc
 
7e1ffc
-	ret = load_hmac_file(&file;;
7e1ffc
+	ret = load_hmac_file(&hmac, hmac_path);
7e1ffc
 	if (ret < 0) {
7e1ffc
 		_gnutls_debug_log("Could not load hmac file: %s\n",
7e1ffc
 				  gnutls_strerror(ret));
7e1ffc
 		return ret;
7e1ffc
 	}
7e1ffc
 
7e1ffc
-	ret = check_lib_hmac(&file.gnutls, GNUTLS_LIBRARY_NAME, "gnutls_global_init");
7e1ffc
+	ret = check_lib_hmac(&hmac.gnutls, paths.gnutls);
7e1ffc
 	if (ret < 0)
7e1ffc
 		return ret;
7e1ffc
-	ret = check_lib_hmac(&file.nettle, NETTLE_LIBRARY_NAME, "nettle_aes_set_encrypt_key");
7e1ffc
+	ret = check_lib_hmac(&hmac.nettle, paths.nettle);
7e1ffc
 	if (ret < 0)
7e1ffc
 		return ret;
7e1ffc
-	ret = check_lib_hmac(&file.hogweed, HOGWEED_LIBRARY_NAME, "nettle_mpz_sizeinbase_256_u");
7e1ffc
+	ret = check_lib_hmac(&hmac.hogweed, paths.hogweed);
7e1ffc
 	if (ret < 0)
7e1ffc
 		return ret;
7e1ffc
-	ret = check_lib_hmac(&file.gmp, GMP_LIBRARY_NAME, "__gmpz_init");
7e1ffc
+	ret = check_lib_hmac(&hmac.gmp, paths.gmp);
7e1ffc
 	if (ret < 0)
7e1ffc
 		return ret;
7e1ffc
 
7e1ffc
diff --color -ruNp a/lib/fipshmac.c b/lib/fipshmac.c
7e1ffc
--- a/lib/fipshmac.c	2022-12-15 10:59:57.461279049 +0100
7e1ffc
+++ b/lib/fipshmac.c	2022-12-15 11:00:18.832698623 +0100
7e1ffc
@@ -22,12 +22,14 @@
7e1ffc
 
7e1ffc
 #include "config.h"
7e1ffc
 
7e1ffc
-#include <gnutls/gnutls.h>
7e1ffc
-#include <gnutls/crypto.h>
7e1ffc
-#include <dlfcn.h>
7e1ffc
-#include <stdint.h>
7e1ffc
 #include <stdio.h>
7e1ffc
 #include <stdlib.h>
7e1ffc
+
7e1ffc
+#ifdef HAVE_DL_ITERATE_PHDR
7e1ffc
+
7e1ffc
+#include <gnutls/gnutls.h>
7e1ffc
+#include <gnutls/crypto.h>
7e1ffc
+#include <link.h>
7e1ffc
 #include "dirname.h"
7e1ffc
 #include "errors.h"
7e1ffc
 
7e1ffc
@@ -36,40 +38,6 @@
7e1ffc
 #define HMAC_ALGO GNUTLS_MAC_SHA256
7e1ffc
 #define HMAC_STR_SIZE (2 * HMAC_SIZE + 1)
7e1ffc
 
7e1ffc
-static int get_path(const char *lib, const char *symbol, char *path, size_t path_size)
7e1ffc
-{
7e1ffc
-	int ret;
7e1ffc
-	void *dl, *sym;
7e1ffc
-	Dl_info info;
7e1ffc
-
7e1ffc
-	dl = dlopen(lib, RTLD_LAZY);
7e1ffc
-	if (dl == NULL)
7e1ffc
-		return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
7e1ffc
-
7e1ffc
-	sym = dlsym(dl, symbol);
7e1ffc
-	if (sym == NULL) {
7e1ffc
-		ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
7e1ffc
-		goto cleanup;
7e1ffc
-	}
7e1ffc
-
7e1ffc
-	ret = dladdr(sym, &info;;
7e1ffc
-	if (ret == 0) {
7e1ffc
-		ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
7e1ffc
-		goto cleanup;
7e1ffc
-	}
7e1ffc
-
7e1ffc
-	ret = snprintf(path, path_size, "%s", info.dli_fname);
7e1ffc
-	if ((size_t)ret >= path_size) {
7e1ffc
-		ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
7e1ffc
-		goto cleanup;
7e1ffc
-	}
7e1ffc
-
7e1ffc
-	ret = 0;
7e1ffc
-cleanup:
7e1ffc
-	dlclose(dl);
7e1ffc
-	return ret;
7e1ffc
-}
7e1ffc
-
7e1ffc
 static int get_hmac(const char *path, char *hmac, size_t hmac_size)
7e1ffc
 {
7e1ffc
 	int ret;
7e1ffc
@@ -99,7 +67,7 @@ static int get_hmac(const char *path, ch
7e1ffc
 	return 0;
7e1ffc
 }
7e1ffc
 
7e1ffc
-static int print_lib_path(const char *path)
7e1ffc
+static int print_lib(const char *path, const char *soname)
7e1ffc
 {
7e1ffc
 	int ret;
7e1ffc
 	char *real_path = NULL;
7e1ffc
@@ -119,7 +87,7 @@ static int print_lib_path(const char *pa
7e1ffc
 		goto cleanup;
7e1ffc
 	}
7e1ffc
 
7e1ffc
-	printf("[%s]\n", last_component(path));
7e1ffc
+	printf("[%s]\n", soname);
7e1ffc
 	printf("path = %s\n", real_path);
7e1ffc
 	printf("hmac = %s\n", hmac);
7e1ffc
 
7e1ffc
@@ -128,25 +96,24 @@ cleanup:
7e1ffc
 	return ret;
7e1ffc
 }
7e1ffc
 
7e1ffc
-static int print_lib_dl(const char *lib, const char *sym)
7e1ffc
+static int callback(struct dl_phdr_info *info, size_t size, void *data)
7e1ffc
 {
7e1ffc
-	int ret;
7e1ffc
-	char path[GNUTLS_PATH_MAX];
7e1ffc
-
7e1ffc
-	ret = get_path(lib, sym, path, sizeof(path));
7e1ffc
-	if (ret < 0) {
7e1ffc
-		fprintf(stderr, "Could not get lib path for %s: %s\n",
7e1ffc
-                        lib, gnutls_strerror(ret));
7e1ffc
-		return ret;
7e1ffc
-	}
7e1ffc
+	const char *path = info->dlpi_name;
7e1ffc
+	const char *soname = last_component(path);
7e1ffc
 
7e1ffc
-	return print_lib_path(path);
7e1ffc
+	if (!strcmp(soname, GNUTLS_LIBRARY_SONAME))
7e1ffc
+		return print_lib(data ? data : path, soname);
7e1ffc
+	if (!strcmp(soname, NETTLE_LIBRARY_SONAME))
7e1ffc
+		return print_lib(path, soname);
7e1ffc
+	if (!strcmp(soname, HOGWEED_LIBRARY_SONAME))
7e1ffc
+		return print_lib(path, soname);
7e1ffc
+	if (!strcmp(soname, GMP_LIBRARY_SONAME))
7e1ffc
+		return print_lib(path, soname);
7e1ffc
+        return 0;
7e1ffc
 }
7e1ffc
 
7e1ffc
 int main(int argc, char **argv)
7e1ffc
 {
7e1ffc
-	int ret;
7e1ffc
-
7e1ffc
 	if (argc != 1 && argc != 2) {
7e1ffc
 		fprintf(stderr, "Usage: %s [gnutls_so_path]\n", last_component(argv[0]));
7e1ffc
 		return EXIT_FAILURE;
7e1ffc
@@ -155,24 +122,15 @@ int main(int argc, char **argv)
7e1ffc
 	printf("[global]\n");
7e1ffc
 	printf("format-version = %d\n", FORMAT_VERSION);
7e1ffc
 
7e1ffc
-	if (argc == 2)
7e1ffc
-		ret = print_lib_path(argv[1]);
7e1ffc
-	else
7e1ffc
-		ret = print_lib_dl(GNUTLS_LIBRARY_SONAME, "gnutls_global_init");
7e1ffc
-	if (ret < 0)
7e1ffc
-		return EXIT_FAILURE;
7e1ffc
+	return dl_iterate_phdr(callback, argc == 2 ? argv[1] : NULL);
7e1ffc
+}
7e1ffc
 
7e1ffc
-	ret = print_lib_dl(NETTLE_LIBRARY_SONAME, "nettle_aes_set_encrypt_key");
7e1ffc
-	if (ret < 0)
7e1ffc
-		return EXIT_FAILURE;
7e1ffc
-	
7e1ffc
-	ret = print_lib_dl(HOGWEED_LIBRARY_SONAME, "nettle_mpz_sizeinbase_256_u");
7e1ffc
-	if (ret < 0)
7e1ffc
-		return EXIT_FAILURE;
7e1ffc
-	
7e1ffc
-	ret = print_lib_dl(GMP_LIBRARY_SONAME, "__gmpz_init");
7e1ffc
-	if (ret < 0)
7e1ffc
-		return EXIT_FAILURE;
7e1ffc
+#else
7e1ffc
 
7e1ffc
-	return EXIT_SUCCESS;
7e1ffc
+int main(void)
7e1ffc
+{
7e1ffc
+	fprintf(stderr, "Function dl_iterate_phdr is missing\n");
7e1ffc
+	return EXIT_FAILURE;
7e1ffc
 }
7e1ffc
+
7e1ffc
+#endif /* HAVE_DL_ITERATE_PHDR */
7e1ffc
diff --color -ruNp a/lib/Makefile.am b/lib/Makefile.am
7e1ffc
--- a/lib/Makefile.am	2022-05-18 16:46:00.000000000 +0200
7e1ffc
+++ b/lib/Makefile.am	2022-12-15 11:00:18.789697779 +0100
7e1ffc
@@ -202,14 +202,14 @@ noinst_PROGRAMS = fipshmac
7e1ffc
 fipshmac_SOURCES = fipshmac.c
7e1ffc
 fipshmac_LDADD = libgnutls.la ../gl/libgnu.la
7e1ffc
 
7e1ffc
-hmac_files = .libs/.gnutls.hmac
7e1ffc
+hmac_file = .libs/.$(gnutls_so).hmac
7e1ffc
 
7e1ffc
-all-local: $(hmac_files)
7e1ffc
+all-local: $(hmac_file)
7e1ffc
 
7e1ffc
-.libs/.gnutls.hmac: libgnutls.la fipshmac
7e1ffc
+$(hmac_file): libgnutls.la fipshmac
7e1ffc
 	$(AM_V_GEN) $(builddir)/fipshmac > $@-t && mv $@-t $@
7e1ffc
 
7e1ffc
-CLEANFILES = $(hmac_files)
7e1ffc
+CLEANFILES = $(hmac_file)
7e1ffc
 endif
7e1ffc
 
7e1ffc
 if NEED_LTLIBDL