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