diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h --- a/llvm/include/llvm/Object/MachO.h +++ b/llvm/include/llvm/Object/MachO.h @@ -652,6 +652,13 @@ return std::string(std::string(Version.str())); } + /// If the input path is a .dSYM bundle (as created by the dsymutil tool), + /// return the paths to the object files found in the bundle, otherwise return + /// an empty vector. If the path appears to be a .dSYM bundle but no objects + /// were found or there was a filesystem error, then return an error. + static Expected> + findDsymObjectMembers(StringRef Path); + private: MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, Error &Err, uint32_t UniversalCputype = 0, diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -28,10 +28,12 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/Host.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" #include "llvm/Support/SwapByteOrder.h" #include "llvm/Support/raw_ostream.h" #include @@ -4719,3 +4721,38 @@ .Case("debug_str_offs", "debug_str_offsets") .Default(Name); } + +Expected> +MachOObjectFile::findDsymObjectMembers(StringRef Path) { + SmallString<256> BundlePath(Path); + // Normalize input path. This is necessary to accept `bundle.dSYM/`. + sys::path::remove_dots(BundlePath); + if (!sys::fs::is_directory(BundlePath) || + sys::path::extension(BundlePath) != ".dSYM") + return std::vector(); + sys::path::append(BundlePath, "Contents", "Resources", "DWARF"); + std::vector ObjectPaths; + std::error_code EC; + for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd; + Dir != DirEnd && !EC; Dir.increment(EC)) { + StringRef ObjectPath = Dir->path(); + sys::fs::file_status Status; + if (auto EC = sys::fs::status(ObjectPath, Status)) + return createFileError(ObjectPath, errorCodeToError(EC)); + switch (Status.type()) { + case sys::fs::file_type::regular_file: + case sys::fs::file_type::symlink_file: + case sys::fs::file_type::type_unknown: + ObjectPaths.push_back(ObjectPath.str()); + break; + default: /*ignore*/; + } + } + if (EC) + return createFileError(BundlePath, errorCodeToError(EC)); + if (ObjectPaths.empty()) + return createStringError(std::error_code(), + "%s: no objects found in dSYM bundle", + Path.str().c_str()); + return ObjectPaths; +} diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp --- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -24,7 +24,6 @@ #include "llvm/Support/Format.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" #include "llvm/Support/Regex.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" @@ -265,6 +264,13 @@ /// @} //===----------------------------------------------------------------------===// +static void error(Error Err) { + if (!Err) + return; + WithColor::error() << toString(std::move(Err)) << "\n"; + exit(1); +} + static void error(StringRef Prefix, Error Err) { if (!Err) return; @@ -581,41 +587,6 @@ return handleBuffer(Filename, *Buffer, HandleObj, OS); } -/// If the input path is a .dSYM bundle (as created by the dsymutil tool), -/// replace it with individual entries for each of the object files inside the -/// bundle otherwise return the input path. -static std::vector expandBundle(const std::string &InputPath) { - std::vector BundlePaths; - SmallString<256> BundlePath(InputPath); - // Normalize input path. This is necessary to accept `bundle.dSYM/`. - sys::path::remove_dots(BundlePath); - // Manually open up the bundle to avoid introducing additional dependencies. - if (sys::fs::is_directory(BundlePath) && - sys::path::extension(BundlePath) == ".dSYM") { - std::error_code EC; - sys::path::append(BundlePath, "Contents", "Resources", "DWARF"); - for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd; - Dir != DirEnd && !EC; Dir.increment(EC)) { - const std::string &Path = Dir->path(); - sys::fs::file_status Status; - EC = sys::fs::status(Path, Status); - error(Path, EC); - switch (Status.type()) { - case sys::fs::file_type::regular_file: - case sys::fs::file_type::symlink_file: - case sys::fs::file_type::type_unknown: - BundlePaths.push_back(Path); - break; - default: /*ignore*/; - } - } - error(BundlePath, EC); - } - if (!BundlePaths.size()) - BundlePaths.push_back(InputPath); - return BundlePaths; -} - int main(int argc, char **argv) { InitLLVM X(argc, argv); @@ -684,8 +655,13 @@ // Expand any .dSYM bundles to the individual object files contained therein. std::vector Objects; for (const auto &F : InputFilenames) { - auto Objs = expandBundle(F); - llvm::append_range(Objects, Objs); + if (auto DsymObjectsOrErr = MachOObjectFile::findDsymObjectMembers(F)) { + if (DsymObjectsOrErr->empty()) + Objects.push_back(F); + else + llvm::append_range(Objects, *DsymObjectsOrErr); + } else + error(DsymObjectsOrErr.takeError()); } bool Success = true; diff --git a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp --- a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp +++ b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp @@ -20,7 +20,6 @@ #include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Regex.h" #include "llvm/Support/Signals.h" @@ -126,6 +125,13 @@ /// @} //===----------------------------------------------------------------------===// +static void error(Error Err) { + if (!Err) + return; + WithColor::error() << toString(std::move(Err)) << "\n"; + exit(1); +} + static void error(StringRef Prefix, llvm::Error Err) { if (!Err) return; @@ -141,39 +147,6 @@ exit(1); } -/// If the input path is a .dSYM bundle (as created by the dsymutil tool), -/// replace it with individual entries for each of the object files inside the -/// bundle otherwise return the input path. -static std::vector expandBundle(const std::string &InputPath) { - std::vector BundlePaths; - SmallString<256> BundlePath(InputPath); - // Manually open up the bundle to avoid introducing additional dependencies. - if (sys::fs::is_directory(BundlePath) && - sys::path::extension(BundlePath) == ".dSYM") { - std::error_code EC; - sys::path::append(BundlePath, "Contents", "Resources", "DWARF"); - for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd; - Dir != DirEnd && !EC; Dir.increment(EC)) { - const std::string &Path = Dir->path(); - sys::fs::file_status Status; - EC = sys::fs::status(Path, Status); - error(Path, EC); - switch (Status.type()) { - case sys::fs::file_type::regular_file: - case sys::fs::file_type::symlink_file: - case sys::fs::file_type::type_unknown: - BundlePaths.push_back(Path); - break; - default: /*ignore*/; - } - } - error(BundlePath, EC); - } - if (!BundlePaths.size()) - BundlePaths.push_back(InputPath); - return BundlePaths; -} - static uint32_t getCPUType(MachOObjectFile &MachO) { if (MachO.is64Bit()) return MachO.getHeader64().cputype; @@ -420,8 +393,14 @@ OS << "Input file: " << ConvertFilename << "\n"; - auto Objs = expandBundle(ConvertFilename); - llvm::append_range(Objects, Objs); + if (auto DsymObjectsOrErr = + MachOObjectFile::findDsymObjectMembers(ConvertFilename)) { + if (DsymObjectsOrErr->empty()) + Objects.push_back(ConvertFilename); + else + llvm::append_range(Objects, *DsymObjectsOrErr); + } else + error(DsymObjectsOrErr.takeError()); for (auto Object : Objects) { if (auto Err = handleFileConversionToGSYM(Object, OutFile))