diff options
author | 2025-02-05 18:23:42 +0000 | |
---|---|---|
committer | 2025-02-11 11:24:55 -0800 | |
commit | 9dd0dc2b8997caa4abce1923177ff3951a237883 (patch) | |
tree | 81be25f389cd659b2d2a0f5cf90f44cf2ea098c0 /dex2oat | |
parent | ac94fdd1de99bd059535f5ec562996eddcc227b4 (diff) |
Remove more dead code for ELF file.
`writable` is always false. `program_header_only` is always true except
for in some tests.
The code that obtains information through ElfFile with
`program_header_only=true` in tests are replaced by code that uses
libelf.
Bug: 377474232
Bug: 6527146
Test: art/test.py --host -g
Change-Id: Icc9b4dbae612a90f54b50e090e191fad0a19f709
Diffstat (limited to 'dex2oat')
-rw-r--r-- | dex2oat/Android.bp | 4 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 6 | ||||
-rw-r--r-- | dex2oat/dex2oat_test.cc | 4 | ||||
-rw-r--r-- | dex2oat/dex2oat_vdex_test.cc | 1 | ||||
-rw-r--r-- | dex2oat/linker/elf_writer_test.cc | 135 |
5 files changed, 82 insertions, 68 deletions
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp index 186794e243..5df1fbbad2 100644 --- a/dex2oat/Android.bp +++ b/dex2oat/Android.bp @@ -410,6 +410,9 @@ art_cc_library_static { art_cc_defaults { name: "art_dex2oat_tests_defaults", + defaults: [ + "elfutils_transitive_defaults", // For libelf + ], device_common_data: [ ":art-gtest-jars-AbstractMethod", ":art-gtest-jars-ArrayClassWithUnresolvedComponent", @@ -506,6 +509,7 @@ art_cc_defaults { "liblog", ], static_libs: [ + "libelf", "libgmock", "liblz4", // libart(d)-dex2oat dependency; must be repeated here since it's a static lib. ], diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index a8d3d9346c..24bd112aef 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -1270,8 +1270,7 @@ class Dex2Oat final { if (!input_vdex_.empty()) { std::string error_msg; input_vdex_file_ = VdexFile::Open(input_vdex_, - /* writable */ false, - /* low_4gb */ false, + /*low_4gb=*/false, &error_msg); } @@ -1321,8 +1320,7 @@ class Dex2Oat final { input_vdex_file_ = VdexFile::Open(input_vdex_fd_, s.st_size, "vdex", - /* writable */ false, - /* low_4gb */ false, + /*low_4gb=*/false, &error_msg); // If there's any problem with the passed vdex, just warn and proceed // without it. diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc index 9d837cbf67..97c467b600 100644 --- a/dex2oat/dex2oat_test.cc +++ b/dex2oat/dex2oat_test.cc @@ -1430,7 +1430,6 @@ TEST_F(Dex2oatTest, DontExtract) { { // Check the vdex doesn't have dex. std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location, - /*writable=*/false, /*low_4gb=*/false, &error_msg)); ASSERT_TRUE(vdex != nullptr); @@ -1776,7 +1775,6 @@ TEST_F(Dex2oatTest, DontCopyPlainDex) { // Check that the vdex doesn't have dex code. std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location, - /*writable=*/false, /*low_4gb=*/false, &error_msg)); ASSERT_TRUE(vdex != nullptr); @@ -2031,8 +2029,6 @@ TEST_F(Dex2oatTest, LoadOutOfDateOatFile) { { std::string error_msg; std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file.get(), - /*writable=*/false, - /*program_header_only=*/true, /*low_4gb=*/false, &error_msg)); ASSERT_TRUE(elf_file != nullptr) << error_msg; diff --git a/dex2oat/dex2oat_vdex_test.cc b/dex2oat/dex2oat_vdex_test.cc index afea20cadf..4dc64e3289 100644 --- a/dex2oat/dex2oat_vdex_test.cc +++ b/dex2oat/dex2oat_vdex_test.cc @@ -74,7 +74,6 @@ class Dex2oatVdexTest : public Dex2oatEnvironmentTest { // Verify the vdex file content: only the classes using public APIs should be verified. std::string error_msg; std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location, - /*writable=*/false, /*low_4gb=*/false, &error_msg)); // Check the vdex doesn't have dex. diff --git a/dex2oat/linker/elf_writer_test.cc b/dex2oat/linker/elf_writer_test.cc index e37e41d3b5..913f865e8f 100644 --- a/dex2oat/linker/elf_writer_test.cc +++ b/dex2oat/linker/elf_writer_test.cc @@ -14,8 +14,13 @@ * limitations under the License. */ +#include <gelf.h> +#include <libelf.h> #include <sys/mman.h> // For the PROT_NONE constant. +#include <cstdint> + +#include "android-base/scopeguard.h" #include "base/file_utils.h" #include "base/mem_map.h" #include "base/unix_file/fd_file.h" @@ -83,18 +88,38 @@ class ElfWriterTest : public CommonCompilerDriverTest { } }; -#define EXPECT_ELF_FILE_ADDRESS(ef, expected_value, symbol_name, build_map) \ - do { \ - void* addr = reinterpret_cast<void*>((ef)->FindSymbolAddress(SHT_DYNSYM, \ - symbol_name, \ - build_map)); \ - EXPECT_NE(nullptr, addr); \ - if ((expected_value) == nullptr) { \ - (expected_value) = addr; \ - } \ - EXPECT_EQ(expected_value, addr); \ - EXPECT_EQ(expected_value, (ef)->FindDynamicSymbolAddress(symbol_name)); \ - } while (false) +static void FindSymbolAddress(File* file, const char* symbol_name, /*out*/ uint8_t** addr) { + ASSERT_NE(elf_version(EV_CURRENT), EV_NONE) << "libelf initialization failed: " << elf_errmsg(-1); + + Elf* elf = elf_begin(file->Fd(), ELF_C_READ, /*ref=*/nullptr); + ASSERT_NE(elf, nullptr) << elf_errmsg(-1); + auto elf_cleanup = android::base::make_scope_guard([&]() { elf_end(elf); }); + + Elf_Scn* dyn_scn = nullptr; + GElf_Shdr scn_hdr; + while ((dyn_scn = elf_nextscn(elf, dyn_scn)) != nullptr) { + ASSERT_EQ(gelf_getshdr(dyn_scn, &scn_hdr), &scn_hdr) << elf_errmsg(-1); + if (scn_hdr.sh_type == SHT_DYNSYM) { + break; + } + } + ASSERT_NE(dyn_scn, nullptr) << "Section SHT_DYNSYM not found"; + + Elf_Data* data = elf_getdata(dyn_scn, /*data=*/nullptr); + + // Iterate through dynamic section entries. + for (int i = 0; i < scn_hdr.sh_size / scn_hdr.sh_entsize; i++) { + GElf_Sym sym; + ASSERT_EQ(gelf_getsym(data, i, &sym), &sym) << elf_errmsg(-1); + const char* name = elf_strptr(elf, scn_hdr.sh_link, sym.st_name); + if (strcmp(name, symbol_name) == 0) { + *addr = reinterpret_cast<uint8_t*>(sym.st_value); + break; + } + } + + ASSERT_NE(*addr, nullptr) << "Symbol " << symbol_name << "not found"; +} TEST_F(ElfWriterTest, dlsym) { std::string elf_location = GetCoreOatLocation(); @@ -102,65 +127,65 @@ TEST_F(ElfWriterTest, dlsym) { LOG(INFO) << "elf_filename=" << elf_filename; UnreserveImageSpace(); - void* dl_oatdata = nullptr; - void* dl_oatexec = nullptr; - void* dl_oatlastword = nullptr; + uint8_t* dl_oatdata = nullptr; + uint8_t* dl_oatexec = nullptr; + uint8_t* dl_oatlastword = nullptr; std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str())); ASSERT_TRUE(file.get() != nullptr) << elf_filename; + ASSERT_NO_FATAL_FAILURE(FindSymbolAddress(file.get(), "oatdata", &dl_oatdata)); + ASSERT_NO_FATAL_FAILURE(FindSymbolAddress(file.get(), "oatexec", &dl_oatexec)); + ASSERT_NO_FATAL_FAILURE(FindSymbolAddress(file.get(), "oatlastword", &dl_oatlastword)); { std::string error_msg; std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(), - /*writable=*/ false, - /*program_header_only=*/ false, /*low_4gb=*/false, &error_msg)); CHECK(ef.get() != nullptr) << error_msg; - EXPECT_ELF_FILE_ADDRESS(ef, dl_oatdata, "oatdata", false); - EXPECT_ELF_FILE_ADDRESS(ef, dl_oatexec, "oatexec", false); - EXPECT_ELF_FILE_ADDRESS(ef, dl_oatlastword, "oatlastword", false); - } - { - std::string error_msg; - std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(), - /*writable=*/ false, - /*program_header_only=*/ false, - /*low_4gb=*/ false, - &error_msg)); - CHECK(ef.get() != nullptr) << error_msg; - EXPECT_ELF_FILE_ADDRESS(ef, dl_oatdata, "oatdata", true); - EXPECT_ELF_FILE_ADDRESS(ef, dl_oatexec, "oatexec", true); - EXPECT_ELF_FILE_ADDRESS(ef, dl_oatlastword, "oatlastword", true); - } - { - std::string error_msg; - std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(), - /*writable=*/ false, - /*program_header_only=*/ true, - /*low_4gb=*/ false, - &error_msg)); - CHECK(ef.get() != nullptr) << error_msg; size_t size; bool success = ef->GetLoadedSize(&size, &error_msg); CHECK(success) << error_msg; MemMap reservation = MemMap::MapAnonymous("ElfWriterTest#dlsym reservation", RoundUp(size, MemMap::GetPageSize()), PROT_NONE, - /*low_4gb=*/ true, + /*low_4gb=*/true, &error_msg); CHECK(reservation.IsValid()) << error_msg; uint8_t* base = reservation.Begin(); success = - ef->Load(file.get(), /*executable=*/ false, /*low_4gb=*/ false, &reservation, &error_msg); + ef->Load(file.get(), /*executable=*/false, /*low_4gb=*/false, &reservation, &error_msg); CHECK(success) << error_msg; CHECK(!reservation.IsValid()); EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatdata) + reinterpret_cast<uintptr_t>(base), - reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatdata"))); + reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatdata"))); EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatexec) + reinterpret_cast<uintptr_t>(base), - reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatexec"))); + reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatexec"))); EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatlastword) + reinterpret_cast<uintptr_t>(base), - reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatlastword"))); + reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatlastword"))); + } +} + +static void HasSection(File* file, const char* section_name, /*out*/ bool* result) { + ASSERT_NE(elf_version(EV_CURRENT), EV_NONE) << "libelf initialization failed: " << elf_errmsg(-1); + + Elf* elf = elf_begin(file->Fd(), ELF_C_READ, /*ref=*/nullptr); + ASSERT_NE(elf, nullptr) << elf_errmsg(-1); + auto elf_cleanup = android::base::make_scope_guard([&]() { elf_end(elf); }); + + size_t shstrndx = 0; + ASSERT_EQ(elf_getshdrstrndx(elf, &shstrndx), 0) << elf_errmsg(-1); + + Elf_Scn* dyn_scn = nullptr; + GElf_Shdr scn_hdr; + while ((dyn_scn = elf_nextscn(elf, dyn_scn)) != nullptr) { + ASSERT_EQ(gelf_getshdr(dyn_scn, &scn_hdr), &scn_hdr) << elf_errmsg(-1); + const char* name = elf_strptr(elf, shstrndx, scn_hdr.sh_name); + if (strcmp(name, section_name) == 0) { + *result = true; + return; + } } + *result = false; } TEST_F(ElfWriterTest, CheckBuildIdPresent) { @@ -170,16 +195,10 @@ TEST_F(ElfWriterTest, CheckBuildIdPresent) { std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str())); ASSERT_TRUE(file.get() != nullptr); - { - std::string error_msg; - std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(), - /*writable=*/ false, - /*program_header_only=*/ false, - /*low_4gb=*/ false, - &error_msg)); - CHECK(ef.get() != nullptr) << error_msg; - EXPECT_TRUE(ef->HasSection(".note.gnu.build-id")); - } + + bool result; + ASSERT_NO_FATAL_FAILURE(HasSection(file.get(), ".note.gnu.build-id", &result)); + EXPECT_TRUE(result); } // Check that dynamic sections (.dynamic, .dynsym, .dynstr, .hash) in an oat file are formed @@ -231,9 +250,7 @@ TEST_F(ElfWriterTest, CheckDynamicSection) { std::string error_msg; std::unique_ptr<ElfFile> ef(ElfFile::Open(tmp_oat.GetFile(), - /*writable=*/ false, - /*program_header_only=*/ true, - /*low_4gb=*/ false, + /*low_4gb=*/false, &error_msg)); ASSERT_NE(ef.get(), nullptr) << error_msg; ASSERT_TRUE(ef->Load(tmp_oat.GetFile(), |