Index: third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc |
diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8dddd8b412a0583c7095774d7e2d14f5199ff1d7 |
--- /dev/null |
+++ b/third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc |
@@ -0,0 +1,292 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "packer.h" |
+ |
+#include <vector> |
+#include "elf.h" |
+#include "elf_traits.h" |
+#include "gtest/gtest.h" |
+ |
+ |
+template <typename ELF> |
+static void AddRelocation(typename ELF::Addr addr, |
+ typename ELF::Xword info, |
+ typename ELF::Sxword addend, |
+ std::vector<typename ELF::Rela>* relocations) { |
+ typename ELF::Rela relocation; |
+ relocation.r_offset = addr; |
+ relocation.r_info = info; |
+ relocation.r_addend = addend; |
+ |
+ relocations->push_back(relocation); |
+} |
+ |
+template <typename ELF> |
+static bool CheckRelocation(typename ELF::Addr addr, |
+ typename ELF::Xword info, |
+ typename ELF::Sxword addend, |
+ const typename ELF::Rela& relocation) { |
+ return relocation.r_offset == addr && |
+ relocation.r_info == info && |
+ relocation.r_addend == addend; |
+} |
+ |
+namespace relocation_packer { |
+ |
+template <typename ELF> |
+static void DoPackNoAddend() { |
+ std::vector<typename ELF::Rela> relocations; |
+ std::vector<uint8_t> packed; |
+ // Initial relocation. |
+ AddRelocation<ELF>(0xd1ce0000, 0x11, 0, &relocations); |
+ // Two more relocations, 4 byte deltas. |
+ AddRelocation<ELF>(0xd1ce0004, 0x11, 0, &relocations); |
+ AddRelocation<ELF>(0xd1ce0008, 0x11, 0, &relocations); |
+ // Three more relocations, 8 byte deltas. |
+ AddRelocation<ELF>(0xd1ce0010, 0x11, 0, &relocations); |
+ AddRelocation<ELF>(0xd1ce0018, 0x11, 0, &relocations); |
+ AddRelocation<ELF>(0xd1ce0020, 0x11, 0, &relocations); |
+ |
+ RelocationPacker<ELF> packer; |
+ |
+ packed.clear(); |
+ packer.PackRelocations(relocations, &packed); |
+ |
+ ASSERT_EQ(18U, packed.size()); |
+ // Identifier. |
+ size_t ndx = 0; |
+ EXPECT_EQ('A', packed[ndx++]); |
+ EXPECT_EQ('P', packed[ndx++]); |
+ EXPECT_EQ('U', packed[ndx++]); |
+ EXPECT_EQ('2', packed[ndx++]); |
+ // relocation count |
+ EXPECT_EQ(6, packed[ndx++]); |
+ // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d |
+ EXPECT_EQ(0xfc, packed[ndx++]); |
+ EXPECT_EQ(0xff, packed[ndx++]); |
+ EXPECT_EQ(0xb7, packed[ndx++]); |
+ EXPECT_EQ(0x8e, packed[ndx++]); |
+ EXPECT_EQ(0x0d, packed[ndx++]); |
+ // first group |
+ EXPECT_EQ(3, packed[ndx++]); // size |
+ EXPECT_EQ(3, packed[ndx++]); // flags |
+ EXPECT_EQ(4, packed[ndx++]); // r_offset_delta |
+ EXPECT_EQ(0x11, packed[ndx++]); // r_info |
+ // second group |
+ EXPECT_EQ(3, packed[ndx++]); // size |
+ EXPECT_EQ(3, packed[ndx++]); // flags |
+ EXPECT_EQ(8, packed[ndx++]); // r_offset_delta |
+ EXPECT_EQ(0x11, packed[ndx++]); // r_info |
+ |
+ EXPECT_EQ(ndx, packed.size()); |
+} |
+ |
+TEST(Packer, PackNoAddend) { |
+ DoPackNoAddend<ELF32_traits>(); |
+ DoPackNoAddend<ELF64_traits>(); |
+} |
+ |
+template <typename ELF> |
+static void DoUnpackNoAddend() { |
+ std::vector<typename ELF::Rela> relocations; |
+ std::vector<uint8_t> packed; |
+ packed.push_back('A'); |
+ packed.push_back('P'); |
+ packed.push_back('U'); |
+ packed.push_back('2'); |
+ // relocation count |
+ packed.push_back(6); |
+ // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d |
+ packed.push_back(0xfc); |
+ packed.push_back(0xff); |
+ packed.push_back(0xb7); |
+ packed.push_back(0x8e); |
+ packed.push_back(0x0d); |
+ // first group |
+ packed.push_back(3); // size |
+ packed.push_back(3); // flags |
+ packed.push_back(4); // r_offset_delta |
+ packed.push_back(0x11); // r_info |
+ // second group |
+ packed.push_back(3); // size |
+ packed.push_back(3); // flags |
+ packed.push_back(8); // r_offset_delta |
+ packed.push_back(0x11); // r_info |
+ |
+ RelocationPacker<ELF> packer; |
+ packer.UnpackRelocations(packed, &relocations); |
+ |
+ size_t ndx = 0; |
+ EXPECT_EQ(6U, relocations.size()); |
+ EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0000, 0x11, 0, relocations[ndx++])); |
+ EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0004, 0x11, 0, relocations[ndx++])); |
+ EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0008, 0x11, 0, relocations[ndx++])); |
+ |
+ EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0010, 0x11, 0, relocations[ndx++])); |
+ EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0018, 0x11, 0, relocations[ndx++])); |
+ EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0020, 0x11, 0, relocations[ndx++])); |
+ |
+ EXPECT_EQ(ndx, relocations.size()); |
+} |
+ |
+TEST(Packer, UnpackNoAddend) { |
+ DoUnpackNoAddend<ELF32_traits>(); |
+ DoUnpackNoAddend<ELF64_traits>(); |
+} |
+ |
+template <typename ELF> |
+static void DoPackWithAddend() { |
+ std::vector<typename ELF::Rela> relocations; |
+ |
+ // Initial relocation. |
+ AddRelocation<ELF>(0xd1ce0000, 0x01, 10024, &relocations); |
+ // Two more relocations, 4 byte offset deltas, 12 byte addend deltas. |
+ AddRelocation<ELF>(0xd1ce0004, 0x01, 10012, &relocations); |
+ AddRelocation<ELF>(0xd1ce0008, 0x01, 10024, &relocations); |
+ // Three more relocations, 8 byte deltas, -24 byte addend deltas. |
+ AddRelocation<ELF>(0xd1ce0010, 0x01, 10000, &relocations); |
+ AddRelocation<ELF>(0xd1ce0018, 0x01, 9976, &relocations); |
+ AddRelocation<ELF>(0xd1ce0020, 0x01, 9952, &relocations); |
+ |
+ std::vector<uint8_t> packed; |
+ |
+ RelocationPacker<ELF> packer; |
+ |
+ packed.clear(); |
+ packer.PackRelocations(relocations, &packed); |
+ |
+ EXPECT_EQ(26U, packed.size()); |
+ size_t ndx = 0; |
+ // Identifier. |
+ EXPECT_EQ('A', packed[ndx++]); |
+ EXPECT_EQ('P', packed[ndx++]); |
+ EXPECT_EQ('S', packed[ndx++]); |
+ EXPECT_EQ('2', packed[ndx++]); |
+ // Relocation count |
+ EXPECT_EQ(6U, packed[ndx++]); |
+ // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d/7d (depending on ELF::Addr) |
+ EXPECT_EQ(0xfc, packed[ndx++]); |
+ EXPECT_EQ(0xff, packed[ndx++]); |
+ EXPECT_EQ(0xb7, packed[ndx++]); |
+ EXPECT_EQ(0x8e, packed[ndx++]); |
+ if (sizeof(typename ELF::Addr) == 8) { |
+ // positive for uint64_t |
+ EXPECT_EQ(0x0d, packed[ndx++]); |
+ } else { |
+ // negative for uint32_t |
+ EXPECT_EQ(0x7d, packed[ndx++]); |
+ } |
+ // group 1 |
+ EXPECT_EQ(0x03, packed[ndx++]); // size |
+ EXPECT_EQ(0x0b, packed[ndx++]); // flags |
+ EXPECT_EQ(0x04, packed[ndx++]); // r_offset_delta |
+ EXPECT_EQ(0x01, packed[ndx++]); // r_info |
+ // group 1 - addend 1: 10024 = 0xa8, 0xce, 0x80 |
+ EXPECT_EQ(0xa8, packed[ndx++]); |
+ EXPECT_EQ(0xce, packed[ndx++]); |
+ EXPECT_EQ(0x00, packed[ndx++]); |
+ // group 1 - addend 2: -12 = 0x74 |
+ EXPECT_EQ(0x74, packed[ndx++]); |
+ // group 1 - addend 3: +12 = 0x0c |
+ EXPECT_EQ(0x0c, packed[ndx++]); |
+ |
+ // group 2 |
+ EXPECT_EQ(0x03, packed[ndx++]); // size |
+ EXPECT_EQ(0x0b, packed[ndx++]); // flags |
+ EXPECT_EQ(0x08, packed[ndx++]); // r_offset_delta |
+ EXPECT_EQ(0x01, packed[ndx++]); // r_info |
+ |
+ // group 2 - addend 1: -24 = 0x68 |
+ EXPECT_EQ(0x68, packed[ndx++]); |
+ // group 2 - addend 2: -24 = 0x68 |
+ EXPECT_EQ(0x68, packed[ndx++]); |
+ // group 2 - addend 3: -24 = 0x68 |
+ EXPECT_EQ(0x68, packed[ndx++]); |
+ |
+ EXPECT_EQ(ndx, packed.size()); |
+} |
+ |
+TEST(Packer, PackWithAddend) { |
+ DoPackWithAddend<ELF32_traits>(); |
+ DoPackWithAddend<ELF64_traits>(); |
+} |
+ |
+template <typename ELF> |
+static void DoUnpackWithAddend() { |
+ std::vector<uint8_t> packed; |
+ // Identifier. |
+ packed.push_back('A'); |
+ packed.push_back('P'); |
+ packed.push_back('S'); |
+ packed.push_back('2'); |
+ // Relocation count |
+ packed.push_back(6U); |
+ // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d |
+ packed.push_back(0xfc); |
+ packed.push_back(0xff); |
+ packed.push_back(0xb7); |
+ packed.push_back(0x8e); |
+ if (sizeof(typename ELF::Addr) == 8) { |
+ // positive for uint64_t |
+ packed.push_back(0x0d); |
+ } else { |
+ // negative for uint32_t |
+ packed.push_back(0x7d); |
+ } |
+ // group 1 |
+ packed.push_back(0x03); // size |
+ packed.push_back(0x0b); // flags |
+ packed.push_back(0x04); // r_offset_delta |
+ packed.push_back(0x01); // r_info |
+ // group 1 - addend 1: 10024 = 0xa8, 0xce, 0x80 |
+ packed.push_back(0xa8); |
+ packed.push_back(0xce); |
+ packed.push_back(0x00); |
+ // group 1 - addend 2: -12 = 0x74 |
+ packed.push_back(0x74); |
+ // group 1 - addend 3: +12 = 0x0c |
+ packed.push_back(0x0c); |
+ |
+ // group 2 |
+ packed.push_back(0x03); // size |
+ packed.push_back(0x0b); // flags |
+ packed.push_back(0x08); // r_offset_delta |
+ packed.push_back(0x01); // r_info |
+ |
+ // group 2 - addend 1: -24 = 0x68 |
+ packed.push_back(0x68); |
+ // group 2 - addend 2: -24 = 0x68 |
+ packed.push_back(0x68); |
+ // group 2 - addend 3: -24 = 0x68 |
+ packed.push_back(0x68); |
+ |
+ std::vector<typename ELF::Rela> relocations; |
+ |
+ RelocationPacker<ELF> packer; |
+ |
+ relocations.clear(); |
+ packer.UnpackRelocations(packed, &relocations); |
+ |
+ EXPECT_EQ(6U, relocations.size()); |
+ size_t ndx = 0; |
+ // Initial relocation. |
+ EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0000, 0x01, 10024, relocations[ndx++])); |
+ // Two more relocations, 4 byte offset deltas, 12 byte addend deltas. |
+ EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0004, 0x01, 10012, relocations[ndx++])); |
+ EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0008, 0x01, 10024, relocations[ndx++])); |
+ // Three more relocations, 8 byte offset deltas, -24 byte addend deltas. |
+ EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0010, 0x01, 10000, relocations[ndx++])); |
+ EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0018, 0x01, 9976, relocations[ndx++])); |
+ EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0020, 0x01, 9952, relocations[ndx++])); |
+ |
+ EXPECT_EQ(ndx, relocations.size()); |
+} |
+ |
+TEST(Packer, UnpackWithAddend) { |
+ DoUnpackWithAddend<ELF32_traits>(); |
+ DoUnpackWithAddend<ELF64_traits>(); |
+} |
+ |
+} // namespace relocation_packer |