llvm-dwarfdump: support dumping UUIDs of Mach-O binaries.

This is a feature supported by Darwin dwarfdump. UUIDs are used to
associate executables with their .dSYM bundles.

llvm-svn: 313165
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index e9b3c0c..02c91d2 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -80,6 +80,27 @@
   Accel.dump(OS);
 }
 
+/// Dump the UUID load command.
+static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj) {
+  auto *MachO = dyn_cast<MachOObjectFile>(&Obj);
+  if (!MachO)
+    return;
+  for (auto LC : MachO->load_commands()) {
+    raw_ostream::uuid_t UUID;
+    if (LC.C.cmd == MachO::LC_UUID) {
+      if (LC.C.cmdsize < sizeof(UUID) + sizeof(LC.C)) {
+        OS << "error: UUID load command is too short.\n";
+        return;
+      }
+      OS << "UUID: ";
+      memcpy(&UUID, LC.Ptr+sizeof(LC.C), sizeof(UUID));
+      OS.write_uuid(UUID);
+      OS << ' ' << MachO->getFileFormatName();
+      OS << ' ' << MachO->getFileName() << '\n';
+    }
+  }
+}
+
 static void
 dumpDWARFv5StringOffsetsSection(raw_ostream &OS, StringRef SectionName,
                                 const DWARFObject &Obj,
@@ -203,6 +224,13 @@
   uint64_t DumpType = DumpOpts.DumpType;
   bool DumpEH = DumpOpts.DumpEH;
 
+  const auto *ObjFile = DObj->getFile();
+  if (!(DumpType & DIDT_UUID) || DumpType == DIDT_All)
+    outs() << ObjFile->getFileName() << ":\tfile format "
+           << ObjFile->getFileFormatName() << "\n\n";
+  if (DumpType & DIDT_UUID)
+    dumpUUID(OS, *ObjFile);
+
   if (DumpType & DIDT_DebugAbbrev) {
     OS << ".debug_abbrev contents:\n";
     getDebugAbbrev()->dump(OS);
diff --git a/llvm/lib/ObjectYAML/MachOYAML.cpp b/llvm/lib/ObjectYAML/MachOYAML.cpp
index ab452a7..85079f2 100644
--- a/llvm/lib/ObjectYAML/MachOYAML.cpp
+++ b/llvm/lib/ObjectYAML/MachOYAML.cpp
@@ -55,11 +55,7 @@
 bool ScalarTraits<char_16>::mustQuote(StringRef S) { return needsQuotes(S); }
 
 void ScalarTraits<uuid_t>::output(const uuid_t &Val, void *, raw_ostream &Out) {
-  for (int Idx = 0; Idx < 16; ++Idx) {
-    Out << format("%02" PRIX32, Val[Idx]);
-    if (Idx == 3 || Idx == 5 || Idx == 7 || Idx == 9)
-      Out << "-";
-  }
+  Out.write_uuid(Val);
 }
 
 StringRef ScalarTraits<uuid_t>::input(StringRef Scalar, void *, uuid_t &Val) {
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 6a0f086..c66457c 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -139,6 +139,16 @@
   return *this;
 }
 
+raw_ostream &raw_ostream::write_uuid(const uuid_t UUID) {
+  for (int Idx = 0; Idx < 16; ++Idx) {
+    *this << format("%02" PRIX32, UUID[Idx]);
+    if (Idx == 3 || Idx == 5 || Idx == 7 || Idx == 9)
+      *this << "-";
+  }
+  return *this;
+}
+
+
 raw_ostream &raw_ostream::write_escaped(StringRef Str,
                                         bool UseHexEscapes) {
   for (unsigned char c : Str) {