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 224