1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file.
4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "run_length_encoder.h"
6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <vector>
8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "elf.h"
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "elf_traits.h"
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace {
13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void AddRelocation(ELF::Addr addr, std::vector<ELF::Rel>* relocations) {
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ELF::Rel relocation;
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  relocation.r_offset = addr;
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  relocation.r_info = ELF_R_INFO(0, ELF::kRelativeRelocationCode);
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  relocations->push_back(relocation);
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool CheckRelocation(ELF::Addr addr, const ELF::Rel& relocation) {
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return relocation.r_offset == addr &&
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ELF_R_SYM(relocation.r_info) == 0 &&
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ELF_R_TYPE(relocation.r_info) == ELF::kRelativeRelocationCode;
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace relocation_packer {
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST(RunLength, Encode) {
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<ELF::Rel> relocations;
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<ELF::Xword> packed;
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RelocationRunLengthCodec codec;
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packed.clear();
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  codec.Encode(relocations, &packed);
39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(0, packed.size());
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Add one relocation (insufficient data to encode).
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AddRelocation(0xf00d0000, &relocations);
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packed.clear();
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  codec.Encode(relocations, &packed);
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(0, packed.size());
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Add a second relocation, 4 byte delta (minimum data to encode).
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AddRelocation(0xf00d0004, &relocations);
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packed.clear();
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  codec.Encode(relocations, &packed);
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(4, packed.size());
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // One count-delta pair present.
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(1, packed[0]);
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Initial relocation.
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(0xf00d0000, packed[1]);
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Run of a single relocation, 4 byte delta.
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(1, packed[2]);
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(4, packed[3]);
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Add a third relocation, 4 byte delta.
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AddRelocation(0xf00d0008, &relocations);
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Add three more relocations, 8 byte deltas.
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AddRelocation(0xf00d0010, &relocations);
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AddRelocation(0xf00d0018, &relocations);
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AddRelocation(0xf00d0020, &relocations);
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packed.clear();
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  codec.Encode(relocations, &packed);
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(6, packed.size());
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Two count-delta pairs present.
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(2, packed[0]);
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Initial relocation.
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(0xf00d0000, packed[1]);
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Run of two relocations, 4 byte deltas.
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(2, packed[2]);
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(4, packed[3]);
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Run of three relocations, 8 byte deltas.
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(3, packed[4]);
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(8, packed[5]);
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST(RunLength, Decode) {
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<ELF::Xword> packed;
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<ELF::Rel> relocations;
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RelocationRunLengthCodec codec;
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  codec.Decode(packed, &relocations);
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(0, relocations.size());
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Two count-delta pairs.
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  packed.push_back(2);
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Initial relocation.
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packed.push_back(0xc0de0000);
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Run of two relocations, 4 byte deltas.
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  packed.push_back(2);
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  packed.push_back(4);
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Run of three relocations, 8 byte deltas.
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  packed.push_back(3);
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  packed.push_back(8);
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  relocations.clear();
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  codec.Decode(packed, &relocations);
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(6, relocations.size());
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Initial relocation.
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(CheckRelocation(0xc0de0000, relocations[0]));
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Two relocations, 4 byte deltas.
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(CheckRelocation(0xc0de0004, relocations[1]));
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(CheckRelocation(0xc0de0008, relocations[2]));
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Three relocations, 8 byte deltas.
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(CheckRelocation(0xc0de0010, relocations[3]));
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(CheckRelocation(0xc0de0018, relocations[4]));
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(CheckRelocation(0xc0de0020, relocations[5]));
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace relocation_packer
125