Move .oat files to ELF format

Generates .oat in ELF file format using MCLinker
- Uses MCLinker IRBuilder to create a synthetic .o from OatWriter output.
- Uses new ElfFile for prelinking to support art image optimizations.

Adapted OatFile to load using dlopen, ElfFile, or memory, removing raw MemMap mechanism.

Changed image code to not assume oat data will be immediately after
image to allow space for ELF headers.

Passes test-art and works with installd.

Change-Id: Idc026eddb5de93f4b97490c405f3ed7b39589749
diff --git a/src/elf_file.h b/src/elf_file.h
new file mode 100644
index 0000000..2c49f32
--- /dev/null
+++ b/src/elf_file.h
@@ -0,0 +1,133 @@
+/*
+ * 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_SRC_ELF_FILE_H_
+#define ART_SRC_ELF_FILE_H_
+
+#include <vector>
+
+#include <llvm/Support/ELF.h>
+
+#include "base/unix_file/fd_file.h"
+#include "globals.h"
+#include "mem_map.h"
+#include "os.h"
+#include "UniquePtr.h"
+
+namespace art {
+
+// Used for compile time and runtime for ElfFile access. Because of
+// the need for use at runtime, cannot directly use LLVM classes such as
+// ELFObjectFile.
+class ElfFile {
+ public:
+  static ElfFile* Open(File* file, bool writable, bool program_header_only);
+  ~ElfFile();
+
+  // Load segments into memory based on PT_LOAD program headers
+
+  File& GetFile() const {
+    return *file_;
+  }
+
+  byte* Begin() {
+    return map_->Begin();
+  }
+
+  byte* End() {
+    return map_->End();
+  }
+
+  size_t Size() const {
+    return map_->Size();
+  }
+
+  llvm::ELF::Elf32_Ehdr& GetHeader();
+
+  llvm::ELF::Elf32_Word GetProgramHeaderNum();
+  llvm::ELF::Elf32_Phdr& GetProgramHeader(llvm::ELF::Elf32_Word);
+  llvm::ELF::Elf32_Phdr* FindProgamHeaderByType(llvm::ELF::Elf32_Word type);
+
+  llvm::ELF::Elf32_Word GetSectionHeaderNum();
+  llvm::ELF::Elf32_Shdr& GetSectionHeader(llvm::ELF::Elf32_Word);
+  llvm::ELF::Elf32_Shdr* FindSectionByType(llvm::ELF::Elf32_Word type);
+
+  byte* FindDynamicSymbolAddress(const std::string& symbol_name);
+
+  static bool IsSymbolSectionType(llvm::ELF::Elf32_Word section_type);
+  llvm::ELF::Elf32_Word GetSymbolNum(llvm::ELF::Elf32_Shdr&);
+  llvm::ELF::Elf32_Sym& GetSymbol(llvm::ELF::Elf32_Word section_type, llvm::ELF::Elf32_Word i);
+  llvm::ELF::Elf32_Sym* FindSymbolByName(llvm::ELF::Elf32_Word section_type,
+                                         const std::string& symbol_name);
+  llvm::ELF::Elf32_Addr FindSymbolAddress(llvm::ELF::Elf32_Word section_type,
+                                          const std::string& symbol_name);
+
+  char* GetString(llvm::ELF::Elf32_Shdr&, llvm::ELF::Elf32_Word);
+
+  llvm::ELF::Elf32_Word GetDynamicNum();
+  llvm::ELF::Elf32_Dyn& GetDynamic(llvm::ELF::Elf32_Word);
+
+  // Returns the expected size when the file is loaded at runtime
+  size_t GetLoadedSize();
+
+  // Load segments into memory based on PT_LOAD program headers
+  bool Load();
+
+ private:
+  ElfFile();
+
+  bool Setup(File* file, bool writable, bool program_header_only);
+
+  bool SetMap(MemMap* map);
+
+  byte* GetProgramHeadersStart();
+  byte* GetSectionHeadersStart();
+  llvm::ELF::Elf32_Phdr& GetDynamicProgramHeader();
+  llvm::ELF::Elf32_Dyn* GetDynamicSectionStart();
+  llvm::ELF::Elf32_Sym* GetSymbolSectionStart(llvm::ELF::Elf32_Word section_type);
+  char* GetSymbolStringSectionStart(llvm::ELF::Elf32_Word section_type);
+  llvm::ELF::Elf32_Word* GetHashSectionStart();
+  llvm::ELF::Elf32_Word GetHashBucketNum();
+  llvm::ELF::Elf32_Word GetHashChainNum();
+  llvm::ELF::Elf32_Word GetHashBucket(size_t i);
+  llvm::ELF::Elf32_Word GetHashChain(size_t i);
+
+  File* file_;
+  bool writable_;
+  bool program_header_only_;
+  UniquePtr<MemMap> map_;
+  llvm::ELF::Elf32_Ehdr* header_;
+  std::vector<MemMap*> segments_;
+  byte* base_address_;
+
+  // The program header should always available but use GetProgramHeadersStart() to be sure.
+  byte* program_headers_start_;
+
+  // Conditionally available values. Use accessors to ensure they exist if they are required.
+  byte* section_headers_start_;
+  llvm::ELF::Elf32_Phdr* dynamic_program_header_;
+  llvm::ELF::Elf32_Dyn* dynamic_section_start_;
+  llvm::ELF::Elf32_Sym* symtab_section_start_;
+  llvm::ELF::Elf32_Sym* dynsym_section_start_;
+  char* strtab_section_start_;
+  char* dynstr_section_start_;
+  llvm::ELF::Elf32_Word* hash_section_start_;
+
+};
+
+}  // namespace art
+
+#endif  // ART_SRC_ELF_FILE_H_