tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ElfLoader.cpp (40564B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include <cstring>
      6 #include <cstdlib>
      7 #include <cstdio>
      8 #include <dlfcn.h>
      9 #include <link.h>
     10 #include <optional>
     11 #include <unistd.h>
     12 #include <errno.h>
     13 #include <algorithm>
     14 #include <fcntl.h>
     15 #include "ElfLoader.h"
     16 #include "BaseElf.h"
     17 #include "CustomElf.h"
     18 #include "Mappable.h"
     19 #include "Logging.h"
     20 #include "Utils.h"
     21 #include <inttypes.h>
     22 #include "mozilla/ScopeExit.h"
     23 
     24 // From Utils.h
     25 mozilla::Atomic<size_t, mozilla::ReleaseAcquire> gPageSize;
     26 
     27 #if defined(ANDROID)
     28 #  include <sys/syscall.h>
     29 #  include <sys/system_properties.h>
     30 #  include <math.h>
     31 
     32 #  include <android/api-level.h>
     33 
     34 /**
     35 * Return the current Android version, or 0 on failure.
     36 */
     37 static int GetAndroidSDKVersion() {
     38  static int version = 0;
     39  if (version) {
     40    return version;
     41  }
     42 
     43  char version_string[PROP_VALUE_MAX] = {'\0'};
     44  int len = __system_property_get("ro.build.version.sdk", version_string);
     45  if (len) {
     46    version = static_cast<int>(strtol(version_string, nullptr, 10));
     47  }
     48  return version;
     49 }
     50 
     51 #endif /* ANDROID */
     52 
     53 #ifdef __ARM_EABI__
     54 extern "C" MOZ_EXPORT const void* __gnu_Unwind_Find_exidx(void* pc, int* pcount)
     55    __attribute__((weak));
     56 #endif
     57 
     58 /* Pointer to the PT_DYNAMIC section of the executable or library
     59 * containing this code. */
     60 extern "C" Elf::Dyn _DYNAMIC[];
     61 
     62 /**
     63 * dlfcn.h replacements functions
     64 */
     65 
     66 void* __wrap_dlopen(const char* path, int flags) {
     67 #if defined(ANDROID)
     68  if (GetAndroidSDKVersion() >= 23) {
     69    return dlopen(path, flags);
     70  }
     71 #endif
     72 
     73  RefPtr<LibHandle> handle = ElfLoader::Singleton.Load(path, flags);
     74  if (handle) handle->AddDirectRef();
     75  return handle;
     76 }
     77 
     78 const char* __wrap_dlerror(void) {
     79 #if defined(ANDROID)
     80  if (GetAndroidSDKVersion() >= 23) {
     81    return dlerror();
     82  }
     83 #endif
     84 
     85  const char* error = ElfLoader::Singleton.lastError.exchange(nullptr);
     86  if (error) {
     87    // Return a custom error if available.
     88    return error;
     89  }
     90  // Or fallback to the system error.
     91  return dlerror();
     92 }
     93 
     94 void* __wrap_dlsym(void* handle, const char* symbol) {
     95 #if defined(ANDROID)
     96  if (GetAndroidSDKVersion() >= 23) {
     97    return dlsym(handle, symbol);
     98  }
     99 #endif
    100 
    101  if (!handle) {
    102    ElfLoader::Singleton.lastError = "dlsym(NULL, sym) unsupported";
    103    return nullptr;
    104  }
    105  if (handle != RTLD_DEFAULT && handle != RTLD_NEXT) {
    106    LibHandle* h = reinterpret_cast<LibHandle*>(handle);
    107    return h->GetSymbolPtr(symbol);
    108  }
    109 
    110  ElfLoader::Singleton.lastError = nullptr;  // Use system dlerror.
    111  return dlsym(handle, symbol);
    112 }
    113 
    114 int __wrap_dlclose(void* handle) {
    115 #if defined(ANDROID)
    116  if (GetAndroidSDKVersion() >= 23) {
    117    return dlclose(handle);
    118  }
    119 #endif
    120 
    121  if (!handle) {
    122    ElfLoader::Singleton.lastError = "No handle given to dlclose()";
    123    return -1;
    124  }
    125  reinterpret_cast<LibHandle*>(handle)->ReleaseDirectRef();
    126  return 0;
    127 }
    128 
    129 int __wrap_dladdr(const void* addr, Dl_info* info) {
    130 #if defined(ANDROID)
    131  if (GetAndroidSDKVersion() >= 23) {
    132    return dladdr(addr, info);
    133  }
    134 #endif
    135 
    136  RefPtr<LibHandle> handle =
    137      ElfLoader::Singleton.GetHandleByPtr(const_cast<void*>(addr));
    138  if (!handle) {
    139    return dladdr(addr, info);
    140  }
    141  info->dli_fname = handle->GetPath();
    142  info->dli_fbase = handle->GetBase();
    143  return 1;
    144 }
    145 
    146 class DlIteratePhdrHelper {
    147 public:
    148  DlIteratePhdrHelper() {
    149    int pipefd[2];
    150    valid_pipe = (pipe(pipefd) == 0);
    151    read_fd.emplace(pipefd[0]);
    152    write_fd.emplace(pipefd[1]);
    153  }
    154 
    155  int fill_and_call(dl_phdr_cb callback, const void* l_addr, const char* l_name,
    156                    void* data);
    157 
    158 private:
    159  bool valid_pipe;
    160  std::optional<AutoCloseFD> read_fd;
    161  std::optional<AutoCloseFD> write_fd;
    162 };
    163 
    164 // This function is called for each shared library iterated over by
    165 // dl_iterate_phdr, and is used to fill a dl_phdr_info which is then
    166 // sent through to the dl_iterate_phdr callback.
    167 int DlIteratePhdrHelper::fill_and_call(dl_phdr_cb callback, const void* l_addr,
    168                                       const char* l_name, void* data) {
    169  dl_phdr_info info;
    170  info.dlpi_addr = reinterpret_cast<Elf::Addr>(l_addr);
    171  info.dlpi_name = l_name;
    172  info.dlpi_phdr = nullptr;
    173  info.dlpi_phnum = 0;
    174 
    175  // Assuming l_addr points to Elf headers (in most cases, this is true),
    176  // get the Phdr location from there.
    177  // Unfortunately, when l_addr doesn't point to Elf headers, it may point
    178  // to unmapped memory, or worse, unreadable memory. The only way to detect
    179  // the latter without causing a SIGSEGV is to use the pointer in a system
    180  // call that will try to read from there, and return an EFAULT error if
    181  // it can't. One such system call is write(). It used to be possible to
    182  // use a file descriptor on /dev/null for these kind of things, but recent
    183  // Linux kernels never return an EFAULT error when using /dev/null.
    184  // So instead, we use a self pipe. We do however need to read() from the
    185  // read end of the pipe as well so as to not fill up the pipe buffer and
    186  // block on subsequent writes.
    187  // In the unlikely event reads from or write to the pipe fail for some
    188  // other reason than EFAULT, we don't try any further and just skip setting
    189  // the Phdr location for all subsequent libraries, rather than trying to
    190  // start over with a new pipe.
    191  int can_read = true;
    192  if (valid_pipe) {
    193    int ret;
    194    char raw_ehdr[sizeof(Elf::Ehdr)];
    195    static_assert(sizeof(raw_ehdr) < PIPE_BUF, "PIPE_BUF is too small");
    196    do {
    197      // writes are atomic when smaller than PIPE_BUF, per POSIX.1-2008.
    198      ret = write(*write_fd, l_addr, sizeof(raw_ehdr));
    199    } while (ret == -1 && errno == EINTR);
    200    if (ret != sizeof(raw_ehdr)) {
    201      if (ret == -1 && errno == EFAULT) {
    202        can_read = false;
    203      } else {
    204        valid_pipe = false;
    205      }
    206    } else {
    207      size_t nbytes = 0;
    208      do {
    209        // Per POSIX.1-2008, interrupted reads can return a length smaller
    210        // than the given one instead of failing with errno EINTR.
    211        ret = read(*read_fd, raw_ehdr + nbytes, sizeof(raw_ehdr) - nbytes);
    212        if (ret > 0) nbytes += ret;
    213      } while ((nbytes != sizeof(raw_ehdr) && ret > 0) ||
    214               (ret == -1 && errno == EINTR));
    215      if (nbytes != sizeof(raw_ehdr)) {
    216        valid_pipe = false;
    217      }
    218    }
    219  }
    220 
    221  if (valid_pipe && can_read) {
    222    const Elf::Ehdr* ehdr = Elf::Ehdr::validate(l_addr);
    223    if (ehdr) {
    224      info.dlpi_phdr = reinterpret_cast<const Elf::Phdr*>(
    225          reinterpret_cast<const char*>(ehdr) + ehdr->e_phoff);
    226      info.dlpi_phnum = ehdr->e_phnum;
    227    }
    228  }
    229 
    230  return callback(&info, sizeof(dl_phdr_info), data);
    231 }
    232 
    233 int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void* data) {
    234 #if defined(ANDROID)
    235  if (GetAndroidSDKVersion() >= 23) {
    236    return dl_iterate_phdr(callback, data);
    237  }
    238 #endif
    239 
    240  DlIteratePhdrHelper helper;
    241  AutoLock lock(&ElfLoader::Singleton.handlesMutex);
    242 
    243  for (ElfLoader::LibHandleList::reverse_iterator it =
    244           ElfLoader::Singleton.handles.rbegin();
    245       it < ElfLoader::Singleton.handles.rend(); ++it) {
    246    BaseElf* elf = (*it)->AsBaseElf();
    247    if (!elf) {
    248      continue;
    249    }
    250    int ret = helper.fill_and_call(callback, (*it)->GetBase(), (*it)->GetPath(),
    251                                   data);
    252    if (ret) return ret;
    253  }
    254  return dl_iterate_phdr(callback, data);
    255 }
    256 
    257 #ifdef __ARM_EABI__
    258 const void* __wrap___gnu_Unwind_Find_exidx(void* pc, int* pcount) {
    259  RefPtr<LibHandle> handle = ElfLoader::Singleton.GetHandleByPtr(pc);
    260  if (handle) return handle->FindExidx(pcount);
    261  if (__gnu_Unwind_Find_exidx) return __gnu_Unwind_Find_exidx(pc, pcount);
    262  *pcount = 0;
    263  return nullptr;
    264 }
    265 #endif
    266 
    267 namespace {
    268 
    269 /**
    270 * Returns the part after the last '/' for the given path
    271 */
    272 const char* LeafName(const char* path) {
    273  const char* lastSlash = strrchr(path, '/');
    274  if (lastSlash) return lastSlash + 1;
    275  return path;
    276 }
    277 
    278 /**
    279 * Run the given lambda while holding the internal lock of the system linker.
    280 * To take the lock, we call the system dl_iterate_phdr and invoke the lambda
    281 * from the callback, which is called while the lock is held. Return true on
    282 * success.
    283 */
    284 template <class Lambda>
    285 static bool RunWithSystemLinkerLock(Lambda&& aLambda) {
    286 #if defined(ANDROID)
    287  if (GetAndroidSDKVersion() < 23) {
    288    // dl_iterate_phdr is _not_ protected by a lock on Android < 23.
    289    // Also return false here if we failed to get the version.
    290    return false;
    291  }
    292 #endif
    293 
    294  dl_iterate_phdr(
    295      [](dl_phdr_info*, size_t, void* lambda) -> int {
    296        (*static_cast<Lambda*>(lambda))();
    297        // Return 1 to stop iterating.
    298        return 1;
    299      },
    300      &aLambda);
    301  return true;
    302 }
    303 
    304 } /* Anonymous namespace */
    305 
    306 /**
    307 * LibHandle
    308 */
    309 LibHandle::~LibHandle() { free(path); }
    310 
    311 const char* LibHandle::GetName() const {
    312  return path ? LeafName(path) : nullptr;
    313 }
    314 
    315 /**
    316 * SystemElf
    317 */
    318 already_AddRefed<LibHandle> SystemElf::Load(const char* path, int flags) {
    319  /* The Android linker returns a handle when the file name matches an
    320   * already loaded library, even when the full path doesn't exist */
    321  if (path && path[0] == '/' && (access(path, F_OK) == -1)) {
    322    DEBUG_LOG("dlopen(\"%s\", 0x%x) = %p", path, flags, (void*)nullptr);
    323    ElfLoader::Singleton.lastError = "Specified file does not exist";
    324    return nullptr;
    325  }
    326 
    327  ElfLoader::Singleton.lastError = nullptr;  // Use system dlerror.
    328  void* handle = dlopen(path, flags);
    329  DEBUG_LOG("dlopen(\"%s\", 0x%x) = %p", path, flags, handle);
    330  if (handle) {
    331    SystemElf* elf = new SystemElf(path, handle);
    332    ElfLoader::Singleton.Register(elf);
    333    RefPtr<LibHandle> lib(elf);
    334    return lib.forget();
    335  }
    336  return nullptr;
    337 }
    338 
    339 SystemElf::~SystemElf() {
    340  if (!dlhandle) return;
    341  DEBUG_LOG("dlclose(%p [\"%s\"])", dlhandle, GetPath());
    342  ElfLoader::Singleton.lastError = nullptr;  // Use system dlerror.
    343  dlclose(dlhandle);
    344  ElfLoader::Singleton.Forget(this);
    345 }
    346 
    347 void* SystemElf::GetSymbolPtr(const char* symbol) const {
    348  ElfLoader::Singleton.lastError = nullptr;  // Use system dlerror.
    349  void* sym = dlsym(dlhandle, symbol);
    350  DEBUG_LOG("dlsym(%p [\"%s\"], \"%s\") = %p", dlhandle, GetPath(), symbol,
    351            sym);
    352  return sym;
    353 }
    354 
    355 #ifdef __ARM_EABI__
    356 const void* SystemElf::FindExidx(int* pcount) const {
    357  /* TODO: properly implement when ElfLoader::GetHandleByPtr
    358     does return SystemElf handles */
    359  *pcount = 0;
    360  return nullptr;
    361 }
    362 #endif
    363 
    364 /**
    365 * ElfLoader
    366 */
    367 
    368 /* Unique ElfLoader instance */
    369 MOZ_RUNINIT ElfLoader ElfLoader::Singleton;
    370 
    371 already_AddRefed<LibHandle> ElfLoader::Load(const char* path, int flags,
    372                                            LibHandle* parent) {
    373  /* Ensure logging is initialized or refresh if environment changed. */
    374  Logging::Init();
    375 
    376  /* Ensure self_elf initialization. */
    377  if (!self_elf) Init();
    378 
    379  RefPtr<LibHandle> handle;
    380 
    381  /* Handle dlopen(nullptr) directly. */
    382  if (!path) {
    383    handle = SystemElf::Load(nullptr, flags);
    384    return handle.forget();
    385  }
    386 
    387  /* TODO: Handle relative paths correctly */
    388  const char* name = LeafName(path);
    389 
    390  /* Search the list of handles we already have for a match. When the given
    391   * path is not absolute, compare file names, otherwise compare full paths. */
    392  if (name == path) {
    393    AutoLock lock(&handlesMutex);
    394    for (LibHandleList::iterator it = handles.begin(); it < handles.end(); ++it)
    395      if ((*it)->GetName() && (strcmp((*it)->GetName(), name) == 0)) {
    396        handle = *it;
    397        return handle.forget();
    398      }
    399  } else {
    400    AutoLock lock(&handlesMutex);
    401    for (LibHandleList::iterator it = handles.begin(); it < handles.end(); ++it)
    402      if ((*it)->GetPath() && (strcmp((*it)->GetPath(), path) == 0)) {
    403        handle = *it;
    404        return handle.forget();
    405      }
    406  }
    407 
    408  char* abs_path = nullptr;
    409  const char* requested_path = path;
    410 
    411  /* When the path is not absolute and the library is being loaded for
    412   * another, first try to load the library from the directory containing
    413   * that parent library. */
    414  if ((name == path) && parent) {
    415    const char* parentPath = parent->GetPath();
    416    abs_path = new char[strlen(parentPath) + strlen(path)];
    417    strcpy(abs_path, parentPath);
    418    char* slash = strrchr(abs_path, '/');
    419    strcpy(slash + 1, path);
    420    path = abs_path;
    421  }
    422 
    423  Mappable* mappable = GetMappableFromPath(path);
    424 
    425  /* Try loading with the custom linker if we have a Mappable */
    426  if (mappable) handle = CustomElf::Load(mappable, path, flags);
    427 
    428  /* Try loading with the system linker if everything above failed */
    429  if (!handle) handle = SystemElf::Load(path, flags);
    430 
    431  /* If we didn't have an absolute path and haven't been able to load
    432   * a library yet, try in the system search path */
    433  if (!handle && abs_path) handle = SystemElf::Load(name, flags);
    434 
    435  delete[] abs_path;
    436  DEBUG_LOG("ElfLoader::Load(\"%s\", 0x%x, %p [\"%s\"]) = %p", requested_path,
    437            flags, reinterpret_cast<void*>(parent),
    438            parent ? parent->GetPath() : "", static_cast<void*>(handle));
    439 
    440  return handle.forget();
    441 }
    442 
    443 already_AddRefed<LibHandle> ElfLoader::GetHandleByPtr(void* addr) {
    444  AutoLock lock(&handlesMutex);
    445  /* Scan the list of handles we already have for a match */
    446  for (LibHandleList::iterator it = handles.begin(); it < handles.end(); ++it) {
    447    if ((*it)->Contains(addr)) {
    448      RefPtr<LibHandle> lib = *it;
    449      return lib.forget();
    450    }
    451  }
    452  return nullptr;
    453 }
    454 
    455 Mappable* ElfLoader::GetMappableFromPath(const char* path) {
    456  return Mappable::Create(path);
    457 }
    458 
    459 void ElfLoader::Register(LibHandle* handle) {
    460  AutoLock lock(&handlesMutex);
    461  handles.push_back(handle);
    462 }
    463 
    464 void ElfLoader::Register(CustomElf* handle) {
    465  Register(static_cast<LibHandle*>(handle));
    466  if (dbg) {
    467    // We could race with the system linker when modifying the debug map, so
    468    // only do so while holding the system linker's internal lock.
    469    RunWithSystemLinkerLock([this, handle] { dbg.Add(handle); });
    470  }
    471 }
    472 
    473 void ElfLoader::Forget(LibHandle* handle) {
    474  /* Ensure logging is initialized or refresh if environment changed. */
    475  Logging::Init();
    476 
    477  AutoLock lock(&handlesMutex);
    478  LibHandleList::iterator it =
    479      std::find(handles.begin(), handles.end(), handle);
    480  if (it != handles.end()) {
    481    DEBUG_LOG("ElfLoader::Forget(%p [\"%s\"])", reinterpret_cast<void*>(handle),
    482              handle->GetPath());
    483    handles.erase(it);
    484  } else {
    485    DEBUG_LOG("ElfLoader::Forget(%p [\"%s\"]): Handle not found",
    486              reinterpret_cast<void*>(handle), handle->GetPath());
    487  }
    488 }
    489 
    490 void ElfLoader::Forget(CustomElf* handle) {
    491  Forget(static_cast<LibHandle*>(handle));
    492  if (dbg) {
    493    // We could race with the system linker when modifying the debug map, so
    494    // only do so while holding the system linker's internal lock.
    495    RunWithSystemLinkerLock([this, handle] { dbg.Remove(handle); });
    496  }
    497 }
    498 
    499 void ElfLoader::Init() {
    500  Dl_info info;
    501  /* On Android < 4.1 can't reenter dl* functions. So when the library
    502   * containing this code is dlopen()ed, it can't call dladdr from a
    503   * static initializer. */
    504  if (dladdr(_DYNAMIC, &info) != 0) {
    505    self_elf = LoadedElf::Create(info.dli_fname, info.dli_fbase);
    506  }
    507 }
    508 
    509 ElfLoader::~ElfLoader() {
    510  LibHandleList list;
    511 
    512  if (!Singleton.IsShutdownExpected()) {
    513    MOZ_CRASH("Unexpected shutdown");
    514  }
    515 
    516  /* Release self_elf and libc */
    517  self_elf = nullptr;
    518 
    519  AutoLock lock(&handlesMutex);
    520  /* Build up a list of all library handles with direct (external) references.
    521   * We actually skip system library handles because we want to keep at least
    522   * some of these open. Most notably, Mozilla codebase keeps a few libgnome
    523   * libraries deliberately open because of the mess that libORBit destruction
    524   * is. dlclose()ing these libraries actually leads to problems. */
    525  for (LibHandleList::reverse_iterator it = handles.rbegin();
    526       it < handles.rend(); ++it) {
    527    if ((*it)->DirectRefCount()) {
    528      if (SystemElf* se = (*it)->AsSystemElf()) {
    529        se->Forget();
    530      } else {
    531        list.push_back(*it);
    532      }
    533    }
    534  }
    535  /* Force release all external references to the handles collected above */
    536  for (LibHandleList::iterator it = list.begin(); it < list.end(); ++it) {
    537    while ((*it)->ReleaseDirectRef()) {
    538    }
    539  }
    540  /* Remove the remaining system handles. */
    541  if (handles.size()) {
    542    list = handles;
    543    for (LibHandleList::reverse_iterator it = list.rbegin(); it < list.rend();
    544         ++it) {
    545      if ((*it)->AsSystemElf()) {
    546        DEBUG_LOG(
    547            "ElfLoader::~ElfLoader(): Remaining handle for \"%s\" "
    548            "[%" PRIdPTR " direct refs, %" PRIdPTR " refs total]",
    549            (*it)->GetPath(), (*it)->DirectRefCount(), (*it)->refCount());
    550      } else {
    551        DEBUG_LOG(
    552            "ElfLoader::~ElfLoader(): Unexpected remaining handle for \"%s\" "
    553            "[%" PRIdPTR " direct refs, %" PRIdPTR " refs total]",
    554            (*it)->GetPath(), (*it)->DirectRefCount(), (*it)->refCount());
    555        /* Not removing, since it could have references to other libraries,
    556         * destroying them as a side effect, and possibly leaving dangling
    557         * pointers in the handle list we're scanning */
    558      }
    559    }
    560  }
    561  pthread_mutex_destroy(&handlesMutex);
    562 }
    563 
    564 #ifdef __ARM_EABI__
    565 int ElfLoader::__wrap_aeabi_atexit(void* that, ElfLoader::Destructor destructor,
    566                                   void* dso_handle) {
    567  Singleton.destructors.push_back(
    568      DestructorCaller(destructor, that, dso_handle));
    569  return 0;
    570 }
    571 #else
    572 int ElfLoader::__wrap_cxa_atexit(ElfLoader::Destructor destructor, void* that,
    573                                 void* dso_handle) {
    574  Singleton.destructors.push_back(
    575      DestructorCaller(destructor, that, dso_handle));
    576  return 0;
    577 }
    578 #endif
    579 
    580 void ElfLoader::__wrap_cxa_finalize(void* dso_handle) {
    581  /* Call all destructors for the given DSO handle in reverse order they were
    582   * registered. */
    583  std::vector<DestructorCaller>::reverse_iterator it;
    584  for (it = Singleton.destructors.rbegin(); it < Singleton.destructors.rend();
    585       ++it) {
    586    if (it->IsForHandle(dso_handle)) {
    587      it->Call();
    588    }
    589  }
    590 }
    591 
    592 void ElfLoader::DestructorCaller::Call() {
    593  if (destructor) {
    594    DEBUG_LOG("ElfLoader::DestructorCaller::Call(%p, %p, %p)",
    595              FunctionPtr(destructor), object, dso_handle);
    596    destructor(object);
    597    destructor = nullptr;
    598  }
    599 }
    600 
    601 ElfLoader::DebuggerHelper::DebuggerHelper()
    602    : dbg(nullptr), firstAdded(nullptr) {
    603  /* Find ELF auxiliary vectors.
    604   *
    605   * The kernel stores the following data on the stack when starting a
    606   * program:
    607   *   argc
    608   *   argv[0] (pointer into argv strings defined below)
    609   *   argv[1] (likewise)
    610   *   ...
    611   *   argv[argc - 1] (likewise)
    612   *   nullptr
    613   *   envp[0] (pointer into environment strings defined below)
    614   *   envp[1] (likewise)
    615   *   ...
    616   *   envp[n] (likewise)
    617   *   nullptr
    618   *   ... (more NULLs on some platforms such as Android 4.3)
    619   *   auxv[0] (first ELF auxiliary vector)
    620   *   auxv[1] (second ELF auxiliary vector)
    621   *   ...
    622   *   auxv[p] (last ELF auxiliary vector)
    623   *   (AT_NULL, nullptr)
    624   *   padding
    625   *   argv strings, separated with '\0'
    626   *   environment strings, separated with '\0'
    627   *   nullptr
    628   *
    629   * What we are after are the auxv values defined by the following struct.
    630   */
    631  struct AuxVector {
    632    Elf::Addr type;
    633    Elf::Addr value;
    634  };
    635 
    636  /* Pointer to the environment variables list */
    637  extern char** environ;
    638 
    639  /* The environment may have changed since the program started, in which
    640   * case the environ variables list isn't the list the kernel put on stack
    641   * anymore. But in this new list, variables that didn't change still point
    642   * to the strings the kernel put on stack. It is quite unlikely that two
    643   * modified environment variables point to two consecutive strings in memory,
    644   * so we assume that if two consecutive environment variables point to two
    645   * consecutive strings, we found strings the kernel put on stack. */
    646  char** env;
    647  for (env = environ; *env; env++)
    648    if (*env + strlen(*env) + 1 == env[1]) break;
    649  if (!*env) return;
    650 
    651  /* Next, we scan the stack backwards to find a pointer to one of those
    652   * strings we found above, which will give us the location of the original
    653   * envp list. As we are looking for pointers, we need to look at 32-bits or
    654   * 64-bits aligned values, depening on the architecture. */
    655  char** scan = reinterpret_cast<char**>(reinterpret_cast<uintptr_t>(*env) &
    656                                         ~(sizeof(void*) - 1));
    657  while (*env != *scan) scan--;
    658 
    659  /* Finally, scan forward to find the last environment variable pointer and
    660   * thus the first auxiliary vector. */
    661  while (*scan++);
    662 
    663  /* Some platforms have more NULLs here, so skip them if we encounter them */
    664  while (!*scan) scan++;
    665 
    666  AuxVector* auxv = reinterpret_cast<AuxVector*>(scan);
    667 
    668  /* The two values of interest in the auxiliary vectors are AT_PHDR and
    669   * AT_PHNUM, which gives us the the location and size of the ELF program
    670   * headers. */
    671  Array<Elf::Phdr> phdrs;
    672  char* base = nullptr;
    673  while (auxv->type) {
    674    if (auxv->type == AT_PHDR) {
    675      phdrs.Init(reinterpret_cast<Elf::Phdr*>(auxv->value));
    676      /* Assume the base address is the first byte of the same page */
    677      base = reinterpret_cast<char*>(PageAlignedPtr(auxv->value));
    678    }
    679    if (auxv->type == AT_PHNUM) phdrs.Init(auxv->value);
    680    auxv++;
    681  }
    682 
    683  if (!phdrs) {
    684    DEBUG_LOG("Couldn't find program headers");
    685    return;
    686  }
    687 
    688  /* In some cases, the address for the program headers we get from the
    689   * auxiliary vectors is not mapped, because of the PT_LOAD segments
    690   * definitions in the program executable. Trying to map anonymous memory
    691   * with a hint giving the base address will return a different address
    692   * if something is mapped there, and the base address otherwise. */
    693  MappedPtr mem(MemoryRange::mmap(base, PageSize(), PROT_NONE,
    694                                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
    695  if (mem == base) {
    696    /* If program headers aren't mapped, try to map them */
    697    int fd = open("/proc/self/exe", O_RDONLY);
    698    if (fd == -1) {
    699      DEBUG_LOG("Failed to open /proc/self/exe");
    700      return;
    701    }
    702    mem.Assign(
    703        MemoryRange::mmap(base, PageSize(), PROT_READ, MAP_PRIVATE, fd, 0));
    704    /* If we don't manage to map at the right address, just give up. */
    705    if (mem != base) {
    706      DEBUG_LOG("Couldn't read program headers");
    707      return;
    708    }
    709  }
    710  /* Sanity check: the first bytes at the base address should be an ELF
    711   * header. */
    712  if (!Elf::Ehdr::validate(base)) {
    713    DEBUG_LOG("Couldn't find program base");
    714    return;
    715  }
    716 
    717  /* Search for the program PT_DYNAMIC segment */
    718  Array<Elf::Dyn> dyns;
    719  for (Array<Elf::Phdr>::iterator phdr = phdrs.begin(); phdr < phdrs.end();
    720       ++phdr) {
    721    /* While the program headers are expected within the first mapped page of
    722     * the program executable, the executable PT_LOADs may actually make them
    723     * loaded at an address that is not the wanted base address of the
    724     * library. We thus need to adjust the base address, compensating for the
    725     * virtual address of the PT_LOAD segment corresponding to offset 0. */
    726    if (phdr->p_type == PT_LOAD && phdr->p_offset == 0) base -= phdr->p_vaddr;
    727    if (phdr->p_type == PT_DYNAMIC)
    728      dyns.Init(base + phdr->p_vaddr, phdr->p_filesz);
    729  }
    730  if (!dyns) {
    731    DEBUG_LOG("Failed to find PT_DYNAMIC section in program");
    732    return;
    733  }
    734 
    735  /* Search for the DT_DEBUG information */
    736  for (Array<Elf::Dyn>::iterator dyn = dyns.begin(); dyn < dyns.end(); ++dyn) {
    737    if (dyn->d_tag == DT_DEBUG) {
    738      dbg = reinterpret_cast<r_debug*>(dyn->d_un.d_ptr);
    739      break;
    740    }
    741  }
    742  DEBUG_LOG("DT_DEBUG points at %p", static_cast<void*>(dbg));
    743 }
    744 
    745 /**
    746 * Helper class to ensure the given pointer is writable within the scope of
    747 * an instance. Permissions to the memory page where the pointer lies are
    748 * restored to their original value when the instance is destroyed.
    749 */
    750 class EnsureWritable {
    751 public:
    752  template <typename T>
    753  explicit EnsureWritable(T* ptr, size_t length_ = sizeof(T)) {
    754    MOZ_ASSERT(length_ < PageSize());
    755    prot = -1;
    756    page = MAP_FAILED;
    757 
    758    char* firstPage = PageAlignedPtr(reinterpret_cast<char*>(ptr));
    759    char* lastPageEnd =
    760        PageAlignedEndPtr(reinterpret_cast<char*>(ptr) + length_);
    761    length = lastPageEnd - firstPage;
    762    uintptr_t start = reinterpret_cast<uintptr_t>(firstPage);
    763    uintptr_t end;
    764 
    765    prot = getProt(start, &end);
    766    if (prot == -1 || (start + length) > end) MOZ_CRASH();
    767 
    768    if (prot & PROT_WRITE) {
    769      success = true;
    770      return;
    771    }
    772 
    773    page = firstPage;
    774    int ret = mprotect(page, length, prot | PROT_WRITE);
    775    success = ret == 0;
    776    if (!success) {
    777      ERROR("mprotect(%p, %zu, %d) = %d (errno=%d; %s)", page, length,
    778            prot | PROT_WRITE, ret, errno, strerror(errno));
    779    }
    780  }
    781 
    782  bool IsWritable() const { return success; }
    783 
    784  ~EnsureWritable() {
    785    if (success && page != MAP_FAILED) {
    786      mprotect(page, length, prot);
    787    }
    788  }
    789 
    790 private:
    791  int getProt(uintptr_t addr, uintptr_t* end) {
    792    /* The interesting part of the /proc/self/maps format looks like:
    793     * startAddr-endAddr rwxp */
    794    int result = 0;
    795    FILE* const f = fopen("/proc/self/maps", "r");
    796    const auto cleanup = mozilla::MakeScopeExit([&]() {
    797      if (f) fclose(f);
    798    });
    799    while (f) {
    800      unsigned long long startAddr, endAddr;
    801      char perms[5];
    802      if (fscanf(f, "%llx-%llx %4s %*1024[^\n] ", &startAddr, &endAddr,
    803                 perms) != 3)
    804        return -1;
    805      if (addr < startAddr || addr >= endAddr) continue;
    806      if (perms[0] == 'r')
    807        result |= PROT_READ;
    808      else if (perms[0] != '-')
    809        return -1;
    810      if (perms[1] == 'w')
    811        result |= PROT_WRITE;
    812      else if (perms[1] != '-')
    813        return -1;
    814      if (perms[2] == 'x')
    815        result |= PROT_EXEC;
    816      else if (perms[2] != '-')
    817        return -1;
    818      *end = endAddr;
    819      return result;
    820    }
    821    return -1;
    822  }
    823 
    824  int prot;
    825  void* page;
    826  size_t length;
    827  bool success;
    828 };
    829 
    830 /**
    831 * The system linker maintains a doubly linked list of library it loads
    832 * for use by the debugger. Unfortunately, it also uses the list pointers
    833 * in a lot of operations and adding our data in the list is likely to
    834 * trigger crashes when the linker tries to use data we don't provide or
    835 * that fall off the amount data we allocated. Fortunately, the linker only
    836 * traverses the list forward and accesses the head of the list from a
    837 * private pointer instead of using the value in the r_debug structure.
    838 * This means we can safely add members at the beginning of the list.
    839 * Unfortunately, gdb checks the coherency of l_prev values, so we have
    840 * to adjust the l_prev value for the first element the system linker
    841 * knows about. Fortunately, it doesn't use l_prev, and the first element
    842 * is not ever going to be released before our elements, since it is the
    843 * program executable, so the system linker should not be changing
    844 * r_debug::r_map.
    845 */
    846 void ElfLoader::DebuggerHelper::Add(ElfLoader::link_map* map) {
    847  if (!dbg->r_brk) return;
    848 
    849  dbg->r_state = r_debug::RT_ADD;
    850  dbg->r_brk();
    851 
    852  if (!firstAdded) {
    853    /* When adding a library for the first time, r_map points to data
    854     * handled by the system linker, and that data may be read-only */
    855    EnsureWritable w(&dbg->r_map->l_prev);
    856    if (!w.IsWritable()) {
    857      dbg->r_state = r_debug::RT_CONSISTENT;
    858      dbg->r_brk();
    859      return;
    860    }
    861 
    862    firstAdded = map;
    863    dbg->r_map->l_prev = map;
    864  } else
    865    dbg->r_map->l_prev = map;
    866 
    867  map->l_prev = nullptr;
    868  map->l_next = dbg->r_map;
    869 
    870  dbg->r_map = map;
    871  dbg->r_state = r_debug::RT_CONSISTENT;
    872  dbg->r_brk();
    873 }
    874 
    875 void ElfLoader::DebuggerHelper::Remove(ElfLoader::link_map* map) {
    876  if (!dbg->r_brk) return;
    877 
    878  dbg->r_state = r_debug::RT_DELETE;
    879  dbg->r_brk();
    880 
    881  if (map == firstAdded) {
    882    /* When removing the first added library, its l_next is going to be
    883     * data handled by the system linker, and that data may be read-only */
    884    EnsureWritable w(&map->l_next->l_prev);
    885    if (!w.IsWritable()) {
    886      dbg->r_state = r_debug::RT_CONSISTENT;
    887      dbg->r_brk();
    888      return;
    889    }
    890 
    891    firstAdded = map->l_prev;
    892    map->l_next->l_prev = map->l_prev;
    893  } else if (map->l_next) {
    894    map->l_next->l_prev = map->l_prev;
    895  }
    896 
    897  if (dbg->r_map == map)
    898    dbg->r_map = map->l_next;
    899  else if (map->l_prev) {
    900    map->l_prev->l_next = map->l_next;
    901  }
    902  dbg->r_state = r_debug::RT_CONSISTENT;
    903  dbg->r_brk();
    904 }
    905 
    906 #if defined(ANDROID) && defined(__NR_sigaction)
    907 /* As some system libraries may be calling signal() or sigaction() to
    908 * set a SIGSEGV handler, effectively breaking MappableSeekableZStream,
    909 * or worse, restore our SIGSEGV handler with wrong flags (which using
    910 * signal() will do), we want to hook into the system's sigaction() to
    911 * replace it with our own wrapper instead, so that our handler is never
    912 * replaced. We used to only do that with libraries this linker loads,
    913 * but it turns out at least one system library does call signal() and
    914 * breaks us (libsc-a3xx.so on the Samsung Galaxy S4).
    915 * As libc's signal (bsd_signal/sysv_signal, really) calls sigaction
    916 * under the hood, instead of calling the signal system call directly,
    917 * we only need to hook sigaction. This is true for both bionic and
    918 * glibc.
    919 */
    920 
    921 /* libc's sigaction */
    922 extern "C" int sigaction(int signum, const struct sigaction* act,
    923                         struct sigaction* oldact);
    924 
    925 /* Simple reimplementation of sigaction. This is roughly equivalent
    926 * to the assembly that comes in bionic, but not quite equivalent to
    927 * glibc's implementation, so we only use this on Android. */
    928 int sys_sigaction(int signum, const struct sigaction* act,
    929                  struct sigaction* oldact) {
    930  return syscall(__NR_sigaction, signum, act, oldact);
    931 }
    932 
    933 /* Replace the first instructions of the given function with a jump
    934 * to the given new function. */
    935 template <typename T>
    936 static bool Divert(T func, T new_func) {
    937  void* ptr = FunctionPtr(func);
    938  uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
    939 
    940 #  if defined(__i386__)
    941  // A 32-bit jump is a 5 bytes instruction.
    942  EnsureWritable w(ptr, 5);
    943  *reinterpret_cast<unsigned char*>(addr) = 0xe9;  // jmp
    944  *reinterpret_cast<intptr_t*>(addr + 1) =
    945      reinterpret_cast<uintptr_t>(new_func) - addr - 5;  // target displacement
    946  return true;
    947 #  elif defined(__arm__) || defined(__aarch64__)
    948  const unsigned char trampoline[] = {
    949 #    ifdef __arm__
    950      // .thumb
    951      0x46, 0x04,              // nop
    952      0x78, 0x47,              // bx pc
    953      0x46, 0x04,              // nop
    954                               // .arm
    955      0x04, 0xf0, 0x1f, 0xe5,  // ldr pc, [pc, #-4]
    956                               // .word <new_func>
    957 #    else  // __aarch64__
    958      0x50, 0x00,
    959      0x00, 0x58,  // ldr x16, [pc, #8]   ; x16 (aka ip0) is the first
    960      0x00, 0x02,
    961      0x1f, 0xd6,  // br x16              ; intra-procedure-call
    962                   // .word <new_func.lo> ; scratch register.
    963                   // .word <new_func.hi>
    964 #    endif
    965  };
    966  const unsigned char* start;
    967 #    ifdef __arm__
    968  if (addr & 0x01) {
    969    /* Function is thumb, the actual address of the code is without the
    970     * least significant bit. */
    971    addr--;
    972    /* The arm part of the trampoline needs to be 32-bit aligned */
    973    if (addr & 0x02)
    974      start = trampoline;
    975    else
    976      start = trampoline + 2;
    977  } else {
    978    /* Function is arm, we only need the arm part of the trampoline */
    979    start = trampoline + 6;
    980  }
    981 #    else  // __aarch64__
    982  start = trampoline;
    983 #    endif
    984 
    985  size_t len = sizeof(trampoline) - (start - trampoline);
    986  EnsureWritable w(reinterpret_cast<void*>(addr), len + sizeof(void*));
    987  memcpy(reinterpret_cast<void*>(addr), start, len);
    988  *reinterpret_cast<void**>(addr + len) = FunctionPtr(new_func);
    989  __builtin___clear_cache(reinterpret_cast<char*>(addr),
    990                          reinterpret_cast<char*>(addr + len + sizeof(void*)));
    991  return true;
    992 #  else
    993  return false;
    994 #  endif
    995 }
    996 #else
    997 #  define sys_sigaction sigaction
    998 template <typename T>
    999 static bool Divert(T func, T new_func) {
   1000  return false;
   1001 }
   1002 #endif
   1003 
   1004 namespace {
   1005 
   1006 /* Clock that only accounts for time spent in the current process. */
   1007 static uint64_t ProcessTimeStamp_Now() {
   1008  struct timespec ts;
   1009  int rv = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
   1010 
   1011  if (rv != 0) {
   1012    return 0;
   1013  }
   1014 
   1015  uint64_t baseNs = (uint64_t)ts.tv_sec * 1000000000;
   1016  return baseNs + (uint64_t)ts.tv_nsec;
   1017 }
   1018 
   1019 }  // namespace
   1020 
   1021 /* Data structure used to pass data to the temporary signal handler,
   1022 * as well as triggering a test crash. */
   1023 struct TmpData {
   1024  volatile int crash_int;
   1025  volatile uint64_t crash_timestamp;
   1026 };
   1027 
   1028 SEGVHandler::SEGVHandler()
   1029    : initialized(false), registeredHandler(false), signalHandlingSlow(true) {
   1030  /* Ensure logging is initialized before the DEBUG_LOG in the test_handler.
   1031   * As this constructor runs before the ElfLoader constructor (by effect
   1032   * of ElfLoader inheriting from this class), this also initializes on behalf
   1033   * of ElfLoader and DebuggerHelper. */
   1034  Logging::Init();
   1035 
   1036  /* Initialize oldStack.ss_flags to an invalid value when used to set
   1037   * an alternative stack, meaning we haven't got information about the
   1038   * original alternative stack and thus don't mean to restore it in
   1039   * the destructor. */
   1040  oldStack.ss_flags = SS_ONSTACK;
   1041 
   1042  /* Get the current segfault signal handler. */
   1043  struct sigaction old_action;
   1044  sys_sigaction(SIGSEGV, nullptr, &old_action);
   1045 
   1046  /* Some devices have a kernel option enabled that makes SIGSEGV handler
   1047   * have an overhead so high that it affects how on-demand decompression
   1048   * performs. The handler will set signalHandlingSlow if the triggered
   1049   * SIGSEGV took too much time. */
   1050  struct sigaction action;
   1051  action.sa_sigaction = &SEGVHandler::test_handler;
   1052  sigemptyset(&action.sa_mask);
   1053  action.sa_flags = SA_SIGINFO | SA_NODEFER;
   1054  action.sa_restorer = nullptr;
   1055  stackPtr.Assign(MemoryRange::mmap(nullptr, PageSize(), PROT_READ | PROT_WRITE,
   1056                                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
   1057  if (stackPtr.get() == MAP_FAILED) return;
   1058  if (sys_sigaction(SIGSEGV, &action, nullptr)) return;
   1059 
   1060  TmpData* data = reinterpret_cast<TmpData*>(stackPtr.get());
   1061  data->crash_timestamp = ProcessTimeStamp_Now();
   1062  mprotect(stackPtr, stackPtr.GetLength(), PROT_NONE);
   1063  data->crash_int = 123;
   1064  /* Restore the original segfault signal handler. */
   1065  sys_sigaction(SIGSEGV, &old_action, nullptr);
   1066  stackPtr.Assign(MAP_FAILED, 0);
   1067 }
   1068 
   1069 void SEGVHandler::FinishInitialization() {
   1070  /* Ideally, we'd need some locking here, but in practice, we're not
   1071   * going to race with another thread. */
   1072  initialized = true;
   1073 
   1074  if (signalHandlingSlow) {
   1075    return;
   1076  }
   1077 
   1078  typedef int (*sigaction_func)(int, const struct sigaction*,
   1079                                struct sigaction*);
   1080 
   1081  sigaction_func libc_sigaction;
   1082 
   1083 #if defined(ANDROID)
   1084  /* Android > 4.4 comes with a sigaction wrapper in a LD_PRELOADed library
   1085   * (libsigchain) for ART. That wrapper kind of does the same trick as we
   1086   * do, so we need extra care in handling it.
   1087   * - Divert the libc's sigaction, assuming the LD_PRELOADed library uses
   1088   *   it under the hood (which is more or less true according to the source
   1089   *   of that library, since it's doing a lookup in RTLD_NEXT)
   1090   * - With the LD_PRELOADed library in place, all calls to sigaction from
   1091   *   from system libraries will go to the LD_PRELOADed library.
   1092   * - The LD_PRELOADed library calls to sigaction go to our __wrap_sigaction.
   1093   * - The calls to sigaction from libraries faulty.lib loads are sent to
   1094   *   the LD_PRELOADed library.
   1095   * In practice, for signal handling, this means:
   1096   * - The signal handler registered to the kernel is ours.
   1097   * - Our handler redispatches to the LD_PRELOADed library's if there's a
   1098   *   segfault we don't handle.
   1099   * - The LD_PRELOADed library redispatches according to whatever system
   1100   *   library or faulty.lib-loaded library set with sigaction.
   1101   *
   1102   * When there is no sigaction wrapper in place:
   1103   * - Divert the libc's sigaction.
   1104   * - Calls to sigaction from system library and faulty.lib-loaded libraries
   1105   *   all go to the libc's sigaction, which end up in our __wrap_sigaction.
   1106   * - The signal handler registered to the kernel is ours.
   1107   * - Our handler redispatches according to whatever system library or
   1108   *   faulty.lib-loaded library set with sigaction.
   1109   */
   1110  void* libc = dlopen("libc.so", RTLD_GLOBAL | RTLD_LAZY);
   1111  if (libc) {
   1112    /*
   1113     * Lollipop bionic only has a small trampoline in sigaction, with the real
   1114     * work happening in __sigaction. Divert there instead of sigaction if it
   1115     * exists. Bug 1154803
   1116     */
   1117    libc_sigaction =
   1118        reinterpret_cast<sigaction_func>(dlsym(libc, "__sigaction"));
   1119 
   1120    if (!libc_sigaction) {
   1121      libc_sigaction =
   1122          reinterpret_cast<sigaction_func>(dlsym(libc, "sigaction"));
   1123    }
   1124  } else
   1125 #endif
   1126  {
   1127    libc_sigaction = sigaction;
   1128  }
   1129 
   1130  if (!Divert(libc_sigaction, __wrap_sigaction)) return;
   1131 
   1132  /* Setup an alternative stack if the already existing one is not big
   1133   * enough, or if there is none. */
   1134  if (sigaltstack(nullptr, &oldStack) == 0) {
   1135    if (oldStack.ss_flags == SS_ONSTACK) oldStack.ss_flags = 0;
   1136    if (!oldStack.ss_sp || oldStack.ss_size < stackSize) {
   1137      stackPtr.Assign(MemoryRange::mmap(nullptr, stackSize,
   1138                                        PROT_READ | PROT_WRITE,
   1139                                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
   1140      if (stackPtr.get() == MAP_FAILED) return;
   1141      stack_t stack;
   1142      stack.ss_sp = stackPtr;
   1143      stack.ss_size = stackSize;
   1144      stack.ss_flags = 0;
   1145      if (sigaltstack(&stack, nullptr) != 0) return;
   1146    }
   1147  }
   1148  /* Register our own handler, and store the already registered one in
   1149   * SEGVHandler's struct sigaction member */
   1150  action.sa_sigaction = &SEGVHandler::handler;
   1151  action.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
   1152  registeredHandler = !sys_sigaction(SIGSEGV, &action, &this->action);
   1153 }
   1154 
   1155 SEGVHandler::~SEGVHandler() {
   1156  /* Restore alternative stack for signals */
   1157  if (oldStack.ss_flags != SS_ONSTACK) sigaltstack(&oldStack, nullptr);
   1158  /* Restore original signal handler */
   1159  if (registeredHandler) sys_sigaction(SIGSEGV, &this->action, nullptr);
   1160 }
   1161 
   1162 /* Test handler for a deliberately triggered SIGSEGV that determines whether
   1163 * the segfault handler is called quickly enough. */
   1164 void SEGVHandler::test_handler(int signum, siginfo_t* info, void* context) {
   1165  SEGVHandler& that = ElfLoader::Singleton;
   1166  mprotect(that.stackPtr, that.stackPtr.GetLength(), PROT_READ | PROT_WRITE);
   1167  TmpData* data = reinterpret_cast<TmpData*>(that.stackPtr.get());
   1168  uint64_t latency = ProcessTimeStamp_Now() - data->crash_timestamp;
   1169  DEBUG_LOG("SEGVHandler latency: %" PRIu64, latency);
   1170  /* See bug 886736 for timings on different devices, 150 µs is reasonably above
   1171   * the latency on "working" devices and seems to be short enough to not incur
   1172   * a huge overhead to on-demand decompression. */
   1173  if (latency <= 150000) that.signalHandlingSlow = false;
   1174 }
   1175 
   1176 /* TODO: "properly" handle signal masks and flags */
   1177 void SEGVHandler::handler(int signum, siginfo_t* info, void* context) {
   1178  // ASSERT(signum == SIGSEGV);
   1179  DEBUG_LOG("Caught segmentation fault @%p", info->si_addr);
   1180 
   1181  /* Redispatch to the registered handler */
   1182  SEGVHandler& that = ElfLoader::Singleton;
   1183  if (that.action.sa_flags & SA_SIGINFO) {
   1184    DEBUG_LOG("Redispatching to registered handler @%p",
   1185              FunctionPtr(that.action.sa_sigaction));
   1186    that.action.sa_sigaction(signum, info, context);
   1187  } else if (that.action.sa_handler == SIG_DFL) {
   1188    DEBUG_LOG("Redispatching to default handler");
   1189    /* Reset the handler to the default one, and trigger it. */
   1190    sys_sigaction(signum, &that.action, nullptr);
   1191    raise(signum);
   1192  } else if (that.action.sa_handler != SIG_IGN) {
   1193    DEBUG_LOG("Redispatching to registered handler @%p",
   1194              FunctionPtr(that.action.sa_handler));
   1195    that.action.sa_handler(signum);
   1196  } else {
   1197    DEBUG_LOG("Ignoring");
   1198  }
   1199 }
   1200 
   1201 int SEGVHandler::__wrap_sigaction(int signum, const struct sigaction* act,
   1202                                  struct sigaction* oldact) {
   1203  SEGVHandler& that = ElfLoader::Singleton;
   1204 
   1205  /* Use system sigaction() function for all but SIGSEGV signals. */
   1206  if (!that.registeredHandler || (signum != SIGSEGV))
   1207    return sys_sigaction(signum, act, oldact);
   1208 
   1209  if (oldact) *oldact = that.action;
   1210  if (act) that.action = *act;
   1211  return 0;
   1212 }