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 // TODO(simonb): Extend for 64-bit target libraries.
      6 
      7 #include "packer.h"
      8 
      9 #include <string.h>
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "debug.h"
     14 #include "leb128.h"
     15 #include "run_length_encoder.h"
     16 
     17 namespace relocation_packer {
     18 
     19 // Pack R_ARM_RELATIVE relocations into a run-length encoded packed
     20 // representation.
     21 void RelocationPacker::PackRelativeRelocations(
     22     const std::vector<Elf32_Rel>& relocations,
     23     std::vector<uint8_t>* packed) {
     24 
     25   // Run-length encode.
     26   std::vector<Elf32_Word> packed_words;
     27   RelocationRunLengthCodec codec;
     28   codec.Encode(relocations, &packed_words);
     29 
     30   // If insufficient data to run-length encode, do nothing.
     31   if (packed_words.empty())
     32     return;
     33 
     34   // LEB128 encode, with "APR1" prefix.
     35   Leb128Encoder encoder;
     36   encoder.Enqueue('A');
     37   encoder.Enqueue('P');
     38   encoder.Enqueue('R');
     39   encoder.Enqueue('1');
     40   encoder.EnqueueAll(packed_words);
     41 
     42   encoder.GetEncoding(packed);
     43 
     44   // Pad packed to a whole number of words.  This padding will decode as
     45   // LEB128 zeroes.  Run-length decoding ignores it because encoding
     46   // embeds the pairs count in the stream itself.
     47   while (packed->size() % sizeof(uint32_t))
     48     packed->push_back(0);
     49 }
     50 
     51 // Unpack R_ARM_RELATIVE relocations from a run-length encoded packed
     52 // representation.
     53 void RelocationPacker::UnpackRelativeRelocations(
     54     const std::vector<uint8_t>& packed,
     55     std::vector<Elf32_Rel>* relocations) {
     56 
     57   // LEB128 decode, after checking and stripping "APR1" prefix.
     58   std::vector<Elf32_Word> packed_words;
     59   Leb128Decoder decoder(packed);
     60   CHECK(decoder.Dequeue() == 'A' && decoder.Dequeue() == 'P' &&
     61         decoder.Dequeue() == 'R' && decoder.Dequeue() == '1');
     62   decoder.DequeueAll(&packed_words);
     63 
     64   // Run-length decode.
     65   RelocationRunLengthCodec codec;
     66   codec.Decode(packed_words, relocations);
     67 }
     68 
     69 }  // namespace relocation_packer
     70