blob: 951351c3200cc540073a76b1ca705f295124992f [file] [log] [blame]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001/*
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07002 * Copyright (C) 2008 The Android Open Source Project
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08003 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
Dmitriy Ivanov19133522015-06-02 17:36:54 -070029#include <android/api-level.h>
Elliott Hughes46882792012-08-03 16:49:39 -070030#include <errno.h>
31#include <fcntl.h>
Elliott Hughes0266ae52014-02-10 17:46:57 -080032#include <inttypes.h>
Elliott Hughes46882792012-08-03 16:49:39 -070033#include <pthread.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080034#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
Elliott Hughes46882792012-08-03 16:49:39 -070037#include <sys/mman.h>
Dmitriy Ivanovec18ce02014-11-09 19:27:20 -080038#include <sys/param.h>
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -070039#include <sys/vfs.h>
Elliott Hughes46882792012-08-03 16:49:39 -070040#include <unistd.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080041
Dmitriy Ivanov0d150942014-08-22 12:25:04 -070042#include <new>
Dmitriy Ivanovd165f562015-03-23 18:43:02 -070043#include <string>
Dmitriy Ivanovb4827502015-09-28 16:38:31 -070044#include <unordered_map>
Dmitriy Ivanovd165f562015-03-23 18:43:02 -070045#include <vector>
Dmitriy Ivanov0d150942014-08-22 12:25:04 -070046
Logan Chiendd184722018-05-08 20:17:26 +080047#include <android-base/properties.h>
Tom Cherryb8ab6182017-04-05 16:20:29 -070048#include <android-base/scopeguard.h>
49
Christopher Ferris7a3681e2017-04-24 17:48:32 -070050#include <async_safe/log.h>
51
Elliott Hughes46882792012-08-03 16:49:39 -070052// Private C library headers.
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080053
54#include "linker.h"
Dmitriy Ivanovc9ce70d2015-03-10 15:30:26 -070055#include "linker_block_allocator.h"
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070056#include "linker_cfi.h"
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -080057#include "linker_config.h"
Dimitry Ivanov6b788ee2016-02-17 16:08:03 -080058#include "linker_gdb_support.h"
Dimitry Ivanov48ec2882016-08-04 11:50:36 -070059#include "linker_globals.h"
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080060#include "linker_debug.h"
Dimitry Ivanov769b33f2016-07-21 11:33:40 -070061#include "linker_dlwarning.h"
Dimitry Ivanov3f660572016-09-09 10:00:39 -070062#include "linker_main.h"
Dimitry Ivanovb943f302016-08-03 16:00:10 -070063#include "linker_namespaces.h"
Dmitriy Ivanov18870d32015-04-22 13:10:04 -070064#include "linker_sleb128.h"
David 'Digit' Turner23363ed2012-06-18 18:13:49 +020065#include "linker_phdr.h"
Dmitriy Ivanovcefef7d2015-01-08 23:30:15 -080066#include "linker_relocs.h"
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -080067#include "linker_reloc_iterators.h"
Dmitriy Ivanova1feb112015-10-01 18:41:57 -070068#include "linker_utils.h"
tony.ys_liub4474402015-07-29 18:00:22 +080069
dimitryfe1b27c2017-08-11 14:43:21 +020070#include "android-base/macros.h"
Elliott Hughes939a7e02015-12-04 15:27:46 -080071#include "android-base/strings.h"
Dimitry Ivanovb996d602016-07-11 18:11:39 -070072#include "android-base/stringprintf.h"
Simon Baldwinaef71952015-01-16 13:22:54 +000073#include "ziparchive/zip_archive.h"
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080074
Elliott Hughes1801db32015-06-08 18:04:00 -070075// Override macros to use C++ style casts.
Dmitriy Ivanov1649e7e2015-01-22 16:04:25 -080076#undef ELF_ST_TYPE
77#define ELF_ST_TYPE(x) (static_cast<uint32_t>(x) & 0xf)
78
dimitry06016f22018-01-05 11:39:28 +010079static std::unordered_map<void*, size_t> g_dso_handle_counters;
80
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -070081static android_namespace_t* g_anonymous_namespace = &g_default_namespace;
Jiyong Park01de74e2017-04-03 23:10:37 +090082static std::unordered_map<std::string, android_namespace_t*> g_exported_namespaces;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -070083
Dmitriy Ivanov600bc3c2015-03-10 15:43:50 -070084static LinkerTypeAllocator<soinfo> g_soinfo_allocator;
85static LinkerTypeAllocator<LinkedListEntry<soinfo>> g_soinfo_links_allocator;
Magnus Malmbornba98d922012-09-12 13:00:55 +020086
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -070087static LinkerTypeAllocator<android_namespace_t> g_namespace_allocator;
Dimitry Ivanovaca299a2016-04-11 12:42:58 -070088static LinkerTypeAllocator<LinkedListEntry<android_namespace_t>> g_namespace_list_allocator;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -070089
dimitryfe1b27c2017-08-11 14:43:21 +020090static const char* const kLdConfigArchFilePath = "/system/etc/ld.config." ABI_STRING ".txt";
91
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -080092static const char* const kLdConfigFilePath = "/system/etc/ld.config.txt";
Logan Chiendd184722018-05-08 20:17:26 +080093static const char* const kLdConfigVndkLiteFilePath = "/system/etc/ld.config.vndk_lite.txt";
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -080094
Elliott Hughes4eeb1f12013-10-25 17:38:02 -070095#if defined(__LP64__)
Dimitry Ivanova1446972017-03-17 00:08:23 +000096static const char* const kSystemLibDir = "/system/lib64";
Alin Jerpelea074a9fd2017-09-25 17:47:49 +020097static const char* const kOdmLibDir = "/odm/lib64";
Dimitry Ivanova1446972017-03-17 00:08:23 +000098static const char* const kVendorLibDir = "/vendor/lib64";
Vishwath Mohan4113def2017-03-29 15:31:34 -070099static const char* const kAsanSystemLibDir = "/data/asan/system/lib64";
Alin Jerpelea074a9fd2017-09-25 17:47:49 +0200100static const char* const kAsanOdmLibDir = "/data/asan/odm/lib64";
Vishwath Mohan4113def2017-03-29 15:31:34 -0700101static const char* const kAsanVendorLibDir = "/data/asan/vendor/lib64";
Elliott Hughes011bc0b2013-10-08 14:27:10 -0700102#else
Dimitry Ivanova1446972017-03-17 00:08:23 +0000103static const char* const kSystemLibDir = "/system/lib";
Alin Jerpelea074a9fd2017-09-25 17:47:49 +0200104static const char* const kOdmLibDir = "/odm/lib";
Dimitry Ivanova1446972017-03-17 00:08:23 +0000105static const char* const kVendorLibDir = "/vendor/lib";
Vishwath Mohan4113def2017-03-29 15:31:34 -0700106static const char* const kAsanSystemLibDir = "/data/asan/system/lib";
Alin Jerpelea074a9fd2017-09-25 17:47:49 +0200107static const char* const kAsanOdmLibDir = "/data/asan/odm/lib";
Vishwath Mohan4113def2017-03-29 15:31:34 -0700108static const char* const kAsanVendorLibDir = "/data/asan/vendor/lib";
Elliott Hughes011bc0b2013-10-08 14:27:10 -0700109#endif
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -0700110
Vishwath Mohan4113def2017-03-29 15:31:34 -0700111static const char* const kAsanLibDirPrefix = "/data/asan";
112
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -0700113static const char* const kDefaultLdPaths[] = {
114 kSystemLibDir,
Alin Jerpelea074a9fd2017-09-25 17:47:49 +0200115 kOdmLibDir,
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -0700116 kVendorLibDir,
Dmitriy Ivanov851135b2014-08-29 12:02:36 -0700117 nullptr
Elliott Hughes124fae92012-10-31 14:20:03 -0700118};
David Bartleybc3a5c22009-06-02 18:27:28 -0700119
Evgenii Stepanovd640b222015-07-10 17:54:01 -0700120static const char* const kAsanDefaultLdPaths[] = {
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -0700121 kAsanSystemLibDir,
122 kSystemLibDir,
Alin Jerpelea074a9fd2017-09-25 17:47:49 +0200123 kAsanOdmLibDir,
124 kOdmLibDir,
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -0700125 kAsanVendorLibDir,
126 kVendorLibDir,
Evgenii Stepanovd640b222015-07-10 17:54:01 -0700127 nullptr
128};
129
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -0700130// Is ASAN enabled?
131static bool g_is_asan = false;
132
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -0700133static CFIShadowWriter g_cfi_shadow;
134
135CFIShadowWriter* get_cfi_shadow() {
136 return &g_cfi_shadow;
137}
138
Dimitry Ivanov769b33f2016-07-21 11:33:40 -0700139static bool is_system_library(const std::string& realpath) {
140 for (const auto& dir : g_default_namespace.get_default_library_paths()) {
141 if (file_is_in_dir(realpath, dir)) {
142 return true;
143 }
144 }
145 return false;
146}
147
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -0700148// Checks if the file exists and not a directory.
149static bool file_exists(const char* path) {
Dimitry Ivanov4cf70242016-08-11 11:11:52 -0700150 struct stat s;
151
152 if (stat(path, &s) != 0) {
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -0700153 return false;
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -0700154 }
Dimitry Ivanov4cf70242016-08-11 11:11:52 -0700155
156 return S_ISREG(s.st_mode);
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -0700157}
Dimitry Ivanov769b33f2016-07-21 11:33:40 -0700158
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -0800159static std::string resolve_soname(const std::string& name) {
160 // We assume that soname equals to basename here
161
162 // TODO(dimitry): consider having honest absolute-path -> soname resolution
163 // note that since we might end up refusing to load this library because
164 // it is not in shared libs list we need to get the soname without actually loading
165 // the library.
166 //
167 // On the other hand there are several places where we already assume that
168 // soname == basename in particular for any not-loaded library mentioned
169 // in DT_NEEDED list.
170 return basename(name.c_str());
171}
172
173static bool maybe_accessible_via_namespace_links(android_namespace_t* ns, const char* name) {
174 std::string soname = resolve_soname(name);
175 for (auto& ns_link : ns->linked_namespaces()) {
176 if (ns_link.is_accessible(soname.c_str())) {
177 return true;
178 }
179 }
180
181 return false;
182}
183
Dimitry Ivanov769b33f2016-07-21 11:33:40 -0700184// TODO(dimitry): The grey-list is a workaround for http://b/26394120 ---
185// gradually remove libraries from this list until it is gone.
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -0800186static bool is_greylisted(android_namespace_t* ns, const char* name, const soinfo* needed_by) {
Dimitry Ivanov769b33f2016-07-21 11:33:40 -0700187 static const char* const kLibraryGreyList[] = {
188 "libandroid_runtime.so",
189 "libbinder.so",
190 "libcrypto.so",
191 "libcutils.so",
192 "libexpat.so",
193 "libgui.so",
194 "libmedia.so",
195 "libnativehelper.so",
196 "libskia.so",
197 "libssl.so",
198 "libstagefright.so",
199 "libsqlite.so",
200 "libui.so",
201 "libutils.so",
202 "libvorbisidec.so",
203 nullptr
204 };
205
Elliott Hughes5bc78c82016-11-16 11:35:43 -0800206 // If you're targeting N, you don't get the greylist.
Elliott Hughes9e27e582017-03-23 17:42:49 -0700207 if (g_greylist_disabled || get_application_target_sdk_version() >= __ANDROID_API_N__) {
Dimitry Ivanov769b33f2016-07-21 11:33:40 -0700208 return false;
209 }
210
211 // if the library needed by a system library - implicitly assume it
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -0800212 // is greylisted unless it is in the list of shared libraries for one or
213 // more linked namespaces
Dimitry Ivanov769b33f2016-07-21 11:33:40 -0700214 if (needed_by != nullptr && is_system_library(needed_by->get_realpath())) {
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -0800215 return !maybe_accessible_via_namespace_links(ns, name);
Dimitry Ivanov769b33f2016-07-21 11:33:40 -0700216 }
217
218 // if this is an absolute path - make sure it points to /system/lib(64)
219 if (name[0] == '/' && dirname(name) == kSystemLibDir) {
220 // and reduce the path to basename
221 name = basename(name);
222 }
223
224 for (size_t i = 0; kLibraryGreyList[i] != nullptr; ++i) {
225 if (strcmp(name, kLibraryGreyList[i]) == 0) {
226 return true;
227 }
228 }
229
230 return false;
231}
232// END OF WORKAROUND
233
Dmitriy Ivanovd165f562015-03-23 18:43:02 -0700234static std::vector<std::string> g_ld_preload_names;
Elliott Hughesa4aafd12014-01-13 16:37:47 -0800235
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800236static bool g_anonymous_namespace_initialized;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700237
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800238#if STATS
Elliott Hughesbedfe382012-08-14 14:07:59 -0700239struct linker_stats_t {
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700240 int count[kRelocMax];
Elliott Hughesbedfe382012-08-14 14:07:59 -0700241};
242
243static linker_stats_t linker_stats;
244
Dmitriy Ivanov114ff692015-01-14 11:36:38 -0800245void count_relocation(RelocationKind kind) {
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700246 ++linker_stats.count[kind];
Elliott Hughesbedfe382012-08-14 14:07:59 -0700247}
248#else
Dmitriy Ivanov114ff692015-01-14 11:36:38 -0800249void count_relocation(RelocationKind) {
Elliott Hughesbedfe382012-08-14 14:07:59 -0700250}
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800251#endif
252
253#if COUNT_PAGES
Dmitriy Ivanov114ff692015-01-14 11:36:38 -0800254uint32_t bitmask[4096];
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800255#endif
256
Elliott Hughesbedfe382012-08-14 14:07:59 -0700257static void notify_gdb_of_load(soinfo* info) {
Dimitry Ivanove97d8ed2016-03-01 15:55:56 -0800258 if (info->is_linker() || info->is_main_executable()) {
259 // gdb already knows about the linker and the main executable.
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700260 return;
261 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800262
Dimitry Ivanov6b788ee2016-02-17 16:08:03 -0800263 link_map* map = &(info->link_map_head);
Nicolas Geoffray0fa54102016-02-18 09:31:24 +0000264
Dimitry Ivanov6b788ee2016-02-17 16:08:03 -0800265 map->l_addr = info->load_bias;
266 // link_map l_name field is not const.
267 map->l_name = const_cast<char*>(info->get_realpath());
268 map->l_ld = info->dynamic;
Nicolas Geoffray0fa54102016-02-18 09:31:24 +0000269
Dimitry Ivanove97d8ed2016-03-01 15:55:56 -0800270 CHECK(map->l_name != nullptr);
271 CHECK(map->l_name[0] != '\0');
272
Dimitry Ivanov6b788ee2016-02-17 16:08:03 -0800273 notify_gdb_of_load(map);
Iliyan Malchev5e12d7e2009-03-24 19:02:00 -0700274}
275
Elliott Hughesbedfe382012-08-14 14:07:59 -0700276static void notify_gdb_of_unload(soinfo* info) {
Dimitry Ivanov6b788ee2016-02-17 16:08:03 -0800277 notify_gdb_of_unload(&(info->link_map_head));
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800278}
279
Dmitriy Ivanovd59e5002014-05-09 09:10:14 -0700280LinkedListEntry<soinfo>* SoinfoListAllocator::alloc() {
281 return g_soinfo_links_allocator.alloc();
282}
283
284void SoinfoListAllocator::free(LinkedListEntry<soinfo>* entry) {
285 g_soinfo_links_allocator.free(entry);
286}
287
Dimitry Ivanovaca299a2016-04-11 12:42:58 -0700288LinkedListEntry<android_namespace_t>* NamespaceListAllocator::alloc() {
289 return g_namespace_list_allocator.alloc();
290}
291
292void NamespaceListAllocator::free(LinkedListEntry<android_namespace_t>* entry) {
293 g_namespace_list_allocator.free(entry);
294}
295
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700296soinfo* soinfo_alloc(android_namespace_t* ns, const char* name,
297 struct stat* file_stat, off64_t file_offset,
298 uint32_t rtld_flags) {
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700299 if (strlen(name) >= PATH_MAX) {
Elliott Hughes7b0af7a2017-09-15 16:09:22 -0700300 async_safe_fatal("library name \"%s\" too long", name);
Magnus Malmbornba98d922012-09-12 13:00:55 +0200301 }
302
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700303 TRACE("name %s: allocating soinfo for ns=%p", name, ns);
304
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700305 soinfo* si = new (g_soinfo_allocator.alloc()) soinfo(ns, name, file_stat,
306 file_offset, rtld_flags);
Dmitriy Ivanovd59e5002014-05-09 09:10:14 -0700307
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700308 solist_add_soinfo(si);
Magnus Malmbornba98d922012-09-12 13:00:55 +0200309
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -0700310 si->generate_handle();
311 ns->add_soinfo(si);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700312
Elliott Hughesca0c11b2013-03-12 10:40:45 -0700313 TRACE("name %s: allocated soinfo @ %p", name, si);
Magnus Malmbornba98d922012-09-12 13:00:55 +0200314 return si;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800315}
316
Elliott Hughesfaf05ba2014-02-11 16:59:37 -0800317static void soinfo_free(soinfo* si) {
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700318 if (si == nullptr) {
319 return;
320 }
321
322 if (si->base != 0 && si->size != 0) {
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800323 if (!si->is_mapped_by_caller()) {
324 munmap(reinterpret_cast<void*>(si->base), si->size);
325 } else {
326 // remap the region as PROT_NONE, MAP_ANONYMOUS | MAP_NORESERVE
327 mmap(reinterpret_cast<void*>(si->base), si->size, PROT_NONE,
328 MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
329 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700330 }
331
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -0700332 TRACE("name %s: freeing soinfo @ %p", si->get_realpath(), si);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700333
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700334 if (!solist_remove_soinfo(si)) {
dimitry965d06d2017-11-28 16:03:07 +0100335 async_safe_fatal("soinfo=%p is not in soinfo_list (double unload?)", si);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700336 }
Elliott Hughes46882792012-08-03 16:49:39 -0700337
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700338 // clear links to/from si
339 si->remove_all_links();
Dmitriy Ivanovd59e5002014-05-09 09:10:14 -0700340
Dmitriy Ivanov609f11b2015-07-08 15:26:46 -0700341 si->~soinfo();
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700342 g_soinfo_allocator.free(si);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800343}
344
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700345static void parse_path(const char* path, const char* delimiters,
346 std::vector<std::string>* resolved_paths) {
347 std::vector<std::string> paths;
348 split_path(path, delimiters, &paths);
349 resolve_paths(paths, resolved_paths);
350}
351
Elliott Hughescade4c32012-12-20 14:42:14 -0800352static void parse_LD_LIBRARY_PATH(const char* path) {
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700353 std::vector<std::string> ld_libary_paths;
354 parse_path(path, ":", &ld_libary_paths);
355 g_default_namespace.set_ld_library_paths(std::move(ld_libary_paths));
Elliott Hughescade4c32012-12-20 14:42:14 -0800356}
357
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700358static bool realpath_fd(int fd, std::string* realpath) {
359 std::vector<char> buf(PATH_MAX), proc_self_fd(PATH_MAX);
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700360 async_safe_format_buffer(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd);
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700361 if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) {
Dimitry Ivanov769b33f2016-07-21 11:33:40 -0700362 PRINT("readlink(\"%s\") failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700363 return false;
364 }
365
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700366 *realpath = &buf[0];
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700367 return true;
368}
369
Elliott Hughes4eeb1f12013-10-25 17:38:02 -0700370#if defined(__arm__)
Elliott Hughes46882792012-08-03 16:49:39 -0700371
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700372// For a given PC, find the .so that it belongs to.
373// Returns the base address of the .ARM.exidx section
374// for that .so, and the number of 8-byte entries
375// in that section (via *pcount).
376//
377// Intended to be called by libc's __gnu_Unwind_Find_exidx().
Dimitry Ivanovd9e427c2016-11-22 16:55:25 -0800378_Unwind_Ptr do_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) {
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700379 for (soinfo* si = solist_get_head(); si != 0; si = si->next) {
Elliott Hughesf2c6ad62017-04-21 10:25:56 -0700380 if ((pc >= si->base) && (pc < (si->base + si->size))) {
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700381 *pcount = si->ARM_exidx_count;
Dmitriy Ivanov1649e7e2015-01-22 16:04:25 -0800382 return reinterpret_cast<_Unwind_Ptr>(si->ARM_exidx);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800383 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700384 }
385 *pcount = 0;
Elliott Hughesf2c6ad62017-04-21 10:25:56 -0700386 return 0;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800387}
Elliott Hughes46882792012-08-03 16:49:39 -0700388
Christopher Ferris24053a42013-08-19 17:45:09 -0700389#endif
Elliott Hughes46882792012-08-03 16:49:39 -0700390
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700391// Here, we only have to provide a callback to iterate across all the
392// loaded libraries. gcc_eh does the rest.
Dmitriy Ivanov7271caf2015-06-29 14:48:25 -0700393int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700394 int rv = 0;
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700395 for (soinfo* si = solist_get_head(); si != nullptr; si = si->next) {
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700396 dl_phdr_info dl_info;
397 dl_info.dlpi_addr = si->link_map_head.l_addr;
398 dl_info.dlpi_name = si->link_map_head.l_name;
399 dl_info.dlpi_phdr = si->phdr;
400 dl_info.dlpi_phnum = si->phnum;
401 rv = cb(&dl_info, sizeof(dl_phdr_info), data);
402 if (rv != 0) {
403 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800404 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700405 }
406 return rv;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800407}
Elliott Hughes46882792012-08-03 16:49:39 -0700408
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800409
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700410bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi,
Dimitry Ivanovb943f302016-08-03 16:00:10 -0700411 soinfo** si_found_in, const soinfo_list_t& global_group,
412 const soinfo_list_t& local_group, const ElfW(Sym)** symbol) {
Dmitriy Ivanovec18ce02014-11-09 19:27:20 -0800413 SymbolName symbol_name(name);
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700414 const ElfW(Sym)* s = nullptr;
Iliyan Malchev6ed80c82009-09-28 19:38:04 -0700415
Dmitriy Ivanov96bc37f2014-09-29 12:10:36 -0700416 /* "This element's presence in a shared object library alters the dynamic linker's
417 * symbol resolution algorithm for references within the library. Instead of starting
418 * a symbol search with the executable file, the dynamic linker starts from the shared
419 * object itself. If the shared object fails to supply the referenced symbol, the
420 * dynamic linker then searches the executable file and other shared objects as usual."
421 *
422 * http://www.sco.com/developers/gabi/2012-12-31/ch5.dynamic.html
423 *
424 * Note that this is unlikely since static linker avoids generating
425 * relocations for -Bsymbolic linked dynamic executables.
426 */
Dmitriy Ivanovd225a5e2014-08-28 14:12:12 -0700427 if (si_from->has_DT_SYMBOLIC) {
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -0700428 DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si_from->get_realpath(), name);
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700429 if (!si_from->find_symbol_by_name(symbol_name, vi, &s)) {
430 return false;
431 }
432
Dmitriy Ivanov8f61d992014-09-16 14:31:06 -0700433 if (s != nullptr) {
Dmitriy Ivanovd225a5e2014-08-28 14:12:12 -0700434 *si_found_in = si_from;
Dmitriy Ivanov96bc37f2014-09-29 12:10:36 -0700435 }
436 }
437
Dmitriy Ivanovd225a5e2014-08-28 14:12:12 -0700438 // 1. Look for it in global_group
439 if (s == nullptr) {
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700440 bool error = false;
Dmitriy Ivanovd225a5e2014-08-28 14:12:12 -0700441 global_group.visit([&](soinfo* global_si) {
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700442 DEBUG("%s: looking up %s in %s (from global group)",
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -0700443 si_from->get_realpath(), name, global_si->get_realpath());
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700444 if (!global_si->find_symbol_by_name(symbol_name, vi, &s)) {
445 error = true;
446 return false;
447 }
448
Dmitriy Ivanov96bc37f2014-09-29 12:10:36 -0700449 if (s != nullptr) {
Dmitriy Ivanovd225a5e2014-08-28 14:12:12 -0700450 *si_found_in = global_si;
451 return false;
Dmitriy Ivanov96bc37f2014-09-29 12:10:36 -0700452 }
Dmitriy Ivanovc2048942014-08-29 10:15:25 -0700453
Dmitriy Ivanovd225a5e2014-08-28 14:12:12 -0700454 return true;
455 });
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700456
457 if (error) {
458 return false;
459 }
Dmitriy Ivanov96bc37f2014-09-29 12:10:36 -0700460 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700461
Dmitriy Ivanovd225a5e2014-08-28 14:12:12 -0700462 // 2. Look for it in the local group
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700463 if (s == nullptr) {
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700464 bool error = false;
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700465 local_group.visit([&](soinfo* local_si) {
Dmitriy Ivanovd225a5e2014-08-28 14:12:12 -0700466 if (local_si == si_from && si_from->has_DT_SYMBOLIC) {
Dmitriy Ivanove47b3f82014-10-23 14:19:07 -0700467 // we already did this - skip
468 return true;
469 }
470
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -0700471 DEBUG("%s: looking up %s in %s (from local group)",
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -0700472 si_from->get_realpath(), name, local_si->get_realpath());
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700473 if (!local_si->find_symbol_by_name(symbol_name, vi, &s)) {
474 error = true;
475 return false;
476 }
477
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700478 if (s != nullptr) {
Dmitriy Ivanovd225a5e2014-08-28 14:12:12 -0700479 *si_found_in = local_si;
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700480 return false;
481 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700482
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700483 return true;
484 });
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700485
486 if (error) {
487 return false;
488 }
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700489 }
490
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700491 if (s != nullptr) {
492 TRACE_TYPE(LOOKUP, "si %s sym %s s->st_value = %p, "
493 "found in %s, base = %p, load bias = %p",
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -0700494 si_from->get_realpath(), name, reinterpret_cast<void*>(s->st_value),
495 (*si_found_in)->get_realpath(), reinterpret_cast<void*>((*si_found_in)->base),
Dmitriy Ivanovd225a5e2014-08-28 14:12:12 -0700496 reinterpret_cast<void*>((*si_found_in)->load_bias));
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -0700497 }
Iliyan Malchev6ed80c82009-09-28 19:38:04 -0700498
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700499 *symbol = s;
500 return true;
Iliyan Malchev6ed80c82009-09-28 19:38:04 -0700501}
502
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700503ProtectedDataGuard::ProtectedDataGuard() {
504 if (ref_count_++ == 0) {
505 protect_data(PROT_READ | PROT_WRITE);
506 }
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700507
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700508 if (ref_count_ == 0) { // overflow
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700509 async_safe_fatal("Too many nested calls to dlopen()");
Dmitriy Ivanov279a22f2015-01-23 12:03:53 -0800510 }
Dimitry Ivanov68e6c032017-02-01 12:55:11 -0800511}
Dmitriy Ivanov279a22f2015-01-23 12:03:53 -0800512
Dimitry Ivanov68e6c032017-02-01 12:55:11 -0800513ProtectedDataGuard::~ProtectedDataGuard() {
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700514 if (--ref_count_ == 0) {
515 protect_data(PROT_READ);
Dmitriy Ivanov279a22f2015-01-23 12:03:53 -0800516 }
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700517}
Dmitriy Ivanov279a22f2015-01-23 12:03:53 -0800518
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700519void ProtectedDataGuard::protect_data(int protection) {
520 g_soinfo_allocator.protect_all(protection);
521 g_soinfo_links_allocator.protect_all(protection);
522 g_namespace_allocator.protect_all(protection);
523 g_namespace_list_allocator.protect_all(protection);
524}
Dmitriy Ivanov279a22f2015-01-23 12:03:53 -0800525
526size_t ProtectedDataGuard::ref_count_ = 0;
527
Dmitriy Ivanov0cd83eb2014-09-01 16:15:52 -0700528// Each size has it's own allocator.
529template<size_t size>
530class SizeBasedAllocator {
531 public:
532 static void* alloc() {
533 return allocator_.alloc();
534 }
Dmitriy Ivanov4bea4982014-08-29 14:01:48 -0700535
Dmitriy Ivanov0cd83eb2014-09-01 16:15:52 -0700536 static void free(void* ptr) {
537 allocator_.free(ptr);
538 }
Dmitriy Ivanov4bea4982014-08-29 14:01:48 -0700539
Dmitriy Ivanov0cd83eb2014-09-01 16:15:52 -0700540 private:
541 static LinkerBlockAllocator allocator_;
542};
543
544template<size_t size>
545LinkerBlockAllocator SizeBasedAllocator<size>::allocator_(size);
546
547template<typename T>
548class TypeBasedAllocator {
549 public:
550 static T* alloc() {
551 return reinterpret_cast<T*>(SizeBasedAllocator<sizeof(T)>::alloc());
552 }
553
554 static void free(T* ptr) {
555 SizeBasedAllocator<sizeof(T)>::free(ptr);
556 }
557};
558
Dmitriy Ivanov14669a92014-09-05 16:42:53 -0700559class LoadTask {
560 public:
561 struct deleter_t {
562 void operator()(LoadTask* t) {
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -0700563 t->~LoadTask();
Dmitriy Ivanov14669a92014-09-05 16:42:53 -0700564 TypeBasedAllocator<LoadTask>::free(t);
565 }
566 };
567
Dmitriy Ivanov14669a92014-09-05 16:42:53 -0700568 static deleter_t deleter;
569
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800570 static LoadTask* create(const char* name,
571 soinfo* needed_by,
Jiyong Park02586a22017-05-20 01:01:24 +0900572 android_namespace_t* start_from,
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -0700573 std::unordered_map<const soinfo*, ElfReader>* readers_map) {
Dmitriy Ivanov14669a92014-09-05 16:42:53 -0700574 LoadTask* ptr = TypeBasedAllocator<LoadTask>::alloc();
Jiyong Park02586a22017-05-20 01:01:24 +0900575 return new (ptr) LoadTask(name, needed_by, start_from, readers_map);
Dmitriy Ivanov14669a92014-09-05 16:42:53 -0700576 }
577
578 const char* get_name() const {
579 return name_;
580 }
581
582 soinfo* get_needed_by() const {
583 return needed_by_;
584 }
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -0700585
586 soinfo* get_soinfo() const {
587 return si_;
588 }
589
590 void set_soinfo(soinfo* si) {
591 si_ = si;
592 }
593
594 off64_t get_file_offset() const {
595 return file_offset_;
596 }
597
598 void set_file_offset(off64_t offset) {
599 file_offset_ = offset;
600 }
601
602 int get_fd() const {
603 return fd_;
604 }
605
606 void set_fd(int fd, bool assume_ownership) {
607 fd_ = fd;
608 close_fd_ = assume_ownership;
609 }
610
611 const android_dlextinfo* get_extinfo() const {
612 return extinfo_;
613 }
614
615 void set_extinfo(const android_dlextinfo* extinfo) {
616 extinfo_ = extinfo;
617 }
618
Dimitry Ivanov769b33f2016-07-21 11:33:40 -0700619 bool is_dt_needed() const {
620 return is_dt_needed_;
621 }
622
623 void set_dt_needed(bool is_dt_needed) {
624 is_dt_needed_ = is_dt_needed;
625 }
626
Jiyong Park02586a22017-05-20 01:01:24 +0900627 // returns the namespace from where we need to start loading this.
628 const android_namespace_t* get_start_from() const {
629 return start_from_;
630 }
631
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -0700632 const ElfReader& get_elf_reader() const {
633 CHECK(si_ != nullptr);
634 return (*elf_readers_map_)[si_];
635 }
636
637 ElfReader& get_elf_reader() {
638 CHECK(si_ != nullptr);
639 return (*elf_readers_map_)[si_];
640 }
641
642 std::unordered_map<const soinfo*, ElfReader>* get_readers_map() {
643 return elf_readers_map_;
644 }
645
646 bool read(const char* realpath, off64_t file_size) {
647 ElfReader& elf_reader = get_elf_reader();
648 return elf_reader.Read(realpath, fd_, file_offset_, file_size);
649 }
650
651 bool load() {
652 ElfReader& elf_reader = get_elf_reader();
653 if (!elf_reader.Load(extinfo_)) {
654 return false;
655 }
656
657 si_->base = elf_reader.load_start();
658 si_->size = elf_reader.load_size();
Dimitry Ivanovf45b0e92016-01-15 11:13:35 -0800659 si_->set_mapped_by_caller(elf_reader.is_mapped_by_caller());
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -0700660 si_->load_bias = elf_reader.load_bias();
661 si_->phnum = elf_reader.phdr_count();
662 si_->phdr = elf_reader.loaded_phdr();
663
664 return true;
665 }
666
Dmitriy Ivanov14669a92014-09-05 16:42:53 -0700667 private:
Dimitry Ivanov7d429d32017-02-01 15:28:52 -0800668 LoadTask(const char* name,
669 soinfo* needed_by,
Jiyong Park02586a22017-05-20 01:01:24 +0900670 android_namespace_t* start_from,
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -0700671 std::unordered_map<const soinfo*, ElfReader>* readers_map)
672 : name_(name), needed_by_(needed_by), si_(nullptr),
Dimitry Ivanov769b33f2016-07-21 11:33:40 -0700673 fd_(-1), close_fd_(false), file_offset_(0), elf_readers_map_(readers_map),
Jiyong Park02586a22017-05-20 01:01:24 +0900674 is_dt_needed_(false), start_from_(start_from) {}
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -0700675
676 ~LoadTask() {
677 if (fd_ != -1 && close_fd_) {
678 close(fd_);
679 }
680 }
Dmitriy Ivanov14669a92014-09-05 16:42:53 -0700681
682 const char* name_;
683 soinfo* needed_by_;
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -0700684 soinfo* si_;
685 const android_dlextinfo* extinfo_;
686 int fd_;
687 bool close_fd_;
688 off64_t file_offset_;
689 std::unordered_map<const soinfo*, ElfReader>* elf_readers_map_;
Dimitry Ivanov769b33f2016-07-21 11:33:40 -0700690 // TODO(dimitry): needed by workaround for http://b/26394120 (the grey-list)
691 bool is_dt_needed_;
692 // END OF WORKAROUND
Jiyong Park02586a22017-05-20 01:01:24 +0900693 const android_namespace_t* const start_from_;
Dmitriy Ivanov14669a92014-09-05 16:42:53 -0700694
695 DISALLOW_IMPLICIT_CONSTRUCTORS(LoadTask);
696};
697
Ningsheng Jiane93be992014-09-16 15:22:10 +0800698LoadTask::deleter_t LoadTask::deleter;
699
Dmitriy Ivanov0cd83eb2014-09-01 16:15:52 -0700700template <typename T>
701using linked_list_t = LinkedList<T, TypeBasedAllocator<LinkedListEntry<T>>>;
702
703typedef linked_list_t<soinfo> SoinfoLinkedList;
Dmitriy Ivanov14669a92014-09-05 16:42:53 -0700704typedef linked_list_t<const char> StringLinkedList;
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -0700705typedef std::vector<LoadTask*> LoadTaskList;
Dmitriy Ivanov0cd83eb2014-09-01 16:15:52 -0700706
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800707enum walk_action_result_t : uint32_t {
708 kWalkStop = 0,
709 kWalkContinue = 1,
710 kWalkSkip = 2
711};
Dmitriy Ivanovaa0f2bd2014-07-28 17:32:20 -0700712
Christopher R. Palmer37425572017-04-08 22:40:01 +0200713#ifdef LD_SHIM_LIBS
714// g_ld_all_shim_libs maintains the references to memory as it used
715// in the soinfo structures and in the g_active_shim_libs list.
716
717static std::vector<ShimDescriptor> g_ld_all_shim_libs;
718
719// g_active_shim_libs are all shim libs that are still eligible
720// to be loaded. We must remove a shim lib from the list before
721// we load the library to avoid recursive loops (load shim libA
722// for libB where libA also links against libB).
723static linked_list_t<const ShimDescriptor> g_active_shim_libs;
724
725static void reset_g_active_shim_libs(void) {
726 g_active_shim_libs.clear();
727 for (const auto& pair : g_ld_all_shim_libs) {
728 g_active_shim_libs.push_back(&pair);
729 }
730}
731
732void parse_LD_SHIM_LIBS(const char* path) {
733 g_ld_all_shim_libs.clear();
734 if (path != nullptr) {
735 // We have historically supported ':' as well as ' ' in LD_SHIM_LIBS.
736 for (const auto& pair : android::base::Split(path, " :")) {
737 std::vector<std::string> pieces = android::base::Split(pair, "|");
738 if (pieces.size() != 2) continue;
739 char resolved_path[PATH_MAX];
740 if (realpath(pieces[0].c_str(), resolved_path) != nullptr) {
741 auto desc = std::pair<std::string, std::string>(std::string(resolved_path), pieces[1]);
742 g_ld_all_shim_libs.push_back(desc);
743 }
744 }
745 }
746 reset_g_active_shim_libs();
747}
748
749std::vector<const ShimDescriptor*> shim_matching_pairs(const char* path) {
750 std::vector<const ShimDescriptor*> matched_pairs;
751
752 g_active_shim_libs.for_each([&](const ShimDescriptor* a_pair) {
753 if (a_pair->first == path) {
754 matched_pairs.push_back(a_pair);
755 }
756 });
757
758 g_active_shim_libs.remove_if([&](const ShimDescriptor* a_pair) {
759 return a_pair->first == path;
760 });
761
762 return matched_pairs;
763}
764#endif
765
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700766// This function walks down the tree of soinfo dependencies
767// in breadth-first order and
768// * calls action(soinfo* si) for each node, and
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800769// * terminates walk if action returns kWalkStop
770// * skips children of the node if action
771// return kWalkSkip
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700772//
773// walk_dependencies_tree returns false if walk was terminated
774// by the action and true otherwise.
775template<typename F>
dimitry965d06d2017-11-28 16:03:07 +0100776static bool walk_dependencies_tree(soinfo* root_soinfo, F action) {
Dmitriy Ivanov0cd83eb2014-09-01 16:15:52 -0700777 SoinfoLinkedList visit_list;
778 SoinfoLinkedList visited;
779
dimitry965d06d2017-11-28 16:03:07 +0100780 visit_list.push_back(root_soinfo);
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700781
782 soinfo* si;
783 while ((si = visit_list.pop_front()) != nullptr) {
784 if (visited.contains(si)) {
Dmitriy Ivanov042426b2014-08-12 21:02:13 -0700785 continue;
786 }
787
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800788 walk_action_result_t result = action(si);
789
790 if (result == kWalkStop) {
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700791 return false;
Dmitriy Ivanovaa0f2bd2014-07-28 17:32:20 -0700792 }
793
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700794 visited.push_back(si);
795
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800796 if (result != kWalkSkip) {
797 si->get_children().for_each([&](soinfo* child) {
798 visit_list.push_back(child);
799 });
800 }
Dmitriy Ivanovaa0f2bd2014-07-28 17:32:20 -0700801 }
802
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700803 return true;
804}
805
806
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800807static const ElfW(Sym)* dlsym_handle_lookup(android_namespace_t* ns,
808 soinfo* root,
809 soinfo* skip_until,
810 soinfo** found,
811 SymbolName& symbol_name,
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -0800812 const version_info* vi) {
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700813 const ElfW(Sym)* result = nullptr;
Dmitriy Ivanov697bd9f2015-05-12 11:12:27 -0700814 bool skip_lookup = skip_until != nullptr;
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700815
dimitry965d06d2017-11-28 16:03:07 +0100816 walk_dependencies_tree(root, [&](soinfo* current_soinfo) {
Dmitriy Ivanov697bd9f2015-05-12 11:12:27 -0700817 if (skip_lookup) {
818 skip_lookup = current_soinfo != skip_until;
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800819 return kWalkContinue;
820 }
821
822 if (!ns->is_accessible(current_soinfo)) {
823 return kWalkSkip;
Dmitriy Ivanov697bd9f2015-05-12 11:12:27 -0700824 }
825
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -0800826 if (!current_soinfo->find_symbol_by_name(symbol_name, vi, &result)) {
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700827 result = nullptr;
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800828 return kWalkStop;
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700829 }
830
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700831 if (result != nullptr) {
832 *found = current_soinfo;
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800833 return kWalkStop;
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700834 }
835
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800836 return kWalkContinue;
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -0700837 });
838
839 return result;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800840}
841
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -0800842static const ElfW(Sym)* dlsym_linear_lookup(android_namespace_t* ns,
843 const char* name,
844 const version_info* vi,
845 soinfo** found,
846 soinfo* caller,
847 void* handle);
848
Dmitriy Ivanov697bd9f2015-05-12 11:12:27 -0700849// This is used by dlsym(3). It performs symbol lookup only within the
850// specified soinfo object and its dependencies in breadth first order.
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800851static const ElfW(Sym)* dlsym_handle_lookup(soinfo* si,
852 soinfo** found,
853 const char* name,
854 const version_info* vi) {
Dmitriy Ivanovf439b5a2015-05-30 13:04:39 -0700855 // According to man dlopen(3) and posix docs in the case when si is handle
856 // of the main executable we need to search not only in the executable and its
857 // dependencies but also in all libraries loaded with RTLD_GLOBAL.
858 //
859 // Since RTLD_GLOBAL is always set for the main executable and all dt_needed shared
860 // libraries and they are loaded in breath-first (correct) order we can just execute
861 // dlsym(RTLD_DEFAULT, ...); instead of doing two stage lookup.
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700862 if (si == solist_get_somain()) {
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -0800863 return dlsym_linear_lookup(&g_default_namespace, name, vi, found, nullptr, RTLD_DEFAULT);
Dmitriy Ivanovf439b5a2015-05-30 13:04:39 -0700864 }
865
Dmitriy Ivanov697bd9f2015-05-12 11:12:27 -0700866 SymbolName symbol_name(name);
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800867 // note that the namespace is not the namespace associated with caller_addr
868 // we use ns associated with root si intentionally here. Using caller_ns
869 // causes problems when user uses dlopen_ext to open a library in the separate
870 // namespace and then calls dlsym() on the handle.
871 return dlsym_handle_lookup(si->get_primary_namespace(), si, nullptr, found, symbol_name, vi);
Dmitriy Ivanov697bd9f2015-05-12 11:12:27 -0700872}
873
Brian Carlstromd4ee82d2013-02-28 15:58:45 -0800874/* This is used by dlsym(3) to performs a global symbol lookup. If the
875 start value is null (for RTLD_DEFAULT), the search starts at the
876 beginning of the global solist. Otherwise the search starts at the
877 specified soinfo (for RTLD_NEXT).
Iliyan Malchev6ed80c82009-09-28 19:38:04 -0700878 */
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -0800879static const ElfW(Sym)* dlsym_linear_lookup(android_namespace_t* ns,
880 const char* name,
881 const version_info* vi,
882 soinfo** found,
883 soinfo* caller,
884 void* handle) {
Dmitriy Ivanovec18ce02014-11-09 19:27:20 -0800885 SymbolName symbol_name(name);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800886
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -0700887 auto& soinfo_list = ns->soinfo_list();
888 auto start = soinfo_list.begin();
Dmitriy Ivanov76ac1ac2015-04-01 14:45:10 -0700889
890 if (handle == RTLD_NEXT) {
Dmitriy Ivanovb96ac412015-05-22 12:34:42 -0700891 if (caller == nullptr) {
Dmitriy Ivanov76ac1ac2015-04-01 14:45:10 -0700892 return nullptr;
893 } else {
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -0700894 auto it = soinfo_list.find(caller);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700895 CHECK (it != soinfo_list.end());
896 start = ++it;
Dmitriy Ivanov76ac1ac2015-04-01 14:45:10 -0700897 }
Elliott Hughescade4c32012-12-20 14:42:14 -0800898 }
899
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700900 const ElfW(Sym)* s = nullptr;
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -0700901 for (auto it = start, end = soinfo_list.end(); it != end; ++it) {
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -0700902 soinfo* si = *it;
Dmitriy Ivanov19133522015-06-02 17:36:54 -0700903 // Do not skip RTLD_LOCAL libraries in dlsym(RTLD_DEFAULT, ...)
Elliott Hughes5bc78c82016-11-16 11:35:43 -0800904 // if the library is opened by application with target api level < M.
Dmitriy Ivanov19133522015-06-02 17:36:54 -0700905 // See http://b/21565766
Elliott Hughes5bc78c82016-11-16 11:35:43 -0800906 if ((si->get_rtld_flags() & RTLD_GLOBAL) == 0 &&
907 si->get_target_sdk_version() >= __ANDROID_API_M__) {
Dmitriy Ivanove8ba50f2014-09-15 17:00:10 -0700908 continue;
909 }
910
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -0800911 if (!si->find_symbol_by_name(symbol_name, vi, &s)) {
Dmitriy Ivanov2a815362015-04-09 13:42:33 -0700912 return nullptr;
913 }
914
Dmitriy Ivanov851135b2014-08-29 12:02:36 -0700915 if (s != nullptr) {
Elliott Hughescade4c32012-12-20 14:42:14 -0800916 *found = si;
917 break;
Matt Fischer1698d9e2009-12-31 12:17:56 -0600918 }
Elliott Hughescade4c32012-12-20 14:42:14 -0800919 }
Matt Fischer1698d9e2009-12-31 12:17:56 -0600920
dimitry153168c2018-02-20 16:51:41 +0100921 // If not found - use dlsym_handle_lookup for caller's local_group
922 if (s == nullptr && caller != nullptr) {
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -0800923 soinfo* local_group_root = caller->get_local_group_root();
924
925 return dlsym_handle_lookup(local_group_root->get_primary_namespace(),
926 local_group_root,
927 (handle == RTLD_NEXT) ? caller : nullptr,
928 found,
929 symbol_name,
930 vi);
Dmitriy Ivanov76ac1ac2015-04-01 14:45:10 -0700931 }
932
Dmitriy Ivanov851135b2014-08-29 12:02:36 -0700933 if (s != nullptr) {
Elliott Hughesc00f2cb2013-10-04 17:01:33 -0700934 TRACE_TYPE(LOOKUP, "%s s->st_value = %p, found->base = %p",
935 name, reinterpret_cast<void*>(s->st_value), reinterpret_cast<void*>((*found)->base));
Elliott Hughescade4c32012-12-20 14:42:14 -0800936 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800937
Elliott Hughescade4c32012-12-20 14:42:14 -0800938 return s;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800939}
940
Kito Chengfa8c05d2013-03-12 14:58:06 +0800941soinfo* find_containing_library(const void* p) {
Elliott Hughes0266ae52014-02-10 17:46:57 -0800942 ElfW(Addr) address = reinterpret_cast<ElfW(Addr)>(p);
Dimitry Ivanov3f660572016-09-09 10:00:39 -0700943 for (soinfo* si = solist_get_head(); si != nullptr; si = si->next) {
Kito Chengfa8c05d2013-03-12 14:58:06 +0800944 if (address >= si->base && address - si->base < si->size) {
945 return si;
Matt Fischere2a8b1f2009-12-31 12:17:40 -0600946 }
Kito Chengfa8c05d2013-03-12 14:58:06 +0800947 }
Dmitriy Ivanov851135b2014-08-29 12:02:36 -0700948 return nullptr;
Matt Fischere2a8b1f2009-12-31 12:17:40 -0600949}
950
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700951class ZipArchiveCache {
952 public:
953 ZipArchiveCache() {}
954 ~ZipArchiveCache();
955
956 bool get_or_open(const char* zip_path, ZipArchiveHandle* handle);
957 private:
958 DISALLOW_COPY_AND_ASSIGN(ZipArchiveCache);
959
960 std::unordered_map<std::string, ZipArchiveHandle> cache_;
961};
962
963bool ZipArchiveCache::get_or_open(const char* zip_path, ZipArchiveHandle* handle) {
964 std::string key(zip_path);
965
966 auto it = cache_.find(key);
967 if (it != cache_.end()) {
968 *handle = it->second;
969 return true;
970 }
971
972 int fd = TEMP_FAILURE_RETRY(open(zip_path, O_RDONLY | O_CLOEXEC));
973 if (fd == -1) {
974 return false;
975 }
976
977 if (OpenArchiveFd(fd, "", handle) != 0) {
978 // invalid zip-file (?)
Yabin Cui722072d2016-03-21 17:10:12 -0700979 CloseArchive(handle);
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700980 close(fd);
981 return false;
982 }
983
984 cache_[key] = *handle;
985 return true;
986}
987
988ZipArchiveCache::~ZipArchiveCache() {
Dmitriy Ivanov5dce8942015-10-13 12:14:16 -0700989 for (const auto& it : cache_) {
Dmitriy Ivanovb4827502015-09-28 16:38:31 -0700990 CloseArchive(it.second);
991 }
992}
993
994static int open_library_in_zipfile(ZipArchiveCache* zip_archive_cache,
Dmitriy Ivanova1feb112015-10-01 18:41:57 -0700995 const char* const input_path,
996 off64_t* file_offset, std::string* realpath) {
997 std::string normalized_path;
998 if (!normalize_path(input_path, &normalized_path)) {
999 return -1;
1000 }
1001
1002 const char* const path = normalized_path.c_str();
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07001003 TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
Simon Baldwinaef71952015-01-16 13:22:54 +00001004
Dmitriy Ivanov402a7502015-06-09 13:46:51 -07001005 // Treat an '!/' separator inside a path as the separator between the name
Simon Baldwinaef71952015-01-16 13:22:54 +00001006 // of the zip file on disk and the subdirectory to search within it.
Dmitriy Ivanov402a7502015-06-09 13:46:51 -07001007 // For example, if path is "foo.zip!/bar/bas/x.so", then we search for
Simon Baldwinaef71952015-01-16 13:22:54 +00001008 // "bar/bas/x.so" within "foo.zip".
Dmitriy Ivanova1feb112015-10-01 18:41:57 -07001009 const char* const separator = strstr(path, kZipFileSeparator);
Simon Baldwinaef71952015-01-16 13:22:54 +00001010 if (separator == nullptr) {
1011 return -1;
Elliott Hughes124fae92012-10-31 14:20:03 -07001012 }
Simon Baldwinaef71952015-01-16 13:22:54 +00001013
1014 char buf[512];
1015 if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) {
1016 PRINT("Warning: ignoring very long library path: %s", path);
1017 return -1;
1018 }
1019
1020 buf[separator - path] = '\0';
1021
1022 const char* zip_path = buf;
Dmitriy Ivanov402a7502015-06-09 13:46:51 -07001023 const char* file_path = &buf[separator - path + 2];
Simon Baldwinaef71952015-01-16 13:22:54 +00001024 int fd = TEMP_FAILURE_RETRY(open(zip_path, O_RDONLY | O_CLOEXEC));
1025 if (fd == -1) {
1026 return -1;
1027 }
1028
1029 ZipArchiveHandle handle;
Dmitriy Ivanovb4827502015-09-28 16:38:31 -07001030 if (!zip_archive_cache->get_or_open(zip_path, &handle)) {
Simon Baldwinaef71952015-01-16 13:22:54 +00001031 // invalid zip-file (?)
1032 close(fd);
1033 return -1;
1034 }
1035
Simon Baldwinaef71952015-01-16 13:22:54 +00001036 ZipEntry entry;
1037
Yusuke Sato56f40fb2015-06-25 14:56:07 -07001038 if (FindEntry(handle, ZipString(file_path), &entry) != 0) {
Simon Baldwinaef71952015-01-16 13:22:54 +00001039 // Entry was not found.
1040 close(fd);
1041 return -1;
1042 }
1043
1044 // Check if it is properly stored
1045 if (entry.method != kCompressStored || (entry.offset % PAGE_SIZE) != 0) {
1046 close(fd);
1047 return -1;
1048 }
1049
1050 *file_offset = entry.offset;
Dmitriy Ivanova1feb112015-10-01 18:41:57 -07001051
1052 if (realpath_fd(fd, realpath)) {
1053 *realpath += separator;
1054 } else {
1055 PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
1056 normalized_path.c_str());
1057 *realpath = normalized_path;
1058 }
1059
Simon Baldwinaef71952015-01-16 13:22:54 +00001060 return fd;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001061}
1062
Dmitriy Ivanovd165f562015-03-23 18:43:02 -07001063static bool format_path(char* buf, size_t buf_size, const char* path, const char* name) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -07001064 int n = async_safe_format_buffer(buf, buf_size, "%s/%s", path, name);
Dmitriy Ivanovd165f562015-03-23 18:43:02 -07001065 if (n < 0 || n >= static_cast<int>(buf_size)) {
1066 PRINT("Warning: ignoring very long library path: %s/%s", path, name);
1067 return false;
1068 }
Simon Baldwinaef71952015-01-16 13:22:54 +00001069
Dmitriy Ivanovd165f562015-03-23 18:43:02 -07001070 return true;
1071}
1072
Dmitriy Ivanovb4827502015-09-28 16:38:31 -07001073static int open_library_on_paths(ZipArchiveCache* zip_archive_cache,
1074 const char* name, off64_t* file_offset,
Dmitriy Ivanova1feb112015-10-01 18:41:57 -07001075 const std::vector<std::string>& paths,
1076 std::string* realpath) {
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001077 for (const auto& path : paths) {
Dmitriy Ivanovd165f562015-03-23 18:43:02 -07001078 char buf[512];
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001079 if (!format_path(buf, sizeof(buf), path.c_str(), name)) {
Dmitriy Ivanovd165f562015-03-23 18:43:02 -07001080 continue;
1081 }
1082
1083 int fd = -1;
Dmitriy Ivanov730ed9d2015-07-16 04:52:06 -07001084 if (strstr(buf, kZipFileSeparator) != nullptr) {
Dmitriy Ivanova1feb112015-10-01 18:41:57 -07001085 fd = open_library_in_zipfile(zip_archive_cache, buf, file_offset, realpath);
Simon Baldwinaef71952015-01-16 13:22:54 +00001086 }
1087
1088 if (fd == -1) {
1089 fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC));
1090 if (fd != -1) {
1091 *file_offset = 0;
Dmitriy Ivanova1feb112015-10-01 18:41:57 -07001092 if (!realpath_fd(fd, realpath)) {
1093 PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.", buf);
1094 *realpath = buf;
1095 }
Simon Baldwinaef71952015-01-16 13:22:54 +00001096 }
1097 }
Dmitriy Ivanovd165f562015-03-23 18:43:02 -07001098
1099 if (fd != -1) {
1100 return fd;
1101 }
Simon Baldwinaef71952015-01-16 13:22:54 +00001102 }
1103
Dmitriy Ivanovd165f562015-03-23 18:43:02 -07001104 return -1;
Simon Baldwinaef71952015-01-16 13:22:54 +00001105}
1106
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001107static int open_library(android_namespace_t* ns,
1108 ZipArchiveCache* zip_archive_cache,
Dmitriy Ivanovb4827502015-09-28 16:38:31 -07001109 const char* name, soinfo *needed_by,
Dmitriy Ivanova1feb112015-10-01 18:41:57 -07001110 off64_t* file_offset, std::string* realpath) {
Jiyong Park02586a22017-05-20 01:01:24 +09001111 TRACE("[ opening %s at namespace %s]", name, ns->get_name());
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001112
Elliott Hughes124fae92012-10-31 14:20:03 -07001113 // If the name contains a slash, we should attempt to open it directly and not search the paths.
Dmitriy Ivanov851135b2014-08-29 12:02:36 -07001114 if (strchr(name, '/') != nullptr) {
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001115 int fd = -1;
1116
Dmitriy Ivanov730ed9d2015-07-16 04:52:06 -07001117 if (strstr(name, kZipFileSeparator) != nullptr) {
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001118 fd = open_library_in_zipfile(zip_archive_cache, name, file_offset, realpath);
1119 }
1120
1121 if (fd == -1) {
1122 fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CLOEXEC));
Simon Baldwinaef71952015-01-16 13:22:54 +00001123 if (fd != -1) {
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001124 *file_offset = 0;
1125 if (!realpath_fd(fd, realpath)) {
1126 PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.", name);
1127 *realpath = name;
1128 }
Simon Baldwinaef71952015-01-16 13:22:54 +00001129 }
1130 }
1131
Dmitriy Ivanove44fffd2015-03-17 17:12:18 -07001132 return fd;
Elliott Hughes124fae92012-10-31 14:20:03 -07001133 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001134
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001135 // Otherwise we try LD_LIBRARY_PATH first, and fall back to the default library path
1136 int fd = open_library_on_paths(zip_archive_cache, name, file_offset, ns->get_ld_library_paths(), realpath);
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001137 if (fd == -1 && needed_by != nullptr) {
Dmitriy Ivanova1feb112015-10-01 18:41:57 -07001138 fd = open_library_on_paths(zip_archive_cache, name, file_offset, needed_by->get_dt_runpath(), realpath);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001139 // Check if the library is accessible
1140 if (fd != -1 && !ns->is_accessible(*realpath)) {
1141 fd = -1;
1142 }
Evgenii Stepanov68650822015-06-10 13:38:39 -07001143 }
Dmitriy Ivanovb4827502015-09-28 16:38:31 -07001144
Elliott Hughes124fae92012-10-31 14:20:03 -07001145 if (fd == -1) {
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001146 fd = open_library_on_paths(zip_archive_cache, name, file_offset, ns->get_default_library_paths(), realpath);
Elliott Hughes124fae92012-10-31 14:20:03 -07001147 }
Dmitriy Ivanovb4827502015-09-28 16:38:31 -07001148
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07001149 // TODO(dimitry): workaround for http://b/26394120 (the grey-list)
Jiyong Park37b91af2017-05-05 22:07:05 +09001150 if (fd == -1 && ns->is_greylist_enabled() && is_greylisted(ns, name, needed_by)) {
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07001151 // try searching for it on default_namespace default_library_path
1152 fd = open_library_on_paths(zip_archive_cache, name, file_offset,
1153 g_default_namespace.get_default_library_paths(), realpath);
1154 }
1155 // END OF WORKAROUND
1156
Elliott Hughes124fae92012-10-31 14:20:03 -07001157 return fd;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001158}
1159
Dimitry Ivanov3f660572016-09-09 10:00:39 -07001160const char* fix_dt_needed(const char* dt_needed, const char* sopath __unused) {
Dmitriy Ivanovd974e882015-05-27 18:29:41 -07001161#if !defined(__LP64__)
1162 // Work around incorrect DT_NEEDED entries for old apps: http://b/21364029
Elliott Hughes9076b0c2018-02-28 11:29:45 -08001163 int app_target_api_level = get_application_target_sdk_version();
1164 if (app_target_api_level < __ANDROID_API_M__) {
Dmitriy Ivanovd974e882015-05-27 18:29:41 -07001165 const char* bname = basename(dt_needed);
1166 if (bname != dt_needed) {
Elliott Hughes9076b0c2018-02-28 11:29:45 -08001167 DL_WARN_documented_change(__ANDROID_API_M__,
1168 "invalid-dt_needed-entries-enforced-for-api-level-23",
1169 "library \"%s\" has invalid DT_NEEDED entry \"%s\"",
1170 sopath, dt_needed, app_target_api_level);
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07001171 add_dlwarning(sopath, "invalid DT_NEEDED entry", dt_needed);
Dmitriy Ivanovd974e882015-05-27 18:29:41 -07001172 }
1173
1174 return bname;
1175 }
1176#endif
1177 return dt_needed;
1178}
1179
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001180template<typename F>
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001181static void for_each_dt_needed(const ElfReader& elf_reader, F action) {
1182 for (const ElfW(Dyn)* d = elf_reader.dynamic(); d->d_tag != DT_NULL; ++d) {
1183 if (d->d_tag == DT_NEEDED) {
1184 action(fix_dt_needed(elf_reader.get_string(d->d_un.d_val), elf_reader.name()));
1185 }
1186 }
1187}
1188
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -07001189static bool find_loaded_library_by_inode(android_namespace_t* ns,
1190 const struct stat& file_stat,
1191 off64_t file_offset,
1192 bool search_linked_namespaces,
1193 soinfo** candidate) {
1194
1195 auto predicate = [&](soinfo* si) {
1196 return si->get_st_dev() != 0 &&
1197 si->get_st_ino() != 0 &&
1198 si->get_st_dev() == file_stat.st_dev &&
1199 si->get_st_ino() == file_stat.st_ino &&
1200 si->get_file_offset() == file_offset;
1201 };
1202
1203 *candidate = ns->soinfo_list().find_if(predicate);
1204
1205 if (*candidate == nullptr && search_linked_namespaces) {
1206 for (auto& link : ns->linked_namespaces()) {
1207 android_namespace_t* linked_ns = link.linked_namespace();
1208 soinfo* si = linked_ns->soinfo_list().find_if(predicate);
1209
1210 if (si != nullptr && link.is_accessible(si->get_soname())) {
1211 *candidate = si;
1212 return true;
1213 }
1214 }
1215 }
1216
1217 return *candidate != nullptr;
1218}
1219
Evgenii Stepanov9e77a642017-07-27 14:55:44 -07001220static bool find_loaded_library_by_realpath(android_namespace_t* ns, const char* realpath,
1221 bool search_linked_namespaces, soinfo** candidate) {
1222 auto predicate = [&](soinfo* si) { return strcmp(realpath, si->get_realpath()) == 0; };
1223
1224 *candidate = ns->soinfo_list().find_if(predicate);
1225
1226 if (*candidate == nullptr && search_linked_namespaces) {
1227 for (auto& link : ns->linked_namespaces()) {
1228 android_namespace_t* linked_ns = link.linked_namespace();
1229 soinfo* si = linked_ns->soinfo_list().find_if(predicate);
1230
1231 if (si != nullptr && link.is_accessible(si->get_soname())) {
1232 *candidate = si;
1233 return true;
1234 }
1235 }
1236 }
1237
1238 return *candidate != nullptr;
1239}
1240
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001241static bool load_library(android_namespace_t* ns,
1242 LoadTask* task,
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001243 LoadTaskList* load_tasks,
1244 int rtld_flags,
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -07001245 const std::string& realpath,
1246 bool search_linked_namespaces) {
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001247 off64_t file_offset = task->get_file_offset();
1248 const char* name = task->get_name();
1249 const android_dlextinfo* extinfo = task->get_extinfo();
1250
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -07001251 if ((file_offset % PAGE_SIZE) != 0) {
Dmitriy Ivanova6c12792014-10-21 12:09:18 -07001252 DL_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset);
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001253 return false;
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -07001254 }
Yabin Cui16f7f8d2014-11-04 11:08:05 -08001255 if (file_offset < 0) {
1256 DL_ERR("file offset for the library \"%s\" is negative: %" PRId64, name, file_offset);
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001257 return false;
Yabin Cui16f7f8d2014-11-04 11:08:05 -08001258 }
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -07001259
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001260 struct stat file_stat;
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001261 if (TEMP_FAILURE_RETRY(fstat(task->get_fd(), &file_stat)) != 0) {
Dmitriy Ivanova6c12792014-10-21 12:09:18 -07001262 DL_ERR("unable to stat file for the library \"%s\": %s", name, strerror(errno));
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001263 return false;
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001264 }
Yabin Cui16f7f8d2014-11-04 11:08:05 -08001265 if (file_offset >= file_stat.st_size) {
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07001266 DL_ERR("file offset for the library \"%s\" >= file size: %" PRId64 " >= %" PRId64,
1267 name, file_offset, file_stat.st_size);
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001268 return false;
Yabin Cui16f7f8d2014-11-04 11:08:05 -08001269 }
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001270
1271 // Check for symlink and other situations where
Dmitriy Ivanov9b821362015-04-02 16:03:56 -07001272 // file can have different names, unless ANDROID_DLEXT_FORCE_LOAD is set
1273 if (extinfo == nullptr || (extinfo->flags & ANDROID_DLEXT_FORCE_LOAD) == 0) {
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -07001274 soinfo* si = nullptr;
1275 if (find_loaded_library_by_inode(ns, file_stat, file_offset, search_linked_namespaces, &si)) {
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001276 TRACE("library \"%s\" is already loaded under different name/path \"%s\" - "
1277 "will return existing soinfo", name, si->get_realpath());
1278 task->set_soinfo(si);
1279 return true;
1280 }
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001281 }
Dmitriy Ivanovd59e5002014-05-09 09:10:14 -07001282
Dmitriy Ivanove8ba50f2014-09-15 17:00:10 -07001283 if ((rtld_flags & RTLD_NOLOAD) != 0) {
Dmitriy Ivanova6ac54a2014-09-09 10:21:42 -07001284 DL_ERR("library \"%s\" wasn't loaded and RTLD_NOLOAD prevented it", name);
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001285 return false;
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001286 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001287
Dimitry Ivanovbf34ba32017-04-21 13:12:05 -07001288 struct statfs fs_stat;
1289 if (TEMP_FAILURE_RETRY(fstatfs(task->get_fd(), &fs_stat)) != 0) {
1290 DL_ERR("unable to fstatfs file for the library \"%s\": %s", name, strerror(errno));
1291 return false;
1292 }
1293
1294 // do not check accessibility using realpath if fd is located on tmpfs
1295 // this enables use of memfd_create() for apps
1296 if ((fs_stat.f_type != TMPFS_MAGIC) && (!ns->is_accessible(realpath))) {
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07001297 // TODO(dimitry): workaround for http://b/26394120 - the grey-list
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001298
1299 // TODO(dimitry) before O release: add a namespace attribute to have this enabled
1300 // only for classloader-namespaces
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07001301 const soinfo* needed_by = task->is_dt_needed() ? task->get_needed_by() : nullptr;
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001302 if (is_greylisted(ns, name, needed_by)) {
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07001303 // print warning only if needed by non-system library
1304 if (needed_by == nullptr || !is_system_library(needed_by->get_realpath())) {
1305 const soinfo* needed_or_dlopened_by = task->get_needed_by();
1306 const char* sopath = needed_or_dlopened_by == nullptr ? "(unknown)" :
1307 needed_or_dlopened_by->get_realpath();
Elliott Hughes9076b0c2018-02-28 11:29:45 -08001308 DL_WARN_documented_change(__ANDROID_API_N__,
1309 "private-api-enforced-for-api-level-24",
1310 "library \"%s\" (\"%s\") needed or dlopened by \"%s\" "
1311 "is not accessible by namespace \"%s\"",
1312 name, realpath.c_str(), sopath, ns->get_name());
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07001313 add_dlwarning(sopath, "unauthorized access to", name);
1314 }
1315 } else {
1316 // do not load libraries if they are not accessible for the specified namespace.
1317 const char* needed_or_dlopened_by = task->get_needed_by() == nullptr ?
1318 "(unknown)" :
1319 task->get_needed_by()->get_realpath();
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001320
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07001321 DL_ERR("library \"%s\" needed or dlopened by \"%s\" is not accessible for the namespace \"%s\"",
1322 name, needed_or_dlopened_by, ns->get_name());
Dimitry Ivanovd17a3772016-03-01 13:11:28 -08001323
Dimitry Ivanov35c8e3b2017-02-27 12:17:47 -08001324 // do not print this if a library is in the list of shared libraries for linked namespaces
1325 if (!maybe_accessible_via_namespace_links(ns, name)) {
1326 PRINT("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"
1327 " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","
1328 " permitted_paths=\"%s\"]",
1329 name, realpath.c_str(),
1330 needed_or_dlopened_by,
1331 ns->get_name(),
1332 android::base::Join(ns->get_ld_library_paths(), ':').c_str(),
1333 android::base::Join(ns->get_default_library_paths(), ':').c_str(),
1334 android::base::Join(ns->get_permitted_paths(), ':').c_str());
1335 }
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07001336 return false;
1337 }
Dimitry Ivanov22840aa2015-12-04 18:28:49 -08001338 }
1339
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001340 soinfo* si = soinfo_alloc(ns, realpath.c_str(), &file_stat, file_offset, rtld_flags);
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001341 if (si == nullptr) {
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001342 return false;
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001343 }
Dmitriy Ivanovd59e5002014-05-09 09:10:14 -07001344
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001345 task->set_soinfo(si);
1346
1347 // Read the ELF header and some of the segments.
1348 if (!task->read(realpath.c_str(), file_stat.st_size)) {
Dmitriy Ivanovfd7a91e2015-11-06 10:44:37 -08001349 soinfo_free(si);
1350 task->set_soinfo(nullptr);
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001351 return false;
1352 }
1353
1354 // find and set DT_RUNPATH and dt_soname
1355 // Note that these field values are temporary and are
1356 // going to be overwritten on soinfo::prelink_image
1357 // with values from PT_LOAD segments.
1358 const ElfReader& elf_reader = task->get_elf_reader();
1359 for (const ElfW(Dyn)* d = elf_reader.dynamic(); d->d_tag != DT_NULL; ++d) {
1360 if (d->d_tag == DT_RUNPATH) {
1361 si->set_dt_runpath(elf_reader.get_string(d->d_un.d_val));
1362 }
1363 if (d->d_tag == DT_SONAME) {
1364 si->set_soname(elf_reader.get_string(d->d_un.d_val));
1365 }
1366 }
1367
Christopher R. Palmer37425572017-04-08 22:40:01 +02001368#ifdef LD_SHIM_LIBS
1369 for_each_matching_shim(realpath.c_str(), [&](const char* name) {
1370 load_tasks->push_back(LoadTask::create(name, si, ns, task->get_readers_map()));
1371 });
1372#endif
1373
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001374 for_each_dt_needed(task->get_elf_reader(), [&](const char* name) {
Jiyong Park02586a22017-05-20 01:01:24 +09001375 load_tasks->push_back(LoadTask::create(name, si, ns, task->get_readers_map()));
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001376 });
Dmitriy Ivanovd59e5002014-05-09 09:10:14 -07001377
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001378 return true;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001379}
1380
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001381static bool load_library(android_namespace_t* ns,
1382 LoadTask* task,
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001383 ZipArchiveCache* zip_archive_cache,
1384 LoadTaskList* load_tasks,
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -07001385 int rtld_flags,
1386 bool search_linked_namespaces) {
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001387 const char* name = task->get_name();
1388 soinfo* needed_by = task->get_needed_by();
1389 const android_dlextinfo* extinfo = task->get_extinfo();
1390
Dmitriy Ivanova1feb112015-10-01 18:41:57 -07001391 off64_t file_offset;
1392 std::string realpath;
Spencer Low0346ad72015-04-22 18:06:51 -07001393 if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
Dmitriy Ivanova1feb112015-10-01 18:41:57 -07001394 file_offset = 0;
Spencer Low0346ad72015-04-22 18:06:51 -07001395 if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
1396 file_offset = extinfo->library_fd_offset;
1397 }
Dmitriy Ivanova1feb112015-10-01 18:41:57 -07001398
1399 if (!realpath_fd(extinfo->library_fd, &realpath)) {
1400 PRINT("warning: unable to get realpath for the library \"%s\" by extinfo->library_fd. "
1401 "Will use given name.", name);
1402 realpath = name;
1403 }
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001404
1405 task->set_fd(extinfo->library_fd, false);
1406 task->set_file_offset(file_offset);
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -07001407 return load_library(ns, task, load_tasks, rtld_flags, realpath, search_linked_namespaces);
Spencer Low0346ad72015-04-22 18:06:51 -07001408 }
1409
1410 // Open the file.
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001411 int fd = open_library(ns, zip_archive_cache, name, needed_by, &file_offset, &realpath);
Spencer Low0346ad72015-04-22 18:06:51 -07001412 if (fd == -1) {
1413 DL_ERR("library \"%s\" not found", name);
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001414 return false;
Spencer Low0346ad72015-04-22 18:06:51 -07001415 }
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001416
1417 task->set_fd(fd, true);
1418 task->set_file_offset(file_offset);
1419
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -07001420 return load_library(ns, task, load_tasks, rtld_flags, realpath, search_linked_namespaces);
Spencer Low0346ad72015-04-22 18:06:51 -07001421}
1422
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001423static bool find_loaded_library_by_soname(android_namespace_t* ns,
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -07001424 const char* name,
1425 soinfo** candidate) {
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001426 return !ns->soinfo_list().visit([&](soinfo* si) {
Dmitriy Ivanov618f1a32015-03-17 20:06:36 -07001427 const char* soname = si->get_soname();
1428 if (soname != nullptr && (strcmp(name, soname) == 0)) {
Dimitry Ivanov3bd90612017-02-01 08:54:43 -08001429 *candidate = si;
1430 return false;
Ard Biesheuvel12c78bb2012-08-14 12:30:09 +02001431 }
Dmitriy Ivanova9703332015-06-16 15:38:21 -07001432
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001433 return true;
1434 });
Ard Biesheuvel12c78bb2012-08-14 12:30:09 +02001435}
1436
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -07001437// Returns true if library was found and false otherwise
1438static bool find_loaded_library_by_soname(android_namespace_t* ns,
1439 const char* name,
1440 bool search_linked_namespaces,
1441 soinfo** candidate) {
1442 *candidate = nullptr;
1443
1444 // Ignore filename with path.
1445 if (strchr(name, '/') != nullptr) {
1446 return false;
1447 }
1448
1449 bool found = find_loaded_library_by_soname(ns, name, candidate);
1450
1451 if (!found && search_linked_namespaces) {
1452 // if a library was not found - look into linked namespaces
1453 for (auto& link : ns->linked_namespaces()) {
1454 if (!link.is_accessible(name)) {
1455 continue;
1456 }
1457
1458 android_namespace_t* linked_ns = link.linked_namespace();
1459
1460 if (find_loaded_library_by_soname(linked_ns, name, candidate)) {
1461 return true;
1462 }
1463 }
1464 }
1465
1466 return found;
1467}
1468
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001469static bool find_library_in_linked_namespace(const android_namespace_link_t& namespace_link,
Jiyong Park02586a22017-05-20 01:01:24 +09001470 LoadTask* task) {
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001471 android_namespace_t* ns = namespace_link.linked_namespace();
1472
1473 soinfo* candidate;
1474 bool loaded = false;
1475
1476 std::string soname;
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -07001477 if (find_loaded_library_by_soname(ns, task->get_name(), false, &candidate)) {
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001478 loaded = true;
1479 soname = candidate->get_soname();
1480 } else {
1481 soname = resolve_soname(task->get_name());
1482 }
1483
1484 if (!namespace_link.is_accessible(soname.c_str())) {
1485 // the library is not accessible via namespace_link
1486 return false;
1487 }
1488
1489 // if library is already loaded - return it
1490 if (loaded) {
1491 task->set_soinfo(candidate);
1492 return true;
1493 }
1494
Jiyong Park02586a22017-05-20 01:01:24 +09001495 // returning true with empty soinfo means that the library is okay to be
Logan Chien9ee45912018-01-18 12:05:09 +08001496 // loaded in the namespace but has not yet been loaded there before.
Jiyong Park02586a22017-05-20 01:01:24 +09001497 task->set_soinfo(nullptr);
1498 return true;
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001499}
1500
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001501static bool find_library_internal(android_namespace_t* ns,
1502 LoadTask* task,
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001503 ZipArchiveCache* zip_archive_cache,
1504 LoadTaskList* load_tasks,
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001505 int rtld_flags,
1506 bool search_linked_namespaces) {
Dmitriy Ivanova9703332015-06-16 15:38:21 -07001507 soinfo* candidate;
1508
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -07001509 if (find_loaded_library_by_soname(ns, task->get_name(), search_linked_namespaces, &candidate)) {
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001510 task->set_soinfo(candidate);
1511 return true;
Dmitriy Ivanova9703332015-06-16 15:38:21 -07001512 }
Dmitriy Ivanovb648a8a2014-05-19 15:06:58 -07001513
1514 // Library might still be loaded, the accurate detection
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001515 // of this fact is done by load_library.
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07001516 TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder...]",
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001517 task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
Dmitriy Ivanova9703332015-06-16 15:38:21 -07001518
Dimitry Ivanovd3e7d082017-03-27 14:11:02 -07001519 if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags, search_linked_namespaces)) {
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001520 return true;
1521 }
1522
1523 if (search_linked_namespaces) {
1524 // if a library was not found - look into linked namespaces
dimitry8db36a52017-10-23 15:10:10 +02001525 // preserve current dlerror in the case it fails.
1526 DlErrorRestorer dlerror_restorer;
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001527 for (auto& linked_namespace : ns->linked_namespaces()) {
1528 if (find_library_in_linked_namespace(linked_namespace,
Jiyong Park02586a22017-05-20 01:01:24 +09001529 task)) {
1530 if (task->get_soinfo() == nullptr) {
1531 // try to load the library - once namespace boundary is crossed
1532 // we need to load a library within separate load_group
1533 // to avoid using symbols from foreign namespace while.
1534 //
1535 // However, actual linking is deferred until when the global group
1536 // is fully identified and is applied to all namespaces.
1537 // Otherwise, the libs in the linked namespace won't get symbols from
1538 // the global group.
1539 if (load_library(linked_namespace.linked_namespace(), task, zip_archive_cache, load_tasks, rtld_flags, false)) {
1540 return true;
1541 }
Jiyong Park02586a22017-05-20 01:01:24 +09001542 } else {
1543 // lib is already loaded
1544 return true;
1545 }
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001546 }
1547 }
1548 }
1549
1550 return false;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001551}
1552
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001553static void soinfo_unload(soinfo* si);
1554
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001555static void shuffle(std::vector<LoadTask*>* v) {
1556 for (size_t i = 0, size = v->size(); i < size; ++i) {
1557 size_t n = size - i;
1558 size_t r = arc4random_uniform(n);
1559 std::swap((*v)[n-1], (*v)[r]);
1560 }
1561}
1562
Evgenii Stepanov0cdef7e2015-07-06 17:56:31 -07001563// add_as_children - add first-level loaded libraries (i.e. library_names[], but
1564// not their transitive dependencies) as children of the start_with library.
1565// This is false when find_libraries is called for dlopen(), when newly loaded
1566// libraries must form a disjoint tree.
Dimitry Ivanov3f660572016-09-09 10:00:39 -07001567bool find_libraries(android_namespace_t* ns,
1568 soinfo* start_with,
1569 const char* const library_names[],
1570 size_t library_names_count,
1571 soinfo* soinfos[],
1572 std::vector<soinfo*>* ld_preloads,
1573 size_t ld_preloads_count,
1574 int rtld_flags,
1575 const android_dlextinfo* extinfo,
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001576 bool add_as_children,
Jiyong Park02586a22017-05-20 01:01:24 +09001577 bool search_linked_namespaces,
Jiyong Park02586a22017-05-20 01:01:24 +09001578 std::vector<android_namespace_t*>* namespaces) {
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001579 // Step 0: prepare.
dimitry965d06d2017-11-28 16:03:07 +01001580 std::unordered_map<const soinfo*, ElfReader> readers_map;
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001581 LoadTaskList load_tasks;
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001582
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -07001583 for (size_t i = 0; i < library_names_count; ++i) {
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001584 const char* name = library_names[i];
Jiyong Park02586a22017-05-20 01:01:24 +09001585 load_tasks.push_back(LoadTask::create(name, start_with, ns, &readers_map));
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001586 }
1587
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -07001588 // If soinfos array is null allocate one on stack.
1589 // The array is needed in case of failure; for example
1590 // when library_names[] = {libone.so, libtwo.so} and libone.so
1591 // is loaded correctly but libtwo.so failed for some reason.
1592 // In this case libone.so should be unloaded on return.
1593 // See also implementation of failure_guard below.
1594
1595 if (soinfos == nullptr) {
1596 size_t soinfos_size = sizeof(soinfo*)*library_names_count;
1597 soinfos = reinterpret_cast<soinfo**>(alloca(soinfos_size));
1598 memset(soinfos, 0, soinfos_size);
1599 }
1600
1601 // list of libraries to link - see step 2.
1602 size_t soinfos_count = 0;
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001603
Tom Cherryb8ab6182017-04-05 16:20:29 -07001604 auto scope_guard = android::base::make_scope_guard([&]() {
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001605 for (LoadTask* t : load_tasks) {
1606 LoadTask::deleter(t);
1607 }
1608 });
1609
Dmitriy Ivanovb4827502015-09-28 16:38:31 -07001610 ZipArchiveCache zip_archive_cache;
1611
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001612 // Step 1: expand the list of load_tasks to include
1613 // all DT_NEEDED libraries (do not load them just yet)
1614 for (size_t i = 0; i<load_tasks.size(); ++i) {
1615 LoadTask* task = load_tasks[i];
Evgenii Stepanov68650822015-06-10 13:38:39 -07001616 soinfo* needed_by = task->get_needed_by();
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001617
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -07001618 bool is_dt_needed = needed_by != nullptr && (needed_by != start_with || add_as_children);
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001619 task->set_extinfo(is_dt_needed ? nullptr : extinfo);
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07001620 task->set_dt_needed(is_dt_needed);
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -07001621
Jiyong Park02586a22017-05-20 01:01:24 +09001622 // Note: start from the namespace that is stored in the LoadTask. This namespace
1623 // is different from the current namespace when the LoadTask is for a transitive
1624 // dependency and the lib that created the LoadTask is not found in the
1625 // current namespace but in one of the linked namespace.
1626 if (!find_library_internal(const_cast<android_namespace_t*>(task->get_start_from()),
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001627 task,
1628 &zip_archive_cache,
1629 &load_tasks,
1630 rtld_flags,
1631 search_linked_namespaces || is_dt_needed)) {
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001632 return false;
1633 }
1634
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001635 soinfo* si = task->get_soinfo();
1636
Dmitriy Ivanovedfc9f62015-09-02 16:32:02 -07001637 if (is_dt_needed) {
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001638 needed_by->add_child(si);
Dmitriy Ivanovab972b92014-11-29 13:57:41 -08001639 }
1640
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -07001641 // When ld_preloads is not null, the first
1642 // ld_preloads_count libs are in fact ld_preloads.
1643 if (ld_preloads != nullptr && soinfos_count < ld_preloads_count) {
Dmitriy Ivanovd165f562015-03-23 18:43:02 -07001644 ld_preloads->push_back(si);
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001645 }
1646
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -07001647 if (soinfos_count < library_names_count) {
1648 soinfos[soinfos_count++] = si;
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001649 }
1650 }
1651
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001652 // Step 2: Load libraries in random order (see b/24047022)
1653 LoadTaskList load_list;
1654 for (auto&& task : load_tasks) {
1655 soinfo* si = task->get_soinfo();
1656 auto pred = [&](const LoadTask* t) {
1657 return t->get_soinfo() == si;
1658 };
1659
1660 if (!si->is_linked() &&
1661 std::find_if(load_list.begin(), load_list.end(), pred) == load_list.end() ) {
1662 load_list.push_back(task);
1663 }
1664 }
1665 shuffle(&load_list);
1666
1667 for (auto&& task : load_list) {
1668 if (!task->load()) {
1669 return false;
1670 }
1671 }
1672
1673 // Step 3: pre-link all DT_NEEDED libraries in breadth first order.
1674 for (auto&& task : load_tasks) {
1675 soinfo* si = task->get_soinfo();
1676 if (!si->is_linked() && !si->prelink_image()) {
1677 return false;
1678 }
1679 }
1680
Jiyong Park02586a22017-05-20 01:01:24 +09001681 // Step 4: Construct the global group. Note: DF_1_GLOBAL bit of a library is
1682 // determined at step 3.
1683
1684 // Step 4-1: DF_1_GLOBAL bit is force set for LD_PRELOADed libs because they
1685 // must be added to the global group
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001686 if (ld_preloads != nullptr) {
1687 for (auto&& si : *ld_preloads) {
1688 si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
1689 }
1690 }
1691
Jiyong Park02586a22017-05-20 01:01:24 +09001692 // Step 4-2: Gather all DF_1_GLOBAL libs which were newly loaded during this
1693 // run. These will be the new member of the global group
1694 soinfo_list_t new_global_group_members;
1695 for (auto&& task : load_tasks) {
1696 soinfo* si = task->get_soinfo();
1697 if (!si->is_linked() && (si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
1698 new_global_group_members.push_back(si);
1699 }
1700 }
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07001701
Jiyong Park02586a22017-05-20 01:01:24 +09001702 // Step 4-3: Add the new global group members to all the linked namespaces
Jiyong Park01162f22017-10-16 15:31:09 +09001703 if (namespaces != nullptr) {
Jiyong Park02586a22017-05-20 01:01:24 +09001704 for (auto linked_ns : *namespaces) {
Jiyong Park01162f22017-10-16 15:31:09 +09001705 for (auto si : new_global_group_members) {
1706 if (si->get_primary_namespace() != linked_ns) {
1707 linked_ns->add_soinfo(si);
1708 si->add_secondary_namespace(linked_ns);
1709 }
Jiyong Park02586a22017-05-20 01:01:24 +09001710 }
1711 }
1712 }
1713
dimitry965d06d2017-11-28 16:03:07 +01001714 // Step 5: Collect roots of local_groups.
1715 // Whenever needed_by->si link crosses a namespace boundary it forms its own local_group.
1716 // Here we collect new roots to link them separately later on. Note that we need to avoid
1717 // collecting duplicates. Also the order is important. They need to be linked in the same
1718 // BFS order we link individual libraries.
1719 std::vector<soinfo*> local_group_roots;
1720 if (start_with != nullptr && add_as_children) {
1721 local_group_roots.push_back(start_with);
1722 } else {
1723 CHECK(soinfos_count == 1);
1724 local_group_roots.push_back(soinfos[0]);
1725 }
1726
Jiyong Park02586a22017-05-20 01:01:24 +09001727 for (auto&& task : load_tasks) {
1728 soinfo* si = task->get_soinfo();
dimitry965d06d2017-11-28 16:03:07 +01001729 soinfo* needed_by = task->get_needed_by();
1730 bool is_dt_needed = needed_by != nullptr && (needed_by != start_with || add_as_children);
1731 android_namespace_t* needed_by_ns =
1732 is_dt_needed ? needed_by->get_primary_namespace() : ns;
1733
1734 if (!si->is_linked() && si->get_primary_namespace() != needed_by_ns) {
1735 auto it = std::find(local_group_roots.begin(), local_group_roots.end(), si);
1736 LD_LOG(kLogDlopen,
1737 "Crossing namespace boundary (si=%s@%p, si_ns=%s@%p, needed_by=%s@%p, ns=%s@%p, needed_by_ns=%s@%p) adding to local_group_roots: %s",
1738 si->get_realpath(),
1739 si,
1740 si->get_primary_namespace()->get_name(),
1741 si->get_primary_namespace(),
1742 needed_by == nullptr ? "(nullptr)" : needed_by->get_realpath(),
1743 needed_by,
1744 ns->get_name(),
1745 ns,
1746 needed_by_ns->get_name(),
1747 needed_by_ns,
1748 it == local_group_roots.end() ? "yes" : "no");
1749
1750 if (it == local_group_roots.end()) {
1751 local_group_roots.push_back(si);
Jiyong Park02586a22017-05-20 01:01:24 +09001752 }
1753 }
1754 }
1755
dimitry965d06d2017-11-28 16:03:07 +01001756 // Step 6: Link all local groups
1757 for (auto root : local_group_roots) {
1758 soinfo_list_t local_group;
1759 android_namespace_t* local_group_ns = root->get_primary_namespace();
1760
1761 walk_dependencies_tree(root,
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -07001762 [&] (soinfo* si) {
dimitry965d06d2017-11-28 16:03:07 +01001763 if (local_group_ns->is_accessible(si)) {
1764 local_group.push_back(si);
1765 return kWalkContinue;
1766 } else {
1767 return kWalkSkip;
1768 }
1769 });
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -07001770
dimitry965d06d2017-11-28 16:03:07 +01001771 soinfo_list_t global_group = local_group_ns->get_global_group();
1772 bool linked = local_group.visit([&](soinfo* si) {
1773 // Even though local group may contain accessible soinfos from other namesapces
1774 // we should avoid linking them (because if they are not linked -> they
1775 // are in the local_group_roots and will be linked later).
1776 if (!si->is_linked() && si->get_primary_namespace() == local_group_ns) {
1777 if (!si->link_image(global_group, local_group, extinfo) ||
1778 !get_cfi_shadow()->AfterLoad(si, solist_get_head())) {
1779 return false;
1780 }
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001781 }
Dmitriy Ivanovcfa97f12014-10-21 09:23:18 -07001782
dimitry965d06d2017-11-28 16:03:07 +01001783 return true;
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001784 });
Elliott Hughes27f18062017-11-29 18:47:42 +00001785
dimitry965d06d2017-11-28 16:03:07 +01001786 if (!linked) {
1787 return false;
1788 }
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001789 }
1790
dimitry965d06d2017-11-28 16:03:07 +01001791 // Step 7: Mark all load_tasks as linked and increment refcounts
1792 // for references between load_groups (at this point it does not matter if
1793 // referenced load_groups were loaded by previous dlopen or as part of this
1794 // one on step 6)
1795 if (start_with != nullptr && add_as_children) {
1796 start_with->set_linked();
1797 }
1798
1799 for (auto&& task : load_tasks) {
1800 soinfo* si = task->get_soinfo();
1801 si->set_linked();
1802 }
1803
1804 for (auto&& task : load_tasks) {
1805 soinfo* si = task->get_soinfo();
1806 soinfo* needed_by = task->get_needed_by();
1807 if (needed_by != nullptr &&
1808 needed_by != start_with &&
1809 needed_by->get_local_group_root() != si->get_local_group_root()) {
1810 si->increment_ref_count();
1811 }
1812 }
1813
1814
1815 return true;
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001816}
1817
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07001818static soinfo* find_library(android_namespace_t* ns,
1819 const char* name, int rtld_flags,
Evgenii Stepanov0cdef7e2015-07-06 17:56:31 -07001820 const android_dlextinfo* extinfo,
1821 soinfo* needed_by) {
dimitry965d06d2017-11-28 16:03:07 +01001822 soinfo* si = nullptr;
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001823
Dmitriy Ivanovab972b92014-11-29 13:57:41 -08001824 if (name == nullptr) {
Dimitry Ivanov3f660572016-09-09 10:00:39 -07001825 si = solist_get_somain();
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001826 } else if (!find_libraries(ns,
1827 needed_by,
1828 &name,
1829 1,
1830 &si,
1831 nullptr,
1832 0,
1833 rtld_flags,
1834 extinfo,
1835 false /* add_as_children */,
dimitry965d06d2017-11-28 16:03:07 +01001836 true /* search_linked_namespaces */)) {
1837 if (si != nullptr) {
1838 soinfo_unload(si);
1839 }
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07001840 return nullptr;
1841 }
1842
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08001843 si->increment_ref_count();
1844
Elliott Hughesd23736e2012-11-01 15:16:56 -07001845 return si;
1846}
Elliott Hughesbedfe382012-08-14 14:07:59 -07001847
dimitry06016f22018-01-05 11:39:28 +01001848static void soinfo_unload_impl(soinfo* root) {
Dimitry Ivanov6705e8c2017-03-21 10:29:06 -07001849 ScopedTrace trace((std::string("unload ") + root->get_realpath()).c_str());
dimitry06016f22018-01-05 11:39:28 +01001850 bool is_linked = root->is_linked();
Dimitry Ivanov6705e8c2017-03-21 10:29:06 -07001851
Dmitriy Ivanovab972b92014-11-29 13:57:41 -08001852 if (!root->can_unload()) {
dimitryc92ce712017-10-27 14:12:53 +02001853 LD_LOG(kLogDlopen,
1854 "... dlclose(root=\"%s\"@%p) ... not unloading - the load group is flagged with NODELETE",
1855 root->get_realpath(),
1856 root);
Dmitriy Ivanov1b20daf2014-05-19 15:06:58 -07001857 return;
1858 }
1859
Dmitriy Ivanovab972b92014-11-29 13:57:41 -08001860
Dimitry Ivanovb943f302016-08-03 16:00:10 -07001861 soinfo_list_t unload_list;
dimitry965d06d2017-11-28 16:03:07 +01001862 unload_list.push_back(root);
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001863
Dimitry Ivanovb943f302016-08-03 16:00:10 -07001864 soinfo_list_t local_unload_list;
1865 soinfo_list_t external_unload_list;
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001866 soinfo* si = nullptr;
1867
1868 while ((si = unload_list.pop_front()) != nullptr) {
1869 if (local_unload_list.contains(si)) {
1870 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001871 }
Elliott Hughesd23736e2012-11-01 15:16:56 -07001872
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001873 local_unload_list.push_back(si);
Dmitriy Ivanovab972b92014-11-29 13:57:41 -08001874
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001875 if (si->has_min_version(0)) {
1876 soinfo* child = nullptr;
1877 while ((child = si->get_children().pop_front()) != nullptr) {
1878 TRACE("%s@%p needs to unload %s@%p", si->get_realpath(), si,
1879 child->get_realpath(), child);
Dmitriy Ivanovab972b92014-11-29 13:57:41 -08001880
Dimitry Ivanovec90e242017-02-10 11:04:20 -08001881 child->get_parents().remove(si);
1882
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001883 if (local_unload_list.contains(child)) {
1884 continue;
1885 } else if (child->is_linked() && child->get_local_group_root() != root) {
1886 external_unload_list.push_back(child);
Dimitry Ivanovec90e242017-02-10 11:04:20 -08001887 } else if (child->get_parents().empty()) {
1888 unload_list.push_back(child);
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001889 }
1890 }
1891 } else {
1892#if !defined(__work_around_b_24465209__)
Christopher Ferris7a3681e2017-04-24 17:48:32 -07001893 async_safe_fatal("soinfo for \"%s\"@%p has no version", si->get_realpath(), si);
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001894#else
1895 PRINT("warning: soinfo for \"%s\"@%p has no version", si->get_realpath(), si);
1896 for_each_dt_needed(si, [&] (const char* library_name) {
1897 TRACE("deprecated (old format of soinfo): %s needs to unload %s",
1898 si->get_realpath(), library_name);
1899
1900 soinfo* needed = find_library(si->get_primary_namespace(),
1901 library_name, RTLD_NOLOAD, nullptr, nullptr);
1902
1903 if (needed != nullptr) {
1904 // Not found: for example if symlink was deleted between dlopen and dlclose
1905 // Since we cannot really handle errors at this point - print and continue.
1906 PRINT("warning: couldn't find %s needed by %s on unload.",
1907 library_name, si->get_realpath());
1908 return;
1909 } else if (local_unload_list.contains(needed)) {
1910 // already visited
1911 return;
1912 } else if (needed->is_linked() && needed->get_local_group_root() != root) {
1913 // external group
1914 external_unload_list.push_back(needed);
1915 } else {
1916 // local group
1917 unload_list.push_front(needed);
1918 }
1919 });
1920#endif
Dmitriy Ivanovab972b92014-11-29 13:57:41 -08001921 }
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001922 }
1923
1924 local_unload_list.for_each([](soinfo* si) {
dimitryc92ce712017-10-27 14:12:53 +02001925 LD_LOG(kLogDlopen,
1926 "... dlclose: calling destructors for \"%s\"@%p ... ",
1927 si->get_realpath(),
1928 si);
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001929 si->call_destructors();
dimitryc92ce712017-10-27 14:12:53 +02001930 LD_LOG(kLogDlopen,
1931 "... dlclose: calling destructors for \"%s\"@%p ... done",
1932 si->get_realpath(),
1933 si);
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001934 });
1935
1936 while ((si = local_unload_list.pop_front()) != nullptr) {
dimitryc92ce712017-10-27 14:12:53 +02001937 LD_LOG(kLogDlopen,
1938 "... dlclose: unloading \"%s\"@%p ...",
1939 si->get_realpath(),
1940 si);
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001941 notify_gdb_of_unload(si);
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -07001942 get_cfi_shadow()->BeforeUnload(si);
Dimitry Ivanov83fcb542016-05-04 17:19:14 -07001943 soinfo_free(si);
1944 }
1945
dimitry965d06d2017-11-28 16:03:07 +01001946 if (is_linked) {
1947 while ((si = external_unload_list.pop_front()) != nullptr) {
1948 LD_LOG(kLogDlopen,
1949 "... dlclose: unloading external reference \"%s\"@%p ...",
1950 si->get_realpath(),
1951 si);
1952 soinfo_unload(si);
1953 }
1954 } else {
1955 LD_LOG(kLogDlopen,
1956 "... dlclose: unload_si was not linked - not unloading external references ...");
Dmitriy Ivanova2547052014-11-18 12:03:09 -08001957 }
1958}
1959
dimitry06016f22018-01-05 11:39:28 +01001960static void soinfo_unload(soinfo* unload_si) {
1961 // Note that the library can be loaded but not linked;
1962 // in which case there is no root but we still need
1963 // to walk the tree and unload soinfos involved.
1964 //
1965 // This happens on unsuccessful dlopen, when one of
1966 // the DT_NEEDED libraries could not be linked/found.
1967 bool is_linked = unload_si->is_linked();
1968 soinfo* root = is_linked ? unload_si->get_local_group_root() : unload_si;
1969
1970 LD_LOG(kLogDlopen,
1971 "... dlclose(realpath=\"%s\"@%p) ... load group root is \"%s\"@%p",
1972 unload_si->get_realpath(),
1973 unload_si,
1974 root->get_realpath(),
1975 root);
1976
1977
1978 size_t ref_count = is_linked ? root->decrement_ref_count() : 0;
1979 if (ref_count > 0) {
1980 LD_LOG(kLogDlopen,
1981 "... dlclose(root=\"%s\"@%p) ... not unloading - decrementing ref_count to %zd",
1982 root->get_realpath(),
1983 root,
1984 ref_count);
1985 return;
1986 }
1987
1988 soinfo_unload_impl(root);
1989}
1990
1991void increment_dso_handle_reference_counter(void* dso_handle) {
1992 if (dso_handle == nullptr) {
1993 return;
1994 }
1995
1996 auto it = g_dso_handle_counters.find(dso_handle);
1997 if (it != g_dso_handle_counters.end()) {
1998 CHECK(++it->second != 0);
1999 } else {
2000 soinfo* si = find_containing_library(dso_handle);
2001 if (si != nullptr) {
2002 ProtectedDataGuard guard;
2003 si->set_tls_nodelete();
2004 } else {
2005 async_safe_fatal(
2006 "increment_dso_handle_reference_counter: Couldn't find soinfo by dso_handle=%p",
2007 dso_handle);
2008 }
2009 g_dso_handle_counters[dso_handle] = 1U;
2010 }
2011}
2012
2013void decrement_dso_handle_reference_counter(void* dso_handle) {
2014 if (dso_handle == nullptr) {
2015 return;
2016 }
2017
2018 auto it = g_dso_handle_counters.find(dso_handle);
2019 CHECK(it != g_dso_handle_counters.end());
2020 CHECK(it->second != 0);
2021
2022 if (--it->second == 0) {
2023 soinfo* si = find_containing_library(dso_handle);
2024 if (si != nullptr) {
2025 ProtectedDataGuard guard;
2026 si->unset_tls_nodelete();
2027 if (si->get_ref_count() == 0) {
2028 // Perform deferred unload - note that soinfo_unload_impl does not decrement ref_count
2029 soinfo_unload_impl(si);
2030 }
2031 } else {
2032 async_safe_fatal(
2033 "decrement_dso_handle_reference_counter: Couldn't find soinfo by dso_handle=%p",
2034 dso_handle);
2035 }
2036 g_dso_handle_counters.erase(it);
2037 }
2038}
2039
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -08002040static std::string symbol_display_name(const char* sym_name, const char* sym_ver) {
2041 if (sym_ver == nullptr) {
2042 return sym_name;
2043 }
2044
Dimitry Ivanov9cf99cb2015-12-11 14:22:24 -08002045 return std::string(sym_name) + ", version " + sym_ver;
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -08002046}
2047
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07002048static android_namespace_t* get_caller_namespace(soinfo* caller) {
2049 return caller != nullptr ? caller->get_primary_namespace() : g_anonymous_namespace;
2050}
2051
Elliott Hughesa4aafd12014-01-13 16:37:47 -08002052void do_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
Christopher Ferris052fa3a2014-08-26 20:48:11 -07002053 // Use basic string manipulation calls to avoid snprintf.
2054 // snprintf indirectly calls pthread_getspecific to get the size of a buffer.
2055 // When debug malloc is enabled, this call returns 0. This in turn causes
2056 // snprintf to do nothing, which causes libraries to fail to load.
2057 // See b/17302493 for further details.
2058 // Once the above bug is fixed, this code can be modified to use
2059 // snprintf again.
Dimitry Ivanov77ad6422017-03-06 13:02:29 -08002060 const auto& default_ld_paths = g_default_namespace.get_default_library_paths();
2061
2062 size_t required_size = 0;
2063 for (const auto& path : default_ld_paths) {
2064 required_size += path.size() + 1;
Evgenii Stepanovd640b222015-07-10 17:54:01 -07002065 }
Dimitry Ivanov77ad6422017-03-06 13:02:29 -08002066
2067 if (buffer_size < required_size) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -07002068 async_safe_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: "
2069 "buffer len %zu, required len %zu", buffer_size, required_size);
Christopher Ferris052fa3a2014-08-26 20:48:11 -07002070 }
Dimitry Ivanov77ad6422017-03-06 13:02:29 -08002071
Evgenii Stepanovd640b222015-07-10 17:54:01 -07002072 char* end = buffer;
Dimitry Ivanov77ad6422017-03-06 13:02:29 -08002073 for (size_t i = 0; i < default_ld_paths.size(); ++i) {
Evgenii Stepanovd640b222015-07-10 17:54:01 -07002074 if (i > 0) *end++ = ':';
Dimitry Ivanov77ad6422017-03-06 13:02:29 -08002075 end = stpcpy(end, default_ld_paths[i].c_str());
Evgenii Stepanovd640b222015-07-10 17:54:01 -07002076 }
Elliott Hughesa4aafd12014-01-13 16:37:47 -08002077}
2078
Elliott Hughescade4c32012-12-20 14:42:14 -08002079void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
Nick Kralevich6bb01b62015-03-07 13:37:05 -08002080 parse_LD_LIBRARY_PATH(ld_library_path);
Elliott Hughescade4c32012-12-20 14:42:14 -08002081}
2082
Dimitry Ivanovb996d602016-07-11 18:11:39 -07002083static std::string android_dlextinfo_to_string(const android_dlextinfo* info) {
2084 if (info == nullptr) {
2085 return "(null)";
2086 }
2087
2088 return android::base::StringPrintf("[flags=0x%" PRIx64 ","
2089 " reserved_addr=%p,"
2090 " reserved_size=0x%zx,"
2091 " relro_fd=%d,"
2092 " library_fd=%d,"
2093 " library_fd_offset=0x%" PRIx64 ","
2094 " library_namespace=%s@%p]",
2095 info->flags,
2096 info->reserved_addr,
2097 info->reserved_size,
2098 info->relro_fd,
2099 info->library_fd,
2100 info->library_fd_offset,
2101 (info->flags & ANDROID_DLEXT_USE_NAMESPACE) != 0 ?
2102 (info->library_namespace != nullptr ?
2103 info->library_namespace->get_name() : "(null)") : "(n/a)",
2104 (info->flags & ANDROID_DLEXT_USE_NAMESPACE) != 0 ?
2105 info->library_namespace : nullptr);
2106}
2107
Dimitry Ivanovd9e427c2016-11-22 16:55:25 -08002108void* do_dlopen(const char* name, int flags,
2109 const android_dlextinfo* extinfo,
2110 const void* caller_addr) {
Dimitry Ivanov5c4a5802017-03-17 16:41:34 -07002111 std::string trace_prefix = std::string("dlopen: ") + (name == nullptr ? "(nullptr)" : name);
2112 ScopedTrace trace(trace_prefix.c_str());
2113 ScopedTrace loading_trace((trace_prefix + " - loading and linking").c_str());
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -08002114 soinfo* const caller = find_containing_library(caller_addr);
Dimitry Ivanovb996d602016-07-11 18:11:39 -07002115 android_namespace_t* ns = get_caller_namespace(caller);
2116
2117 LD_LOG(kLogDlopen,
2118 "dlopen(name=\"%s\", flags=0x%x, extinfo=%s, caller=\"%s\", caller_ns=%s@%p) ...",
2119 name,
2120 flags,
2121 android_dlextinfo_to_string(extinfo).c_str(),
2122 caller == nullptr ? "(null)" : caller->get_realpath(),
2123 ns == nullptr ? "(null)" : ns->get_name(),
2124 ns);
2125
Tom Cherryb8ab6182017-04-05 16:20:29 -07002126 auto failure_guard = android::base::make_scope_guard(
2127 [&]() { LD_LOG(kLogDlopen, "... dlopen failed: %s", linker_get_error_buffer()); });
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -08002128
Dmitriy Ivanov1b20daf2014-05-19 15:06:58 -07002129 if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NODELETE|RTLD_NOLOAD)) != 0) {
Elliott Hughese66190d2012-12-18 15:57:55 -08002130 DL_ERR("invalid flags to dlopen: %x", flags);
Dmitriy Ivanov851135b2014-08-29 12:02:36 -07002131 return nullptr;
Elliott Hughese66190d2012-12-18 15:57:55 -08002132 }
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002133
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -07002134 if (extinfo != nullptr) {
2135 if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) {
2136 DL_ERR("invalid extended flags to android_dlopen_ext: 0x%" PRIx64, extinfo->flags);
2137 return nullptr;
2138 }
Dmitriy Ivanov126af752015-10-07 16:34:20 -07002139
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -07002140 if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 &&
Dmitriy Ivanova6c12792014-10-21 12:09:18 -07002141 (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002142 DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without "
2143 "ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags);
Dmitriy Ivanov07e5bc12014-10-03 17:52:44 -07002144 return nullptr;
2145 }
Dmitriy Ivanov126af752015-10-07 16:34:20 -07002146
2147 if ((extinfo->flags & ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS) != 0 &&
2148 (extinfo->flags & (ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_HINT)) != 0) {
2149 DL_ERR("invalid extended flag combination: ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS is not "
2150 "compatible with ANDROID_DLEXT_RESERVED_ADDRESS/ANDROID_DLEXT_RESERVED_ADDRESS_HINT");
2151 return nullptr;
2152 }
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002153
2154 if ((extinfo->flags & ANDROID_DLEXT_USE_NAMESPACE) != 0) {
2155 if (extinfo->library_namespace == nullptr) {
2156 DL_ERR("ANDROID_DLEXT_USE_NAMESPACE is set but extinfo->library_namespace is null");
2157 return nullptr;
2158 }
2159 ns = extinfo->library_namespace;
2160 }
Torne (Richard Coles)012cb452014-02-06 14:34:21 +00002161 }
Dmitriy Ivanov279a22f2015-01-23 12:03:53 -08002162
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -07002163 std::string asan_name_holder;
2164
2165 const char* translated_name = name;
Dimitry Ivanov6c14f862016-12-05 13:35:47 -08002166 if (g_is_asan && translated_name != nullptr && translated_name[0] == '/') {
Evgenii Stepanov9e77a642017-07-27 14:55:44 -07002167 char original_path[PATH_MAX];
2168 if (realpath(name, original_path) != nullptr) {
2169 asan_name_holder = std::string(kAsanLibDirPrefix) + original_path;
Vishwath Mohan4113def2017-03-29 15:31:34 -07002170 if (file_exists(asan_name_holder.c_str())) {
Evgenii Stepanov9e77a642017-07-27 14:55:44 -07002171 soinfo* si = nullptr;
2172 if (find_loaded_library_by_realpath(ns, original_path, true, &si)) {
2173 PRINT("linker_asan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
2174 asan_name_holder.c_str());
2175 } else {
2176 PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
2177 translated_name = asan_name_holder.c_str();
2178 }
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -07002179 }
2180 }
2181 }
2182
Dmitriy Ivanov279a22f2015-01-23 12:03:53 -08002183 ProtectedDataGuard guard;
Christopher R. Palmer37425572017-04-08 22:40:01 +02002184#ifdef LD_SHIM_LIBS
2185 reset_g_active_shim_libs();
2186#endif
Dimitry Ivanov45d25ca2016-08-09 19:38:43 -07002187 soinfo* si = find_library(ns, translated_name, flags, extinfo, caller);
Dimitry Ivanov5c4a5802017-03-17 16:41:34 -07002188 loading_trace.End();
2189
Dmitriy Ivanov851135b2014-08-29 12:02:36 -07002190 if (si != nullptr) {
Dimitry Ivanovb996d602016-07-11 18:11:39 -07002191 void* handle = si->to_handle();
2192 LD_LOG(kLogDlopen,
Dimitry Ivanovae4a0c12016-11-21 10:44:35 -08002193 "... dlopen calling constructors: realpath=\"%s\", soname=\"%s\", handle=%p",
2194 si->get_realpath(), si->get_soname(), handle);
2195 si->call_constructors();
Tom Cherryb8ab6182017-04-05 16:20:29 -07002196 failure_guard.Disable();
Dimitry Ivanovae4a0c12016-11-21 10:44:35 -08002197 LD_LOG(kLogDlopen,
Dimitry Ivanovb996d602016-07-11 18:11:39 -07002198 "... dlopen successful: realpath=\"%s\", soname=\"%s\", handle=%p",
2199 si->get_realpath(), si->get_soname(), handle);
2200 return handle;
Elliott Hughesd23736e2012-11-01 15:16:56 -07002201 }
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002202
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002203 return nullptr;
Elliott Hughesd23736e2012-11-01 15:16:56 -07002204}
2205
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -08002206int do_dladdr(const void* addr, Dl_info* info) {
2207 // Determine if this address can be found in any library currently mapped.
2208 soinfo* si = find_containing_library(addr);
2209 if (si == nullptr) {
2210 return 0;
2211 }
2212
2213 memset(info, 0, sizeof(Dl_info));
2214
2215 info->dli_fname = si->get_realpath();
2216 // Address at which the shared object is loaded.
2217 info->dli_fbase = reinterpret_cast<void*>(si->base);
2218
2219 // Determine if any symbol in the library contains the specified address.
2220 ElfW(Sym)* sym = si->find_symbol_by_address(addr);
2221 if (sym != nullptr) {
2222 info->dli_sname = si->get_string(sym->st_name);
2223 info->dli_saddr = reinterpret_cast<void*>(si->resolve_symbol_address(sym));
2224 }
2225
2226 return 1;
2227}
2228
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002229static soinfo* soinfo_from_handle(void* handle) {
2230 if ((reinterpret_cast<uintptr_t>(handle) & 1) != 0) {
2231 auto it = g_soinfo_handles_map.find(reinterpret_cast<uintptr_t>(handle));
2232 if (it == g_soinfo_handles_map.end()) {
2233 return nullptr;
2234 } else {
2235 return it->second;
2236 }
2237 }
2238
2239 return static_cast<soinfo*>(handle);
2240}
2241
Dimitry Ivanovd9e427c2016-11-22 16:55:25 -08002242bool do_dlsym(void* handle,
2243 const char* sym_name,
2244 const char* sym_ver,
2245 const void* caller_addr,
2246 void** symbol) {
Dimitry Ivanov6705e8c2017-03-21 10:29:06 -07002247 ScopedTrace trace("dlsym");
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -08002248#if !defined(__LP64__)
2249 if (handle == nullptr) {
2250 DL_ERR("dlsym failed: library handle is null");
2251 return false;
2252 }
2253#endif
2254
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -08002255 soinfo* found = nullptr;
2256 const ElfW(Sym)* sym = nullptr;
2257 soinfo* caller = find_containing_library(caller_addr);
Dimitry Ivanovaca299a2016-04-11 12:42:58 -07002258 android_namespace_t* ns = get_caller_namespace(caller);
Dimitry Ivanov4742abd2016-12-12 16:30:15 -08002259 soinfo* si = nullptr;
2260 if (handle != RTLD_DEFAULT && handle != RTLD_NEXT) {
2261 si = soinfo_from_handle(handle);
2262 }
2263
2264 LD_LOG(kLogDlsym,
2265 "dlsym(handle=%p(\"%s\"), sym_name=\"%s\", sym_ver=\"%s\", caller=\"%s\", caller_ns=%s@%p) ...",
2266 handle,
2267 si != nullptr ? si->get_realpath() : "n/a",
2268 sym_name,
2269 sym_ver,
2270 caller == nullptr ? "(null)" : caller->get_realpath(),
2271 ns == nullptr ? "(null)" : ns->get_name(),
2272 ns);
2273
Tom Cherryb8ab6182017-04-05 16:20:29 -07002274 auto failure_guard = android::base::make_scope_guard(
2275 [&]() { LD_LOG(kLogDlsym, "... dlsym failed: %s", linker_get_error_buffer()); });
Dimitry Ivanov4742abd2016-12-12 16:30:15 -08002276
2277 if (sym_name == nullptr) {
2278 DL_ERR("dlsym failed: symbol name is null");
2279 return false;
2280 }
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -08002281
2282 version_info vi_instance;
2283 version_info* vi = nullptr;
2284
2285 if (sym_ver != nullptr) {
Dimitry Ivanov9cf99cb2015-12-11 14:22:24 -08002286 vi_instance.name = sym_ver;
2287 vi_instance.elf_hash = calculate_elf_hash(sym_ver);
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -08002288 vi = &vi_instance;
2289 }
2290
2291 if (handle == RTLD_DEFAULT || handle == RTLD_NEXT) {
2292 sym = dlsym_linear_lookup(ns, sym_name, vi, &found, caller, handle);
2293 } else {
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002294 if (si == nullptr) {
2295 DL_ERR("dlsym failed: invalid handle: %p", handle);
2296 return false;
2297 }
2298 sym = dlsym_handle_lookup(si, &found, sym_name, vi);
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -08002299 }
2300
2301 if (sym != nullptr) {
2302 uint32_t bind = ELF_ST_BIND(sym->st_info);
2303
2304 if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) {
2305 *symbol = reinterpret_cast<void*>(found->resolve_symbol_address(sym));
Tom Cherryb8ab6182017-04-05 16:20:29 -07002306 failure_guard.Disable();
Dimitry Ivanov4742abd2016-12-12 16:30:15 -08002307 LD_LOG(kLogDlsym,
2308 "... dlsym successful: sym_name=\"%s\", sym_ver=\"%s\", found in=\"%s\", address=%p",
2309 sym_name, sym_ver, found->get_soname(), *symbol);
Dimitry Ivanov4a2c5aa2015-12-10 16:08:14 -08002310 return true;
2311 }
2312
2313 DL_ERR("symbol \"%s\" found but not global", symbol_display_name(sym_name, sym_ver).c_str());
2314 return false;
2315 }
2316
2317 DL_ERR("undefined symbol: %s", symbol_display_name(sym_name, sym_ver).c_str());
2318 return false;
2319}
2320
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002321int do_dlclose(void* handle) {
Dimitry Ivanov6705e8c2017-03-21 10:29:06 -07002322 ScopedTrace trace("dlclose");
Dmitriy Ivanov279a22f2015-01-23 12:03:53 -08002323 ProtectedDataGuard guard;
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002324 soinfo* si = soinfo_from_handle(handle);
2325 if (si == nullptr) {
2326 DL_ERR("invalid handle: %p", handle);
2327 return -1;
2328 }
2329
dimitryc92ce712017-10-27 14:12:53 +02002330 LD_LOG(kLogDlopen,
2331 "dlclose(handle=%p, realpath=\"%s\"@%p) ...",
2332 handle,
2333 si->get_realpath(),
2334 si);
Dmitriy Ivanovb648a8a2014-05-19 15:06:58 -07002335 soinfo_unload(si);
dimitryc92ce712017-10-27 14:12:53 +02002336 LD_LOG(kLogDlopen,
2337 "dlclose(handle=%p) ... done",
2338 handle);
Dimitry Ivanovd88e1f32016-03-24 15:30:30 -07002339 return 0;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002340}
2341
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08002342bool init_anonymous_namespace(const char* shared_lib_sonames, const char* library_search_path) {
2343 if (g_anonymous_namespace_initialized) {
2344 DL_ERR("anonymous namespace has already been initialized.");
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002345 return false;
2346 }
2347
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002348 ProtectedDataGuard guard;
2349
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08002350 // create anonymous namespace
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08002351 // When the caller is nullptr - create_namespace will take global group
2352 // from the anonymous namespace, which is fine because anonymous namespace
2353 // is still pointing to the default one.
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08002354 android_namespace_t* anon_ns =
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08002355 create_namespace(nullptr,
2356 "(anonymous)",
2357 nullptr,
2358 library_search_path,
Dimitry Ivanovc9dced22017-03-27 15:42:17 -07002359 ANDROID_NAMESPACE_TYPE_ISOLATED,
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08002360 nullptr,
2361 &g_default_namespace);
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08002362
2363 if (anon_ns == nullptr) {
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08002364 return false;
2365 }
2366
2367 if (!link_namespaces(anon_ns, &g_default_namespace, shared_lib_sonames)) {
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08002368 return false;
2369 }
Dimitry Ivanov7d429d32017-02-01 15:28:52 -08002370
Dmitriy Ivanov1ffec1c2015-11-23 11:26:35 -08002371 g_anonymous_namespace = anon_ns;
Dimitry Ivanov3e0821d2017-03-07 11:02:10 -08002372 g_anonymous_namespace_initialized = true;
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08002373
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002374 return true;
2375}
2376
Dimitry Ivanovb943f302016-08-03 16:00:10 -07002377static void add_soinfos_to_namespace(const soinfo_list_t& soinfos, android_namespace_t* ns) {
2378 ns->add_soinfos(soinfos);
2379 for (auto si : soinfos) {
2380 si->add_secondary_namespace(ns);
2381 }
2382}
2383
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08002384android_namespace_t* create_namespace(const void* caller_addr,
2385 const char* name,
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002386 const char* ld_library_path,
2387 const char* default_library_path,
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08002388 uint64_t type,
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07002389 const char* permitted_when_isolated_path,
2390 android_namespace_t* parent_namespace) {
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07002391 if (parent_namespace == nullptr) {
Dimitry Ivanov52408632016-05-23 10:31:11 -07002392 // if parent_namespace is nullptr -> set it to the caller namespace
2393 soinfo* caller_soinfo = find_containing_library(caller_addr);
2394
2395 parent_namespace = caller_soinfo != nullptr ?
2396 caller_soinfo->get_primary_namespace() :
2397 g_anonymous_namespace;
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07002398 }
2399
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002400 ProtectedDataGuard guard;
2401 std::vector<std::string> ld_library_paths;
2402 std::vector<std::string> default_library_paths;
Dimitry Ivanov284ae352015-12-08 10:47:13 -08002403 std::vector<std::string> permitted_paths;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002404
2405 parse_path(ld_library_path, ":", &ld_library_paths);
2406 parse_path(default_library_path, ":", &default_library_paths);
Dimitry Ivanov284ae352015-12-08 10:47:13 -08002407 parse_path(permitted_when_isolated_path, ":", &permitted_paths);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002408
2409 android_namespace_t* ns = new (g_namespace_allocator.alloc()) android_namespace_t();
2410 ns->set_name(name);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08002411 ns->set_isolated((type & ANDROID_NAMESPACE_TYPE_ISOLATED) != 0);
Jiyong Park37b91af2017-05-05 22:07:05 +09002412 ns->set_greylist_enabled((type & ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED) != 0);
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002413
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08002414 if ((type & ANDROID_NAMESPACE_TYPE_SHARED) != 0) {
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07002415 // append parent namespace paths.
2416 std::copy(parent_namespace->get_ld_library_paths().begin(),
2417 parent_namespace->get_ld_library_paths().end(),
2418 back_inserter(ld_library_paths));
2419
2420 std::copy(parent_namespace->get_default_library_paths().begin(),
2421 parent_namespace->get_default_library_paths().end(),
2422 back_inserter(default_library_paths));
2423
2424 std::copy(parent_namespace->get_permitted_paths().begin(),
2425 parent_namespace->get_permitted_paths().end(),
2426 back_inserter(permitted_paths));
2427
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07002428 // If shared - clone the parent namespace
Dimitry Ivanovb943f302016-08-03 16:00:10 -07002429 add_soinfos_to_namespace(parent_namespace->soinfo_list(), ns);
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07002430 // and copy parent namespace links
2431 for (auto& link : parent_namespace->linked_namespaces()) {
Logan Chien9ee45912018-01-18 12:05:09 +08002432 ns->add_linked_namespace(link.linked_namespace(), link.shared_lib_sonames(),
2433 link.allow_all_shared_libs());
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07002434 }
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08002435 } else {
Dimitry Ivanovfc2da532016-05-12 15:20:21 -07002436 // If not shared - copy only the shared group
Jiyong Park02586a22017-05-20 01:01:24 +09002437 add_soinfos_to_namespace(parent_namespace->get_shared_group(), ns);
Dimitry Ivanov7331fe12015-12-14 14:11:17 -08002438 }
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002439
Dimitry Ivanovf1cb6692017-05-01 17:45:38 -07002440 ns->set_ld_library_paths(std::move(ld_library_paths));
2441 ns->set_default_library_paths(std::move(default_library_paths));
2442 ns->set_permitted_paths(std::move(permitted_paths));
2443
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07002444 return ns;
2445}
2446
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08002447bool link_namespaces(android_namespace_t* namespace_from,
2448 android_namespace_t* namespace_to,
2449 const char* shared_lib_sonames) {
2450 if (namespace_to == nullptr) {
2451 namespace_to = &g_default_namespace;
2452 }
2453
2454 if (namespace_from == nullptr) {
2455 DL_ERR("error linking namespaces: namespace_from is null.");
2456 return false;
2457 }
2458
2459 if (shared_lib_sonames == nullptr || shared_lib_sonames[0] == '\0') {
2460 DL_ERR("error linking namespaces \"%s\"->\"%s\": the list of shared libraries is empty.",
2461 namespace_from->get_name(), namespace_to->get_name());
2462 return false;
2463 }
2464
2465 auto sonames = android::base::Split(shared_lib_sonames, ":");
2466 std::unordered_set<std::string> sonames_set(sonames.begin(), sonames.end());
2467
2468 ProtectedDataGuard guard;
Logan Chien9ee45912018-01-18 12:05:09 +08002469 namespace_from->add_linked_namespace(namespace_to, sonames_set, false);
2470
2471 return true;
2472}
2473
2474bool link_namespaces_all_libs(android_namespace_t* namespace_from,
2475 android_namespace_t* namespace_to) {
2476 if (namespace_from == nullptr) {
2477 DL_ERR("error linking namespaces: namespace_from is null.");
2478 return false;
2479 }
2480
2481 if (namespace_to == nullptr) {
2482 DL_ERR("error linking namespaces: namespace_to is null.");
2483 return false;
2484 }
2485
2486 ProtectedDataGuard guard;
2487 namespace_from->add_linked_namespace(namespace_to, std::unordered_set<std::string>(), true);
Dimitry Ivanov7a34b9d2017-02-03 14:07:34 -08002488
2489 return true;
2490}
2491
Dimitry Ivanov48ec2882016-08-04 11:50:36 -07002492ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr) {
Dmitriy Ivanov9aea1642014-09-11 15:16:03 -07002493 typedef ElfW(Addr) (*ifunc_resolver_t)(void);
2494 ifunc_resolver_t ifunc_resolver = reinterpret_cast<ifunc_resolver_t>(resolver_addr);
2495 ElfW(Addr) ifunc_addr = ifunc_resolver();
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002496 TRACE_TYPE(RELO, "Called ifunc_resolver@%p. The result is %p",
2497 ifunc_resolver, reinterpret_cast<void*>(ifunc_addr));
Brigid Smithc5a13ef2014-07-23 11:22:25 -07002498
Dmitriy Ivanov9aea1642014-09-11 15:16:03 -07002499 return ifunc_addr;
Brigid Smithc5a13ef2014-07-23 11:22:25 -07002500}
Brigid Smithc5a13ef2014-07-23 11:22:25 -07002501
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07002502const version_info* VersionTracker::get_version_info(ElfW(Versym) source_symver) const {
2503 if (source_symver < 2 ||
2504 source_symver >= version_infos.size() ||
2505 version_infos[source_symver].name == nullptr) {
2506 return nullptr;
2507 }
2508
2509 return &version_infos[source_symver];
2510}
2511
2512void VersionTracker::add_version_info(size_t source_index,
2513 ElfW(Word) elf_hash,
2514 const char* ver_name,
2515 const soinfo* target_si) {
2516 if (source_index >= version_infos.size()) {
2517 version_infos.resize(source_index+1);
2518 }
2519
2520 version_infos[source_index].elf_hash = elf_hash;
2521 version_infos[source_index].name = ver_name;
2522 version_infos[source_index].target_si = target_si;
2523}
2524
2525bool VersionTracker::init_verneed(const soinfo* si_from) {
2526 uintptr_t verneed_ptr = si_from->get_verneed_ptr();
2527
2528 if (verneed_ptr == 0) {
2529 return true;
2530 }
2531
2532 size_t verneed_cnt = si_from->get_verneed_cnt();
2533
2534 for (size_t i = 0, offset = 0; i<verneed_cnt; ++i) {
2535 const ElfW(Verneed)* verneed = reinterpret_cast<ElfW(Verneed)*>(verneed_ptr + offset);
2536 size_t vernaux_offset = offset + verneed->vn_aux;
2537 offset += verneed->vn_next;
2538
2539 if (verneed->vn_version != 1) {
2540 DL_ERR("unsupported verneed[%zd] vn_version: %d (expected 1)", i, verneed->vn_version);
2541 return false;
2542 }
2543
2544 const char* target_soname = si_from->get_string(verneed->vn_file);
2545 // find it in dependencies
2546 soinfo* target_si = si_from->get_children().find_if([&](const soinfo* si) {
Dmitriy Ivanov406d9962015-05-06 11:05:27 -07002547 return si->get_soname() != nullptr && strcmp(si->get_soname(), target_soname) == 0;
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07002548 });
2549
2550 if (target_si == nullptr) {
2551 DL_ERR("cannot find \"%s\" from verneed[%zd] in DT_NEEDED list for \"%s\"",
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07002552 target_soname, i, si_from->get_realpath());
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07002553 return false;
2554 }
2555
2556 for (size_t j = 0; j<verneed->vn_cnt; ++j) {
2557 const ElfW(Vernaux)* vernaux = reinterpret_cast<ElfW(Vernaux)*>(verneed_ptr + vernaux_offset);
2558 vernaux_offset += vernaux->vna_next;
2559
2560 const ElfW(Word) elf_hash = vernaux->vna_hash;
2561 const char* ver_name = si_from->get_string(vernaux->vna_name);
2562 ElfW(Half) source_index = vernaux->vna_other;
2563
2564 add_version_info(source_index, elf_hash, ver_name, target_si);
2565 }
2566 }
2567
2568 return true;
2569}
2570
Dimitry Ivanov48ec2882016-08-04 11:50:36 -07002571template <typename F>
2572static bool for_each_verdef(const soinfo* si, F functor) {
2573 if (!si->has_min_version(2)) {
2574 return true;
2575 }
2576
2577 uintptr_t verdef_ptr = si->get_verdef_ptr();
2578 if (verdef_ptr == 0) {
2579 return true;
2580 }
2581
2582 size_t offset = 0;
2583
2584 size_t verdef_cnt = si->get_verdef_cnt();
2585 for (size_t i = 0; i<verdef_cnt; ++i) {
2586 const ElfW(Verdef)* verdef = reinterpret_cast<ElfW(Verdef)*>(verdef_ptr + offset);
2587 size_t verdaux_offset = offset + verdef->vd_aux;
2588 offset += verdef->vd_next;
2589
2590 if (verdef->vd_version != 1) {
2591 DL_ERR("unsupported verdef[%zd] vd_version: %d (expected 1) library: %s",
2592 i, verdef->vd_version, si->get_realpath());
2593 return false;
2594 }
2595
2596 if ((verdef->vd_flags & VER_FLG_BASE) != 0) {
2597 // "this is the version of the file itself. It must not be used for
2598 // matching a symbol. It can be used to match references."
2599 //
2600 // http://www.akkadia.org/drepper/symbol-versioning
2601 continue;
2602 }
2603
2604 if (verdef->vd_cnt == 0) {
2605 DL_ERR("invalid verdef[%zd] vd_cnt == 0 (version without a name)", i);
2606 return false;
2607 }
2608
2609 const ElfW(Verdaux)* verdaux = reinterpret_cast<ElfW(Verdaux)*>(verdef_ptr + verdaux_offset);
2610
2611 if (functor(i, verdef, verdaux) == true) {
2612 break;
2613 }
2614 }
2615
2616 return true;
2617}
2618
2619bool find_verdef_version_index(const soinfo* si, const version_info* vi, ElfW(Versym)* versym) {
2620 if (vi == nullptr) {
2621 *versym = kVersymNotNeeded;
2622 return true;
2623 }
2624
2625 *versym = kVersymGlobal;
2626
2627 return for_each_verdef(si,
2628 [&](size_t, const ElfW(Verdef)* verdef, const ElfW(Verdaux)* verdaux) {
2629 if (verdef->vd_hash == vi->elf_hash &&
2630 strcmp(vi->name, si->get_string(verdaux->vda_name)) == 0) {
2631 *versym = verdef->vd_ndx;
2632 return true;
2633 }
2634
2635 return false;
2636 }
2637 );
2638}
2639
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07002640bool VersionTracker::init_verdef(const soinfo* si_from) {
2641 return for_each_verdef(si_from,
2642 [&](size_t, const ElfW(Verdef)* verdef, const ElfW(Verdaux)* verdaux) {
2643 add_version_info(verdef->vd_ndx, verdef->vd_hash,
2644 si_from->get_string(verdaux->vda_name), si_from);
2645 return false;
2646 }
2647 );
2648}
2649
2650bool VersionTracker::init(const soinfo* si_from) {
2651 if (!si_from->has_min_version(2)) {
2652 return true;
2653 }
2654
2655 return init_verneed(si_from) && init_verdef(si_from);
2656}
2657
Dimitry Ivanov48ec2882016-08-04 11:50:36 -07002658// TODO (dimitry): Methods below need to be moved out of soinfo
2659// and in more isolated file in order minimize dependencies on
2660// unnecessary object in the linker binary. Consider making them
2661// independent from soinfo (?).
Dmitriy Ivanov31b408d2015-04-30 16:11:48 -07002662bool soinfo::lookup_version_info(const VersionTracker& version_tracker, ElfW(Word) sym,
2663 const char* sym_name, const version_info** vi) {
2664 const ElfW(Versym)* sym_ver_ptr = get_versym(sym);
2665 ElfW(Versym) sym_ver = sym_ver_ptr == nullptr ? 0 : *sym_ver_ptr;
2666
2667 if (sym_ver != VER_NDX_LOCAL && sym_ver != VER_NDX_GLOBAL) {
2668 *vi = version_tracker.get_version_info(sym_ver);
2669
2670 if (*vi == nullptr) {
2671 DL_ERR("cannot find verneed/verdef for version index=%d "
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07002672 "referenced by symbol \"%s\" at \"%s\"", sym_ver, sym_name, get_realpath());
Dmitriy Ivanov31b408d2015-04-30 16:11:48 -07002673 return false;
2674 }
2675 } else {
2676 // there is no version info
2677 *vi = nullptr;
2678 }
2679
2680 return true;
2681}
2682
Rahul Chaudhryf16b6592018-01-25 15:34:15 -08002683void soinfo::apply_relr_reloc(ElfW(Addr) offset) {
2684 ElfW(Addr) address = offset + load_bias;
2685 *reinterpret_cast<ElfW(Addr)*>(address) += load_bias;
2686}
2687
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08002688// Process relocations in SHT_RELR section (experimental).
Rahul Chaudhryf16b6592018-01-25 15:34:15 -08002689// Details of the encoding are described in this post:
2690// https://groups.google.com/d/msg/generic-abi/bX460iggiKg/Pi9aSwwABgAJ
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08002691bool soinfo::relocate_relr() {
2692 ElfW(Relr)* begin = relr_;
2693 ElfW(Relr)* end = relr_ + relr_count_;
Rahul Chaudhryf16b6592018-01-25 15:34:15 -08002694 constexpr size_t wordsize = sizeof(ElfW(Addr));
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08002695
Rahul Chaudhryf16b6592018-01-25 15:34:15 -08002696 ElfW(Addr) base = 0;
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08002697 for (ElfW(Relr)* current = begin; current < end; ++current) {
Rahul Chaudhryf16b6592018-01-25 15:34:15 -08002698 ElfW(Relr) entry = *current;
2699 ElfW(Addr) offset;
2700
2701 if ((entry&1) == 0) {
2702 // Even entry: encodes the offset for next relocation.
2703 offset = static_cast<ElfW(Addr)>(entry);
2704 apply_relr_reloc(offset);
2705 // Set base offset for subsequent bitmap entries.
2706 base = offset + wordsize;
2707 continue;
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08002708 }
Rahul Chaudhryf16b6592018-01-25 15:34:15 -08002709
2710 // Odd entry: encodes bitmap for relocations starting at base.
2711 offset = base;
2712 while (entry != 0) {
2713 entry >>= 1;
2714 if ((entry&1) != 0) {
2715 apply_relr_reloc(offset);
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08002716 }
Rahul Chaudhryf16b6592018-01-25 15:34:15 -08002717 offset += wordsize;
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08002718 }
Rahul Chaudhryf16b6592018-01-25 15:34:15 -08002719
2720 // Advance base offset by 63 words for 64-bit platforms,
2721 // or 31 words for 32-bit platforms.
2722 base += (8*wordsize - 1) * wordsize;
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08002723 }
2724 return true;
2725}
2726
Dimitry Ivanov576a3752016-08-09 06:58:55 -07002727#if !defined(__mips__)
2728#if defined(USE_RELA)
2729static ElfW(Addr) get_addend(ElfW(Rela)* rela, ElfW(Addr) reloc_addr __unused) {
2730 return rela->r_addend;
2731}
2732#else
2733static ElfW(Addr) get_addend(ElfW(Rel)* rel, ElfW(Addr) reloc_addr) {
2734 if (ELFW(R_TYPE)(rel->r_info) == R_GENERIC_RELATIVE ||
2735 ELFW(R_TYPE)(rel->r_info) == R_GENERIC_IRELATIVE) {
2736 return *reinterpret_cast<ElfW(Addr)*>(reloc_addr);
2737 }
2738 return 0;
2739}
2740#endif
2741
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -08002742template<typename ElfRelIteratorT>
Dmitriy Ivanov7e4bbba2015-04-30 19:49:19 -07002743bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
2744 const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -08002745 for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
2746 const auto rel = rel_iterator.next();
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08002747 if (rel == nullptr) {
2748 return false;
2749 }
2750
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002751 ElfW(Word) type = ELFW(R_TYPE)(rel->r_info);
2752 ElfW(Word) sym = ELFW(R_SYM)(rel->r_info);
2753
2754 ElfW(Addr) reloc = static_cast<ElfW(Addr)>(rel->r_offset + load_bias);
Elliott Hughes0266ae52014-02-10 17:46:57 -08002755 ElfW(Addr) sym_addr = 0;
Dmitriy Ivanov851135b2014-08-29 12:02:36 -07002756 const char* sym_name = nullptr;
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002757 ElfW(Addr) addend = get_addend(rel, reloc);
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07002758
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07002759 DEBUG("Processing \"%s\" relocation at index %zd", get_realpath(), idx);
Dmitriy Ivanovcefef7d2015-01-08 23:30:15 -08002760 if (type == R_GENERIC_NONE) {
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07002761 continue;
2762 }
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07002763
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07002764 const ElfW(Sym)* s = nullptr;
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07002765 soinfo* lsi = nullptr;
2766
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07002767 if (sym != 0) {
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08002768 sym_name = get_string(symtab_[sym].st_name);
Dmitriy Ivanov31b408d2015-04-30 16:11:48 -07002769 const version_info* vi = nullptr;
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07002770
Dmitriy Ivanov31b408d2015-04-30 16:11:48 -07002771 if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
2772 return false;
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07002773 }
Dmitriy Ivanov31b408d2015-04-30 16:11:48 -07002774
2775 if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
2776 return false;
2777 }
2778
Dmitriy Ivanov851135b2014-08-29 12:02:36 -07002779 if (s == nullptr) {
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07002780 // We only allow an undefined symbol if this is a weak reference...
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08002781 s = &symtab_[sym];
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07002782 if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07002783 DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, get_realpath());
Dmitriy Ivanov114ff692015-01-14 11:36:38 -08002784 return false;
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07002785 }
2786
2787 /* IHI0044C AAELF 4.5.1.1:
2788
2789 Libraries are not searched to resolve weak references.
2790 It is not an error for a weak reference to remain unsatisfied.
2791
2792 During linking, the value of an undefined weak reference is:
2793 - Zero if the relocation type is absolute
2794 - The address of the place if the relocation is pc-relative
2795 - The address of nominal base address if the relocation
2796 type is base-relative.
2797 */
2798
2799 switch (type) {
Dmitriy Ivanov1b694692015-01-13 12:17:31 -08002800 case R_GENERIC_JUMP_SLOT:
2801 case R_GENERIC_GLOB_DAT:
2802 case R_GENERIC_RELATIVE:
2803 case R_GENERIC_IRELATIVE:
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002804#if defined(__aarch64__)
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07002805 case R_AARCH64_ABS64:
2806 case R_AARCH64_ABS32:
2807 case R_AARCH64_ABS16:
Dmitriy Ivanov1b694692015-01-13 12:17:31 -08002808#elif defined(__x86_64__)
2809 case R_X86_64_32:
2810 case R_X86_64_64:
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002811#elif defined(__arm__)
2812 case R_ARM_ABS32:
2813#elif defined(__i386__)
2814 case R_386_32:
Dmitriy Ivanov1b694692015-01-13 12:17:31 -08002815#endif
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07002816 /*
2817 * The sym_addr was initialized to be zero above, or the relocation
2818 * code below does not care about value of sym_addr.
2819 * No need to do anything.
2820 */
2821 break;
Dmitriy Ivanov1b694692015-01-13 12:17:31 -08002822#if defined(__x86_64__)
Dimitry Ivanovd338aac2015-01-13 22:31:54 +00002823 case R_X86_64_PC32:
2824 sym_addr = reloc;
2825 break;
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002826#elif defined(__i386__)
2827 case R_386_PC32:
2828 sym_addr = reloc;
2829 break;
2830#endif
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07002831 default:
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002832 DL_ERR("unknown weak reloc type %d @ %p (%zu)", type, rel, idx);
Dmitriy Ivanov114ff692015-01-14 11:36:38 -08002833 return false;
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07002834 }
Dmitriy Ivanovec83a612015-07-26 07:37:09 -07002835 } else { // We got a definition.
2836#if !defined(__LP64__)
2837 // When relocating dso with text_relocation .text segment is
2838 // not executable. We need to restore elf flags before resolving
2839 // STT_GNU_IFUNC symbol.
2840 bool protect_segments = has_text_relocations &&
2841 lsi == this &&
2842 ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC;
2843 if (protect_segments) {
2844 if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
2845 DL_ERR("can't protect segments for \"%s\": %s",
2846 get_realpath(), strerror(errno));
2847 return false;
2848 }
2849 }
2850#endif
Elliott Hughes45a93c12018-03-23 18:46:07 -07002851 if (ELF_ST_TYPE(s->st_info) == STT_TLS) {
2852 DL_ERR("unsupported ELF TLS symbol \"%s\" referenced by \"%s\"",
2853 sym_name, get_realpath());
2854 return false;
2855 }
Dmitriy Ivanov9aea1642014-09-11 15:16:03 -07002856 sym_addr = lsi->resolve_symbol_address(s);
Dmitriy Ivanovec83a612015-07-26 07:37:09 -07002857#if !defined(__LP64__)
2858 if (protect_segments) {
2859 if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
2860 DL_ERR("can't unprotect loadable segments for \"%s\": %s",
2861 get_realpath(), strerror(errno));
2862 return false;
2863 }
2864 }
2865#endif
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07002866 }
2867 count_relocation(kRelocSymbol);
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07002868 }
2869
2870 switch (type) {
Dmitriy Ivanovcefef7d2015-01-08 23:30:15 -08002871 case R_GENERIC_JUMP_SLOT:
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002872 count_relocation(kRelocAbsolute);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002873 MARK(rel->r_offset);
2874 TRACE_TYPE(RELO, "RELO JMP_SLOT %16p <- %16p %s\n",
2875 reinterpret_cast<void*>(reloc),
2876 reinterpret_cast<void*>(sym_addr + addend), sym_name);
2877
2878 *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002879 break;
Dmitriy Ivanovcefef7d2015-01-08 23:30:15 -08002880 case R_GENERIC_GLOB_DAT:
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002881 count_relocation(kRelocAbsolute);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002882 MARK(rel->r_offset);
2883 TRACE_TYPE(RELO, "RELO GLOB_DAT %16p <- %16p %s\n",
2884 reinterpret_cast<void*>(reloc),
2885 reinterpret_cast<void*>(sym_addr + addend), sym_name);
2886 *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002887 break;
Dmitriy Ivanovcefef7d2015-01-08 23:30:15 -08002888 case R_GENERIC_RELATIVE:
2889 count_relocation(kRelocRelative);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002890 MARK(rel->r_offset);
2891 TRACE_TYPE(RELO, "RELO RELATIVE %16p <- %16p\n",
2892 reinterpret_cast<void*>(reloc),
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08002893 reinterpret_cast<void*>(load_bias + addend));
2894 *reinterpret_cast<ElfW(Addr)*>(reloc) = (load_bias + addend);
Dmitriy Ivanovcefef7d2015-01-08 23:30:15 -08002895 break;
Dmitriy Ivanovcefef7d2015-01-08 23:30:15 -08002896 case R_GENERIC_IRELATIVE:
2897 count_relocation(kRelocRelative);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002898 MARK(rel->r_offset);
2899 TRACE_TYPE(RELO, "RELO IRELATIVE %16p <- %16p\n",
2900 reinterpret_cast<void*>(reloc),
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08002901 reinterpret_cast<void*>(load_bias + addend));
Dmitriy Ivanovec83a612015-07-26 07:37:09 -07002902 {
2903#if !defined(__LP64__)
2904 // When relocating dso with text_relocation .text segment is
2905 // not executable. We need to restore elf flags for this
2906 // particular call.
2907 if (has_text_relocations) {
2908 if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
2909 DL_ERR("can't protect segments for \"%s\": %s",
2910 get_realpath(), strerror(errno));
2911 return false;
2912 }
2913 }
2914#endif
2915 ElfW(Addr) ifunc_addr = call_ifunc_resolver(load_bias + addend);
2916#if !defined(__LP64__)
2917 // Unprotect it afterwards...
2918 if (has_text_relocations) {
2919 if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
2920 DL_ERR("can't unprotect loadable segments for \"%s\": %s",
2921 get_realpath(), strerror(errno));
2922 return false;
2923 }
2924 }
2925#endif
2926 *reinterpret_cast<ElfW(Addr)*>(reloc) = ifunc_addr;
2927 }
Dmitriy Ivanovcefef7d2015-01-08 23:30:15 -08002928 break;
2929
2930#if defined(__aarch64__)
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07002931 case R_AARCH64_ABS64:
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002932 count_relocation(kRelocAbsolute);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002933 MARK(rel->r_offset);
Elliott Hughes0266ae52014-02-10 17:46:57 -08002934 TRACE_TYPE(RELO, "RELO ABS64 %16llx <- %16llx %s\n",
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07002935 reloc, sym_addr + addend, sym_name);
2936 *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002937 break;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07002938 case R_AARCH64_ABS32:
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002939 count_relocation(kRelocAbsolute);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002940 MARK(rel->r_offset);
Elliott Hughes0266ae52014-02-10 17:46:57 -08002941 TRACE_TYPE(RELO, "RELO ABS32 %16llx <- %16llx %s\n",
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07002942 reloc, sym_addr + addend, sym_name);
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002943 {
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002944 const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT32_MIN);
2945 const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT32_MAX);
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07002946 if ((min_value <= (sym_addr + addend)) &&
2947 ((sym_addr + addend) <= max_value)) {
2948 *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002949 } else {
2950 DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07002951 sym_addr + addend, min_value, max_value);
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002952 return false;
2953 }
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002954 }
2955 break;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07002956 case R_AARCH64_ABS16:
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002957 count_relocation(kRelocAbsolute);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002958 MARK(rel->r_offset);
Elliott Hughes0266ae52014-02-10 17:46:57 -08002959 TRACE_TYPE(RELO, "RELO ABS16 %16llx <- %16llx %s\n",
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07002960 reloc, sym_addr + addend, sym_name);
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002961 {
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002962 const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT16_MIN);
2963 const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT16_MAX);
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07002964 if ((min_value <= (sym_addr + addend)) &&
2965 ((sym_addr + addend) <= max_value)) {
2966 *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002967 } else {
2968 DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07002969 sym_addr + addend, min_value, max_value);
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002970 return false;
2971 }
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002972 }
2973 break;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07002974 case R_AARCH64_PREL64:
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002975 count_relocation(kRelocRelative);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002976 MARK(rel->r_offset);
Elliott Hughes0266ae52014-02-10 17:46:57 -08002977 TRACE_TYPE(RELO, "RELO REL64 %16llx <- %16llx - %16llx %s\n",
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07002978 reloc, sym_addr + addend, rel->r_offset, sym_name);
2979 *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset;
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002980 break;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07002981 case R_AARCH64_PREL32:
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002982 count_relocation(kRelocRelative);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08002983 MARK(rel->r_offset);
Elliott Hughes0266ae52014-02-10 17:46:57 -08002984 TRACE_TYPE(RELO, "RELO REL32 %16llx <- %16llx - %16llx %s\n",
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07002985 reloc, sym_addr + addend, rel->r_offset, sym_name);
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002986 {
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002987 const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT32_MIN);
2988 const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT32_MAX);
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07002989 if ((min_value <= (sym_addr + addend - rel->r_offset)) &&
2990 ((sym_addr + addend - rel->r_offset) <= max_value)) {
2991 *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset;
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002992 } else {
2993 DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07002994 sym_addr + addend - rel->r_offset, min_value, max_value);
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07002995 return false;
2996 }
Marcus Oaklande365f9d2013-10-10 15:19:31 +01002997 }
2998 break;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07002999 case R_AARCH64_PREL16:
Marcus Oaklande365f9d2013-10-10 15:19:31 +01003000 count_relocation(kRelocRelative);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08003001 MARK(rel->r_offset);
Elliott Hughes0266ae52014-02-10 17:46:57 -08003002 TRACE_TYPE(RELO, "RELO REL16 %16llx <- %16llx - %16llx %s\n",
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07003003 reloc, sym_addr + addend, rel->r_offset, sym_name);
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07003004 {
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07003005 const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT16_MIN);
3006 const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT16_MAX);
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07003007 if ((min_value <= (sym_addr + addend - rel->r_offset)) &&
3008 ((sym_addr + addend - rel->r_offset) <= max_value)) {
3009 *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset;
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07003010 } else {
3011 DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
Dmitriy Ivanov77f91c62015-10-15 13:26:03 -07003012 sym_addr + addend - rel->r_offset, min_value, max_value);
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07003013 return false;
3014 }
Marcus Oaklande365f9d2013-10-10 15:19:31 +01003015 }
3016 break;
3017
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003018 case R_AARCH64_COPY:
Nick Kralevich76e289c2014-07-03 12:04:31 -07003019 /*
3020 * ET_EXEC is not supported so this should not happen.
3021 *
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003022 * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
Nick Kralevich76e289c2014-07-03 12:04:31 -07003023 *
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003024 * Section 4.6.11 "Dynamic relocations"
Nick Kralevich76e289c2014-07-03 12:04:31 -07003025 * R_AARCH64_COPY may only appear in executable objects where e_type is
3026 * set to ET_EXEC.
3027 */
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07003028 DL_ERR("%s R_AARCH64_COPY relocations are not supported", get_realpath());
Dmitriy Ivanov114ff692015-01-14 11:36:38 -08003029 return false;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003030 case R_AARCH64_TLS_TPREL64:
Elliott Hughes0266ae52014-02-10 17:46:57 -08003031 TRACE_TYPE(RELO, "RELO TLS_TPREL64 *** %16llx <- %16llx - %16llx\n",
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08003032 reloc, (sym_addr + addend), rel->r_offset);
Marcus Oaklande365f9d2013-10-10 15:19:31 +01003033 break;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003034 case R_AARCH64_TLS_DTPREL32:
Elliott Hughes0266ae52014-02-10 17:46:57 -08003035 TRACE_TYPE(RELO, "RELO TLS_DTPREL32 *** %16llx <- %16llx - %16llx\n",
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08003036 reloc, (sym_addr + addend), rel->r_offset);
Marcus Oaklande365f9d2013-10-10 15:19:31 +01003037 break;
3038#elif defined(__x86_64__)
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003039 case R_X86_64_32:
3040 count_relocation(kRelocRelative);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08003041 MARK(rel->r_offset);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003042 TRACE_TYPE(RELO, "RELO R_X86_64_32 %08zx <- +%08zx %s", static_cast<size_t>(reloc),
3043 static_cast<size_t>(sym_addr), sym_name);
Junichi Uekawaff35b1e2015-11-18 10:18:59 +09003044 *reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr + addend;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003045 break;
3046 case R_X86_64_64:
3047 count_relocation(kRelocRelative);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08003048 MARK(rel->r_offset);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003049 TRACE_TYPE(RELO, "RELO R_X86_64_64 %08zx <- +%08zx %s", static_cast<size_t>(reloc),
3050 static_cast<size_t>(sym_addr), sym_name);
Junichi Uekawaff35b1e2015-11-18 10:18:59 +09003051 *reinterpret_cast<Elf64_Addr*>(reloc) = sym_addr + addend;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003052 break;
3053 case R_X86_64_PC32:
3054 count_relocation(kRelocRelative);
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08003055 MARK(rel->r_offset);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003056 TRACE_TYPE(RELO, "RELO R_X86_64_PC32 %08zx <- +%08zx (%08zx - %08zx) %s",
3057 static_cast<size_t>(reloc), static_cast<size_t>(sym_addr - reloc),
3058 static_cast<size_t>(sym_addr), static_cast<size_t>(reloc), sym_name);
Junichi Uekawaff35b1e2015-11-18 10:18:59 +09003059 *reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr + addend - reloc;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003060 break;
Dmitriy Ivanovbcc04d02015-01-13 12:12:38 -08003061#elif defined(__arm__)
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003062 case R_ARM_ABS32:
3063 count_relocation(kRelocAbsolute);
3064 MARK(rel->r_offset);
3065 TRACE_TYPE(RELO, "RELO ABS %08x <- %08x %s", reloc, sym_addr, sym_name);
3066 *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr;
3067 break;
3068 case R_ARM_REL32:
3069 count_relocation(kRelocRelative);
3070 MARK(rel->r_offset);
3071 TRACE_TYPE(RELO, "RELO REL32 %08x <- %08x - %08x %s",
3072 reloc, sym_addr, rel->r_offset, sym_name);
3073 *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr - rel->r_offset;
3074 break;
3075 case R_ARM_COPY:
3076 /*
3077 * ET_EXEC is not supported so this should not happen.
3078 *
3079 * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
3080 *
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003081 * Section 4.6.1.10 "Dynamic relocations"
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003082 * R_ARM_COPY may only appear in executable objects where e_type is
3083 * set to ET_EXEC.
3084 */
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07003085 DL_ERR("%s R_ARM_COPY relocations are not supported", get_realpath());
Dmitriy Ivanov114ff692015-01-14 11:36:38 -08003086 return false;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003087#elif defined(__i386__)
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003088 case R_386_32:
3089 count_relocation(kRelocRelative);
3090 MARK(rel->r_offset);
3091 TRACE_TYPE(RELO, "RELO R_386_32 %08x <- +%08x %s", reloc, sym_addr, sym_name);
3092 *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr;
3093 break;
3094 case R_386_PC32:
3095 count_relocation(kRelocRelative);
3096 MARK(rel->r_offset);
3097 TRACE_TYPE(RELO, "RELO R_386_PC32 %08x <- +%08x (%08x - %08x) %s",
3098 reloc, (sym_addr - reloc), sym_addr, reloc, sym_name);
3099 *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr - reloc);
3100 break;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003101#endif
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003102 default:
3103 DL_ERR("unknown reloc type %d @ %p (%zu)", type, rel, idx);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003104 return false;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003105 }
3106 }
3107 return true;
Raghu Gandhamd7daacb2012-07-31 12:07:22 -07003108}
Dmitriy Ivanov114ff692015-01-14 11:36:38 -08003109#endif // !defined(__mips__)
Raghu Gandhamd7daacb2012-07-31 12:07:22 -07003110
Dimitry Ivanov48ec2882016-08-04 11:50:36 -07003111// An empty list of soinfos
Dimitry Ivanovb943f302016-08-03 16:00:10 -07003112static soinfo_list_t g_empty_list;
Dmitriy Ivanovd59e5002014-05-09 09:10:14 -07003113
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003114bool soinfo::prelink_image() {
Ningsheng Jiane93be992014-09-16 15:22:10 +08003115 /* Extract dynamic section */
3116 ElfW(Word) dynamic_flags = 0;
3117 phdr_table_get_dynamic_section(phdr, phnum, load_bias, &dynamic, &dynamic_flags);
Dmitriy Ivanov498eb182014-09-05 14:57:59 -07003118
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003119 /* We can't log anything until the linker is relocated */
Dmitriy Ivanovab972b92014-11-29 13:57:41 -08003120 bool relocating_linker = (flags_ & FLAG_LINKER) != 0;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003121 if (!relocating_linker) {
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07003122 INFO("[ Linking \"%s\" ]", get_realpath());
Dmitriy Ivanovab972b92014-11-29 13:57:41 -08003123 DEBUG("si->base = %p si->flags = 0x%08x", reinterpret_cast<void*>(base), flags_);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003124 }
3125
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003126 if (dynamic == nullptr) {
David 'Digit' Turnerb52e4382012-06-19 01:24:17 +02003127 if (!relocating_linker) {
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07003128 DL_ERR("missing PT_DYNAMIC in \"%s\"", get_realpath());
David 'Digit' Turnerb52e4382012-06-19 01:24:17 +02003129 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003130 return false;
3131 } else {
3132 if (!relocating_linker) {
3133 DEBUG("dynamic = %p", dynamic);
David 'Digit' Turner63f99f42012-06-19 00:08:39 +02003134 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003135 }
David 'Digit' Turner63f99f42012-06-19 00:08:39 +02003136
Elliott Hughes4eeb1f12013-10-25 17:38:02 -07003137#if defined(__arm__)
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003138 (void) phdr_table_get_arm_exidx(phdr, phnum, load_bias,
3139 &ARM_exidx, &ARM_exidx_count);
David 'Digit' Turner63f99f42012-06-19 00:08:39 +02003140#endif
3141
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003142 // Extract useful information from dynamic section.
Dmitriy Ivanov618f1a32015-03-17 20:06:36 -07003143 // Note that: "Except for the DT_NULL element at the end of the array,
3144 // and the relative order of DT_NEEDED elements, entries may appear in any order."
3145 //
3146 // source: http://www.sco.com/developers/gabi/1998-04-29/ch5.dynamic.html
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003147 uint32_t needed_count = 0;
3148 for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
3149 DEBUG("d = %p, d[0](tag) = %p d[1](val) = %p",
3150 d, reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
3151 switch (d->d_tag) {
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003152 case DT_SONAME:
Dmitriy Ivanov618f1a32015-03-17 20:06:36 -07003153 // this is parsed after we have strtab initialized (see below).
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003154 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003155
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003156 case DT_HASH:
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003157 nbucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
3158 nchain_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
3159 bucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8);
3160 chain_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8 + nbucket_ * 4);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003161 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003162
Dmitriy Ivanovec18ce02014-11-09 19:27:20 -08003163 case DT_GNU_HASH:
Dmitriy Ivanov3597b802015-03-09 12:02:02 -07003164 gnu_nbucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
Dmitriy Ivanovec18ce02014-11-09 19:27:20 -08003165 // skip symndx
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003166 gnu_maskwords_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[2];
3167 gnu_shift2_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[3];
Dmitriy Ivanovec18ce02014-11-09 19:27:20 -08003168
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003169 gnu_bloom_filter_ = reinterpret_cast<ElfW(Addr)*>(load_bias + d->d_un.d_ptr + 16);
Dmitriy Ivanov3597b802015-03-09 12:02:02 -07003170 gnu_bucket_ = reinterpret_cast<uint32_t*>(gnu_bloom_filter_ + gnu_maskwords_);
Dmitriy Ivanovec18ce02014-11-09 19:27:20 -08003171 // amend chain for symndx = header[1]
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07003172 gnu_chain_ = gnu_bucket_ + gnu_nbucket_ -
3173 reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
Dmitriy Ivanovec18ce02014-11-09 19:27:20 -08003174
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003175 if (!powerof2(gnu_maskwords_)) {
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07003176 DL_ERR("invalid maskwords for gnu_hash = 0x%x, in \"%s\" expecting power to two",
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003177 gnu_maskwords_, get_realpath());
Dmitriy Ivanovec18ce02014-11-09 19:27:20 -08003178 return false;
3179 }
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003180 --gnu_maskwords_;
Dmitriy Ivanovec18ce02014-11-09 19:27:20 -08003181
Dmitriy Ivanovab972b92014-11-29 13:57:41 -08003182 flags_ |= FLAG_GNU_HASH;
Dmitriy Ivanovec18ce02014-11-09 19:27:20 -08003183 break;
3184
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003185 case DT_STRTAB:
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003186 strtab_ = reinterpret_cast<const char*>(load_bias + d->d_un.d_ptr);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003187 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003188
Dmitriy Ivanov6cdeb522014-09-29 19:14:45 -07003189 case DT_STRSZ:
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003190 strtab_size_ = d->d_un.d_val;
Dmitriy Ivanov6cdeb522014-09-29 19:14:45 -07003191 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003192
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003193 case DT_SYMTAB:
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003194 symtab_ = reinterpret_cast<ElfW(Sym)*>(load_bias + d->d_un.d_ptr);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003195 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003196
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003197 case DT_SYMENT:
3198 if (d->d_un.d_val != sizeof(ElfW(Sym))) {
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003199 DL_ERR("invalid DT_SYMENT: %zd in \"%s\"",
3200 static_cast<size_t>(d->d_un.d_val), get_realpath());
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003201 return false;
3202 }
3203 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003204
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003205 case DT_PLTREL:
Dmitriy Ivanov513e29e2014-10-06 11:30:43 -07003206#if defined(USE_RELA)
3207 if (d->d_un.d_val != DT_RELA) {
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003208 DL_ERR("unsupported DT_PLTREL in \"%s\"; expected DT_RELA", get_realpath());
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003209 return false;
3210 }
Dmitriy Ivanov513e29e2014-10-06 11:30:43 -07003211#else
3212 if (d->d_un.d_val != DT_REL) {
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003213 DL_ERR("unsupported DT_PLTREL in \"%s\"; expected DT_REL", get_realpath());
Dmitriy Ivanov513e29e2014-10-06 11:30:43 -07003214 return false;
3215 }
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07003216#endif
Dmitriy Ivanov513e29e2014-10-06 11:30:43 -07003217 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003218
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003219 case DT_JMPREL:
Elliott Hughes4eeb1f12013-10-25 17:38:02 -07003220#if defined(USE_RELA)
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003221 plt_rela_ = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07003222#else
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003223 plt_rel_ = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07003224#endif
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003225 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003226
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003227 case DT_PLTRELSZ:
Elliott Hughes4eeb1f12013-10-25 17:38:02 -07003228#if defined(USE_RELA)
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003229 plt_rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela));
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07003230#else
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003231 plt_rel_count_ = d->d_un.d_val / sizeof(ElfW(Rel));
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07003232#endif
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003233 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003234
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003235 case DT_PLTGOT:
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003236#if defined(__mips__)
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003237 // Used by mips and mips64.
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003238 plt_got_ = reinterpret_cast<ElfW(Addr)**>(load_bias + d->d_un.d_ptr);
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07003239#endif
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003240 // Ignore for other platforms... (because RTLD_LAZY is not supported)
3241 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003242
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003243 case DT_DEBUG:
3244 // Set the DT_DEBUG entry to the address of _r_debug for GDB
3245 // if the dynamic table is writable
Chris Dearman99186652014-02-06 20:36:51 -08003246// FIXME: not working currently for N64
3247// The flags for the LOAD and DYNAMIC program headers do not agree.
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07003248// The LOAD section containing the dynamic table has been mapped as
Chris Dearman99186652014-02-06 20:36:51 -08003249// read-only, but the DYNAMIC header claims it is writable.
3250#if !(defined(__mips__) && defined(__LP64__))
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003251 if ((dynamic_flags & PF_W) != 0) {
3252 d->d_un.d_val = reinterpret_cast<uintptr_t>(&_r_debug);
3253 }
Chris Dearman99186652014-02-06 20:36:51 -08003254#endif
Dmitriy Ivanovc6292ea2015-02-13 16:29:50 -08003255 break;
Elliott Hughes4eeb1f12013-10-25 17:38:02 -07003256#if defined(USE_RELA)
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003257 case DT_RELA:
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003258 rela_ = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003259 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003260
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003261 case DT_RELASZ:
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003262 rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela));
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003263 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003264
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003265 case DT_ANDROID_RELA:
3266 android_relocs_ = reinterpret_cast<uint8_t*>(load_bias + d->d_un.d_ptr);
3267 break;
3268
3269 case DT_ANDROID_RELASZ:
3270 android_relocs_size_ = d->d_un.d_val;
3271 break;
3272
3273 case DT_ANDROID_REL:
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003274 DL_ERR("unsupported DT_ANDROID_REL in \"%s\"", get_realpath());
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003275 return false;
3276
3277 case DT_ANDROID_RELSZ:
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003278 DL_ERR("unsupported DT_ANDROID_RELSZ in \"%s\"", get_realpath());
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003279 return false;
3280
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003281 case DT_RELAENT:
3282 if (d->d_un.d_val != sizeof(ElfW(Rela))) {
Dmitriy Ivanovf240aa82014-09-16 23:34:20 -07003283 DL_ERR("invalid DT_RELAENT: %zd", static_cast<size_t>(d->d_un.d_val));
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003284 return false;
3285 }
3286 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003287
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08003288 // Ignored (see DT_RELCOUNT comments for details).
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003289 case DT_RELACOUNT:
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003290 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003291
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003292 case DT_REL:
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003293 DL_ERR("unsupported DT_REL in \"%s\"", get_realpath());
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003294 return false;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003295
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003296 case DT_RELSZ:
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003297 DL_ERR("unsupported DT_RELSZ in \"%s\"", get_realpath());
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003298 return false;
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003299
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07003300#else
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003301 case DT_REL:
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003302 rel_ = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003303 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003304
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003305 case DT_RELSZ:
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003306 rel_count_ = d->d_un.d_val / sizeof(ElfW(Rel));
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003307 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003308
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003309 case DT_RELENT:
3310 if (d->d_un.d_val != sizeof(ElfW(Rel))) {
Dmitriy Ivanovf240aa82014-09-16 23:34:20 -07003311 DL_ERR("invalid DT_RELENT: %zd", static_cast<size_t>(d->d_un.d_val));
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003312 return false;
3313 }
3314 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003315
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003316 case DT_ANDROID_REL:
3317 android_relocs_ = reinterpret_cast<uint8_t*>(load_bias + d->d_un.d_ptr);
3318 break;
3319
3320 case DT_ANDROID_RELSZ:
3321 android_relocs_size_ = d->d_un.d_val;
3322 break;
3323
3324 case DT_ANDROID_RELA:
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003325 DL_ERR("unsupported DT_ANDROID_RELA in \"%s\"", get_realpath());
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003326 return false;
3327
3328 case DT_ANDROID_RELASZ:
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003329 DL_ERR("unsupported DT_ANDROID_RELASZ in \"%s\"", get_realpath());
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003330 return false;
3331
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003332 // "Indicates that all RELATIVE relocations have been concatenated together,
3333 // and specifies the RELATIVE relocation count."
3334 //
3335 // TODO: Spec also mentions that this can be used to optimize relocation process;
3336 // Not currently used by bionic linker - ignored.
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003337 case DT_RELCOUNT:
Dmitriy Ivanov4a6e9a82014-09-16 15:51:25 -07003338 break;
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003339
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003340 case DT_RELA:
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003341 DL_ERR("unsupported DT_RELA in \"%s\"", get_realpath());
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003342 return false;
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003343
3344 case DT_RELASZ:
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003345 DL_ERR("unsupported DT_RELASZ in \"%s\"", get_realpath());
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003346 return false;
3347
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07003348#endif
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08003349 case DT_RELR:
3350 relr_ = reinterpret_cast<ElfW(Relr)*>(load_bias + d->d_un.d_ptr);
3351 break;
3352
3353 case DT_RELRSZ:
3354 relr_count_ = d->d_un.d_val / sizeof(ElfW(Relr));
3355 break;
3356
3357 case DT_RELRENT:
3358 if (d->d_un.d_val != sizeof(ElfW(Relr))) {
3359 DL_ERR("invalid DT_RELRENT: %zd", static_cast<size_t>(d->d_un.d_val));
3360 return false;
3361 }
3362 break;
3363
3364 // Ignored (see DT_RELCOUNT comments for details).
3365 case DT_RELRCOUNT:
3366 break;
3367
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003368 case DT_INIT:
Dimitry Ivanov55437462016-07-20 15:33:07 -07003369 init_func_ = reinterpret_cast<linker_ctor_function_t>(load_bias + d->d_un.d_ptr);
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003370 DEBUG("%s constructors (DT_INIT) found at %p", get_realpath(), init_func_);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003371 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003372
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003373 case DT_FINI:
Dimitry Ivanov55437462016-07-20 15:33:07 -07003374 fini_func_ = reinterpret_cast<linker_dtor_function_t>(load_bias + d->d_un.d_ptr);
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003375 DEBUG("%s destructors (DT_FINI) found at %p", get_realpath(), fini_func_);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003376 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003377
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003378 case DT_INIT_ARRAY:
Dimitry Ivanov55437462016-07-20 15:33:07 -07003379 init_array_ = reinterpret_cast<linker_ctor_function_t*>(load_bias + d->d_un.d_ptr);
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003380 DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", get_realpath(), init_array_);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003381 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003382
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003383 case DT_INIT_ARRAYSZ:
Dmitriy Ivanov1649e7e2015-01-22 16:04:25 -08003384 init_array_count_ = static_cast<uint32_t>(d->d_un.d_val) / sizeof(ElfW(Addr));
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003385 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003386
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003387 case DT_FINI_ARRAY:
Dimitry Ivanov55437462016-07-20 15:33:07 -07003388 fini_array_ = reinterpret_cast<linker_dtor_function_t*>(load_bias + d->d_un.d_ptr);
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003389 DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", get_realpath(), fini_array_);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003390 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003391
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003392 case DT_FINI_ARRAYSZ:
Dmitriy Ivanov1649e7e2015-01-22 16:04:25 -08003393 fini_array_count_ = static_cast<uint32_t>(d->d_un.d_val) / sizeof(ElfW(Addr));
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003394 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003395
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003396 case DT_PREINIT_ARRAY:
Dimitry Ivanov55437462016-07-20 15:33:07 -07003397 preinit_array_ = reinterpret_cast<linker_ctor_function_t*>(load_bias + d->d_un.d_ptr);
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003398 DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", get_realpath(), preinit_array_);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003399 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003400
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003401 case DT_PREINIT_ARRAYSZ:
Dmitriy Ivanov1649e7e2015-01-22 16:04:25 -08003402 preinit_array_count_ = static_cast<uint32_t>(d->d_un.d_val) / sizeof(ElfW(Addr));
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003403 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003404
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003405 case DT_TEXTREL:
Dimitry Ivanov56be6ed2015-04-01 21:18:48 +00003406#if defined(__LP64__)
Dimitry Ivanov816676e2016-10-19 11:00:28 -07003407 DL_ERR("\"%s\" has text relocations", get_realpath());
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003408 return false;
Dimitry Ivanov56be6ed2015-04-01 21:18:48 +00003409#else
3410 has_text_relocations = true;
3411 break;
3412#endif
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003413
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003414 case DT_SYMBOLIC:
Dmitriy Ivanov96bc37f2014-09-29 12:10:36 -07003415 has_DT_SYMBOLIC = true;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003416 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003417
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003418 case DT_NEEDED:
3419 ++needed_count;
3420 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003421
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003422 case DT_FLAGS:
3423 if (d->d_un.d_val & DF_TEXTREL) {
Dimitry Ivanov56be6ed2015-04-01 21:18:48 +00003424#if defined(__LP64__)
Dimitry Ivanov816676e2016-10-19 11:00:28 -07003425 DL_ERR("\"%s\" has text relocations", get_realpath());
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003426 return false;
Dimitry Ivanov56be6ed2015-04-01 21:18:48 +00003427#else
3428 has_text_relocations = true;
3429#endif
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08003430 }
Dmitriy Ivanov96bc37f2014-09-29 12:10:36 -07003431 if (d->d_un.d_val & DF_SYMBOLIC) {
3432 has_DT_SYMBOLIC = true;
3433 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003434 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003435
Dmitriy Ivanov6cdeb522014-09-29 19:14:45 -07003436 case DT_FLAGS_1:
Dmitriy Ivanovd225a5e2014-08-28 14:12:12 -07003437 set_dt_flags_1(d->d_un.d_val);
Dmitriy Ivanov1b20daf2014-05-19 15:06:58 -07003438
Dmitriy Ivanovd225a5e2014-08-28 14:12:12 -07003439 if ((d->d_un.d_val & ~SUPPORTED_DT_FLAGS_1) != 0) {
Elliott Hughes9076b0c2018-02-28 11:29:45 -08003440 DL_WARN("Warning: \"%s\" has unsupported flags DT_FLAGS_1=%p "
3441 "(ignoring unsupported flags)",
3442 get_realpath(), reinterpret_cast<void*>(d->d_un.d_val));
Dmitriy Ivanov6cdeb522014-09-29 19:14:45 -07003443 }
3444 break;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003445#if defined(__mips__)
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003446 case DT_MIPS_RLD_MAP:
3447 // Set the DT_MIPS_RLD_MAP entry to the address of _r_debug for GDB.
3448 {
3449 r_debug** dp = reinterpret_cast<r_debug**>(load_bias + d->d_un.d_ptr);
3450 *dp = &_r_debug;
3451 }
3452 break;
Lazar Trsic83b44a92016-04-06 13:39:17 +02003453 case DT_MIPS_RLD_MAP_REL:
3454 // Set the DT_MIPS_RLD_MAP_REL entry to the address of _r_debug for GDB.
Raghu Gandham68815722014-12-18 19:12:19 -08003455 {
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -07003456 r_debug** dp = reinterpret_cast<r_debug**>(
3457 reinterpret_cast<ElfW(Addr)>(d) + d->d_un.d_val);
Raghu Gandham68815722014-12-18 19:12:19 -08003458 *dp = &_r_debug;
3459 }
3460 break;
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003461
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003462 case DT_MIPS_RLD_VERSION:
3463 case DT_MIPS_FLAGS:
3464 case DT_MIPS_BASE_ADDRESS:
3465 case DT_MIPS_UNREFEXTNO:
3466 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08003467
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003468 case DT_MIPS_SYMTABNO:
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003469 mips_symtabno_ = d->d_un.d_val;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003470 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08003471
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003472 case DT_MIPS_LOCAL_GOTNO:
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003473 mips_local_gotno_ = d->d_un.d_val;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003474 break;
3475
3476 case DT_MIPS_GOTSYM:
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003477 mips_gotsym_ = d->d_un.d_val;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003478 break;
3479#endif
Dmitriy Ivanovea6eae12014-10-15 14:59:01 -07003480 // Ignored: "Its use has been superseded by the DF_BIND_NOW flag"
3481 case DT_BIND_NOW:
3482 break;
3483
Dmitriy Ivanov513e29e2014-10-06 11:30:43 -07003484 case DT_VERSYM:
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07003485 versym_ = reinterpret_cast<ElfW(Versym)*>(load_bias + d->d_un.d_ptr);
3486 break;
3487
Dmitriy Ivanov513e29e2014-10-06 11:30:43 -07003488 case DT_VERDEF:
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07003489 verdef_ptr_ = load_bias + d->d_un.d_ptr;
3490 break;
Dmitriy Ivanov513e29e2014-10-06 11:30:43 -07003491 case DT_VERDEFNUM:
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07003492 verdef_cnt_ = d->d_un.d_val;
3493 break;
3494
Alexander Ivchenkoe8314332014-12-02 15:32:25 +03003495 case DT_VERNEED:
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07003496 verneed_ptr_ = load_bias + d->d_un.d_ptr;
3497 break;
3498
Alexander Ivchenkoe8314332014-12-02 15:32:25 +03003499 case DT_VERNEEDNUM:
Dmitriy Ivanov2a815362015-04-09 13:42:33 -07003500 verneed_cnt_ = d->d_un.d_val;
Dmitriy Ivanov513e29e2014-10-06 11:30:43 -07003501 break;
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003502
Evgenii Stepanov68650822015-06-10 13:38:39 -07003503 case DT_RUNPATH:
3504 // this is parsed after we have strtab initialized (see below).
3505 break;
3506
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003507 default:
Dmitriy Ivanov8f61d992014-09-16 14:31:06 -07003508 if (!relocating_linker) {
Elliott Hughes45a93c12018-03-23 18:46:07 -07003509 if (d->d_tag == DT_TLSDESC_GOT || d->d_tag == DT_TLSDESC_PLT) {
3510 DL_ERR("unsupported ELF TLS DT entry in \"%s\"", get_realpath());
3511 return false;
3512 }
3513
Elliott Hughes6eae4cc2017-08-30 09:02:33 -07003514 const char* tag_name;
3515 if (d->d_tag == DT_RPATH) {
3516 tag_name = "DT_RPATH";
3517 } else if (d->d_tag == DT_ENCODING) {
3518 tag_name = "DT_ENCODING";
3519 } else if (d->d_tag >= DT_LOOS && d->d_tag <= DT_HIOS) {
3520 tag_name = "unknown OS-specific";
3521 } else if (d->d_tag >= DT_LOPROC && d->d_tag <= DT_HIPROC) {
3522 tag_name = "unknown processor-specific";
3523 } else {
3524 tag_name = "unknown";
3525 }
Elliott Hughes9076b0c2018-02-28 11:29:45 -08003526 DL_WARN("Warning: \"%s\" unused DT entry: %s (type %p arg %p) (ignoring)",
Elliott Hughes6eae4cc2017-08-30 09:02:33 -07003527 get_realpath(),
3528 tag_name,
3529 reinterpret_cast<void*>(d->d_tag),
3530 reinterpret_cast<void*>(d->d_un.d_val));
Dmitriy Ivanov8f61d992014-09-16 14:31:06 -07003531 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003532 break;
Brian Carlstromd4ee82d2013-02-28 15:58:45 -08003533 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003534 }
3535
Duane Sandbc425c72015-06-01 16:29:14 -07003536#if defined(__mips__) && !defined(__LP64__)
3537 if (!mips_check_and_adjust_fp_modes()) {
3538 return false;
3539 }
3540#endif
3541
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003542 DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003543 reinterpret_cast<void*>(base), strtab_, symtab_);
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003544
3545 // Sanity checks.
3546 if (relocating_linker && needed_count != 0) {
3547 DL_ERR("linker cannot have DT_NEEDED dependencies on other libraries");
3548 return false;
3549 }
Dmitriy Ivanov3597b802015-03-09 12:02:02 -07003550 if (nbucket_ == 0 && gnu_nbucket_ == 0) {
Dmitriy Ivanovaae859c2015-03-31 11:14:03 -07003551 DL_ERR("empty/missing DT_HASH/DT_GNU_HASH in \"%s\" "
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07003552 "(new hash type from the future?)", get_realpath());
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003553 return false;
3554 }
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003555 if (strtab_ == 0) {
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07003556 DL_ERR("empty/missing DT_STRTAB in \"%s\"", get_realpath());
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003557 return false;
3558 }
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003559 if (symtab_ == 0) {
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07003560 DL_ERR("empty/missing DT_SYMTAB in \"%s\"", get_realpath());
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003561 return false;
3562 }
Dmitriy Ivanov75108f42015-06-02 13:28:06 -07003563
Dmitriy Ivanov624b8f12015-06-08 10:41:33 -07003564 // second pass - parse entries relying on strtab
3565 for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
Evgenii Stepanov68650822015-06-10 13:38:39 -07003566 switch (d->d_tag) {
3567 case DT_SONAME:
Dmitriy Ivanov4f7a7ad2015-10-15 12:07:25 -07003568 set_soname(get_string(d->d_un.d_val));
Evgenii Stepanov68650822015-06-10 13:38:39 -07003569 break;
3570 case DT_RUNPATH:
Evgenii Stepanov68650822015-06-10 13:38:39 -07003571 set_dt_runpath(get_string(d->d_un.d_val));
3572 break;
Dmitriy Ivanov624b8f12015-06-08 10:41:33 -07003573 }
3574 }
3575
Dmitriy Ivanov75108f42015-06-02 13:28:06 -07003576 // Before M release linker was using basename in place of soname.
Dmitriy Ivanov19133522015-06-02 17:36:54 -07003577 // In the case when dt_soname is absent some apps stop working
Dmitriy Ivanov75108f42015-06-02 13:28:06 -07003578 // because they can't find dt_needed library by soname.
Elliott Hughes9076b0c2018-02-28 11:29:45 -08003579 // This workaround should keep them working. (Applies only
3580 // for apps targeting sdk version < M.) Make an exception for
3581 // the main executable and linker; they do not need to have dt_soname.
3582 // TODO: >= O the linker doesn't need this workaround.
Dimitry Ivanov3f660572016-09-09 10:00:39 -07003583 if (soname_ == nullptr &&
3584 this != solist_get_somain() &&
3585 (flags_ & FLAG_LINKER) == 0 &&
Elliott Hughes5bc78c82016-11-16 11:35:43 -08003586 get_application_target_sdk_version() < __ANDROID_API_M__) {
Dmitriy Ivanov75108f42015-06-02 13:28:06 -07003587 soname_ = basename(realpath_.c_str());
Elliott Hughes9076b0c2018-02-28 11:29:45 -08003588 DL_WARN_documented_change(__ANDROID_API_M__,
3589 "missing-soname-enforced-for-api-level-23",
3590 "\"%s\" has no DT_SONAME (will use %s instead)",
3591 get_realpath(), soname_);
3592
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07003593 // Don't call add_dlwarning because a missing DT_SONAME isn't important enough to show in the UI
Dmitriy Ivanov75108f42015-06-02 13:28:06 -07003594 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003595 return true;
Dmitriy Ivanov14669a92014-09-05 16:42:53 -07003596}
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08003597
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003598bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group,
3599 const android_dlextinfo* extinfo) {
dimitry965d06d2017-11-28 16:03:07 +01003600 if (is_image_linked()) {
3601 // already linked.
3602 return true;
3603 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08003604
Dmitriy Ivanovab972b92014-11-29 13:57:41 -08003605 local_group_root_ = local_group.front();
3606 if (local_group_root_ == nullptr) {
3607 local_group_root_ = this;
3608 }
3609
Dmitriy Ivanov19133522015-06-02 17:36:54 -07003610 if ((flags_ & FLAG_LINKER) == 0 && local_group_root_ == this) {
3611 target_sdk_version_ = get_application_target_sdk_version();
3612 }
3613
Dmitriy Ivanov7e4bbba2015-04-30 19:49:19 -07003614 VersionTracker version_tracker;
3615
3616 if (!version_tracker.init(this)) {
3617 return false;
3618 }
3619
Dimitry Ivanov56be6ed2015-04-01 21:18:48 +00003620#if !defined(__LP64__)
3621 if (has_text_relocations) {
Elliott Hughes5bc78c82016-11-16 11:35:43 -08003622 // Fail if app is targeting M or above.
Elliott Hughes9076b0c2018-02-28 11:29:45 -08003623 int app_target_api_level = get_application_target_sdk_version();
3624 if (app_target_api_level >= __ANDROID_API_M__) {
Elliott Hughes763f6e12017-04-10 09:52:33 -07003625 DL_ERR_AND_LOG("\"%s\" has text relocations (https://android.googlesource.com/platform/"
3626 "bionic/+/master/android-changes-for-ndk-developers.md#Text-Relocations-"
3627 "Enforced-for-API-level-23)", get_realpath());
Dmitriy Ivanove4ad91f2015-06-12 15:00:31 -07003628 return false;
3629 }
Dimitry Ivanov56be6ed2015-04-01 21:18:48 +00003630 // Make segments writable to allow text relocations to work properly. We will later call
Dmitriy Ivanov7e039932015-10-01 14:02:19 -07003631 // phdr_table_protect_segments() after all of them are applied.
Elliott Hughes9076b0c2018-02-28 11:29:45 -08003632 DL_WARN_documented_change(__ANDROID_API_M__,
3633 "Text-Relocations-Enforced-for-API-level-23",
3634 "\"%s\" has text relocations",
3635 get_realpath());
Dimitry Ivanov769b33f2016-07-21 11:33:40 -07003636 add_dlwarning(get_realpath(), "text relocations");
Dimitry Ivanov56be6ed2015-04-01 21:18:48 +00003637 if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
Elliott Hughes9076b0c2018-02-28 11:29:45 -08003638 DL_ERR("can't unprotect loadable segments for \"%s\": %s", get_realpath(), strerror(errno));
Dimitry Ivanov56be6ed2015-04-01 21:18:48 +00003639 return false;
3640 }
3641 }
3642#endif
3643
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003644 if (android_relocs_ != nullptr) {
3645 // check signature
3646 if (android_relocs_size_ > 3 &&
3647 android_relocs_[0] == 'A' &&
3648 android_relocs_[1] == 'P' &&
Dmitriy Ivanov18870d32015-04-22 13:10:04 -07003649 android_relocs_[2] == 'S' &&
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003650 android_relocs_[3] == '2') {
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07003651 DEBUG("[ android relocating %s ]", get_realpath());
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003652
3653 bool relocated = false;
3654 const uint8_t* packed_relocs = android_relocs_ + 4;
3655 const size_t packed_relocs_size = android_relocs_size_ - 4;
3656
Dmitriy Ivanov18870d32015-04-22 13:10:04 -07003657 relocated = relocate(
Dmitriy Ivanov7e4bbba2015-04-30 19:49:19 -07003658 version_tracker,
Dmitriy Ivanov18870d32015-04-22 13:10:04 -07003659 packed_reloc_iterator<sleb128_decoder>(
3660 sleb128_decoder(packed_relocs, packed_relocs_size)),
3661 global_group, local_group);
Dmitriy Ivanov18a69562015-02-04 16:05:30 -08003662
3663 if (!relocated) {
3664 return false;
3665 }
3666 } else {
3667 DL_ERR("bad android relocation header.");
3668 return false;
3669 }
3670 }
3671
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08003672 if (relr_ != nullptr) {
3673 DEBUG("[ relocating %s relr ]", get_realpath());
3674 if (!relocate_relr()) {
3675 return false;
3676 }
3677 }
3678
Elliott Hughes4eeb1f12013-10-25 17:38:02 -07003679#if defined(USE_RELA)
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003680 if (rela_ != nullptr) {
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08003681 DEBUG("[ relocating %s rela ]", get_realpath());
Dmitriy Ivanov7e4bbba2015-04-30 19:49:19 -07003682 if (!relocate(version_tracker,
3683 plain_reloc_iterator(rela_, rela_count_), global_group, local_group)) {
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003684 return false;
Elliott Hughesc00f2cb2013-10-04 17:01:33 -07003685 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003686 }
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003687 if (plt_rela_ != nullptr) {
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08003688 DEBUG("[ relocating %s plt rela ]", get_realpath());
Dmitriy Ivanov7e4bbba2015-04-30 19:49:19 -07003689 if (!relocate(version_tracker,
3690 plain_reloc_iterator(plt_rela_, plt_rela_count_), global_group, local_group)) {
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003691 return false;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08003692 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003693 }
Dmitriy Ivanov9aea1642014-09-11 15:16:03 -07003694#else
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003695 if (rel_ != nullptr) {
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08003696 DEBUG("[ relocating %s rel ]", get_realpath());
Dmitriy Ivanov7e4bbba2015-04-30 19:49:19 -07003697 if (!relocate(version_tracker,
3698 plain_reloc_iterator(rel_, rel_count_), global_group, local_group)) {
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003699 return false;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08003700 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003701 }
Dmitriy Ivanov047b5932014-11-13 09:39:20 -08003702 if (plt_rel_ != nullptr) {
Rahul Chaudhryb7feec72017-12-19 15:25:23 -08003703 DEBUG("[ relocating %s plt rel ]", get_realpath());
Dmitriy Ivanov7e4bbba2015-04-30 19:49:19 -07003704 if (!relocate(version_tracker,
3705 plain_reloc_iterator(plt_rel_, plt_rel_count_), global_group, local_group)) {
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003706 return false;
Brigid Smithc5a13ef2014-07-23 11:22:25 -07003707 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003708 }
Dmitriy Ivanov9aea1642014-09-11 15:16:03 -07003709#endif
Brigid Smithc5a13ef2014-07-23 11:22:25 -07003710
Elliott Hughes4eeb1f12013-10-25 17:38:02 -07003711#if defined(__mips__)
Dmitriy Ivanovf39cb632015-04-30 20:17:03 -07003712 if (!mips_relocate_got(version_tracker, global_group, local_group)) {
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003713 return false;
3714 }
Raghu Gandhamd7daacb2012-07-31 12:07:22 -07003715#endif
3716
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07003717 DEBUG("[ finished linking %s ]", get_realpath());
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08003718
Dimitry Ivanov56be6ed2015-04-01 21:18:48 +00003719#if !defined(__LP64__)
3720 if (has_text_relocations) {
3721 // All relocations are done, we can protect our segments back to read-only.
3722 if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
3723 DL_ERR("can't protect segments for \"%s\": %s",
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07003724 get_realpath(), strerror(errno));
Dimitry Ivanov56be6ed2015-04-01 21:18:48 +00003725 return false;
3726 }
3727 }
3728#endif
3729
Mingwei Shibe910522015-11-12 07:02:14 +00003730 // We can also turn on GNU RELRO protection if we're not linking the dynamic linker
3731 // itself --- it can't make system calls yet, and will have to call protect_relro later.
3732 if (!is_linker() && !protect_relro()) {
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003733 return false;
3734 }
Nick Kralevich9ec0f032012-02-28 10:40:00 -08003735
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003736 /* Handle serializing/sharing the RELRO segment */
3737 if (extinfo && (extinfo->flags & ANDROID_DLEXT_WRITE_RELRO)) {
3738 if (phdr_table_serialize_gnu_relro(phdr, phnum, load_bias,
3739 extinfo->relro_fd) < 0) {
3740 DL_ERR("failed serializing GNU RELRO section for \"%s\": %s",
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07003741 get_realpath(), strerror(errno));
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003742 return false;
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +00003743 }
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003744 } else if (extinfo && (extinfo->flags & ANDROID_DLEXT_USE_RELRO)) {
3745 if (phdr_table_map_gnu_relro(phdr, phnum, load_bias,
3746 extinfo->relro_fd) < 0) {
3747 DL_ERR("failed mapping GNU RELRO section for \"%s\": %s",
Dmitriy Ivanov3edb9182015-05-07 10:48:00 -07003748 get_realpath(), strerror(errno));
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003749 return false;
3750 }
3751 }
Torne (Richard Coles)183ad9d2014-02-27 13:18:00 +00003752
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003753 notify_gdb_of_load(this);
dimitry965d06d2017-11-28 16:03:07 +01003754 set_image_linked();
Dmitriy Ivanov6abf6242014-09-12 09:43:13 -07003755 return true;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08003756}
3757
Mingwei Shibe910522015-11-12 07:02:14 +00003758bool soinfo::protect_relro() {
3759 if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias) < 0) {
3760 DL_ERR("can't enable GNU RELRO protection for \"%s\": %s",
3761 get_realpath(), strerror(errno));
3762 return false;
3763 }
3764 return true;
3765}
3766
Jiyong Park02586a22017-05-20 01:01:24 +09003767static std::vector<android_namespace_t*> init_default_namespace_no_config(bool is_asan) {
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07003768 g_default_namespace.set_isolated(false);
Dimitry Ivanov77ad6422017-03-06 13:02:29 -08003769 auto default_ld_paths = is_asan ? kAsanDefaultLdPaths : kDefaultLdPaths;
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07003770
neo.chae2589f9d2016-10-04 11:00:27 +09003771 char real_path[PATH_MAX];
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07003772 std::vector<std::string> ld_default_paths;
Dimitry Ivanov77ad6422017-03-06 13:02:29 -08003773 for (size_t i = 0; default_ld_paths[i] != nullptr; ++i) {
3774 if (realpath(default_ld_paths[i], real_path) != nullptr) {
neo.chae2589f9d2016-10-04 11:00:27 +09003775 ld_default_paths.push_back(real_path);
3776 } else {
Dimitry Ivanov77ad6422017-03-06 13:02:29 -08003777 ld_default_paths.push_back(default_ld_paths[i]);
neo.chae2589f9d2016-10-04 11:00:27 +09003778 }
Dmitriy Ivanov42d5fcb2015-10-29 17:01:24 -07003779 }
3780
3781 g_default_namespace.set_default_library_paths(std::move(ld_default_paths));
Jiyong Park02586a22017-05-20 01:01:24 +09003782
3783 std::vector<android_namespace_t*> namespaces;
3784 namespaces.push_back(&g_default_namespace);
3785 return namespaces;
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -08003786}
3787
Logan Chien21e496c2018-05-08 17:52:18 +08003788static std::string get_ld_config_file_vndk_path() {
Logan Chiendd184722018-05-08 20:17:26 +08003789 if (android::base::GetBoolProperty("ro.vndk.lite", false)) {
3790 return kLdConfigVndkLiteFilePath;
3791 }
3792
Logan Chien21e496c2018-05-08 17:52:18 +08003793 std::string ld_config_file_vndk = kLdConfigFilePath;
3794 size_t insert_pos = ld_config_file_vndk.find_last_of('.');
3795 if (insert_pos == std::string::npos) {
3796 insert_pos = ld_config_file_vndk.length();
3797 }
3798 ld_config_file_vndk.insert(insert_pos, Config::get_vndk_version_string('.'));
3799 return ld_config_file_vndk;
3800}
3801
3802static std::string get_ld_config_file_path() {
3803#ifdef USE_LD_CONFIG_FILE
3804 // This is a debugging/testing only feature. Must not be available on
3805 // production builds.
3806 const char* ld_config_file_env = getenv("LD_CONFIG_FILE");
3807 if (ld_config_file_env != nullptr && file_exists(ld_config_file_env)) {
3808 return ld_config_file_env;
3809 }
3810#endif
3811
3812 if (file_exists(kLdConfigArchFilePath)) {
3813 return kLdConfigArchFilePath;
3814 }
3815
3816 std::string ld_config_file_vndk = get_ld_config_file_vndk_path();
3817 if (file_exists(ld_config_file_vndk.c_str())) {
3818 return ld_config_file_vndk;
3819 }
3820
3821 return kLdConfigFilePath;
3822}
3823
Jiyong Park02586a22017-05-20 01:01:24 +09003824std::vector<android_namespace_t*> init_default_namespaces(const char* executable_path) {
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -08003825 g_default_namespace.set_name("(default)");
3826
3827 soinfo* somain = solist_get_somain();
3828
3829 const char *interp = phdr_table_get_interpreter_name(somain->phdr, somain->phnum,
3830 somain->load_bias);
Dan Willemsen7ccc50d2017-09-18 21:28:14 -07003831 const char* bname = (interp != nullptr) ? basename(interp) : nullptr;
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -08003832
3833 g_is_asan = bname != nullptr &&
3834 (strcmp(bname, "linker_asan") == 0 ||
3835 strcmp(bname, "linker_asan64") == 0);
3836
3837 const Config* config = nullptr;
3838
3839 std::string error_msg;
3840
Logan Chien21e496c2018-05-08 17:52:18 +08003841 std::string ld_config_file_path = get_ld_config_file_path();
Jiyong Park02586a22017-05-20 01:01:24 +09003842
Logan Chien21e496c2018-05-08 17:52:18 +08003843 if (!Config::read_binary_config(ld_config_file_path.c_str(),
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -08003844 executable_path,
3845 g_is_asan,
3846 &config,
3847 &error_msg)) {
3848 if (!error_msg.empty()) {
Elliott Hughes9076b0c2018-02-28 11:29:45 -08003849 DL_WARN("Warning: couldn't read \"%s\" for \"%s\" (using default configuration instead): %s",
Logan Chien21e496c2018-05-08 17:52:18 +08003850 ld_config_file_path.c_str(),
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -08003851 executable_path,
3852 error_msg.c_str());
3853 }
3854 config = nullptr;
3855 }
3856
3857 if (config == nullptr) {
Jiyong Park02586a22017-05-20 01:01:24 +09003858 return init_default_namespace_no_config(g_is_asan);
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -08003859 }
3860
3861 const auto& namespace_configs = config->namespace_configs();
3862 std::unordered_map<std::string, android_namespace_t*> namespaces;
3863
3864 // 1. Initialize default namespace
3865 const NamespaceConfig* default_ns_config = config->default_namespace_config();
3866
3867 g_default_namespace.set_isolated(default_ns_config->isolated());
3868 g_default_namespace.set_default_library_paths(default_ns_config->search_paths());
3869 g_default_namespace.set_permitted_paths(default_ns_config->permitted_paths());
3870
3871 namespaces[default_ns_config->name()] = &g_default_namespace;
Justin Yun90de9f02017-07-07 16:21:53 +09003872 if (default_ns_config->visible()) {
3873 g_exported_namespaces[default_ns_config->name()] = &g_default_namespace;
3874 }
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -08003875
3876 // 2. Initialize other namespaces
3877
3878 for (auto& ns_config : namespace_configs) {
3879 if (namespaces.find(ns_config->name()) != namespaces.end()) {
3880 continue;
3881 }
3882
3883 android_namespace_t* ns = new (g_namespace_allocator.alloc()) android_namespace_t();
3884 ns->set_name(ns_config->name());
3885 ns->set_isolated(ns_config->isolated());
3886 ns->set_default_library_paths(ns_config->search_paths());
3887 ns->set_permitted_paths(ns_config->permitted_paths());
3888
3889 namespaces[ns_config->name()] = ns;
Jiyong Park01de74e2017-04-03 23:10:37 +09003890 if (ns_config->visible()) {
3891 g_exported_namespaces[ns_config->name()] = ns;
3892 }
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -08003893 }
3894
3895 // 3. Establish links between namespaces
3896 for (auto& ns_config : namespace_configs) {
3897 auto it_from = namespaces.find(ns_config->name());
3898 CHECK(it_from != namespaces.end());
3899 android_namespace_t* namespace_from = it_from->second;
3900 for (const NamespaceLinkConfig& ns_link : ns_config->links()) {
3901 auto it_to = namespaces.find(ns_link.ns_name());
3902 CHECK(it_to != namespaces.end());
3903 android_namespace_t* namespace_to = it_to->second;
Logan Chien9ee45912018-01-18 12:05:09 +08003904 if (ns_link.allow_all_shared_libs()) {
3905 link_namespaces_all_libs(namespace_from, namespace_to);
3906 } else {
3907 link_namespaces(namespace_from, namespace_to, ns_link.shared_libs().c_str());
3908 }
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -08003909 }
3910 }
3911 // we can no longer rely on the fact that libdl.so is part of default namespace
3912 // this is why we want to add ld-android.so to all namespaces from ld.config.txt
3913 soinfo* ld_android_so = solist_get_head();
dimitry69c68c42018-05-09 15:22:38 +02003914
3915 // we also need vdso to be available for all namespaces (if present)
3916 soinfo* vdso = solist_get_vdso();
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -08003917 for (auto it : namespaces) {
3918 it.second->add_soinfo(ld_android_so);
dimitry69c68c42018-05-09 15:22:38 +02003919 if (vdso != nullptr) {
3920 it.second->add_soinfo(vdso);
3921 }
Jiyong Park02586a22017-05-20 01:01:24 +09003922 // somain and ld_preloads are added to these namespaces after LD_PRELOAD libs are linked
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -08003923 }
3924
Danny Baumann91b596b2018-08-29 11:21:52 +02003925 uint32_t target_sdk = config->target_sdk_version();
3926#ifdef SDK_VERSION_OVERRIDES
3927 for (const auto& entry : android::base::Split(SDK_VERSION_OVERRIDES, " ")) {
3928 auto splitted = android::base::Split(entry, "=");
3929 if (splitted.size() == 2 && splitted[0] == executable_path) {
3930 target_sdk = static_cast<uint32_t>(std::stoul(splitted[1]));
3931 break;
3932 }
3933 }
3934 DEBUG("Target SDK for %s = %d", executable_path, target_sdk);
3935#endif
3936 set_application_target_sdk_version(target_sdk);
Jiyong Park02586a22017-05-20 01:01:24 +09003937
3938 std::vector<android_namespace_t*> created_namespaces;
3939 created_namespaces.reserve(namespaces.size());
3940 for (auto kv : namespaces) {
3941 created_namespaces.push_back(kv.second);
3942 }
3943 return created_namespaces;
Dimitry Ivanov4cabfaa2017-03-07 11:19:05 -08003944}
Jiyong Park01de74e2017-04-03 23:10:37 +09003945
3946// This function finds a namespace exported in ld.config.txt by its name.
3947// A namespace can be exported by setting .visible property to true.
3948android_namespace_t* get_exported_namespace(const char* name) {
3949 if (name == nullptr) {
3950 return nullptr;
3951 }
3952 auto it = g_exported_namespaces.find(std::string(name));
3953 if (it == g_exported_namespaces.end()) {
3954 return nullptr;
3955 }
3956 return it->second;
3957}