1 //===-- utilities_posix.cpp -------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "gwp_asan/definitions.h"
10 #include "gwp_asan/utilities.h"
11 
12 #include <assert.h>
13 
14 #ifdef __BIONIC__
15 #include <stdlib.h>
16 extern "C" GWP_ASAN_WEAK void android_set_abort_message(const char *);
17 #else // __BIONIC__
18 #include <stdio.h>
19 #endif
20 
21 namespace gwp_asan {
22 
23 #ifdef __BIONIC__
Check(bool Condition,const char * Message)24 void Check(bool Condition, const char *Message) {
25   if (Condition)
26     return;
27   if (&android_set_abort_message != nullptr)
28     android_set_abort_message(Message);
29   abort();
30 }
31 #else  // __BIONIC__
32 void Check(bool Condition, const char *Message) {
33   if (Condition)
34     return;
35   fprintf(stderr, "%s", Message);
36   __builtin_trap();
37 }
38 #endif // __BIONIC__
39 
40 // See `bionic/tests/malloc_test.cpp` in the Android source for documentation
41 // regarding their alignment guarantees. We always round up to the closest
42 // 8-byte window. As GWP-ASan's malloc(X) can always get exactly an X-sized
43 // allocation, an allocation that rounds up to 16-bytes will always be given a
44 // 16-byte aligned allocation.
alignBionic(size_t RealAllocationSize)45 static size_t alignBionic(size_t RealAllocationSize) {
46   if (RealAllocationSize % 8 == 0)
47     return RealAllocationSize;
48   return RealAllocationSize + 8 - (RealAllocationSize % 8);
49 }
50 
alignPowerOfTwo(size_t RealAllocationSize)51 static size_t alignPowerOfTwo(size_t RealAllocationSize) {
52   if (RealAllocationSize <= 2)
53     return RealAllocationSize;
54   if (RealAllocationSize <= 4)
55     return 4;
56   if (RealAllocationSize <= 8)
57     return 8;
58   if (RealAllocationSize % 16 == 0)
59     return RealAllocationSize;
60   return RealAllocationSize + 16 - (RealAllocationSize % 16);
61 }
62 
63 #ifdef __BIONIC__
64 static constexpr AlignmentStrategy PlatformDefaultAlignment =
65     AlignmentStrategy::BIONIC;
66 #else  // __BIONIC__
67 static constexpr AlignmentStrategy PlatformDefaultAlignment =
68     AlignmentStrategy::POWER_OF_TWO;
69 #endif // __BIONIC__
70 
rightAlignedAllocationSize(size_t RealAllocationSize,AlignmentStrategy Align)71 size_t rightAlignedAllocationSize(size_t RealAllocationSize,
72                                   AlignmentStrategy Align) {
73   assert(RealAllocationSize > 0);
74   if (Align == AlignmentStrategy::DEFAULT)
75     Align = PlatformDefaultAlignment;
76 
77   switch (Align) {
78   case AlignmentStrategy::BIONIC:
79     return alignBionic(RealAllocationSize);
80   case AlignmentStrategy::POWER_OF_TWO:
81     return alignPowerOfTwo(RealAllocationSize);
82   case AlignmentStrategy::PERFECT:
83     return RealAllocationSize;
84   case AlignmentStrategy::DEFAULT:
85     __builtin_unreachable();
86   }
87   __builtin_unreachable();
88 }
89 
90 } // namespace gwp_asan
91