blob: 23fc88a3a926667db4fc202a46c1677edb26ad5d [file] [log] [blame]
Martin Stjernholmb3d2e832018-11-15 18:09:35 +00001/*
2 * Copyright (C) 2018 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
Martin Stjernholm2ccc9c32019-01-09 23:21:36 +000017#include "art_api/dex_file_support.h"
Martin Stjernholmb3d2e832018-11-15 18:09:35 +000018
Martin Stjernholmfe94b1c2019-01-31 17:40:39 +000019#include <dlfcn.h>
David Srbecky2ddb98b2021-03-09 00:37:04 +000020#include <inttypes.h>
Martin Stjernholmfe94b1c2019-01-31 17:40:39 +000021#include <mutex>
David Srbecky2ddb98b2021-03-09 00:37:04 +000022#include <sys/stat.h>
23
24#include <android-base/mapped_file.h>
25#include <android-base/stringprintf.h>
Martin Stjernholmfe94b1c2019-01-31 17:40:39 +000026
27#ifndef STATIC_LIB
28// Not used in the static lib, so avoid a dependency on this header in
29// libdexfile_support_static.
30#include <log/log.h>
31#endif
32
Martin Stjernholmb3d2e832018-11-15 18:09:35 +000033namespace art_api {
34namespace dex {
35
David Srbecky30d4d2f2021-03-24 16:11:49 +000036#if defined(STATIC_LIB)
37#define DEFINE_ADEX_FILE_SYMBOL(DLFUNC) decltype(DLFUNC)* g_##DLFUNC = DLFUNC;
Martin Stjernholmfe94b1c2019-01-31 17:40:39 +000038#else
David Srbecky30d4d2f2021-03-24 16:11:49 +000039#define DEFINE_ADEX_FILE_SYMBOL(DLFUNC) decltype(DLFUNC)* g_##DLFUNC = nullptr;
Martin Stjernholmfe94b1c2019-01-31 17:40:39 +000040#endif
David Srbecky30d4d2f2021-03-24 16:11:49 +000041FOR_EACH_ADEX_FILE_SYMBOL(DEFINE_ADEX_FILE_SYMBOL)
42#undef DEFINE_ADEX_FILE_SYMBOL
Martin Stjernholmfe94b1c2019-01-31 17:40:39 +000043
David Srbecky30d4d2f2021-03-24 16:11:49 +000044bool TryLoadLibdexfile([[maybe_unused]] std::string* err_msg) {
Martin Stjernholmfe94b1c2019-01-31 17:40:39 +000045#if defined(STATIC_LIB)
46 // Nothing to do here since all function pointers are initialised statically.
Martin Stjernholm44901122019-10-04 01:03:48 +010047 return true;
Martin Stjernholmfe94b1c2019-01-31 17:40:39 +000048#elif defined(NO_DEXFILE_SUPPORT)
Martin Stjernholm44901122019-10-04 01:03:48 +010049 *err_msg = "Dex file support not available.";
50 return false;
Martin Stjernholmfe94b1c2019-01-31 17:40:39 +000051#else
Martin Stjernholm44901122019-10-04 01:03:48 +010052 // Use a plain old mutex since we want to try again if loading fails (to set
53 // err_msg, if nothing else).
54 static std::mutex load_mutex;
55 static bool is_loaded = false;
56 std::lock_guard<std::mutex> lock(load_mutex);
57
58 if (!is_loaded) {
59 // Check which version is already loaded to avoid loading both debug and
60 // release builds. We might also be backtracing from separate process, in
61 // which case neither is loaded.
Martin Stjernholmd3e9ff32021-03-16 00:44:25 +000062 const char* so_name = "libdexfiled.so";
David Srbecky7711c352019-04-10 17:50:12 +010063 void* handle = dlopen(so_name, RTLD_NOLOAD | RTLD_NOW | RTLD_NODELETE);
64 if (handle == nullptr) {
Martin Stjernholmd3e9ff32021-03-16 00:44:25 +000065 so_name = "libdexfile.so";
David Srbecky7711c352019-04-10 17:50:12 +010066 handle = dlopen(so_name, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
67 }
Martin Stjernholm44901122019-10-04 01:03:48 +010068 if (handle == nullptr) {
69 *err_msg = dlerror();
70 return false;
71 }
Martin Stjernholmfe94b1c2019-01-31 17:40:39 +000072
David Srbecky30d4d2f2021-03-24 16:11:49 +000073#define RESOLVE_ADEX_FILE_SYMBOL(DLFUNC) \
74 auto DLFUNC##_ptr = reinterpret_cast<decltype(DLFUNC)*>(dlsym(handle, #DLFUNC)); \
75 if (DLFUNC##_ptr == nullptr) { \
Martin Stjernholm44901122019-10-04 01:03:48 +010076 *err_msg = dlerror(); \
77 return false; \
78 }
David Srbecky30d4d2f2021-03-24 16:11:49 +000079FOR_EACH_ADEX_FILE_SYMBOL(RESOLVE_ADEX_FILE_SYMBOL)
80#undef RESOLVE_ADEX_FILE_SYMBOL
Martin Stjernholmfe94b1c2019-01-31 17:40:39 +000081
David Srbecky30d4d2f2021-03-24 16:11:49 +000082#define SET_ADEX_FILE_SYMBOL(DLFUNC) g_##DLFUNC = DLFUNC##_ptr;
83 FOR_EACH_ADEX_FILE_SYMBOL(SET_ADEX_FILE_SYMBOL);
84#undef SET_ADEX_FILE_SYMBOL
Martin Stjernholm44901122019-10-04 01:03:48 +010085
86 is_loaded = true;
87 }
88
89 return is_loaded;
Martin Stjernholmfe94b1c2019-01-31 17:40:39 +000090#endif // !defined(NO_DEXFILE_SUPPORT) && !defined(STATIC_LIB)
91}
92
David Srbecky30d4d2f2021-03-24 16:11:49 +000093void LoadLibdexfile() {
Martin Stjernholm44901122019-10-04 01:03:48 +010094#ifndef STATIC_LIB
David Srbecky30d4d2f2021-03-24 16:11:49 +000095 if (std::string err_msg; !TryLoadLibdexfile(&err_msg)) {
Martin Stjernholm44901122019-10-04 01:03:48 +010096 LOG_ALWAYS_FATAL("%s", err_msg.c_str());
97 }
98#endif
99}
100
Martin Stjernholmb3d2e832018-11-15 18:09:35 +0000101} // namespace dex
102} // namespace art_api