Revert "Allow method references across oat files for multi-image."
Breaks Quick tests.
This reverts commit 6065402316da2b51eed5fc34cffbd991766bd408.
Change-Id: I8a5469ba7cea5f46b85cb489b3e0ef06ed548f03
diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h
index f7da609..b673eeb 100644
--- a/compiler/elf_builder.h
+++ b/compiler/elf_builder.h
@@ -86,24 +86,12 @@
// Base class of all sections.
class Section : public OutputStream {
public:
- Section(ElfBuilder<ElfTypes>* owner,
- const std::string& name,
- Elf_Word type,
- Elf_Word flags,
- const Section* link,
- Elf_Word info,
- Elf_Word align,
- Elf_Word entsize)
- : OutputStream(name),
- owner_(owner),
- header_(),
- section_index_(0),
- name_(name),
- link_(link),
- started_(false),
- finished_(false),
- phdr_flags_(PF_R),
- phdr_type_(0) {
+ Section(ElfBuilder<ElfTypes>* owner, const std::string& name,
+ Elf_Word type, Elf_Word flags, const Section* link,
+ Elf_Word info, Elf_Word align, Elf_Word entsize)
+ : OutputStream(name), owner_(owner), header_(),
+ section_index_(0), name_(name), link_(link),
+ started_(false), finished_(false), phdr_flags_(PF_R), phdr_type_(0) {
DCHECK_GE(align, 1u);
header_.sh_type = type;
header_.sh_flags = flags;
@@ -240,84 +228,12 @@
DISALLOW_COPY_AND_ASSIGN(Section);
};
- class CachedSection : public Section {
- public:
- CachedSection(ElfBuilder<ElfTypes>* owner,
- const std::string& name,
- Elf_Word type,
- Elf_Word flags,
- const Section* link,
- Elf_Word info,
- Elf_Word align,
- Elf_Word entsize)
- : Section(owner, name, type, flags, link, info, align, entsize), cache_() { }
-
- Elf_Word Add(const void* data, size_t length) {
- Elf_Word offset = cache_.size();
- const uint8_t* d = reinterpret_cast<const uint8_t*>(data);
- cache_.insert(cache_.end(), d, d + length);
- return offset;
- }
-
- Elf_Word GetCacheSize() {
- return cache_.size();
- }
-
- void Write() {
- this->WriteFully(cache_.data(), cache_.size());
- cache_.clear();
- cache_.shrink_to_fit();
- }
-
- void WriteCachedSection() {
- this->Start();
- Write();
- this->End();
- }
-
- private:
- std::vector<uint8_t> cache_;
- };
-
- // Writer of .dynstr section.
- class CachedStringSection FINAL : public CachedSection {
- public:
- CachedStringSection(ElfBuilder<ElfTypes>* owner,
- const std::string& name,
- Elf_Word flags,
- Elf_Word align)
- : CachedSection(owner,
- name,
- SHT_STRTAB,
- flags,
- /* link */ nullptr,
- /* info */ 0,
- align,
- /* entsize */ 0) { }
-
- Elf_Word Add(const std::string& name) {
- if (CachedSection::GetCacheSize() == 0u) {
- DCHECK(name.empty());
- }
- return CachedSection::Add(name.c_str(), name.length() + 1);
- }
- };
-
- // Writer of .strtab and .shstrtab sections.
+ // Writer of .dynstr .strtab and .shstrtab sections.
class StringSection FINAL : public Section {
public:
- StringSection(ElfBuilder<ElfTypes>* owner,
- const std::string& name,
- Elf_Word flags,
- Elf_Word align)
- : Section(owner,
- name,
- SHT_STRTAB,
- flags,
- /* link */ nullptr,
- /* info */ 0,
- align,
- /* entsize */ 0),
+ StringSection(ElfBuilder<ElfTypes>* owner, const std::string& name,
+ Elf_Word flags, Elf_Word align)
+ : Section(owner, name, SHT_STRTAB, flags, nullptr, 0, align, 0),
current_offset_(0) {
}
@@ -336,60 +252,42 @@
};
// Writer of .dynsym and .symtab sections.
- class SymbolSection FINAL : public CachedSection {
+ class SymbolSection FINAL : public Section {
public:
- SymbolSection(ElfBuilder<ElfTypes>* owner,
- const std::string& name,
- Elf_Word type,
- Elf_Word flags,
- Section* strtab)
- : CachedSection(owner,
- name,
- type,
- flags,
- strtab,
- /* info */ 0,
- sizeof(Elf_Off),
- sizeof(Elf_Sym)) {
- // The symbol table always has to start with NULL symbol.
- Elf_Sym null_symbol = Elf_Sym();
- CachedSection::Add(&null_symbol, sizeof(null_symbol));
+ SymbolSection(ElfBuilder<ElfTypes>* owner, const std::string& name,
+ Elf_Word type, Elf_Word flags, StringSection* strtab)
+ : Section(owner, name, type, flags, strtab, 0,
+ sizeof(Elf_Off), sizeof(Elf_Sym)) {
}
// Buffer symbol for this section. It will be written later.
// If the symbol's section is null, it will be considered absolute (SHN_ABS).
// (we use this in JIT to reference code which is stored outside the debug ELF file)
- void Add(Elf_Word name,
- const Section* section,
- Elf_Addr addr,
- bool is_relative,
- Elf_Word size,
- uint8_t binding,
- uint8_t type,
- uint8_t other = 0) {
- DCHECK(section != nullptr || !is_relative);
- Elf_Addr abs_addr = addr + (is_relative ? section->GetAddress() : 0);
- Elf_Word section_index =
- (section != nullptr) ? section->GetSectionIndex() : static_cast<Elf_Word>(SHN_ABS);
- Add(name, section_index, abs_addr, size, binding, type, other);
- }
-
- void Add(Elf_Word name,
- Elf_Word section_index,
- Elf_Addr addr,
- Elf_Word size,
- uint8_t binding,
- uint8_t type,
- uint8_t other = 0) {
+ void Add(Elf_Word name, const Section* section,
+ Elf_Addr addr, bool is_relative, Elf_Word size,
+ uint8_t binding, uint8_t type, uint8_t other = 0) {
Elf_Sym sym = Elf_Sym();
sym.st_name = name;
- sym.st_value = addr;
+ sym.st_value = addr + (is_relative ? section->GetAddress() : 0);
sym.st_size = size;
sym.st_other = other;
- sym.st_shndx = section_index;
+ sym.st_shndx = (section != nullptr ? section->GetSectionIndex()
+ : static_cast<Elf_Word>(SHN_ABS));
sym.st_info = (binding << 4) + (type & 0xf);
- CachedSection::Add(&sym, sizeof(sym));
+ symbols_.push_back(sym);
}
+
+ void Write() {
+ // The symbol table always has to start with NULL symbol.
+ Elf_Sym null_symbol = Elf_Sym();
+ this->WriteFully(&null_symbol, sizeof(null_symbol));
+ this->WriteFully(symbols_.data(), symbols_.size() * sizeof(symbols_[0]));
+ symbols_.clear();
+ symbols_.shrink_to_fit();
+ }
+
+ private:
+ std::vector<Elf_Sym> symbols_;
};
ElfBuilder(InstructionSet isa, OutputStream* output)
@@ -411,8 +309,6 @@
debug_line_(this, ".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0),
shstrtab_(this, ".shstrtab", 0, 1),
started_(false),
- write_program_headers_(false),
- loaded_size_(0u),
virtual_address_(0) {
text_.phdr_flags_ = PF_R | PF_X;
bss_.phdr_flags_ = PF_R | PF_W;
@@ -484,14 +380,6 @@
void End() {
DCHECK(started_);
- // Note: loaded_size_ == 0 for tests that don't write .rodata, .text, .bss,
- // .dynstr, dynsym, .hash and .dynamic. These tests should not read loaded_size_.
- // TODO: Either refactor the .eh_frame creation so that it counts towards loaded_size_,
- // or remove all support for .eh_frame. (The currently unused .eh_frame counts towards
- // the virtual_address_ but we don't consider it for loaded_size_.)
- CHECK(loaded_size_ == 0 || loaded_size_ == RoundUp(virtual_address_, kPageSize))
- << loaded_size_ << " " << virtual_address_;
-
// Write section names and finish the section headers.
shstrtab_.Start();
shstrtab_.Write("");
@@ -546,58 +434,45 @@
// information like the address and size of .rodata and .text.
// It also contains other metadata like the SONAME.
// The .dynamic section is found using the PT_DYNAMIC program header.
- void PrepareDynamicSection(const std::string& elf_file_path,
- Elf_Word rodata_size,
- Elf_Word text_size,
- Elf_Word bss_size) {
+ void WriteDynamicSection(const std::string& elf_file_path) {
std::string soname(elf_file_path);
size_t directory_separator_pos = soname.rfind('/');
if (directory_separator_pos != std::string::npos) {
soname = soname.substr(directory_separator_pos + 1);
}
- // Calculate addresses of .text, .bss and .dynstr.
- DCHECK_EQ(rodata_.header_.sh_addralign, static_cast<Elf_Word>(kPageSize));
- DCHECK_EQ(text_.header_.sh_addralign, static_cast<Elf_Word>(kPageSize));
- DCHECK_EQ(bss_.header_.sh_addralign, static_cast<Elf_Word>(kPageSize));
- DCHECK_EQ(dynstr_.header_.sh_addralign, static_cast<Elf_Word>(kPageSize));
- Elf_Word rodata_address = rodata_.GetAddress();
- Elf_Word text_address = RoundUp(rodata_address + rodata_size, kPageSize);
- Elf_Word bss_address = RoundUp(text_address + text_size, kPageSize);
- Elf_Word dynstr_address = RoundUp(bss_address + bss_size, kPageSize);
-
- // Cache .dynstr, .dynsym and .hash data.
- dynstr_.Add(""); // dynstr should start with empty string.
- Elf_Word rodata_index = rodata_.GetSectionIndex();
- Elf_Word oatdata = dynstr_.Add("oatdata");
- dynsym_.Add(oatdata, rodata_index, rodata_address, rodata_size, STB_GLOBAL, STT_OBJECT);
- if (text_size != 0u) {
- Elf_Word text_index = rodata_index + 1u;
- Elf_Word oatexec = dynstr_.Add("oatexec");
- dynsym_.Add(oatexec, text_index, text_address, text_size, STB_GLOBAL, STT_OBJECT);
- Elf_Word oatlastword = dynstr_.Add("oatlastword");
- Elf_Word oatlastword_address = text_address + text_size - 4;
- dynsym_.Add(oatlastword, text_index, oatlastword_address, 4, STB_GLOBAL, STT_OBJECT);
- } else if (rodata_size != 0) {
+ dynstr_.Start();
+ dynstr_.Write(""); // dynstr should start with empty string.
+ dynsym_.Add(dynstr_.Write("oatdata"), &rodata_, 0, true,
+ rodata_.GetSize(), STB_GLOBAL, STT_OBJECT);
+ if (text_.GetSize() != 0u) {
+ dynsym_.Add(dynstr_.Write("oatexec"), &text_, 0, true,
+ text_.GetSize(), STB_GLOBAL, STT_OBJECT);
+ dynsym_.Add(dynstr_.Write("oatlastword"), &text_, text_.GetSize() - 4,
+ true, 4, STB_GLOBAL, STT_OBJECT);
+ } else if (rodata_.GetSize() != 0) {
// rodata_ can be size 0 for dwarf_test.
- Elf_Word oatlastword = dynstr_.Add("oatlastword");
- Elf_Word oatlastword_address = rodata_address + rodata_size - 4;
- dynsym_.Add(oatlastword, rodata_index, oatlastword_address, 4, STB_GLOBAL, STT_OBJECT);
+ dynsym_.Add(dynstr_.Write("oatlastword"), &rodata_, rodata_.GetSize() - 4,
+ true, 4, STB_GLOBAL, STT_OBJECT);
}
- if (bss_size != 0u) {
- Elf_Word bss_index = rodata_index + 1u + (text_size != 0 ? 1u : 0u);
- Elf_Word oatbss = dynstr_.Add("oatbss");
- dynsym_.Add(oatbss, bss_index, bss_address, bss_size, STB_GLOBAL, STT_OBJECT);
- Elf_Word oatbsslastword = dynstr_.Add("oatbsslastword");
- Elf_Word bsslastword_address = bss_address + bss_size - 4;
- dynsym_.Add(oatbsslastword, bss_index, bsslastword_address, 4, STB_GLOBAL, STT_OBJECT);
+ if (bss_.finished_) {
+ dynsym_.Add(dynstr_.Write("oatbss"), &bss_,
+ 0, true, bss_.GetSize(), STB_GLOBAL, STT_OBJECT);
+ dynsym_.Add(dynstr_.Write("oatbsslastword"), &bss_,
+ bss_.GetSize() - 4, true, 4, STB_GLOBAL, STT_OBJECT);
}
- Elf_Word soname_offset = dynstr_.Add(soname);
+ Elf_Word soname_offset = dynstr_.Write(soname);
+ dynstr_.End();
+
+ dynsym_.Start();
+ dynsym_.Write();
+ dynsym_.End();
// We do not really need a hash-table since there is so few entries.
// However, the hash-table is the only way the linker can actually
// determine the number of symbols in .dynsym so it is required.
- int count = dynsym_.GetCacheSize() / sizeof(Elf_Sym); // Includes NULL.
+ hash_.Start();
+ int count = dynsym_.GetSize() / sizeof(Elf_Sym); // Includes NULL.
std::vector<Elf_Word> hash;
hash.push_back(1); // Number of buckets.
hash.push_back(count); // Number of chains.
@@ -609,44 +484,21 @@
hash.push_back(i + 1); // Each symbol points to the next one.
}
hash.push_back(0); // Last symbol terminates the chain.
- hash_.Add(hash.data(), hash.size() * sizeof(hash[0]));
+ hash_.WriteFully(hash.data(), hash.size() * sizeof(hash[0]));
+ hash_.End();
- // Calculate addresses of .dynsym, .hash and .dynamic.
- DCHECK_EQ(dynstr_.header_.sh_flags, dynsym_.header_.sh_flags);
- DCHECK_EQ(dynsym_.header_.sh_flags, hash_.header_.sh_flags);
- Elf_Word dynsym_address =
- RoundUp(dynstr_address + dynstr_.GetCacheSize(), dynsym_.header_.sh_addralign);
- Elf_Word hash_address =
- RoundUp(dynsym_address + dynsym_.GetCacheSize(), hash_.header_.sh_addralign);
- DCHECK_EQ(dynamic_.header_.sh_addralign, static_cast<Elf_Word>(kPageSize));
- Elf_Word dynamic_address = RoundUp(hash_address + dynsym_.GetCacheSize(), kPageSize);
-
+ dynamic_.Start();
Elf_Dyn dyns[] = {
- { DT_HASH, { hash_address } },
- { DT_STRTAB, { dynstr_address } },
- { DT_SYMTAB, { dynsym_address } },
+ { DT_HASH, { hash_.GetAddress() } },
+ { DT_STRTAB, { dynstr_.GetAddress() } },
+ { DT_SYMTAB, { dynsym_.GetAddress() } },
{ DT_SYMENT, { sizeof(Elf_Sym) } },
- { DT_STRSZ, { dynstr_.GetCacheSize() } },
+ { DT_STRSZ, { dynstr_.GetSize() } },
{ DT_SONAME, { soname_offset } },
{ DT_NULL, { 0 } },
};
- dynamic_.Add(&dyns, sizeof(dyns));
-
- loaded_size_ = RoundUp(dynamic_address + dynamic_.GetCacheSize(), kPageSize);
- }
-
- void WriteDynamicSection() {
- dynstr_.WriteCachedSection();
- dynsym_.WriteCachedSection();
- hash_.WriteCachedSection();
- dynamic_.WriteCachedSection();
-
- CHECK_EQ(loaded_size_, RoundUp(dynamic_.GetAddress() + dynamic_.GetSize(), kPageSize));
- }
-
- Elf_Word GetLoadedSize() {
- CHECK_NE(loaded_size_, 0u);
- return loaded_size_;
+ dynamic_.WriteFully(&dyns, sizeof(dyns));
+ dynamic_.End();
}
// Returns true if all writes and seeks on the output stream succeeded.
@@ -824,10 +676,10 @@
Section rodata_;
Section text_;
Section bss_;
- CachedStringSection dynstr_;
+ StringSection dynstr_;
SymbolSection dynsym_;
- CachedSection hash_;
- CachedSection dynamic_;
+ Section hash_;
+ Section dynamic_;
Section eh_frame_;
Section eh_frame_hdr_;
StringSection strtab_;
@@ -842,14 +694,12 @@
std::vector<Section*> sections_;
bool started_;
- bool write_program_headers_;
-
- // The size of the memory taken by the ELF file when loaded.
- size_t loaded_size_;
// Used for allocation of virtual address space.
Elf_Addr virtual_address_;
+ size_t write_program_headers_;
+
DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
};