OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "delta_encoder.h" |
| 6 |
| 7 #include <vector> |
| 8 #include "elf.h" |
| 9 #include "gtest/gtest.h" |
| 10 |
| 11 namespace { |
| 12 |
| 13 template <typename T> |
| 14 void AddRelocation(uint32_t addr, |
| 15 uint32_t info, |
| 16 int32_t addend, |
| 17 std::vector<T>* relocations) { |
| 18 T relocation; |
| 19 relocation.r_offset = addr; |
| 20 relocation.r_info = info; |
| 21 relocation.r_addend = addend; |
| 22 relocations->push_back(relocation); |
| 23 } |
| 24 |
| 25 template <typename T> |
| 26 bool CheckRelocation(uint32_t addr, |
| 27 uint32_t info, |
| 28 int32_t addend, |
| 29 const T& relocation) { |
| 30 return relocation.r_offset == addr && |
| 31 relocation.r_info == info && |
| 32 relocation.r_addend == addend; |
| 33 } |
| 34 |
| 35 } // namespace |
| 36 |
| 37 namespace relocation_packer { |
| 38 |
| 39 template <typename ELF> |
| 40 static void encode() { |
| 41 std::vector<typename ELF::Rela> relocations; |
| 42 std::vector<typename ELF::Addr> packed; |
| 43 |
| 44 RelocationDeltaCodec<ELF> codec; |
| 45 |
| 46 codec.Encode(relocations, &packed); |
| 47 |
| 48 ASSERT_EQ(0U, packed.size()); |
| 49 |
| 50 // Initial relocation. |
| 51 AddRelocation(0xf00d0000, 11U, 10000, &relocations); |
| 52 |
| 53 codec.Encode(relocations, &packed); |
| 54 |
| 55 // size of reloc table, size of group, flags, 3 fields, zero |
| 56 EXPECT_EQ(7U, packed.size()); |
| 57 // One pair present. |
| 58 size_t ndx = 0; |
| 59 EXPECT_EQ(1U, packed[ndx++]); |
| 60 EXPECT_EQ(0xf00d0000, packed[ndx++]); |
| 61 EXPECT_EQ(1U, packed[ndx++]); // group_size |
| 62 EXPECT_EQ(8U, packed[ndx++]); // flags |
| 63 // Delta from the neutral element is zero |
| 64 EXPECT_EQ(0U, packed[ndx++]); // offset_delta |
| 65 EXPECT_EQ(11U, packed[ndx++]); // info |
| 66 EXPECT_EQ(10000U, packed[ndx++]); // addend_delta |
| 67 |
| 68 // Add a second relocation, 4 byte offset delta, 12 byte addend delta. |
| 69 // same info |
| 70 AddRelocation(0xf00d0004, 11U, 10012, &relocations); |
| 71 |
| 72 packed.clear(); |
| 73 codec.Encode(relocations, &packed); |
| 74 |
| 75 ndx = 0; |
| 76 EXPECT_EQ(8U, packed.size()); |
| 77 |
| 78 EXPECT_EQ(2U, packed[ndx++]); // relocs count |
| 79 EXPECT_EQ(0xf00cfffc, packed[ndx++]); // initial offset |
| 80 EXPECT_EQ(2U, packed[ndx++]); // group count |
| 81 EXPECT_EQ(11U, packed[ndx++]); // flags |
| 82 EXPECT_EQ(4U, packed[ndx++]); // group offset delta |
| 83 EXPECT_EQ(11U, packed[ndx++]); // info |
| 84 |
| 85 EXPECT_EQ(10000U, packed[ndx++]); // addend delta |
| 86 EXPECT_EQ(12U, packed[ndx++]); // addend delta |
| 87 |
| 88 // Add a third relocation, 4 byte offset delta, 12 byte addend delta. |
| 89 // different info |
| 90 AddRelocation(0xf00d0008, 41U, 10024, &relocations); |
| 91 |
| 92 // Add three more relocations, 8 byte offset deltas, -24 byte addend deltas. |
| 93 AddRelocation(0xf00d0010, 42U, 10000, &relocations); |
| 94 AddRelocation(0xf00d0018, 42U, 9976, &relocations); |
| 95 AddRelocation(0xf00d0020, 42U, 9952, &relocations); |
| 96 |
| 97 AddRelocation(0xf00d2028, 1042U, 0, &relocations); |
| 98 AddRelocation(0xf00d2030, 3442U, 0, &relocations); |
| 99 |
| 100 packed.clear(); |
| 101 codec.Encode(relocations, &packed); |
| 102 |
| 103 ndx = 0; |
| 104 EXPECT_EQ(26U, packed.size()); |
| 105 // Total number of relocs |
| 106 EXPECT_EQ(8U, packed[ndx++]); |
| 107 EXPECT_EQ(0xf00cfffc, packed[ndx++]); |
| 108 // 2 in first group |
| 109 EXPECT_EQ(2U, packed[ndx++]); |
| 110 EXPECT_EQ(11U, packed[ndx++]); //flags |
| 111 EXPECT_EQ(4U, packed[ndx++]); // group offset delta |
| 112 EXPECT_EQ(11U, packed[ndx++]); // info |
| 113 |
| 114 // Initial relocation. |
| 115 EXPECT_EQ(10000U, packed[ndx++]); // addend delta |
| 116 // Two relocations, 4 byte offset deltas, 12 byte addend deltas. |
| 117 EXPECT_EQ(12U, packed[ndx++]); // addend delta |
| 118 |
| 119 // second group has only one reloc |
| 120 EXPECT_EQ(1U, packed[ndx++]); // count |
| 121 EXPECT_EQ(8U, packed[ndx++]); // flags |
| 122 |
| 123 EXPECT_EQ(4U, packed[ndx++]); // offset delta |
| 124 EXPECT_EQ(41U, packed[ndx++]); // info |
| 125 EXPECT_EQ(12U, packed[ndx++]); // addend delta |
| 126 |
| 127 // next - 3 relocs grouped by info |
| 128 EXPECT_EQ(3U, packed[ndx++]); // count |
| 129 EXPECT_EQ(11U, packed[ndx++]); // flags |
| 130 EXPECT_EQ(8U, packed[ndx++]); // group offset delta |
| 131 EXPECT_EQ(42U, packed[ndx++]); // info |
| 132 // Three relocations, 8 byte offset deltas, -24 byte addend deltas. |
| 133 EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]); |
| 134 EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]); |
| 135 EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]); |
| 136 |
| 137 // and last - 2 relocations without addend |
| 138 EXPECT_EQ(2U, packed[ndx++]); |
| 139 EXPECT_EQ(0U, packed[ndx++]); // flags |
| 140 // offset_deltas and r_infos for next 2 relocations |
| 141 EXPECT_EQ(0x2008U, packed[ndx++]); // offset delta |
| 142 EXPECT_EQ(1042U, packed[ndx++]); // r_info |
| 143 EXPECT_EQ(0x8U, packed[ndx++]); // offset delta |
| 144 EXPECT_EQ(3442U, packed[ndx++]); // r_info |
| 145 |
| 146 EXPECT_EQ(packed.size(), ndx); |
| 147 } |
| 148 |
| 149 TEST(Delta, Encode32) { |
| 150 encode<ELF32_traits>(); |
| 151 } |
| 152 |
| 153 TEST(Delta, Encode64) { |
| 154 encode<ELF64_traits>(); |
| 155 } |
| 156 |
| 157 template <typename ELF> |
| 158 static void decode() { |
| 159 std::vector<typename ELF::Addr> packed; |
| 160 std::vector<typename ELF::Rela> relocations; |
| 161 |
| 162 RelocationDeltaCodec<ELF> codec; |
| 163 codec.Decode(packed, &relocations); |
| 164 |
| 165 EXPECT_EQ(0U, relocations.size()); |
| 166 |
| 167 // Six pairs. |
| 168 packed.push_back(6U); // count |
| 169 packed.push_back(0xc0ddfffc); // base offset |
| 170 packed.push_back(3U); // group count |
| 171 packed.push_back(11U); // flags |
| 172 packed.push_back(4U); // offset delta |
| 173 packed.push_back(11U); // info |
| 174 // Initial relocation. |
| 175 packed.push_back(10000U); |
| 176 // Two relocations, 4 byte offset deltas, 12 byte addend deltas. |
| 177 packed.push_back(12U); // addend |
| 178 packed.push_back(12U); // addend |
| 179 |
| 180 // Three relocations, 8 byte offset deltas, -24 byte addend deltas. |
| 181 packed.push_back(1U); // group count |
| 182 packed.push_back(9U); // flags |
| 183 packed.push_back(11U); // info |
| 184 |
| 185 packed.push_back(8U); |
| 186 packed.push_back(static_cast<typename ELF::Addr>(-24)); |
| 187 // next group with 2 relocs |
| 188 packed.push_back(2U); // group count |
| 189 packed.push_back(11U); // flags |
| 190 packed.push_back(8U); // offset |
| 191 packed.push_back(42U); // info |
| 192 |
| 193 packed.push_back(static_cast<typename ELF::Addr>(-24)); // addend |
| 194 packed.push_back(static_cast<typename ELF::Addr>(-24)); // addend |
| 195 |
| 196 relocations.clear(); |
| 197 codec.Decode(packed, &relocations); |
| 198 |
| 199 EXPECT_EQ(6U, relocations.size()); |
| 200 // Initial relocation. |
| 201 EXPECT_TRUE(CheckRelocation(0xc0de0000, 11U, 10000, relocations[0])); |
| 202 // Two relocations, 4 byte offset deltas, 12 byte addend deltas. |
| 203 EXPECT_TRUE(CheckRelocation(0xc0de0004, 11U, 10012, relocations[1])); |
| 204 EXPECT_TRUE(CheckRelocation(0xc0de0008, 11U, 10024, relocations[2])); |
| 205 // Three relocations, 8 byte offset deltas, -24 byte addend deltas. |
| 206 EXPECT_TRUE(CheckRelocation(0xc0de0010, 11U, 10000, relocations[3])); |
| 207 EXPECT_TRUE(CheckRelocation(0xc0de0018, 42U, 9976, relocations[4])); |
| 208 EXPECT_TRUE(CheckRelocation(0xc0de0020, 42U, 9952, relocations[5])); |
| 209 } |
| 210 |
| 211 TEST(Delta, Decode32) { |
| 212 decode<ELF32_traits>(); |
| 213 } |
| 214 |
| 215 TEST(Delta, Decode64) { |
| 216 decode<ELF64_traits>(); |
| 217 } |
| 218 |
| 219 // TODO (dimitry): add more tests (fix by 19 January 2038 03:14:07 UTC) |
| 220 // TODO (dimtiry): 1. Incorrect packed array for decode |
| 221 // TODO (dimtiry): 2. Try to catch situation where it is likely to get series of
groups with size 1 |
| 222 |
| 223 } // namespace relocation_packer |
OLD | NEW |