xref: /freebsd/contrib/llvm-project/llvm/lib/Support/Unix/DynamicLibrary.inc (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric//===- Unix/DynamicLibrary.cpp - Unix DL Implementation ---------*- C++ -*-===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric//
90b57cec5SDimitry Andric// This file provides the UNIX specific implementation of DynamicLibrary.
100b57cec5SDimitry Andric//
110b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
140b57cec5SDimitry Andric#include <dlfcn.h>
150b57cec5SDimitry Andric
160b57cec5SDimitry AndricDynamicLibrary::HandleSet::~HandleSet() {
170b57cec5SDimitry Andric  // Close the libraries in reverse order.
180b57cec5SDimitry Andric  for (void *Handle : llvm::reverse(Handles))
190b57cec5SDimitry Andric    ::dlclose(Handle);
200b57cec5SDimitry Andric  if (Process)
210b57cec5SDimitry Andric    ::dlclose(Process);
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric  // llvm_shutdown called, Return to default
240b57cec5SDimitry Andric  DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker;
250b57cec5SDimitry Andric}
260b57cec5SDimitry Andric
270b57cec5SDimitry Andricvoid *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
280b57cec5SDimitry Andric  void *Handle = ::dlopen(File, RTLD_LAZY | RTLD_GLOBAL);
290b57cec5SDimitry Andric  if (!Handle) {
30*bdd1243dSDimitry Andric    if (Err)
31*bdd1243dSDimitry Andric      *Err = ::dlerror();
320b57cec5SDimitry Andric    return &DynamicLibrary::Invalid;
330b57cec5SDimitry Andric  }
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric#ifdef __CYGWIN__
360b57cec5SDimitry Andric  // Cygwin searches symbols only in the main
370b57cec5SDimitry Andric  // with the handle of dlopen(NULL, RTLD_GLOBAL).
380b57cec5SDimitry Andric  if (!File)
390b57cec5SDimitry Andric    Handle = RTLD_DEFAULT;
400b57cec5SDimitry Andric#endif
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric  return Handle;
430b57cec5SDimitry Andric}
440b57cec5SDimitry Andric
45*bdd1243dSDimitry Andricvoid DynamicLibrary::HandleSet::DLClose(void *Handle) { ::dlclose(Handle); }
460b57cec5SDimitry Andric
470b57cec5SDimitry Andricvoid *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
480b57cec5SDimitry Andric  return ::dlsym(Handle, Symbol);
490b57cec5SDimitry Andric}
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric#else // !HAVE_DLOPEN
520b57cec5SDimitry Andric
530b57cec5SDimitry AndricDynamicLibrary::HandleSet::~HandleSet() {}
540b57cec5SDimitry Andric
550b57cec5SDimitry Andricvoid *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
56*bdd1243dSDimitry Andric  if (Err)
57*bdd1243dSDimitry Andric    *Err = "dlopen() not supported on this platform";
580b57cec5SDimitry Andric  return &Invalid;
590b57cec5SDimitry Andric}
600b57cec5SDimitry Andric
61*bdd1243dSDimitry Andricvoid DynamicLibrary::HandleSet::DLClose(void *Handle) {}
620b57cec5SDimitry Andric
630b57cec5SDimitry Andricvoid *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
640b57cec5SDimitry Andric  return nullptr;
650b57cec5SDimitry Andric}
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric#endif
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric// Must declare the symbols in the global namespace.
700b57cec5SDimitry Andricstatic void *DoSearch(const char *SymbolName) {
710b57cec5SDimitry Andric#define EXPLICIT_SYMBOL(SYM)                                                   \
72*bdd1243dSDimitry Andric  extern void *SYM;                                                            \
73*bdd1243dSDimitry Andric  if (!strcmp(SymbolName, #SYM))                                               \
74*bdd1243dSDimitry Andric  return (void *)&SYM
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric  // If this is darwin, it has some funky issues, try to solve them here.  Some
770b57cec5SDimitry Andric  // important symbols are marked 'private external' which doesn't allow
780b57cec5SDimitry Andric  // SearchForAddressOfSymbol to find them.  As such, we special case them here,
790b57cec5SDimitry Andric  // there is only a small handful of them.
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric#ifdef __APPLE__
820b57cec5SDimitry Andric  {
830b57cec5SDimitry Andric    // __eprintf is sometimes used for assert() handling on x86.
840b57cec5SDimitry Andric    //
850b57cec5SDimitry Andric    // FIXME: Currently disabled when using Clang, as we don't always have our
860b57cec5SDimitry Andric    // runtime support libraries available.
870b57cec5SDimitry Andric#ifndef __clang__
880b57cec5SDimitry Andric#ifdef __i386__
890b57cec5SDimitry Andric    EXPLICIT_SYMBOL(__eprintf);
900b57cec5SDimitry Andric#endif
910b57cec5SDimitry Andric#endif
920b57cec5SDimitry Andric  }
930b57cec5SDimitry Andric#endif
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric#ifdef __CYGWIN__
960b57cec5SDimitry Andric  {
970b57cec5SDimitry Andric    EXPLICIT_SYMBOL(_alloca);
980b57cec5SDimitry Andric    EXPLICIT_SYMBOL(__main);
990b57cec5SDimitry Andric  }
1000b57cec5SDimitry Andric#endif
1010b57cec5SDimitry Andric
1020b57cec5SDimitry Andric#undef EXPLICIT_SYMBOL
1030b57cec5SDimitry Andric
1040b57cec5SDimitry Andric// This macro returns the address of a well-known, explicit symbol
1050b57cec5SDimitry Andric#define EXPLICIT_SYMBOL(SYM)                                                   \
106*bdd1243dSDimitry Andric  if (!strcmp(SymbolName, #SYM))                                               \
107*bdd1243dSDimitry Andric  return &SYM
1080b57cec5SDimitry Andric
1090b57cec5SDimitry Andric// Under glibc we have a weird situation. The stderr/out/in symbols are both
1100b57cec5SDimitry Andric// macros and global variables because of standards requirements. So, we
1110b57cec5SDimitry Andric// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
1120b57cec5SDimitry Andric#if defined(__GLIBC__)
1130b57cec5SDimitry Andric  {
1140b57cec5SDimitry Andric    EXPLICIT_SYMBOL(stderr);
1150b57cec5SDimitry Andric    EXPLICIT_SYMBOL(stdout);
1160b57cec5SDimitry Andric    EXPLICIT_SYMBOL(stdin);
1170b57cec5SDimitry Andric  }
1180b57cec5SDimitry Andric#else
1190b57cec5SDimitry Andric  // For everything else, we want to check to make sure the symbol isn't defined
1200b57cec5SDimitry Andric  // as a macro before using EXPLICIT_SYMBOL.
1210b57cec5SDimitry Andric  {
1220b57cec5SDimitry Andric#ifndef stdin
1230b57cec5SDimitry Andric    EXPLICIT_SYMBOL(stdin);
1240b57cec5SDimitry Andric#endif
1250b57cec5SDimitry Andric#ifndef stdout
1260b57cec5SDimitry Andric    EXPLICIT_SYMBOL(stdout);
1270b57cec5SDimitry Andric#endif
1280b57cec5SDimitry Andric#ifndef stderr
1290b57cec5SDimitry Andric    EXPLICIT_SYMBOL(stderr);
1300b57cec5SDimitry Andric#endif
1310b57cec5SDimitry Andric  }
1320b57cec5SDimitry Andric#endif
1330b57cec5SDimitry Andric#undef EXPLICIT_SYMBOL
1340b57cec5SDimitry Andric
1350b57cec5SDimitry Andric  return nullptr;
1360b57cec5SDimitry Andric}
137