Merge "Move frameworks/compile/linkloader into frameworks/rs." into jb-mr2-dev
diff --git a/Android.mk b/Android.mk
index 5d5dccb..1c71962 100644
--- a/Android.mk
+++ b/Android.mk
@@ -245,5 +245,207 @@
 
 include $(BUILD_HOST_STATIC_LIBRARY)
 
+
+LLVM_ROOT_PATH := external/llvm
+
+#=============================================================================
+# android librsloader for libbcc (Device)
+#-----------------------------------------------------------------------------
+
+rsloader_SRC_FILES := \
+  driver/linkloader/android/librsloader.cpp \
+  driver/linkloader/lib/ELFHeader.cpp \
+  driver/linkloader/lib/ELFSymbol.cpp \
+  driver/linkloader/lib/ELFSectionHeader.cpp \
+  driver/linkloader/lib/ELFTypes.cpp \
+  driver/linkloader/lib/GOT.cpp \
+  driver/linkloader/lib/MemChunk.cpp \
+  driver/linkloader/lib/StubLayout.cpp \
+  driver/linkloader/utils/helper.cpp \
+  driver/linkloader/utils/raw_ostream.cpp \
+  driver/linkloader/utils/rsl_assert.cpp
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := librsloader
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(rsloader_SRC_FILES)
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_CFLAGS += $(rs_base_CFLAGS)
+
+LOCAL_C_INCLUDES := \
+  $(LOCAL_PATH)/driver/linkloader \
+  $(LOCAL_PATH)/driver/linkloader/include \
+  $(LOCAL_C_INCLUDES)
+
+include $(LLVM_ROOT_PATH)/llvm-device-build.mk
+include $(BUILD_STATIC_LIBRARY)
+
+
+#=============================================================================
+# android librsloader for libbcc (Host)
+#-----------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := librsloader
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(rsloader_SRC_FILES)
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_CFLAGS += $(rs_base_CFLAGS)
+LOCAL_CFLAGS += -D__HOST__
+
+LOCAL_C_INCLUDES := \
+  $(LOCAL_PATH)/driver/linkloader \
+  $(LOCAL_PATH)/driver/linkloader/include \
+  $(LOCAL_C_INCLUDES)
+
+include $(LLVM_ROOT_PATH)/llvm-host-build.mk
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+
+#=============================================================================
+# librsloader-test (Device)
+#-----------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := test-librsloader
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SHARED_LIBRARIES := \
+  libstlport
+
+LOCAL_STATIC_LIBRARIES := \
+  librsloader \
+  libcutils \
+  libLLVMSupport
+
+LOCAL_SRC_FILES := \
+  driver/linkloader/android/test-librsloader.c
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_CFLAGS += $(rs_base_CFLAGS)
+
+LOCAL_C_INCLUDES := \
+  $(LOCAL_PATH)/driver/linkloader \
+  $(LOCAL_PATH)/driver/linkloader/include
+
+include $(LLVM_ROOT_PATH)/llvm-device-build.mk
+include $(BUILD_EXECUTABLE)
+
+
+#=============================================================================
+# librsloader-test (Host)
+#-----------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := test-librsloader
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_LDLIBS := \
+  -lpthread \
+  -ldl
+
+LOCAL_STATIC_LIBRARIES := \
+  librsloader \
+  libcutils \
+  libLLVMSupport
+
+LOCAL_SRC_FILES := \
+  driver/linkloader/android/test-librsloader.c
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_CFLAGS += $(rs_base_CFLAGS)
+
+LOCAL_C_INCLUDES := \
+  $(LOCAL_PATH)/driver/linkloader \
+  $(LOCAL_PATH)/driver/linkloader/include
+
+include $(LLVM_ROOT_PATH)/llvm-host-build.mk
+include $(BUILD_HOST_EXECUTABLE)
+
+
+#=============================================================================
+# rsloader
+#-----------------------------------------------------------------------------
+
+ifdef BUILD_RSLOADER_TOOL
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := rsloader
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SHARED_LIBRARIES := \
+  libstlport
+
+LOCAL_STATIC_LIBRARIES := \
+  libLLVMSupport
+
+LOCAL_SRC_FILES := \
+  driver/linkloader/lib/ELFHeader.cpp \
+  driver/linkloader/lib/ELFSymbol.cpp \
+  driver/linkloader/lib/ELFSectionHeader.cpp \
+  driver/linkloader/lib/ELFTypes.cpp \
+  driver/linkloader/lib/StubLayout.cpp \
+  driver/linkloader/utils/raw_ostream.cpp \
+  driver/linkloader/utils/rsl_assert.cpp \
+  driver/linkloader/utils/helper.cpp \
+  driver/linkloader/main.cpp
+
+LOCAL_C_INCLUDES := \
+  $(LOCAL_PATH)/driver/linkloader \
+  $(LOCAL_PATH)/driver/linkloader/include \
+  $(LOCAL_C_INCLUDES)
+
+include $(LLVM_ROOT_PATH)/llvm-device-build.mk
+include $(BUILD_EXECUTABLE)
+endif
+
+
+#=============================================================================
+# stub-layout-unit-test
+#-----------------------------------------------------------------------------
+
+ifdef BUILD_STUB_LAYOUT_TEST
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := stub-layout-unit-test
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SHARED_LIBRARIES := \
+  libstlport
+
+LOCAL_SRC_FILES := \
+  driver/linkloader/lib/StubLayout.cpp \
+  driver/linkloader/utils/raw_ostream.cpp \
+  driver/linkloader/utils/helper.cpp \
+  driver/linkloader/tests/stub-test.cpp
+
+LOCAL_C_INCLUDES := \
+  $(LOCAL_PATH)/driver/linkloader \
+  $(LOCAL_PATH)/driver/linkloader/include \
+  $(LOCAL_C_INCLUDES)
+
+include $(LLVM_ROOT_PATH)/llvm-device-build.mk
+include $(BUILD_EXECUTABLE)
+endif
+
+
 include $(call all-makefiles-under,$(LOCAL_PATH))
 
diff --git a/driver/linkloader/android/librsloader.cpp b/driver/linkloader/android/librsloader.cpp
new file mode 100644
index 0000000..200006f
--- /dev/null
+++ b/driver/linkloader/android/librsloader.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2011-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 "librsloader.h"
+
+#include "ELFObject.h"
+#include "ELFSectionSymTab.h"
+#include "ELFSymbol.h"
+
+#include "utils/serialize.h"
+
+#define LOG_TAG "bcc"
+#include "cutils/log.h"
+
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/Support/ELF.h>
+
+static inline RSExecRef wrap(ELFObject<32> *object) {
+  return reinterpret_cast<RSExecRef>(object);
+}
+
+static inline ELFObject<32> *unwrap(RSExecRef object) {
+  return reinterpret_cast<ELFObject<32> *>(object);
+}
+
+extern "C" RSExecRef rsloaderCreateExec(unsigned char const *buf,
+                                        size_t buf_size,
+                                        RSFindSymbolFn find_symbol,
+                                        void *find_symbol_context) {
+  RSExecRef object = rsloaderLoadExecutable(buf, buf_size);
+  if (!object) {
+    return NULL;
+  }
+
+  if (!rsloaderRelocateExecutable(object, find_symbol, find_symbol_context)) {
+    rsloaderDisposeExec(object);
+    return NULL;
+  }
+
+  return object;
+}
+
+extern "C" RSExecRef rsloaderLoadExecutable(unsigned char const *buf,
+                                            size_t buf_size) {
+  ArchiveReaderLE AR(buf, buf_size);
+
+  llvm::OwningPtr<ELFObject<32> > object(ELFObject<32>::read(AR));
+  if (!object) {
+    ALOGE("Unable to load the ELF object.");
+    return NULL;
+  }
+
+  return wrap(object.take());
+}
+
+extern "C" int rsloaderRelocateExecutable(RSExecRef object_,
+                                          RSFindSymbolFn find_symbol,
+                                          void *find_symbol_context) {
+  ELFObject<32>* object = unwrap(object_);
+
+  object->relocate(find_symbol, find_symbol_context);
+  return (object->getMissingSymbols() == 0);
+}
+
+extern "C" void rsloaderUpdateSectionHeaders(RSExecRef object_,
+                                             unsigned char *buf) {
+  ELFObject<32> *object = unwrap(object_);
+
+  // Remap the section header addresses to match the loaded code
+  llvm::ELF::Elf32_Ehdr* header = reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(buf);
+
+  llvm::ELF::Elf32_Shdr* shtab =
+      reinterpret_cast<llvm::ELF::Elf32_Shdr*>(buf + header->e_shoff);
+
+  for (int i = 0; i < header->e_shnum; i++) {
+    if (shtab[i].sh_flags & SHF_ALLOC) {
+      ELFSectionBits<32>* bits =
+          static_cast<ELFSectionBits<32>*>(object->getSectionByIndex(i));
+      if (bits) {
+        const unsigned char* addr = bits->getBuffer();
+        shtab[i].sh_addr = reinterpret_cast<llvm::ELF::Elf32_Addr>(addr);
+      }
+    }
+  }
+}
+
+extern "C" void rsloaderDisposeExec(RSExecRef object) {
+  delete unwrap(object);
+}
+
+extern "C" void *rsloaderGetSymbolAddress(RSExecRef object_,
+                                          char const *name) {
+  ELFObject<32> *object = unwrap(object_);
+
+  ELFSectionSymTab<32> *symtab =
+    static_cast<ELFSectionSymTab<32> *>(object->getSectionByName(".symtab"));
+
+  if (!symtab) {
+    return NULL;
+  }
+
+  ELFSymbol<32> *symbol = symtab->getByName(name);
+
+  if (!symbol) {
+    ALOGV("Symbol not found: %s\n", name);
+    return NULL;
+  }
+
+  int machine = object->getHeader()->getMachine();
+
+  return symbol->getAddress(machine, false);
+}
+
+extern "C" size_t rsloaderGetSymbolSize(RSExecRef object_, char const *name) {
+  ELFObject<32> *object = unwrap(object_);
+
+  ELFSectionSymTab<32> *symtab =
+    static_cast<ELFSectionSymTab<32> *>(object->getSectionByName(".symtab"));
+
+  if (!symtab) {
+    return 0;
+  }
+
+  ELFSymbol<32> *symbol = symtab->getByName(name);
+
+  if (!symbol) {
+    ALOGV("Symbol not found: %s\n", name);
+    return 0;
+  }
+
+  return (size_t)symbol->getSize();
+}
+
+extern "C" size_t rsloaderGetFuncCount(RSExecRef object) {
+  ELFSectionSymTab<32> *symtab = static_cast<ELFSectionSymTab<32> *>(
+    unwrap(object)->getSectionByName(".symtab"));
+
+  if (!symtab) {
+    return 0;
+  }
+
+  return symtab->getFuncCount();
+}
+
+extern "C" void rsloaderGetFuncNameList(RSExecRef object,
+                                        size_t size,
+                                        char const **list) {
+  ELFSectionSymTab<32> *symtab = static_cast<ELFSectionSymTab<32> *>(
+    unwrap(object)->getSectionByName(".symtab"));
+
+  if (symtab) {
+    symtab->getFuncNameList(size, list);
+  }
+}
diff --git a/driver/linkloader/android/librsloader.h b/driver/linkloader/android/librsloader.h
new file mode 100644
index 0000000..ab8361a
--- /dev/null
+++ b/driver/linkloader/android/librsloader.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2011-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 LIBRSLOADER_H
+#define LIBRSLOADER_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct RSExecOpaque;
+typedef struct RSExecOpaque *RSExecRef;
+typedef void *(*RSFindSymbolFn)(void *, char const *);
+
+RSExecRef rsloaderCreateExec(unsigned char const *buf,
+                             size_t buf_size,
+                             RSFindSymbolFn find_symbol,
+                             void *find_symbol_context);
+
+RSExecRef rsloaderLoadExecutable(unsigned char const *buf,
+                                 size_t buf_size);
+
+int rsloaderRelocateExecutable(RSExecRef object,
+                               RSFindSymbolFn find_symbol,
+                               void *find_symbol_context);
+
+void rsloaderUpdateSectionHeaders(RSExecRef object, unsigned char *buf);
+
+void rsloaderDisposeExec(RSExecRef object);
+
+void *rsloaderGetSymbolAddress(RSExecRef object, char const *name);
+
+size_t rsloaderGetSymbolSize(RSExecRef object, char const *name);
+
+size_t rsloaderGetFuncCount(RSExecRef object);
+
+void rsloaderGetFuncNameList(RSExecRef object, size_t size, char const **list);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LIBRSLOADER_H */
diff --git a/driver/linkloader/android/test-librsloader.c b/driver/linkloader/android/test-librsloader.c
new file mode 100644
index 0000000..3c9ac2d
--- /dev/null
+++ b/driver/linkloader/android/test-librsloader.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2011, 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 "librsloader.h"
+#include "utils/rsl_assert.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+struct func_entry_t {
+  char const *name;
+  size_t name_len;
+  void *addr;
+};
+
+void *find_sym(void *context, char const *name) {
+  static struct func_entry_t const tab[] = {
+#define DEF(NAME, ADDR) \
+    { NAME, sizeof(NAME) - 1, (void *)(&(ADDR)) },
+
+    DEF("printf", printf)
+    DEF("scanf", scanf)
+    DEF("__isoc99_scanf", scanf)
+    DEF("rand", rand)
+    DEF("time", time)
+    DEF("srand", srand)
+#undef DEF
+  };
+
+  static size_t const tab_size = sizeof(tab) / sizeof(struct func_entry_t);
+
+  // Note: Since our table is small, we are using trivial O(n) searching
+  // function.  For bigger table, it will be better to use binary
+  // search or hash function.
+  size_t i;
+  size_t name_len = strlen(name);
+  for (i = 0; i < tab_size; ++i) {
+    if (name_len == tab[i].name_len && strcmp(name, tab[i].name) == 0) {
+      return tab[i].addr;
+    }
+  }
+
+  rsl_assert(0 && "Can't find symbol.");
+  return 0;
+}
+
+int main(int argc, char **argv) {
+  if (argc < 2) {
+    fprintf(stderr, "USAGE: %s [ELF] [ARGS]\n", argv[0]);
+    exit(EXIT_FAILURE);
+  }
+
+  int fd = open(argv[1], O_RDONLY);
+  if (fd < 0) {
+    fprintf(stderr, "ERROR: Unable to open the file: %s\n", argv[1]);
+    exit(EXIT_FAILURE);
+  }
+
+  struct stat sb;
+  if (fstat(fd, &sb) != 0) {
+    fprintf(stderr, "ERROR: Unable to stat the file: %s\n", argv[1]);
+    close(fd);
+    exit(EXIT_FAILURE);
+  }
+
+  unsigned char const *image = (unsigned char const *)
+    mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+
+  if (image == MAP_FAILED) {
+    fprintf(stderr, "ERROR: Unable to mmap the file: %s\n", argv[1]);
+    close(fd);
+    exit(EXIT_FAILURE);
+  }
+
+  RSExecRef object = rsloaderCreateExec(image, sb.st_size, find_sym, 0);
+  if (!object) {
+    fprintf(stderr, "ERROR: Unable to load elf object.\n");
+    close(fd);
+    exit(EXIT_FAILURE);
+  }
+
+  int (*main_stub)(int, char **) =
+    (int (*)(int, char **))rsloaderGetSymbolAddress(object, "main");
+
+  int ret = main_stub(argc - 1, argv + 1);
+  printf("============================================================\n");
+  printf("ELF object finished with code: %d\n", ret);
+  fflush(stdout);
+
+  rsloaderDisposeExec(object);
+
+  close(fd);
+
+  return EXIT_SUCCESS;
+}
diff --git a/driver/linkloader/include/ELF.h b/driver/linkloader/include/ELF.h
new file mode 100644
index 0000000..6205b98
--- /dev/null
+++ b/driver/linkloader/include/ELF.h
@@ -0,0 +1,19 @@
+#ifndef ELF_H
+#define ELF_H
+
+#include <llvm/Support/ELF.h>
+// FIXME: Can't using namespace in header file!
+using namespace llvm::ELF;
+
+// These definitions are not defined in include/llvm/Support/ELF.h.
+// So we define them here.
+
+#ifndef ET_LOOS
+#define ET_LOOS 0xfe00
+#endif
+
+#ifndef ET_HIOS
+#define ET_HIOS 0xfeff
+#endif
+
+#endif // ELF_H
diff --git a/driver/linkloader/include/ELFHeader.h b/driver/linkloader/include/ELFHeader.h
new file mode 100644
index 0000000..98fa920
--- /dev/null
+++ b/driver/linkloader/include/ELFHeader.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2011, 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 ELF_HEADER_H
+#define ELF_HEADER_H
+
+#include "ELFTypes.h"
+#include "ELF.h"
+
+#include <llvm/ADT/OwningPtr.h>
+
+#include <string.h>
+
+class ELFHeaderHelperMixin {
+protected:
+  static char const *getClassStr(int clazz);
+  static char const *getEndiannessStr(int endianness);
+  static char const *getOSABIStr(int abi);
+  static char const *getObjectTypeStr(uint16_t type);
+  static char const *getMachineStr(uint16_t machine);
+  static char const *getVersionStr(uint32_t version);
+};
+
+template <unsigned Bitwidth>
+class ELFHeader : private ELFHeaderHelperMixin {
+public:
+  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
+
+protected:
+  byte_t   e_ident[EI_NIDENT];
+  half_t   e_type;
+  half_t   e_machine;
+  word_t   e_version;
+  addr_t   e_entry;
+  offset_t e_phoff;
+  offset_t e_shoff;
+  word_t   e_flags;
+  half_t   e_ehsize;
+  half_t   e_phentsize;
+  half_t   e_phnum;
+  half_t   e_shentsize;
+  half_t   e_shnum;
+  half_t   e_shstrndx;
+
+protected:
+  ELFHeader() { }
+
+public:
+  byte_t getClass() const {
+    return e_ident[EI_CLASS];
+  }
+
+  byte_t getEndianness() const {
+    return e_ident[EI_DATA];
+  }
+
+  byte_t getVersionFromIdent() const {
+    return e_ident[EI_VERSION];
+  }
+
+  byte_t getOSABI() const {
+    return e_ident[EI_OSABI];
+  }
+
+  byte_t getABIVersion() const {
+    return e_ident[EI_ABIVERSION];
+  }
+
+  bool is32bit() const {
+    return e_ident[EI_CLASS] == ELFCLASS32;
+  }
+
+  bool is64bit() const {
+    return e_ident[EI_CLASS] == ELFCLASS64;
+  }
+
+  bool isBigEndian() const {
+    return e_ident[EI_DATA] == ELFDATA2MSB;
+  }
+
+  bool isLittleEndian() const {
+    return e_ident[EI_DATA] == ELFDATA2LSB;
+  }
+
+  half_t getObjectType() const {
+    return e_type;
+  }
+
+  half_t getMachine() const {
+    return e_machine;
+  }
+
+  word_t getVersion() const {
+    return e_version;
+  }
+
+  addr_t getEntryAddress() const {
+    return e_entry;
+  }
+
+  offset_t getProgramHeaderTableOffset() const {
+    return e_phoff;
+  }
+
+  offset_t getSectionHeaderTableOffset() const {
+    return e_shoff;
+  }
+
+  word_t getFlags() const {
+    return e_flags;
+  }
+
+  half_t getELFHeaderSize() const {
+    return e_ehsize;
+  }
+
+  half_t getProgramHeaderEntrySize() const {
+    return e_phentsize;
+  }
+
+  half_t getProgramHeaderNum() const {
+    return e_phnum;
+  }
+
+  half_t getSectionHeaderEntrySize() const {
+    return e_shentsize;
+  }
+
+  half_t getSectionHeaderNum() const {
+    return e_shnum;
+  }
+
+  half_t getStringSectionIndex() const {
+    return e_shstrndx;
+  }
+
+  template <typename Archiver>
+  static ELFHeader *read(Archiver &AR) {
+    if (!AR) {
+      // Archiver is in bad state before calling read function.
+      // Return NULL and do nothing.
+      return 0;
+    }
+
+    llvm::OwningPtr<ELFHeader> header(new ELFHeader());
+    if (!header->serialize(AR)) {
+      // Unable to read the structure.  Return NULL.
+      return 0;
+    }
+
+    if (!header->isValid()) {
+      // Header read from archiver is not valid.  Return NULL.
+      return 0;
+    }
+
+    return header.take();
+  }
+
+  void print();
+
+  bool isValid() const {
+    return (isValidELFIdent() && isCompatibleHeaderSize());
+  }
+
+private:
+  template <typename Archiver>
+  bool serialize(Archiver &AR) {
+    AR.prologue(TypeTraits<ELFHeaderTy>::size);
+
+    AR & e_ident;
+    AR & e_type;
+    AR & e_machine;
+    AR & e_version;
+    AR & e_entry;
+    AR & e_phoff;
+    AR & e_shoff;
+    AR & e_flags;
+    AR & e_ehsize;
+    AR & e_phentsize;
+    AR & e_phnum;
+    AR & e_shentsize;
+    AR & e_shnum;
+    AR & e_shstrndx;
+
+    AR.epilogue(TypeTraits<ELFHeaderTy>::size);
+    return AR;
+  }
+
+  bool isValidMagicWord() const {
+    return (memcmp(e_ident, "\x7f" "ELF", 4) == 0);
+  }
+
+  bool isValidClass() const {
+    return ((Bitwidth == 32 && is32bit()) ||
+            (Bitwidth == 64 && is64bit()));
+  }
+
+  bool isValidEndianness() const {
+    return (isBigEndian() || isLittleEndian());
+  }
+
+  bool isValidHeaderVersion() const {
+    return (getVersion() == EV_CURRENT);
+  }
+
+  bool isUnusedZeroedPadding() const {
+    for (size_t i = EI_PAD; i < EI_NIDENT; ++i) {
+      if (e_ident[i] != 0) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  bool isValidELFIdent() const {
+    return (isValidMagicWord() &&
+            isValidClass() &&
+            isValidEndianness() &&
+            isValidHeaderVersion() &&
+            isUnusedZeroedPadding());
+  }
+
+  bool isCompatibleHeaderSize() const {
+    return (
+      (e_ehsize == TypeTraits<ELFHeaderTy>::size) &&
+      (e_phnum == 0 || e_phentsize == TypeTraits<ELFProgramHeaderTy>::size) &&
+      (e_shnum == 0 || e_shentsize == TypeTraits<ELFSectionHeaderTy>::size));
+  }
+};
+
+#include "impl/ELFHeader.hxx"
+
+#endif // ELF_HEADER_H
diff --git a/driver/linkloader/include/ELFObject.h b/driver/linkloader/include/ELFObject.h
new file mode 100644
index 0000000..d715d51
--- /dev/null
+++ b/driver/linkloader/include/ELFObject.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2011, 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 ELF_OBJECT_H
+#define ELF_OBJECT_H
+
+#include "ELFTypes.h"
+#include "MemChunk.h"
+
+#include "utils/rsl_assert.h"
+
+#include <llvm/ADT/OwningPtr.h>
+
+#include <string>
+#include <vector>
+
+template <unsigned Bitwidth>
+class ELFObject {
+public:
+  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
+
+private:
+  llvm::OwningPtr<ELFHeaderTy> header;
+  llvm::OwningPtr<ELFSectionHeaderTableTy> shtab;
+  std::vector<ELFSectionTy *> stab;
+
+  MemChunk SHNCommonData;
+  unsigned char *SHNCommonDataPtr;
+  size_t SHNCommonDataFreeSize;
+
+  bool missingSymbols;
+
+  // TODO: Need refactor!
+  bool initSHNCommonDataSize(size_t SHNCommonDataSize) {
+    rsl_assert(!SHNCommonDataPtr && "Can't init twice.");
+    if (!SHNCommonData.allocate(SHNCommonDataSize)) {
+      return false;
+    }
+
+    SHNCommonDataPtr = SHNCommonData.getBuffer();
+    SHNCommonDataFreeSize = SHNCommonDataSize;
+    return true;
+  }
+
+private:
+  ELFObject() : SHNCommonDataPtr(NULL), missingSymbols(false) { }
+
+public:
+  template <typename Archiver>
+  static ELFObject *read(Archiver &AR);
+
+  ELFHeaderTy const *getHeader() const {
+    return header.get();
+  }
+
+  ELFSectionHeaderTableTy const *getSectionHeaderTable() const {
+    return shtab.get();
+  }
+
+  char const *getSectionName(size_t i) const;
+  ELFSectionTy const *getSectionByIndex(size_t i) const;
+  ELFSectionTy *getSectionByIndex(size_t i);
+  ELFSectionTy const *getSectionByName(std::string const &str) const;
+  ELFSectionTy *getSectionByName(std::string const &str);
+
+  inline bool getMissingSymbols() const {
+    return missingSymbols;
+  }
+
+  void *allocateSHNCommonData(size_t size, size_t align = 1) {
+    rsl_assert(size > 0 && align != 0);
+
+    rsl_assert(SHNCommonDataPtr && "Must init common data size before use!");
+
+    // Ensure alignment
+    size_t rem = ((uintptr_t)SHNCommonDataPtr) % align;
+    if (rem != 0) {
+      SHNCommonDataPtr += align - rem;
+      SHNCommonDataFreeSize -= align - rem;
+    }
+
+    // Ensure the free size is sufficient
+    if (SHNCommonDataFreeSize < size) {
+      return NULL;
+    }
+
+    // Allcoate
+    void *result = SHNCommonDataPtr;
+    SHNCommonDataPtr += size;
+    SHNCommonDataFreeSize -= size;
+
+    return result;
+  }
+
+  void relocate(void *(*find_sym)(void *context, char const *name),
+                void *context);
+
+  void print() const;
+
+  ~ELFObject() {
+    for (size_t i = 0; i < stab.size(); ++i) {
+      // Delete will check the pointer is nullptr or not by himself.
+      delete stab[i];
+    }
+  }
+
+private:
+  void relocateARM(void *(*find_sym)(void *context, char const *name),
+                   void *context,
+                   ELFSectionRelTableTy *reltab,
+                   ELFSectionProgBitsTy *text);
+
+  void relocateX86_32(void *(*find_sym)(void *context, char const *name),
+                      void *context,
+                      ELFSectionRelTableTy *reltab,
+                      ELFSectionProgBitsTy *text);
+
+  void relocateX86_64(void *(*find_sym)(void *context, char const *name),
+                      void *context,
+                      ELFSectionRelTableTy *reltab,
+                      ELFSectionProgBitsTy *text);
+
+  void relocateMIPS(void *(*find_sym)(void *context, char const *name),
+                    void *context,
+                    ELFSectionRelTableTy *reltab,
+                    ELFSectionProgBitsTy *text);
+};
+
+#include "impl/ELFObject.hxx"
+
+#endif // ELF_OBJECT_H
diff --git a/driver/linkloader/include/ELFReloc.h b/driver/linkloader/include/ELFReloc.h
new file mode 100644
index 0000000..c6bf759
--- /dev/null
+++ b/driver/linkloader/include/ELFReloc.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2011, 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 ELF_RELOC_H
+#define ELF_RELOC_H
+
+#include "ELFTypes.h"
+#include "utils/rsl_assert.h"
+
+#include <llvm/ADT/OwningPtr.h>
+#include <string>
+#include <stdint.h>
+
+template <unsigned Bitwidth>
+class ELFReloc_CRTP {
+public:
+  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
+
+protected:
+  size_t index;
+
+  addr_t    r_offset;
+  relinfo_t r_info;
+  addend_t  r_addend;
+
+protected:
+  ELFReloc_CRTP() : index(0), r_offset(0), r_addend(0) { }
+  ~ELFReloc_CRTP() { }
+
+public:
+  size_t getIndex() const {
+    return index;
+  }
+
+  addr_t getOffset() const {
+    return r_offset;
+  }
+
+  addend_t getAddend() const {
+    return r_addend;
+  }
+
+  bool isValid() const {
+    // FIXME: Should check the correctness of the relocation entite.
+    return true;
+  }
+
+  template <typename Archiver>
+  static ELFRelocTy *readRel(Archiver &AR, size_t index);
+
+  template <typename Archiver>
+  static ELFRelocTy *readRela(Archiver &AR, size_t index);
+
+  void print(bool shouldPrintHeader = false) const;
+
+private:
+  ELFRelocTy *concrete() {
+    return static_cast<ELFRelocTy *>(this);
+  }
+
+  ELFRelocTy const *concrete() const {
+    return static_cast<ELFRelocTy const *>(this);
+  }
+
+  template <typename Archiver>
+  bool serializeRel(Archiver &AR) {
+    rsl_assert(r_addend == 0 && "r_addend should be zero before serialization.");
+
+    AR.prologue(TypeTraits<ELFRelocRelTy>::size);
+
+    AR & r_offset;
+    AR & r_info;
+
+    AR.epilogue(TypeTraits<ELFRelocRelTy>::size);
+    return AR;
+  }
+
+  template <typename Archiver>
+  bool serializeRela(Archiver &AR) {
+    AR.prologue(TypeTraits<ELFRelocRelaTy>::size);
+
+    AR & r_offset;
+    AR & r_info;
+    AR & r_addend;
+
+    AR.epilogue(TypeTraits<ELFRelocRelaTy>::size);
+    return AR;
+  }
+
+};
+
+template <>
+class ELFReloc<32> : public ELFReloc_CRTP<32> {
+  friend class ELFReloc_CRTP<32>;
+
+private:
+  ELFReloc() {
+  }
+
+public:
+  word_t getSymTabIndex() const {
+#define ELF32_R_SYM(i)  ((i)>>8)
+    return ELF32_R_SYM(this->r_info);
+#undef ELF32_R_SYM
+  }
+
+  word_t getType() const {
+#define ELF32_R_TYPE(i)   ((unsigned char)(i))
+    return ELF32_R_TYPE(this->r_info);
+#undef ELF32_R_TYPE
+  }
+
+};
+
+template <>
+class ELFReloc<64> : public ELFReloc_CRTP<64> {
+  friend class ELFReloc_CRTP<64>;
+
+private:
+  ELFReloc() {
+  }
+
+public:
+  xword_t getSymTabIndex() const {
+#define ELF64_R_SYM(i)    ((i)>>32)
+    return ELF64_R_SYM(this->r_info);
+#undef ELF64_R_SYM
+  }
+
+  xword_t getType() const {
+#define ELF64_R_TYPE(i)   ((i)&0xffffffffL)
+    return ELF64_R_TYPE(this->r_info);
+#undef ELF64_R_TYPE
+  }
+};
+
+#include "impl/ELFReloc.hxx"
+
+#endif // ELF_RELOC_H
diff --git a/driver/linkloader/include/ELFSection.h b/driver/linkloader/include/ELFSection.h
new file mode 100644
index 0000000..74c4c13
--- /dev/null
+++ b/driver/linkloader/include/ELFSection.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_H
+#define ELF_SECTION_H
+
+#include "ELFTypes.h"
+#include <llvm/ADT/OwningPtr.h>
+
+template <unsigned Bitwidth>
+class ELFSection {
+public:
+  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
+
+protected:
+  ELFSection() { }
+
+public:
+  virtual ~ELFSection() { }
+
+  virtual void print() const = 0;
+
+  template <typename Archiver>
+  static ELFSection *read(Archiver &AR, ELFObjectTy *,
+                          ELFSectionHeaderTy const *);
+};
+
+#include "impl/ELFSection.hxx"
+
+#endif // ELF_SECTION_H
diff --git a/driver/linkloader/include/ELFSectionBits.h b/driver/linkloader/include/ELFSectionBits.h
new file mode 100644
index 0000000..2d80c1a
--- /dev/null
+++ b/driver/linkloader/include/ELFSectionBits.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_BITS_H
+#define ELF_SECTION_BITS_H
+
+#include "ELFTypes.h"
+#include "ELFSection.h"
+#include "MemChunk.h"
+
+#include <llvm/ADT/OwningPtr.h>
+
+template <unsigned Bitwidth>
+class ELFSectionBits : public ELFSection<Bitwidth> {
+protected:
+  ELFSectionHeader<Bitwidth> const *sh;
+  MemChunk chunk;
+
+protected:
+  ELFSectionBits() : sh(NULL) { }
+
+public:
+  virtual void print() const;
+
+  bool protect();
+
+  unsigned char const *getBuffer() const {
+    return chunk.getBuffer();
+  }
+
+  unsigned char *getBuffer() {
+    return chunk.getBuffer();
+  }
+
+  unsigned char &operator[](size_t index) {
+    return chunk[index];
+  }
+
+  unsigned char const &operator[](size_t index) const {
+    return chunk[index];
+  }
+
+  size_t size() const {
+    return chunk.size();
+  }
+
+};
+
+#include "impl/ELFSectionBits.hxx"
+
+#endif // ELF_SECTION_BITS_H
diff --git a/driver/linkloader/include/ELFSectionHeader.h b/driver/linkloader/include/ELFSectionHeader.h
new file mode 100644
index 0000000..7871315
--- /dev/null
+++ b/driver/linkloader/include/ELFSectionHeader.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_HEADER_H
+#define ELF_SECTION_HEADER_H
+
+#include "ELFTypes.h"
+
+#include <llvm/ADT/OwningPtr.h>
+#include <stdint.h>
+
+class ELFSectionHeaderHelperMixin {
+protected:
+  static char const *getSectionTypeStr(uint32_t type);
+};
+
+template <unsigned Bitwidth>
+class ELFSectionHeader_CRTP : private ELFSectionHeaderHelperMixin {
+public:
+  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
+
+protected:
+  ELFObjectTy const *owner;
+
+  size_t index;
+
+  word_t sh_name;
+  word_t sh_type;
+  addr_t sh_addr;
+  offset_t sh_offset;
+  word_t sh_link;
+  word_t sh_info;
+
+protected:
+  ELFSectionHeader_CRTP() { }
+  ~ELFSectionHeader_CRTP() { }
+
+public:
+  size_t getIndex() const {
+    return index;
+  }
+
+  word_t getNameIndex() const {
+    return sh_name;
+  }
+
+  char const *getName() const;
+
+  word_t getType() const {
+    return sh_type;
+  }
+
+  addr_t getAddress() const {
+    return sh_addr;
+  }
+
+  offset_t getOffset() const {
+    return sh_offset;
+  }
+
+  word_t getLink() const {
+    return sh_link;
+  }
+
+  word_t getExtraInfo() const {
+    return sh_info;
+  }
+
+  bool isValid() const {
+    // FIXME: Should check the correctness of the section header.
+    return true;
+  }
+
+  template <typename Archiver>
+  static ELFSectionHeaderTy *
+  read(Archiver &AR, ELFObjectTy const *owner, size_t index = 0);
+
+  void print(bool shouldPrintHeader = false) const;
+
+private:
+  ELFSectionHeaderTy *concrete() {
+    return static_cast<ELFSectionHeaderTy *>(this);
+  }
+
+  ELFSectionHeaderTy const *concrete() const {
+    return static_cast<ELFSectionHeaderTy const *>(this);
+  }
+};
+
+
+#include "impl/ELFSectionHeader.hxx"
+
+template <>
+class ELFSectionHeader<32> : public ELFSectionHeader_CRTP<32> {
+  friend class ELFSectionHeader_CRTP<32>;
+
+private:
+  word_t sh_flags;
+  word_t sh_size;
+  word_t sh_addralign;
+  word_t sh_entsize;
+
+private:
+  ELFSectionHeader() {
+  }
+
+  template <typename Archiver>
+  bool serialize(Archiver &AR) {
+    AR.prologue(TypeTraits<ELFSectionHeader>::size);
+
+    AR & sh_name;
+    AR & sh_type;
+    AR & sh_flags;
+    AR & sh_addr;
+    AR & sh_offset;
+    AR & sh_size;
+    AR & sh_link;
+    AR & sh_info;
+    AR & sh_addralign;
+    AR & sh_entsize;
+
+    AR.epilogue(TypeTraits<ELFSectionHeader>::size);
+    return AR;
+  }
+
+public:
+  word_t getFlags() const {
+    return sh_flags;
+  }
+
+  word_t getSize() const {
+    return sh_size;
+  }
+
+  word_t getAddressAlign() const {
+    return sh_addralign;
+  }
+
+  word_t getEntrySize() const {
+    return sh_entsize;
+  }
+};
+
+template <>
+class ELFSectionHeader<64> : public ELFSectionHeader_CRTP<64> {
+  friend class ELFSectionHeader_CRTP<64>;
+
+private:
+  xword_t sh_flags;
+  xword_t sh_size;
+  xword_t sh_addralign;
+  xword_t sh_entsize;
+
+private:
+  ELFSectionHeader() {
+  }
+
+  template <typename Archiver>
+  bool serialize(Archiver &AR) {
+    AR.prologue(TypeTraits<ELFSectionHeader>::size);
+
+    AR & sh_name;
+    AR & sh_type;
+    AR & sh_flags;
+    AR & sh_addr;
+    AR & sh_offset;
+    AR & sh_size;
+    AR & sh_link;
+    AR & sh_info;
+    AR & sh_addralign;
+    AR & sh_entsize;
+
+    AR.epilogue(TypeTraits<ELFSectionHeader>::size);
+    return AR;
+  }
+
+public:
+  xword_t getFlags() const {
+    return sh_flags;
+  }
+
+  xword_t getSize() const {
+    return sh_size;
+  }
+
+  xword_t getAddressAlign() const {
+    return sh_addralign;
+  }
+
+  xword_t getEntrySize() const {
+    return sh_entsize;
+  }
+};
+
+#endif // ELF_SECTION_HEADER_H
diff --git a/driver/linkloader/include/ELFSectionHeaderTable.h b/driver/linkloader/include/ELFSectionHeaderTable.h
new file mode 100644
index 0000000..fb7f9ed
--- /dev/null
+++ b/driver/linkloader/include/ELFSectionHeaderTable.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_HEADER_TABLE_H
+#define ELF_SECTION_HEADER_TABLE_H
+
+#include "ELFTypes.h"
+
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/ADT/StringMap.h>
+
+#include <vector>
+#include <string>
+
+template <unsigned Bitwidth>
+class ELFSectionHeaderTable {
+public:
+  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
+
+private:
+  std::vector<ELFSectionHeaderTy *> table;
+  llvm::StringMap<ELFSectionHeaderTy *> name_map;
+
+private:
+  ELFSectionHeaderTable() {
+  }
+
+public:
+  ~ELFSectionHeaderTable();
+
+  template <typename Archiver>
+  static ELFSectionHeaderTableTy *read(Archiver &AR, ELFObjectTy *owner);
+
+  ELFSectionHeaderTy const *operator[](size_t i) const {
+    return table[i];
+  }
+
+  ELFSectionHeaderTy *operator[](size_t i) {
+    return table[i];
+  }
+
+  void buildNameMap();
+
+  ELFSectionHeaderTy const *getByName(const std::string &name) const;
+  ELFSectionHeaderTy *getByName(const std::string &name);
+
+  void print() const;
+};
+
+#include "impl/ELFSectionHeaderTable.hxx"
+
+#endif // ELF_SECTION_HEADER_TABLE_H
diff --git a/driver/linkloader/include/ELFSectionNoBits.h b/driver/linkloader/include/ELFSectionNoBits.h
new file mode 100644
index 0000000..5c4b3f2
--- /dev/null
+++ b/driver/linkloader/include/ELFSectionNoBits.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_NOBITS_H
+#define ELF_SECTION_NOBITS_H
+
+#include "ELFTypes.h"
+#include "ELFSectionBits.h"
+#include "ELFSectionHeader.h"
+#include "MemChunk.h"
+
+template <unsigned Bitwidth>
+class ELFSectionNoBits : public ELFSectionBits<Bitwidth> {
+public:
+  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
+
+public:
+  template <typename Archiver>
+  static ELFSectionNoBits *read(Archiver &AR, ELFSectionHeaderTy const *sh);
+};
+
+#include "impl/ELFSectionNoBits.hxx"
+
+#endif // ELF_SECTION_NOBITS_H
diff --git a/driver/linkloader/include/ELFSectionProgBits.h b/driver/linkloader/include/ELFSectionProgBits.h
new file mode 100644
index 0000000..e0da71e
--- /dev/null
+++ b/driver/linkloader/include/ELFSectionProgBits.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_PROGBITS_H
+#define ELF_SECTION_PROGBITS_H
+
+#include "ELFTypes.h"
+#include "ELFSectionBits.h"
+#include "ELFSectionHeader.h"
+#include "MemChunk.h"
+#include "StubLayout.h"
+
+template <unsigned Bitwidth>
+class ELFSectionProgBits : public ELFSectionBits<Bitwidth> {
+public:
+  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
+
+private:
+  StubLayout *stubs;
+
+public:
+  template <typename Archiver>
+  static ELFSectionProgBits *read(Archiver &AR,
+                                  ELFObjectTy *owner,
+                                  ELFSectionHeaderTy const *sh);
+
+  StubLayout *getStubLayout() {
+    return stubs;
+  }
+
+  ELFSectionProgBits(int machine) {
+    switch(machine) {
+    case EM_ARM:
+        stubs = new StubLayoutARM();
+      break;
+
+    case EM_MIPS:
+        stubs = new StubLayoutMIPS();
+      break;
+
+    default:
+        stubs = NULL;
+    }
+  }
+
+  ~ELFSectionProgBits() {
+    if (stubs)
+      delete stubs;
+  }
+
+private:
+  template <typename Archiver>
+  bool serialize(Archiver &AR) {
+    ELFSectionHeaderTy const *sh = this->sh;
+    MemChunk &chunk = this->chunk;
+
+    AR.seek(sh->getOffset(), true);
+    AR.prologue(sh->getSize());
+    AR.readBytes(chunk.getBuffer(), sh->getSize());
+    AR.epilogue(sh->getSize());
+
+    return AR;
+  }
+};
+
+#include "impl/ELFSectionProgBits.hxx"
+
+#endif // ELF_SECTION_PROGBITS_H
diff --git a/driver/linkloader/include/ELFSectionRelTable.h b/driver/linkloader/include/ELFSectionRelTable.h
new file mode 100644
index 0000000..2799501
--- /dev/null
+++ b/driver/linkloader/include/ELFSectionRelTable.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_REL_TABLE_H
+#define ELF_SECTION_REL_TABLE_H
+
+#include "ELFTypes.h"
+#include "ELFSection.h"
+
+#include <string>
+#include <vector>
+
+template <unsigned Bitwidth>
+class ELFSectionRelTable : public ELFSection<Bitwidth> {
+public:
+  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
+
+private:
+  std::vector<ELFRelocTy *> table;
+
+private:
+  ELFSectionRelTable() { }
+
+public:
+  virtual ~ELFSectionRelTable();
+
+  virtual void print() const;
+
+  template <typename Archiver>
+  static ELFSectionRelTable *read(Archiver &AR, ELFSectionHeaderTy const *sh);
+
+  size_t size() const {
+    return table.size();
+  }
+
+  ELFRelocTy const *operator[](size_t index) const {
+    return table[index];
+  }
+
+  ELFRelocTy *operator[](size_t index) {
+    return table[index];
+  }
+
+  size_t getMaxNumStubs(ELFObjectTy const *) const;
+};
+
+#include "impl/ELFSectionRelTable.hxx"
+
+#endif // ELF_SECTION_REL_TABLE_H
diff --git a/driver/linkloader/include/ELFSectionStrTab.h b/driver/linkloader/include/ELFSectionStrTab.h
new file mode 100644
index 0000000..458dfa3
--- /dev/null
+++ b/driver/linkloader/include/ELFSectionStrTab.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_STRTAB_H
+#define ELF_SECTION_STRTAB_H
+
+#include "ELFTypes.h"
+#include "ELFSection.h"
+
+#include <vector>
+
+template <unsigned Bitwidth>
+class ELFSectionStrTab : public ELFSection<Bitwidth> {
+public:
+  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
+
+private:
+  ELFSectionHeaderTy const *section_header;
+  std::vector<char> buf;
+
+private:
+  ELFSectionStrTab() { }
+
+public:
+  template <typename Archiver>
+  static ELFSectionStrTab *read(Archiver &AR, ELFSectionHeaderTy const *sh);
+
+  virtual void print() const;
+
+  char const *operator[](size_t index) const {
+    return &*buf.begin() + index;
+  }
+};
+
+#include "impl/ELFSectionStrTab.hxx"
+
+#endif // ELF_SECTION_STRTAB_H
diff --git a/driver/linkloader/include/ELFSectionSymTab.h b/driver/linkloader/include/ELFSectionSymTab.h
new file mode 100644
index 0000000..821067f
--- /dev/null
+++ b/driver/linkloader/include/ELFSectionSymTab.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_SYMTAB_H
+#define ELF_SECTION_SYMTAB_H
+
+#include "ELFTypes.h"
+
+#include <llvm/ADT/StringMap.h>
+
+#include <vector>
+#include <string>
+
+template <unsigned Bitwidth>
+class ELFSectionSymTab : public ELFSection<Bitwidth> {
+public:
+  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
+
+private:
+  std::vector<ELFSymbolTy *> table;
+  llvm::StringMap<ELFSymbolTy *> name_map;
+
+private:
+  ELFSectionSymTab() { }
+
+public:
+  ~ELFSectionSymTab();
+
+  template <typename Archiver>
+  static ELFSectionSymTab *
+  read(Archiver &AR, ELFObjectTy *owner, ELFSectionHeaderTy const *sh);
+
+  virtual void print() const;
+
+  size_t size() const {
+    return table.size();
+  }
+
+  ELFSymbolTy const *operator[](size_t index) const {
+    return table[index];
+  }
+
+  ELFSymbolTy *operator[](size_t index) {
+    return table[index];
+  }
+
+  void buildNameMap();
+
+  ELFSymbolTy const *getByName(std::string const &name) const;
+
+  ELFSymbolTy *getByName(std::string const &name) {
+    return const_cast<ELFSymbolTy *>(
+           const_cast<ELFSectionSymTabTy const *>(this)->getByName(name));
+  }
+
+  size_t getFuncCount() const;
+
+  void getFuncNameList(size_t size, char const **list) const;
+
+  size_t getExternFuncCount() const;
+
+};
+
+#include "impl/ELFSectionSymTab.hxx"
+
+#endif // ELF_SECTION_SYMTAB_H
diff --git a/driver/linkloader/include/ELFSymbol.h b/driver/linkloader/include/ELFSymbol.h
new file mode 100644
index 0000000..d78ba5a
--- /dev/null
+++ b/driver/linkloader/include/ELFSymbol.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2011, 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 ELF_SYMBOL_H
+#define ELF_SYMBOL_H
+
+#include "ELFTypes.h"
+#include "ELF.h"
+
+#include <llvm/ADT/OwningPtr.h>
+
+#include <string>
+#include <algorithm>
+
+#include <stdint.h>
+#include <stdlib.h>
+
+class ELFSymbolHelperMixin {
+protected:
+  static char const *getTypeStr(uint8_t);
+  static char const *getBindingAttributeStr(uint8_t);
+  static char const *getVisibilityStr(uint8_t);
+};
+
+template <unsigned Bitwidth>
+class ELFSymbol_CRTP : private ELFSymbolHelperMixin {
+public:
+  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
+
+protected:
+  ELFObject<Bitwidth> const *owner;
+
+  size_t index;
+
+  word_t st_name;
+  byte_t st_info;
+  byte_t st_other;
+  half_t st_shndx;
+  addr_t st_value;
+  symsize_t st_size;
+
+  mutable void *my_addr;
+
+protected:
+  ELFSymbol_CRTP() { my_addr = 0; }
+
+  ~ELFSymbol_CRTP() {
+#if 0
+    if (my_addr != 0 &&
+        getType() == STT_OBJECT &&
+        getSectionIndex() == SHN_COMMON) {
+      std::free(my_addr);
+    }
+#endif
+  }
+
+public:
+  size_t getIndex() const {
+    return index;
+  }
+
+  word_t getNameIndex() const {
+    return st_name;
+  }
+
+  char const *getName() const;
+
+// I don't want to include elf.h in .h file, so define those macro by ourself.
+#define ELF_ST_BIND(i)   ((i)>>4)
+#define ELF_ST_TYPE(i)   ((i)&0xf)
+#define ELF_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
+  byte_t getType() const {
+    return ELF_ST_TYPE(st_info);
+  }
+
+  byte_t getBindingAttribute() const {
+    return ELF_ST_BIND(st_info);
+  }
+#undef ELF_ST_BIND
+#undef ELF_ST_TYPE
+#undef ELF_ST_INFO
+
+#define ELF_ST_VISIBILITY(o) ((o)&0x3)
+  byte_t getVisibility() const {
+    return ELF_ST_VISIBILITY(st_other);
+  }
+#undef ELF_ST_VISIBILITY
+
+  half_t getSectionIndex() const {
+    return st_shndx;
+  }
+
+  addr_t getValue() const {
+    return st_value;
+  }
+
+  symsize_t getSize() const {
+    return st_size;
+  }
+
+  void *getAddress(int machine, bool autoAlloc = true) const;
+
+  void setAddress(void *addr) {
+    my_addr = addr;
+  }
+
+  bool isValid() const {
+    // FIXME: Should check the correctness of the section header.
+    return true;
+  }
+
+  bool isConcreteFunc() const {
+    return getType() == STT_FUNC;
+  }
+
+  bool isExternFunc() const {
+    return getType() == STT_NOTYPE;
+  }
+
+  template <typename Archiver>
+  static ELFSymbolTy *
+  read(Archiver &AR, ELFObject<Bitwidth> const *owner, size_t index = 0);
+
+  void print(bool shouldPrintHeader = false) const;
+
+private:
+  ELFSymbolTy *concrete() {
+    return static_cast<ELFSymbolTy *>(this);
+  }
+
+  ELFSymbolTy const *concrete() const {
+    return static_cast<ELFSymbolTy const *>(this);
+  }
+};
+
+template <>
+class ELFSymbol<32> : public ELFSymbol_CRTP<32> {
+  friend class ELFSymbol_CRTP<32>;
+
+private:
+  ELFSymbol() {
+  }
+
+  template <typename Archiver>
+  bool serialize(Archiver &AR) {
+    AR.prologue(TypeTraits<ELFSymbol>::size);
+
+    AR & st_name;
+    AR & st_value;
+    AR & st_size;
+    AR & st_info;
+    AR & st_other;
+    AR & st_shndx;
+
+    AR.epilogue(TypeTraits<ELFSymbol>::size);
+    return AR;
+  }
+};
+
+template <>
+class ELFSymbol<64> : public ELFSymbol_CRTP<64> {
+  friend class ELFSymbol_CRTP<64>;
+
+private:
+  ELFSymbol() {
+  }
+
+  template <typename Archiver>
+  bool serialize(Archiver &AR) {
+    AR.prologue(TypeTraits<ELFSymbol>::size);
+
+    AR & st_name;
+    AR & st_info;
+    AR & st_other;
+    AR & st_shndx;
+    AR & st_value;
+    AR & st_size;
+
+    AR.epilogue(TypeTraits<ELFSymbol>::size);
+    return AR;
+  }
+};
+
+#include "impl/ELFSymbol.hxx"
+
+#endif // ELF_SYMBOL_H
diff --git a/driver/linkloader/include/ELFTypes.h b/driver/linkloader/include/ELFTypes.h
new file mode 100644
index 0000000..3e99f78
--- /dev/null
+++ b/driver/linkloader/include/ELFTypes.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2011, 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 ELF_TYPES_H
+#define ELF_TYPES_H
+
+#include "utils/traits.h"
+
+#include <stdint.h>
+#include <llvm/Support/raw_ostream.h>
+
+
+// ELF structure forward declarations
+template <unsigned Bitwidth> class ELFHeader;
+template <unsigned Bitwidth> class ELFObject;
+template <unsigned Bitwidth> class ELFProgramHeader;
+template <unsigned Bitwidth> class ELFReloc;
+template <unsigned Bitwidth> class ELFRelocRel; // For TypeTraits
+template <unsigned Bitwidth> class ELFRelocRela; // For TypeTraits
+template <unsigned Bitwidth> class ELFSection;
+template <unsigned Bitwidth> class ELFSectionBits;
+template <unsigned Bitwidth> class ELFSectionHeader;
+template <unsigned Bitwidth> class ELFSectionHeaderTable;
+template <unsigned Bitwidth> class ELFSectionNoBits;
+template <unsigned Bitwidth> class ELFSectionProgBits;
+template <unsigned Bitwidth> class ELFSectionRelTable;
+template <unsigned Bitwidth> class ELFSectionStrTab;
+template <unsigned Bitwidth> class ELFSectionSymTab;
+template <unsigned Bitwidth> class ELFSymbol;
+
+// Note: Following TypeTraits specialization MUST be compliant to the
+// System V Application Binary Interface, Chap 4, Data Representation.
+
+TYPE_TRAITS_SPECIALIZE(ELFHeader<32>        , 52, 4)
+TYPE_TRAITS_SPECIALIZE(ELFHeader<64>        , 64, 8)
+
+TYPE_TRAITS_SPECIALIZE(ELFProgramHeader<32> , 32, 4)
+TYPE_TRAITS_SPECIALIZE(ELFProgramHeader<64> , 56, 8)
+
+TYPE_TRAITS_SPECIALIZE(ELFSectionHeader<32> , 40, 4)
+TYPE_TRAITS_SPECIALIZE(ELFSectionHeader<64> , 64, 8)
+
+TYPE_TRAITS_SPECIALIZE(ELFSymbol<32>        , 16, 4)
+TYPE_TRAITS_SPECIALIZE(ELFSymbol<64>        , 24, 8)
+
+TYPE_TRAITS_SPECIALIZE(ELFRelocRel<32>      , 8, 4)
+TYPE_TRAITS_SPECIALIZE(ELFRelocRel<64>      , 16, 8)
+
+TYPE_TRAITS_SPECIALIZE(ELFRelocRela<32>     , 12, 4)
+TYPE_TRAITS_SPECIALIZE(ELFRelocRela<64>     , 24, 8)
+
+
+// ELF primitive type wrappers
+namespace detail {
+#define ELF_TYPE_WRAPPER(TYPE, IMPL)                                        \
+  struct TYPE {                                                             \
+    IMPL value;                                                             \
+                                                                            \
+    TYPE() : value(0) { }                                                   \
+    TYPE(IMPL val) : value(val) { }                                         \
+                                                                            \
+    TYPE &operator=(TYPE const &with) { value = with.value; return *this; } \
+    TYPE &operator=(IMPL val) { value = val; return *this; }                \
+                                                                            \
+    operator IMPL() const { return value; }                                 \
+  };
+
+  ELF_TYPE_WRAPPER(ELFHalf      , uint16_t)
+  ELF_TYPE_WRAPPER(ELFWord      , uint32_t)
+  ELF_TYPE_WRAPPER(ELFSword     , int32_t)
+  ELF_TYPE_WRAPPER(ELFXword     , uint64_t)
+  ELF_TYPE_WRAPPER(ELFSxword    , int64_t)
+  ELF_TYPE_WRAPPER(ELF32Address , uint32_t)
+  ELF_TYPE_WRAPPER(ELF32Offset  , uint32_t)
+  ELF_TYPE_WRAPPER(ELF64Address , uint64_t)
+  ELF_TYPE_WRAPPER(ELF64Offset  , uint64_t)
+
+#undef ELF_TYPE_WRAPPER
+
+  extern llvm::raw_ostream &operator<<(llvm::raw_ostream &,
+                                       ELF32Address const &);
+  extern llvm::raw_ostream &operator<<(llvm::raw_ostream &,
+                                       ELF32Offset const &);
+  extern llvm::raw_ostream &operator<<(llvm::raw_ostream &,
+                                       ELF64Address const &);
+  extern llvm::raw_ostream &operator<<(llvm::raw_ostream &,
+                                       ELF64Offset const &);
+}
+
+// Note: Following TypeTraits specialization MUST be compliant to the
+// System V Application Binary Interface, Chap 4, Data Representation.
+
+TYPE_TRAITS_SPECIALIZE(detail::ELFHalf      , 2, 2)
+TYPE_TRAITS_SPECIALIZE(detail::ELFWord      , 4, 4)
+TYPE_TRAITS_SPECIALIZE(detail::ELFSword     , 4, 4)
+TYPE_TRAITS_SPECIALIZE(detail::ELFXword     , 8, 8)
+TYPE_TRAITS_SPECIALIZE(detail::ELFSxword    , 8, 8)
+TYPE_TRAITS_SPECIALIZE(detail::ELF32Address , 4, 4)
+TYPE_TRAITS_SPECIALIZE(detail::ELF32Offset  , 4, 4)
+TYPE_TRAITS_SPECIALIZE(detail::ELF64Address , 8, 8)
+TYPE_TRAITS_SPECIALIZE(detail::ELF64Offset  , 8, 8)
+
+template <unsigned Bitwidth>
+struct ELFPrimitiveTypes;
+
+template <>
+struct ELFPrimitiveTypes<32> {
+  typedef detail::ELF32Address  address;
+  typedef detail::ELF32Offset   offset;
+
+  typedef unsigned char         byte;
+  typedef detail::ELFHalf       half;
+  typedef detail::ELFWord       word;
+  typedef detail::ELFSword      sword;
+
+  typedef detail::ELFWord       relinfo;
+  typedef detail::ELFSword      addend;
+  typedef detail::ELFWord       symsize;
+
+  // Note: Don't use these types.  They are not in the specification of
+  // ELF 32.  However, we need these typedefs to define the type introduce
+  // macro.
+  typedef void xword;
+  typedef void sxword;
+};
+
+template <>
+struct ELFPrimitiveTypes<64> {
+  typedef detail::ELF64Address  address;
+  typedef detail::ELF64Offset   offset;
+
+  typedef unsigned char         byte;
+  typedef detail::ELFHalf       half;
+  typedef detail::ELFWord       word;
+  typedef detail::ELFSword      sword;
+  typedef detail::ELFXword      xword;
+  typedef detail::ELFSxword     sxword;
+
+  typedef detail::ELFXword      relinfo;
+  typedef detail::ELFSxword     addend;
+  typedef detail::ELFXword      symsize;
+};
+
+
+// Macros to introduce these ELF types to a specific scope
+
+#define ELF_STRUCT_TYPE_INTRO_TO_SCOPE(BITWIDTH)                            \
+  typedef ELFHeader<BITWIDTH>             ELFHeaderTy;                      \
+  typedef ELFObject<BITWIDTH>             ELFObjectTy;                      \
+  typedef ELFProgramHeader<BITWIDTH>      ELFProgramHeaderTy;               \
+  typedef ELFReloc<BITWIDTH>              ELFRelocTy;                       \
+  typedef ELFRelocRel<BITWIDTH>           ELFRelocRelTy;                    \
+  typedef ELFRelocRela<BITWIDTH>          ELFRelocRelaTy;                   \
+  typedef ELFSection<BITWIDTH>            ELFSectionTy;                     \
+  typedef ELFSectionBits<BITWIDTH>        ELFSectionBitsTy;                 \
+  typedef ELFSectionHeader<BITWIDTH>      ELFSectionHeaderTy;               \
+  typedef ELFSectionHeaderTable<BITWIDTH> ELFSectionHeaderTableTy;          \
+  typedef ELFSectionNoBits<BITWIDTH>      ELFSectionNoBitsTy;               \
+  typedef ELFSectionProgBits<BITWIDTH>    ELFSectionProgBitsTy;             \
+  typedef ELFSectionRelTable<BITWIDTH>    ELFSectionRelTableTy;             \
+  typedef ELFSectionStrTab<BITWIDTH>      ELFSectionStrTabTy;               \
+  typedef ELFSectionSymTab<BITWIDTH>      ELFSectionSymTabTy;               \
+  typedef ELFSymbol<BITWIDTH>             ELFSymbolTy;
+
+
+#define ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(BITWIDTH)                          \
+  /* ELF structures */                                                      \
+  ELF_STRUCT_TYPE_INTRO_TO_SCOPE(BITWIDTH)                                  \
+                                                                            \
+  /* ELF primitives */                                                      \
+  typedef typename ELFPrimitiveTypes<BITWIDTH>::address addr_t;             \
+  typedef typename ELFPrimitiveTypes<BITWIDTH>::offset  offset_t;           \
+  typedef typename ELFPrimitiveTypes<BITWIDTH>::byte    byte_t;             \
+  typedef typename ELFPrimitiveTypes<BITWIDTH>::half    half_t;             \
+  typedef typename ELFPrimitiveTypes<BITWIDTH>::word    word_t;             \
+  typedef typename ELFPrimitiveTypes<BITWIDTH>::sword   sword_t;            \
+  typedef typename ELFPrimitiveTypes<BITWIDTH>::xword   xword_t;            \
+  typedef typename ELFPrimitiveTypes<BITWIDTH>::sxword  sxword_t;           \
+  typedef typename ELFPrimitiveTypes<BITWIDTH>::relinfo relinfo_t;          \
+  typedef typename ELFPrimitiveTypes<BITWIDTH>::addend  addend_t;           \
+  typedef typename ELFPrimitiveTypes<BITWIDTH>::symsize symsize_t;
+
+
+#define ELF_TYPE_INTRO_TO_SCOPE(BITWIDTH)                                   \
+  /* ELF structures */                                                      \
+  ELF_STRUCT_TYPE_INTRO_TO_SCOPE(BITWIDTH)                                  \
+                                                                            \
+  /* ELF primitives */                                                      \
+  typedef ELFPrimitiveTypes<BITWIDTH>::address  addr_t;                     \
+  typedef ELFPrimitiveTypes<BITWIDTH>::offset   offset_t;                   \
+  typedef ELFPrimitiveTypes<BITWIDTH>::byte     byte_t;                     \
+  typedef ELFPrimitiveTypes<BITWIDTH>::half     half_t;                     \
+  typedef ELFPrimitiveTypes<BITWIDTH>::word     word_t;                     \
+  typedef ELFPrimitiveTypes<BITWIDTH>::sword    sword_t;                    \
+  typedef ELFPrimitiveTypes<BITWIDTH>::xword    xword_t;                    \
+  typedef ELFPrimitiveTypes<BITWIDTH>::sxword   sxword_t;                   \
+  typedef ELFPrimitiveTypes<BITWIDTH>::relinfo  relinfo_t;                  \
+  typedef ELFPrimitiveTypes<BITWIDTH>::addend   addend_t;                   \
+  typedef ELFPrimitiveTypes<BITWIDTH>::symsize  symsize_t;
+
+
+#endif // ELF_TYPES_H
diff --git a/driver/linkloader/include/GOT.h b/driver/linkloader/include/GOT.h
new file mode 100644
index 0000000..b72bf66
--- /dev/null
+++ b/driver/linkloader/include/GOT.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011, 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 GOT_H
+#define GOT_H
+
+#include "utils/rsl_assert.h"
+#include "ELF.h"
+
+#define GP_OFFSET	((int)0x8000)
+#define GOT_SIZE	(1 << 16)	// bytes
+#define GOT_ENTRY_SIZE	4	// bytes
+#define NUM_OF_GOT_ENTRY	(GOT_SIZE/GOT_ENTRY_SIZE)
+
+void *got_address();
+int search_got(int symbol_index, void *addr, uint8_t bind_type);
+
+#endif // GOT_H
diff --git a/driver/linkloader/include/MemChunk.h b/driver/linkloader/include/MemChunk.h
new file mode 100644
index 0000000..fb853e9
--- /dev/null
+++ b/driver/linkloader/include/MemChunk.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2011, 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 MEM_CHUNK_H
+#define MEM_CHUNK_H
+
+#include <stddef.h>
+#include <stdlib.h>
+
+class MemChunk {
+private:
+  unsigned char *buf;
+  size_t buf_size;
+
+public:
+  MemChunk();
+
+  ~MemChunk();
+
+  bool allocate(size_t size);
+
+  void print() const;
+
+  bool protect(int prot);
+
+  unsigned char const *getBuffer() const {
+    return buf;
+  }
+
+  unsigned char *getBuffer() {
+    return buf;
+  }
+
+  unsigned char &operator[](size_t index) {
+    return buf[index];
+  }
+
+  unsigned char const &operator[](size_t index) const {
+    return buf[index];
+  }
+
+  size_t size() const {
+    return buf_size;
+  }
+
+};
+
+#endif // MEM_CHUNK_H
diff --git a/driver/linkloader/include/StubLayout.h b/driver/linkloader/include/StubLayout.h
new file mode 100644
index 0000000..9705743
--- /dev/null
+++ b/driver/linkloader/include/StubLayout.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2011, 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 STUB_LAYOUT_H
+#define STUB_LAYOUT_H
+
+#include <map>
+#include <stdlib.h>
+
+class StubLayout {
+private:
+  unsigned char *table;
+  size_t count;
+
+  std::map<void *, void *> stub_index;
+
+public:
+  StubLayout();
+  virtual ~StubLayout() { }
+
+  void initStubTable(unsigned char *table, size_t count);
+  void *allocateStub(void *addr = 0);
+
+  size_t calcStubTableSize(size_t count) const;
+  virtual size_t getUnitStubSize() const = 0;
+
+private:
+  virtual void setStubAddress(void *stub, void *addr) = 0;
+
+};
+
+class StubLayoutARM : public StubLayout {
+public:
+  StubLayoutARM() { }
+  size_t getUnitStubSize() const;
+
+private:
+  virtual void setStubAddress(void *stub, void *addr);
+};
+
+class StubLayoutMIPS : public StubLayout {
+public:
+  StubLayoutMIPS() { }
+  size_t getUnitStubSize() const;
+
+private:
+  virtual void setStubAddress(void *stub, void *addr);
+};
+
+
+#endif // STUB_LAYOUT_H
diff --git a/driver/linkloader/include/impl/ELFHeader.hxx b/driver/linkloader/include/impl/ELFHeader.hxx
new file mode 100644
index 0000000..993b0e2
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFHeader.hxx
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2011, 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 ELF_HEADER_HXX
+#define ELF_HEADER_HXX
+
+#include "utils/raw_ostream.h"
+
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/Format.h>
+
+template <unsigned Bitwidth>
+void ELFHeader<Bitwidth>::print() {
+  using namespace llvm;
+
+  out() << fillformat('=', 79) << '\n';
+  out().changeColor(raw_ostream::WHITE, true);
+  out() << "ELF Header\n";
+  out().resetColor();
+  out() << fillformat('-', 79) << '\n';
+
+#define PRINT_LINT(title, value) \
+  out() << format("  %-32s : ", (char const *)(title)) << (value) << '\n'
+  PRINT_LINT("Class",                 getClassStr(getClass()));
+  PRINT_LINT("Endianness",            getEndiannessStr(getEndianness()));
+  PRINT_LINT("Header Version",        (unsigned)getVersion());
+  PRINT_LINT("OS ABI",                getOSABIStr(getOSABI()));
+  PRINT_LINT("ABI Version",           (unsigned)getABIVersion());
+  PRINT_LINT("Object Type",           getObjectTypeStr(getObjectType()));
+  PRINT_LINT("Machine",               getMachineStr(getMachine()));
+  PRINT_LINT("Version",               getVersionStr(getVersion()));
+  PRINT_LINT("Entry Address",         getEntryAddress());
+  PRINT_LINT("Program Header Offset", getProgramHeaderTableOffset());
+  PRINT_LINT("Section Header Offset", getSectionHeaderTableOffset());
+  PRINT_LINT("Flags",                 getFlags());
+  PRINT_LINT("ELF Header Size",       getELFHeaderSize());
+  PRINT_LINT("Program Header Size",   getProgramHeaderEntrySize());
+  PRINT_LINT("Program Header Num",    getProgramHeaderNum());
+  PRINT_LINT("Section Header Size",   getSectionHeaderEntrySize());
+  PRINT_LINT("Section Header Num",    getSectionHeaderNum());
+  PRINT_LINT("String Section Index",  getStringSectionIndex());
+#undef PRINT_LINT
+
+  out() << fillformat('=', 79) << "\n\n";
+}
+
+#endif // ELF_HEADER_HXX
diff --git a/driver/linkloader/include/impl/ELFObject.hxx b/driver/linkloader/include/impl/ELFObject.hxx
new file mode 100644
index 0000000..ca47820
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFObject.hxx
@@ -0,0 +1,740 @@
+/*
+ * Copyright 2011-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 ELF_OBJECT_HXX
+#define ELF_OBJECT_HXX
+
+#include "ELFHeader.h"
+#include "ELFReloc.h"
+#include "ELFSection.h"
+#include "ELFSectionHeaderTable.h"
+#include "StubLayout.h"
+#include "GOT.h"
+#include "ELF.h"
+
+#include <llvm/ADT/SmallVector.h>
+
+#include "utils/rsl_assert.h"
+
+template <unsigned Bitwidth>
+template <typename Archiver>
+inline ELFObject<Bitwidth> *
+ELFObject<Bitwidth>::read(Archiver &AR) {
+  llvm::OwningPtr<ELFObjectTy> object(new ELFObjectTy());
+
+  // Read header
+  object->header.reset(ELFHeaderTy::read(AR));
+  if (!object->header) {
+    return 0;
+  }
+
+  // Read section table
+  object->shtab.reset(ELFSectionHeaderTableTy::read(AR, object.get()));
+  if (!object->shtab) {
+    return 0;
+  }
+
+  // Read each section
+  llvm::SmallVector<size_t, 4> progbits_ndx;
+  for (size_t i = 0; i < object->header->getSectionHeaderNum(); ++i) {
+    if ((*object->shtab)[i]->getType() == SHT_PROGBITS) {
+      object->stab.push_back(NULL);
+      progbits_ndx.push_back(i);
+    } else {
+      llvm::OwningPtr<ELFSectionTy> sec(
+        ELFSectionTy::read(AR, object.get(), (*object->shtab)[i]));
+      object->stab.push_back(sec.take());
+    }
+  }
+
+  object->shtab->buildNameMap();
+  ELFSectionSymTabTy *symtab =
+    static_cast<ELFSectionSymTabTy *>(object->getSectionByName(".symtab"));
+  rsl_assert(symtab && "Symtab is required.");
+  symtab->buildNameMap();
+
+  for (size_t i = 0; i < progbits_ndx.size(); ++i) {
+    size_t index = progbits_ndx[i];
+
+    llvm::OwningPtr<ELFSectionTy> sec(
+      ELFSectionTy::read(AR, object.get(), (*object->shtab)[index]));
+    object->stab[index] = sec.take();
+  }
+
+  return object.take();
+}
+
+template <unsigned Bitwidth>
+inline char const *ELFObject<Bitwidth>::getSectionName(size_t i) const {
+  ELFSectionTy const *sec = stab[header->getStringSectionIndex()];
+
+  if (sec) {
+    ELFSectionStrTabTy const &st =
+      static_cast<ELFSectionStrTabTy const &>(*sec);
+    return st[i];
+  }
+
+  return NULL;
+}
+
+template <unsigned Bitwidth>
+inline ELFSection<Bitwidth> const *
+ELFObject<Bitwidth>::getSectionByIndex(size_t i) const {
+  return stab[i];
+}
+
+template <unsigned Bitwidth>
+inline ELFSection<Bitwidth> *
+ELFObject<Bitwidth>::getSectionByIndex(size_t i) {
+  return stab[i];
+}
+
+template <unsigned Bitwidth>
+inline ELFSection<Bitwidth> const *
+ELFObject<Bitwidth>::getSectionByName(std::string const &str) const {
+  size_t idx = getSectionHeaderTable()->getByName(str)->getIndex();
+  return stab[idx];
+}
+
+template <unsigned Bitwidth>
+inline ELFSection<Bitwidth> *
+ELFObject<Bitwidth>::getSectionByName(std::string const &str) {
+  ELFObjectTy const *const_this = this;
+  ELFSectionTy const *sptr = const_this->getSectionByName(str);
+  // Const cast for the same API's const and non-const versions.
+  return const_cast<ELFSectionTy *>(sptr);
+}
+
+
+template <unsigned Bitwidth>
+inline void ELFObject<Bitwidth>::
+relocateARM(void *(*find_sym)(void *context, char const *name),
+            void *context,
+            ELFSectionRelTableTy *reltab,
+            ELFSectionProgBitsTy *text) {
+  // FIXME: Should be implement in independent files.
+  rsl_assert(Bitwidth == 32 && "ARM only have 32 bits.");
+
+  ELFSectionSymTabTy *symtab =
+    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
+  rsl_assert(symtab && "Symtab is required.");
+
+  for (size_t i = 0; i < reltab->size(); ++i) {
+    // FIXME: Can not implement here, use Fixup!
+    ELFRelocTy *rel = (*reltab)[i];
+    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
+
+    // FIXME: May be not uint32_t *.
+    typedef int32_t Inst_t;
+    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
+    Inst_t P = (Inst_t)(int64_t)inst;
+    Inst_t A = 0;
+    Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_ARM);
+    Inst_t T = 0;
+
+    if (sym->isConcreteFunc() && (sym->getValue() & 0x1)) {
+      T = 1;
+    }
+
+    word_t reltype = rel->getType();
+    switch (reltype) {
+    default:
+      rsl_assert(0 && "Not implemented relocation type.");
+      break;
+
+    case R_ARM_ABS32:
+      {
+        if (S == 0 && sym->getType() == STT_NOTYPE) {
+          void *ext_sym = find_sym(context, sym->getName());
+          if (!ext_sym) {
+            missingSymbols = true;
+          }
+          S = (Inst_t)(uintptr_t)ext_sym;
+          sym->setAddress(ext_sym);
+        }
+        A = *inst;
+        *inst = (S + A) | T;
+      }
+      break;
+
+      // FIXME: Predefine relocation codes.
+    case R_ARM_CALL:
+    case R_ARM_THM_CALL:
+    case R_ARM_JUMP24:
+    case R_ARM_THM_JUMP24:
+      {
+#define SIGN_EXTEND(x, l) (((x)^(1<<((l)-1)))-(1<<(l-1)))
+        if (reltype == R_ARM_CALL || reltype == R_ARM_JUMP24) {
+          A = (Inst_t)(int64_t)SIGN_EXTEND(*inst & 0xFFFFFF, 24);
+          A <<= 2;
+        } else {
+          // Hack for two 16bit.
+          *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
+          Inst_t s  = (*inst >> 26) & 0x1u,    // 26
+                 u  = (*inst >> 16) & 0x3FFu,  // 25-16
+                 l  =  *inst        & 0x7FFu, // 10-0
+                 j1 = (*inst >> 13) & 0x1u,    // 13
+                 j2 = (*inst >> 11) & 0x1u;    // 11
+          Inst_t i1 = (~(j1 ^ s)) & 0x1u,
+                 i2 = (~(j2 ^ s)) & 0x1u;
+          // [31-25][24][23][22][21-12][11-1][0]
+          //      0   s  i1  i2      u     l  0
+          A = SIGN_EXTEND((s << 23) | (i1 << 22) | (i2 << 21) | (u << 11) | l, 24);
+          A <<= 1;
+        }
+#undef SIGN_EXTEND
+
+        void *callee_addr = sym->getAddress(EM_ARM);
+
+        switch (sym->getType()) {
+        default:
+          rsl_assert(0 && "Wrong type for R_ARM_CALL relocation.");
+          abort();
+          break;
+
+        case STT_FUNC:
+          // NOTE: Callee function is in the object file, but it may be
+          // in different PROGBITS section (which may be far call).
+
+          if (callee_addr == 0) {
+            rsl_assert(0 && "We should get function address at previous "
+                   "sym->getAddress(EM_ARM) function call.");
+            abort();
+          }
+          break;
+
+        case STT_NOTYPE:
+          // NOTE: Callee function is an external function.  Call find_sym
+          // if it has not resolved yet.
+
+          if (callee_addr == 0) {
+            callee_addr = find_sym(context, sym->getName());
+            if (!callee_addr) {
+              missingSymbols = true;
+            }
+            sym->setAddress(callee_addr);
+          }
+          break;
+        }
+
+        // Get the stub for this function
+        StubLayout *stub_layout = text->getStubLayout();
+
+        if (!stub_layout) {
+          llvm::errs() << "unable to get stub layout." << "\n";
+          abort();
+        }
+
+        void *stub = stub_layout->allocateStub(callee_addr);
+
+        if (!stub) {
+          llvm::errs() << "unable to allocate stub." << "\n";
+          abort();
+        }
+
+        //LOGI("Function %s: using stub %p\n", sym->getName(), stub);
+        S = (uint32_t)(uintptr_t)stub;
+
+        if (reltype == R_ARM_CALL || reltype == R_ARM_JUMP24) {
+          // Relocate the R_ARM_CALL relocation type
+          uint32_t result = (S + A - P) >> 2;
+
+          if (result > 0x007FFFFF && result < 0xFF800000) {
+            rsl_assert(0 && "Stub is still too far");
+            abort();
+          }
+
+          *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000);
+        } else {
+          P &= ~0x3;  // Base address align to 4 bytes.  (For BLX.)
+
+          // Relocate the R_ARM_THM_CALL relocation type
+          uint32_t result = (S + A - P) >> 1;
+
+          if (result > 0x007FFFFF && result < 0xFF800000) {
+            rsl_assert(0 && "Stub is still too far");
+            abort();
+          }
+
+          //*inst &= 0xF800D000u;
+          // Rewrite instruction to BLX.  (Stub is always ARM.)
+          *inst &= 0xF800C000u;
+          // [31-25][24][23][22][21-12][11-1][0]
+          //      0   s  i1  i2      u     l  0
+          Inst_t s  = (result >> 23) & 0x1u,   // 26
+                 u  = (result >> 11) & 0x3FFu, // 25-16
+                 // For BLX, bit [0] is 0.
+                 l  =  result        & 0x7FEu, // 10-0
+                 i1 = (result >> 22) & 0x1u,
+                 i2 = (result >> 21) & 0x1u;
+          Inst_t j1 = ((~i1) ^ s) & 0x01u,       // 13
+                 j2 = ((~i2) ^ s) & 0x01u;       // 11
+          *inst |= s << 26;
+          *inst |= u << 16;
+          *inst |= l;
+          *inst |= j1 << 13;
+          *inst |= j2 << 11;
+          // Hack for two 16bit.
+          *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
+        }
+      }
+      break;
+    case R_ARM_MOVT_ABS:
+    case R_ARM_MOVW_ABS_NC:
+    case R_ARM_THM_MOVW_ABS_NC:
+    case R_ARM_THM_MOVT_ABS:
+      {
+        if (S == 0 && sym->getType() == STT_NOTYPE) {
+          void *ext_sym = find_sym(context, sym->getName());
+          if (!ext_sym) {
+            missingSymbols = true;
+          }
+          S = (Inst_t)(uintptr_t)ext_sym;
+          sym->setAddress(ext_sym);
+        }
+        if (reltype == R_ARM_MOVT_ABS
+            || reltype == R_ARM_THM_MOVT_ABS) {
+          S >>= 16;
+        }
+
+        if (reltype == R_ARM_MOVT_ABS
+            || reltype == R_ARM_MOVW_ABS_NC) {
+          // No need sign extend.
+          A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF);
+          uint32_t result = (S + A);
+          *inst = (((result) & 0xF000) << 4) |
+            ((result) & 0xFFF) |
+            (*inst & 0xFFF0F000);
+        } else {
+          // Hack for two 16bit.
+          *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
+          // imm16: [19-16][26][14-12][7-0]
+          A = (((*inst >>  4) & 0xF000u) |
+               ((*inst >> 15) & 0x0800u) |
+               ((*inst >>  4) & 0x0700u) |
+               ( *inst        & 0x00FFu));
+          uint32_t result;
+          if (reltype == R_ARM_THM_MOVT_ABS) {
+            result = (S + A);
+          } else {
+            result = (S + A) | T;
+          }
+          // imm16: [19-16][26][14-12][7-0]
+          *inst &= 0xFBF08F00u;
+          *inst |= (result & 0xF000u) << 4;
+          *inst |= (result & 0x0800u) << 15;
+          *inst |= (result & 0x0700u) << 4;
+          *inst |= (result & 0x00FFu);
+          // Hack for two 16bit.
+          *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
+        }
+      }
+      break;
+    }
+    //llvm::errs() << "S:     " << (void *)S << '\n';
+    //llvm::errs() << "A:     " << (void *)A << '\n';
+    //llvm::errs() << "P:     " << (void *)P << '\n';
+    //llvm::errs() << "S+A:   " << (void *)(S+A) << '\n';
+    //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n';
+  }
+}
+
+template <unsigned Bitwidth>
+inline void ELFObject<Bitwidth>::
+relocateX86_64(void *(*find_sym)(void *context, char const *name),
+               void *context,
+               ELFSectionRelTableTy *reltab,
+               ELFSectionProgBitsTy *text) {
+  rsl_assert(Bitwidth == 64 && "Only support X86_64.");
+
+  ELFSectionSymTabTy *symtab =
+    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
+  rsl_assert(symtab && "Symtab is required.");
+
+  for (size_t i = 0; i < reltab->size(); ++i) {
+    // FIXME: Can not implement here, use Fixup!
+    ELFRelocTy *rel = (*reltab)[i];
+    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
+
+    //typedef uint64_t Inst_t;
+    typedef int32_t Inst_t;
+    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
+    Inst_t P = (Inst_t)(int64_t)inst;
+    Inst_t A = (Inst_t)(int64_t)rel->getAddend();
+    Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_X86_64);
+
+    if (S == 0) {
+      S = (Inst_t)(int64_t)find_sym(context, sym->getName());
+      if (!S) {
+        missingSymbols = true;
+      }
+      sym->setAddress((void *)S);
+    }
+
+    switch (rel->getType()) {
+      default:
+        rsl_assert(0 && "Not implemented relocation type.");
+        break;
+
+      // FIXME: XXX: R_X86_64_64 is 64 bit, there is a big problem here.
+      case 1: // R_X86_64_64
+        *inst = (S+A);
+        break;
+
+      case 2: // R_X86_64_PC32
+        *inst = (S+A-P);
+        break;
+
+      case 10: // R_X86_64_32
+      case 11: // R_X86_64_32S
+        *inst = (S+A);
+        break;
+    }
+  }
+}
+
+template <unsigned Bitwidth>
+inline void ELFObject<Bitwidth>::
+relocateX86_32(void *(*find_sym)(void *context, char const *name),
+               void *context,
+               ELFSectionRelTableTy *reltab,
+               ELFSectionProgBitsTy *text) {
+  rsl_assert(Bitwidth == 32 && "Only support X86.");
+
+  ELFSectionSymTabTy *symtab =
+    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
+  rsl_assert(symtab && "Symtab is required.");
+
+  for (size_t i = 0; i < reltab->size(); ++i) {
+    // FIXME: Can not implement here, use Fixup!
+    ELFRelocTy *rel = (*reltab)[i];
+    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
+
+    //typedef uint64_t Inst_t;
+    typedef int32_t Inst_t;
+    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
+    Inst_t P = (Inst_t)(uintptr_t)inst;
+    Inst_t A = (Inst_t)(uintptr_t)*inst;
+    Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_386);
+
+    if (S == 0) {
+      S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
+      if (!S) {
+        missingSymbols = true;
+      }
+      sym->setAddress((void *)S);
+    }
+
+    switch (rel->getType()) {
+    default:
+      rsl_assert(0 && "Not implemented relocation type.");
+      break;
+
+    case R_386_PC32:
+      *inst = (S+A-P);
+      break;
+
+    case R_386_32:
+      *inst = (S+A);
+      break;
+    }
+  }
+}
+
+template <unsigned Bitwidth>
+inline void ELFObject<Bitwidth>::
+relocateMIPS(void *(*find_sym)(void *context, char const *name),
+             void *context,
+             ELFSectionRelTableTy *reltab,
+             ELFSectionProgBitsTy *text) {
+  rsl_assert(Bitwidth == 32 && "Only support 32-bit MIPS.");
+
+  ELFSectionSymTabTy *symtab =
+    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
+  rsl_assert(symtab && "Symtab is required.");
+
+  for (size_t i = 0; i < reltab->size(); ++i) {
+    // FIXME: Can not implement here, use Fixup!
+    ELFRelocTy *rel = (*reltab)[i];
+    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
+
+    typedef int32_t Inst_t;
+    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
+    Inst_t P = (Inst_t)(uintptr_t)inst;
+    Inst_t A = (Inst_t)(uintptr_t)*inst;
+    Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_MIPS);
+
+    bool need_stub = false;
+
+    if (S == 0 && strcmp (sym->getName(), "_gp_disp") != 0) {
+      need_stub = true;
+      S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
+      if (!S) {
+        missingSymbols = true;
+      }
+      sym->setAddress((void *)S);
+    }
+
+    switch (rel->getType()) {
+    default:
+      rsl_assert(0 && "Not implemented relocation type.");
+      break;
+
+    case R_MIPS_NONE:
+    case R_MIPS_JALR: // ignore this
+      break;
+
+    case R_MIPS_16:
+      *inst &= 0xFFFF0000;
+      A = A & 0xFFFF;
+      A = S + (short)A;
+      rsl_assert(A >= -32768 && A <= 32767 && "R_MIPS_16 overflow.");
+      *inst |= (A & 0xFFFF);
+      break;
+
+    case R_MIPS_32:
+      *inst = S + A;
+      break;
+
+    case R_MIPS_26:
+      *inst &= 0xFC000000;
+      if (need_stub == false) {
+        A = (A & 0x3FFFFFF) << 2;
+        if (sym->getBindingAttribute() == STB_LOCAL) { // local binding
+          A |= ((P + 4) & 0xF0000000);
+          A += S;
+          *inst |= ((A >> 2) & 0x3FFFFFF);
+        } else { // external binding
+          if (A & 0x08000000) // Sign extend from bit 27
+            A |= 0xF0000000;
+          A += S;
+          *inst |= ((A >> 2) & 0x3FFFFFF);
+          if (((P + 4) >> 28) != (A >> 28)) { // far local call
+            void *stub = text->getStubLayout()->allocateStub((void *)A);
+            rsl_assert(stub && "cannot allocate stub.");
+            sym->setAddress(stub);
+            S = (int32_t)(intptr_t)stub;
+            *inst |= ((S >> 2) & 0x3FFFFFF);
+            rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far.");
+          }
+        }
+      } else { // shared-library call
+        A = (A & 0x3FFFFFF) << 2;
+        rsl_assert(A == 0 && "R_MIPS_26 addend is not zero.");
+        void *stub = text->getStubLayout()->allocateStub((void *)S);
+        rsl_assert(stub && "cannot allocate stub.");
+        sym->setAddress(stub);
+        S = (int32_t)(intptr_t)stub;
+        *inst |= ((S >> 2) & 0x3FFFFFF);
+        rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far.");
+      }
+      break;
+
+    case R_MIPS_HI16:
+      *inst &= 0xFFFF0000;
+      A = (A & 0xFFFF) << 16;
+      // Find the nearest LO16 relocation type after this entry
+      for (size_t j = i + 1; j < reltab->size(); j++) {
+        ELFRelocTy *this_rel = (*reltab)[j];
+        ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()];
+        if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) {
+          Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()];
+          Inst_t this_A = (Inst_t)(uintptr_t)*this_inst;
+          this_A = this_A & 0xFFFF;
+          A += (short)this_A;
+          break;
+        }
+      }
+      if (strcmp (sym->getName(), "_gp_disp") == 0) {
+          S = (int)(intptr_t)got_address() + GP_OFFSET - (int)P;
+          sym->setAddress((void *)S);
+      }
+      *inst |= (((S + A + (int)0x8000) >> 16) & 0xFFFF);
+      break;
+
+    case R_MIPS_LO16:
+      *inst &= 0xFFFF0000;
+      A = A & 0xFFFF;
+      if (strcmp (sym->getName(), "_gp_disp") == 0) {
+          S = (Inst_t)(intptr_t)sym->getAddress(EM_MIPS);
+      }
+      *inst |= ((S + A) & 0xFFFF);
+      break;
+
+    case R_MIPS_GOT16:
+    case R_MIPS_CALL16:
+      {
+        *inst &= 0xFFFF0000;
+        A = A & 0xFFFF;
+        if (rel->getType() == R_MIPS_GOT16) {
+          if (sym->getBindingAttribute() == STB_LOCAL) {
+            A <<= 16;
+
+            // Find the nearest LO16 relocation type after this entry
+            for (size_t j = i + 1; j < reltab->size(); j++) {
+              ELFRelocTy *this_rel = (*reltab)[j];
+              ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()];
+              if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) {
+                Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()];
+                Inst_t this_A = (Inst_t)(uintptr_t)*this_inst;
+                this_A = this_A & 0xFFFF;
+                A += (short)this_A;
+                break;
+              }
+            }
+          } else {
+            rsl_assert(A == 0 && "R_MIPS_GOT16 addend is not 0.");
+          }
+        } else { // R_MIPS_CALL16
+          rsl_assert(A == 0 && "R_MIPS_CALL16 addend is not 0.");
+        }
+        int got_index = search_got((int)rel->getSymTabIndex(), (void *)(S + A),
+                                   sym->getBindingAttribute());
+        int got_offset = (got_index << 2) - GP_OFFSET;
+        *inst |= (got_offset & 0xFFFF);
+      }
+      break;
+
+    case R_MIPS_GPREL32:
+      *inst = A + S - ((int)(intptr_t)got_address() + GP_OFFSET);
+      break;
+    }
+  }
+}
+
+
+// TODO: Refactor all relocations.
+template <unsigned Bitwidth>
+inline void ELFObject<Bitwidth>::
+relocate(void *(*find_sym)(void *context, char const *name), void *context) {
+  // Init SHNCommonDataSize.
+  // Need refactoring
+  size_t SHNCommonDataSize = 0;
+
+  ELFSectionSymTabTy *symtab =
+    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
+  rsl_assert(symtab && "Symtab is required.");
+
+  for (size_t i = 0; i < symtab->size(); ++i) {
+    ELFSymbolTy *sym = (*symtab)[i];
+
+    if (sym->getType() != STT_OBJECT) {
+      continue;
+    }
+
+    size_t idx = (size_t)sym->getSectionIndex();
+    switch (idx) {
+    default:
+      if ((*shtab)[idx]->getType() == SHT_NOBITS) {
+        // FIXME(logan): This is a workaround for .lcomm directives
+        // bug of LLVM ARM MC code generator.  Remove this when the
+        // LLVM bug is fixed.
+
+        size_t align = 16;
+        SHNCommonDataSize += (size_t)sym->getSize() + align;
+      }
+      break;
+
+    case SHN_COMMON:
+      {
+        size_t align = (size_t)sym->getValue();
+        SHNCommonDataSize += (size_t)sym->getSize() + align;
+      }
+      break;
+
+    case SHN_ABS:
+    case SHN_UNDEF:
+    case SHN_XINDEX:
+      break;
+    }
+  }
+  if (!initSHNCommonDataSize(SHNCommonDataSize)) {
+    rsl_assert("Allocate memory for common variable fail!");
+    // TODO: Refactor object loading to use proper status/error returns.
+    // We mark the object as having missing symbols and return early in this
+    // case to signal a loading error (usually due to running out of
+    // available memory to allocate).
+    missingSymbols = true;
+    return;
+  }
+
+  for (size_t i = 0; i < stab.size(); ++i) {
+    ELFSectionHeaderTy *sh = (*shtab)[i];
+    if (sh->getType() != SHT_REL && sh->getType() != SHT_RELA) {
+      continue;
+    }
+    ELFSectionRelTableTy *reltab =
+      static_cast<ELFSectionRelTableTy *>(stab[i]);
+    rsl_assert(reltab && "Relocation section can't be NULL.");
+
+    const char *reltab_name = sh->getName();
+    const char *need_rel_name;
+    if (sh->getType() == SHT_REL) {
+      need_rel_name = reltab_name + 4;
+      // ".rel.xxxx"
+      //      ^ start from here.
+    } else {
+      need_rel_name = reltab_name + 5;
+    }
+
+    ELFSectionProgBitsTy *need_rel =
+      static_cast<ELFSectionProgBitsTy *>(getSectionByName(need_rel_name));
+    rsl_assert(need_rel && "Need be relocated section can't be NULL.");
+
+    switch (getHeader()->getMachine()) {
+      case EM_ARM:
+        relocateARM(find_sym, context, reltab, need_rel);
+        break;
+      case EM_386:
+        relocateX86_32(find_sym, context, reltab, need_rel);
+        break;
+      case EM_X86_64:
+        relocateX86_64(find_sym, context, reltab, need_rel);
+        break;
+      case EM_MIPS:
+        relocateMIPS(find_sym, context, reltab, need_rel);
+        break;
+
+      default:
+        rsl_assert(0 && "Only support ARM, MIPS, X86, and X86_64 relocation.");
+        break;
+    }
+  }
+
+  for (size_t i = 0; i < stab.size(); ++i) {
+    ELFSectionHeaderTy *sh = (*shtab)[i];
+    if (sh->getType() == SHT_PROGBITS || sh->getType() == SHT_NOBITS) {
+      if (stab[i]) {
+        static_cast<ELFSectionBitsTy *>(stab[i])->protect();
+      }
+    }
+  }
+}
+
+template <unsigned Bitwidth>
+inline void ELFObject<Bitwidth>::print() const {
+  header->print();
+  shtab->print();
+
+  for (size_t i = 0; i < stab.size(); ++i) {
+    ELFSectionTy *sec = stab[i];
+    if (sec) {
+      sec->print();
+    }
+  }
+}
+
+#endif // ELF_OBJECT_HXX
diff --git a/driver/linkloader/include/impl/ELFReloc.hxx b/driver/linkloader/include/impl/ELFReloc.hxx
new file mode 100644
index 0000000..6b55e02
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFReloc.hxx
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2011, 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 ELF_RELOC_HXX
+#define ELF_RELOC_HXX
+
+#include "utils/raw_ostream.h"
+
+#include <llvm/Support/Format.h>
+#include <llvm/Support/raw_ostream.h>
+
+template <unsigned Bitwidth>
+template <typename Archiver>
+inline ELFReloc<Bitwidth> *
+ELFReloc_CRTP<Bitwidth>::readRela(Archiver &AR, size_t index) {
+  if (!AR) {
+    // Archiver is in bad state before calling read function.
+    // Return NULL and do nothing.
+    return 0;
+  }
+
+  llvm::OwningPtr<ELFRelocTy> sh(new ELFRelocTy());
+
+  if (!sh->serializeRela(AR)) {
+    // Unable to read the structure.  Return NULL.
+    return 0;
+  }
+
+  if (!sh->isValid()) {
+    // Rel read from archiver is not valid.  Return NULL.
+    return 0;
+  }
+
+  // Set the section header index
+  sh->index = index;
+
+  return sh.take();
+}
+
+template <unsigned Bitwidth>
+template <typename Archiver>
+inline ELFReloc<Bitwidth> *
+ELFReloc_CRTP<Bitwidth>::readRel(Archiver &AR, size_t index) {
+  if (!AR) {
+    // Archiver is in bad state before calling read function.
+    // Return NULL and do nothing.
+    return 0;
+  }
+
+  llvm::OwningPtr<ELFRelocTy> sh(new ELFRelocTy());
+
+  sh->r_addend = 0;
+  if (!sh->serializeRel(AR)) {
+    return 0;
+  }
+
+  if (!sh->isValid()) {
+    // Rel read from archiver is not valid.  Return NULL.
+    return 0;
+  }
+
+  // Set the section header index
+  sh->index = index;
+
+  return sh.take();
+}
+
+template <unsigned Bitwidth>
+inline void ELFReloc_CRTP<Bitwidth>::print(bool shouldPrintHeader) const {
+  using namespace llvm;
+  if (shouldPrintHeader) {
+    out() << '\n' << fillformat('=', 79) << '\n';
+    out().changeColor(raw_ostream::WHITE, true);
+    out() << "ELF Relaocation Table Entry "
+          << this->getIndex() << '\n';
+    out().resetColor();
+    out() << fillformat('-', 79) << '\n';
+  } else {
+    out() << fillformat('-', 79) << '\n';
+    out().changeColor(raw_ostream::YELLOW, true);
+    out() << "ELF Relaocation Table Entry "
+          << this->getIndex() << " : " << '\n';
+    out().resetColor();
+  }
+
+#define PRINT_LINT(title, value) \
+  out() << format("  %-13s : ", (char const *)(title)) << (value) << '\n'
+  PRINT_LINT("Offset",       concrete()->getOffset()       );
+  PRINT_LINT("SymTab Index", concrete()->getSymTabIndex()  );
+  PRINT_LINT("Type",         concrete()->getType()         );
+  PRINT_LINT("Addend",       concrete()->getAddend()       );
+#undef PRINT_LINT
+}
+
+#endif // ELF_RELOC_HXX
diff --git a/driver/linkloader/include/impl/ELFSection.hxx b/driver/linkloader/include/impl/ELFSection.hxx
new file mode 100644
index 0000000..fb0e6f6
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFSection.hxx
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_HXX
+#define ELF_SECTION_HXX
+
+#include "utils/raw_ostream.h"
+
+#include <llvm/Support/raw_ostream.h>
+
+#include "ELFSectionHeader.h"
+#include "ELFSectionStrTab.h"
+#include "ELFSectionSymTab.h"
+#include "ELFSectionProgBits.h"
+#include "ELFSectionNoBits.h"
+#include "ELFSectionRelTable.h"
+
+template <unsigned Bitwidth>
+template <typename Archiver>
+inline ELFSection<Bitwidth> *
+ELFSection<Bitwidth>::read(Archiver &AR,
+                           ELFObjectTy *owner,
+                           ELFSectionHeaderTy const *sh) {
+  using namespace std;
+
+  switch (sh->getType()) {
+    default:
+      // Uknown type of ELF section.  Return NULL.
+      //llvm::errs() << "WARNING: Unknown section type.\n";
+      return 0;
+
+    case SHT_STRTAB:
+      return ELFSectionStrTabTy::read(AR, sh);
+
+    case SHT_SYMTAB:
+      return ELFSectionSymTabTy::read(AR, owner, sh);
+
+    case SHT_PROGBITS:
+      return ELFSectionProgBitsTy::read(AR, owner, sh);
+
+    case SHT_NOBITS:
+      return ELFSectionNoBitsTy::read(AR, sh);
+
+    case SHT_REL:
+    case SHT_RELA:
+      return ELFSectionRelTableTy::read(AR, sh);
+
+    case SHT_NULL:
+      // TODO: Not Yet Implemented
+      return 0;
+  };
+}
+
+#endif // ELF_SECTION_HXX
diff --git a/driver/linkloader/include/impl/ELFSectionBits.hxx b/driver/linkloader/include/impl/ELFSectionBits.hxx
new file mode 100644
index 0000000..bd585d4
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFSectionBits.hxx
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_BITS_HXX
+#define ELF_SECTION_BITS_HXX
+
+#include "utils/flush_cpu_cache.h"
+#include "utils/helper.h"
+
+#include <llvm/Support/raw_ostream.h>
+
+#include <sys/mman.h>
+
+template <unsigned Bitwidth>
+inline void ELFSectionBits<Bitwidth>::print() const {
+  using namespace llvm;
+
+  char const *section_type_str =
+    (sh->getType() == SHT_NOBITS) ? "NOBITS" : "PROGBITS";
+
+  out() << '\n' << fillformat('=', 79) << '\n';
+  out().changeColor(raw_ostream::WHITE, true);
+  out() << "ELF " << section_type_str << ": " << sh->getName() << '\n';
+  out().resetColor();
+  out() << fillformat('-', 79) << '\n';
+
+  out() << "  Size         : " << sh->getSize() << '\n';
+  out() << "  Start Address: " << (void *)chunk.getBuffer() << '\n';
+  out() << fillformat('-', 79) << '\n';
+
+  chunk.print();
+
+  out() << fillformat('=', 79) << '\n';
+}
+
+template <unsigned Bitwidth>
+inline bool ELFSectionBits<Bitwidth>::protect() {
+  int prot = PROT_READ;
+
+  if (sh->getFlags() & SHF_WRITE) {
+    prot |= PROT_WRITE;
+  }
+
+  if (sh->getFlags() & SHF_EXECINSTR) {
+    prot |= PROT_EXEC;
+  }
+
+  return chunk.protect(prot);
+}
+
+#endif // ELF_SECTION_BITS_HXX
diff --git a/driver/linkloader/include/impl/ELFSectionHeader.hxx b/driver/linkloader/include/impl/ELFSectionHeader.hxx
new file mode 100644
index 0000000..78a5495
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFSectionHeader.hxx
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_HEADER_HXX
+#define ELF_SECTION_HEADER_HXX
+
+#include "utils/raw_ostream.h"
+#include <llvm/Support/Format.h>
+#include <llvm/Support/raw_ostream.h>
+
+#include "ELFObject.h"
+
+template <unsigned Bitwidth>
+char const *ELFSectionHeader_CRTP<Bitwidth>::getName() const {
+  return owner->getSectionName(getNameIndex());
+}
+
+template <unsigned Bitwidth>
+template <typename Archiver>
+typename ELFSectionHeader_CRTP<Bitwidth>::ELFSectionHeaderTy *
+ELFSectionHeader_CRTP<Bitwidth>::read(Archiver &AR,
+                                      ELFObjectTy const *owner,
+                                      size_t index) {
+
+  if (!AR) {
+    // Archiver is in bad state before calling read function.
+    // Return NULL and do nothing.
+    return 0;
+  }
+
+  llvm::OwningPtr<ELFSectionHeaderTy> sh(new ELFSectionHeaderTy());
+
+  if (!sh->serialize(AR)) {
+    // Unable to read the structure.  Return NULL.
+    return 0;
+  }
+
+  if (!sh->isValid()) {
+    // Header read from archiver is not valid.  Return NULL.
+    return 0;
+  }
+
+  // Set the section header index
+  sh->index = index;
+
+  // Set the owner elf object
+  sh->owner = owner;
+
+  return sh.take();
+}
+
+template <unsigned Bitwidth>
+void ELFSectionHeader_CRTP<Bitwidth>::print(bool shouldPrintHeader) const {
+  using namespace llvm;
+
+  if (shouldPrintHeader) {
+    out() << '\n' << fillformat('=', 79) << '\n';
+    out().changeColor(raw_ostream::WHITE, true);
+    out() << "ELF Section Header "
+      << this->getIndex() << '\n';
+    out().resetColor();
+    out() << fillformat('-', 79) << '\n';
+  } else {
+    out() << fillformat('-', 79) << '\n';
+    out().changeColor(raw_ostream::YELLOW, true);
+    out() << "ELF Section Header "
+      << this->getIndex() << " : " << '\n';
+    out().resetColor();
+  }
+
+#define PRINT_LINT(title, value) \
+  out() << format("  %-13s : ", (char const *)(title)) << (value) << '\n'
+  PRINT_LINT("Name",          getName() );
+  PRINT_LINT("Type",          getSectionTypeStr(getType()));
+  PRINT_LINT("Flags",         concrete()->getFlags());
+  PRINT_LINT("Address",       getAddress());
+  PRINT_LINT("Offset",        getOffset());
+  PRINT_LINT("Size",          concrete()->getSize());
+  PRINT_LINT("Link",          getLink());
+  PRINT_LINT("Extra Info",    getExtraInfo());
+  PRINT_LINT("Address Align", concrete()->getAddressAlign());
+  PRINT_LINT("Entry Size",    concrete()->getEntrySize());
+#undef PRINT_LINT
+
+  if (shouldPrintHeader) {
+    out() << fillformat('=', 79) << '\n';
+  }
+}
+
+#endif // ELF_SECTION_HEADER_HXX
diff --git a/driver/linkloader/include/impl/ELFSectionHeaderTable.hxx b/driver/linkloader/include/impl/ELFSectionHeaderTable.hxx
new file mode 100644
index 0000000..1f693a4
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFSectionHeaderTable.hxx
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_HEADER_TABLE_HXX
+#define ELF_SECTION_HEADER_TABLE_HXX
+
+#include "ELFHeader.h"
+#include "ELFObject.h"
+#include "ELFSectionHeader.h"
+
+#include "utils/rsl_assert.h"
+
+template <unsigned Bitwidth>
+ELFSectionHeaderTable<Bitwidth>::~ELFSectionHeaderTable() {
+  for (size_t i = 0; i < table.size(); ++i) {
+    delete table[i];
+  }
+}
+
+template <unsigned Bitwidth>
+template <typename Archiver>
+inline ELFSectionHeaderTable<Bitwidth> *
+ELFSectionHeaderTable<Bitwidth>::read(Archiver &AR, ELFObjectTy *owner) {
+  if (!AR) {
+    // Archiver is in bad state before calling read function.
+    // Return NULL and do nothing.
+    return 0;
+  }
+
+  // Allocate a new section header table and assign the owner.
+  llvm::OwningPtr<ELFSectionHeaderTable> tab(new ELFSectionHeaderTable());
+
+  // Get ELF header
+  ELFHeaderTy const *header = owner->getHeader();
+
+  rsl_assert(header->getSectionHeaderEntrySize() ==
+         TypeTraits<ELFSectionHeaderTy>::size);
+
+  // Seek to the address of section header
+  AR.seek(header->getSectionHeaderTableOffset(), true);
+
+  for (size_t i = 0; i < header->getSectionHeaderNum(); ++i) {
+    llvm::OwningPtr<ELFSectionHeaderTy> sh(
+      ELFSectionHeaderTy::read(AR, owner, i));
+
+    if (!sh) {
+      // Something wrong while reading the section header.
+      return 0;
+    }
+
+    tab->table.push_back(sh.take());
+  }
+
+  return tab.take();
+}
+
+template <unsigned Bitwidth>
+inline void ELFSectionHeaderTable<Bitwidth>::print() const {
+  using namespace llvm;
+
+  out() << '\n' << fillformat('=', 79) << '\n';
+  out().changeColor(raw_ostream::WHITE, true);
+  out() << "ELF Section Header Table" << '\n';
+  out().resetColor();
+
+  for (size_t i = 0; i < table.size(); ++i) {
+    (*this)[i]->print();
+  }
+
+  out() << fillformat('=', 79) << '\n';
+}
+
+template <unsigned Bitwidth>
+inline void ELFSectionHeaderTable<Bitwidth>::buildNameMap() {
+  for (size_t i = 0; i < table.size(); ++i) {
+    ELFSectionHeaderTy *sh = table[i];
+    if ( sh ) {
+      name_map[sh->getName()] = sh;
+    }
+  }
+}
+
+template <unsigned Bitwidth>
+inline ELFSectionHeader<Bitwidth> const *
+ELFSectionHeaderTable<Bitwidth>::getByName(const std::string &name) const {
+  typename llvm::StringMap<ELFSectionHeaderTy *>::const_iterator sh =
+    name_map.find(name);
+  if (sh == name_map.end()) {
+    // Return SHN_UNDEF section header;
+    return table[0];
+  }
+  return sh->getValue();
+}
+
+template <unsigned Bitwidth>
+inline ELFSectionHeader<Bitwidth> *
+ELFSectionHeaderTable<Bitwidth>::getByName(const std::string &name) {
+  ELFSectionHeaderTableTy const *const_this = this;
+  ELFSectionHeaderTy const *shptr = const_this->getByName(name);
+  // Const cast for the same API's const and non-const versions.
+  return const_cast<ELFSectionHeaderTy *>(shptr);
+}
+
+#endif // ELF_SECTION_HEADER_TABLE_HXX
diff --git a/driver/linkloader/include/impl/ELFSectionNoBits.hxx b/driver/linkloader/include/impl/ELFSectionNoBits.hxx
new file mode 100644
index 0000000..d1a6436
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFSectionNoBits.hxx
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_NOBITS_HXX
+#define ELF_SECTION_NOBITS_HXX
+
+#include "ELFTypes.h"
+
+#include "utils/raw_ostream.h"
+
+#include <llvm/Support/Format.h>
+#include <llvm/Support/raw_ostream.h>
+
+#include <sys/mman.h>
+
+template <unsigned Bitwidth>
+template <typename Archiver>
+inline ELFSectionNoBits<Bitwidth> *
+ELFSectionNoBits<Bitwidth>::read(Archiver &AR, ELFSectionHeaderTy const *sh) {
+  llvm::OwningPtr<ELFSectionNoBits> result(new ELFSectionNoBits());
+
+  if (!result->chunk.allocate(sh->getSize())) {
+    return NULL;
+  }
+
+  result->sh = sh;
+
+  return result.take();
+}
+
+#endif // ELF_SECTION_NOBITS_HXX
diff --git a/driver/linkloader/include/impl/ELFSectionProgBits.hxx b/driver/linkloader/include/impl/ELFSectionProgBits.hxx
new file mode 100644
index 0000000..434e5b5
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFSectionProgBits.hxx
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_PROGBITS_HXX
+#define ELF_SECTION_PROGBITS_HXX
+
+#include "ELFTypes.h"
+#include "StubLayout.h"
+
+#include <llvm/Support/Format.h>
+#include <llvm/Support/raw_ostream.h>
+
+#include "utils/raw_ostream.h"
+
+#include <string.h>
+
+template <unsigned Bitwidth>
+template <typename Archiver>
+ELFSectionProgBits<Bitwidth> *
+ELFSectionProgBits<Bitwidth>::read(Archiver &AR,
+                                   ELFObjectTy *owner,
+                                   ELFSectionHeaderTy const *sh) {
+  int machine = owner->getHeader()->getMachine();
+  ELFSectionProgBits *secp = new ELFSectionProgBits(machine);
+  llvm::OwningPtr<ELFSectionProgBits> result(secp);
+  size_t max_num_stubs = 0;
+  // Align section boundary to 4 bytes.
+  size_t section_size = (sh->getSize() + 3) / 4 * 4;
+  size_t alloc_size = section_size;
+  StubLayout *stubs = result->getStubLayout();
+  if (stubs) {
+    // Compute the maximal possible numbers of stubs
+    std::string reltab_name(".rel" + std::string(sh->getName()));
+
+    ELFSectionRelTableTy const *reltab =
+      static_cast<ELFSectionRelTableTy *>(
+        owner->getSectionByName(reltab_name.c_str()));
+
+    if (reltab) {
+      // If we have relocation table, then get the approximation of
+      // maximum numbers of stubs.
+      max_num_stubs = reltab->getMaxNumStubs(owner);
+    }
+
+    // Compute the stub table size
+    size_t stub_table_size = stubs->calcStubTableSize(max_num_stubs);
+
+    // Allocate PROGBITS section with stubs table
+    alloc_size += stub_table_size;
+  }
+
+  // Allocate text section
+  if (!result->chunk.allocate(alloc_size)) {
+    return NULL;
+  }
+
+  if (stubs) {
+    stubs->initStubTable(result->chunk.getBuffer() + section_size,
+                         max_num_stubs);
+  }
+
+  result->sh = sh;
+
+  if (!result->serialize(AR)) {
+    // Unable to read the progbits section.
+    return NULL;
+  }
+
+  return result.take();
+}
+
+#endif // ELF_SECTION_PROGBITS_HXX
diff --git a/driver/linkloader/include/impl/ELFSectionRelTable.hxx b/driver/linkloader/include/impl/ELFSectionRelTable.hxx
new file mode 100644
index 0000000..c6c4dde
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFSectionRelTable.hxx
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_REL_TABLE_HXX
+#define ELF_SECTION_REL_TABLE_HXX
+
+#include "ELF.h"
+#include "ELFHeader.h"
+#include "ELFObject.h"
+#include "ELFReloc.h"
+#include "ELFTypes.h"
+
+#include <set>
+
+template <unsigned Bitwidth>
+ELFSectionRelTable<Bitwidth>::~ELFSectionRelTable() {
+  using namespace std;
+  for (size_t i = 0; i < table.size(); ++i) {
+    delete table[i];
+  }
+}
+
+template <unsigned Bitwidth>
+void ELFSectionRelTable<Bitwidth>::print() const {
+  using namespace llvm;
+
+  out() << '\n' << fillformat('=', 79) << '\n';
+  out().changeColor(raw_ostream::WHITE, true);
+  out() << "Relocation Table" << '\n';
+  out().resetColor();
+
+  for (size_t i = 0; i < this->size(); ++i) {
+    (*this)[i]->print();
+  }
+
+  out() << fillformat('=', 79) << '\n';
+}
+
+template <unsigned Bitwidth>
+template <typename Archiver>
+ELFSectionRelTable<Bitwidth> *
+ELFSectionRelTable<Bitwidth>::read(Archiver &AR,
+                                   ELFSectionHeaderTy const *sh) {
+
+  rsl_assert(sh->getType() == SHT_REL || sh->getType() == SHT_RELA);
+
+  llvm::OwningPtr<ELFSectionRelTable> rt(new ELFSectionRelTable());
+
+  // Seek to the start of the table
+  AR.seek(sh->getOffset(), true);
+
+  // Count the relocation entries
+  size_t size = sh->getSize() / sh->getEntrySize();
+
+  // Read every relocation entries
+  if (sh->getType() == SHT_REL) {
+    rsl_assert(sh->getEntrySize() == TypeTraits<ELFRelocRelTy>::size);
+    for (size_t i = 0; i < size; ++i) {
+      rt->table.push_back(ELFRelocTy::readRel(AR, i));
+    }
+
+  } else {
+    rsl_assert(sh->getEntrySize() == TypeTraits<ELFRelocRelaTy>::size);
+    for (size_t i = 0; i < size; ++i) {
+      rt->table.push_back(ELFRelocTy::readRela(AR, i));
+    }
+  }
+
+  if (!AR) {
+    // Unable to read the table.
+    return 0;
+  }
+
+  return rt.take();
+}
+
+template <unsigned Bitwidth>
+size_t ELFSectionRelTable<Bitwidth>::
+getMaxNumStubs(ELFObjectTy const *obj) const {
+  switch (obj->getHeader()->getMachine()) {
+  case EM_ARM:
+    {
+      std::set<uint32_t> sym_index_set;
+
+      for (size_t i = 0; i < size(); ++i) {
+        ELFRelocTy *rel = table[i];
+
+        switch (rel->getType()) {
+        case R_ARM_CALL:
+        case R_ARM_THM_CALL:
+        case R_ARM_JUMP24:
+        case R_ARM_THM_JUMP24:
+          sym_index_set.insert(rel->getSymTabIndex());
+          break;
+        }
+      }
+
+      return sym_index_set.size();
+    }
+
+  case EM_MIPS:
+    {
+      std::set<uint32_t> sym_index_set;
+
+      for (size_t i = 0; i < size(); ++i) {
+        ELFRelocTy *rel = table[i];
+
+        if (rel->getType() == R_MIPS_26) {
+          sym_index_set.insert(rel->getSymTabIndex());
+        }
+      }
+
+      return sym_index_set.size();
+    }
+
+  case EM_386:
+  case EM_X86_64:
+    return 0;
+
+  default:
+    rsl_assert(0 && "Only support ARM, MIPS, X86, and X86_64 relocation.");
+    return 0;
+  }
+}
+
+#endif // ELF_SECTION_REL_TABLE_HXX
diff --git a/driver/linkloader/include/impl/ELFSectionStrTab.hxx b/driver/linkloader/include/impl/ELFSectionStrTab.hxx
new file mode 100644
index 0000000..4e9eb4e
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFSectionStrTab.hxx
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_STR_TAB_HXX
+#define ELF_SECTION_STR_TAB_HXX
+
+#include "utils/helper.h"
+#include "utils/raw_ostream.h"
+
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/Support/Format.h>
+#include <llvm/Support/raw_ostream.h>
+
+template <unsigned Bitwidth>
+template <typename Archiver>
+ELFSectionStrTab<Bitwidth> *
+ELFSectionStrTab<Bitwidth>::read(Archiver &AR,
+                                 ELFSectionHeaderTy const *sh) {
+
+  llvm::OwningPtr<ELFSectionStrTab> st(new ELFSectionStrTab());
+  st->buf.resize(sh->getSize());
+
+  // Save section_header
+  st->section_header = sh;
+
+  AR.seek(sh->getOffset(), true);
+  AR.prologue(sh->getSize());
+  AR.readBytes(&*st->buf.begin(), sh->getSize());
+  AR.epilogue(sh->getSize());
+
+  if (!AR) {
+    // Unable to read the string table.
+    return 0;
+  }
+
+  return st.take();
+}
+
+template <unsigned Bitwidth>
+void ELFSectionStrTab<Bitwidth>::print() const {
+  using namespace llvm;
+
+  out() << '\n' << fillformat('=', 79) << '\n';
+  out().changeColor(raw_ostream::WHITE, true);
+  out() << "ELF String Table: " << this->section_header->getName() << '\n';
+  out().resetColor();
+  out() << fillformat('-', 79) << '\n';
+
+  dump_hex((unsigned char const *)&*buf.begin(), buf.size(), 0, buf.size());
+
+  out() << fillformat('=', 79) << '\n';
+}
+
+#endif // ELF_SECTION_STR_TAB_HXX
diff --git a/driver/linkloader/include/impl/ELFSectionSymTab.hxx b/driver/linkloader/include/impl/ELFSectionSymTab.hxx
new file mode 100644
index 0000000..b179383
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFSectionSymTab.hxx
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2011, 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 ELF_SECTION_SYM_TAB_HXX
+#define ELF_SECTION_SYM_TAB_HXX
+
+#include "ELFSectionHeader.h"
+#include "ELFSymbol.h"
+#include "utils/rsl_assert.h"
+
+template <unsigned Bitwidth>
+ELFSectionSymTab<Bitwidth>::~ELFSectionSymTab() {
+  for (size_t i = 0; i < table.size(); ++i) {
+    delete table[i];
+  }
+}
+
+template <unsigned Bitwidth>
+size_t ELFSectionSymTab<Bitwidth>::getFuncCount() const {
+  size_t result = 0;
+  for (size_t i = 0; i < table.size(); ++i) {
+    if (table[i] && table[i]->isConcreteFunc()) {
+      result++;
+    }
+  }
+  return result;
+}
+
+template <unsigned Bitwidth>
+inline size_t ELFSectionSymTab<Bitwidth>::getExternFuncCount() const {
+  size_t result = 0;
+  for (size_t i = 0; i < table.size(); ++i) {
+    if (table[i] && table[i]->isExternFunc()) {
+      result++;
+    }
+  }
+  return result;
+}
+
+template <unsigned Bitwidth>
+inline void ELFSectionSymTab<Bitwidth>::buildNameMap() {
+  for (size_t i = 0; i < table.size(); ++i) {
+    ELFSymbolTy *symbol = table[i];
+    if ( symbol ) {
+      name_map[symbol->getName()] = symbol;
+    }
+  }
+}
+
+template <unsigned Bitwidth>
+inline ELFSymbol<Bitwidth> const *
+ELFSectionSymTab<Bitwidth>::getByName(std::string const &name) const {
+  typename llvm::StringMap<ELFSymbolTy *>::const_iterator symbol =
+    name_map.find(name);
+  if (symbol == name_map.end()) {
+    return NULL;
+  }
+  return symbol->getValue();
+}
+
+template <unsigned Bitwidth>
+inline void
+ELFSectionSymTab<Bitwidth>::getFuncNameList(size_t size,
+                                            char const **list) const {
+  for (size_t i = 0, j = 0; i < table.size() && j < size; ++i) {
+    if (table[i] && table[i]->isConcreteFunc()) {
+      list[j++] = table[i]->getName();
+    }
+  }
+}
+
+template <unsigned Bitwidth>
+template <typename Archiver>
+ELFSectionSymTab<Bitwidth> *
+ELFSectionSymTab<Bitwidth>::read(Archiver &AR,
+                                 ELFObjectTy *owner,
+                                 ELFSectionHeaderTy const *sh) {
+
+  llvm::OwningPtr<ELFSectionSymTabTy> st(new ELFSectionSymTabTy());
+
+  // Assert that entry size will be the same as standard.
+  rsl_assert(sh->getEntrySize() == TypeTraits<ELFSymbolTy>::size);
+
+  // Seek to the start of symbol table
+  AR.seek(sh->getOffset(), true);
+
+  // Read all symbol table entry
+  size_t size = sh->getSize() / sh->getEntrySize();
+  for (size_t i = 0; i < size; ++i) {
+    st->table.push_back(ELFSymbolTy::read(AR, owner, i));
+  }
+
+  if (!AR) {
+    // Unable to read the table.
+    return 0;
+  }
+
+  return st.take();
+}
+
+template <unsigned Bitwidth>
+void ELFSectionSymTab<Bitwidth>::print() const {
+  using namespace llvm;
+
+  out() << '\n' << fillformat('=', 79) << '\n';
+  out().changeColor(raw_ostream::WHITE, true);
+  out() << "Symbol Table" << '\n';
+  out().resetColor();
+
+  for (size_t i = 0; i < table.size(); ++i) {
+    table[i]->print();
+  }
+
+  out() << fillformat('=', 79) << '\n';
+}
+
+#endif // ELF_SECTION_SYM_TAB_HXX
diff --git a/driver/linkloader/include/impl/ELFSymbol.hxx b/driver/linkloader/include/impl/ELFSymbol.hxx
new file mode 100644
index 0000000..b3c6087
--- /dev/null
+++ b/driver/linkloader/include/impl/ELFSymbol.hxx
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2011, 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 ELF_SYMBOL_HXX
+#define ELF_SYMBOL_HXX
+
+#include "ELFSectionHeaderTable.h"
+#include "ELFSection.h"
+#include "ELFSectionStrTab.h"
+
+#include "ELFObject.h"
+#include "ELFSectionHeaderTable.h"
+#include "ELFSectionProgBits.h"
+#include "ELFSectionNoBits.h"
+
+#include "utils/rsl_assert.h"
+#include "ELF.h"
+
+template <unsigned Bitwidth>
+inline char const *ELFSymbol_CRTP<Bitwidth>::getName() const {
+  ELFSectionHeaderTableTy const &shtab = *owner->getSectionHeaderTable();
+  size_t const index = shtab.getByName(std::string(".strtab"))->getIndex();
+  ELFSectionTy const *section = owner->getSectionByIndex(index);
+  ELFSectionStrTabTy const &strtab =
+    *static_cast<ELFSectionStrTabTy const *>(section);
+  return strtab[getNameIndex()];
+}
+
+template <unsigned Bitwidth>
+template <typename Archiver>
+inline ELFSymbol<Bitwidth> *
+ELFSymbol_CRTP<Bitwidth>::read(Archiver &AR,
+                               ELFObjectTy const *owner,
+                               size_t index) {
+  if (!AR) {
+    // Archiver is in bad state before calling read function.
+    // Return NULL and do nothing.
+    return 0;
+  }
+
+  llvm::OwningPtr<ELFSymbolTy> sh(new ELFSymbolTy());
+
+  if (!sh->serialize(AR)) {
+    // Unable to read the structure.  Return NULL.
+    return 0;
+  }
+
+  if (!sh->isValid()) {
+    // SymTabEntry read from archiver is not valid.  Return NULL.
+    return 0;
+  }
+
+  // Set the section header index
+  sh->index = index;
+
+  // Set the owner elf object
+  sh->owner = owner;
+
+  return sh.take();
+}
+
+template <unsigned Bitwidth>
+inline void ELFSymbol_CRTP<Bitwidth>::print(bool shouldPrintHeader) const {
+  using namespace llvm;
+
+  if (shouldPrintHeader) {
+    out() << '\n' << fillformat('=', 79) << '\n';
+    out().changeColor(raw_ostream::WHITE, true);
+    out() << "ELF Symbol Table Entry "
+          << this->getIndex() << '\n';
+    out().resetColor();
+    out() << fillformat('-', 79) << '\n';
+  } else {
+    out() << fillformat('-', 79) << '\n';
+    out().changeColor(raw_ostream::YELLOW, true);
+    out() << "ELF Symbol Table Entry "
+          << this->getIndex() << " : " << '\n';
+    out().resetColor();
+  }
+
+#define PRINT_LINT(title, value) \
+  out() << format("  %-11s : ", (char const *)(title)) << (value) << '\n'
+  PRINT_LINT("Name",        getName()                                    );
+  PRINT_LINT("Type",        getTypeStr(getType())                        );
+  PRINT_LINT("Bind",        getBindingAttributeStr(getBindingAttribute()));
+  PRINT_LINT("Visibility",  getVisibilityStr(getVisibility())            );
+  PRINT_LINT("Shtab Index", getSectionIndex()                            );
+  PRINT_LINT("Value",       getValue()                                   );
+  PRINT_LINT("Size",        getSize()                                    );
+#undef PRINT_LINT
+
+// TODO: Horizontal type or vertical type can use option to decide.
+#if 0
+  using namespace term::color;
+  using namespace std;
+
+  cout << setw(20) << getName() <<
+          setw(10) << getTypeStr(getType()) <<
+          setw(10) << getBindingAttributeStr(getBindingAttribute()) <<
+          setw(15) << getVisibilityStr(getVisibility()) <<
+          setw(10) << getSectionIndex() <<
+          setw(7) << getValue() <<
+          setw(7) << getSize() <<
+          endl;
+#endif
+}
+
+template <unsigned Bitwidth>
+void *ELFSymbol_CRTP<Bitwidth>::getAddress(int machine, bool autoAlloc) const {
+  if (my_addr != 0) {
+    return my_addr;
+  }
+  size_t idx = (size_t)getSectionIndex();
+  switch (getType()) {
+    default:
+      break;
+
+    case STT_OBJECT:
+      switch (idx) {
+        default:
+          {
+            ELFSectionHeaderTableTy const *header =
+              owner->getSectionHeaderTable();
+
+            unsigned section_type = (*header)[idx]->getType();
+
+            rsl_assert((section_type == SHT_PROGBITS ||
+                        section_type == SHT_NOBITS) &&
+                       "STT_OBJECT with not BITS section.");
+
+            if (section_type == SHT_NOBITS) {
+              // FIXME(logan): This is a workaround for .lcomm directives
+              // bug of LLVM ARM MC code generator.  Remove this when the
+              // LLVM bug is fixed.
+
+              size_t align = 16;
+
+              my_addr = const_cast<ELFObjectTy *>(owner)->
+                allocateSHNCommonData((size_t)getSize(), align);
+
+              if (!my_addr) {
+                rsl_assert(0 && "Unable to allocate memory for SHN_COMMON.");
+                abort();
+              }
+            } else {
+              ELFSectionTy const *sec = owner->getSectionByIndex(idx);
+              rsl_assert(sec != 0 && "STT_OBJECT with null section.");
+
+              ELFSectionBitsTy const &st =
+                static_cast<ELFSectionBitsTy const &>(*sec);
+              my_addr =const_cast<unsigned char *>(&st[0] + (off_t)getValue());
+            }
+          }
+          break;
+
+        case SHN_COMMON:
+          {
+            if (!autoAlloc) {
+              return NULL;
+            }
+#if 0
+#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
+            if (posix_memalign(&my_addr,
+                               std::max((size_t)getValue(), sizeof(void*)),
+                               (size_t)getSize()) != 0) {
+              rsl_assert(0 && "posix_memalign failed.");
+            }
+#else
+            my_addr = memalign(std::max((size_t)getValue(), sizeof(void *)),
+                               (size_t)getSize());
+
+            rsl_assert(my_addr != NULL && "memalign failed.");
+#endif
+            if (my_addr) {
+              memset(my_addr, '\0', getSize());
+            }
+#else
+            size_t align = (size_t)getValue();
+            my_addr = const_cast<ELFObjectTy *>(owner)->
+                          allocateSHNCommonData((size_t)getSize(), align);
+            if (!my_addr) {
+              rsl_assert(0 && "Unable to allocate memory for SHN_COMMON.");
+              abort();
+            }
+#endif
+          }
+          break;
+
+        case SHN_UNDEF:
+          if (machine == EM_MIPS && strcmp(getName(), "_gp_disp") == 0) // OK for MIPS
+            break;
+
+        case SHN_ABS:
+        case SHN_XINDEX:
+          rsl_assert(0 && "STT_OBJECT with special st_shndx.");
+          break;
+      }
+      break;
+
+
+    case STT_FUNC:
+      switch (idx) {
+        default:
+          {
+#ifndef NDEBUG
+            ELFSectionHeaderTableTy const *header =
+              owner->getSectionHeaderTable();
+            rsl_assert((*header)[idx]->getType() == SHT_PROGBITS &&
+                   "STT_FUNC with not PROGBITS section.");
+#endif
+            ELFSectionTy const *sec = owner->getSectionByIndex(idx);
+            rsl_assert(sec != 0 && "STT_FUNC with null section.");
+
+            ELFSectionProgBitsTy const &st =
+              static_cast<ELFSectionProgBitsTy const &>(*sec);
+            my_addr = const_cast<unsigned char *>(&st[0] + (off_t)getValue());
+          }
+          break;
+
+        case SHN_ABS:
+        case SHN_COMMON:
+        case SHN_UNDEF:
+        case SHN_XINDEX:
+          rsl_assert(0 && "STT_FUNC with special st_shndx.");
+          break;
+      }
+      break;
+
+
+    case STT_SECTION:
+      switch (idx) {
+        default:
+          {
+#ifndef NDEBUG
+            ELFSectionHeaderTableTy const *header =
+              owner->getSectionHeaderTable();
+            rsl_assert(((*header)[idx]->getType() == SHT_PROGBITS ||
+                    (*header)[idx]->getType() == SHT_NOBITS) &&
+                   "STT_SECTION with not BITS section.");
+#endif
+            ELFSectionTy const *sec = owner->getSectionByIndex(idx);
+            rsl_assert(sec != 0 && "STT_SECTION with null section.");
+
+            ELFSectionBitsTy const &st =
+              static_cast<ELFSectionBitsTy const &>(*sec);
+            my_addr = const_cast<unsigned char *>(&st[0] + (off_t)getValue());
+          }
+          break;
+
+        case SHN_ABS:
+        case SHN_COMMON:
+        case SHN_UNDEF:
+        case SHN_XINDEX:
+          rsl_assert(0 && "STT_SECTION with special st_shndx.");
+          break;
+      }
+      break;
+
+    case STT_NOTYPE:
+      switch (idx) {
+        default:
+          {
+#ifndef NDEBUG
+            ELFSectionHeaderTableTy const *header =
+              owner->getSectionHeaderTable();
+            rsl_assert(((*header)[idx]->getType() == SHT_PROGBITS ||
+                    (*header)[idx]->getType() == SHT_NOBITS) &&
+                   "STT_SECTION with not BITS section.");
+#endif
+            ELFSectionTy const *sec = owner->getSectionByIndex(idx);
+            rsl_assert(sec != 0 && "STT_SECTION with null section.");
+
+            ELFSectionBitsTy const &st =
+              static_cast<ELFSectionBitsTy const &>(*sec);
+            my_addr = const_cast<unsigned char *>(&st[0] + (off_t)getValue());
+          }
+          break;
+
+        case SHN_ABS:
+        case SHN_COMMON:
+        case SHN_XINDEX:
+          rsl_assert(0 && "STT_SECTION with special st_shndx.");
+          break;
+        case SHN_UNDEF:
+          return 0;
+      }
+      break;
+      return 0;
+
+    case STT_COMMON:
+    case STT_FILE:
+    case STT_TLS:
+    case STT_LOOS:
+    case STT_HIOS:
+    case STT_LOPROC:
+    case STT_HIPROC:
+      rsl_assert(0 && "Not implement.");
+      return 0;
+  }
+  return my_addr;
+}
+
+#endif // ELF_SYMBOL_HXX
diff --git a/driver/linkloader/lib/ELFHeader.cpp b/driver/linkloader/lib/ELFHeader.cpp
new file mode 100644
index 0000000..5e21d3e
--- /dev/null
+++ b/driver/linkloader/lib/ELFHeader.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2011, 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 "ELFHeader.h"
+#include "ELF.h"
+
+char const *ELFHeaderHelperMixin::getClassStr(int clazz) {
+  switch (clazz) {
+  default:
+#define CASE_PAIR(A, B) case A: return B;
+  CASE_PAIR(ELFCLASSNONE, "Invalid class")
+  CASE_PAIR(ELFCLASS32, "32bit")
+  CASE_PAIR(ELFCLASS64, "64bit")
+#undef CASE_PAIR
+  }
+}
+
+char const *ELFHeaderHelperMixin::getEndiannessStr(int endianness) {
+  switch (endianness) {
+  default:
+#define CASE_PAIR(A, B) case A: return B;
+  CASE_PAIR(ELFDATANONE, "Invalid endianness")
+  CASE_PAIR(ELFDATA2LSB, "Little endian")
+  CASE_PAIR(ELFDATA2MSB, "Big endian")
+#undef CASE_PAIR
+  }
+}
+
+char const *ELFHeaderHelperMixin::getOSABIStr(int abi) {
+  if (abi >= 64 && abi <= 255) {
+    return "Architecture specific";
+  }
+
+  switch (abi) {
+  default: return "Unknown OS ABI";
+#define CASE_PAIR(A, B) case A: return B;
+  CASE_PAIR(ELFOSABI_NONE, "No extensions or not specified")
+  CASE_PAIR(ELFOSABI_HPUX, "HP-UX")
+  CASE_PAIR(ELFOSABI_NETBSD, "NetBSD")
+  CASE_PAIR(ELFOSABI_LINUX, "Linux")
+  CASE_PAIR(ELFOSABI_SOLARIS, "Solaris")
+  CASE_PAIR(ELFOSABI_AIX, "AIX")
+  CASE_PAIR(ELFOSABI_FREEBSD, "FreeBSD")
+  CASE_PAIR(ELFOSABI_TRU64, "Tru64")
+  CASE_PAIR(ELFOSABI_MODESTO, "Modesto")
+  CASE_PAIR(ELFOSABI_OPENBSD, "OpenBSD")
+#undef CASE_PAIR
+  }
+}
+
+char const *ELFHeaderHelperMixin::getObjectTypeStr(uint16_t type) {
+  switch (type) {
+  default: return "No file type";
+
+  case ET_REL:  return "Relocatable file";
+  case ET_EXEC: return "Executable file";
+  case ET_DYN:  return "Shared object file";
+  case ET_CORE: return "Core file";
+
+  case ET_LOOS: case ET_HIOS:
+    return "Operating system-specific";
+
+  case ET_LOPROC: case ET_HIPROC:
+    return "Processor-specific";
+  }
+}
+
+char const *ELFHeaderHelperMixin::getMachineStr(uint16_t machine) {
+  switch (machine) {
+    default: return "No machine or unknown";
+    case EM_386: return "Intel 80386 (X86)";
+    case EM_X86_64: return "AMD x86-64 architecture";
+    case EM_ARM: return "Advanced RISC Machine (ARM)";
+    case EM_MIPS: return "MIPS";
+  }
+}
+
+char const *ELFHeaderHelperMixin::getVersionStr(uint32_t version) {
+  switch (version) {
+    default: return "Invalid version";
+    case EV_CURRENT: return "Current version";
+  }
+}
diff --git a/driver/linkloader/lib/ELFSectionHeader.cpp b/driver/linkloader/lib/ELFSectionHeader.cpp
new file mode 100644
index 0000000..03930d6
--- /dev/null
+++ b/driver/linkloader/lib/ELFSectionHeader.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2011, 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 "ELFSectionHeader.h"
+#include "ELF.h"
+
+// ARM Section Header Type Definitions
+
+// TODO: These definitions are not defined in external/elfutils/libelf/
+// elf.h.  So we to this by ourself.  Maybe we should update elf.h
+// instead.
+
+#ifndef SHT_ARM_EXIDX
+#define SHT_ARM_EXIDX (SHT_LOPROC + 1)
+#endif
+
+#ifndef SHT_ARM_PREEMPTMAP
+#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2)
+#endif
+
+#ifndef SHT_ARM_ATTRIBUTES
+#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3)
+#endif
+
+char const *ELFSectionHeaderHelperMixin::getSectionTypeStr(uint32_t type) {
+  switch (type) {
+    default: return "(UNKNOWN)";
+
+#define CASE(TYPE) \
+    case SHT_##TYPE: return #TYPE;
+
+    // General section header type
+    CASE(NULL) CASE(PROGBITS) CASE(SYMTAB) CASE(STRTAB) CASE(RELA) CASE(HASH)
+    CASE(DYNAMIC) CASE(NOTE) CASE(NOBITS) CASE(REL) CASE(SHLIB)
+    CASE(DYNSYM) CASE(INIT_ARRAY) CASE(FINI_ARRAY) CASE(PREINIT_ARRAY)
+    CASE(GROUP) CASE(SYMTAB_SHNDX) CASE(LOOS) CASE(HIOS) CASE(LOPROC)
+    CASE(HIPROC) CASE(LOUSER) CASE(HIUSER)
+
+    // ARM-specific section header type
+    CASE(ARM_EXIDX) CASE(ARM_PREEMPTMAP) CASE(ARM_ATTRIBUTES)
+
+#undef CASE
+  }
+}
diff --git a/driver/linkloader/lib/ELFSymbol.cpp b/driver/linkloader/lib/ELFSymbol.cpp
new file mode 100644
index 0000000..cfdab1c
--- /dev/null
+++ b/driver/linkloader/lib/ELFSymbol.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2011, 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 "ELFSymbol.h"
+#include "ELF.h"
+
+char const *
+ELFSymbolHelperMixin::getTypeStr(uint8_t type) {
+  switch (type) {
+    default: return "(UNKNOWN)";
+
+#define CASE(TYPE) \
+    case STT_##TYPE: return #TYPE;
+
+    CASE(NOTYPE)
+    CASE(OBJECT)
+    CASE(FUNC)
+    CASE(SECTION)
+    CASE(FILE)
+    CASE(COMMON)
+    CASE(TLS)
+    CASE(LOOS)
+    CASE(HIOS)
+    CASE(LOPROC)
+    CASE(HIPROC)
+
+#undef CASE
+  }
+}
+
+char const *
+ELFSymbolHelperMixin::getBindingAttributeStr(uint8_t type) {
+  switch (type) {
+    default: return "(UNKNOWN)";
+
+#define CASE(TYPE) \
+    case STB_##TYPE: return #TYPE;
+
+    CASE(LOCAL)
+    CASE(GLOBAL)
+    CASE(WEAK)
+    CASE(LOOS)
+    CASE(HIOS)
+    CASE(LOPROC)
+    CASE(HIPROC)
+
+#undef CASE
+  }
+}
+char const *
+ELFSymbolHelperMixin::getVisibilityStr(uint8_t type) {
+  switch (type) {
+    default: return "(UNKNOWN)";
+
+#define CASE(TYPE) \
+    case STV_##TYPE: return #TYPE;
+
+    CASE(DEFAULT)
+    CASE(INTERNAL)
+    CASE(HIDDEN)
+    CASE(PROTECTED)
+
+#undef CASE
+  }
+}
diff --git a/driver/linkloader/lib/ELFTypes.cpp b/driver/linkloader/lib/ELFTypes.cpp
new file mode 100644
index 0000000..7c82eab
--- /dev/null
+++ b/driver/linkloader/lib/ELFTypes.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011, 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 "ELFTypes.h"
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/Format.h>
+
+namespace detail {
+
+#define ELF_TYPE_PRINT_OPERATOR(TYPE, FORMAT_WIDTH)                         \
+  llvm::raw_ostream &operator<<(llvm::raw_ostream &os, TYPE const &val) {   \
+    os << llvm::format("%0*x", FORMAT_WIDTH, val.value);                    \
+    return os;                                                              \
+  }
+
+  ELF_TYPE_PRINT_OPERATOR(ELF32Address, 8)
+  ELF_TYPE_PRINT_OPERATOR(ELF32Offset,  8)
+  ELF_TYPE_PRINT_OPERATOR(ELF64Address, 16)
+  ELF_TYPE_PRINT_OPERATOR(ELF64Offset,  16)
+
+#undef ELF_TYPE_PRINT_OPERATOR
+
+} // end namespace detail
diff --git a/driver/linkloader/lib/GOT.cpp b/driver/linkloader/lib/GOT.cpp
new file mode 100644
index 0000000..3f523c5
--- /dev/null
+++ b/driver/linkloader/lib/GOT.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2011, 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 <stdio.h>
+#include "GOT.h"
+
+void *got_symbol_addresses[NUM_OF_GOT_ENTRY];
+int got_symbol_indexes[NUM_OF_GOT_ENTRY];
+size_t got_symbol_count = 0;
+
+void *got_address()
+{
+  return &got_symbol_addresses[0];
+}
+
+int search_got(int symbol_index, void *addr, uint8_t bind_type)
+{
+  size_t i;
+
+  // For local symbols (R_MIPS_GOT16), we only store the high 16-bit value
+  // after adding 0x8000.
+  if (bind_type == STB_LOCAL)
+    addr = (void *)(((intptr_t)addr + 0x8000) & 0xFFFF0000);
+
+  for (i = 0; i < got_symbol_count; i++) {
+    if (got_symbol_indexes[i] == symbol_index) {
+      if (bind_type == STB_LOCAL) {
+        // Check if the value is the same for local symbols.
+        // If yes, we can reuse this entry.
+        // If not, we continue searching.
+        if (got_symbol_addresses[i] == addr) {
+          return i;
+        }
+      }
+      else {
+        // The value must be the same for global symbols .
+        rsl_assert (got_symbol_addresses[i] == addr
+                    && "MIPS GOT address error.");
+        return i;
+      }
+    }
+  }
+
+  // Cannot find this symbol with correct value, so we need to create one
+  rsl_assert (got_symbol_count < NUM_OF_GOT_ENTRY && "MIPS GOT is full.");
+  got_symbol_indexes[got_symbol_count] = symbol_index;
+  got_symbol_addresses[got_symbol_count] = addr;
+  got_symbol_count++;
+  return (got_symbol_count - 1);
+}
diff --git a/driver/linkloader/lib/MemChunk.cpp b/driver/linkloader/lib/MemChunk.cpp
new file mode 100644
index 0000000..24dcf8e
--- /dev/null
+++ b/driver/linkloader/lib/MemChunk.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2011, 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 "MemChunk.h"
+
+#include "utils/flush_cpu_cache.h"
+#include "utils/helper.h"
+
+#include <llvm/Support/raw_ostream.h>
+
+#include <sys/mman.h>
+
+#include <stdlib.h>
+
+#ifndef MAP_32BIT
+#define MAP_32BIT 0
+// Note: If the <sys/mman.h> does not come with MAP_32BIT, then we
+// define it as zero, so that it won't manipulate the flags.
+#endif
+
+//#define USE_FIXED_ADDR_MEM_CHUNK 1
+
+#if USE_FIXED_ADDR_MEM_CHUNK
+static uintptr_t StartAddr = 0x7e000000UL;
+#endif
+
+MemChunk::MemChunk() : buf((unsigned char *)MAP_FAILED), buf_size(0) {
+}
+
+MemChunk::~MemChunk() {
+  if (buf != MAP_FAILED) {
+    munmap(buf, buf_size);
+  }
+}
+
+bool MemChunk::allocate(size_t size) {
+  if (size == 0) {
+    return true;
+  }
+#if USE_FIXED_ADDR_MEM_CHUNK
+  buf = (unsigned char *)mmap((void *)StartAddr, size,
+                              PROT_READ | PROT_WRITE,
+                              MAP_PRIVATE | MAP_ANON | MAP_32BIT,
+                              -1, 0);
+#else
+  buf = (unsigned char *)mmap(0, size,
+                              PROT_READ | PROT_WRITE,
+                              MAP_PRIVATE | MAP_ANON | MAP_32BIT,
+                              -1, 0);
+#endif
+
+  if (buf == MAP_FAILED) {
+    return false;
+  }
+
+#if USE_FIXED_ADDR_MEM_CHUNK
+  StartAddr += (size + 4095) / 4096 * 4096;
+#endif
+
+  buf_size = size;
+  return true;
+}
+
+void MemChunk::print() const {
+  if (buf != MAP_FAILED) {
+    dump_hex(buf, buf_size, 0, buf_size);
+  }
+}
+
+bool MemChunk::protect(int prot) {
+  if (buf_size > 0) {
+    int ret = mprotect((void *)buf, buf_size, prot);
+    if (ret == -1) {
+      llvm::errs() << "Error: Can't mprotect.\n";
+      return false;
+    }
+
+    if (prot & PROT_EXEC) {
+      FLUSH_CPU_CACHE(buf, buf + buf_size);
+    }
+  }
+
+  return true;
+}
diff --git a/driver/linkloader/lib/StubLayout.cpp b/driver/linkloader/lib/StubLayout.cpp
new file mode 100644
index 0000000..00555ad
--- /dev/null
+++ b/driver/linkloader/lib/StubLayout.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2011, 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 "StubLayout.h"
+
+#include "utils/flush_cpu_cache.h"
+#include "utils/raw_ostream.h"
+#include "utils/rsl_assert.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+StubLayout::StubLayout() : table(NULL), count(0) {
+}
+
+void StubLayout::initStubTable(unsigned char *table_, size_t count_) {
+  table = table_;
+  count = count_;
+}
+
+void *StubLayout::allocateStub(void *addr) {
+  // Check if we have created this stub or not.
+  std::map<void *, void *>::iterator index_iter = stub_index.find(addr);
+
+  if (index_iter != stub_index.end()) {
+    return index_iter->second;
+  }
+
+  // We have to create a new stub
+  if (count == 0) {
+    // No free stub slot is available
+    return NULL;
+  }
+
+  // Initialize the stub
+  unsigned char *stub = table;
+  setStubAddress(stub, addr);
+  stub_index.insert(std::make_pair(addr, stub));
+
+  // Increase the free stub slot pointer
+  table += getUnitStubSize();
+  count--;
+
+  return stub;
+}
+
+size_t StubLayout::calcStubTableSize(size_t count) const {
+  return count * getUnitStubSize();
+}
+
+size_t StubLayoutARM::getUnitStubSize() const {
+  return 8;
+}
+
+void StubLayoutARM::setStubAddress(void *stub_, void *addr) {
+  uint8_t *stub = (uint8_t *)stub_;
+  stub[0] = 0x04; // ldr pc, [pc, #-4]
+  stub[1] = 0xf0; // ldr pc, [pc, #-4]
+  stub[2] = 0x1f; // ldr pc, [pc, #-4]
+  stub[3] = 0xe5; // ldr pc, [pc, #-4]
+
+  void **target = (void **)(stub + 4);
+  *target = addr;
+}
+
+size_t StubLayoutMIPS::getUnitStubSize() const {
+  return 16;
+}
+
+void StubLayoutMIPS::setStubAddress(void *stub_, void *addr) {
+  uint32_t addr32 = (uint32_t)(uintptr_t)addr;
+  uint16_t addr_hi16 = (addr32 >> 16) &  0xffff;
+  uint16_t addr_lo16 = addr32 & 0xffff;
+
+  uint32_t *stub = (uint32_t *)stub_;
+  stub[0] = 0x3c190000ul | addr_hi16; // lui
+  stub[1] = 0x37390000ul | addr_lo16; // ori
+  stub[2] = 0x03200008ul; // jr (jump register)
+  stub[3] = 0x00000000ul; // nop
+}
diff --git a/driver/linkloader/main.cpp b/driver/linkloader/main.cpp
new file mode 100644
index 0000000..2ead7ec
--- /dev/null
+++ b/driver/linkloader/main.cpp
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2011, 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 "ELFObject.h"
+
+#include "utils/serialize.h"
+#include "ELF.h"
+
+#include <llvm/ADT/OwningPtr.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <map>
+#include <stdio.h>
+#include <stdarg.h>
+
+using namespace std;
+
+bool open_mmap_file(char const *filename,
+                    int &fd,
+                    unsigned char const *&image,
+                    size_t &size);
+
+void close_mmap_file(int fd,
+                     unsigned char const *image,
+                     size_t size);
+
+void dump_and_run_file(unsigned char const *image, size_t size,
+                       int argc, char **argv);
+
+int main(int argc, char **argv) {
+  // Check arguments
+  if (argc < 2) {
+    llvm::errs() << "USAGE: " << argv[0] << " [ELFObjectFile] [ARGS]\n";
+    exit(EXIT_FAILURE);
+  }
+
+  // Filename from argument
+  char const *filename = argv[1];
+
+  // Open the file
+  int fd = -1;
+  unsigned char const *image = NULL;
+  size_t image_size = 0;
+
+  if (!open_mmap_file(filename, fd, image, image_size)) {
+    exit(EXIT_FAILURE);
+  }
+
+  // Dump and run the file
+  dump_and_run_file(image, image_size, argc - 1, argv + 1);
+
+  // Close the file
+  close_mmap_file(fd, image, image_size);
+
+  return EXIT_SUCCESS;
+}
+
+// FIXME: I don't like these stub as well.  However, before we implement
+// x86 64bit far jump stub, we have to ensure find_sym only returns
+// near address.
+
+int stub_printf(char const *fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  int result = vprintf(fmt, ap);
+  va_end(ap);
+  return result;
+}
+
+int stub_scanf(char const *fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  int result = vscanf(fmt, ap);
+  va_end(ap);
+  return result;
+}
+
+void stub_srand(unsigned int seed) {
+  srand(seed);
+}
+
+int stub_rand() {
+  return rand();
+}
+
+time_t stub_time(time_t *output) {
+  return time(output);
+}
+
+void *find_sym(void *context, char const *name) {
+  struct func_entry_t {
+    char const *name;
+    size_t name_len;
+    void *addr;
+  };
+
+  static func_entry_t const tab[] = {
+#define DEF(NAME, ADDR) \
+    { NAME, sizeof(NAME) - 1, (void *)(ADDR) },
+
+    DEF("printf", stub_printf)
+    DEF("scanf", stub_scanf)
+    DEF("__isoc99_scanf", stub_scanf)
+    DEF("rand", stub_rand)
+    DEF("time", stub_time)
+    DEF("srand", stub_srand)
+#undef DEF
+  };
+
+  static size_t const tab_size = sizeof(tab) / sizeof(func_entry_t);
+
+  // Note: Since our table is small, we are using trivial O(n) searching
+  // function.  For bigger table, it will be better to use binary
+  // search or hash function.
+  size_t name_len = strlen(name);
+  for (size_t i = 0; i < tab_size; ++i) {
+    if (name_len == tab[i].name_len && strcmp(name, tab[i].name) == 0) {
+      return tab[i].addr;
+    }
+  }
+
+  assert(0 && "Can't find symbol.");
+  return 0;
+}
+
+template <unsigned Bitwidth, typename Archiver>
+void dump_and_run_object(Archiver &AR, int argc, char **argv) {
+  llvm::OwningPtr<ELFObject<Bitwidth> > object(ELFObject<Bitwidth>::read(AR));
+
+  if (!object) {
+    llvm::errs() << "ERROR: Unable to load object\n";
+  }
+
+  object->print();
+  out().flush();
+
+  ELFSectionSymTab<Bitwidth> *symtab =
+    static_cast<ELFSectionSymTab<Bitwidth> *>(
+        object->getSectionByName(".symtab"));
+
+  object->relocate(find_sym, 0);
+  out() << "relocate finished!\n";
+  out().flush();
+
+  int machine = object->getHeader()->getMachine();
+
+  void *main_addr = symtab->getByName("main")->getAddress(machine);
+  out() << "main address: " << main_addr << "\n";
+  out().flush();
+
+  ((int (*)(int, char **))main_addr)(argc, argv);
+  fflush(stdout);
+}
+
+template <typename Archiver>
+void dump_and_run_file_from_archive(bool is32bit, Archiver &AR,
+                                    int argc, char **argv) {
+  if (is32bit) {
+    dump_and_run_object<32>(AR, argc, argv);
+  } else {
+    dump_and_run_object<64>(AR, argc, argv);
+  }
+}
+
+void dump_and_run_file(unsigned char const *image, size_t size,
+                       int argc, char **argv) {
+  if (size < EI_NIDENT) {
+    llvm::errs() << "ERROR: ELF identification corrupted.\n";
+    return;
+  }
+
+  if (image[EI_DATA] != ELFDATA2LSB && image[EI_DATA] != ELFDATA2MSB) {
+    llvm::errs() << "ERROR: Unknown endianness.\n";
+    return;
+  }
+
+  if (image[EI_CLASS] != ELFCLASS32 && image[EI_CLASS] != ELFCLASS64) {
+    llvm::errs() << "ERROR: Unknown machine class.\n";
+    return;
+  }
+
+  bool isLittleEndian = (image[EI_DATA] == ELFDATA2LSB);
+  bool is32bit = (image[EI_CLASS] == ELFCLASS32);
+
+  if (isLittleEndian) {
+    ArchiveReaderLE AR(image, size);
+    dump_and_run_file_from_archive(is32bit, AR, argc, argv);
+  } else {
+    ArchiveReaderBE AR(image, size);
+    dump_and_run_file_from_archive(is32bit, AR, argc, argv);
+  }
+}
+
+bool open_mmap_file(char const *filename,
+                    int &fd,
+                    unsigned char const *&image,
+                    size_t &size) {
+  // Query the file status
+  struct stat sb;
+  if (stat(filename, &sb) != 0) {
+    llvm::errs() << "ERROR: " << filename << " not found.\n";
+    return false;
+  }
+
+  if (!S_ISREG(sb.st_mode)) {
+    llvm::errs() << "ERROR: " << filename << " is not a regular file.\n";
+    return false;
+  }
+
+  size = (size_t)sb.st_size;
+
+  // Open the file in readonly mode
+  fd = open(filename, O_RDONLY);
+  if (fd < 0) {
+    llvm::errs() << "ERROR: Unable to open " << filename << "\n";
+    return false;
+  }
+
+  // Map the file image
+  image = static_cast<unsigned char const *>(
+    mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0));
+
+  if (image == MAP_FAILED) {
+    llvm::errs() << "ERROR: Unable to map " << filename << " to memory.\n";
+    close(fd);
+    return false;
+  }
+
+  return true;
+}
+
+void close_mmap_file(int fd,
+                     unsigned char const *image,
+                     size_t size) {
+  if (image) {
+    munmap((void *)image, size);
+  }
+
+  if (fd >= 0) {
+    close(fd);
+  }
+}
diff --git a/driver/linkloader/tests/images/clean-testcases.sh b/driver/linkloader/tests/images/clean-testcases.sh
new file mode 100755
index 0000000..1c2d0be
--- /dev/null
+++ b/driver/linkloader/tests/images/clean-testcases.sh
@@ -0,0 +1,18 @@
+#!/bin/bash -e
+
+
+# Copyright (C) 2011 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.
+
+rm -rf *.o *.bc
diff --git a/driver/linkloader/tests/images/gen-testcases.sh b/driver/linkloader/tests/images/gen-testcases.sh
new file mode 100755
index 0000000..26c7cdf
--- /dev/null
+++ b/driver/linkloader/tests/images/gen-testcases.sh
@@ -0,0 +1,41 @@
+#!/bin/bash -e
+
+
+# Copyright (C) 2011-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.
+
+
+CYAN='\033[1;36m'
+RESET='\033[m'
+
+echo -e "${CYAN}Generating bitcode ...${RESET}"
+clang -emit-llvm -std=c89 -Wall -c test.c -o test.bc
+clang -emit-llvm -std=c89 -Wall -c simple-test.c -o simple-test.bc
+clang -emit-llvm -std=c89 -Wall -c rodata-test.c -o rodata-test.bc
+
+function gen_test_cases {
+  echo -e "${CYAN}Generating for $1 ...${RESET}"
+  llc -filetype=obj -relocation-model=static -mtriple $2 $3 test.bc -o test-$1.o
+  llc -filetype=obj -relocation-model=static -mtriple $2 $3 simple-test.bc -o simple-test-$1.o
+  llc -filetype=obj -relocation-model=static -mtriple $2 $3 rodata-test.bc -o rodata-test-$1.o
+}
+
+gen_test_cases arm    armv7-none-linux-gnueabi
+gen_test_cases tegra2 armv7-none-linux-gnueabi '-mcpu=cortex-a9 -mattr=+vfp3'
+gen_test_cases thumb2 thumb-none-linux-gnueabi '-march=thumb -mattr=+thumb2'
+gen_test_cases thumb2lc thumb-none-linux-gnueabi '-mattr=+thumb2,+neonfp,+vfp3 -arm-long-calls'
+gen_test_cases thumb2lc-xoom thumb-none-linux-gnueabi '-mattr=+thumb2 -arm-long-calls'
+gen_test_cases x86_32 i686-none-linux
+gen_test_cases x86_64 x86_64-none-linux
+gen_test_cases mipsel mipsel-none-linux-gnueabi
diff --git a/driver/linkloader/tests/images/rodata-test.c b/driver/linkloader/tests/images/rodata-test.c
new file mode 100644
index 0000000..d695d01
--- /dev/null
+++ b/driver/linkloader/tests/images/rodata-test.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2011, 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<stdio.h>
+
+static char const *const test_str[] = {
+  "string 1",
+  "string 2",
+  "string 3",
+  "long long long long long long string"
+};
+
+static size_t test_str_count = sizeof(test_str) / sizeof(char const *const);
+
+int main(){
+  int i;
+  printf("test_str: %p\n", &test_str);
+  for (i = 0; i < test_str_count; ++i) {
+    printf("%p\n", test_str[i]);
+    printf("%s\n", test_str[i]);
+  }
+
+  return 0;
+}
diff --git a/driver/linkloader/tests/images/simple-test.c b/driver/linkloader/tests/images/simple-test.c
new file mode 100644
index 0000000..c59201d
--- /dev/null
+++ b/driver/linkloader/tests/images/simple-test.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011, 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 <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+int main() {
+  srand(time(NULL));
+
+  unsigned int ans = rand() % 100;
+  unsigned int user = 100;
+  unsigned int left = 0;
+  unsigned int right = 99;
+
+  printf("Hello, droid!  Let's play a number guessing game!\n");
+
+  while (user != ans) {
+    printf("Please input a number [%d-%d]:\n", left, right);
+
+    if (scanf("%u", &user) != 1) {
+      break;
+    }
+
+    if (user < left || user > right) {
+      /* Out of range, ignore this answer. */
+      continue;
+    } else if (user == ans) {
+      printf("You got it!\n");
+      break;
+    } else if (user < ans) {
+      left = user;
+    } else {
+      right = user;
+    }
+  }
+
+  return 0;
+}
diff --git a/driver/linkloader/tests/images/test.c b/driver/linkloader/tests/images/test.c
new file mode 100644
index 0000000..01b69a1
--- /dev/null
+++ b/driver/linkloader/tests/images/test.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2011, 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<stdio.h>
+static void hello_function(const char *ptr){
+        printf("%s", ptr);
+}
+int my_add(int para_x, int para_y){
+        return para_x + para_y;
+}
+int global_z_i;
+double global_z_d;
+int global_big_z_i[1000];
+double global_big_z_d[1000];
+static int global_static_z_i;
+static double global_static_z_d;
+static int global_static_big_z_i[1000];
+static double global_static_big_z_d[1000];
+int global_z_i_init = 1;
+double global_z_d_init = 1.1;
+/*extern int extern_z_i;   */
+/*extern double extern_z_d;*/
+int main(){
+        static int local_static_z_i;
+        static double local_static_z_d;
+        static int local_static_z_i_init = 2;
+        static double local_static_z_d_init = 2.2;
+        local_static_z_i = local_static_z_i_init;
+        local_static_z_d = local_static_z_d_init;
+        printf("%d %f\n", local_static_z_i, local_static_z_d);
+        printf("%d %f\n", local_static_z_i_init, local_static_z_d_init);
+        hello_function("Hello world!1\n");
+        hello_function("Hello world!2\n");
+        hello_function("Hello world!3\n");
+        global_z_i = my_add(1,2);
+        global_z_d = 3.3;
+        printf("%d %f\n", global_z_i, global_z_d);
+        global_big_z_i[100] = 4;
+        global_big_z_d[100] = 4.4;
+        printf("%d %f\n", global_big_z_i[100], global_big_z_d[100]);
+        global_static_z_i = my_add(2,1);
+        global_static_z_d = 3.3;
+        printf("%d %f\n", global_static_z_i, global_static_z_d);
+        int local_z_i = global_static_z_i = global_z_i;
+        double local_z_d = global_static_z_d = global_z_d;
+        printf("%d %f\n", local_z_i, local_z_d);
+        global_static_big_z_i[500] = 5;
+        global_static_big_z_d[500] = 5.5;
+        printf("%d %f\n", global_static_big_z_i[500], global_static_big_z_d[500]);
+        global_z_i_init = 6;
+        global_z_d_init = 6.6;
+        printf("%d %f\n", global_z_i_init, global_z_d_init);
+        /*printf("%d %f\n", extern_z_i, extern_z_d);*/
+        return 0;
+}
diff --git a/driver/linkloader/tests/stubs/arm-stub.c b/driver/linkloader/tests/stubs/arm-stub.c
new file mode 100644
index 0000000..2138f9a
--- /dev/null
+++ b/driver/linkloader/tests/stubs/arm-stub.c
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+
+// Note: The first instruction stands for ldr, which loads the data from
+// memory to the specified register.  Notice that due to the pipeline design,
+// when ldr is executed, the program will be advanced by 8.  So, to get our
+// address we should substract it by 4.
+
+uint32_t stub[] = {
+  0xe51ff004ul, // ldr pc, [pc, #-4]
+  0x00000000ul  // address
+};
+
+int test() {
+  printf("hello world!\n");
+  return 5;
+}
+
+int main() {
+  int (*f)() = (int (*)())stub;
+  stub[1] = (uint32_t)(uintptr_t)test;
+
+  printf("return = %d\n", f());
+  return EXIT_SUCCESS;
+}
diff --git a/driver/linkloader/tests/stubs/mips-stub.c b/driver/linkloader/tests/stubs/mips-stub.c
new file mode 100644
index 0000000..ff34d03
--- /dev/null
+++ b/driver/linkloader/tests/stubs/mips-stub.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+// --------------
+// Register Usage
+// --------------
+// $0       zero
+// $1       at
+// $2-$3    function return value registers
+// $4-$7    function argument registers
+// $8-$15   temporary
+// $16-$23  saved register
+// $24-$25  temporary
+// $26-$27  os kernel
+// $28      global pointer
+// $29      stack pointer
+// $30      saved register
+// $31      return addres reigster
+
+// --------------------
+// Instruction Encoding
+// --------------------
+// lui: 0011 1100 000t tttt iiii iiii iiii iiii
+// ori: 0011 01ss ssst tttt iiii iiii iiii iiii
+// jr:  0000 00ss sss0 0000 0000 0000 0000 1000
+// nop:  0000 0000 0000 0000 0000 0000 0000 0000
+
+uint32_t stub[] = {
+  0x3c190000ul,
+  0x37390000ul,
+  0x03200008ul,
+  0x00000000ul
+};
+
+int test() {
+  printf("hello world!\n");
+  return 5;
+}
+
+int main() {
+  int (*f)() = (int (*)())stub;
+  stub[0] |= (((uint32_t)(uintptr_t)test) >> 16) & 0xffff;
+  stub[1] |= (((uint32_t)(uintptr_t)test)) & 0xffff;
+
+  printf("return = %d\n", f());
+  return EXIT_SUCCESS;
+}
diff --git a/driver/linkloader/tests/stubs/stub-layout-test.cpp b/driver/linkloader/tests/stubs/stub-layout-test.cpp
new file mode 100644
index 0000000..ba07cd2
--- /dev/null
+++ b/driver/linkloader/tests/stubs/stub-layout-test.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2011, 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 <stdio.h>
+#include <stdlib.h>
+
+#include "StubLayout.h"
+
+void function1() {
+  printf("hello ");
+}
+
+void function2() {
+  printf("world!\n");
+}
+
+int main() {
+  StubLayout stubs;
+
+  void (*func1)() = (void (*)())stubs.allocateStub((void *)&function1);
+  void (*func2)() = (void (*)())stubs.allocateStub((void *)&function2);
+
+  if (!func1) {
+    fprintf(stderr, "ERROR: Unable to allocate stub for function1\n");
+    exit(EXIT_FAILURE);
+  }
+
+  if (!func2) {
+    fprintf(stderr, "ERROR: Unable to allocate stub for function2\n");
+    exit(EXIT_FAILURE);
+  }
+
+  function1();
+  function2();
+
+  func1();
+  func2();
+
+  return EXIT_SUCCESS;
+}
diff --git a/driver/linkloader/utils/flush_cpu_cache.h b/driver/linkloader/utils/flush_cpu_cache.h
new file mode 100644
index 0000000..7a269ed
--- /dev/null
+++ b/driver/linkloader/utils/flush_cpu_cache.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011, 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 FLUSH_CPU_CACHE_H
+#define FLUSH_CPU_CACHE_H
+
+#if defined(__arm__) || defined(__mips__)
+
+// Note: Though we wish to use the gcc builtin function __clear_cache to
+// invalidate the instruction cache; however, the toolchain of Android
+// has not supported it properly.  We are going to use cacheflush system
+// call to invalidate the instruction cache.
+//
+// As a side note, Dalvik VM use the same system call to invalidate the
+// instruction as well.
+
+#include <unistd.h>
+
+#define FLUSH_CPU_CACHE(BEGIN, END) \
+  cacheflush(((long)(BEGIN)), ((long)(END)), 0)
+
+#if 0 && defined(__mips__)
+
+// Note: Following code does not work with Android Toolchain, though they
+// works while using standalone mips-linux-gnu-gcc.
+
+#include <sys/cachectl.h>
+#define FLUSH_CPU_CACHE(BEGIN, END) \
+  _flush_cache(reinterpret_cast<char*>(BEGIN), END-BEGIN+1, BCACHE);
+
+#endif
+
+#else
+
+#define FLUSH_CPU_CACHE(BEGIN, END) do { } while (0)
+
+#endif
+
+#endif // FLUSH_CPU_CACHE_H
diff --git a/driver/linkloader/utils/helper.cpp b/driver/linkloader/utils/helper.cpp
new file mode 100644
index 0000000..2dce54f
--- /dev/null
+++ b/driver/linkloader/utils/helper.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2011, 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 "helper.h"
+#include "raw_ostream.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+
+using namespace llvm;
+
+void dump_hex(unsigned char const *data,
+              size_t size, size_t begin, size_t end) {
+  if (end <= begin) {
+    // Nothing to print now.  Return directly.
+    return;
+  }
+
+  size_t lower = begin & (~0xfUL);
+  size_t upper = (end & (~0xfUL)) ? end : ((end + 16UL) & (~0xfUL));
+
+  for (size_t i = lower; i < upper; i += 16) {
+    out() << format("%08x", i) << ':';
+
+    if (i < begin) {
+      out().changeColor(raw_ostream::MAGENTA);
+    }
+
+    for (size_t j = i, k = i + 16; j < k; ++j) {
+      if (j == begin) {
+        out().resetColor();
+      }
+
+      if (j == end) {
+        out().changeColor(raw_ostream::MAGENTA);
+      }
+
+      if (j < size) {
+        out() << ' ' << format("%02x", (unsigned)data[j]);
+      }
+    }
+
+    out().resetColor();
+    out() << "  ";
+
+    for (size_t j = i, k = i + 16; j < k; ++j) {
+      if (data[j] > 0x20 && data[j] < 0x7f) {
+        out() << (char)data[j];
+      } else {
+        out() << '.';
+      }
+    }
+
+    out() << '\n';
+  }
+}
diff --git a/driver/linkloader/utils/helper.h b/driver/linkloader/utils/helper.h
new file mode 100644
index 0000000..000666a
--- /dev/null
+++ b/driver/linkloader/utils/helper.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011, 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 HELPER_H
+#define HELPER_H
+
+#include <stdlib.h>
+
+extern void dump_hex(unsigned char const *data,
+                     size_t size, size_t begin, size_t end);
+
+#endif // HELPER_H
diff --git a/driver/linkloader/utils/raw_ostream.cpp b/driver/linkloader/utils/raw_ostream.cpp
new file mode 100644
index 0000000..7efd10e
--- /dev/null
+++ b/driver/linkloader/utils/raw_ostream.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2011, 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 "raw_ostream.h"
+
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/Format.h>
+#include <cstdarg>
+#include <cstring>
+
+llvm::raw_ostream &out() {
+  static llvm::raw_ostream &singleton = llvm::outs();
+  return singleton;
+}
+
+MyFormat const fillformat(char const fill_char, // Fill character.
+                          int const length,     // Fill Width.
+                          char const *format_s, // Format string.
+                          ...) {                // Format variable.
+  using namespace std;
+  struct MyFormat t_format;
+  va_list valist;
+  va_start(valist, format_s);
+  t_format.ptr = new char[length+1];
+  t_format.ptr[length] = '\0';
+  vsnprintf(t_format.ptr, length, format_s, valist);
+  int real_len = strlen(t_format.ptr);
+  int fill_len = length;
+  memmove(t_format.ptr + fill_len, t_format.ptr, real_len);
+  memset(t_format.ptr, fill_char, fill_len);
+  return t_format;
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &os, MyFormat const &mf) {
+  os << mf.ptr;
+  delete mf.ptr;
+  return os;
+}
diff --git a/driver/linkloader/utils/raw_ostream.h b/driver/linkloader/utils/raw_ostream.h
new file mode 100644
index 0000000..0f7a5be
--- /dev/null
+++ b/driver/linkloader/utils/raw_ostream.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011, 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 RAW_OSTREAM_H
+#define RAW_OSTREAM_H
+
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/Format.h>
+
+extern llvm::raw_ostream &out();
+struct MyFormat {
+  char *ptr;
+};
+extern MyFormat const fillformat(char const,        // Fill character.
+                                 int const,         // Fill Width.
+                                 char const * = "", // Format string.
+                                 ...);              // Format variable.
+extern llvm::raw_ostream &operator<<(llvm::raw_ostream &, MyFormat const &);
+
+#endif // RAW_OSTREAM_H
diff --git a/driver/linkloader/utils/rsl_assert.cpp b/driver/linkloader/utils/rsl_assert.cpp
new file mode 100644
index 0000000..cdd3207
--- /dev/null
+++ b/driver/linkloader/utils/rsl_assert.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2011, 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 "rsl_assert.h"
+
+#include <llvm/Support/raw_ostream.h>
+
+#include <stdlib.h>
+
+#if !defined(__HOST__)
+#define LOG_TAG "bcc"
+#include <cutils/log.h>
+#endif
+
+extern "C" void ASSERT_FAILED(char const *file,
+                              unsigned line,
+                              char const *expr) {
+#if defined(__HOST__)
+  llvm::errs() << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
+  llvm::errs() << "rslAssert [" << file << ":" << line << "] " << expr << "\n";
+  llvm::errs() << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
+#else
+  ALOGE("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+  ALOGE("rslAssert [%s:%d] %s\n", file, line, expr);
+  ALOGE("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+#endif
+
+  abort();
+}
diff --git a/driver/linkloader/utils/rsl_assert.h b/driver/linkloader/utils/rsl_assert.h
new file mode 100644
index 0000000..cd20b83
--- /dev/null
+++ b/driver/linkloader/utils/rsl_assert.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2011, 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 RSL_ASSERT_H
+#define RSL_ASSERT_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+extern void ASSERT_FAILED(char const *file,
+                          unsigned line,
+                          char const *expr);
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
+
+#ifdef RSL_NDEBUG
+
+#define rsl_assert(EXPR) \
+  do { } while (0)
+
+#else
+
+#define rsl_assert(EXPR)                                      \
+  do {                                                        \
+    if (!(EXPR)) {                                            \
+      ASSERT_FAILED(__FILE__, __LINE__, #EXPR);               \
+    }                                                         \
+  } while (0)
+
+#endif
+
+#endif // RSL_ASSERT_H
diff --git a/driver/linkloader/utils/serialize.h b/driver/linkloader/utils/serialize.h
new file mode 100644
index 0000000..3d15158
--- /dev/null
+++ b/driver/linkloader/utils/serialize.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2011, 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.
+ */
+
+#if !defined(SERIALIZE_H)
+#define SERIALIZE_H
+
+#include "traits.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "utils/rsl_assert.h"
+#include <string.h>
+#include <stdint.h>
+#include <stddef.h>
+
+namespace detail {
+  inline bool is_host_little_endian() {
+    unsigned long one = 0x1UL;
+    return *reinterpret_cast<unsigned char *>(&one);
+  }
+
+  inline void swap_byte_order(unsigned char (&array)[1]) {
+    // Nothing to do
+  }
+
+  inline void swap_byte_order(unsigned char (&array)[2]) {
+    std::swap(array[0], array[1]);
+  }
+
+  inline void swap_byte_order(unsigned char (&array)[4]) {
+    std::swap(array[0], array[3]);
+    std::swap(array[1], array[2]);
+  }
+
+  inline void swap_byte_order(unsigned char (&array)[8]) {
+    std::swap(array[0], array[7]);
+    std::swap(array[1], array[6]);
+    std::swap(array[2], array[5]);
+    std::swap(array[3], array[4]);
+  }
+}
+
+
+template <bool isArchiveLittleEndian>
+class ArchiveReader {
+private:
+  unsigned char const *buf_begin;
+  unsigned char const *buf_end;
+  unsigned char const *cursor;
+  unsigned char const *cursor_base;
+
+  bool good;
+
+public:
+  ArchiveReader(unsigned char const *buf = NULL, size_t size = 0)
+  : buf_begin(buf), buf_end(buf + size),
+    cursor(buf), cursor_base(NULL), good(buf != NULL) {
+  }
+
+  void prologue(size_t size) {
+    rsl_assert(cursor_base == NULL);
+    cursor_base = cursor;
+  }
+
+  void epilogue(size_t size) {
+    rsl_assert(cursor_base != NULL);
+    rsl_assert(cursor_base + size >= cursor);
+    cursor = cursor_base + size;
+    cursor_base = NULL;
+  }
+
+  void seek(off_t off, bool from_begin = false) {
+    if (from_begin) {
+      cursor = buf_begin + off;
+    } else {
+      cursor += off;
+    }
+  }
+
+  void readBytes(void *array, size_t size) {
+    if (!good || cursor + size > buf_end) {
+      good = false;
+    } else {
+      memcpy(array, cursor, size);
+    }
+  }
+
+  template <size_t size>
+  void operator&(char (&array)[size]) {
+    readBytes(array, size);
+    seek(size);
+  }
+
+  template <size_t size>
+  void operator&(unsigned char (&array)[size]) {
+    readBytes(array, size);
+    seek(size);
+  }
+
+  template <typename T>
+  void operator&(T &v) {
+    seekAlignment<T>();
+    readBytes(&v, TypeTraits<T>::size);
+    seek(TypeTraits<T>::size);
+
+    if (isArchiveLittleEndian != detail::is_host_little_endian()) {
+      detail::swap_byte_order(
+        reinterpret_cast<unsigned char (&)[TypeTraits<T>::size]>(v));
+    }
+  }
+
+  operator void const *() const {
+    return good ? this : 0;
+  }
+
+  bool operator!() const {
+    return !good;
+  }
+
+private:
+  template <typename T>
+  void seekAlignment() {
+    size_t align = TypeTraits<T>::align;
+    size_t delta = static_cast<size_t>(cursor - buf_begin) % align;
+
+    if (delta > 0) {
+      seek(align - delta);
+    }
+  }
+
+};
+
+typedef ArchiveReader<true>  ArchiveReaderLE;
+typedef ArchiveReader<false> ArchiveReaderBE;
+
+#endif // SERIALIZE_H
diff --git a/driver/linkloader/utils/traits.h b/driver/linkloader/utils/traits.h
new file mode 100644
index 0000000..df7e7f7
--- /dev/null
+++ b/driver/linkloader/utils/traits.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2011, 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 TRAITS_H
+#define TRAITS_H
+
+#include <stddef.h>
+
+template <typename Type>
+struct TypeTraits {
+private:
+  struct AlignmentTest {
+    char pending;
+    Type element;
+  };
+
+public:
+  enum { size = sizeof(Type) };
+  enum { align = offsetof(AlignmentTest, element) };
+};
+
+#define TYPE_TRAITS_SPECIALIZE(TYPE, SIZE, ALIGN) \
+template <> \
+struct TypeTraits<TYPE> { \
+  enum { size = SIZE }; \
+  enum { align = ALIGN }; \
+};
+
+#endif // TRAITS_H