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 // Delta encode and decode REL/RELA section of elf file. 6 // 7 // The encoded data format is sequence of elements of ElfAddr type (unsigned long): 8 // 9 // [00] relocation_count - the total count of relocations 10 // [01] initial r_offset - this is initial r_offset for the 11 // relocation table. 12 // followed by group structures: 13 // [02] group 14 // ... 15 // [nn] group 16 17 // the generalized format of the group is (! - always present ? - depends on group_flags): 18 // -------------- 19 // ! group_size 20 // ! group_flags 21 // ? group_r_offset_delta when RELOCATION_GROUPED_BY_OFFSET_DELTA flag is set 22 // ? group_r_info when RELOCATION_GROUPED_BY_INFO flag is set 23 // ? group_r_addend_group_delta when RELOCATION_GROUP_HAS_ADDEND and RELOCATION_GROUPED_BY_ADDEND 24 // flag is set 25 // 26 // The group description is followed by individual relocations. 27 // please note that there is a case when individual relocation 28 // section could be empty - that is if every field ends up grouped. 29 // 30 // The format for individual relocations section is: 31 // ? r_offset_delta - when RELOCATION_GROUPED_BY_OFFSET_DELTA is not set 32 // ? r_info - when RELOCATION_GROUPED_BY_INFO flag is not set 33 // ? r_addend_delta - RELOCATION_GROUP_HAS_ADDEND is set and RELOCATION_GROUPED_BY_ADDEND is not set 34 // 35 // For example lets pack the following relocations: 36 // 37 // Relocation section '.rela.dyn' at offset 0xbf58 contains 939 entries: 38 // Offset Info Type Symbol's Value Symbol's Name + Addend 39 // 00000000000a2178 0000000000000403 R_AARCH64_RELATIVE 177a8 40 // 00000000000a2180 0000000000000403 R_AARCH64_RELATIVE 177cc 41 // 00000000000a2188 0000000000000403 R_AARCH64_RELATIVE 177e0 42 // 00000000000a2190 0000000000000403 R_AARCH64_RELATIVE 177f4 43 // 00000000000a2198 0000000000000403 R_AARCH64_RELATIVE 17804 44 // 00000000000a21a0 0000000000000403 R_AARCH64_RELATIVE 17818 45 // 00000000000a21a8 0000000000000403 R_AARCH64_RELATIVE 1782c 46 // 00000000000a21b0 0000000000000403 R_AARCH64_RELATIVE 17840 47 // 00000000000a21b8 0000000000000403 R_AARCH64_RELATIVE 17854 48 // 00000000000a21c0 0000000000000403 R_AARCH64_RELATIVE 17868 49 // 00000000000a21c8 0000000000000403 R_AARCH64_RELATIVE 1787c 50 // 00000000000a21d0 0000000000000403 R_AARCH64_RELATIVE 17890 51 // 00000000000a21d8 0000000000000403 R_AARCH64_RELATIVE 178a4 52 // 00000000000a21e8 0000000000000403 R_AARCH64_RELATIVE 178b8 53 // 54 // The header is going to be 55 // [00] 14 <- count 56 // [01] 0x00000000000a2170 <- initial relocation (first relocation - delta, 57 // the delta is 8 in this case) 58 // -- starting the first and only group 59 // [03] 14 <- group size 60 // [03] 0xb <- flags RELOCATION_GROUP_HAS_ADDEND | RELOCATION_GROUPED_BY_OFFSET_DELTA 61 // | RELOCATION_GROUPED_BY_INFO 62 // [04] 8 <- offset delta 63 // [05] 0x403 <- r_info 64 // -- end of group definition, starting list of r_addend deltas 65 // [06] 0x177a8 66 // [07] 0x24 = 177cc - 177a8 67 // [08] 0x14 = 177e0 - 177cc 68 // [09] 0x14 = 177f4 - 177e0 69 // [10] 0x10 = 17804 - 177f4 70 // [11] 0x14 = 17818 - 17804 71 // [12] 0x14 = 1782c - 17818 72 // [13] 0x14 = 17840 - 1782c 73 // [14] 0x14 = 17854 - 17840 74 // [15] 0x14 = 17868 - 17854 75 // [16] 0x14 = 1787c - 17868 76 // [17] 0x14 = 17890 - 1787c 77 // [18] 0x14 = 178a4 - 17890 78 // [19] 0x14 = 178b8 - 178a4 79 // -- the end. 80 81 // TODO (dimitry): consider using r_addend_group_delta in the way we use group offset delta, it can 82 // save us more bytes... 83 84 // The input ends when sum(group_size) == relocation_count 85 86 #ifndef TOOLS_RELOCATION_PACKER_SRC_DELTA_ENCODER_H_ 87 #define TOOLS_RELOCATION_PACKER_SRC_DELTA_ENCODER_H_ 88 89 #include <vector> 90 91 #include "elf.h" 92 #include "elf_traits.h" 93 94 namespace relocation_packer { 95 96 // A RelocationDeltaCodec packs vectors of relative relocations with 97 // addends into more compact forms, and unpacks them to reproduce the 98 // pre-packed data. 99 template <typename ELF> 100 class RelocationDeltaCodec { 101 public: 102 typedef typename ELF::Addr ElfAddr; 103 typedef typename ELF::Rela ElfRela; 104 105 // Encode relocations with addends into a more compact form. 106 // |relocations| is a vector of relative relocation with addend structs. 107 // |packed| is the vector of packed words into which relocations are packed. 108 static void Encode(const std::vector<ElfRela>& relocations, 109 std::vector<ElfAddr>* packed); 110 111 // Decode relative relocations with addends from their more compact form. 112 // |packed| is the vector of packed relocations. 113 // |relocations| is a vector of unpacked relative relocations. 114 static void Decode(const std::vector<ElfAddr>& packed, 115 std::vector<ElfRela>* relocations); 116 117 private: 118 static void DetectGroup(const std::vector<ElfRela>& relocations, 119 size_t group_starts_with, ElfAddr previous_offset, 120 ElfAddr* group_size, ElfAddr* group_flags, 121 ElfAddr* group_offset_delta, ElfAddr* group_info, 122 ElfAddr* group_addend); 123 124 static void DetectGroupFields(const ElfRela& reloc_one, const ElfRela& reloc_two, 125 ElfAddr current_offset_delta, ElfAddr* group_flags, 126 ElfAddr* group_offset_delta, ElfAddr* group_info, 127 ElfAddr* group_addend); 128 }; 129 130 } // namespace relocation_packer 131 132 #endif // TOOLS_RELOCATION_PACKER_SRC_DELTA_ENCODER_H_ 133