diff --git a/Dockerfile b/Dockerfile index 8b09023c..6adb6e2d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ # # Base image # -FROM ubuntu:xenial +FROM ubuntu:focal # # Dependencies @@ -27,12 +27,11 @@ FROM ubuntu:xenial # Kitware installs CMake v3.20.5 RUN apt-get update && apt-get install -y software-properties-common apt-transport-https ca-certificates gnupg wget && \ - add-apt-repository -y ppa:openjdk-r/ppa && \ test -f /usr/share/doc/kitware-archive-keyring/copyright || \ wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null \ | gpg --dearmor - \ | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null && \ - echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ xenial main' \ + echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' \ | tee /etc/apt/sources.list.d/kitware.list >/dev/null && \ apt-get update && \ apt-get install kitware-archive-keyring @@ -82,7 +81,7 @@ RUN git clone --depth=1 -b curl-8_10_1 https://github.com/curl/curl.git /tmp/cur RUN git clone --depth=1 -b v2.1.2 https://github.com/gflags/gflags.git /tmp/gflags && \ cd /tmp/gflags && \ mkdir build && cd build && \ - cmake -DCMAKE_CXX_FLAGS=-fpic -DGFLAGS_NAMESPACE=google .. && \ + cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_CXX_FLAGS=-fpic -DGFLAGS_NAMESPACE=google .. && \ make -j && make install && \ cd ~ && rm -rf /tmp/gflags @@ -94,46 +93,62 @@ RUN mkdir /tmp/glog && cd /tmp/glog && \ cd ~ && rm -rf /tmp/glog # gRPC & protobuf - build using CMake -# Use the protobuf version from gRPC for everything to avoid conflicting -# versions to be linked in. Disable OpenSSL embedding: when it's on, the build +# Disable OpenSSL embedding: when it's on, the build # process of gRPC puts the OpenSSL static object files into the gRPC archive # which causes link errors later when the agent is linked with the static # OpenSSL library itself. # Limit the number of threads used by make, as unlimited threads causes # memory exhausted error on the Kokoro VM. -# -DCMAKE_CXX_STANDARD=11 is necessary since it is the minimum version supported -# by gRPC dependencies. Xenial sets default version to c++98. +# -DCMAKE_CXX_STANDARD=17 is necessary since it is the minimum version supported +# by gRPC dependencies. # -# See https://github.com/grpc/grpc/blob/v1.46.7/test/distrib/cpp/run_distrib_test_cmake_pkgconfig.sh -RUN git clone --depth=1 --recursive -b v1.46.7 https://github.com/grpc/grpc.git /tmp/grpc && \ +# See https://github.com/grpc/grpc/blob/v1.66.0/test/distrib/cpp/run_distrib_test_cmake_pkgconfig.sh +RUN git clone --depth=1 --recursive -b v1.66.0 https://github.com/grpc/grpc.git /tmp/grpc && \ cd /tmp/grpc/ && \ - # Install protobuf - mkdir -p third_party/protobuf/cmake/build && \ - (cd third_party/protobuf/cmake/build && \ - cmake -Dprotobuf_BUILD_TESTS=OFF -DCMAKE_CXX_STANDARD=11 -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -DCMAKE_BUILD_TYPE=Release .. && \ - make -j4 install) && \ - # Install finish - protobuf - # Install gRPC + # Modern Protobuf (v22+) depends on Abseil. To prevent symbol conflicts and undefined references + # when gRPC links against Protobuf, Abseil must be built and installed as a shared system package + # first from gRPC's submodule. Then both Protobuf and gRPC consume it via package (-D..._ABSL_PROVIDER=package). + # Protobuf CMakeLists.txt moved to repo root in newer releases, so we build in third_party/protobuf/build. + # Step 1: Install Abseil as a shared package first + mkdir -p third_party/abseil-cpp/build && \ + (cd third_party/abseil-cpp/build && \ + cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DABSL_BUILD_TESTING=OFF -DABSL_ENABLE_INSTALL=ON -DCMAKE_CXX_STANDARD=17 -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_LIBDIR=lib .. && \ + make -j8 install) && \ + # Step 2: Install Protobuf (using shared Abseil package) + mkdir -p third_party/protobuf/build && \ + (cd third_party/protobuf/build && \ + cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_ABSL_PROVIDER=package -DCMAKE_CXX_STANDARD=17 -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_LIBDIR=lib .. && \ + make -j8 install) && \ + # Step 3: Install RE2 and generate re2.pc using RE2's official Makefile target (bundled version in gRPC v1.66.0 lacks CMake .pc generation) + mkdir -p third_party/re2/build && \ + (cd third_party/re2/build && \ + cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DRE2_BUILD_TESTING=OFF -DCMAKE_CXX_STANDARD=17 -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_LIBDIR=lib .. && \ + make -j8 install && \ + make -C .. common-install prefix=/usr/local) && \ + # Step 4: Install gRPC (using shared Abseil, Protobuf, and RE2 packages) mkdir -p cmake/build && \ (cd cmake/build && \ cmake \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DOPENSSL_ROOT_DIR=/usr/local/ssl \ -DOPENSSL_INCLUDE_DIR=/usr/local/ssl/include \ -DOPENSSL_CRYPTO_LIB=/usr/local/ssl/lib \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_CXX_STANDARD=11 \ + -DCMAKE_CXX_STANDARD=17 \ -DCMAKE_INSTALL_PREFIX=/usr/local/grpc \ + -DCMAKE_INSTALL_LIBDIR=lib \ -DgRPC_INSTALL=ON \ -DgRPC_BUILD_TESTS=OFF \ - -DgRPC_ABSL_PROVIDER=module \ + -DgRPC_ABSL_PROVIDER=package \ -DgRPC_CARES_PROVIDER=module \ - -DgRPC_RE2_PROVIDER=module \ + -DgRPC_RE2_PROVIDER=package \ -DgRPC_ZLIB_PROVIDER=module \ -DgRPC_PROTOBUF_PROVIDER=package \ -DgRPC_SSL_PROVIDER=package \ ../.. && \ - make -j4 install) && \ + make -j8 install) && \ cd ~ && rm -rf /tmp/grpc -ENV PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/local/ssl/lib/pkgconfig:/usr/local/grpc/lib/pkgconfig:/usr/local/lib64/pkgconfig" +# Add /usr/local/grpc/lib64/pkgconfig and /usr/local/lib/pkgconfig as 64-bit builds on Focal may install .pc files there. +ENV PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/local/ssl/lib/pkgconfig:/usr/local/grpc/lib/pkgconfig:/usr/local/grpc/lib64/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/lib64/pkgconfig:/usr/local/lib/x86_64-linux-gnu/pkgconfig:/usr/local/share/pkgconfig" ENV PATH="${PATH}:/usr/local/grpc/bin" diff --git a/Dockerfile.alpine b/Dockerfile.alpine index 90fcd9df..83465b95 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -67,7 +67,7 @@ RUN git clone --depth=1 -b curl-8_10_1 https://github.com/curl/curl.git /tmp/cur RUN git clone --depth=1 -b v2.1.2 https://github.com/gflags/gflags.git /tmp/gflags && \ cd /tmp/gflags && \ mkdir build && cd build && \ - cmake -DCMAKE_CXX_FLAGS=-fpic -DGFLAGS_NAMESPACE=google .. && \ + cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_CXX_FLAGS=-fpic -DGFLAGS_NAMESPACE=google .. && \ make -j && make install && \ cd ~ && rm -rf /tmp/gflags @@ -88,34 +88,53 @@ RUN mkdir /tmp/glog && cd /tmp/glog && \ # Limit the number of threads used by make, as unlimited threads causes # memory exhausted error on the Kokoro VM. # -# See https://github.com/grpc/grpc/blob/v1.46.7/test/distrib/cpp/run_distrib_test_cmake_pkgconfig.sh -RUN git clone --depth=1 --recursive -b v1.46.7 https://github.com/grpc/grpc.git /tmp/grpc && \ +# See https://github.com/grpc/grpc/blob/v1.66.0/test/distrib/cpp/run_distrib_test_cmake_pkgconfig.sh +RUN git clone --depth=1 --recursive -b v1.66.0 https://github.com/grpc/grpc.git /tmp/grpc && \ cd /tmp/grpc/ && \ - # Install protobuf - mkdir -p third_party/protobuf/cmake/build && \ - (cd third_party/protobuf/cmake/build && \ - cmake -Dprotobuf_BUILD_TESTS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -DCMAKE_BUILD_TYPE=Release .. && \ - make -j4 install) && \ - # Install gRPC + # Modern Protobuf (v22+) depends on Abseil. To prevent symbol conflicts and undefined references + # when gRPC links against Protobuf, Abseil must be built and installed as a shared system package + # first from gRPC's submodule. Then both Protobuf and gRPC consume it via package (-D..._ABSL_PROVIDER=package). + # Protobuf CMakeLists.txt moved to repo root in newer releases, so we build in third_party/protobuf/build. + # Step 1: Install Abseil as a shared package first + mkdir -p third_party/abseil-cpp/build && \ + (cd third_party/abseil-cpp/build && \ + cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DABSL_BUILD_TESTING=OFF -DABSL_ENABLE_INSTALL=ON -DCMAKE_CXX_STANDARD=17 -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_LIBDIR=lib .. && \ + make -j8 install) && \ + # Step 2: Install Protobuf (using shared Abseil package) + mkdir -p third_party/protobuf/build && \ + (cd third_party/protobuf/build && \ + cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_ABSL_PROVIDER=package -DCMAKE_CXX_STANDARD=17 -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_LIBDIR=lib .. && \ + make -j8 install) && \ + # Step 3: Install RE2 and generate re2.pc using RE2's official Makefile target (bundled version in gRPC v1.66.0 lacks CMake .pc generation) + mkdir -p third_party/re2/build && \ + (cd third_party/re2/build && \ + cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DRE2_BUILD_TESTING=OFF -DCMAKE_CXX_STANDARD=17 -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_LIBDIR=lib .. && \ + make -j8 install && \ + make -C .. common-install prefix=/usr/local) && \ + # Step 4: Install gRPC (using shared Abseil, Protobuf, and RE2 packages) mkdir -p cmake/build && \ - cd cmake/build && \ + (cd cmake/build && \ cmake \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DOPENSSL_ROOT_DIR=/usr/local/ssl \ -DOPENSSL_INCLUDE_DIR=/usr/local/ssl/include \ -DOPENSSL_CRYPTO_LIB=/usr/local/ssl/lib \ -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_STANDARD=17 \ -DCMAKE_INSTALL_PREFIX=/usr/local/grpc \ + -DCMAKE_INSTALL_LIBDIR=lib \ -DgRPC_INSTALL=ON \ -DgRPC_BUILD_TESTS=OFF \ - -DgRPC_ABSL_PROVIDER=module \ + -DgRPC_ABSL_PROVIDER=package \ -DgRPC_CARES_PROVIDER=module \ - -DgRPC_RE2_PROVIDER=module \ + -DgRPC_RE2_PROVIDER=package \ -DgRPC_ZLIB_PROVIDER=module \ -DgRPC_PROTOBUF_PROVIDER=package \ -DgRPC_SSL_PROVIDER=package \ ../.. && \ - make -j4 install && \ + make -j8 install) && \ cd ~ && rm -rf /tmp/grpc -ENV PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/local/ssl/lib/pkgconfig:/usr/local/grpc/lib/pkgconfig:/usr/local/grpc/lib64/pkgconfig:/usr/local/lib64/pkgconfig" +# Add /usr/local/grpc/lib64/pkgconfig and /usr/local/lib/pkgconfig as 64-bit builds on Alpine may install .pc files there. +ENV PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/local/ssl/lib/pkgconfig:/usr/local/grpc/lib/pkgconfig:/usr/local/grpc/lib64/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/lib64/pkgconfig:/usr/local/lib/x86_64-linux-gnu/pkgconfig:/usr/local/share/pkgconfig" ENV PATH="${PATH}:/usr/local/grpc/bin" diff --git a/Makefile b/Makefile index 9bd1ede3..53982665 100644 --- a/Makefile +++ b/Makefile @@ -18,8 +18,9 @@ CC = g++ machine_type := $(shell uname -m) # -fpermissive used to bypass <:: errors from gcc 4.7 +# -std=c++17 is required by gRPC v1.58+ and modern Abseil dependencies. CFLAGS = \ - -std=c++11 \ + -std=c++17 \ -fpermissive \ -fPIC \ -Wall \ @@ -31,7 +32,7 @@ CFLAGS = \ -g0 \ -DSTANDALONE_BUILD \ -D_GNU_SOURCE \ - $(shell pkg-config --cflags protobuf grpc) + $(shell PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/local/ssl/lib/pkgconfig:/usr/local/grpc/lib/pkgconfig:/usr/local/grpc/lib64/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/lib64/pkgconfig:/usr/local/lib/x86_64-linux-gnu/pkgconfig:/usr/local/share/pkgconfig" pkg-config --cflags protobuf grpc++) ifeq ($(machine_type),$(filter $(machine_type),aarch64 arm64)) # Building on an ARM64 machine. @@ -69,6 +70,7 @@ INCLUDES = \ -I$(GENFILES_PATH) \ -I$(GENFILES_PATH)/third_party \ -I$(INCLUDE_PATH) \ + -I/usr/local/grpc/include \ -I$(PROTOBUF_INCLUDE_PATH) \ TARGET_AGENT = $(OUT_PATH)/profiler_java_agent.so @@ -77,6 +79,7 @@ TARGET_NOTICES = $(OUT_PATH)/NOTICES PROFILE_PROTO_SOURCES = \ $(GENFILES_PATH)/$(PROFILE_PROTO_PATH)/profile.pb.cc \ $(PROFILE_PROTO_PATH)/builder.cc \ + $(PROFILE_PROTO_PATH)/aslr.cc \ PROFILER_API_SOURCES = \ $(GENFILES_PATH)/google/api/annotations.pb.cc \ @@ -163,7 +166,9 @@ HEADERS = \ VERSION_SCRIPT = $(JAVA_AGENT_PATH)/cloud_profiler_java_agent.lds OPT_FLAGS = -O3 -LDFLAGS = -L/usr/local/lib -static-libstdc++ -shared $(shell pkg-config --libs --static protobuf grpc++) +# Static libraries for Protobuf, gRPC, and Abseil are wrapped in -Wl,--start-group ... -Wl,--end-group +# to resolve cyclic symbol dependencies between generated protobuf code, gRPC, and Abseil logging/debugging internals. +LDFLAGS = -L/usr/local/lib -L/usr/local/grpc/lib -L/usr/local/grpc/lib64 -static-libstdc++ -shared -Wl,--start-group $(shell PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/local/ssl/lib/pkgconfig:/usr/local/grpc/lib/pkgconfig:/usr/local/grpc/lib64/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/lib64/pkgconfig:/usr/local/lib/x86_64-linux-gnu/pkgconfig:/usr/local/share/pkgconfig" pkg-config --libs --static protobuf grpc++) -labsl_log_internal_message -labsl_log_internal_check_op -labsl_log_internal_nullguard -labsl_die_if_null -labsl_examine_stack -labsl_log_internal_format -labsl_log_internal_proto -labsl_log_internal_log_sink_set -labsl_log_sink -labsl_log_entry -labsl_log_globals -labsl_symbolize -labsl_stacktrace -labsl_debugging_internal -labsl_demangle_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_str_format_internal -labsl_strings -labsl_strings_internal -labsl_int128 -labsl_base -labsl_raw_logging_internal -labsl_spinlock_wait -labsl_throw_delegate -labsl_bad_optional_access -labsl_bad_variant_access -Wl,--end-group LDS_FLAGS = -Wl,-z,defs -Wl,--version-script=$(VERSION_SCRIPT) LIB_ROOT_PATH ?= /usr/local @@ -171,11 +176,15 @@ LIB_ROOT_PATH ?= /usr/local # Linking OpenSSL statically as different distributions have different version # of the libraries, including different soname. And we'd prefer to have a single # agent binary which runs everywhere. +# Static libssl.a, libcrypto.a, and -lz must come after libcurl.a to satisfy encryption and compression symbol requirements. LIBS1= \ -ldl \ -lrt \ -pthread \ $(LIB_ROOT_PATH)/lib/libcurl.a \ + $(LIB_ROOT_PATH)/ssl/lib/libssl.a \ + $(LIB_ROOT_PATH)/ssl/lib/libcrypto.a \ + -lz \ $(LIB_ROOT_PATH)/lib/libglog.a \ $(LIB_ROOT_PATH)/lib/libgflags.a \ diff --git a/src/cloud_env.cc b/src/cloud_env.cc index 5cd0d8f8..db692e79 100644 --- a/src/cloud_env.cc +++ b/src/cloud_env.cc @@ -90,11 +90,7 @@ std::string GceMetadataRequest(HTTPRequest* req, const std::string& path) { } const char* Getenv(const std::string& var) { -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) || ALPINE == 1 return secure_getenv(var.c_str()); -#else - return __secure_getenv(var.c_str()); -#endif } } // namespace diff --git a/src/cloud_env.h b/src/cloud_env.h index 5a58dfb5..cbefaf90 100644 --- a/src/cloud_env.h +++ b/src/cloud_env.h @@ -36,7 +36,7 @@ class CloudEnv { CloudEnv(const CloudEnv&) = delete; CloudEnv& operator=(const CloudEnv&) = delete; - virtual ~CloudEnv() {} + virtual ~CloudEnv() = default; // Returns the current cloud project ID. virtual std::string ProjectID(); diff --git a/src/globals.h b/src/globals.h index a5826223..d096c229 100644 --- a/src/globals.h +++ b/src/globals.h @@ -36,13 +36,17 @@ using std::string; // ALLOW_STD_STRING #define FRIEND_TEST(A, B) +#ifndef DISALLOW_COPY_AND_ASSIGN #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName &); \ void operator=(const TypeName &) +#endif // DISALLOW_COPY_AND_ASSIGN +#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ TypeName(); \ DISALLOW_COPY_AND_ASSIGN(TypeName) +#endif // DISALLOW_IMPLICIT_CONSTRUCTORS #ifndef CLOUD_PROFILER_AGENT_VERSION #define CLOUD_PROFILER_AGENT_VERSION "unknown" diff --git a/src/pem_roots.cc b/src/pem_roots.cc index c192ed41..4ff7b786 100644 --- a/src/pem_roots.cc +++ b/src/pem_roots.cc @@ -23,66 +23,150 @@ namespace profiler { // // We embed these in the source to avoid having to ship a separate file. -const char *const kPemRootCerts = R"|( -# Operating CA: DigiCert -# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust -# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust -# Label: "Baltimore CyberTrust Root" -# Serial: 33554617 -# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 -# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 -# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb +const char* const kPemRootCerts = R"|( +# Operating CA: Google Trust Services LLC +# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R1 +# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R1 +# Label: "GTS Root R1" +# Serial: 0203E5936F31B01349886BA217 +# MD5 Fingerprint: 05:FE:D0:BF:71:A8:A3:76:63:DA:01:E0:D8:52:DC:40 +# SHA1 Fingerprint: E5:8C:1C:C4:91:3B:38:63:4B:E9:10:6E:E3:AD:8E:6B:9D:D9:81:4A +# SHA256 Fingerprint: D9:47:43:2A:BD:E7:B7:FA:90:FC:2E:6B:59:10:1B:12:80:E0:E1:C7:E4:E4:0F:A3:C6:88:7F:FF:57:A7:F4:CF -----BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo +27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w +Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw +TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl +qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH +szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8 +Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk +MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 +wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p +aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN +VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID +AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb +C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe +QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy +h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4 +7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J +ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef +MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/ +Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT +6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ +0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm +2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb +bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c -----END CERTIFICATE----- -# Operating CA: DigiCert -# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Assured ID Root CA" -# Serial: 17154717934120587862167794914071425081 -# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72 -# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43 -# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c +# Operating CA: Google Trust Services LLC +# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R2 +# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R2 +# Label: "GTS Root R2" +# Serial: 0203E5AEC58D04251AAB1125AA +# MD5 Fingerprint=1E:39:C0:53:E6:1E:29:82:0B:CA:52:55:36:5D:57:DC +# SHA1 Fingerprint=9A:44:49:76:32:DB:DE:FA:D0:BC:FB:5A:7B:17:BD:9E:56:09:24:94 +# SHA256 Fingerprint=8D:25:CD:97:22:9D:BF:70:35:6B:DA:4E:B3:CC:73:40:31:E2:4C:F0:0F:AF:CF:D3:2D:C7:6E:B5:84:1C:7E:A8 -----BEGIN CERTIFICATE----- -MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c -JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP -mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ -wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 -VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ -AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB -AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun -pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC -dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf -fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm -NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx -H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt +nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY +6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu +MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k +RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg +f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV ++3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo +dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW +Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa +G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq +gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID +AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H +vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 +0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC +B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u +NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg +yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev +HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6 +xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR +TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg +JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV +7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl +6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL +-----END CERTIFICATE----- + +# Operating CA: Google Trust Services LLC +# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R3 +# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R3 +# Label: "GTS Root R3" +# Serial: 0203E5B882EB20F825276D3D66 +# MD5 Fingerprint: 3E:E7:9D:58:02:94:46:51:94:E5:E0:22:4A:8B:E7:73 +# SHA1 Fingerprint: ED:E5:71:80:2B:C8:92:B9:5B:83:3C:D2:32:68:3F:09:CD:A0:1E:46 +# SHA256 Fingerprint: 34:D8:A7:3E:E2:08:D9:BC:DB:0D:95:65:20:93:4B:4E:40:E6:94:82:59:6E:8B:6F:73:C8:42:6B:01:0A:6F:48 +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD +VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG +A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw +WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz +IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G +jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2 +4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7 +VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm +ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X +-----END CERTIFICATE----- + +# Operating CA: Google Trust Services LLC +# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R4 +# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R4 +# Label: "GTS Root R4" +# Serial: 0203E5C068EF631A9C72905052 +# MD5 Fingerprint=43:96:83:77:19:4D:76:B3:9D:65:52:E4:1D:22:A5:E8 +# SHA1 Fingerprint=77:D3:03:67:B5:E0:0C:15:F6:0C:38:61:DF:7C:E1:3B:92:46:4D:47 +# SHA256 Fingerprint=34:9D:FA:40:58:C5:E2:63:12:3B:39:8A:E7:95:57:3C:4E:13:13:C8:3F:E6:8F:93:55:6C:D5:E8:03:1B:3C:7D +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD +VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG +A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw +WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz +IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi +QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR +HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D +9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8 +p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD +-----END CERTIFICATE----- + +# Operating CA: Google Trust Services LLC +# Subject: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign +# Issuer: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign +# Label: "GlobalSign R4" +# Serial: 0203E57EF53F93FDA50921B2A6 +# MD5 Fingerprint: 26:29:F8:6D:E1:88:BF:A2:65:7F:AA:C4:CD:0F:7F:FC +# SHA1 Fingerprint: 6B:A0:B0:98:E1:71:EF:5A:AD:FE:48:15:80:77:10:F4:BD:6F:0B:28 +# SHA256 Fingerprint: B0:85:D7:0B:96:4F:19:1A:73:E4:AF:0D:54:AE:7A:0E:07:AA:FD:AF:9B:71:DD:08:62:13:8A:B7:32:5A:24:A2 +-----BEGIN CERTIFICATE----- +MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD +VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw +MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g +UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT +BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx +uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV +HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/ ++wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147 +bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm -----END CERTIFICATE----- # Operating CA: DigiCert @@ -140,36 +224,6 @@ JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv 6pZjamVFkpUBtA== -----END CERTIFICATE----- -# Operating CA: DigiCert -# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Global Root CA" -# Serial: 10944719598952040374951832963794454346 -# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e -# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36 -# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61 ------BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE----- # Operating CA: DigiCert # Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com @@ -226,37 +280,6 @@ oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 sycX -----END CERTIFICATE----- -# Operating CA: DigiCert -# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert High Assurance EV Root CA" -# Serial: 3553400076410547919724730734378100087 -# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a -# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25 -# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm -+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW -PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM -xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB -Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 -hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg -EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA -FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec -nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z -eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF -hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 -Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep -+OkuE6N36B9K ------END CERTIFICATE----- # Operating CA: DigiCert # Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com @@ -299,287 +322,6 @@ r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ -----END CERTIFICATE----- -# Operating CA: Entrust Datacard -# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. -# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. -# Label: "Entrust Root Certification Authority" -# Serial: 1164660820 -# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 -# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 -# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c ------BEGIN CERTIFICATE----- -MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 -Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW -KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw -NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw -NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy -ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV -BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo -Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 -4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 -KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI -rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi -94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB -sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi -gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo -kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE -vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t -O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua -AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP -9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ -eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m -0vdXcDazv/wor3ElhVsT/h5/WrQ8 ------END CERTIFICATE----- - -# Operating CA: Entrust Datacard -# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only -# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only -# Label: "Entrust Root Certification Authority - EC1" -# Serial: 51543124481930649114116133369 -# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc -# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47 -# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5 ------BEGIN CERTIFICATE----- -MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG -A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 -d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu -dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq -RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy -MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD -VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 -L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g -Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi -A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt -ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH -Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O -BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC -R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX -hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G ------END CERTIFICATE----- - -# Operating CA: Entrust Datacard -# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only -# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only -# Label: "Entrust Root Certification Authority - G2" -# Serial: 1246989352 -# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2 -# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4 -# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39 ------BEGIN CERTIFICATE----- -MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 -cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs -IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz -dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy -NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu -dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt -dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 -aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T -RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN -cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW -wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 -U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 -jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP -BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN -BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ -jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ -Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v -1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R -nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH -VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== ------END CERTIFICATE----- - -# Operating CA: Entrust Datacard -# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Label: "Entrust.net Premium 2048 Secure Server CA" -# Serial: 946069240 -# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90 -# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31 -# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77 ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 -MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq -K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe -sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX -MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT -XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ -HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH -4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub -j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo -U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf -zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b -u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ -bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er -fF6adulZkMV8gzURZVE= ------END CERTIFICATE----- - -# Operating CA: Entrust Datacard -# Issuer: CN=AffirmTrust Commercial O=AffirmTrust -# Subject: CN=AffirmTrust Commercial O=AffirmTrust -# Label: "AffirmTrust Commercial" -# Serial: 8608355977964138876 -# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7 -# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7 -# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7 ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP -Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr -ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL -MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 -yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr -VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ -nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG -XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj -vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt -Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g -N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC -nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ------END CERTIFICATE----- - -# Operating CA: Entrust Datacard -# Issuer: CN=AffirmTrust Networking O=AffirmTrust -# Subject: CN=AffirmTrust Networking O=AffirmTrust -# Label: "AffirmTrust Networking" -# Serial: 8957382827206547757 -# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f -# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f -# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y -YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua -kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL -QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp -6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG -yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i -QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO -tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu -QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ -Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u -olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 -x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ------END CERTIFICATE----- - -# Operating CA: Entrust Datacard -# Issuer: CN=AffirmTrust Premium O=AffirmTrust -# Subject: CN=AffirmTrust Premium O=AffirmTrust -# Label: "AffirmTrust Premium" -# Serial: 7893706540734352110 -# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57 -# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27 -# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz -dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG -A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U -cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf -qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ -JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ -+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS -s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 -HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 -70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG -V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S -qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S -5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia -C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX -OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE -FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 -KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B -8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ -MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc -0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ -u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF -u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH -YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 -GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO -RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e -KeC2uAloGRwYQw== ------END CERTIFICATE----- - -# Operating CA: Entrust Datacard -# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust -# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust -# Label: "AffirmTrust Premium ECC" -# Serial: 8401224907861490260 -# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d -# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb -# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23 ------BEGIN CERTIFICATE----- -MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC -VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ -cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ -BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt -VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D -0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 -ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G -A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs -aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I -flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== ------END CERTIFICATE----- - -# Operating CA: GlobalSign -# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA -# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA -# Label: "GlobalSign Root CA" -# Serial: 4835703278459707669005204 -# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a -# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c -# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 ------BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG -A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw -MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i -YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT -aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ -jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp -xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp -1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG -snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ -U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 -9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B -AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz -yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE -38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP -AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad -DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME -HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== ------END CERTIFICATE----- - # Operating CA: GlobalSign # Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 # Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 @@ -740,138 +482,6 @@ pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 -----END CERTIFICATE----- -# Operating CA: GoDaddy -# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority -# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority -# Label: "Starfield Class 2 CA" -# Serial: 0 -# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24 -# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a -# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58 ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl -MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp -U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw -NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE -ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp -ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 -DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf -8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN -+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 -X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa -K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA -1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G -A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR -zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 -YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD -bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w -DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 -L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D -eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl -xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp -VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY -WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= ------END CERTIFICATE----- - -# Operating CA: GoDaddy -# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority -# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority -# Label: "Go Daddy Class 2 CA" -# Serial: 0 -# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67 -# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4 -# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4 ------BEGIN CERTIFICATE----- -MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh -MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE -YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 -MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo -ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg -MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN -ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA -PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w -wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi -EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY -avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ -YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE -sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h -/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 -IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD -ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy -OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P -TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ -HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER -dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf -ReYNnyicsbkqWletNw+vHX/bvZ8= ------END CERTIFICATE----- - -# Operating CA: Sectigo -# Issuer: CN=AAA Certificate Services O=Comodo CA Limited -# Subject: CN=AAA Certificate Services O=Comodo CA Limited -# Label: "Comodo AAA Services root" -# Serial: 1 -# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0 -# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49 -# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4 ------BEGIN CERTIFICATE----- -MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj -YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM -GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua -BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe -3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 -YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR -rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm -ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU -oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v -QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t -b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF -AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q -GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz -Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 -G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi -l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 -smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== ------END CERTIFICATE----- - -# Operating CA: Sectigo -# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO Certification Authority O=COMODO CA Limited -# Label: "COMODO Certification Authority" -# Serial: 43390818032842818540635488309124489234 -# MD5 Fingerprint: 20:E7:4F:82:C2:7E:94:80:34:82:8A:13:A9:17:1D:97 -# SHA1 Fingerprint EE:86:93:87:FF:FD:83:49:AB:5A:D1:43:22:58:87:89:A4:57:B0:12 -# SHA256 Fingerprint: 1A:0D:20:44:5D:E5:BA:18:62:D1:9E:F8:80:85:8C:BC:E5:01:02:B3:6E:8F:0A:04:0C:3C:69:E7:45:22:FE:6E ------BEGIN CERTIFICATE----- -MIID0DCCArigAwIBAgIQIKTEf93f4cdTYwcTiHdgEjANBgkqhkiG9w0BAQUFADCB -gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV -BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xMTAxMDEwMDAw -MDBaFw0zMDEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl -YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P -RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 -UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI -2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 -Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp -+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ -DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O -nKVIrLsm9wIDAQABo0IwQDAdBgNVHQ4EFgQUC1jli8ZMFTekQKkwqSG+RzZaVv8w -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD -ggEBAC/JxBwHO89hAgCx2SFRdXIDMLDEFh9sAIsQrK/xR9SuEDwMGvjUk2ysEDd8 -t6aDZK3N3w6HM503sMZ7OHKx8xoOo/lVem0DZgMXlUrxsXrfViEGQo+x06iF3u6X -HWLrp+cxEmbDD6ZLLkGC9/3JG6gbr+48zuOcrigHoSybJMIPIyaDMouGDx8rEkYl -Fo92kANr3ryqImhrjKGsKxE5pttwwn1y6TPn/CbxdFqR5p2ErPioBhlG5qfpqjQi -pKGfeq23sqSaM4hxAjwu1nqyH6LKwN0vEJT9s4yEIHlG1QXUEOTS22RPuFvuG8Ug -R1uUq27UlTMdphVx8fiUylQ5PsE= ------END CERTIFICATE----- - # Operating CA: Sectigo # Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited # Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited @@ -1008,149 +618,67 @@ L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG jjxDah2nGN59PRbxYvnKkKj9 -----END CERTIFICATE----- -# Operating CA: Google Trust Services LLC -# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R1 -# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R1 -# Label: "GTS Root R1" -# Serial: 0203E5936F31B01349886BA217 -# MD5 Fingerprint: 05:FE:D0:BF:71:A8:A3:76:63:DA:01:E0:D8:52:DC:40 -# SHA1 Fingerprint: E5:8C:1C:C4:91:3B:38:63:4B:E9:10:6E:E3:AD:8E:6B:9D:D9:81:4A -# SHA256 Fingerprint: D9:47:43:2A:BD:E7:B7:FA:90:FC:2E:6B:59:10:1B:12:80:E0:E1:C7:E4:E4:0F:A3:C6:88:7F:FF:57:A7:F4:CF ------BEGIN CERTIFICATE----- -MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw -CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw -MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo -27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w -Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw -TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl -qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH -szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8 -Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk -MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 -wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p -aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN -VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID -AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb -C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe -QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy -h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4 -7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J -ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef -MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/ -Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT -6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ -0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm -2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb -bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c ------END CERTIFICATE----- - -# Operating CA: Google Trust Services LLC -# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R2 -# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R2 -# Label: "GTS Root R2" -# Serial: 0203E5AEC58D04251AAB1125AA -# MD5 Fingerprint=1E:39:C0:53:E6:1E:29:82:0B:CA:52:55:36:5D:57:DC -# SHA1 Fingerprint=9A:44:49:76:32:DB:DE:FA:D0:BC:FB:5A:7B:17:BD:9E:56:09:24:94 -# SHA256 Fingerprint=8D:25:CD:97:22:9D:BF:70:35:6B:DA:4E:B3:CC:73:40:31:E2:4C:F0:0F:AF:CF:D3:2D:C7:6E:B5:84:1C:7E:A8 ------BEGIN CERTIFICATE----- -MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw -CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw -MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt -nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY -6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu -MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k -RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg -f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV -+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo -dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW -Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa -G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq -gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID -AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H -vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 -0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC -B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u -NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg -yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev -HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6 -xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR -TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg -JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV -7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl -6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL ------END CERTIFICATE----- - -# Operating CA: Google Trust Services LLC -# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R3 -# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R3 -# Label: "GTS Root R3" -# Serial: 0203E5B882EB20F825276D3D66 -# MD5 Fingerprint: 3E:E7:9D:58:02:94:46:51:94:E5:E0:22:4A:8B:E7:73 -# SHA1 Fingerprint: ED:E5:71:80:2B:C8:92:B9:5B:83:3C:D2:32:68:3F:09:CD:A0:1E:46 -# SHA256 Fingerprint: 34:D8:A7:3E:E2:08:D9:BC:DB:0D:95:65:20:93:4B:4E:40:E6:94:82:59:6E:8B:6F:73:C8:42:6B:01:0A:6F:48 ------BEGIN CERTIFICATE----- -MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD -VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG -A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw -WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz -IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi -AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G -jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2 -4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7 -VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm -ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X ------END CERTIFICATE----- - -# Operating CA: Google Trust Services LLC -# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R4 -# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R4 -# Label: "GTS Root R4" -# Serial: 0203E5C068EF631A9C72905052 -# MD5 Fingerprint=43:96:83:77:19:4D:76:B3:9D:65:52:E4:1D:22:A5:E8 -# SHA1 Fingerprint=77:D3:03:67:B5:E0:0C:15:F6:0C:38:61:DF:7C:E1:3B:92:46:4D:47 -# SHA256 Fingerprint=34:9D:FA:40:58:C5:E2:63:12:3B:39:8A:E7:95:57:3C:4E:13:13:C8:3F:E6:8F:93:55:6C:D5:E8:03:1B:3C:7D ------BEGIN CERTIFICATE----- -MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD -VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG -A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw -WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz -IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi -AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi -QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR -HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D -9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8 -p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD ------END CERTIFICATE----- - -# Operating CA: Google Trust Services LLC -# Subject: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign -# Issuer: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign -# Label: "GlobalSign R4" -# Serial: 0203E57EF53F93FDA50921B2A6 -# MD5 Fingerprint: 26:29:F8:6D:E1:88:BF:A2:65:7F:AA:C4:CD:0F:7F:FC -# SHA1 Fingerprint: 6B:A0:B0:98:E1:71:EF:5A:AD:FE:48:15:80:77:10:F4:BD:6F:0B:28 -# SHA256 Fingerprint: B0:85:D7:0B:96:4F:19:1A:73:E4:AF:0D:54:AE:7A:0E:07:AA:FD:AF:9B:71:DD:08:62:13:8A:B7:32:5A:24:A2 ------BEGIN CERTIFICATE----- -MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD -VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh -bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw -MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g -UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT -BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx -uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV -HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/ -+wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147 -bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm +# Operating CA: SSL.com +# Issuer: CN=SSL.com Client RSA Root CA 2022 O=SSL Corporation +# Subject: CN=SSL.com Client RSA Root CA 2022 O=SSL Corporation +# Label: SSL.com Client RSA Root CA 2022 +# Serial Number: 76AFEE88931545B650539B809CA4DF9A +# SHA-1 Fingerprint: AA:59:70:E5:20:32:9F:CB:D0:D5:79:9F:FB:1B:82:1D:FD:1F:79:65 +# SHA-256 Fingerprint: 1D:4C:A4:A2:AB:21:D0:09:36:59:80:4F:C0:EB:21:75:A6:17:27:9B:56:A2:47:52:45:C9:51:7A:FE:B5:91:53 +-----BEGIN CERTIFICATE----- +MIIFjzCCA3egAwIBAgIQdq/uiJMVRbZQU5uAnKTfmjANBgkqhkiG9w0BAQsFADBR +MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSgwJgYDVQQD +DB9TU0wuY29tIENsaWVudCBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzEw +N1oXDTQ2MDgxOTE2MzEwNlowUTELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBD +b3Jwb3JhdGlvbjEoMCYGA1UEAwwfU1NMLmNvbSBDbGllbnQgUlNBIFJvb3QgQ0Eg +MjAyMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALhY20Yw+8k/48jw +ATM04tpIqBjpIG6a1wHh1SmPMLQjauTLYrC+4p8gvT5UoDlox4Y3ZnQGBu90K9rc +n4SpUi+Q0u5+fPulIq1vcEZnlj0p1KO7VnsUBFnBIWNEHrIfElyQh2UNiPYeiCLi +Y1S78zb41n/c2v8pNanGbg5pWz/YvoKHFXBdsMdcEg9jpjjNz3O5ww6JJjcbP2Ic +MmnRm9n/VZAx3rFj3c/FdHf874ghU78AMRomLAAwpV9s4+T2AIrKmIecdAN6i2bs +fv2jjzUlXHils6T7PW2pivBsiIKL/UrQb+TXo7SONEk4vs5F5dIcyl7CNxSLzWZW +Mzed5WvsQ5JkoELadW/AFez5ab00uYp7+hb7Vf5SIOgEBFZWZfU3RJjIikbpt6y4 +6L5ijlQ2W/c7cL9d7i26X95CGYbwf4vrCMvYvuoOQkKgNnNXF+0y6tCN6Acbm5no +xJpiBA5I9zwSuvdYwZqM6cewIzZWNB3LbNq6B4Qd/dGsn+bCie/DuWwYs2mHV1+1 +DDhbpyEkKjunNJGetFTqKE/TwaOL5OYr1fKdv5thACLd1ktEHz9dVv7enHjMmVuq +5L2620NLrUwmTKNNNIpsdDYT22L8m7IFgf+uPwzN9hui9DnnyvVMXPtUdzWAWsAS +oRMBM2c9nYGhqfWFJFiIeOf042hVAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8w +HwYDVR0jBBgwFoAU8DhClDSpPAB/Uu45pfdLDbxqfSMwHQYDVR0OBBYEFPA4QpQ0 +qTwAf1LuOaX3Sw28an0jMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOC +AgEAmU/b8OrWEfoq/cirbeQOc2LSQp8V/nxwUj9kh4IxP0VALuEinwZmKfyW0y2N +tjjH2fMnwVkpoIz2cyQPKCLXTmHdE93bnzJSk/tPzOo4PJhqA6sWryHRQq59RSvq +xM+KWZ+CcHY6+GImyRCXWEAkpC25LymAJ+GJa3LKSQhxN1MF8YDO00IC0vzC0ZQG +7gfi9oPif5/nu1bDW7/dlZMJHiTBzybNraSuwrRp56q17TeU6d3RY4VrmnpKVnbc +GYUo1OTGpNi4lkF30LRZ8UYFh4cCH2m5ghjQQ9km2hpnqNZ1durybQ5C/4gmom6E +/n5iG/DGPe3AHGrHkda4ADdJm7mEBaHNbjHWROpTi7pTmB2hkIrphfgb8pNYw8jc +miZPPiDPT0PzEIx/EGF6NsqqC33Mn0dEWa6llcaZU+MHaz1JELAY/10OhUMUS+dr +00q1smBh3GlJAiNd6JJxw5yfRWd5HtwyhrqqVTxkbzK1EEAV3nJAeOBucLtu6wno +OdmsupJ13UPKugGVrRqBKzrw48UvDBhNEMauwO3+BVJ/GQXLqa81CAw4IuT+VuVT +Pr/k1rPZCMM91TMygSTFqeFlEbgyMzBxGEkdGkXGmhSKWDkobvPLUblJJmR4A8eR +EYOpuZA0tm+qBZ6FKFeZvn8nBkliTaH8CeErRglMFJtWj0U= +-----END CERTIFICATE----- + +# Operating CA: SSL.com +# Issuer: CN=SSL.com Client ECC Root CA 2022 O=SSL Corporation +# Subject: CN=SSL.com Client ECC Root CA 2022 O=SSL Corporation +# Label: SSL.com Client ECC Root CA 2022 +# Serial Number: 76F8481EAEF03C701FE03F25540183D5 +# SHA-1 Fingerprint: 80:7B:1D:9D:65:72:3D:C7:56:F9:EC:C5:00:83:49:F6:F2:AC:F4:86 +# SHA-256 Fingerprint: AD:7D:D5:8D:03:AE:DB:22:A3:0B:50:84:39:49:20:CE:12:23:0C:2D:80:17:AD:9B:81:AB:04:07:9B:DD:02:6B +-----BEGIN CERTIFICATE----- +MIICQDCCAcagAwIBAgIQdvhIHq7wPHAf4D8lVAGD1TAKBggqhkjOPQQDAzBRMQsw +CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSgwJgYDVQQDDB9T +U0wuY29tIENsaWVudCBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzAzMloX +DTQ2MDgxOTE2MzAzMVowUTELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw +b3JhdGlvbjEoMCYGA1UEAwwfU1NMLmNvbSBDbGllbnQgRUNDIFJvb3QgQ0EgMjAy +MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABC1Tfp+LPrM2ulDizOvcuiaK04wGP2cP +7/UX5dSumkYqQQEHaedncfHCAzbG8CtSjs8UkmikPnBREmmNeKKCyikUwOSUIrJE +kmBvyASkZ9Wi0PPQ1+qOPA+60kBHkDTufaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAf +BgNVHSMEGDAWgBS3/i1ixYFTzVIaL11goMNd+7IcHDAdBgNVHQ4EFgQUt/4tYsWB +U81SGi9dYKDDXfuyHBwwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUC +ME0HES0R+7kmwyHdcuEX/MHPFOpJznGHjtZT3BHNXVSKr9kt9IxR6rxmR+J/lYNg +ZQIxAIwhTE+75bBQ35BiSebMkdv4P11xkQiOT5LJf6Zc6hN+7W3E6MMqb1wR4aXz +alqaTQ== -----END CERTIFICATE----- )|"; // end kPemRootCerts diff --git a/src/profiler.cc b/src/profiler.cc index 95943284..e390af85 100644 --- a/src/profiler.cc +++ b/src/profiler.cc @@ -297,7 +297,7 @@ bool WallProfiler::Collect() { pid_t my_tid = GetTid(); Clock *clock = DefaultClock(); - struct timespec profile_period = {0, period_nanos_}; + struct timespec profile_period = NanosToTimeSpec(period_nanos_); struct timespec finish_line = TimeAdd(clock->Now(), NanosToTimeSpec(duration_nanos_)); diff --git a/src/profiler.h b/src/profiler.h index 5d4f9122..373be04a 100644 --- a/src/profiler.h +++ b/src/profiler.h @@ -30,7 +30,7 @@ namespace profiler { class SignalHandler { public: - SignalHandler() {} + SignalHandler() = default; // This type is neither copyable nor movable. SignalHandler(const SignalHandler &) = delete; @@ -56,7 +56,7 @@ class Profiler { Profiler(const Profiler &) = delete; Profiler &operator=(const Profiler &) = delete; - virtual ~Profiler() {} + virtual ~Profiler() = default; // Collect performance data. // Implicitly does a Reset() before starting collection. diff --git a/src/proto.cc b/src/proto.cc index 31c4218e..234c94dc 100644 --- a/src/proto.cc +++ b/src/proto.cc @@ -26,6 +26,7 @@ #include #include "perftools/profiles/proto/builder.h" +#include "absl/types/span.h" #include "third_party/javaprofiler/display.h" #include "third_party/javaprofiler/stacktrace_fixer.h" @@ -41,7 +42,7 @@ class ProfileProtoBuilder { const google::javaprofiler::NativeProcessInfo &native_info) : jvmti_(jvmti), native_info_(native_info) { for (const auto &it : google::javaprofiler::AttributeTable::GetStrings()) { - builder_.StringId(it.c_str()); + builder_.StringId(it); } } @@ -68,7 +69,7 @@ class ProfileProtoBuilder { } private: - void AddSample(const std::vector &locations, int64_t count, + void AddSample(absl::Span locations, int64_t count, int64_t weight, int64_t attr); uint64_t LocationID(JNIEnv *jni, const google::javaprofiler::JVMPI_CallFrame &frame); @@ -227,7 +228,8 @@ void ProfileProtoBuilder::Populate( int64_t period_ns) { perftools::profiles::Profile *profile = builder_.mutable_profile(); - profile->mutable_period_type()->set_type(builder_.StringId(profile_type)); + profile->mutable_period_type()->set_type( + builder_.StringId(absl::NullSafeStringView(profile_type))); profile->mutable_period_type()->set_unit(builder_.StringId("nanoseconds")); profile->set_period(period_ns); perftools::profiles::ValueType *sample_type = profile->add_sample_type(); @@ -235,10 +237,12 @@ void ProfileProtoBuilder::Populate( sample_type->set_unit(builder_.StringId("count")); sample_type = profile->add_sample_type(); - sample_type->set_type(builder_.StringId(profile_type)); + sample_type->set_type( + builder_.StringId(absl::NullSafeStringView(profile_type))); sample_type->set_unit(builder_.StringId("nanoseconds")); - profile->set_default_sample_type(builder_.StringId(profile_type)); + profile->set_default_sample_type( + builder_.StringId(absl::NullSafeStringView(profile_type))); profile->set_duration_nanos(duration_ns); @@ -259,11 +263,11 @@ void ProfileProtoBuilder::Populate( m->set_id(profile->mapping_size()); m->set_memory_start(mapping.start); m->set_memory_limit(mapping.limit); - m->set_filename(builder_.StringId(mapping.name.c_str())); + m->set_filename(builder_.StringId(mapping.name)); } } -void ProfileProtoBuilder::AddSample(const std::vector &locations, +void ProfileProtoBuilder::AddSample(absl::Span locations, int64_t count, int64_t weight, int64_t attr) { perftools::profiles::Profile *profile = builder_.mutable_profile(); diff --git a/src/string.cc b/src/string.cc index 7db47be4..e7f69036 100644 --- a/src/string.cc +++ b/src/string.cc @@ -14,6 +14,7 @@ #include "src/string.h" +#include #include #include #include diff --git a/src/throttler.h b/src/throttler.h index 81604048..e366fa91 100644 --- a/src/throttler.h +++ b/src/throttler.h @@ -43,7 +43,7 @@ constexpr char kTypeThreads[] = "threads"; // } class Throttler { public: - virtual ~Throttler() {} + virtual ~Throttler() = default; // Waits until the next profiling session can be taken. Once the call returns, // the client should collect the profile as soon as possible and upload its diff --git a/src/throttler_api.cc b/src/throttler_api.cc index 80f70ce9..77c05974 100644 --- a/src/throttler_api.cc +++ b/src/throttler_api.cc @@ -161,10 +161,13 @@ bool AbortedBackoffDuration(const grpc::ClientContext& ctx, int64_t* backoff_ns) { *backoff_ns = 0; auto md = ctx.GetServerTrailingMetadata(); - auto it = md.find(kRetryInfoMetadata); - if (it != md.end() && !it->second.empty()) { + auto eq_range = md.equal_range(kRetryInfoMetadata); + auto it = eq_range.first; + auto end = eq_range.second; + if (it != end && !it->second.empty()) { google::rpc::RetryInfo ri; - if (!ri.ParseFromArray(it->second.data(), it->second.size())) { + if (!ri.ParseFromString( + absl::string_view(it->second.data(), it->second.size()))) { return false; } const google::protobuf::Duration& delay = ri.retry_delay(); @@ -177,7 +180,7 @@ bool AbortedBackoffDuration(const grpc::ClientContext& ctx, // Initializes deployment information from environment properties and label // string in "name1=val1,name2=val2,..." format. Returns false on error. bool InitializeDeployment(CloudEnv* env, const std::string& labels, - const std::string& language, api::Deployment* d) { + absl::string_view language, api::Deployment* d) { std::string project_id = env->ProjectID(); if (project_id.empty()) { LOG(ERROR) << "Project ID is unknown"; diff --git a/src/uploader.h b/src/uploader.h index 6808c95c..4f321cfb 100644 --- a/src/uploader.h +++ b/src/uploader.h @@ -26,7 +26,7 @@ namespace profiler { class ProfileUploader { public: - virtual ~ProfileUploader() {} + virtual ~ProfileUploader() = default; virtual bool Upload(const std::string& profile_type, const std::string& profile) = 0; }; diff --git a/third_party/javaprofiler/accessors.cc b/third_party/javaprofiler/accessors.cc index de84c48b..df3a1616 100644 --- a/third_party/javaprofiler/accessors.cc +++ b/third_party/javaprofiler/accessors.cc @@ -19,9 +19,9 @@ namespace google { namespace javaprofiler { -__thread JNIEnv *Accessors::env_; +__thread JNIEnv* Accessors::env_; __thread int64_t Accessors::attr_; -__thread Tags *Accessors::tags_; +__thread Tags* Accessors::tags_; void Accessors::InitTags() { assert(tags_ == nullptr); @@ -29,7 +29,7 @@ void Accessors::InitTags() { } void Accessors::DestroyTags() { - const Tags *tags_tmp = tags_; + const Tags* tags_tmp = tags_; tags_ = nullptr; // The thread local storage tags_ is set to null before deallocation to avoid // getting the destructed object in the signal handler. The compiler barrier @@ -39,11 +39,11 @@ void Accessors::DestroyTags() { delete tags_tmp; } -Tags *Accessors::AllocateAndCopyTags() { +Tags* Accessors::AllocateAndCopyTags() { return tags_ == nullptr ? nullptr : new Tags(*tags_); } -void Accessors::ApplyAndDeleteTags(Tags *tags) { +void Accessors::ApplyAndDeleteTags(Tags* tags) { if (tags_ != nullptr) { *tags_ = std::move(*tags); } diff --git a/third_party/javaprofiler/accessors.h b/third_party/javaprofiler/accessors.h index bf360eca..d6f66042 100644 --- a/third_party/javaprofiler/accessors.h +++ b/third_party/javaprofiler/accessors.h @@ -28,8 +28,8 @@ namespace javaprofiler { // Accessors for a JNIEnv for this thread. class Accessors { public: - static void SetCurrentJniEnv(JNIEnv *env) { env_ = env; } - static JNIEnv *CurrentJniEnv() { return env_; } + static void SetCurrentJniEnv(JNIEnv* env) { env_ = env; } + static JNIEnv* CurrentJniEnv() { return env_; } static void SetAttribute(int64_t value) { attr_ = value; } static int64_t GetAttribute() { return attr_; } @@ -46,10 +46,10 @@ class Accessors { // For all Java threads, InitTags() is called inside the callback function of // onThreadStart. However, non-Java threads do not trigger the callback, // which leaves InitTags() not called. - static const Tags &GetTags() { + static const Tags& GetTags() { return tags_ == nullptr ? Tags::Empty() : *tags_; } - static Tags *GetMutableTags() { return tags_; } + static Tags* GetMutableTags() { return tags_; } // AllocateAndCopyTags() and ApplyAndDeleteTags() are used to propagate tags // between threads. The usage should be like: @@ -64,14 +64,14 @@ class Accessors { // Copies the thread-local tags. Returns the pointer of newly allocated Tags // on success; otherwise, return nullptr. - static Tags *AllocateAndCopyTags(); + static Tags* AllocateAndCopyTags(); // Overrides the thread-local tags with the tags passed in and releases the // memory pointed by tags. - static void ApplyAndDeleteTags(Tags *tags); + static void ApplyAndDeleteTags(Tags* tags); template - static inline FunctionType GetJvmFunction(const char *function_name) { - static void *handle = GetJvmLibHandle(); + static inline FunctionType GetJvmFunction(const char* function_name) { + static void* handle = GetJvmLibHandle(); if (handle == nullptr) { return nullptr; } @@ -81,8 +81,8 @@ class Accessors { } private: - static void *GetJvmLibHandle() { - void *handle = dlopen("libjvm.so", RTLD_LAZY); + static void* GetJvmLibHandle() { + void* handle = dlopen("libjvm.so", RTLD_LAZY); if (handle != nullptr) { return handle; } @@ -103,13 +103,13 @@ class Accessors { // in musl / Alpine, see // https://wiki.musl-libc.org/design-concepts.html#Thread-local-storage. #if defined(JAVAPROFILER_GLOBAL_DYNAMIC_TLS) || defined(ALPINE) - static __thread JNIEnv *env_ __attribute__((tls_model("global-dynamic"))); + static __thread JNIEnv* env_ __attribute__((tls_model("global-dynamic"))); static __thread int64_t attr_ __attribute__((tls_model("global-dynamic"))); - static __thread Tags *tags_ __attribute__((tls_model("global-dynamic"))); + static __thread Tags* tags_ __attribute__((tls_model("global-dynamic"))); #else - static __thread JNIEnv *env_ __attribute__((tls_model("initial-exec"))); + static __thread JNIEnv* env_ __attribute__((tls_model("initial-exec"))); static __thread int64_t attr_ __attribute__((tls_model("initial-exec"))); - static __thread Tags *tags_ __attribute__((tls_model("initial-exec"))); + static __thread Tags* tags_ __attribute__((tls_model("initial-exec"))); #endif }; diff --git a/third_party/javaprofiler/async_ref_counted_string.cc b/third_party/javaprofiler/async_ref_counted_string.cc index 31b38722..b42138c8 100644 --- a/third_party/javaprofiler/async_ref_counted_string.cc +++ b/third_party/javaprofiler/async_ref_counted_string.cc @@ -28,7 +28,7 @@ using StringRefCountTable = using StringRefCount = StringRefCountTable::value_type; // Maps string to its reference count. -std::unordered_map> *string_table = nullptr; +std::unordered_map>* string_table = nullptr; // All accesses to string_table should be protected by string_table_mutex. std::mutex string_table_mutex; @@ -48,7 +48,7 @@ std::mutex string_table_mutex; // Resolves the StringRefCount of a given string, increments the reference count // and returns the pointer of StringRefCount. It returns nullptr if the internal // string table is not initialized. -StringRefCount *AcquireByString(const std::string &str) { +StringRefCount* AcquireByString(const std::string& str) { std::lock_guard lock(string_table_mutex); if (string_table == nullptr) { return nullptr; @@ -59,7 +59,7 @@ StringRefCount *AcquireByString(const std::string &str) { // atomic copy constructor is deleted. Since gcc-4.8 is used in the docker // container to generate the cloud Java agent, use the pair's piecewise // constructor to make it compilable under gcc-4.8 - const auto &it = + const auto& it = string_table ->emplace(std::piecewise_construct, std::forward_as_tuple(str), std::forward_as_tuple(0)) @@ -71,7 +71,7 @@ StringRefCount *AcquireByString(const std::string &str) { // Increments the reference count of the given StringRefCount pointer if it is // not null, and returns the StringRefCount pointer. It is used to copy the // StringRefCount from another AsyncRefCountedString. -StringRefCount *AcquireByCopy(StringRefCount *str_ref_cnt) { +StringRefCount* AcquireByCopy(StringRefCount* str_ref_cnt) { if (str_ref_cnt != nullptr) { // As "other" already holds a valid StringRefCount, we can directly // increment the reference count by 1. If "other" is owned by another @@ -85,7 +85,7 @@ StringRefCount *AcquireByCopy(StringRefCount *str_ref_cnt) { // pointer. It is async-signal-safe. If the string is not referred by any other // AsyncRefCountedString and needs removing from the string table, it fails by // returning false. -bool AsyncSafeRelease(StringRefCount *str_ref_cnt) { +bool AsyncSafeRelease(StringRefCount* str_ref_cnt) { if (str_ref_cnt == nullptr) { return true; } @@ -103,7 +103,7 @@ bool AsyncSafeRelease(StringRefCount *str_ref_cnt) { // pointer. It firstly calls AsyncSafeRelease() to release the string. If // AsyncSafeRelease(), it acquires the lock of the string table to make it // succeed eventually. -void Release(StringRefCount *str_ref_cnt) { +void Release(StringRefCount* str_ref_cnt) { if (!AsyncSafeRelease(str_ref_cnt)) { std::lock_guard lock(string_table_mutex); if (str_ref_cnt->second.fetch_sub(1) == 1) { @@ -115,12 +115,12 @@ void Release(StringRefCount *str_ref_cnt) { } // namespace -AsyncRefCountedString::AsyncRefCountedString(const std::string &str) +AsyncRefCountedString::AsyncRefCountedString(const std::string& str) : AsyncRefCountedString() { Release(ptr_.exchange(AcquireByString(str))); } -AsyncRefCountedString::AsyncRefCountedString(const AsyncRefCountedString &other) +AsyncRefCountedString::AsyncRefCountedString(const AsyncRefCountedString& other) : AsyncRefCountedString() { Release(ptr_.exchange(AcquireByCopy(other.ptr_.load()))); } @@ -129,28 +129,28 @@ AsyncRefCountedString::~AsyncRefCountedString() { Release(ptr_.exchange(nullptr)); } -AsyncRefCountedString &AsyncRefCountedString::operator=( - const std::string &str) { +AsyncRefCountedString& AsyncRefCountedString::operator=( + const std::string& str) { Release(ptr_.exchange(AcquireByString(str))); return *this; } -AsyncRefCountedString &AsyncRefCountedString::operator=( - const AsyncRefCountedString &other) { +AsyncRefCountedString& AsyncRefCountedString::operator=( + const AsyncRefCountedString& other) { Release(ptr_.exchange(AcquireByCopy(other.ptr_.load()))); return *this; } -AsyncRefCountedString &AsyncRefCountedString::operator=( - AsyncRefCountedString &&other) { +AsyncRefCountedString& AsyncRefCountedString::operator=( + AsyncRefCountedString&& other) { Reset(); ptr_.store(other.ptr_); other.ptr_ = nullptr; return *this; } -AsyncRefCountedString &AsyncRefCountedString::AsyncSafeCopy( - const AsyncRefCountedString &other) { +AsyncRefCountedString& AsyncRefCountedString::AsyncSafeCopy( + const AsyncRefCountedString& other) { assert(ptr_.load() == nullptr); ptr_.exchange(AcquireByCopy(other.ptr_.load())); return *this; @@ -162,8 +162,8 @@ void AsyncRefCountedString::AsyncSafeReset() { assert(AsyncSafeRelease(ptr_.exchange(nullptr))); } -const std::string *AsyncRefCountedString::Get() const { - StringRefCount *str_ref_cnt = ptr_.load(); +const std::string* AsyncRefCountedString::Get() const { + StringRefCount* str_ref_cnt = ptr_.load(); if (str_ref_cnt == nullptr) { return nullptr; } else { diff --git a/third_party/javaprofiler/async_ref_counted_string.h b/third_party/javaprofiler/async_ref_counted_string.h index 63623efb..41e59c0e 100644 --- a/third_party/javaprofiler/async_ref_counted_string.h +++ b/third_party/javaprofiler/async_ref_counted_string.h @@ -47,27 +47,27 @@ namespace javaprofiler { class AsyncRefCountedString { public: AsyncRefCountedString() : ptr_(nullptr) {} - explicit AsyncRefCountedString(const std::string &str); - AsyncRefCountedString(const AsyncRefCountedString &other); + explicit AsyncRefCountedString(const std::string& str); + AsyncRefCountedString(const AsyncRefCountedString& other); ~AsyncRefCountedString(); - AsyncRefCountedString &operator=(const std::string &str); - AsyncRefCountedString &operator=(const AsyncRefCountedString &other); - AsyncRefCountedString &operator=(AsyncRefCountedString &&other); + AsyncRefCountedString& operator=(const std::string& str); + AsyncRefCountedString& operator=(const AsyncRefCountedString& other); + AsyncRefCountedString& operator=(AsyncRefCountedString&& other); // Async-signal-safe version of operator=(const AsyncRefCountedString &other). // It requires that the instance refers to nullptr (does not contain any // string). Otherwise, it asserts an error. - AsyncRefCountedString &AsyncSafeCopy(const AsyncRefCountedString &other); + AsyncRefCountedString& AsyncSafeCopy(const AsyncRefCountedString& other); // Tests whether the referred string equals the one in another // AsyncRefCountedString. As a specific string only has one internal copy, the // stored string address is directly used for comparison without checking the // string content. Async-signal-safe. - bool operator==(const AsyncRefCountedString &other) const { + bool operator==(const AsyncRefCountedString& other) const { return ptr_.load() == other.ptr_.load(); } // Async-signal-safe. - bool operator!=(const AsyncRefCountedString &other) const { + bool operator!=(const AsyncRefCountedString& other) const { return !(*this == other); } @@ -83,7 +83,7 @@ class AsyncRefCountedString { // Returns nullptr when it does not refer to any string. // The returned string pointer is valid as long as the AsyncRefCountedString // instance stay unchanged and it is async-signal-safe. - const std::string *Get() const; + const std::string* Get() const; // Returns the hash value. As a specific string only has one internal copy, // the stored string address is directly used as the hash value. @@ -104,7 +104,7 @@ class AsyncRefCountedString { private: // The value of ptr_ requires to be changed atomically so that // its value will not get corrupted upon interrupts. - std::atomic> *> ptr_; + std::atomic>*> ptr_; }; } // namespace javaprofiler diff --git a/third_party/javaprofiler/clock.cc b/third_party/javaprofiler/clock.cc index d6fe5718..0922190b 100644 --- a/third_party/javaprofiler/clock.cc +++ b/third_party/javaprofiler/clock.cc @@ -18,7 +18,7 @@ namespace google { namespace javaprofiler { namespace { - Clock DefaultClockInstance; +Clock DefaultClockInstance; } bool AlmostThere(Clock* clock, const struct timespec& finish, @@ -31,9 +31,7 @@ bool AlmostThere(Clock* clock, const struct timespec& finish, return TimeLessThan(finish, TimeAdd(now, laps)); } -Clock* DefaultClock() { - return &DefaultClockInstance; -} +Clock* DefaultClock() { return &DefaultClockInstance; } } // namespace javaprofiler } // namespace google diff --git a/third_party/javaprofiler/clock.h b/third_party/javaprofiler/clock.h index a096c563..61cdcaab 100644 --- a/third_party/javaprofiler/clock.h +++ b/third_party/javaprofiler/clock.h @@ -17,6 +17,7 @@ #ifndef GOOGLE_JAVAPROFILER_CLOCK_H_ #define GOOGLE_JAVAPROFILER_CLOCK_H_ +#include #include #include @@ -31,14 +32,14 @@ constexpr int64_t kNanosPerMilli = 1000 * 1000; inline struct timespec TimeAdd(const struct timespec t1, const struct timespec t2) { struct timespec t = {t1.tv_sec + t2.tv_sec, t1.tv_nsec + t2.tv_nsec}; - if (t.tv_nsec > kNanosPerSecond) { + if (t.tv_nsec >= kNanosPerSecond) { t.tv_sec += t.tv_nsec / kNanosPerSecond; t.tv_nsec = t.tv_nsec % kNanosPerSecond; } return t; } -inline bool TimeLessThan(const struct timespec &t1, const struct timespec &t2) { +inline bool TimeLessThan(const struct timespec& t1, const struct timespec& t2) { return (t1.tv_sec < t2.tv_sec) || (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec); } @@ -49,7 +50,7 @@ inline struct timespec NanosToTimeSpec(int64_t nanos) { return timespec{seconds, nano_seconds}; } -inline int64_t TimeSpecToNanos(const struct timespec &ts) { +inline int64_t TimeSpecToNanos(const struct timespec& ts) { return kNanosPerSecond * ts.tv_sec + ts.tv_nsec; } @@ -68,23 +69,24 @@ class Clock { // Blocks the current thread until the specified point in time. virtual void SleepUntil(struct timespec ts) { - while (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, nullptr) > 0) { + while (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, nullptr) == + EINTR) { } } // Blocks the current thread for the specified duration. virtual void SleepFor(struct timespec ts) { - while (clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts) > 0) { + while (clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts) == EINTR) { } } }; // Determines if there is time for another lap before reaching the finish line. // Uses a margin of multiple laps to ensure to not overrun the finish line. -bool AlmostThere(Clock *clock, const struct timespec &finish, - const struct timespec &lap); +bool AlmostThere(Clock* clock, const struct timespec& finish, + const struct timespec& lap); -Clock *DefaultClock(); +Clock* DefaultClock(); } // namespace javaprofiler } // namespace google diff --git a/third_party/javaprofiler/display.cc b/third_party/javaprofiler/display.cc index bbdc3783..f5a80f52 100644 --- a/third_party/javaprofiler/display.cc +++ b/third_party/javaprofiler/display.cc @@ -15,6 +15,7 @@ #include "third_party/javaprofiler/display.h" #include + #include #include "third_party/javaprofiler/stacktrace_fixer.h" @@ -26,7 +27,7 @@ namespace { // This method changes the standard class signature "Lfoo/bar;" format // to a more readable "foo.bar" format. -bool CleanJavaSignature(char *signature_ptr) { +bool CleanJavaSignature(char* signature_ptr) { size_t signature_length = strlen(signature_ptr); // ugh! if (signature_length < 3) { // I'm not going to even try. return false; @@ -50,16 +51,16 @@ const char kMethodIDUnknown[] = "UnknownMethodID"; // Since the method is unknown, associated signature is empty. const char kSignatureUnknown[] = ""; -void GetMethodName(jvmtiEnv *jvmti, jmethodID method_id, - std::string *method_name, std::string *signature) { +void GetMethodName(jvmtiEnv* jvmti, jmethodID method_id, + std::string* method_name, std::string* signature) { jint error; JvmtiScopedPtr signature_ptr(jvmti); JvmtiScopedPtr name_ptr(jvmti); // Get method name, put it in name_ptr if ((error = jvmti->GetMethodName(method_id, name_ptr.GetRef(), - signature_ptr.GetRef(), - nullptr)) == JVMTI_ERROR_NONE) { + signature_ptr.GetRef(), nullptr)) == + JVMTI_ERROR_NONE) { *method_name = name_ptr.Get(); *signature = signature_ptr.Get(); return; @@ -88,9 +89,9 @@ void GetMethodName(jvmtiEnv *jvmti, jmethodID method_id, *signature = kSignatureUnknown; } -void GetClassAndFileName(jvmtiEnv *jvmti, jmethodID method_id, - jclass declaring_class, std::string *file_name, - std::string *class_name) { +void GetClassAndFileName(jvmtiEnv* jvmti, jmethodID method_id, + jclass declaring_class, std::string* file_name, + std::string* class_name) { JvmtiScopedPtr source_name_ptr(jvmti); if (JVMTI_ERROR_NONE != jvmti->GetSourceFileName(declaring_class, source_name_ptr.GetRef())) { @@ -117,9 +118,9 @@ void GetClassAndFileName(jvmtiEnv *jvmti, jmethodID method_id, } } -void FillFieldsWithUnknown(std::string *file_name, std::string *class_name, - std::string *method_name, std::string *signature, - int *line_number) { +void FillFieldsWithUnknown(std::string* file_name, std::string* class_name, + std::string* method_name, std::string* signature, + int* line_number) { *file_name = kFileUnknown; *class_name = kClassUnknown; *method_name = kMethodUnknown; @@ -129,9 +130,9 @@ void FillFieldsWithUnknown(std::string *file_name, std::string *class_name, } } -void FillMethodSignatureAndLine(jvmtiEnv *jvmti, const JVMPI_CallFrame &frame, - std::string *method_name, - std::string *signature, int *line_number) { +void FillMethodSignatureAndLine(jvmtiEnv* jvmti, const JVMPI_CallFrame& frame, + std::string* method_name, + std::string* signature, int* line_number) { GetMethodName(jvmti, frame.method_id, method_name, signature); // frame.lineno is actually a bci if it is a Java method; Asgct is piggy @@ -144,7 +145,7 @@ void FillMethodSignatureAndLine(jvmtiEnv *jvmti, const JVMPI_CallFrame &frame, } // end namespace -jint GetLineNumber(jvmtiEnv *jvmti, jmethodID method, jlocation location) { +jint GetLineNumber(jvmtiEnv* jvmti, jmethodID method, jlocation location) { jint entry_count; JvmtiScopedPtr table_ptr_ctr(jvmti); jint line_number = -1; @@ -161,16 +162,16 @@ jint GetLineNumber(jvmtiEnv *jvmti, jmethodID method, jlocation location) { if (JVMTI_ERROR_ABSENT_INFORMATION == jvmti_error) { static bool no_debug_info = false; if (!no_debug_info) { - LOG(INFO) - << "No line number information was found in your bytecode." - " Some monitoring interfaces may report -1 ""for line numbers."; + LOG(INFO) << "No line number information was found in your bytecode." + " Some monitoring interfaces may report -1 " + "for line numbers."; no_debug_info = true; } } return -1; } - jvmtiLineNumberEntry *table_ptr = table_ptr_ctr.Get(); + jvmtiLineNumberEntry* table_ptr = table_ptr_ctr.Get(); if (entry_count == 1) { return table_ptr[0].line_number; } @@ -198,10 +199,10 @@ jint GetLineNumber(jvmtiEnv *jvmti, jmethodID method, jlocation location) { return -1; } -bool GetStackFrameElements(JNIEnv *jni, jvmtiEnv *jvmti, - const JVMPI_CallFrame &frame, std::string *file_name, - std::string *class_name, std::string *method_name, - std::string *signature, int *line_number) { +bool GetStackFrameElements(JNIEnv* jni, jvmtiEnv* jvmti, + const JVMPI_CallFrame& frame, std::string* file_name, + std::string* class_name, std::string* method_name, + std::string* signature, int* line_number) { if (!jvmti) { FillFieldsWithUnknown(file_name, class_name, method_name, signature, line_number); @@ -223,10 +224,10 @@ bool GetStackFrameElements(JNIEnv *jni, jvmtiEnv *jvmti, class_name, method_name, signature, line_number); } -bool GetStackFrameElements(jvmtiEnv *jvmti, const JVMPI_CallFrame &frame, - jclass declaring_class, std::string *file_name, - std::string *class_name, std::string *method_name, - std::string *signature, int *line_number) { +bool GetStackFrameElements(jvmtiEnv* jvmti, const JVMPI_CallFrame& frame, + jclass declaring_class, std::string* file_name, + std::string* class_name, std::string* method_name, + std::string* signature, int* line_number) { if (!jvmti) { FillFieldsWithUnknown(file_name, class_name, method_name, signature, line_number); diff --git a/third_party/javaprofiler/display.h b/third_party/javaprofiler/display.h index ffaccb87..7e1a9842 100644 --- a/third_party/javaprofiler/display.h +++ b/third_party/javaprofiler/display.h @@ -31,16 +31,16 @@ namespace javaprofiler { // Walks the line number table and return the associated Java line number from a // given method and location. // Returns -1 on error or for native methods. -jint GetLineNumber(jvmtiEnv *jvmti, jmethodID method, jlocation location); +jint GetLineNumber(jvmtiEnv* jvmti, jmethodID method, jlocation location); // Fill the file_name, class_name, method_name, and line_number parameters using // the information provided by the frame and using the JVMTI environment. // When unknown, it fills the parameters with: UnknownFile, UnknownClass, // UnknownMethod, "", and -1. -bool GetStackFrameElements(JNIEnv *jni, jvmtiEnv *jvmti, - const JVMPI_CallFrame &frame, std::string *file_name, - std::string *class_name, std::string *method_name, - std::string *signature, int *line_number); +bool GetStackFrameElements(JNIEnv* jni, jvmtiEnv* jvmti, + const JVMPI_CallFrame& frame, std::string* file_name, + std::string* class_name, std::string* method_name, + std::string* signature, int* line_number); // Fill the file_name, class_name, method_name, and line_number parameters using // the information provided by the frame and using the JVMTI environment. @@ -48,10 +48,10 @@ bool GetStackFrameElements(JNIEnv *jni, jvmtiEnv *jvmti, // the frame method. Compared to the version above, which must calculate it. // When unknown, it fills the parameters with: UnknownFile, UnknownClass, // UnknownMethod, "", and -1. -bool GetStackFrameElements(jvmtiEnv *jvmti, const JVMPI_CallFrame &frame, - jclass declaring_class, std::string *file_name, - std::string *class_name, std::string *method_name, - std::string *signature, int *line_number); +bool GetStackFrameElements(jvmtiEnv* jvmti, const JVMPI_CallFrame& frame, + jclass declaring_class, std::string* file_name, + std::string* class_name, std::string* method_name, + std::string* signature, int* line_number); } // namespace javaprofiler } // namespace google diff --git a/third_party/javaprofiler/globals.h b/third_party/javaprofiler/globals.h index 75787aef..2cc7c100 100644 --- a/third_party/javaprofiler/globals.h +++ b/third_party/javaprofiler/globals.h @@ -24,6 +24,7 @@ #include "third_party/javaprofiler/jvmti_error.h" #include + #include using std::hash; @@ -31,14 +32,14 @@ using std::string; #ifndef DISALLOW_COPY_AND_ASSIGN #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName &); \ - void operator=(const TypeName &) + TypeName(const TypeName&); \ + void operator=(const TypeName&) #endif // Short version: reinterpret_cast produces undefined behavior in many // cases where memcpy doesn't. template -inline Dest bit_cast(const Source &source) { +inline Dest bit_cast(const Source& source) { // Compile time assertion: sizeof(Dest) == sizeof(Source) // A compile error here means your Dest and Source have different sizes. typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1] @@ -55,36 +56,36 @@ namespace javaprofiler { template class JvmtiScopedPtr { public: - explicit JvmtiScopedPtr(jvmtiEnv *jvmti) : jvmti_(jvmti), ref_(NULL) {} + explicit JvmtiScopedPtr(jvmtiEnv* jvmti) : jvmti_(jvmti), ref_(NULL) {} // This type is neither copyable nor movable. JvmtiScopedPtr(const JvmtiScopedPtr&) = delete; JvmtiScopedPtr& operator=(const JvmtiScopedPtr&) = delete; - JvmtiScopedPtr(jvmtiEnv *jvmti, T *ref) : jvmti_(jvmti), ref_(ref) {} + JvmtiScopedPtr(jvmtiEnv* jvmti, T* ref) : jvmti_(jvmti), ref_(ref) {} ~JvmtiScopedPtr() { if (NULL != ref_) { - JVMTI_ERROR(jvmti_->Deallocate((unsigned char *)ref_)); + JVMTI_ERROR(jvmti_->Deallocate((unsigned char*)ref_)); } } - T **GetRef() { + T** GetRef() { assert(ref_ == NULL); return &ref_; } - T *Get() { return ref_; } + T* Get() { return ref_; } private: - jvmtiEnv *jvmti_; - T *ref_; + jvmtiEnv* jvmti_; + T* ref_; }; template class ScopedLocalRef { public: - ScopedLocalRef(JNIEnv *jni, T ref) : jni_(jni), ref_(ref) {} + ScopedLocalRef(JNIEnv* jni, T ref) : jni_(jni), ref_(ref) {} // This type is neither copyable nor movable. ScopedLocalRef(const ScopedLocalRef&) = delete; @@ -99,7 +100,7 @@ class ScopedLocalRef { T Get() { return ref_; } private: - JNIEnv *jni_; + JNIEnv* jni_; T ref_; }; diff --git a/third_party/javaprofiler/heap_sampler.cc b/third_party/javaprofiler/heap_sampler.cc index 0524476c..8bda5313 100644 --- a/third_party/javaprofiler/heap_sampler.cc +++ b/third_party/javaprofiler/heap_sampler.cc @@ -24,6 +24,8 @@ #include // NOLINT #include +#include "absl/container/inlined_vector.h" +#include "absl/synchronization/mutex.h" #include "third_party/javaprofiler/accessors.h" #include "third_party/javaprofiler/heap_sampler.h" #include "third_party/javaprofiler/profile_proto_builder.h" @@ -34,7 +36,7 @@ namespace { using google::javaprofiler::JVMPI_CallFrame; -std::vector TransformFrames(jvmtiFrameInfo *stack_frames, +std::vector TransformFrames(jvmtiFrameInfo* stack_frames, jint count) { std::vector frames(count); @@ -49,17 +51,8 @@ std::vector TransformFrames(jvmtiFrameInfo *stack_frames, return frames; } -std::unique_ptr> GetTrace(JNIEnv *jni) { - std::unique_ptr> trace_result = nullptr; - -// Cannot use the fast stacktrace for standalone builds as their standard -// libraries do not support getcontext. - - return trace_result; -} - std::unique_ptr> GetTraceUsingJvmti( - JNIEnv *jni, jvmtiEnv *jvmti, jthread thread) { + JNIEnv* jni, jvmtiEnv* jvmti, jthread thread) { jint count = 0; jvmtiFrameInfo stack_frames[google::javaprofiler::kMaxFramesToCapture]; @@ -75,56 +68,24 @@ std::unique_ptr> GetTraceUsingJvmti( new std::vector(TransformFrames(stack_frames, count))); } -static jstring GetClassName(JNIEnv *jni_env, jobject object, - jclass object_klass) { - jclass cls = jni_env->FindClass("java/lang/Class"); - jmethodID get_name_id = - jni_env->GetMethodID(cls, "getName", "()Ljava/lang/String;"); - jstring name_obj = static_cast( - jni_env->CallObjectMethod(object_klass, get_name_id)); - return name_obj; -} - -static jlong GetThreadId(JNIEnv *jni_env, jthread thread) { - jclass thread_class = jni_env->FindClass("java/lang/Thread"); - jmethodID get_id_method_id = - jni_env->GetMethodID(thread_class, "getId", "()J"); - jlong thread_id = jni_env->CallLongMethod(thread, get_id_method_id); - return thread_id; -} - -extern "C" JNIEXPORT void SampledObjectAlloc(jvmtiEnv *jvmti_env, - JNIEnv *jni_env, jthread thread, +extern "C" JNIEXPORT void SampledObjectAlloc(jvmtiEnv* jvmti_env, + JNIEnv* jni_env, jthread thread, jobject object, jclass object_klass, jlong size) { if (!google::javaprofiler::HeapMonitor::Enabled()) { return; } - if (!google::javaprofiler::HeapMonitor::HasAllocationInstrumentation() && - !google::javaprofiler::HeapMonitor::HasGarbageInstrumentation()) { - google::javaprofiler::HeapMonitor::AddSample( - jni_env, thread, object, object_klass, size, nullptr, 0, 0); - return; - } - jstring class_name = GetClassName(jni_env, object, object_klass); - const char *name_str = jni_env->GetStringUTFChars(class_name, NULL); - int name_len = strlen(name_str); - jbyte *name_bytes = - const_cast(reinterpret_cast(name_str)); - - jlong thread_id = GetThreadId(jni_env, thread); - + google::javaprofiler::HeapMonitor::InvokeSampledObjectAllocCallbacks( + jvmti_env, jni_env, thread, object, object_klass, size); google::javaprofiler::HeapMonitor::AddSample(jni_env, thread, object, - object_klass, size, name_bytes, - name_len, thread_id); + object_klass, size); // Invoke all functions in HeapMonitor::alloc_inst_functions_ google::javaprofiler::HeapMonitor::InvokeAllocationInstrumentationFunctions( - thread_id, name_bytes, name_len, size, 0); - jni_env->ReleaseStringUTFChars(class_name, name_str); + size); } -extern "C" JNIEXPORT void GarbageCollectionFinish(jvmtiEnv *jvmti_env) { +extern "C" JNIEXPORT void GarbageCollectionFinish(jvmtiEnv* jvmti_env) { google::javaprofiler::HeapMonitor::NotifyGCWaitingThread(); } @@ -134,21 +95,19 @@ namespace google { namespace javaprofiler { const HeapEventStorage::GcCallback HeapMonitor::gc_callback_ = - [](const HeapObjectTrace &elem) { - HeapMonitor::InvokeGarbageInstrumentationFunctions( - elem.ThreadId(), elem.Name(), elem.NameLength(), elem.Size(), 0); + [](const HeapObjectTrace& elem) { + HeapMonitor::InvokeGarbageInstrumentationFunctions(elem.Size()); }; -std::atomic HeapMonitor::heap_monitor_; +std::atomic HeapMonitor::heap_monitor_; -std::atomic HeapMonitor::jvmti_; +std::atomic HeapMonitor::jvmti_; std::atomic HeapMonitor::sampling_interval_; -std::atomic HeapMonitor::use_jvm_trace_; -std::vector +std::vector HeapMonitor::alloc_inst_functions_; std::vector HeapMonitor::gc_inst_functions_; -HeapEventStorage::HeapEventStorage(jvmtiEnv *jvmti, ProfileFrameCache *cache, +HeapEventStorage::HeapEventStorage(jvmtiEnv* jvmti, ProfileFrameCache* cache, int max_garbage_size, GcCallback gc_callback) : peak_profile_size_(0), max_garbage_size_(max_garbage_size), @@ -157,25 +116,23 @@ HeapEventStorage::HeapEventStorage(jvmtiEnv *jvmti, ProfileFrameCache *cache, cache_(cache), gc_callback_(gc_callback) {} -void HeapEventStorage::Add(JNIEnv *jni, jthread thread, jobject object, +void HeapEventStorage::Add(JNIEnv* jni, jthread thread, jobject object, jclass klass, jlong size, - std::vector frames, jbyte *name, - jint name_len, jlong thread_id) { + std::vector frames) { jweak weak_ref = jni->NewWeakGlobalRef(object); if (jni->ExceptionCheck()) { LOG(WARNING) << "Failed to create NewWeakGlobalRef, skipping heap sample"; return; } - HeapObjectTrace live_object(weak_ref, size, std::move(frames), name, name_len, - thread_id); + HeapObjectTrace live_object(weak_ref, size, std::move(frames)); // Only now lock and get things done quickly. std::lock_guard lock(storage_lock_); newly_allocated_objects_.push_back(std::move(live_object)); } -void HeapEventStorage::AddToGarbage(HeapObjectTrace &&obj) { +void HeapEventStorage::AddToGarbage(HeapObjectTrace&& obj) { if (garbage_objects_.size() >= max_garbage_size_) { garbage_objects_[cur_garbage_pos_] = std::move(obj); cur_garbage_pos_ = (cur_garbage_pos_ + 1) % max_garbage_size_; @@ -185,9 +142,9 @@ void HeapEventStorage::AddToGarbage(HeapObjectTrace &&obj) { } void HeapEventStorage::MoveLiveObjects( - JNIEnv *env, std::vector *objects, - std::vector *still_live_objects) { - for (auto &elem : *objects) { + JNIEnv* env, std::vector* objects, + std::vector* still_live_objects) { + for (auto& elem : *objects) { if (elem.IsLive(env)) { still_live_objects->push_back(std::move(elem)); } else { @@ -199,15 +156,15 @@ void HeapEventStorage::MoveLiveObjects( } int64_t HeapEventStorage::ProfileSize( - const std::vector &live_objects) const { + const std::vector& live_objects) const { int64_t total = 0; - for (auto &trace : live_objects) { + for (auto& trace : live_objects) { total += trace.Size(); } return total; } -void HeapEventStorage::CompactSamples(JNIEnv *env) { +void HeapEventStorage::CompactSamples(JNIEnv* env) { std::lock_guard lock(storage_lock_); std::vector still_live; @@ -229,7 +186,7 @@ void HeapEventStorage::CompactSamples(JNIEnv *env) { peak_profile_size_ = curr_profile_size; peak_objects_.clear(); - for (auto &object : live_objects_) { + for (auto& object : live_objects_) { peak_objects_.push_back(object.Copy()); } } @@ -243,8 +200,8 @@ HeapEventStorage::StackTraceArrayBuilder::StackTraceArrayBuilder( call_trace_data_(new JVMPI_CallTrace[objects_size_]) {} void HeapEventStorage::StackTraceArrayBuilder::AddTrace( - HeapObjectTrace &object) { - std::vector &frames = object.Frames(); + HeapObjectTrace& object) { + std::vector& frames = object.Frames(); call_trace_data_[curr_trace_] = {nullptr, static_cast(frames.size()), frames.data()}; @@ -260,7 +217,7 @@ void HeapEventStorage::StackTraceArrayBuilder::AddTrace( } std::unique_ptr HeapEventStorage::ConvertToProto( - ProfileProtoBuilder *builder, std::vector &objects) { + ProfileProtoBuilder* builder, std::vector& objects) { StackTraceArrayBuilder stack_trace_builder(objects.size()); for (int i = 0; i < objects.size(); ++i) { stack_trace_builder.AddTrace(objects[i]); @@ -271,7 +228,7 @@ std::unique_ptr HeapEventStorage::ConvertToProto( } std::unique_ptr -HeapEventStorage::GetPeakHeapProfiles(JNIEnv *env, int sampling_interval) { +HeapEventStorage::GetPeakHeapProfiles(JNIEnv* env, int sampling_interval) { auto builder = ProfileProtoBuilder::ForHeap(env, jvmti_, sampling_interval, cache_); @@ -280,7 +237,7 @@ HeapEventStorage::GetPeakHeapProfiles(JNIEnv *env, int sampling_interval) { } std::unique_ptr HeapEventStorage::GetProfiles( - JNIEnv *env, int sampling_interval, bool force_gc, bool get_live) { + JNIEnv* env, int sampling_interval, bool force_gc, bool get_live) { auto builder = ProfileProtoBuilder::ForHeap(env, jvmti_, sampling_interval, cache_); @@ -304,7 +261,7 @@ std::unique_ptr HeapEventStorage::GetProfiles( } } -bool HeapMonitor::CreateGCWaitingThread(jvmtiEnv *jvmti, JNIEnv *jni) { +bool HeapMonitor::CreateGCWaitingThread(jvmtiEnv* jvmti, JNIEnv* jni) { jclass cls = jni->FindClass("java/lang/Thread"); jmethodID constructor = jni->GetMethodID(cls, "", "()V"); jobject thread = jni->NewGlobalRef(jni->NewObject(cls, constructor)); @@ -322,7 +279,7 @@ bool HeapMonitor::CreateGCWaitingThread(jvmtiEnv *jvmti, JNIEnv *jni) { return true; } -bool HeapMonitor::Supported(jvmtiEnv *jvmti) { +bool HeapMonitor::Supported(jvmtiEnv* jvmti) { jvmtiCapabilities caps; memset(&caps, 0, sizeof(caps)); if (jvmti->GetPotentialCapabilities(&caps) != JVMTI_ERROR_NONE) { @@ -350,75 +307,89 @@ bool HeapMonitor::Supported(jvmtiEnv *jvmti) { return true; } -void HeapMonitor::AddSample(JNIEnv *jni_env, jthread thread, jobject object, - jclass object_klass, jlong size, jbyte *name, - jint name_len, jlong thread_id) { - auto trace = use_jvm_trace_.load() - ? GetTrace(jni_env) - : GetTraceUsingJvmti(jni_env, jvmti_.load(), thread); +void HeapMonitor::AddSample(JNIEnv* jni_env, jthread thread, jobject object, + jclass object_klass, jlong size) { + auto trace = GetTraceUsingJvmti(jni_env, jvmti_.load(), thread); if (trace == nullptr) { return; } // HeapMonitor is never deleted, but the pointer is cleared during // disablement. Ensure we are not racing with disablement and check if the // HeapMonitor is nullptr. - HeapMonitor *instance = TryGetInstance(); + HeapMonitor* instance = TryGetInstance(); if (instance == nullptr) { return; } instance->storage_.Add(jni_env, thread, object, object_klass, size, - std::move(*trace), name, name_len, thread_id); + std::move(*trace)); } -void HeapMonitor::InvokeAllocationInstrumentationFunctions( - jlong thread_id, jbyte *name, int name_length, jlong size, jlong gcontext) { - HeapMonitor *instance = TryGetInstance(); - if (instance == nullptr) { +void HeapMonitor::AddSampledObjectAllocCallback( + jvmtiEventSampledObjectAlloc callback) { + if (callback == nullptr) { return; } - for (auto fn : instance->alloc_inst_functions_) { - fn(thread_id, name, name_length, size, gcontext); + HeapMonitor* instance = TryGetInstance(); + if (instance == nullptr) { + return; } + absl::MutexLock lock(&instance->sampled_object_alloc_callbacks_lock_); + instance->sampled_object_alloc_callbacks_.push_back(callback); } -void HeapMonitor::AddAllocationInstrumentation( - AllocationInstrumentationFunction fn) { - HeapMonitor *instance = TryGetInstance(); +void HeapMonitor::InvokeSampledObjectAllocCallbacks( + jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread, jobject object, + jclass object_klass, jlong size) { + HeapMonitor* instance = TryGetInstance(); if (instance == nullptr) { return; } - instance->alloc_inst_functions_.push_back(fn); + absl::InlinedVector callbacks; + { + // Copy the callbacks to a local variable to avoid holding the lock while + // invoking the callbacks. + absl::MutexLock lock(&instance->sampled_object_alloc_callbacks_lock_); + if (instance->sampled_object_alloc_callbacks_.empty()) { + return; + } + callbacks = instance->sampled_object_alloc_callbacks_; + } + for (jvmtiEventSampledObjectAlloc callback : callbacks) { + (*callback)(jvmti_env, jni_env, thread, object, object_klass, size); + } } -bool HeapMonitor::HasAllocationInstrumentation() { - HeapMonitor *instance = TryGetInstance(); +void HeapMonitor::InvokeAllocationInstrumentationFunctions(jlong size) { + HeapMonitor* instance = TryGetInstance(); if (instance == nullptr) { - return false; + return; + } + for (auto fn : instance->alloc_inst_functions_) { + fn(size); } - return !instance->alloc_inst_functions_.empty(); } -bool HeapMonitor::HasGarbageInstrumentation() { - HeapMonitor *instance = TryGetInstance(); +void HeapMonitor::AddAllocationInstrumentation( + AllocationSamplingInstrumentationFunction fn) { + HeapMonitor* instance = TryGetInstance(); if (instance == nullptr) { - return false; + return; } - return !instance->gc_inst_functions_.empty(); + instance->alloc_inst_functions_.push_back(fn); } -void HeapMonitor::InvokeGarbageInstrumentationFunctions( - jlong thread_id, jbyte *name, int name_length, jlong size, jlong gcontext) { - HeapMonitor *instance = TryGetInstance(); +void HeapMonitor::InvokeGarbageInstrumentationFunctions(jlong size) { + HeapMonitor* instance = TryGetInstance(); if (instance == nullptr) { return; } for (auto fn : instance->gc_inst_functions_) { - fn(thread_id, name, name_length, size, gcontext); + fn(size); } } void HeapMonitor::AddGarbageInstrumentation(GarbageInstrumentationFunction fn) { - HeapMonitor *instance = TryGetInstance(); + HeapMonitor* instance = TryGetInstance(); if (instance == nullptr) { return; } @@ -441,14 +412,14 @@ void HeapMonitor::WaitForShutdown() { gc_waiting_cv_.wait(lock, [this] { return gc_thread_shutdown; }); } -void HeapMonitor::AddCallback(jvmtiEventCallbacks *callbacks) { +void HeapMonitor::AddCallback(jvmtiEventCallbacks* callbacks) { callbacks->SampledObjectAlloc = &SampledObjectAlloc; callbacks->GarbageCollectionFinish = &GarbageCollectionFinish; } // Currently, we enable once and forget about it. -bool HeapMonitor::Enable(jvmtiEnv *jvmti, JNIEnv *jni, int sampling_interval, - int max_garbage_size, bool use_jvm_trace) { +bool HeapMonitor::Enable(jvmtiEnv* jvmti, JNIEnv* jni, int sampling_interval, + int max_garbage_size) { if (!Supported(jvmti)) { LOG(WARNING) << "Heap sampling is not supported by the JVM, disabling the " << " heap sampling monitor"; @@ -493,18 +464,13 @@ bool HeapMonitor::Enable(jvmtiEnv *jvmti, JNIEnv *jni, int sampling_interval, return false; } - if (use_jvm_trace) { - Asgct::SetAsgct(Accessors::GetJvmFunction("AsyncGetCallTrace")); - } - sampling_interval_.store(sampling_interval); - use_jvm_trace_.store(use_jvm_trace); jvmti_.store(jvmti); // Ensure this is really a singleton i.e. don't recreate it if sampling is // re-enabled. if (heap_monitor_ == nullptr) { - static HeapMonitor *monitor = new HeapMonitor(max_garbage_size); + static HeapMonitor* monitor = new HeapMonitor(max_garbage_size); if (!monitor->CreateGCWaitingThread(jvmti, jni)) { return false; } @@ -515,12 +481,12 @@ bool HeapMonitor::Enable(jvmtiEnv *jvmti, JNIEnv *jni, int sampling_interval, } void HeapMonitor::Disable() { - HeapMonitor *monitor = heap_monitor_.load(); + HeapMonitor* monitor = heap_monitor_.load(); if (monitor == nullptr) { // Already disabled. return; } - jvmtiEnv *jvmti = jvmti_.load(); + jvmtiEnv* jvmti = jvmti_.load(); jvmti->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, nullptr); @@ -532,10 +498,10 @@ void HeapMonitor::Disable() { } std::unique_ptr HeapMonitor::GetHeapProfiles( - JNIEnv *env, bool force_gc) { + JNIEnv* env, bool force_gc) { // Note: technically this means that you cannot disable the sampler and then // get the profile afterwards; this could be changed if needed. - HeapMonitor *monitor = TryGetInstance(); + HeapMonitor* monitor = TryGetInstance(); if (monitor != nullptr) { return monitor->storage_.GetHeapProfiles(env, sampling_interval_, force_gc); } @@ -543,10 +509,10 @@ std::unique_ptr HeapMonitor::GetHeapProfiles( } std::unique_ptr HeapMonitor::GetPeakHeapProfiles( - JNIEnv *env, bool force_gc) { + JNIEnv* env, bool force_gc) { // Note: technically this means that you cannot disable the sampler and then // get the profile afterwards; this could be changed if needed. - HeapMonitor *monitor = TryGetInstance(); + HeapMonitor* monitor = TryGetInstance(); if (monitor != nullptr) { return monitor->storage_.GetPeakHeapProfiles(env, sampling_interval_); } @@ -554,10 +520,10 @@ std::unique_ptr HeapMonitor::GetPeakHeapProfiles( } std::unique_ptr -HeapMonitor::GetGarbageHeapProfiles(JNIEnv *env, bool force_gc) { +HeapMonitor::GetGarbageHeapProfiles(JNIEnv* env, bool force_gc) { // Note: technically this means that you cannot disable the sampler and then // get the profile afterwards; this could be changed if needed. - HeapMonitor *monitor = TryGetInstance(); + HeapMonitor* monitor = TryGetInstance(); if (monitor != nullptr) { return monitor->storage_.GetGarbageHeapProfiles(env, sampling_interval_, force_gc); @@ -566,7 +532,7 @@ HeapMonitor::GetGarbageHeapProfiles(JNIEnv *env, bool force_gc) { } std::unique_ptr HeapMonitor::EmptyHeapProfile( - JNIEnv *jni_env) { + JNIEnv* jni_env) { return ProfileProtoBuilder::ForHeap(jni_env, jvmti_, sampling_interval_) ->CreateProto(); } @@ -588,15 +554,15 @@ HeapMonitor::GcEvent HeapMonitor::WaitForGC() { return result; } -void HeapMonitor::GCWaitingThread(jvmtiEnv *jvmti_env, JNIEnv *jni_env, - void *arg) { - HeapMonitor *monitor; +void HeapMonitor::GCWaitingThread(jvmtiEnv* jvmti_env, JNIEnv* jni_env, + void* arg) { + HeapMonitor* monitor; while ((monitor = TryGetInstance()) == nullptr) { } monitor->GCWaitingThreadRun(jni_env); } -void HeapMonitor::GCWaitingThreadRun(JNIEnv *jni_env) { +void HeapMonitor::GCWaitingThreadRun(JNIEnv* jni_env) { while (true) { GcEvent event = WaitForGC(); @@ -614,7 +580,7 @@ void HeapMonitor::GCWaitingThreadRun(JNIEnv *jni_env) { LOG(INFO) << "Heap sampling GC waiting thread finished"; } -void HeapMonitor::CompactData(JNIEnv *jni_env) { +void HeapMonitor::CompactData(JNIEnv* jni_env) { storage_.CompactSamples(jni_env); } diff --git a/third_party/javaprofiler/heap_sampler.h b/third_party/javaprofiler/heap_sampler.h index 51b2f61a..18cf4b00 100644 --- a/third_party/javaprofiler/heap_sampler.h +++ b/third_party/javaprofiler/heap_sampler.h @@ -28,15 +28,15 @@ #include // NOLINT #include +#include "absl/base/thread_annotations.h" +#include "absl/container/inlined_vector.h" +#include "absl/synchronization/mutex.h" #include "third_party/javaprofiler/profile_proto_builder.h" -typedef void (*AllocationInstrumentationFunction)(jlong thread_id, jbyte *name, - int name_length, jlong size, - jlong gcontext); +// Deprecated. Use jvmtiEventSampledObjectAlloc callback instead. +typedef void (*AllocationSamplingInstrumentationFunction)(jlong size); -typedef void (*GarbageInstrumentationFunction)(jlong thread_id, jbyte *name, - int name_length, jlong size, - jlong gcontext); +typedef void (*GarbageInstrumentationFunction)(jlong size); namespace google { namespace javaprofiler { @@ -47,43 +47,27 @@ class HeapObjectTrace { public: // This object owns the jweak object parameter. It is freed when the object // is sent to the garbage list, and the object is set to nullptr. - HeapObjectTrace(jweak object, jlong size, std::vector frames, - jbyte *name, int name_length, jlong thread_id) - : object_(object), - size_(size), - frames_(std::move(frames)), - name_(name), - name_length_(name_length), - thread_id_(thread_id) {} - - HeapObjectTrace(jweak object, jlong size, - const std::vector &frames) - : object_(object), size_(size), frames_(frames) {} + HeapObjectTrace(jweak object, jlong size, std::vector frames) + : object_(object), size_(size), frames_(std::move(frames)) {} // Allow moving. - HeapObjectTrace(HeapObjectTrace &&o) = default; - HeapObjectTrace &operator=(HeapObjectTrace &&o) = default; + HeapObjectTrace(HeapObjectTrace&& o) = default; + HeapObjectTrace& operator=(HeapObjectTrace&& o) = default; // No copying allowed. - HeapObjectTrace(const HeapObjectTrace &o) = delete; - HeapObjectTrace &operator=(const HeapObjectTrace &o) = delete; + HeapObjectTrace(const HeapObjectTrace& o) = delete; + HeapObjectTrace& operator=(const HeapObjectTrace& o) = delete; - std::vector &Frames() { return frames_; } + std::vector& Frames() { return frames_; } jlong Size() const { return size_; } - jbyte *Name() const { return name_; } - - int NameLength() const { return name_length_; } - - jlong ThreadId() const { return thread_id_; } - - void DeleteWeakReference(JNIEnv *env) { + void DeleteWeakReference(JNIEnv* env) { env->DeleteWeakGlobalRef(object_); object_ = nullptr; } - bool IsLive(JNIEnv *env) { + bool IsLive(JNIEnv* env) { // When GC collects the object, the object represented by the weak // reference will be considered as the same object as NULL. return !env->IsSameObject(object_, NULL); @@ -97,30 +81,26 @@ class HeapObjectTrace { jweak object_; jlong size_; std::vector frames_; - jbyte *name_; - int name_length_; - jlong thread_id_; }; // Storage for the sampled heap objects recorded from the heap sampling JVMTI // API callbacks. class HeapEventStorage { public: - typedef std::function GcCallback; + typedef std::function GcCallback; HeapEventStorage( - jvmtiEnv *jvmti, ProfileFrameCache *cache = nullptr, + jvmtiEnv* jvmti, ProfileFrameCache* cache = nullptr, int max_garbage_size = 200, - GcCallback gc_callback = [](const HeapObjectTrace &t) {}); + GcCallback gc_callback = [](const HeapObjectTrace& t) {}); // TODO: establish correct shutdown sequence: how do we ensure that // things are not going to go awfully wrong at shutdown, is it this class' job // or should it be the owner of this class' instance's job? // Adds an object to the storage system. - void Add(JNIEnv *jni, jthread thread, jobject object, jclass klass, - jlong size, std::vector frames, jbyte *name, - jint name_len, jlong thread_id); + void Add(JNIEnv* jni, jthread thread, jobject object, jclass klass, + jlong size, std::vector frames); // Returns a perftools::profiles::Profile with the objects stored via // calls to the Add method. @@ -128,13 +108,13 @@ class HeapEventStorage { // profiles; // setting force_gc to true has a performance impact and is discouraged. std::unique_ptr GetHeapProfiles( - JNIEnv *env, int sampling_interval, bool force_gc = false) { + JNIEnv* env, int sampling_interval, bool force_gc = false) { return GetProfiles(env, sampling_interval, force_gc, true); } // Return the largest profile recorded so far. std::unique_ptr GetPeakHeapProfiles( - JNIEnv *env, int sampling_interval); + JNIEnv* env, int sampling_interval); // Returns a perftools::profiles::Profile with the objects that have been // GC'd. @@ -142,15 +122,15 @@ class HeapEventStorage { // profiles; // setting force_gc to true has a performance impact and is discouraged. std::unique_ptr GetGarbageHeapProfiles( - JNIEnv *env, int sampling_interval, bool force_gc = false) { + JNIEnv* env, int sampling_interval, bool force_gc = false) { return GetProfiles(env, sampling_interval, force_gc, false); } - void CompactSamples(JNIEnv *env); + void CompactSamples(JNIEnv* env); // Not copyable or movable. - HeapEventStorage(const HeapEventStorage &) = delete; - HeapEventStorage &operator=(const HeapEventStorage &) = delete; + HeapEventStorage(const HeapEventStorage&) = delete; + HeapEventStorage& operator=(const HeapEventStorage&) = delete; private: // Helper for creating a google::javaprofiler::ProfileStackTrace array @@ -159,9 +139,9 @@ class HeapEventStorage { public: StackTraceArrayBuilder(std::size_t objects_size); - void AddTrace(HeapObjectTrace &object); + void AddTrace(HeapObjectTrace& object); - google::javaprofiler::ProfileStackTrace *GetStackTraceData() const { + google::javaprofiler::ProfileStackTrace* GetStackTraceData() const { return stack_trace_data_.get(); } @@ -174,22 +154,22 @@ class HeapEventStorage { }; static std::unique_ptr ConvertToProto( - ProfileProtoBuilder *builder, std::vector &objects); + ProfileProtoBuilder* builder, std::vector& objects); std::unique_ptr GetProfiles( - JNIEnv *env, int sampling_interval, bool force_gc, bool get_live); + JNIEnv* env, int sampling_interval, bool force_gc, bool get_live); // Add object to the garbage list: it uses a queue with a max size of // max_garbage_size, provided via the constructor. // obj will be std::move'd to the garbage_list. - void AddToGarbage(HeapObjectTrace &&obj); + void AddToGarbage(HeapObjectTrace&& obj); // Moves live objects from objects to still_live_objects; live elements from // the objects vector are replaced with nullptr via std::move. - void MoveLiveObjects(JNIEnv *env, std::vector *objects, - std::vector *still_live_objects); + void MoveLiveObjects(JNIEnv* env, std::vector* objects, + std::vector* still_live_objects); - int64_t ProfileSize(const std::vector &objects) const; + int64_t ProfileSize(const std::vector& objects) const; std::vector newly_allocated_objects_; std::vector live_objects_; @@ -204,65 +184,67 @@ class HeapEventStorage { std::vector garbage_objects_; std::mutex storage_lock_; - jvmtiEnv *jvmti_; - ProfileFrameCache *cache_; + jvmtiEnv* jvmti_; + ProfileFrameCache* cache_; const GcCallback gc_callback_; }; // Due to the JVMTI callback, everything here is static. class HeapMonitor { public: - static bool Enable(jvmtiEnv *jvmti, JNIEnv *jni, int sampling_interval, - int max_garbage_size = 200, - // TODO: Remove 'use_jvm_trace' and associated - // code after Q2 2024. - bool use_jvm_trace = false); + static bool Enable(jvmtiEnv* jvmti, JNIEnv* jni, int sampling_interval, + int max_garbage_size = 200); static void Disable(); static bool Enabled() { return heap_monitor_ != nullptr; } + static int GetSamplingInterval() { + return sampling_interval_.load(std::memory_order_relaxed); + } + // Returns a perftools::profiles::Profile with the objects provided by the // HeapEventStorage. static std::unique_ptr GetHeapProfiles( - JNIEnv *env, bool force_gc); + JNIEnv* env, bool force_gc); // Returns a perftools::profiles::Profile with the GC'd objects provided by // the HeapEventStorage. static std::unique_ptr GetGarbageHeapProfiles( - JNIEnv *env, bool force_gc); + JNIEnv* env, bool force_gc); // Return the largest profile recorded so far. static std::unique_ptr GetPeakHeapProfiles( - JNIEnv *env, bool force_gc); + JNIEnv* env, bool force_gc); - static void AddSample(JNIEnv *jni_env, jthread thread, jobject object, - jclass object_klass, jlong size, jbyte *name, - jint name_len, jlong thread_id); + static void AddSample(JNIEnv* jni_env, jthread thread, jobject object, + jclass object_klass, jlong size); - static void InvokeAllocationInstrumentationFunctions(jlong thread_id, - jbyte *name, - int name_length, - jlong size, - jlong gcontext); + // Adds a callback to be called when an object is allocated. + // The callback may be executed concurrently by multiple threads, so it must + // take care of thread safety. + static void AddSampledObjectAllocCallback( + jvmtiEventSampledObjectAlloc callback); - static void AddAllocationInstrumentation( - AllocationInstrumentationFunction fn); + static void InvokeSampledObjectAllocCallbacks(jvmtiEnv* jvmti_env, + JNIEnv* jni_env, jthread thread, + jobject object, + jclass object_klass, + jlong size); + + static void InvokeAllocationInstrumentationFunctions(jlong size); - static bool HasAllocationInstrumentation(); + // Deprecated. Use AddSampledObjectAllocCallback instead. + static void AddAllocationInstrumentation( + AllocationSamplingInstrumentationFunction fn); - static void InvokeGarbageInstrumentationFunctions(jlong thread_id, - jbyte *name, - int name_length, jlong size, - jlong gcontext); + static void InvokeGarbageInstrumentationFunctions(jlong size); static void AddGarbageInstrumentation(GarbageInstrumentationFunction fn); - static bool HasGarbageInstrumentation(); - - static void AddCallback(jvmtiEventCallbacks *callbacks); + static void AddCallback(jvmtiEventCallbacks* callbacks); static void NotifyGCWaitingThread() { - HeapMonitor *monitor = TryGetInstance(); + HeapMonitor* monitor = TryGetInstance(); if (monitor == nullptr) { return; } @@ -270,8 +252,8 @@ class HeapMonitor { } // Not copyable or movable. - HeapMonitor(const HeapMonitor &) = delete; - HeapMonitor &operator=(const HeapMonitor &) = delete; + HeapMonitor(const HeapMonitor&) = delete; + HeapMonitor& operator=(const HeapMonitor&) = delete; private: static const HeapEventStorage::GcCallback gc_callback_; @@ -280,40 +262,44 @@ class HeapMonitor { : storage_(jvmti_.load(), GetFrameCache(), max_garbage_size, gc_callback_) {} - static std::atomic heap_monitor_; + static std::atomic heap_monitor_; // Return a nullptr if heap_monitor_ happens to be empty. You must check // whether the return value is nullptr. - static HeapMonitor *TryGetInstance() { return heap_monitor_; } + static HeapMonitor* TryGetInstance() { return heap_monitor_; } - ProfileFrameCache *GetFrameCache() { - ProfileFrameCache *cache = nullptr; + ProfileFrameCache* GetFrameCache() { + ProfileFrameCache* cache = nullptr; return cache; } - static bool Supported(jvmtiEnv *jvmti); + static bool Supported(jvmtiEnv* jvmti); enum class GcEvent { NO_EVENT, GC_FINISHED, SHUTDOWN }; - bool CreateGCWaitingThread(jvmtiEnv *jvmti, JNIEnv *jni); + bool CreateGCWaitingThread(jvmtiEnv* jvmti, JNIEnv* jni); void ShutdownGCWaitingThread(); - static void GCWaitingThread(jvmtiEnv *jvmti_env, JNIEnv *jni_env, void *arg); - void GCWaitingThreadRun(JNIEnv *jni_env); + static void GCWaitingThread(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg); + void GCWaitingThreadRun(JNIEnv* jni_env); GcEvent WaitForGC(); void NotifyGCWaitingThreadInternal(GcEvent event); void WaitForShutdown(); - void CompactData(JNIEnv *jni_env); + void CompactData(JNIEnv* jni_env); - static std::vector alloc_inst_functions_; + static std::vector + alloc_inst_functions_; static std::vector gc_inst_functions_; static std::unique_ptr EmptyHeapProfile( - JNIEnv *jni_env); + JNIEnv* jni_env); - static std::atomic jvmti_; + static std::atomic jvmti_; static std::atomic sampling_interval_; - static std::atomic use_jvm_trace_; + absl::Mutex sampled_object_alloc_callbacks_lock_; + absl::InlinedVector + sampled_object_alloc_callbacks_ + ABSL_GUARDED_BY(sampled_object_alloc_callbacks_lock_); std::list gc_notify_events_; bool gc_thread_shutdown = false; std::condition_variable gc_waiting_cv_; diff --git a/third_party/javaprofiler/method_info.cc b/third_party/javaprofiler/method_info.cc index 688c1716..e8c6d341 100644 --- a/third_party/javaprofiler/method_info.cc +++ b/third_party/javaprofiler/method_info.cc @@ -24,7 +24,7 @@ namespace google { namespace javaprofiler { -int64_t MethodInfo::LineNumber(const JVMPI_CallFrame &frame) { +int64_t MethodInfo::LineNumber(const JVMPI_CallFrame& frame) { // lineno is actually the BCI of the frame. int bci = frame.lineno; diff --git a/third_party/javaprofiler/method_info.h b/third_party/javaprofiler/method_info.h index 9eca8494..c8b744e5 100644 --- a/third_party/javaprofiler/method_info.h +++ b/third_party/javaprofiler/method_info.h @@ -17,8 +17,9 @@ #ifndef GOOGLE_JAVAPROFILER_METHOD_INFO_H_ #define GOOGLE_JAVAPROFILER_METHOD_INFO_H_ -#include #include + +#include #include #include @@ -34,29 +35,27 @@ namespace javaprofiler { class MethodInfo { public: // Constructor providing all the information regarding a method. - MethodInfo(jvmtiEnv *jvmti_env, - const std::string &method_name, - const std::string &class_name, - const std::string &file_name, - const int &start_line) + MethodInfo(jvmtiEnv* jvmti_env, const std::string& method_name, + const std::string& class_name, const std::string& file_name, + const int& start_line) : jvmti_env_(jvmti_env), method_name_(method_name), class_name_(class_name), file_name_(file_name), start_line_(start_line) {} - int64_t LineNumber(const JVMPI_CallFrame &frame); + int64_t LineNumber(const JVMPI_CallFrame& frame); - const std::string &MethodName() const { return method_name_; } + const std::string& MethodName() const { return method_name_; } - const std::string &ClassName() const { return class_name_; } + const std::string& ClassName() const { return class_name_; } - const std::string &FileName() const { return file_name_; } + const std::string& FileName() const { return file_name_; } int StartLine() const { return start_line_; } private: - jvmtiEnv *jvmti_env_; + jvmtiEnv* jvmti_env_; std::string method_name_; std::string class_name_; diff --git a/third_party/javaprofiler/native.cc b/third_party/javaprofiler/native.cc index 3a27655b..d17f1f8d 100644 --- a/third_party/javaprofiler/native.cc +++ b/third_party/javaprofiler/native.cc @@ -30,13 +30,13 @@ namespace google { namespace javaprofiler { -NativeProcessInfo::NativeProcessInfo(const std::string &procmaps_filename) +NativeProcessInfo::NativeProcessInfo(const std::string& procmaps_filename) : procmaps_filename_(procmaps_filename) { Refresh(); } void NativeProcessInfo::Refresh() { - FILE *f = fopen(procmaps_filename_.c_str(), "r"); + FILE* f = fopen(procmaps_filename_.c_str(), "r"); if (f == nullptr) { LOG(ERROR) << "Could not open maps file: " << procmaps_filename_; @@ -74,7 +74,7 @@ void NativeProcessInfo::Refresh() { continue; } - const char *filename = &line[filename_index]; + const char* filename = &line[filename_index]; size_t filename_len = strcspn(filename, " \t\n"); mappings_.emplace_back( Mapping{start, limit, std::string(filename, filename_len)}); diff --git a/third_party/javaprofiler/native.h b/third_party/javaprofiler/native.h index 5fcd50be..9ab42068 100644 --- a/third_party/javaprofiler/native.h +++ b/third_party/javaprofiler/native.h @@ -31,7 +31,7 @@ class NativeProcessInfo { public: // procmaps_filename contains the path of a file describing the memory // regions in the current process, in /proc//maps format. - explicit NativeProcessInfo(const std::string &procmaps_filename); + explicit NativeProcessInfo(const std::string& procmaps_filename); struct Mapping { uint64_t start, limit; @@ -39,7 +39,7 @@ class NativeProcessInfo { }; void Refresh(); - const std::vector &Mappings() const { return mappings_; } + const std::vector& Mappings() const { return mappings_; } private: const std::string procmaps_filename_; diff --git a/third_party/javaprofiler/profile_proto_builder.cc b/third_party/javaprofiler/profile_proto_builder.cc index 93b3cc96..62b4d32b 100644 --- a/third_party/javaprofiler/profile_proto_builder.cc +++ b/third_party/javaprofiler/profile_proto_builder.cc @@ -13,12 +13,11 @@ // limitations under the License. #include "third_party/javaprofiler/display.h" -#include "third_party/javaprofiler/stacktrace_fixer.h" #include "third_party/javaprofiler/profile_proto_builder.h" +#include "third_party/javaprofiler/stacktrace_fixer.h" using std::string; using std::unique_ptr; -using std::vector; namespace google { namespace javaprofiler { @@ -26,7 +25,7 @@ namespace javaprofiler { namespace { // Hashes a string using an initial hash value of h. -size_t HashString(const string &str, size_t h) { +size_t HashString(const string& str, size_t h) { hash hash_string; return 31U * h + hash_string(str); } @@ -36,30 +35,26 @@ const int kMetric = 1; } // namespace -ProfileProtoBuilder::ProfileProtoBuilder(JNIEnv *jni_env, jvmtiEnv *jvmti_env, - ProfileFrameCache *native_cache, +ProfileProtoBuilder::ProfileProtoBuilder(JNIEnv* jni_env, jvmtiEnv* jvmti_env, + ProfileFrameCache* native_cache, int64_t sampling_rate, - const SampleType &count_type, - const SampleType &metric_type, - bool skip_top_native_frames, - vector skip_frames) + const SampleType& count_type, + const SampleType& metric_type, + bool skip_top_native_frames) : sampling_rate_(sampling_rate), - jni_env_(jni_env), - jvmti_env_(jvmti_env), method_info_cache_(jni_env, jvmti_env), native_cache_(native_cache), location_builder_(&builder_), - skip_top_native_frames_(skip_top_native_frames) - { + skip_top_native_frames_(skip_top_native_frames) { AddSampleType(count_type); AddSampleType(metric_type); builder_.mutable_profile()->set_default_sample_type( - builder_.StringId(metric_type.type.c_str())); + builder_.StringId(metric_type.type)); SetPeriodType(metric_type); } -void ProfileProtoBuilder::AddTraces(const ProfileStackTrace *traces, +void ProfileProtoBuilder::AddTraces(const ProfileStackTrace* traces, int num_traces) { if (native_cache_) { native_cache_->ProcessTraces(traces, num_traces); @@ -70,8 +65,8 @@ void ProfileProtoBuilder::AddTraces(const ProfileStackTrace *traces, } } -void ProfileProtoBuilder::AddTraces(const ProfileStackTrace *traces, - const int32_t *counts, int num_traces) { +void ProfileProtoBuilder::AddTraces(const ProfileStackTrace* traces, + const int32_t* counts, int num_traces) { if (native_cache_) { native_cache_->ProcessTraces(traces, num_traces); } @@ -81,10 +76,10 @@ void ProfileProtoBuilder::AddTraces(const ProfileStackTrace *traces, } } -void ProfileProtoBuilder::AddArtificialTrace(const string &name, int count, +void ProfileProtoBuilder::AddArtificialTrace(const string& name, int count, int sampling_rate) { - perftools::profiles::Location *location = location_builder_.LocationFor( - name, name, "", 0, -1, 0); + perftools::profiles::Location* location = + location_builder_.LocationFor(name, name, "", 0, -1, 0); auto profile = builder_.mutable_profile(); auto sample = profile->add_sample(); @@ -108,13 +103,8 @@ void ProfileProtoBuilder::UnsampleMetrics() { } } -bool ProfileProtoBuilder::SkipFrame( - const string &function_name) const { - bool result = false; - return result; -} - -int ProfileProtoBuilder::SkipTopNativeFrames(const JVMPI_CallTrace &trace) { +int ProfileProtoBuilder::SkipTopNativeFrames( + const JVMPI_CallTrace& trace) const { if (!skip_top_native_frames_) { return 0; } @@ -132,7 +122,7 @@ int ProfileProtoBuilder::SkipTopNativeFrames(const JVMPI_CallTrace &trace) { } unique_ptr - ProfileProtoBuilder::CreateSampledProto() { +ProfileProtoBuilder::CreateSampledProto() { #ifndef STANDALONE_BUILD builder_.AddCurrentMappings(); #endif @@ -141,7 +131,7 @@ unique_ptr } unique_ptr - ProfileProtoBuilder::CreateUnsampledProto() { +ProfileProtoBuilder::CreateUnsampledProto() { #ifndef STANDALONE_BUILD builder_.AddCurrentMappings(); #endif @@ -150,50 +140,50 @@ unique_ptr return unique_ptr(builder_.Consume()); } -void ProfileProtoBuilder::AddSampleType(const SampleType &sample_type) { +void ProfileProtoBuilder::AddSampleType(const SampleType& sample_type) { auto sample_type_proto = builder_.mutable_profile()->add_sample_type(); - sample_type_proto->set_type(builder_.StringId(sample_type.type.c_str())); - sample_type_proto->set_unit(builder_.StringId(sample_type.unit.c_str())); + sample_type_proto->set_type(builder_.StringId(sample_type.type)); + sample_type_proto->set_unit(builder_.StringId(sample_type.unit)); } -void ProfileProtoBuilder::SetPeriodType(const SampleType &metric_type) { +void ProfileProtoBuilder::SetPeriodType(const SampleType& metric_type) { auto period_type = builder_.mutable_profile()->mutable_period_type(); - period_type->set_type(builder_.StringId(metric_type.type.c_str())); - period_type->set_unit(builder_.StringId(metric_type.unit.c_str())); + period_type->set_type(builder_.StringId(metric_type.type)); + period_type->set_unit(builder_.StringId(metric_type.unit)); } void ProfileProtoBuilder::UpdateSampleValues( - perftools::profiles::Sample *sample, int64_t count, int64_t size) { + perftools::profiles::Sample* sample, int64_t count, int64_t size) { sample->set_value(kCount, sample->value(kCount) + count); sample->set_value(kMetric, sample->value(kMetric) + size); } -void ProfileProtoBuilder::InitSampleValues(perftools::profiles::Sample *sample, +void ProfileProtoBuilder::InitSampleValues(perftools::profiles::Sample* sample, int64_t count, int64_t metric) { sample->add_value(count); sample->add_value(metric); } -void ProfileProtoBuilder::AddLabels(const TraceAndLabels &trace_and_labels, - perftools::profiles::Sample *sample) { - for (const auto &label : trace_and_labels.labels) { +void ProfileProtoBuilder::AddLabels(const TraceAndLabels& trace_and_labels, + perftools::profiles::Sample* sample) { + for (const auto& label : trace_and_labels.labels) { auto new_label = sample->add_label(); - new_label->set_key(builder_.StringId(label.key.c_str())); + new_label->set_key(builder_.StringId(label.key)); if (label.is_string_label) { - new_label->set_str(builder_.StringId(label.str_label.c_str())); + new_label->set_str(builder_.StringId(label.str_label)); } else { new_label->set_num(label.num_label.value); // Note that if the unit is not defined in the label, it will be empty and // thus end up being a 0 as, by definition, "" has 0 as a string Id. - new_label->set_num_unit(builder_.StringId(label.num_label.unit.c_str())); + new_label->set_num_unit(builder_.StringId(label.num_label.unit)); } } } -void ProfileProtoBuilder::AddTrace(const ProfileStackTrace &profile_trace, +void ProfileProtoBuilder::AddTrace(const ProfileStackTrace& profile_trace, int32_t count) { - const TraceAndLabels &trace_and_labels = profile_trace.trace_and_labels; + const TraceAndLabels& trace_and_labels = profile_trace.trace_and_labels; auto sample = trace_samples_.SampleFor(trace_and_labels); auto metric_value = profile_trace.metric_value; @@ -210,51 +200,46 @@ void ProfileProtoBuilder::AddTrace(const ProfileStackTrace &profile_trace, InitSampleValues(sample, count, metric_value); - const JVMPI_CallTrace *trace = trace_and_labels.trace; + const JVMPI_CallTrace* trace = trace_and_labels.trace; int first_frame = SkipTopNativeFrames(*trace); for (int i = first_frame; i < trace->num_frames; ++i) { - auto &jvm_frame = trace->frames[i]; + auto& jvm_frame = trace->frames[i]; + bool is_leaf_pc = (i == first_frame && is_cpu_profile_); if (jvm_frame.lineno == kNativeFrameLineNum) { - AddNativeInfo(jvm_frame, profile, sample); + AddNativeInfo(jvm_frame, profile, sample, is_leaf_pc); } else { AddJavaInfo(jvm_frame, profile, sample); } } } -void ProfileProtoBuilder::AddJavaInfo( - const JVMPI_CallFrame &jvm_frame, - perftools::profiles::Profile *profile, - perftools::profiles::Sample *sample) { +void ProfileProtoBuilder::AddJavaInfo(const JVMPI_CallFrame& jvm_frame, + perftools::profiles::Profile* profile, + perftools::profiles::Sample* sample) { if (!jvm_frame.method_id) { - perftools::profiles::Location *location = location_builder_.LocationFor( - "", "[Unknown method]", "", 0, 0, 0); + perftools::profiles::Location* location = + location_builder_.LocationFor("", "[Unknown method]", "", 0, 0, 0); sample->add_location_id(location->id()); return; } - MethodInfo *method_info = method_info_cache_.Method(jvm_frame.method_id); + MethodInfo* method_info = method_info_cache_.Method(jvm_frame.method_id); int64_t line_number = method_info->LineNumber(jvm_frame); - perftools::profiles::Location *location = - location_builder_.LocationFor(method_info->ClassName(), - method_info->MethodName(), - method_info->FileName(), - method_info->StartLine(), - line_number, - 0); + perftools::profiles::Location* location = location_builder_.LocationFor( + method_info->ClassName(), method_info->MethodName(), + method_info->FileName(), method_info->StartLine(), line_number, 0); sample->add_location_id(location->id()); } -MethodInfoCache::MethodInfoCache(JNIEnv *jni_env, jvmtiEnv *jvmti_env) - : jni_env_(jni_env), jvmti_env_(jvmti_env) { -} +MethodInfoCache::MethodInfoCache(JNIEnv* jni_env, jvmtiEnv* jvmti_env) + : jni_env_(jni_env), jvmti_env_(jvmti_env) {} -MethodInfo *MethodInfoCache::Method(jmethodID method_id) { +MethodInfo* MethodInfoCache::Method(jmethodID method_id) { auto it = methods_.find(method_id); if (it != methods_.end()) { return it->second.get(); @@ -267,41 +252,50 @@ MethodInfo *MethodInfoCache::Method(jmethodID method_id) { int start_line = 0; // Set lineno to zero to get method first line. - JVMPI_CallFrame jvm_frame = { 0, method_id }; + JVMPI_CallFrame jvm_frame = {0, method_id}; GetStackFrameElements(jni_env_, jvmti_env_, jvm_frame, &file_name, &class_name, &method_name, &signature, &start_line); FixMethodParameters(&signature); string full_method_name = class_name + "." + method_name + signature; - unique_ptr unique_method( - new MethodInfo(jvmti_env_, full_method_name, class_name, file_name, - start_line)); + unique_ptr unique_method(new MethodInfo( + jvmti_env_, full_method_name, class_name, file_name, start_line)); auto method_ptr = unique_method.get(); methods_[method_id] = std::move(unique_method); return method_ptr; } -void ProfileProtoBuilder::AddNativeInfo(const JVMPI_CallFrame &jvm_frame, - perftools::profiles::Profile *profile, - perftools::profiles::Sample *sample) { - if (!native_cache_) { - int64_t address = reinterpret_cast(jvm_frame.method_id); - perftools::profiles::Location *location = location_builder_.LocationFor( - "", "[Unknown non-Java frame]", "", 0, kNativeFrameLineNum, address); - sample->add_location_id(location->id()); - return; - } +void ProfileProtoBuilder::AddNativeInfo(const JVMPI_CallFrame& jvm_frame, + perftools::profiles::Profile* profile, + perftools::profiles::Sample* sample, + bool is_leaf_pc) { + int64_t adjusted_address = reinterpret_cast(jvm_frame.method_id); - string function_name = native_cache_->GetFunctionName(jvm_frame); + // Adjust address by -1, so that the address is within the call instruction + // instead of at the start of the return instruction, as per + // go/new-z-page#ret-addr-fixup + // + // Note: This adjustment is not needed for leaf PCs in CPU profiler + // (b/496543822) + // + // We use 0 (NULL) to indicate the absence of a valid address, and so + // do not do this where it would be invalid i.e. leading to -1 + if (!is_leaf_pc && adjusted_address > 0) { + adjusted_address--; + } - if (SkipFrame(function_name)) { + if (!native_cache_) { + perftools::profiles::Location* location = + location_builder_.LocationFor("", "[Unknown non-Java frame]", "", 0, + kNativeFrameLineNum, adjusted_address); + sample->add_location_id(location->id()); return; } - perftools::profiles::Location *location = - native_cache_->GetLocation(jvm_frame, &location_builder_); + perftools::profiles::Location* location = native_cache_->GetLocation( + jvm_frame, &location_builder_, adjusted_address); sample->add_location_id(location->id()); } @@ -322,8 +316,7 @@ void ContentionProfileProtoBuilder::MultiplyBySamplingRate() { } size_t LocationBuilder::LocationInfoHash::operator()( - const LocationInfo &info) const { - + const LocationInfo& info) const { unsigned int h = 1; hash hash_string; @@ -339,42 +332,27 @@ size_t LocationBuilder::LocationInfoHash::operator()( } bool LocationBuilder::LocationInfoEquals::operator()( - const LocationInfo &info1, const LocationInfo &info2) const { + const LocationInfo& info1, const LocationInfo& info2) const { return info1.class_name == info2.class_name && - info1.function_name == info2.function_name && - info1.file_name == info2.file_name && - info1.line_number == info2.line_number && - info1.address == info2.address; + info1.function_name == info2.function_name && + info1.file_name == info2.file_name && + info1.line_number == info2.line_number && + info1.address == info2.address; } -perftools::profiles::Location *LocationBuilder::LocationFor( - const string &class_name, const string &function_name, - const string &file_name, int start_line, int line_number, - int64_t address) { +perftools::profiles::Location* LocationBuilder::LocationFor( + const string& class_name, const string& function_name, + const string& file_name, int start_line, int line_number, int64_t address) { auto profile = builder_->mutable_profile(); - // Adjust address by -1, so that the address is within the call instruction - // instead of at the start of the return instruction, as per - // go/new-z-page#ret-addr-fixup - // - // We use 0 (NULL) to indicate the absence of a valid address, and so - // do not do this where it would be invalid i.e. leading to -1 - address = (address > 0) ? address - 1 : 0; - - LocationInfo info { - class_name, - function_name, - file_name, - line_number, - address - }; + LocationInfo info{class_name, function_name, file_name, line_number, address}; if (locations_.count(info) > 0) { return locations_.find(info)->second; } auto location_id = profile->location_size() + 1; - perftools::profiles::Location *location = profile->add_location(); + perftools::profiles::Location* location = profile->add_location(); location->set_id(location_id); location->set_address(address); @@ -389,7 +367,7 @@ perftools::profiles::Location *LocationBuilder::LocationFor( SimplifyFunctionName(&simplified_name); auto function_id = builder_->FunctionId(simplified_name.c_str(), function_name.c_str(), - file_name.c_str(), start_line); + file_name.c_str(), start_line); line->set_function_id(function_id); line->set_line(line_number); @@ -398,7 +376,7 @@ perftools::profiles::Location *LocationBuilder::LocationFor( return location; } -bool SampleLabel::operator==(const SampleLabel &other) const { +bool SampleLabel::operator==(const SampleLabel& other) const { if (other.key != key) { return false; } @@ -432,27 +410,27 @@ size_t NumLabelValue::Hash(size_t current_hash_value) const { } size_t TraceSamples::TraceHash::operator()( - const TraceAndLabels &trace_values) const { + const TraceAndLabels& trace_values) const { unsigned int hash = 1; - const JVMPI_CallTrace *trace = trace_values.trace; + const JVMPI_CallTrace* trace = trace_values.trace; for (int f = 0; f < trace->num_frames; f++) { { int len = sizeof(jint); - char *arr = reinterpret_cast(&trace->frames[f].lineno); + char* arr = reinterpret_cast(&trace->frames[f].lineno); for (int i = 0; i < len; i++) { hash = 31U * hash + arr[i]; } } { int len = sizeof(jmethodID); - char *arr = reinterpret_cast(&trace->frames[f].method_id); + char* arr = reinterpret_cast(&trace->frames[f].method_id); for (int i = 0; i < len; i++) { hash = 31U * hash + arr[i]; } } } - for (const SampleLabel &label : trace_values.labels) { + for (const SampleLabel& label : trace_values.labels) { hash = label.Hash(hash); } @@ -460,14 +438,14 @@ size_t TraceSamples::TraceHash::operator()( } bool TraceSamples::TraceEquals::operator()( - const TraceAndLabels &trace_values1, - const TraceAndLabels &trace_values2) const { + const TraceAndLabels& trace_values1, + const TraceAndLabels& trace_values2) const { if (trace_values1.labels != trace_values2.labels) { return false; } - const JVMPI_CallTrace *trace1 = trace_values1.trace; - const JVMPI_CallTrace *trace2 = trace_values2.trace; + const JVMPI_CallTrace* trace1 = trace_values1.trace; + const JVMPI_CallTrace* trace2 = trace_values2.trace; if (trace1->num_frames != trace2->num_frames) { return false; } @@ -485,8 +463,8 @@ bool TraceSamples::TraceEquals::operator()( return true; } -perftools::profiles::Sample *TraceSamples::SampleFor( - const TraceAndLabels &trace) const { +perftools::profiles::Sample* TraceSamples::SampleFor( + const TraceAndLabels& trace) const { auto found = traces_.find(trace); if (found == traces_.end()) { return nullptr; @@ -494,8 +472,8 @@ perftools::profiles::Sample *TraceSamples::SampleFor( return found->second; } -void TraceSamples::Add(const TraceAndLabels &trace, - perftools::profiles::Sample *sample) { +void TraceSamples::Add(const TraceAndLabels& trace, + perftools::profiles::Sample* sample) { traces_[trace] = sample; } @@ -515,32 +493,30 @@ double CalculateSamplingRatio(int64_t rate, int64_t count, } unique_ptr ProfileProtoBuilder::ForHeap( - JNIEnv *jni_env, jvmtiEnv *jvmti_env, int64_t sampling_rate, - ProfileFrameCache *cache) { + JNIEnv* jni_env, jvmtiEnv* jvmti_env, int64_t sampling_rate, + ProfileFrameCache* cache) { // Cache can be nullptr because the heap sampler can be using a JVMTI // Java-only stackframe gatherer. - return unique_ptr( - new HeapProfileProtoBuilder(jni_env, jvmti_env, sampling_rate, cache, - true, {})); + return unique_ptr(new HeapProfileProtoBuilder( + jni_env, jvmti_env, sampling_rate, cache, true)); } unique_ptr ProfileProtoBuilder::ForCpu( - JNIEnv *jni_env, jvmtiEnv *jvmti_env, int64_t duration_ns, - int64_t sampling_rate, ProfileFrameCache *cache) { - CHECK (cache != nullptr) + JNIEnv* jni_env, jvmtiEnv* jvmti_env, int64_t duration_ns, + int64_t sampling_rate, ProfileFrameCache* cache) { + CHECK(cache != nullptr) << "CPU profiles may have native frames, cache must be provided"; - return unique_ptr( - new CpuProfileProtoBuilder(jni_env, jvmti_env, duration_ns, - sampling_rate, cache, false, {})); + return unique_ptr(new CpuProfileProtoBuilder( + jni_env, jvmti_env, duration_ns, sampling_rate, cache, false)); } unique_ptr ProfileProtoBuilder::ForContention( - JNIEnv *jni_env, jvmtiEnv *jvmti_env, int64_t sampling_rate, - int64_t duration_nanos, ProfileFrameCache *cache) { - CHECK (cache != nullptr) + JNIEnv* jni_env, jvmtiEnv* jvmti_env, int64_t sampling_rate, + int64_t duration_nanos, ProfileFrameCache* cache) { + CHECK(cache != nullptr) << "Contention profiles may have native frames, cache must be provided"; return unique_ptr(new ContentionProfileProtoBuilder( - jni_env, jvmti_env, sampling_rate, duration_nanos, cache, false, {})); + jni_env, jvmti_env, sampling_rate, duration_nanos, cache, false)); } } // namespace javaprofiler diff --git a/third_party/javaprofiler/profile_proto_builder.h b/third_party/javaprofiler/profile_proto_builder.h index fbb738f7..972cb8f9 100644 --- a/third_party/javaprofiler/profile_proto_builder.h +++ b/third_party/javaprofiler/profile_proto_builder.h @@ -17,10 +17,10 @@ #ifndef THIRD_PARTY_JAVAPROFILER_PROFILE_PROTO_BUILDER_H__ #define THIRD_PARTY_JAVAPROFILER_PROFILE_PROTO_BUILDER_H__ +#include #include #include -#include #include #include #include @@ -28,6 +28,7 @@ #include #include "perftools/profiles/proto/builder.h" +#include "absl/strings/string_view.h" #include "third_party/javaprofiler/method_info.h" #include "third_party/javaprofiler/stacktrace_decls.h" @@ -43,10 +44,10 @@ struct NumLabelValue { const std::string unit; // Constructor with a value and unit name. - NumLabelValue(int64_t v = 0, const std::string &u = "") : value(v), unit(u) {} + NumLabelValue(int64_t v = 0, const std::string& u = "") : value(v), unit(u) {} // Equality operator with another NumLabelValue. - bool operator==(const NumLabelValue &other) const { + bool operator==(const NumLabelValue& other) const { return value == other.value && unit == other.unit; } @@ -60,11 +61,11 @@ struct SampleLabel { SampleLabel() : key(""), is_string_label(true) {} // Constructor for a string label. - SampleLabel(const std::string &k, const std::string &str) + SampleLabel(const std::string& k, const std::string& str) : key(k), str_label(str), is_string_label(true) {} // Constructor for a numerical label. - SampleLabel(const std::string &k, int64_t num, const std::string &unit = "") + SampleLabel(const std::string& k, int64_t num, const std::string& unit = "") : key(k), num_label(num, unit), is_string_label(false) {} // The label key. @@ -79,7 +80,7 @@ struct SampleLabel { const bool is_string_label; // Equality operator for the label. - bool operator==(const SampleLabel &other) const; + bool operator==(const SampleLabel& other) const; // Hash method for this numerical label. size_t Hash(size_t current_hash_value) const; @@ -89,25 +90,25 @@ struct SampleLabel { // constructing the profile proto. struct TraceAndLabels { // Constructor for a trace without labels. - TraceAndLabels(const JVMPI_CallTrace *t) : trace(t) {} + TraceAndLabels(const JVMPI_CallTrace* t) : trace(t) {} // Constructor for a trace with labels. - TraceAndLabels(const JVMPI_CallTrace *t, const std::vector &l) + TraceAndLabels(const JVMPI_CallTrace* t, const std::vector& l) : trace(t), labels(l) {} // Adds a string label to the associated trace. - void AddLabel(const std::string &key, const std::string &str_value) { + void AddLabel(const std::string& key, const std::string& str_value) { labels.push_back({key, str_value}); } // Adds a numeric label to the associated trace. - void AddLabel(const std::string &key, int64_t num_value, - const std::string &unit = "") { + void AddLabel(const std::string& key, int64_t num_value, + const std::string& unit = "") { labels.push_back({key, num_value, unit}); } // Trace associated with given labels. - const JVMPI_CallTrace *trace; + const JVMPI_CallTrace* trace; // Labels associated with the trace. std::vector labels; }; @@ -116,12 +117,12 @@ struct TraceAndLabels { // potential labels associated with this trace. struct ProfileStackTrace { // Constructor for a stack trace without any label. - ProfileStackTrace(const JVMPI_CallTrace *trace = nullptr, int64_t m_value = 0) + ProfileStackTrace(const JVMPI_CallTrace* trace = nullptr, int64_t m_value = 0) : metric_value(m_value), trace_and_labels(trace) {} // Constructor for a stack trace with labels. - ProfileStackTrace(const JVMPI_CallTrace *trace, int64_t m_value, - const std::vector &labels) + ProfileStackTrace(const JVMPI_CallTrace* trace, int64_t m_value, + const std::vector& labels) : metric_value(m_value), trace_and_labels(trace, labels) {} // Metric associated with the trace and labels. @@ -136,47 +137,43 @@ class TraceSamples { public: // Returns an existing sample with the same trace and labels if exists, // nullptr otherwise. - perftools::profiles::Sample *SampleFor(const TraceAndLabels &trace) const; + perftools::profiles::Sample* SampleFor(const TraceAndLabels& trace) const; // Adds a given trace and label to storage and associates it with a given // sample. - void Add(const TraceAndLabels &trace, perftools::profiles::Sample *sample); + void Add(const TraceAndLabels& trace, perftools::profiles::Sample* sample); private: struct TraceHash { - size_t operator()(const TraceAndLabels &trace_values) const; + size_t operator()(const TraceAndLabels& trace_values) const; }; struct TraceEquals { - bool operator()(const TraceAndLabels &trace_values1, - const TraceAndLabels &trace_values2) const; + bool operator()(const TraceAndLabels& trace_values1, + const TraceAndLabels& trace_values2) const; }; - std::unordered_map traces_; }; -enum class NativeSymbolization { - SYMBOLS, - NO_SYMBOLS -}; +enum class NativeSymbolization { SYMBOLS, NO_SYMBOLS }; // Store locations previously seen so that the profile is only // modified for new locations. class LocationBuilder { public: - explicit LocationBuilder(perftools::profiles::Builder *builder) + explicit LocationBuilder(perftools::profiles::Builder* builder) : builder_(builder) {} // Return an existing or new location matching the given parameters, // modifying the profile as needed to add new function and location // information. - perftools::profiles::Location *LocationFor(const std::string &class_name, - const std::string &function_name, - const std::string &file_name, - int start_line, - int line_number, + perftools::profiles::Location* LocationFor(const std::string& class_name, + const std::string& function_name, + const std::string& file_name, + int start_line, int line_number, int64_t address); private: @@ -189,30 +186,30 @@ class LocationBuilder { }; struct LocationInfoHash { - size_t operator()(const LocationInfo &info) const; + size_t operator()(const LocationInfo& info) const; }; struct LocationInfoEquals { - bool operator()(const LocationInfo &info1, const LocationInfo &info2) const; + bool operator()(const LocationInfo& info1, const LocationInfo& info2) const; }; - perftools::profiles::Builder *builder_; + perftools::profiles::Builder* builder_; - std::unordered_map locations_; + std::unordered_map + locations_; }; // Remember traces and use the information to create locations with native // information if supported. class ProfileFrameCache { public: - virtual void ProcessTraces(const ProfileStackTrace *traces, + virtual void ProcessTraces(const ProfileStackTrace* traces, int num_traces) = 0; - virtual perftools::profiles::Location *GetLocation( - const JVMPI_CallFrame &jvm_frame, LocationBuilder *location_builder) = 0; - - virtual std::string GetFunctionName(const JVMPI_CallFrame &jvm_frame) = 0; + virtual perftools::profiles::Location* GetLocation( + const JVMPI_CallFrame& jvm_frame, LocationBuilder* location_builder, + int64_t adjusted_address) = 0; virtual ~ProfileFrameCache() {} }; @@ -231,13 +228,13 @@ class ProfileFrameCache { // cache-size management. class MethodInfoCache { public: - MethodInfoCache(JNIEnv *jni_env, jvmtiEnv *jvmti_env); + MethodInfoCache(JNIEnv* jni_env, jvmtiEnv* jvmti_env); - MethodInfo *Method(jmethodID id); + MethodInfo* Method(jmethodID id); private: - JNIEnv *jni_env_; - jvmtiEnv *jvmti_env_; + JNIEnv* jni_env_; + jvmtiEnv* jvmti_env_; std::unordered_map> methods_; }; @@ -249,19 +246,28 @@ class ProfileProtoBuilder { // Adds traces to the proto. The traces array must not be deleted // before calling CreateProto. - void AddTraces(const ProfileStackTrace *traces, int num_traces); + void AddTraces(const ProfileStackTrace* traces, int num_traces); // Adds traces to the proto, where each trace has a defined count // of occurrences. The traces array must not be deleted // before calling CreateProto. - void AddTraces(const ProfileStackTrace *traces, const int32_t *counts, + void AddTraces(const ProfileStackTrace* traces, const int32_t* counts, int num_traces); // Adds a "fake" trace with a single frame. Used to represent JVM // tasks such as JIT compilation and GC. - void AddArtificialTrace(const std::string &name, int count, + void AddArtificialTrace(const std::string& name, int count, int sampling_rate); + // Sets the regular expression which is used to drop matching frames, along + // with their successors. + void SetDropFrames(absl::string_view drop_frames) { + if (drop_frames.empty()) { + return; + } + builder_.mutable_profile()->set_drop_frames(builder_.StringId(drop_frames)); + } + // Builds the proto. Calling any other method on the class after calling // this has undefined behavior. virtual std::unique_ptr CreateProto() = 0; @@ -273,22 +279,22 @@ class ProfileProtoBuilder { // GetStackTrace and remain in pure Java land frames. Other ForX methods // will fail an assertion when attempting a nullptr cache. static std::unique_ptr ForHeap( - JNIEnv *jni_env, jvmtiEnv *jvmti_env, int64_t sampling_rate, - ProfileFrameCache *cache = nullptr); + JNIEnv* jni_env, jvmtiEnv* jvmti_env, int64_t sampling_rate, + ProfileFrameCache* cache = nullptr); - static std::unique_ptr ForCpu(JNIEnv *jni_env, - jvmtiEnv *jvmti_env, + static std::unique_ptr ForCpu(JNIEnv* jni_env, + jvmtiEnv* jvmti_env, int64_t duration_ns, int64_t sampling_rate, - ProfileFrameCache *cache); + ProfileFrameCache* cache); static std::unique_ptr ForContention( - JNIEnv *jni_env, jvmtiEnv *jvmti_env, int64_t duration_ns, - int64_t sampling_rate, ProfileFrameCache *cache); + JNIEnv* jni_env, jvmtiEnv* jvmti_env, int64_t duration_ns, + int64_t sampling_rate, ProfileFrameCache* cache); protected: struct SampleType { - SampleType(const std::string &type_in, const std::string &unit_in) + SampleType(const std::string& type_in, const std::string& unit_in) : type(type_in), unit(unit_in) {} std::string type; @@ -298,12 +304,11 @@ class ProfileProtoBuilder { // Create the profile proto builder, if native_cache is nullptr, then no // information about native frames can be provided. The proto buffer will then // contain "Unknown native method" frames. - ProfileProtoBuilder(JNIEnv *env, jvmtiEnv *jvmti_env, - ProfileFrameCache *native_cache, int64_t sampling_rate, - const SampleType &count_type, - const SampleType &metric_type, - bool skip_top_native_frames, - std::vector skip_frames); + ProfileProtoBuilder(JNIEnv* env, jvmtiEnv* jvmti_env, + ProfileFrameCache* native_cache, int64_t sampling_rate, + const SampleType& count_type, + const SampleType& metric_type, + bool skip_top_native_frames); // Build the proto, unsampling the sample metrics. Calling any other method // on the class after calling this has undefined behavior. @@ -315,35 +320,32 @@ class ProfileProtoBuilder { perftools::profiles::Builder builder_; int64_t sampling_rate_ = 0; + bool is_cpu_profile_ = false; private: - bool SkipFrame(const std::string &function_name) const; - int SkipTopNativeFrames(const JVMPI_CallTrace &trace); - void AddSampleType(const SampleType &sample_type); - void SetPeriodType(const SampleType &metric_type); - void InitSampleValues(perftools::profiles::Sample *sample, int64_t count, + int SkipTopNativeFrames(const JVMPI_CallTrace& trace) const; + void AddSampleType(const SampleType& sample_type); + void SetPeriodType(const SampleType& metric_type); + void InitSampleValues(perftools::profiles::Sample* sample, int64_t count, int64_t metric); - void UpdateSampleValues(perftools::profiles::Sample *sample, int64_t count, + void UpdateSampleValues(perftools::profiles::Sample* sample, int64_t count, int64_t size); - void AddTrace(const ProfileStackTrace &trace, int32_t count); - void AddJavaInfo(const JVMPI_CallFrame &jvm_frame, - perftools::profiles::Profile *profile, - perftools::profiles::Sample *sample); - void AddNativeInfo(const JVMPI_CallFrame &jvm_frame, - perftools::profiles::Profile *profile, - perftools::profiles::Sample *sample); + void AddTrace(const ProfileStackTrace& trace, int32_t count); + void AddJavaInfo(const JVMPI_CallFrame& jvm_frame, + perftools::profiles::Profile* profile, + perftools::profiles::Sample* sample); + void AddNativeInfo(const JVMPI_CallFrame& jvm_frame, + perftools::profiles::Profile* profile, + perftools::profiles::Sample* sample, bool is_leaf_pc); void UnsampleMetrics(); - int64_t Location(MethodInfo *method, const JVMPI_CallFrame &frame); - - void AddLabels(const TraceAndLabels &trace_and_labels, - perftools::profiles::Sample *sample); + int64_t Location(MethodInfo* method, const JVMPI_CallFrame& frame); - JNIEnv *jni_env_; - jvmtiEnv *jvmti_env_; + void AddLabels(const TraceAndLabels& trace_and_labels, + perftools::profiles::Sample* sample); MethodInfoCache method_info_cache_; - ProfileFrameCache *native_cache_; + ProfileFrameCache* native_cache_; TraceSamples trace_samples_; LocationBuilder location_builder_; @@ -361,17 +363,15 @@ double CalculateSamplingRatio(int64_t rate, int64_t count, class CpuProfileProtoBuilder : public ProfileProtoBuilder { public: - CpuProfileProtoBuilder(JNIEnv *jni_env, jvmtiEnv *jvmti_env, + CpuProfileProtoBuilder(JNIEnv* jni_env, jvmtiEnv* jvmti_env, int64_t duration_ns, int64_t sampling_rate, - ProfileFrameCache *cache, - bool skip_top_native_frames, - std::vector skip_frames) + ProfileFrameCache* cache, bool skip_top_native_frames) : ProfileProtoBuilder( jni_env, jvmti_env, cache, sampling_rate, ProfileProtoBuilder::SampleType("samples", "count"), ProfileProtoBuilder::SampleType("cpu", "nanoseconds"), - skip_top_native_frames, - skip_frames) { + skip_top_native_frames) { + is_cpu_profile_ = true; builder_.mutable_profile()->set_duration_nanos(duration_ns); builder_.mutable_profile()->set_period(sampling_rate); } @@ -383,18 +383,14 @@ class CpuProfileProtoBuilder : public ProfileProtoBuilder { class HeapProfileProtoBuilder : public ProfileProtoBuilder { public: - HeapProfileProtoBuilder(JNIEnv *jni_env, jvmtiEnv *jvmti_env, - int64_t sampling_rate, ProfileFrameCache *cache, - bool skip_top_native_frames, - std::vector skip_frames) + HeapProfileProtoBuilder(JNIEnv* jni_env, jvmtiEnv* jvmti_env, + int64_t sampling_rate, ProfileFrameCache* cache, + bool skip_top_native_frames) : ProfileProtoBuilder( jni_env, jvmti_env, cache, sampling_rate, ProfileProtoBuilder::SampleType("inuse_objects", "count"), ProfileProtoBuilder::SampleType("inuse_space", "bytes"), - skip_top_native_frames, - skip_frames) - { - } + skip_top_native_frames) {} std::unique_ptr CreateProto() override { return CreateUnsampledProto(); @@ -403,17 +399,15 @@ class HeapProfileProtoBuilder : public ProfileProtoBuilder { class ContentionProfileProtoBuilder : public ProfileProtoBuilder { public: - ContentionProfileProtoBuilder(JNIEnv *jni_env, jvmtiEnv *jvmti_env, + ContentionProfileProtoBuilder(JNIEnv* jni_env, jvmtiEnv* jvmti_env, int64_t duration_nanos, int64_t sampling_rate, - ProfileFrameCache *cache, - bool skip_top_native_frames, - std::vector skip_frames) + ProfileFrameCache* cache, + bool skip_top_native_frames) : ProfileProtoBuilder( jni_env, jvmti_env, cache, sampling_rate, ProfileProtoBuilder::SampleType("contentions", "count"), ProfileProtoBuilder::SampleType("delay", "microseconds"), - skip_top_native_frames, - skip_frames) { + skip_top_native_frames) { builder_.mutable_profile()->set_duration_nanos(duration_nanos); builder_.mutable_profile()->set_period(sampling_rate); builder_.mutable_profile()->set_default_sample_type( diff --git a/third_party/javaprofiler/profile_test_lib.cc b/third_party/javaprofiler/profile_test_lib.cc index 8c99146a..65c99877 100644 --- a/third_party/javaprofiler/profile_test_lib.cc +++ b/third_party/javaprofiler/profile_test_lib.cc @@ -14,6 +14,8 @@ #include "third_party/javaprofiler/profile_test_lib.h" +#include + #include "testing/base/public/gunit.h" namespace google { @@ -23,8 +25,7 @@ std::atomic JvmProfileTestLib::line_number_call_count; std::atomic JvmProfileTestLib::method_declaring_class_call_count; std::atomic JvmProfileTestLib::method_name_call_count; -static jvmtiError Allocate(jvmtiEnv* jvmti, - jlong size, +static jvmtiError Allocate(jvmtiEnv* jvmti, jlong size, unsigned char** mem_ptr) { *mem_ptr = reinterpret_cast(malloc(size)); return JVMTI_ERROR_NONE; @@ -62,7 +63,7 @@ static jvmtiError GetMethodName(jvmtiEnv* jvmti, jmethodID method_id, CreateJvmtiString(jvmti, "()V", sig_str); break; case 4: - CreateJvmtiString(jvmti, "fourthMethodName$$Lambda$42.42", name_str); + CreateJvmtiString(jvmti, "fourthMethodName$$Lambda.0x42.run", name_str); CreateJvmtiString(jvmti, "()V", sig_str); break; default: @@ -94,15 +95,15 @@ static jvmtiError GetClassSignature(jvmtiEnv* jvmti, jclass declaring_class, return JVMTI_ERROR_NONE; } -static jvmtiError GetMethodDeclaringClass(jvmtiEnv *env, jmethodID method, - jclass *declaring_class) { +static jvmtiError GetMethodDeclaringClass(jvmtiEnv* env, jmethodID method, + jclass* declaring_class) { JvmProfileTestLib::method_declaring_class_call_count++; *declaring_class = reinterpret_cast(method); return JVMTI_ERROR_NONE; } -static jvmtiError GetSourceFileName(jvmtiEnv *env, jclass klass, - char **source_name_ptr) { +static jvmtiError GetSourceFileName(jvmtiEnv* env, jclass klass, + char** source_name_ptr) { if (source_name_ptr) { switch (reinterpret_cast(klass)) { case 1: @@ -126,23 +127,19 @@ static jvmtiError GetSourceFileName(jvmtiEnv *env, jclass klass, } static jvmtiLineNumberEntry fake_line_number_table[] = { - { 30, 4 }, - { 60, 5 }, - { 90, 6 }, - { 120, 7 }, - { 150, 8 }, + {30, 4}, {60, 5}, {90, 6}, {120, 7}, {150, 8}, }; -static jvmtiError GetLineNumberTable(jvmtiEnv *env, jmethodID method, - jint *entry_count_ptr, - jvmtiLineNumberEntry **table_ptr) { +static jvmtiError GetLineNumberTable(jvmtiEnv* env, jmethodID method, + jint* entry_count_ptr, + jvmtiLineNumberEntry** table_ptr) { JvmProfileTestLib::line_number_call_count++; - size_t table_size = arraysize(fake_line_number_table) * - sizeof(jvmtiLineNumberEntry); + size_t table_size = + std::size(fake_line_number_table) * sizeof(jvmtiLineNumberEntry); env->Allocate(table_size, reinterpret_cast(table_ptr)); - *entry_count_ptr = arraysize(fake_line_number_table); + *entry_count_ptr = std::size(fake_line_number_table); std::memcpy(*table_ptr, fake_line_number_table, table_size); return JVMTI_ERROR_NONE; @@ -170,7 +167,7 @@ static jvmtiError GetStackTrace(jvmtiEnv* env, jthread thread, jint start_depth, break; } - jint count = std::min(max_frame_count, (jint) frames.size()); + jint count = std::min(max_frame_count, (jint)frames.size()); memcpy(frame_buffer, &frames[0], sizeof(*frame_buffer) * count); *count_ptr = count; @@ -189,8 +186,8 @@ std::vector CreateStackTrace(int i) { frames.push_back({128, reinterpret_cast(3)}); break; default: - // Add nothing - ; + // Add nothing + ; } return frames; diff --git a/third_party/javaprofiler/profile_test_lib.h b/third_party/javaprofiler/profile_test_lib.h index c0251e49..01537628 100644 --- a/third_party/javaprofiler/profile_test_lib.h +++ b/third_party/javaprofiler/profile_test_lib.h @@ -26,17 +26,15 @@ namespace google { namespace javaprofiler { class TestProfileFrameCache : public ProfileFrameCache { - void ProcessTraces(const ProfileStackTrace *traces, int num_traces) override { + void ProcessTraces(const ProfileStackTrace* traces, int num_traces) override { } - perftools::profiles::Location *GetLocation( - const JVMPI_CallFrame &jvm_frame, - LocationBuilder *location_builder) override { + perftools::profiles::Location* GetLocation( + const JVMPI_CallFrame& jvm_frame, LocationBuilder* location_builder, + int64_t adjusted_address) override { return &nop_; } - std::string GetFunctionName(const JVMPI_CallFrame &jvm_frame) { return ""; } - private: perftools::profiles::Location nop_; }; diff --git a/third_party/javaprofiler/stacktrace_decls.h b/third_party/javaprofiler/stacktrace_decls.h index c7fa1200..c677ad75 100644 --- a/third_party/javaprofiler/stacktrace_decls.h +++ b/third_party/javaprofiler/stacktrace_decls.h @@ -55,9 +55,9 @@ typedef struct { // frames - the JVMPI_CallFrames that make up this trace. Callee // followed by callers. typedef struct { - JNIEnv *env_id; + JNIEnv* env_id; jint num_frames; - JVMPI_CallFrame *frames; + JVMPI_CallFrame* frames; } JVMPI_CallTrace; // Placeholder (fake) line number for native frames in ASGCT_CallFrame. A native diff --git a/third_party/javaprofiler/stacktrace_fixer.cc b/third_party/javaprofiler/stacktrace_fixer.cc index 5e461b41..a92383b9 100644 --- a/third_party/javaprofiler/stacktrace_fixer.cc +++ b/third_party/javaprofiler/stacktrace_fixer.cc @@ -12,14 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "third_party/javaprofiler/stacktrace_fixer.h" + #include #include -#include #include -#include "third_party/javaprofiler/stacktrace_fixer.h" - namespace google { namespace javaprofiler { @@ -29,7 +28,7 @@ namespace { // followed by specified suffix chars and removing those. For example, // calling the function with ("foo123bar", "foo", "321") returns "foobar". template -void SimplifySuffixedName(std::string *name, const char (&trigger)[M], +void SimplifySuffixedName(std::string* name, const char (&trigger)[M], const char (&suffix_chars)[N]) { size_t first = 0; while ((first = name->find(trigger, first)) != std::string::npos) { @@ -50,61 +49,35 @@ constexpr char hexdigits[] = "0123456789abcdef"; // or '$$EnhancedBy*$$' in its name) to make it more human readable, and group // related functions under a single name. This could be done with a regexp // replacement, but including RE2 increases the size of the agent. -void SimplifyDynamicClassName(std::string *name) { +void SimplifyDynamicClassName(std::string* name) { // Replace $$[0-9a-f]+ by $$ to remove unique values, for example in // $FastClassByCGLIB$$fd6bdf6d.invoke. SimplifySuffixedName(name, "$$", hexdigits); } -// Simplifies the name of a lambda method to remove unique values. -// For JDK 11 and older, replaces $$Lambda$[0-9]+\.[0-9]+ with $$Lambda$. -// For example: com.google.something.Something$$Lambda$197.1849072452.run. -// For JDK 21 and newer, replaces $$Lambda\.0x[0-9a-f]+ with $$Lambda. -// For example: com.google.something.Something$$Lambda.0x00007ff38d3c11f8.run. -void SimplifyLambdaName(std::string *name) { +// Simplifies the name of a lambda method to replace $$Lambda\.0x[0-9a-f]+ with +// $$Lambda to remove unique values, for example in +// com.google.something.Something$$Lambda.0x00007ff38d3c11f8.run. +// Note that this naming format is valid in JDK 21 and later. +void SimplifyLambdaName(std::string* name) { constexpr char trigger[] = "$$Lambda"; const size_t trigger_length = strlen(trigger); - // Assume and handle just one instance of a $$Lambda$ pattern. + // Assume and handle just one instance of a $$Lambda pattern. size_t first = name->find(trigger); if (first == std::string::npos) { return; } first += trigger_length; - if (first >= name->size()) { + // Skip '.0x' + if (first + 3 >= name->size() || (*name)[first] != '.' || + (*name)[first + 1] != '0' || (*name)[first + 2] != 'x') { return; } - bool is_pre_jdk21 = false; - if ((*name)[first] == '$') { - is_pre_jdk21 = true; - first++; - } - - size_t last; - if (is_pre_jdk21) { - if (first >= name->size() || !std::isdigit((*name)[first])) { - return; - } - last = name->find_first_not_of(digits, first); - if (last == std::string::npos || (*name)[last] != '.') { - return; - } - last++; // skip the dot - if (last >= name->size() || !std::isdigit((*name)[last])) { - return; - } - last = name->find_first_not_of(digits, last); - } else { - // Skip '0x' - if (first + 3 >= name->size() || (*name)[first] != '.' || - (*name)[first + 1] != '0' || (*name)[first + 2] != 'x') { - return; - } - last = name->find_first_not_of(hexdigits, first + 3); - // check for '.' after the 0x... address - if (last != std::string::npos && (*name)[last] != '.') { - return; - } + size_t last = name->find_first_not_of(hexdigits, first + 3); + // check for '.' after the 0x... address + if (last != std::string::npos && (*name)[last] != '.') { + return; } if (last == std::string::npos) { @@ -117,50 +90,38 @@ void SimplifyLambdaName(std::string *name) { // Simplifies the name of a method generated by the runtime as a reflection // stub. See the test file for examples, or generateName() in // jdk/internal/reflect/MethodAccessorGenerator.java. -void SimplifyInternalReflectionMethodName(std::string *name) { +void SimplifyInternalReflectionMethodName(std::string* name) { SimplifySuffixedName( - name, - "jdk.internal.reflect.GeneratedConstructorAccessor", - digits); + name, "jdk.internal.reflect.GeneratedConstructorAccessor", digits); - SimplifySuffixedName( - name, - "jdk.internal.reflect.GeneratedMethodAccessor", - digits); + SimplifySuffixedName(name, "jdk.internal.reflect.GeneratedMethodAccessor", + digits); SimplifySuffixedName( - name, - "jdk.internal.reflect.GeneratedSerializationConstructorAccessor", + name, "jdk.internal.reflect.GeneratedSerializationConstructorAccessor", digits); } // Simplifies the name of a method generated by the runtime as a reflection // stub. See the test file for examples, or generateName() in // sun/reflect/MethodAccessorGenerator.java. -void SimplifyReflectionMethodName(std::string *name) { - SimplifySuffixedName( - name, - "sun.reflect.GeneratedConstructorAccessor", - digits); +void SimplifyReflectionMethodName(std::string* name) { + SimplifySuffixedName(name, "sun.reflect.GeneratedConstructorAccessor", + digits); - SimplifySuffixedName( - name, - "sun.reflect.GeneratedMethodAccessor", - digits); + SimplifySuffixedName(name, "sun.reflect.GeneratedMethodAccessor", digits); SimplifySuffixedName( - name, - "sun.reflect.GeneratedSerializationConstructorAccessor", - digits); + name, "sun.reflect.GeneratedSerializationConstructorAccessor", digits); } -std::string ParseMethodTypeSignatureWithReturn(const char *buffer, - int buffer_size, int *pos); +std::string ParseMethodTypeSignatureWithReturn(const char* buffer, + int buffer_size, int* pos); // JVM type signature parser and pretty printer. It returns the pretty-printed // string; it also modifies the position pointer in the input buffer. // TODO: Move ParseFieldType to replace the string directly. -std::string ParseFieldType(const char *buffer, int buffer_size, int *pos) { +std::string ParseFieldType(const char* buffer, int buffer_size, int* pos) { if (*pos >= buffer_size) { return ""; } @@ -197,9 +158,9 @@ std::string ParseFieldType(const char *buffer, int buffer_size, int *pos) { } case 'L': { // Parse the following string ending with semicolon. - const char *begin = buffer + *pos; - const char *end = buffer + buffer_size; - for (const char *cur = begin; cur < end; cur++) { + const char* begin = buffer + *pos; + const char* end = buffer + buffer_size; + for (const char* cur = begin; cur < end; cur++) { if (*cur == ';') { *pos += (cur - begin) + 1; return std::string(begin, cur); @@ -225,12 +186,12 @@ std::string ParseFieldType(const char *buffer, int buffer_size, int *pos) { } } -inline bool AtSignatureEnd(const char* buffer, int buffer_size, int *pos) { +inline bool AtSignatureEnd(const char* buffer, int buffer_size, int* pos) { return *pos >= buffer_size || buffer[*pos] == ')'; } -std::string ParseMethodTypeSignatureInternal(const char *buffer, - int buffer_size, int *pos) { +std::string ParseMethodTypeSignatureInternal(const char* buffer, + int buffer_size, int* pos) { if (buffer == nullptr || pos == nullptr || *pos >= buffer_size || buffer[*pos] != '(') { return ""; @@ -259,13 +220,13 @@ std::string ParseMethodTypeSignatureInternal(const char *buffer, // JVM method type signature parser and pretty printer. It returns the // pretty-printed string; it also modifies the position pointer in the input // buffer. -std::string ParseMethodTypeSignature(const char *buffer, int buffer_size, - int *pos) { +std::string ParseMethodTypeSignature(const char* buffer, int buffer_size, + int* pos) { return ParseMethodTypeSignatureInternal(buffer, buffer_size, pos); } -std::string ParseMethodTypeSignatureWithReturn(const char *buffer, - int buffer_size, int *pos) { +std::string ParseMethodTypeSignatureWithReturn(const char* buffer, + int buffer_size, int* pos) { std::string argument_string = ParseMethodTypeSignatureInternal(buffer, buffer_size, pos); if (argument_string.empty()) { @@ -283,25 +244,24 @@ std::string ParseMethodTypeSignatureWithReturn(const char *buffer, } // namespace -void SimplifyFunctionName(std::string *name) { +void SimplifyFunctionName(std::string* name) { SimplifyDynamicClassName(name); SimplifyLambdaName(name); SimplifyReflectionMethodName(name); SimplifyInternalReflectionMethodName(name); } -void FixPath(std::string *s) { std::replace(s->begin(), s->end(), '/', '.'); } +void FixPath(std::string* s) { std::replace(s->begin(), s->end(), '/', '.'); } -void PrettyPrintSignature(std::string *s) { +void PrettyPrintSignature(std::string* s) { int pos = 0; std::string result = ParseFieldType(s->data(), s->length(), &pos); FixPath(&result); *s = result; } -void FixMethodParameters(std::string *signature) { - if (signature == nullptr || signature->empty() || - signature->at(0) != '(') { +void FixMethodParameters(std::string* signature) { + if (signature == nullptr || signature->empty() || signature->at(0) != '(') { return; } diff --git a/third_party/javaprofiler/stacktrace_fixer.h b/third_party/javaprofiler/stacktrace_fixer.h index ed15fd9f..8d9842bd 100644 --- a/third_party/javaprofiler/stacktrace_fixer.h +++ b/third_party/javaprofiler/stacktrace_fixer.h @@ -24,19 +24,19 @@ namespace google { namespace javaprofiler { - // Simplifies the name of a function to make it more human readable, and group - // related functions under a single name. -void SimplifyFunctionName(std::string *name); +// Simplifies the name of a function to make it more human readable, and group +// related functions under a single name. +void SimplifyFunctionName(std::string* name); // Fix the parameter signature from a JVM type signature to a pretty-print // one. -void FixMethodParameters(std::string *signature); +void FixMethodParameters(std::string* signature); // Convert class name format from "pkg/name/class" to "pkg.name.class". -void FixPath(std::string *s); +void FixPath(std::string* s); // Pretty-prints a JVM type signature. -void PrettyPrintSignature(std::string *s); +void PrettyPrintSignature(std::string* s); } // namespace javaprofiler } // namespace google diff --git a/third_party/javaprofiler/stacktraces.cc b/third_party/javaprofiler/stacktraces.cc index 87b27619..8329f725 100644 --- a/third_party/javaprofiler/stacktraces.cc +++ b/third_party/javaprofiler/stacktraces.cc @@ -19,16 +19,16 @@ namespace javaprofiler { ASGCTType Asgct::asgct_; -std::mutex *AttributeTable::mutex_; -std::unordered_map *AttributeTable::string_map_; -std::vector *AttributeTable::strings_; +std::mutex* AttributeTable::mutex_; +std::unordered_map* AttributeTable::string_map_; +std::vector* AttributeTable::strings_; -bool AsyncSafeTraceMultiset::Add(int attr, JVMPI_CallTrace *trace) { +bool AsyncSafeTraceMultiset::Add(int attr, JVMPI_CallTrace* trace) { uint64_t hash_val = CalculateHash(attr, trace->num_frames, &trace->frames[0]); for (int64_t i = 0; i < MaxEntries(); i++) { int64_t idx = (i + hash_val) % MaxEntries(); - auto &entry = traces_[idx]; + auto& entry = traces_[idx]; int64_t count_zero = 0; entry.active_updates.fetch_add(1, std::memory_order_acquire); int64_t count = entry.count.load(std::memory_order_acquire); @@ -40,7 +40,7 @@ bool AsyncSafeTraceMultiset::Add(int attr, JVMPI_CallTrace *trace) { // with Extract, so decrement active_updates early. entry.active_updates.fetch_sub(1, std::memory_order_release); // memcpy is not async safe - JVMPI_CallFrame *fb = entry.frame_buffer; + JVMPI_CallFrame* fb = entry.frame_buffer; int num_frames = trace->num_frames; for (int frame_num = 0; frame_num < num_frames; ++frame_num) { fb[frame_num].lineno = trace->frames[frame_num].lineno; @@ -80,12 +80,12 @@ bool AsyncSafeTraceMultiset::Add(int attr, JVMPI_CallTrace *trace) { return false; } -int AsyncSafeTraceMultiset::Extract(int location, int64_t *attr, int max_frames, - JVMPI_CallFrame *frames, int64_t *count) { +int AsyncSafeTraceMultiset::Extract(int location, int64_t* attr, int max_frames, + JVMPI_CallFrame* frames, int64_t* count) { if (location < 0 || location >= MaxEntries()) { return 0; } - auto &entry = traces_[location]; + auto& entry = traces_[location]; int64_t c = entry.count.load(std::memory_order_acquire); if (c <= 0) { // Unused or in process of being updated, skip for now. @@ -115,7 +115,7 @@ int AsyncSafeTraceMultiset::Extract(int location, int64_t *attr, int max_frames, return num_frames; } -void TraceMultiset::Add(int64_t attr, int num_frames, JVMPI_CallFrame *frames, +void TraceMultiset::Add(int64_t attr, int num_frames, JVMPI_CallFrame* frames, int64_t count) { CallTrace t; t.attr = attr; @@ -129,7 +129,7 @@ void TraceMultiset::Add(int64_t attr, int num_frames, JVMPI_CallFrame *frames, traces_.emplace(std::move(t), count); } -int HarvestSamples(AsyncSafeTraceMultiset *from, TraceMultiset *to) { +int HarvestSamples(AsyncSafeTraceMultiset* from, TraceMultiset* to) { int trace_count = 0; int64_t num_traces = from->MaxEntries(); for (int64_t i = 0; i < num_traces; i++) { @@ -147,7 +147,7 @@ int HarvestSamples(AsyncSafeTraceMultiset *from, TraceMultiset *to) { } uint64_t CalculateHash(int64_t attr, int num_frames, - const JVMPI_CallFrame *frame) { + const JVMPI_CallFrame* frame) { // Make hash-value uint64_t h = attr; h += h << 10; @@ -165,8 +165,8 @@ uint64_t CalculateHash(int64_t attr, int num_frames, return h; } -bool Equal(int num_frames, const JVMPI_CallFrame *f1, - const JVMPI_CallFrame *f2) { +bool Equal(int num_frames, const JVMPI_CallFrame* f1, + const JVMPI_CallFrame* f2) { // Compare individual members to avoid differences in padding. for (int i = 0; i < num_frames; i++) { if (f1[i].method_id != f2[i].method_id || f1[i].lineno != f2[i].lineno) { diff --git a/third_party/javaprofiler/stacktraces.h b/third_party/javaprofiler/stacktraces.h index b491dc6d..420af240 100644 --- a/third_party/javaprofiler/stacktraces.h +++ b/third_party/javaprofiler/stacktraces.h @@ -35,11 +35,11 @@ namespace javaprofiler { const int kMaxFramesToCapture = 128; uint64_t CalculateHash(int64_t attr, int num_frames, - const JVMPI_CallFrame *frame); -bool Equal(int num_frames, const JVMPI_CallFrame *f1, - const JVMPI_CallFrame *f2); + const JVMPI_CallFrame* frame); +bool Equal(int num_frames, const JVMPI_CallFrame* f1, + const JVMPI_CallFrame* f2); -typedef void (*ASGCTType)(JVMPI_CallTrace *, jint, void *); +typedef void (*ASGCTType)(JVMPI_CallTrace*, jint, void*); const int kNumCallTraceErrors = 10; @@ -71,7 +71,7 @@ class AttributeTable { strings_->push_back(""); } - static int RegisterString(const char *value) { + static int RegisterString(const char* value) { if (mutex_ == nullptr || value == nullptr || !*value) { // Not initialized or empty string. return 0; @@ -97,9 +97,9 @@ class AttributeTable { } private: - static std::mutex *mutex_; - static std::unordered_map *string_map_; - static std::vector *strings_; + static std::mutex* mutex_; + static std::unordered_map* string_map_; + static std::vector* strings_; }; // Multiset of stack traces. There is a maximum number of distinct @@ -124,13 +124,11 @@ class AsyncSafeTraceMultiset { public: AsyncSafeTraceMultiset() { Reset(); } - void Reset() { - memset(traces_, 0, sizeof(traces_)); - } + void Reset() { memset(traces_, 0, sizeof(traces_)); } // Add a trace to the set. If it is already present, increment its // count. This operation is thread safe and async safe. - bool Add(int attr, JVMPI_CallTrace *trace); + bool Add(int attr, JVMPI_CallTrace* trace); // Extract a trace from the array. frames must point to at least // max_frames contiguous frames. It will return the number of frames @@ -138,8 +136,8 @@ class AsyncSafeTraceMultiset { // there is no valid trace at this location. This operation is // thread safe with respect to Add() but only a single call to // Extract can be done at a time. - int Extract(int location, int64_t *attr, int max_frames, - JVMPI_CallFrame *frames, int64_t *count); + int Extract(int location, int64_t* attr, int max_frames, + JVMPI_CallFrame* frames, int64_t* count); int64_t MaxEntries() const { return kMaxStackTraces; } @@ -186,14 +184,14 @@ class TraceMultiset { } CallTrace; struct CallTraceHash { - std::size_t operator()(const CallTrace &trace) const { + std::size_t operator()(const CallTrace& trace) const { return CalculateHash(trace.attr, trace.frames.size(), trace.frames.data()); } }; struct CallTraceEqual { - bool operator()(const CallTrace &t1, const CallTrace &t2) const { + bool operator()(const CallTrace& t1, const CallTrace& t2) const { if (t1.attr != t2.attr) { return false; } @@ -212,7 +210,7 @@ class TraceMultiset { // Add a trace to the array. If it is already in the array, // increment its count. - void Add(int64_t attr, int num_frames, JVMPI_CallFrame *frames, + void Add(int64_t attr, int num_frames, JVMPI_CallFrame* frames, int64_t count); typedef CountMap::iterator iterator; @@ -237,7 +235,7 @@ class TraceMultiset { // and copies them into a trace multiset. It returns the number of samples // that were copied. This is thread-safe with respect to other threads adding // samples into the asyncsafe set. -int HarvestSamples(AsyncSafeTraceMultiset *from, TraceMultiset *to); +int HarvestSamples(AsyncSafeTraceMultiset* from, TraceMultiset* to); } // namespace javaprofiler } // namespace google diff --git a/third_party/javaprofiler/tags.cc b/third_party/javaprofiler/tags.cc index 600d10a4..5b39adfc 100644 --- a/third_party/javaprofiler/tags.cc +++ b/third_party/javaprofiler/tags.cc @@ -28,20 +28,20 @@ namespace { // Protects the global variables keys and key_to_id. std::mutex mutex; -const Tags *empty_tags = nullptr; -const AsyncRefCountedString *empty_async_string = nullptr; +const Tags* empty_tags = nullptr; +const AsyncRefCountedString* empty_async_string = nullptr; // Stores all the keys. -std::vector *keys = nullptr; +std::vector* keys = nullptr; // Maps key to its id. The index of a key stored in keys (called id or key_id) // is used to retrieve a key or value quickly as it is very friendly to vectors. -std::unordered_map *key_to_id = nullptr; +std::unordered_map* key_to_id = nullptr; // Returns the id of the key if the key has been registered. Otherwise, it tries // to add the key and returns its id upon success or returns -1 if there is no // extra space. -int32_t RegisterKey(const std::string &key) { +int32_t RegisterKey(const std::string& key) { std::lock_guard lock(mutex); - const auto &target = key_to_id->find(key); + const auto& target = key_to_id->find(key); if (target != key_to_id->end()) { // Key is found and directly return its id. return target->second; @@ -65,7 +65,7 @@ const char kAttrKey[] = "attr"; // Returns the id of the key if the key has been registered; otherwise, returns // -1. -int32_t Tags::GetIdByKey(const std::string &key) { +int32_t Tags::GetIdByKey(const std::string& key) { std::lock_guard lock(mutex); auto target = key_to_id->find(key); if (target == key_to_id->end()) { @@ -74,13 +74,13 @@ int32_t Tags::GetIdByKey(const std::string &key) { return target->second; } -void Tags::AsyncSafeCopy(const Tags &from) { +void Tags::AsyncSafeCopy(const Tags& from) { for (int i = 0; i < kMaxNumTags; i++) { values_[i].AsyncSafeCopy(from.values_[i]); } } -bool Tags::Set(const std::string &key, const AsyncRefCountedString &value) { +bool Tags::Set(const std::string& key, const AsyncRefCountedString& value) { // All values are stored in the vector "values_" and "key_id" (resolved by // "key") is used to locate the right position. int32_t key_id = RegisterKey(key); @@ -92,18 +92,18 @@ bool Tags::Set(const std::string &key, const AsyncRefCountedString &value) { } void Tags::ClearAll() { - for (auto &val : values_) { + for (auto& val : values_) { val.Reset(); } } void Tags::AsyncSafeClearAll() { - for (auto &val : values_) { + for (auto& val : values_) { val.AsyncSafeReset(); } } -bool Tags::operator==(const Tags &other) const { +bool Tags::operator==(const Tags& other) const { for (int i = 0; i < kMaxNumTags; i++) { if (values_[i] != other.values_[i]) { return false; @@ -114,7 +114,7 @@ bool Tags::operator==(const Tags &other) const { uint64_t Tags::Hash() const { uint64_t h = 0; - for (const auto &val : values_) { + for (const auto& val : values_) { h += val.Hash(); h += h << 10; h ^= h >> 6; @@ -122,7 +122,7 @@ uint64_t Tags::Hash() const { return h; } -const AsyncRefCountedString &Tags::Get(const std::string &key) const { +const AsyncRefCountedString& Tags::Get(const std::string& key) const { int32_t key_id = GetIdByKey(key); if (key_id >= 0) { return values_[key_id]; @@ -149,14 +149,14 @@ void Tags::SetAttribute(int64_t value) { } int64_t Tags::GetAttribute() const { - const std::string *value = Get(kAttrKey).Get(); + const std::string* value = Get(kAttrKey).Get(); if (value == nullptr) { return 0; } return static_cast(std::stol(*value)); } -const Tags &Tags::Empty() { return *empty_tags; } +const Tags& Tags::Empty() { return *empty_tags; } bool Tags::Init() { { diff --git a/third_party/javaprofiler/tags.h b/third_party/javaprofiler/tags.h index a84da3a6..0b9e161b 100644 --- a/third_party/javaprofiler/tags.h +++ b/third_party/javaprofiler/tags.h @@ -36,12 +36,12 @@ class Tags { // Returns the value (in AsyncRefCountedString reference) indexed by "key". Be // cautious that the referenced AsyncRefCountedString may change if modifiers // (e.g., Set(), Clear()) are invoked later. - const AsyncRefCountedString &Get(const std::string &key) const; + const AsyncRefCountedString& Get(const std::string& key) const; // Sets the value indexed by "key" to "value". It returns true on success; // otherwise returns false. The failure usually comes from that "key" does not // exist in the key list while there is no space to accommodate this new // "key". - bool Set(const std::string &key, const AsyncRefCountedString &value); + bool Set(const std::string& key, const AsyncRefCountedString& value); // Resets all values to nullptr. void ClearAll(); // Returns all the key-value pairs stored in this Tags. @@ -55,18 +55,18 @@ class Tags { // Async-signal-safe version of operator=(const Tags &other). It requires that // the instance should be empty (does not refer to any string). Otherwise, it // asserts an error. - void AsyncSafeCopy(const Tags &from); + void AsyncSafeCopy(const Tags& from); // Async-signal-safe version of ClearAll(). It will succeed if no enty is // removed from the AsyncRefCountedString internal string table. Otherwise, it // asserts an error. void AsyncSafeClearAll(); // Async-signal-safe. - bool operator==(const Tags &other) const; + bool operator==(const Tags& other) const; // Async-signal-safe. uint64_t Hash() const; // Async-signal-safe. - static const Tags &Empty(); + static const Tags& Empty(); // Initializes the internal for key table and empty Tags and // AsyncRefCountedString instances. Must be called after // AsyncRefCountedString::Init(), and before using Tags to store any key-value @@ -82,7 +82,7 @@ class Tags { private: // // Returns the id of "key" if "key" is present; otherwise, returns -1. - static int32_t GetIdByKey(const std::string &key); + static int32_t GetIdByKey(const std::string& key); AsyncRefCountedString values_[kMaxNumTags]; diff --git a/third_party/perftools/profiles/proto/aslr.cc b/third_party/perftools/profiles/proto/aslr.cc new file mode 100644 index 00000000..ccf26f2a --- /dev/null +++ b/third_party/perftools/profiles/proto/aslr.cc @@ -0,0 +1,69 @@ +#include "perftools/profiles/proto/aslr.h" + +#include + +#include +#include +#include + +#include "perftools/profiles/proto/builder.h" +#include "absl/container/flat_hash_map.h" + +#include "google/protobuf/arena.h" + +namespace perftools { +namespace profiles { +namespace internal { + +bool SerializeWithAslrEntropyRedaction(const Profile& profile, + ZeroCopyOutputStream& out_stream) { + const size_t page_size = getpagesize(); + uint64_t fake_start_address = 0x200000ULL; + absl::flat_hash_map mapping_to_difference; + + google::protobuf::Arena arena; + Profile* redacted = google::protobuf::Arena::Create(&arena); + + *redacted = profile; + + for (auto& mapping : *redacted->mutable_mapping()) { + // Fake mappings that should not be redacted. + if (Builder::IsFullAddressSpaceMapping(mapping) || + (mapping.memory_start() == 0 && + (mapping.memory_limit() == std::numeric_limits::max() || + mapping.memory_limit() == 0))) { + continue; + } + + int64_t difference = static_cast(mapping.memory_start()) - + static_cast(fake_start_address); + uint64_t size = mapping.memory_limit() - mapping.memory_start(); + + mapping.set_memory_start(fake_start_address); + mapping.set_memory_limit(mapping.memory_start() + size); + + // Round up to the next page boundary. + size = (size + page_size - 1) & ~(page_size - 1); + fake_start_address += size; + mapping_to_difference[mapping.id()] = difference; + } + + for (auto& location : *redacted->mutable_location()) { + if (location.address() == 0) { + continue; + } + + const auto it = mapping_to_difference.find(location.mapping_id()); + if (it == mapping_to_difference.end()) { + continue; + } + + const int64_t difference = it->second; + location.set_address(location.address() - difference); + } + return redacted->SerializeToZeroCopyStream(&out_stream); +} + +} // namespace internal +} // namespace profiles +} // namespace perftools diff --git a/third_party/perftools/profiles/proto/aslr.h b/third_party/perftools/profiles/proto/aslr.h new file mode 100644 index 00000000..03854460 --- /dev/null +++ b/third_party/perftools/profiles/proto/aslr.h @@ -0,0 +1,22 @@ +#ifndef PERFTOOLS_PROFILES_PROTO_ASLR_H_ +#define PERFTOOLS_PROFILES_PROTO_ASLR_H_ + +#include "google/protobuf/io/zero_copy_stream.h" +#include "perftools/profiles/proto/profile.pb.h" + +namespace perftools { +namespace profiles { + +using ::google::protobuf::io::ZeroCopyOutputStream; + +namespace internal { + +bool SerializeWithAslrEntropyRedaction(const Profile& profile, + ZeroCopyOutputStream& out_stream); + +} // namespace internal + +} // namespace profiles +} // namespace perftools + +#endif // PERFTOOLS_PROFILES_PROTO_ASLR_H_ diff --git a/third_party/perftools/profiles/proto/builder.cc b/third_party/perftools/profiles/proto/builder.cc index a9c5084f..9aa6d2d8 100644 --- a/third_party/perftools/profiles/proto/builder.cc +++ b/third_party/perftools/profiles/proto/builder.cc @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -25,8 +26,10 @@ #include #include -#include -#include +#include "perftools/profiles/proto/aslr.h" +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" +#include "absl/strings/string_view.h" #include "glog/logging.h" #include "google/protobuf/io/gzip_stream.h" @@ -39,13 +42,9 @@ using google::protobuf::RepeatedField; namespace perftools { namespace profiles { -typedef std::unordered_map IndexMap; -typedef std::unordered_set IndexSet; -} // namespace profiles -} // namespace perftools -namespace perftools { -namespace profiles { +typedef absl::flat_hash_map IndexMap; +typedef absl::flat_hash_set IndexSet; void AddCallstackToSample(Sample *sample, const void *const *stack, int depth, CallstackType type) { @@ -67,14 +66,14 @@ Builder::Builder() : profile_(new Profile()) { profile_->add_string_table(""); } -int64_t Builder::StringId(const char *str) { - if (str == nullptr || !str[0]) { +int64_t Builder::StringId(absl::string_view str) { + if (str.empty()) { return 0; } return InternalStringId(str); } -int64_t Builder::InternalStringId(const std::string &str) { +int64_t Builder::InternalStringId(absl::string_view str) { const int64_t index = profile_->string_table_size(); const auto inserted = strings_.emplace(str, index); if (!inserted.second) { @@ -87,9 +86,9 @@ int64_t Builder::InternalStringId(const std::string &str) { uint64_t Builder::FunctionId(const char *name, const char *system_name, const char *file, int64_t start_line) { - int64_t name_index = StringId(name); - int64_t system_name_index = StringId(system_name); - int64_t file_index = StringId(file); + int64_t name_index = StringId(absl::NullSafeStringView(name)); + int64_t system_name_index = StringId(absl::NullSafeStringView(system_name)); + int64_t file_index = StringId(absl::NullSafeStringView(file)); auto fn = std::make_tuple(name_index, system_name_index, file_index, start_line); @@ -135,28 +134,28 @@ bool Builder::Emit(std::string *output) { return Marshal(*profile_, output); } -bool Builder::Marshal(const Profile &profile, std::string *output) { +bool Builder::Marshal(const Profile& profile, std::string* output) { *output = ""; StringOutputStream stream(output); GzipOutputStream gzip_stream(&stream); - if (!profile.SerializeToZeroCopyStream(&gzip_stream)) { + if (!internal::SerializeWithAslrEntropyRedaction(profile, gzip_stream)) { LOG(ERROR) << "Failed to serialize to gzip stream"; return false; } return gzip_stream.Close(); } -bool Builder::MarshalToFile(const Profile &profile, int fd) { +bool Builder::MarshalToFile(const Profile& profile, int fd) { FileOutputStream stream(fd); GzipOutputStream gzip_stream(&stream); - if (!profile.SerializeToZeroCopyStream(&gzip_stream)) { + if (!internal::SerializeWithAslrEntropyRedaction(profile, gzip_stream)) { LOG(ERROR) << "Failed to serialize to gzip stream"; return false; } return gzip_stream.Close(); } -bool Builder::MarshalToFile(const Profile &profile, const char *filename) { +bool Builder::MarshalToFile(const Profile& profile, const char* filename) { int fd; while ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0 && errno == EINTR) { @@ -314,6 +313,9 @@ bool Builder::Finalize() { if (profile_->mapping_size() > 0) { std::map > mapping_map; for (const auto &mapping : profile_->mapping()) { + if (IsFullAddressSpaceMapping(mapping)) { + continue; + } mapping_map[mapping.memory_start()] = std::make_pair(mapping.memory_limit(), mapping.id()); } @@ -338,5 +340,13 @@ bool Builder::Finalize() { return CheckValid(*profile_); } +uint64_t Builder::AddFullAddressSpaceMapping() { + Mapping* mapping = profile_->add_mapping(); + mapping->set_id(profile_->mapping_size()); + mapping->set_memory_start(0); + mapping->set_memory_limit(std::numeric_limits::max()); + return mapping->id(); +} + } // namespace profiles } // namespace perftools diff --git a/third_party/perftools/profiles/proto/builder.h b/third_party/perftools/profiles/proto/builder.h index 73fae393..6de118f3 100644 --- a/third_party/perftools/profiles/proto/builder.h +++ b/third_party/perftools/profiles/proto/builder.h @@ -17,50 +17,31 @@ #include -#include #include +#include #include #include #include #include -#include - -namespace perftools { -namespace profiles { - -typedef int64_t int64; -typedef uint64_t uint64; -typedef std::string string; - -typedef std::unordered_map StringIndexMap; - -class FunctionHasher { - public: - size_t operator()(const std::tuple &f) const { - int64 hash = std::get<0>(f); - hash = hash + ((hash << 8) ^ std::get<1>(f)); - hash = hash + ((hash << 8) ^ std::get<2>(f)); - hash = hash + ((hash << 8) ^ std::get<3>(f)); - return static_cast(hash); - } -}; - -typedef std::unordered_map, int64, - FunctionHasher> - FunctionIndexMap; - -} // namespace profiles -} // namespace perftools +#include "absl/base/attributes.h" +#include "absl/base/macros.h" +#include "absl/container/flat_hash_map.h" +#include "absl/strings/string_view.h" #include "perftools/profiles/proto/profile.pb.h" namespace perftools { namespace profiles { +typedef absl::flat_hash_map StringIndexMap; +typedef absl::flat_hash_map, + int64_t> + FunctionIndexMap; + enum CallstackType { kRegular = 0, kInterrupt = 1 }; -void AddCallstackToSample(Sample *sample, const void *const *stack, int depth, +void AddCallstackToSample(Sample* sample, const void* const* stack, int depth, CallstackType type); // Provides mechanisms to facilitate the generation of profiles @@ -76,19 +57,31 @@ class Builder { // Adds a string to the profile string table if not already present. // Returns a unique integer id for this string. - int64_t StringId(const char *str); + int64_t StringId(absl::string_view str); // Adds a function with these attributes to the profile function // table, if not already present. Returns a unique integer id for // this function. - uint64_t FunctionId(const char *name, const char *system_name, - const char *file, int64_t start_line); + uint64_t FunctionId(const char* name, const char* system_name, + const char* file, int64_t start_line); // Adds mappings for the currently running binary to the profile. void AddCurrentMappings(); + // Adds a synthetic mapping covering [0, UINT64_MAX] and returns its ID. + // Finalize() skips it, so callers must explicitly set mapping_id on + // locations whose addresses must survive ASLR redaction. The caller must + // show that this will not leak any ASLR entropy. + [[nodiscard]] uint64_t AddFullAddressSpaceMapping(); + + // Returns true if mapping is a synthetic full-address-space mapping. + [[nodiscard]] static bool IsFullAddressSpaceMapping(const Mapping& mapping) { + return mapping.memory_start() == 0 && + mapping.memory_limit() == std::numeric_limits::max(); + } + // Add documentation URL. - void SetDocURL(const std::string &url); + void SetDocURL(const std::string& url); // Prepares the profile for encoding. Returns true on success. // If the profile has no locations, inserts location using the @@ -100,25 +93,25 @@ class Builder { // Serializes and compresses the profile into a string, replacing // its contents. It calls Finalize() and returns whether the // encoding was successful. - bool Emit(std::string *output); + bool Emit(std::string* output); // Serializes and compresses a profile into a string, replacing its // contents. Returns false if there were errors on the serialization // or compression, and the output string will not contain valid data. - static bool Marshal(const Profile &profile, std::string *output); + static bool Marshal(const Profile& profile, std::string* output); // Serializes and compresses a profile into a file represented by a // file descriptor. Returns false if there were errors on the // serialization or compression. - static bool MarshalToFile(const Profile &profile, int fd); + static bool MarshalToFile(const Profile& profile, int fd); // Serializes and compresses a profile into a file, creating a new // file or replacing its contents if it already exists. - static bool MarshalToFile(const Profile &profile, const char *filename); + static bool MarshalToFile(const Profile& profile, const char* filename); // Determines if the profile is internally consistent (suitable for // serialization). Returns true if no errors were encountered. - static bool CheckValid(const Profile &profile); + static bool CheckValid(const Profile& profile); // Extract the profile from the builder object. No further calls // should be made to the builder after this. @@ -128,10 +121,10 @@ class Builder { // managed by the builder. The fields function and string_table // should be populated through Builder::StringId and // Builder::FunctionId. - Profile *mutable_profile() { return profile_.get(); } + Profile* mutable_profile() { return profile_.get(); } private: - int64_t InternalStringId(const std::string &str); + int64_t InternalStringId(absl::string_view str); // Maps to deduplicate strings and functions. StringIndexMap strings_; diff --git a/third_party/perftools/profiles/proto/profile.proto b/third_party/perftools/profiles/proto/profile.proto index 81050c26..c6521183 100644 --- a/third_party/perftools/profiles/proto/profile.proto +++ b/third_party/perftools/profiles/proto/profile.proto @@ -4,7 +4,7 @@ // 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 +// 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, @@ -93,11 +93,11 @@ message Profile { // Index into the string table of the type of the preferred sample // value. If unset, clients should default to the last sample value. int64 default_sample_type = 14; - // Documentation link for this profile. The URL must be absolute, + // Documentation link for this profile type. The URL must be absolute, // e.g., http://pprof.example.com/cpu-profile.html // - // The URL may be missing if the profile was generated by older code or code - // that did not bother to supply a link. + // The URL may be missing if the profile was generated by code that did not + // supply a link. int64 doc_url = 15; // Index into string table. }