aboutsummaryrefslogtreecommitdiff
path: root/tests/dlfcn_test.cpp
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2022-01-13 15:43:23 -0800
committerElliott Hughes <enh@google.com>2022-01-13 15:46:13 -0800
commit1ff7be0713f25a6dae81303acceddfc82e1c835e (patch)
treeee7c25945b301983858fa0240e843e3130b272c6 /tests/dlfcn_test.cpp
parentc79b02088b0cc46f13a6c2391526761aa2d49c54 (diff)
downloadbionic-1ff7be0713f25a6dae81303acceddfc82e1c835e.tar.gz
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
Diffstat (limited to 'tests/dlfcn_test.cpp')
-rw-r--r--tests/dlfcn_test.cpp98
1 files changed, 21 insertions, 77 deletions
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index a9c2b87ab..0bf877507 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 @@ TEST(dlfcn, RTLD_macros) {
#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)
-
-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;
- }
- }
- break;
- }
- }
+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();
- 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 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;
+
+ // 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