Merge "base: Avoid compilation error when compiled with -Wdangling-else." into nyc-dev
diff --git a/base/include/android-base/thread_annotations.h b/base/include/android-base/thread_annotations.h
new file mode 100644
index 0000000..90979df
--- /dev/null
+++ b/base/include/android-base/thread_annotations.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 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 UTILS_THREAD_ANNOTATIONS_H
+#define UTILS_THREAD_ANNOTATIONS_H
+
+#if defined(__SUPPORT_TS_ANNOTATION__) || defined(__clang__)
+#define THREAD_ANNOTATION_ATTRIBUTE__(x)   __attribute__((x))
+#else
+#define THREAD_ANNOTATION_ATTRIBUTE__(x)   // no-op
+#endif
+
+#define CAPABILITY(x) \
+      THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
+
+#define SCOPED_CAPABILITY \
+      THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
+
+#define GUARDED_BY(x) \
+      THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
+
+#define PT_GUARDED_BY(x) \
+      THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
+
+#define ACQUIRED_BEFORE(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
+
+#define ACQUIRED_AFTER(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
+
+#define REQUIRES(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
+
+#define REQUIRES_SHARED(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
+
+#define ACQUIRE(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
+
+#define ACQUIRE_SHARED(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
+
+#define RELEASE(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
+
+#define RELEASE_SHARED(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
+
+#define TRY_ACQUIRE(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
+
+#define TRY_ACQUIRE_SHARED(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
+
+#define EXCLUDES(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
+
+#define ASSERT_CAPABILITY(x) \
+      THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
+
+#define ASSERT_SHARED_CAPABILITY(x) \
+      THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
+
+#define RETURN_CAPABILITY(x) \
+      THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
+
+#define NO_THREAD_SAFETY_ANALYSIS \
+      THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
+
+#endif  // UTILS_THREAD_ANNOTATIONS_H
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index ee56a5e..d5a7e06 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -86,18 +86,34 @@
 libbacktrace_offline_src_files := \
 	BacktraceOffline.cpp \
 
+# Use shared llvm library on device to save space.
 libbacktrace_offline_shared_libraries := \
 	libbacktrace \
+	libbase \
 	liblog \
 	libunwind \
-
-# Use shared llvm library on device to save space.
-libbacktrace_offline_shared_libraries_target := \
+	libutils \
 	libLLVM \
 
+libbacktrace_offline_static_libraries := \
+	libziparchive \
+	libz \
+
+module := libbacktrace_offline
+build_type := target
+build_target := SHARED_LIBRARY
+include $(LOCAL_PATH)/Android.build.mk
+
+libbacktrace_offline_shared_libraries := \
+	libbacktrace \
+	libbase \
+	liblog \
+	libunwind \
+	libziparchive-host \
+
 # Use static llvm libraries on host to remove dependency on 32-bit llvm shared library
 # which is not included in the prebuilt.
-libbacktrace_offline_static_libraries_host := \
+libbacktrace_offline_static_libraries := \
 	libLLVMObject \
 	libLLVMBitReader \
 	libLLVMMC \
@@ -106,10 +122,6 @@
 	libLLVMSupport \
 
 module := libbacktrace_offline
-module_tag := optional
-build_type := target
-build_target := SHARED_LIBRARY
-include $(LOCAL_PATH)/Android.build.mk
 build_type := host
 libbacktrace_multilib := both
 include $(LOCAL_PATH)/Android.build.mk
diff --git a/libbacktrace/BacktraceOffline.cpp b/libbacktrace/BacktraceOffline.cpp
index dc3ed67..9a4f622 100644
--- a/libbacktrace/BacktraceOffline.cpp
+++ b/libbacktrace/BacktraceOffline.cpp
@@ -29,11 +29,14 @@
 #include <ucontext.h>
 #include <unistd.h>
 
+#include <memory>
 #include <string>
 #include <vector>
 
+#include <android-base/file.h>
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
+#include <ziparchive/zip_archive.h>
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wunused-parameter"
@@ -641,15 +644,103 @@
   return memcmp(buf, elf_magic, 4) == 0;
 }
 
+static bool IsValidApkPath(const std::string& apk_path) {
+  static const char zip_preamble[] = {0x50, 0x4b, 0x03, 0x04};
+  struct stat st;
+  if (stat(apk_path.c_str(), &st) != 0 || !S_ISREG(st.st_mode)) {
+    return false;
+  }
+  FILE* fp = fopen(apk_path.c_str(), "reb");
+  if (fp == nullptr) {
+    return false;
+  }
+  char buf[4];
+  if (fread(buf, 4, 1, fp) != 1) {
+    fclose(fp);
+    return false;
+  }
+  fclose(fp);
+  return memcmp(buf, zip_preamble, 4) == 0;
+}
+
+class ScopedZiparchiveHandle {
+ public:
+  ScopedZiparchiveHandle(ZipArchiveHandle handle) : handle_(handle) {
+  }
+
+  ~ScopedZiparchiveHandle() {
+    CloseArchive(handle_);
+  }
+
+ private:
+  ZipArchiveHandle handle_;
+};
+
+llvm::object::OwningBinary<llvm::object::Binary> OpenEmbeddedElfFile(const std::string& filename) {
+  llvm::object::OwningBinary<llvm::object::Binary> nothing;
+  size_t pos = filename.find("!/");
+  if (pos == std::string::npos) {
+    return nothing;
+  }
+  std::string apk_file = filename.substr(0, pos);
+  std::string elf_file = filename.substr(pos + 2);
+  if (!IsValidApkPath(apk_file)) {
+    BACK_LOGW("%s is not a valid apk file", apk_file.c_str());
+    return nothing;
+  }
+  ZipArchiveHandle handle;
+  int32_t ret_code = OpenArchive(apk_file.c_str(), &handle);
+  if (ret_code != 0) {
+    CloseArchive(handle);
+    BACK_LOGW("failed to open archive %s: %s", apk_file.c_str(), ErrorCodeString(ret_code));
+    return nothing;
+  }
+  ScopedZiparchiveHandle scoped_handle(handle);
+  ZipEntry zentry;
+  ret_code = FindEntry(handle, ZipString(elf_file.c_str()), &zentry);
+  if (ret_code != 0) {
+    BACK_LOGW("failed to find %s in %s: %s", elf_file.c_str(), apk_file.c_str(),
+              ErrorCodeString(ret_code));
+    return nothing;
+  }
+  if (zentry.method != kCompressStored || zentry.compressed_length != zentry.uncompressed_length) {
+    BACK_LOGW("%s is compressed in %s, which doesn't support running directly", elf_file.c_str(),
+              apk_file.c_str());
+    return nothing;
+  }
+  auto buffer_or_err = llvm::MemoryBuffer::getOpenFileSlice(GetFileDescriptor(handle), apk_file,
+                                                            zentry.uncompressed_length,
+                                                            zentry.offset);
+  if (!buffer_or_err) {
+    BACK_LOGW("failed to read %s in %s: %s", elf_file.c_str(), apk_file.c_str(),
+              buffer_or_err.getError().message().c_str());
+    return nothing;
+  }
+  auto binary_or_err = llvm::object::createBinary(buffer_or_err.get()->getMemBufferRef());
+  if (!binary_or_err) {
+    BACK_LOGW("failed to create binary for %s in %s: %s", elf_file.c_str(), apk_file.c_str(),
+              binary_or_err.getError().message().c_str());
+    return nothing;
+  }
+  return llvm::object::OwningBinary<llvm::object::Binary>(std::move(binary_or_err.get()),
+                                                          std::move(buffer_or_err.get()));
+}
+
 static DebugFrameInfo* ReadDebugFrameFromFile(const std::string& filename) {
-  if (!IsValidElfPath(filename)) {
-    return nullptr;
+  llvm::object::OwningBinary<llvm::object::Binary> owning_binary;
+  if (filename.find("!/") != std::string::npos) {
+    owning_binary = OpenEmbeddedElfFile(filename);
+  } else {
+    if (!IsValidElfPath(filename)) {
+      return nullptr;
+    }
+    auto binary_or_err = llvm::object::createBinary(llvm::StringRef(filename));
+    if (!binary_or_err) {
+      return nullptr;
+    }
+    owning_binary = std::move(binary_or_err.get());
   }
-  auto owning_binary = llvm::object::createBinary(llvm::StringRef(filename));
-  if (owning_binary.getError()) {
-    return nullptr;
-  }
-  llvm::object::Binary* binary = owning_binary.get().getBinary();
+  llvm::object::Binary* binary = owning_binary.getBinary();
   auto obj = llvm::dyn_cast<llvm::object::ObjectFile>(binary);
   if (obj == nullptr) {
     return nullptr;
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 5fc3475..ec7a941 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -40,8 +40,7 @@
 static constexpr const char* kPublicNativeLibrariesConfig = "/system/etc/public.libraries.txt";
 
 static bool namespace_workaround_enabled(int32_t target_sdk_version) {
-  // target_sdk_version = 0 is another way of saying "target current sdk level"
-  return target_sdk_version != 0 && target_sdk_version <= 23;
+  return target_sdk_version <= 23;
 }
 
 class LibraryNamespaces {
diff --git a/mkbootimg/mkbootimg b/mkbootimg/mkbootimg
index 7b04bcc..5a13da2 100755
--- a/mkbootimg/mkbootimg
+++ b/mkbootimg/mkbootimg
@@ -102,12 +102,12 @@
 def parse_os_version(x):
     match = re.search(r'^(\d{1,3})(?:\.(\d{1,3})(?:\.(\d{1,3}))?)?', x)
     if match:
-        a = parse_int(match.group(1))
+        a = int(match.group(1))
         b = c = 0
         if match.lastindex >= 2:
-            b = parse_int(match.group(2))
+            b = int(match.group(2))
         if match.lastindex == 3:
-            c = parse_int(match.group(3))
+            c = int(match.group(3))
         # 7 bits allocated for each field
         assert a < 128
         assert b < 128
@@ -118,8 +118,8 @@
 def parse_os_patch_level(x):
     match = re.search(r'^(\d{4})-(\d{2})-(\d{2})', x)
     if match:
-        y = parse_int(match.group(1)) - 2000
-        m = parse_int(match.group(2))
+        y = int(match.group(1)) - 2000
+        m = int(match.group(2))
         # 7 bits allocated for the year, 4 bits for the month
         assert y >= 0 and y < 128
         assert m > 0 and m <= 12