1a02c0d94Savl-llvm //===- Utils.h --------------------------------------------------*- C++ -*-===// 2a02c0d94Savl-llvm // 3a02c0d94Savl-llvm // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a02c0d94Savl-llvm // See https://llvm.org/LICENSE.txt for license information. 5a02c0d94Savl-llvm // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a02c0d94Savl-llvm // 7a02c0d94Savl-llvm //===----------------------------------------------------------------------===// 8a02c0d94Savl-llvm 9a02c0d94Savl-llvm #ifndef LLVM_DWARFLINKER_UTILS_H 10a02c0d94Savl-llvm #define LLVM_DWARFLINKER_UTILS_H 11a02c0d94Savl-llvm 12a02c0d94Savl-llvm #include "llvm/ADT/SmallString.h" 13a02c0d94Savl-llvm #include "llvm/ADT/Twine.h" 14a02c0d94Savl-llvm #include "llvm/Support/Error.h" 15a02c0d94Savl-llvm #include "llvm/Support/FileSystem.h" 16a02c0d94Savl-llvm #include "llvm/Support/Path.h" 17a02c0d94Savl-llvm 18a02c0d94Savl-llvm namespace llvm { 19a02c0d94Savl-llvm namespace dwarf_linker { 20a02c0d94Savl-llvm 21a02c0d94Savl-llvm /// This function calls \p Iteration() until it returns false. 22a02c0d94Savl-llvm /// If number of iterations exceeds \p MaxCounter then an Error is returned. 23a02c0d94Savl-llvm /// This function should be used for loops which assumed to have number of 24a02c0d94Savl-llvm /// iterations significantly smaller than \p MaxCounter to avoid infinite 25a02c0d94Savl-llvm /// looping in error cases. 26a02c0d94Savl-llvm inline Error finiteLoop(function_ref<Expected<bool>()> Iteration, 27a02c0d94Savl-llvm size_t MaxCounter = 100000) { 28a02c0d94Savl-llvm size_t iterationsCounter = 0; 29a02c0d94Savl-llvm while (iterationsCounter++ < MaxCounter) { 30a02c0d94Savl-llvm Expected<bool> IterationResultOrError = Iteration(); 31a02c0d94Savl-llvm if (!IterationResultOrError) 32a02c0d94Savl-llvm return IterationResultOrError.takeError(); 33a02c0d94Savl-llvm if (!IterationResultOrError.get()) 34a02c0d94Savl-llvm return Error::success(); 35a02c0d94Savl-llvm } 36a02c0d94Savl-llvm return createStringError(std::errc::invalid_argument, "Infinite recursion"); 37a02c0d94Savl-llvm } 38a02c0d94Savl-llvm 39a02c0d94Savl-llvm /// Make a best effort to guess the 40f8cc183eSAdrian Prantl /// Xcode.app/Contents/Developer path from an SDK path. guessDeveloperDir(StringRef SysRoot)41f8cc183eSAdrian Prantlinline StringRef guessDeveloperDir(StringRef SysRoot) { 42a02c0d94Savl-llvm // Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk 43f8cc183eSAdrian Prantl auto it = sys::path::rbegin(SysRoot); 44f8cc183eSAdrian Prantl auto end = sys::path::rend(SysRoot); 45f8cc183eSAdrian Prantl if (it == end || !it->ends_with(".sdk")) 46f8cc183eSAdrian Prantl return {}; 47f8cc183eSAdrian Prantl ++it; 48f8cc183eSAdrian Prantl // Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs 49f8cc183eSAdrian Prantl if (it == end || *it != "SDKs") 50f8cc183eSAdrian Prantl return {}; 51f8cc183eSAdrian Prantl auto developerEnd = it; 52f8cc183eSAdrian Prantl ++it; 53f8cc183eSAdrian Prantl while (it != end) { 54f8cc183eSAdrian Prantl // Contents/Developer/Platforms/MacOSX.platform/Developer 55f8cc183eSAdrian Prantl if (*it != "Developer") 56f8cc183eSAdrian Prantl return {}; 57f8cc183eSAdrian Prantl ++it; 58f8cc183eSAdrian Prantl if (it == end) 59f8cc183eSAdrian Prantl return {}; 60f8cc183eSAdrian Prantl if (*it == "Contents") 61f8cc183eSAdrian Prantl return StringRef(SysRoot.data(), 62f8cc183eSAdrian Prantl developerEnd - sys::path::rend(SysRoot) - 1); 63f8cc183eSAdrian Prantl // Contents/Developer/Platforms/MacOSX.platform 64f8cc183eSAdrian Prantl if (!it->ends_with(".platform")) 65f8cc183eSAdrian Prantl return {}; 66f8cc183eSAdrian Prantl ++it; 67f8cc183eSAdrian Prantl // Contents/Developer/Platforms 68f8cc183eSAdrian Prantl if (it == end || *it != "Platforms") 69f8cc183eSAdrian Prantl return {}; 70f8cc183eSAdrian Prantl developerEnd = it; 71f8cc183eSAdrian Prantl ++it; 72f8cc183eSAdrian Prantl } 73f8cc183eSAdrian Prantl return {}; 74a02c0d94Savl-llvm } 75a02c0d94Savl-llvm 76*22ada554SAdrian Prantl /// Make a best effort to determine whether Path is inside a toolchain. isInToolchainDir(StringRef Path)77*22ada554SAdrian Prantlinline bool isInToolchainDir(StringRef Path) { 78*22ada554SAdrian Prantl // Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2024-05-15-a.xctoolchain/usr/lib/swift/macosx/_StringProcessing.swiftmodule/arm64-apple-macos.private.swiftinterface 79*22ada554SAdrian Prantl for (auto it = sys::path::rbegin(Path), end = sys::path::rend(Path); 80*22ada554SAdrian Prantl it != end; ++it) { 81*22ada554SAdrian Prantl if (it->ends_with(".xctoolchain")) { 82*22ada554SAdrian Prantl ++it; 83*22ada554SAdrian Prantl if (it == end) 84*22ada554SAdrian Prantl return false; 85*22ada554SAdrian Prantl if (*it != "Toolchains") 86*22ada554SAdrian Prantl return false; 87*22ada554SAdrian Prantl ++it; 88*22ada554SAdrian Prantl if (it == end) 89*22ada554SAdrian Prantl return false; 90*22ada554SAdrian Prantl if (*it != "Developer") 91*22ada554SAdrian Prantl return false; 92*22ada554SAdrian Prantl return true; 93*22ada554SAdrian Prantl } 94*22ada554SAdrian Prantl } 95*22ada554SAdrian Prantl return false; 96*22ada554SAdrian Prantl } 97*22ada554SAdrian Prantl isPathAbsoluteOnWindowsOrPosix(const Twine & Path)98a02c0d94Savl-llvminline bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) { 99a02c0d94Savl-llvm // Debug info can contain paths from any OS, not necessarily 100a02c0d94Savl-llvm // an OS we're currently running on. Moreover different compilation units can 101a02c0d94Savl-llvm // be compiled on different operating systems and linked together later. 102a02c0d94Savl-llvm return sys::path::is_absolute(Path, sys::path::Style::posix) || 103a02c0d94Savl-llvm sys::path::is_absolute(Path, sys::path::Style::windows); 104a02c0d94Savl-llvm } 105a02c0d94Savl-llvm 106a02c0d94Savl-llvm } // end of namespace dwarf_linker 107a02c0d94Savl-llvm } // end of namespace llvm 108a02c0d94Savl-llvm 109a02c0d94Savl-llvm #endif // LLVM_DWARFLINKER_UTILS_H 110