Don't use LLVM when readelf(1) will do. This was probably the least worst choice at the time, but we have toybox readelf now, which is a much lighter-weight dependency (that we already have for some other tests). This is also one less use of the *renderscript* LLVM, which we'll be wanting to finally delete soon. Test: treehugger Change-Id: I0e05b8f139ec6e6a425b575368f3d514b8b1cc64
diff --git a/tests/Android.bp b/tests/Android.bp index e7273c0..b6d7774 100644 --- a/tests/Android.bp +++ b/tests/Android.bp
@@ -772,12 +772,6 @@ "libmeminfo", "libprocinfo", "libziparchive", - "libLLVMObject", - "libLLVMBitReader", - "libLLVMMC", - "libLLVMMCParser", - "libLLVMCore", - "libLLVMSupport", ], }, }, @@ -867,12 +861,6 @@ "libziparchive", "libz", "libutils", - "libLLVMObject", - "libLLVMBitReader", - "libLLVMMC", - "libLLVMMCParser", - "libLLVMCore", - "libLLVMSupport", ], ldflags: [ "-Wl,--rpath,${ORIGIN}/bionic-loader-test-libs",
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp index a9c2b87..0bf8775 100644 --- a/tests/dlfcn_test.cpp +++ b/tests/dlfcn_test.cpp
@@ -17,7 +17,9 @@ #include <gtest/gtest.h> #include <dlfcn.h> +#include <elf.h> #include <limits.h> +#include <link.h> #include <stdint.h> #include <stdio.h> #include <string.h> @@ -38,24 +40,6 @@ #include "dlfcn_symlink_support.h" #include "utils.h" -#if defined(__BIONIC__) && (defined(__arm__) || defined(__i386__)) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-parameter" - -#include <llvm/ADT/StringRef.h> -#include <llvm/Object/Binary.h> -#include <llvm/Object/ELFObjectFile.h> -#include <llvm/Object/ObjectFile.h> - -#pragma clang diagnostic pop -#endif // defined(__ANDROID__) && (defined(__arm__) || defined(__i386__)) - -// Declared manually because the macro definitions in <elf.h> conflict with LLVM headers. -#ifdef __arm__ -typedef uintptr_t _Unwind_Ptr; -extern "C" _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr, int*); -#endif - #define ASSERT_SUBSTR(needle, haystack) \ ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack) @@ -1542,75 +1526,35 @@ #if defined(__BIONIC__) #if defined(__arm__) -const llvm::ELF::Elf32_Dyn* to_dynamic_table(const char* p) { - return reinterpret_cast<const llvm::ELF::Elf32_Dyn*>(p); -} -// Duplicate these definitions here because they are android specific -// - note that we cannot include <elf.h> because #defines conflict with -// enum names provided by LLVM. -// - we also don't use llvm::ELF::DT_LOOS because its value is 0x60000000 -// rather than the 0x6000000d we expect -#define DT_LOOS 0x6000000d -#define DT_ANDROID_REL (DT_LOOS + 2) -#define DT_ANDROID_RELA (DT_LOOS + 4) +void validate_compatibility_of_native_library(const std::string& soname, const std::string& path) { + // Grab the dynamic section in text form... + ExecTestHelper eth; + eth.SetArgs({"readelf", "-dW", path.c_str(), nullptr}); + eth.Run([&]() { execvpe("readelf", eth.GetArgs(), eth.GetEnv()); }, 0, nullptr); + std::string output = eth.GetOutput(); -template<typename ELFT> -void validate_compatibility_of_native_library(const std::string& soname, - const std::string& path, ELFT* elf) { - bool has_elf_hash = false; - bool has_android_rel = false; - bool has_rel = false; - // Find dynamic section and check that DT_HASH and there is no DT_ANDROID_REL - for (auto it = elf->section_begin(); it != elf->section_end(); ++it) { - const llvm::object::ELFSectionRef& section_ref = *it; - if (section_ref.getType() == llvm::ELF::SHT_DYNAMIC) { - llvm::StringRef data; - ASSERT_TRUE(!it->getContents(data)) << "unable to get SHT_DYNAMIC section data"; - for (auto d = to_dynamic_table(data.data()); d->d_tag != llvm::ELF::DT_NULL; ++d) { - if (d->d_tag == llvm::ELF::DT_HASH) { - has_elf_hash = true; - } else if (d->d_tag == DT_ANDROID_REL || d->d_tag == DT_ANDROID_RELA) { - has_android_rel = true; - } else if (d->d_tag == llvm::ELF::DT_REL || d->d_tag == llvm::ELF::DT_RELA) { - has_rel = true; - } - } + // Check that there *is* a legacy DT_HASH (not just a GNU hash)... + ASSERT_TRUE(std::regex_search(output, std::regex("\\(HASH\\)"))) << output; + // Check that there is no DT_ANDROID_REL or DT_ANDROID_RELA... + ASSERT_FALSE(std::regex_search(output, std::regex("\\(ANDROID_REL\\)"))) << output; + ASSERT_FALSE(std::regex_search(output, std::regex("\\(ANDROID_RELA\\)"))) << output; - break; - } - } - - ASSERT_TRUE(has_elf_hash) << path.c_str() << ": missing elf hash (DT_HASH)"; - ASSERT_TRUE(!has_android_rel) << path.c_str() << ": has packed relocations"; - // libdl.so is simple enough that it might not have any relocations, so - // exempt it from the DT_REL/DT_RELA check. - if (soname != "libdl.so") { - ASSERT_TRUE(has_rel) << path.c_str() << ": missing DT_REL/DT_RELA"; - } + // Check that we have regular non-packed relocations. + // libdl.so is simple enough that it doesn't have any relocations. + ASSERT_TRUE(std::regex_search(output, std::regex("\\(RELA?\\)")) || soname == "libdl.so") + << output; } void validate_compatibility_of_native_library(const std::string& soname) { // On the systems with emulation system libraries would be of different // architecture. Try to use alternate paths first. std::string path = std::string(ALTERNATE_PATH_TO_SYSTEM_LIB) + soname; - auto binary_or_error = llvm::object::createBinary(path); - if (!binary_or_error) { + if (access(path.c_str(), R_OK) != 0) { path = std::string(PATH_TO_SYSTEM_LIB) + soname; - binary_or_error = llvm::object::createBinary(path); + ASSERT_EQ(0, access(path.c_str(), R_OK)); } - ASSERT_FALSE(!binary_or_error); - - llvm::object::Binary* binary = binary_or_error.get().getBinary(); - - auto obj = llvm::dyn_cast<llvm::object::ObjectFile>(binary); - ASSERT_TRUE(obj != nullptr); - - auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(obj); - - ASSERT_TRUE(elf != nullptr); - - validate_compatibility_of_native_library(soname, path, elf); + validate_compatibility_of_native_library(soname, path); } // This is a test for app compatibility workaround for arm apps