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 "packer.h"
6
7 #include <vector>
8 #include "elf.h"
9 #include "elf_traits.h"
10 #include "gtest/gtest.h"
11
12
13 template <typename ELF>
AddRelocation(typename ELF::Addr addr,typename ELF::Xword info,typename ELF::Sxword addend,std::vector<typename ELF::Rela> * relocations)14 static void AddRelocation(typename ELF::Addr addr,
15 typename ELF::Xword info,
16 typename ELF::Sxword addend,
17 std::vector<typename ELF::Rela>* relocations) {
18 typename ELF::Rela relocation;
19 relocation.r_offset = addr;
20 relocation.r_info = info;
21 relocation.r_addend = addend;
22
23 relocations->push_back(relocation);
24 }
25
26 template <typename ELF>
CheckRelocation(typename ELF::Addr addr,typename ELF::Xword info,typename ELF::Sxword addend,const typename ELF::Rela & relocation)27 static bool CheckRelocation(typename ELF::Addr addr,
28 typename ELF::Xword info,
29 typename ELF::Sxword addend,
30 const typename ELF::Rela& relocation) {
31 return relocation.r_offset == addr &&
32 relocation.r_info == info &&
33 relocation.r_addend == addend;
34 }
35
36 namespace relocation_packer {
37
38 template <typename ELF>
DoPackNoAddend()39 static void DoPackNoAddend() {
40 std::vector<typename ELF::Rela> relocations;
41 std::vector<uint8_t> packed;
42 bool is_32 = sizeof(typename ELF::Addr) == 4;
43 // Initial relocation.
44 AddRelocation<ELF>(0xd1ce0000, 0x11, 0, &relocations);
45 // Two more relocations, 4 byte deltas.
46 AddRelocation<ELF>(0xd1ce0004, 0x11, 0, &relocations);
47 AddRelocation<ELF>(0xd1ce0008, 0x11, 0, &relocations);
48 // Three more relocations, 8 byte deltas.
49 AddRelocation<ELF>(0xd1ce0010, 0x11, 0, &relocations);
50 AddRelocation<ELF>(0xd1ce0018, 0x11, 0, &relocations);
51 AddRelocation<ELF>(0xd1ce0020, 0x11, 0, &relocations);
52
53 RelocationPacker<ELF> packer;
54
55 packed.clear();
56 packer.PackRelocations(relocations, &packed);
57
58 ASSERT_EQ(18U, packed.size());
59 // Identifier.
60 size_t ndx = 0;
61 EXPECT_EQ('A', packed[ndx++]);
62 EXPECT_EQ('P', packed[ndx++]);
63 EXPECT_EQ('S', packed[ndx++]);
64 EXPECT_EQ('2', packed[ndx++]);
65 // relocation count
66 EXPECT_EQ(6, packed[ndx++]);
67 // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 7d/0d (32/64bit)
68 EXPECT_EQ(0xfc, packed[ndx++]);
69 EXPECT_EQ(0xff, packed[ndx++]);
70 EXPECT_EQ(0xb7, packed[ndx++]);
71 EXPECT_EQ(0x8e, packed[ndx++]);
72 EXPECT_EQ(is_32 ? 0x7d : 0x0d, packed[ndx++]);
73 // first group
74 EXPECT_EQ(3, packed[ndx++]); // size
75 EXPECT_EQ(3, packed[ndx++]); // flags
76 EXPECT_EQ(4, packed[ndx++]); // r_offset_delta
77 EXPECT_EQ(0x11, packed[ndx++]); // r_info
78 // second group
79 EXPECT_EQ(3, packed[ndx++]); // size
80 EXPECT_EQ(3, packed[ndx++]); // flags
81 EXPECT_EQ(8, packed[ndx++]); // r_offset_delta
82 EXPECT_EQ(0x11, packed[ndx++]); // r_info
83
84 EXPECT_EQ(ndx, packed.size());
85 }
86
TEST(Packer,PackNoAddend32)87 TEST(Packer, PackNoAddend32) {
88 DoPackNoAddend<ELF32_traits>();
89 }
90
TEST(Packer,PackNoAddend64)91 TEST(Packer, PackNoAddend64) {
92 DoPackNoAddend<ELF64_traits>();
93 }
94
95 template <typename ELF>
DoUnpackNoAddend()96 static void DoUnpackNoAddend() {
97 std::vector<typename ELF::Rela> relocations;
98 std::vector<uint8_t> packed;
99 bool is_32 = sizeof(typename ELF::Addr) == 4;
100 packed.push_back('A');
101 packed.push_back('P');
102 packed.push_back('S');
103 packed.push_back('2');
104 // relocation count
105 packed.push_back(6);
106 // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 7d/0d (32/64bit)
107 packed.push_back(0xfc);
108 packed.push_back(0xff);
109 packed.push_back(0xb7);
110 packed.push_back(0x8e);
111 packed.push_back(is_32 ? 0x7d : 0x0d);
112 // first group
113 packed.push_back(3); // size
114 packed.push_back(3); // flags
115 packed.push_back(4); // r_offset_delta
116 packed.push_back(0x11); // r_info
117 // second group
118 packed.push_back(3); // size
119 packed.push_back(3); // flags
120 packed.push_back(8); // r_offset_delta
121 packed.push_back(0x11); // r_info
122
123 RelocationPacker<ELF> packer;
124 packer.UnpackRelocations(packed, &relocations);
125
126 size_t ndx = 0;
127 EXPECT_EQ(6U, relocations.size());
128 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0000, 0x11, 0, relocations[ndx++]));
129 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0004, 0x11, 0, relocations[ndx++]));
130 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0008, 0x11, 0, relocations[ndx++]));
131
132 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0010, 0x11, 0, relocations[ndx++]));
133 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0018, 0x11, 0, relocations[ndx++]));
134 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0020, 0x11, 0, relocations[ndx++]));
135
136 EXPECT_EQ(ndx, relocations.size());
137 }
138
TEST(Packer,UnpackNoAddend32)139 TEST(Packer, UnpackNoAddend32) {
140 DoUnpackNoAddend<ELF32_traits>();
141 }
142
TEST(Packer,UnpackNoAddend64)143 TEST(Packer, UnpackNoAddend64) {
144 DoUnpackNoAddend<ELF64_traits>();
145 }
146
147 template <typename ELF>
DoPackWithAddend()148 static void DoPackWithAddend() {
149 std::vector<typename ELF::Rela> relocations;
150
151 // Initial relocation.
152 AddRelocation<ELF>(0xd1ce0000, 0x01, 10024, &relocations);
153 // Two more relocations, 4 byte offset deltas, 12 byte addend deltas.
154 AddRelocation<ELF>(0xd1ce0004, 0x01, 10012, &relocations);
155 AddRelocation<ELF>(0xd1ce0008, 0x01, 10024, &relocations);
156 // Three more relocations, 8 byte deltas, -24 byte addend deltas.
157 AddRelocation<ELF>(0xd1ce0010, 0x01, 10000, &relocations);
158 AddRelocation<ELF>(0xd1ce0018, 0x01, 9976, &relocations);
159 AddRelocation<ELF>(0xd1ce0020, 0x01, 9952, &relocations);
160
161 std::vector<uint8_t> packed;
162
163 RelocationPacker<ELF> packer;
164
165 packed.clear();
166 packer.PackRelocations(relocations, &packed);
167
168 EXPECT_EQ(26U, packed.size());
169 size_t ndx = 0;
170 // Identifier.
171 EXPECT_EQ('A', packed[ndx++]);
172 EXPECT_EQ('P', packed[ndx++]);
173 EXPECT_EQ('S', packed[ndx++]);
174 EXPECT_EQ('2', packed[ndx++]);
175 // Relocation count
176 EXPECT_EQ(6U, packed[ndx++]);
177 // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d/7d (depending on ELF::Addr)
178 EXPECT_EQ(0xfc, packed[ndx++]);
179 EXPECT_EQ(0xff, packed[ndx++]);
180 EXPECT_EQ(0xb7, packed[ndx++]);
181 EXPECT_EQ(0x8e, packed[ndx++]);
182 if (sizeof(typename ELF::Addr) == 8) {
183 // positive for uint64_t
184 EXPECT_EQ(0x0d, packed[ndx++]);
185 } else {
186 // negative for uint32_t
187 EXPECT_EQ(0x7d, packed[ndx++]);
188 }
189 // group 1
190 EXPECT_EQ(0x03, packed[ndx++]); // size
191 EXPECT_EQ(0x0b, packed[ndx++]); // flags
192 EXPECT_EQ(0x04, packed[ndx++]); // r_offset_delta
193 EXPECT_EQ(0x01, packed[ndx++]); // r_info
194 // group 1 - addend 1: 10024 = 0xa8, 0xce, 0x80
195 EXPECT_EQ(0xa8, packed[ndx++]);
196 EXPECT_EQ(0xce, packed[ndx++]);
197 EXPECT_EQ(0x00, packed[ndx++]);
198 // group 1 - addend 2: -12 = 0x74
199 EXPECT_EQ(0x74, packed[ndx++]);
200 // group 1 - addend 3: +12 = 0x0c
201 EXPECT_EQ(0x0c, packed[ndx++]);
202
203 // group 2
204 EXPECT_EQ(0x03, packed[ndx++]); // size
205 EXPECT_EQ(0x0b, packed[ndx++]); // flags
206 EXPECT_EQ(0x08, packed[ndx++]); // r_offset_delta
207 EXPECT_EQ(0x01, packed[ndx++]); // r_info
208
209 // group 2 - addend 1: -24 = 0x68
210 EXPECT_EQ(0x68, packed[ndx++]);
211 // group 2 - addend 2: -24 = 0x68
212 EXPECT_EQ(0x68, packed[ndx++]);
213 // group 2 - addend 3: -24 = 0x68
214 EXPECT_EQ(0x68, packed[ndx++]);
215
216 EXPECT_EQ(ndx, packed.size());
217 }
218
TEST(Packer,PackWithAddend)219 TEST(Packer, PackWithAddend) {
220 DoPackWithAddend<ELF32_traits>();
221 DoPackWithAddend<ELF64_traits>();
222 }
223
224 template <typename ELF>
DoUnpackWithAddend()225 static void DoUnpackWithAddend() {
226 std::vector<uint8_t> packed;
227 // Identifier.
228 packed.push_back('A');
229 packed.push_back('P');
230 packed.push_back('S');
231 packed.push_back('2');
232 // Relocation count
233 packed.push_back(6U);
234 // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d
235 packed.push_back(0xfc);
236 packed.push_back(0xff);
237 packed.push_back(0xb7);
238 packed.push_back(0x8e);
239 if (sizeof(typename ELF::Addr) == 8) {
240 // positive for uint64_t
241 packed.push_back(0x0d);
242 } else {
243 // negative for uint32_t
244 packed.push_back(0x7d);
245 }
246 // group 1
247 packed.push_back(0x03); // size
248 packed.push_back(0x0b); // flags
249 packed.push_back(0x04); // r_offset_delta
250 packed.push_back(0x01); // r_info
251 // group 1 - addend 1: 10024 = 0xa8, 0xce, 0x80
252 packed.push_back(0xa8);
253 packed.push_back(0xce);
254 packed.push_back(0x00);
255 // group 1 - addend 2: -12 = 0x74
256 packed.push_back(0x74);
257 // group 1 - addend 3: +12 = 0x0c
258 packed.push_back(0x0c);
259
260 // group 2
261 packed.push_back(0x03); // size
262 packed.push_back(0x0b); // flags
263 packed.push_back(0x08); // r_offset_delta
264 packed.push_back(0x01); // r_info
265
266 // group 2 - addend 1: -24 = 0x68
267 packed.push_back(0x68);
268 // group 2 - addend 2: -24 = 0x68
269 packed.push_back(0x68);
270 // group 2 - addend 3: -24 = 0x68
271 packed.push_back(0x68);
272
273 std::vector<typename ELF::Rela> relocations;
274
275 RelocationPacker<ELF> packer;
276
277 relocations.clear();
278 packer.UnpackRelocations(packed, &relocations);
279
280 EXPECT_EQ(6U, relocations.size());
281 size_t ndx = 0;
282 // Initial relocation.
283 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0000, 0x01, 10024, relocations[ndx++]));
284 // Two more relocations, 4 byte offset deltas, 12 byte addend deltas.
285 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0004, 0x01, 10012, relocations[ndx++]));
286 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0008, 0x01, 10024, relocations[ndx++]));
287 // Three more relocations, 8 byte offset deltas, -24 byte addend deltas.
288 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0010, 0x01, 10000, relocations[ndx++]));
289 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0018, 0x01, 9976, relocations[ndx++]));
290 EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0020, 0x01, 9952, relocations[ndx++]));
291
292 EXPECT_EQ(ndx, relocations.size());
293 }
294
TEST(Packer,UnpackWithAddend)295 TEST(Packer, UnpackWithAddend) {
296 DoUnpackWithAddend<ELF32_traits>();
297 DoUnpackWithAddend<ELF64_traits>();
298 }
299
300 } // namespace relocation_packer
301