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 94namespace 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. 99template <typename ELF> 100class 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