[scudo][standalone] Introduce the Secondary allocator
Summary:
The Secondary allocator wraps the platform allocation primitives. It is
meant to be used for larger sizes that the Primary can't fullfill, as
it will be slower, and sizes are multiple of the system page size.
This also changes some of the existing code, notably the opaque
platform data being passed to the platform specific functions: we can
shave a couple of syscalls on Fuchsia by storing additional data (this
addresses a TODO).
Reviewers: eugenis, vitalybuka, hctim, morehouse
Reviewed By: morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D60787
llvm-svn: 359097
2019-04-24 22:20:49 +08:00
|
|
|
//===-- secondary.h ---------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef SCUDO_SECONDARY_H_
|
|
|
|
#define SCUDO_SECONDARY_H_
|
|
|
|
|
|
|
|
#include "common.h"
|
[scudo][standalone] Consolidate lists
Summary:
This is a clean patch using the last diff of D69265, but using git
instead of svn, since svn went ro and arc was making my life harded
than it needed to be.
I was going to introduce a couple more lists and realized that our
lists are currently a bit all over the place. While we have a singly
linked list type relatively well defined, we are using doubly linked
lists defined on the fly for the stats and for the secondary blocks.
This CL adds a doubly linked list object, reorganizing the singly list
one to extract as much of the common code as possible. We use this
new type in the stats and the secondary. We also reorganize the list
tests to benefit from this consolidation.
There are a few side effect changes such as using for iterator loops
that are, in my opinion, cleaner in a couple of places.
Reviewers: hctim, morehouse, pcc, cferris
Reviewed By: hctim
Subscribers: jfb, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69516
2019-10-29 00:25:04 +08:00
|
|
|
#include "list.h"
|
[scudo][standalone] Introduce the Secondary allocator
Summary:
The Secondary allocator wraps the platform allocation primitives. It is
meant to be used for larger sizes that the Primary can't fullfill, as
it will be slower, and sizes are multiple of the system page size.
This also changes some of the existing code, notably the opaque
platform data being passed to the platform specific functions: we can
shave a couple of syscalls on Fuchsia by storing additional data (this
addresses a TODO).
Reviewers: eugenis, vitalybuka, hctim, morehouse
Reviewed By: morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D60787
llvm-svn: 359097
2019-04-24 22:20:49 +08:00
|
|
|
#include "mutex.h"
|
|
|
|
#include "stats.h"
|
[scudo][standalone] Get statistics in a char buffer
Summary:
Following up on D68471, this CL introduces some `getStats` APIs to
gather statistics in char buffers (`ScopedString` really) instead of
printing them out right away. Ultimately `printStats` will just
output the buffer, but that allows us to potentially do some work
on the intermediate buffer, and can be used for a `mallocz` type
of functionality. This allows us to pretty much get rid of all the
`Printf` calls around, but I am keeping the function in for
debugging purposes.
This changes the existing tests to use the new APIs when required.
I will add new tests as suggested in D68471 in another CL.
Reviewers: morehouse, hctim, vitalybuka, eugenis, cferris
Reviewed By: morehouse
Subscribers: delcypher, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D68653
llvm-svn: 374173
2019-10-09 23:09:28 +08:00
|
|
|
#include "string_utils.h"
|
[scudo][standalone] Introduce the Secondary allocator
Summary:
The Secondary allocator wraps the platform allocation primitives. It is
meant to be used for larger sizes that the Primary can't fullfill, as
it will be slower, and sizes are multiple of the system page size.
This also changes some of the existing code, notably the opaque
platform data being passed to the platform specific functions: we can
shave a couple of syscalls on Fuchsia by storing additional data (this
addresses a TODO).
Reviewers: eugenis, vitalybuka, hctim, morehouse
Reviewed By: morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D60787
llvm-svn: 359097
2019-04-24 22:20:49 +08:00
|
|
|
|
|
|
|
namespace scudo {
|
|
|
|
|
|
|
|
// This allocator wraps the platform allocation primitives, and as such is on
|
|
|
|
// the slower side and should preferably be used for larger sized allocations.
|
|
|
|
// Blocks allocated will be preceded and followed by a guard page, and hold
|
|
|
|
// their own header that is not checksummed: the guard pages and the Combined
|
|
|
|
// header should be enough for our purpose.
|
|
|
|
|
|
|
|
namespace LargeBlock {
|
|
|
|
|
|
|
|
struct Header {
|
|
|
|
LargeBlock::Header *Prev;
|
|
|
|
LargeBlock::Header *Next;
|
|
|
|
uptr BlockEnd;
|
|
|
|
uptr MapBase;
|
|
|
|
uptr MapSize;
|
|
|
|
MapPlatformData Data;
|
|
|
|
};
|
|
|
|
|
|
|
|
constexpr uptr getHeaderSize() {
|
|
|
|
return roundUpTo(sizeof(Header), 1U << SCUDO_MIN_ALIGNMENT_LOG);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Header *getHeader(uptr Ptr) {
|
|
|
|
return reinterpret_cast<Header *>(Ptr - getHeaderSize());
|
|
|
|
}
|
|
|
|
|
|
|
|
static Header *getHeader(const void *Ptr) {
|
|
|
|
return getHeader(reinterpret_cast<uptr>(Ptr));
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace LargeBlock
|
|
|
|
|
[scudo][standalone] Add a free list to the Secondary
Summary:
The secondary allocator is slow, because we map and unmap each block
on allocation and deallocation.
While I really like the security benefits of such a behavior, this
yields very disappointing performance numbers on Android for larger
allocation benchmarks.
So this change adds a free list to the secondary, that will hold
recently deallocated chunks, and (currently) release the extraneous
memory. This allows to save on some memory mapping operations on
allocation and deallocation. I do not think that this lowers the
security of the secondary, but can increase the memory footprint a
little bit (RSS & VA).
The maximum number of blocks the free list can hold is templatable,
`0U` meaning that we fallback to the old behavior. The higher that
number, the higher the extra memory footprint.
I added default configurations for all our platforms, but they are
likely to change in the near future based on needs and feedback.
Reviewers: hctim, morehouse, cferris, pcc, eugenis, vitalybuka
Subscribers: mgorny, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69570
2019-10-30 00:30:50 +08:00
|
|
|
template <uptr MaxFreeListSize = 32U> class MapAllocator {
|
[scudo][standalone] Introduce the Secondary allocator
Summary:
The Secondary allocator wraps the platform allocation primitives. It is
meant to be used for larger sizes that the Primary can't fullfill, as
it will be slower, and sizes are multiple of the system page size.
This also changes some of the existing code, notably the opaque
platform data being passed to the platform specific functions: we can
shave a couple of syscalls on Fuchsia by storing additional data (this
addresses a TODO).
Reviewers: eugenis, vitalybuka, hctim, morehouse
Reviewed By: morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D60787
llvm-svn: 359097
2019-04-24 22:20:49 +08:00
|
|
|
public:
|
[scudo][standalone] Make tests work on Fuchsia
Summary:
This CL makes unit tests compatible with Fuchsia's zxtest. This
required a few changes here and there, but also unearthed some
incompatibilities that had to be addressed.
A header is introduced to allow to account for the zxtest/gtest
differences, some `#if SCUDO_FUCHSIA` are used to disable incompatible
code (the 32-bit primary, or the exclusive TSD).
It also brought to my attention that I was using
`__scudo_default_options` in different tests, which ended up in a
single binary, and I am not sure how that ever worked. So move
this to the main cpp.
Additionally fully disable the secondary freelist on Fuchsia as we do
not track VMOs for secondary allocations, so no release possible.
With some modifications to Scudo's BUILD.gn in Fuchsia:
```
[==========] 79 tests from 23 test cases ran (10280 ms total).
[ PASSED ] 79 tests
```
Reviewers: mcgrathr, phosek, hctim, pcc, eugenis, cferris
Subscribers: srhines, jfb, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D70682
2019-11-26 02:28:57 +08:00
|
|
|
// Ensure the freelist is disabled on Fuchsia, since it doesn't support
|
|
|
|
// releasing Secondary blocks yet.
|
2019-11-28 01:35:47 +08:00
|
|
|
static_assert(!SCUDO_FUCHSIA || MaxFreeListSize == 0U, "");
|
[scudo][standalone] Make tests work on Fuchsia
Summary:
This CL makes unit tests compatible with Fuchsia's zxtest. This
required a few changes here and there, but also unearthed some
incompatibilities that had to be addressed.
A header is introduced to allow to account for the zxtest/gtest
differences, some `#if SCUDO_FUCHSIA` are used to disable incompatible
code (the 32-bit primary, or the exclusive TSD).
It also brought to my attention that I was using
`__scudo_default_options` in different tests, which ended up in a
single binary, and I am not sure how that ever worked. So move
this to the main cpp.
Additionally fully disable the secondary freelist on Fuchsia as we do
not track VMOs for secondary allocations, so no release possible.
With some modifications to Scudo's BUILD.gn in Fuchsia:
```
[==========] 79 tests from 23 test cases ran (10280 ms total).
[ PASSED ] 79 tests
```
Reviewers: mcgrathr, phosek, hctim, pcc, eugenis, cferris
Subscribers: srhines, jfb, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D70682
2019-11-26 02:28:57 +08:00
|
|
|
|
[scudo][standalone] Introduce the Secondary allocator
Summary:
The Secondary allocator wraps the platform allocation primitives. It is
meant to be used for larger sizes that the Primary can't fullfill, as
it will be slower, and sizes are multiple of the system page size.
This also changes some of the existing code, notably the opaque
platform data being passed to the platform specific functions: we can
shave a couple of syscalls on Fuchsia by storing additional data (this
addresses a TODO).
Reviewers: eugenis, vitalybuka, hctim, morehouse
Reviewed By: morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D60787
llvm-svn: 359097
2019-04-24 22:20:49 +08:00
|
|
|
void initLinkerInitialized(GlobalStats *S) {
|
|
|
|
Stats.initLinkerInitialized();
|
[scudo][standalone] Optimization pass
Summary:
This introduces a bunch of small optimizations with the purpose of
making the fastpath tighter:
- tag more conditions as `LIKELY`/`UNLIKELY`: as a rule of thumb we
consider that every operation related to the secondary is unlikely
- attempt to reduce the number of potentially extraneous instructions
- reorganize the `Chunk` header to not straddle a word boundary and
use more appropriate types
Note that some `LIKELY`/`UNLIKELY` impact might be less obvious as
they are in slow paths (for example in `secondary.cc`), but at this
point I am throwing a pretty wide net, and it's consistant and doesn't
hurt.
This was mosly done for the benfit of Android, but other platforms
benefit from it too. An aarch64 Android benchmark gives:
- before:
```
BM_youtube/min_time:15.000/repeats:4/manual_time_mean 445244 us 659385 us 4
BM_youtube/min_time:15.000/repeats:4/manual_time_median 445007 us 658970 us 4
BM_youtube/min_time:15.000/repeats:4/manual_time_stddev 885 us 1332 us 4
```
- after:
```
BM_youtube/min_time:15.000/repeats:4/manual_time_mean 415697 us 621925 us 4
BM_youtube/min_time:15.000/repeats:4/manual_time_median 415913 us 622061 us 4
BM_youtube/min_time:15.000/repeats:4/manual_time_stddev 990 us 1163 us 4
```
Additional since `-Werror=conversion` is enabled on some platforms we
are built on, enable it upstream to catch things early: a few sign
conversions had slept through and needed additional casting.
Reviewers: hctim, morehouse, eugenis, vitalybuka
Reviewed By: vitalybuka
Subscribers: srhines, mgorny, javed.absar, kristof.beyls, delcypher, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D64664
llvm-svn: 366918
2019-07-25 00:36:01 +08:00
|
|
|
if (LIKELY(S))
|
[scudo][standalone] Introduce the Secondary allocator
Summary:
The Secondary allocator wraps the platform allocation primitives. It is
meant to be used for larger sizes that the Primary can't fullfill, as
it will be slower, and sizes are multiple of the system page size.
This also changes some of the existing code, notably the opaque
platform data being passed to the platform specific functions: we can
shave a couple of syscalls on Fuchsia by storing additional data (this
addresses a TODO).
Reviewers: eugenis, vitalybuka, hctim, morehouse
Reviewed By: morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D60787
llvm-svn: 359097
2019-04-24 22:20:49 +08:00
|
|
|
S->link(&Stats);
|
|
|
|
}
|
|
|
|
void init(GlobalStats *S) {
|
|
|
|
memset(this, 0, sizeof(*this));
|
|
|
|
initLinkerInitialized(S);
|
|
|
|
}
|
|
|
|
|
[scudo][standalone] Fix Secondary bug w/ freelist
Summary:
cferris@ found an issue due to the new Secondary free list behavior
and unfortunately it's completely my fault. The issue is twofold:
- I lost track of the (major) fact that the Combined assumes that
all chunks returned by the Secondary are zero'd out apprioriately
when dealing with `ZeroContents`. With the introduction of the
freelist, it's no longer the case as there can be a small portion
of memory between the header and the next page boundary that is
left untouched (the rest is zero'd via release). So the next time
that block is returned, it's not fully zero'd out.
- There was no test that would exercise that behavior :(
There are several ways to fix this, the one I chose makes the most
sense to me: we pass `ZeroContents` to the Secondary's `allocate`
and it zero's out the block if requested and it's coming from the
freelist. The prevents an extraneous `memset` in case the block
comes from `map`. Another possbility could have been to `memset`
in `deallocate`, but it's probably overzealous as all secondary
blocks don't need to be zero'd out.
Add a test that would have found the issue prior to fix.
Reviewers: morehouse, hctim, cferris, pcc, eugenis, vitalybuka
Subscribers: #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69675
2019-11-01 01:31:49 +08:00
|
|
|
void *allocate(uptr Size, uptr AlignmentHint = 0, uptr *BlockEnd = nullptr,
|
|
|
|
bool ZeroContents = false);
|
[scudo][standalone] Introduce the Secondary allocator
Summary:
The Secondary allocator wraps the platform allocation primitives. It is
meant to be used for larger sizes that the Primary can't fullfill, as
it will be slower, and sizes are multiple of the system page size.
This also changes some of the existing code, notably the opaque
platform data being passed to the platform specific functions: we can
shave a couple of syscalls on Fuchsia by storing additional data (this
addresses a TODO).
Reviewers: eugenis, vitalybuka, hctim, morehouse
Reviewed By: morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D60787
llvm-svn: 359097
2019-04-24 22:20:49 +08:00
|
|
|
|
|
|
|
void deallocate(void *Ptr);
|
|
|
|
|
|
|
|
static uptr getBlockEnd(void *Ptr) {
|
|
|
|
return LargeBlock::getHeader(Ptr)->BlockEnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uptr getBlockSize(void *Ptr) {
|
|
|
|
return getBlockEnd(Ptr) - reinterpret_cast<uptr>(Ptr);
|
|
|
|
}
|
|
|
|
|
[scudo][standalone] Get statistics in a char buffer
Summary:
Following up on D68471, this CL introduces some `getStats` APIs to
gather statistics in char buffers (`ScopedString` really) instead of
printing them out right away. Ultimately `printStats` will just
output the buffer, but that allows us to potentially do some work
on the intermediate buffer, and can be used for a `mallocz` type
of functionality. This allows us to pretty much get rid of all the
`Printf` calls around, but I am keeping the function in for
debugging purposes.
This changes the existing tests to use the new APIs when required.
I will add new tests as suggested in D68471 in another CL.
Reviewers: morehouse, hctim, vitalybuka, eugenis, cferris
Reviewed By: morehouse
Subscribers: delcypher, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D68653
llvm-svn: 374173
2019-10-09 23:09:28 +08:00
|
|
|
void getStats(ScopedString *Str) const;
|
[scudo][standalone] Introduce the Secondary allocator
Summary:
The Secondary allocator wraps the platform allocation primitives. It is
meant to be used for larger sizes that the Primary can't fullfill, as
it will be slower, and sizes are multiple of the system page size.
This also changes some of the existing code, notably the opaque
platform data being passed to the platform specific functions: we can
shave a couple of syscalls on Fuchsia by storing additional data (this
addresses a TODO).
Reviewers: eugenis, vitalybuka, hctim, morehouse
Reviewed By: morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D60787
llvm-svn: 359097
2019-04-24 22:20:49 +08:00
|
|
|
|
|
|
|
void disable() { Mutex.lock(); }
|
|
|
|
|
|
|
|
void enable() { Mutex.unlock(); }
|
|
|
|
|
|
|
|
template <typename F> void iterateOverBlocks(F Callback) const {
|
[scudo][standalone] Consolidate lists
Summary:
This is a clean patch using the last diff of D69265, but using git
instead of svn, since svn went ro and arc was making my life harded
than it needed to be.
I was going to introduce a couple more lists and realized that our
lists are currently a bit all over the place. While we have a singly
linked list type relatively well defined, we are using doubly linked
lists defined on the fly for the stats and for the secondary blocks.
This CL adds a doubly linked list object, reorganizing the singly list
one to extract as much of the common code as possible. We use this
new type in the stats and the secondary. We also reorganize the list
tests to benefit from this consolidation.
There are a few side effect changes such as using for iterator loops
that are, in my opinion, cleaner in a couple of places.
Reviewers: hctim, morehouse, pcc, cferris
Reviewed By: hctim
Subscribers: jfb, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69516
2019-10-29 00:25:04 +08:00
|
|
|
for (const auto &H : InUseBlocks)
|
|
|
|
Callback(reinterpret_cast<uptr>(&H) + LargeBlock::getHeaderSize());
|
[scudo][standalone] Introduce the Secondary allocator
Summary:
The Secondary allocator wraps the platform allocation primitives. It is
meant to be used for larger sizes that the Primary can't fullfill, as
it will be slower, and sizes are multiple of the system page size.
This also changes some of the existing code, notably the opaque
platform data being passed to the platform specific functions: we can
shave a couple of syscalls on Fuchsia by storing additional data (this
addresses a TODO).
Reviewers: eugenis, vitalybuka, hctim, morehouse
Reviewed By: morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D60787
llvm-svn: 359097
2019-04-24 22:20:49 +08:00
|
|
|
}
|
|
|
|
|
[scudo][standalone] Add a free list to the Secondary
Summary:
The secondary allocator is slow, because we map and unmap each block
on allocation and deallocation.
While I really like the security benefits of such a behavior, this
yields very disappointing performance numbers on Android for larger
allocation benchmarks.
So this change adds a free list to the secondary, that will hold
recently deallocated chunks, and (currently) release the extraneous
memory. This allows to save on some memory mapping operations on
allocation and deallocation. I do not think that this lowers the
security of the secondary, but can increase the memory footprint a
little bit (RSS & VA).
The maximum number of blocks the free list can hold is templatable,
`0U` meaning that we fallback to the old behavior. The higher that
number, the higher the extra memory footprint.
I added default configurations for all our platforms, but they are
likely to change in the near future based on needs and feedback.
Reviewers: hctim, morehouse, cferris, pcc, eugenis, vitalybuka
Subscribers: mgorny, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69570
2019-10-30 00:30:50 +08:00
|
|
|
static uptr getMaxFreeListSize(void) { return MaxFreeListSize; }
|
|
|
|
|
[scudo][standalone] Introduce the Secondary allocator
Summary:
The Secondary allocator wraps the platform allocation primitives. It is
meant to be used for larger sizes that the Primary can't fullfill, as
it will be slower, and sizes are multiple of the system page size.
This also changes some of the existing code, notably the opaque
platform data being passed to the platform specific functions: we can
shave a couple of syscalls on Fuchsia by storing additional data (this
addresses a TODO).
Reviewers: eugenis, vitalybuka, hctim, morehouse
Reviewed By: morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D60787
llvm-svn: 359097
2019-04-24 22:20:49 +08:00
|
|
|
private:
|
[scudo][standalone] Merge Spin & Blocking mutex into a Hybrid one
Summary:
We ran into a problem on Fuchsia where yielding threads would never
be deboosted, ultimately resulting in several threads spinning on the
same TSD, and no possibility for another thread to be scheduled,
dead-locking the process.
While this was fixed in Zircon, this lead to discussions about if
spinning without a break condition was a good decision, and settled on
a new hybrid model that would spin for a while then block.
Currently we are using a number of iterations for spinning that is
mostly arbitrary (based on sanitizer_common values), but this can
be tuned in the future.
Since we are touching `common.h`, we also use this change as a vehicle
for an Android optimization (the page size is fixed in Bionic, so use
a fixed value too).
Reviewers: morehouse, hctim, eugenis, dvyukov, vitalybuka
Reviewed By: hctim
Subscribers: srhines, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D64358
llvm-svn: 365790
2019-07-11 23:32:26 +08:00
|
|
|
HybridMutex Mutex;
|
[scudo][standalone] Consolidate lists
Summary:
This is a clean patch using the last diff of D69265, but using git
instead of svn, since svn went ro and arc was making my life harded
than it needed to be.
I was going to introduce a couple more lists and realized that our
lists are currently a bit all over the place. While we have a singly
linked list type relatively well defined, we are using doubly linked
lists defined on the fly for the stats and for the secondary blocks.
This CL adds a doubly linked list object, reorganizing the singly list
one to extract as much of the common code as possible. We use this
new type in the stats and the secondary. We also reorganize the list
tests to benefit from this consolidation.
There are a few side effect changes such as using for iterator loops
that are, in my opinion, cleaner in a couple of places.
Reviewers: hctim, morehouse, pcc, cferris
Reviewed By: hctim
Subscribers: jfb, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69516
2019-10-29 00:25:04 +08:00
|
|
|
DoublyLinkedList<LargeBlock::Header> InUseBlocks;
|
[scudo][standalone] Add a free list to the Secondary
Summary:
The secondary allocator is slow, because we map and unmap each block
on allocation and deallocation.
While I really like the security benefits of such a behavior, this
yields very disappointing performance numbers on Android for larger
allocation benchmarks.
So this change adds a free list to the secondary, that will hold
recently deallocated chunks, and (currently) release the extraneous
memory. This allows to save on some memory mapping operations on
allocation and deallocation. I do not think that this lowers the
security of the secondary, but can increase the memory footprint a
little bit (RSS & VA).
The maximum number of blocks the free list can hold is templatable,
`0U` meaning that we fallback to the old behavior. The higher that
number, the higher the extra memory footprint.
I added default configurations for all our platforms, but they are
likely to change in the near future based on needs and feedback.
Reviewers: hctim, morehouse, cferris, pcc, eugenis, vitalybuka
Subscribers: mgorny, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69570
2019-10-30 00:30:50 +08:00
|
|
|
// The free list is sorted based on the committed size of blocks.
|
|
|
|
DoublyLinkedList<LargeBlock::Header> FreeBlocks;
|
[scudo][standalone] Introduce the Secondary allocator
Summary:
The Secondary allocator wraps the platform allocation primitives. It is
meant to be used for larger sizes that the Primary can't fullfill, as
it will be slower, and sizes are multiple of the system page size.
This also changes some of the existing code, notably the opaque
platform data being passed to the platform specific functions: we can
shave a couple of syscalls on Fuchsia by storing additional data (this
addresses a TODO).
Reviewers: eugenis, vitalybuka, hctim, morehouse
Reviewed By: morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D60787
llvm-svn: 359097
2019-04-24 22:20:49 +08:00
|
|
|
uptr AllocatedBytes;
|
|
|
|
uptr FreedBytes;
|
|
|
|
uptr LargestSize;
|
|
|
|
u32 NumberOfAllocs;
|
|
|
|
u32 NumberOfFrees;
|
|
|
|
LocalStats Stats;
|
|
|
|
};
|
|
|
|
|
[scudo][standalone] Add a free list to the Secondary
Summary:
The secondary allocator is slow, because we map and unmap each block
on allocation and deallocation.
While I really like the security benefits of such a behavior, this
yields very disappointing performance numbers on Android for larger
allocation benchmarks.
So this change adds a free list to the secondary, that will hold
recently deallocated chunks, and (currently) release the extraneous
memory. This allows to save on some memory mapping operations on
allocation and deallocation. I do not think that this lowers the
security of the secondary, but can increase the memory footprint a
little bit (RSS & VA).
The maximum number of blocks the free list can hold is templatable,
`0U` meaning that we fallback to the old behavior. The higher that
number, the higher the extra memory footprint.
I added default configurations for all our platforms, but they are
likely to change in the near future based on needs and feedback.
Reviewers: hctim, morehouse, cferris, pcc, eugenis, vitalybuka
Subscribers: mgorny, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69570
2019-10-30 00:30:50 +08:00
|
|
|
// As with the Primary, the size passed to this function includes any desired
|
|
|
|
// alignment, so that the frontend can align the user allocation. The hint
|
|
|
|
// parameter allows us to unmap spurious memory when dealing with larger
|
|
|
|
// (greater than a page) alignments on 32-bit platforms.
|
|
|
|
// Due to the sparsity of address space available on those platforms, requesting
|
|
|
|
// an allocation from the Secondary with a large alignment would end up wasting
|
|
|
|
// VA space (even though we are not committing the whole thing), hence the need
|
|
|
|
// to trim off some of the reserved space.
|
|
|
|
// For allocations requested with an alignment greater than or equal to a page,
|
|
|
|
// the committed memory will amount to something close to Size - AlignmentHint
|
|
|
|
// (pending rounding and headers).
|
|
|
|
template <uptr MaxFreeListSize>
|
|
|
|
void *MapAllocator<MaxFreeListSize>::allocate(uptr Size, uptr AlignmentHint,
|
[scudo][standalone] Fix Secondary bug w/ freelist
Summary:
cferris@ found an issue due to the new Secondary free list behavior
and unfortunately it's completely my fault. The issue is twofold:
- I lost track of the (major) fact that the Combined assumes that
all chunks returned by the Secondary are zero'd out apprioriately
when dealing with `ZeroContents`. With the introduction of the
freelist, it's no longer the case as there can be a small portion
of memory between the header and the next page boundary that is
left untouched (the rest is zero'd via release). So the next time
that block is returned, it's not fully zero'd out.
- There was no test that would exercise that behavior :(
There are several ways to fix this, the one I chose makes the most
sense to me: we pass `ZeroContents` to the Secondary's `allocate`
and it zero's out the block if requested and it's coming from the
freelist. The prevents an extraneous `memset` in case the block
comes from `map`. Another possbility could have been to `memset`
in `deallocate`, but it's probably overzealous as all secondary
blocks don't need to be zero'd out.
Add a test that would have found the issue prior to fix.
Reviewers: morehouse, hctim, cferris, pcc, eugenis, vitalybuka
Subscribers: #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69675
2019-11-01 01:31:49 +08:00
|
|
|
uptr *BlockEnd,
|
|
|
|
bool ZeroContents) {
|
2019-11-15 06:33:23 +08:00
|
|
|
DCHECK_GE(Size, AlignmentHint);
|
[scudo][standalone] Add a free list to the Secondary
Summary:
The secondary allocator is slow, because we map and unmap each block
on allocation and deallocation.
While I really like the security benefits of such a behavior, this
yields very disappointing performance numbers on Android for larger
allocation benchmarks.
So this change adds a free list to the secondary, that will hold
recently deallocated chunks, and (currently) release the extraneous
memory. This allows to save on some memory mapping operations on
allocation and deallocation. I do not think that this lowers the
security of the secondary, but can increase the memory footprint a
little bit (RSS & VA).
The maximum number of blocks the free list can hold is templatable,
`0U` meaning that we fallback to the old behavior. The higher that
number, the higher the extra memory footprint.
I added default configurations for all our platforms, but they are
likely to change in the near future based on needs and feedback.
Reviewers: hctim, morehouse, cferris, pcc, eugenis, vitalybuka
Subscribers: mgorny, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69570
2019-10-30 00:30:50 +08:00
|
|
|
const uptr PageSize = getPageSizeCached();
|
|
|
|
const uptr RoundedSize =
|
|
|
|
roundUpTo(Size + LargeBlock::getHeaderSize(), PageSize);
|
|
|
|
|
|
|
|
if (MaxFreeListSize && AlignmentHint < PageSize) {
|
|
|
|
ScopedLock L(Mutex);
|
|
|
|
for (auto &H : FreeBlocks) {
|
|
|
|
const uptr FreeBlockSize = H.BlockEnd - reinterpret_cast<uptr>(&H);
|
|
|
|
if (FreeBlockSize < RoundedSize)
|
|
|
|
continue;
|
|
|
|
// Candidate free block should only be at most 4 pages larger.
|
|
|
|
if (FreeBlockSize > RoundedSize + 4 * PageSize)
|
|
|
|
break;
|
|
|
|
FreeBlocks.remove(&H);
|
|
|
|
InUseBlocks.push_back(&H);
|
|
|
|
AllocatedBytes += FreeBlockSize;
|
|
|
|
NumberOfAllocs++;
|
|
|
|
Stats.add(StatAllocated, FreeBlockSize);
|
|
|
|
if (BlockEnd)
|
|
|
|
*BlockEnd = H.BlockEnd;
|
[scudo][standalone] Fix Secondary bug w/ freelist
Summary:
cferris@ found an issue due to the new Secondary free list behavior
and unfortunately it's completely my fault. The issue is twofold:
- I lost track of the (major) fact that the Combined assumes that
all chunks returned by the Secondary are zero'd out apprioriately
when dealing with `ZeroContents`. With the introduction of the
freelist, it's no longer the case as there can be a small portion
of memory between the header and the next page boundary that is
left untouched (the rest is zero'd via release). So the next time
that block is returned, it's not fully zero'd out.
- There was no test that would exercise that behavior :(
There are several ways to fix this, the one I chose makes the most
sense to me: we pass `ZeroContents` to the Secondary's `allocate`
and it zero's out the block if requested and it's coming from the
freelist. The prevents an extraneous `memset` in case the block
comes from `map`. Another possbility could have been to `memset`
in `deallocate`, but it's probably overzealous as all secondary
blocks don't need to be zero'd out.
Add a test that would have found the issue prior to fix.
Reviewers: morehouse, hctim, cferris, pcc, eugenis, vitalybuka
Subscribers: #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69675
2019-11-01 01:31:49 +08:00
|
|
|
void *Ptr = reinterpret_cast<void *>(reinterpret_cast<uptr>(&H) +
|
|
|
|
LargeBlock::getHeaderSize());
|
|
|
|
if (ZeroContents)
|
|
|
|
memset(Ptr, 0, H.BlockEnd - reinterpret_cast<uptr>(Ptr));
|
|
|
|
return Ptr;
|
[scudo][standalone] Add a free list to the Secondary
Summary:
The secondary allocator is slow, because we map and unmap each block
on allocation and deallocation.
While I really like the security benefits of such a behavior, this
yields very disappointing performance numbers on Android for larger
allocation benchmarks.
So this change adds a free list to the secondary, that will hold
recently deallocated chunks, and (currently) release the extraneous
memory. This allows to save on some memory mapping operations on
allocation and deallocation. I do not think that this lowers the
security of the secondary, but can increase the memory footprint a
little bit (RSS & VA).
The maximum number of blocks the free list can hold is templatable,
`0U` meaning that we fallback to the old behavior. The higher that
number, the higher the extra memory footprint.
I added default configurations for all our platforms, but they are
likely to change in the near future based on needs and feedback.
Reviewers: hctim, morehouse, cferris, pcc, eugenis, vitalybuka
Subscribers: mgorny, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69570
2019-10-30 00:30:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MapPlatformData Data = {};
|
|
|
|
const uptr MapSize = RoundedSize + 2 * PageSize;
|
|
|
|
uptr MapBase =
|
|
|
|
reinterpret_cast<uptr>(map(nullptr, MapSize, "scudo:secondary",
|
|
|
|
MAP_NOACCESS | MAP_ALLOWNOMEM, &Data));
|
|
|
|
if (UNLIKELY(!MapBase))
|
|
|
|
return nullptr;
|
|
|
|
uptr CommitBase = MapBase + PageSize;
|
|
|
|
uptr MapEnd = MapBase + MapSize;
|
|
|
|
|
|
|
|
// In the unlikely event of alignments larger than a page, adjust the amount
|
|
|
|
// of memory we want to commit, and trim the extra memory.
|
|
|
|
if (UNLIKELY(AlignmentHint >= PageSize)) {
|
|
|
|
// For alignments greater than or equal to a page, the user pointer (eg: the
|
|
|
|
// pointer that is returned by the C or C++ allocation APIs) ends up on a
|
|
|
|
// page boundary , and our headers will live in the preceding page.
|
|
|
|
CommitBase = roundUpTo(MapBase + PageSize + 1, AlignmentHint) - PageSize;
|
|
|
|
const uptr NewMapBase = CommitBase - PageSize;
|
|
|
|
DCHECK_GE(NewMapBase, MapBase);
|
|
|
|
// We only trim the extra memory on 32-bit platforms: 64-bit platforms
|
|
|
|
// are less constrained memory wise, and that saves us two syscalls.
|
|
|
|
if (SCUDO_WORDSIZE == 32U && NewMapBase != MapBase) {
|
|
|
|
unmap(reinterpret_cast<void *>(MapBase), NewMapBase - MapBase, 0, &Data);
|
|
|
|
MapBase = NewMapBase;
|
|
|
|
}
|
|
|
|
const uptr NewMapEnd = CommitBase + PageSize +
|
|
|
|
roundUpTo((Size - AlignmentHint), PageSize) +
|
|
|
|
PageSize;
|
|
|
|
DCHECK_LE(NewMapEnd, MapEnd);
|
|
|
|
if (SCUDO_WORDSIZE == 32U && NewMapEnd != MapEnd) {
|
|
|
|
unmap(reinterpret_cast<void *>(NewMapEnd), MapEnd - NewMapEnd, 0, &Data);
|
|
|
|
MapEnd = NewMapEnd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const uptr CommitSize = MapEnd - PageSize - CommitBase;
|
|
|
|
const uptr Ptr =
|
|
|
|
reinterpret_cast<uptr>(map(reinterpret_cast<void *>(CommitBase),
|
|
|
|
CommitSize, "scudo:secondary", 0, &Data));
|
|
|
|
LargeBlock::Header *H = reinterpret_cast<LargeBlock::Header *>(Ptr);
|
|
|
|
H->MapBase = MapBase;
|
|
|
|
H->MapSize = MapEnd - MapBase;
|
|
|
|
H->BlockEnd = CommitBase + CommitSize;
|
|
|
|
H->Data = Data;
|
|
|
|
{
|
|
|
|
ScopedLock L(Mutex);
|
|
|
|
InUseBlocks.push_back(H);
|
|
|
|
AllocatedBytes += CommitSize;
|
|
|
|
if (LargestSize < CommitSize)
|
|
|
|
LargestSize = CommitSize;
|
|
|
|
NumberOfAllocs++;
|
|
|
|
Stats.add(StatAllocated, CommitSize);
|
|
|
|
Stats.add(StatMapped, H->MapSize);
|
|
|
|
}
|
|
|
|
if (BlockEnd)
|
|
|
|
*BlockEnd = CommitBase + CommitSize;
|
|
|
|
return reinterpret_cast<void *>(Ptr + LargeBlock::getHeaderSize());
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uptr MaxFreeListSize>
|
|
|
|
void MapAllocator<MaxFreeListSize>::deallocate(void *Ptr) {
|
|
|
|
LargeBlock::Header *H = LargeBlock::getHeader(Ptr);
|
[scudo][standalone] Make tests work on Fuchsia
Summary:
This CL makes unit tests compatible with Fuchsia's zxtest. This
required a few changes here and there, but also unearthed some
incompatibilities that had to be addressed.
A header is introduced to allow to account for the zxtest/gtest
differences, some `#if SCUDO_FUCHSIA` are used to disable incompatible
code (the 32-bit primary, or the exclusive TSD).
It also brought to my attention that I was using
`__scudo_default_options` in different tests, which ended up in a
single binary, and I am not sure how that ever worked. So move
this to the main cpp.
Additionally fully disable the secondary freelist on Fuchsia as we do
not track VMOs for secondary allocations, so no release possible.
With some modifications to Scudo's BUILD.gn in Fuchsia:
```
[==========] 79 tests from 23 test cases ran (10280 ms total).
[ PASSED ] 79 tests
```
Reviewers: mcgrathr, phosek, hctim, pcc, eugenis, cferris
Subscribers: srhines, jfb, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D70682
2019-11-26 02:28:57 +08:00
|
|
|
const uptr Block = reinterpret_cast<uptr>(H);
|
[scudo][standalone] Add a free list to the Secondary
Summary:
The secondary allocator is slow, because we map and unmap each block
on allocation and deallocation.
While I really like the security benefits of such a behavior, this
yields very disappointing performance numbers on Android for larger
allocation benchmarks.
So this change adds a free list to the secondary, that will hold
recently deallocated chunks, and (currently) release the extraneous
memory. This allows to save on some memory mapping operations on
allocation and deallocation. I do not think that this lowers the
security of the secondary, but can increase the memory footprint a
little bit (RSS & VA).
The maximum number of blocks the free list can hold is templatable,
`0U` meaning that we fallback to the old behavior. The higher that
number, the higher the extra memory footprint.
I added default configurations for all our platforms, but they are
likely to change in the near future based on needs and feedback.
Reviewers: hctim, morehouse, cferris, pcc, eugenis, vitalybuka
Subscribers: mgorny, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69570
2019-10-30 00:30:50 +08:00
|
|
|
{
|
|
|
|
ScopedLock L(Mutex);
|
|
|
|
InUseBlocks.remove(H);
|
[scudo][standalone] Make tests work on Fuchsia
Summary:
This CL makes unit tests compatible with Fuchsia's zxtest. This
required a few changes here and there, but also unearthed some
incompatibilities that had to be addressed.
A header is introduced to allow to account for the zxtest/gtest
differences, some `#if SCUDO_FUCHSIA` are used to disable incompatible
code (the 32-bit primary, or the exclusive TSD).
It also brought to my attention that I was using
`__scudo_default_options` in different tests, which ended up in a
single binary, and I am not sure how that ever worked. So move
this to the main cpp.
Additionally fully disable the secondary freelist on Fuchsia as we do
not track VMOs for secondary allocations, so no release possible.
With some modifications to Scudo's BUILD.gn in Fuchsia:
```
[==========] 79 tests from 23 test cases ran (10280 ms total).
[ PASSED ] 79 tests
```
Reviewers: mcgrathr, phosek, hctim, pcc, eugenis, cferris
Subscribers: srhines, jfb, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D70682
2019-11-26 02:28:57 +08:00
|
|
|
const uptr CommitSize = H->BlockEnd - Block;
|
[scudo][standalone] Add a free list to the Secondary
Summary:
The secondary allocator is slow, because we map and unmap each block
on allocation and deallocation.
While I really like the security benefits of such a behavior, this
yields very disappointing performance numbers on Android for larger
allocation benchmarks.
So this change adds a free list to the secondary, that will hold
recently deallocated chunks, and (currently) release the extraneous
memory. This allows to save on some memory mapping operations on
allocation and deallocation. I do not think that this lowers the
security of the secondary, but can increase the memory footprint a
little bit (RSS & VA).
The maximum number of blocks the free list can hold is templatable,
`0U` meaning that we fallback to the old behavior. The higher that
number, the higher the extra memory footprint.
I added default configurations for all our platforms, but they are
likely to change in the near future based on needs and feedback.
Reviewers: hctim, morehouse, cferris, pcc, eugenis, vitalybuka
Subscribers: mgorny, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69570
2019-10-30 00:30:50 +08:00
|
|
|
FreedBytes += CommitSize;
|
|
|
|
NumberOfFrees++;
|
|
|
|
Stats.sub(StatAllocated, CommitSize);
|
|
|
|
if (MaxFreeListSize && FreeBlocks.size() < MaxFreeListSize) {
|
|
|
|
bool Inserted = false;
|
|
|
|
for (auto &F : FreeBlocks) {
|
|
|
|
const uptr FreeBlockSize = F.BlockEnd - reinterpret_cast<uptr>(&F);
|
|
|
|
if (FreeBlockSize >= CommitSize) {
|
|
|
|
FreeBlocks.insert(H, &F);
|
|
|
|
Inserted = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!Inserted)
|
|
|
|
FreeBlocks.push_back(H);
|
|
|
|
const uptr RoundedAllocationStart =
|
[scudo][standalone] Make tests work on Fuchsia
Summary:
This CL makes unit tests compatible with Fuchsia's zxtest. This
required a few changes here and there, but also unearthed some
incompatibilities that had to be addressed.
A header is introduced to allow to account for the zxtest/gtest
differences, some `#if SCUDO_FUCHSIA` are used to disable incompatible
code (the 32-bit primary, or the exclusive TSD).
It also brought to my attention that I was using
`__scudo_default_options` in different tests, which ended up in a
single binary, and I am not sure how that ever worked. So move
this to the main cpp.
Additionally fully disable the secondary freelist on Fuchsia as we do
not track VMOs for secondary allocations, so no release possible.
With some modifications to Scudo's BUILD.gn in Fuchsia:
```
[==========] 79 tests from 23 test cases ran (10280 ms total).
[ PASSED ] 79 tests
```
Reviewers: mcgrathr, phosek, hctim, pcc, eugenis, cferris
Subscribers: srhines, jfb, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D70682
2019-11-26 02:28:57 +08:00
|
|
|
roundUpTo(Block + LargeBlock::getHeaderSize(), getPageSizeCached());
|
[scudo][standalone] Add a free list to the Secondary
Summary:
The secondary allocator is slow, because we map and unmap each block
on allocation and deallocation.
While I really like the security benefits of such a behavior, this
yields very disappointing performance numbers on Android for larger
allocation benchmarks.
So this change adds a free list to the secondary, that will hold
recently deallocated chunks, and (currently) release the extraneous
memory. This allows to save on some memory mapping operations on
allocation and deallocation. I do not think that this lowers the
security of the secondary, but can increase the memory footprint a
little bit (RSS & VA).
The maximum number of blocks the free list can hold is templatable,
`0U` meaning that we fallback to the old behavior. The higher that
number, the higher the extra memory footprint.
I added default configurations for all our platforms, but they are
likely to change in the near future based on needs and feedback.
Reviewers: hctim, morehouse, cferris, pcc, eugenis, vitalybuka
Subscribers: mgorny, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69570
2019-10-30 00:30:50 +08:00
|
|
|
MapPlatformData Data = H->Data;
|
|
|
|
// TODO(kostyak): use release_to_os_interval_ms
|
[scudo][standalone] Make tests work on Fuchsia
Summary:
This CL makes unit tests compatible with Fuchsia's zxtest. This
required a few changes here and there, but also unearthed some
incompatibilities that had to be addressed.
A header is introduced to allow to account for the zxtest/gtest
differences, some `#if SCUDO_FUCHSIA` are used to disable incompatible
code (the 32-bit primary, or the exclusive TSD).
It also brought to my attention that I was using
`__scudo_default_options` in different tests, which ended up in a
single binary, and I am not sure how that ever worked. So move
this to the main cpp.
Additionally fully disable the secondary freelist on Fuchsia as we do
not track VMOs for secondary allocations, so no release possible.
With some modifications to Scudo's BUILD.gn in Fuchsia:
```
[==========] 79 tests from 23 test cases ran (10280 ms total).
[ PASSED ] 79 tests
```
Reviewers: mcgrathr, phosek, hctim, pcc, eugenis, cferris
Subscribers: srhines, jfb, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D70682
2019-11-26 02:28:57 +08:00
|
|
|
releasePagesToOS(Block, RoundedAllocationStart - Block,
|
[scudo][standalone] Add a free list to the Secondary
Summary:
The secondary allocator is slow, because we map and unmap each block
on allocation and deallocation.
While I really like the security benefits of such a behavior, this
yields very disappointing performance numbers on Android for larger
allocation benchmarks.
So this change adds a free list to the secondary, that will hold
recently deallocated chunks, and (currently) release the extraneous
memory. This allows to save on some memory mapping operations on
allocation and deallocation. I do not think that this lowers the
security of the secondary, but can increase the memory footprint a
little bit (RSS & VA).
The maximum number of blocks the free list can hold is templatable,
`0U` meaning that we fallback to the old behavior. The higher that
number, the higher the extra memory footprint.
I added default configurations for all our platforms, but they are
likely to change in the near future based on needs and feedback.
Reviewers: hctim, morehouse, cferris, pcc, eugenis, vitalybuka
Subscribers: mgorny, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69570
2019-10-30 00:30:50 +08:00
|
|
|
H->BlockEnd - RoundedAllocationStart, &Data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Stats.sub(StatMapped, H->MapSize);
|
|
|
|
}
|
|
|
|
void *Addr = reinterpret_cast<void *>(H->MapBase);
|
|
|
|
const uptr Size = H->MapSize;
|
|
|
|
MapPlatformData Data = H->Data;
|
|
|
|
unmap(Addr, Size, UNMAP_ALL, &Data);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uptr MaxFreeListSize>
|
|
|
|
void MapAllocator<MaxFreeListSize>::getStats(ScopedString *Str) const {
|
|
|
|
Str->append(
|
|
|
|
"Stats: MapAllocator: allocated %zu times (%zuK), freed %zu times "
|
|
|
|
"(%zuK), remains %zu (%zuK) max %zuM\n",
|
|
|
|
NumberOfAllocs, AllocatedBytes >> 10, NumberOfFrees, FreedBytes >> 10,
|
|
|
|
NumberOfAllocs - NumberOfFrees, (AllocatedBytes - FreedBytes) >> 10,
|
|
|
|
LargestSize >> 20);
|
|
|
|
}
|
|
|
|
|
[scudo][standalone] Introduce the Secondary allocator
Summary:
The Secondary allocator wraps the platform allocation primitives. It is
meant to be used for larger sizes that the Primary can't fullfill, as
it will be slower, and sizes are multiple of the system page size.
This also changes some of the existing code, notably the opaque
platform data being passed to the platform specific functions: we can
shave a couple of syscalls on Fuchsia by storing additional data (this
addresses a TODO).
Reviewers: eugenis, vitalybuka, hctim, morehouse
Reviewed By: morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D60787
llvm-svn: 359097
2019-04-24 22:20:49 +08:00
|
|
|
} // namespace scudo
|
|
|
|
|
|
|
|
#endif // SCUDO_SECONDARY_H_
|