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 9 #include "debug.h" 10 #include "delta_encoder.h" 11 #include "elf_traits.h" 12 #include "leb128.h" 13 #include "run_length_encoder.h" 14 #include "sleb128.h" 15 16 namespace relocation_packer { 17 18 // Pack relative relocations into a run-length encoded packed 19 // representation. 20 void RelocationPacker::PackRelativeRelocations( 21 const std::vector<ELF::Rel>& relocations, 22 std::vector<uint8_t>* packed) { 23 // Run-length encode. 24 std::vector<ELF::Xword> packed_words; 25 RelocationRunLengthCodec codec; 26 codec.Encode(relocations, &packed_words); 27 28 // If insufficient data to run-length encode, do nothing. 29 if (packed_words.empty()) 30 return; 31 32 // LEB128 encode, with "APR1" prefix. 33 Leb128Encoder encoder; 34 encoder.Enqueue('A'); 35 encoder.Enqueue('P'); 36 encoder.Enqueue('R'); 37 encoder.Enqueue('1'); 38 encoder.EnqueueAll(packed_words); 39 40 encoder.GetEncoding(packed); 41 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)) 46 packed->push_back(0); 47 } 48 49 // Unpack relative relocations from a run-length encoded packed 50 // representation. 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); 62 63 // Run-length decode. 64 RelocationRunLengthCodec codec; 65 codec.Decode(packed_words, relocations); 66 } 67 68 // Pack relative relocations with addends into a delta encoded packed 69 // representation. 70 void RelocationPacker::PackRelativeRelocations( 71 const std::vector<ELF::Rela>& relocations, 72 std::vector<uint8_t>* packed) { 73 // Delta encode. 74 std::vector<ELF::Sxword> packed_words; 75 RelocationDeltaCodec codec; 76 codec.Encode(relocations, &packed_words); 77 78 // If insufficient data to delta encode, do nothing. 79 if (packed_words.empty()) 80 return; 81 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); 88 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()); 94 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)) 99 packed->push_back(0); 100 } 101 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'); 112 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); 118 119 // Delta decode. 120 RelocationDeltaCodec codec; 121 codec.Decode(packed_words, relocations); 122 } 123 124 } // namespace relocation_packer 125