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