summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorTong Shen <endlessroad@google.com>2014-09-03 17:24:56 -0700
committerTong Shen <endlessroad@google.com>2014-10-03 11:25:11 -0700
commit62d1ca3182a6cbb921799825f43ad36821233fd7 (patch)
tree54d9663f5ce10f41e95fe774d4e4841c1a78bbc3 /compiler
parent63462448ca4e377074a10a4720aa22f71154dbe9 (diff)
downloadart-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.mk2
-rw-r--r--compiler/elf_builder.h3
-rw-r--r--compiler/elf_fixup.cc182
-rw-r--r--compiler/elf_fixup.h56
-rw-r--r--compiler/elf_stripper.cc138
-rw-r--r--compiler/elf_stripper.h39
-rw-r--r--compiler/elf_writer.cc16
-rw-r--r--compiler/elf_writer.h4
-rw-r--r--compiler/image_test.cc4
-rw-r--r--compiler/image_writer.cc7
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, &section_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) {