diff options
author | 2024-09-11 17:22:10 +0100 | |
---|---|---|
committer | 2024-09-16 11:29:17 +0000 | |
commit | 3df5451580a6cc40047deb445ad75c75325b92b7 (patch) | |
tree | 672651115491913a74ea4ddd2264de80edf1067f | |
parent | b1aeb15401fc27fea97d21d2d392e2bb91a4654a (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.cc | 118 | ||||
-rw-r--r-- | runtime/gc/collector/immune_spaces_test.cc | 5 | ||||
-rw-r--r-- | runtime/oat/elf_file.cc | 2 | ||||
-rw-r--r-- | runtime/oat/elf_file.h | 2 | ||||
-rw-r--r-- | runtime/oat/oat_file.cc | 48 | ||||
-rw-r--r-- | runtime/oat/oat_file.h | 4 |
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; |