auto import from //depot/cupcake/@135843
diff --git a/tools/isprelinked/Android.mk b/tools/isprelinked/Android.mk
new file mode 100755
index 0000000..e085f29
--- /dev/null
+++ b/tools/isprelinked/Android.mk
@@ -0,0 +1,40 @@
+# Copyright 2005 The Android Open Source Project
+#
+# Android.mk for apriori 
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+ifeq ($(TARGET_ARCH),arm)
+include $(CLEAR_VARS)
+
+LOCAL_LDLIBS += -ldl
+LOCAL_CFLAGS += -O2 -g 
+LOCAL_CFLAGS += -fno-function-sections -fno-data-sections -fno-inline 
+LOCAL_CFLAGS += -Wall -Wno-unused-function #-Werror
+LOCAL_CFLAGS += -DSUPPORT_ANDROID_PRELINK_TAGS
+LOCAL_CFLAGS += -DARM_SPECIFIC_HACKS
+LOCAL_CFLAGS += -DDEBUG
+
+ifeq ($(HOST_OS),windows)
+LOCAL_LDLIBS += -lintl
+endif
+
+LOCAL_SRC_FILES := \
+	isprelinked.c \
+	debug.c \
+	prelink_info.c
+
+LOCAL_C_INCLUDES:= \
+	$(LOCAL_PATH)/ \
+	external/elfutils/lib/ \
+	external/elfutils/libelf/ \
+	external/elfutils/libebl/ \
+	external/elfcopy/
+
+LOCAL_STATIC_LIBRARIES := libelfcopy libelf libebl libebl_arm #dl
+
+LOCAL_MODULE := isprelinked
+
+include $(BUILD_HOST_EXECUTABLE)
+endif #TARGET_ARCH==arm
diff --git a/tools/isprelinked/common.h b/tools/isprelinked/common.h
new file mode 100644
index 0000000..f5d9d2e
--- /dev/null
+++ b/tools/isprelinked/common.h
@@ -0,0 +1,28 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <libelf.h>
+#include <elf.h>
+
+#define unlikely(expr) __builtin_expect (expr, 0)
+#define likely(expr)   __builtin_expect (expr, 1)
+
+#define MIN(a,b) ((a)<(b)?(a):(b)) /* no side effects in arguments allowed! */
+
+static inline int is_host_little(void)
+{
+    short val = 0x10;
+    return ((char *)&val)[0] != 0;
+}
+
+static inline long switch_endianness(long val)
+{
+	long newval;
+	((char *)&newval)[3] = ((char *)&val)[0];
+	((char *)&newval)[2] = ((char *)&val)[1];
+	((char *)&newval)[1] = ((char *)&val)[2];
+	((char *)&newval)[0] = ((char *)&val)[3];
+	return newval;
+}
+
+#endif/*COMMON_H*/
diff --git a/tools/isprelinked/debug.c b/tools/isprelinked/debug.c
new file mode 100644
index 0000000..6066543
--- /dev/null
+++ b/tools/isprelinked/debug.c
@@ -0,0 +1,37 @@
+#include <debug.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define NUM_COLS  (32)
+
+int dump_hex_buffer(FILE *s, void *b, size_t len, size_t elsize) {
+    int num_nonprintable = 0;
+    int i, last;
+    char *pchr = (char *)b;
+    fputc('\n', s);
+    for (i = last = 0; i < len; i++) {
+        if (!elsize) {
+            if (i && !(i % 4)) fprintf(s, " ");
+            if (i && !(i % 8)) fprintf(s, " ");
+        } else {
+            if (i && !(i % elsize)) fprintf(s, " ");
+        }
+
+        if (i && !(i % NUM_COLS)) {
+            while (last < i) {
+                if (isprint(pchr[last]))
+                    fputc(pchr[last], s);
+                else {
+                    fputc('.', s); 
+                    num_nonprintable++;
+                }
+                last++;
+            }
+            fprintf(s, " (%d)\n", i);
+        }
+        fprintf(s, "%02x", (unsigned char)pchr[i]);
+    }
+    if (i && (i % NUM_COLS)) fputs("\n", s);
+    return num_nonprintable;
+}
+
diff --git a/tools/isprelinked/debug.h b/tools/isprelinked/debug.h
new file mode 100644
index 0000000..3996898
--- /dev/null
+++ b/tools/isprelinked/debug.h
@@ -0,0 +1,88 @@
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <common.h>
+
+#ifdef DEBUG
+
+    #define FAILIF(cond, msg...) do {                        \
+	if (unlikely(cond)) {                                \
+        fprintf(stderr, "%s(%d): ", __FILE__, __LINE__); \
+		fprintf(stderr, ##msg);                          \
+		exit(1);                                         \
+	}                                                    \
+} while(0)
+
+/* Debug enabled */
+    #define ASSERT(x) do {                                \
+	if (unlikely(!(x))) {                             \
+		fprintf(stderr,                               \
+				"ASSERTION FAILURE %s:%d: [%s]\n",    \
+				__FILE__, __LINE__, #x);              \
+		exit(1);                                      \
+	}                                                 \
+} while(0)
+
+#else
+
+    #define FAILIF(cond, msg...) do { \
+	if (unlikely(cond)) {         \
+		fprintf(stderr, ##msg);   \
+		exit(1);                  \
+	}                             \
+} while(0)
+
+/* No debug */
+    #define ASSERT(x)   do { } while(0)
+
+#endif/* DEBUG */
+
+#define FAILIF_LIBELF(cond, function) \
+    FAILIF(cond, "%s(): %s\n", #function, elf_errmsg(elf_errno()));
+
+static inline void *MALLOC(unsigned int size) {
+    void *m = malloc(size);
+    FAILIF(NULL == m, "malloc(%d) failed!\n", size);
+    return m;
+}
+
+static inline void *CALLOC(unsigned int num_entries, unsigned int entry_size) {
+    void *m = calloc(num_entries, entry_size);
+    FAILIF(NULL == m, "calloc(%d, %d) failed!\n", num_entries, entry_size);
+    return m;
+}
+
+static inline void *REALLOC(void *ptr, unsigned int size) {
+    void *m = realloc(ptr, size);
+    FAILIF(NULL == m, "realloc(%p, %d) failed!\n", ptr, size);
+    return m;
+}
+
+static inline void FREE(void *ptr) {
+    free(ptr);
+}
+
+static inline void FREEIF(void *ptr) {
+    if (ptr) FREE(ptr);
+}
+
+#define PRINT(x...)  do {                             \
+    extern int quiet_flag;                            \
+    if(likely(!quiet_flag))                           \
+        fprintf(stdout, ##x);                         \
+} while(0)
+
+#define ERROR PRINT
+
+#define INFO(x...)  do {                              \
+    extern int verbose_flag;                          \
+    if(unlikely(verbose_flag))                        \
+        fprintf(stdout, ##x);                         \
+} while(0)
+
+/* Prints a hex and ASCII dump of the selected buffer to the selected stream. */
+int dump_hex_buffer(FILE *s, void *b, size_t l, size_t elsize);
+
+#endif/*DEBUG_H*/
diff --git a/tools/isprelinked/isprelinked.c b/tools/isprelinked/isprelinked.c
new file mode 100644
index 0000000..c677e39
--- /dev/null
+++ b/tools/isprelinked/isprelinked.c
@@ -0,0 +1,89 @@
+/* TODO:
+   1. check the ARM EABI version--this works for versions 1 and 2.
+   2. use a more-intelligent approach to finding the symbol table, symbol-string
+      table, and the .dynamic section.
+   3. fix the determination of the host and ELF-file endianness
+   4. write the help screen
+*/
+
+#include <stdio.h>
+#include <common.h>
+#include <debug.h>
+#include <libelf.h>
+#include <libebl.h>
+#ifdef ARM_SPECIFIC_HACKS
+    #include <libebl_arm.h>
+#endif/*ARM_SPECIFIC_HACKS*/
+#include <elf.h>
+#include <gelf.h>
+#include <string.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <rangesort.h>
+#include <prelink_info.h>
+#include <libgen.h>
+
+
+/* Flag set by --verbose.  This variable is global as it is accessed by the
+   macro INFO() in multiple compilation unites. */
+int verbose_flag = 0;
+/* Flag set by --quiet.  This variable is global as it is accessed by the
+   macro PRINT() in multiple compilation unites. */
+int quiet_flag = 0;
+
+int main(int argc, char **argv) {
+
+    argc--, argv++;
+    if (!argc)
+        return 0;
+
+    /* Check to see whether the ELF library is current. */
+    FAILIF (elf_version(EV_CURRENT) == EV_NONE, "libelf is out of date!\n");
+
+    const char *filename;
+    for (; argc; argc--) {
+        filename = *argv++;
+
+        Elf *elf;
+        GElf_Ehdr elf_hdr;
+        int fd; 
+        int prelinked;
+        long prelink_addr = 0;
+
+        INFO("Processing file [%s]\n", filename);
+
+        fd = open(filename, O_RDONLY);
+        FAILIF(fd < 0, "open(%d): %s (%d).\n", 
+               filename,
+               strerror(errno),
+               errno);
+
+        elf = elf_begin(fd, ELF_C_READ_MMAP_PRIVATE, NULL);
+        FAILIF_LIBELF(elf == NULL, elf_begin);
+
+        FAILIF_LIBELF(0 == gelf_getehdr(elf, &elf_hdr), 
+                      gelf_getehdr);
+
+#ifdef SUPPORT_ANDROID_PRELINK_TAGS
+        prelinked = check_prelinked(filename, elf_hdr.e_ident[EI_DATA] == ELFDATA2LSB, 
+                                    &prelink_addr);
+#else
+        #error 'SUPPORT_ANDROID_PRELINK_TAGS is not defined!'
+#endif
+
+        if (prelinked)
+            PRINT("%s: 0x%08x\n", filename, prelink_addr);
+        else
+            PRINT("%s: not prelinked\n", filename);
+
+        FAILIF_LIBELF(elf_end(elf), elf_end);
+        close(fd);
+    }
+    
+    return 0;
+} 
+
diff --git a/tools/isprelinked/prelink_info.c b/tools/isprelinked/prelink_info.c
new file mode 100644
index 0000000..21b1519
--- /dev/null
+++ b/tools/isprelinked/prelink_info.c
@@ -0,0 +1,71 @@
+#ifdef SUPPORT_ANDROID_PRELINK_TAGS
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <prelink_info.h>
+#include <debug.h>
+#include <common.h>
+
+typedef struct {
+	long mmap_addr;
+	char tag[4]; /* 'P', 'R', 'E', ' ' */
+} prelink_info_t __attribute__((packed));
+
+static inline void set_prelink(long *prelink_addr, 
+							   int elf_little,
+							   prelink_info_t *info)
+{
+    FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t));
+	if (prelink_addr) {
+		if (!(elf_little ^ is_host_little())) {
+			/* Same endianness */
+			*prelink_addr = info->mmap_addr;
+		}
+		else {
+			/* Different endianness */
+			*prelink_addr = switch_endianness(info->mmap_addr);
+		}
+	}
+}
+
+int check_prelinked(const char *fname, int elf_little, long *prelink_addr)
+{
+    FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t));
+	int fd = open(fname, O_RDONLY);
+	FAILIF(fd < 0, "open(%s, O_RDONLY): %s (%d)!\n",
+		   fname, strerror(errno), errno);
+	off_t end = lseek(fd, 0, SEEK_END);
+
+    int nr = sizeof(prelink_info_t);
+
+    off_t sz = lseek(fd, -nr, SEEK_CUR);
+	ASSERT((long)(end - sz) == (long)nr);
+	FAILIF(sz == (off_t)-1, 
+		   "lseek(%d, 0, SEEK_END): %s (%d)!\n", 
+		   fd, strerror(errno), errno);
+
+	prelink_info_t info;
+	int num_read = read(fd, &info, nr);
+	FAILIF(num_read < 0, 
+		   "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
+		   fd, strerror(errno), errno);
+	FAILIF(num_read != sizeof(info),
+		   "read(%d, &info, sizeof(prelink_info_t)): did not read %d bytes as "
+		   "expected (read %d)!\n",
+		   fd, sizeof(info), num_read);
+
+	int prelinked = 0;
+	if (!strncmp(info.tag, "PRE ", 4)) {
+		set_prelink(prelink_addr, elf_little, &info);
+		prelinked = 1;
+	}
+	FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
+	return prelinked;
+}
+
+#endif /*SUPPORT_ANDROID_PRELINK_TAGS*/
diff --git a/tools/isprelinked/prelink_info.h b/tools/isprelinked/prelink_info.h
new file mode 100644
index 0000000..afc03e9
--- /dev/null
+++ b/tools/isprelinked/prelink_info.h
@@ -0,0 +1,8 @@
+#ifndef PRELINK_INFO_H
+#define PRELINK_INFO_H
+#ifdef SUPPORT_ANDROID_PRELINK_TAGS
+
+int check_prelinked(const char *fname, int elf_little, long *prelink_addr);
+
+#endif
+#endif/*PRELINK_INFO_H*/