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 "delta_encoder.h"
      6 
      7 #include <vector>
      8 #include "elf.h"
      9 #include "gtest/gtest.h"
     10 
     11 namespace {
     12 
     13 template <typename T>
     14 void AddRelocation(uint32_t addr,
     15                    uint32_t info,
     16                    int32_t addend,
     17                    std::vector<T>* relocations) {
     18   T relocation;
     19   relocation.r_offset = addr;
     20   relocation.r_info = info;
     21   relocation.r_addend = addend;
     22   relocations->push_back(relocation);
     23 }
     24 
     25 template <typename T>
     26 bool CheckRelocation(uint32_t addr,
     27                      uint32_t info,
     28                      int32_t addend,
     29                      const T& relocation) {
     30   return relocation.r_offset == addr &&
     31       relocation.r_info == info &&
     32       relocation.r_addend == addend;
     33 }
     34 
     35 }  // namespace
     36 
     37 namespace relocation_packer {
     38 
     39 template <typename ELF>
     40 static void encode() {
     41   std::vector<typename ELF::Rela> relocations;
     42   std::vector<typename ELF::Addr> packed;
     43 
     44   RelocationDeltaCodec<ELF> codec;
     45 
     46   codec.Encode(relocations, &packed);
     47 
     48   ASSERT_EQ(0U, packed.size());
     49 
     50   // Initial relocation.
     51   AddRelocation(0xf00d0000, 11U, 10000, &relocations);
     52 
     53   codec.Encode(relocations, &packed);
     54 
     55   // size of reloc table, size of group, flags, 3 fields, zero
     56   EXPECT_EQ(7U, packed.size());
     57   // One pair present.
     58   size_t ndx = 0;
     59   EXPECT_EQ(1U, packed[ndx++]);
     60   EXPECT_EQ(0xf00d0000, packed[ndx++]);
     61   EXPECT_EQ(1U, packed[ndx++]); // group_size
     62   EXPECT_EQ(8U, packed[ndx++]); // flags
     63   // Delta from the neutral element is zero
     64   EXPECT_EQ(0U, packed[ndx++]); // offset_delta
     65   EXPECT_EQ(11U, packed[ndx++]); // info
     66   EXPECT_EQ(10000U, packed[ndx++]); // addend_delta
     67 
     68   // Add a second relocation, 4 byte offset delta, 12 byte addend delta.
     69   // same info
     70   AddRelocation(0xf00d0004, 11U, 10012, &relocations);
     71 
     72   packed.clear();
     73   codec.Encode(relocations, &packed);
     74 
     75   ndx = 0;
     76   EXPECT_EQ(8U, packed.size());
     77 
     78   EXPECT_EQ(2U, packed[ndx++]); // relocs count
     79   EXPECT_EQ(0xf00cfffc, packed[ndx++]); // initial offset
     80   EXPECT_EQ(2U, packed[ndx++]); // group count
     81   EXPECT_EQ(11U, packed[ndx++]); // flags
     82   EXPECT_EQ(4U, packed[ndx++]); // group offset delta
     83   EXPECT_EQ(11U, packed[ndx++]); // info
     84 
     85   EXPECT_EQ(10000U, packed[ndx++]); // addend delta
     86   EXPECT_EQ(12U, packed[ndx++]); // addend delta
     87 
     88   // Add a third relocation, 4 byte offset delta, 12 byte addend delta.
     89   // different info
     90   AddRelocation(0xf00d0008, 41U, 10024, &relocations);
     91 
     92   // Add three more relocations, 8 byte offset deltas, -24 byte addend deltas.
     93   AddRelocation(0xf00d0010, 42U, 10000, &relocations);
     94   AddRelocation(0xf00d0018, 42U, 9976, &relocations);
     95   AddRelocation(0xf00d0020, 42U, 9952, &relocations);
     96 
     97   AddRelocation(0xf00d2028, 1042U, 0, &relocations);
     98   AddRelocation(0xf00d2030, 3442U, 0, &relocations);
     99 
    100   packed.clear();
    101   codec.Encode(relocations, &packed);
    102 
    103   ndx = 0;
    104   EXPECT_EQ(26U, packed.size());
    105   // Total number of relocs
    106   EXPECT_EQ(8U, packed[ndx++]);
    107   EXPECT_EQ(0xf00cfffc, packed[ndx++]);
    108   // 2 in first group
    109   EXPECT_EQ(2U, packed[ndx++]);
    110   EXPECT_EQ(11U, packed[ndx++]); //flags
    111   EXPECT_EQ(4U, packed[ndx++]); // group offset delta
    112   EXPECT_EQ(11U, packed[ndx++]); // info
    113 
    114   // Initial relocation.
    115   EXPECT_EQ(10000U, packed[ndx++]); // addend delta
    116   // Two relocations, 4 byte offset deltas, 12 byte addend deltas.
    117   EXPECT_EQ(12U, packed[ndx++]); // addend delta
    118 
    119   // second group has only one reloc
    120   EXPECT_EQ(1U, packed[ndx++]); // count
    121   EXPECT_EQ(8U, packed[ndx++]); // flags
    122 
    123   EXPECT_EQ(4U, packed[ndx++]); // offset delta
    124   EXPECT_EQ(41U, packed[ndx++]); // info
    125   EXPECT_EQ(12U, packed[ndx++]); // addend delta
    126 
    127   // next - 3 relocs grouped by info
    128   EXPECT_EQ(3U, packed[ndx++]); // count
    129   EXPECT_EQ(11U, packed[ndx++]); // flags
    130   EXPECT_EQ(8U, packed[ndx++]); // group offset delta
    131   EXPECT_EQ(42U, packed[ndx++]); // info
    132   // Three relocations, 8 byte offset deltas, -24 byte addend deltas.
    133   EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]);
    134   EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]);
    135   EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]);
    136 
    137   // and last - 2 relocations without addend
    138   EXPECT_EQ(2U, packed[ndx++]);
    139   EXPECT_EQ(0U, packed[ndx++]); // flags
    140   // offset_deltas and r_infos for next 2 relocations
    141   EXPECT_EQ(0x2008U, packed[ndx++]); // offset delta
    142   EXPECT_EQ(1042U, packed[ndx++]); // r_info
    143   EXPECT_EQ(0x8U, packed[ndx++]); // offset delta
    144   EXPECT_EQ(3442U, packed[ndx++]); // r_info
    145 
    146   EXPECT_EQ(packed.size(), ndx);
    147 }
    148 
    149 TEST(Delta, Encode32) {
    150   encode<ELF32_traits>();
    151 }
    152 
    153 TEST(Delta, Encode64) {
    154   encode<ELF64_traits>();
    155 }
    156 
    157 template <typename ELF>
    158 static void decode() {
    159   std::vector<typename ELF::Addr> packed;
    160   std::vector<typename ELF::Rela> relocations;
    161 
    162   RelocationDeltaCodec<ELF> codec;
    163   codec.Decode(packed, &relocations);
    164 
    165   EXPECT_EQ(0U, relocations.size());
    166 
    167   // Six pairs.
    168   packed.push_back(6U); // count
    169   packed.push_back(0xc0ddfffc); // base offset
    170   packed.push_back(3U); // group count
    171   packed.push_back(11U); // flags
    172   packed.push_back(4U); // offset delta
    173   packed.push_back(11U); // info
    174   // Initial relocation.
    175   packed.push_back(10000U);
    176   // Two relocations, 4 byte offset deltas, 12 byte addend deltas.
    177   packed.push_back(12U); // addend
    178   packed.push_back(12U); // addend
    179 
    180   // Three relocations, 8 byte offset deltas, -24 byte addend deltas.
    181   packed.push_back(1U); // group count
    182   packed.push_back(9U); // flags
    183   packed.push_back(11U); // info
    184 
    185   packed.push_back(8U);
    186   packed.push_back(static_cast<typename ELF::Addr>(-24));
    187   // next group with 2 relocs
    188   packed.push_back(2U); // group count
    189   packed.push_back(11U); // flags
    190   packed.push_back(8U); // offset
    191   packed.push_back(42U); // info
    192 
    193   packed.push_back(static_cast<typename ELF::Addr>(-24)); // addend
    194   packed.push_back(static_cast<typename ELF::Addr>(-24)); // addend
    195 
    196   relocations.clear();
    197   codec.Decode(packed, &relocations);
    198 
    199   EXPECT_EQ(6U, relocations.size());
    200   // Initial relocation.
    201   EXPECT_TRUE(CheckRelocation(0xc0de0000, 11U, 10000, relocations[0]));
    202   // Two relocations, 4 byte offset deltas, 12 byte addend deltas.
    203   EXPECT_TRUE(CheckRelocation(0xc0de0004, 11U, 10012, relocations[1]));
    204   EXPECT_TRUE(CheckRelocation(0xc0de0008, 11U, 10024, relocations[2]));
    205   // Three relocations, 8 byte offset deltas, -24 byte addend deltas.
    206   EXPECT_TRUE(CheckRelocation(0xc0de0010, 11U, 10000, relocations[3]));
    207   EXPECT_TRUE(CheckRelocation(0xc0de0018, 42U, 9976, relocations[4]));
    208   EXPECT_TRUE(CheckRelocation(0xc0de0020, 42U, 9952, relocations[5]));
    209 }
    210 
    211 TEST(Delta, Decode32) {
    212   decode<ELF32_traits>();
    213 }
    214 
    215 TEST(Delta, Decode64) {
    216   decode<ELF64_traits>();
    217 }
    218 
    219 // TODO (dimitry): add more tests (fix by 19 January 2038 03:14:07 UTC)
    220 // TODO (dimtiry): 1. Incorrect packed array for decode
    221 // TODO (dimtiry): 2. Try to catch situation where it is likely to get series of groups with size 1
    222 
    223 }  // namespace relocation_packer
    224