llvm-project

Форк
0
244 строки · 7.5 Кб
1
//===- Utils.cpp ----------------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Implements utility functions for TextAPI Darwin operations.
10
//
11
//===----------------------------------------------------------------------===//
12

13
#include "llvm/TextAPI/Utils.h"
14
#include "llvm/ADT/StringExtras.h"
15
#include "llvm/TextAPI/TextAPIError.h"
16

17
using namespace llvm;
18
using namespace llvm::MachO;
19

20
void llvm::MachO::replace_extension(SmallVectorImpl<char> &Path,
21
                                    const Twine &Extension) {
22
  StringRef P(Path.begin(), Path.size());
23
  auto ParentPath = sys::path::parent_path(P);
24
  auto Filename = sys::path::filename(P);
25

26
  if (!ParentPath.ends_with(Filename.str() + ".framework")) {
27
    sys::path::replace_extension(Path, Extension);
28
    return;
29
  }
30
  // Framework dylibs do not have a file extension, in those cases the new
31
  // extension is appended. e.g. given Path: "Foo.framework/Foo" and Extension:
32
  // "tbd", the result is "Foo.framework/Foo.tbd".
33
  SmallString<8> Storage;
34
  StringRef Ext = Extension.toStringRef(Storage);
35

36
  // Append '.' if needed.
37
  if (!Ext.empty() && Ext[0] != '.')
38
    Path.push_back('.');
39

40
  // Append extension.
41
  Path.append(Ext.begin(), Ext.end());
42
}
43

44
std::error_code llvm::MachO::shouldSkipSymLink(const Twine &Path,
45
                                               bool &Result) {
46
  Result = false;
47
  SmallString<PATH_MAX> Storage;
48
  auto P = Path.toNullTerminatedStringRef(Storage);
49
  sys::fs::file_status Stat1;
50
  auto EC = sys::fs::status(P.data(), Stat1);
51
  if (EC == std::errc::too_many_symbolic_link_levels) {
52
    Result = true;
53
    return {};
54
  }
55

56
  if (EC)
57
    return EC;
58

59
  StringRef Parent = sys::path::parent_path(P);
60
  while (!Parent.empty()) {
61
    sys::fs::file_status Stat2;
62
    if (auto ec = sys::fs::status(Parent, Stat2))
63
      return ec;
64

65
    if (sys::fs::equivalent(Stat1, Stat2)) {
66
      Result = true;
67
      return {};
68
    }
69

70
    Parent = sys::path::parent_path(Parent);
71
  }
72
  return {};
73
}
74

75
std::error_code
76
llvm::MachO::make_relative(StringRef From, StringRef To,
77
                           SmallVectorImpl<char> &RelativePath) {
78
  SmallString<PATH_MAX> Src = From;
79
  SmallString<PATH_MAX> Dst = To;
80
  if (auto EC = sys::fs::make_absolute(Src))
81
    return EC;
82

83
  if (auto EC = sys::fs::make_absolute(Dst))
84
    return EC;
85

86
  SmallString<PATH_MAX> Result;
87
  Src = sys::path::parent_path(From);
88
  auto IT1 = sys::path::begin(Src), IT2 = sys::path::begin(Dst),
89
       IE1 = sys::path::end(Src), IE2 = sys::path::end(Dst);
90
  // Ignore the common part.
91
  for (; IT1 != IE1 && IT2 != IE2; ++IT1, ++IT2) {
92
    if (*IT1 != *IT2)
93
      break;
94
  }
95

96
  for (; IT1 != IE1; ++IT1)
97
    sys::path::append(Result, "../");
98

99
  for (; IT2 != IE2; ++IT2)
100
    sys::path::append(Result, *IT2);
101

102
  if (Result.empty())
103
    Result = ".";
104

105
  RelativePath.swap(Result);
106

107
  return {};
108
}
109

110
bool llvm::MachO::isPrivateLibrary(StringRef Path, bool IsSymLink) {
111
  // Remove the iOSSupport and DriverKit prefix to identify public locations.
112
  Path.consume_front(MACCATALYST_PREFIX_PATH);
113
  Path.consume_front(DRIVERKIT_PREFIX_PATH);
114
  // Also /Library/Apple prefix for ROSP.
115
  Path.consume_front("/Library/Apple");
116

117
  if (Path.starts_with("/usr/local/lib"))
118
    return true;
119

120
  if (Path.starts_with("/System/Library/PrivateFrameworks"))
121
    return true;
122

123
  // Everything in /usr/lib/swift (including sub-directories) are considered
124
  // public.
125
  if (Path.consume_front("/usr/lib/swift/"))
126
    return false;
127

128
  // Only libraries directly in /usr/lib are public. All other libraries in
129
  // sub-directories are private.
130
  if (Path.consume_front("/usr/lib/"))
131
    return Path.contains('/');
132

133
  // "/System/Library/Frameworks/" is a public location.
134
  if (Path.starts_with("/System/Library/Frameworks/")) {
135
    StringRef Name, Rest;
136
    std::tie(Name, Rest) =
137
        Path.drop_front(sizeof("/System/Library/Frameworks")).split('.');
138

139
    // Allow symlinks to top-level frameworks.
140
    if (IsSymLink && Rest == "framework")
141
      return false;
142

143
    // Only top level framework are public.
144
    // /System/Library/Frameworks/Foo.framework/Foo ==> true
145
    // /System/Library/Frameworks/Foo.framework/Versions/A/Foo ==> true
146
    // /System/Library/Frameworks/Foo.framework/Resources/libBar.dylib ==> false
147
    // /System/Library/Frameworks/Foo.framework/Frameworks/Bar.framework/Bar
148
    // ==> false
149
    // /System/Library/Frameworks/Foo.framework/Frameworks/Xfoo.framework/XFoo
150
    // ==> false
151
    return !(Rest.starts_with("framework/") &&
152
             (Rest.ends_with(Name) || Rest.ends_with((Name + ".tbd").str()) ||
153
              (IsSymLink && Rest.ends_with("Current"))));
154
  }
155
  return false;
156
}
157

158
static StringLiteral RegexMetachars = "()^$|+.[]\\{}";
159

160
llvm::Expected<Regex> llvm::MachO::createRegexFromGlob(StringRef Glob) {
161
  SmallString<128> RegexString("^");
162
  unsigned NumWildcards = 0;
163
  for (unsigned i = 0; i < Glob.size(); ++i) {
164
    char C = Glob[i];
165
    switch (C) {
166
    case '?':
167
      RegexString += '.';
168
      break;
169
    case '*': {
170
      const char *PrevChar = i > 0 ? Glob.data() + i - 1 : nullptr;
171
      NumWildcards = 1;
172
      ++i;
173
      while (i < Glob.size() && Glob[i] == '*') {
174
        ++NumWildcards;
175
        ++i;
176
      }
177
      const char *NextChar = i < Glob.size() ? Glob.data() + i : nullptr;
178

179
      if ((NumWildcards > 1) && (PrevChar == nullptr || *PrevChar == '/') &&
180
          (NextChar == nullptr || *NextChar == '/')) {
181
        RegexString += "(([^/]*(/|$))*)";
182
      } else
183
        RegexString += "([^/]*)";
184
      break;
185
    }
186
    default:
187
      if (RegexMetachars.contains(C))
188
        RegexString.push_back('\\');
189
      RegexString.push_back(C);
190
    }
191
  }
192
  RegexString.push_back('$');
193
  if (NumWildcards == 0)
194
    return make_error<StringError>("not a glob", inconvertibleErrorCode());
195

196
  llvm::Regex Rule = Regex(RegexString);
197
  std::string Error;
198
  if (!Rule.isValid(Error))
199
    return make_error<StringError>(Error, inconvertibleErrorCode());
200

201
  return std::move(Rule);
202
}
203

204
Expected<AliasMap>
205
llvm::MachO::parseAliasList(std::unique_ptr<llvm::MemoryBuffer> &Buffer) {
206
  SmallVector<StringRef, 16> Lines;
207
  AliasMap Aliases;
208
  Buffer->getBuffer().split(Lines, "\n", /*MaxSplit=*/-1,
209
                            /*KeepEmpty=*/false);
210
  for (const StringRef Line : Lines) {
211
    StringRef L = Line.trim();
212
    if (L.empty())
213
      continue;
214
    // Skip comments.
215
    if (L.starts_with("#"))
216
      continue;
217
    StringRef Symbol, Remain, Alias;
218
    // Base symbol is separated by whitespace.
219
    std::tie(Symbol, Remain) = getToken(L);
220
    // The Alias symbol ends before a comment or EOL.
221
    std::tie(Alias, Remain) = getToken(Remain, "#");
222
    Alias = Alias.trim();
223
    if (Alias.empty())
224
      return make_error<TextAPIError>(
225
          TextAPIError(TextAPIErrorCode::InvalidInputFormat,
226
                       ("missing alias for: " + Symbol).str()));
227
    SimpleSymbol AliasSym = parseSymbol(Alias);
228
    SimpleSymbol BaseSym = parseSymbol(Symbol);
229
    Aliases[{AliasSym.Name.str(), AliasSym.Kind}] = {BaseSym.Name.str(),
230
                                                     BaseSym.Kind};
231
  }
232

233
  return Aliases;
234
}
235

236
PathSeq llvm::MachO::getPathsForPlatform(const PathToPlatformSeq &Paths,
237
                                         PlatformType Platform) {
238
  PathSeq Result;
239
  for (const auto &[Path, CurrP] : Paths) {
240
    if (!CurrP.has_value() || CurrP.value() == Platform)
241
      Result.push_back(Path);
242
  }
243
  return Result;
244
}
245

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.