Refine abcc for debuggability.

Change-Id: Ifcddc5808bc62d4a77f5031a1c17a651053e65b9
diff --git a/tests/abcc/jni/Abcc.cpp b/tests/abcc/jni/Abcc.cpp
index 300e16f..20017f0 100644
--- a/tests/abcc/jni/Abcc.cpp
+++ b/tests/abcc/jni/Abcc.cpp
@@ -21,6 +21,10 @@
 #include <stdint.h>
 #include <unistd.h>
 #include "Abcc.h"
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 using namespace abcc;
 
 TargetAbi::TargetAbi(const std::string &abi) {
@@ -46,58 +50,55 @@
 
 int BitcodeInfo::readWrapper(BitcodeCompiler &compiler) {
   int fd = open(mBCPath.c_str(), O_RDONLY);
+
   if (fd < 0) {
     return -1;
   }
 
-  unsigned char buffer[5] = {'\0', '\0', '\0', '\0', '\0'};
-  read(fd, buffer, 4);  // Skip magic number, we have checked
-  read(fd, buffer, 4);  // version
-  read(fd, buffer, 4);  // offset
-  swapEndian(buffer, 4);
-  int offset = transferBytesToNum(buffer, 4);
-  lseek(fd, 4*7, SEEK_SET);
-  offset -= 4*7;  // Useless, skip
+  unsigned char *buf, *p;
+  struct stat st;
+  int bc_offset;
 
-  while (offset > 0) {
-    read(fd, buffer, 4);
-    swapEndian(buffer, 4);
-    uint16_t length = transferBytesToNum(buffer, 2);
-    uint16_t tag = transferBytesToNum(buffer+2, 2);
-    LOGV("length: %d", length);
-    LOGV("tag: %d", tag);
-    length = (length + 3) & ~3;
+  fstat (fd, &st);
+  buf = (unsigned char *) mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+  close (fd);
 
-    unsigned char *large_buffer = (unsigned char*) malloc(length+1);
-    if (large_buffer == 0) {
-      LOGE("Cannot create buffer for wrapper field");
-      close(fd);
-      return -1;
-    }
-    large_buffer[length] = '\0';
-    int n = read(fd, large_buffer, length);
-    if (n != length) {
-      LOGE("Read wrapper field error");
-      close(fd);
-      return -1;
+  bc_offset = transferBytesToNumLe (buf+ 8, 4);
+  p = buf + 4 * 7;      // Offset to tag fields.
+
+  while (p < buf + bc_offset) {
+    uint16_t tag, length;
+
+    tag = transferBytesToNumLe (p, 2);
+    length = transferBytesToNumLe (p + 2, 2);
+    p += 4;
+    switch (tag) {
+      case 0x4002:       // Optimization Level,. e.g., 2 for -O2
+        mOptimizationLevel = transferBytesToNumLe (p, 4);
+        LOGV("Wrapper field: -O%d", mOptimizationLevel);
+        break;
+
+      case 0x5002:       // LDFLAGS string
+        LOGV("Wrapper field: %s", p);
+        if (compiler.parseLDFlags (*this, reinterpret_cast<const char *>(p)) != 0) {
+          LOGE("Cannot parse ldflags from wrapper");
+          close(fd);
+          return -1;
+        }
+        break;
+
+      case 0x4001:       // Compiler Version, e.g., 3300 for llvm-3.3.
+      case 0x5001:       // Bitcode Type, e.g., rel, shared, or exec.
+      default:
+        // Some field maybe useful, but we use wrapper to encode command line,
+        // this is not necessary for now.
+        break;
     }
 
-    if (tag == 0x5002) {
-      const char* ldflags = reinterpret_cast<char*>(large_buffer);
-      LOGV("Wrapper field: %s", ldflags);
-      if (compiler.parseLDFlags(*this, ldflags) != 0) {
-        LOGE("Cannot parse ldflags from wrapper");
-        close(fd);
-        return -1;
-      }
-    } else {
-      // Some field maybe useful, but we use wrapper to encode command line,
-      // this is not necessary for now.
-    }
-    offset -= (length + 4);
-    free(large_buffer);
-  } // while
-  close(fd);
+    p += (length + 3) & ~3;  // Data are always padding to 4-byte boundary.
+  }
+
+  munmap (buf, st.st_size);
   return 0;
 }
 
@@ -116,24 +117,17 @@
   }
 }
 
-void BitcodeInfo::swapEndian(unsigned char *buffer, size_t n) {
-  // We uses le32, so it must be LITTLE ENDIAN
-  for (size_t i = 0; i < n/2; ++i) {
-    char tmp = buffer[i];
-    buffer[i] = buffer[n-i-1];
-    buffer[n-i-1] =tmp;
-  }
-}
-
-int BitcodeInfo::transferBytesToNum(const unsigned char *buffer, size_t n) {
+// This function reads N bytes from BUFFER in little endian.
+int BitcodeInfo::transferBytesToNumLe(const unsigned char *buffer, size_t n) {
   int ret = 0;
-  for (size_t i = 0; i < n; ++i) {
-    ret = ret * 0x100 + buffer[i];
-  }
+  const unsigned char *p = buffer + n;
+
+  while (--p >= buffer)
+    ret = ret * 0x100 + *p;
+
   return ret;
 }
 
-
 BitcodeCompiler::BitcodeCompiler(const std::string &abi, const std::string &sysroot, const std::string &working_dir, const bool savetemps)
   : mAbi(abi), mSysroot(sysroot), mWorkingDir(working_dir), mRet(RET_OK), mSaveTemps(savetemps) {
   // CFlags
@@ -142,12 +136,6 @@
   mGlobalCFlags += " -filetype=obj -relocation-model=pic -code-model=small";
   mGlobalCFlags += " -use-init-array -mc-relax-all";
 
-#ifdef DEBUG
-  mGlobalCFlags += std::string(" ") + "-O0";
-#else
-  mGlobalCFlags += std::string(" ") + "-O2";
-#endif
-
   if (mAbi == TargetAbi::ARMEABI || mAbi == TargetAbi::ARMEABI_V7A)
     mGlobalCFlags += std::string(" ") + "-arm-enable-ehabi -arm-enable-ehabi-descriptors -float-abi=soft";
 
@@ -182,14 +170,19 @@
   for (std::vector<BitcodeInfo>::const_iterator i = mBitcodeFiles.begin(),
        e = mBitcodeFiles.end(); i != e; ++i) {
     const BitcodeInfo &bc = *i;
-    std::string cmd = mExecutableToolsPath[(unsigned)CMD_COMPILE];
-    cmd += " " + mGlobalCFlags;
-    cmd += " " + bc.mTargetBCPath + " -o " + bc.mObjPath;
+    std::ostringstream os;
+
+    os << mExecutableToolsPath[(unsigned)CMD_COMPILE]
+       << " " << mGlobalCFlags
+       << " -O" << bc.mOptimizationLevel
+       << " " << bc.mTargetBCPath
+       << " -o " << bc.mObjPath;
+
 #if ON_DEVICE && VERBOSE
     Timer t_llc;
     t_llc.start();
 #endif
-    runCmd(cmd, /*dump=*/true);
+    runCmd(os.str(), /*dump=*/true);
 #if ON_DEVICE && VERBOSE
     llc_usec += t_llc.stop();
 #endif
diff --git a/tests/abcc/jni/Abcc.h b/tests/abcc/jni/Abcc.h
index 8f9e779..033dc96 100644
--- a/tests/abcc/jni/Abcc.h
+++ b/tests/abcc/jni/Abcc.h
@@ -105,6 +105,7 @@
   static void dropExternalLDLibs(SONameMap &map);
 
   bool mShared;
+  int mOptimizationLevel;
   std::string mBCPath;
   std::string mTargetBCPath;
   std::string mObjPath;
@@ -115,8 +116,7 @@
   std::string mLDLibsStr; // Immutable once read in
 
 public:
-  static void swapEndian(unsigned char *buffer, size_t n);
-  static int transferBytesToNum(const unsigned char *buffer, size_t n);
+  static int transferBytesToNumLe(const unsigned char *buffer, size_t n);
 };
 
 
diff --git a/tests/abcc/jni/device/Abcc_device.cpp b/tests/abcc/jni/device/Abcc_device.cpp
index 0bdd468..ddaca36 100644
--- a/tests/abcc/jni/device/Abcc_device.cpp
+++ b/tests/abcc/jni/device/Abcc_device.cpp
@@ -128,8 +128,7 @@
     unsigned char buffer[4];
     read(fd, buffer, 4);
     close(fd);
-    BitcodeInfo::swapEndian(buffer, 4);
-    int magic = BitcodeInfo::transferBytesToNum(buffer, 4);
+    int magic = BitcodeInfo::transferBytesToNumLe(buffer, 4);
 
     if (magic != 0x0b17c0de) {
       LOGV("Found file %s magic: %x, but we need a wrapped bitcode.", full_path.c_str(), magic);