[Object] Search for architecures by name in MachOUniversalBinary::getObjectForArch()
authorFrederic Riss <friss@apple.com>
Mon, 22 Jun 2015 21:33:24 +0000 (21:33 +0000)
committerFrederic Riss <friss@apple.com>
Mon, 22 Jun 2015 21:33:24 +0000 (21:33 +0000)
The reason we need to search by name rather than by Triple::ArchType
is to handle subarchitecture correclty. There is no different ArchType
for the x86_64h architecture (it identifies itself as x86_64), or for
the various ARM subarches. The only way to get to the subarch slice
in an universal binary is to search by name.

This issue led to hard to debug and transient symbolication failures
in Asan tests (it mostly works, because the files are very similar).

This also affects the Profiling infrastucture as it is the other user
of that API.

Reviewers: samsonov, bogner

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D10604

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

include/llvm/Object/MachOUniversal.h
include/llvm/ProfileData/CoverageMapping.h
include/llvm/ProfileData/CoverageMappingReader.h
lib/Object/MachOUniversal.cpp
lib/ProfileData/CoverageMapping.cpp
lib/ProfileData/CoverageMappingReader.cpp
test/tools/llvm-symbolizer/Inputs/fat.c [new file with mode: 0644]
test/tools/llvm-symbolizer/Inputs/fat.o [new file with mode: 0644]
test/tools/llvm-symbolizer/fat.test [new file with mode: 0644]
tools/llvm-cov/CodeCoverage.cpp
tools/llvm-symbolizer/LLVMSymbolize.cpp

index ebc8b906691a4420d28c842c8921aac33d4445d7..3cdf9f0a4c0bbb727449e1b8422c403889ceb368 100644 (file)
@@ -109,7 +109,7 @@ public:
   }
 
   ErrorOr<std::unique_ptr<MachOObjectFile>>
-  getObjectForArch(Triple::ArchType Arch) const;
+  getObjectForArch(StringRef ArchName) const;
 };
 
 } // namespace object
index 94e655c3edcb62d068f9c68dad9767a58ceeaa68..3488e793d84fb8f9614858dac96df047a204e3d6 100644 (file)
@@ -410,7 +410,7 @@ public:
   /// \brief Load the coverage mapping from the given files.
   static ErrorOr<std::unique_ptr<CoverageMapping>>
   load(StringRef ObjectFilename, StringRef ProfileFilename,
-       Triple::ArchType Arch = Triple::ArchType::UnknownArch);
+       StringRef Arch = StringRef());
 
   /// \brief The number of functions that couldn't have their profiles mapped.
   ///
index 020edbd3e6c135a6a0b1a013c651562525ffa9a1..38fb4680476bee6e7d7c9e7f2f6107b400683171 100644 (file)
@@ -171,7 +171,7 @@ private:
 public:
   static ErrorOr<std::unique_ptr<BinaryCoverageReader>>
   create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
-         Triple::ArchType Arch = Triple::ArchType::UnknownArch);
+         StringRef Arch);
 
   std::error_code readNextRecord(CoverageMappingRecord &Record) override;
 };
index 2705e7dc40e59d1c474ca65886c5708083dfdfca..1d0e69e4622db217fd2cfdf6b348ae8cce1ba9a1 100644 (file)
@@ -123,25 +123,13 @@ MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source,
   ec = std::error_code();
 }
 
-static bool getCTMForArch(Triple::ArchType Arch, MachO::CPUType &CTM) {
-  switch (Arch) {
-    case Triple::x86:    CTM = MachO::CPU_TYPE_I386; return true;
-    case Triple::x86_64: CTM = MachO::CPU_TYPE_X86_64; return true;
-    case Triple::arm:    CTM = MachO::CPU_TYPE_ARM; return true;
-    case Triple::sparc:  CTM = MachO::CPU_TYPE_SPARC; return true;
-    case Triple::ppc:    CTM = MachO::CPU_TYPE_POWERPC; return true;
-    case Triple::ppc64:  CTM = MachO::CPU_TYPE_POWERPC64; return true;
-    default: return false;
-  }
-}
-
 ErrorOr<std::unique_ptr<MachOObjectFile>>
-MachOUniversalBinary::getObjectForArch(Triple::ArchType Arch) const {
-  MachO::CPUType CTM;
-  if (!getCTMForArch(Arch, CTM))
+MachOUniversalBinary::getObjectForArch(StringRef ArchName) const {
+  if (Triple(ArchName).getArch() == Triple::ArchType::UnknownArch)
     return object_error::arch_not_found;
+
   for (object_iterator I = begin_objects(), E = end_objects(); I != E; ++I) {
-    if (I->getCPUType() == static_cast<uint32_t>(CTM))
+    if (I->getArchTypeName() == ArchName)
       return I->getAsObjectFile();
   }
   return object_error::arch_not_found;
index b6c2489bd5c68c1c8ad09cfe1d21dbf4ba308933..a650f76f39414887a34614b44a8bfbce2b95ba1f 100644 (file)
@@ -236,7 +236,7 @@ CoverageMapping::load(CoverageMappingReader &CoverageReader,
 
 ErrorOr<std::unique_ptr<CoverageMapping>>
 CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename,
-                      Triple::ArchType Arch) {
+                      StringRef Arch) {
   auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename);
   if (std::error_code EC = CounterMappingBuff.getError())
     return EC;
index 32de0babcb2fb2712a64a1e5517d8332737d0072..43d5ecffe30530ccce756d713a1c5f94851075a3 100644 (file)
@@ -448,7 +448,7 @@ static std::error_code loadBinaryFormat(MemoryBufferRef ObjectBuffer,
                                         StringRef &CoverageMapping,
                                         uint8_t &BytesInAddress,
                                         support::endianness &Endian,
-                                        Triple::ArchType Arch) {
+                                        StringRef Arch) {
   auto BinOrErr = object::createBinary(ObjectBuffer);
   if (std::error_code EC = BinOrErr.getError())
     return EC;
@@ -465,7 +465,7 @@ static std::error_code loadBinaryFormat(MemoryBufferRef ObjectBuffer,
     // For any other object file, upcast and take ownership.
     OF.reset(cast<object::ObjectFile>(Bin.release()));
     // If we've asked for a particular arch, make sure they match.
-    if (Arch != Triple::ArchType::UnknownArch && OF->getArch() != Arch)
+    if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
       return object_error::arch_not_found;
   } else
     // We can only handle object files.
@@ -495,7 +495,7 @@ static std::error_code loadBinaryFormat(MemoryBufferRef ObjectBuffer,
 
 ErrorOr<std::unique_ptr<BinaryCoverageReader>>
 BinaryCoverageReader::create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
-                             Triple::ArchType Arch) {
+                             StringRef Arch) {
   std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader());
 
   SectionData Profile;
diff --git a/test/tools/llvm-symbolizer/Inputs/fat.c b/test/tools/llvm-symbolizer/Inputs/fat.c
new file mode 100644 (file)
index 0000000..0331c09
--- /dev/null
@@ -0,0 +1,15 @@
+/* Compile with:
+   clang -arch armv7 -arch armv7m -arch armv7em -arch x86_64 -arch x86_64h -c
+*/
+
+#ifdef __x86_64h__
+void x86_64h_function() {}
+#elif defined(__x86_64__)
+void x86_64_function() {}
+#elif defined(__ARM_ARCH_7EM__)
+void armv7em_function() {}
+#elif defined(__ARM_ARCH_7M__)
+void armv7m_function() {}
+#elif defined(__ARM_ARCH_7A__)
+void armv7_function() {}
+#endif
diff --git a/test/tools/llvm-symbolizer/Inputs/fat.o b/test/tools/llvm-symbolizer/Inputs/fat.o
new file mode 100644 (file)
index 0000000..947cfc2
Binary files /dev/null and b/test/tools/llvm-symbolizer/Inputs/fat.o differ
diff --git a/test/tools/llvm-symbolizer/fat.test b/test/tools/llvm-symbolizer/fat.test
new file mode 100644 (file)
index 0000000..1ecd1ab
--- /dev/null
@@ -0,0 +1,11 @@
+RUN: echo 0 | llvm-symbolizer -obj=%p/Inputs/fat.o -default-arch=x86_64 | FileCheck --check-prefix=X86_64 %s
+RUN: echo 0 | llvm-symbolizer -obj=%p/Inputs/fat.o -default-arch=x86_64h | FileCheck --check-prefix=X86_64H %s
+RUN: echo 0 | llvm-symbolizer -obj=%p/Inputs/fat.o -default-arch=armv7 | FileCheck --check-prefix=ARMV7 %s
+RUN: echo 0 | llvm-symbolizer -obj=%p/Inputs/fat.o -default-arch=armv7em | FileCheck --check-prefix=ARMV7EM %s
+RUN: echo 0 | llvm-symbolizer -obj=%p/Inputs/fat.o -default-arch=armv7m | FileCheck --check-prefix=ARMV7M %s
+
+X86_64: x86_64_function
+X86_64H: x86_64h_function
+ARMV7: armv7_function
+ARMV7EM: armv7em_function
+ARMV7M: armv7m_function
index 4ff53301881d1b55069d71a99ceb1abccf4d2b9c..8dc4d665f23ca62784c959895e7c3f93cbc63d94 100644 (file)
@@ -89,7 +89,7 @@ public:
       LoadedSourceFiles;
   bool CompareFilenamesOnly;
   StringMap<std::string> RemappedFilenames;
-  llvm::Triple::ArchType CoverageArch;
+  std::string CoverageArch;
 };
 }
 
@@ -349,15 +349,12 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
       Filters.push_back(std::unique_ptr<CoverageFilter>(StatFilterer));
     }
 
-    if (Arch.empty())
-      CoverageArch = llvm::Triple::ArchType::UnknownArch;
-    else {
-      CoverageArch = Triple(Arch).getArch();
-      if (CoverageArch == llvm::Triple::ArchType::UnknownArch) {
-        errs() << "error: Unknown architecture: " << Arch << "\n";
-        return 1;
-      }
+    if (!Arch.empty() &&
+        Triple(Arch).getArch() == llvm::Triple::ArchType::UnknownArch) {
+      errs() << "error: Unknown architecture: " << Arch << "\n";
+      return 1;
     }
+    CoverageArch = Arch;
 
     for (const auto &File : InputSourceFiles) {
       SmallString<128> Path(File);
index b8fa83839cf796bf91c96b9d97729a5b99605631..448cfe99dddac5fdab1c0f3b856ce75001e5cf26 100644 (file)
@@ -436,7 +436,7 @@ LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin,
     if (I != ObjectFileForArch.end())
       return I->second;
     ErrorOr<std::unique_ptr<ObjectFile>> ParsedObj =
-        UB->getObjectForArch(Triple(ArchName).getArch());
+        UB->getObjectForArch(ArchName);
     if (ParsedObj) {
       Res = ParsedObj.get().get();
       ParsedBinariesAndObjects.push_back(std::move(ParsedObj.get()));