107 lines
4.2 KiB
C++
107 lines
4.2 KiB
C++
/*
|
|
* Copyright (C) 2022 The Android Open Source Project
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <dlfcn.h>
|
|
#include <string>
|
|
#include <unistd.h>
|
|
|
|
namespace android::mediautils {
|
|
|
|
/**
|
|
* Returns a shared pointer to the library instance.
|
|
*
|
|
* When the last reference to the library is removed, the library will be dlclose().
|
|
*
|
|
* Notes:
|
|
* 1) The Android bionic linker always uses RTLD_GLOBAL for executable linking
|
|
* which provides the symbols for other subsequent libraries.
|
|
*
|
|
* 2) RTLD_GLOBAL like RTLD_NODELETE disables unloading of the library
|
|
* when the reference count drops to zero.
|
|
*
|
|
* 3) RTLD_LOCAL is the default in the absence of RTLD_GLOBAL.
|
|
* RTLD_LOCAL may be ignored in some situations, for example:
|
|
* https://stackoverflow.com/questions/56808889/static-objects-destructed-before-dlclose
|
|
*
|
|
* 4) We default to use RTLD_LAZY to delay symbol relocations until needed.
|
|
* This flag may be ignored by Android. RTLD_LAZY may allow
|
|
* unresolved symbols if not accessed, or symbols added later with another library
|
|
* loaded with RTLD_GLOBAL. See RTLD_NOW for comparison.
|
|
*
|
|
* 5) Avoid both staticly loading and dynamically loading the same library.
|
|
* This is known to cause double free issues as library symbols may map to
|
|
* the same location. RTLD_DEEPBIND does not appear supported as of T.
|
|
* https://stackoverflow.com/questions/34073051/when-we-are-supposed-to-use-rtld-deepbind
|
|
* https://stackoverflow.com/questions/31209693/static-library-linked-two-times
|
|
*
|
|
* Details on Android linker and debugging here:
|
|
* See: adb shell setprop debug.ld.all dlerror,dlopen,dlsym
|
|
* See: https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md
|
|
*
|
|
* Some other relevant info:
|
|
* See: Soong double_loadable:true go/double_loadable
|
|
* See: https://en.wikipedia.org/wiki/One_Definition_Rule#Summary
|
|
*
|
|
* TODO(b/228093151): Consider moving to platform/system.
|
|
*
|
|
* \param libraryName
|
|
* \param flags one of the dlopen RTLD_* flags. https://linux.die.net/man/3/dlopen
|
|
* \return shared_ptr to the library. This will be nullptr if it isn't found.
|
|
*/
|
|
std::shared_ptr<void> loadLibrary(const char *libraryName, int flags = RTLD_LAZY);
|
|
|
|
/**
|
|
* Returns a shared pointer to an object in the library
|
|
*
|
|
* The object will be a global variable or method in the library.
|
|
* The object reference counting is aliased to the library shared ptr.
|
|
*
|
|
* Note: If any internals of the shared library are exposed, for example by
|
|
* a method returning a pointer to library globals,
|
|
* or returning an object whose class definition is from the library,
|
|
* then the shared_ptr must be kept alive while such references to
|
|
* library internals exist to prevent library unloading.
|
|
*
|
|
* See usage of RTLD_NODELETE as a flag to prevent unloading.
|
|
*
|
|
* \param objectName of the library object.
|
|
* \param library a shared pointer to the library returned by loadLibrary().
|
|
* \return shared_ptr to the object, but whose refcount is
|
|
* aliased to the library shared ptr.
|
|
*/
|
|
std::shared_ptr<void> getUntypedObjectFromLibrary(
|
|
const char *objectName, const std::shared_ptr<void>& library);
|
|
|
|
/**
|
|
* Returns a shared pointer to an object in the library
|
|
*
|
|
* This is the template typed version of getUntypedObjectFromLibrary().
|
|
*
|
|
* \param objectName of the library object.
|
|
* \param library a shared pointer to the library
|
|
* \return shared_ptr to the object, but whose refcount is
|
|
* aliased to the library shared ptr.
|
|
*/
|
|
template <typename T>
|
|
std::shared_ptr<T> getObjectFromLibrary(
|
|
const char *objectName, const std::shared_ptr<void>& library) {
|
|
return std::static_pointer_cast<T>(getUntypedObjectFromLibrary(objectName, library));
|
|
}
|
|
|
|
} // android::mediautils
|