Index: 0001-fs-Prevent-symlink-destroying.patch =================================================================== --- /dev/null +++ 0001-fs-Prevent-symlink-destroying.patch @@ -0,0 +1,72 @@ +From 074d8425af1fe39b7315962af5a48585ac600d0e Mon Sep 17 00:00:00 2001 +From: Dmitry Chestnykh +Date: Fri, 6 Jan 2023 20:42:15 +0300 +Subject: [PATCH] [fs] Prevent symlink destroying. + +If we open symlink with llvm-strip then +the current behaviour is to destroy it and create +new regular file. This behaviour is different from +the behaviour of binutils strip. +The new behaviour is to modify the real file +and to keep symlink. +PR#59848 +--- + llvm/lib/Support/raw_ostream.cpp | 19 ++++++++++++++++--- + .../tools/llvm-objcopy/keep-dso-symlink.test | 7 +++++++ + 2 files changed, 23 insertions(+), 3 deletions(-) + create mode 100644 llvm/test/tools/llvm-objcopy/keep-dso-symlink.test + +diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp +index 92b15f14c62f..8cc979b33904 100644 +--- a/llvm/lib/Support/raw_ostream.cpp ++++ b/llvm/lib/Support/raw_ostream.cpp +@@ -982,17 +982,30 @@ void buffer_ostream::anchor() {} + + void buffer_unique_ostream::anchor() {} + +-Error llvm::writeToOutput(StringRef OutputFileName, ++Error llvm::writeToOutput(StringRef OutputCandidateFileName, + std::function Write) { +- if (OutputFileName == "-") ++ if (OutputCandidateFileName == "-") + return Write(outs()); + +- if (OutputFileName == "/dev/null") { ++ if (OutputCandidateFileName == "/dev/null") { + raw_null_ostream Out; + return Write(Out); + } + + unsigned Mode = sys::fs::all_read | sys::fs::all_write | sys::fs::all_exe; ++ ++ llvm::SmallString<128> RealPathOfSymlink; ++ if (sys::fs::is_symlink_file(OutputCandidateFileName)) { ++ std::error_code EC = ++ sys::fs::real_path(OutputCandidateFileName, RealPathOfSymlink); ++ if (EC) ++ return errorCodeToError(EC); ++ } ++ ++ Twine OutputFileName = RealPathOfSymlink.str().empty() ++ ? OutputCandidateFileName ++ : Twine(RealPathOfSymlink); ++ + Expected Temp = + sys::fs::TempFile::create(OutputFileName + ".temp-stream-%%%%%%", Mode); + if (!Temp) +diff --git a/llvm/test/tools/llvm-objcopy/keep-dso-symlink.test b/llvm/test/tools/llvm-objcopy/keep-dso-symlink.test +new file mode 100644 +index 000000000000..2b854cedbb00 +--- /dev/null ++++ b/llvm/test/tools/llvm-objcopy/keep-dso-symlink.test +@@ -0,0 +1,7 @@ ++# RUN: touch empty.c ++# RUN: clang empty.c -shared -o empty.so.1 ++# RUN: ln -sf empty.so.1 empty.so ++# RUN: llvm-strip --strip-unneeded empty.so ++# RUN: [ -L empty.so ] && echo "Still symlink" | FileCheck %s ++ ++; CHECK: Still symlink +-- +2.34.1 + Index: llvm/lib/Support/raw_ostream.cpp =================================================================== --- llvm/lib/Support/raw_ostream.cpp +++ llvm/lib/Support/raw_ostream.cpp @@ -982,17 +982,30 @@ void buffer_unique_ostream::anchor() {} -Error llvm::writeToOutput(StringRef OutputFileName, +Error llvm::writeToOutput(StringRef OutputCandidateFileName, std::function Write) { - if (OutputFileName == "-") + if (OutputCandidateFileName == "-") return Write(outs()); - if (OutputFileName == "/dev/null") { + if (OutputCandidateFileName == "/dev/null") { raw_null_ostream Out; return Write(Out); } unsigned Mode = sys::fs::all_read | sys::fs::all_write | sys::fs::all_exe; + + llvm::SmallString<128> RealPathOfSymlink; + if (sys::fs::is_symlink_file(OutputCandidateFileName)) { + std::error_code EC = + sys::fs::real_path(OutputCandidateFileName, RealPathOfSymlink); + if (EC) + return errorCodeToError(EC); + } + + Twine OutputFileName = RealPathOfSymlink.str().empty() + ? OutputCandidateFileName + : Twine(RealPathOfSymlink); + Expected Temp = sys::fs::TempFile::create(OutputFileName + ".temp-stream-%%%%%%", Mode); if (!Temp) Index: llvm/test/tools/llvm-objcopy/keep-dso-symlink.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-objcopy/keep-dso-symlink.test @@ -0,0 +1,8 @@ +# REQUIRES: shell +# RUN: touch empty.c +# RUN: clang empty.c -shared -o empty.so.1 +# RUN: ln -sf empty.so.1 empty.so +# RUN: llvm-strip --strip-unneeded empty.so +# RUN: [ -L empty.so ] && echo "Still symlink" | FileCheck %s + +; CHECK: Still symlink