1297eecfbSDimitry Andric //===- Utils.h --------------------------------------------------*- C++ -*-===// 2297eecfbSDimitry Andric // 3297eecfbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4297eecfbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5297eecfbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6297eecfbSDimitry Andric // 7297eecfbSDimitry Andric //===----------------------------------------------------------------------===// 8297eecfbSDimitry Andric 9297eecfbSDimitry Andric #ifndef LLVM_DWARFLINKER_UTILS_H 10297eecfbSDimitry Andric #define LLVM_DWARFLINKER_UTILS_H 11297eecfbSDimitry Andric 12297eecfbSDimitry Andric #include "llvm/ADT/SmallString.h" 13297eecfbSDimitry Andric #include "llvm/ADT/Twine.h" 14297eecfbSDimitry Andric #include "llvm/Support/Error.h" 15297eecfbSDimitry Andric #include "llvm/Support/FileSystem.h" 16297eecfbSDimitry Andric #include "llvm/Support/Path.h" 17297eecfbSDimitry Andric 18297eecfbSDimitry Andric namespace llvm { 19297eecfbSDimitry Andric namespace dwarf_linker { 20297eecfbSDimitry Andric 21297eecfbSDimitry Andric /// This function calls \p Iteration() until it returns false. 22297eecfbSDimitry Andric /// If number of iterations exceeds \p MaxCounter then an Error is returned. 23297eecfbSDimitry Andric /// This function should be used for loops which assumed to have number of 24297eecfbSDimitry Andric /// iterations significantly smaller than \p MaxCounter to avoid infinite 25297eecfbSDimitry Andric /// looping in error cases. 26297eecfbSDimitry Andric inline Error finiteLoop(function_ref<Expected<bool>()> Iteration, 27297eecfbSDimitry Andric size_t MaxCounter = 100000) { 28297eecfbSDimitry Andric size_t iterationsCounter = 0; 29297eecfbSDimitry Andric while (iterationsCounter++ < MaxCounter) { 30297eecfbSDimitry Andric Expected<bool> IterationResultOrError = Iteration(); 31297eecfbSDimitry Andric if (!IterationResultOrError) 32297eecfbSDimitry Andric return IterationResultOrError.takeError(); 33297eecfbSDimitry Andric if (!IterationResultOrError.get()) 34297eecfbSDimitry Andric return Error::success(); 35297eecfbSDimitry Andric } 36297eecfbSDimitry Andric return createStringError(std::errc::invalid_argument, "Infinite recursion"); 37297eecfbSDimitry Andric } 38297eecfbSDimitry Andric 39297eecfbSDimitry Andric /// Make a best effort to guess the 40*0fca6ea1SDimitry Andric /// Xcode.app/Contents/Developer path from an SDK path. 41*0fca6ea1SDimitry Andric inline StringRef guessDeveloperDir(StringRef SysRoot) { 42297eecfbSDimitry Andric // Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk 43*0fca6ea1SDimitry Andric auto it = sys::path::rbegin(SysRoot); 44*0fca6ea1SDimitry Andric auto end = sys::path::rend(SysRoot); 45*0fca6ea1SDimitry Andric if (it == end || !it->ends_with(".sdk")) 46*0fca6ea1SDimitry Andric return {}; 47*0fca6ea1SDimitry Andric ++it; 48*0fca6ea1SDimitry Andric // Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs 49*0fca6ea1SDimitry Andric if (it == end || *it != "SDKs") 50*0fca6ea1SDimitry Andric return {}; 51*0fca6ea1SDimitry Andric auto developerEnd = it; 52*0fca6ea1SDimitry Andric ++it; 53*0fca6ea1SDimitry Andric while (it != end) { 54*0fca6ea1SDimitry Andric // Contents/Developer/Platforms/MacOSX.platform/Developer 55*0fca6ea1SDimitry Andric if (*it != "Developer") 56*0fca6ea1SDimitry Andric return {}; 57*0fca6ea1SDimitry Andric ++it; 58*0fca6ea1SDimitry Andric if (it == end) 59*0fca6ea1SDimitry Andric return {}; 60*0fca6ea1SDimitry Andric if (*it == "Contents") 61*0fca6ea1SDimitry Andric return StringRef(SysRoot.data(), 62*0fca6ea1SDimitry Andric developerEnd - sys::path::rend(SysRoot) - 1); 63*0fca6ea1SDimitry Andric // Contents/Developer/Platforms/MacOSX.platform 64*0fca6ea1SDimitry Andric if (!it->ends_with(".platform")) 65*0fca6ea1SDimitry Andric return {}; 66*0fca6ea1SDimitry Andric ++it; 67*0fca6ea1SDimitry Andric // Contents/Developer/Platforms 68*0fca6ea1SDimitry Andric if (it == end || *it != "Platforms") 69*0fca6ea1SDimitry Andric return {}; 70*0fca6ea1SDimitry Andric developerEnd = it; 71*0fca6ea1SDimitry Andric ++it; 72*0fca6ea1SDimitry Andric } 73*0fca6ea1SDimitry Andric return {}; 74*0fca6ea1SDimitry Andric } 75*0fca6ea1SDimitry Andric 76*0fca6ea1SDimitry Andric /// Make a best effort to determine whether Path is inside a toolchain. 77*0fca6ea1SDimitry Andric inline bool isInToolchainDir(StringRef Path) { 78*0fca6ea1SDimitry Andric // Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2024-05-15-a.xctoolchain/usr/lib/swift/macosx/_StringProcessing.swiftmodule/arm64-apple-macos.private.swiftinterface 79*0fca6ea1SDimitry Andric for (auto it = sys::path::rbegin(Path), end = sys::path::rend(Path); 80*0fca6ea1SDimitry Andric it != end; ++it) { 81*0fca6ea1SDimitry Andric if (it->ends_with(".xctoolchain")) { 82*0fca6ea1SDimitry Andric ++it; 83*0fca6ea1SDimitry Andric if (it == end) 84*0fca6ea1SDimitry Andric return false; 85*0fca6ea1SDimitry Andric if (*it != "Toolchains") 86*0fca6ea1SDimitry Andric return false; 87*0fca6ea1SDimitry Andric ++it; 88*0fca6ea1SDimitry Andric if (it == end) 89*0fca6ea1SDimitry Andric return false; 90*0fca6ea1SDimitry Andric if (*it != "Developer") 91*0fca6ea1SDimitry Andric return false; 92*0fca6ea1SDimitry Andric return true; 93*0fca6ea1SDimitry Andric } 94*0fca6ea1SDimitry Andric } 95*0fca6ea1SDimitry Andric return false; 96297eecfbSDimitry Andric } 97297eecfbSDimitry Andric 98297eecfbSDimitry Andric inline bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) { 99297eecfbSDimitry Andric // Debug info can contain paths from any OS, not necessarily 100297eecfbSDimitry Andric // an OS we're currently running on. Moreover different compilation units can 101297eecfbSDimitry Andric // be compiled on different operating systems and linked together later. 102297eecfbSDimitry Andric return sys::path::is_absolute(Path, sys::path::Style::posix) || 103297eecfbSDimitry Andric sys::path::is_absolute(Path, sys::path::Style::windows); 104297eecfbSDimitry Andric } 105297eecfbSDimitry Andric 106297eecfbSDimitry Andric } // end of namespace dwarf_linker 107297eecfbSDimitry Andric } // end of namespace llvm 108297eecfbSDimitry Andric 109297eecfbSDimitry Andric #endif // LLVM_DWARFLINKER_UTILS_H 110