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.
Details
- Reviewers
int3 - Group Reviewers
Restricted Project - Commits
- rG2b2e858e9cbb: [lld-macho] Handle filename being passed in -lto_object_path
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
lld/MachO/LTO.cpp | ||
---|---|---|
145 | create_directories is fine if the directory already exists, so this check isn't necessary More generally, the nice way to do FS operations is to attempt things first and then handle any errors. It doesn't really matter in this case, but there's always the possibility that e.g. a directory gets removed by say tmpcleaner between your check and the actual dir creation attempt. (And it's my bad for not adding any error checking for the existing create_directories call...) So my suggestion is to do the create_directories call first and then dispatch on its std::error_code return value to determine objPathIsDir. | |
150–153 | hm, I wonder if there's a more elegant way of checking whether full or thinLTO is being used. Is this an idiom used elsewhere in the LLVM codebase too? |
lld/MachO/LTO.cpp | ||
---|---|---|
150–153 | I looked through ld.lld's source code, and didn't see any full vs thin LTO checks there. libLTO does export a method named LTOModule::isThinLTO which is used by ld64, but I couldn't find a similar method in llvm::lto::LTO. |
lld/MachO/LTO.cpp | ||
---|---|---|
145 | I need to backtrack on this change. fs::create_directories(path) succeeds even if path is not a directory, contrary to its documentation (mkdir returns EEXIST even if the existing path is a file, we can't differentiate between files/directories that way). Looks like we can't avoid a fs::is_directory call after all. unfortunate :/ |
Re-added the fs::is_directory call; added an error message if fs::create_directories fails
lld/MachO/LTO.cpp | ||
---|---|---|
146–147 | can we have a test that covers this error condition + the one below? thanks! |
lld/MachO/LTO.cpp | ||
---|---|---|
146–147 | Sure! For the "cannot create LTO object path" case, I will pass a read-only directory in -object_path_lto. For the other error, I will mix a ThinLTO and a full LTO object (which isn't handled correctly by ld64: https://openradar.appspot.com/FB10663394) |
Would it be okay to close https://github.com/llvm/llvm-project/issues/54805 with this?
As far as I can tell, the crash described there didn't have anything to do with the (invalid) --plugin-opt=-lto-embed-bitcode=optimized argument, but was due to Clang passing a temporary file instead of a directory in -lto_object_path because Full LTO was used.
create_directories is fine if the directory already exists, so this check isn't necessary
More generally, the nice way to do FS operations is to attempt things first and then handle any errors. It doesn't really matter in this case, but there's always the possibility that e.g. a directory gets removed by say tmpcleaner between your check and the actual dir creation attempt. (And it's my bad for not adding any error checking for the existing create_directories call...)
So my suggestion is to do the create_directories call first and then dispatch on its std::error_code return value to determine objPathIsDir.