Skip to content

Commit 2b2e858

Browse files
committed
[lld-macho] Handle filename being passed in -lto_object_path
Clang passes a filename rather than a directory in -lto_object_path when using FullLTO. Previously, it was always treated it as a directory, so lld would crash when it attempted to create temporary files inside it. Fixes #54805 Differential Revision: https://reviews.llvm.org/D129705
1 parent deac0ac commit 2b2e858

File tree

3 files changed

+62
-13
lines changed

3 files changed

+62
-13
lines changed

lld/MachO/LTO.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,22 @@ std::vector<ObjFile *> BitcodeCompiler::compile() {
138138
saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o");
139139
}
140140

141-
if (!config->ltoObjPath.empty())
142-
fs::create_directories(config->ltoObjPath);
141+
// In ThinLTO mode, Clang passes a temporary directory in -object_path_lto,
142+
// while the argument is a single file in FullLTO mode.
143+
bool objPathIsDir = true;
144+
if (!config->ltoObjPath.empty()) {
145+
if (std::error_code ec = fs::create_directories(config->ltoObjPath))
146+
fatal("cannot create LTO object path " + config->ltoObjPath + ": " +
147+
ec.message());
148+
149+
if (!fs::is_directory(config->ltoObjPath)) {
150+
objPathIsDir = false;
151+
unsigned objCount =
152+
count_if(buf, [](const SmallString<0> &b) { return !b.empty(); });
153+
if (objCount > 1)
154+
fatal("-object_path_lto must specify a directory when using ThinLTO");
155+
}
156+
}
143157

144158
std::vector<ObjFile *> ret;
145159
for (unsigned i = 0; i != maxTasks; ++i) {
@@ -149,9 +163,10 @@ std::vector<ObjFile *> BitcodeCompiler::compile() {
149163
uint32_t modTime = 0;
150164
if (!config->ltoObjPath.empty()) {
151165
filePath = config->ltoObjPath;
152-
path::append(filePath, Twine(i) + "." +
153-
getArchitectureName(config->arch()) +
154-
".lto.o");
166+
if (objPathIsDir)
167+
path::append(filePath, Twine(i) + "." +
168+
getArchitectureName(config->arch()) +
169+
".lto.o");
155170
saveBuffer(buf[i], filePath);
156171
modTime = getModTime(filePath);
157172
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
; REQUIRES: x86
2+
3+
;; Creating read-only directories with `chmod 400` isn't supported on Windows
4+
; UNSUPPORTED: system-windows
5+
6+
;; -object_path_lto specifies a directory that cannot be created
7+
; RUN: rm -rf %t && mkdir %t && mkdir %t/dir
8+
; RUN: chmod 400 %t/dir
9+
; RUN: llvm-as %s -o %t/full.o
10+
; RUN: not %lld %t/full.o -o /dev/null -object_path_lto %t/dir/dir2 2>&1 | FileCheck %s --check-prefix=READONLY -DDIR=%t/dir/dir2
11+
12+
; READONLY: error: cannot create LTO object path [[DIR]]: {{.*}}
13+
14+
;; Multiple objects need to be created, but -object_path_lto doesn't point to a directory
15+
; RUN: touch %t/out.o
16+
; RUN: opt -module-summary %s -o %t/thin.o
17+
; RUN: not %lld %t/full.o %t/thin.o -o /dev/null -object_path_lto %t/out.o 2>&1 | FileCheck %s --check-prefix=MULTIPLE
18+
19+
; MULTIPLE: error: -object_path_lto must specify a directory when using ThinLTO
20+
21+
22+
target triple = "x86_64-apple-macosx10.15.0"
23+
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
24+
25+
define void @main() {
26+
ret void
27+
}

lld/test/MachO/lto-object-path.ll

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,23 @@
88
; RUN: llvm-nm -pa %t/test | FileCheck %s --check-prefixes CHECK,NOOBJPATH
99

1010
; RUN: %lld %t/test.o -o %t/test -object_path_lto %t/lto-temps
11-
; RUN: llvm-nm -pa %t/test | FileCheck %s --check-prefixes CHECK,OBJPATH -DDIR=%t/lto-temps
11+
; RUN: llvm-nm -pa %t/test | FileCheck %s --check-prefixes CHECK,OBJPATH-DIR -DDIR=%t/lto-temps
1212

13-
; CHECK: 0000000000000000 - 00 0000 SO /tmp/test.cpp
14-
; NOOBJPATH-NEXT: 0000000000000000 - 03 0001 OSO /tmp/lto.tmp
13+
;; check that the object path can be an existing file
14+
; RUN: touch %t/lto-tmp.o
15+
; RUN: %lld %t/test.o -o %t/test -object_path_lto %t/lto-tmp.o
16+
; RUN: llvm-nm -pa %t/test | FileCheck %s --check-prefixes CHECK,OBJPATH-FILE -DFILE=%t/lto-tmp.o
17+
18+
19+
; CHECK: 0000000000000000 - 00 0000 SO /tmp/test.cpp
20+
; NOOBJPATH-NEXT: 0000000000000000 - 03 0001 OSO /tmp/lto.tmp
1521
;; check that modTime is nonzero when `-object_path_lto` is provided
16-
; OBJPATH-NEXT: {{[0-9a-f]*[1-9a-f]+[0-9a-f]*}} - 03 0001 OSO [[DIR]]/0.x86_64.lto.o
17-
; CHECK-NEXT: {{[0-9a-f]+}} - 01 0000 FUN _main
18-
; CHECK-NEXT: 0000000000000001 - 00 0000 FUN
19-
; CHECK-NEXT: 0000000000000000 - 01 0000 SO
20-
; CHECK-NEXT: {{[0-9a-f]+}} T _main
22+
; OBJPATH-DIR-NEXT: {{[0-9a-f]*[1-9a-f]+[0-9a-f]*}} - 03 0001 OSO [[DIR]]/0.x86_64.lto.o
23+
; OBJPATH-FILE-NEXT: {{[0-9a-f]*[1-9a-f]+[0-9a-f]*}} - 03 0001 OSO [[FILE]]
24+
; CHECK-NEXT: {{[0-9a-f]+}} - 01 0000 FUN _main
25+
; CHECK-NEXT: 0000000000000001 - 00 0000 FUN
26+
; CHECK-NEXT: 0000000000000000 - 01 0000 SO
27+
; CHECK-NEXT: {{[0-9a-f]+}} T _main
2128

2229
target triple = "x86_64-apple-macosx10.15.0"
2330
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

0 commit comments

Comments
 (0)