From 30d4d2f8dba0d7cd29cb0eeee53883d73542b7cc Mon Sep 17 00:00:00 2001 From: David Srbecky Date: Wed, 24 Mar 2021 16:11:49 +0000 Subject: Rewrite libdexfile C API to follow NDK guidelines better. Bug: 123517037 Bug: 145347927 Test: test-art-host-gtest-art_libdexfile_support_tests64 Test: test-art-host-gtest-art_libdexfile_external_tests64 Change-Id: I9673872585456937d2f54abb63e3dbd8aad4e9ad --- libdexfile/external/dex_file_supp.cc | 127 +++++------------------------------ 1 file changed, 16 insertions(+), 111 deletions(-) (limited to 'libdexfile/external/dex_file_supp.cc') diff --git a/libdexfile/external/dex_file_supp.cc b/libdexfile/external/dex_file_supp.cc index 6313afea06..23fc88a3a9 100644 --- a/libdexfile/external/dex_file_supp.cc +++ b/libdexfile/external/dex_file_supp.cc @@ -33,21 +33,15 @@ namespace art_api { namespace dex { -#define FOR_ALL_DLFUNCS(MACRO) \ - MACRO(DexFile, ExtDexFileOpenFromMemory) \ - MACRO(DexFile, ExtDexFileGetMethodInfoForOffset) \ - MACRO(DexFile, ExtDexFileGetAllMethodInfos) \ - MACRO(DexFile, ExtDexFileClose) - -#ifdef STATIC_LIB -#define DEFINE_DLFUNC_PTR(CLASS, DLFUNC) decltype(DLFUNC)* CLASS::g_##DLFUNC = DLFUNC; +#if defined(STATIC_LIB) +#define DEFINE_ADEX_FILE_SYMBOL(DLFUNC) decltype(DLFUNC)* g_##DLFUNC = DLFUNC; #else -#define DEFINE_DLFUNC_PTR(CLASS, DLFUNC) decltype(DLFUNC)* CLASS::g_##DLFUNC = nullptr; +#define DEFINE_ADEX_FILE_SYMBOL(DLFUNC) decltype(DLFUNC)* g_##DLFUNC = nullptr; #endif -FOR_ALL_DLFUNCS(DEFINE_DLFUNC_PTR) -#undef DEFINE_DLFUNC_PTR +FOR_EACH_ADEX_FILE_SYMBOL(DEFINE_ADEX_FILE_SYMBOL) +#undef DEFINE_ADEX_FILE_SYMBOL -bool TryLoadLibdexfileExternal([[maybe_unused]] std::string* err_msg) { +bool TryLoadLibdexfile([[maybe_unused]] std::string* err_msg) { #if defined(STATIC_LIB) // Nothing to do here since all function pointers are initialised statically. return true; @@ -76,18 +70,18 @@ bool TryLoadLibdexfileExternal([[maybe_unused]] std::string* err_msg) { return false; } -#define RESOLVE_DLFUNC_PTR(CLASS, DLFUNC) \ - decltype(DLFUNC)* DLFUNC##_ptr = reinterpret_cast(dlsym(handle, #DLFUNC)); \ - if ((DLFUNC) == nullptr) { \ +#define RESOLVE_ADEX_FILE_SYMBOL(DLFUNC) \ + auto DLFUNC##_ptr = reinterpret_cast(dlsym(handle, #DLFUNC)); \ + if (DLFUNC##_ptr == nullptr) { \ *err_msg = dlerror(); \ return false; \ } - FOR_ALL_DLFUNCS(RESOLVE_DLFUNC_PTR); -#undef RESOLVE_DLFUNC_PTR +FOR_EACH_ADEX_FILE_SYMBOL(RESOLVE_ADEX_FILE_SYMBOL) +#undef RESOLVE_ADEX_FILE_SYMBOL -#define SET_DLFUNC_PTR(CLASS, DLFUNC) CLASS::g_##DLFUNC = DLFUNC##_ptr; - FOR_ALL_DLFUNCS(SET_DLFUNC_PTR); -#undef SET_DLFUNC_PTR +#define SET_ADEX_FILE_SYMBOL(DLFUNC) g_##DLFUNC = DLFUNC##_ptr; + FOR_EACH_ADEX_FILE_SYMBOL(SET_ADEX_FILE_SYMBOL); +#undef SET_ADEX_FILE_SYMBOL is_loaded = true; } @@ -96,102 +90,13 @@ bool TryLoadLibdexfileExternal([[maybe_unused]] std::string* err_msg) { #endif // !defined(NO_DEXFILE_SUPPORT) && !defined(STATIC_LIB) } -void LoadLibdexfileExternal() { +void LoadLibdexfile() { #ifndef STATIC_LIB - if (std::string err_msg; !TryLoadLibdexfileExternal(&err_msg)) { + if (std::string err_msg; !TryLoadLibdexfile(&err_msg)) { LOG_ALWAYS_FATAL("%s", err_msg.c_str()); } #endif } -DexFile::~DexFile() { g_ExtDexFileClose(ext_dex_file_); } - -std::unique_ptr DexFile::OpenFromMemory(const void* addr, - size_t* size, - const std::string& location, - /*out*/ std::string* error_msg) { - if (UNLIKELY(g_ExtDexFileOpenFromMemory == nullptr)) { - // Load libdexfile_external.so in this factory function, so instance - // methods don't need to check this. - LoadLibdexfileExternal(); - } - ExtDexFile* ext_dex_file; - int res = g_ExtDexFileOpenFromMemory(addr, size, location.c_str(), &ext_dex_file); - switch (static_cast(res)) { - case kExtDexFileOk: - return std::unique_ptr(new DexFile(ext_dex_file)); - case kExtDexFileInvalidHeader: - *error_msg = std::string("Invalid DexFile header ") + location; - return nullptr; - case kExtDexFileNotEnoughData: - *error_msg = std::string("Not enough data"); - return nullptr; - case kExtDexFileError: - break; - } - *error_msg = std::string("Failed to open DexFile ") + location; - return nullptr; -} - -std::unique_ptr DexFile::OpenFromFd(int fd, - off_t offset, - const std::string& location, - /*out*/ std::string* error_msg) { - using android::base::StringPrintf; - size_t length; - { - struct stat sbuf; - std::memset(&sbuf, 0, sizeof(sbuf)); - if (fstat(fd, &sbuf) == -1) { - *error_msg = StringPrintf("fstat '%s' failed: %s", location.c_str(), std::strerror(errno)); - return nullptr; - } - if (S_ISDIR(sbuf.st_mode)) { - *error_msg = StringPrintf("Attempt to mmap directory '%s'", location.c_str()); - return nullptr; - } - length = sbuf.st_size; - } - - if (static_cast(length) < offset) { - *error_msg = StringPrintf( - "Offset %" PRId64 " too large for '%s' of size %zu", - int64_t{offset}, - location.c_str(), - length); - return nullptr; - } - length -= offset; - - std::unique_ptr map; - map = android::base::MappedFile::FromFd(fd, offset, length, PROT_READ); - if (map == nullptr) { - *error_msg = StringPrintf("mmap '%s' failed: %s", location.c_str(), std::strerror(errno)); - return nullptr; - } - - std::unique_ptr dex = OpenFromMemory(map->data(), &length, location, error_msg); - if (dex != nullptr) { - dex->map_ = std::move(map); // Ensure the map gets freed with the dex file. - } - return dex; -} - -MethodInfo DexFile::GetMethodInfoForOffset(int64_t dex_offset, bool with_signature) { - MethodInfo res{}; - auto set_method = [&res](ExtDexFileMethodInfo* info) { res = AbsorbMethodInfo(info); }; - uint32_t flags = with_signature ? kExtDexFileWithSignature : 0; - GetMethodInfoForOffset(dex_offset, set_method, flags); - return res; -} - -std::vector DexFile::GetAllMethodInfos(bool with_signature) { - std::vector res; - auto add_method = [&res](ExtDexFileMethodInfo* info) { res.push_back(AbsorbMethodInfo(info)); }; - uint32_t flags = with_signature ? kExtDexFileWithSignature : 0; - GetAllMethodInfos(add_method, flags); - return res; -} - } // namespace dex } // namespace art_api -- cgit v1.2.3-59-g8ed1b