Skip to content

Commit a60fdf7

Browse files
committed
[lld-macho] Process OSO prefix only textually in both input and output
The processing of `-oso_prefix` uses `llvm::sys::fs::real_path` from the user value, but it is later tried to be matched with the result of `make_absolute`. While `real_path` resolves special symbols like `.`, `..` and `~`, and resolves symlinks along the path, `make_absolute` does neither, causing an incompatibility in some situations. In macOS, temporary directories would normally be reported as `/var/folders/<random>`, but `/var` is in fact a symlink to `private/var`. If own is working on a temporary directory and uses `-oso_prefix .`, it will be expanded to `/private/var/folder/<random>`, while `make_absolute` will expand to `/var/folder/<random>` instead, and `-oso_prefix` will fail to remove the prefix from the `N_OSO` entries, leaving absolute paths to the temporary directory in the resulting file. This would happen in any situation in which the working directory includes a symlink, not only in temporary directories. One can change the usage of `make_absolute` to use `real_path` as well, but `real_path` will mean checking the file system for each `N_OSO` entry. The other solution is stop using `real_path` when processing `-oso_prefix` and manually expand an input of `.` like `make_absolute` will do. This second option is the one implemented here, since it is the closest to the visible behaviour of ld64 (like the removed comment notes), so it is the better one for compatibility. This means that a test that checked the usage of the tilde as `-oso_prefix` needs to be removed (since it was done by using `real_path`), and two new tests are provided checking that symlinks do not affect the result. The second test checks a change in behaviour, in which if one provides the input files with a prefix of `./`, even when using `-oso_prefix .` because the matching is textual, the `./` prefix will stay in the `N_OSO` entries. This matches the observed behaviour of ld64.
1 parent 03e902c commit a60fdf7

File tree

2 files changed

+25
-19
lines changed

2 files changed

+25
-19
lines changed

lld/MachO/Driver.cpp

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,27 +1635,23 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
16351635

16361636
config->osoPrefix = args.getLastArgValue(OPT_oso_prefix);
16371637
if (!config->osoPrefix.empty()) {
1638-
// Expand special characters, such as ".", "..", or "~", if present.
1639-
// Note: LD64 only expands "." and not other special characters.
1640-
// That seems silly to imitate so we will not try to follow it, but rather
1641-
// just use real_path() to do it.
1642-
16431638
// The max path length is 4096, in theory. However that seems quite long
16441639
// and seems unlikely that any one would want to strip everything from the
16451640
// path. Hence we've picked a reasonably large number here.
16461641
SmallString<1024> expanded;
1647-
if (!fs::real_path(config->osoPrefix, expanded,
1648-
/*expand_tilde=*/true)) {
1649-
// Note: LD64 expands "." to be `<current_dir>/`
1650-
// (ie., it has a slash suffix) whereas real_path() doesn't.
1651-
// So we have to append '/' to be consistent.
1652-
StringRef sep = sys::path::get_separator();
1653-
// real_path removes trailing slashes as part of the normalization, but
1654-
// these are meaningful for our text based stripping
1655-
if (config->osoPrefix == "." || config->osoPrefix.ends_with(sep))
1656-
expanded += sep;
1657-
config->osoPrefix = saver().save(expanded.str());
1642+
// Expand "." into the current working directory.
1643+
if (config->osoPrefix == ".") {
1644+
if (!fs::current_path(expanded)) {
1645+
// Note: LD64 expands "." to be `<current_dir>/
1646+
// (ie., it has a slash suffix) whereas current_path() doesn't.
1647+
// So we have to append '/' to be consistent because this is
1648+
// meaningful for our text based stripping.
1649+
expanded += sys::path::get_separator();
1650+
}
1651+
} else {
1652+
expanded = config->osoPrefix;
16581653
}
1654+
config->osoPrefix = saver().save(expanded.str());
16591655
}
16601656

16611657
bool pie = args.hasFlag(OPT_pie, OPT_no_pie, true);

lld/test/MachO/stabs.s

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,18 @@
6363
# RUN: dsymutil -s %t/test-rel | grep 'N_OSO' | FileCheck %s -D#TEST_TIME=0x10 -D#FOO_TIME=0x20 --check-prefix=REL-PATH-NO-SLASH
6464
# RUN: cd %t && ZERO_AR_DATE=0 %lld -lSystem test.o foo.o no-debug.o -oso_prefix "." -o %t/test-rel-dot
6565
# RUN: dsymutil -s %t/test-rel-dot | grep 'N_OSO' | FileCheck %s -D#TEST_TIME=0x10 -D#FOO_TIME=0x20 --check-prefix=REL-DOT
66-
## Set HOME to %t (for ~ to expand to)
67-
# RUN: cd %t && env HOME=%t ZERO_AR_DATE=0 %lld -lSystem test.o foo.o no-debug.o -oso_prefix "~" -o %t/test-rel-tilde
68-
# RUN: dsymutil -s %t/test-rel-tilde | grep 'N_OSO' | FileCheck %s -D#TEST_TIME=0x10 -D#FOO_TIME=0x20 --check-prefix=REL-PATH
66+
# RUN: cd %t && ZERO_AR_DATE=0 %lld -lSystem ./test.o ./foo.o ./no-debug.o -oso_prefix "." -o %t/test-rel-dot
67+
# RUN: dsymutil -s %t/test-rel-dot | grep 'N_OSO' | FileCheck %s -D#TEST_TIME=0x10 -D#FOO_TIME=0x20 --check-prefix=REL-DOT-EXPLICIT
68+
69+
## Check that symlinks are not expanded when -oso_prefix . is used.
70+
# RUN: mkdir -p %t/private/var/folders/tmp && ln -s private/var %t/var
71+
# RUN: cp %t/test.o %t/foo.o %t/no-debug.o %t/private/var/folders/tmp
72+
# RUN: env TZ=GMT touch -t "197001010000.16" %t/private/var/folders/tmp/test.o
73+
# RUN: env TZ=GMT touch -t "197001010000.32" %t/private/var/folders/tmp/foo.o
74+
# RUN: cd %t/var/folders/tmp && ZERO_AR_DATE=0 %lld -lSystem test.o foo.o no-debug.o -oso_prefix "." -o test-rel-symlink
75+
# RUN: dsymutil -s %t/private/var/folders/tmp/test-rel-symlink | grep 'N_OSO' | FileCheck %s -D#TEST_TIME=0x10 -D#FOO_TIME=0x20 --check-prefix=REL-DOT
76+
# RUN: cd %t/var/folders/tmp && ZERO_AR_DATE=0 %lld -lSystem ./test.o ./foo.o ./no-debug.o -oso_prefix "." -o test-rel-symlink
77+
# RUN: dsymutil -s %t/private/var/folders/tmp/test-rel-symlink | grep 'N_OSO' | FileCheck %s -D#TEST_TIME=0x10 -D#FOO_TIME=0x20 --check-prefix=REL-DOT-EXPLICIT
6978

7079
## Check that we don't emit DWARF or stabs when -S is used
7180
# RUN: %lld -lSystem test.o foo.o no-debug.o -S -o %t/test-no-debug
@@ -91,6 +100,7 @@
91100
# REL-PATH: (N_OSO ) 03 0001 [[#%.16x,TEST_TIME]] '/test.o'
92101
# REL-PATH-NO-SLASH: (N_OSO ) 03 0001 [[#%.16x,TEST_TIME]] 'test.o'
93102
# REL-DOT: (N_OSO ) 03 0001 [[#%.16x,TEST_TIME]] 'test.o'
103+
# REL-DOT-EXPLICIT: (N_OSO ) 03 0001 [[#%.16x,TEST_TIME]] './test.o'
94104
# CHECK-NEXT: (N_STSYM ) [[#%.2d,MORE_DATA_ID + 1]] 0000 [[#%.16x,STATIC:]] '_static_var'
95105
# CHECK-NEXT: (N_FUN ) [[#%.2d,TEXT_ID + 1]] 0000 [[#%.16x,MAIN:]] '_main'
96106
# CHECK-NEXT: (N_FUN ) 00 0000 0000000000000006{{$}}

0 commit comments

Comments
 (0)