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 #include "elf.h"
      9 #include "elf_traits.h"
     10 #include "gtest/gtest.h"
     11 
     12 
     13 template <typename ELF>
     14 static void AddRelocation(typename ELF::Addr addr,
     15                    typename ELF::Xword info,
     16                    typename ELF::Sxword addend,
     17                    std::vector<typename ELF::Rela>* relocations) {
     18   typename ELF::Rela relocation;
     19   relocation.r_offset = addr;
     20   relocation.r_info = info;
     21   relocation.r_addend = addend;
     22 
     23   relocations->push_back(relocation);
     24 }
     25 
     26 template <typename ELF>
     27 static bool CheckRelocation(typename ELF::Addr addr,
     28                      typename ELF::Xword info,
     29                      typename ELF::Sxword addend,
     30                      const typename ELF::Rela& relocation) {
     31   return relocation.r_offset == addr &&
     32       relocation.r_info == info &&
     33       relocation.r_addend == addend;
     34 }
     35 
     36 namespace relocation_packer {
     37 
     38 template <typename ELF>
     39 static void DoPackNoAddend() {
     40   std::vector<typename ELF::Rela> relocations;
     41   std::vector<uint8_t> packed;
     42   bool is_32 = sizeof(typename ELF::Addr) == 4;
     43   // Initial relocation.
     44   AddRelocation<ELF>(0xd1ce0000, 0x11, 0, &relocations);
     45   // Two more relocations, 4 byte deltas.
     46   AddRelocation<ELF>(0xd1ce0004, 0x11, 0, &relocations);
     47   AddRelocation<ELF>(0xd1ce0008, 0x11, 0, &relocations);
     48   // Three more relocations, 8 byte deltas.
     49   AddRelocation<ELF>(0xd1ce0010, 0x11, 0, &relocations);
     50   AddRelocation<ELF>(0xd1ce0018, 0x11, 0, &relocations);
     51   AddRelocation<ELF>(0xd1ce0020, 0x11, 0, &relocations);
     52 
     53   RelocationPacker<ELF> packer;
     54 
     55   packed.clear();
     56   packer.PackRelocations(relocations, &packed);
     57 
     58   ASSERT_EQ(18U, packed.size());
     59   // Identifier.
     60   size_t ndx = 0;
     61   EXPECT_EQ('A', packed[ndx++]);
     62   EXPECT_EQ('P', packed[ndx++]);
     63   EXPECT_EQ('S', packed[ndx++]);
     64   EXPECT_EQ('2', packed[ndx++]);
     65   // relocation count
     66   EXPECT_EQ(6, packed[ndx++]);
     67   // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 7d/0d (32/64bit)
     68   EXPECT_EQ(0xfc, packed[ndx++]);
     69   EXPECT_EQ(0xff, packed[ndx++]);
     70   EXPECT_EQ(0xb7, packed[ndx++]);
     71   EXPECT_EQ(0x8e, packed[ndx++]);
     72   EXPECT_EQ(is_32 ? 0x7d : 0x0d, packed[ndx++]);
     73   // first group
     74   EXPECT_EQ(3, packed[ndx++]);  // size
     75   EXPECT_EQ(3, packed[ndx++]); // flags
     76   EXPECT_EQ(4, packed[ndx++]); // r_offset_delta
     77   EXPECT_EQ(0x11, packed[ndx++]); // r_info
     78   // second group
     79   EXPECT_EQ(3, packed[ndx++]);  // size
     80   EXPECT_EQ(3, packed[ndx++]); // flags
     81   EXPECT_EQ(8, packed[ndx++]); // r_offset_delta
     82   EXPECT_EQ(0x11, packed[ndx++]); // r_info
     83 
     84   EXPECT_EQ(ndx, packed.size());
     85 }
     86 
     87 TEST(Packer, PackNoAddend32) {
     88   DoPackNoAddend<ELF32_traits>();
     89 }
     90 
     91 TEST(Packer, PackNoAddend64) {
     92   DoPackNoAddend<ELF64_traits>();
     93 }
     94 
     95 template <typename ELF>
     96 static void DoUnpackNoAddend() {
     97   std::vector<typename ELF::Rela> relocations;
     98   std::vector<uint8_t> packed;
     99   bool is_32 = sizeof(typename ELF::Addr) == 4;
    100   packed.push_back('A');
    101   packed.push_back('P');
    102   packed.push_back('S');
    103   packed.push_back('2');
    104   // relocation count
    105   packed.push_back(6);
    106   // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 7d/0d (32/64bit)
    107   packed.push_back(0xfc);
    108   packed.push_back(0xff);
    109   packed.push_back(0xb7);
    110   packed.push_back(0x8e);
    111   packed.push_back(is_32 ? 0x7d : 0x0d);
    112   // first group
    113   packed.push_back(3);  // size
    114   packed.push_back(3); // flags
    115   packed.push_back(4); // r_offset_delta
    116   packed.push_back(0x11); // r_info
    117   // second group
    118   packed.push_back(3);  // size
    119   packed.push_back(3); // flags
    120   packed.push_back(8); // r_offset_delta
    121   packed.push_back(0x11); // r_info
    122 
    123   RelocationPacker<ELF> packer;
    124   packer.UnpackRelocations(packed, &relocations);
    125 
    126   size_t ndx = 0;
    127   EXPECT_EQ(6U, relocations.size());
    128   EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0000, 0x11, 0, relocations[ndx++]));
    129   EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0004, 0x11, 0, relocations[ndx++]));
    130   EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0008, 0x11, 0, relocations[ndx++]));
    131 
    132   EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0010, 0x11, 0, relocations[ndx++]));
    133   EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0018, 0x11, 0, relocations[ndx++]));
    134   EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0020, 0x11, 0, relocations[ndx++]));
    135 
    136   EXPECT_EQ(ndx, relocations.size());
    137 }
    138 
    139 TEST(Packer, UnpackNoAddend32) {
    140   DoUnpackNoAddend<ELF32_traits>();
    141 }
    142 
    143 TEST(Packer, UnpackNoAddend64) {
    144   DoUnpackNoAddend<ELF64_traits>();
    145 }
    146 
    147 template <typename ELF>
    148 static void DoPackWithAddend() {
    149   std::vector<typename ELF::Rela> relocations;
    150 
    151   // Initial relocation.
    152   AddRelocation<ELF>(0xd1ce0000, 0x01, 10024, &relocations);
    153   // Two more relocations, 4 byte offset deltas, 12 byte addend deltas.
    154   AddRelocation<ELF>(0xd1ce0004, 0x01, 10012, &relocations);
    155   AddRelocation<ELF>(0xd1ce0008, 0x01, 10024, &relocations);
    156   // Three more relocations, 8 byte deltas, -24 byte addend deltas.
    157   AddRelocation<ELF>(0xd1ce0010, 0x01, 10000, &relocations);
    158   AddRelocation<ELF>(0xd1ce0018, 0x01, 9976, &relocations);
    159   AddRelocation<ELF>(0xd1ce0020, 0x01, 9952, &relocations);
    160 
    161   std::vector<uint8_t> packed;
    162 
    163   RelocationPacker<ELF> packer;
    164 
    165   packed.clear();
    166   packer.PackRelocations(relocations, &packed);
    167 
    168   EXPECT_EQ(26U, packed.size());
    169   size_t ndx = 0;
    170   // Identifier.
    171   EXPECT_EQ('A', packed[ndx++]);
    172   EXPECT_EQ('P', packed[ndx++]);
    173   EXPECT_EQ('S', packed[ndx++]);
    174   EXPECT_EQ('2', packed[ndx++]);
    175   // Relocation count
    176   EXPECT_EQ(6U, packed[ndx++]);
    177   // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d/7d (depending on ELF::Addr)
    178   EXPECT_EQ(0xfc, packed[ndx++]);
    179   EXPECT_EQ(0xff, packed[ndx++]);
    180   EXPECT_EQ(0xb7, packed[ndx++]);
    181   EXPECT_EQ(0x8e, packed[ndx++]);
    182   if (sizeof(typename ELF::Addr) == 8) {
    183     // positive for uint64_t
    184     EXPECT_EQ(0x0d, packed[ndx++]);
    185   } else {
    186     // negative for uint32_t
    187     EXPECT_EQ(0x7d, packed[ndx++]);
    188   }
    189   // group 1
    190   EXPECT_EQ(0x03, packed[ndx++]); // size
    191   EXPECT_EQ(0x0b, packed[ndx++]); // flags
    192   EXPECT_EQ(0x04, packed[ndx++]); // r_offset_delta
    193   EXPECT_EQ(0x01, packed[ndx++]); // r_info
    194   // group 1 - addend 1: 10024 = 0xa8, 0xce, 0x80
    195   EXPECT_EQ(0xa8, packed[ndx++]);
    196   EXPECT_EQ(0xce, packed[ndx++]);
    197   EXPECT_EQ(0x00, packed[ndx++]);
    198   // group 1 - addend 2: -12 = 0x74
    199   EXPECT_EQ(0x74, packed[ndx++]);
    200   // group 1 - addend 3: +12 = 0x0c
    201   EXPECT_EQ(0x0c, packed[ndx++]);
    202 
    203   // group 2
    204   EXPECT_EQ(0x03, packed[ndx++]); // size
    205   EXPECT_EQ(0x0b, packed[ndx++]); // flags
    206   EXPECT_EQ(0x08, packed[ndx++]); // r_offset_delta
    207   EXPECT_EQ(0x01, packed[ndx++]); // r_info
    208 
    209   // group 2 - addend 1: -24 = 0x68
    210   EXPECT_EQ(0x68, packed[ndx++]);
    211   // group 2 - addend 2: -24 = 0x68
    212   EXPECT_EQ(0x68, packed[ndx++]);
    213   // group 2 - addend 3: -24 = 0x68
    214   EXPECT_EQ(0x68, packed[ndx++]);
    215 
    216   EXPECT_EQ(ndx, packed.size());
    217 }
    218 
    219 TEST(Packer, PackWithAddend) {
    220   DoPackWithAddend<ELF32_traits>();
    221   DoPackWithAddend<ELF64_traits>();
    222 }
    223 
    224 template <typename ELF>
    225 static void DoUnpackWithAddend() {
    226   std::vector<uint8_t> packed;
    227   // Identifier.
    228   packed.push_back('A');
    229   packed.push_back('P');
    230   packed.push_back('S');
    231   packed.push_back('2');
    232   // Relocation count
    233   packed.push_back(6U);
    234   // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d
    235   packed.push_back(0xfc);
    236   packed.push_back(0xff);
    237   packed.push_back(0xb7);
    238   packed.push_back(0x8e);
    239   if (sizeof(typename ELF::Addr) == 8) {
    240     // positive for uint64_t
    241     packed.push_back(0x0d);
    242   } else {
    243     // negative for uint32_t
    244     packed.push_back(0x7d);
    245   }
    246   // group 1
    247   packed.push_back(0x03); // size
    248   packed.push_back(0x0b); // flags
    249   packed.push_back(0x04); // r_offset_delta
    250   packed.push_back(0x01); // r_info
    251   // group 1 - addend 1: 10024 = 0xa8, 0xce, 0x80
    252   packed.push_back(0xa8);
    253   packed.push_back(0xce);
    254   packed.push_back(0x00);
    255   // group 1 - addend 2: -12 = 0x74
    256   packed.push_back(0x74);
    257   // group 1 - addend 3: +12 = 0x0c
    258   packed.push_back(0x0c);
    259 
    260   // group 2
    261   packed.push_back(0x03); // size
    262   packed.push_back(0x0b); // flags
    263   packed.push_back(0x08); // r_offset_delta
    264   packed.push_back(0x01); // r_info
    265 
    266   // group 2 - addend 1: -24 = 0x68
    267   packed.push_back(0x68);
    268   // group 2 - addend 2: -24 = 0x68
    269   packed.push_back(0x68);
    270   // group 2 - addend 3: -24 = 0x68
    271   packed.push_back(0x68);
    272 
    273   std::vector<typename ELF::Rela> relocations;
    274 
    275   RelocationPacker<ELF> packer;
    276 
    277   relocations.clear();
    278   packer.UnpackRelocations(packed, &relocations);
    279 
    280   EXPECT_EQ(6U, relocations.size());
    281   size_t ndx = 0;
    282   // Initial relocation.
    283   EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0000, 0x01, 10024, relocations[ndx++]));
    284   // Two more relocations, 4 byte offset deltas, 12 byte addend deltas.
    285   EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0004, 0x01, 10012, relocations[ndx++]));
    286   EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0008, 0x01, 10024, relocations[ndx++]));
    287   // Three more relocations, 8 byte offset deltas, -24 byte addend deltas.
    288   EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0010, 0x01, 10000, relocations[ndx++]));
    289   EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0018, 0x01, 9976, relocations[ndx++]));
    290   EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0020, 0x01, 9952, relocations[ndx++]));
    291 
    292   EXPECT_EQ(ndx, relocations.size());
    293 }
    294 
    295 TEST(Packer, UnpackWithAddend) {
    296   DoUnpackWithAddend<ELF32_traits>();
    297   DoUnpackWithAddend<ELF64_traits>();
    298 }
    299 
    300 }  // namespace relocation_packer
    301