blob: 92e5a75aea10ced05b99bc3291a389cf4bba6be8 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "common/dlfcn_injection.h"
#include <irt_syscalls.h>
#include <private/dl_dst_lib.h>
#include <private/inject_arc_linker_hooks.h>
#include <sys/mman.h>
#include <string>
#include <utility>
#include "base/containers/hash_tables.h"
#include "base/strings/string_split.h"
#include "common/alog.h"
#include "common/ndk_support/mmap.h"
#include "common/ndk_support/syscall.h"
#include "common/wrapped_functions.h"
namespace arc {
namespace {
// A map from wrapped symbol names to their function pointers.
typedef base::hash_map<std::string, void*> SymbolMap; // NOLINT
SymbolMap* g_wrapped_symbol_map;
// Names of Android's libraries which we statically link to the main nexe.
typedef base::hash_set<std::string> LibraryNameSet; // NOLINT
LibraryNameSet* g_android_library_names;
// For mmap/munmap, we use --wrap to use posix_translation based
// implementation. We need to convert IRT ABI to libc ABI.
int __nacl_irt_mmap_posix_translation(void** addr, size_t len, int prot,
int flags, int fd, nacl_abi_off_t off) {
// This is __wrap_mmap call so we will kick posix_translation.
void* result = mmap(*addr, len, prot, flags, fd, off);
if (result == MAP_FAILED)
return errno;
*addr = result;
return 0;
}
int __nacl_irt_munmap_posix_translation(void* addr, size_t len) {
// This is __wrap_munmap call so we will kick posix_translation.
int result = munmap(addr, len);
if (result < 0)
return errno;
return 0;
}
} // namespace
void InitDlfcnInjection() {
g_wrapped_symbol_map = new SymbolMap();
for (WrappedFunction* p = kWrappedFunctions; p->name; p++) {
if (!g_wrapped_symbol_map->insert(
std::make_pair(p->name, reinterpret_cast<void*>(p->func))).second)
LOG_ALWAYS_FATAL("Duplicated symbol: %s", p->name);
}
// TODO(crbug.com/336316): Build graphics translation as DSO. Currently
// it is linked statically to arc.nexe, so we need special handling of related
// DSOs.
g_android_library_names = new LibraryNameSet();
g_android_library_names->insert("libEGL.so");
g_android_library_names->insert("libGLESv1_CM.so");
g_android_library_names->insert("libGLESv2.so");
#if !defined(__native_client__)
// Redirect syscall() libc calls to posix_translation when necessary.
(*g_wrapped_symbol_map)["syscall"] = reinterpret_cast<void*>(&RunLibcSyscall);
// See src/common/ndk_support/mmap.h for detail.
(*g_wrapped_symbol_map)["mmap"] = reinterpret_cast<void*>(&MmapForNdk);
(*g_wrapped_symbol_map)["mprotect"] =
reinterpret_cast<void*>(&MprotectForNdk);
#endif // __native_client__
// Inject the custom symbol resolver and posix_translation based
// file operations to the Bionic loader. After we inject the
// posix_translation based file functions, we use munmap and close
// based on posix_translation in dlclose. This is safe as we call
// InitDlfcnInjection before the first dlopen is called, and we do
// not dlclose DT_NEEDED ELF objects.
//
// Note that we have already set up IRT hooks in InitializeIRTHooks,
// so __nacl_irt_close, __nacl_irt_open, __nacl_irt_read, and
// __nacl_irt_write here are not the original IRT functions, but
// ARC's customized versions which call __wrap_*.
__arc_linker_hooks hooks = {
ResolveWrappedSymbol,
IsStaticallyLinkedSharedObject,
__nacl_irt_close,
__nacl_irt_mmap_posix_translation,
__nacl_irt_munmap_posix_translation,
__nacl_irt_open,
__nacl_irt_read,
__nacl_irt_write,
__nacl_irt_fstat,
};
__inject_arc_linker_hooks(&hooks);
}
void* ResolveWrappedSymbol(const char* symbol) {
SymbolMap::const_iterator found = g_wrapped_symbol_map->find(symbol);
return found != g_wrapped_symbol_map->end() ? found->second : NULL;
}
int IsStaticallyLinkedSharedObject(const char* filename) {
LibraryNameSet::const_iterator found =
g_android_library_names->find(filename);
return found != g_android_library_names->end();
}
} // namespace arc