Source: google-perftools
Version: 2.5-2.2
Severity: important
Tags: patch, fixed-upstream

With one cherry-pick from upstream, google-perftools builds cleanly on
s390x and all tests pass.
diff -urpN google-perftools-2.5.orig/debian/control google-perftools-2.5/debian/control
--- google-perftools-2.5.orig/debian/control	2017-08-17 22:36:49.000000000 +0000
+++ google-perftools-2.5/debian/control	2017-08-17 22:38:16.154296198 +0000
@@ -11,7 +11,7 @@ Vcs-Browser: http://svn.debian.org/viewv
 
 Package: libgoogle-perftools-dev
 Section: libdevel
-Architecture: i386 amd64 powerpc ppc64el arm64 armel armhf
+Architecture: i386 amd64 powerpc ppc64el arm64 armel armhf s390x
 Depends: ${misc:Depends}, libgoogle-perftools4 (= ${binary:Version}), libtcmalloc-minimal4 (= ${binary:Version}), libunwind8-dev [amd64]
 Description: libraries for CPU and heap analysis, plus an efficient thread-caching malloc
  The gperftools, previously called google-perftools, package contains some
@@ -22,7 +22,7 @@ Description: libraries for CPU and heap
 
 Package: libtcmalloc-minimal4
 Section: libs
-Architecture: i386 amd64 powerpc ppc64el arm64 armel armhf
+Architecture: i386 amd64 powerpc ppc64el arm64 armel armhf s390x
 Depends: ${shlibs:Depends}, ${misc:Depends}
 Description: efficient thread-caching malloc
  The gperftools, previously called google-perftools, package contains some
@@ -31,7 +31,7 @@ Description: efficient thread-caching ma
 
 Package: libgoogle-perftools4
 Section: libs
-Architecture: i386 amd64 powerpc ppc64el arm64 armel armhf
+Architecture: i386 amd64 powerpc ppc64el arm64 armel armhf s390x
 Depends: libtcmalloc-minimal4 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
 Conflicts: libgoogle-perftools0
 Description: libraries for CPU and heap analysis, plus an efficient thread-caching malloc
diff -urpN google-perftools-2.5.orig/debian/patches/Add-support-for-31-bit-s390-merge-linux_syscall_supp.patch google-perftools-2.5/debian/patches/Add-support-for-31-bit-s390-merge-linux_syscall_supp.patch
--- google-perftools-2.5.orig/debian/patches/Add-support-for-31-bit-s390-merge-linux_syscall_supp.patch	1970-01-01 00:00:00.000000000 +0000
+++ google-perftools-2.5/debian/patches/Add-support-for-31-bit-s390-merge-linux_syscall_supp.patch	2017-08-17 23:18:16.546439347 +0000
@@ -0,0 +1,606 @@
+From bf8eacce69df877d1cecdab8c7a6cc3f218ebcc2 Mon Sep 17 00:00:00 2001
+From: Bryan Chan <[email protected]>
+Date: Wed, 15 Jun 2016 00:10:45 -0400
+Subject: [PATCH] Add support for 31-bit s390; merge linux_syscall_support.h
+ changes from upstream.
+
+---
+ configure.ac                     |   4 +-
+ m4/pc_from_ucontext.m4           |   2 +-
+ src/base/basictypes.h            |   2 +-
+ src/base/linux_syscall_support.h | 293 ++++++++++++++++++++++++++++-----------
+ src/base/linuxthreads.h          |   2 +-
+ src/getpc.h                      |   5 +
+ src/malloc_hook_mmap_linux.h     |  16 +--
+ 7 files changed, 222 insertions(+), 102 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index c7221ca..a688a25 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -53,8 +53,8 @@ case "$host" in
+    *-darwin*) default_enable_heap_checker=no;;
+ esac
+ 
+-# Currently only backtrace works on s390x.
+-AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [return __s390x__])],
++# Currently only backtrace works on s390.
++AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [return __s390__])],
+                   [default_enable_libunwind=no
+                    default_enable_backtrace=yes],
+                   [default_enable_libunwind=yes
+diff --git a/m4/pc_from_ucontext.m4 b/m4/pc_from_ucontext.m4
+index d743fa4..c9224bc 100644
+--- a/m4/pc_from_ucontext.m4
++++ b/m4/pc_from_ucontext.m4
+@@ -27,7 +27,7 @@ AC_DEFUN([AC_PC_FROM_UCONTEXT],
+    pc_fields="$pc_fields uc_mcontext.sc_ip"            # Linux (ia64)
+    pc_fields="$pc_fields uc_mcontext.pc"               # Linux (mips)
+    pc_fields="$pc_fields uc_mcontext.uc_regs->gregs[[PT_NIP]]" # Linux (ppc)
+-   pc_fields="$pc_fields uc_mcontext.psw.addr"         # Linux (s390x)
++   pc_fields="$pc_fields uc_mcontext.psw.addr"         # Linux (s390)
+    pc_fields="$pc_fields uc_mcontext.gregs[[R15]]"     # Linux (arm old [untested])
+    pc_fields="$pc_fields uc_mcontext.arm_pc"           # Linux (arm arch 5)
+    pc_fields="$pc_fields uc_mcontext.gp_regs[[PT_NIP]]"  # Suse SLES 11 (ppc64)
+diff --git a/src/base/basictypes.h b/src/base/basictypes.h
+index b628709..72c27b4 100644
+--- a/src/base/basictypes.h
++++ b/src/base/basictypes.h
+@@ -363,7 +363,7 @@ class AssignAttributeStartEnd {
+ # elif (defined(__aarch64__))
+ #   define CACHELINE_ALIGNED __attribute__((aligned(64)))
+     // implementation specific, Cortex-A53 and 57 should have 64 bytes
+-# elif (defined(__s390x__))
++# elif (defined(__s390__))
+ #   define CACHELINE_ALIGNED __attribute__((aligned(256)))
+ # else
+ #   error Could not determine cache line length - unknown architecture
+diff --git a/src/base/linux_syscall_support.h b/src/base/linux_syscall_support.h
+index 5d578cd..235f2ad 100644
+--- a/src/base/linux_syscall_support.h
++++ b/src/base/linux_syscall_support.h
+@@ -130,12 +130,13 @@
+ #ifndef SYS_LINUX_SYSCALL_SUPPORT_H
+ #define SYS_LINUX_SYSCALL_SUPPORT_H
+ 
+-/* We currently only support x86-32, x86-64, ARM, MIPS, PPC/PPC64, Aarch64 and s390x on Linux.
++/* We currently only support x86-32, x86-64, ARM, MIPS, PPC/PPC64, Aarch64, s390 and s390x
++ * on Linux.
+  * Porting to other related platforms should not be difficult.
+  */
+ #if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \
+      defined(__mips__) || defined(__PPC__) || \
+-     defined(__aarch64__) || defined(__s390x__)) \
++     defined(__aarch64__) || defined(__s390__)) \
+   && (defined(__linux))
+ 
+ #ifndef SYS_CPLUSPLUS
+@@ -247,7 +248,8 @@ struct kernel_rusage {
+   long               ru_nivcsw;
+ };
+ 
+-#if defined(__i386__) || defined(__arm__) || defined(__PPC__)
++#if defined(__i386__) || defined(__arm__) \
++  || defined(__PPC__) || (defined(__s390__) && !defined(__s390x__))
+ 
+ /* include/asm-{arm,i386,mips,ppc}/signal.h                                  */
+ struct kernel_old_sigaction {
+@@ -261,8 +263,8 @@ struct kernel_old_sigaction {
+ } __attribute__((packed,aligned(4)));
+ #elif (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32)
+   #define kernel_old_sigaction kernel_sigaction
+-#elif defined(__aarch64__) || defined(__s390x__)
+-  // No kernel_old_sigaction defined for arm64 or s390x.
++#elif defined(__aarch64__)
++  // No kernel_old_sigaction defined for arm64.
+ #endif
+ 
+ /* Some kernel functions (e.g. sigaction() in 2.6.23) require that the
+@@ -306,7 +308,7 @@ struct kernel_sigaction {
+ #endif
+ };
+ 
+-/* include/asm-{arm,i386,mips,ppc}/stat.h                                    */
++/* include/asm-{arm,i386,mips,ppc,s390}/stat.h                               */
+ #ifdef __mips__
+ #if _MIPS_SIM == _MIPS_SIM_ABI64
+ struct kernel_stat {
+@@ -514,6 +516,29 @@ struct kernel_stat {
+   long               st_blocks;
+   unsigned long      __unused[3];
+ };
++#elif defined(__s390__)
++struct kernel_stat {
++  unsigned short     st_dev;
++  unsigned short     __pad1;
++  unsigned long      st_ino;
++  unsigned short     st_mode;
++  unsigned short     st_nlink;
++  unsigned short     st_uid;
++  unsigned short     st_gid;
++  unsigned short     st_rdev;
++  unsigned short     __pad2;
++  unsigned long      st_size;
++  unsigned long      st_blksize;
++  unsigned long      st_blocks;
++  unsigned long      st_atime_;
++  unsigned long      st_atime_nsec_;
++  unsigned long      st_mtime_;
++  unsigned long      st_mtime_nsec_;
++  unsigned long      st_ctime_;
++  unsigned long      st_ctime_nsec_;
++  unsigned long      __unused4;
++  unsigned long      __unused5;
++};
+ #endif
+ 
+ 
+@@ -728,7 +753,7 @@ struct kernel_stat {
+ #define __NR_fstatat             79
+ #endif
+ /* End of aarch64 defininitions                                              */
+-#elif defined(__s390x__)
++#elif defined(__s390__)
+ #ifndef __NR_quotactl
+ #define __NR_quotactl           131
+ #endif
+@@ -753,27 +778,6 @@ struct kernel_stat {
+ #ifndef __NR_pwrite64
+ #define __NR_pwrite64           181
+ #endif
+-#ifndef __NR_getrlimit
+-#define __NR_getrlimit          191
+-#endif
+-#ifndef __NR_setresuid
+-#define __NR_setresuid          208
+-#endif
+-#ifndef __NR_getresuid
+-#define __NR_getresuid          209
+-#endif
+-#ifndef __NR_setresgid
+-#define __NR_setresgid          210
+-#endif
+-#ifndef __NR_getresgid
+-#define __NR_getresgid          211
+-#endif
+-#ifndef __NR_setfsuid
+-#define __NR_setfsuid           215
+-#endif
+-#ifndef __NR_setfsgid
+-#define __NR_setfsgid           216
+-#endif
+ #ifndef __NR_getdents64
+ #define __NR_getdents64         220
+ #endif
+@@ -816,9 +820,6 @@ struct kernel_stat {
+ #ifndef __NR_set_tid_address
+ #define __NR_set_tid_address    252
+ #endif
+-#ifndef __NR_fadvise64
+-#define __NR_fadvise64          253
+-#endif
+ #ifndef __NR_clock_gettime
+ #define __NR_clock_gettime      260
+ #endif
+@@ -840,9 +841,6 @@ struct kernel_stat {
+ #ifndef __NR_openat
+ #define __NR_openat             288
+ #endif
+-#ifndef __NR_newfstatat
+-#define __NR_newfstatat         293
+-#endif
+ #ifndef __NR_unlinkat
+ #define __NR_unlinkat           294
+ #endif
+@@ -855,7 +853,89 @@ struct kernel_stat {
+ #ifndef __NR_fallocate
+ #define __NR_fallocate          314
+ #endif
+-/* End of s390x definitions                                                  */
++/* Some syscalls are named/numbered differently between s390 and s390x. */
++#ifdef __s390x__
++# ifndef __NR_getrlimit
++# define __NR_getrlimit          191
++# endif
++# ifndef __NR_setresuid
++# define __NR_setresuid          208
++# endif
++# ifndef __NR_getresuid
++# define __NR_getresuid          209
++# endif
++# ifndef __NR_setresgid
++# define __NR_setresgid          210
++# endif
++# ifndef __NR_getresgid
++# define __NR_getresgid          211
++# endif
++# ifndef __NR_setfsuid
++# define __NR_setfsuid           215
++# endif
++# ifndef __NR_setfsgid
++# define __NR_setfsgid           216
++# endif
++# ifndef __NR_fadvise64
++# define __NR_fadvise64          253
++# endif
++# ifndef __NR_newfstatat
++# define __NR_newfstatat         293
++# endif
++#else /* __s390x__ */
++# ifndef __NR_getrlimit
++# define __NR_getrlimit          76
++# endif
++# ifndef __NR_setfsuid
++# define __NR_setfsuid           138
++# endif
++# ifndef __NR_setfsgid
++# define __NR_setfsgid           139
++# endif
++# ifndef __NR_setresuid
++# define __NR_setresuid          164
++# endif
++# ifndef __NR_getresuid
++# define __NR_getresuid          165
++# endif
++# ifndef __NR_setresgid
++# define __NR_setresgid          170
++# endif
++# ifndef __NR_getresgid
++# define __NR_getresgid          171
++# endif
++# ifndef __NR_ugetrlimit
++# define __NR_ugetrlimit         191
++# endif
++# ifndef __NR_mmap2
++# define __NR_mmap2              192
++# endif
++# ifndef __NR_setresuid32
++# define __NR_setresuid32        208
++# endif
++# ifndef __NR_getresuid32
++# define __NR_getresuid32        209
++# endif
++# ifndef __NR_setresgid32
++# define __NR_setresgid32        210
++# endif
++# ifndef __NR_getresgid32
++# define __NR_getresgid32        211
++# endif
++# ifndef __NR_setfsuid32
++# define __NR_setfsuid32         215
++# endif
++# ifndef __NR_setfsgid32
++# define __NR_setfsgid32         216
++# endif
++# ifndef __NR_fadvise64_64
++# define __NR_fadvise64_64       264
++# endif
++# ifndef __NR_fstatat64
++# define __NR_fstatat64          293
++# endif
++#endif /* __s390__ */
++/* End of s390/s390x definitions                                             */
+ #endif
+ 
+ 
+@@ -919,7 +999,7 @@ struct kernel_stat {
+ 
+   #undef  LSS_RETURN
+   #if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) ||        \
+-       defined(__aarch64__) || defined(__s390x__))
++       defined(__aarch64__) || defined(__s390__))
+   /* Failing system calls return a negative result in the range of
+    * -1..-4095. These are "errno" values with the sign inverted.
+    */
+@@ -2236,19 +2316,20 @@ struct kernel_stat {
+       }
+       LSS_RETURN(int, __res);
+     }
+-  #elif defined(__s390x__)
++  #elif defined(__s390__)
+     #undef  LSS_REG
+     #define LSS_REG(r, a) register unsigned long __r##r __asm__("r"#r) = (unsigned long) a
+     #undef  LSS_BODY
+     #define LSS_BODY(type, name, args...)                                     \
++        register unsigned long __nr __asm__("r1")                             \
++            = (unsigned long)(__NR_##name);                                   \
+         register long __res_r2 __asm__("r2");                                 \
+         long __res;                                                           \
+         __asm__ __volatile__                                                  \
+-            ("lgfi %%r1, %1\n\t"                                              \
+-             "svc 0\n\t"                                                      \
+-             : "=&r"(__res_r2)                                                \
+-             : "i"(__NR_##name), ## args                                      \
+-             : "r1", "memory");                                               \
++            ("svc 0\n\t"                                                      \
++             : "=d"(__res_r2)                                                 \
++             : "d"(__nr), ## args                                             \
++             : "memory");                                                     \
+         __res = __res_r2;                                                     \
+         LSS_RETURN(type, __res)
+     #undef _syscall0
+@@ -2266,13 +2347,13 @@ struct kernel_stat {
+     #define _syscall2(type, name, type1, arg1, type2, arg2)                   \
+        type LSS_NAME(name)(type1 arg1, type2 arg2) {                          \
+           LSS_REG(2, arg1); LSS_REG(3, arg2);                                 \
+-          LSS_BODY(type, name, "0"(__r2), "r"(__r3));                         \
++          LSS_BODY(type, name, "0"(__r2), "d"(__r3));                         \
+        }
+     #undef _syscall3
+     #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3)      \
+        type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) {              \
+           LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3);               \
+-          LSS_BODY(type, name, "0"(__r2), "r"(__r3), "r"(__r4));              \
++          LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4));              \
+        }
+     #undef _syscall4
+     #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3,      \
+@@ -2281,8 +2362,8 @@ struct kernel_stat {
+                            type4 arg4) {                                      \
+           LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3);               \
+           LSS_REG(5, arg4);                                                   \
+-          LSS_BODY(type, name, "0"(__r2), "r"(__r3), "r"(__r4),               \
+-                               "r"(__r5));                                    \
++          LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4),               \
++                               "d"(__r5));                                    \
+        }
+     #undef _syscall5
+     #define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3,      \
+@@ -2291,8 +2372,8 @@ struct kernel_stat {
+                            type4 arg4, type5 arg5) {                          \
+           LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3);               \
+           LSS_REG(5, arg4); LSS_REG(6, arg5);                                 \
+-          LSS_BODY(type, name, "0"(__r2), "r"(__r3), "r"(__r4),               \
+-                               "r"(__r5), "r"(__r6));                         \
++          LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4),               \
++                               "d"(__r5), "d"(__r6));                         \
+        }
+     #undef _syscall6
+     #define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3,      \
+@@ -2301,8 +2382,8 @@ struct kernel_stat {
+                            type4 arg4, type5 arg5, type6 arg6) {              \
+           LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3);               \
+           LSS_REG(5, arg4); LSS_REG(6, arg5); LSS_REG(7, arg6);               \
+-          LSS_BODY(type, name, "0"(__r2), "r"(__r3), "r"(__r4),               \
+-                               "r"(__r5), "r"(__r6), "r"(__r7));              \
++          LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4),               \
++                               "d"(__r5), "d"(__r6), "d"(__r7));              \
+        }
+     LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
+                                    int flags, void *arg, int *parent_tidptr,
+@@ -2317,6 +2398,27 @@ struct kernel_stat {
+         register void  *__newtls         __asm__ ("r6")  = newtls;
+         register int   *__ctidptr        __asm__ ("r5")  = child_tidptr;
+         __asm__ __volatile__ (
++    #ifndef __s390x__
++                                  /* arg already in r0 */
++          "ltr %4, %4\n\t"        /* check fn, which is already in r1 */
++          "jz 1f\n\t"             /* NULL function pointer, return -EINVAL */
++          "ltr %5, %5\n\t"        /* check child_stack, which is already in r2 */
++          "jz 1f\n\t"             /* NULL stack pointer, return -EINVAL */
++                                  /* flags already in r3 */
++                                  /* parent_tidptr already in r4 */
++                                  /* child_tidptr already in r5 */
++                                  /* newtls already in r6 */
++          "svc %2\n\t"            /* invoke clone syscall */
++          "ltr %0,%%r2\n\t"       /* load return code into __ret and test */
++          "jnz 1f\n\t"            /* return to parent if non-zero */
++                                  /* start child thread */
++          "lr %%r2, %7\n\t"       /* set first parameter to void *arg */
++          "ahi %%r15, -96\n\t"    /* make room on the stack for the save area */
++          "xc 0(4,%%r15), 0(%%r15)\n\t"
++          "basr %%r14, %4\n\t"    /* jump to fn */
++          "svc %3\n"              /* invoke exit syscall */
++          "1:\n"
++    #else
+                                   /* arg already in r0 */
+           "ltgr %4, %4\n\t"       /* check fn, which is already in r1 */
+           "jz 1f\n\t"             /* NULL function pointer, return -EINVAL */
+@@ -2335,12 +2437,12 @@ struct kernel_stat {
+           "xc 0(8,%%r15), 0(%%r15)\n\t"
+           "basr %%r14, %4\n\t"    /* jump to fn */
+           "svc %3\n"              /* invoke exit syscall */
+-
+           "1:\n"
++    #endif
+           : "=r" (__ret)
+           : "0" (-EINVAL), "i" (__NR_clone), "i" (__NR_exit),
+-            "r" (__fn), "r" (__cstack), "r" (__flags), "r" (__arg),
+-            "r" (__ptidptr), "r" (__newtls), "r" (__ctidptr)
++            "d" (__fn), "d" (__cstack), "d" (__flags), "d" (__arg),
++            "d" (__ptidptr), "d" (__newtls), "d" (__ctidptr)
+           : "cc", "r14", "memory"
+         );
+       }
+@@ -2429,18 +2531,6 @@ struct kernel_stat {
+                          int,                     t, int,       p)
+   #endif
+   #if defined(__x86_64__) || defined(__s390x__)
+-    #if defined(__s390x__)
+-    LSS_INLINE _syscall1(void*, mmap, void*, a)
+-    #else
+-    /* Need to make sure __off64_t isn't truncated to 32-bits under x32.  */
+-    LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
+-                                    __off64_t o) {
+-      LSS_BODY(6, void*, mmap, LSS_SYSCALL_ARG(s), LSS_SYSCALL_ARG(l),
+-                               LSS_SYSCALL_ARG(p), LSS_SYSCALL_ARG(f),
+-                               LSS_SYSCALL_ARG(d), (uint64_t)(o));
+-    }
+-    #endif
+-
+     LSS_INLINE int LSS_NAME(sigaction)(int signum,
+                                        const struct kernel_sigaction *act,
+                                        struct kernel_sigaction *oldact) {
+@@ -2458,10 +2548,8 @@ struct kernel_stat {
+                                       (KERNEL_NSIG+7)/8);
+       } else
+       #endif
+-      {
+         return LSS_NAME(rt_sigaction)(signum, act, oldact,
+                                       (KERNEL_NSIG+7)/8);
+-      }
+     }
+ 
+     LSS_INLINE int LSS_NAME(sigprocmask)(int how,
+@@ -2542,26 +2630,30 @@ struct kernel_stat {
+     }
+   }
+ 
+-  #if defined(__i386__) || \
+-      defined(__arm__) || \
+-     (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || defined(__PPC__)
++  #if defined(__i386__) ||                                                    \
++      defined(__arm__) ||                                                     \
++     (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) ||                   \
++      defined(__PPC__) ||                                                     \
++     (defined(__s390__) && !defined(__s390x__))
+     #define __NR__sigaction   __NR_sigaction
+     #define __NR__sigprocmask __NR_sigprocmask
+     LSS_INLINE _syscall2(int, fstat64,             int, f,
+                          struct kernel_stat64 *, b)
+     LSS_INLINE _syscall5(int, _llseek,     uint, fd, ulong, hi, ulong, lo,
+                          loff_t *, res, uint, wh)
+-#ifdef __PPC64__
+-    LSS_INLINE _syscall6(void*, mmap,              void*, s,
+-                         size_t,                   l, int,               p,
+-                         int,                      f, int,               d,
+-                         off_t,                    o)
+-#else
+-    #ifndef __ARM_EABI__
+-    /* Not available on ARM EABI Linux.  */
+-    LSS_INLINE _syscall1(void*, mmap,              void*, a)
+-    #endif
+-    LSS_INLINE _syscall6(void*, mmap2,             void*, s,
++#if defined(__s390__) && !defined(__s390x__)
++    /* On s390, mmap2() arguments are passed in memory. */
++    LSS_INLINE void* LSS_NAME(_mmap2)(void *s, size_t l, int p, int f, int d,
++                                      off_t o) {
++      unsigned long buf[6] = { (unsigned long) s, (unsigned long) l,
++                               (unsigned long) p, (unsigned long) f,
++                               (unsigned long) d, (unsigned long) o };
++      LSS_REG(2, buf);
++      LSS_BODY(void*, mmap2, "0"(__r2));
++    }
++#elif !defined(__PPC64__)
++    #define __NR__mmap2 __NR_mmap2
++    LSS_INLINE _syscall6(void*, _mmap2,            void*, s,
+                          size_t,                   l, int,               p,
+                          int,                      f, int,               d,
+                          off_t,                    o)
+@@ -2654,11 +2746,48 @@ struct kernel_stat {
+       return rc;
+     }
+   #endif
++  #if defined(__i386__) ||                                                    \
++      defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) ||                     \
++     (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) ||                   \
++     (defined(__PPC__) && !defined(__PPC64__)) ||                             \
++     (defined(__s390__) && !defined(__s390x__))
++    /* On these architectures, implement mmap() with mmap2(). */
++    LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
++                                    int64_t o) {
++      if (o % 4096) {
++        LSS_ERRNO = EINVAL;
++        return (void *) -1;
++      }
++      return LSS_NAME(_mmap2)(s, l, p, f, d, (o / 4096));
++    }
++  #elif defined(__s390x__)
++    /* On s390x, mmap() arguments are passed in memory. */
++    LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
++                                    int64_t o) {
++      unsigned long buf[6] = { (unsigned long) s, (unsigned long) l,
++                               (unsigned long) p, (unsigned long) f,
++                               (unsigned long) d, (unsigned long) o };
++      LSS_REG(2, buf);
++      LSS_BODY(void*, mmap, "0"(__r2));
++    }
++  #elif defined(__x86_64__)
++    /* Need to make sure __off64_t isn't truncated to 32-bits under x32.  */
++    LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
++                                    int64_t o) {
++      LSS_BODY(6, void*, mmap, LSS_SYSCALL_ARG(s), LSS_SYSCALL_ARG(l),
++                               LSS_SYSCALL_ARG(p), LSS_SYSCALL_ARG(f),
++                               LSS_SYSCALL_ARG(d), (uint64_t)(o));
++    }
++  #else
++    /* Remaining 64-bit architectures. */
++    LSS_INLINE _syscall6(void*, mmap, void*, addr, size_t, length, int, prot,
++                         int, flags, int, fd, int64_t, offset)
++  #endif
+   #if defined(__i386__) || \
+       defined(__PPC__) || \
+       (defined(__arm__) && !defined(__ARM_EABI__)) || \
+       (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \
+-      defined(__s390x__)
++      defined(__s390__)
+ 
+     /* See sys_socketcall in net/socket.c in kernel source.
+      * It de-multiplexes on its first arg and unpacks the arglist
+diff --git a/src/base/linuxthreads.h b/src/base/linuxthreads.h
+index b715190..09ce45f 100644
+--- a/src/base/linuxthreads.h
++++ b/src/base/linuxthreads.h
+@@ -42,7 +42,7 @@
+  */
+ #if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \
+      defined(__mips__) || defined(__PPC__) || defined(__aarch64__) ||       \
+-     defined(__s390x__)) && defined(__linux)
++     defined(__s390__)) && defined(__linux)
+ 
+ /* Define the THREADS symbol to make sure that there is exactly one core dumper
+  * built into the library.
+diff --git a/src/getpc.h b/src/getpc.h
+index 25fee39..163873e 100644
+--- a/src/getpc.h
++++ b/src/getpc.h
+@@ -179,7 +179,12 @@ inline void* GetPC(const struct ucontext_t& signal_ucontext) {
+ // configure.ac (or set it manually in your config.h).
+ #else
+ inline void* GetPC(const ucontext_t& signal_ucontext) {
++#if defined(__s390__) && !defined(__s390x__)
++  // Mask out the AMODE31 bit from the PC recorded in the context.
++  return (void*)((unsigned long)signal_ucontext.PC_FROM_UCONTEXT & 0x7fffffffUL);
++#else
+   return (void*)signal_ucontext.PC_FROM_UCONTEXT;   // defined in config.h
++#endif
+ }
+ 
+ #endif
+diff --git a/src/malloc_hook_mmap_linux.h b/src/malloc_hook_mmap_linux.h
+index 1c4c766..4b13861 100755
+--- a/src/malloc_hook_mmap_linux.h
++++ b/src/malloc_hook_mmap_linux.h
+@@ -52,7 +52,7 @@
+ 
+ // I test for 64-bit first so I don't have to do things like
+ // '#if (defined(__mips__) && !defined(__MIPS64__))' as a mips32 check.
+-#if defined(__x86_64__) || defined(__PPC64__) || defined(__aarch64__) || (defined(_MIPS_SIM) && _MIPS_SIM == _ABI64)
++#if defined(__x86_64__) || defined(__PPC64__) || defined(__aarch64__) || (defined(_MIPS_SIM) && _MIPS_SIM == _ABI64) || defined(__s390__)
+ 
+ static inline void* do_mmap64(void *start, size_t length,
+                               int prot, int flags,
+@@ -119,20 +119,6 @@ static inline void* do_mmap64(void *start, size_t length,
+ 
+ #define MALLOC_HOOK_HAVE_DO_MMAP64 1
+ 
+-#elif defined(__s390x__)
+-
+-static inline void* do_mmap64(void *start, size_t length,
+-                              int prot, int flags,
+-                              int fd, __off64_t offset) __THROW {
+-  // mmap on s390x uses the old syscall interface
+-  unsigned long args[6] = { (unsigned long) start, (unsigned long) length,
+-                            (unsigned long) prot, (unsigned long) flags,
+-                            (unsigned long) fd, (unsigned long) offset };
+-  return sys_mmap(args);
+-}
+-
+-#define MALLOC_HOOK_HAVE_DO_MMAP64 1
+-
+ #endif  // #if defined(__x86_64__)
+ 
+ 
+-- 
+2.14.1
+
diff -urpN google-perftools-2.5.orig/debian/rules google-perftools-2.5/debian/rules
--- google-perftools-2.5.orig/debian/rules	2017-08-17 22:36:49.000000000 +0000
+++ google-perftools-2.5/debian/rules	2017-08-17 22:38:36.370296198 +0000
@@ -23,7 +23,7 @@ DEB_INSTALL_CHANGELOGS_ALL := ChangeLog
 
 ifeq (,$(findstring nocheck, $(DEB_BUILD_OPTIONS)))
 # List of architectures for which test execution is enabled
-TEST_ARCHS=i386 amd64
+TEST_ARCHS=i386 amd64 s390x
 ifneq (,$(findstring $(DEB_HOST_ARCH), $(TEST_ARCHS)))
 DEB_MAKE_CHECK_TARGET := check
 endif # TEST_ARCHS

Reply via email to