Index: lib/sanitizer_common/sanitizer_posix.cc =================================================================== --- lib/sanitizer_common/sanitizer_posix.cc +++ lib/sanitizer_common/sanitizer_posix.cc @@ -76,17 +76,79 @@ } #endif // SANITIZER_WORDSIZE == 32 +#if defined(__powerpc64__) && SANITIZER_LINUX + +// Compare two decimal digit strings by their numeric value. +// The strings are terminated by any non-digit character. +// Empty strings are allowed and are treated as zero. +// Return -1, 0 or 1 when a is less than, equal to or greater than b +// respectively. +// Update a and b to point just past the end of the digit strings. +static int cmp_decimal(const char *&a, const char *&b) { + // Skip leading zeros. + while (*a == '0') + ++a; + while (*b == '0') + ++b; + // Compare string lengths. + size_t la = 0, lb = 0; + while (a[la] >= '0' && a[la] <= '9') + ++la; + while (b[lb] >= '0' && b[lb] <= '9') + ++lb; + if (la != lb) + return la > lb ? 1 : -1; + // Compare strings lexicographically. + for (; la--; ++a, ++b) + if (*a != *b) + return *a > *b ? 1 : -1; + return 0; +} + +// Compare two version strings of the form "x", "x.y", "x.y.z" etc. +// The strings are terminated by any non-digit, non-dot character. +// Any missing trailing components are treated as zero. +// Return -1, 0 or 1 when a is less than, equal to or greater than b +// respectively. +static int cmp_version(const char *a, const char *b) { + while (true) { + int ret = cmp_decimal(a, b); + if (ret) + return ret; + if (*a != '.' && *b != '.') + return 0; + if (*a == '.') + ++a; + if (*b == '.') + ++b; + } +} + +#endif // defined(__powerpc64__) && SANITIZER_LINUX + uptr GetMaxVirtualAddress() { #if SANITIZER_WORDSIZE == 64 -# if defined(__powerpc64__) && defined(__BIG_ENDIAN__) +# if defined(__powerpc64__) // On PowerPC64 we have two different address space layouts: 44- and 46-bit. // We somehow need to figure out which one we are using now and choose // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL. // Note that with 'ulimit -s unlimited' the stack is moved away from the top // of the address space, so simply checking the stack address is not enough. +# if SANITIZER_LINUX + // Linux switched to 46-bit addressing in version 3.7. + struct utsname uname_info; + if (uname(&uname_info) == 0) { + if (cmp_version(uname_info.release, "3.7") >= 0) + return (1ULL << 46) - 1; // 0x00003fffffffffffUL + else + return (1ULL << 44) - 1; // 0x00000fffffffffffUL + } +# endif +# if defined(__BIG_ENDIAN__) return (1ULL << 44) - 1; // 0x00000fffffffffffUL -# elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) +# else return (1ULL << 46) - 1; // 0x00003fffffffffffUL +# endif # elif defined(__aarch64__) return (1ULL << 39) - 1; # else