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 "delta_encoder.h"
6
7#include <vector>
8#include "elf.h"
9#include "elf_traits.h"
10#include "testing/gtest/include/gtest/gtest.h"
11
12namespace {
13
14void AddRelocation(ELF::Addr addr,
15                   ELF::Sxword addend,
16                   std::vector<ELF::Rela>* relocations) {
17  ELF::Rela relocation;
18  relocation.r_offset = addr;
19  relocation.r_info = ELF_R_INFO(0, ELF::kRelativeRelocationCode);
20  relocation.r_addend = addend;
21  relocations->push_back(relocation);
22}
23
24bool CheckRelocation(ELF::Addr addr,
25                     ELF::Sxword addend,
26                     const ELF::Rela& relocation) {
27  return relocation.r_offset == addr &&
28      ELF_R_SYM(relocation.r_info) == 0 &&
29      ELF_R_TYPE(relocation.r_info) == ELF::kRelativeRelocationCode &&
30      relocation.r_addend == addend;
31}
32
33}  // namespace
34
35namespace relocation_packer {
36
37TEST(Delta, Encode) {
38  std::vector<ELF::Rela> relocations;
39  std::vector<ELF::Sxword> packed;
40
41  RelocationDeltaCodec codec;
42
43  packed.clear();
44  codec.Encode(relocations, &packed);
45
46  EXPECT_EQ(0, packed.size());
47
48  // Initial relocation.
49  AddRelocation(0xf00d0000, 10000, &relocations);
50
51  packed.clear();
52  codec.Encode(relocations, &packed);
53
54  EXPECT_EQ(3, packed.size());
55  // One pair present.
56  EXPECT_EQ(1, packed[0]);
57  // Delta from the neutral element is the initial relocation.
58  EXPECT_EQ(0xf00d0000, packed[1]);
59  EXPECT_EQ(10000, packed[2]);
60
61  // Add a second relocation, 4 byte offset delta, 12 byte addend delta.
62  AddRelocation(0xf00d0004, 10012, &relocations);
63
64  packed.clear();
65  codec.Encode(relocations, &packed);
66
67  EXPECT_EQ(5, packed.size());
68  // Two pairs present.
69  EXPECT_EQ(2, packed[0]);
70  // Delta from the neutral element is the initial relocation.
71  EXPECT_EQ(0xf00d0000, packed[1]);
72  EXPECT_EQ(10000, packed[2]);
73  // 4 byte offset delta, 12 byte addend delta.
74  EXPECT_EQ(4, packed[3]);
75  EXPECT_EQ(12, packed[4]);
76
77  // Add a third relocation, 4 byte offset delta, 12 byte addend delta.
78  AddRelocation(0xf00d0008, 10024, &relocations);
79
80  // Add three more relocations, 8 byte offset deltas, -24 byte addend deltas.
81  AddRelocation(0xf00d0010, 10000, &relocations);
82  AddRelocation(0xf00d0018, 9976, &relocations);
83  AddRelocation(0xf00d0020, 9952, &relocations);
84
85  packed.clear();
86  codec.Encode(relocations, &packed);
87
88  EXPECT_EQ(13, packed.size());
89  // Six pairs present.
90  EXPECT_EQ(6, packed[0]);
91  // Initial relocation.
92  EXPECT_EQ(0xf00d0000, packed[1]);
93  EXPECT_EQ(10000, packed[2]);
94  // Two relocations, 4 byte offset deltas, 12 byte addend deltas.
95  EXPECT_EQ(4, packed[3]);
96  EXPECT_EQ(12, packed[4]);
97  EXPECT_EQ(4, packed[5]);
98  EXPECT_EQ(12, packed[6]);
99  // Three relocations, 8 byte offset deltas, -24 byte addend deltas.
100  EXPECT_EQ(8, packed[7]);
101  EXPECT_EQ(-24, packed[8]);
102  EXPECT_EQ(8, packed[9]);
103  EXPECT_EQ(-24, packed[10]);
104  EXPECT_EQ(8, packed[11]);
105  EXPECT_EQ(-24, packed[12]);
106}
107
108TEST(Delta, Decode) {
109  std::vector<ELF::Sxword> packed;
110  std::vector<ELF::Rela> relocations;
111
112  RelocationDeltaCodec codec;
113  codec.Decode(packed, &relocations);
114
115  EXPECT_EQ(0, relocations.size());
116
117  // Six pairs.
118  packed.push_back(6);
119  // Initial relocation.
120  packed.push_back(0xc0de0000);
121  packed.push_back(10000);
122  // Two relocations, 4 byte offset deltas, 12 byte addend deltas.
123  packed.push_back(4);
124  packed.push_back(12);
125  packed.push_back(4);
126  packed.push_back(12);
127  // Three relocations, 8 byte offset deltas, -24 byte addend deltas.
128  packed.push_back(8);
129  packed.push_back(-24);
130  packed.push_back(8);
131  packed.push_back(-24);
132  packed.push_back(8);
133  packed.push_back(-24);
134
135  relocations.clear();
136  codec.Decode(packed, &relocations);
137
138  EXPECT_EQ(6, relocations.size());
139  // Initial relocation.
140  EXPECT_TRUE(CheckRelocation(0xc0de0000, 10000, relocations[0]));
141  // Two relocations, 4 byte offset deltas, 12 byte addend deltas.
142  EXPECT_TRUE(CheckRelocation(0xc0de0004, 10012, relocations[1]));
143  EXPECT_TRUE(CheckRelocation(0xc0de0008, 10024, relocations[2]));
144  // Three relocations, 8 byte offset deltas, -24 byte addend deltas.
145  EXPECT_TRUE(CheckRelocation(0xc0de0010, 10000, relocations[3]));
146  EXPECT_TRUE(CheckRelocation(0xc0de0018, 9976, relocations[4]));
147  EXPECT_TRUE(CheckRelocation(0xc0de0020, 9952, relocations[5]));
148}
149
150}  // namespace relocation_packer
151