Skip to content

Commit d2f4a98

Browse files
committed
[Autolink Extract] Keep a set of linker flags instead of vector
Otherwise we can duplicate linker flags across input binaries, which can result in very large linkerr invocation commands. Resolves #58380
1 parent 415c5c1 commit d2f4a98

File tree

2 files changed

+26
-9
lines changed

2 files changed

+26
-9
lines changed

lib/DriverTool/autolink_extract_main.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <string>
2020
#include <vector>
21+
#include <unordered_set>
2122

2223
#include "swift/AST/DiagnosticsFrontend.h"
2324
#include "swift/Frontend/Frontend.h"
@@ -112,6 +113,7 @@ class AutolinkExtractInvocation {
112113
/// Return 'true' if there was an error, and 'false' otherwise.
113114
static bool
114115
extractLinkerFlagsFromObjectFile(const llvm::object::ObjectFile *ObjectFile,
116+
std::unordered_set<std::string> &SeenLinkerFlags,
115117
std::vector<std::string> &LinkerFlags,
116118
CompilerInstance &Instance) {
117119
// Search for the section we hold autolink entries in
@@ -140,8 +142,11 @@ extractLinkerFlagsFromObjectFile(const llvm::object::ObjectFile *ObjectFile,
140142
llvm::SmallVector<llvm::StringRef, 4> SplitFlags;
141143
SectionData->split(SplitFlags, llvm::StringRef("\0", 1), -1,
142144
/*KeepEmpty=*/false);
143-
for (const auto &Flag : SplitFlags)
144-
LinkerFlags.push_back(Flag.str());
145+
for (const auto &Flag : SplitFlags) {
146+
auto SeenFlagsInsertResult = SeenLinkerFlags.insert(Flag.str());
147+
if (SeenFlagsInsertResult.second == true)
148+
LinkerFlags.push_back(Flag.str());
149+
}
145150
}
146151
}
147152
return false;
@@ -152,6 +157,7 @@ extractLinkerFlagsFromObjectFile(const llvm::object::ObjectFile *ObjectFile,
152157
/// 'true' if there was an error, and 'false' otherwise.
153158
static bool
154159
extractLinkerFlagsFromObjectFile(const llvm::object::WasmObjectFile *ObjectFile,
160+
std::unordered_set<std::string> &SeenLinkerFlags,
155161
std::vector<std::string> &LinkerFlags,
156162
CompilerInstance &Instance) {
157163
// Search for the data segment we hold autolink entries in
@@ -164,8 +170,11 @@ extractLinkerFlagsFromObjectFile(const llvm::object::WasmObjectFile *ObjectFile,
164170
llvm::SmallVector<llvm::StringRef, 4> SplitFlags;
165171
SegmentData.split(SplitFlags, llvm::StringRef("\0", 1), -1,
166172
/*KeepEmpty=*/false);
167-
for (const auto &Flag : SplitFlags)
168-
LinkerFlags.push_back(Flag.str());
173+
for (const auto &Flag : SplitFlags) {
174+
auto SeenFlagsInsertResult = SeenLinkerFlags.insert(Flag.str());
175+
if (SeenFlagsInsertResult.second == true)
176+
LinkerFlags.push_back(Flag.str());
177+
}
169178
}
170179
}
171180
return false;
@@ -178,12 +187,13 @@ extractLinkerFlagsFromObjectFile(const llvm::object::WasmObjectFile *ObjectFile,
178187
static bool extractLinkerFlags(const llvm::object::Binary *Bin,
179188
CompilerInstance &Instance,
180189
StringRef BinaryFileName,
190+
std::unordered_set<std::string> &SeenLinkerFlags,
181191
std::vector<std::string> &LinkerFlags) {
182192
if (auto *ObjectFile = llvm::dyn_cast<llvm::object::ELFObjectFileBase>(Bin)) {
183-
return extractLinkerFlagsFromObjectFile(ObjectFile, LinkerFlags, Instance);
193+
return extractLinkerFlagsFromObjectFile(ObjectFile, SeenLinkerFlags, LinkerFlags, Instance);
184194
} else if (auto *ObjectFile =
185195
llvm::dyn_cast<llvm::object::WasmObjectFile>(Bin)) {
186-
return extractLinkerFlagsFromObjectFile(ObjectFile, LinkerFlags, Instance);
196+
return extractLinkerFlagsFromObjectFile(ObjectFile, SeenLinkerFlags, LinkerFlags, Instance);
187197
} else if (auto *Archive = llvm::dyn_cast<llvm::object::Archive>(Bin)) {
188198
llvm::Error Error = llvm::Error::success();
189199
for (const auto &Child : Archive->children(Error)) {
@@ -197,7 +207,7 @@ static bool extractLinkerFlags(const llvm::object::Binary *Bin,
197207
return true;
198208
}
199209
if (extractLinkerFlags(ChildBinary->get(), Instance, BinaryFileName,
200-
LinkerFlags)) {
210+
SeenLinkerFlags, LinkerFlags)) {
201211
return true;
202212
}
203213
}
@@ -228,6 +238,7 @@ int autolink_extract_main(ArrayRef<const char *> Args, const char *Argv0,
228238
}
229239

230240
std::vector<std::string> LinkerFlags;
241+
std::unordered_set<std::string> SeenLinkerFlags;
231242

232243
// Extract the linker flags from the objects.
233244
for (const auto &BinaryFileName : Invocation.getInputFilenames()) {
@@ -245,7 +256,7 @@ int autolink_extract_main(ArrayRef<const char *> Args, const char *Argv0,
245256
}
246257

247258
if (extractLinkerFlags(BinaryOwner->getBinary(), Instance, BinaryFileName,
248-
LinkerFlags)) {
259+
SeenLinkerFlags, LinkerFlags)) {
249260
return 1;
250261
}
251262
}

test/AutolinkExtract/import.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swiftc_driver -emit-module -emit-module-path %t/empty.swiftmodule -module-name empty -module-link-name empty %S/empty.swift
33
// RUN: %target-swiftc_driver -c %s -I %t -o %t/import_experimental.o
4-
// RUN: %target-swift-autolink-extract %t/import_experimental.o -o - | %FileCheck --check-prefix CHECK-%target-object-format %s
4+
// RUN: %target-swiftc_driver -c %s -I %t -o %t/import_experimental_again.o
5+
// RUN: %target-swift-autolink-extract %t/import_experimental.o %t/import_experimental_again.o -o - | %FileCheck --check-prefix CHECK-%target-object-format %s
6+
7+
// RUN: %target-swift-autolink-extract %t/import_experimental.o %t/import_experimental_again.o -o - | %FileCheck --check-prefix UNIQUE %s
58

69
// REQUIRES: autolink-extract
710

11+
// UNIQUE-COUNT-1: -lempty
12+
// UNIQUE-COUNT-1: -lswiftCore
13+
814
// CHECK-elf-DAG: -lswiftCore
915
// CHECK-elf-DAG: -lempty
1016

0 commit comments

Comments
 (0)