Add patchoat tool to Art.
Add a new executable called patchoat to art. This tool takes already
compiled images and oat files and changes their base address, acting as
a cheap form of relocation.
Add a --include-patch-information flag to dex2oat and code to add
required patch information to oat files created with the quick compiler.
Bug: 15358152
Change-Id: Ie0c580db45bb14ec180deb84930def6c3628d97d
diff --git a/runtime/elf_utils.h b/runtime/elf_utils.h
index 2c50047..5966d05 100644
--- a/runtime/elf_utils.h
+++ b/runtime/elf_utils.h
@@ -22,6 +22,8 @@
// Explicitly include our own elf.h to avoid Linux and other dependencies.
#include "./elf.h"
+#include "base/logging.h"
+
// Architecture dependent flags for the ELF header.
#define EF_ARM_EABI_VER5 0x05000000
#define EF_MIPS_ABI_O32 0x00001000
@@ -62,8 +64,103 @@
#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */
#define DT_MIPS_RLD_MAP 0x70000016 /* Address of debug map pointer */
+// Patching section type
+#define SHT_OAT_PATCH SHT_LOUSER
+
inline void SetBindingAndType(Elf32_Sym* sym, unsigned char b, unsigned char t) {
sym->st_info = (b << 4) + (t & 0x0f);
}
+inline bool IsDynamicSectionPointer(Elf32_Word d_tag, Elf32_Word e_machine) {
+ switch (d_tag) {
+ // case 1: well known d_tag values that imply Elf32_Dyn.d_un contains an address in d_ptr
+ case DT_PLTGOT:
+ case DT_HASH:
+ case DT_STRTAB:
+ case DT_SYMTAB:
+ case DT_RELA:
+ case DT_INIT:
+ case DT_FINI:
+ case DT_REL:
+ case DT_DEBUG:
+ case DT_JMPREL: {
+ return true;
+ }
+ // d_val or ignored values
+ case DT_NULL:
+ case DT_NEEDED:
+ case DT_PLTRELSZ:
+ case DT_RELASZ:
+ case DT_RELAENT:
+ case DT_STRSZ:
+ case DT_SYMENT:
+ case DT_SONAME:
+ case DT_RPATH:
+ case DT_SYMBOLIC:
+ case DT_RELSZ:
+ case DT_RELENT:
+ case DT_PLTREL:
+ case DT_TEXTREL:
+ case DT_BIND_NOW:
+ case DT_INIT_ARRAYSZ:
+ case DT_FINI_ARRAYSZ:
+ case DT_RUNPATH:
+ case DT_FLAGS: {
+ return false;
+ }
+ // boundary values that should not be used
+ case DT_ENCODING:
+ case DT_LOOS:
+ case DT_HIOS:
+ case DT_LOPROC:
+ case DT_HIPROC: {
+ LOG(FATAL) << "Illegal d_tag value 0x" << std::hex << d_tag;
+ return false;
+ }
+ default: {
+ // case 2: "regular" DT_* ranges where even d_tag values imply an address in d_ptr
+ if ((DT_ENCODING < d_tag && d_tag < DT_LOOS)
+ || (DT_LOOS < d_tag && d_tag < DT_HIOS)
+ || (DT_LOPROC < d_tag && d_tag < DT_HIPROC)) {
+ // Special case for MIPS which breaks the regular rules between DT_LOPROC and DT_HIPROC
+ if (e_machine == EM_MIPS) {
+ switch (d_tag) {
+ case DT_MIPS_RLD_VERSION:
+ case DT_MIPS_TIME_STAMP:
+ case DT_MIPS_ICHECKSUM:
+ case DT_MIPS_IVERSION:
+ case DT_MIPS_FLAGS:
+ case DT_MIPS_LOCAL_GOTNO:
+ case DT_MIPS_CONFLICTNO:
+ case DT_MIPS_LIBLISTNO:
+ case DT_MIPS_SYMTABNO:
+ case DT_MIPS_UNREFEXTNO:
+ case DT_MIPS_GOTSYM:
+ case DT_MIPS_HIPAGENO: {
+ return false;
+ }
+ case DT_MIPS_BASE_ADDRESS:
+ case DT_MIPS_CONFLICT:
+ case DT_MIPS_LIBLIST:
+ case DT_MIPS_RLD_MAP: {
+ return true;
+ }
+ default: {
+ LOG(FATAL) << "Unknown MIPS d_tag value 0x" << std::hex << d_tag;
+ return false;
+ }
+ }
+ } else if ((d_tag % 2) == 0) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ LOG(FATAL) << "Unknown d_tag value 0x" << std::hex << d_tag;
+ return false;
+ }
+ }
+ }
+}
+
#endif // ART_RUNTIME_ELF_UTILS_H_