]> granicus.if.org Git - llvm/commitdiff
Fix llvm-symbolizer to correctly sort a symbol array and calculate symbol sizes
authorKuba Brecka <kuba.brecka@gmail.com>
Tue, 15 Nov 2016 21:07:03 +0000 (21:07 +0000)
committerKuba Brecka <kuba.brecka@gmail.com>
Tue, 15 Nov 2016 21:07:03 +0000 (21:07 +0000)
Sometimes, llvm-symbolizer gives wrong results due to incorrect sizes of some symbols. The reason for that was an incorrectly sorted array in computeSymbolSizes. The comparison function used subtraction of unsigned types, which is incorrect. Let's change this to return explicit -1 or 1.

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

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

include/llvm/Object/SymbolSize.h
lib/Object/SymbolSize.cpp
unittests/CMakeLists.txt
unittests/Object/CMakeLists.txt [new file with mode: 0644]
unittests/Object/SymbolSizeTest.cpp [new file with mode: 0644]

index f2ce70f4208def7ba838460ea3a2c1afb37eaaf0..1a1dc8752943077bb437d6f88ea490190881b343 100644 (file)
 
 namespace llvm {
 namespace object {
+
+struct SymEntry {
+  symbol_iterator I;
+  uint64_t Address;
+  unsigned Number;
+  unsigned SectionID;
+};
+
+int compareAddress(const SymEntry *A, const SymEntry *B);
+
 std::vector<std::pair<SymbolRef, uint64_t>>
 computeSymbolSizes(const ObjectFile &O);
+
 }
 } // namespace llvm
 
index 1d5cd78e6d9cb587dbcb16d71fa563cf712abb8c..dd49d5f116b3dbeb118cda992243c276d1bad2d0 100644 (file)
 using namespace llvm;
 using namespace object;
 
-namespace {
-struct SymEntry {
-  symbol_iterator I;
-  uint64_t Address;
-  unsigned Number;
-  unsigned SectionID;
-};
-}
-
-static int compareAddress(const SymEntry *A, const SymEntry *B) {
+// Orders increasingly by (SectionID, Address).
+int llvm::object::compareAddress(const SymEntry *A, const SymEntry *B) {
   if (A->SectionID != B->SectionID)
-    return A->SectionID - B->SectionID;
-  return A->Address - B->Address;
+    return A->SectionID < B->SectionID ? -1 : 1;
+  if (A->Address != B->Address)
+    return A->Address < B->Address ? -1 : 1;
+  return 0;
 }
 
 static unsigned getSectionID(const ObjectFile &O, SectionRef Sec) {
index 6caed0e5d1992f376620a41afe7831596297175f..8dbca211d0268dec2141cd2e3f49f9928904a9d1 100644 (file)
@@ -17,6 +17,7 @@ add_subdirectory(LineEditor)
 add_subdirectory(Linker)
 add_subdirectory(MC)
 add_subdirectory(MI)
+add_subdirectory(Object)
 add_subdirectory(ObjectYAML)
 add_subdirectory(Option)
 add_subdirectory(ProfileData)
diff --git a/unittests/Object/CMakeLists.txt b/unittests/Object/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7a63c16
--- /dev/null
@@ -0,0 +1,8 @@
+set(LLVM_LINK_COMPONENTS
+  Object
+  )
+
+add_llvm_unittest(ObjectTests
+  SymbolSizeTest.cpp
+  )
+
diff --git a/unittests/Object/SymbolSizeTest.cpp b/unittests/Object/SymbolSizeTest.cpp
new file mode 100644 (file)
index 0000000..ad9c40b
--- /dev/null
@@ -0,0 +1,33 @@
+//===- SymbolSizeTest.cpp - Tests for SymbolSize.cpp ----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/SymbolSize.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::object;
+
+TEST(Object, SymbolSizeSort) {
+  auto it = symbol_iterator(SymbolRef());
+  std::vector<SymEntry> Syms{
+      SymEntry{it, 0xffffffff00000000ull, 1, 0},
+      SymEntry{it, 0x00ffffff00000000ull, 2, 0},
+      SymEntry{it, 0x00ffffff000000ffull, 3, 0},
+      SymEntry{it, 0x0000000100000000ull, 4, 0},
+      SymEntry{it, 0x00000000000000ffull, 5, 0},
+      SymEntry{it, 0x00000001000000ffull, 6, 0},
+      SymEntry{it, 0x000000010000ffffull, 7, 0},
+  };
+
+  array_pod_sort(Syms.begin(), Syms.end(), compareAddress);
+
+  for (unsigned I = 0, N = Syms.size(); I < N - 1; ++I) {
+    EXPECT_LE(Syms[I].Address, Syms[I + 1].Address);
+  }
+}