• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <dlfcn.h>
20 #include <memory>
21 #include <string>
22 #include <unistd.h>
23 
24 namespace android::mediautils {
25 
26 /**
27  * Returns a shared pointer to the library instance.
28  *
29  * When the last reference to the library is removed, the library will be dlclose().
30  *
31  * Notes:
32  * 1) The Android bionic linker always uses RTLD_GLOBAL for executable linking
33  * which provides the symbols for other subsequent libraries.
34  *
35  * 2) RTLD_GLOBAL like RTLD_NODELETE disables unloading of the library
36  * when the reference count drops to zero.
37  *
38  * 3) RTLD_LOCAL is the default in the absence of RTLD_GLOBAL.
39  * RTLD_LOCAL may be ignored in some situations, for example:
40  * https://stackoverflow.com/questions/56808889/static-objects-destructed-before-dlclose
41  *
42  * 4) We default to use RTLD_LAZY to delay symbol relocations until needed.
43  * This flag may be ignored by Android.  RTLD_LAZY may allow
44  * unresolved symbols if not accessed, or symbols added later with another library
45  * loaded with RTLD_GLOBAL. See RTLD_NOW for comparison.
46  *
47  * 5) Avoid both staticly loading and dynamically loading the same library.
48  * This is known to cause double free issues as library symbols may map to
49  * the same location.  RTLD_DEEPBIND does not appear supported as of T.
50  * https://stackoverflow.com/questions/34073051/when-we-are-supposed-to-use-rtld-deepbind
51  * https://stackoverflow.com/questions/31209693/static-library-linked-two-times
52  *
53  * Details on Android linker and debugging here:
54  * See: adb shell setprop debug.ld.all dlerror,dlopen,dlsym
55  * See: https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md
56  *
57  * Some other relevant info:
58  * See: Soong double_loadable:true go/double_loadable
59  * See: https://en.wikipedia.org/wiki/One_Definition_Rule#Summary
60  *
61  * TODO(b/228093151): Consider moving to platform/system.
62  *
63  * \param libraryName
64  * \param flags one of the dlopen RTLD_* flags. https://linux.die.net/man/3/dlopen
65  * \return shared_ptr to the library. This will be nullptr if it isn't found.
66  */
67 std::shared_ptr<void> loadLibrary(const char *libraryName, int flags = RTLD_LAZY);
68 
69 /**
70  * Returns a shared pointer to an object in the library
71  *
72  * The object will be a global variable or method in the library.
73  * The object reference counting is aliased to the library shared ptr.
74  *
75  * Note: If any internals of the shared library are exposed, for example by
76  * a method returning a pointer to library globals,
77  * or returning an object whose class definition is from the library,
78  * then the shared_ptr must be kept alive while such references to
79  * library internals exist to prevent library unloading.
80  *
81  * See usage of RTLD_NODELETE as a flag to prevent unloading.
82  *
83  * \param objectName of the library object.
84  * \param library a shared pointer to the library returned by loadLibrary().
85  * \return shared_ptr to the object, but whose refcount is
86  *         aliased to the library shared ptr.
87  */
88 std::shared_ptr<void> getUntypedObjectFromLibrary(
89         const char *objectName, const std::shared_ptr<void>& library);
90 
91 /**
92  * Returns a shared pointer to an object in the library
93  *
94  * This is the template typed version of getUntypedObjectFromLibrary().
95  *
96  * \param objectName of the library object.
97  * \param library a shared pointer to the library
98  * \return shared_ptr to the object, but whose refcount is
99  *         aliased to the library shared ptr.
100  */
101 template <typename T>
getObjectFromLibrary(const char * objectName,const std::shared_ptr<void> & library)102 std::shared_ptr<T> getObjectFromLibrary(
103         const char *objectName, const std::shared_ptr<void>& library) {
104     return std::static_pointer_cast<T>(getUntypedObjectFromLibrary(objectName, library));
105 }
106 
107 } // android::mediautils
108