summaryrefslogtreecommitdiff
path: root/dex2oat
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2025-02-05 18:23:42 +0000
committer Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2025-02-11 11:24:55 -0800
commit9dd0dc2b8997caa4abce1923177ff3951a237883 (patch)
tree81be25f389cd659b2d2a0f5cf90f44cf2ea098c0 /dex2oat
parentac94fdd1de99bd059535f5ec562996eddcc227b4 (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.bp4
-rw-r--r--dex2oat/dex2oat.cc6
-rw-r--r--dex2oat/dex2oat_test.cc4
-rw-r--r--dex2oat/dex2oat_vdex_test.cc1
-rw-r--r--dex2oat/linker/elf_writer_test.cc135
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(),