From dc5370b9cc0e8c6f1bee0861cdf7d763d131d05d Mon Sep 17 00:00:00 2001 From: Frederic Riss Date: Thu, 6 Aug 2015 21:05:06 +0000 Subject: [PATCH] [dsymutil] Implement dSYM bundle creation A dSYM bundle is a file hierarchy that looks slike this: .dSYM/ Contents/ Info.plist Resources/ DWARF/ This is the default output mode of dsymutil. llvm-svn: 244270 --- .../tools/dsymutil/X86/basic-linking-bundle.test | 33 +++++++ llvm/test/tools/dsymutil/X86/multiple-inputs.test | 42 +++++--- llvm/tools/dsymutil/dsymutil.cpp | 107 +++++++++++++++++++-- 3 files changed, 165 insertions(+), 17 deletions(-) create mode 100644 llvm/test/tools/dsymutil/X86/basic-linking-bundle.test diff --git a/llvm/test/tools/dsymutil/X86/basic-linking-bundle.test b/llvm/test/tools/dsymutil/X86/basic-linking-bundle.test new file mode 100644 index 0000000..44b66fe --- /dev/null +++ b/llvm/test/tools/dsymutil/X86/basic-linking-bundle.test @@ -0,0 +1,33 @@ +REQUIRES: shell +RUN: rm -rf %T/basic-linking-bundle +RUN: mkdir -p %T/basic-linking-bundle/dsymdest +RUN: cat %p/../Inputs/basic.macho.x86_64 > %T/basic-linking-bundle/basic.macho.x86_64 + +RUN: llvm-dsymutil -oso-prepend-path=%p/.. %T/basic-linking-bundle/basic.macho.x86_64 +RUN: llvm-dwarfdump %T/basic-linking-bundle/basic.macho.x86_64.dSYM/Contents/Resources/DWARF/basic.macho.x86_64 | FileCheck %S/basic-linking-x86.test +RUN: FileCheck %s --input-file %T/basic-linking-bundle/basic.macho.x86_64.dSYM/Contents/Info.plist + +RUN: llvm-dsymutil -oso-prepend-path=%p/.. %T/basic-linking-bundle/basic.macho.x86_64 -o %T/basic-linking-bundle/dsymdest/basic.macho.x86_64.dSYM +RUN: llvm-dwarfdump %T/basic-linking-bundle/dsymdest/basic.macho.x86_64.dSYM/Contents/Resources/DWARF/basic.macho.x86_64 | FileCheck %S/basic-linking-x86.test +RUN: FileCheck %s --input-file %T/basic-linking-bundle/dsymdest/basic.macho.x86_64.dSYM/Contents/Info.plist + +CHECK: +CHECK-NEXT: +CHECK-NEXT: +CHECK-NEXT: +CHECK-NEXT: CFBundleDevelopmentRegion +CHECK-NEXT: English +CHECK-NEXT: CFBundleIdentifier +CHECK-NEXT: com.apple.xcode.dsym.basic.macho.x86_64 +CHECK-NEXT: CFBundleInfoDictionaryVersion +CHECK-NEXT: 6.0 +CHECK-NEXT: CFBundlePackageType +CHECK-NEXT: dSYM +CHECK-NEXT: CFBundleSignature +CHECK-NEXT: ???? +CHECK-NEXT: CFBundleShortVersionString +CHECK-NEXT: 1.0 +CHECK-NEXT: CFBundleVersion +CHECK-NEXT: 1 +CHECK-NEXT: +CHECK-NEXT: diff --git a/llvm/test/tools/dsymutil/X86/multiple-inputs.test b/llvm/test/tools/dsymutil/X86/multiple-inputs.test index 97f6d6d..8db8947 100644 --- a/llvm/test/tools/dsymutil/X86/multiple-inputs.test +++ b/llvm/test/tools/dsymutil/X86/multiple-inputs.test @@ -1,12 +1,32 @@ REQUIRES: shell -RUN: cat %p/../Inputs/basic.macho.x86_64 > %t1 -RUN: cat %p/../Inputs/basic-archive.macho.x86_64 > %t2 -RUN: cat %p/../Inputs/basic-lto.macho.x86_64 > %t3 -RUN: cat %p/../Inputs/basic-lto-dw4.macho.x86_64 > %t4 -RUN: llvm-dsymutil -f -oso-prepend-path=%p/.. %t1 %t2 %t3 %t4 -RUN: llvm-dwarfdump %t1.dwarf \ -RUN: | FileCheck %S/basic-linking-x86.test --check-prefix=CHECK --check-prefix=BASIC -RUN: llvm-dwarfdump %t2.dwarf \ -RUN: | FileCheck %S/basic-linking-x86.test --check-prefix=CHECK --check-prefix=ARCHIVE -RUN: llvm-dwarfdump %t3.dwarf | FileCheck %S/basic-lto-linking-x86.test -RUN: llvm-dwarfdump %t4.dwarf | FileCheck %S/basic-lto-dw4-linking-x86.test +RUN: rm -rf %T/multiple-inputs +RUN: mkdir -p %T/multiple-inputs + +RUN: cat %p/../Inputs/basic.macho.x86_64 > %T/multiple-inputs/basic.macho.x86_64 +RUN: cat %p/../Inputs/basic-archive.macho.x86_64 > %T/multiple-inputs/basic-archive.macho.x86_64 +RUN: cat %p/../Inputs/basic-lto.macho.x86_64 > %T/multiple-inputs/basic-lto.macho.x86_64 +RUN: cat %p/../Inputs/basic-lto-dw4.macho.x86_64 > %T/multiple-inputs/basic-lto-dw4.macho.x86_64 + +# Multiple inputs in flat mode +RUN: llvm-dsymutil -f -oso-prepend-path=%p/.. %T/multiple-inputs/basic.macho.x86_64 %T/multiple-inputs/basic-archive.macho.x86_64 %T/multiple-inputs/basic-lto.macho.x86_64 %T/multiple-inputs/basic-lto-dw4.macho.x86_64 +RUN: llvm-dwarfdump %T/multiple-inputs/basic.macho.x86_64.dwarf \ +RUN: | FileCheck %S/basic-linking-x86.test --check-prefix=CHECK --check-prefix=BASIC +RUN: llvm-dwarfdump %T/multiple-inputs/basic-archive.macho.x86_64.dwarf \ +RUN: | FileCheck %S/basic-linking-x86.test --check-prefix=CHECK --check-prefix=ARCHIVE +RUN: llvm-dwarfdump %T/multiple-inputs/basic-lto.macho.x86_64.dwarf | FileCheck %S/basic-lto-linking-x86.test +RUN: llvm-dwarfdump %T/multiple-inputs/basic-lto-dw4.macho.x86_64.dwarf | FileCheck %S/basic-lto-dw4-linking-x86.test + +# Multiple inputs that end up in the same named bundle +RUN: llvm-dsymutil -oso-prepend-path=%p/.. %T/multiple-inputs/basic.macho.x86_64 %T/multiple-inputs/basic-archive.macho.x86_64 %T/multiple-inputs/basic-lto.macho.x86_64 %T/multiple-inputs/basic-lto-dw4.macho.x86_64 -o %t.dSYM +RUN: llvm-dwarfdump %t.dSYM/Contents/Resources/DWARF/basic.macho.x86_64 \ +RUN: | FileCheck %S/basic-linking-x86.test --check-prefix=CHECK --check-prefix=BASIC +RUN: llvm-dwarfdump %t.dSYM/Contents/Resources/DWARF/basic-archive.macho.x86_64 \ +RUN: | FileCheck %S/basic-linking-x86.test --check-prefix=CHECK --check-prefix=ARCHIVE +RUN: llvm-dwarfdump %t.dSYM/Contents/Resources/DWARF/basic-lto.macho.x86_64 | FileCheck %S/basic-lto-linking-x86.test +RUN: llvm-dwarfdump %t.dSYM/Contents/Resources/DWARF/basic-lto-dw4.macho.x86_64 | FileCheck %S/basic-lto-dw4-linking-x86.test + +# Multiple inputs in a named bundle in flat mode... impossible. +RUN: not llvm-dsymutil -f -oso-prepend-path=%p/.. %T/multiple-inputs/basic.macho.x86_64 %T/multiple-inputs/basic-archive.macho.x86_64 %T/multiple-inputs/basic-lto.macho.x86_64 %T/multiple-inputs/basic-lto-dw4.macho.x86_64 -o %t.dSYM 2>&1 | FileCheck %s + +CHECK: error: cannot use -o with multiple inputs in flat mode + diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp index a609d19..1b89ddc 100644 --- a/llvm/tools/dsymutil/dsymutil.cpp +++ b/llvm/tools/dsymutil/dsymutil.cpp @@ -16,6 +16,7 @@ #include "MachOUtils.h" #include "dsymutil.h" #include "llvm/Object/MachO.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Options.h" @@ -84,6 +85,74 @@ static opt InputIsYAMLDebugMap( init(false), cat(DsymCategory)); } +static bool createPlistFile(llvm::StringRef BundleRoot) { + if (NoOutput) + return true; + + // Create plist file to write to. + llvm::SmallString<128> InfoPlist(BundleRoot); + llvm::sys::path::append(InfoPlist, "Contents/Info.plist"); + std::error_code EC; + llvm::raw_fd_ostream PL(InfoPlist, EC, llvm::sys::fs::F_Text); + if (EC) { + llvm::errs() << "error: cannot create plist file " << InfoPlist << ": " + << EC.message() << '\n'; + return false; + } + + // FIXME: Use CoreFoundation to get executable bundle info. Use + // dummy values for now. + std::string bundleVersionStr = "1", bundleShortVersionStr = "1.0", + bundleIDStr; + + llvm::StringRef BundleID = *llvm::sys::path::rbegin(BundleRoot); + if (llvm::sys::path::extension(BundleRoot) == ".dSYM") + bundleIDStr = llvm::sys::path::stem(BundleID); + else + bundleIDStr = BundleID; + + // Print out information to the plist file. + PL << "\n" + << "\n" + << "\n" + << "\t\n" + << "\t\tCFBundleDevelopmentRegion\n" + << "\t\tEnglish\n" + << "\t\tCFBundleIdentifier\n" + << "\t\tcom.apple.xcode.dsym." << bundleIDStr << "\n" + << "\t\tCFBundleInfoDictionaryVersion\n" + << "\t\t6.0\n" + << "\t\tCFBundlePackageType\n" + << "\t\tdSYM\n" + << "\t\tCFBundleSignature\n" + << "\t\t\?\?\?\?\n" + << "\t\tCFBundleShortVersionString\n" + << "\t\t" << bundleShortVersionStr << "\n" + << "\t\tCFBundleVersion\n" + << "\t\t" << bundleVersionStr << "\n" + << "\t\n" + << "\n"; + + PL.close(); + return true; +} + +static bool createBundleDir(llvm::StringRef BundleBase) { + if (NoOutput) + return true; + + llvm::SmallString<128> Bundle(BundleBase); + llvm::sys::path::append(Bundle, "Contents", "Resources", "DWARF"); + if (std::error_code EC = create_directories(Bundle.str(), true, + llvm::sys::fs::perms::all_all)) { + llvm::errs() << "error: cannot create directory " << Bundle << ": " + << EC.message() << "\n"; + return false; + } + return true; +} + static std::error_code getUniqueFile(const llvm::Twine &Model, int &ResultFD, llvm::SmallVectorImpl &ResultPath) { // If in NoOutput mode, use the createUniqueFile variant that @@ -99,7 +168,9 @@ static std::error_code getUniqueFile(const llvm::Twine &Model, int &ResultFD, static std::string getOutputFileName(llvm::StringRef InputFile, bool TempFile = false) { if (TempFile) { - llvm::Twine OutputFile = InputFile + ".tmp%%%%%%.dwarf"; + llvm::StringRef Basename = + OutputFileOpt.empty() ? InputFile : llvm::StringRef(OutputFileOpt); + llvm::Twine OutputFile = Basename + ".tmp%%%%%%.dwarf"; int FD; llvm::SmallString<128> UniqueFile; if (auto EC = getUniqueFile(OutputFile, FD, UniqueFile)) { @@ -116,12 +187,36 @@ static std::string getOutputFileName(llvm::StringRef InputFile, return UniqueFile.str(); } - if (OutputFileOpt.empty()) { - if (InputFile == "-") - return "a.out.dwarf"; - return (InputFile + ".dwarf").str(); + if (FlatOut) { + // If a flat dSYM has been requested, things are pretty simple. + if (OutputFileOpt.empty()) { + if (InputFile == "-") + return "a.out.dwarf"; + return (InputFile + ".dwarf").str(); + } + + return OutputFileOpt; } - return OutputFileOpt; + + // We need to create/update a dSYM bundle. + // A bundle hierarchy looks like this: + // .dSYM/ + // Contents/ + // Info.plist + // Resources/ + // DWARF/ + // + std::string DwarfFile = + InputFile == "-" ? llvm::StringRef("a.out") : InputFile; + llvm::SmallString<128> BundleDir(OutputFileOpt); + if (BundleDir.empty()) + BundleDir = DwarfFile + ".dSYM"; + if (!createBundleDir(BundleDir) || !createPlistFile(BundleDir)) + return ""; + + llvm::sys::path::append(BundleDir, "Contents", "Resources", "DWARF", + llvm::sys::path::filename(DwarfFile)); + return BundleDir.str(); } void llvm::dsymutil::exitDsymutil(int ExitStatus) { -- 2.7.4