1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <dlfcn.h>
17 #include <string>
18
19 #include "hook.h"
20 #include "thread_private_data_ctl.h"
21 #include "wrapper_log.h"
22
23 using GetGlHookTableFunc = OHOS::GlHookTable* (*)();
24 using GetGlHookTableKeyFunc = pthread_key_t(*)();
25 template<typename Func = void*>
GetEglApi(const char * procname)26 Func GetEglApi(const char* procname)
27 {
28 #if (defined(__aarch64__) || defined(__x86_64__))
29 static const char* libEGL = "/system/lib64/platformsdk/libEGL.so";
30 #else
31 static const char* libEGL = "/system/lib/platformsdk/libEGL.so";
32 #endif
33 void* dlEglHandle = dlopen(libEGL, RTLD_NOW | RTLD_GLOBAL);
34 if (!dlEglHandle) {
35 WLOGE("Failed to load EGL library (%s) using dlopen", libEGL);
36 return nullptr;
37 }
38
39 void* func = dlsym(dlEglHandle, procname);
40 if (func) {
41 return reinterpret_cast<Func>(func);
42 };
43
44 return nullptr;
45 }
46 static GetGlHookTableFunc g_pfnGetGlHookTable = GetEglApi<GetGlHookTableFunc>("GetHookTable");
47 static GetGlHookTableKeyFunc g_pfnGetGlHookTableKey = GetEglApi<GetGlHookTableKeyFunc>("GetHookTableKey");
48
49 static pthread_key_t g_glHookTableKey = -1;
50
GetHookTable()51 __attribute__((__always_inline__))__inline__ static OHOS::GlHookTable *GetHookTable()
52 {
53 if (__builtin_expect(g_glHookTableKey != static_cast<pthread_key_t>(-1), 1)) {
54 OHOS::GlHookTable *table = static_cast<OHOS::GlHookTable *>(pthread_getspecific(g_glHookTableKey));
55 if (__builtin_expect(table != nullptr, 1)) {
56 return table;
57 }
58 }
59
60 OHOS::GlHookTable *table = g_pfnGetGlHookTable();
61 g_glHookTableKey = g_pfnGetGlHookTableKey();
62 return table;
63 }
64
65 #undef CALL_HOOK_API
66 #define CALL_HOOK_API(api, ...) \
67 do { \
68 OHOS::GlHookTable *table = GetHookTable(); \
69 if (table && table->table3.api) { \
70 table->table3.api(__VA_ARGS__); \
71 } else { \
72 WLOGE("%{public}s is invalid.", #api); \
73 } \
74 } while (0); \
75 }
76
77 #undef CALL_HOOK_API_RET
78 #define CALL_HOOK_API_RET(api, ...) do { \
79 OHOS::GlHookTable *table = GetHookTable(); \
80 if (table && table->table3.api) { \
81 return table->table3.api(__VA_ARGS__); \
82 } else { \
83 WLOGE("%{public}s is invalid.", #api); \
84 return 0; \
85 } \
86 } while (0); \
87 }
88 #undef HOOK_API_ENTRY
89 #define HOOK_API_ENTRY(r, api, ...) r api(__VA_ARGS__) { \
90
91 extern "C" {
92 #pragma GCC diagnostic ignored "-Wunused-parameter"
93 #include "gl3_hook_entries.in"
94 #pragma GCC diagnostic warning "-Wunused-parameter"
95 }
96