diff options
author | Tong Shen <endlessroad@google.com> | 2014-09-03 17:24:56 -0700 |
---|---|---|
committer | Tong Shen <endlessroad@google.com> | 2014-10-03 11:25:11 -0700 |
commit | 62d1ca3182a6cbb921799825f43ad36821233fd7 (patch) | |
tree | 54d9663f5ce10f41e95fe774d4e4841c1a78bbc3 /compiler | |
parent | 63462448ca4e377074a10a4720aa22f71154dbe9 (diff) | |
download | art-62d1ca3182a6cbb921799825f43ad36821233fd7.zip art-62d1ca3182a6cbb921799825f43ad36821233fd7.tar.gz art-62d1ca3182a6cbb921799825f43ad36821233fd7.tar.bz2 |
ART: Prepare for ELF64.
Only expose necessary interface in ElfFile, and move all details into template class ElfFileImpl.
Change-Id: I9df2bbc55f32ba0ba91f4f3d5d0009e84a2ddf74
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/Android.mk | 2 | ||||
-rw-r--r-- | compiler/elf_builder.h | 3 | ||||
-rw-r--r-- | compiler/elf_fixup.cc | 182 | ||||
-rw-r--r-- | compiler/elf_fixup.h | 56 | ||||
-rw-r--r-- | compiler/elf_stripper.cc | 138 | ||||
-rw-r--r-- | compiler/elf_stripper.h | 39 | ||||
-rw-r--r-- | compiler/elf_writer.cc | 16 | ||||
-rw-r--r-- | compiler/elf_writer.h | 4 | ||||
-rw-r--r-- | compiler/image_test.cc | 4 | ||||
-rw-r--r-- | compiler/image_writer.cc | 7 |
10 files changed, 25 insertions, 426 deletions
diff --git a/compiler/Android.mk b/compiler/Android.mk index 8b5e6d5..133044a 100644 --- a/compiler/Android.mk +++ b/compiler/Android.mk @@ -125,8 +125,6 @@ LIBART_COMPILER_SRC_FILES := \ utils/scoped_arena_allocator.cc \ buffered_output_stream.cc \ compiler.cc \ - elf_fixup.cc \ - elf_stripper.cc \ elf_writer.cc \ elf_writer_quick.cc \ file_output_stream.cc \ diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h index 3be2478..74ee038 100644 --- a/compiler/elf_builder.h +++ b/compiler/elf_builder.h @@ -1094,7 +1094,8 @@ class ElfBuilder FINAL { elf_header_.e_ident[EI_MAG1] = ELFMAG1; elf_header_.e_ident[EI_MAG2] = ELFMAG2; elf_header_.e_ident[EI_MAG3] = ELFMAG3; - elf_header_.e_ident[EI_CLASS] = ELFCLASS32; + elf_header_.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr)) + ? ELFCLASS32 : ELFCLASS64;; elf_header_.e_ident[EI_DATA] = ELFDATA2LSB; elf_header_.e_ident[EI_VERSION] = EV_CURRENT; elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX; diff --git a/compiler/elf_fixup.cc b/compiler/elf_fixup.cc deleted file mode 100644 index 0d34879..0000000 --- a/compiler/elf_fixup.cc +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "elf_fixup.h" - -#include <inttypes.h> -#include <memory> - -#include "base/logging.h" -#include "base/stringprintf.h" -#include "elf_file.h" -#include "elf_writer.h" - -namespace art { - -static const bool DEBUG_FIXUP = false; - -bool ElfFixup::Fixup(File* file, uintptr_t oat_data_begin) { - std::string error_msg; - std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, &error_msg)); - CHECK(elf_file.get() != nullptr) << error_msg; - - // Lookup "oatdata" symbol address. - Elf32_Addr oatdata_address = ElfWriter::GetOatDataAddress(elf_file.get()); - Elf32_Off base_address = oat_data_begin - oatdata_address; - - if (!FixupDynamic(*elf_file.get(), base_address)) { - LOG(WARNING) << "Failed to fixup .dynamic in " << file->GetPath(); - return false; - } - if (!FixupSectionHeaders(*elf_file.get(), base_address)) { - LOG(WARNING) << "Failed to fixup section headers in " << file->GetPath(); - return false; - } - if (!FixupProgramHeaders(*elf_file.get(), base_address)) { - LOG(WARNING) << "Failed to fixup program headers in " << file->GetPath(); - return false; - } - if (!FixupSymbols(*elf_file.get(), base_address, true)) { - LOG(WARNING) << "Failed to fixup .dynsym in " << file->GetPath(); - return false; - } - if (!FixupSymbols(*elf_file.get(), base_address, false)) { - LOG(WARNING) << "Failed to fixup .symtab in " << file->GetPath(); - return false; - } - if (!FixupRelocations(*elf_file.get(), base_address)) { - LOG(WARNING) << "Failed to fixup .rel.dyn in " << file->GetPath(); - return false; - } - if (!elf_file->FixupDebugSections(base_address)) { - LOG(WARNING) << "Failed to fixup debug sections in " << file->GetPath(); - return false; - } - return true; -} - - -bool ElfFixup::FixupDynamic(ElfFile& elf_file, uintptr_t base_address) { - for (Elf32_Word i = 0; i < elf_file.GetDynamicNum(); i++) { - Elf32_Dyn& elf_dyn = elf_file.GetDynamic(i); - Elf32_Word d_tag = elf_dyn.d_tag; - if (IsDynamicSectionPointer(d_tag, elf_file.GetHeader().e_machine)) { - uint32_t d_ptr = elf_dyn.d_un.d_ptr; - if (DEBUG_FIXUP) { - LOG(INFO) << StringPrintf("In %s moving Elf32_Dyn[%d] from 0x%08x to 0x%08" PRIxPTR, - elf_file.GetFile().GetPath().c_str(), i, - d_ptr, d_ptr + base_address); - } - d_ptr += base_address; - elf_dyn.d_un.d_ptr = d_ptr; - } - } - return true; -} - -bool ElfFixup::FixupSectionHeaders(ElfFile& elf_file, uintptr_t base_address) { - for (Elf32_Word i = 0; i < elf_file.GetSectionHeaderNum(); i++) { - Elf32_Shdr* sh = elf_file.GetSectionHeader(i); - CHECK(sh != nullptr); - // 0 implies that the section will not exist in the memory of the process - if (sh->sh_addr == 0) { - continue; - } - if (DEBUG_FIXUP) { - LOG(INFO) << StringPrintf("In %s moving Elf32_Shdr[%d] from 0x%08x to 0x%08" PRIxPTR, - elf_file.GetFile().GetPath().c_str(), i, - sh->sh_addr, sh->sh_addr + base_address); - } - sh->sh_addr += base_address; - } - return true; -} - -bool ElfFixup::FixupProgramHeaders(ElfFile& elf_file, uintptr_t base_address) { - // TODO: ELFObjectFile doesn't have give to Elf32_Phdr, so we do that ourselves for now. - for (Elf32_Word i = 0; i < elf_file.GetProgramHeaderNum(); i++) { - Elf32_Phdr* ph = elf_file.GetProgramHeader(i); - CHECK(ph != nullptr); - CHECK_EQ(ph->p_vaddr, ph->p_paddr) << elf_file.GetFile().GetPath() << " i=" << i; - CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1)))) - << elf_file.GetFile().GetPath() << " i=" << i; - if (DEBUG_FIXUP) { - LOG(INFO) << StringPrintf("In %s moving Elf32_Phdr[%d] from 0x%08x to 0x%08" PRIxPTR, - elf_file.GetFile().GetPath().c_str(), i, - ph->p_vaddr, ph->p_vaddr + base_address); - } - ph->p_vaddr += base_address; - ph->p_paddr += base_address; - CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1)))) - << elf_file.GetFile().GetPath() << " i=" << i; - } - return true; -} - -bool ElfFixup::FixupSymbols(ElfFile& elf_file, uintptr_t base_address, bool dynamic) { - Elf32_Word section_type = dynamic ? SHT_DYNSYM : SHT_SYMTAB; - // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile - Elf32_Shdr* symbol_section = elf_file.FindSectionByType(section_type); - if (symbol_section == nullptr) { - // file is missing optional .symtab - CHECK(!dynamic) << elf_file.GetFile().GetPath(); - return true; - } - for (uint32_t i = 0; i < elf_file.GetSymbolNum(*symbol_section); i++) { - Elf32_Sym* symbol = elf_file.GetSymbol(section_type, i); - CHECK(symbol != nullptr); - if (symbol->st_value != 0) { - if (DEBUG_FIXUP) { - LOG(INFO) << StringPrintf("In %s moving Elf32_Sym[%d] from 0x%08x to 0x%08" PRIxPTR, - elf_file.GetFile().GetPath().c_str(), i, - symbol->st_value, symbol->st_value + base_address); - } - symbol->st_value += base_address; - } - } - return true; -} - -bool ElfFixup::FixupRelocations(ElfFile& elf_file, uintptr_t base_address) { - for (Elf32_Word i = 0; i < elf_file.GetSectionHeaderNum(); i++) { - Elf32_Shdr* sh = elf_file.GetSectionHeader(i); - CHECK(sh != nullptr); - if (sh->sh_type == SHT_REL) { - for (uint32_t i = 0; i < elf_file.GetRelNum(*sh); i++) { - Elf32_Rel& rel = elf_file.GetRel(*sh, i); - if (DEBUG_FIXUP) { - LOG(INFO) << StringPrintf("In %s moving Elf32_Rel[%d] from 0x%08x to 0x%08" PRIxPTR, - elf_file.GetFile().GetPath().c_str(), i, - rel.r_offset, rel.r_offset + base_address); - } - rel.r_offset += base_address; - } - } else if (sh->sh_type == SHT_RELA) { - for (uint32_t i = 0; i < elf_file.GetRelaNum(*sh); i++) { - Elf32_Rela& rela = elf_file.GetRela(*sh, i); - if (DEBUG_FIXUP) { - LOG(INFO) << StringPrintf("In %s moving Elf32_Rela[%d] from 0x%08x to 0x%08" PRIxPTR, - elf_file.GetFile().GetPath().c_str(), i, - rela.r_offset, rela.r_offset + base_address); - } - rela.r_offset += base_address; - } - } - } - return true; -} - -} // namespace art diff --git a/compiler/elf_fixup.h b/compiler/elf_fixup.h deleted file mode 100644 index 1abf06b..0000000 --- a/compiler/elf_fixup.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_COMPILER_ELF_FIXUP_H_ -#define ART_COMPILER_ELF_FIXUP_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "os.h" - -namespace art { - -class ElfFile; - -class ElfFixup { - public: - // Fixup an ELF file so that that oat header will be loaded at oat_begin. - // Returns true on success, false on failure. - static bool Fixup(File* file, uintptr_t oat_data_begin); - - private: - // Fixup .dynamic d_ptr values for the expected base_address. - static bool FixupDynamic(ElfFile& elf_file, uintptr_t base_address); - - // Fixup Elf32_Shdr p_vaddr to load at the desired address. - static bool FixupSectionHeaders(ElfFile& elf_file, uintptr_t base_address); - - // Fixup Elf32_Phdr p_vaddr to load at the desired address. - static bool FixupProgramHeaders(ElfFile& elf_file, uintptr_t base_address); - - // Fixup symbol table - static bool FixupSymbols(ElfFile& elf_file, uintptr_t base_address, bool dynamic); - - // Fixup dynamic relocations - static bool FixupRelocations(ElfFile& elf_file, uintptr_t base_address); - - DISALLOW_IMPLICIT_CONSTRUCTORS(ElfFixup); -}; - -} // namespace art - -#endif // ART_COMPILER_ELF_FIXUP_H_ diff --git a/compiler/elf_stripper.cc b/compiler/elf_stripper.cc deleted file mode 100644 index 457d8a0..0000000 --- a/compiler/elf_stripper.cc +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "elf_stripper.h" - -#include <unistd.h> -#include <sys/types.h> -#include <memory> -#include <vector> - -#include "base/logging.h" -#include "base/stringprintf.h" -#include "elf_file.h" -#include "elf_utils.h" -#include "utils.h" - -namespace art { - -bool ElfStripper::Strip(File* file, std::string* error_msg) { - std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, error_msg)); - if (elf_file.get() == nullptr) { - return false; - } - - // ELF files produced by MCLinker look roughly like this - // - // +------------+ - // | Elf32_Ehdr | contains number of Elf32_Shdr and offset to first - // +------------+ - // | Elf32_Phdr | program headers - // | Elf32_Phdr | - // | ... | - // | Elf32_Phdr | - // +------------+ - // | section | mixture of needed and unneeded sections - // +------------+ - // | section | - // +------------+ - // | ... | - // +------------+ - // | section | - // +------------+ - // | Elf32_Shdr | section headers - // | Elf32_Shdr | - // | ... | contains offset to section start - // | Elf32_Shdr | - // +------------+ - // - // To strip: - // - leave the Elf32_Ehdr and Elf32_Phdr values in place. - // - walk the sections making a new set of Elf32_Shdr section headers for what we want to keep - // - move the sections are keeping up to fill in gaps of sections we want to strip - // - write new Elf32_Shdr section headers to end of file, updating Elf32_Ehdr - // - truncate rest of file - // - - std::vector<Elf32_Shdr> section_headers; - std::vector<Elf32_Word> section_headers_original_indexes; - section_headers.reserve(elf_file->GetSectionHeaderNum()); - - - Elf32_Shdr* string_section = elf_file->GetSectionNameStringSection(); - CHECK(string_section != nullptr); - for (Elf32_Word i = 0; i < elf_file->GetSectionHeaderNum(); i++) { - Elf32_Shdr* sh = elf_file->GetSectionHeader(i); - CHECK(sh != nullptr); - const char* name = elf_file->GetString(*string_section, sh->sh_name); - if (name == nullptr) { - CHECK_EQ(0U, i); - section_headers.push_back(*sh); - section_headers_original_indexes.push_back(0); - continue; - } - if (StartsWith(name, ".debug") - || (strcmp(name, ".strtab") == 0) - || (strcmp(name, ".symtab") == 0)) { - continue; - } - section_headers.push_back(*sh); - section_headers_original_indexes.push_back(i); - } - CHECK_NE(0U, section_headers.size()); - CHECK_EQ(section_headers.size(), section_headers_original_indexes.size()); - - // section 0 is the NULL section, sections start at offset of first section - CHECK(elf_file->GetSectionHeader(1) != nullptr); - Elf32_Off offset = elf_file->GetSectionHeader(1)->sh_offset; - for (size_t i = 1; i < section_headers.size(); i++) { - Elf32_Shdr& new_sh = section_headers[i]; - Elf32_Shdr* old_sh = elf_file->GetSectionHeader(section_headers_original_indexes[i]); - CHECK(old_sh != nullptr); - CHECK_EQ(new_sh.sh_name, old_sh->sh_name); - if (old_sh->sh_addralign > 1) { - offset = RoundUp(offset, old_sh->sh_addralign); - } - if (old_sh->sh_offset == offset) { - // already in place - offset += old_sh->sh_size; - continue; - } - // shift section earlier - memmove(elf_file->Begin() + offset, - elf_file->Begin() + old_sh->sh_offset, - old_sh->sh_size); - new_sh.sh_offset = offset; - offset += old_sh->sh_size; - } - - Elf32_Off shoff = offset; - size_t section_headers_size_in_bytes = section_headers.size() * sizeof(Elf32_Shdr); - memcpy(elf_file->Begin() + offset, §ion_headers[0], section_headers_size_in_bytes); - offset += section_headers_size_in_bytes; - - elf_file->GetHeader().e_shnum = section_headers.size(); - elf_file->GetHeader().e_shoff = shoff; - int result = ftruncate(file->Fd(), offset); - if (result != 0) { - *error_msg = StringPrintf("Failed to truncate while stripping ELF file: '%s': %s", - file->GetPath().c_str(), strerror(errno)); - return false; - } - return true; -} - -} // namespace art diff --git a/compiler/elf_stripper.h b/compiler/elf_stripper.h deleted file mode 100644 index f1a1d46..0000000 --- a/compiler/elf_stripper.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_COMPILER_ELF_STRIPPER_H_ -#define ART_COMPILER_ELF_STRIPPER_H_ - -#include <string> - -#include "base/macros.h" -#include "os.h" - -namespace art { - -class ElfStripper { - public: - // Strip an ELF file of unneeded debugging information. - // Returns true on success, false on failure. - static bool Strip(File* file, std::string* error_msg); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(ElfStripper); -}; - -} // namespace art - -#endif // ART_COMPILER_ELF_STRIPPER_H_ diff --git a/compiler/elf_writer.cc b/compiler/elf_writer.cc index 55ee18e..47402f3 100644 --- a/compiler/elf_writer.cc +++ b/compiler/elf_writer.cc @@ -30,8 +30,8 @@ namespace art { -uint32_t ElfWriter::GetOatDataAddress(ElfFile* elf_file) { - Elf32_Addr oatdata_address = elf_file->FindSymbolAddress(SHT_DYNSYM, +uintptr_t ElfWriter::GetOatDataAddress(ElfFile* elf_file) { + uintptr_t oatdata_address = elf_file->FindSymbolAddress(SHT_DYNSYM, "oatdata", false); CHECK_NE(0U, oatdata_address); @@ -51,4 +51,16 @@ void ElfWriter::GetOatElfInformation(File* file, CHECK_NE(0U, oat_data_offset); } +bool ElfWriter::Fixup(File* file, uintptr_t oat_data_begin) { + std::string error_msg; + std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, &error_msg)); + CHECK(elf_file.get() != nullptr) << error_msg; + + // Lookup "oatdata" symbol address. + uintptr_t oatdata_address = ElfWriter::GetOatDataAddress(elf_file.get()); + uintptr_t base_address = oat_data_begin - oatdata_address; + + return elf_file->Fixup(base_address); +} + } // namespace art diff --git a/compiler/elf_writer.h b/compiler/elf_writer.h index 03b965a..033c1f8 100644 --- a/compiler/elf_writer.h +++ b/compiler/elf_writer.h @@ -42,7 +42,9 @@ class ElfWriter { size_t& oat_data_offset); // Returns runtime oat_data runtime address for an opened ElfFile. - static uint32_t GetOatDataAddress(ElfFile* elf_file); + static uintptr_t GetOatDataAddress(ElfFile* elf_file); + + static bool Fixup(File* file, uintptr_t oat_data_begin); protected: ElfWriter(const CompilerDriver& driver, File* elf_file) diff --git a/compiler/image_test.cc b/compiler/image_test.cc index 2a37049..5834e8e 100644 --- a/compiler/image_test.cc +++ b/compiler/image_test.cc @@ -23,7 +23,7 @@ #include "base/unix_file/fd_file.h" #include "class_linker.h" #include "common_compiler_test.h" -#include "elf_fixup.h" +#include "elf_writer.h" #include "gc/space/image_space.h" #include "image_writer.h" #include "lock_word.h" @@ -101,7 +101,7 @@ TEST_F(ImageTest, WriteRead) { bool success_image = writer.Write(image_file.GetFilename(), dup_oat->GetPath(), dup_oat->GetPath()); ASSERT_TRUE(success_image); - bool success_fixup = ElfFixup::Fixup(dup_oat.get(), writer.GetOatDataBegin()); + bool success_fixup = ElfWriter::Fixup(dup_oat.get(), writer.GetOatDataBegin()); ASSERT_TRUE(success_fixup); } diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 1c8b8d5..6fff5f4 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -811,11 +811,12 @@ void ImageWriter::FixupMethod(ArtMethod* orig, ArtMethod* copy) { } static OatHeader* GetOatHeaderFromElf(ElfFile* elf) { - Elf32_Shdr* data_sec = elf->FindSectionByName(".rodata"); - if (data_sec == nullptr) { + uint64_t data_sec_offset; + bool has_data_sec = elf->GetSectionOffsetAndSize(".rodata", &data_sec_offset, nullptr); + if (!has_data_sec) { return nullptr; } - return reinterpret_cast<OatHeader*>(elf->Begin() + data_sec->sh_offset); + return reinterpret_cast<OatHeader*>(elf->Begin() + data_sec_offset); } void ImageWriter::SetOatChecksumFromElfFile(File* elf_file) { |