15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "delta_encoder.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <vector> 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "elf.h" 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "elf_traits.h" 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace { 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void AddRelocation(ELF::Addr addr, 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ELF::Sxword addend, 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<ELF::Rela>* relocations) { 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ELF::Rela relocation; 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relocation.r_offset = addr; 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relocation.r_info = ELF_R_INFO(0, ELF::kRelativeRelocationCode); 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relocation.r_addend = addend; 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relocations->push_back(relocation); 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool CheckRelocation(ELF::Addr addr, 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ELF::Sxword addend, 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const ELF::Rela& relocation) { 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return relocation.r_offset == addr && 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ELF_R_SYM(relocation.r_info) == 0 && 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ELF_R_TYPE(relocation.r_info) == ELF::kRelativeRelocationCode && 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relocation.r_addend == addend; 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace relocation_packer { 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST(Delta, Encode) { 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<ELF::Rela> relocations; 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<ELF::Sxword> packed; 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RelocationDeltaCodec codec; 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.clear(); 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) codec.Encode(relocations, &packed); 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(0, packed.size()); 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Initial relocation. 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AddRelocation(0xf00d0000, 10000, &relocations); 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.clear(); 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) codec.Encode(relocations, &packed); 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(3, packed.size()); 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // One pair present. 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(1, packed[0]); 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Delta from the neutral element is the initial relocation. 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(0xf00d0000, packed[1]); 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(10000, packed[2]); 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Add a second relocation, 4 byte offset delta, 12 byte addend delta. 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AddRelocation(0xf00d0004, 10012, &relocations); 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.clear(); 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) codec.Encode(relocations, &packed); 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(5, packed.size()); 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Two pairs present. 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(2, packed[0]); 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Delta from the neutral element is the initial relocation. 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(0xf00d0000, packed[1]); 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(10000, packed[2]); 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // 4 byte offset delta, 12 byte addend delta. 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(4, packed[3]); 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(12, packed[4]); 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Add a third relocation, 4 byte offset delta, 12 byte addend delta. 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AddRelocation(0xf00d0008, 10024, &relocations); 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Add three more relocations, 8 byte offset deltas, -24 byte addend deltas. 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AddRelocation(0xf00d0010, 10000, &relocations); 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AddRelocation(0xf00d0018, 9976, &relocations); 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AddRelocation(0xf00d0020, 9952, &relocations); 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.clear(); 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) codec.Encode(relocations, &packed); 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(13, packed.size()); 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Six pairs present. 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(6, packed[0]); 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Initial relocation. 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(0xf00d0000, packed[1]); 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(10000, packed[2]); 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Two relocations, 4 byte offset deltas, 12 byte addend deltas. 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(4, packed[3]); 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(12, packed[4]); 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(4, packed[5]); 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(12, packed[6]); 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Three relocations, 8 byte offset deltas, -24 byte addend deltas. 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(8, packed[7]); 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(-24, packed[8]); 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(8, packed[9]); 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(-24, packed[10]); 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(8, packed[11]); 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(-24, packed[12]); 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST(Delta, Decode) { 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<ELF::Sxword> packed; 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<ELF::Rela> relocations; 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RelocationDeltaCodec codec; 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) codec.Decode(packed, &relocations); 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(0, relocations.size()); 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Six pairs. 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(6); 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Initial relocation. 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(0xc0de0000); 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(10000); 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Two relocations, 4 byte offset deltas, 12 byte addend deltas. 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(4); 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(12); 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(4); 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(12); 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Three relocations, 8 byte offset deltas, -24 byte addend deltas. 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(8); 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(-24); 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(8); 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(-24); 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(8); 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) packed.push_back(-24); 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relocations.clear(); 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) codec.Decode(packed, &relocations); 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(6, relocations.size()); 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Initial relocation. 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(CheckRelocation(0xc0de0000, 10000, relocations[0])); 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Two relocations, 4 byte offset deltas, 12 byte addend deltas. 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(CheckRelocation(0xc0de0004, 10012, relocations[1])); 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(CheckRelocation(0xc0de0008, 10024, relocations[2])); 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Three relocations, 8 byte offset deltas, -24 byte addend deltas. 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(CheckRelocation(0xc0de0010, 10000, relocations[3])); 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(CheckRelocation(0xc0de0018, 9976, relocations[4])); 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(CheckRelocation(0xc0de0020, 9952, relocations[5])); 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace relocation_packer 151