Add regression 1030 (dl_iterate_phdr())

Adds a simple test for the dl_iterate_phdr() function.

Signed-off-by: Jerome Forissier <jerome@forissier.org>
Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
Acked-by: Etienne Carriere <etienne.carriere@linaro.org>
diff --git a/host/xtest/regression_1000.c b/host/xtest/regression_1000.c
index efe1030..dfc1399 100644
--- a/host/xtest/regression_1000.c
+++ b/host/xtest/regression_1000.c
@@ -2226,3 +2226,30 @@
 }
 ADBG_CASE_DEFINE(regression, 1029, xtest_tee_test_1029,
 		 "Test __thread attribute");
+
+static void xtest_tee_test_1030(ADBG_Case_t *c)
+{
+	TEEC_Session session = { 0 };
+	uint32_t ret_orig = 0;
+
+	if (!ADBG_EXPECT_TEEC_SUCCESS(c,
+			xtest_teec_open_session(&session, &os_test_ta_uuid,
+						NULL, &ret_orig)))
+		return;
+
+	Do_ADBG_BeginSubCase(c, "Before dlopen()");
+	ADBG_EXPECT_TEEC_SUCCESS(c,
+		TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_DL_PHDR, NULL,
+				   &ret_orig));
+	Do_ADBG_EndSubCase(c, "Before dlopen()");
+
+	Do_ADBG_BeginSubCase(c, "After dlopen()");
+	ADBG_EXPECT_TEEC_SUCCESS(c,
+		TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_DL_PHDR_DL, NULL,
+				   &ret_orig));
+	Do_ADBG_EndSubCase(c, "After dlopen()");
+
+	TEEC_CloseSession(&session);
+}
+ADBG_CASE_DEFINE(regression, 1030, xtest_tee_test_1030,
+		 "Test dl_iterate_phdr()");
diff --git a/ta/os_test/include/os_test.h b/ta/os_test/include/os_test.h
index 6f05c0d..ee17cc9 100644
--- a/ta/os_test/include/os_test.h
+++ b/ta/os_test/include/os_test.h
@@ -30,5 +30,7 @@
 TEE_Result ta_entry_client_identity(uint32_t param_types, TEE_Param params[4]);
 TEE_Result ta_entry_tls_test_main(void);
 TEE_Result ta_entry_tls_test_shlib(void);
+TEE_Result ta_entry_dl_phdr(void);
+TEE_Result ta_entry_dl_phdr_dl(void);
 
 #endif /*OS_TEST_H */
diff --git a/ta/os_test/include/ta_os_test.h b/ta/os_test/include/ta_os_test.h
index 2b8639c..89cdb02 100644
--- a/ta/os_test/include/ta_os_test.h
+++ b/ta/os_test/include/ta_os_test.h
@@ -32,5 +32,7 @@
 #define TA_OS_TEST_CMD_CLIENT_IDENTITY      20
 #define TA_OS_TEST_CMD_TLS_TEST_MAIN        21
 #define TA_OS_TEST_CMD_TLS_TEST_SHLIB       22
+#define TA_OS_TEST_CMD_DL_PHDR              23
+#define TA_OS_TEST_CMD_DL_PHDR_DL           24
 
 #endif /*TA_OS_TEST_H */
diff --git a/ta/os_test/os_test.c b/ta/os_test/os_test.c
index 11be6ec..9eca1df 100644
--- a/ta/os_test/os_test.c
+++ b/ta/os_test/os_test.c
@@ -5,6 +5,7 @@
  */
 #include <compiler.h>
 #include <dlfcn.h>
+#include <link.h>
 #include <setjmp.h>
 #include <stdint.h>
 #include <string.h>
@@ -1330,3 +1331,69 @@
 
 	return TEE_SUCCESS;
 }
+
+static int iterate_hdr_cb(struct dl_phdr_info *info __maybe_unused,
+			  size_t size __unused, void *data)
+{
+	int *count = data;
+
+	(*count)++;
+	IMSG("ELF module index: %d", *count);
+	IMSG(" dlpi_addr=%p", (void *)info->dlpi_addr);
+	IMSG(" dlpi_name='%s'", info->dlpi_name);
+	IMSG(" dlpi_phdr=%p", (void *)info->dlpi_phdr);
+	IMSG(" dlpi_phnum=%hu", info->dlpi_phnum);
+	IMSG(" dlpi_adds=%llu", info->dlpi_adds);
+	IMSG(" dlpi_subs=%llu", info->dlpi_subs);
+	IMSG(" dlpi_tls_modid=%zu", info->dlpi_tls_modid);
+	IMSG(" dlpi_tls_data=%p", info->dlpi_tls_data);
+
+	return 123;
+}
+
+static TEE_Result expect_dl_count_ge(size_t exp_count)
+{
+	int st = 0;
+	size_t count = 0;
+
+	st = dl_iterate_phdr(iterate_hdr_cb, (void *)&count);
+	if (st != 123) {
+		/*
+		 * dl_iterate_phdr() should return the last value returned by
+		 * the callback
+		 */
+		EMSG("Expected return value 123, got %d", st);
+		return TEE_ERROR_GENERIC;
+	}
+	if (count < exp_count) {
+		/*
+		 * Expect >= and not == since there could be more shared
+		 * libraries (for instance, CFG_ULIBS_SHARED=y)
+		 */
+		EMSG("Expected count > %zu, got: %zu", exp_count, count);
+		return TEE_ERROR_GENERIC;
+	}
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result ta_entry_dl_phdr(void)
+{
+	return expect_dl_count_ge(2);
+}
+
+TEE_Result ta_entry_dl_phdr_dl(void)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	void *handle = NULL;
+
+	handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba",
+			RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
+	if (!handle)
+		return TEE_ERROR_GENERIC;
+
+	res = expect_dl_count_ge(3);
+	dlclose(handle);
+
+	return res;
+}
diff --git a/ta/os_test/ta_entry.c b/ta/os_test/ta_entry.c
index 0fb7629..890d174 100644
--- a/ta/os_test/ta_entry.c
+++ b/ta/os_test/ta_entry.c
@@ -115,6 +115,12 @@
 	case TA_OS_TEST_CMD_TLS_TEST_SHLIB:
 		return ta_entry_tls_test_shlib();
 
+	case TA_OS_TEST_CMD_DL_PHDR:
+		return ta_entry_dl_phdr();
+
+	case TA_OS_TEST_CMD_DL_PHDR_DL:
+		return ta_entry_dl_phdr_dl();
+
 	default:
 		return TEE_ERROR_BAD_PARAMETERS;
 	}