Home | History | Annotate | Download | only in src
      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