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 "gtest/gtest.h"
10
11 namespace {
12
13 template <typename T>
AddRelocation(uint32_t addr,uint32_t info,int32_t addend,std::vector<T> * relocations)14 void AddRelocation(uint32_t addr,
15 uint32_t info,
16 int32_t addend,
17 std::vector<T>* relocations) {
18 T relocation;
19 relocation.r_offset = addr;
20 relocation.r_info = info;
21 relocation.r_addend = addend;
22 relocations->push_back(relocation);
23 }
24
25 template <typename T>
CheckRelocation(uint32_t addr,uint32_t info,int32_t addend,const T & relocation)26 bool CheckRelocation(uint32_t addr,
27 uint32_t info,
28 int32_t addend,
29 const T& relocation) {
30 return relocation.r_offset == addr &&
31 relocation.r_info == info &&
32 relocation.r_addend == addend;
33 }
34
35 } // namespace
36
37 namespace relocation_packer {
38
39 template <typename ELF>
encode()40 static void encode() {
41 std::vector<typename ELF::Rela> relocations;
42 std::vector<typename ELF::Addr> packed;
43
44 RelocationDeltaCodec<ELF> codec;
45
46 codec.Encode(relocations, &packed);
47
48 ASSERT_EQ(0U, packed.size());
49
50 // Initial relocation.
51 AddRelocation(0xf00d0000, 11U, 10000, &relocations);
52
53 codec.Encode(relocations, &packed);
54
55 // size of reloc table, size of group, flags, 3 fields, zero
56 EXPECT_EQ(7U, packed.size());
57 // One pair present.
58 size_t ndx = 0;
59 EXPECT_EQ(1U, packed[ndx++]);
60 EXPECT_EQ(0xf00d0000, packed[ndx++]);
61 EXPECT_EQ(1U, packed[ndx++]); // group_size
62 EXPECT_EQ(8U, packed[ndx++]); // flags
63 // Delta from the neutral element is zero
64 EXPECT_EQ(0U, packed[ndx++]); // offset_delta
65 EXPECT_EQ(11U, packed[ndx++]); // info
66 EXPECT_EQ(10000U, packed[ndx++]); // addend_delta
67
68 // Add a second relocation, 4 byte offset delta, 12 byte addend delta.
69 // same info
70 AddRelocation(0xf00d0004, 11U, 10012, &relocations);
71
72 packed.clear();
73 codec.Encode(relocations, &packed);
74
75 ndx = 0;
76 EXPECT_EQ(8U, packed.size());
77
78 EXPECT_EQ(2U, packed[ndx++]); // relocs count
79 EXPECT_EQ(0xf00cfffc, packed[ndx++]); // initial offset
80 EXPECT_EQ(2U, packed[ndx++]); // group count
81 EXPECT_EQ(11U, packed[ndx++]); // flags
82 EXPECT_EQ(4U, packed[ndx++]); // group offset delta
83 EXPECT_EQ(11U, packed[ndx++]); // info
84
85 EXPECT_EQ(10000U, packed[ndx++]); // addend delta
86 EXPECT_EQ(12U, packed[ndx++]); // addend delta
87
88 // Add a third relocation, 4 byte offset delta, 12 byte addend delta.
89 // different info
90 AddRelocation(0xf00d0008, 41U, 10024, &relocations);
91
92 // Add three more relocations, 8 byte offset deltas, -24 byte addend deltas.
93 AddRelocation(0xf00d0010, 42U, 10000, &relocations);
94 AddRelocation(0xf00d0018, 42U, 9976, &relocations);
95 AddRelocation(0xf00d0020, 42U, 9952, &relocations);
96
97 AddRelocation(0xf00d2028, 1042U, 0, &relocations);
98 AddRelocation(0xf00d2030, 3442U, 0, &relocations);
99
100 packed.clear();
101 codec.Encode(relocations, &packed);
102
103 ndx = 0;
104 EXPECT_EQ(26U, packed.size());
105 // Total number of relocs
106 EXPECT_EQ(8U, packed[ndx++]);
107 EXPECT_EQ(0xf00cfffc, packed[ndx++]);
108 // 2 in first group
109 EXPECT_EQ(2U, packed[ndx++]);
110 EXPECT_EQ(11U, packed[ndx++]); //flags
111 EXPECT_EQ(4U, packed[ndx++]); // group offset delta
112 EXPECT_EQ(11U, packed[ndx++]); // info
113
114 // Initial relocation.
115 EXPECT_EQ(10000U, packed[ndx++]); // addend delta
116 // Two relocations, 4 byte offset deltas, 12 byte addend deltas.
117 EXPECT_EQ(12U, packed[ndx++]); // addend delta
118
119 // second group has only one reloc
120 EXPECT_EQ(1U, packed[ndx++]); // count
121 EXPECT_EQ(8U, packed[ndx++]); // flags
122
123 EXPECT_EQ(4U, packed[ndx++]); // offset delta
124 EXPECT_EQ(41U, packed[ndx++]); // info
125 EXPECT_EQ(12U, packed[ndx++]); // addend delta
126
127 // next - 3 relocs grouped by info
128 EXPECT_EQ(3U, packed[ndx++]); // count
129 EXPECT_EQ(11U, packed[ndx++]); // flags
130 EXPECT_EQ(8U, packed[ndx++]); // group offset delta
131 EXPECT_EQ(42U, packed[ndx++]); // info
132 // Three relocations, 8 byte offset deltas, -24 byte addend deltas.
133 EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]);
134 EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]);
135 EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]);
136
137 // and last - 2 relocations without addend
138 EXPECT_EQ(2U, packed[ndx++]);
139 EXPECT_EQ(0U, packed[ndx++]); // flags
140 // offset_deltas and r_infos for next 2 relocations
141 EXPECT_EQ(0x2008U, packed[ndx++]); // offset delta
142 EXPECT_EQ(1042U, packed[ndx++]); // r_info
143 EXPECT_EQ(0x8U, packed[ndx++]); // offset delta
144 EXPECT_EQ(3442U, packed[ndx++]); // r_info
145
146 EXPECT_EQ(packed.size(), ndx);
147 }
148
TEST(Delta,Encode32)149 TEST(Delta, Encode32) {
150 encode<ELF32_traits>();
151 }
152
TEST(Delta,Encode64)153 TEST(Delta, Encode64) {
154 encode<ELF64_traits>();
155 }
156
157 template <typename ELF>
decode()158 static void decode() {
159 std::vector<typename ELF::Addr> packed;
160 std::vector<typename ELF::Rela> relocations;
161
162 RelocationDeltaCodec<ELF> codec;
163 codec.Decode(packed, &relocations);
164
165 EXPECT_EQ(0U, relocations.size());
166
167 // Six pairs.
168 packed.push_back(6U); // count
169 packed.push_back(0xc0ddfffc); // base offset
170 packed.push_back(3U); // group count
171 packed.push_back(11U); // flags
172 packed.push_back(4U); // offset delta
173 packed.push_back(11U); // info
174 // Initial relocation.
175 packed.push_back(10000U);
176 // Two relocations, 4 byte offset deltas, 12 byte addend deltas.
177 packed.push_back(12U); // addend
178 packed.push_back(12U); // addend
179
180 // Three relocations, 8 byte offset deltas, -24 byte addend deltas.
181 packed.push_back(1U); // group count
182 packed.push_back(9U); // flags
183 packed.push_back(11U); // info
184
185 packed.push_back(8U);
186 packed.push_back(static_cast<typename ELF::Addr>(-24));
187 // next group with 2 relocs
188 packed.push_back(2U); // group count
189 packed.push_back(11U); // flags
190 packed.push_back(8U); // offset
191 packed.push_back(42U); // info
192
193 packed.push_back(static_cast<typename ELF::Addr>(-24)); // addend
194 packed.push_back(static_cast<typename ELF::Addr>(-24)); // addend
195
196 relocations.clear();
197 codec.Decode(packed, &relocations);
198
199 EXPECT_EQ(6U, relocations.size());
200 // Initial relocation.
201 EXPECT_TRUE(CheckRelocation(0xc0de0000, 11U, 10000, relocations[0]));
202 // Two relocations, 4 byte offset deltas, 12 byte addend deltas.
203 EXPECT_TRUE(CheckRelocation(0xc0de0004, 11U, 10012, relocations[1]));
204 EXPECT_TRUE(CheckRelocation(0xc0de0008, 11U, 10024, relocations[2]));
205 // Three relocations, 8 byte offset deltas, -24 byte addend deltas.
206 EXPECT_TRUE(CheckRelocation(0xc0de0010, 11U, 10000, relocations[3]));
207 EXPECT_TRUE(CheckRelocation(0xc0de0018, 42U, 9976, relocations[4]));
208 EXPECT_TRUE(CheckRelocation(0xc0de0020, 42U, 9952, relocations[5]));
209 }
210
TEST(Delta,Decode32)211 TEST(Delta, Decode32) {
212 decode<ELF32_traits>();
213 }
214
TEST(Delta,Decode64)215 TEST(Delta, Decode64) {
216 decode<ELF64_traits>();
217 }
218
219 // TODO (dimitry): add more tests (fix by 19 January 2038 03:14:07 UTC)
220 // TODO (dimtiry): 1. Incorrect packed array for decode
221 // TODO (dimtiry): 2. Try to catch situation where it is likely to get series of groups with size 1
222
223 } // namespace relocation_packer
224