# ~~~
add_executable(dynamic_rendering_get_proc_addr dynamic_rendering_get_proc_addr.cpp)
-target_link_libraries(dynamic_rendering_get_proc_addr testing_dependencies)
\ No newline at end of file
+target_link_libraries(dynamic_rendering_get_proc_addr testing_dependencies)
+
+add_subdirectory(dynamic_loader_behavior)
\ No newline at end of file
--- /dev/null
+# ~~~
+# Copyright (c) 2022 Valve Corporation
+# Copyright (c) 2022 LunarG, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ~~~
+
+if (WIN32)
+ #tests use dlsym and linux specific library names
+else()
+add_library(dynamic_library_a dynamic_library.cpp)
+target_link_libraries(dynamic_library_a PUBLIC testing_framework_util)
+target_compile_definitions(dynamic_library_a PRIVATE PRINT_OUTPUT_A)
+
+add_library(dynamic_library_b dynamic_library.cpp)
+target_link_libraries(dynamic_library_b PUBLIC testing_framework_util)
+target_compile_definitions(dynamic_library_b PRIVATE PRINT_OUTPUT_B)
+
+add_library(dynamic_library_c dynamic_library.cpp)
+target_link_libraries(dynamic_library_c PUBLIC testing_framework_util)
+target_compile_definitions(dynamic_library_c PRIVATE PRINT_OUTPUT_C)
+
+add_executable(test_dynamic_linking_a_first test_dynamic_linking.cpp)
+add_executable(test_dynamic_linking_b_first test_dynamic_linking.cpp)
+add_executable(test_dynamic_linking_c_then_load test_dynamic_linking.cpp)
+target_link_libraries(test_dynamic_linking_a_first PUBLIC dynamic_library_a dynamic_library_b)
+target_link_libraries(test_dynamic_linking_b_first PUBLIC dynamic_library_b dynamic_library_a)
+target_link_libraries(test_dynamic_linking_c_then_load PUBLIC dynamic_library_c)
+target_compile_definitions(test_dynamic_linking_c_then_load PRIVATE PRINT_OUTPUT_C)
+
+
+add_executable(test_dynamic_loading test_dynamic_loading.cpp)
+target_link_libraries(test_dynamic_loading PUBLIC testing_framework_util)
+
+add_executable(test_dynamic_loading_and_linking test_dynamic_loading_and_linking.cpp)
+target_link_libraries(test_dynamic_loading_and_linking PUBLIC testing_framework_util)
+target_link_libraries(test_dynamic_loading_and_linking PUBLIC dynamic_library_a)
+endif()
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2022 The Khronos Group Inc.
+ * Copyright (c) 2022 Valve Corporation
+ * Copyright (c) 2022 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and/or associated documentation files (the "Materials"), to
+ * deal in the Materials without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Materials, and to permit persons to whom the Materials are
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included in
+ * all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
+ * USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ * Author: Charles Giessen <charles@lunarg.com>
+ */
+
+#include "dynamic_library.h"
+
+FRAMEWORK_EXPORT char do_logic() {
+#if defined(PRINT_OUTPUT_A)
+ return 'A';
+#elif defined(PRINT_OUTPUT_B)
+ return 'B';
+#elif defined(PRINT_OUTPUT_C)
+ return 'C';
+#endif
+}
+
+FRAMEWORK_EXPORT void init() {
+#if defined(PRINT_OUTPUT_A)
+ static LibraryWrapper b{};
+ static LibraryWrapper a{};
+ a = LibraryWrapper{"./libdynamic_library_a.dylib"};
+ b = LibraryWrapper{"./libdynamic_library_b.dylib"};
+#endif
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2022 The Khronos Group Inc.
+ * Copyright (c) 2022 Valve Corporation
+ * Copyright (c) 2022 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and/or associated documentation files (the "Materials"), to
+ * deal in the Materials without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Materials, and to permit persons to whom the Materials are
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included in
+ * all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
+ * USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ * Author: Charles Giessen <charles@lunarg.com>
+ */
+
+#include "test_util.h"
+
+extern "C" {
+
+using DoLogicFunction = char (*)();
+#define DO_LOGIC_FUNCTION_NAME "do_logic"
+FRAMEWORK_EXPORT char do_logic();
+
+using InitFunction = void (*)();
+#define INIT_FUNCTION_NAME "init"
+FRAMEWORK_EXPORT void init();
+};
+
+#if defined(WIN32)
+#ifndef LIB_EXT
+#define LIB_EXT "dll"
+#endif
+#elif defined(__APPLE__)
+#ifndef LIB_EXT
+#define LIB_EXT "dylib"
+#endif
+#else
+#ifndef LIB_EXT
+#define LIB_EXT "so"
+#endif
+#endif
\ No newline at end of file
--- /dev/null
+# General behavior of dynamic linkers on linux and macOS
+
+## Linking only
+
+Symbols are found based on link order. If two libraries export the same symbol,
+the first library in the link list is the library which is called.
+
+## Loading
+
+Applications cannot load symbols without specifying a library.
+Putting RTLD_NEXT in dlsym will not find any symbols even if a loaded library
+should contain them.
+An app _must_ reference a library that was loaded with `dlopen` to be able to
+get at its exported symbols through `dlsym`.
+If a loaded library loads subsequent libraries, and they all export the same
+symbols, the library which the application explicitly loaded is the one whose
+symbols are used.
+
+## Linking and Loading
+
+Applications can now use RTLD_NEXT to query symbols.
+They will always be the first linked library is that exported the symbol.
+In other words, loading a library explicitly doesn't change the behavior.
+
+Similarly, explicitly loaded libraries behave the same.
+Symbols from loaded libraries must be referenced to load the symbol, RTLD_NEXT
+doesn't work.
+If a loaded library subsequently loads another library which exports the same
+symbols, then the library the application explicitly loaded is used.
+If one of the subsequently loaded libraries happened to be linked, this doesn't
+affect the behavior when querying functions from the application loaded library.
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2022 The Khronos Group Inc.
+ * Copyright (c) 2022 Valve Corporation
+ * Copyright (c) 2022 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and/or associated documentation files (the "Materials"), to
+ * deal in the Materials without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Materials, and to permit persons to whom the Materials are
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included in
+ * all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
+ * USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ * Author: Charles Giessen <charles@lunarg.com>
+ */
+
+#include "dynamic_library.h"
+
+int main() {
+ std::cout << do_logic() << "\n";
+#if defined(PRINT_OUTPUT_C)
+ LibraryWrapper dynamic_library_c{std::string("./libdynamic_library_c.") + LIB_EXT};
+ InitFunction init = dynamic_library_c.get_symbol(INIT_FUNCTION_NAME);
+ if (init == nullptr) return 1;
+ init();
+ DoLogicFunction do_logic = dynamic_library_c.get_symbol(DO_LOGIC_FUNCTION_NAME);
+ if (do_logic == nullptr || do_logic() != 'C') return 2;
+
+ do_logic = reinterpret_cast<DoLogicFunction>(dlsym(RTLD_NEXT, DO_LOGIC_FUNCTION_NAME));
+ if (do_logic == nullptr || do_logic() != 'A') return 3;
+ std::cout << "Success\n";
+#endif
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2022 The Khronos Group Inc.
+ * Copyright (c) 2022 Valve Corporation
+ * Copyright (c) 2022 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and/or associated documentation files (the "Materials"), to
+ * deal in the Materials without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Materials, and to permit persons to whom the Materials are
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included in
+ * all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
+ * USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ * Author: Charles Giessen <charles@lunarg.com>
+ */
+
+#include "dynamic_library.h"
+
+int main() {
+ {
+ LibraryWrapper dynamic_library_a{std::string("./libdynamic_library_a.") + LIB_EXT};
+ LibraryWrapper dynamic_library_b{std::string("./libdynamic_library_b.") + LIB_EXT};
+
+ DoLogicFunction do_logic = nullptr;
+ do_logic = dynamic_library_a.get_symbol(DO_LOGIC_FUNCTION_NAME);
+ if (do_logic == nullptr || do_logic() != 'A') return 1;
+ do_logic = dynamic_library_b.get_symbol(DO_LOGIC_FUNCTION_NAME);
+ if (do_logic == nullptr || do_logic() != 'B') return 2;
+ }
+ {
+ LibraryWrapper dynamic_library_c{std::string("./libdynamic_library_c.") + LIB_EXT};
+ InitFunction init = dynamic_library_c.get_symbol(INIT_FUNCTION_NAME);
+ if (init == nullptr) return 3;
+ init();
+ DoLogicFunction do_logic = dynamic_library_c.get_symbol(DO_LOGIC_FUNCTION_NAME);
+ if (do_logic == nullptr || do_logic() != 'C') return 4;
+ // should fail because RTLD_NEXT on linux only is for dynamically *linked* libraries
+ do_logic = reinterpret_cast<DoLogicFunction>(dlsym(RTLD_NEXT, DO_LOGIC_FUNCTION_NAME));
+ if (do_logic != nullptr) return 5;
+ }
+ std::cout << "Success\n";
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2022 The Khronos Group Inc.
+ * Copyright (c) 2022 Valve Corporation
+ * Copyright (c) 2022 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and/or associated documentation files (the "Materials"), to
+ * deal in the Materials without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Materials, and to permit persons to whom the Materials are
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included in
+ * all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
+ * USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ * Author: Charles Giessen <charles@lunarg.com>
+ */
+
+#include "dynamic_library.h"
+
+int main() {
+ DoLogicFunction do_logic = nullptr;
+ do_logic = reinterpret_cast<DoLogicFunction>(dlsym(RTLD_NEXT, DO_LOGIC_FUNCTION_NAME));
+ if (do_logic == nullptr || do_logic() != 'A') return 1;
+
+ LibraryWrapper dynamic_library_c{std::string("./libdynamic_library_c.") + LIB_EXT};
+ InitFunction init = dynamic_library_c.get_symbol(INIT_FUNCTION_NAME);
+ if (init == nullptr) return 2;
+ init();
+
+ do_logic = dynamic_library_c.get_symbol(DO_LOGIC_FUNCTION_NAME);
+ if (do_logic == nullptr || do_logic() != 'C') return 3;
+
+ do_logic = reinterpret_cast<DoLogicFunction>(dlsym(RTLD_NEXT, DO_LOGIC_FUNCTION_NAME));
+ if (do_logic == nullptr || do_logic() != 'A') return 4;
+
+ std::cout << "Success\n";
+ return 0;
+}
\ No newline at end of file