Skip to content
  • primiano's avatar
    Allocator shim skeleton + Linux impl behind a build flag · 4e68ed2d
    primiano authored
    TL;DR
    -----
    This CL introduces the skeleton for the unified allocator shim and
    an actual working implementation for Linux.
    The Linux implementation is really just taking the headers that today
    define the malloc symbols in tcmalloc and copying them to base.
    All the changes introduced are conditioned behind the build-time flag
    use_experimental_allocator_shim, which is disabled by default.
    
    Background Context
    ------------------
    There are two reasons why we want to intercept allocations in Chrome:
    1) To enforce some security properties (suicide on malloc failure via
       std::new_handler, preventing allocations > 2GB which can trigger
       signed vs. unsigned bugs in third_party libraries).
    2) For diagnostic purposes (heap profiling).
    
    Today (before this CL) allocation calls are already intercepted in
    most Chrome platforms, but that happens in a disorganized and
    inconsistent fashion. More in details:
    On Linux: TCMalloc redefines the malloc()/new() symbols and we added
      code to the internal fork of tcmalloc to achieve 1).
    On Mac: we inject our hooks in the default malloc zone in
      EnableTerminationOnOutOfMemory() (memory_mac.mm)
    On Windows: we strip the malloc symbols out of libcmt and re-define
      them in allocator_shim_win.cc
    On Android: we don't have 1)
    
    The purpose of this work is to refactor and uniform this.
    The goal is to have all the OS call into a single module (herein
    allocator_shim.h) which performs 1) in base (as opposite to forking
    allocator-specific code) and which offers a uniform interface for 2).
    
    Why is this good?
    -----------------
    - Makes the allocator code more readable.
    - Allows to unfork code from tcmalloc.
    - Allows to design a more maintainable heap profiler, which shares
      the same code paths of the security enforcement layer.
    
    Notes about execution
    ---------------------
    Essentially on each platform we need to do three things:
     - Dismantle the code that defines the malloc()/new symbols.
     - Let the malloc()/new symbols route through the shim.
     - Have the shim ultimately invoke the actual allocator (tcmalloc,
       winheap, system allocator) as defined by the build config.
    This clearly cannot happen atomically in one CL.
    The plan, therefore, is to make the above happen behind a build-time
    flag (use_experimental_allocator_shim), so the shim can be easily
    tested / rolled-back in case of failures, and ultimately drop the
    build-time flag (and remove the dead cde) once everything works.
    This also will make dealing with reverts very manageable.
    
    Therefore this CL (and likely all the future ones) is meant to be
    a no-op until use_experimental_allocator_shim==true.
    
    Design doc: bit.ly/allocator-shim
    
    BUG=550886
    TEST=build with use_experimental_allocator_shim=true, base_unittests --gtest_filter=AllocatorShimTest.*
    
    Review URL: https://codereview.chromium.org/1675143004
    
    Cr-Commit-Position: refs/heads/master@{#380196}
    4e68ed2d