You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bigtop.apache.org by gu...@apache.org on 2022/06/29 03:16:23 UTC

[bigtop] branch master updated: BIGTOP-3709. Bring protobuf 2.5.0 back for building HBase on aarch64 and ppc64le. (#920)

This is an automated email from the ASF dual-hosted git repository.

guyuqi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bigtop.git


The following commit(s) were added to refs/heads/master by this push:
     new 3020ab58 BIGTOP-3709. Bring protobuf 2.5.0 back for building HBase on aarch64 and ppc64le. (#920)
3020ab58 is described below

commit 3020ab58c66d2e04298efbfc3e326eab24c8f535
Author: Masatake Iwasaki <iw...@apache.org>
AuthorDate: Wed Jun 29 12:16:18 2022 +0900

    BIGTOP-3709. Bring protobuf 2.5.0 back for building HBase on aarch64 and ppc64le. (#920)
---
 .../src/common/hbase/do-component-build            |   4 +-
 ...omic-operations-with-support-of-arm64-and.patch | 573 +++++++++++++++++++++
 ...569-Improve-performance-of-parsing-unknow.patch | 430 ++++++++++++++++
 bigtop_toolchain/manifests/protobuf.pp             |  35 ++
 4 files changed, 1040 insertions(+), 2 deletions(-)

diff --git a/bigtop-packages/src/common/hbase/do-component-build b/bigtop-packages/src/common/hbase/do-component-build
index ed8493db..fe3d2587 100644
--- a/bigtop-packages/src/common/hbase/do-component-build
+++ b/bigtop-packages/src/common/hbase/do-component-build
@@ -36,7 +36,7 @@ if [ $HOSTTYPE = "powerpc64le" ] ; then
   sed -i "s|<asciidoctor.plugin.version>.*</asciidoctor.plugin.version>|<asciidoctor.plugin.version>1.5.3</asciidoctor.plugin.version>|" pom.xml
   sed -i 's|<asciidoctorj.pdf.version>.*</asciidoctorj.pdf.version>|<asciidoctorj.pdf.version>1.5.0-alpha.11</asciidoctorj.pdf.version>|' pom.xml
   mvn install:install-file -DgroupId=com.google.protobuf -DartifactId=protoc -Dversion=2.5.0 \
-      -Dclassifier=linux-ppcle_64 -Dpackaging=exe -Dfile=/usr/local/bin/protoc
+      -Dclassifier=linux-ppcle_64 -Dpackaging=exe -Dfile=/usr/local/protobuf-2.5.0/bin/protoc
   mvn install:install-file -DgroupId=com.google.protobuf -DartifactId=protoc -Dversion=3.17.3 \
       -Dclassifier=linux-ppcle_64 -Dpackaging=exe -Dfile=/usr/local/protobuf-3.17.3/bin/protoc
   MVN_ARGS+="-Dexternal.protobuf.groupid=com.google.protobuf -Dexternal.protoc.version=2.5.0 "
@@ -50,7 +50,7 @@ if [ $HOSTTYPE = "aarch64" ] ; then
 '\             <version>9.1.8.0</version>\n'\
 '\          <\/dependency>' pom.xml
   mvn install:install-file -DgroupId=com.google.protobuf -DartifactId=protoc -Dversion=2.5.0 \
-      -Dclassifier=linux-aarch_64 -Dpackaging=exe -Dfile=/usr/local/bin/protoc
+      -Dclassifier=linux-aarch_64 -Dpackaging=exe -Dfile=/usr/local/protobuf-2.5.0/bin/protoc
   MVN_ARGS+="-Dexternal.protobuf.groupid=com.google.protobuf -Dexternal.protoc.version=2.5.0 "
 fi
 
diff --git a/bigtop_toolchain/files/0001-Backport-atomic-operations-with-support-of-arm64-and.patch b/bigtop_toolchain/files/0001-Backport-atomic-operations-with-support-of-arm64-and.patch
new file mode 100644
index 00000000..b1dfde49
--- /dev/null
+++ b/bigtop_toolchain/files/0001-Backport-atomic-operations-with-support-of-arm64-and.patch
@@ -0,0 +1,573 @@
+From 810f9fae7e12142c3bd47ab7011ed071284760f8 Mon Sep 17 00:00:00 2001
+From: Jun He <ju...@arm.com>
+Date: Fri, 5 Mar 2021 02:49:08 +0000
+Subject: [PATCH] Backport atomic operations with support of arm64 and generic
+
+Signed-off-by: Jun He <ju...@arm.com>
+---
+ src/Makefile.am                               |   2 +
+ src/google/protobuf/stubs/atomicops.h         |   8 +-
+ .../stubs/atomicops_internals_arm64_gcc.h     | 325 ++++++++++++++++++
+ .../stubs/atomicops_internals_generic_gcc.h   | 137 ++++++++
+ src/google/protobuf/stubs/platform_macros.h   |  16 +
+ 5 files changed, 486 insertions(+), 2 deletions(-)
+ create mode 100644 src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h
+ create mode 100644 src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index df733d9b8..f9fa82ec0 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -40,6 +40,7 @@ MAINTAINERCLEANFILES =   \
+ nobase_include_HEADERS =                                        \
+   google/protobuf/stubs/atomicops.h                             \
+   google/protobuf/stubs/atomicops_internals_arm_gcc.h           \
++  google/protobuf/stubs/atomicops_internals_arm64_gcc.h         \
+   google/protobuf/stubs/atomicops_internals_arm_qnx.h           \
+   google/protobuf/stubs/atomicops_internals_atomicword_compat.h \
+   google/protobuf/stubs/atomicops_internals_macosx.h            \
+@@ -47,6 +48,7 @@ nobase_include_HEADERS =                                        \
+   google/protobuf/stubs/atomicops_internals_pnacl.h             \
+   google/protobuf/stubs/atomicops_internals_x86_gcc.h           \
+   google/protobuf/stubs/atomicops_internals_x86_msvc.h          \
++  google/protobuf/stubs/atomicops_internals_generic_gcc.h       \
+   google/protobuf/stubs/common.h                                \
+   google/protobuf/stubs/platform_macros.h                       \
+   google/protobuf/stubs/once.h                                  \
+diff --git a/src/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h
+index b8581fa27..5b2e64cb5 100644
+--- a/src/google/protobuf/stubs/atomicops.h
++++ b/src/google/protobuf/stubs/atomicops.h
+@@ -176,14 +176,18 @@ GOOGLE_PROTOBUF_ATOMICOPS_ERROR
+ #elif defined(__GNUC__)
+ #if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64)
+ #include <google/protobuf/stubs/atomicops_internals_x86_gcc.h>
+-#elif defined(GOOGLE_PROTOBUF_ARCH_ARM)
++#elif defined(GOOGLE_PROTOBUF_ARCH_ARM) && defined(__linux__)
+ #include <google/protobuf/stubs/atomicops_internals_arm_gcc.h>
++#elif defined(GOOGLE_PROTOBUF_ARCH_AARCH64)
++#include <google/protobuf/stubs/atomicops_internals_arm64_gcc.h>
+ #elif defined(GOOGLE_PROTOBUF_ARCH_ARM_QNX)
+ #include <google/protobuf/stubs/atomicops_internals_arm_qnx.h>
+-#elif defined(GOOGLE_PROTOBUF_ARCH_MIPS)
++#elif defined(GOOGLE_PROTOBUF_ARCH_MIPS) || defined(GOOGLE_PROTOBUF_ARCH_MIPS64)
+ #include <google/protobuf/stubs/atomicops_internals_mips_gcc.h>
+ #elif defined(__pnacl__)
+ #include <google/protobuf/stubs/atomicops_internals_pnacl.h>
++#elif (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))
++#include <google/protobuf/stubs/atomicops_internals_generic_gcc.h>
+ #else
+ GOOGLE_PROTOBUF_ATOMICOPS_ERROR
+ #endif
+diff --git a/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h b/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h
+new file mode 100644
+index 000000000..fe9727ad0
+--- /dev/null
++++ b/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h
+@@ -0,0 +1,325 @@
++// Protocol Buffers - Google's data interchange format
++// Copyright 2012 Google Inc.  All rights reserved.
++// http://code.google.com/p/protobuf/
++//
++// Redistribution and use in source and binary forms, with or without
++// modification, are permitted provided that the following conditions are
++// met:
++//
++//     * Redistributions of source code must retain the above copyright
++// notice, this list of conditions and the following disclaimer.
++//     * Redistributions in binary form must reproduce the above
++// copyright notice, this list of conditions and the following disclaimer
++// in the documentation and/or other materials provided with the
++// distribution.
++//     * Neither the name of Google Inc. nor the names of its
++// contributors may be used to endorse or promote products derived from
++// this software without specific prior written permission.
++//
++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++
++// This file is an internal atomic implementation, use atomicops.h instead.
++
++#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_
++#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_
++
++namespace google {
++namespace protobuf {
++namespace internal {
++
++inline void MemoryBarrier() {
++  __asm__ __volatile__ ("dmb ish" ::: "memory");  // NOLINT
++}
++
++// NoBarrier versions of the operation include "memory" in the clobber list.
++// This is not required for direct usage of the NoBarrier versions of the
++// operations. However this is required for correctness when they are used as
++// part of the Acquire or Release versions, to ensure that nothing from outside
++// the call is reordered between the operation and the memory barrier. This does
++// not change the code generated, so has no or minimal impact on the
++// NoBarrier operations.
++
++inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
++                                         Atomic32 old_value,
++                                         Atomic32 new_value) {
++  Atomic32 prev;
++  int32_t temp;
++
++  __asm__ __volatile__ (  // NOLINT
++    "0:                                    \n\t"
++    "ldxr %w[prev], %[ptr]                 \n\t"  // Load the previous value.
++    "cmp %w[prev], %w[old_value]           \n\t"
++    "bne 1f                                \n\t"
++    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
++    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
++    "1:                                    \n\t"
++    : [prev]"=&r" (prev),
++      [temp]"=&r" (temp),
++      [ptr]"+Q" (*ptr)
++    : [old_value]"IJr" (old_value),
++      [new_value]"r" (new_value)
++    : "cc", "memory"
++  );  // NOLINT
++
++  return prev;
++}
++
++inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
++                                         Atomic32 new_value) {
++  Atomic32 result;
++  int32_t temp;
++
++  __asm__ __volatile__ (  // NOLINT
++    "0:                                    \n\t"
++    "ldxr %w[result], %[ptr]               \n\t"  // Load the previous value.
++    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
++    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
++    : [result]"=&r" (result),
++      [temp]"=&r" (temp),
++      [ptr]"+Q" (*ptr)
++    : [new_value]"r" (new_value)
++    : "memory"
++  );  // NOLINT
++
++  return result;
++}
++
++inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
++                                          Atomic32 increment) {
++  Atomic32 result;
++  int32_t temp;
++
++  __asm__ __volatile__ (  // NOLINT
++    "0:                                       \n\t"
++    "ldxr %w[result], %[ptr]                  \n\t"  // Load the previous value.
++    "add %w[result], %w[result], %w[increment]\n\t"
++    "stxr %w[temp], %w[result], %[ptr]        \n\t"  // Try to store the result.
++    "cbnz %w[temp], 0b                        \n\t"  // Retry on failure.
++    : [result]"=&r" (result),
++      [temp]"=&r" (temp),
++      [ptr]"+Q" (*ptr)
++    : [increment]"IJr" (increment)
++    : "memory"
++  );  // NOLINT
++
++  return result;
++}
++
++inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
++                                        Atomic32 increment) {
++  MemoryBarrier();
++  Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment);
++  MemoryBarrier();
++
++  return result;
++}
++
++inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
++                                       Atomic32 old_value,
++                                       Atomic32 new_value) {
++  Atomic32 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
++  MemoryBarrier();
++
++  return prev;
++}
++
++inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
++                                       Atomic32 old_value,
++                                       Atomic32 new_value) {
++  MemoryBarrier();
++  Atomic32 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
++
++  return prev;
++}
++
++inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
++  *ptr = value;
++}
++
++inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
++  *ptr = value;
++  MemoryBarrier();
++}
++
++inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
++  __asm__ __volatile__ (  // NOLINT
++    "stlr %w[value], %[ptr]  \n\t"
++    : [ptr]"=Q" (*ptr)
++    : [value]"r" (value)
++    : "memory"
++  );  // NOLINT
++}
++
++inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
++  return *ptr;
++}
++
++inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
++  Atomic32 value;
++
++  __asm__ __volatile__ (  // NOLINT
++    "ldar %w[value], %[ptr]  \n\t"
++    : [value]"=r" (value)
++    : [ptr]"Q" (*ptr)
++    : "memory"
++  );  // NOLINT
++
++  return value;
++}
++
++inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
++  MemoryBarrier();
++  return *ptr;
++}
++
++// 64-bit versions of the operations.
++// See the 32-bit versions for comments.
++
++inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
++                                         Atomic64 old_value,
++                                         Atomic64 new_value) {
++  Atomic64 prev;
++  int32_t temp;
++
++  __asm__ __volatile__ (  // NOLINT
++    "0:                                    \n\t"
++    "ldxr %[prev], %[ptr]                  \n\t"
++    "cmp %[prev], %[old_value]             \n\t"
++    "bne 1f                                \n\t"
++    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
++    "cbnz %w[temp], 0b                     \n\t"
++    "1:                                    \n\t"
++    : [prev]"=&r" (prev),
++      [temp]"=&r" (temp),
++      [ptr]"+Q" (*ptr)
++    : [old_value]"IJr" (old_value),
++      [new_value]"r" (new_value)
++    : "cc", "memory"
++  );  // NOLINT
++
++  return prev;
++}
++
++inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
++                                         Atomic64 new_value) {
++  Atomic64 result;
++  int32_t temp;
++
++  __asm__ __volatile__ (  // NOLINT
++    "0:                                    \n\t"
++    "ldxr %[result], %[ptr]                \n\t"
++    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
++    "cbnz %w[temp], 0b                     \n\t"
++    : [result]"=&r" (result),
++      [temp]"=&r" (temp),
++      [ptr]"+Q" (*ptr)
++    : [new_value]"r" (new_value)
++    : "memory"
++  );  // NOLINT
++
++  return result;
++}
++
++inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
++                                          Atomic64 increment) {
++  Atomic64 result;
++  int32_t temp;
++
++  __asm__ __volatile__ (  // NOLINT
++    "0:                                     \n\t"
++    "ldxr %[result], %[ptr]                 \n\t"
++    "add %[result], %[result], %[increment] \n\t"
++    "stxr %w[temp], %[result], %[ptr]       \n\t"
++    "cbnz %w[temp], 0b                      \n\t"
++    : [result]"=&r" (result),
++      [temp]"=&r" (temp),
++      [ptr]"+Q" (*ptr)
++    : [increment]"IJr" (increment)
++    : "memory"
++  );  // NOLINT
++
++  return result;
++}
++
++inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
++                                        Atomic64 increment) {
++  MemoryBarrier();
++  Atomic64 result = NoBarrier_AtomicIncrement(ptr, increment);
++  MemoryBarrier();
++
++  return result;
++}
++
++inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
++                                       Atomic64 old_value,
++                                       Atomic64 new_value) {
++  Atomic64 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
++  MemoryBarrier();
++
++  return prev;
++}
++
++inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
++                                       Atomic64 old_value,
++                                       Atomic64 new_value) {
++  MemoryBarrier();
++  Atomic64 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
++
++  return prev;
++}
++
++inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
++  *ptr = value;
++}
++
++inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
++  *ptr = value;
++  MemoryBarrier();
++}
++
++inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
++  __asm__ __volatile__ (  // NOLINT
++    "stlr %x[value], %[ptr]  \n\t"
++    : [ptr]"=Q" (*ptr)
++    : [value]"r" (value)
++    : "memory"
++  );  // NOLINT
++}
++
++inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
++  return *ptr;
++}
++
++inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
++  Atomic64 value;
++
++  __asm__ __volatile__ (  // NOLINT
++    "ldar %x[value], %[ptr]  \n\t"
++    : [value]"=r" (value)
++    : [ptr]"Q" (*ptr)
++    : "memory"
++  );  // NOLINT
++
++  return value;
++}
++
++inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
++  MemoryBarrier();
++  return *ptr;
++}
++
++}  // namespace internal
++}  // namespace protobuf
++}  // namespace google
++
++#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_
+diff --git a/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
+new file mode 100644
+index 000000000..e30bb4449
+--- /dev/null
++++ b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
+@@ -0,0 +1,137 @@
++// Copyright 2013 Red Hat Inc.  All rights reserved.
++//
++// Redistribution and use in source and binary forms, with or without
++// modification, are permitted provided that the following conditions are
++// met:
++//
++//     * Redistributions of source code must retain the above copyright
++// notice, this list of conditions and the following disclaimer.
++//     * Redistributions in binary form must reproduce the above
++// copyright notice, this list of conditions and the following disclaimer
++// in the documentation and/or other materials provided with the
++// distribution.
++//     * Neither the name of Red Hat Inc. nor the names of its
++// contributors may be used to endorse or promote products derived from
++// this software without specific prior written permission.
++//
++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++
++// This file is an internal atomic implementation, use atomicops.h instead.
++
++#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_
++#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_
++
++namespace google {
++namespace protobuf {
++namespace internal {
++
++inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
++                                         Atomic32 old_value,
++                                         Atomic32 new_value) {
++  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
++                              __ATOMIC_RELAXED, __ATOMIC_RELAXED);
++  return old_value;
++}
++
++inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
++                                         Atomic32 new_value) {
++  return __atomic_exchange_n(ptr, new_value, __ATOMIC_RELAXED);
++}
++
++inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
++                                          Atomic32 increment) {
++  return __atomic_add_fetch(ptr, increment, __ATOMIC_RELAXED);
++}
++
++inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
++                                        Atomic32 increment) {
++  return __atomic_add_fetch(ptr, increment, __ATOMIC_SEQ_CST);
++}
++
++inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
++                                       Atomic32 old_value,
++                                       Atomic32 new_value) {
++  __atomic_compare_exchange(ptr, &old_value, &new_value, true,
++                            __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
++  return old_value;
++}
++
++inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
++                                       Atomic32 old_value,
++                                       Atomic32 new_value) {
++  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
++                              __ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
++  return old_value;
++}
++
++inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
++  __atomic_store_n(ptr, value, __ATOMIC_RELAXED);
++}
++
++inline void MemoryBarrier() {
++  __sync_synchronize();
++}
++
++inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
++  __atomic_store_n(ptr, value, __ATOMIC_ACQUIRE);
++}
++
++inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
++  __atomic_store_n(ptr, value, __ATOMIC_RELEASE);
++}
++
++inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
++  return __atomic_load_n(ptr, __ATOMIC_RELAXED);
++}
++
++inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
++  return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
++}
++
++inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
++  return __atomic_load_n(ptr, __ATOMIC_RELEASE);
++}
++
++#ifdef __LP64__
++
++inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
++  __atomic_store_n(ptr, value, __ATOMIC_RELEASE);
++}
++
++inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
++  return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
++}
++
++inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
++                                       Atomic64 old_value,
++                                       Atomic64 new_value) {
++  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
++                              __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
++  return old_value;
++}
++
++inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
++                                         Atomic64 old_value,
++                                         Atomic64 new_value) {
++  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
++                              __ATOMIC_RELAXED, __ATOMIC_RELAXED);
++  return old_value;
++}
++
++#endif // defined(__LP64__)
++
++}  // namespace internal
++}  // namespace protobuf
++}  // namespace google
++
++#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_
+diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h
+index b1df60e46..1705b4162 100644
+--- a/src/google/protobuf/stubs/platform_macros.h
++++ b/src/google/protobuf/stubs/platform_macros.h
+@@ -49,14 +49,30 @@
+ #elif defined(__ARMEL__)
+ #define GOOGLE_PROTOBUF_ARCH_ARM 1
+ #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
++#elif defined(__aarch64__)
++#define GOOGLE_PROTOBUF_ARCH_AARCH64 1
++#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
+ #elif defined(__MIPSEL__)
++#if defined(__LP64__)
++#define GOOGLE_PROTOBUF_ARCH_MIPS64 1
++#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
++#else
+ #define GOOGLE_PROTOBUF_ARCH_MIPS 1
+ #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
++#endif
+ #elif defined(__pnacl__)
+ #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+ #elif defined(__ppc__)
+ #define GOOGLE_PROTOBUF_ARCH_PPC 1
+ #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
++#elif defined(__GNUC__) && \
++ (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))
++// We fallback to the generic GCC >= 4.7 implementation in atomicops.h
++# if __LP64__
++#  define GOOGLE_PROTOBUF_ARCH_64_BIT 1
++# else
++#  define GOOGLE_PROTOBUF_ARCH_32_BIT 1
++# endif
+ #else
+ #error Host architecture was not detected as supported by protobuf
+ #endif
+-- 
+2.17.1
+
diff --git a/bigtop_toolchain/files/0001-CVE-2021-22569-Improve-performance-of-parsing-unknow.patch b/bigtop_toolchain/files/0001-CVE-2021-22569-Improve-performance-of-parsing-unknow.patch
new file mode 100644
index 00000000..c6192b4b
--- /dev/null
+++ b/bigtop_toolchain/files/0001-CVE-2021-22569-Improve-performance-of-parsing-unknow.patch
@@ -0,0 +1,430 @@
+From 0b10440b61f3328d7478b93fbf27e879a0dbac91 Mon Sep 17 00:00:00 2001
+From: Andrew Purtell <ap...@salesforce.com>
+Date: Mon, 14 Feb 2022 15:00:03 -0800
+Subject: [PATCH] CVE-2021-22569: Improve performance of parsing unknown fields
+ in Java
+
+An issue in protobuf-java allowed the interleaving of UnknownFieldSet fields
+in such a way that would be processed out of order. A small malicious payload
+can occupy the parser for several minutes by creating large numbers of short-
+lived objects that cause frequent, repeated pauses.
+
+Port fix from https://github.com/protocolbuffers/protobuf/pull/9371. It uses
+a TreeMap to process fields in a well ordered way.
+
+Reason: Security
+Test Plan: Unit tests
+---
+ Makefile.am                                   |   1 +
+ .../com/google/protobuf/UnknownFieldSet.java  | 179 +++++++++---------
+ .../UnknownFieldSetPerformanceTest.java       |  76 ++++++++
+ 4 files changed, 171 insertions(+), 86 deletions(-)
+ create mode 100644 java/src/test/java/com/google/protobuf/UnknownFieldSetPerformanceTest.java
+
+diff --git a/Makefile.am b/Makefile.am
+index c9286132b..aedd021c3 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -140,6 +140,7 @@ EXTRA_DIST =                                                                 \
+   java/src/test/java/com/google/protobuf/TestUtil.java                       \
+   java/src/test/java/com/google/protobuf/TextFormatTest.java                 \
+   java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java            \
++  java/src/test/java/com/google/protobuf/UnknownFieldSetPerformanceTest.java \
+   java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \
+   java/src/test/java/com/google/protobuf/WireFormatTest.java                 \
+   java/src/test/java/com/google/protobuf/multiple_files_test.proto           \
+diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
+index 45e2e6e40..f02377cf0 100644
+--- a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
++++ b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
+@@ -57,7 +57,6 @@ import java.util.TreeMap;
+  * @author kenton@google.com Kenton Varda
+  */
+ public final class UnknownFieldSet implements MessageLite {
+-  private UnknownFieldSet() {}
+ 
+   /** Create a new {@link Builder}. */
+   public static Builder newBuilder() {
+@@ -80,16 +79,20 @@ public final class UnknownFieldSet implements MessageLite {
+     return defaultInstance;
+   }
+   private static final UnknownFieldSet defaultInstance =
+-    new UnknownFieldSet(Collections.<Integer, Field>emptyMap());
++    new UnknownFieldSet(new TreeMap<Integer, Field>());
++
++  private UnknownFieldSet() {
++    fields = new TreeMap<Integer, Field>();
++  }
+ 
+   /**
+    * Construct an {@code UnknownFieldSet} around the given map.  The map is
+    * expected to be immutable.
+    */
+-  private UnknownFieldSet(final Map<Integer, Field> fields) {
++  private UnknownFieldSet(final TreeMap<Integer, Field> fields) {
+     this.fields = fields;
+   }
+-  private Map<Integer, Field> fields;
++  private final TreeMap<Integer, Field> fields;
+ 
+   @Override
+   public boolean equals(final Object other) {
+@@ -196,8 +199,10 @@ public final class UnknownFieldSet implements MessageLite {
+   /** Get the number of bytes required to encode this set. */
+   public int getSerializedSize() {
+     int result = 0;
+-    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+-      result += entry.getValue().getSerializedSize(entry.getKey());
++    if (!fields.isEmpty()) {
++      for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
++        result += entry.getValue().getSerializedSize(entry.getKey());
++      }
+     }
+     return result;
+   }
+@@ -281,62 +286,44 @@ public final class UnknownFieldSet implements MessageLite {
+     // This constructor should never be called directly (except from 'create').
+     private Builder() {}
+ 
+-    private Map<Integer, Field> fields;
+-
+-    // Optimization:  We keep around a builder for the last field that was
+-    //   modified so that we can efficiently add to it multiple times in a
+-    //   row (important when parsing an unknown repeated field).
+-    private int lastFieldNumber;
+-    private Field.Builder lastField;
++    private TreeMap<Integer, Field.Builder> fieldBuilders =
++        new TreeMap<Integer, Field.Builder>();
+ 
+     private static Builder create() {
+-      Builder builder = new Builder();
+-      builder.reinitialize();
+-      return builder;
++      return new Builder();
+     }
+ 
+     /**
+      * Get a field builder for the given field number which includes any
+      * values that already exist.
+      */
+-    private Field.Builder getFieldBuilder(final int number) {
+-      if (lastField != null) {
+-        if (number == lastFieldNumber) {
+-          return lastField;
+-        }
+-        // Note:  addField() will reset lastField and lastFieldNumber.
+-        addField(lastFieldNumber, lastField.build());
+-      }
++    private Field.Builder getFieldBuilder(int number) {
+       if (number == 0) {
+         return null;
+       } else {
+-        final Field existing = fields.get(number);
+-        lastFieldNumber = number;
+-        lastField = Field.newBuilder();
+-        if (existing != null) {
+-          lastField.mergeFrom(existing);
++        Field.Builder builder = fieldBuilders.get(number);
++        if (builder == null) {
++          builder = Field.newBuilder();
++          fieldBuilders.put(number, builder);
+         }
+-        return lastField;
++        return builder;
+       }
+     }
+ 
+     /**
+      * Build the {@link UnknownFieldSet} and return it.
+-     *
+-     * <p>Once {@code build()} has been called, the {@code Builder} will no
+-     * longer be usable.  Calling any method after {@code build()} will result
+-     * in undefined behavior and can cause a {@code NullPointerException} to be
+-     * thrown.
+      */
+     public UnknownFieldSet build() {
+-      getFieldBuilder(0);  // Force lastField to be built.
+-      final UnknownFieldSet result;
+-      if (fields.isEmpty()) {
++      UnknownFieldSet result;
++      if (fieldBuilders.isEmpty()) {
+         result = getDefaultInstance();
+       } else {
+-        result = new UnknownFieldSet(Collections.unmodifiableMap(fields));
++        TreeMap<Integer, Field> fields = new TreeMap<Integer, Field>();
++        for (Map.Entry<Integer, Field.Builder> entry : fieldBuilders.entrySet()) {
++          fields.put(entry.getKey(), entry.getValue().build());
++        }
++        result = new UnknownFieldSet(fields);
+       }
+-      fields = null;
+       return result;
+     }
+ 
+@@ -347,24 +334,22 @@ public final class UnknownFieldSet implements MessageLite {
+ 
+     @Override
+     public Builder clone() {
+-      getFieldBuilder(0);  // Force lastField to be built.
+-      return UnknownFieldSet.newBuilder().mergeFrom(
+-          new UnknownFieldSet(fields));
++      Builder clone = UnknownFieldSet.newBuilder();
++      for (Map.Entry<Integer, Field.Builder> entry : fieldBuilders.entrySet()) {
++        Integer key = entry.getKey();
++        Field.Builder value = entry.getValue();
++        clone.fieldBuilders.put(key, value.clone());
++      }
++      return clone;
+     }
+ 
+     public UnknownFieldSet getDefaultInstanceForType() {
+       return UnknownFieldSet.getDefaultInstance();
+     }
+ 
+-    private void reinitialize() {
+-      fields = Collections.emptyMap();
+-      lastFieldNumber = 0;
+-      lastField = null;
+-    }
+-
+     /** Reset the builder to an empty set. */
+     public Builder clear() {
+-      reinitialize();
++      fieldBuilders = new TreeMap<Integer, Field.Builder>();
+       return this;
+     }
+ 
+@@ -415,11 +400,8 @@ public final class UnknownFieldSet implements MessageLite {
+     }
+ 
+     /** Check if the given field number is present in the set. */
+-    public boolean hasField(final int number) {
+-      if (number == 0) {
+-        throw new IllegalArgumentException("Zero is not a valid field number.");
+-      }
+-      return number == lastFieldNumber || fields.containsKey(number);
++    public boolean hasField(int number) {
++      return fieldBuilders.containsKey(number);
+     }
+ 
+     /**
+@@ -430,15 +412,7 @@ public final class UnknownFieldSet implements MessageLite {
+       if (number == 0) {
+         throw new IllegalArgumentException("Zero is not a valid field number.");
+       }
+-      if (lastField != null && lastFieldNumber == number) {
+-        // Discard this.
+-        lastField = null;
+-        lastFieldNumber = 0;
+-      }
+-      if (fields.isEmpty()) {
+-        fields = new TreeMap<Integer,Field>();
+-      }
+-      fields.put(number, field);
++      fieldBuilders.put(number, Field.newBuilder(field));
+       return this;
+     }
+ 
+@@ -447,7 +421,10 @@ public final class UnknownFieldSet implements MessageLite {
+      * fields are added, the changes may or may not be reflected in this map.
+      */
+     public Map<Integer, Field> asMap() {
+-      getFieldBuilder(0);  // Force lastField to be built.
++      TreeMap<Integer, Field> fields = new TreeMap<Integer, Field>();
++      for (Map.Entry<Integer, Field.Builder> entry : fieldBuilders.entrySet()) {
++        fields.put(entry.getKey(), entry.getValue().build());
++      }
+       return Collections.unmodifiableMap(fields);
+     }
+ 
+@@ -809,54 +786,84 @@ public final class UnknownFieldSet implements MessageLite {
+      * <p>Use {@link Field#newBuilder()} to construct a {@code Builder}.
+      */
+     public static final class Builder {
+-      // This constructor should never be called directly (except from 'create').
+-      private Builder() {}
++      // This constructor should only be called directly from 'create' and 'clone'.
++      private Builder() {
++        result = new Field();
++      }
+ 
+       private static Builder create() {
+         Builder builder = new Builder();
+-        builder.result = new Field();
+         return builder;
+       }
+ 
+       private Field result;
+ 
++      @Override
++      public Builder clone() {
++        Field copy = new Field();
++        if (result.varint == null) {
++          copy.varint = null;
++        } else {
++          copy.varint = new ArrayList<Long>(result.varint);
++        }
++        if (result.fixed32 == null) {
++          copy.fixed32 = null;
++        } else {
++          copy.fixed32 = new ArrayList<Integer>(result.fixed32);
++        }
++        if (result.fixed64 == null) {
++          copy.fixed64 = null;
++        } else {
++          copy.fixed64 = new ArrayList<Long>(result.fixed64);
++        }
++        if (result.lengthDelimited == null) {
++          copy.lengthDelimited = null;
++        } else {
++          copy.lengthDelimited = new ArrayList<ByteString>(result.lengthDelimited);
++        }
++        if (result.group == null) {
++          copy.group = null;
++        } else {
++          copy.group = new ArrayList<UnknownFieldSet>(result.group);
++        }
++
++        Builder clone = new Builder();
++        clone.result = copy;
++        return clone;
++      }
++
+       /**
+-       * Build the field.  After {@code build()} has been called, the
+-       * {@code Builder} is no longer usable.  Calling any other method will
+-       * result in undefined behavior and can cause a
+-       * {@code NullPointerException} to be thrown.
++       * Build the field.
+        */
+       public Field build() {
++        Field built = new Field();
+         if (result.varint == null) {
+-          result.varint = Collections.emptyList();
++          built.varint = Collections.emptyList();
+         } else {
+-          result.varint = Collections.unmodifiableList(result.varint);
++          built.varint = Collections.unmodifiableList(result.varint);
+         }
+         if (result.fixed32 == null) {
+-          result.fixed32 = Collections.emptyList();
++          built.fixed32 = Collections.emptyList();
+         } else {
+-          result.fixed32 = Collections.unmodifiableList(result.fixed32);
++          built.fixed32 = Collections.unmodifiableList(result.fixed32);
+         }
+         if (result.fixed64 == null) {
+-          result.fixed64 = Collections.emptyList();
++          built.fixed64 = Collections.emptyList();
+         } else {
+-          result.fixed64 = Collections.unmodifiableList(result.fixed64);
++          built.fixed64 = Collections.unmodifiableList(result.fixed64);
+         }
+         if (result.lengthDelimited == null) {
+-          result.lengthDelimited = Collections.emptyList();
++          built.lengthDelimited = Collections.emptyList();
+         } else {
+-          result.lengthDelimited =
++          built.lengthDelimited =
+             Collections.unmodifiableList(result.lengthDelimited);
+         }
+         if (result.group == null) {
+-          result.group = Collections.emptyList();
++          built.group = Collections.emptyList();
+         } else {
+-          result.group = Collections.unmodifiableList(result.group);
++          built.group = Collections.unmodifiableList(result.group);
+         }
+-
+-        final Field returnMe = result;
+-        result = null;
+-        return returnMe;
++        return built;
+       }
+ 
+       /** Discard the field's contents. */
+diff --git a/java/src/test/java/com/google/protobuf/UnknownFieldSetPerformanceTest.java b/java/src/test/java/com/google/protobuf/UnknownFieldSetPerformanceTest.java
+new file mode 100644
+index 000000000..9b913b50f
+--- /dev/null
++++ b/java/src/test/java/com/google/protobuf/UnknownFieldSetPerformanceTest.java
+@@ -0,0 +1,76 @@
++// Protocol Buffers - Google's data interchange format
++// Copyright 2008 Google Inc.  All rights reserved.
++// https://developers.google.com/protocol-buffers/
++//
++// Redistribution and use in source and binary forms, with or without
++// modification, are permitted provided that the following conditions are
++// met:
++//
++//     * Redistributions of source code must retain the above copyright
++// notice, this list of conditions and the following disclaimer.
++//     * Redistributions in binary form must reproduce the above
++// copyright notice, this list of conditions and the following disclaimer
++// in the documentation and/or other materials provided with the
++// distribution.
++//     * Neither the name of Google Inc. nor the names of its
++// contributors may be used to endorse or promote products derived from
++// this software without specific prior written permission.
++//
++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++
++package com.google.protobuf;
++
++import java.io.ByteArrayInputStream;
++import java.io.IOException;
++import java.io.InputStream;
++
++import org.junit.Assert;
++
++import junit.framework.TestCase;
++
++public final class UnknownFieldSetPerformanceTest extends TestCase {
++
++  private static byte[] generateBytes(int length) {
++    Assert.assertTrue((length % 4) == 0);
++    byte[] input = new byte[length];
++    for (int i = 0; i < length; i += 4) {
++        input[i] =     (byte) 0x08; // field 1, wiretype 0
++        input[i + 1] = (byte) 0x08; // field 1, payload 8
++        input[i + 2] = (byte) 0x20; // field 4, wiretype 0
++        input[i + 3] = (byte) 0x20; // field 4, payload 32
++    }
++    return input;
++  }
++
++  // This is a performance test. Failure here is a timeout.
++  public void testAlternatingFieldNumbers() throws IOException {
++    byte[] input = generateBytes(800000);
++    InputStream in = new ByteArrayInputStream(input);
++    UnknownFieldSet.Builder builder = UnknownFieldSet.newBuilder();
++    CodedInputStream codedInput = CodedInputStream.newInstance(in);
++    builder.mergeFrom(codedInput);
++  }
++
++  // This is a performance test. Failure here is a timeout.
++  public void testAddField() {
++    UnknownFieldSet.Builder builder = UnknownFieldSet.newBuilder();
++    for (int i = 1; i <= 100000; i++) {
++      UnknownFieldSet.Field field = UnknownFieldSet.Field.newBuilder().addFixed32(i).build();
++      builder.addField(i, field);
++    }
++    UnknownFieldSet fieldSet = builder.build();
++    assertTrue(fieldSet.getField(100000).getFixed32List().get(0) == 100000);
++  }
++
++}
++
+-- 
+2.33.0
+
diff --git a/bigtop_toolchain/manifests/protobuf.pp b/bigtop_toolchain/manifests/protobuf.pp
index 7445187a..120cbfab 100644
--- a/bigtop_toolchain/manifests/protobuf.pp
+++ b/bigtop_toolchain/manifests/protobuf.pp
@@ -38,6 +38,41 @@ class bigtop_toolchain::protobuf {
      timeout => 3000
   }
 
+  if ($architecture in ['aarch64', 'ppc64le']) {
+    file { "/usr/src/0001-Backport-atomic-operations-with-support-of-arm64-and.patch":
+      source => "puppet:///modules/bigtop_toolchain/0001-Backport-atomic-operations-with-support-of-arm64-and.patch"
+    }
+
+    file { "/usr/src/0001-CVE-2021-22569-Improve-performance-of-parsing-unknow.patch":
+      source => "puppet:///modules/bigtop_toolchain/0001-CVE-2021-22569-Improve-performance-of-parsing-unknow.patch"
+    }
+
+    exec { "download protobuf 2.5.0":
+      cwd  => "/usr/src",
+      command => "/usr/bin/wget https://github.com/google/protobuf/releases/download/v2.5.0/protobuf-2.5.0.tar.gz && \
+                  mkdir -p /usr/src/protobuf-2.5.0 && \
+                  /bin/tar -xvzf protobuf-2.5.0.tar.gz -C /usr/src/protobuf-2.5.0 --strip-components=1 && \
+                  cd /usr/src/protobuf-2.5.0 && \
+                  /usr/bin/patch -p1 </usr/src/0001-Backport-atomic-operations-with-support-of-arm64-and.patch && \
+                  /usr/bin/patch -p1 </usr/src/0001-CVE-2021-22569-Improve-performance-of-parsing-unknow.patch && \
+                  curl -o config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' && \
+                  cp config.guess gtest/build-aux/",
+      creates => "/usr/src/protobuf-2.5.0",
+      require => [File["/usr/src/0001-Backport-atomic-operations-with-support-of-arm64-and.patch"],
+                  File["/usr/src/0001-CVE-2021-22569-Improve-performance-of-parsing-unknow.patch"]]
+    }
+
+    exec { "install protobuf 2.5.0":
+      cwd => "/usr/src/protobuf-2.5.0",
+      command => "/usr/src/protobuf-2.5.0/autogen.sh && \
+                  /usr/src/protobuf-2.5.0/configure --prefix=/usr/local/protobuf-2.5.0 --disable-shared --with-pic && \
+                  /usr/bin/make install",
+      creates => "/usr/local/protobuf-2.5.0",
+      require => Exec["download protobuf 2.5.0"],
+      timeout => 3000
+    }
+  }
+  
   if ($architecture == 'ppc64le') {
     exec { "download protobuf 3.17.3":
       cwd  => "/usr/src",