1This document describes how malloc / new calls are routed in the various Chrome 2platforms. 3 4Bear in mind that the chromium codebase does not always just use `malloc()`. 5Some examples: 6 - Large parts of the renderer (Blink) use two home-brewed allocators, 7 PartitionAlloc and BlinkGC (Oilpan). 8 - Some subsystems, such as the V8 JavaScript engine, handle memory management 9 autonomously. 10 - Various parts of the codebase use abstractions such as `SharedMemory` or 11 `DiscardableMemory` which, similarly to the above, have their own page-level 12 memory management. 13 14Background 15---------- 16The `allocator` target defines at compile-time the platform-specific choice of 17the allocator and extra-hooks which services calls to malloc/new. The relevant 18build-time flags involved are `use_allocator_shim` and 19`use_partition_alloc_as_malloc`. 20 21By default, these are true on all platforms except iOS (not yet supported) and 22NaCl (no plan to support). 23Furthermore, when building with a sanitizer (e.g. `asan`, `msan`, ...) both the 24allocator and the shim layer are disabled. 25 26 27Layering and build deps 28----------------------- 29The `allocator` target provides the linker flags required for the Windows shim 30layer. The `base` target is (almost) the only one depending on `allocator`. No 31other targets should depend on it, with the exception of the very few 32executables / dynamic libraries that don't depend, either directly or 33indirectly, on `base` within the scope of a linker unit. 34 35More importantly, **no other place outside of `/base` should depend on the 36specific allocator**. 37If such a functional dependency is required that should be achieved using 38abstractions in `base` (see `/base/allocator/allocator_extension.h` and 39`/base/memory/`) 40 41**Why `base` depends on `allocator`?** 42Because it needs to provide services that depend on the actual allocator 43implementation. In the past `base` used to pretend to be allocator-agnostic 44and get the dependencies injected by other layers. This ended up being an 45inconsistent mess. 46See the [allocator cleanup doc][url-allocator-cleanup] for more context. 47 48Linker unit targets (executables and shared libraries) that depend in some way 49on `base` (most of the targets in the codebase) automatically get the correct 50set of linker flags to pull in the Windows shim-layer (if needed). 51 52 53Source code 54----------- 55This directory contains just the allocator (i.e. shim) layer that switches 56between the different underlying memory allocation implementations. 57 58 59Unified allocator shim 60---------------------- 61On most platforms, Chrome overrides the malloc / operator new symbols (and 62corresponding free / delete and other variants). This is to enforce security 63checks and lately to enable the 64[memory-infra heap profiler][url-memory-infra-heap-profiler]. 65Historically each platform had its special logic for defining the allocator 66symbols in different places of the codebase. The unified allocator shim is 67a project aimed to unify the symbol definition and allocator routing logic in 68a central place. 69 70 - Full documentation: [Allocator shim design doc][url-allocator-shim]. 71 - Current state: Available and enabled by default on Android, CrOS, Linux, 72 Mac OS and Windows. 73 - Tracking bug: [crbug.com/550886](https://crbug.com/550886). 74 - Build-time flag: `use_allocator_shim`. 75 76**Overview of the unified allocator shim** 77The allocator shim consists of three stages: 78``` 79+-------------------------+ +-----------------------+ +----------------+ 80| malloc & friends | -> | shim layer | -> | Routing to | 81| symbols definition | | implementation | | allocator | 82+-------------------------+ +-----------------------+ +----------------+ 83| - libc symbols (malloc, | | - Security checks | | - glibc | 84| calloc, free, ...) | | - Chain of dispatchers| | - Android | 85| - C++ symbols (operator | | that can intercept | | bionic | 86| new, delete, ...) | | and override | | - WinHeap | 87| - glibc weak symbols | | allocations | | - Partition | 88| (__libc_malloc, ...) | +-----------------------+ | Alloc | 89+-------------------------+ +----------------+ 90``` 91 92**1. malloc symbols definition** 93This stage takes care of overriding the symbols `malloc`, `free`, 94`operator new`, `operator delete` and friends and routing those calls inside the 95allocator shim (next point). 96This is taken care of by the headers in `allocator_shim_override_*`. 97 98*On Windows*: Windows' UCRT (Universal C Runtime) exports weak symbols, that we 99can override in `allocator_shim_override_ucrt_symbols_win.h`. 100 101*On Linux/CrOS*: the allocator symbols are defined as exported global symbols 102in `allocator_shim_override_libc_symbols.h` (for `malloc`, `free` and friends) 103and in `allocator_shim_override_cpp_symbols.h` (for `operator new`, 104`operator delete` and friends). 105This enables proper interposition of malloc symbols referenced by the main 106executable and any third party libraries. Symbol resolution on Linux is a breadth first search that starts from the root link unit, that is the executable 107(see EXECUTABLE AND LINKABLE FORMAT (ELF) - Portable Formats Specification). 108The Linux/CrOS shim was introduced by 109[crrev.com/1675143004](https://crrev.com/1675143004). 110 111*On Android*: load-time symbol interposition (unlike the Linux/CrOS case) is not 112possible. This is because Android processes are `fork()`-ed from the Android 113zygote, which pre-loads libc.so and only later native code gets loaded via 114`dlopen()` (symbols from `dlopen()`-ed libraries get a different resolution 115scope). 116In this case, the approach instead of wrapping symbol resolution at link time 117(i.e. during the build), via the `--Wl,-wrap,malloc` linker flag. 118The use of this wrapping flag causes: 119 - All references to allocator symbols in the Chrome codebase to be rewritten as 120 references to `__wrap_malloc` and friends. The `__wrap_malloc` symbols are 121 defined in the `allocator_shim_override_linker_wrapped_symbols.h` and 122 route allocator calls inside the shim layer. 123 - The reference to the original `malloc` symbols (which typically is defined by 124 the system's libc.so) are accessible via the special `__real_malloc` and 125 friends symbols (which will be relocated, at load time, against `malloc`). 126 127In summary, this approach is transparent to the dynamic loader, which still sees 128undefined symbol references to malloc symbols. 129These symbols will be resolved against libc.so as usual. 130More details in [crrev.com/1719433002](https://crrev.com/1719433002). 131 132**2. Shim layer implementation** 133This stage contains the actual shim implementation. This consists of: 134- A singly linked list of dispatchers (structs with function pointers to `malloc`-like functions). Dispatchers can be dynamically inserted at runtime 135(using the `InsertAllocatorDispatch` API). They can intercept and override 136allocator calls. 137- The security checks (suicide on malloc-failure via `std::new_handler`, etc). 138This happens inside `allocator_shim.cc` 139 140**3. Final allocator routing** 141The final element of the aforementioned dispatcher chain is statically defined 142at build time and ultimately routes the allocator calls to the actual allocator 143(as described in the *Background* section above). This is taken care of by the 144headers in `allocator_shim_default_dispatch_to_*` files. 145 146 147Related links 148------------- 149- [Unified allocator shim doc - Feb 2016][url-allocator-shim] 150- [Allocator cleanup doc - Jan 2016][url-allocator-cleanup] 151- [Proposal to use PartitionAlloc as default allocator](https://crbug.com/339604) 152- [Memory-Infra: Tools to profile memory usage in Chrome](/docs/memory-infra/README.md) 153 154[url-allocator-cleanup]: https://docs.google.com/document/d/1V77Kgp_4tfaaWPEZVxNevoD02wXiatnAv7Ssgr0hmjg/edit?usp=sharing 155[url-memory-infra-heap-profiler]: /docs/memory-infra/heap_profiler.md 156[url-allocator-shim]: https://docs.google.com/document/d/1yKlO1AO4XjpDad9rjcBOI15EKdAGsuGO_IeZy0g0kxo/edit?usp=sharing 157