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)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Implementation notes:
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// We need to remove a piece from the ELF shared library.  However, we also
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// want to ensure that code and data loads at the same addresses as before
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// packing, so that tools like breakpad can still match up addresses found
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// in any crash dumps with data extracted from the pre-packed version of
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// the shared library.
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Arranging this means that we have to split one of the LOAD segments into
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// two.  Unfortunately, the program headers are located at the very start
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// of the shared library file, so expanding the program header section
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// would cause a lot of consequent changes to files offsets that we don't
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// really want to have to handle.
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Luckily, though, there is a segment that is always present and always
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// unused on Android; the GNU_STACK segment.  What we do is to steal that
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// and repurpose it to be one of the split LOAD segments.  We then have to
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// sort LOAD segments by offset to keep the crazy linker happy.
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// All of this takes place in SplitProgramHeadersForHole(), used on packing,
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// and is unraveled on unpacking in CoalesceProgramHeadersForHole().  See
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// commentary on those functions for an example of this segment stealing
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// in action.
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "elf_file.h"
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <stdlib.h>
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <sys/types.h>
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <unistd.h>
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <algorithm>
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <string>
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <vector>
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "debug.h"
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "elf_traits.h"
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "libelf.h"
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "packer.h"
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace relocation_packer {
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Stub identifier written to 'null out' packed data, "NULL".
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const uint32_t kStubIdentifier = 0x4c4c554eu;
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Out-of-band dynamic tags used to indicate the offset and size of the
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// android packed relocations section.
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const ELF::Sword DT_ANDROID_REL_OFFSET = DT_LOOS;
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const ELF::Sword DT_ANDROID_REL_SIZE = DT_LOOS + 1;
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Alignment to preserve, in bytes.  This must be at least as large as the
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// largest d_align and sh_addralign values found in the loaded file.
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Out of caution for RELRO page alignment, we preserve to a complete target
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// page.  See http://www.airs.com/blog/archives/189.
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const size_t kPreserveAlignment = 4096;
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace {
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Get section data.  Checks that the section has exactly one data entry,
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// so that the section size and the data size are the same.  True in
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// practice for all sections we resize when packing or unpacking.  Done
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// by ensuring that a call to elf_getdata(section, data) returns NULL as
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the next data entry.
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Elf_Data* GetSectionData(Elf_Scn* section) {
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Elf_Data* data = elf_getdata(section, NULL);
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(data && elf_getdata(section, data) == NULL);
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return data;
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Rewrite section data.  Allocates new data and makes it the data element's
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// buffer.  Relies on program exit to free allocated data.
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void RewriteSectionData(Elf_Data* data,
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        const void* section_data,
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        size_t size) {
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(size == data->d_size);
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uint8_t* area = new uint8_t[size];
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  memcpy(area, section_data, size);
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data->d_buf = area;
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Verbose ELF header logging.
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void VerboseLogElfHeader(const ELF::Ehdr* elf_header) {
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "e_phoff = " << elf_header->e_phoff;
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "e_shoff = " << elf_header->e_shoff;
87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "e_ehsize = " << elf_header->e_ehsize;
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "e_phentsize = " << elf_header->e_phentsize;
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "e_phnum = " << elf_header->e_phnum;
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "e_shnum = " << elf_header->e_shnum;
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "e_shstrndx = " << elf_header->e_shstrndx;
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Verbose ELF program header logging.
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void VerboseLogProgramHeader(size_t program_header_index,
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             const ELF::Phdr* program_header) {
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string type;
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  switch (program_header->p_type) {
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case PT_NULL: type = "NULL"; break;
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case PT_LOAD: type = "LOAD"; break;
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case PT_DYNAMIC: type = "DYNAMIC"; break;
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case PT_INTERP: type = "INTERP"; break;
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case PT_PHDR: type = "PHDR"; break;
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case PT_GNU_RELRO: type = "GNU_RELRO"; break;
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case PT_GNU_STACK: type = "GNU_STACK"; break;
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case PT_ARM_EXIDX: type = "EXIDX"; break;
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    default: type = "(OTHER)"; break;
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VLOG(1) << "phdr[" << program_header_index << "] : " << type;
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "  p_offset = " << program_header->p_offset;
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "  p_vaddr = " << program_header->p_vaddr;
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "  p_paddr = " << program_header->p_paddr;
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "  p_filesz = " << program_header->p_filesz;
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "  p_memsz = " << program_header->p_memsz;
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VLOG(1) << "  p_flags = " << program_header->p_flags;
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VLOG(1) << "  p_align = " << program_header->p_align;
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Verbose ELF section header logging.
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void VerboseLogSectionHeader(const std::string& section_name,
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             const ELF::Shdr* section_header) {
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "section " << section_name;
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "  sh_addr = " << section_header->sh_addr;
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "  sh_offset = " << section_header->sh_offset;
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "  sh_size = " << section_header->sh_size;
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "  sh_addralign = " << section_header->sh_addralign;
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Verbose ELF section data logging.
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void VerboseLogSectionData(const Elf_Data* data) {
131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "  data";
132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "    d_buf = " << data->d_buf;
133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "    d_off = " << data->d_off;
134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "    d_size = " << data->d_size;
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "    d_align = " << data->d_align;
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Load the complete ELF file into a memory image in libelf, and identify
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the .rel.dyn or .rela.dyn, .dynamic, and .android.rel.dyn or
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// .android.rela.dyn sections.  No-op if the ELF file has already been loaded.
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool ElfFile::Load() {
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (elf_)
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return true;
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Elf* elf = elf_begin(fd_, ELF_C_RDWR, NULL);
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CHECK(elf);
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (elf_kind(elf) != ELF_K_ELF) {
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG(ERROR) << "File not in ELF format";
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ELF::Ehdr* elf_header = ELF::getehdr(elf);
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!elf_header) {
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Failed to load ELF header: " << elf_errmsg(elf_errno());
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (elf_header->e_machine != ELF::kMachine) {
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "ELF file architecture is not " << ELF::Machine();
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (elf_header->e_type != ET_DYN) {
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "ELF file is not a shared object";
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Require that our endianness matches that of the target, and that both
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // are little-endian.  Safe for all current build/target combinations.
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int endian = elf_header->e_ident[EI_DATA];
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(endian == ELFDATA2LSB);
173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__);
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Also require that the file class is as expected.
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int file_class = elf_header->e_ident[EI_CLASS];
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CHECK(file_class == ELF::kFileClass);
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VLOG(1) << "endian = " << endian << ", file class = " << file_class;
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  VerboseLogElfHeader(elf_header);
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const ELF::Phdr* elf_program_header = ELF::getphdr(elf);
183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(elf_program_header);
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const ELF::Phdr* dynamic_program_header = NULL;
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t i = 0; i < elf_header->e_phnum; ++i) {
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const ELF::Phdr* program_header = &elf_program_header[i];
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    VerboseLogProgramHeader(i, program_header);
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (program_header->p_type == PT_DYNAMIC) {
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CHECK(dynamic_program_header == NULL);
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dynamic_program_header = program_header;
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(dynamic_program_header != NULL);
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t string_index;
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  elf_getshdrstrndx(elf, &string_index);
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Notes of the dynamic relocations, packed relocations, and .dynamic
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // sections.  Found while iterating sections, and later stored in class
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // attributes.
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Elf_Scn* found_relocations_section = NULL;
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Elf_Scn* found_android_relocations_section = NULL;
205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Elf_Scn* found_dynamic_section = NULL;
206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Notes of relocation section types seen.  We require one or the other of
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // these; both is unsupported.
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool has_rel_relocations = false;
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool has_rela_relocations = false;
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Elf_Scn* section = NULL;
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  while ((section = elf_nextscn(elf, section)) != NULL) {
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const ELF::Shdr* section_header = ELF::getshdr(section);
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    std::string name = elf_strptr(elf, string_index, section_header->sh_name);
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    VerboseLogSectionHeader(name, section_header);
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Note relocation section types.
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (section_header->sh_type == SHT_REL) {
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      has_rel_relocations = true;
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (section_header->sh_type == SHT_RELA) {
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      has_rela_relocations = true;
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Note special sections as we encounter them.
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if ((name == ".rel.dyn" || name == ".rela.dyn") &&
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        section_header->sh_size > 0) {
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      found_relocations_section = section;
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if ((name == ".android.rel.dyn" || name == ".android.rela.dyn") &&
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        section_header->sh_size > 0) {
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      found_android_relocations_section = section;
234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (section_header->sh_offset == dynamic_program_header->p_offset) {
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      found_dynamic_section = section;
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Ensure we preserve alignment, repeated later for the data block(s).
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CHECK(section_header->sh_addralign <= kPreserveAlignment);
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Elf_Data* data = NULL;
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    while ((data = elf_getdata(section, data)) != NULL) {
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CHECK(data->d_align <= kPreserveAlignment);
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      VerboseLogSectionData(data);
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Loading failed if we did not find the required special sections.
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!found_relocations_section) {
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Missing or empty .rel.dyn or .rela.dyn section";
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!found_android_relocations_section) {
2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Missing or empty .android.rel.dyn or .android.rela.dyn "
2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               << "section (to fix, run with --help and follow the "
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               << "pre-packing instructions)";
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!found_dynamic_section) {
261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG(ERROR) << "Missing .dynamic section";
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Loading failed if we could not identify the relocations type.
2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!has_rel_relocations && !has_rela_relocations) {
2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "No relocations sections found";
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (has_rel_relocations && has_rela_relocations) {
2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Multiple relocations sections with different types found, "
2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               << "not currently supported";
273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  elf_ = elf;
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  relocations_section_ = found_relocations_section;
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  dynamic_section_ = found_dynamic_section;
2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  android_relocations_section_ = found_android_relocations_section;
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  relocations_type_ = has_rel_relocations ? REL : RELA;
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace {
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Helper for ResizeSection().  Adjust the main ELF header for the hole.
2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void AdjustElfHeaderForHole(ELF::Ehdr* elf_header,
2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            ELF::Off hole_start,
2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            ssize_t hole_size) {
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (elf_header->e_phoff > hole_start) {
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    elf_header->e_phoff += hole_size;
292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    VLOG(1) << "e_phoff adjusted to " << elf_header->e_phoff;
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (elf_header->e_shoff > hole_start) {
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    elf_header->e_shoff += hole_size;
296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    VLOG(1) << "e_shoff adjusted to " << elf_header->e_shoff;
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Helper for ResizeSection().  Adjust all section headers for the hole.
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void AdjustSectionHeadersForHole(Elf* elf,
3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 ELF::Off hole_start,
3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 ssize_t hole_size) {
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t string_index;
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  elf_getshdrstrndx(elf, &string_index);
306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Elf_Scn* section = NULL;
308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while ((section = elf_nextscn(elf, section)) != NULL) {
3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ELF::Shdr* section_header = ELF::getshdr(section);
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    std::string name = elf_strptr(elf, string_index, section_header->sh_name);
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (section_header->sh_offset > hole_start) {
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      section_header->sh_offset += hole_size;
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      VLOG(1) << "section " << name
315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              << " sh_offset adjusted to " << section_header->sh_offset;
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper for ResizeSection().  Adjust the offsets of any program headers
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// that have offsets currently beyond the hole start.
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AdjustProgramHeaderOffsets(ELF::Phdr* program_headers,
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                size_t count,
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                ELF::Phdr* ignored_1,
3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                ELF::Phdr* ignored_2,
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                ELF::Off hole_start,
3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                ssize_t hole_size) {
3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t i = 0; i < count; ++i) {
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ELF::Phdr* program_header = &program_headers[i];
3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (program_header == ignored_1 || program_header == ignored_2)
3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      continue;
3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (program_header->p_offset > hole_start) {
3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // The hole start is past this segment, so adjust offset.
3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      program_header->p_offset += hole_size;
3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      VLOG(1) << "phdr[" << i
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              << "] p_offset adjusted to "<< program_header->p_offset;
3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper for ResizeSection().  Find the first loadable segment in the
3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// file.  We expect it to map from file offset zero.
3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciELF::Phdr* FindFirstLoadSegment(ELF::Phdr* program_headers,
3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                size_t count) {
3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ELF::Phdr* first_loadable_segment = NULL;
3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t i = 0; i < count; ++i) {
3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ELF::Phdr* program_header = &program_headers[i];
3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (program_header->p_type == PT_LOAD &&
3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        program_header->p_offset == 0 &&
3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        program_header->p_vaddr == 0 &&
3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        program_header->p_paddr == 0) {
3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      first_loadable_segment = program_header;
3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LOG_IF(FATAL, !first_loadable_segment)
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      << "Cannot locate a LOAD segment with address and offset zero";
3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return first_loadable_segment;
3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper for ResizeSection().  Find the PT_GNU_STACK segment, and check
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// that it contains what we expect so we can restore it on unpack if needed.
3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciELF::Phdr* FindUnusedGnuStackSegment(ELF::Phdr* program_headers,
3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     size_t count) {
3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ELF::Phdr* unused_segment = NULL;
3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t i = 0; i < count; ++i) {
3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ELF::Phdr* program_header = &program_headers[i];
3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (program_header->p_type == PT_GNU_STACK &&
3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        program_header->p_offset == 0 &&
3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        program_header->p_vaddr == 0 &&
3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        program_header->p_paddr == 0 &&
3781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        program_header->p_filesz == 0 &&
3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        program_header->p_memsz == 0 &&
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        program_header->p_flags == (PF_R | PF_W) &&
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        program_header->p_align == ELF::kGnuStackSegmentAlignment) {
3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      unused_segment = program_header;
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LOG_IF(FATAL, !unused_segment)
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      << "Cannot locate the expected GNU_STACK segment";
3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return unused_segment;
3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper for ResizeSection().  Find the segment that was the first loadable
3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// one before we split it into two.  This is the one into which we coalesce
3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// the split segments on unpacking.
3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciELF::Phdr* FindOriginalFirstLoadSegment(ELF::Phdr* program_headers,
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        size_t count) {
3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const ELF::Phdr* first_loadable_segment =
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FindFirstLoadSegment(program_headers, count);
3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ELF::Phdr* original_first_loadable_segment = NULL;
4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t i = 0; i < count; ++i) {
4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ELF::Phdr* program_header = &program_headers[i];
4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // The original first loadable segment is the one that follows on from
4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // the one we wrote on split to be the current first loadable segment.
4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (program_header->p_type == PT_LOAD &&
4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        program_header->p_offset == first_loadable_segment->p_filesz) {
4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      original_first_loadable_segment = program_header;
4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LOG_IF(FATAL, !original_first_loadable_segment)
4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      << "Cannot locate the LOAD segment that follows a LOAD at offset zero";
4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return original_first_loadable_segment;
4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper for ResizeSection().  Find the segment that contains the hole.
4181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciElf_Scn* FindSectionContainingHole(Elf* elf,
4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   ELF::Off hole_start,
4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   ssize_t hole_size) {
4211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Elf_Scn* section = NULL;
4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Elf_Scn* last_unholed_section = NULL;
4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while ((section = elf_nextscn(elf, section)) != NULL) {
4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ELF::Shdr* section_header = ELF::getshdr(section);
4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Because we get here after section headers have been adjusted for the
4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // hole, we need to 'undo' that adjustment to give a view of the original
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // sections layout.
4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ELF::Off offset = section_header->sh_offset;
4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (section_header->sh_offset >= hole_start) {
4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      offset -= hole_size;
4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (offset <= hole_start) {
4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      last_unholed_section = section;
4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LOG_IF(FATAL, !last_unholed_section)
4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      << "Cannot identify the section before the one containing the hole";
4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The section containing the hole is the one after the last one found
4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // by the loop above.
4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Elf_Scn* holed_section = elf_nextscn(elf, last_unholed_section);
4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LOG_IF(FATAL, !holed_section)
4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      << "Cannot identify the section containing the hole";
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return holed_section;
4491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper for ResizeSection().  Find the last section contained in a segment.
4521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciElf_Scn* FindLastSectionInSegment(Elf* elf,
4531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  ELF::Phdr* program_header,
4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  ELF::Off hole_start,
4551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  ssize_t hole_size) {
4561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const ELF::Off segment_end =
4571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      program_header->p_offset + program_header->p_filesz;
4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Elf_Scn* section = NULL;
4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Elf_Scn* last_section = NULL;
4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while ((section = elf_nextscn(elf, section)) != NULL) {
4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ELF::Shdr* section_header = ELF::getshdr(section);
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // As above, 'undo' any section offset adjustment to give a view of the
4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // original sections layout.
4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ELF::Off offset = section_header->sh_offset;
4681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (section_header->sh_offset >= hole_start) {
4691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      offset -= hole_size;
4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (offset < segment_end) {
4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      last_section = section;
4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LOG_IF(FATAL, !last_section)
4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      << "Cannot identify the last section in the given segment";
4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return last_section;
4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper for ResizeSection().  Order loadable segments by their offsets.
4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The crazy linker contains assumptions about loadable segment ordering,
4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// and it is better if we do not break them.
4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SortOrderSensitiveProgramHeaders(ELF::Phdr* program_headers,
4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      size_t count) {
4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::vector<ELF::Phdr*> orderable;
4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Collect together orderable program headers.  These are all the LOAD
4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // segments, and any GNU_STACK that may be present (removed on packing,
4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // but replaced on unpacking).
4921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t i = 0; i < count; ++i) {
4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ELF::Phdr* program_header = &program_headers[i];
4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (program_header->p_type == PT_LOAD ||
4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        program_header->p_type == PT_GNU_STACK) {
4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      orderable.push_back(program_header);
4981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Order these program headers so that any PT_GNU_STACK is last, and
5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // the LOAD segments that precede it appear in offset order.  Uses
5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // insertion sort.
5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t i = 1; i < orderable.size(); ++i) {
5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (size_t j = i; j > 0; --j) {
5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ELF::Phdr* first = orderable[j - 1];
5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ELF::Phdr* second = orderable[j];
5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (!(first->p_type == PT_GNU_STACK ||
5101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            first->p_offset > second->p_offset)) {
5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        break;
512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
5131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      std::swap(*first, *second);
514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper for ResizeSection().  The GNU_STACK program header is unused in
5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Android, so we can repurpose it here.  Before packing, the program header
5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// table contains something like:
5211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//
5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//   Type      Offset    VirtAddr   PhysAddr   FileSiz   MemSiz    Flg Align
5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//   LOAD      0x000000  0x00000000 0x00000000 0x1efc818 0x1efc818 R E 0x1000
5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//   LOAD      0x1efd008 0x01efe008 0x01efe008 0x17ec3c  0x1a0324  RW  0x1000
5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//   DYNAMIC   0x205ec50 0x0205fc50 0x0205fc50 0x00108   0x00108   RW  0x4
5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//   GNU_STACK 0x000000  0x00000000 0x00000000 0x00000   0x00000   RW  0
5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//
5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The hole in the file is in the first of these.  In order to preserve all
5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// load addresses, what we do is to turn the GNU_STACK into a new LOAD entry
5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// that maps segments up to where we created the hole, adjust the first LOAD
5311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// entry so that it maps segments after that, adjust any other program
5321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// headers whose offset is after the hole start, and finally order the LOAD
5331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// segments by offset, to give:
5341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//
5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//   Type      Offset    VirtAddr   PhysAddr   FileSiz   MemSiz    Flg Align
5361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//   LOAD      0x000000  0x00000000 0x00000000 0x14ea4   0x14ea4   R E 0x1000
5371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//   LOAD      0x014ea4  0x00212ea4 0x00212ea4 0x1cea164 0x1cea164 R E 0x1000
5381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//   DYNAMIC   0x1e60c50 0x0205fc50 0x0205fc50 0x00108   0x00108   RW  0x4
5391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//   LOAD      0x1cff008 0x01efe008 0x01efe008 0x17ec3c  0x1a0324  RW  0x1000
5401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//
5411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// We work out the split points by finding the .rel.dyn or .rela.dyn section
5421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// that contains the hole, and by finding the last section in a given segment.
5431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//
5441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// To unpack, we reverse the above to leave the file as it was originally.
5451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitProgramHeadersForHole(Elf* elf,
5461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                ELF::Off hole_start,
5471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                ssize_t hole_size) {
5481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(hole_size < 0);
5491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const ELF::Ehdr* elf_header = ELF::getehdr(elf);
5501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(elf_header);
5511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ELF::Phdr* elf_program_header = ELF::getphdr(elf);
5531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(elf_program_header);
5541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const size_t program_header_count = elf_header->e_phnum;
5561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Locate the segment that we can overwrite to form the new LOAD entry,
5581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // and the segment that we are going to split into two parts.
5591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ELF::Phdr* spliced_header =
5601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FindUnusedGnuStackSegment(elf_program_header, program_header_count);
5611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ELF::Phdr* split_header =
5621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FindFirstLoadSegment(elf_program_header, program_header_count);
5631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VLOG(1) << "phdr[" << split_header - elf_program_header << "] split";
5651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VLOG(1) << "phdr[" << spliced_header - elf_program_header << "] new LOAD";
5661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Find the section that contains the hole.  We split on the section that
5681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // follows it.
5691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Elf_Scn* holed_section =
5701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FindSectionContainingHole(elf, hole_start, hole_size);
5711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  size_t string_index;
5731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  elf_getshdrstrndx(elf, &string_index);
5741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ELF::Shdr* section_header = ELF::getshdr(holed_section);
5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string name = elf_strptr(elf, string_index, section_header->sh_name);
5771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VLOG(1) << "section " << name << " split after";
5781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Find the last section in the segment we are splitting.
5801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Elf_Scn* last_section =
5811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FindLastSectionInSegment(elf, split_header, hole_start, hole_size);
5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  section_header = ELF::getshdr(last_section);
5841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  name = elf_strptr(elf, string_index, section_header->sh_name);
5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VLOG(1) << "section " << name << " split end";
5861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Split on the section following the holed one, and up to (but not
5881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // including) the section following the last one in the split segment.
5891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Elf_Scn* split_section = elf_nextscn(elf, holed_section);
5901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LOG_IF(FATAL, !split_section)
5911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      << "No section follows the section that contains the hole";
5921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Elf_Scn* end_section = elf_nextscn(elf, last_section);
5931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LOG_IF(FATAL, !end_section)
5941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      << "No section follows the last section in the segment being split";
5951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Split the first portion of split_header into spliced_header.
5971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const ELF::Shdr* split_section_header = ELF::getshdr(split_section);
5981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_type = split_header->p_type;
5991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_offset = split_header->p_offset;
6001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_vaddr = split_header->p_vaddr;
6011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_paddr = split_header->p_paddr;
6021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(split_header->p_filesz == split_header->p_memsz);
6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_filesz = split_section_header->sh_offset;
6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_memsz = split_section_header->sh_offset;
6051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_flags = split_header->p_flags;
6061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_align = split_header->p_align;
6071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Now rewrite split_header to remove the part we spliced from it.
6091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const ELF::Shdr* end_section_header = ELF::getshdr(end_section);
6101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  split_header->p_offset = spliced_header->p_filesz;
6111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(split_header->p_vaddr == split_header->p_paddr);
6121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  split_header->p_vaddr = split_section_header->sh_addr;
6131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  split_header->p_paddr = split_section_header->sh_addr;
6141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(split_header->p_filesz == split_header->p_memsz);
6151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  split_header->p_filesz =
6161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      end_section_header->sh_offset - spliced_header->p_filesz;
6171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  split_header->p_memsz =
6181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      end_section_header->sh_offset - spliced_header->p_filesz;
6191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Adjust the offsets of all program headers that are not one of the pair
6211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // we just created by splitting.
6221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AdjustProgramHeaderOffsets(elf_program_header,
6231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             program_header_count,
6241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             spliced_header,
6251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             split_header,
6261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             hole_start,
6271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             hole_size);
6281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Finally, order loadable segments by offset/address.  The crazy linker
6301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // contains assumptions about loadable segment ordering.
6311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SortOrderSensitiveProgramHeaders(elf_program_header,
6321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   program_header_count);
6331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
6341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper for ResizeSection().  Undo the work of SplitProgramHeadersForHole().
6361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CoalesceProgramHeadersForHole(Elf* elf,
6371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   ELF::Off hole_start,
6381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   ssize_t hole_size) {
6391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(hole_size > 0);
6401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const ELF::Ehdr* elf_header = ELF::getehdr(elf);
6411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(elf_header);
6421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ELF::Phdr* elf_program_header = ELF::getphdr(elf);
6441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(elf_program_header);
6451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const size_t program_header_count = elf_header->e_phnum;
6471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Locate the segment that we overwrote to form the new LOAD entry, and
6491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // the segment that we split into two parts on packing.
6501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ELF::Phdr* spliced_header =
6511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FindFirstLoadSegment(elf_program_header, program_header_count);
6521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ELF::Phdr* split_header =
6531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FindOriginalFirstLoadSegment(elf_program_header, program_header_count);
6541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VLOG(1) << "phdr[" << spliced_header - elf_program_header << "] stack";
6561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VLOG(1) << "phdr[" << split_header - elf_program_header << "] coalesce";
6571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Find the last section in the second segment we are coalescing.
6591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Elf_Scn* last_section =
6601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FindLastSectionInSegment(elf, split_header, hole_start, hole_size);
6611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  size_t string_index;
6631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  elf_getshdrstrndx(elf, &string_index);
6641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const ELF::Shdr* section_header = ELF::getshdr(last_section);
6661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string name = elf_strptr(elf, string_index, section_header->sh_name);
6671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VLOG(1) << "section " << name << " coalesced";
6681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Rewrite the coalesced segment into split_header.
6701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const ELF::Shdr* last_section_header = ELF::getshdr(last_section);
6711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  split_header->p_offset = spliced_header->p_offset;
6721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(split_header->p_vaddr == split_header->p_paddr);
6731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  split_header->p_vaddr = spliced_header->p_vaddr;
6741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  split_header->p_paddr = spliced_header->p_vaddr;
6751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(split_header->p_filesz == split_header->p_memsz);
6761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  split_header->p_filesz =
6771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      last_section_header->sh_offset + last_section_header->sh_size;
6781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  split_header->p_memsz =
6791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      last_section_header->sh_offset + last_section_header->sh_size;
6801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Reconstruct the original GNU_STACK segment into spliced_header.
6821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_type = PT_GNU_STACK;
6831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_offset = 0;
6841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_vaddr = 0;
6851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_paddr = 0;
6861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_filesz = 0;
6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_memsz = 0;
6881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_flags = PF_R | PF_W;
6891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spliced_header->p_align = ELF::kGnuStackSegmentAlignment;
6901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Adjust the offsets of all program headers that are not one of the pair
6921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // we just coalesced.
6931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AdjustProgramHeaderOffsets(elf_program_header,
6941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             program_header_count,
6951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             spliced_header,
6961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             split_header,
6971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             hole_start,
6981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             hole_size);
6991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Finally, order loadable segments by offset/address.  The crazy linker
7011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // contains assumptions about loadable segment ordering.
7021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SortOrderSensitiveProgramHeaders(elf_program_header,
7031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   program_header_count);
7041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
7051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper for ResizeSection().  Rewrite program headers.
7071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid RewriteProgramHeadersForHole(Elf* elf,
7081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  ELF::Off hole_start,
7091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  ssize_t hole_size) {
7101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If hole_size is negative then we are removing a piece of the file, and
7111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // we want to split program headers so that we keep the same addresses
7121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // for text and data.  If positive, then we are putting that piece of the
7131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // file back in, so we coalesce the previously split program headers.
7141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (hole_size < 0)
7151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SplitProgramHeadersForHole(elf, hole_start, hole_size);
7161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  else if (hole_size > 0)
7171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CoalesceProgramHeadersForHole(elf, hole_start, hole_size);
7181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
7191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper for ResizeSection().  Locate and return the dynamic section.
7211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciElf_Scn* GetDynamicSection(Elf* elf) {
7221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const ELF::Ehdr* elf_header = ELF::getehdr(elf);
7231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(elf_header);
7241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const ELF::Phdr* elf_program_header = ELF::getphdr(elf);
7261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(elf_program_header);
7271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Find the program header that describes the dynamic section.
7291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const ELF::Phdr* dynamic_program_header = NULL;
7301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t i = 0; i < elf_header->e_phnum; ++i) {
7311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ELF::Phdr* program_header = &elf_program_header[i];
7321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (program_header->p_type == PT_DYNAMIC) {
7341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      dynamic_program_header = program_header;
7351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
7361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(dynamic_program_header);
7381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Now find the section with the same offset as this program header.
7401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Elf_Scn* dynamic_section = NULL;
7411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Elf_Scn* section = NULL;
7421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while ((section = elf_nextscn(elf, section)) != NULL) {
7431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ELF::Shdr* section_header = ELF::getshdr(section);
7441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (section_header->sh_offset == dynamic_program_header->p_offset) {
7461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      dynamic_section = section;
7471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
7481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(dynamic_section != NULL);
7501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return dynamic_section;
7521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
7531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
754f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Helper for ResizeSection().  Adjust the .dynamic section for the hole.
7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <typename Rel>
756f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void AdjustDynamicSectionForHole(Elf_Scn* dynamic_section,
7575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 ELF::Off hole_start,
7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 ssize_t hole_size) {
759f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Elf_Data* data = GetSectionData(dynamic_section);
760f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf);
7625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<ELF::Dyn> dynamics(
763f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dynamic_base,
764f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dynamic_base + data->d_size / sizeof(dynamics[0]));
765f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
766f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t i = 0; i < dynamics.size(); ++i) {
7675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ELF::Dyn* dynamic = &dynamics[i];
7685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const ELF::Sword tag = dynamic->d_tag;
769f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // DT_RELSZ or DT_RELASZ indicate the overall size of relocations.
7716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Only one will be present.  Adjust by hole size.
7726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (tag == DT_RELSZ || tag == DT_RELASZ) {
7735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      dynamic->d_un.d_val += hole_size;
7745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag
7755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              << " d_val adjusted to " << dynamic->d_un.d_val;
7765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
777f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // DT_RELCOUNT or DT_RELACOUNT hold the count of relative relocations.
7796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Only one will be present.  Packing reduces it to the alignment
7806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // padding, if any; unpacking restores it to its former value.  The
7816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // crazy linker does not use it, but we update it anyway.
7826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (tag == DT_RELCOUNT || tag == DT_RELACOUNT) {
7835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // Cast sizeof to a signed type to avoid the division result being
7845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // promoted into an unsigned size_t.
7855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const ssize_t sizeof_rel = static_cast<ssize_t>(sizeof(Rel));
7865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      dynamic->d_un.d_val += hole_size / sizeof_rel;
7875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag
7885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              << " d_val adjusted to " << dynamic->d_un.d_val;
7895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
7905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // DT_RELENT and DT_RELAENT do not change, but make sure they are what
7926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // we expect.  Only one will be present.
7936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (tag == DT_RELENT || tag == DT_RELAENT) {
7945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      CHECK(dynamic->d_un.d_val == sizeof(Rel));
795f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
796f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
797f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
798f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void* section_data = &dynamics[0];
799f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t bytes = dynamics.size() * sizeof(dynamics[0]);
800f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RewriteSectionData(data, section_data, bytes);
801f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
802f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
803f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Resize a section.  If the new size is larger than the current size, open
804f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// up a hole by increasing file offsets that come after the hole.  If smaller
805f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// than the current size, remove the hole by decreasing those offsets.
8065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <typename Rel>
807f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size) {
8085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ELF::Shdr* section_header = ELF::getshdr(section);
809f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (section_header->sh_size == new_size)
810f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
811f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
8121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Note if we are resizing the real dyn relocations.
813f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t string_index;
814f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  elf_getshdrstrndx(elf, &string_index);
815f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const std::string section_name =
816f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      elf_strptr(elf, string_index, section_header->sh_name);
8175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const bool is_relocations_resize =
8185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      (section_name == ".rel.dyn" || section_name == ".rela.dyn");
819f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
820f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Require that the section size and the data size are the same.  True
821f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // in practice for all sections we resize when packing or unpacking.
822f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Elf_Data* data = GetSectionData(section);
823f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(data->d_off == 0 && data->d_size == section_header->sh_size);
824f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
825f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Require that the section is not zero-length (that is, has allocated
826f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // data that we can validly expand).
827f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(data->d_size && data->d_buf);
828f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
8295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const ELF::Off hole_start = section_header->sh_offset;
8305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const ssize_t hole_size = new_size - data->d_size;
831f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
832116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG_IF(1, (hole_size > 0)) << "expand section size = " << data->d_size;
833116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG_IF(1, (hole_size < 0)) << "shrink section size = " << data->d_size;
834f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
835f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Resize the data and the section header.
836f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data->d_size += hole_size;
837f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  section_header->sh_size += hole_size;
838f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
839f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Add the hole size to all offsets in the ELF file that are after the
840f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // start of the hole.  If the hole size is positive we are expanding the
841f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // section to create a new hole; if negative, we are closing up a hole.
842f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
843f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Start with the main ELF header.
8441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ELF::Ehdr* elf_header = ELF::getehdr(elf);
845f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AdjustElfHeaderForHole(elf_header, hole_start, hole_size);
846f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
847f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Adjust all section headers.
848f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AdjustSectionHeadersForHole(elf, hole_start, hole_size);
849f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
8501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If resizing the dynamic relocations, rewrite the program headers to
8511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // either split or coalesce segments, and adjust dynamic entries to match.
8521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (is_relocations_resize) {
8531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    RewriteProgramHeadersForHole(elf, hole_start, hole_size);
854f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
8551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Elf_Scn* dynamic_section = GetDynamicSection(elf);
8561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AdjustDynamicSectionForHole<Rel>(dynamic_section, hole_start, hole_size);
857f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
858f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
859f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
8605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Find the first slot in a dynamics array with the given tag.  The array
8615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// always ends with a free (unused) element, and which we exclude from the
8625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// search.  Returns dynamics->size() if not found.
8635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)size_t FindDynamicEntry(ELF::Sword tag,
8645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        std::vector<ELF::Dyn>* dynamics) {
8655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Loop until the penultimate entry.  We exclude the end sentinel.
8665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (size_t i = 0; i < dynamics->size() - 1; ++i) {
8675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (dynamics->at(i).d_tag == tag)
8685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return i;
8695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
8705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // The tag was not found.
8725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return dynamics->size();
8735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
8745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
875f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Replace the first free (unused) slot in a dynamics vector with the given
876f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// value.  The vector always ends with a free (unused) element, so the slot
877f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found cannot be the last one in the vector.
8785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void AddDynamicEntry(const ELF::Dyn& dyn,
8795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     std::vector<ELF::Dyn>* dynamics) {
8805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t slot = FindDynamicEntry(DT_NULL, dynamics);
8815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (slot == dynamics->size()) {
8825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(FATAL) << "No spare dynamic array slots found "
8835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               << "(to fix, increase gold's --spare-dynamic-tags value)";
884f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
885f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
8865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Replace this entry with the one supplied.
8875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  dynamics->at(slot) = dyn;
8885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VLOG(1) << "dynamic[" << slot << "] overwritten with " << dyn.d_tag;
889f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
890f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
891f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Remove the element in the dynamics vector that matches the given tag with
892f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// unused slot data.  Shuffle the following elements up, and ensure that the
893f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// last is the null sentinel.
8945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void RemoveDynamicEntry(ELF::Sword tag,
8955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        std::vector<ELF::Dyn>* dynamics) {
8965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t slot = FindDynamicEntry(tag, dynamics);
8975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CHECK(slot != dynamics->size());
8985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Remove this entry by shuffling up everything that follows.
9005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (size_t i = slot; i < dynamics->size() - 1; ++i) {
9015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    dynamics->at(i) = dynamics->at(i + 1);
9025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VLOG(1) << "dynamic[" << i
9035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            << "] overwritten with dynamic[" << i + 1 << "]";
904f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
905f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
9065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Ensure that the end sentinel is still present.
9075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CHECK(dynamics->at(dynamics->size() - 1).d_tag == DT_NULL);
908f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
909f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
9105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <typename Rel>
9115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void PadRelocations(size_t count, std::vector<Rel>* relocations);
9125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <>
9145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void PadRelocations<ELF::Rel>(size_t count,
9155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              std::vector<ELF::Rel>* relocations) {
9165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ELF::Rel null_relocation;
9175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  null_relocation.r_offset = 0;
9185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  null_relocation.r_info = ELF_R_INFO(0, ELF::kNoRelocationCode);
9195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<ELF::Rel> padding(count, null_relocation);
9205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  relocations->insert(relocations->end(), padding.begin(), padding.end());
9215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
9225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <>
9245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void PadRelocations<ELF::Rela>(size_t count,
9255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               std::vector<ELF::Rela>* relocations) {
9265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ELF::Rela null_relocation;
9275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  null_relocation.r_offset = 0;
9285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  null_relocation.r_info = ELF_R_INFO(0, ELF::kNoRelocationCode);
9295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  null_relocation.r_addend = 0;
9305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<ELF::Rela> padding(count, null_relocation);
931f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  relocations->insert(relocations->end(), padding.begin(), padding.end());
932f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
933f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
934f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace
935f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
9365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Remove relative entries from dynamic relocations and write as packed
9375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// data into android packed relocations.
938f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool ElfFile::PackRelocations() {
939f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Load the ELF file into libelf.
940f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!Load()) {
9415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Failed to load as ELF";
942f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
943f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
944f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
9455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Retrieve the current dynamic relocations section data.
9465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Elf_Data* data = GetSectionData(relocations_section_);
947f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
9485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (relocations_type_ == REL) {
9495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Convert data to a vector of relocations.
9505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const ELF::Rel* relocations_base = reinterpret_cast<ELF::Rel*>(data->d_buf);
9515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    std::vector<ELF::Rel> relocations(
9525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        relocations_base,
9535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        relocations_base + data->d_size / sizeof(relocations[0]));
9545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(INFO) << "Relocations   : REL";
9565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return PackTypedRelocations<ELF::Rel>(relocations, data);
9575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
958f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
9595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (relocations_type_ == RELA) {
9605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Convert data to a vector of relocations with addends.
9615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const ELF::Rela* relocations_base =
9625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        reinterpret_cast<ELF::Rela*>(data->d_buf);
9635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    std::vector<ELF::Rela> relocations(
9645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        relocations_base,
9655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        relocations_base + data->d_size / sizeof(relocations[0]));
9665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(INFO) << "Relocations   : RELA";
9685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return PackTypedRelocations<ELF::Rela>(relocations, data);
9695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
9705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  NOTREACHED();
9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return false;
9735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Helper for PackRelocations().  Rel type is one of ELF::Rel or ELF::Rela.
9765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <typename Rel>
9775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool ElfFile::PackTypedRelocations(const std::vector<Rel>& relocations,
9785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   Elf_Data* data) {
9795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Filter relocations into those that are relative and others.
9805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<Rel> relative_relocations;
9815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<Rel> other_relocations;
982f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
983f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t i = 0; i < relocations.size(); ++i) {
9845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const Rel& relocation = relocations[i];
9855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (ELF_R_TYPE(relocation.r_info) == ELF::kRelativeRelocationCode) {
9865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      CHECK(ELF_R_SYM(relocation.r_info) == 0);
987f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      relative_relocations.push_back(relocation);
988f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else {
989f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      other_relocations.push_back(relocation);
990f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
991f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
9925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  LOG(INFO) << "Relative      : " << relative_relocations.size() << " entries";
993116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LOG(INFO) << "Other         : " << other_relocations.size() << " entries";
994116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LOG(INFO) << "Total         : " << relocations.size() << " entries";
995f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
996f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If no relative relocations then we have nothing packable.  Perhaps
997f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // the shared object has already been packed?
998f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (relative_relocations.empty()) {
9995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "No relative relocations found (already packed?)";
1000f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
1001f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1002f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
10031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If not padding fully, apply only enough padding to preserve alignment.
10041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Otherwise, pad so that we do not shrink the relocations section at all.
10055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!is_padding_relocations_) {
10061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Calculate the size of the hole we will close up when we rewrite
10071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // dynamic relocations.
10085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ELF::Shdr* section_header = ELF::getshdr(relocations_section_);
10095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const ELF::Off hole_start = section_header->sh_offset;
10105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ssize_t hole_size =
1011f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        relative_relocations.size() * sizeof(relative_relocations[0]);
10125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const ssize_t unaligned_hole_size = hole_size;
1013f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
10145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Adjust the actual hole size to preserve alignment.  We always adjust
10155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // by a whole number of NONE-type relocations.
10165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    while (hole_size % kPreserveAlignment)
10175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      hole_size -= sizeof(relative_relocations[0]);
1018116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG(INFO) << "Compaction    : " << hole_size << " bytes";
1019f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1020f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Adjusting for alignment may have removed any packing benefit.
1021f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (hole_size == 0) {
10225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      LOG(INFO) << "Too few relative relocations to pack after alignment";
1023f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
1024f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
1025f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
10265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Find the padding needed in other_relocations to preserve alignment.
10275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Ensure that we never completely empty the real relocations section.
10285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t padding_bytes = unaligned_hole_size - hole_size;
10295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (padding_bytes == 0 && other_relocations.size() == 0) {
10305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      do {
10315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        padding_bytes += sizeof(relative_relocations[0]);
10325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      } while (padding_bytes % kPreserveAlignment);
10335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1034f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CHECK(padding_bytes % sizeof(other_relocations[0]) == 0);
10355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const size_t padding = padding_bytes / sizeof(other_relocations[0]);
10365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Padding may have removed any packing benefit.
10385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (padding >= relative_relocations.size()) {
10395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      LOG(INFO) << "Too few relative relocations to pack after padding";
10405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return false;
10415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
10425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Add null relocations to other_relocations to preserve alignment.
10445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PadRelocations<Rel>(padding, &other_relocations);
10455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(INFO) << "Alignment pad : " << padding << " relocations";
1046f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
10475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // If padding, add NONE-type relocations to other_relocations to make it
1048f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // the same size as the the original relocations we read in.  This makes
1049f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // the ResizeSection() below a no-op.
10505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const size_t padding = relocations.size() - other_relocations.size();
10515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PadRelocations<Rel>(padding, &other_relocations);
1052f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1053f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
10545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Pack relative relocations.
1055f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const size_t initial_bytes =
1056f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      relative_relocations.size() * sizeof(relative_relocations[0]);
10575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  LOG(INFO) << "Unpacked relative: " << initial_bytes << " bytes";
1058f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::vector<uint8_t> packed;
1059f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RelocationPacker packer;
1060f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packer.PackRelativeRelocations(relative_relocations, &packed);
1061f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const void* packed_data = &packed[0];
1062f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const size_t packed_bytes = packed.size() * sizeof(packed[0]);
10635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  LOG(INFO) << "Packed   relative: " << packed_bytes << " bytes";
1064f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
10655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // If we have insufficient relative relocations to form a run then
1066f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // packing fails.
1067f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (packed.empty()) {
10685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(INFO) << "Too few relative relocations to pack";
1069f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
1070f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1071f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1072f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Run a loopback self-test as a check that packing is lossless.
10735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<Rel> unpacked;
1074f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packer.UnpackRelativeRelocations(packed, &unpacked);
1075f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(unpacked.size() == relative_relocations.size());
10765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CHECK(!memcmp(&unpacked[0],
10775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                &relative_relocations[0],
10785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                unpacked.size() * sizeof(unpacked[0])));
1079f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1080f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Make sure packing saved some space.
1081f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (packed_bytes >= initial_bytes) {
10825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(INFO) << "Packing relative relocations saves no space";
1083f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
1084f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1085f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
10865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Rewrite the current dynamic relocations section to be only the ARM
10875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // non-relative relocations, then shrink it to size.
1088f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const void* section_data = &other_relocations[0];
1089f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const size_t bytes = other_relocations.size() * sizeof(other_relocations[0]);
10905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ResizeSection<Rel>(elf_, relocations_section_, bytes);
1091f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RewriteSectionData(data, section_data, bytes);
1092f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
10935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Rewrite the current packed android relocations section to hold the packed
10945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // relative relocations.
10955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  data = GetSectionData(android_relocations_section_);
10965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ResizeSection<Rel>(elf_, android_relocations_section_, packed_bytes);
1097f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RewriteSectionData(data, packed_data, packed_bytes);
1098f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
10995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Rewrite .dynamic to include two new tags describing the packed android
11005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // relocations.
1101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data = GetSectionData(dynamic_section_);
11025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf);
11035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<ELF::Dyn> dynamics(
1104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dynamic_base,
1105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dynamic_base + data->d_size / sizeof(dynamics[0]));
11065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Use two of the spare slots to describe the packed section.
11075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ELF::Shdr* section_header = ELF::getshdr(android_relocations_section_);
11081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  {
11091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ELF::Dyn dyn;
11101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dyn.d_tag = DT_ANDROID_REL_OFFSET;
11111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dyn.d_un.d_ptr = section_header->sh_offset;
11121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AddDynamicEntry(dyn, &dynamics);
11131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
11141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  {
11151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ELF::Dyn dyn;
11161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dyn.d_tag = DT_ANDROID_REL_SIZE;
11171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dyn.d_un.d_val = section_header->sh_size;
11181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AddDynamicEntry(dyn, &dynamics);
11191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const void* dynamics_data = &dynamics[0];
1121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]);
1122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RewriteSectionData(data, dynamics_data, dynamics_bytes);
1123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Flush();
1125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
1126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
1127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
11285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Find packed relative relocations in the packed android relocations
11295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// section, unpack them, and rewrite the dynamic relocations section to
11305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// contain unpacked data.
1131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool ElfFile::UnpackRelocations() {
1132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Load the ELF file into libelf.
1133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!Load()) {
11345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Failed to load as ELF";
1135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
1136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
11385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Retrieve the current packed android relocations section data.
11395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Elf_Data* data = GetSectionData(android_relocations_section_);
1140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Convert data to a vector of bytes.
1142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const uint8_t* packed_base = reinterpret_cast<uint8_t*>(data->d_buf);
1143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::vector<uint8_t> packed(
1144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      packed_base,
1145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      packed_base + data->d_size / sizeof(packed[0]));
1146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
11475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (packed.size() > 3 &&
11485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      packed[0] == 'A' &&
11495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      packed[1] == 'P' &&
11505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      packed[2] == 'R' &&
11515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      packed[3] == '1') {
11525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Signature is APR1, unpack relocations.
11535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CHECK(relocations_type_ == REL);
11545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(INFO) << "Relocations   : REL";
11555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return UnpackTypedRelocations<ELF::Rel>(packed, data);
1156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
11585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (packed.size() > 3 &&
11595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      packed[0] == 'A' &&
11605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      packed[1] == 'P' &&
11615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      packed[2] == 'A' &&
11625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      packed[3] == '1') {
11635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Signature is APA1, unpack relocations with addends.
11645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CHECK(relocations_type_ == RELA);
11655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(INFO) << "Relocations   : RELA";
11665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return UnpackTypedRelocations<ELF::Rela>(packed, data);
11675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
11685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  LOG(ERROR) << "Packed relative relocations not found (not packed?)";
11705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return false;
11715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
11725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Helper for UnpackRelocations().  Rel type is one of ELF::Rel or ELF::Rela.
11745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <typename Rel>
11755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool ElfFile::UnpackTypedRelocations(const std::vector<uint8_t>& packed,
11765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     Elf_Data* data) {
11775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Unpack the data to re-materialize the relative relocations.
1178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const size_t packed_bytes = packed.size() * sizeof(packed[0]);
11795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  LOG(INFO) << "Packed   relative: " << packed_bytes << " bytes";
11805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<Rel> relative_relocations;
1181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RelocationPacker packer;
1182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packer.UnpackRelativeRelocations(packed, &relative_relocations);
1183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const size_t unpacked_bytes =
1184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      relative_relocations.size() * sizeof(relative_relocations[0]);
11855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  LOG(INFO) << "Unpacked relative: " << unpacked_bytes << " bytes";
1186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
11875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Retrieve the current dynamic relocations section data.
11885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  data = GetSectionData(relocations_section_);
1189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
11906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Interpret data as relocations.
11915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const Rel* relocations_base = reinterpret_cast<Rel*>(data->d_buf);
11925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<Rel> relocations(
1193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      relocations_base,
1194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      relocations_base + data->d_size / sizeof(relocations[0]));
1195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
11965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<Rel> other_relocations;
1197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t padding = 0;
1198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
11995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Filter relocations to locate any that are NONE-type.  These will occur
1200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // if padding was turned on for packing.
1201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t i = 0; i < relocations.size(); ++i) {
12025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const Rel& relocation = relocations[i];
12035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (ELF_R_TYPE(relocation.r_info) != ELF::kNoRelocationCode) {
1204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      other_relocations.push_back(relocation);
1205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else {
1206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ++padding;
1207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
1208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
12095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  LOG(INFO) << "Relative      : " << relative_relocations.size() << " entries";
1210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LOG(INFO) << "Other         : " << other_relocations.size() << " entries";
1211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
12125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // If we found the same number of null relocation entries in the dynamic
12135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // relocations section as we hold as unpacked relative relocations, then
12145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // this is a padded file.
1215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const bool is_padded = padding == relative_relocations.size();
1216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
12175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Unless padded, pre-apply relative relocations to account for the
1218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // hole, and pre-adjust all relocation offsets accordingly.
1219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!is_padded) {
1220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Pre-calculate the size of the hole we will open up when we rewrite
12215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // dynamic relocations.  We have to adjust relocation addresses to
12225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // account for this.
12235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ELF::Shdr* section_header = ELF::getshdr(relocations_section_);
12245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const ELF::Off hole_start = section_header->sh_offset;
12255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ssize_t hole_size =
1226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        relative_relocations.size() * sizeof(relative_relocations[0]);
1227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Adjust the hole size for the padding added to preserve alignment.
1229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    hole_size -= padding * sizeof(other_relocations[0]);
1230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG(INFO) << "Expansion     : " << hole_size << " bytes";
1231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
12335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Rewrite the current dynamic relocations section to be the relative
12345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // relocations followed by other relocations.  This is the usual order in
12355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // which we find them after linking, so this action will normally put the
12365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // entire dynamic relocations section back to its pre-split-and-packed state.
1237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  relocations.assign(relative_relocations.begin(), relative_relocations.end());
1238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  relocations.insert(relocations.end(),
1239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     other_relocations.begin(), other_relocations.end());
1240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const void* section_data = &relocations[0];
1241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const size_t bytes = relocations.size() * sizeof(relocations[0]);
1242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LOG(INFO) << "Total         : " << relocations.size() << " entries";
12435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ResizeSection<Rel>(elf_, relocations_section_, bytes);
1244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RewriteSectionData(data, section_data, bytes);
1245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
12465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Nearly empty the current packed android relocations section.  Leaves a
12475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // four-byte stub so that some data remains allocated to the section.
12485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // This is a convenience which allows us to re-pack this file again without
1249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // having to remove the section and then add a new small one with objcopy.
1250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // The way we resize sections relies on there being some data in a section.
12515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  data = GetSectionData(android_relocations_section_);
12525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ResizeSection<Rel>(
12535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      elf_, android_relocations_section_, sizeof(kStubIdentifier));
1254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RewriteSectionData(data, &kStubIdentifier, sizeof(kStubIdentifier));
1255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
12565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Rewrite .dynamic to remove two tags describing packed android relocations.
1257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data = GetSectionData(dynamic_section_);
12585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf);
12595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<ELF::Dyn> dynamics(
1260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dynamic_base,
1261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dynamic_base + data->d_size / sizeof(dynamics[0]));
12625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RemoveDynamicEntry(DT_ANDROID_REL_OFFSET, &dynamics);
12635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RemoveDynamicEntry(DT_ANDROID_REL_SIZE, &dynamics);
1264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const void* dynamics_data = &dynamics[0];
1265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]);
1266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RewriteSectionData(data, dynamics_data, dynamics_bytes);
1267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Flush();
1269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
1270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
1271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Flush rewritten shared object file data.
1273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ElfFile::Flush() {
1274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Flag all ELF data held in memory as needing to be written back to the
1275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // file, and tell libelf that we have controlled the file layout.
1276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  elf_flagelf(elf_, ELF_C_SET, ELF_F_DIRTY);
1277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  elf_flagelf(elf_, ELF_C_SET, ELF_F_LAYOUT);
1278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Write ELF data back to disk.
1280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const off_t file_bytes = elf_update(elf_, ELF_C_WRITE);
1281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(file_bytes > 0);
1282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VLOG(1) << "elf_update returned: " << file_bytes;
1283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Clean up libelf, and truncate the output file to the number of bytes
1285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // written by elf_update().
1286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  elf_end(elf_);
1287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  elf_ = NULL;
1288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const int truncate = ftruncate(fd_, file_bytes);
1289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(truncate == 0);
1290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
1291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace relocation_packer
1293