[llvm-dwp] Abort when dwo_id is unset

Summary:
An empty dwo_id indicates a degenerate .dwo file that should not have been generated in the first place. Instead of discovering this error later when merging with another degenerate .dwo file, print an error immediately when noticing an unset dwo_id, including the filename of the offending file.

Test case created by compiling a trivial file w/ `-fno-split-dwarf-inlining -gmlt -gsplit-dwarf -c` prior to r353771

Reviewers: dblaikie

Reviewed By: dblaikie

Subscribers: jdoerfert, aprantl, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D58085

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@353846 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/tools/llvm-dwp/Inputs/missing_dwo_id.dwo b/test/tools/llvm-dwp/Inputs/missing_dwo_id.dwo
new file mode 100644
index 0000000..f92b458
--- /dev/null
+++ b/test/tools/llvm-dwp/Inputs/missing_dwo_id.dwo
Binary files differ
diff --git a/test/tools/llvm-dwp/X86/invalid_string_form.test b/test/tools/llvm-dwp/X86/invalid_string_form.test
index e78a145..2d3cf6f 100644
--- a/test/tools/llvm-dwp/X86/invalid_string_form.test
+++ b/test/tools/llvm-dwp/X86/invalid_string_form.test
@@ -1,3 +1,3 @@
 RUN: not llvm-dwp %p/../Inputs/invalid_string_form.dwo -o %t 2>&1 | FileCheck %s
 
-CHECK: error: string field encoded without DW_FORM_string or DW_FORM_GNU_str_index
+CHECK: error: {{.*}}invalid_string_form.dwo': string field encoded without DW_FORM_string or DW_FORM_GNU_str_index
diff --git a/test/tools/llvm-dwp/X86/missing_dwo_id.test b/test/tools/llvm-dwp/X86/missing_dwo_id.test
new file mode 100644
index 0000000..a07bcb8
--- /dev/null
+++ b/test/tools/llvm-dwp/X86/missing_dwo_id.test
@@ -0,0 +1,3 @@
+RUN: not llvm-dwp %p/../Inputs/missing_dwo_id.dwo -o %t 2>&1 | FileCheck %s
+
+CHECK: error: {{.*}}missing_dwo_id.dwo': compile unit missing dwo_id
diff --git a/test/tools/llvm-dwp/X86/non_cu_top_level.test b/test/tools/llvm-dwp/X86/non_cu_top_level.test
index 60b8742..92f53a7 100644
--- a/test/tools/llvm-dwp/X86/non_cu_top_level.test
+++ b/test/tools/llvm-dwp/X86/non_cu_top_level.test
@@ -1,3 +1,3 @@
 RUN: not llvm-dwp %p/../Inputs/non_cu_top_level.dwo -o %t 2>&1 | FileCheck %s
 
-CHECK: error: top level DIE is not a compile unit
+CHECK: error: {{.*}}non_cu_top_level.dwo': top level DIE is not a compile unit
diff --git a/tools/llvm-dwp/llvm-dwp.cpp b/tools/llvm-dwp/llvm-dwp.cpp
index cb4df9f..87831a8 100644
--- a/tools/llvm-dwp/llvm-dwp.cpp
+++ b/tools/llvm-dwp/llvm-dwp.cpp
@@ -13,6 +13,7 @@
 #include "DWPError.h"
 #include "DWPStringPool.h"
 #include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
@@ -159,6 +160,7 @@
   uint32_t Name;
   dwarf::Form Form;
   CompileUnitIdentifiers ID;
+  Optional<uint64_t> Signature = None;
   while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |
          (Form = static_cast<dwarf::Form>(AbbrevData.getULEB128(&AbbrevOffset))) &&
          (Name != 0 || Form != 0)) {
@@ -180,13 +182,16 @@
       break;
     }
     case dwarf::DW_AT_GNU_dwo_id:
-      ID.Signature = InfoData.getU64(&Offset);
+      Signature = InfoData.getU64(&Offset);
       break;
     default:
       DWARFFormValue::skipValue(Form, InfoData, &Offset,
                                 dwarf::FormParams({Version, AddrSize, Format}));
     }
   }
+  if (!Signature)
+    return make_error<DWPError>("compile unit missing dwo_id");
+  ID.Signature = *Signature;
   return ID;
 }
 
@@ -560,7 +565,7 @@
       Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
           AbbrevSection, InfoSection, CurStrOffsetSection, CurStrSection);
       if (!EID)
-        return EID.takeError();
+        return createFileError(Input, EID.takeError());
       const auto &ID = *EID;
       auto P = IndexEntries.insert(std::make_pair(ID.Signature, CurEntry));
       if (!P.second)
@@ -588,7 +593,7 @@
           getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
           CurStrSection);
       if (!EID)
-        return EID.takeError();
+        return createFileError(Input, EID.takeError());
       const auto &ID = *EID;
       if (!P.second)
         return buildDuplicateError(*P.first, ID, Input);