147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/* 247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Copyright 2004 The WebRTC Project Authors. All rights reserved. 347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * 447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Use of this source code is governed by a BSD-style license 547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * in the file PATENTS. All contributing project authors may 847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */ 1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/latebindingsymboltable.h" 1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX) 1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <dlfcn.h> 1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h" 1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc { 2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX) 2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const DllHandle kInvalidDllHandle = NULL; 2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#error Not implemented 2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const char *GetDllError() { 2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX) 2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const char *err = dlerror(); 3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (err) { 3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return err; 3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return "No error"; 3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#error Not implemented 3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic bool LoadSymbol(DllHandle handle, 4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const char *symbol_name, 4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void **symbol) { 4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX) 4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *symbol = dlsym(handle, symbol_name); 4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const char *err = dlerror(); 4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (err) { 4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Error loading symbol " << symbol_name << ": " << err; 4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (!*symbol) { 5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // ELF allows for symbols to be NULL, but that should never happen for our 5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // usage. 5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Symbol " << symbol_name << " is NULL"; 5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#error Not implemented 5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgLateBindingSymbolTable::LateBindingSymbolTable(const TableInfo *info, 6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void **table) 6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org : info_(info), 6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org table_(table), 6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org handle_(kInvalidDllHandle), 6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org undefined_symbols_(false) { 6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ClearSymbols(); 6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgLateBindingSymbolTable::~LateBindingSymbolTable() { 7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Unload(); 7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool LateBindingSymbolTable::IsLoaded() const { 7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return handle_ != kInvalidDllHandle; 7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool LateBindingSymbolTable::Load() { 7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(info_->dll_name != NULL); 8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return LoadFromPath(info_->dll_name); 8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool LateBindingSymbolTable::LoadFromPath(const char *dll_path) { 8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (IsLoaded()) { 8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (undefined_symbols_) { 8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // We do not attempt to load again because repeated attempts are not 8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // likely to succeed and DLL loading is costly. 9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "We know there are undefined symbols"; 9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX) 9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org handle_ = dlopen(dll_path, 9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // RTLD_NOW front-loads symbol resolution so that errors are 9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // caught early instead of causing a process abort later. 9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // RTLD_LOCAL prevents other modules from automatically 9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // seeing symbol definitions in the newly-loaded tree. This 10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // is necessary for same-named symbols in different ABI 10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // versions of the same library to not explode. 10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org RTLD_NOW|RTLD_LOCAL 103f854f30d7981795f687f9b4379100c037934535dniklas.enbom@webrtc.org#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) && defined(RTLD_DEEPBIND) 10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // RTLD_DEEPBIND makes symbol dependencies in the 10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // newly-loaded tree prefer to resolve to definitions within 10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // that tree (the default on OS X). This is necessary for 10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // same-named symbols in different ABI versions of the same 10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // library to not explode. 10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org |RTLD_DEEPBIND 11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ); // NOLINT 11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#error Not implemented 11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (handle_ == kInvalidDllHandle) { 11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_WARNING) << "Can't load " << dll_path << ": " 11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << GetDllError(); 11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX) 12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Clear any old errors. 12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org dlerror(); 12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (int i = 0; i < info_->num_symbols; ++i) { 12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!LoadSymbol(handle_, info_->symbol_names[i], &table_[i])) { 12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org undefined_symbols_ = true; 12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Unload(); 12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid LateBindingSymbolTable::Unload() { 13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!IsLoaded()) { 13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX) 14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (dlclose(handle_) != 0) { 14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << GetDllError(); 14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#error Not implemented 14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org handle_ = kInvalidDllHandle; 14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ClearSymbols(); 15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid LateBindingSymbolTable::ClearSymbols() { 15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org memset(table_, 0, sizeof(void *) * info_->num_symbols); 15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc 157