1 /*
2  * Copyright (C) 2019 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 #include <android-base/logging.h>
18 
19 #include <dlfcn.h>
20 
21 #include "globals.h"
22 
23 namespace art {
24 
25 #ifdef __APPLE__
26 // dlopen(3) on Linux with just an SO name will search the already
27 // opened libraries. On Darwin, we need dlopen(3) needs the SO name
28 // qualified with it's path (if the SO is not on the search path). Use
29 // linker path when compiling app. See man pages for dlopen(3) and
30 // dlyd(1).
31   static constexpr const char kLibArtBaseDebug[] = "@rpath/libartbased.dylib";
32   static constexpr const char kLibArtBaseRelease[] = "@rpath/libartbase.dylib";
33 #else
34   static constexpr const char kLibArtBaseDebug[] = "libartbased.so";
35   static constexpr const char kLibArtBaseRelease[] = "libartbase.so";
36 #endif  // __APPLE__
37 
38 // Check that we have not loaded both debug and release version of libartbase at the same time.
39 //
40 // This can be a cascade problem originating from a call to
41 // LoadLibdexfileExternal in libdexfile_support: If it was called before any ART
42 // libraries were loaded it will default to the non-debug version, which can
43 // then clash with a later load of the debug version.
44 static struct CheckLoadedBuild {
CheckLoadedBuildart::CheckLoadedBuild45   CheckLoadedBuild() {
46     bool debug_build_loaded = (dlopen(kLibArtBaseDebug, RTLD_NOW | RTLD_NOLOAD) != nullptr);
47     bool release_build_loaded = (dlopen(kLibArtBaseRelease, RTLD_NOW | RTLD_NOLOAD) != nullptr);
48     // TODO: The exit calls below are needed as CHECK would cause recursive backtracing. Fix it.
49     if (!(debug_build_loaded || release_build_loaded)) {
50       LOG(FATAL_WITHOUT_ABORT) << "Failed to dlopen "
51                                << kLibArtBaseDebug
52                                << " or "
53                                << kLibArtBaseRelease;
54       exit(1);
55     }
56     if (kIsDebugBuild && release_build_loaded) {
57       LOG(FATAL_WITHOUT_ABORT) << "Loading "
58                                << kLibArtBaseDebug
59                                << " while "
60                                << kLibArtBaseRelease
61                                << " is already loaded";
62       exit(1);
63     }
64     if (!kIsDebugBuild && debug_build_loaded) {
65       LOG(FATAL_WITHOUT_ABORT) << "Loading "
66                                << kLibArtBaseRelease
67                                << " while "
68                                << kLibArtBaseDebug
69                                << " is already loaded";
70       exit(1);
71     }
72   }
73 } g_check_loaded_build;
74 
75 }  // namespace art
76