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.
10 #include "delta_encoder.h"
11 #include "elf_traits.h"
13 #include "run_length_encoder.h"
16 namespace relocation_packer
{
18 // Pack relative relocations into a run-length encoded packed
20 void RelocationPacker::PackRelativeRelocations(
21 const std::vector
<ELF::Rel
>& relocations
,
22 std::vector
<uint8_t>* packed
) {
24 std::vector
<ELF::Xword
> packed_words
;
25 RelocationRunLengthCodec codec
;
26 codec
.Encode(relocations
, &packed_words
);
28 // If insufficient data to run-length encode, do nothing.
29 if (packed_words
.empty())
32 // LEB128 encode, with "APR1" prefix.
33 Leb128Encoder encoder
;
38 encoder
.EnqueueAll(packed_words
);
40 encoder
.GetEncoding(packed
);
42 // Pad packed to a whole number of words. This padding will decode as
43 // LEB128 zeroes. Run-length decoding ignores it because encoding
44 // embeds the pairs count in the stream itself.
45 while (packed
->size() % sizeof(ELF::Word
))
49 // Unpack relative relocations from a run-length encoded packed
51 void RelocationPacker::UnpackRelativeRelocations(
52 const std::vector
<uint8_t>& packed
,
53 std::vector
<ELF::Rel
>* relocations
) {
54 // LEB128 decode, after checking and stripping "APR1" prefix.
55 std::vector
<ELF::Xword
> packed_words
;
56 Leb128Decoder
decoder(packed
);
57 CHECK(decoder
.Dequeue() == 'A' &&
58 decoder
.Dequeue() == 'P' &&
59 decoder
.Dequeue() == 'R' &&
60 decoder
.Dequeue() == '1');
61 decoder
.DequeueAll(&packed_words
);
64 RelocationRunLengthCodec codec
;
65 codec
.Decode(packed_words
, relocations
);
68 // Pack relative relocations with addends into a delta encoded packed
70 void RelocationPacker::PackRelativeRelocations(
71 const std::vector
<ELF::Rela
>& relocations
,
72 std::vector
<uint8_t>* packed
) {
74 std::vector
<ELF::Sxword
> packed_words
;
75 RelocationDeltaCodec codec
;
76 codec
.Encode(relocations
, &packed_words
);
78 // If insufficient data to delta encode, do nothing.
79 if (packed_words
.empty())
82 // Signed LEB128 encode, with "APA1" prefix. ASCII does not encode as
83 // itself under signed LEB128, so we have to treat it specially.
84 Sleb128Encoder encoder
;
85 encoder
.EnqueueAll(packed_words
);
86 std::vector
<uint8_t> encoded
;
87 encoder
.GetEncoding(&encoded
);
89 packed
->push_back('A');
90 packed
->push_back('P');
91 packed
->push_back('A');
92 packed
->push_back('1');
93 packed
->insert(packed
->end(), encoded
.begin(), encoded
.end());
95 // Pad packed to a whole number of words. This padding will decode as
96 // signed LEB128 zeroes. Delta decoding ignores it because encoding
97 // embeds the pairs count in the stream itself.
98 while (packed
->size() % sizeof(ELF::Word
))
102 // Unpack relative relocations with addends from a delta encoded
103 // packed representation.
104 void RelocationPacker::UnpackRelativeRelocations(
105 const std::vector
<uint8_t>& packed
,
106 std::vector
<ELF::Rela
>* relocations
) {
107 // Check "APA1" prefix.
108 CHECK(packed
.at(0) == 'A' &&
109 packed
.at(1) == 'P' &&
110 packed
.at(2) == 'A' &&
111 packed
.at(3) == '1');
113 // Signed LEB128 decode, after stripping "APA1" prefix.
114 std::vector
<ELF::Sxword
> packed_words
;
115 std::vector
<uint8_t> stripped(packed
.begin() + 4, packed
.end());
116 Sleb128Decoder
decoder(stripped
);
117 decoder
.DequeueAll(&packed_words
);
120 RelocationDeltaCodec codec
;
121 codec
.Decode(packed_words
, relocations
);
124 } // namespace relocation_packer