Index: tools/relocation_packer/src/elf_file.h |
diff --git a/tools/relocation_packer/src/elf_file.h b/tools/relocation_packer/src/elf_file.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..51239c01691c8420f24efedf7ba4d8870e51b8c8 |
--- /dev/null |
+++ b/tools/relocation_packer/src/elf_file.h |
@@ -0,0 +1,136 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// ELF shared object file updates handler. |
+// |
+// Provides functions to remove relative relocations from the .rel.dyn |
+// or .rela.dyn sections and pack into .android.rel.dyn or .android.rela.dyn, |
+// and unpack to return the file to its pre-packed state. |
+// |
+// Files to be packed or unpacked must include an existing .android.rel.dyn |
+// or android.rela.dyn section. A standard libchrome.<version>.so will not |
+// contain this section, so the following can be used to add one: |
+// |
+// echo -n 'NULL' >/tmp/small |
+// if file libchrome.<version>.so | grep -q 'ELF 32'; then |
+// arm-linux-androideabi-objcopy |
+// --add-section .android.rel.dyn=/tmp/small |
+// libchrome.<version>.so libchrome.<version>.so.packed |
+// else |
+// aarch64-linux-android-objcopy |
+// --add-section .android.rela.dyn=/tmp/small |
+// libchrome.<version>.so libchrome.<version>.so.packed |
+// fi |
+// rm /tmp/small |
+// |
+// To use, open the file and pass the file descriptor to the constructor, |
+// then pack or unpack as desired. Packing or unpacking will flush the file |
+// descriptor on success. Example: |
+// |
+// int fd = open(..., O_RDWR); |
+// ElfFile elf_file(fd); |
+// bool status; |
+// if (is_packing) |
+// status = elf_file.PackRelocations(); |
+// else |
+// status = elf_file.UnpackRelocations(); |
+// close(fd); |
+// |
+// SetPadding() causes PackRelocations() to pad .rel.dyn or .rela.dyn with |
+// NONE-type entries rather than cutting a hole out of the shared object |
+// file. This keeps all load addresses and offsets constant, and enables |
+// easier debugging and testing. |
+// |
+// A packed shared object file has all of its relative relocations |
+// removed from .rel.dyn or .rela.dyn, and replaced as packed data in |
+// .android.rel.dyn or .android.rela.dyn respectively. The resulting file |
+// is shorter than its non-packed original. |
+// |
+// Unpacking a packed file restores the file to its non-packed state, by |
+// expanding the packed data in .android.rel.dyn or .android.rela.dyn, |
+// combining the relative relocations with the data already in .rel.dyn |
+// or .rela.dyn, and then writing back the now expanded section. |
+ |
+#ifndef TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_ |
+#define TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_ |
+ |
+#include <string.h> |
+#include <vector> |
+ |
+#include "elf.h" |
+#include "libelf.h" |
+#include "packer.h" |
+ |
+namespace relocation_packer { |
+ |
+// An ElfFile reads shared objects, and shuttles relative relocations |
+// between .rel.dyn or .rela.dyn and .android.rel.dyn or .android.rela.dyn |
+// sections. |
+class ElfFile { |
+ public: |
+ explicit ElfFile(int fd) |
+ : fd_(fd), is_padding_relocations_(false), elf_(NULL), |
+ relocations_section_(NULL), dynamic_section_(NULL), |
+ android_relocations_section_(NULL), relocations_type_(NONE) {} |
+ ~ElfFile() {} |
+ |
+ // Set padding mode. When padding, PackRelocations() will not shrink |
+ // the .rel.dyn or .rela.dyn section, but instead replace relative with |
+ // NONE-type entries. |
+ // |flag| is true to pad .rel.dyn or .rela.dyn, false to shrink it. |
+ inline void SetPadding(bool flag) { is_padding_relocations_ = flag; } |
+ |
+ // Transfer relative relocations from .rel.dyn or .rela.dyn to a packed |
+ // representation in .android.rel.dyn or .android.rela.dyn. Returns true |
+ // on success. |
+ bool PackRelocations(); |
+ |
+ // Transfer relative relocations from a packed representation in |
+ // .android.rel.dyn or .android.rela.dyn to .rel.dyn or .rela.dyn. Returns |
+ // true on success. |
+ bool UnpackRelocations(); |
+ |
+ private: |
+ // Load a new ElfFile from a filedescriptor. If flushing, the file must |
+ // be open for read/write. Returns true on successful ELF file load. |
+ // |fd| is an open file descriptor for the shared object. |
+ bool Load(); |
+ |
+ // Templated packer, helper for PackRelocations(). Rel type is one of |
+ // ELF::Rel or ELF::Rela. |
+ template <typename Rel> |
+ bool PackTypedRelocations(const std::vector<Rel>& relocations, |
+ Elf_Data* data); |
+ |
+ // Templated unpacker, helper for UnpackRelocations(). Rel type is one of |
+ // ELF::Rel or ELF::Rela. |
+ template <typename Rel> |
+ bool UnpackTypedRelocations(const std::vector<uint8_t>& packed, |
+ Elf_Data* data); |
+ |
+ // Write ELF file changes. |
+ void Flush(); |
+ |
+ // File descriptor opened on the shared object. |
+ int fd_; |
+ |
+ // If set, pad rather than shrink .rel.dyn or .rela.dyn. Primarily for |
+ // debugging, allows packing to be checked without affecting load addresses. |
+ bool is_padding_relocations_; |
+ |
+ // Libelf handle, assigned by Load(). |
+ Elf* elf_; |
+ |
+ // Sections that we manipulate, assigned by Load(). |
+ Elf_Scn* relocations_section_; |
+ Elf_Scn* dynamic_section_; |
+ Elf_Scn* android_relocations_section_; |
+ |
+ // Relocation type found, assigned by Load(). |
+ enum { NONE = 0, REL, RELA } relocations_type_; |
+}; |
+ |
+} // namespace relocation_packer |
+ |
+#endif // TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_ |