[Remarks] Warn if a remark file is not found when processing static archives
authorFrancis Visoiu Mistrih <francisvm@yahoo.com>
Fri, 3 Jan 2020 22:50:19 +0000 (14:50 -0800)
committerFrancis Visoiu Mistrih <francisvm@yahoo.com>
Sat, 4 Jan 2020 01:02:10 +0000 (17:02 -0800)
Static archives contain object files which contain sections pointing to
external remark files.

When static archives are shipped without the remark files, dsymutil
shouldn't generate an error.

Instead, generate a warning to inform the user that remarks for that
library won't be available in the .dSYM.

llvm/include/llvm/Support/Error.h
llvm/test/tools/dsymutil/Inputs/basic1.c
llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.archive.x86_64 [new file with mode: 0755]
llvm/test/tools/dsymutil/Inputs/remarks/libbasic.a [new file with mode: 0644]
llvm/test/tools/dsymutil/X86/remarks-linking-archive.text [new file with mode: 0644]
llvm/tools/dsymutil/DwarfLinker.cpp

index 75fca01..4467633 100644 (file)
@@ -1232,6 +1232,8 @@ public:
     Err->log(OS);
   }
 
+  StringRef getFileName() { return FileName; }
+
   Error takeError() { return Error(std::move(Err)); }
 
   std::error_code convertToErrorCode() const override;
index 2029206..af96081 100644 (file)
       done
       clang basic1.macho.remarks.x86_64.o basic2.macho.remarks.x86_64.o basic3.macho.remarks.x86_64.o -o basic.macho.remarks.x86_64 -Wl,-dead_strip
 
+    Remarks archive compilation (after remarks compilation):
+    ar -q libbasic.a basic1.macho.x86_64.o basic2.macho.x86_64.o basic3.macho.x86_64.o
+    clang -lbasic -L. -o basic.macho.remarks.archive.x86_64 -Wl,-dead_strip
+
 */
 
 int foo(int);
diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.archive.x86_64 b/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.archive.x86_64
new file mode 100755 (executable)
index 0000000..f4ab141
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.archive.x86_64 differ
diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/libbasic.a b/llvm/test/tools/dsymutil/Inputs/remarks/libbasic.a
new file mode 100644 (file)
index 0000000..c6b1dde
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/remarks/libbasic.a differ
diff --git a/llvm/test/tools/dsymutil/X86/remarks-linking-archive.text b/llvm/test/tools/dsymutil/X86/remarks-linking-archive.text
new file mode 100644 (file)
index 0000000..117349c
--- /dev/null
@@ -0,0 +1,43 @@
+RUN: rm -rf %t
+RUN: mkdir -p %t
+RUN: cat %p/../Inputs/remarks/basic.macho.remarks.archive.x86_64 > %t/basic.macho.remarks.archive.x86_64
+
+RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.archive.x86_64
+
+Check that the remark file in the bundle exists and is sane:
+RUN: llvm-bcanalyzer -dump %t/basic.macho.remarks.archive.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.archive.x86_64 | FileCheck %s
+
+Check that we don't error if we're missing remark files from an archive, but we warn instead.
+Instead of creating a new binary, just remove the remarks prepend path.
+RUN: dsymutil -oso-prepend-path=%p/../Inputs %t/basic.macho.remarks.archive.x86_64 2>&1 | FileCheck %s --check-prefix=CHECK-MISSING
+
+CHECK: <Meta
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK: <Remark Num
+CHECK-NOT: <Remark Num
+
+CHECK-MISSING: warning: '/remarks/basic1.macho.remarks.x86_64.opt.bitstream': No such file or directory
+CHECK-MISSING-NEXT: note: while processing {{.*}}libbasic.a(basic1.macho.remarks.x86_64.o)
+CHECK-MISSING-NEXT: warning: '/remarks/basic2.macho.remarks.x86_64.opt.bitstream': No such file or directory
+CHECK-MISSING-NEXT: note: while processing {{.*}}libbasic.a(basic2.macho.remarks.x86_64.o)
+CHECK-MISSING-NEXT: warning: '/remarks/basic3.macho.remarks.x86_64.opt.bitstream': No such file or directory
+CHECK-MISSING-NEXT: note: while processing {{.*}}libbasic.a(basic3.macho.remarks.x86_64.o)
index 64acab6..53f6b28 100644 (file)
@@ -188,6 +188,30 @@ static bool isTypeTag(uint16_t Tag) {
   return false;
 }
 
+static Error remarksErrorHandler(const DebugMapObject &DMO, DwarfLinker &Linker,
+                                 std::unique_ptr<FileError> FE) {
+  bool IsArchive = DMO.getObjectFilename().endswith(")");
+  // Don't report errors for missing remark files from static
+  // archives.
+  if (!IsArchive)
+    return Error(std::move(FE));
+
+  std::string Message = FE->message();
+  Error E = FE->takeError();
+  Error NewE = handleErrors(std::move(E), [&](std::unique_ptr<ECError> EC) {
+    if (EC->convertToErrorCode() != std::errc::no_such_file_or_directory)
+      return Error(std::move(EC));
+
+    Linker.reportWarning(Message, DMO);
+    return Error(Error::success());
+  });
+
+  if (!NewE)
+    return Error::success();
+
+  return createFileError(FE->getFileName(), std::move(NewE));
+}
+
 bool DwarfLinker::DIECloner::getDIENames(const DWARFDie &Die,
                                          AttributesInfo &Info,
                                          OffsetsStringPool &StringPool,
@@ -2946,9 +2970,15 @@ bool DwarfLinker::link(const DebugMap &Map) {
   auto RemarkLinkLambda = [&](size_t i) {
     // Link remarks from one object file.
     auto &LinkContext = ObjectContexts[i];
-    if (const object::ObjectFile *Obj = LinkContext.ObjectFile)
-      if (Error E = RL.link(*Obj))
-        return E;
+    if (const object::ObjectFile *Obj = LinkContext.ObjectFile) {
+      Error E = RL.link(*Obj);
+      if (Error NewE = handleErrors(
+              std::move(E), [&](std::unique_ptr<FileError> EC) -> Error {
+                return remarksErrorHandler(LinkContext.DMO, *this,
+                                           std::move(EC));
+              }))
+        return NewE;
+    }
     return Error(Error::success());
   };