Import changes for goma client

  - 21f14a33dde4673e2f62bbdb8bbef9712d8b1ba2 [rustc] Add rustc libs to compiler_info resources.
  - 37d16ad77d8bd0c2d1fe3c8a4e951150d178350d base: use C++11 delete functions instead of DISABLE_COPY_...
  - 3ed23bc150903060a915c68df33bc0ec2e2b8ce2 introduce more logs for busyloop debug
  - 6c015e0c3e6d2143494628a4397ae11d95f9183e lib: use C++11 delete functions instead of DISABLE_COPY_A...
  - 47a01f5c04d02d8bb7c8780ad93801c44c5b3d11 Roll client/third_party/boringssl/src 78c88c999..c37e64cba
  - 45c9fb951f3c8cea4c6411f432548532242be7ac Support not only x86_64-cros but also other clang.
  - 6694153f78fbd02b8a359748f288fa659012ec39 Hack to create directory for EXEC_PREFIX detection.
  - e71870bf67c0e9bfb42c7243b59e4cc71410deb9 update broken bots.proto link
  - 2cb1819cf28fce6879137730acb11d1ed689eeec update protobuf to 3.8.0
  - 92829246bcb02885ce0e38d136e5424f7e754147 Also add python2 as ChromeOS clang's dependency.
  - d607dc24455ffcc2d9aedd7b45736c5903a445d0 [rustc] Use rustc's sysroot/bin/rustc as its real path in...
  - 544379c9deb20b675b75562f363fa9615bfd01ce Roll client/third_party/boringssl/src 79ab5e8fa..78c88c999

GitOrigin-RevId: 21f14a33dde4673e2f62bbdb8bbef9712d8b1ba2
Change-Id: Ie88b870ff08a9d919d59b0ee4e55a9e28d009559
diff --git a/DEPS b/DEPS
index 52ff4a5..7120ff5 100644
--- a/DEPS
+++ b/DEPS
@@ -3,12 +3,12 @@
 }
 
 deps = {
-     # protobuf 3.6.1
+     # protobuf 3.8.0
      # Note: When you update protobuf, you will need to update
      # test/goma_data.pb.{h,cc}. Copying them from your output directory should
      # work.
      "client/third_party/protobuf/protobuf":
-     "https://github.com/google/protobuf.git@48cb18e5c419ddd23d9badcfe4e9df7bde1979b2",
+     "https://github.com/google/protobuf.git@09745575a923640154bcf307fba8aedff47f240a",
 
      # google-glog v0.4.0
      "client/third_party/glog":
@@ -37,7 +37,7 @@
 
      # chrome's deps/third_party/boringssl
      "client/third_party/boringssl/src":
-     "https://boringssl.googlesource.com/boringssl@79ab5e8faa04871e13542e35374657185adee5c8",
+     "https://boringssl.googlesource.com/boringssl@c37e64cba55256dff3ca4575dfcac1cfb2aa111e",
 
      # google-breakpad
      "client/third_party/breakpad/breakpad":
diff --git a/base/lockhelper.h b/base/lockhelper.h
index f3398bc..d82a1f4 100644
--- a/base/lockhelper.h
+++ b/base/lockhelper.h
@@ -7,7 +7,6 @@
 #define DEVTOOLS_GOMA_BASE_LOCKHELPER_H_
 
 #include "absl/base/thread_annotations.h"
-#include "basictypes.h"
 
 #ifdef __MACH__
 # include <libkern/OSAtomic.h>
@@ -33,6 +32,8 @@
  public:
   Lock();
   ~Lock();
+  Lock(const Lock&) = delete;
+  Lock& operator=(const Lock&) = delete;
 
   // If the lock is not held, take it and return true.  If the lock is already
   // held by something else, immediately return false.
@@ -51,7 +52,6 @@
   friend class WinVistaCondVar;
 #endif
   OSLockType os_lock_;
-  DISALLOW_COPY_AND_ASSIGN(Lock);
 };
 
 #ifdef __MACH__
@@ -89,6 +89,8 @@
  public:
   ReadWriteLock();
   ~ReadWriteLock();
+  ReadWriteLock(const ReadWriteLock&) = delete;
+  ReadWriteLock& operator=(const ReadWriteLock&) = delete;
 
   void AcquireShared() SHARED_LOCK_FUNCTION();
   void ReleaseShared() UNLOCK_FUNCTION();
@@ -102,7 +104,6 @@
 #else
   OSRWLockType os_rwlock_;
 #endif
-  DISALLOW_COPY_AND_ASSIGN(ReadWriteLock);
 };
 
 class SCOPED_LOCKABLE AutoLock {
@@ -118,9 +119,11 @@
     lock_->Release();
   }
 
+  AutoLock(const AutoLock&) = delete;
+  AutoLock& operator=(const AutoLock&) = delete;
+
  private:
   Lock* lock_;
-  DISALLOW_COPY_AND_ASSIGN(AutoLock);
 };
 
 class SCOPED_LOCKABLE AutoFastLock {
@@ -156,9 +159,11 @@
     lock_->ReleaseExclusive();
   }
 
+  AutoExclusiveLock(const AutoExclusiveLock&) = delete;
+  AutoExclusiveLock& operator=(const AutoExclusiveLock&) = delete;
+
  private:
   ReadWriteLock* lock_;
-  DISALLOW_COPY_AND_ASSIGN(AutoExclusiveLock);
 };
 
 class SCOPED_LOCKABLE AutoSharedLock {
@@ -174,9 +179,11 @@
     lock_->ReleaseShared();
   }
 
+  AutoSharedLock(const AutoSharedLock&) = delete;
+  AutoSharedLock& operator=(const AutoSharedLock&) = delete;
+
  private:
   ReadWriteLock* lock_;
-  DISALLOW_COPY_AND_ASSIGN(AutoSharedLock);
 };
 
 // POSIX conditional variable
@@ -184,6 +191,8 @@
  public:
   ConditionVariable();
   ~ConditionVariable();
+  ConditionVariable(const ConditionVariable&) = delete;
+  ConditionVariable& operator=(const ConditionVariable&) = delete;
 
   void Wait(Lock* lock);
   void Signal();
@@ -195,7 +204,6 @@
 #else  // Assume POSIX
   pthread_cond_t condition_;
 #endif
-  DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
 };
 
 }  // namespace devtools_goma
diff --git a/base/lockhelper_unittest.cc b/base/lockhelper_unittest.cc
index c31cd99..cb95a31 100644
--- a/base/lockhelper_unittest.cc
+++ b/base/lockhelper_unittest.cc
@@ -23,6 +23,8 @@
  public:
   explicit BasicLockTestThread(Lock* lock) : lock_(lock), acquired_(0) {
   }
+  BasicLockTestThread(const BasicLockTestThread&) = delete;
+  BasicLockTestThread& operator=(const BasicLockTestThread&) = delete;
 
   void ThreadMain() override {
     for (int i = 0; i < 10; i++) {
@@ -50,8 +52,6 @@
  private:
   Lock* lock_;
   int acquired_;
-
-  DISALLOW_COPY_AND_ASSIGN(BasicLockTestThread);
 };
 
 bool BasicLockTest() {
@@ -101,6 +101,8 @@
  public:
   explicit TryLockTestThread(Lock* lock) : lock_(lock), got_lock_(false) {
   }
+  TryLockTestThread(const TryLockTestThread&) = delete;
+  TryLockTestThread& operator=(const TryLockTestThread&) = delete;
 
   void ThreadMain() override {
     if (lock_->Try()) {
@@ -116,8 +118,6 @@
  private:
   Lock* lock_;
   bool got_lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(TryLockTestThread);
 };
 
 bool TryLockTest() {
@@ -166,6 +166,8 @@
 class MutexLockTestThread : public PlatformThread::Delegate {
  public:
   MutexLockTestThread(Lock* lock, int* value) : lock_(lock), value_(value) {}
+  MutexLockTestThread(const MutexLockTestThread&) = delete;
+  MutexLockTestThread& operator=(const MutexLockTestThread&) = delete;
 
   // Static helper which can also be called from the main thread.
   static void DoStuff(Lock* lock, int* value) {
@@ -185,8 +187,6 @@
  private:
   Lock* lock_;
   int* value_;
-
-  DISALLOW_COPY_AND_ASSIGN(MutexLockTestThread);
 };
 
 bool MutexTwoThreads() {
@@ -247,6 +247,9 @@
                               Data* data)
       : id_(id), lock_(lock), cond_(cond), data_(data) {
   }
+  ConditionVariableTestThread(const ConditionVariableTestThread&) = delete;
+  ConditionVariableTestThread& operator=(const ConditionVariableTestThread&) =
+      delete;
 
   void ThreadMain() override {
     if (id_ == 1) {
@@ -305,8 +308,6 @@
   Lock* lock_;
   ConditionVariable* cond_;
   Data* data_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConditionVariableTestThread);
 };
 
 bool ConditionVar() {
@@ -340,6 +341,9 @@
       : lock_(lock),
         num_(num) {
   }
+  ReadWriteLockBasicTestThread(const ReadWriteLockBasicTestThread&) = delete;
+  ReadWriteLockBasicTestThread& operator=(const ReadWriteLockBasicTestThread&) =
+      delete;
 
   void ThreadMain() override {
     for (int i = 0; i < 10; i++) {
@@ -364,8 +368,6 @@
  private:
   ReadWriteLock* lock_;
   int* num_;
-
-  DISALLOW_COPY_AND_ASSIGN(ReadWriteLockBasicTestThread);
 };
 
 bool ReadWriteLockBasicTest() {
@@ -396,6 +398,10 @@
       num_(num),
       started_(false) {
   }
+  ReadWriteLockAcquireExclusiveThread(
+      const ReadWriteLockAcquireExclusiveThread&) = delete;
+  ReadWriteLockAcquireExclusiveThread& operator=(
+      const ReadWriteLockAcquireExclusiveThread&) = delete;
 
   void ThreadMain() override {
     SetStarted();
@@ -419,8 +425,6 @@
 
   mutable Lock mu_;
   bool started_;
-
-  DISALLOW_COPY_AND_ASSIGN(ReadWriteLockAcquireExclusiveThread);
 };
 
 bool ReadWriteLockAcquireExclusiveTest1() {
@@ -491,6 +495,10 @@
       gotten_num_(0),
       started_(false) {
   }
+  ReadWriteLockAcquireSharedThread(const ReadWriteLockAcquireSharedThread&) =
+      delete;
+  ReadWriteLockAcquireSharedThread& operator=(
+      const ReadWriteLockAcquireSharedThread&) = delete;
 
   void ThreadMain() override {
     SetStarted();
@@ -519,8 +527,6 @@
 
   mutable Lock mu_;
   bool started_;
-
-  DISALLOW_COPY_AND_ASSIGN(ReadWriteLockAcquireSharedThread);
 };
 
 
diff --git a/base/socket_helper_win.cc b/base/socket_helper_win.cc
index cd26faf..df676a8 100644
--- a/base/socket_helper_win.cc
+++ b/base/socket_helper_win.cc
@@ -107,6 +107,8 @@
 
 class ServerThread : public devtools_goma::PlatformThread::Delegate {
  public:
+  ServerThread(const ServerThread&) = delete;
+  ServerThread& operator=(const ServerThread&) = delete;
   // Creates |*listener| socket and starts listen at |*listener| on |*port|.
   // Returns WSA error code.  If success, returns 0.
   // |*port| is allocated from available port by system.
@@ -230,14 +232,14 @@
   SOCKET listener_;
   SOCKET* accept_;
   int result_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServerThread);
 };
 
 class ClientThread : public devtools_goma::PlatformThread::Delegate {
  public:
   explicit ClientThread(SOCKET* client, int port)
       : client_(client), port_(port), result_(WSAETIMEDOUT) {}
+  ClientThread(const ClientThread&) = delete;
+  ClientThread& operator=(const ClientThread&) = delete;
 
   void ThreadMain() override {
     *client_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -304,8 +306,6 @@
   SOCKET* client_;
   int port_;
   int result_;
-
-  DISALLOW_COPY_AND_ASSIGN(ClientThread);
 };
 
 }  // namespace
diff --git a/base/socket_helper_win.h b/base/socket_helper_win.h
index 37bee18..39e4817 100644
--- a/base/socket_helper_win.h
+++ b/base/socket_helper_win.h
@@ -14,7 +14,6 @@
 //       It should be safe to ignore those warnings.
 
 #pragma once
-#include "basictypes.h"
 #include "compiler_specific.h"
 #include "config_win.h"
 #include <winsock2.h>
@@ -33,12 +32,12 @@
  public:
   WinsockHelper();
   ~WinsockHelper();
+  WinsockHelper(const WinsockHelper&) = delete;
+  WinsockHelper& operator=(const WinsockHelper&) = delete;
   bool initialized() const { return initialized_; }
 
  private:
   bool initialized_;
-
-  DISALLOW_COPY_AND_ASSIGN(WinsockHelper);
 };
 
 #endif  // _WIN32
diff --git a/base/socket_helper_win_unittest.cc b/base/socket_helper_win_unittest.cc
index a5befed..a0ab0a0 100644
--- a/base/socket_helper_win_unittest.cc
+++ b/base/socket_helper_win_unittest.cc
@@ -40,6 +40,9 @@
     CloseHandle(signal_);
   }
 
+  SocketPairTestThread(const SocketPairTestThread&) = delete;
+  SocketPairTestThread& operator=(const SocketPairTestThread&) = delete;
+
   void ThreadMain() override {
     bool terminate_signaled = false;
     for (; !terminate_signaled; ) {
@@ -123,7 +126,6 @@
   std::string message_;
   HANDLE signal_;
   int socket_;
-  DISALLOW_COPY_AND_ASSIGN(SocketPairTestThread);
 };
 
 TEST(SocketHelperWin, BlockingSocketPair) {
diff --git a/client/BUILD.gn b/client/BUILD.gn
index 6f1d967..bb3f8f2 100644
--- a/client/BUILD.gn
+++ b/client/BUILD.gn
@@ -79,6 +79,7 @@
     ]
 
     public_deps += [ ":rand_util_lib" ]  # posix_helper_win always require this
+    deps += [ "//third_party/abseil" ]
   }
 
   if (os == "linux") {
diff --git a/client/compile_service.cc b/client/compile_service.cc
index af2f6b2..15a8839 100644
--- a/client/compile_service.cc
+++ b/client/compile_service.cc
@@ -88,6 +88,10 @@
 
 namespace {
 
+// TODO: set proper dimensions instead.
+//                    e.g. compilers may not work if libc in remote image is
+//                    older than that of the requested compiler especially for
+//                    Linux.
 void SetDefaultOSSpecificRequesterInfo(RequesterInfo* info) {
 #ifdef _WIN32
   info->add_dimensions("os:win");
diff --git a/client/compiler_info.h b/client/compiler_info.h
index 7146197..5b18e54 100644
--- a/client/compiler_info.h
+++ b/client/compiler_info.h
@@ -11,6 +11,7 @@
 
 #include "absl/time/time.h"
 #include "absl/types/optional.h"
+#include "basictypes.h"
 #include "compiler_specific.h"
 #include "file_stat.h"
 #include "lockhelper.h"
diff --git a/client/compiler_info_builder.h b/client/compiler_info_builder.h
index ef0f293..96df562 100644
--- a/client/compiler_info_builder.h
+++ b/client/compiler_info_builder.h
@@ -11,6 +11,7 @@
 #include "absl/strings/string_view.h"
 #include "absl/time/time.h"
 #include "absl/types/optional.h"
+#include "basictypes.h"
 #include "compiler_flags.h"
 #include "compiler_specific.h"
 #include "sha256_hash_cache.h"
diff --git a/client/compiler_info_builder_unittest.cc b/client/compiler_info_builder_unittest.cc
index 05ddf40..63adc74 100644
--- a/client/compiler_info_builder_unittest.cc
+++ b/client/compiler_info_builder_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "compiler_info_builder.h"
 
+#include "basictypes.h"
 #include "compiler_flags_parser.h"
 #include "compiler_info.h"
 #include "compiler_type_specific_collection.h"
diff --git a/client/cxx/chromeos_compiler_info_builder_helper.cc b/client/cxx/chromeos_compiler_info_builder_helper.cc
index bd1ef22..8567501 100644
--- a/client/cxx/chromeos_compiler_info_builder_helper.cc
+++ b/client/cxx/chromeos_compiler_info_builder_helper.cc
@@ -19,11 +19,21 @@
 
 namespace {
 
-bool IsKnownClangInChroot(absl::string_view local_compiler_path) {
-  return local_compiler_path == "/usr/bin/clang" ||
-         local_compiler_path == "/usr/bin/clang++" ||
-         local_compiler_path == "/usr/bin/x86_64-cros-linux-gnu-clang" ||
-         local_compiler_path == "/usr/bin/x86_64-cros-linux-gnu-clang++";
+constexpr absl::string_view kClang = "/usr/bin/clang";
+constexpr absl::string_view kClangxx = "/usr/bin/clang++";
+
+bool IsClangWrapperInChroot(const absl::string_view local_compiler_path) {
+  if (file::Dirname(local_compiler_path) != "/usr/bin") {
+    return false;
+  }
+  absl::string_view basename = file::Basename(local_compiler_path);
+  return absl::EndsWith(basename, "-clang") ||
+         absl::EndsWith(basename, "-clang++");
+}
+
+bool IsKnownClangInChroot(const absl::string_view local_compiler_path) {
+  return local_compiler_path == kClang || local_compiler_path == kClangxx ||
+         IsClangWrapperInChroot(local_compiler_path);
 }
 
 bool ParseEnvdPath(absl::string_view envd_path, std::string* path) {
@@ -159,21 +169,14 @@
   return true;
 }
 
-// static
-bool ChromeOSCompilerInfoBuilderHelper::CollectChrootClangResources(
-    const std::string& cwd,
-    absl::string_view local_compiler_path,
-    absl::string_view real_compiler_path,
-    std::vector<std::string>* resource_paths) {
+namespace {
+
+bool SetChrootClangResourcePaths(const std::string& cwd,
+                                 const std::vector<std::string>& files,
+                                 absl::string_view local_compiler_path,
+                                 absl::string_view real_compiler_path,
+                                 std::vector<std::string>* resource_paths) {
   constexpr absl::string_view kLdSoConfPath = "/etc/ld.so.conf";
-
-  int version;
-  if (!EstimateClangMajorVersion(real_compiler_path, &version)) {
-    LOG(ERROR) << "failed to estimate clang major version"
-               << " real_compiler_path=" << real_compiler_path;
-    return false;
-  }
-
   std::string content;
   if (!ReadFileToString(kLdSoConfPath, &content)) {
     LOG(ERROR) << "failed to open/read " << kLdSoConfPath;
@@ -181,68 +184,134 @@
   }
   std::vector<std::string> searchpath = ParseLdSoConf(content);
   ElfDepParser edp(cwd, searchpath, false);
-  absl::flat_hash_set<std::string> deps;
-  if (!edp.GetDeps(local_compiler_path, &deps)) {
-    LOG(ERROR) << "failed to get library dependencies."
-               << " cwd=" << cwd
-               << " local_compiler_path=" << local_compiler_path
-               << " real_compiler_path=" << real_compiler_path;
-    return false;
+
+  absl::flat_hash_set<std::string> exec_deps;
+  for (const auto& file : files) {
+    if (file != local_compiler_path && file != real_compiler_path) {
+      resource_paths->push_back(file);
+    }
+    if (!IsElfFile(file)) {
+      continue;
+    }
+    if (!edp.GetDeps(file, &exec_deps)) {
+      LOG(ERROR) << "failed to get library dependencies for executable."
+                 << " file=" << file << " cwd=" << cwd;
+      return false;
+    }
   }
-  constexpr absl::string_view kClang = "/usr/bin/clang";
-  if (local_compiler_path != kClang && !edp.GetDeps(kClang, &deps)) {
-    LOG(ERROR) << "failed to get library dependencies for clang."
-               << " cwd=" << cwd;
-    return false;
-  }
-  for (const auto& path : deps) {
+  for (const auto& path : exec_deps) {
     resource_paths->push_back(path);
   }
-
-  // TODO: Currently support only target = x86_64.
-  // for target=arm, we need to use other resources.
-  // check local_compiler_path, and if compiler name looks like arm,
-  // we have to use arm-like resources.
-  resource_paths->push_back("/etc/env.d/gcc/.NATIVE");
-  resource_paths->push_back("/etc/env.d/05gcc-x86_64-cros-linux-gnu");
-
-  std::string path_from_envd;
-  if (!ParseEnvdPath("/etc/env.d/05gcc-x86_64-cros-linux-gnu",
-                     &path_from_envd)) {
-    return false;
-  }
-
-  if (local_compiler_path == "/usr/bin/x86_64-cros-linux-gnu-clang") {
-    // Actually /usr/bin/clang is called.
-    // /usr/x86_64-pc-linux-gnu/x86_64-cros-linux-gnu/gcc-bin/4.9.x/x86_64-cros-linux-gnu-clang
-    // is wrapper.
-    resource_paths->push_back("/usr/bin/clang");
-    resource_paths->push_back(
-        file::JoinPath(path_from_envd, "x86_64-cros-linux-gnu-clang"));
-  } else if (local_compiler_path == "/usr/bin/x86_64-cros-linux-gnu-clang++") {
-    // Actually /usr/bin/clang++ is called, and /usr/bin/clang can also be
-    // called. The latter 2 binaries are both wrapper.
-    resource_paths->push_back("/usr/bin/clang");
-    resource_paths->push_back("/usr/bin/clang++");
-    resource_paths->push_back(
-        file::JoinPath(path_from_envd, "x86_64-cros-linux-gnu-clang"));
-    resource_paths->push_back(
-        file::JoinPath(path_from_envd, "x86_64-cros-linux-gnu-clang++"));
-  }
-
   return true;
 }
 
+}  // namespace
+
+// static
+bool ChromeOSCompilerInfoBuilderHelper::CollectChrootClangResources(
+    const std::string& cwd,
+    absl::string_view local_compiler_path,
+    absl::string_view real_compiler_path,
+    std::vector<std::string>* resource_paths) {
+  std::vector<std::string> resources = {
+      std::string(local_compiler_path),
+      std::string(real_compiler_path),
+  };
+
+  if (!IsClangWrapperInChroot(local_compiler_path)) {
+    return SetChrootClangResourcePaths(cwd, resources, local_compiler_path,
+                                       real_compiler_path, resource_paths);
+  }
+
+  //
+  // Code below list up files needed to run the wrapper.
+  //
+  if (IsElfFile(std::string(local_compiler_path))) {
+    // Assuming |local_compiler_path| is a program to detect a position of
+    // the wrapper, and execute.
+    // Then, we need to upload files to decide wrapper positions (.NATIVE
+    // and 05gcc-*), and the wrapper script itself.
+    resources.emplace_back("/etc/env.d/gcc/.NATIVE");
+    absl::string_view compile_target = file::Stem(local_compiler_path);
+    if (!absl::ConsumeSuffix(&compile_target, "-clang") &&
+        !absl::ConsumeSuffix(&compile_target, "-clang++")) {
+      PLOG(ERROR) << "compiler name seems not be expected."
+                  << " local_compiler_path=" << local_compiler_path;
+      return false;
+    }
+    const std::string envfilename =
+        absl::StrCat("/etc/env.d/05gcc-", compile_target);
+    if (access(envfilename.c_str(), R_OK) != 0) {
+      LOG(ERROR) << "env file not found."
+                 << " envfilename=" << envfilename
+                 << " local_compiler_path=" << local_compiler_path
+                 << " real_compiler_path=" << real_compiler_path;
+      return false;
+    }
+    resources.push_back(envfilename);
+    std::string path_from_envd;
+    if (!ParseEnvdPath(envfilename, &path_from_envd)) {
+      LOG(ERROR) << "Failed to parse env file."
+                 << " envfilename=" << envfilename
+                 << " local_compiler_path=" << local_compiler_path
+                 << " real_compiler_path=" << real_compiler_path;
+      return false;
+    }
+
+    // Even if <basename> ends with clang++, we also need clang ones.
+    absl::string_view base_compiler_path = file::Basename(local_compiler_path);
+    resources.push_back(file::JoinPath(path_from_envd, base_compiler_path));
+    if (absl::EndsWith(base_compiler_path, "clang++")) {
+      resources.push_back(file::JoinPath(
+          path_from_envd, absl::StripSuffix(base_compiler_path, "++")));
+    }
+  }
+  // Actually /usr/bin/clang{,++} is called from the wrapper.
+  if (absl::EndsWith(local_compiler_path, "clang++")) {
+    resources.emplace_back(kClangxx);
+  } else {
+    resources.emplace_back(kClang);
+  }
+
+  // We also need python2 for wrapper.
+  // TODO: better way to handle python library usage change.
+  std::vector<std::string> python2_deps = {
+      "/usr/lib64/python2.7/_abcoll.py",
+      "/usr/lib64/python2.7/abc.py",
+      "/usr/lib64/python2.7/codecs.py",
+      "/usr/lib64/python2.7/copy_reg.py",
+      "/usr/lib64/python2.7/encodings/aliases.py",
+      "/usr/lib64/python2.7/encodings/__init__.py",
+      "/usr/lib64/python2.7/encodings/utf_8.py",
+      "/usr/lib64/python2.7/__future__.py",
+      "/usr/lib64/python2.7/genericpath.py",
+      "/usr/lib64/python2.7/linecache.py",
+      "/usr/lib64/python2.7/os.py",
+      "/usr/lib64/python2.7/posixpath.py",
+      "/usr/lib64/python2.7/stat.py",
+      "/usr/lib64/python2.7/types.py",
+      "/usr/lib64/python2.7/UserDict.py",
+      "/usr/lib64/python2.7/warnings.py",
+      "/usr/lib64/python2.7/_weakrefset.py",
+      // "lib-dynload" is needed for detecting EXEC_PREFIX in python.
+      // The following code make it created in remote.
+      "/usr/lib64/python2.7/lib-dynload/../../../bin/python2",
+  };
+  resources.insert(resources.end(),
+                   std::make_move_iterator(python2_deps.begin()),
+                   std::make_move_iterator(python2_deps.end()));
+
+  return SetChrootClangResourcePaths(cwd, resources, local_compiler_path,
+                                     real_compiler_path, resource_paths);
+}
+
 // static
 void ChromeOSCompilerInfoBuilderHelper::SetAdditionalFlags(
     absl::string_view local_compiler_path,
     google::protobuf::RepeatedPtrField<std::string>* additional_flags) {
-  if (local_compiler_path == "/usr/bin/x86_64-cros-linux-gnu-clang" ||
-      local_compiler_path == "/usr/bin/x86_64-cros-linux-gnu-clang++") {
+  if (IsClangWrapperInChroot(local_compiler_path)) {
     // Wrapper tries to set up ccache, but it's meaningless in goma.
     // we have to set -noccache.
-    // TODO: chromeos toolchain should have -noccache by default
-    // if goma is enabled.
     additional_flags->Add("-noccache");
   }
 }
diff --git a/client/cxx/elf_util.cc b/client/cxx/elf_util.cc
index 9641a34..540fab8 100644
--- a/client/cxx/elf_util.cc
+++ b/client/cxx/elf_util.cc
@@ -4,6 +4,7 @@
 
 #include "elf_util.h"
 
+#include "absl/base/macros.h"
 #include "absl/strings/match.h"
 #include "absl/strings/str_replace.h"
 #include "absl/strings/str_split.h"
@@ -12,6 +13,7 @@
 #include "glog/stl_logging.h"
 #include "path.h"
 #include "path_resolver.h"
+#include "scoped_fd.h"
 #include "util.h"
 
 namespace devtools_goma {
@@ -184,4 +186,21 @@
   return ret;
 }
 
+bool IsElfFile(const std::string& filename) {
+  // TODO: better to use elf.h?
+  static constexpr char kELFMagic[] = {0x7f, 'E', 'L', 'F'};
+  ScopedFd fd(ScopedFd::OpenForRead(filename));
+  if (!fd.valid()) {
+    LOG(WARNING) << "failed to open " << filename;
+    return false;
+  }
+  char buf[ABSL_ARRAYSIZE(kELFMagic)];
+  if (fd.Read(buf, sizeof(buf)) != sizeof(buf)) {
+    LOG(WARNING) << "failed to read possibly ELF file."
+                 << " filename=" << filename;
+    return false;
+  }
+  return memcmp(buf, kELFMagic, ABSL_ARRAYSIZE(kELFMagic)) == 0;
+}
+
 }  // namespace devtools_goma
diff --git a/client/cxx/elf_util.h b/client/cxx/elf_util.h
index e842cd5..1e58a17 100644
--- a/client/cxx/elf_util.h
+++ b/client/cxx/elf_util.h
@@ -62,6 +62,9 @@
 // The returned value would be used by ElfDepParser.
 std::vector<std::string> ParseLdSoConf(absl::string_view content);
 
+// Returns true if the file is ELF formatted file.
+bool IsElfFile(const std::string& filename);
+
 }  // namespace devtools_goma
 
 #endif  // DEVTOOLS_GOMA_CLIENT_CXX_ELF_UTIL_H_
diff --git a/client/descriptor_poller_select.cc b/client/descriptor_poller_select.cc
index e1e339c..16bc777 100644
--- a/client/descriptor_poller_select.cc
+++ b/client/descriptor_poller_select.cc
@@ -124,7 +124,14 @@
 
   int PollEventsInternal(absl::Duration timeout) override {
     struct timeval tv = absl::ToTimeval(timeout);
-    return select(max_fd_ + 1, &read_fd_, &write_fd_, nullptr, &tv);
+    int r = select(max_fd_ + 1, &read_fd_, &write_fd_, nullptr, &tv);
+#ifdef _WIN32
+    if (r == SOCKET_ERROR) {
+      LOG(ERROR) << "select error: " << WSAGetLastError();
+    }
+#endif
+
+    return r;
   }
 
   class SelectEventEnumerator : public DescriptorPollerBase::EventEnumerator {
diff --git a/client/goma_file_dump.h b/client/goma_file_dump.h
index 264c740..a15dabe 100644
--- a/client/goma_file_dump.h
+++ b/client/goma_file_dump.h
@@ -9,6 +9,7 @@
 #include <memory>
 #include <string>
 
+#include "basictypes.h"
 #include "goma_file.h"
 
 namespace devtools_goma {
diff --git a/client/named_pipe_server_win.cc b/client/named_pipe_server_win.cc
index 852f563..a271e02 100644
--- a/client/named_pipe_server_win.cc
+++ b/client/named_pipe_server_win.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "absl/strings/string_view.h"
+#include "absl/time/clock.h"
 #include "autolock_timer.h"
 #include "callback.h"
 #include "config_win.h"
@@ -505,7 +506,18 @@
   events[1] = watch_closed_.handle();
   events[2] = reply_.handle();
   events[3] = shutdown_.handle();
+
+  auto loopstart = absl::Now();
+  int loopcnt = 0;
+
   for (;;) {
+    ++loopcnt;
+    if (absl::Now() - loopstart > absl::Minutes(1)) {
+      LOG(INFO) << "loop frequency per minutes: " << loopcnt;
+      loopstart = absl::Now();
+      loopcnt = 0;
+    }
+
     DWORD w = WaitForMultipleObjectsEx(
         4, events,
         FALSE,  // wait all
@@ -719,7 +731,18 @@
   HANDLE events[2];
   events[0] = flush_.handle();
   events[1] = shutdown_.handle();
+
+  auto loopstart = absl::Now();
+  int loopcnt = 0;
+
   for (;;) {
+    ++loopcnt;
+    if (absl::Now() - loopstart > absl::Minutes(1)) {
+      LOG(INFO) << "loop frequency per minutes: " << loopcnt;
+      loopstart = absl::Now();
+      loopcnt = 0;
+    }
+
     DWORD w = WaitForMultipleObjectsEx(
         2, events,
         FALSE,  // wait all
diff --git a/client/rust/rustc_compiler_info_builder.cc b/client/rust/rustc_compiler_info_builder.cc
index acea5a8..8993c64 100644
--- a/client/rust/rustc_compiler_info_builder.cc
+++ b/client/rust/rustc_compiler_info_builder.cc
@@ -7,15 +7,104 @@
 #include "absl/strings/match.h"
 #include "absl/strings/str_split.h"
 #include "absl/strings/strip.h"
+#include "base/file_dir.h"
+#include "base/path.h"
 #include "counterz.h"
 #include "glog/logging.h"
 #include "glog/stl_logging.h"
 #include "ioutil.h"
+#include "lib/path_resolver.h"
 #include "rustc_flags.h"
 #include "util.h"
 
+#ifdef _WIN32
+#include "posix_helper_win.h"
+#endif  // _WIN32
+
 namespace devtools_goma {
 
+namespace {
+bool IsExecutable(const std::string& path) {
+  return access(path.c_str(), X_OK) == 0;
+}
+
+bool AddFilesFromDirectory(const std::string& dirname,
+                           int remaining_depth,
+                           std::vector<std::string>* resource_paths) {
+  if (remaining_depth <= 0)
+    return true;
+
+  std::vector<DirEntry> entries;
+  if (!ListDirectory(dirname, &entries)) {
+    LOG(ERROR) << "Failed to list contents from directory " << dirname;
+    return false;
+  }
+  for (const auto& entry : entries) {
+    if (entry.name == "." || entry.name == "..") {
+      continue;
+    }
+    std::string entry_path = file::JoinPathRespectAbsolute(dirname, entry.name);
+    if (entry.is_dir) {
+      if (!AddFilesFromDirectory(entry_path, remaining_depth - 1,
+                                 resource_paths)) {
+        return false;
+      }
+    } else {
+      resource_paths->push_back(std::move(entry_path));
+    }
+  }
+  return true;
+}
+
+bool AddResourceAsExecutableBinaryInternal(
+    const std::string& resource_path,
+    const std::string& cwd,
+    int remaining_symlink_follow_count,
+    absl::flat_hash_set<std::string>* visited_paths,
+    CompilerInfoData* data) {
+  std::string abs_resource_path =
+      file::JoinPathRespectAbsolute(cwd, resource_path);
+  if (!visited_paths->insert(PathResolver::ResolvePath(abs_resource_path))
+           .second) {
+    // This path has been visited before. Abort.
+    return true;
+  }
+
+  CompilerInfoData::ResourceInfo r;
+  if (!CompilerInfoBuilder::ResourceInfoFromPath(
+          cwd, resource_path, CompilerInfoData::EXECUTABLE_BINARY, &r)) {
+    CompilerInfoBuilder::AddErrorMessage(
+        "failed to get resource info for " + resource_path, data);
+    LOG(ERROR) << "failed to get resource info for " + resource_path;
+    return false;
+  }
+
+  if (r.symlink_path().empty()) {
+    // Not a symlink, add it as a resource directly.
+    *data->add_resource() = std::move(r);
+    return true;
+  }
+
+  // It's a symlink.
+  if (remaining_symlink_follow_count <= 0) {
+    // Too many nested symlink. Abort and return an error.
+    CompilerInfoBuilder::AddErrorMessage(
+        "too deep nested symlink: " + resource_path, data);
+    return false;
+  }
+  std::string symlink_path = file::JoinPathRespectAbsolute(
+      file::Dirname(resource_path), r.symlink_path());
+  // Implementation Note: the original resource must come first. If the resource
+  // is a symlink, the actual file must be added after the symlink. The server
+  // assumes the first resource is a compiler used in a command line, even
+  // if it's a symlink.
+  *data->add_resource() = std::move(r);
+  return AddResourceAsExecutableBinaryInternal(
+      symlink_path, cwd, remaining_symlink_follow_count - 1, visited_paths,
+      data);
+}
+}  // namespace
+
 void RustcCompilerInfoBuilder::SetTypeSpecificCompilerInfo(
     const CompilerFlags& compiler_flags,
     const std::string& local_compiler_path,
@@ -37,6 +126,22 @@
     return;
   }
   data->set_target(std::move(host));
+
+  std::vector<std::string> resources_path;
+  if (!CollectRustcResources(data->real_compiler_path(), &resources_path)) {
+    AddErrorMessage(
+        "Failed to get rustc resources for " + data->real_compiler_path(),
+        data);
+    LOG(ERROR) << data->error_message();
+    return;
+  }
+  absl::flat_hash_set<std::string> visited_paths;
+  for (const auto& file : resources_path) {
+    if (!AddResourceAsExecutableBinary(file, compiler_flags.cwd(),
+                                       &visited_paths, data)) {
+      return;
+    }
+  }
 }
 
 void RustcCompilerInfoBuilder::SetLanguageExtension(
@@ -115,4 +220,77 @@
   return host_was_found;
 }
 
+void RustcCompilerInfoBuilder::SetCompilerPath(
+    const CompilerFlags& flags,
+    const std::string& local_compiler_path,
+    const std::vector<std::string>& compiler_info_envs,
+    CompilerInfoData* data) const {
+  // If rustc is installed by rustup, the local_compiler_path
+  // is actually pointing to a rustup wrapper, which shouldn't
+  // be used for hashing. The real rustc
+  // should be located at `rustc --print sysroot`/bin/rustc
+  data->set_local_compiler_path(local_compiler_path);
+  data->set_real_compiler_path(local_compiler_path);
+  const std::vector<std::string> args{
+      local_compiler_path,
+      "--print",
+      "sysroot",
+  };
+  std::vector<std::string> env(compiler_info_envs);
+  env.emplace_back("LC_ALL=C");
+
+  int32_t status = 0;
+  std::string output =
+      ReadCommandOutput(local_compiler_path, args, env, flags.cwd(),
+                        MERGE_STDOUT_STDERR, &status);
+  LOG(INFO) << "Rust sysroot " << output;
+  if (status != 0) {
+    LOG(ERROR) << "ReadCommandOutput exited with non zero status code."
+               << " rustc_path=" << local_compiler_path << " status=" << status
+               << " args=" << args << " env=" << env << " cwd=" << flags.cwd()
+               << " output=" << output;
+    return;
+  }
+  std::string real_rustc = file::JoinPathRespectAbsolute(
+      absl::StripTrailingAsciiWhitespace(output), "bin/rustc");
+  if (IsExecutable(real_rustc)) {
+    data->set_real_compiler_path(std::move(real_rustc));
+  }
+}
+
+// static
+bool RustcCompilerInfoBuilder::CollectRustcResources(
+    absl::string_view real_compiler_path,
+    std::vector<std::string>* resource_paths) {
+  resource_paths->emplace_back(real_compiler_path);
+  std::vector<std::string> rustc_resource_directories = {"lib"};
+
+  // The real toolchain is located at
+  // ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc
+  // We should use ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu
+  // as rust_root.
+  absl::string_view rust_root =
+      file::Dirname(file::Dirname(real_compiler_path));
+  constexpr int kMaxNestedDirs = 8;
+  for (const auto& dir : rustc_resource_directories) {
+    std::string resource_dir = file::JoinPathRespectAbsolute(rust_root, dir);
+    if (!AddFilesFromDirectory(resource_dir, kMaxNestedDirs, resource_paths)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+// static
+bool RustcCompilerInfoBuilder::AddResourceAsExecutableBinary(
+    const std::string& resource_path,
+    const std::string& cwd,
+    absl::flat_hash_set<std::string>* visited_paths,
+    CompilerInfoData* data) {
+  // On Linux, MAX_NESTED_LINKS is 8.
+  constexpr int kMaxNestedLinks = 8;
+  return AddResourceAsExecutableBinaryInternal(
+      resource_path, cwd, kMaxNestedLinks, visited_paths, data);
+}
+
 }  // namespace devtools_goma
diff --git a/client/rust/rustc_compiler_info_builder.h b/client/rust/rustc_compiler_info_builder.h
index 836e02d..e792f78 100644
--- a/client/rust/rustc_compiler_info_builder.h
+++ b/client/rust/rustc_compiler_info_builder.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include "absl/container/flat_hash_set.h"
 #include "compiler_info_builder.h"
 #include "gtest/gtest_prod.h"
 
@@ -26,6 +27,11 @@
 
   void SetLanguageExtension(CompilerInfoData* data) const override;
 
+  void SetCompilerPath(const CompilerFlags& flags,
+                       const std::string& local_compiler_path,
+                       const std::vector<std::string>& compiler_info_envs,
+                       CompilerInfoData* data) const override;
+
  private:
   // Gets rustc's version and host.
   bool GetRustcVersionHost(const std::string& rustc_path,
@@ -38,6 +44,20 @@
                              std::string* version,
                              std::string* host) const;
 
+  // Collect required library and resource files which are required to
+  // run rustc.
+  static bool CollectRustcResources(absl::string_view real_compiler_path,
+                                    std::vector<std::string>* resource_paths);
+
+  // Add resource as EXECUTABLE_BINARY. If the resource is a symlink,
+  // both the symlink and actual files are added. This is copied from
+  // gcc_compiler_info_builder.
+  static bool AddResourceAsExecutableBinary(
+      const std::string& resource_path,
+      const std::string& cwd,
+      absl::flat_hash_set<std::string>* visited_paths,
+      CompilerInfoData* data);
+
   FRIEND_TEST(RustCompilerInfoBuilderTest, ParseRustcVersionTarget);
 };
 
diff --git a/client/scoped_tmp_file.h b/client/scoped_tmp_file.h
index 938c372..f1183a3 100644
--- a/client/scoped_tmp_file.h
+++ b/client/scoped_tmp_file.h
@@ -8,6 +8,7 @@
 
 #include <string>
 
+#include "basictypes.h"
 #include "scoped_fd.h"
 
 namespace devtools_goma {
diff --git a/client/spawner_posix.h b/client/spawner_posix.h
index 7d00ccf..a3dd655 100644
--- a/client/spawner_posix.h
+++ b/client/spawner_posix.h
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 
+#include "basictypes.h"
 #include "scoped_fd.h"
 #include "simple_timer.h"
 #include "spawner.h"
diff --git a/client/subprocess_controller_server.cc b/client/subprocess_controller_server.cc
index c1cbdf9..99cc0ed 100644
--- a/client/subprocess_controller_server.cc
+++ b/client/subprocess_controller_server.cc
@@ -96,7 +96,18 @@
 #ifndef _WIN32
   DCHECK(signal_fd_.valid());
 #endif
+
+  auto loopstart = absl::Now();
+  int loopcnt = 0;
+
   for (;;) {
+    ++loopcnt;
+    if (absl::Now() - loopstart > absl::Minutes(1)) {
+      LOG(INFO) << "loop frequency per minutes: " << loopcnt;
+      loopstart = absl::Now();
+      loopcnt = 0;
+    }
+
     if (!sock_fd_.valid()) {
       VLOG(1) << "sock_fd closed";
       break;
diff --git a/client/threadpool_http_server.cc b/client/threadpool_http_server.cc
index 5249ffe..bca98d9 100644
--- a/client/threadpool_http_server.cc
+++ b/client/threadpool_http_server.cc
@@ -967,7 +967,18 @@
     cond_.Broadcast();
   }
   LOG(INFO) << "listen on port " << ntohs(sa.sin_port);
+
+  auto loopstart = absl::Now();
+  int loopcnt = 0;
+
   for (;;) {
+    ++loopcnt;
+    if (absl::Now() - loopstart > absl::Minutes(1)) {
+      LOG(INFO) << "loop frequency per minutes: " << loopcnt;
+      loopstart = absl::Now();
+      loopcnt = 0;
+    }
+
     if (http_handler_->shutting_down()) {
       LOG(INFO) << "Shutting down...";
       un_socket_.reset(-1);
@@ -999,6 +1010,14 @@
       }
       continue;
     }
+
+#ifdef _WIN32
+    if (r == SOCKET_ERROR) {
+      LOG(ERROR) << "select error: " << WSAGetLastError();
+      continue;
+    }
+#endif
+
     if (r == -1) {
       PLOG(WARNING) << "select";
       continue;
diff --git a/client/worker_thread.cc b/client/worker_thread.cc
index 75cbc5a..8d425f4 100644
--- a/client/worker_thread.cc
+++ b/client/worker_thread.cc
@@ -531,6 +531,7 @@
     Priority io_priority = iter.first;
     std::deque<OneshotClosure*>& pendings = iter.second;
     while (!pendings.empty()) {
+      LOG_EVERY_SEC(INFO) << "io closure: " << pendings.front();
       // TODO: use original location
       AddClosure(FROM_HERE, io_priority, pendings.front());
       pendings.pop_front();
diff --git a/lib/file_data_output.cc b/lib/file_data_output.cc
index de17674..0ed3e9e 100644
--- a/lib/file_data_output.cc
+++ b/lib/file_data_output.cc
@@ -101,6 +101,8 @@
       remove(filename_.c_str());
     }
   }
+  FileOutputImpl(const FileOutputImpl&) = delete;
+  FileOutputImpl& operator=(const FileOutputImpl&) = delete;
 
   bool IsValid() const override { return fd_.valid(); }
   bool WriteAt(off_t offset, const std::string& content) override {
@@ -138,7 +140,6 @@
   const std::string filename_;
   devtools_goma::ScopedFd fd_;
   bool error_;
-  DISALLOW_COPY_AND_ASSIGN(FileOutputImpl);
 };
 
 class StringOutputImpl : public FileDataOutput {
@@ -146,6 +147,8 @@
   StringOutputImpl(std::string name, std::string* buf)
       : name_(std::move(name)), buf_(buf), size_(0UL) {}
   ~StringOutputImpl() override {}
+  StringOutputImpl(const StringOutputImpl&) = delete;
+  StringOutputImpl& operator=(const StringOutputImpl&) = delete;
 
   bool IsValid() const override { return buf_ != nullptr; }
   bool WriteAt(off_t offset, const std::string& content) override {
@@ -171,7 +174,6 @@
   const std::string name_;
   std::string* buf_;
   size_t size_;
-  DISALLOW_COPY_AND_ASSIGN(StringOutputImpl);
 };
 
 }  // anonymous namespace
diff --git a/lib/file_data_output.h b/lib/file_data_output.h
index e194b83..487e092 100644
--- a/lib/file_data_output.h
+++ b/lib/file_data_output.h
@@ -10,8 +10,6 @@
 #include <memory>
 #include <string>
 
-#include "base/basictypes.h"
-
 namespace devtools_goma {
 
 // TODO: provide Input too.
@@ -20,6 +18,10 @@
  public:
   FileDataOutput() {}
   virtual ~FileDataOutput() {}
+
+  FileDataOutput(const FileDataOutput&) = delete;
+  FileDataOutput& operator=(const FileDataOutput&) = delete;
+
   // IsValid returns true if this output is valid to use.
   virtual bool IsValid() const = 0;
   // WriteAt writes content at offset in output.
@@ -45,9 +47,6 @@
   static std::unique_ptr<FileDataOutput> NewStringOutput(
       const std::string& name,
       std::string* buf);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(FileDataOutput);
 };
 
 }  // namespace devtools_goma
diff --git a/lib/file_reader.h b/lib/file_reader.h
index 698c030..27d0c03 100644
--- a/lib/file_reader.h
+++ b/lib/file_reader.h
@@ -28,6 +28,10 @@
 
 class FileReaderFactory {
  public:
+  // Enforce the class singleton.
+  FileReaderFactory(const FileReaderFactory&) = delete;
+  FileReaderFactory& operator=(const FileReaderFactory&) = delete;
+
   // A type to create an FileReader instance.
   // It returns NULL if it cannot handle the given |filename|.
   typedef std::unique_ptr<FileReader> (*CreateFunction)(
@@ -43,6 +47,7 @@
   static FileReaderFactory* GetInstance();
 
  private:
+  // Enforce the class singleton.
   FileReaderFactory() {}
 
   // Deletes the singleton instance to be called by atexit.
@@ -50,8 +55,6 @@
 
   std::vector<CreateFunction> creators_;
   static FileReaderFactory* factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(FileReaderFactory);
 };
 
 // Wrapper class of ScopedFd.
@@ -60,6 +63,9 @@
  public:
   virtual ~FileReader() {}
 
+  FileReader(const FileReader&) = delete;
+  FileReader& operator=(const FileReader&) = delete;
+
   // Wrapper of ScopedFd's Read.
   // If |len| == 0, returns 0.
   virtual ssize_t Read(void* ptr, size_t len) {
@@ -106,7 +112,6 @@
   ScopedFd fd_;
 
   friend class FileReaderFactory;
-  DISALLOW_COPY_AND_ASSIGN(FileReader);
 };
 
 }  // namespace devtools_goma
diff --git a/lib/flag_parser.h b/lib/flag_parser.h
index ed2c398..002b095 100644
--- a/lib/flag_parser.h
+++ b/lib/flag_parser.h
@@ -11,7 +11,6 @@
 #include <string>
 #include <vector>
 
-#include "base/basictypes.h"
 #include "absl/container/flat_hash_map.h"
 
 class FlagParser {
@@ -44,15 +43,17 @@
    public:
     Callback() {}
     virtual ~Callback() {}
+    Callback(const Callback&) = delete;
+    Callback& operator=(const Callback&) = delete;
     // Returns parsed flag value of value for flag.
     virtual std::string ParseFlagValue(const Flag& flag,
                                        const std::string& value) = 0;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Callback);
   };
   class Flag {
    public:
+    Flag(const Flag&) = delete;
+    Flag& operator=(const Flag&) = delete;
+
     // Uses seen_output to store boolean whether the flag is seen or not.
     // Should be called before calling FlagParser::Parse().
     // *seen_output will be updated in FlagParser::Parse().
@@ -133,11 +134,12 @@
     std::vector<std::string>* values_output_;
     Callback* parse_callback_;
     absl::flat_hash_map<int, std::string> parsed_args_;
-    DISALLOW_COPY_AND_ASSIGN(Flag);
   };
 
   FlagParser();
   ~FlagParser();
+  FlagParser(const FlagParser&) = delete;
+  FlagParser& operator=(const FlagParser&) = delete;
 
   FlagParser::Options* mutable_options() {
     return &opts_;
@@ -182,8 +184,6 @@
   std::vector<std::string> unknown_flag_args_;
 
   std::vector<Flag*> parsed_flags_;
-
-  DISALLOW_COPY_AND_ASSIGN(FlagParser);
 };
 
 #endif  // DEVTOOLS_GOMA_LIB_FLAG_PARSER_H_
diff --git a/lib/goma_file.h b/lib/goma_file.h
index 371fe7a..339cb4b 100644
--- a/lib/goma_file.h
+++ b/lib/goma_file.h
@@ -10,7 +10,6 @@
 #include <string>
 #include <vector>
 
-#include "base/basictypes.h"
 #include "lib/file_reader.h"
 #include "prototmp/goma_data.pb.h"
 
@@ -39,6 +38,8 @@
    public:
     AsyncTask() {}
     virtual ~AsyncTask() {}
+    AsyncTask(const AsyncTask&) = delete;
+    AsyncTask& operator=(const AsyncTask&) = delete;
     const Req& req() const { return req_; }
     Req* mutable_req() { return &req_; }
     const Resp& resp() const { return resp_; }
@@ -51,14 +52,13 @@
    protected:
     Req req_;
     Resp resp_;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(AsyncTask);
   };
 
   FileServiceClient()
       : reader_factory_(FileReaderFactory::GetInstance()) {}
   virtual ~FileServiceClient() {}
+  FileServiceClient(const FileServiceClient&) = delete;
+  FileServiceClient& operator=(const FileServiceClient&) = delete;
 
   // Create |blob| for |filename|.
   // If failed to open |filename|, it will set FileBlob::FILE as blob_type
@@ -136,8 +136,6 @@
       std::unique_ptr<AsyncTask<LookupFileReq, LookupFileResp>> task,
       FileDataOutput* output);
   bool OutputFileChunks(const FileBlob& blob, FileDataOutput* output);
-
-  DISALLOW_COPY_AND_ASSIGN(FileServiceClient);
 };
 
 }  // namespace devtools_goma
diff --git a/lib/path_resolver.h b/lib/path_resolver.h
index a67fa50..80467dc 100644
--- a/lib/path_resolver.h
+++ b/lib/path_resolver.h
@@ -10,7 +10,6 @@
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "base/basictypes.h"
 
 namespace devtools_goma {
 
@@ -29,6 +28,9 @@
   PathResolver();
   ~PathResolver();
 
+  PathResolver(const PathResolver&) = delete;
+  PathResolver& operator=(const PathResolver&) = delete;
+
   // Convert path to platform specific format of running platform.
   static std::string PlatformConvert(const std::string& path);
   static void PlatformConvertToString(const std::string& path,
@@ -77,8 +79,6 @@
 
  private:
   std::vector<std::string> system_paths_;
-
-  DISALLOW_COPY_AND_ASSIGN(PathResolver);
 };
 
 };  // namespace devtools_goma
diff --git a/lib/scoped_fd.h b/lib/scoped_fd.h
index 9dd5f8b..14fd783 100644
--- a/lib/scoped_fd.h
+++ b/lib/scoped_fd.h
@@ -21,7 +21,6 @@
 
 #include "absl/strings/string_view.h"
 #include "absl/time/time.h"
-#include "base/basictypes.h"
 
 namespace devtools_goma {
 
@@ -47,6 +46,9 @@
   ScopedFd(ScopedFd&& other) : fd_(other.release()) {}
   ~ScopedFd();
 
+  ScopedFd(const ScopedFd&) = delete;
+  ScopedFd& operator=(const ScopedFd&) = delete;
+
   ScopedFd& operator=(ScopedFd&& other) {
     if (this == &other) {
       return *this;
@@ -94,8 +96,6 @@
 
  private:
   FileDescriptor fd_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedFd);
 };
 
 enum Errno {
@@ -145,6 +145,9 @@
   ScopedSocket(ScopedSocket&& other) : fd_(other.release()) {}
   ~ScopedSocket() override;
 
+  ScopedSocket(const ScopedSocket&) = delete;
+  ScopedSocket& operator=(const ScopedSocket&) = delete;
+
   ScopedSocket& operator=(ScopedSocket&& other) {
     if (this == &other) {
       return *this;
@@ -196,8 +199,6 @@
 #else
   int fd_;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedSocket);
 };
 
 }  // namespace devtools_goma
diff --git a/third_party/boringssl/BUILD.generated.gni b/third_party/boringssl/BUILD.generated.gni
index 3bdb1d1..c07e0ec 100644
--- a/third_party/boringssl/BUILD.generated.gni
+++ b/third_party/boringssl/BUILD.generated.gni
@@ -127,6 +127,7 @@
   "src/crypto/fipsmodule/ec/internal.h",
   "src/crypto/fipsmodule/ec/p256-x86_64-table.h",
   "src/crypto/fipsmodule/ec/p256-x86_64.h",
+  "src/crypto/fipsmodule/fips_shared_support.c",
   "src/crypto/fipsmodule/is_fips.c",
   "src/crypto/fipsmodule/md5/internal.h",
   "src/crypto/fipsmodule/modes/internal.h",
@@ -274,6 +275,15 @@
   "src/third_party/fiat/internal.h",
   "src/third_party/fiat/p256_32.h",
   "src/third_party/fiat/p256_64.h",
+  "src/third_party/sike/P503.c",
+  "src/third_party/sike/asm/fp_generic.c",
+  "src/third_party/sike/fpx.c",
+  "src/third_party/sike/fpx.h",
+  "src/third_party/sike/isogeny.c",
+  "src/third_party/sike/isogeny.h",
+  "src/third_party/sike/sike.c",
+  "src/third_party/sike/sike.h",
+  "src/third_party/sike/utils.h",
 ]
 
 crypto_headers = [
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn
index 2dda274..39e2a54 100644
--- a/third_party/protobuf/BUILD.gn
+++ b/third_party/protobuf/BUILD.gn
@@ -26,6 +26,9 @@
       "-Wno-unused-function",
 
       "-Wno-inconsistent-missing-override",
+
+      # This is for `friend class DynamicMessage` in map_field.h
+      "-Wno-microsoft-unqualified-friend",
     ]
   }
 }
@@ -65,6 +68,9 @@
       "-Wno-sign-compare",
       "-Wno-unused-local-typedef",
       "-Wno-unused-parameter",
+
+      # This is for `friend class DynamicMessage` in map_field.h
+      "-Wno-microsoft-unqualified-friend",
     ]
   }
 }
@@ -82,7 +88,6 @@
   "protobuf/src/google/protobuf/stubs/once.h",
   "protobuf/src/google/protobuf/stubs/platform_macros.h",
   "protobuf/src/google/protobuf/stubs/port.h",
-  "protobuf/src/google/protobuf/stubs/singleton.h",
   "protobuf/src/google/protobuf/stubs/status.h",
   "protobuf/src/google/protobuf/stubs/stl_util.h",
   "protobuf/src/google/protobuf/stubs/stringpiece.h",
@@ -131,7 +136,6 @@
   "protobuf/src/google/protobuf/unknown_field_set.h",
   "protobuf/src/google/protobuf/wire_format.h",
   "protobuf/src/google/protobuf/wire_format_lite.h",
-  "protobuf/src/google/protobuf/wire_format_lite_inl.h",
   "protobuf/src/google/protobuf/wrappers.pb.h",
   "protobuf/src/google/protobuf/io/coded_stream.h",
   "protobuf/src/google/protobuf/io/printer.h",
@@ -171,14 +175,25 @@
 
 # libprotobuf_lite_la_SOURCES of Makefile.am in protobuf/protobuf/src.
 protobuf_lite_sources = [
+  "protobuf/src/google/protobuf/any_lite.cc",
+  "protobuf/src/google/protobuf/arena.cc",
+  "protobuf/src/google/protobuf/extension_set.cc",
+  "protobuf/src/google/protobuf/generated_message_table_driven_lite.cc",
+  "protobuf/src/google/protobuf/generated_message_table_driven_lite.h",
+  "protobuf/src/google/protobuf/generated_message_util.cc",
+  "protobuf/src/google/protobuf/implicit_weak_message.cc",
+  "protobuf/src/google/protobuf/io/coded_stream.cc",
+  "protobuf/src/google/protobuf/io/coded_stream_inl.h",
+  "protobuf/src/google/protobuf/io/zero_copy_stream.cc",
+  "protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
+  "protobuf/src/google/protobuf/message_lite.cc",
+  "protobuf/src/google/protobuf/repeated_field.cc",
   "protobuf/src/google/protobuf/stubs/bytestream.cc",
   "protobuf/src/google/protobuf/stubs/bytestream.h",
   "protobuf/src/google/protobuf/stubs/common.cc",
   "protobuf/src/google/protobuf/stubs/hash.h",
   "protobuf/src/google/protobuf/stubs/int128.cc",
   "protobuf/src/google/protobuf/stubs/int128.h",
-  "protobuf/src/google/protobuf/stubs/io_win32.cc",
-  "protobuf/src/google/protobuf/stubs/io_win32.h",
   "protobuf/src/google/protobuf/stubs/map_util.h",
   "protobuf/src/google/protobuf/stubs/mathutil.h",
   "protobuf/src/google/protobuf/stubs/status.cc",
@@ -189,15 +204,6 @@
   "protobuf/src/google/protobuf/stubs/stringpiece.cc",
   "protobuf/src/google/protobuf/stubs/stringpiece.h",
   "protobuf/src/google/protobuf/stubs/stringprintf.cc",
-  "protobuf/src/google/protobuf/arena.cc",
-  "protobuf/src/google/protobuf/arenastring.cc",
-  "protobuf/src/google/protobuf/extension_set.cc",
-  "protobuf/src/google/protobuf/generated_message_table_driven_lite.cc",
-  "protobuf/src/google/protobuf/generated_message_table_driven_lite.h",
-  "protobuf/src/google/protobuf/generated_message_util.cc",
-  "protobuf/src/google/protobuf/implicit_weak_message.cc",
-  "protobuf/src/google/protobuf/message_lite.cc",
-  "protobuf/src/google/protobuf/repeated_field.cc",
   "protobuf/src/google/protobuf/stubs/stringprintf.h",
   "protobuf/src/google/protobuf/stubs/structurally_valid.cc",
   "protobuf/src/google/protobuf/stubs/strutil.cc",
@@ -205,10 +211,6 @@
   "protobuf/src/google/protobuf/stubs/time.cc",
   "protobuf/src/google/protobuf/stubs/time.h",
   "protobuf/src/google/protobuf/wire_format_lite.cc",
-  "protobuf/src/google/protobuf/io/coded_stream.cc",
-  "protobuf/src/google/protobuf/io/coded_stream_inl.h",
-  "protobuf/src/google/protobuf/io/zero_copy_stream.cc",
-  "protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
 ]
 
 protobuf_lite_cflags = []
@@ -286,6 +288,7 @@
     "protobuf/src/google/protobuf/generated_message_table_driven.cc",
     "protobuf/src/google/protobuf/generated_message_table_driven_lite.h",
     "protobuf/src/google/protobuf/io/gzip_stream.cc",
+    "protobuf/src/google/protobuf/io/io_win32.cc",
     "protobuf/src/google/protobuf/io/printer.cc",
     "protobuf/src/google/protobuf/io/strtod.cc",
     "protobuf/src/google/protobuf/io/tokenizer.cc",
@@ -467,10 +470,6 @@
     "protobuf/src/google/protobuf/compiler/java/java_generator_factory.h",
     "protobuf/src/google/protobuf/compiler/java/java_helpers.cc",
     "protobuf/src/google/protobuf/compiler/java/java_helpers.h",
-    "protobuf/src/google/protobuf/compiler/java/java_lazy_message_field.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_lazy_message_field.h",
-    "protobuf/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h",
     "protobuf/src/google/protobuf/compiler/java/java_map_field.cc",
     "protobuf/src/google/protobuf/compiler/java/java_map_field.h",
     "protobuf/src/google/protobuf/compiler/java/java_map_field_lite.cc",