diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -174,6 +174,8 @@ bool zeroModTime = false; + llvm::StringRef osoPrefix; + llvm::MachO::Architecture arch() const { return platformInfo.target.Arch; } llvm::MachO::PlatformKind platform() const { diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1095,6 +1095,29 @@ depTracker = make(args.getLastArgValue(OPT_dependency_info)); + config->osoPrefix = args.getLastArgValue(OPT_oso_prefix); + if (!config->osoPrefix.empty()) { + // Expand special characters, such as ".", "..", or "~", if present. + // Note: LD64 only expands "." and not other special characters. + // That seems silly to imitate so we will not try to follow it, but rather + // just use real_path() to do it. + + // The max path length is 4096, in theory. However that seems quite long + // and seems unlikely that any one would want to strip everything from the + // path. Hence we've picked a reasonably large number here. + SmallString<1024> expanded; + if (!fs::real_path(config->osoPrefix, expanded, + /*expand_tilde=*/true)) { + // Note: LD64 expands "." to be `/` + // (ie., it has a slash suffix) whereas real_path() doesn't. + // So we have to append '/' to be consistent. + StringRef sep = sys::path::get_separator(); + if (config->osoPrefix.equals(".") && !expanded.endswith(sep)) + expanded += sep; + config->osoPrefix = saver.save(expanded.str()); + } + } + // Must be set before any InputSections and Symbols are created. config->deadStrip = args.hasArg(OPT_dead_strip); diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -576,7 +576,6 @@ def oso_prefix : Separate<["-"], "oso_prefix">, MetaVarName<"">, HelpText<"Remove the prefix from OSO symbols in the debug map">, - Flags<[HelpHidden]>, Group; def add_ast_path : Separate<["-"], "add_ast_path">, MetaVarName<"">, diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -860,7 +860,10 @@ if (!file->archiveName.empty()) path.append({"(", file->getName(), ")"}); - stab.strx = stringTableSection.addString(saver.save(path.str())); + StringRef adjustedPath = saver.save(path.str()); + adjustedPath.consume_front(config->osoPrefix); + + stab.strx = stringTableSection.addString(adjustedPath); stab.desc = 1; stab.value = file->modTime; stabs.emplace_back(std::move(stab)); diff --git a/lld/test/MachO/stabs.s b/lld/test/MachO/stabs.s --- a/lld/test/MachO/stabs.s +++ b/lld/test/MachO/stabs.s @@ -50,6 +50,17 @@ # RUN: FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.o \ # RUN: -D#TEST_TIME=0x10 -D#FOO_TIME=0x20 +## Check that we emit relative path to object files in OSO entries +## when -oso_prefix is used. +# RUN: cd %t && %lld -lSystem test.o foo.o no-debug.o -oso_prefix "%t" -o %t/test-rel +# RUN: dsymutil -s %t/test-rel | grep 'N_OSO' | FileCheck %s -D#TEST_TIME=0x10 -D#FOO_TIME=0x20 --check-prefix=REL-PATH +# RUN: cd %t && %lld -lSystem test.o foo.o no-debug.o -oso_prefix "." -o %t/test-rel-dot +# RUN: dsymutil -s %t/test-rel-dot | grep 'N_OSO' | FileCheck %s -D#TEST_TIME=0x10 -D#FOO_TIME=0x20 --check-prefix=REL-DOT +## Set HOME to %t (for ~ to expand to) +# RUN: cd %t && env HOME=%t %lld -lSystem test.o foo.o no-debug.o -oso_prefix "~" -o %t/test-rel-tilde +# RUN: dsymutil -s %t/test-rel-tilde | grep 'N_OSO' | FileCheck %s -D#TEST_TIME=0x10 -D#FOO_TIME=0x20 --check-prefix=REL-PATH + + # RUN: cd %t && %lld -lSystem test.o foo.a no-debug.o -o %t/test # RUN: (llvm-objdump --section-headers %t/test; dsymutil -s %t/test) | \ # RUN: FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.a\(foo.o\) \ @@ -65,6 +76,8 @@ # CHECK: (N_SO ) 00 0000 0000000000000000 '/tmp/test.cpp' # CHECK-NEXT: (N_OSO ) 03 0001 [[#%.16x,TEST_TIME]] '[[DIR]]/test.o' +# REL-PATH: (N_OSO ) 03 0001 [[#%.16x,TEST_TIME]] '/test.o' +# REL-DOT: (N_OSO ) 03 0001 [[#%.16x,TEST_TIME]] 'test.o' # CHECK-NEXT: (N_STSYM ) [[#%.2d,MORE_DATA_ID + 1]] 0000 [[#%.16x,STATIC:]] '_static_var' # CHECK-NEXT: (N_FUN ) [[#%.2d,TEXT_ID + 1]] 0000 [[#%.16x,MAIN:]] '_main' # CHECK-NEXT: (N_FUN ) 00 0000 0000000000000006{{$}} @@ -87,6 +100,8 @@ # CHECK-NEXT: (N_SO ) 01 0000 0000000000000000{{$}} # CHECK-NEXT: (N_SO ) 00 0000 0000000000000000 '/foo.cpp' # CHECK-NEXT: (N_OSO ) 03 0001 [[#%.16x,FOO_TIME]] '[[FOO_PATH]]' +# REL-PATH-NEXT: (N_OSO ) 03 0001 [[#%.16x,FOO_TIME]] '/foo.o' +# REL-DOT-NEXT: (N_OSO ) 03 0001 [[#%.16x,FOO_TIME]] 'foo.o' # CHECK-NEXT: (N_FUN ) [[#%.2d,TEXT_ID + 1]] 0000 [[#%.16x,FOO:]] '_foo' # CHECK-NEXT: (N_FUN ) 00 0000 0000000000000001{{$}} # CHECK-NEXT: (N_SO ) 01 0000 0000000000000000{{$}}