[BOLT] Fix getDynoStats to handle BCs with no functions
authorAmir Ayupov <aaupov@fb.com>
Thu, 30 Jun 2022 08:15:49 +0000 (01:15 -0700)
committerAmir Ayupov <aaupov@fb.com>
Thu, 30 Jun 2022 08:18:45 +0000 (01:18 -0700)
Address fuzzer crash

Reviewed By: yota9

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

bolt/include/bolt/Core/DynoStats.h
bolt/include/bolt/Passes/BinaryPasses.h
bolt/lib/Rewrite/BinaryPassManager.cpp
bolt/unittests/Core/CMakeLists.txt
bolt/unittests/Core/DynoStats.cpp [new file with mode: 0644]

index b4785d3..6587aa0 100644 (file)
@@ -146,8 +146,7 @@ DynoStats getDynoStats(const BinaryFunction &BF);
 
 /// Return program-wide dynostats.
 template <typename FuncsType>
-inline DynoStats getDynoStats(const FuncsType &Funcs) {
-  bool IsAArch64 = Funcs.begin()->second.getBinaryContext().isAArch64();
+inline DynoStats getDynoStats(const FuncsType &Funcs, bool IsAArch64) {
   DynoStats dynoStats(IsAArch64);
   for (auto &BFI : Funcs) {
     auto &BF = BFI.second;
@@ -160,16 +159,16 @@ inline DynoStats getDynoStats(const FuncsType &Funcs) {
 /// Call a function with optional before and after dynostats printing.
 template <typename FnType, typename FuncsType>
 inline void callWithDynoStats(FnType &&Func, const FuncsType &Funcs,
-                              StringRef Phase, const bool Flag) {
-  bool IsAArch64 = Funcs.begin()->second.getBinaryContext().isAArch64();
+                              StringRef Phase, const bool Flag,
+                              bool IsAArch64) {
   DynoStats DynoStatsBefore(IsAArch64);
   if (Flag)
-    DynoStatsBefore = getDynoStats(Funcs);
+    DynoStatsBefore = getDynoStats(Funcs, IsAArch64);
 
   Func();
 
   if (Flag) {
-    const DynoStats DynoStatsAfter = getDynoStats(Funcs);
+    const DynoStats DynoStatsAfter = getDynoStats(Funcs, IsAArch64);
     const bool Changed = (DynoStatsAfter != DynoStatsBefore);
     outs() << "BOLT-INFO: program-wide dynostats after running " << Phase
            << (Changed ? "" : " (no change)") << ":\n\n"
index f036f99..ba28a91 100644 (file)
@@ -71,7 +71,8 @@ public:
   bool shouldPrint(const BinaryFunction &BF) const override { return false; }
 
   void runOnFunctions(BinaryContext &BC) override {
-    const DynoStats NewDynoStats = getDynoStats(BC.getBinaryFunctions());
+    const DynoStats NewDynoStats =
+        getDynoStats(BC.getBinaryFunctions(), BC.isAArch64());
     const bool Changed = (NewDynoStats != PrevDynoStats);
     outs() << "BOLT-INFO: program-wide dynostats " << Title
            << (Changed ? "" : " (no change)") << ":\n\n"
index 3230fad..9c6a0fd 100644 (file)
@@ -268,7 +268,7 @@ void BinaryFunctionPassManager::runPasses() {
                        TimerGroupDesc, TimeOpts);
 
     callWithDynoStats([this, &Pass] { Pass->runOnFunctions(BC); }, BFs,
-                      Pass->getName(), opts::DynoStatsAll);
+                      Pass->getName(), opts::DynoStatsAll, BC.isAArch64());
 
     if (opts::VerifyCFG &&
         !std::accumulate(
@@ -307,7 +307,8 @@ void BinaryFunctionPassManager::runPasses() {
 void BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
   BinaryFunctionPassManager Manager(BC);
 
-  const DynoStats InitialDynoStats = getDynoStats(BC.getBinaryFunctions());
+  const DynoStats InitialDynoStats =
+      getDynoStats(BC.getBinaryFunctions(), BC.isAArch64());
 
   Manager.registerPass(std::make_unique<AsmDumpPass>(),
                        opts::AsmDump.getNumOccurrences());
index 6e4538b..0e78d0a 100644 (file)
@@ -8,6 +8,7 @@ set(LLVM_LINK_COMPONENTS
 add_bolt_unittest(CoreTests
   BinaryContext.cpp
   MCPlusBuilder.cpp
+  DynoStats.cpp
   )
 
 target_link_libraries(CoreTests
diff --git a/bolt/unittests/Core/DynoStats.cpp b/bolt/unittests/Core/DynoStats.cpp
new file mode 100644 (file)
index 0000000..1e6f4c4
--- /dev/null
@@ -0,0 +1,24 @@
+//===- llvm/unittest/MC/MCInstPrinter.cpp ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "bolt/Core/DynoStats.h"
+#include "bolt/Core/BinaryFunction.h"
+#include "gtest/gtest.h"
+#include <map>
+
+using namespace llvm::bolt;
+
+TEST(DynoStatsTest, emptyFuncs) {
+  std::map<uint64_t, BinaryFunction> BinaryFunctions;
+  DynoStats DynoStatsAArch64 =
+      getDynoStats(BinaryFunctions, /* BC.isAArch64() = */ true);
+  DynoStats DynoStatsNonAArch64 =
+      getDynoStats(BinaryFunctions, /* BC.isAArch64() = */ false);
+  // Both should be null
+  ASSERT_EQ(DynoStatsAArch64, DynoStatsNonAArch64);
+}