Skip to content

Commit de66661

Browse files
Merge pull request #8820 from adrian-prantl/128571037-6.0
Fix the dsymutil heuristic for excluding system interfaces. (llvm#93745)
2 parents 7ab6dca + 346fe5a commit de66661

File tree

4 files changed

+95
-13
lines changed

4 files changed

+95
-13
lines changed

llvm/include/llvm/DWARFLinker/Utils.h

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,62 @@ inline Error finiteLoop(function_ref<Expected<bool>()> Iteration,
3737
}
3838

3939
/// Make a best effort to guess the
40-
/// Xcode.app/Contents/Developer/Toolchains/ path from an SDK path.
41-
inline SmallString<128> guessToolchainBaseDir(StringRef SysRoot) {
42-
SmallString<128> Result;
40+
/// Xcode.app/Contents/Developer path from an SDK path.
41+
inline StringRef guessDeveloperDir(StringRef SysRoot) {
4342
// Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
44-
StringRef Base = sys::path::parent_path(SysRoot);
45-
if (sys::path::filename(Base) != "SDKs")
46-
return Result;
47-
Base = sys::path::parent_path(Base);
48-
Result = Base;
49-
Result += "/Toolchains";
50-
return Result;
43+
auto it = sys::path::rbegin(SysRoot);
44+
auto end = sys::path::rend(SysRoot);
45+
if (it == end || !it->ends_with(".sdk"))
46+
return {};
47+
++it;
48+
// Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
49+
if (it == end || *it != "SDKs")
50+
return {};
51+
auto developerEnd = it;
52+
++it;
53+
while (it != end) {
54+
// Contents/Developer/Platforms/MacOSX.platform/Developer
55+
if (*it != "Developer")
56+
return {};
57+
++it;
58+
if (it == end)
59+
return {};
60+
if (*it == "Contents")
61+
return StringRef(SysRoot.data(),
62+
developerEnd - sys::path::rend(SysRoot) - 1);
63+
// Contents/Developer/Platforms/MacOSX.platform
64+
if (!it->ends_with(".platform"))
65+
return {};
66+
++it;
67+
// Contents/Developer/Platforms
68+
if (it == end || *it != "Platforms")
69+
return {};
70+
developerEnd = it;
71+
++it;
72+
}
73+
return {};
74+
}
75+
76+
/// Make a best effort to determine whether Path is inside a toolchain.
77+
inline bool isInToolchainDir(StringRef Path) {
78+
// Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2024-05-15-a.xctoolchain/usr/lib/swift/macosx/_StringProcessing.swiftmodule/arm64-apple-macos.private.swiftinterface
79+
for (auto it = sys::path::rbegin(Path), end = sys::path::rend(Path);
80+
it != end; ++it) {
81+
if (it->ends_with(".xctoolchain")) {
82+
++it;
83+
if (it == end)
84+
return false;
85+
if (*it != "Toolchains")
86+
return false;
87+
++it;
88+
if (it == end)
89+
return false;
90+
if (*it != "Developer")
91+
return false;
92+
return true;
93+
}
94+
}
95+
return false;
5196
}
5297

5398
inline bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) {

llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,10 @@ static void analyzeImportedModule(
200200
return;
201201
// Don't track interfaces that are part of the toolchain.
202202
// For example: Swift, _Concurrency, ...
203-
SmallString<128> Toolchain = guessToolchainBaseDir(SysRoot);
204-
if (!Toolchain.empty() && Path.startswith(Toolchain))
203+
StringRef DeveloperDir = guessDeveloperDir(SysRoot);
204+
if (!DeveloperDir.empty() && Path.starts_with(DeveloperDir))
205+
return;
206+
if (isInToolchainDir(Path))
205207
return;
206208
std::optional<const char *> Name =
207209
dwarf::toString(DIE.find(dwarf::DW_AT_name));

llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,14 @@ void CompileUnit::analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry) {
266266
dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_sysroot));
267267
if (SysRoot.empty())
268268
SysRoot = getSysRoot();
269-
if (!SysRoot.empty() && Path.startswith(SysRoot))
269+
if (!SysRoot.empty() && Path.starts_with(SysRoot))
270+
return;
271+
// Don't track interfaces that are part of the toolchain.
272+
// For example: Swift, _Concurrency, ...
273+
StringRef DeveloperDir = guessDeveloperDir(SysRoot);
274+
if (!DeveloperDir.empty() && Path.starts_with(DeveloperDir))
275+
return;
276+
if (isInToolchainDir(Path))
270277
return;
271278
if (std::optional<DWARFFormValue> Val = find(DieEntry, dwarf::DW_AT_name)) {
272279
Expected<const char *> Name = Val->getAsCString();

llvm/unittests/DWARFLinkerParallel/DWARFLinkerTest.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,31 @@
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/DWARFLinker/Utils.h"
10+
#include "gtest/gtest.h"
11+
12+
using namespace llvm;
13+
using namespace dwarf_linker;
14+
15+
#define DEVELOPER_DIR "/Applications/Xcode.app/Contents/Developer"
16+
17+
namespace {
18+
19+
TEST(DWARFLinker, PathTest) {
20+
EXPECT_EQ(guessDeveloperDir("/Foo"), "");
21+
EXPECT_EQ(guessDeveloperDir("Foo.sdk"), "");
22+
EXPECT_EQ(guessDeveloperDir(
23+
DEVELOPER_DIR
24+
"/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk"),
25+
DEVELOPER_DIR);
26+
EXPECT_EQ(guessDeveloperDir(DEVELOPER_DIR "/SDKs/MacOSX.sdk"), DEVELOPER_DIR);
27+
EXPECT_TRUE(
28+
isInToolchainDir("/Library/Developer/Toolchains/"
29+
"swift-DEVELOPMENT-SNAPSHOT-2024-05-15-a.xctoolchain/"
30+
"usr/lib/swift/macosx/_StringProcessing.swiftmodule/"
31+
"arm64-apple-macos.private.swiftinterface"));
32+
EXPECT_FALSE(isInToolchainDir("/Foo/not-an.xctoolchain/Bar/Baz"));
33+
}
34+
35+
} // anonymous namespace

0 commit comments

Comments
 (0)