1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// ELF shared object file updates handler. 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Provides functions to remove relative relocations from the .rel.dyn 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// or .rela.dyn sections and pack into .android.rel.dyn or .android.rela.dyn, 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// and unpack to return the file to its pre-packed state. 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Files to be packed or unpacked must include an existing .android.rel.dyn 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// or android.rela.dyn section. A standard libchrome.<version>.so will not 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// contain this section, so the following can be used to add one: 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// echo -n 'NULL' >/tmp/small 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// if file libchrome.<version>.so | grep -q 'ELF 32'; then 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// arm-linux-androideabi-objcopy 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// --add-section .android.rel.dyn=/tmp/small 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// libchrome.<version>.so libchrome.<version>.so.packed 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// else 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// aarch64-linux-android-objcopy 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// --add-section .android.rela.dyn=/tmp/small 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// libchrome.<version>.so libchrome.<version>.so.packed 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// fi 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// rm /tmp/small 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// To use, open the file and pass the file descriptor to the constructor, 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// then pack or unpack as desired. Packing or unpacking will flush the file 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// descriptor on success. Example: 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// int fd = open(..., O_RDWR); 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// ElfFile elf_file(fd); 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// bool status; 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// if (is_packing) 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// status = elf_file.PackRelocations(); 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// else 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// status = elf_file.UnpackRelocations(); 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// close(fd); 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// SetPadding() causes PackRelocations() to pad .rel.dyn or .rela.dyn with 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// NONE-type entries rather than cutting a hole out of the shared object 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// file. This keeps all load addresses and offsets constant, and enables 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// easier debugging and testing. 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// A packed shared object file has all of its relative relocations 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// removed from .rel.dyn or .rela.dyn, and replaced as packed data in 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// .android.rel.dyn or .android.rela.dyn respectively. The resulting file 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// is shorter than its non-packed original. 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Unpacking a packed file restores the file to its non-packed state, by 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// expanding the packed data in .android.rel.dyn or .android.rela.dyn, 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// combining the relative relocations with the data already in .rel.dyn 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// or .rela.dyn, and then writing back the now expanded section. 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_ 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_ 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <string.h> 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <vector> 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "elf.h" 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "libelf.h" 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "packer.h" 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace relocation_packer { 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// An ElfFile reads shared objects, and shuttles relative relocations 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// between .rel.dyn or .rela.dyn and .android.rel.dyn or .android.rela.dyn 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// sections. 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ElfFile { 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public: 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) explicit ElfFile(int fd) 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : fd_(fd), is_padding_relocations_(false), elf_(NULL), 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relocations_section_(NULL), dynamic_section_(NULL), 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) android_relocations_section_(NULL), relocations_type_(NONE) {} 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ~ElfFile() {} 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Set padding mode. When padding, PackRelocations() will not shrink 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // the .rel.dyn or .rela.dyn section, but instead replace relative with 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // NONE-type entries. 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |flag| is true to pad .rel.dyn or .rela.dyn, false to shrink it. 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) inline void SetPadding(bool flag) { is_padding_relocations_ = flag; } 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Transfer relative relocations from .rel.dyn or .rela.dyn to a packed 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // representation in .android.rel.dyn or .android.rela.dyn. Returns true 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // on success. 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool PackRelocations(); 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Transfer relative relocations from a packed representation in 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // .android.rel.dyn or .android.rela.dyn to .rel.dyn or .rela.dyn. Returns 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // true on success. 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool UnpackRelocations(); 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private: 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Load a new ElfFile from a filedescriptor. If flushing, the file must 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // be open for read/write. Returns true on successful ELF file load. 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // |fd| is an open file descriptor for the shared object. 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool Load(); 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Templated packer, helper for PackRelocations(). Rel type is one of 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // ELF::Rel or ELF::Rela. 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) template <typename Rel> 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool PackTypedRelocations(const std::vector<Rel>& relocations, 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Elf_Data* data); 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Templated unpacker, helper for UnpackRelocations(). Rel type is one of 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // ELF::Rel or ELF::Rela. 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) template <typename Rel> 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool UnpackTypedRelocations(const std::vector<uint8_t>& packed, 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Elf_Data* data); 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Write ELF file changes. 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void Flush(); 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // File descriptor opened on the shared object. 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int fd_; 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // If set, pad rather than shrink .rel.dyn or .rela.dyn. Primarily for 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // debugging, allows packing to be checked without affecting load addresses. 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool is_padding_relocations_; 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Libelf handle, assigned by Load(). 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Elf* elf_; 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Sections that we manipulate, assigned by Load(). 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Elf_Scn* relocations_section_; 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Elf_Scn* dynamic_section_; 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Elf_Scn* android_relocations_section_; 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Relocation type found, assigned by Load(). 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) enum { NONE = 0, REL, RELA } relocations_type_; 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace relocation_packer 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_ 137