Allow a C++ runtime dependency in libssl

I believe the original blocker, gRPC, is now cleared. While I'm here,
make check_imported_libraries print all errors, rather than the first
one. (Though if this sticks, we can probably remove this script. It was
only needed for the C++ runtime check.)

Update-Note: libssl now requires a C++ runtime, in addition to the
pre-existing C++ requirement. Contact the BoringSSL team if this
causes an issue. Some projects may need to switch the final link to
use a C++ linker rather than a C linker.

Change-Id: I94808bf1dad6695ef334e262f3d2426caab0520e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/66288
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5933f02..77ba873 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,14 +59,6 @@
   endif()
 endif()
 
-if(USE_CUSTOM_LIBCXX)
-  set(BORINGSSL_ALLOW_CXX_RUNTIME 1)
-endif()
-
-if(BORINGSSL_ALLOW_CXX_RUNTIME)
-  add_definitions(-DBORINGSSL_ALLOW_CXX_RUNTIME)
-endif()
-
 string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
 if(NOT FIPS)
   if(CMAKE_BUILD_TYPE_LOWER STREQUAL "relwithassert" OR
@@ -177,10 +169,6 @@
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS} -Wmissing-prototypes -Wold-style-definition -Wstrict-prototypes")
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_CXX_FLAGS} -Wmissing-declarations")
 
-  if(NOT MSVC AND NOT BORINGSSL_ALLOW_CXX_RUNTIME)
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
-  endif()
-
   # In GCC, -Wmissing-declarations is the C++ spelling of -Wmissing-prototypes
   # and using the wrong one is an error. In Clang, -Wmissing-prototypes is the
   # spelling for both and -Wmissing-declarations is some other warning.
diff --git a/ssl/internal.h b/ssl/internal.h
index c9facb6..d9972dc 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -227,22 +227,10 @@
   return UniquePtr<T>(New<T>(std::forward<Args>(args)...));
 }
 
-#if defined(BORINGSSL_ALLOW_CXX_RUNTIME)
+// TODO(davidben): Remove these macros after April 2024, once the C++ runtime
+// dependency has stuck.
 #define HAS_VIRTUAL_DESTRUCTOR
 #define PURE_VIRTUAL = 0
-#else
-// HAS_VIRTUAL_DESTRUCTOR should be declared in any base class which defines a
-// virtual destructor. This avoids a dependency on |_ZdlPv| and prevents the
-// class from being used with |delete|.
-#define HAS_VIRTUAL_DESTRUCTOR \
-  void operator delete(void *) { abort(); }
-
-// PURE_VIRTUAL should be used instead of = 0 when defining pure-virtual
-// functions. This avoids a dependency on |__cxa_pure_virtual| but loses
-// compile-time checking.
-#define PURE_VIRTUAL \
-  { abort(); }
-#endif
 
 // Array<T> is an owning array of elements of |T|.
 template <typename T>
diff --git a/util/check_imported_libraries.go b/util/check_imported_libraries.go
index f3803f1..c7aa69f 100644
--- a/util/check_imported_libraries.go
+++ b/util/check_imported_libraries.go
@@ -23,36 +23,49 @@
 	"debug/elf"
 	"fmt"
 	"os"
+	"path/filepath"
 )
 
-func checkImportedLibraries(path string) {
+func checkImportedLibraries(path string) bool {
 	file, err := elf.Open(path)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "Error opening %s: %s\n", path, err)
-		os.Exit(1)
+		return false
 	}
 	defer file.Close()
 
 	libs, err := file.ImportedLibraries()
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "Error reading %s: %s\n", path, err)
-		os.Exit(1)
+		return false
 	}
 
+	allowCpp := filepath.Base(path) == "libssl.so"
 	for _, lib := range libs {
-		if lib != "libc.so.6" && lib != "libcrypto.so" && lib != "libpthread.so.0" {
-			fmt.Printf("Invalid dependency for %s: %s\n", path, lib)
-			fmt.Printf("All dependencies:\n")
-			for _, lib := range libs {
-				fmt.Printf("    %s\n", lib)
-			}
-			os.Exit(1)
+		if lib == "libc.so.6" || lib == "libcrypto.so" || lib == "libpthread.so.0" || lib == "libgcc_s.so.1" {
+			continue
 		}
+		if allowCpp && lib == "libstdc++.so.6" {
+			continue
+		}
+		fmt.Printf("Invalid dependency for %s: %s\n", path, lib)
+		fmt.Printf("All dependencies:\n")
+		for _, lib := range libs {
+			fmt.Printf("    %s\n", lib)
+		}
+		return false
 	}
+	return true
 }
 
 func main() {
+	ok := true
 	for _, path := range os.Args[1:] {
-		checkImportedLibraries(path)
+		if !checkImportedLibraries(path) {
+			ok = false
+		}
+	}
+	if !ok {
+		os.Exit(1)
 	}
 }