diff options
-rw-r--r-- | libdl/libdl.arm.map | 1 | ||||
-rw-r--r-- | libdl/libdl.arm64.map | 1 | ||||
-rw-r--r-- | libdl/libdl.c | 2 | ||||
-rw-r--r-- | libdl/libdl.map.txt | 1 | ||||
-rw-r--r-- | libdl/libdl.mips.map | 1 | ||||
-rw-r--r-- | libdl/libdl.mips64.map | 1 | ||||
-rw-r--r-- | libdl/libdl.x86.map | 1 | ||||
-rw-r--r-- | libdl/libdl.x86_64.map | 1 | ||||
-rw-r--r-- | linker/Android.bp | 1 | ||||
-rw-r--r-- | linker/dlfcn.cpp | 21 | ||||
-rw-r--r-- | linker/linker.cpp | 171 | ||||
-rw-r--r-- | linker/linker_dlwarning.cpp | 47 | ||||
-rw-r--r-- | linker/linker_dlwarning.h | 28 | ||||
-rw-r--r-- | linker/linker_mips.cpp | 2 | ||||
-rw-r--r-- | linker/linker_utils.cpp | 4 |
15 files changed, 241 insertions, 42 deletions
diff --git a/libdl/libdl.arm.map b/libdl/libdl.arm.map index 20efa9a95..2cd49c5da 100644 --- a/libdl/libdl.arm.map +++ b/libdl/libdl.arm.map @@ -21,6 +21,7 @@ LIBC_N { LIBC_PLATFORM { global: + android_dlwarning; android_get_application_target_sdk_version; android_set_application_target_sdk_version; android_get_LD_LIBRARY_PATH; diff --git a/libdl/libdl.arm64.map b/libdl/libdl.arm64.map index daf5a86be..74e029c99 100644 --- a/libdl/libdl.arm64.map +++ b/libdl/libdl.arm64.map @@ -20,6 +20,7 @@ LIBC_N { LIBC_PLATFORM { global: + android_dlwarning; android_get_application_target_sdk_version; android_set_application_target_sdk_version; android_get_LD_LIBRARY_PATH; diff --git a/libdl/libdl.c b/libdl/libdl.c index fa5237f6f..b62ee5ccb 100644 --- a/libdl/libdl.c +++ b/libdl/libdl.c @@ -69,3 +69,5 @@ struct android_namespace_t* android_create_namespace(const char* name __unused, const char* permitted_when_isolated_path __unused) { return 0; } + +void android_dlwarning(void* obj, void (*f)(void*, const char*)) { f(obj, 0); } diff --git a/libdl/libdl.map.txt b/libdl/libdl.map.txt index 79bced3c2..962692ec9 100644 --- a/libdl/libdl.map.txt +++ b/libdl/libdl.map.txt @@ -35,6 +35,7 @@ LIBC_N { LIBC_PLATFORM { global: + android_dlwarning; android_get_application_target_sdk_version; android_set_application_target_sdk_version; android_get_LD_LIBRARY_PATH; diff --git a/libdl/libdl.mips.map b/libdl/libdl.mips.map index daf5a86be..74e029c99 100644 --- a/libdl/libdl.mips.map +++ b/libdl/libdl.mips.map @@ -20,6 +20,7 @@ LIBC_N { LIBC_PLATFORM { global: + android_dlwarning; android_get_application_target_sdk_version; android_set_application_target_sdk_version; android_get_LD_LIBRARY_PATH; diff --git a/libdl/libdl.mips64.map b/libdl/libdl.mips64.map index daf5a86be..74e029c99 100644 --- a/libdl/libdl.mips64.map +++ b/libdl/libdl.mips64.map @@ -20,6 +20,7 @@ LIBC_N { LIBC_PLATFORM { global: + android_dlwarning; android_get_application_target_sdk_version; android_set_application_target_sdk_version; android_get_LD_LIBRARY_PATH; diff --git a/libdl/libdl.x86.map b/libdl/libdl.x86.map index daf5a86be..74e029c99 100644 --- a/libdl/libdl.x86.map +++ b/libdl/libdl.x86.map @@ -20,6 +20,7 @@ LIBC_N { LIBC_PLATFORM { global: + android_dlwarning; android_get_application_target_sdk_version; android_set_application_target_sdk_version; android_get_LD_LIBRARY_PATH; diff --git a/libdl/libdl.x86_64.map b/libdl/libdl.x86_64.map index daf5a86be..74e029c99 100644 --- a/libdl/libdl.x86_64.map +++ b/libdl/libdl.x86_64.map @@ -20,6 +20,7 @@ LIBC_N { LIBC_PLATFORM { global: + android_dlwarning; android_get_application_target_sdk_version; android_set_application_target_sdk_version; android_get_LD_LIBRARY_PATH; diff --git a/linker/Android.bp b/linker/Android.bp index d7e97f04b..a35eb4502 100644 --- a/linker/Android.bp +++ b/linker/Android.bp @@ -18,6 +18,7 @@ cc_binary { "dlfcn.cpp", "linker.cpp", "linker_block_allocator.cpp", + "linker_dlwarning.cpp", "linker_gdb_support.cpp", "linker_libc_support.c", "linker_logger.cpp", diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp index 110846d90..c03ffa812 100644 --- a/linker/dlfcn.cpp +++ b/linker/dlfcn.cpp @@ -15,6 +15,7 @@ */ #include "linker.h" +#include "linker_dlwarning.h" #include <pthread.h> #include <stdio.h> @@ -138,6 +139,11 @@ uint32_t android_get_application_target_sdk_version() { return get_application_target_sdk_version(); } +void android_dlwarning(void* obj, void (*f)(void*, const char*)) { + ScopedPthreadMutexLocker locker(&g_dl_mutex); + get_dlwarning(obj, f); +} + bool android_init_namespaces(const char* public_ns_sonames, const char* anon_ns_library_path) { ScopedPthreadMutexLocker locker(&g_dl_mutex); @@ -199,11 +205,11 @@ static const char ANDROID_LIBDL_STRTAB[] = // 00000000001 1111111112222222222 3333333333444444444455555555556666666666777 777777788888888889999999999 // 01234567890 1234567890123456789 0123456789012345678901234567890123456789012 345678901234567890123456789 "erate_phdr\0android_dlopen_ext\0android_set_application_target_sdk_version\0android_get_application_tar" - // 0000000000111111 111122222222223333333333 4444444444555555555566666 6666677 - // 0123456789012345 678901234567890123456789 0123456789012345678901234 5678901 - "get_sdk_version\0android_init_namespaces\0android_create_namespace\0dlvsym\0" + // 0000000000111111 111122222222223333333333 4444444444555555555566666 6666677 777777778888888888 + // 0123456789012345 678901234567890123456789 0123456789012345678901234 5678901 234567890123456789 + "get_sdk_version\0android_init_namespaces\0android_create_namespace\0dlvsym\0android_dlwarning\0" #if defined(__arm__) - // 272 + // 290 "dl_unwind_find_exidx\0" #endif ; @@ -228,8 +234,9 @@ static ElfW(Sym) g_libdl_symtab[] = { ELFW(SYM_INITIALIZER)(216, &android_init_namespaces, 1), ELFW(SYM_INITIALIZER)(240, &android_create_namespace, 1), ELFW(SYM_INITIALIZER)(265, &dlvsym, 1), + ELFW(SYM_INITIALIZER)(272, &android_dlwarning, 1), #if defined(__arm__) - ELFW(SYM_INITIALIZER)(272, &dl_unwind_find_exidx, 1), + ELFW(SYM_INITIALIZER)(290, &dl_unwind_find_exidx, 1), #endif }; @@ -246,9 +253,9 @@ static ElfW(Sym) g_libdl_symtab[] = { // Note that adding any new symbols here requires stubbing them out in libdl. static unsigned g_libdl_buckets[1] = { 1 }; #if defined(__arm__) -static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 }; +static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 }; #else -static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 }; +static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 }; #endif static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8))); diff --git a/linker/linker.cpp b/linker/linker.cpp index 71e3774af..68b3a537a 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -54,6 +54,7 @@ #include "linker_block_allocator.h" #include "linker_gdb_support.h" #include "linker_debug.h" +#include "linker_dlwarning.h" #include "linker_sleb128.h" #include "linker_phdr.h" #include "linker_relocs.h" @@ -182,6 +183,73 @@ static const char* const kAsanDefaultLdPaths[] = { nullptr }; +static bool is_system_library(const std::string& realpath) { + for (const auto& dir : g_default_namespace.get_default_library_paths()) { + if (file_is_in_dir(realpath, dir)) { + return true; + } + } + return false; +} + +#if defined(__LP64__) +static const char* const kSystemLibDir = "/system/lib64"; +#else +static const char* const kSystemLibDir = "/system/lib"; +#endif + +static std::string dirname(const char *path); + +// TODO(dimitry): The grey-list is a workaround for http://b/26394120 --- +// gradually remove libraries from this list until it is gone. +static bool is_greylisted(const char* name, const soinfo* needed_by) { + static const char* const kLibraryGreyList[] = { + "libandroid_runtime.so", + "libbinder.so", + "libcrypto.so", + "libcutils.so", + "libexpat.so", + "libgui.so", + "libmedia.so", + "libnativehelper.so", + "libskia.so", + "libssl.so", + "libstagefright.so", + "libsqlite.so", + "libui.so", + "libutils.so", + "libvorbisidec.so", + nullptr + }; + + // limit greylisting to apps targeting sdk version 23 and below + if (get_application_target_sdk_version() > 23) { + return false; + } + + // if the library needed by a system library - implicitly assume it + // is greylisted + + if (needed_by != nullptr && is_system_library(needed_by->get_realpath())) { + return true; + } + + // if this is an absolute path - make sure it points to /system/lib(64) + if (name[0] == '/' && dirname(name) == kSystemLibDir) { + // and reduce the path to basename + name = basename(name); + } + + for (size_t i = 0; kLibraryGreyList[i] != nullptr; ++i) { + if (strcmp(name, kLibraryGreyList[i]) == 0) { + return true; + } + } + + return false; +} +// END OF WORKAROUND + static const ElfW(Versym) kVersymNotNeeded = 0; static const ElfW(Versym) kVersymGlobal = 1; @@ -491,7 +559,7 @@ static bool realpath_fd(int fd, std::string* realpath) { std::vector<char> buf(PATH_MAX), proc_self_fd(PATH_MAX); __libc_format_buffer(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd); if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) { - PRINT("readlink('%s') failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd); + PRINT("readlink(\"%s\") failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd); return false; } @@ -672,8 +740,8 @@ static bool is_symbol_global_and_defined(const soinfo* si, const ElfW(Sym)* s) { ELF_ST_BIND(s->st_info) == STB_WEAK) { return s->st_shndx != SHN_UNDEF; } else if (ELF_ST_BIND(s->st_info) != STB_LOCAL) { - DL_WARN("unexpected ST_BIND value: %d for '%s' in '%s'", - ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_realpath()); + DL_WARN("unexpected ST_BIND value: %d for \"%s\" in \"%s\"", + ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_realpath()); } return false; @@ -1081,6 +1149,14 @@ class LoadTask { extinfo_ = extinfo; } + bool is_dt_needed() const { + return is_dt_needed_; + } + + void set_dt_needed(bool is_dt_needed) { + is_dt_needed_ = is_dt_needed; + } + const ElfReader& get_elf_reader() const { CHECK(si_ != nullptr); return (*elf_readers_map_)[si_]; @@ -1120,7 +1196,8 @@ class LoadTask { LoadTask(const char* name, soinfo* needed_by, std::unordered_map<const soinfo*, ElfReader>* readers_map) : name_(name), needed_by_(needed_by), si_(nullptr), - fd_(-1), close_fd_(false), file_offset_(0), elf_readers_map_(readers_map) {} + fd_(-1), close_fd_(false), file_offset_(0), elf_readers_map_(readers_map), + is_dt_needed_(false) {} ~LoadTask() { if (fd_ != -1 && close_fd_) { @@ -1136,6 +1213,9 @@ class LoadTask { bool close_fd_; off64_t file_offset_; std::unordered_map<const soinfo*, ElfReader>* elf_readers_map_; + // TODO(dimitry): needed by workaround for http://b/26394120 (the grey-list) + bool is_dt_needed_; + // END OF WORKAROUND DISALLOW_IMPLICIT_CONSTRUCTORS(LoadTask); }; @@ -1412,7 +1492,7 @@ static int open_library_in_zipfile(ZipArchiveCache* zip_archive_cache, } const char* const path = normalized_path.c_str(); - TRACE("Trying zip file open from path '%s' -> normalized '%s'", input_path, path); + TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path); // Treat an '!/' separator inside a path as the separator between the name // of the zip file on disk and the subdirectory to search within it. @@ -1558,6 +1638,14 @@ static int open_library(android_namespace_t* ns, fd = open_library_on_paths(zip_archive_cache, name, file_offset, ns->get_default_library_paths(), realpath); } + // TODO(dimitry): workaround for http://b/26394120 (the grey-list) + if (fd == -1 && ns != &g_default_namespace && is_greylisted(name, needed_by)) { + // try searching for it on default_namespace default_library_path + fd = open_library_on_paths(zip_archive_cache, name, file_offset, + g_default_namespace.get_default_library_paths(), realpath); + } + // END OF WORKAROUND + return fd; } @@ -1567,7 +1655,8 @@ static const char* fix_dt_needed(const char* dt_needed, const char* sopath __unu if (get_application_target_sdk_version() <= 22) { const char* bname = basename(dt_needed); if (bname != dt_needed) { - DL_WARN("'%s' library has invalid DT_NEEDED entry '%s'", sopath, dt_needed); + DL_WARN("library \"%s\" has invalid DT_NEEDED entry \"%s\"", sopath, dt_needed); + add_dlwarning(sopath, "invalid DT_NEEDED entry", dt_needed); } return bname; @@ -1658,25 +1747,40 @@ static bool load_library(android_namespace_t* ns, } if (!ns->is_accessible(realpath)) { - // do not load libraries if they are not accessible for the specified namespace. - const char* needed_or_dlopened_by = task->get_needed_by() == nullptr ? - "(unknown)" : - task->get_needed_by()->get_realpath(); - - DL_ERR("library \"%s\" needed or dlopened by \"%s\" is not accessible for the namespace \"%s\"", - name, needed_or_dlopened_by, ns->get_name()); - - PRINT("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the" - " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\"," - " permitted_paths=\"%s\"]", - name, realpath.c_str(), - needed_or_dlopened_by, - ns->get_name(), - android::base::Join(ns->get_ld_library_paths(), ':').c_str(), - android::base::Join(ns->get_default_library_paths(), ':').c_str(), - android::base::Join(ns->get_permitted_paths(), ':').c_str()); - - return false; + // TODO(dimitry): workaround for http://b/26394120 - the grey-list + const soinfo* needed_by = task->is_dt_needed() ? task->get_needed_by() : nullptr; + if (is_greylisted(name, needed_by)) { + // print warning only if needed by non-system library + if (needed_by == nullptr || !is_system_library(needed_by->get_realpath())) { + const soinfo* needed_or_dlopened_by = task->get_needed_by(); + const char* sopath = needed_or_dlopened_by == nullptr ? "(unknown)" : + needed_or_dlopened_by->get_realpath(); + DL_WARN("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the namespace \"%s\"" + " - the access is temporarily granted as a workaround for http://b/26394120, note that the access" + " will be removed in future releases of Android.", + name, realpath.c_str(), sopath, ns->get_name()); + add_dlwarning(sopath, "unauthorized access to", name); + } + } else { + // do not load libraries if they are not accessible for the specified namespace. + const char* needed_or_dlopened_by = task->get_needed_by() == nullptr ? + "(unknown)" : + task->get_needed_by()->get_realpath(); + + DL_ERR("library \"%s\" needed or dlopened by \"%s\" is not accessible for the namespace \"%s\"", + name, needed_or_dlopened_by, ns->get_name()); + + PRINT("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the" + " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\"," + " permitted_paths=\"%s\"]", + name, realpath.c_str(), + needed_or_dlopened_by, + ns->get_name(), + android::base::Join(ns->get_ld_library_paths(), ':').c_str(), + android::base::Join(ns->get_default_library_paths(), ':').c_str(), + android::base::Join(ns->get_permitted_paths(), ':').c_str()); + return false; + } } soinfo* si = soinfo_alloc(ns, realpath.c_str(), &file_stat, file_offset, rtld_flags); @@ -1822,7 +1926,7 @@ static bool find_library_internal(android_namespace_t* ns, // Library might still be loaded, the accurate detection // of this fact is done by load_library. - TRACE("[ '%s' find_loaded_library_by_soname returned false (*candidate=%s@%p). Trying harder...]", + TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder...]", task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate); if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags)) { @@ -1950,6 +2054,7 @@ static bool find_libraries(android_namespace_t* ns, bool is_dt_needed = needed_by != nullptr && (needed_by != start_with || add_as_children); task->set_extinfo(is_dt_needed ? nullptr : extinfo); + task->set_dt_needed(is_dt_needed); if(!find_library_internal(ns, task, &zip_archive_cache, &load_tasks, rtld_flags)) { return false; @@ -2079,7 +2184,7 @@ static void soinfo_unload(soinfo* root) { } if (!root->can_unload()) { - TRACE("not unloading '%s' - the binary is flagged with NODELETE", root->get_realpath()); + TRACE("not unloading \"%s\" - the binary is flagged with NODELETE", root->get_realpath()); return; } @@ -2677,7 +2782,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r const char* sym_name = nullptr; ElfW(Addr) addend = get_addend(rel, reloc); - DEBUG("Processing '%s' relocation at index %zd", get_realpath(), idx); + DEBUG("Processing \"%s\" relocation at index %zd", get_realpath(), idx); if (type == R_GENERIC_NONE) { continue; } @@ -3435,7 +3540,7 @@ bool soinfo::prelink_image() { /* We can't log anything until the linker is relocated */ bool relocating_linker = (flags_ & FLAG_LINKER) != 0; if (!relocating_linker) { - INFO("[ Linking '%s' ]", get_realpath()); + INFO("[ Linking \"%s\" ]", get_realpath()); DEBUG("si->base = %p si->flags = 0x%08x", reinterpret_cast<void*>(base), flags_); } @@ -3859,6 +3964,7 @@ bool soinfo::prelink_image() { soname_ = basename(realpath_.c_str()); DL_WARN("%s: is missing DT_SONAME will use basename as a replacement: \"%s\"", get_realpath(), soname_); + // Don't call add_dlwarning because a missing DT_SONAME isn't important enough to show in the UI } return true; } @@ -3893,6 +3999,7 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& // phdr_table_protect_segments() after all of them are applied. DL_WARN("%s has text relocations. This is wasting memory and prevents " "security hardening. Please fix.", get_realpath()); + add_dlwarning(get_realpath(), "text relocations"); if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) { DL_ERR("can't unprotect loadable segments for \"%s\": %s", get_realpath(), strerror(errno)); @@ -4156,11 +4263,11 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW( if (!getauxval(AT_SECURE)) { ldpath_env = getenv("LD_LIBRARY_PATH"); if (ldpath_env != nullptr) { - INFO("[ LD_LIBRARY_PATH set to '%s' ]", ldpath_env); + INFO("[ LD_LIBRARY_PATH set to \"%s\" ]", ldpath_env); } ldpreload_env = getenv("LD_PRELOAD"); if (ldpreload_env != nullptr) { - INFO("[ LD_PRELOAD set to '%s' ]", ldpreload_env); + INFO("[ LD_PRELOAD set to \"%s\" ]", ldpreload_env); } } @@ -4319,7 +4426,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW( #endif ElfW(Addr) entry = args.getauxval(AT_ENTRY); - TRACE("[ Ready to execute '%s' @ %p ]", si->get_realpath(), reinterpret_cast<void*>(entry)); + TRACE("[ Ready to execute \"%s\" @ %p ]", si->get_realpath(), reinterpret_cast<void*>(entry)); return entry; } diff --git a/linker/linker_dlwarning.cpp b/linker/linker_dlwarning.cpp new file mode 100644 index 000000000..c53ad66bd --- /dev/null +++ b/linker/linker_dlwarning.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "linker_dlwarning.h" + +#include <strings.h> + +#include <string> + +static std::string current_msg; + +void add_dlwarning(const char* sopath, const char* message, const char* value) { + if (!current_msg.empty()) { + current_msg += '\n'; + } + + current_msg = current_msg + basename(sopath) + ": " + message; + + if (value != nullptr) { + current_msg = current_msg + " \"" + value + "\""; + } +} + +// Resets the current one (like dlerror but instead of +// being thread-local it is process-local). +void get_dlwarning(void* obj, void (*f)(void*, const char*)) { + if (current_msg.empty()) { + f(obj, nullptr); + } else { + std::string msg = current_msg; + current_msg.clear(); + f(obj, msg.c_str()); + } +} diff --git a/linker/linker_dlwarning.h b/linker/linker_dlwarning.h new file mode 100644 index 000000000..0263c720c --- /dev/null +++ b/linker/linker_dlwarning.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LINKER_DLWARNING_H +#define __LINKER_DLWARNING_H + +void add_dlwarning(const char* sopath, const char* message, const char* value = nullptr); + +// Resets the current one (like dlerror but instead of +// being thread-local it is process-local). The user_data +// is used to avoid forcing user into saving the message +// to a global variable. +void get_dlwarning(void* user_data, void (*f)(void*, const char*)); + +#endif /* __LINKER_DLWARNING_H */ diff --git a/linker/linker_mips.cpp b/linker/linker_mips.cpp index 8520c17fe..02375c45d 100644 --- a/linker/linker_mips.cpp +++ b/linker/linker_mips.cpp @@ -67,7 +67,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfW(Addr) sym_addr = 0; const char* sym_name = nullptr; - DEBUG("Processing '%s' relocation at index %zd", get_realpath(), idx); + DEBUG("Processing \"%s\" relocation at index %zd", get_realpath(), idx); if (type == R_GENERIC_NONE) { continue; } diff --git a/linker/linker_utils.cpp b/linker/linker_utils.cpp index 1b0c4e4c9..fb070eed0 100644 --- a/linker/linker_utils.cpp +++ b/linker/linker_utils.cpp @@ -20,7 +20,7 @@ bool normalize_path(const char* path, std::string* normalized_path) { // Input should be an absolute path if (path[0] != '/') { - PRINT("normalize_path - invalid input: '%s', the input path should be absolute", path); + PRINT("normalize_path - invalid input: \"%s\", the input path should be absolute", path); return false; } @@ -89,7 +89,7 @@ bool parse_zip_path(const char* input_path, std::string* zip_path, std::string* } const char* const path = normalized_path.c_str(); - TRACE("Trying zip file open from path '%s' -> normalized '%s'", input_path, path); + TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path); // Treat an '!/' separator inside a path as the separator between the name // of the zip file on disk and the subdirectory to search within it. |