Skip to content

Commit

Permalink
Load libgapii in GraphicsSpy if it has not been loaded already.
Browse files Browse the repository at this point in the history
  • Loading branch information
pmuetschard committed Feb 27, 2019
1 parent 92b89d0 commit a8ca8c3
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 8 deletions.
5 changes: 4 additions & 1 deletion gapii/vulkan/vk_graphics_spy/cc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ cc_library(
"//tools/build:darwin": [],
"//tools/build:windows": [],
# Android.
"//conditions:default": ["-ldl"],
"//conditions:default": [
"-ldl",
"-llog",
],
}),
visibility = ["//visibility:public"],
deps = ["//core/vulkan/cc/include/vulkan"],
Expand Down
50 changes: 43 additions & 7 deletions gapii/vulkan/vk_graphics_spy/cc/layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,43 @@
* limitations under the License.
*/

#include <alloca.h>
#include <android/log.h>
#include <dlfcn.h>
#include <cstring>

#include <unistd.h>
#include "vulkan/vulkan.h"

extern "C" {

#define VK_LAYER_EXPORT __attribute__((visibility("default")))
typedef void* (*eglGetProcAddress)(const char* procname);

#define PROC(name) \
static PFN_##name fn = (PFN_##name)(getProcAddress()("gapid_" #name)); \
#define LOG_DEBUG(fmt, ...) \
__android_log_print(ANDROID_LOG_DEBUG, "GAPID", fmt, ##__VA_ARGS__)

#define PROC(name) \
static PFN_##name fn = (PFN_##name)(getProcAddress("gapid_" #name)); \
if (fn != nullptr) return fn

// On android due to linker namespaces we cannot open libgapii.so,
// but since we already have it loaded, and libEGL.so hooked,
// we can use eglGetProcAddress to find the functions.
eglGetProcAddress getProcAddress() {
static void* getLibGapii();

// Up to and including Android P, libgapii, which contains the actual layer
// functions, is loaded via JDWP. Thus, use libEGL's eglGetProcAddress to find
// the functions. Starting with Q, libgapii will not be loaded via JDWP
// anymore, so we load it here if eglGetProcAddress can't find the symbol.
static void* getProcAddress(const char* name) {
static void* libegl = dlopen("libEGL.so", RTLD_NOW);
static eglGetProcAddress pa =
(eglGetProcAddress)dlsym(libegl, "eglGetProcAddress");
return pa;

LOG_DEBUG("Looking for function %s", name);
void* result = pa(name);
if (result == nullptr) {
result = dlsym(getLibGapii(), name);
}
return result;
}

VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
Expand Down Expand Up @@ -103,4 +118,25 @@ vkEnumerateDeviceExtensionProperties(VkPhysicalDevice device,
*pCount = 0;
return VK_SUCCESS;
}

static void* getLibGapii() {
static void* libgapii = nullptr;
if (libgapii == nullptr) {
Dl_info me;
dladdr((void*)GraphicsSpyGetDeviceProcAddr, &me);
if (me.dli_fname != nullptr) {
const char* base = strrchr(me.dli_fname, '/');
if (base != nullptr) {
int baseLen = base - me.dli_fname + 1;
char* name = static_cast<char*>(alloca(baseLen + 12 /*"libgapii.so"*/));
memcpy(name, me.dli_fname, baseLen);
strncpy(name + baseLen, "libgapii.so", 12);
LOG_DEBUG("Loading gapii at %s", name);
libgapii = dlopen(name, RTLD_NOW);
}
}
}
return libgapii;
}

} // extern "C"

0 comments on commit a8ca8c3

Please sign in to comment.