[dsymutil] Accept a YAML debug map as input instead of a binary.
authorFrederic Riss <friss@apple.com>
Wed, 3 Jun 2015 16:57:16 +0000 (16:57 +0000)
committerFrederic Riss <friss@apple.com>
Wed, 3 Jun 2015 16:57:16 +0000 (16:57 +0000)
To do this, the user needs to pass the new -y flag.
As it wasn't tested before, the debug map YAML deserialization was
completely buggy (mainly because the DebugMapObject has a dual
mapping that allows to search by name and by address, but only the
StringMap got populated). It's fixed and tested in this commit by
augmenting some test with a 2 stage dwarf link: a frist llvm-dsymutil
reads the debug map and pipes it in a second instance that does the
actual link without touching the initial binary.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238941 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/dsymutil/X86/basic-linking-x86.test
test/tools/dsymutil/X86/basic-lto-linking-x86.test
tools/dsymutil/DebugMap.h
tools/dsymutil/MachODebugMapParser.cpp
tools/dsymutil/dsymutil.cpp
tools/dsymutil/dsymutil.h

index 1059e233f94b9306e46bb72671363fbb4922b2f3..e6d42e464a9ccc9ec83f7bd4b2a3108f2a3a062b 100644 (file)
@@ -6,6 +6,8 @@ RUN: llvm-dsymutil -o %t2 -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_6
 RUN: llvm-dwarfdump %t2 | FileCheck %s
 RUN: llvm-dsymutil -o - -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_64 | llvm-dwarfdump - | FileCheck %s --check-prefix=CHECK --check-prefix=BASIC
 RUN: llvm-dsymutil -o - -oso-prepend-path=%p/.. %p/../Inputs/basic-archive.macho.x86_64 | llvm-dwarfdump - | FileCheck %s --check-prefix=CHECK --check-prefix=ARCHIVE
+RUN: llvm-dsymutil -dump-debug-map -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_64 | llvm-dsymutil -y -o - - | llvm-dwarfdump - | FileCheck %s --check-prefix=CHECK --check-prefix=BASIC
+RUN: llvm-dsymutil -dump-debug-map -oso-prepend-path=%p/.. %p/../Inputs/basic-archive.macho.x86_64 | llvm-dsymutil -o - -oso-prepend-path=%p/.. -y - | llvm-dwarfdump - | FileCheck %s --check-prefix=CHECK --check-prefix=ARCHIVE
 
 CHECK: file format Mach-O 64-bit x86-64
 
index 22b6e0808d8a5d1df2bf8bd9f1b54c340d663fac..44997ee523fbe3507fac1f5406483bf35f649da5 100644 (file)
@@ -1,5 +1,6 @@
 REQUIRES: shell
 RUN: llvm-dsymutil -o - -oso-prepend-path=%p/.. %p/../Inputs/basic-lto.macho.x86_64 | llvm-dwarfdump - | FileCheck %s
+RUN: llvm-dsymutil -oso-prepend-path=%p/.. -dump-debug-map %p/../Inputs/basic-lto.macho.x86_64 | llvm-dsymutil -o - -oso-prepend-path=%p/.. -y - | llvm-dwarfdump - | FileCheck %s
 
 CHECK: file format Mach-O 64-bit x86-64
 
index 8d76f113e91e01bfd422c890b101fd3f5bf720e8..c2917db981eab0503b33d9ac5c3facf6c5897a67 100644 (file)
@@ -69,6 +69,7 @@ class DebugMap {
 
   /// For YAML IO support.
   ///@{
+  friend yaml::MappingTraits<std::unique_ptr<DebugMap>>;
   friend yaml::MappingTraits<DebugMap>;
   DebugMap() = default;
   ///@}
@@ -184,33 +185,35 @@ struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> {
 };
 
 template <> struct MappingTraits<dsymutil::DebugMapObject> {
-  typedef StringMap<dsymutil::DebugMapObject::SymbolMapping> SymbolMap;
-
-  struct SequencedStringMap {
-    SequencedStringMap(IO &io) {}
-
-    SequencedStringMap(IO &io, SymbolMap &Map) {
-      Entries.reserve(Map.size());
-      for (auto &Entry : Map)
+  // Normalize/Denormalize between YAML and a DebugMapObject.
+  struct YamlDMO {
+    YamlDMO(IO &io) {}
+
+    YamlDMO(IO &io, dsymutil::DebugMapObject &Obj) {
+      Filename = Obj.Filename;
+      Entries.reserve(Obj.Symbols.size());
+      for (auto &Entry : Obj.Symbols)
         Entries.push_back(std::make_pair(Entry.getKey(), Entry.getValue()));
     }
 
-    SymbolMap denormalize(IO &) {
-      SymbolMap Res;
-
-      for (auto &Entry : Entries)
-        Res[Entry.first] = Entry.second;
-
+    dsymutil::DebugMapObject denormalize(IO &) {
+      dsymutil::DebugMapObject Res(Filename);
+      for (auto &Entry : Entries) {
+        auto &Mapping = Entry.second;
+        Res.addSymbol(Entry.first, Mapping.ObjectAddress, Mapping.BinaryAddress,
+                      Mapping.Size);
+      }
       return Res;
     }
 
+    std::string Filename;
     std::vector<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries;
   };
 
-  static void mapping(IO &io, dsymutil::DebugMapObject &s) {
-    MappingNormalization<SequencedStringMap, SymbolMap> seq(io, s.Symbols);
-    io.mapRequired("filename", s.Filename);
-    io.mapRequired("symbols", seq->Entries);
+  static void mapping(IO &io, dsymutil::DebugMapObject &DMO) {
+    MappingNormalization<YamlDMO, dsymutil::DebugMapObject> Norm(io, DMO);
+    io.mapRequired("filename", Norm->Filename);
+    io.mapRequired("symbols", Norm->Entries);
   }
 };
 
@@ -222,7 +225,7 @@ template <> struct ScalarTraits<Triple> {
 
   static StringRef input(StringRef scalar, void *, Triple &value) {
     value = Triple(scalar);
-    return value.str();
+    return StringRef();
   }
 
   static bool mustQuote(StringRef) { return true; }
@@ -253,6 +256,15 @@ template <> struct MappingTraits<dsymutil::DebugMap> {
     io.mapOptional("objects", DM.Objects);
   }
 };
+
+ template <> struct MappingTraits<std::unique_ptr<dsymutil::DebugMap>> {
+  static void mapping(IO &io, std::unique_ptr<dsymutil::DebugMap> &DM) {
+    if (!DM)
+      DM.reset(new DebugMap());
+    io.mapRequired("triple", DM->BinaryTriple);
+    io.mapOptional("objects", DM->Objects);
+  }
+};
 }
 }
 
index bf64303b9eab2872ffcea0abffcbbc3837b98602..c8b48823f9896a30b85d018a25b39ca30498208d 100644 (file)
@@ -242,12 +242,32 @@ void MachODebugMapParser::loadMainBinarySymbols() {
   }
 }
 
+ErrorOr<std::unique_ptr<DebugMap>>
+parseYAMLDebugMap(StringRef InputFile, bool Verbose) {
+  auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(InputFile);
+  if (auto Err =ErrOrFile.getError())
+    return Err;
+
+  std::unique_ptr<DebugMap> Res;
+  yaml::Input yin((*ErrOrFile)->getBuffer());
+  yin >> Res;
+
+  if (auto EC = yin.error())
+    return EC;
+
+  return std::move(Res);
+}
+
 namespace llvm {
 namespace dsymutil {
 llvm::ErrorOr<std::unique_ptr<DebugMap>>
-parseDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose) {
-  MachODebugMapParser Parser(InputFile, PrependPath, Verbose);
-  return Parser.parse();
+parseDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose, bool InputIsYAML) {
+  if (!InputIsYAML) {
+    MachODebugMapParser Parser(InputFile, PrependPath, Verbose);
+    return Parser.parse();
+  } else {
+    return parseYAMLDebugMap(InputFile, Verbose);
+  }
 }
 }
 }
index b4a480d7012764cc1fdbeaca95b2f4685f844c37..50091935a44ee3d687b1a76e05e2f9cf400288e5 100644 (file)
@@ -52,6 +52,10 @@ static opt<bool> DumpDebugMap(
     desc("Parse and dump the debug map to standard output. Not DWARF link "
          "will take place."),
     init(false));
+
+static opt<bool> InputIsYAMLDebugMap(
+    "y", desc("Treat the input file is a YAML debug map rather than a binary."),
+    init(false));
 }
 
 int main(int argc, char **argv) {
@@ -61,7 +65,9 @@ int main(int argc, char **argv) {
   LinkOptions Options;
 
   llvm::cl::ParseCommandLineOptions(argc, argv, "llvm dsymutil\n");
-  auto DebugMapPtrOrErr = parseDebugMap(InputFile, OsoPrependPath, Verbose);
+
+  auto DebugMapPtrOrErr =
+      parseDebugMap(InputFile, OsoPrependPath, Verbose, InputIsYAMLDebugMap);
 
   Options.Verbose = Verbose;
   Options.NoOutput = NoOutput;
index e9f7cd951878db59a9ee738283c3a518d7cd9c24..0cbdaf5503a878b26167e6750491a9a317355393 100644 (file)
@@ -34,8 +34,8 @@ struct LinkOptions {
 /// \brief Extract the DebugMap from the given file.
 /// The file has to be a MachO object file.
 llvm::ErrorOr<std::unique_ptr<DebugMap>>
-parseDebugMap(StringRef InputFile, StringRef PrependPath = "",
-              bool Verbose = false);
+parseDebugMap(StringRef InputFile, StringRef PrependPath,
+              bool Verbose, bool InputIsYAML);
 
 /// \brief Link the Dwarf debuginfo as directed by the passed DebugMap
 /// \p DM into a DwarfFile named \p OutputFilename.