diff options
Diffstat (limited to 'tools/libclang/CIndexer.cpp')
-rw-r--r-- | tools/libclang/CIndexer.cpp | 77 |
1 files changed, 67 insertions, 10 deletions
diff --git a/tools/libclang/CIndexer.cpp b/tools/libclang/CIndexer.cpp index 3c6e1530f1..0054c15bc7 100644 --- a/tools/libclang/CIndexer.cpp +++ b/tools/libclang/CIndexer.cpp @@ -1,9 +1,8 @@ -//===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===// +//===- CIndexer.cpp - Clang-C Source Indexing Library ---------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -15,6 +14,7 @@ #include "CXString.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/Version.h" +#include "clang/Driver/Driver.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/MD5.h" @@ -32,12 +32,69 @@ #ifdef _WIN32 #include <windows.h> +#elif defined(_AIX) +#include <errno.h> +#include <sys/ldr.h> #else #include <dlfcn.h> #endif using namespace clang; +#ifdef _AIX +namespace clang { +namespace { + +template <typename LibClangPathType> +void getClangResourcesPathImplAIX(LibClangPathType &LibClangPath) { + int PrevErrno = errno; + + size_t BufSize = 2048u; + std::unique_ptr<char[]> Buf; + while (true) { + Buf = llvm::make_unique<char []>(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<uintptr_t &>(clang_createTranslationUnit); + + // Loop to locate the function entry point in the loadquery() results. + ld_xinfo *CurInfo = reinterpret_cast<ld_xinfo *>(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<ld_xinfo *>(reinterpret_cast<char *>(CurInfo) + + CurInfo->ldinfo_next); + } + + LibClangPath += reinterpret_cast<char *>(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()) @@ -63,7 +120,9 @@ const std::string &CIndexer::getClangResourcesPath() { #endif #endif - LibClangPath += llvm::sys::path::parent_path(path); + LibClangPath += path; +#elif defined(_AIX) + getClangResourcesPathImplAIX(LibClangPath); #else // This silly cast below avoids a C++ warning. Dl_info info; @@ -71,13 +130,11 @@ const std::string &CIndexer::getClangResourcesPath() { llvm_unreachable("Call to dladdr() failed"); // We now have the CIndex directory, locate clang relative to it. - LibClangPath += llvm::sys::path::parent_path(info.dli_fname); + LibClangPath += info.dli_fname; #endif - llvm::sys::path::append(LibClangPath, "clang", CLANG_VERSION_STRING); - // Cache our result. - ResourcesPath = LibClangPath.str(); + ResourcesPath = driver::Driver::GetResourcesPath(LibClangPath); return ResourcesPath; } |