aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorRalf Habacker <ralf.habacker@freenet.de>2020-12-11 14:32:52 +0100
committerRalf Habacker <ralf.habacker@freenet.de>2021-01-17 12:51:39 +0100
commit0ea2334d46ca84c1a27bd086700f620a06401f94 (patch)
tree89e768d6c77492dee9cf6b520d562b8e35a7cee5 /tests
parent06ffb62a31f8986d1cda864bb8c3a8967d5a65fa (diff)
downloaddlfcn-win32-0ea2334d46ca84c1a27bd086700f620a06401f94.tar.gz
dlfcn-win32-0ea2334d46ca84c1a27bd086700f620a06401f94.tar.bz2
dlfcn-win32-0ea2334d46ca84c1a27bd086700f620a06401f94.zip
Add function dladdr() and associated test application test-dladdr
Diffstat (limited to 'tests')
-rw-r--r--tests/CMakeLists.txt8
-rw-r--r--tests/test-dladdr.c184
2 files changed, 192 insertions, 0 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 5fc6c44..f0871e5 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -9,9 +9,17 @@ target_link_libraries(testdll2 dl)
9 9
10add_library(testdll3 SHARED testdll3.c) 10add_library(testdll3 SHARED testdll3.c)
11set_target_properties(testdll3 PROPERTIES PREFIX "") 11set_target_properties(testdll3 PROPERTIES PREFIX "")
12add_executable(test-dladdr test-dladdr.c)
13target_link_libraries(test-dladdr dl)
14if(UNIX)
15 set_target_properties(test-dladdr PROPERTIES COMPILE_FLAGS "-Wl,--export-dynamic -fpie")
16endif()
17
18install(TARGETS test-dladdr EXPORT dlfcn-win32-targets RUNTIME DESTINATION bin)
12 19
13add_executable(t_dlfcn test.c) 20add_executable(t_dlfcn test.c)
14target_link_libraries(t_dlfcn dl) 21target_link_libraries(t_dlfcn dl)
15if(RUN_TESTS) 22if(RUN_TESTS)
16 add_test(NAME t_dlfcn COMMAND ${WRAPPER} $<TARGET_FILE:t_dlfcn> WORKING_DIRECTORY $<TARGET_FILE_DIR:t_dlfcn>) 23 add_test(NAME t_dlfcn COMMAND ${WRAPPER} $<TARGET_FILE:t_dlfcn> WORKING_DIRECTORY $<TARGET_FILE_DIR:t_dlfcn>)
24 add_test(NAME test-dladdr COMMAND ${WRAPPER} $<TARGET_FILE:test-dladdr> WORKING_DIRECTORY $<TARGET_FILE_DIR:test-dladdr>)
17endif() 25endif()
diff --git a/tests/test-dladdr.c b/tests/test-dladdr.c
new file mode 100644
index 0000000..57914cb
--- /dev/null
+++ b/tests/test-dladdr.c
@@ -0,0 +1,184 @@
1/* On Unix like os compile with "-Wl,--export-dynamic -fpie" (default with cmake) */
2
3/* required for non Windows builds, must be set in front of the first system include */
4#define _GNU_SOURCE
5
6#include <dlfcn.h>
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12static int verbose = 0;
13
14typedef enum {
15 Pass = 1,
16 PassWithoutSymbol = 2,
17 PassWithDifferentAddress = 3,
18 Fail = 0,
19 NoInfo = -1,
20} ExpectedResult;
21
22typedef void (* func) (void);
23
24static void print_dl_info( Dl_info *info, char *prefix, char *suffix )
25{
26 printf( "%sfilename: %s base: %p symbol name: '%s' addr: %p%s", prefix, info->dli_fname, info->dli_fbase, info->dli_sname, info->dli_saddr, suffix );
27}
28
29/**
30 * @brief check information returned by dladdr
31 * @param hint text describing what to test
32 * @param addr address to check
33 * @param addrsym
34 * @param expected check against expected result
35 * @return 0 check passed
36 * @return 1 check failed
37 */
38static int check_dladdr( const char *hint, void *addr, char *addrsym, ExpectedResult expected_result )
39{
40 Dl_info info;
41 int result = dladdr( addr, &info );
42 int passed = 0;
43 if (!result)
44 {
45 passed = expected_result == NoInfo || expected_result == Fail;
46 }
47 else
48 {
49 int sym_match = info.dli_sname && strcmp( addrsym, info.dli_sname ) == 0;
50 int addr_match = addr == info.dli_saddr;
51 passed = (expected_result == Pass && sym_match && addr_match)
52 || (expected_result == PassWithoutSymbol && addr_match && !info.dli_sname)
53 || (expected_result == PassWithDifferentAddress && sym_match && !addr_match)
54 || (expected_result == Fail && (!sym_match || !addr_match));
55 }
56 printf( "checking '%s' - address %p which should have symbol '%s' -> %s%s", hint, addr, addrsym, passed ? "passed" : "failed", verbose || !passed ? " " : "\n" );
57 if( verbose || !passed )
58 {
59 if( !result )
60 printf( "(could not get symbol information for address %p)\n", addr );
61 else
62 print_dl_info( &info, "(", ")\n");
63 }
64 return !passed;
65}
66
67#ifdef _WIN32
68/**
69 * @brief check address from a symbol located in a shared lilbrary
70 * @param hint text describing what to test
71 * @param libname libray to get the address from
72 * @param addrsym symbol to get the address for
73 * @param should_match result should match the given values
74 * @return 0 check passed
75 * @return 1 check failed
76 * @return 2 failed to open library
77 * @return 3 failed to get symbol address
78 */
79static int check_dladdr_by_dlopen( const char *hint, char *libname, char *sym, int should_match )
80{
81 void *library = NULL;
82 void *addr = NULL;
83 int result;
84
85 library = dlopen( libname, RTLD_GLOBAL );
86 if ( library == NULL )
87 {
88 fprintf( stderr, "could not open '%s'\n", libname );
89 return 2;
90 }
91
92 addr = dlsym( library, sym );
93 if ( !addr ) {
94 fprintf( stderr, "could not get address from library '%s' for symbol '%s'\n", libname, sym );
95 return 3;
96 }
97
98 result = check_dladdr( hint, addr, sym, should_match );
99 dlclose( library );
100
101 return result;
102}
103#endif
104
105#ifdef _WIN32
106#include <windows.h>
107#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
108/* hide warning "reclared without 'dllimport' attribute" */
109#pragma GCC diagnostic push
110#pragma GCC diagnostic ignored "-Wattributes"
111#elif defined(_MSC_VER)
112/* disable warning C4273 inconsistent dll linkage */
113#pragma warning(push)
114#pragma warning(disable: 4273)
115#endif
116/*
117 * Windows API functions decorated with WINBASEAPI are imported from iat.
118 * For testing force linking by import thunk for the following functions
119 */
120HMODULE WINAPI GetModuleHandleA (LPCSTR lpModuleName);
121SIZE_T WINAPI VirtualQuery (LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
122/* force linking by iat */
123/* WINBASEAPI, which is normally used here, can be overriden by compiler or application, so we cannot use it */
124__declspec(dllimport) HMODULE WINAPI LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
125__declspec(dllimport) int __cdecl atoi(const char *_Str);
126
127#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
128#pragma GCC diagnostic pop
129#elif defined(_MSC_VER)
130#pragma warning(pop)
131#endif
132#endif
133
134#ifdef _WIN32
135#define FailOnWin Fail
136#else
137#define FailOnWin Pass
138#endif
139
140#if defined(_WIN32) && !defined(DLFCN_WIN32_SHARED)
141#define PassOnSharedBuild Fail
142#else
143#define PassOnSharedBuild Pass
144#endif
145
146#define UNUSED(x) (void)x
147
148int main(int argc, char **argv)
149{
150 /* points to non reachable address */
151 unsigned char zero_thunk_address[6] = { 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 };
152 /* points to executable base */
153 unsigned char invalid_thunk_address[6] = { 0xFF, 0x25, 0x00, 0x00, 0x40, 0x00 };
154 /* no import thunk */
155 unsigned char no_import_thunk[6] = { 0xFF, 0x26, 0x00, 0x00, 0x40, 0x00 };
156 int result = 0;
157 UNUSED(argv);
158
159 if (argc == 2)
160 verbose = 1;
161
162 result = check_dladdr( "null pointer", (void*)0, NULL , NoInfo);
163 result |= check_dladdr( "invalid pointer", (void*)0x125, NULL , NoInfo);
164 result |= check_dladdr( "function from dl library", (void*)dladdr, "dladdr" , PassOnSharedBuild );
165 result |= check_dladdr( "function from dl library", (void*)dlopen, "dlopen", PassOnSharedBuild );
166 result |= check_dladdr( "function from glibc/msvcrt library", (void*)atoi, "atoi", Pass );
167 result |= check_dladdr( "function from executable", (void*)main, "main", FailOnWin );
168 result |= check_dladdr( "static function from executable", (void*)print_dl_info, "print_dl_info", Fail );
169 result |= check_dladdr( "address with positive offset", ((char*)atoi)+1, "atoi", PassWithDifferentAddress );
170 result |= check_dladdr( "zero address from import thunk", zero_thunk_address, "", NoInfo );
171 result |= check_dladdr( "invalid address from import thunk", invalid_thunk_address, "", NoInfo );
172 result |= check_dladdr( "no import thunk", no_import_thunk, "", NoInfo );
173
174#ifdef _WIN32
175 result |= check_dladdr( "last entry in iat", (void*)VirtualQuery, "VirtualQuery", PassWithDifferentAddress );
176
177 result |= check_dladdr ( "address through import thunk", (void*)GetModuleHandleA, "GetModuleHandleA", PassWithDifferentAddress );
178 result |= check_dladdr_by_dlopen( "address by dlsym", "kernel32.dll", "GetModuleHandleA", Pass );
179
180 result |= check_dladdr ( "address by image allocation table", (void*)LoadLibraryExA, "LoadLibraryExA", Pass );
181 result |= check_dladdr_by_dlopen( "address by dlsym", "kernel32.dll", "LoadLibraryExA", Pass );
182#endif
183 return result;
184}