summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2024-09-11 17:22:10 +0100
committer Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2024-09-16 11:29:17 +0000
commit3df5451580a6cc40047deb445ad75c75325b92b7 (patch)
tree672651115491913a74ea4ddd2264de80edf1067f
parentb1aeb15401fc27fea97d21d2d392e2bb91a4654a (diff)
Fix discrepancy between oatdump offsets and ELF offsets.
Bug: 154812810 Test: oatdump --oat-file=/system/framework/oat/x86_64/services.odex Change-Id: I83d4da9788f99e2f172fa7e82f861e33df23dd35
-rw-r--r--oatdump/oatdump.cc118
-rw-r--r--runtime/gc/collector/immune_spaces_test.cc5
-rw-r--r--runtime/oat/elf_file.cc2
-rw-r--r--runtime/oat/elf_file.h2
-rw-r--r--runtime/oat/oat_file.cc48
-rw-r--r--runtime/oat/oat_file.h4
6 files changed, 113 insertions, 66 deletions
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 5131a815ad..1afd606f7d 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -396,19 +396,27 @@ class OatDumper {
oat_dex_files_(oat_file.GetOatDexFiles()),
options_(options),
resolved_addr2instr_(0),
- instruction_set_(oat_file_.GetOatHeader().GetInstructionSet()),
- disassembler_(Disassembler::Create(
- instruction_set_,
- new DisassemblerOptions(options_.absolute_addresses_,
- oat_file.Begin(),
- oat_file.End(),
- /* can_read_literals_= */ true,
- Is64BitInstructionSet(instruction_set_) ?
- &Thread::DumpThreadOffset<PointerSize::k64> :
- &Thread::DumpThreadOffset<PointerSize::k32>))) {
+ instruction_set_(oat_file_.GetOatHeader().GetInstructionSet()) {
CHECK(options_.class_loader_ != nullptr);
CHECK(options_.class_filter_ != nullptr);
CHECK(options_.method_filter_ != nullptr);
+
+ std::string error_msg;
+ const uint8_t* elf_begin = oat_file.ComputeElfBegin(&error_msg);
+ DCHECK_NE(elf_begin, nullptr) << error_msg;
+ DCHECK_GE(oat_file.Begin(), elf_begin);
+ oat_offset_ = reinterpret_cast<size_t>(oat_file.Begin()) - reinterpret_cast<size_t>(elf_begin);
+
+ disassembler_ = Disassembler::Create(
+ instruction_set_,
+ new DisassemblerOptions(options_.absolute_addresses_,
+ elf_begin,
+ oat_file.End(),
+ /* can_read_literals_= */ true,
+ Is64BitInstructionSet(instruction_set_) ?
+ &Thread::DumpThreadOffset<PointerSize::k64> :
+ &Thread::DumpThreadOffset<PointerSize::k32>));
+
AddAllOffsets();
}
@@ -453,13 +461,13 @@ class OatDumper {
os << "DEX FILE COUNT:\n";
os << oat_header.GetDexFileCount() << "\n\n";
-#define DUMP_OAT_HEADER_OFFSET(label, offset) \
- os << label " OFFSET:\n"; \
- os << StringPrintf("0x%08x", oat_header.offset()); \
- if (oat_header.offset() != 0 && options_.absolute_addresses_) { \
- os << StringPrintf(" (%p)", oat_file_.Begin() + oat_header.offset()); \
- } \
- os << StringPrintf("\n\n");
+#define DUMP_OAT_HEADER_OFFSET(label, offset) \
+ os << label " OFFSET:\n"; \
+ os << StringPrintf("0x%08zx", AdjustOffset(oat_header.offset())); \
+ if (oat_header.offset() != 0 && options_.absolute_addresses_) { \
+ os << StringPrintf(" (%p)", oat_file_.Begin() + oat_header.offset()); \
+ } \
+ os << StringPrintf("\n\n");
DUMP_OAT_HEADER_OFFSET("EXECUTABLE", GetExecutableOffset);
DUMP_OAT_HEADER_OFFSET("JNI DLSYM LOOKUP TRAMPOLINE",
@@ -508,7 +516,7 @@ class OatDumper {
if (options_.addr2instr_ != 0) {
resolved_addr2instr_ = options_.addr2instr_ + oat_header.GetExecutableOffset();
os << "SEARCH ADDRESS (executable offset + input):\n";
- os << StringPrintf("0x%08x\n\n", resolved_addr2instr_);
+ os << StringPrintf("0x%08zx\n\n", AdjustOffset(resolved_addr2instr_));
}
// Dump .data.img.rel.ro entries.
@@ -932,13 +940,12 @@ class OatDumper {
const uint16_t class_def_index = accessor.GetClassDefIndex();
uint32_t oat_class_offset = oat_dex_file.GetOatClassOffset(class_def_index);
const OatFile::OatClass oat_class = oat_dex_file.GetOatClass(class_def_index);
- os << StringPrintf("%zd: %s (offset=0x%08x) (type_idx=%d)",
+ os << StringPrintf("%zd: %s (offset=0x%08zx) (type_idx=%d)",
static_cast<ssize_t>(class_def_index),
descriptor,
- oat_class_offset,
+ AdjustOffset(oat_class_offset),
accessor.GetClassIdx().index_)
- << " (" << oat_class.GetStatus() << ")"
- << " (" << oat_class.GetType() << ")\n";
+ << " (" << oat_class.GetStatus() << ")" << " (" << oat_class.GetType() << ")\n";
// TODO: include bitmap here if type is kOatClassSomeCompiled?
if (options_.list_classes_) {
continue;
@@ -1186,23 +1193,25 @@ class OatDumper {
if (options_.absolute_addresses_) {
vios->Stream() << StringPrintf("%p ", oat_method_offsets);
}
- vios->Stream() << StringPrintf("(offset=0x%08x)\n", oat_method_offsets_offset);
+ vios->Stream() << StringPrintf("(offset=0x%08zx)\n", AdjustOffset(oat_method_offsets_offset));
if (oat_method_offsets_offset > oat_file_.Size()) {
vios->Stream() << StringPrintf(
- "WARNING: oat method offsets offset 0x%08x is past end of file 0x%08zx.\n",
- oat_method_offsets_offset, oat_file_.Size());
+ "WARNING: oat method offsets offset 0x%08zx is past end of file 0x%08zx.\n",
+ AdjustOffset(oat_method_offsets_offset),
+ AdjustOffset(oat_file_.Size()));
// If we can't read OatMethodOffsets, the rest of the data is dangerous to read.
vios->Stream() << std::flush;
return false;
}
ScopedIndentation indent2(vios);
- vios->Stream() << StringPrintf("code_offset: 0x%08x ", code_offset);
+ vios->Stream() << StringPrintf("code_offset: 0x%08zx ", AdjustOffset(code_offset));
uint32_t aligned_code_begin = AlignCodeOffset(oat_method.GetCodeOffset());
if (aligned_code_begin > oat_file_.Size()) {
- vios->Stream() << StringPrintf("WARNING: "
- "code offset 0x%08x is past end of file 0x%08zx.\n",
- aligned_code_begin, oat_file_.Size());
+ vios->Stream() << StringPrintf(
+ "WARNING: code offset 0x%08zx is past end of file 0x%08zx.\n",
+ AdjustOffset(aligned_code_begin),
+ AdjustOffset(oat_file_.Size()));
success = false;
}
vios->Stream() << "\n";
@@ -1211,18 +1220,19 @@ class OatDumper {
vios->Stream() << "OatQuickMethodHeader ";
uint32_t method_header_offset = oat_method.GetOatQuickMethodHeaderOffset();
const OatQuickMethodHeader* method_header = oat_method.GetOatQuickMethodHeader();
- if (AddStatsObject(method_header)) {
+ if (method_header != nullptr && AddStatsObject(method_header)) {
stats_["QuickMethodHeader"].AddBytes(sizeof(*method_header));
}
if (options_.absolute_addresses_) {
vios->Stream() << StringPrintf("%p ", method_header);
}
- vios->Stream() << StringPrintf("(offset=0x%08x)\n", method_header_offset);
+ vios->Stream() << StringPrintf("(offset=0x%08zx)\n", AdjustOffset(method_header_offset));
if (method_header_offset > oat_file_.Size() ||
sizeof(OatQuickMethodHeader) > oat_file_.Size() - method_header_offset) {
vios->Stream() << StringPrintf(
- "WARNING: oat quick method header at offset 0x%08x is past end of file 0x%08zx.\n",
- method_header_offset, oat_file_.Size());
+ "WARNING: oat quick method header at offset 0x%08zx is past end of file 0x%08zx.\n",
+ AdjustOffset(method_header_offset),
+ AdjustOffset(oat_file_.Size()));
// If we can't read the OatQuickMethodHeader, the rest of the data is dangerous to read.
vios->Stream() << std::flush;
return false;
@@ -1235,14 +1245,15 @@ class OatDumper {
}
uint32_t vmap_table_offset =
(method_header == nullptr) ? 0 : method_header->GetCodeInfoOffset();
- vios->Stream() << StringPrintf("(offset=0x%08x)\n", vmap_table_offset);
-
- size_t vmap_table_offset_limit = method_header->GetCode() - oat_file_.Begin();
- if (vmap_table_offset >= vmap_table_offset_limit) {
- vios->Stream() << StringPrintf("WARNING: "
- "vmap table offset 0x%08x is past end of file 0x%08zx. ",
- vmap_table_offset,
- vmap_table_offset_limit);
+ vios->Stream() << StringPrintf("(offset=0x%08zx)\n", AdjustOffset(vmap_table_offset));
+
+ size_t vmap_table_offset_limit =
+ (method_header == nullptr) ? 0 : (method_header->GetCode() - oat_file_.Begin());
+ if (method_header != nullptr && vmap_table_offset >= vmap_table_offset_limit) {
+ vios->Stream() << StringPrintf(
+ "WARNING: vmap table offset 0x%08zx is past end of file 0x%08zx. ",
+ AdjustOffset(vmap_table_offset),
+ AdjustOffset(vmap_table_offset_limit));
success = false;
} else if (options_.dump_vmap_) {
DumpVmapData(vios, oat_method, code_item_accessor);
@@ -1273,7 +1284,7 @@ class OatDumper {
{
const void* code = oat_method.GetQuickCode();
uint32_t aligned_code_begin = AlignCodeOffset(code_offset);
- uint64_t aligned_code_end = aligned_code_begin + code_size;
+ uint32_t aligned_code_end = aligned_code_begin + code_size;
if (AddStatsObject(code)) {
stats_["Code"].AddBytes(code_size);
}
@@ -1281,24 +1292,23 @@ class OatDumper {
if (options_.absolute_addresses_) {
vios->Stream() << StringPrintf("%p ", code);
}
- vios->Stream() << StringPrintf("(code_offset=0x%08x size=%u)%s\n",
- code_offset,
+ vios->Stream() << StringPrintf("(code_offset=0x%08zx size=%u)%s\n",
+ AdjustOffset(code_offset),
code_size,
code != nullptr ? "..." : "");
ScopedIndentation indent2(vios);
if (aligned_code_begin > oat_file_.Size()) {
- vios->Stream() << StringPrintf("WARNING: "
- "start of code at 0x%08x is past end of file 0x%08zx.",
- aligned_code_begin, oat_file_.Size());
+ vios->Stream() << StringPrintf(
+ "WARNING: start of code at 0x%08zx is past end of file 0x%08zx.",
+ AdjustOffset(aligned_code_begin),
+ AdjustOffset(oat_file_.Size()));
success = false;
} else if (aligned_code_end > oat_file_.Size()) {
vios->Stream() << StringPrintf(
- "WARNING: "
- "end of code at 0x%08" PRIx64 " is past end of file 0x%08zx. "
- "code size is 0x%08x.\n",
- aligned_code_end,
- oat_file_.Size(),
+ "WARNING: end of code at 0x%08zx is past end of file 0x%08zx. code size is 0x%08x.\n",
+ AdjustOffset(aligned_code_end),
+ AdjustOffset(oat_file_.Size()),
code_size);
success = false;
if (options_.disassemble_code_) {
@@ -1764,7 +1774,11 @@ class OatDumper {
// the mask bits would allow reconstructing the other indexes.
}
+ // Adjusts an offset relative to the OAT file begin to an offset relative to the ELF file begin.
+ size_t AdjustOffset(size_t offset) const { return (offset > 0) ? (oat_offset_ + offset) : 0; }
+
const OatFile& oat_file_;
+ size_t oat_offset_;
const std::vector<const OatDexFile*> oat_dex_files_;
const OatDumperOptions& options_;
uint32_t resolved_addr2instr_;
diff --git a/runtime/gc/collector/immune_spaces_test.cc b/runtime/gc/collector/immune_spaces_test.cc
index ee0feb8cbc..d9b60ecff2 100644
--- a/runtime/gc/collector/immune_spaces_test.cc
+++ b/runtime/gc/collector/immune_spaces_test.cc
@@ -38,6 +38,11 @@ class FakeOatFile : public OatFile {
begin_ = begin;
end_ = end;
}
+
+ const uint8_t* ComputeElfBegin(std::string* error_msg) const override {
+ *error_msg = "Not applicable";
+ return nullptr;
+ }
};
class FakeImageSpace : public space::ImageSpace {
diff --git a/runtime/oat/elf_file.cc b/runtime/oat/elf_file.cc
index c66cba1dd0..436a28a603 100644
--- a/runtime/oat/elf_file.cc
+++ b/runtime/oat/elf_file.cc
@@ -1688,6 +1688,8 @@ size_t ElfFile::GetElfSegmentAlignmentFromFile() const {
DELEGATE_TO_IMPL(GetElfSegmentAlignmentFromFile);
}
+const uint8_t* ElfFile::GetBaseAddress() const { DELEGATE_TO_IMPL(GetBaseAddress); }
+
bool ElfFile::Strip(File* file, std::string* error_msg) {
std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, /*low_4gb=*/false, error_msg));
if (elf_file.get() == nullptr) {
diff --git a/runtime/oat/elf_file.h b/runtime/oat/elf_file.h
index 125b4441f1..90e6c61817 100644
--- a/runtime/oat/elf_file.h
+++ b/runtime/oat/elf_file.h
@@ -84,6 +84,8 @@ class ElfFile {
size_t GetElfSegmentAlignmentFromFile() const;
+ const uint8_t* GetBaseAddress() const;
+
// Strip an ELF file of unneeded debugging information.
// Returns true on success, false on failure.
static bool Strip(File* file, std::string* error_msg);
diff --git a/runtime/oat/oat_file.cc b/runtime/oat/oat_file.cc
index 655591f879..879e3f1622 100644
--- a/runtime/oat/oat_file.cc
+++ b/runtime/oat/oat_file.cc
@@ -17,27 +17,17 @@
#include "oat_file.h"
#include <dlfcn.h>
-
-#ifndef __APPLE__
-#include <link.h> // for dl_iterate_phdr.
-#endif
+#include <sys/stat.h>
#include <unistd.h>
+#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <type_traits>
-#include <sys/stat.h>
-
-// dlopen_ext support from bionic.
-#ifdef ART_TARGET_ANDROID
-#include "android/dlext.h"
-#include "nativeloader/dlext_namespaces.h"
-#endif
-#include <android-base/logging.h>
+#include "android-base/logging.h"
#include "android-base/stringprintf.h"
-
#include "arch/instruction_set_features.h"
#include "art_method.h"
#include "base/bit_vector.h"
@@ -61,9 +51,9 @@
#include "dex/utf-inl.h"
#include "elf/elf_utils.h"
#include "elf_file.h"
-#include "gc_root.h"
#include "gc/heap.h"
#include "gc/space/image_space.h"
+#include "gc_root.h"
#include "mirror/class.h"
#include "mirror/object-inl.h"
#include "oat.h"
@@ -73,6 +63,16 @@
#include "vdex_file.h"
#include "verifier/verifier_deps.h"
+#ifndef __APPLE__
+#include <link.h> // for dl_iterate_phdr.
+#endif
+
+// dlopen_ext support from bionic.
+#ifdef ART_TARGET_ANDROID
+#include "android/dlext.h"
+#include "nativeloader/dlext_namespaces.h"
+#endif
+
namespace art HIDDEN {
using android::base::StringAppendV;
@@ -1170,6 +1170,16 @@ class DlOpenOatFile final : public OatFileBase {
// Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
void PreSetup(const std::string& elf_filename) override;
+ const uint8_t* ComputeElfBegin(std::string* error_msg) const override {
+ Dl_info info;
+ if (dladdr(Begin(), &info) == 0) {
+ *error_msg =
+ StringPrintf("Failed to dladdr '%s': %s", GetLocation().c_str(), strerror(errno));
+ return nullptr;
+ }
+ return reinterpret_cast<const uint8_t*>(info.dli_fbase);
+ }
+
private:
bool Dlopen(const std::string& elf_filename,
/*inout*/MemMap* reservation, // Where to load if not null.
@@ -1601,6 +1611,10 @@ class ElfOatFile final : public OatFileBase {
void PreSetup([[maybe_unused]] const std::string& elf_filename) override {}
+ const uint8_t* ComputeElfBegin(std::string*) const override {
+ return elf_file_->GetBaseAddress();
+ }
+
private:
bool ElfFileOpen(File* file,
bool writable,
@@ -1888,6 +1902,12 @@ class OatFileBackedByVdex final : public OatFileBase {
return nullptr;
}
+ const uint8_t* ComputeElfBegin(std::string* error_msg) const override {
+ *error_msg = StringPrintf("Cannot get ELF begin because '%s' is not backed by an ELF file",
+ GetLocation().c_str());
+ return nullptr;
+ }
+
private:
std::unique_ptr<OatHeader> oat_header_;
diff --git a/runtime/oat/oat_file.h b/runtime/oat/oat_file.h
index d37dc76c54..39304f6a8c 100644
--- a/runtime/oat/oat_file.h
+++ b/runtime/oat/oat_file.h
@@ -361,6 +361,10 @@ class OatFile {
return DexEnd() - DexBegin();
}
+ // Returns the base address of the ELF file, or nullptr if the oat file is not backed by an ELF
+ // file or an error occurred.
+ virtual const uint8_t* ComputeElfBegin(std::string* error_msg) const = 0;
+
EXPORT const uint8_t* Begin() const;
EXPORT const uint8_t* End() const;