tor-browser

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

latebindingsymboltable_linux.h (5890B)


      1 /*
      2 *  Copyright (c) 2010 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #ifndef AUDIO_DEVICE_LATEBINDINGSYMBOLTABLE_LINUX_H_
     12 #define AUDIO_DEVICE_LATEBINDINGSYMBOLTABLE_LINUX_H_
     13 
     14 #include <cstddef>
     15 
     16 #include "absl/strings/string_view.h"
     17 #include "rtc_base/checks.h"
     18 
     19 // This file provides macros for creating "symbol table" classes to simplify the
     20 // dynamic loading of symbols from DLLs. Currently the implementation only
     21 // supports Linux and pure C symbols.
     22 // See talk/sound/pulseaudiosymboltable.(h|cc) for an example.
     23 
     24 namespace webrtc {
     25 namespace adm_linux {
     26 
     27 #ifdef WEBRTC_LINUX
     28 typedef void* DllHandle;
     29 
     30 const DllHandle kInvalidDllHandle = NULL;
     31 #else
     32 #error Not implemented
     33 #endif
     34 
     35 // These are helpers for use only by the class below.
     36 DllHandle InternalLoadDll(absl::string_view);
     37 
     38 void InternalUnloadDll(DllHandle handle);
     39 
     40 bool InternalLoadSymbols(DllHandle handle,
     41                         int num_symbols,
     42                         const char* const symbol_names[],
     43                         void* symbols[]);
     44 
     45 template <int SYMBOL_TABLE_SIZE,
     46          const char kDllName[],
     47          const char* const kSymbolNames[]>
     48 class LateBindingSymbolTable {
     49 public:
     50  LateBindingSymbolTable()
     51      : handle_(kInvalidDllHandle), undefined_symbols_(false) {
     52    memset(symbols_, 0, sizeof(symbols_));
     53  }
     54 
     55  ~LateBindingSymbolTable() { Unload(); }
     56 
     57  LateBindingSymbolTable(const LateBindingSymbolTable&) = delete;
     58  LateBindingSymbolTable& operator=(LateBindingSymbolTable&) = delete;
     59 
     60  static int NumSymbols() { return SYMBOL_TABLE_SIZE; }
     61 
     62  // We do not use this, but we offer it for theoretical convenience.
     63  static const char* GetSymbolName(int index) {
     64    RTC_DCHECK_LT(index, NumSymbols());
     65    return kSymbolNames[index];
     66  }
     67 
     68  bool IsLoaded() const { return handle_ != kInvalidDllHandle; }
     69 
     70  // Loads the DLL and the symbol table. Returns true iff the DLL and symbol
     71  // table loaded successfully.
     72  bool Load() {
     73    if (IsLoaded()) {
     74      return true;
     75    }
     76    if (undefined_symbols_) {
     77      // We do not attempt to load again because repeated attempts are not
     78      // likely to succeed and DLL loading is costly.
     79      return false;
     80    }
     81    handle_ = InternalLoadDll(kDllName);
     82    if (!IsLoaded()) {
     83      return false;
     84    }
     85    if (!InternalLoadSymbols(handle_, NumSymbols(), kSymbolNames, symbols_)) {
     86      undefined_symbols_ = true;
     87      Unload();
     88      return false;
     89    }
     90    return true;
     91  }
     92 
     93  void Unload() {
     94    if (!IsLoaded()) {
     95      return;
     96    }
     97    InternalUnloadDll(handle_);
     98    handle_ = kInvalidDllHandle;
     99    memset(symbols_, 0, sizeof(symbols_));
    100  }
    101 
    102  // Retrieves the given symbol. NOTE: Recommended to use LATESYM_GET below
    103  // instead of this.
    104  void* GetSymbol(int index) const {
    105    RTC_DCHECK(IsLoaded());
    106    RTC_DCHECK_LT(index, NumSymbols());
    107    return symbols_[index];
    108  }
    109 
    110 private:
    111  DllHandle handle_;
    112  bool undefined_symbols_;
    113  void* symbols_[SYMBOL_TABLE_SIZE];
    114 };
    115 
    116 // This macro must be invoked in a header to declare a symbol table class.
    117 #define LATE_BINDING_SYMBOL_TABLE_DECLARE_BEGIN(ClassName) enum {
    118 // This macro must be invoked in the header declaration once for each symbol
    119 // (recommended to use an X-Macro to avoid duplication).
    120 // This macro defines an enum with names built from the symbols, which
    121 // essentially creates a hash table in the compiler from symbol names to their
    122 // indices in the symbol table class.
    123 #define LATE_BINDING_SYMBOL_TABLE_DECLARE_ENTRY(ClassName, sym) \
    124  ClassName##_SYMBOL_TABLE_INDEX_##sym,
    125 
    126 // This macro completes the header declaration.
    127 #define LATE_BINDING_SYMBOL_TABLE_DECLARE_END(ClassName)       \
    128  ClassName##_SYMBOL_TABLE_SIZE                                \
    129  }                                                            \
    130  ;                                                            \
    131                                                               \
    132  extern const char ClassName##_kDllName[];                    \
    133  extern const char* const                                     \
    134      ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE]; \
    135                                                               \
    136  typedef ::webrtc::adm_linux::LateBindingSymbolTable<         \
    137      ClassName##_SYMBOL_TABLE_SIZE, ClassName##_kDllName,     \
    138      ClassName##_kSymbolNames>                                \
    139      ClassName;
    140 
    141 // This macro must be invoked in a .cc file to define a previously-declared
    142 // symbol table class.
    143 #define LATE_BINDING_SYMBOL_TABLE_DEFINE_BEGIN(ClassName, dllName) \
    144  const char ClassName##_kDllName[] = dllName;                     \
    145  const char* const ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE] = {
    146 // This macro must be invoked in the .cc definition once for each symbol
    147 // (recommended to use an X-Macro to avoid duplication).
    148 // This would have to use the mangled name if we were to ever support C++
    149 // symbols.
    150 #define LATE_BINDING_SYMBOL_TABLE_DEFINE_ENTRY(ClassName, sym) #sym,
    151 
    152 #define LATE_BINDING_SYMBOL_TABLE_DEFINE_END(ClassName) \
    153  }                                                     \
    154  ;
    155 
    156 // Index of a given symbol in the given symbol table class.
    157 #define LATESYM_INDEXOF(ClassName, sym) (ClassName##_SYMBOL_TABLE_INDEX_##sym)
    158 
    159 // Returns a reference to the given late-binded symbol, with the correct type.
    160 #define LATESYM_GET(ClassName, inst, sym) \
    161  (*reinterpret_cast<__typeof__(&sym)>(   \
    162      (inst)->GetSymbol(LATESYM_INDEXOF(ClassName, sym))))
    163 
    164 }  // namespace adm_linux
    165 }  // namespace webrtc
    166 
    167 #endif  // ADM_LATEBINDINGSYMBOLTABLE_LINUX_H_