Chromium Code Reviews| Index: tools/relocation_packer/src/relocation_packer_elf_file.h |
| diff --git a/tools/relocation_packer/src/relocation_packer_elf_file.h b/tools/relocation_packer/src/relocation_packer_elf_file.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..384171f40377eb251e9aa1bcfd02ad798e926333 |
| --- /dev/null |
| +++ b/tools/relocation_packer/src/relocation_packer_elf_file.h |
| @@ -0,0 +1,120 @@ |
| +// 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 R_ARM_RELATIVE relocations from the .rel.dyn |
| +// section and pack them in .android.rel.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 |
| +// 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 |
| +// arm-linux-gnueabi-objcopy |
| +// --add-section .android.rel.dyn=/tmp/small |
| +// libchrome.<version>.so libchrome.<version>.so.packed |
| +// rm /tmp/small |
| +// |
| +// To use, open the file and pass the file descriptor to the Load() function, |
| +// pack or unpack as desired, and then call Flush(). Example: |
| +// |
| +// int fd = open(..., O_RDWR); |
| +// |
| +// ElfFile elf_file; |
| +// if (!elf_file.Load(fd)) |
| +// abort(); |
| +// |
| +// bool status; |
| +// if (is_packing) |
| +// status = elf_file.PackRelocations(); |
| +// else |
| +// status = elf_file.UnpackRelocations(); |
| +// |
| +// if (status) |
| +// elf_file.Flush(); |
| +// |
| +// SetPadding() causes PackRelocations() to pad .rel.dyn with R_ARM_NONE |
| +// 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 R_ARM_RELATIVE relocations |
| +// removed from .rel.dyn, and replaced as packed data in .android.rel.dyn. |
| +// 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, combining the R_ARM_RELATIVE |
| +// relocations with the data already in .rel.dyn, and then writing back the |
| +// now expanded .rel.dyn section. |
| + |
| +#ifndef RELOCATION_PACKER_ELF_FILE_H |
| +#define RELOCATION_PACKER_ELF_FILE_H |
| + |
| +#include <string.h> |
| + |
| +#include "elf.h" |
| +#include "libelf.h" |
| +#include "relocation_packer_packer.h" |
| + |
| +namespace relocation_packer { |
| + |
| +// An ElfFile reads shared objects, and shuttles R_ARM_RELATIVE relocations |
| +// between .rel.dyn and .android.rel.dyn sections. |
| +class ElfFile { |
|
rmcilroy
2014/06/02 15:16:35
How about "class ArmElfFile : public ElfFile" (wit
simonb (inactive)
2014/06/04 16:40:35
There's no current plan to port to other architect
rmcilroy
2014/06/07 11:49:06
Arm64 is a different architecture. I'm fine with
|
| + public: |
| + // Stub identifier written to 'null out' packed data, "NULL". |
| + static const Elf32_Word kStubIdentifier = 0x4c4c554eu; |
| + |
| + // Additional dynamic tags used to indicate the offset and size of the |
| + // .android.rel.dyn section. |
| + static const Elf32_Sword DT_ANDROID_ARM_REL_OFFSET = DT_LOPROC; |
| + static const Elf32_Sword DT_ANDROID_ARM_REL_SIZE = DT_LOPROC + 1; |
|
rmcilroy
2014/06/02 15:16:35
Do these (and kStubIdentifier above) need to be in
simonb (inactive)
2014/06/04 16:40:35
Done.
|
| + |
| + ElfFile() { ::memset(this, 0, sizeof(*this)); } |
| + ~ElfFile() {} |
| + |
| + // Load a new ElfFile from a filedescriptor. If flushing, the file must |
| + // be open for read/write. |
| + // |fd| is an open file descriptor for the shared object. |
| + bool Load(int fd); |
|
rmcilroy
2014/06/02 15:16:35
nit - mention what is returned on success or failu
simonb (inactive)
2014/06/04 16:40:35
Done.
|
| + |
| + // Set padding mode. When padding, PackRelocations() will not shrink |
| + // the .rel.dyn section, but instead replace R_ARM_RELATIVE with |
| + // R_ARM_NONE entries. |
| + // |flag| is true to pad .rel.dyn, false to shrink it. |
| + inline void SetPadding(bool flag) { is_padding_rel_dyn_ = flag; } |
| + |
| + // Transfer R_ARM_RELATIVE relocations from .rel.dyn to a packed |
| + // representation in .android.rel.dyn. |
| + bool PackRelocations(); |
| + |
| + // Transfer R_ARM_RELATIVE relocations from a packed representation in |
| + // .android.rel.dyn to .rel.dyn. |
| + bool UnpackRelocations(); |
| + |
| + // Write ELF file changes. |
| + void Flush(); |
|
rmcilroy
2014/06/02 15:16:35
Is there a reason to have Load and Flush as separa
simonb (inactive)
2014/06/04 16:40:35
Done.
|
| + |
| + private: |
| + // If set, pad rather than shrink .rel.dyn. Primarily for debugging, |
| + // allows packing to be checked without affecting load addresses. |
| + bool is_padding_rel_dyn_; |
| + |
| + // File descriptor opened on the shared object. |
| + int fd_; |
| + |
| + // Libelf handle, assigned by Load(). |
| + Elf* elf_; |
| + |
| + // Sections that we manipulate, assigned by Load(). |
| + Elf_Scn* rel_dyn_section_; |
| + Elf_Scn* dynamic_section_; |
| + Elf_Scn* android_rel_dyn_section_; |
| +}; |
| + |
| +} // namespace relocation_packer |
| + |
| +#endif // RELOCATION_PACKER_ELF_FILE_H |