| 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 "packer.h" |
| 6 |
| 7 #include <vector> |
| 8 #include "elf.h" |
| 9 #include "elf_traits.h" |
| 10 #include "gtest/gtest.h" |
| 11 |
| 12 |
| 13 template <typename ELF> |
| 14 static void AddRelocation(typename ELF::Addr addr, |
| 15 typename ELF::Xword info, |
| 16 typename ELF::Sxword addend, |
| 17 std::vector<typename ELF::Rela>* relocations) { |
| 18 typename ELF::Rela relocation; |
| 19 relocation.r_offset = addr; |
| 20 relocation.r_info = info; |
| 21 relocation.r_addend = addend; |
| 22 |
| 23 relocations->push_back(relocation); |
| 24 } |
| 25 |
| 26 template <typename ELF> |
| 27 static bool CheckRelocation(typename ELF::Addr addr, |
| 28 typename ELF::Xword info, |
| 29 typename ELF::Sxword addend, |
| 30 const typename ELF::Rela& relocation) { |
| 31 return relocation.r_offset == addr && |
| 32 relocation.r_info == info && |
| 33 relocation.r_addend == addend; |
| 34 } |
| 35 |
| 36 namespace relocation_packer { |
| 37 |
| 38 template <typename ELF> |
| 39 static void DoPackNoAddend() { |
| 40 std::vector<typename ELF::Rela> relocations; |
| 41 std::vector<uint8_t> packed; |
| 42 // Initial relocation. |
| 43 AddRelocation<ELF>(0xd1ce0000, 0x11, 0, &relocations); |
| 44 // Two more relocations, 4 byte deltas. |
| 45 AddRelocation<ELF>(0xd1ce0004, 0x11, 0, &relocations); |
| 46 AddRelocation<ELF>(0xd1ce0008, 0x11, 0, &relocations); |
| 47 // Three more relocations, 8 byte deltas. |
| 48 AddRelocation<ELF>(0xd1ce0010, 0x11, 0, &relocations); |
| 49 AddRelocation<ELF>(0xd1ce0018, 0x11, 0, &relocations); |
| 50 AddRelocation<ELF>(0xd1ce0020, 0x11, 0, &relocations); |
| 51 |
| 52 RelocationPacker<ELF> packer; |
| 53 |
| 54 packed.clear(); |
| 55 packer.PackRelocations(relocations, &packed); |
| 56 |
| 57 ASSERT_EQ(18U, packed.size()); |
| 58 // Identifier. |
| 59 size_t ndx = 0; |
| 60 EXPECT_EQ('A', packed[ndx++]); |
| 61 EXPECT_EQ('P', packed[ndx++]); |
| 62 EXPECT_EQ('U', packed[ndx++]); |
| 63 EXPECT_EQ('2', packed[ndx++]); |
| 64 // relocation count |
| 65 EXPECT_EQ(6, packed[ndx++]); |
| 66 // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d |
| 67 EXPECT_EQ(0xfc, packed[ndx++]); |
| 68 EXPECT_EQ(0xff, packed[ndx++]); |
| 69 EXPECT_EQ(0xb7, packed[ndx++]); |
| 70 EXPECT_EQ(0x8e, packed[ndx++]); |
| 71 EXPECT_EQ(0x0d, packed[ndx++]); |
| 72 // first group |
| 73 EXPECT_EQ(3, packed[ndx++]); // size |
| 74 EXPECT_EQ(3, packed[ndx++]); // flags |
| 75 EXPECT_EQ(4, packed[ndx++]); // r_offset_delta |
| 76 EXPECT_EQ(0x11, packed[ndx++]); // r_info |
| 77 // second group |
| 78 EXPECT_EQ(3, packed[ndx++]); // size |
| 79 EXPECT_EQ(3, packed[ndx++]); // flags |
| 80 EXPECT_EQ(8, packed[ndx++]); // r_offset_delta |
| 81 EXPECT_EQ(0x11, packed[ndx++]); // r_info |
| 82 |
| 83 EXPECT_EQ(ndx, packed.size()); |
| 84 } |
| 85 |
| 86 TEST(Packer, PackNoAddend) { |
| 87 DoPackNoAddend<ELF32_traits>(); |
| 88 DoPackNoAddend<ELF64_traits>(); |
| 89 } |
| 90 |
| 91 template <typename ELF> |
| 92 static void DoUnpackNoAddend() { |
| 93 std::vector<typename ELF::Rela> relocations; |
| 94 std::vector<uint8_t> packed; |
| 95 packed.push_back('A'); |
| 96 packed.push_back('P'); |
| 97 packed.push_back('U'); |
| 98 packed.push_back('2'); |
| 99 // relocation count |
| 100 packed.push_back(6); |
| 101 // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d |
| 102 packed.push_back(0xfc); |
| 103 packed.push_back(0xff); |
| 104 packed.push_back(0xb7); |
| 105 packed.push_back(0x8e); |
| 106 packed.push_back(0x0d); |
| 107 // first group |
| 108 packed.push_back(3); // size |
| 109 packed.push_back(3); // flags |
| 110 packed.push_back(4); // r_offset_delta |
| 111 packed.push_back(0x11); // r_info |
| 112 // second group |
| 113 packed.push_back(3); // size |
| 114 packed.push_back(3); // flags |
| 115 packed.push_back(8); // r_offset_delta |
| 116 packed.push_back(0x11); // r_info |
| 117 |
| 118 RelocationPacker<ELF> packer; |
| 119 packer.UnpackRelocations(packed, &relocations); |
| 120 |
| 121 size_t ndx = 0; |
| 122 EXPECT_EQ(6U, relocations.size()); |
| 123 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0000, 0x11, 0, relocations[ndx++])); |
| 124 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0004, 0x11, 0, relocations[ndx++])); |
| 125 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0008, 0x11, 0, relocations[ndx++])); |
| 126 |
| 127 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0010, 0x11, 0, relocations[ndx++])); |
| 128 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0018, 0x11, 0, relocations[ndx++])); |
| 129 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0020, 0x11, 0, relocations[ndx++])); |
| 130 |
| 131 EXPECT_EQ(ndx, relocations.size()); |
| 132 } |
| 133 |
| 134 TEST(Packer, UnpackNoAddend) { |
| 135 DoUnpackNoAddend<ELF32_traits>(); |
| 136 DoUnpackNoAddend<ELF64_traits>(); |
| 137 } |
| 138 |
| 139 template <typename ELF> |
| 140 static void DoPackWithAddend() { |
| 141 std::vector<typename ELF::Rela> relocations; |
| 142 |
| 143 // Initial relocation. |
| 144 AddRelocation<ELF>(0xd1ce0000, 0x01, 10024, &relocations); |
| 145 // Two more relocations, 4 byte offset deltas, 12 byte addend deltas. |
| 146 AddRelocation<ELF>(0xd1ce0004, 0x01, 10012, &relocations); |
| 147 AddRelocation<ELF>(0xd1ce0008, 0x01, 10024, &relocations); |
| 148 // Three more relocations, 8 byte deltas, -24 byte addend deltas. |
| 149 AddRelocation<ELF>(0xd1ce0010, 0x01, 10000, &relocations); |
| 150 AddRelocation<ELF>(0xd1ce0018, 0x01, 9976, &relocations); |
| 151 AddRelocation<ELF>(0xd1ce0020, 0x01, 9952, &relocations); |
| 152 |
| 153 std::vector<uint8_t> packed; |
| 154 |
| 155 RelocationPacker<ELF> packer; |
| 156 |
| 157 packed.clear(); |
| 158 packer.PackRelocations(relocations, &packed); |
| 159 |
| 160 EXPECT_EQ(26U, packed.size()); |
| 161 size_t ndx = 0; |
| 162 // Identifier. |
| 163 EXPECT_EQ('A', packed[ndx++]); |
| 164 EXPECT_EQ('P', packed[ndx++]); |
| 165 EXPECT_EQ('S', packed[ndx++]); |
| 166 EXPECT_EQ('2', packed[ndx++]); |
| 167 // Relocation count |
| 168 EXPECT_EQ(6U, packed[ndx++]); |
| 169 // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d/7d (depending on ELF::Ad
dr) |
| 170 EXPECT_EQ(0xfc, packed[ndx++]); |
| 171 EXPECT_EQ(0xff, packed[ndx++]); |
| 172 EXPECT_EQ(0xb7, packed[ndx++]); |
| 173 EXPECT_EQ(0x8e, packed[ndx++]); |
| 174 if (sizeof(typename ELF::Addr) == 8) { |
| 175 // positive for uint64_t |
| 176 EXPECT_EQ(0x0d, packed[ndx++]); |
| 177 } else { |
| 178 // negative for uint32_t |
| 179 EXPECT_EQ(0x7d, packed[ndx++]); |
| 180 } |
| 181 // group 1 |
| 182 EXPECT_EQ(0x03, packed[ndx++]); // size |
| 183 EXPECT_EQ(0x0b, packed[ndx++]); // flags |
| 184 EXPECT_EQ(0x04, packed[ndx++]); // r_offset_delta |
| 185 EXPECT_EQ(0x01, packed[ndx++]); // r_info |
| 186 // group 1 - addend 1: 10024 = 0xa8, 0xce, 0x80 |
| 187 EXPECT_EQ(0xa8, packed[ndx++]); |
| 188 EXPECT_EQ(0xce, packed[ndx++]); |
| 189 EXPECT_EQ(0x00, packed[ndx++]); |
| 190 // group 1 - addend 2: -12 = 0x74 |
| 191 EXPECT_EQ(0x74, packed[ndx++]); |
| 192 // group 1 - addend 3: +12 = 0x0c |
| 193 EXPECT_EQ(0x0c, packed[ndx++]); |
| 194 |
| 195 // group 2 |
| 196 EXPECT_EQ(0x03, packed[ndx++]); // size |
| 197 EXPECT_EQ(0x0b, packed[ndx++]); // flags |
| 198 EXPECT_EQ(0x08, packed[ndx++]); // r_offset_delta |
| 199 EXPECT_EQ(0x01, packed[ndx++]); // r_info |
| 200 |
| 201 // group 2 - addend 1: -24 = 0x68 |
| 202 EXPECT_EQ(0x68, packed[ndx++]); |
| 203 // group 2 - addend 2: -24 = 0x68 |
| 204 EXPECT_EQ(0x68, packed[ndx++]); |
| 205 // group 2 - addend 3: -24 = 0x68 |
| 206 EXPECT_EQ(0x68, packed[ndx++]); |
| 207 |
| 208 EXPECT_EQ(ndx, packed.size()); |
| 209 } |
| 210 |
| 211 TEST(Packer, PackWithAddend) { |
| 212 DoPackWithAddend<ELF32_traits>(); |
| 213 DoPackWithAddend<ELF64_traits>(); |
| 214 } |
| 215 |
| 216 template <typename ELF> |
| 217 static void DoUnpackWithAddend() { |
| 218 std::vector<uint8_t> packed; |
| 219 // Identifier. |
| 220 packed.push_back('A'); |
| 221 packed.push_back('P'); |
| 222 packed.push_back('S'); |
| 223 packed.push_back('2'); |
| 224 // Relocation count |
| 225 packed.push_back(6U); |
| 226 // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d |
| 227 packed.push_back(0xfc); |
| 228 packed.push_back(0xff); |
| 229 packed.push_back(0xb7); |
| 230 packed.push_back(0x8e); |
| 231 if (sizeof(typename ELF::Addr) == 8) { |
| 232 // positive for uint64_t |
| 233 packed.push_back(0x0d); |
| 234 } else { |
| 235 // negative for uint32_t |
| 236 packed.push_back(0x7d); |
| 237 } |
| 238 // group 1 |
| 239 packed.push_back(0x03); // size |
| 240 packed.push_back(0x0b); // flags |
| 241 packed.push_back(0x04); // r_offset_delta |
| 242 packed.push_back(0x01); // r_info |
| 243 // group 1 - addend 1: 10024 = 0xa8, 0xce, 0x80 |
| 244 packed.push_back(0xa8); |
| 245 packed.push_back(0xce); |
| 246 packed.push_back(0x00); |
| 247 // group 1 - addend 2: -12 = 0x74 |
| 248 packed.push_back(0x74); |
| 249 // group 1 - addend 3: +12 = 0x0c |
| 250 packed.push_back(0x0c); |
| 251 |
| 252 // group 2 |
| 253 packed.push_back(0x03); // size |
| 254 packed.push_back(0x0b); // flags |
| 255 packed.push_back(0x08); // r_offset_delta |
| 256 packed.push_back(0x01); // r_info |
| 257 |
| 258 // group 2 - addend 1: -24 = 0x68 |
| 259 packed.push_back(0x68); |
| 260 // group 2 - addend 2: -24 = 0x68 |
| 261 packed.push_back(0x68); |
| 262 // group 2 - addend 3: -24 = 0x68 |
| 263 packed.push_back(0x68); |
| 264 |
| 265 std::vector<typename ELF::Rela> relocations; |
| 266 |
| 267 RelocationPacker<ELF> packer; |
| 268 |
| 269 relocations.clear(); |
| 270 packer.UnpackRelocations(packed, &relocations); |
| 271 |
| 272 EXPECT_EQ(6U, relocations.size()); |
| 273 size_t ndx = 0; |
| 274 // Initial relocation. |
| 275 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0000, 0x01, 10024, relocations[ndx++]))
; |
| 276 // Two more relocations, 4 byte offset deltas, 12 byte addend deltas. |
| 277 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0004, 0x01, 10012, relocations[ndx++]))
; |
| 278 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0008, 0x01, 10024, relocations[ndx++]))
; |
| 279 // Three more relocations, 8 byte offset deltas, -24 byte addend deltas. |
| 280 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0010, 0x01, 10000, relocations[ndx++]))
; |
| 281 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0018, 0x01, 9976, relocations[ndx++])); |
| 282 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0020, 0x01, 9952, relocations[ndx++])); |
| 283 |
| 284 EXPECT_EQ(ndx, relocations.size()); |
| 285 } |
| 286 |
| 287 TEST(Packer, UnpackWithAddend) { |
| 288 DoUnpackWithAddend<ELF32_traits>(); |
| 289 DoUnpackWithAddend<ELF64_traits>(); |
| 290 } |
| 291 |
| 292 } // namespace relocation_packer |
| OLD | NEW |