Line data Source code
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 WEBRTC_AUDIO_DEVICE_LATEBINDINGSYMBOLTABLE_LINUX_H
12 : #define WEBRTC_AUDIO_DEVICE_LATEBINDINGSYMBOLTABLE_LINUX_H
13 :
14 : #include <assert.h>
15 : #include <stddef.h> // for NULL
16 : #include <string.h>
17 :
18 : #include "webrtc/base/constructormagic.h"
19 : #include "webrtc/system_wrappers/include/trace.h"
20 :
21 : // This file provides macros for creating "symbol table" classes to simplify the
22 : // dynamic loading of symbols from DLLs. Currently the implementation only
23 : // supports Linux and pure C symbols.
24 : // See talk/sound/pulseaudiosymboltable.(h|cc) for an example.
25 :
26 : namespace webrtc_adm_linux {
27 :
28 : #if defined(WEBRTC_LINUX) || defined(WEBRTC_BSD)
29 : typedef void *DllHandle;
30 :
31 : const DllHandle kInvalidDllHandle = NULL;
32 : #else
33 : #error Not implemented
34 : #endif
35 :
36 : // These are helpers for use only by the class below.
37 : DllHandle InternalLoadDll(const char dll_name[]);
38 :
39 : void InternalUnloadDll(DllHandle handle);
40 :
41 : bool InternalLoadSymbols(DllHandle handle,
42 : int num_symbols,
43 : const char *const symbol_names[],
44 : void *symbols[]);
45 :
46 : template <int SYMBOL_TABLE_SIZE,
47 : const char kDllName[],
48 : const char *const kSymbolNames[]>
49 : class LateBindingSymbolTable {
50 : public:
51 3 : LateBindingSymbolTable()
52 : : handle_(kInvalidDllHandle),
53 3 : undefined_symbols_(false) {
54 3 : memset(symbols_, 0, sizeof(symbols_));
55 3 : }
56 :
57 0 : ~LateBindingSymbolTable() {
58 0 : Unload();
59 0 : }
60 :
61 0 : static int NumSymbols() {
62 0 : return SYMBOL_TABLE_SIZE;
63 : }
64 :
65 : // We do not use this, but we offer it for theoretical convenience.
66 : static const char *GetSymbolName(int index) {
67 : assert(index < NumSymbols());
68 : return kSymbolNames[index];
69 : }
70 :
71 0 : bool IsLoaded() const {
72 0 : return handle_ != kInvalidDllHandle;
73 : }
74 :
75 : // Loads the DLL and the symbol table. Returns true iff the DLL and symbol
76 : // table loaded successfully.
77 0 : bool Load() {
78 0 : if (IsLoaded()) {
79 0 : return true;
80 : }
81 0 : if (undefined_symbols_) {
82 : // We do not attempt to load again because repeated attempts are not
83 : // likely to succeed and DLL loading is costly.
84 : //WEBRTC_TRACE(kTraceError, kTraceAudioDevice, -1,
85 : // "We know there are undefined symbols");
86 0 : return false;
87 : }
88 0 : handle_ = InternalLoadDll(kDllName);
89 0 : if (!IsLoaded()) {
90 0 : return false;
91 : }
92 0 : if (!InternalLoadSymbols(handle_, NumSymbols(), kSymbolNames, symbols_)) {
93 0 : undefined_symbols_ = true;
94 0 : Unload();
95 0 : return false;
96 : }
97 0 : return true;
98 : }
99 :
100 0 : void Unload() {
101 0 : if (!IsLoaded()) {
102 0 : return;
103 : }
104 0 : InternalUnloadDll(handle_);
105 0 : handle_ = kInvalidDllHandle;
106 0 : memset(symbols_, 0, sizeof(symbols_));
107 : }
108 :
109 : // Retrieves the given symbol. NOTE: Recommended to use LATESYM_GET below
110 : // instead of this.
111 0 : void *GetSymbol(int index) const {
112 0 : assert(IsLoaded());
113 0 : assert(index < NumSymbols());
114 0 : return symbols_[index];
115 : }
116 :
117 : private:
118 : DllHandle handle_;
119 : bool undefined_symbols_;
120 : void *symbols_[SYMBOL_TABLE_SIZE];
121 :
122 : RTC_DISALLOW_COPY_AND_ASSIGN(LateBindingSymbolTable);
123 : };
124 :
125 : // This macro must be invoked in a header to declare a symbol table class.
126 : #define LATE_BINDING_SYMBOL_TABLE_DECLARE_BEGIN(ClassName) \
127 : enum {
128 :
129 : // This macro must be invoked in the header declaration once for each symbol
130 : // (recommended to use an X-Macro to avoid duplication).
131 : // This macro defines an enum with names built from the symbols, which
132 : // essentially creates a hash table in the compiler from symbol names to their
133 : // indices in the symbol table class.
134 : #define LATE_BINDING_SYMBOL_TABLE_DECLARE_ENTRY(ClassName, sym) \
135 : ClassName##_SYMBOL_TABLE_INDEX_##sym,
136 :
137 : // This macro completes the header declaration.
138 : #define LATE_BINDING_SYMBOL_TABLE_DECLARE_END(ClassName) \
139 : ClassName##_SYMBOL_TABLE_SIZE \
140 : }; \
141 : \
142 : extern const char ClassName##_kDllName[]; \
143 : extern const char *const \
144 : ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE]; \
145 : \
146 : typedef ::webrtc_adm_linux::LateBindingSymbolTable<ClassName##_SYMBOL_TABLE_SIZE, \
147 : ClassName##_kDllName, \
148 : ClassName##_kSymbolNames> \
149 : ClassName;
150 :
151 : // This macro must be invoked in a .cc file to define a previously-declared
152 : // symbol table class.
153 : #define LATE_BINDING_SYMBOL_TABLE_DEFINE_BEGIN(ClassName, dllName) \
154 : const char ClassName##_kDllName[] = dllName; \
155 : const char *const ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE] = {
156 :
157 : // This macro must be invoked in the .cc definition once for each symbol
158 : // (recommended to use an X-Macro to avoid duplication).
159 : // This would have to use the mangled name if we were to ever support C++
160 : // symbols.
161 : #define LATE_BINDING_SYMBOL_TABLE_DEFINE_ENTRY(ClassName, sym) \
162 : #sym,
163 :
164 : #define LATE_BINDING_SYMBOL_TABLE_DEFINE_END(ClassName) \
165 : };
166 :
167 : // Index of a given symbol in the given symbol table class.
168 : #define LATESYM_INDEXOF(ClassName, sym) \
169 : (ClassName##_SYMBOL_TABLE_INDEX_##sym)
170 :
171 : // Returns a reference to the given late-binded symbol, with the correct type.
172 : #define LATESYM_GET(ClassName, inst, sym) \
173 : (*reinterpret_cast<typeof(&sym)>( \
174 : (inst)->GetSymbol(LATESYM_INDEXOF(ClassName, sym))))
175 :
176 : } // namespace webrtc_adm_linux
177 :
178 : #endif // WEBRTC_ADM_LATEBINDINGSYMBOLTABLE_LINUX_H
|