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