From a7510baf8477c370a9710a52c7de09a8d4a5396d Mon Sep 17 00:00:00 2001 From: Hubert Tong Date: Sat, 23 Mar 2019 18:10:45 +0000 Subject: [PATCH] libclang/CIndexer.cpp: Use loadquery() on AIX for path to library Summary: `dladdr` is not available on AIX. Similar functionality is presented through `loadquery`. This patch replaces a use of `dladdr` with a version based on `loadquery`. Reviewers: sfertile, xingxue, jasonliu Reviewed By: xingxue Subscribers: jsji, lhames, majnemer, asb, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D59233 llvm-svn: 356843 --- clang/tools/libclang/CIndexer.cpp | 59 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/clang/tools/libclang/CIndexer.cpp b/clang/tools/libclang/CIndexer.cpp index 4c06b63..0054c15 100644 --- a/clang/tools/libclang/CIndexer.cpp +++ b/clang/tools/libclang/CIndexer.cpp @@ -32,12 +32,69 @@ #ifdef _WIN32 #include +#elif defined(_AIX) +#include +#include #else #include #endif using namespace clang; +#ifdef _AIX +namespace clang { +namespace { + +template +void getClangResourcesPathImplAIX(LibClangPathType &LibClangPath) { + int PrevErrno = errno; + + size_t BufSize = 2048u; + std::unique_ptr Buf; + while (true) { + Buf = llvm::make_unique(BufSize); + errno = 0; + int Ret = loadquery(L_GETXINFO, Buf.get(), (unsigned int)BufSize); + if (Ret != -1) + break; // loadquery() was successful. + if (errno != ENOMEM) + llvm_unreachable("Encountered an unexpected loadquery() failure"); + + // errno == ENOMEM; try to allocate more memory. + if ((BufSize & ~((-1u) >> 1u)) != 0u) + llvm::report_fatal_error("BufSize needed for loadquery() too large"); + + Buf.release(); + BufSize <<= 1u; + } + + // Extract the function entry point from the function descriptor. + uint64_t EntryAddr = + reinterpret_cast(clang_createTranslationUnit); + + // Loop to locate the function entry point in the loadquery() results. + ld_xinfo *CurInfo = reinterpret_cast(Buf.get()); + while (true) { + uint64_t CurTextStart = (uint64_t)CurInfo->ldinfo_textorg; + uint64_t CurTextEnd = CurTextStart + CurInfo->ldinfo_textsize; + if (CurTextStart <= EntryAddr && EntryAddr < CurTextEnd) + break; // Successfully located. + + if (CurInfo->ldinfo_next == 0u) + llvm::report_fatal_error("Cannot locate entry point in " + "the loadquery() results"); + CurInfo = reinterpret_cast(reinterpret_cast(CurInfo) + + CurInfo->ldinfo_next); + } + + LibClangPath += reinterpret_cast(CurInfo) + CurInfo->ldinfo_filename; + errno = PrevErrno; +} + +} // end anonymous namespace +} // end namespace clang +#endif + const std::string &CIndexer::getClangResourcesPath() { // Did we already compute the path? if (!ResourcesPath.empty()) @@ -64,6 +121,8 @@ const std::string &CIndexer::getClangResourcesPath() { #endif LibClangPath += path; +#elif defined(_AIX) + getClangResourcesPathImplAIX(LibClangPath); #else // This silly cast below avoids a C++ warning. Dl_info info; -- 2.7.4