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.
5 #include "delta_encoder.h"
10 #include "elf_traits.h"
12 namespace relocation_packer
{
14 // Encode relative relocations with addends into a delta encoded (packed)
15 // representation. Represented as simple r_offset and r_addend delta pairs,
16 // with an implicit neutral element at the start.
17 void RelocationDeltaCodec::Encode(const std::vector
<ELF::Rela
>& relocations
,
18 std::vector
<ELF::Sxword
>* packed
) {
19 // One relocation is sufficient for delta encoding.
20 if (relocations
.size() < 1)
23 // Start with the element count, then append the delta pairs.
24 packed
->push_back(relocations
.size());
27 ELF::Sxword addend
= 0;
29 for (size_t i
= 0; i
< relocations
.size(); ++i
) {
30 const ELF::Rela
* relocation
= &relocations
[i
];
31 CHECK(ELF_R_TYPE(relocation
->r_info
) == ELF::kRelativeRelocationCode
);
33 packed
->push_back(relocation
->r_offset
- offset
);
34 offset
= relocation
->r_offset
;
35 packed
->push_back(relocation
->r_addend
- addend
);
36 addend
= relocation
->r_addend
;
40 // Decode relative relocations with addends from a delta encoded (packed)
42 void RelocationDeltaCodec::Decode(const std::vector
<ELF::Sxword
>& packed
,
43 std::vector
<ELF::Rela
>* relocations
) {
44 // We need at least one packed pair after the packed pair count to be
46 if (packed
.size() < 3)
49 // Ensure that the packed data offers enough pairs. There may be zero
50 // padding on it that we ignore.
51 CHECK(static_cast<size_t>(packed
[0]) <= (packed
.size() - 1) >> 1);
54 ELF::Sxword addend
= 0;
56 // The first packed vector element is the pairs count. Start uncondensing
57 // pairs at the second, and finish at the end of the pairs data.
58 const size_t pairs_count
= packed
[0];
59 for (size_t i
= 1; i
< 1 + (pairs_count
<< 1); i
+= 2) {
61 addend
+= packed
[i
+ 1];
63 // Generate a relocation for this offset and addend pair.
65 relocation
.r_offset
= offset
;
66 relocation
.r_info
= ELF_R_INFO(0, ELF::kRelativeRelocationCode
);
67 relocation
.r_addend
= addend
;
68 relocations
->push_back(relocation
);
72 } // namespace relocation_packer