• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
9 #include "debug.h"
10 #include "elf_traits.h"
11 
12 namespace relocation_packer {
13 
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.
Encode(const std::vector<ELF::Rela> & relocations,std::vector<ELF::Sxword> * packed)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)
21     return;
22 
23   // Start with the element count, then append the delta pairs.
24   packed->push_back(relocations.size());
25 
26   ELF::Addr offset = 0;
27   ELF::Sxword addend = 0;
28 
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);
32 
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;
37   }
38 }
39 
40 // Decode relative relocations with addends from a delta encoded (packed)
41 // representation.
Decode(const std::vector<ELF::Sxword> & packed,std::vector<ELF::Rela> * relocations)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
45   // able to unpack.
46   if (packed.size() < 3)
47     return;
48 
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);
52 
53   ELF::Addr offset = 0;
54   ELF::Sxword addend = 0;
55 
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) {
60     offset += packed[i];
61     addend += packed[i + 1];
62 
63     // Generate a relocation for this offset and addend pair.
64     ELF::Rela relocation;
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);
69   }
70 }
71 
72 }  // namespace relocation_packer
73