2014-05-10 04:12:08 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2010 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _BIONIC_MACROS_H_
|
|
|
|
#define _BIONIC_MACROS_H_
|
|
|
|
|
Align-up and randomize shared libraries.
This change implements the following property:
Any 2**N aligned memory region on size 2**N contains no more than one DSO.
The value N can be configured, with 16 or 18 looking like a good choice.
Additionally, DSOs are loaded at random page-aligned address inside these large
regions.
This change has dual purpose:
1. Larger values of N allow a lot more compact CFI shadow implementation.
See change I14dfea630de468eb5620e7f55f92b1397ba06217.
For example, CFI shadow for the system_server process has the following size (RSS, KB):
152 for N = 12, 32 for N = 16, 16 for N = 18.
2. Extra randomization is good for security.
This change does not result in extra RAM usage, because everything is still page-aligned.
It does result in a bit more VM fragmentation because of the gaps between shared libraries.
As it turns out, this fragmentation is barely noticeable because the kernel creates new mapping
at the highest possible address, and we do enough small mappings to almost completely fill the
gaps (ex. in the Zygote the gaps are filled with .ttf file mappings and thread stacks).
I've measured VM fragmentation as the sum of all VM gaps (unmapped regions) that are larger
than 1MB according to /proc/$PID/maps. On aosp_angler-userdebug, the numbers are (in GB):
| N = 12 | N = 18
system_server | 521.9 | 521.1
zygote64 | 522.1 | 521.3
zygote32 | 2.55 | 2.55
mediaserver | 4.00 | 4.00
Change-Id: Ia6df840dd409c82837efd1f263be420d9723c84a
2016-07-16 01:31:42 +02:00
|
|
|
#include <stdint.h>
|
|
|
|
|
2014-11-11 07:04:08 +01:00
|
|
|
// Frameworks OpenGL code currently leaks this header and allows
|
|
|
|
// collisions with other declarations, e.g., from libnativehelper.
|
|
|
|
// TODO: Remove once cleaned up. b/18334516
|
|
|
|
#if !defined(DISALLOW_COPY_AND_ASSIGN)
|
2014-05-10 04:12:08 +02:00
|
|
|
// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions.
|
|
|
|
// It goes in the private: declarations in a class.
|
|
|
|
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
2014-09-09 01:22:22 +02:00
|
|
|
TypeName(const TypeName&) = delete; \
|
|
|
|
void operator=(const TypeName&) = delete
|
2014-11-11 07:04:08 +01:00
|
|
|
#endif // !defined(DISALLOW_COPY_AND_ASSIGN)
|
2014-05-10 04:12:08 +02:00
|
|
|
|
|
|
|
// A macro to disallow all the implicit constructors, namely the
|
|
|
|
// default constructor, copy constructor and operator= functions.
|
|
|
|
//
|
|
|
|
// This should be used in the private: declarations for a class
|
|
|
|
// that wants to prevent anyone from instantiating it. This is
|
|
|
|
// especially useful for classes containing only static methods.
|
|
|
|
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
2014-09-09 01:22:22 +02:00
|
|
|
TypeName() = delete; \
|
2014-05-10 04:12:08 +02:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(TypeName)
|
|
|
|
|
2014-06-13 22:57:51 +02:00
|
|
|
#define BIONIC_ROUND_UP_POWER_OF_2(value) \
|
2015-12-17 01:11:04 +01:00
|
|
|
((sizeof(value) == 8) \
|
2014-07-15 03:47:23 +02:00
|
|
|
? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \
|
2015-12-17 01:11:04 +01:00
|
|
|
: (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value)))))
|
2014-06-13 22:57:51 +02:00
|
|
|
|
2016-07-06 22:20:59 +02:00
|
|
|
static constexpr uintptr_t align_down(uintptr_t p, size_t align) {
|
Align-up and randomize shared libraries.
This change implements the following property:
Any 2**N aligned memory region on size 2**N contains no more than one DSO.
The value N can be configured, with 16 or 18 looking like a good choice.
Additionally, DSOs are loaded at random page-aligned address inside these large
regions.
This change has dual purpose:
1. Larger values of N allow a lot more compact CFI shadow implementation.
See change I14dfea630de468eb5620e7f55f92b1397ba06217.
For example, CFI shadow for the system_server process has the following size (RSS, KB):
152 for N = 12, 32 for N = 16, 16 for N = 18.
2. Extra randomization is good for security.
This change does not result in extra RAM usage, because everything is still page-aligned.
It does result in a bit more VM fragmentation because of the gaps between shared libraries.
As it turns out, this fragmentation is barely noticeable because the kernel creates new mapping
at the highest possible address, and we do enough small mappings to almost completely fill the
gaps (ex. in the Zygote the gaps are filled with .ttf file mappings and thread stacks).
I've measured VM fragmentation as the sum of all VM gaps (unmapped regions) that are larger
than 1MB according to /proc/$PID/maps. On aosp_angler-userdebug, the numbers are (in GB):
| N = 12 | N = 18
system_server | 521.9 | 521.1
zygote64 | 522.1 | 521.3
zygote32 | 2.55 | 2.55
mediaserver | 4.00 | 4.00
Change-Id: Ia6df840dd409c82837efd1f263be420d9723c84a
2016-07-16 01:31:42 +02:00
|
|
|
return p & ~(align - 1);
|
|
|
|
}
|
|
|
|
|
2016-07-06 22:20:59 +02:00
|
|
|
static constexpr uintptr_t align_up(uintptr_t p, size_t align) {
|
Align-up and randomize shared libraries.
This change implements the following property:
Any 2**N aligned memory region on size 2**N contains no more than one DSO.
The value N can be configured, with 16 or 18 looking like a good choice.
Additionally, DSOs are loaded at random page-aligned address inside these large
regions.
This change has dual purpose:
1. Larger values of N allow a lot more compact CFI shadow implementation.
See change I14dfea630de468eb5620e7f55f92b1397ba06217.
For example, CFI shadow for the system_server process has the following size (RSS, KB):
152 for N = 12, 32 for N = 16, 16 for N = 18.
2. Extra randomization is good for security.
This change does not result in extra RAM usage, because everything is still page-aligned.
It does result in a bit more VM fragmentation because of the gaps between shared libraries.
As it turns out, this fragmentation is barely noticeable because the kernel creates new mapping
at the highest possible address, and we do enough small mappings to almost completely fill the
gaps (ex. in the Zygote the gaps are filled with .ttf file mappings and thread stacks).
I've measured VM fragmentation as the sum of all VM gaps (unmapped regions) that are larger
than 1MB according to /proc/$PID/maps. On aosp_angler-userdebug, the numbers are (in GB):
| N = 12 | N = 18
system_server | 521.9 | 521.1
zygote64 | 522.1 | 521.3
zygote32 | 2.55 | 2.55
mediaserver | 4.00 | 4.00
Change-Id: Ia6df840dd409c82837efd1f263be420d9723c84a
2016-07-16 01:31:42 +02:00
|
|
|
return (p + align - 1) & ~(align - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
static inline T* align_down(T* p, size_t align) {
|
|
|
|
return reinterpret_cast<T*>(align_down(reinterpret_cast<uintptr_t>(p), align));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
static inline T* align_up(T* p, size_t align) {
|
|
|
|
return reinterpret_cast<T*>(align_up(reinterpret_cast<uintptr_t>(p), align));
|
|
|
|
}
|
|
|
|
|
2017-10-06 00:18:47 +02:00
|
|
|
#if defined(__arm__)
|
|
|
|
// Do not emit anything for arm, clang does not allow emiting an arm unwind
|
|
|
|
// directive.
|
|
|
|
// #define BIONIC_STOP_UNWIND asm volatile(".cantunwind")
|
|
|
|
#define BIONIC_STOP_UNWIND
|
|
|
|
#elif defined(__aarch64__)
|
|
|
|
#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined x30")
|
|
|
|
#elif defined(__i386__)
|
|
|
|
#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined \%eip")
|
|
|
|
#elif defined(__x86_64__)
|
|
|
|
#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined \%rip")
|
2017-10-13 14:22:10 +02:00
|
|
|
#elif defined (__mips__)
|
|
|
|
#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined $ra")
|
2017-10-06 00:18:47 +02:00
|
|
|
#endif
|
|
|
|
|
2017-11-14 17:50:43 +01:00
|
|
|
// The arraysize(arr) macro returns the # of elements in an array arr.
|
|
|
|
// The expression is a compile-time constant, and therefore can be
|
|
|
|
// used in defining new arrays, for example. If you use arraysize on
|
|
|
|
// a pointer by mistake, you will get a compile-time error.
|
|
|
|
//
|
|
|
|
// One caveat is that arraysize() doesn't accept any array of an
|
|
|
|
// anonymous type or a type defined inside a function.
|
|
|
|
//
|
|
|
|
// This template function declaration is used in defining arraysize.
|
|
|
|
// Note that the function doesn't need an implementation, as we only
|
|
|
|
// use its type.
|
|
|
|
template <typename T, size_t N>
|
|
|
|
char (&ArraySizeHelper(T (&array)[N]))[N]; // NOLINT(readability/casting)
|
|
|
|
|
|
|
|
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
|
|
|
|
|
2014-05-10 04:12:08 +02:00
|
|
|
#endif // _BIONIC_MACROS_H_
|