[lld] [lld-macho] Process OSO prefix only textually in both input and output (PR #152063)

Daniel Rodríguez Troitiño via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 5 13:13:26 PDT 2025


================
@@ -1635,27 +1635,23 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
 
   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 `<current_dir>/`
-      // (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();
-      // real_path removes trailing slashes as part of the normalization, but
-      // these are meaningful for our text based stripping
-      if (config->osoPrefix == "." || config->osoPrefix.ends_with(sep))
-        expanded += sep;
-      config->osoPrefix = saver().save(expanded.str());
+    // Expand "." into the current working directory.
+    if (config->osoPrefix == ".") {
+      if (!fs::current_path(expanded)) {
+        // Note: LD64 expands "." to be `<current_dir>/
+        // (ie., it has a slash suffix) whereas current_path() doesn't.
+        // So we have to append '/' to be consistent because this is
+        // meaningful for our text based stripping.
+        expanded += sys::path::get_separator();
+      }
+    } else {
+      expanded = config->osoPrefix;
----------------
drodriguez wrote:

The main reason is because ld64 doesn't do it, as you pointed in the comment.

The secondary reason is that

https://github.com/llvm/llvm-project/blob/d478502a420c75ca6c52205a58e465998a249826/lld/MachO/SyntheticSections.cpp#L1177-L1196

uses `make_absolute`, which does not do the expansion of `.`, `~` or the contraction of `..`, but tries to remove the post-processed value of `-oso_prefix` as a string, and that causes divergences when the value of `real_path(".")` and `make_absolute(".")` are not the same (like it happens when the current working directory is part of a symlinked folder. Either both sides use `real_path` or both sides use `make_absolute`, but one cannot use different functions in each side.

I preferred to use `current_path` here (which is what `make_absolute` uses underneath) to match both sides, which seems to be more similar to what ld64 does under the hood, and avoids the file system access that `real_path` will need for each path component.

https://github.com/llvm/llvm-project/pull/152063


More information about the llvm-commits mailing list