blob: 06d9c967314f762f3ba762b8985569e8de2043ac [file] [log] [blame]
Dmitriy Ivanov87a06172015-02-06 10:56:28 -08001// 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"
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -08009#include "gtest/gtest.h"
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080010
11namespace {
12
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080013template <typename T>
14void AddRelocation(uint32_t addr,
15 uint32_t info,
16 int32_t addend,
17 std::vector<T>* relocations) {
18 T relocation;
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080019 relocation.r_offset = addr;
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080020 relocation.r_info = info;
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080021 relocation.r_addend = addend;
22 relocations->push_back(relocation);
23}
24
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080025template <typename T>
26bool CheckRelocation(uint32_t addr,
27 uint32_t info,
28 int32_t addend,
29 const T& relocation) {
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080030 return relocation.r_offset == addr &&
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080031 relocation.r_info == info &&
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080032 relocation.r_addend == addend;
33}
34
35} // namespace
36
37namespace relocation_packer {
38
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080039template <typename ELF>
40static void encode() {
41 std::vector<typename ELF::Rela> relocations;
42 std::vector<typename ELF::Addr> packed;
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080043
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080044 RelocationDeltaCodec<ELF> codec;
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080045
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080046 codec.Encode(relocations, &packed);
47
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080048 ASSERT_EQ(0U, packed.size());
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080049
50 // Initial relocation.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080051 AddRelocation(0xf00d0000, 11U, 10000, &relocations);
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080052
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080053 codec.Encode(relocations, &packed);
54
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080055 // size of reloc table, size of group, flags, 3 fields, zero
56 EXPECT_EQ(7U, packed.size());
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080057 // One pair present.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080058 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
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080067
68 // Add a second relocation, 4 byte offset delta, 12 byte addend delta.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080069 // same info
70 AddRelocation(0xf00d0004, 11U, 10012, &relocations);
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080071
72 packed.clear();
73 codec.Encode(relocations, &packed);
74
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080075 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
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080087
88 // Add a third relocation, 4 byte offset delta, 12 byte addend delta.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080089 // different info
90 AddRelocation(0xf00d0008, 41U, 10024, &relocations);
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080091
92 // Add three more relocations, 8 byte offset deltas, -24 byte addend deltas.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -080093 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);
Dmitriy Ivanov87a06172015-02-06 10:56:28 -080099
100 packed.clear();
101 codec.Encode(relocations, &packed);
102
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800103 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
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800114 // Initial relocation.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800115 EXPECT_EQ(10000U, packed[ndx++]); // addend delta
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800116 // Two relocations, 4 byte offset deltas, 12 byte addend deltas.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800117 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
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800132 // Three relocations, 8 byte offset deltas, -24 byte addend deltas.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800133 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);
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800147}
148
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800149TEST(Delta, Encode32) {
150 encode<ELF32_traits>();
151}
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800152
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800153TEST(Delta, Encode64) {
154 encode<ELF64_traits>();
155}
156
157template <typename ELF>
158static void decode() {
159 std::vector<typename ELF::Addr> packed;
160 std::vector<typename ELF::Rela> relocations;
161
162 RelocationDeltaCodec<ELF> codec;
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800163 codec.Decode(packed, &relocations);
164
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800165 EXPECT_EQ(0U, relocations.size());
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800166
167 // Six pairs.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800168 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
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800174 // Initial relocation.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800175 packed.push_back(10000U);
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800176 // Two relocations, 4 byte offset deltas, 12 byte addend deltas.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800177 packed.push_back(12U); // addend
178 packed.push_back(12U); // addend
179
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800180 // Three relocations, 8 byte offset deltas, -24 byte addend deltas.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800181 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
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800195
196 relocations.clear();
197 codec.Decode(packed, &relocations);
198
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800199 EXPECT_EQ(6U, relocations.size());
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800200 // Initial relocation.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800201 EXPECT_TRUE(CheckRelocation(0xc0de0000, 11U, 10000, relocations[0]));
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800202 // Two relocations, 4 byte offset deltas, 12 byte addend deltas.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800203 EXPECT_TRUE(CheckRelocation(0xc0de0004, 11U, 10012, relocations[1]));
204 EXPECT_TRUE(CheckRelocation(0xc0de0008, 11U, 10024, relocations[2]));
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800205 // Three relocations, 8 byte offset deltas, -24 byte addend deltas.
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800206 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]));
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800209}
210
Dmitriy Ivanovf8ff6b12015-01-27 19:32:56 -0800211TEST(Delta, Decode32) {
212 decode<ELF32_traits>();
213}
214
215TEST(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
Dmitriy Ivanov87a06172015-02-06 10:56:28 -0800223} // namespace relocation_packer