• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Implementation notes:
6 //
7 // We need to remove a piece from the ELF shared library.  However, we also
8 // want to ensure that code and data loads at the same addresses as before
9 // packing, so that tools like breakpad can still match up addresses found
10 // in any crash dumps with data extracted from the pre-packed version of
11 // the shared library.
12 //
13 // Arranging this means that we have to split one of the LOAD segments into
14 // two.  Unfortunately, the program headers are located at the very start
15 // of the shared library file, so expanding the program header section
16 // would cause a lot of consequent changes to files offsets that we don't
17 // really want to have to handle.
18 //
19 // Luckily, though, there is a segment that is always present and always
20 // unused on Android; the GNU_STACK segment.  What we do is to steal that
21 // and repurpose it to be one of the split LOAD segments.  We then have to
22 // sort LOAD segments by offset to keep the crazy linker happy.
23 //
24 // All of this takes place in SplitProgramHeadersForHole(), used on packing,
25 // and is unraveled on unpacking in CoalesceProgramHeadersForHole().  See
26 // commentary on those functions for an example of this segment stealing
27 // in action.
28 
29 #include "elf_file.h"
30 
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34 #include <algorithm>
35 #include <string>
36 #include <vector>
37 
38 #include "debug.h"
39 #include "elf_traits.h"
40 #include "libelf.h"
41 #include "packer.h"
42 
43 namespace relocation_packer {
44 
45 // Stub identifier written to 'null out' packed data, "NULL".
46 static const uint32_t kStubIdentifier = 0x4c4c554eu;
47 
48 // Out-of-band dynamic tags used to indicate the offset and size of the
49 // android packed relocations section.
50 static const ELF::Sword DT_ANDROID_REL_OFFSET = DT_LOOS;
51 static const ELF::Sword DT_ANDROID_REL_SIZE = DT_LOOS + 1;
52 
53 // Alignment to preserve, in bytes.  This must be at least as large as the
54 // largest d_align and sh_addralign values found in the loaded file.
55 // Out of caution for RELRO page alignment, we preserve to a complete target
56 // page.  See http://www.airs.com/blog/archives/189.
57 static const size_t kPreserveAlignment = 4096;
58 
59 namespace {
60 
61 // Get section data.  Checks that the section has exactly one data entry,
62 // so that the section size and the data size are the same.  True in
63 // practice for all sections we resize when packing or unpacking.  Done
64 // by ensuring that a call to elf_getdata(section, data) returns NULL as
65 // the next data entry.
GetSectionData(Elf_Scn * section)66 Elf_Data* GetSectionData(Elf_Scn* section) {
67   Elf_Data* data = elf_getdata(section, NULL);
68   CHECK(data && elf_getdata(section, data) == NULL);
69   return data;
70 }
71 
72 // Rewrite section data.  Allocates new data and makes it the data element's
73 // buffer.  Relies on program exit to free allocated data.
RewriteSectionData(Elf_Data * data,const void * section_data,size_t size)74 void RewriteSectionData(Elf_Data* data,
75                         const void* section_data,
76                         size_t size) {
77   CHECK(size == data->d_size);
78   uint8_t* area = new uint8_t[size];
79   memcpy(area, section_data, size);
80   data->d_buf = area;
81 }
82 
83 // Verbose ELF header logging.
VerboseLogElfHeader(const ELF::Ehdr * elf_header)84 void VerboseLogElfHeader(const ELF::Ehdr* elf_header) {
85   VLOG(1) << "e_phoff = " << elf_header->e_phoff;
86   VLOG(1) << "e_shoff = " << elf_header->e_shoff;
87   VLOG(1) << "e_ehsize = " << elf_header->e_ehsize;
88   VLOG(1) << "e_phentsize = " << elf_header->e_phentsize;
89   VLOG(1) << "e_phnum = " << elf_header->e_phnum;
90   VLOG(1) << "e_shnum = " << elf_header->e_shnum;
91   VLOG(1) << "e_shstrndx = " << elf_header->e_shstrndx;
92 }
93 
94 // Verbose ELF program header logging.
VerboseLogProgramHeader(size_t program_header_index,const ELF::Phdr * program_header)95 void VerboseLogProgramHeader(size_t program_header_index,
96                              const ELF::Phdr* program_header) {
97   std::string type;
98   switch (program_header->p_type) {
99     case PT_NULL: type = "NULL"; break;
100     case PT_LOAD: type = "LOAD"; break;
101     case PT_DYNAMIC: type = "DYNAMIC"; break;
102     case PT_INTERP: type = "INTERP"; break;
103     case PT_PHDR: type = "PHDR"; break;
104     case PT_GNU_RELRO: type = "GNU_RELRO"; break;
105     case PT_GNU_STACK: type = "GNU_STACK"; break;
106     case PT_ARM_EXIDX: type = "EXIDX"; break;
107     default: type = "(OTHER)"; break;
108   }
109   VLOG(1) << "phdr[" << program_header_index << "] : " << type;
110   VLOG(1) << "  p_offset = " << program_header->p_offset;
111   VLOG(1) << "  p_vaddr = " << program_header->p_vaddr;
112   VLOG(1) << "  p_paddr = " << program_header->p_paddr;
113   VLOG(1) << "  p_filesz = " << program_header->p_filesz;
114   VLOG(1) << "  p_memsz = " << program_header->p_memsz;
115   VLOG(1) << "  p_flags = " << program_header->p_flags;
116   VLOG(1) << "  p_align = " << program_header->p_align;
117 }
118 
119 // Verbose ELF section header logging.
VerboseLogSectionHeader(const std::string & section_name,const ELF::Shdr * section_header)120 void VerboseLogSectionHeader(const std::string& section_name,
121                              const ELF::Shdr* section_header) {
122   VLOG(1) << "section " << section_name;
123   VLOG(1) << "  sh_addr = " << section_header->sh_addr;
124   VLOG(1) << "  sh_offset = " << section_header->sh_offset;
125   VLOG(1) << "  sh_size = " << section_header->sh_size;
126   VLOG(1) << "  sh_addralign = " << section_header->sh_addralign;
127 }
128 
129 // Verbose ELF section data logging.
VerboseLogSectionData(const Elf_Data * data)130 void VerboseLogSectionData(const Elf_Data* data) {
131   VLOG(1) << "  data";
132   VLOG(1) << "    d_buf = " << data->d_buf;
133   VLOG(1) << "    d_off = " << data->d_off;
134   VLOG(1) << "    d_size = " << data->d_size;
135   VLOG(1) << "    d_align = " << data->d_align;
136 }
137 
138 }  // namespace
139 
140 // Load the complete ELF file into a memory image in libelf, and identify
141 // the .rel.dyn or .rela.dyn, .dynamic, and .android.rel.dyn or
142 // .android.rela.dyn sections.  No-op if the ELF file has already been loaded.
Load()143 bool ElfFile::Load() {
144   if (elf_)
145     return true;
146 
147   Elf* elf = elf_begin(fd_, ELF_C_RDWR, NULL);
148   CHECK(elf);
149 
150   if (elf_kind(elf) != ELF_K_ELF) {
151     LOG(ERROR) << "File not in ELF format";
152     return false;
153   }
154 
155   ELF::Ehdr* elf_header = ELF::getehdr(elf);
156   if (!elf_header) {
157     LOG(ERROR) << "Failed to load ELF header: " << elf_errmsg(elf_errno());
158     return false;
159   }
160   if (elf_header->e_machine != ELF::kMachine) {
161     LOG(ERROR) << "ELF file architecture is not " << ELF::Machine();
162     return false;
163   }
164   if (elf_header->e_type != ET_DYN) {
165     LOG(ERROR) << "ELF file is not a shared object";
166     return false;
167   }
168 
169   // Require that our endianness matches that of the target, and that both
170   // are little-endian.  Safe for all current build/target combinations.
171   const int endian = elf_header->e_ident[EI_DATA];
172   CHECK(endian == ELFDATA2LSB);
173   CHECK(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__);
174 
175   // Also require that the file class is as expected.
176   const int file_class = elf_header->e_ident[EI_CLASS];
177   CHECK(file_class == ELF::kFileClass);
178 
179   VLOG(1) << "endian = " << endian << ", file class = " << file_class;
180   VerboseLogElfHeader(elf_header);
181 
182   const ELF::Phdr* elf_program_header = ELF::getphdr(elf);
183   CHECK(elf_program_header);
184 
185   const ELF::Phdr* dynamic_program_header = NULL;
186   for (size_t i = 0; i < elf_header->e_phnum; ++i) {
187     const ELF::Phdr* program_header = &elf_program_header[i];
188     VerboseLogProgramHeader(i, program_header);
189 
190     if (program_header->p_type == PT_DYNAMIC) {
191       CHECK(dynamic_program_header == NULL);
192       dynamic_program_header = program_header;
193     }
194   }
195   CHECK(dynamic_program_header != NULL);
196 
197   size_t string_index;
198   elf_getshdrstrndx(elf, &string_index);
199 
200   // Notes of the dynamic relocations, packed relocations, and .dynamic
201   // sections.  Found while iterating sections, and later stored in class
202   // attributes.
203   Elf_Scn* found_relocations_section = NULL;
204   Elf_Scn* found_android_relocations_section = NULL;
205   Elf_Scn* found_dynamic_section = NULL;
206 
207   // Notes of relocation section types seen.  We require one or the other of
208   // these; both is unsupported.
209   bool has_rel_relocations = false;
210   bool has_rela_relocations = false;
211 
212   Elf_Scn* section = NULL;
213   while ((section = elf_nextscn(elf, section)) != NULL) {
214     const ELF::Shdr* section_header = ELF::getshdr(section);
215     std::string name = elf_strptr(elf, string_index, section_header->sh_name);
216     VerboseLogSectionHeader(name, section_header);
217 
218     // Note relocation section types.
219     if (section_header->sh_type == SHT_REL) {
220       has_rel_relocations = true;
221     }
222     if (section_header->sh_type == SHT_RELA) {
223       has_rela_relocations = true;
224     }
225 
226     // Note special sections as we encounter them.
227     if ((name == ".rel.dyn" || name == ".rela.dyn") &&
228         section_header->sh_size > 0) {
229       found_relocations_section = section;
230     }
231     if ((name == ".android.rel.dyn" || name == ".android.rela.dyn") &&
232         section_header->sh_size > 0) {
233       found_android_relocations_section = section;
234     }
235     if (section_header->sh_offset == dynamic_program_header->p_offset) {
236       found_dynamic_section = section;
237     }
238 
239     // Ensure we preserve alignment, repeated later for the data block(s).
240     CHECK(section_header->sh_addralign <= kPreserveAlignment);
241 
242     Elf_Data* data = NULL;
243     while ((data = elf_getdata(section, data)) != NULL) {
244       CHECK(data->d_align <= kPreserveAlignment);
245       VerboseLogSectionData(data);
246     }
247   }
248 
249   // Loading failed if we did not find the required special sections.
250   if (!found_relocations_section) {
251     LOG(ERROR) << "Missing or empty .rel.dyn or .rela.dyn section";
252     return false;
253   }
254   if (!found_android_relocations_section) {
255     LOG(ERROR) << "Missing or empty .android.rel.dyn or .android.rela.dyn "
256                << "section (to fix, run with --help and follow the "
257                << "pre-packing instructions)";
258     return false;
259   }
260   if (!found_dynamic_section) {
261     LOG(ERROR) << "Missing .dynamic section";
262     return false;
263   }
264 
265   // Loading failed if we could not identify the relocations type.
266   if (!has_rel_relocations && !has_rela_relocations) {
267     LOG(ERROR) << "No relocations sections found";
268     return false;
269   }
270   if (has_rel_relocations && has_rela_relocations) {
271     LOG(ERROR) << "Multiple relocations sections with different types found, "
272                << "not currently supported";
273     return false;
274   }
275 
276   elf_ = elf;
277   relocations_section_ = found_relocations_section;
278   dynamic_section_ = found_dynamic_section;
279   android_relocations_section_ = found_android_relocations_section;
280   relocations_type_ = has_rel_relocations ? REL : RELA;
281   return true;
282 }
283 
284 namespace {
285 
286 // Helper for ResizeSection().  Adjust the main ELF header for the hole.
AdjustElfHeaderForHole(ELF::Ehdr * elf_header,ELF::Off hole_start,ssize_t hole_size)287 void AdjustElfHeaderForHole(ELF::Ehdr* elf_header,
288                             ELF::Off hole_start,
289                             ssize_t hole_size) {
290   if (elf_header->e_phoff > hole_start) {
291     elf_header->e_phoff += hole_size;
292     VLOG(1) << "e_phoff adjusted to " << elf_header->e_phoff;
293   }
294   if (elf_header->e_shoff > hole_start) {
295     elf_header->e_shoff += hole_size;
296     VLOG(1) << "e_shoff adjusted to " << elf_header->e_shoff;
297   }
298 }
299 
300 // Helper for ResizeSection().  Adjust all section headers for the hole.
AdjustSectionHeadersForHole(Elf * elf,ELF::Off hole_start,ssize_t hole_size)301 void AdjustSectionHeadersForHole(Elf* elf,
302                                  ELF::Off hole_start,
303                                  ssize_t hole_size) {
304   size_t string_index;
305   elf_getshdrstrndx(elf, &string_index);
306 
307   Elf_Scn* section = NULL;
308   while ((section = elf_nextscn(elf, section)) != NULL) {
309     ELF::Shdr* section_header = ELF::getshdr(section);
310     std::string name = elf_strptr(elf, string_index, section_header->sh_name);
311 
312     if (section_header->sh_offset > hole_start) {
313       section_header->sh_offset += hole_size;
314       VLOG(1) << "section " << name
315               << " sh_offset adjusted to " << section_header->sh_offset;
316     }
317   }
318 }
319 
320 // Helper for ResizeSection().  Adjust the offsets of any program headers
321 // that have offsets currently beyond the hole start.
AdjustProgramHeaderOffsets(ELF::Phdr * program_headers,size_t count,ELF::Phdr * ignored_1,ELF::Phdr * ignored_2,ELF::Off hole_start,ssize_t hole_size)322 void AdjustProgramHeaderOffsets(ELF::Phdr* program_headers,
323                                 size_t count,
324                                 ELF::Phdr* ignored_1,
325                                 ELF::Phdr* ignored_2,
326                                 ELF::Off hole_start,
327                                 ssize_t hole_size) {
328   for (size_t i = 0; i < count; ++i) {
329     ELF::Phdr* program_header = &program_headers[i];
330 
331     if (program_header == ignored_1 || program_header == ignored_2)
332       continue;
333 
334     if (program_header->p_offset > hole_start) {
335       // The hole start is past this segment, so adjust offset.
336       program_header->p_offset += hole_size;
337       VLOG(1) << "phdr[" << i
338               << "] p_offset adjusted to "<< program_header->p_offset;
339     }
340   }
341 }
342 
343 // Helper for ResizeSection().  Find the first loadable segment in the
344 // file.  We expect it to map from file offset zero.
FindFirstLoadSegment(ELF::Phdr * program_headers,size_t count)345 ELF::Phdr* FindFirstLoadSegment(ELF::Phdr* program_headers,
346                                 size_t count) {
347   ELF::Phdr* first_loadable_segment = NULL;
348 
349   for (size_t i = 0; i < count; ++i) {
350     ELF::Phdr* program_header = &program_headers[i];
351 
352     if (program_header->p_type == PT_LOAD &&
353         program_header->p_offset == 0 &&
354         program_header->p_vaddr == 0 &&
355         program_header->p_paddr == 0) {
356       first_loadable_segment = program_header;
357     }
358   }
359   LOG_IF(FATAL, !first_loadable_segment)
360       << "Cannot locate a LOAD segment with address and offset zero";
361 
362   return first_loadable_segment;
363 }
364 
365 // Helper for ResizeSection().  Find the PT_GNU_STACK segment, and check
366 // that it contains what we expect so we can restore it on unpack if needed.
FindUnusedGnuStackSegment(ELF::Phdr * program_headers,size_t count)367 ELF::Phdr* FindUnusedGnuStackSegment(ELF::Phdr* program_headers,
368                                      size_t count) {
369   ELF::Phdr* unused_segment = NULL;
370 
371   for (size_t i = 0; i < count; ++i) {
372     ELF::Phdr* program_header = &program_headers[i];
373 
374     if (program_header->p_type == PT_GNU_STACK &&
375         program_header->p_offset == 0 &&
376         program_header->p_vaddr == 0 &&
377         program_header->p_paddr == 0 &&
378         program_header->p_filesz == 0 &&
379         program_header->p_memsz == 0 &&
380         program_header->p_flags == (PF_R | PF_W) &&
381         program_header->p_align == ELF::kGnuStackSegmentAlignment) {
382       unused_segment = program_header;
383     }
384   }
385   LOG_IF(FATAL, !unused_segment)
386       << "Cannot locate the expected GNU_STACK segment";
387 
388   return unused_segment;
389 }
390 
391 // Helper for ResizeSection().  Find the segment that was the first loadable
392 // one before we split it into two.  This is the one into which we coalesce
393 // the split segments on unpacking.
FindOriginalFirstLoadSegment(ELF::Phdr * program_headers,size_t count)394 ELF::Phdr* FindOriginalFirstLoadSegment(ELF::Phdr* program_headers,
395                                         size_t count) {
396   const ELF::Phdr* first_loadable_segment =
397       FindFirstLoadSegment(program_headers, count);
398 
399   ELF::Phdr* original_first_loadable_segment = NULL;
400 
401   for (size_t i = 0; i < count; ++i) {
402     ELF::Phdr* program_header = &program_headers[i];
403 
404     // The original first loadable segment is the one that follows on from
405     // the one we wrote on split to be the current first loadable segment.
406     if (program_header->p_type == PT_LOAD &&
407         program_header->p_offset == first_loadable_segment->p_filesz) {
408       original_first_loadable_segment = program_header;
409     }
410   }
411   LOG_IF(FATAL, !original_first_loadable_segment)
412       << "Cannot locate the LOAD segment that follows a LOAD at offset zero";
413 
414   return original_first_loadable_segment;
415 }
416 
417 // Helper for ResizeSection().  Find the segment that contains the hole.
FindSectionContainingHole(Elf * elf,ELF::Off hole_start,ssize_t hole_size)418 Elf_Scn* FindSectionContainingHole(Elf* elf,
419                                    ELF::Off hole_start,
420                                    ssize_t hole_size) {
421   Elf_Scn* section = NULL;
422   Elf_Scn* last_unholed_section = NULL;
423 
424   while ((section = elf_nextscn(elf, section)) != NULL) {
425     const ELF::Shdr* section_header = ELF::getshdr(section);
426 
427     // Because we get here after section headers have been adjusted for the
428     // hole, we need to 'undo' that adjustment to give a view of the original
429     // sections layout.
430     ELF::Off offset = section_header->sh_offset;
431     if (section_header->sh_offset >= hole_start) {
432       offset -= hole_size;
433     }
434 
435     if (offset <= hole_start) {
436       last_unholed_section = section;
437     }
438   }
439   LOG_IF(FATAL, !last_unholed_section)
440       << "Cannot identify the section before the one containing the hole";
441 
442   // The section containing the hole is the one after the last one found
443   // by the loop above.
444   Elf_Scn* holed_section = elf_nextscn(elf, last_unholed_section);
445   LOG_IF(FATAL, !holed_section)
446       << "Cannot identify the section containing the hole";
447 
448   return holed_section;
449 }
450 
451 // Helper for ResizeSection().  Find the last section contained in a segment.
FindLastSectionInSegment(Elf * elf,ELF::Phdr * program_header,ELF::Off hole_start,ssize_t hole_size)452 Elf_Scn* FindLastSectionInSegment(Elf* elf,
453                                   ELF::Phdr* program_header,
454                                   ELF::Off hole_start,
455                                   ssize_t hole_size) {
456   const ELF::Off segment_end =
457       program_header->p_offset + program_header->p_filesz;
458 
459   Elf_Scn* section = NULL;
460   Elf_Scn* last_section = NULL;
461 
462   while ((section = elf_nextscn(elf, section)) != NULL) {
463     const ELF::Shdr* section_header = ELF::getshdr(section);
464 
465     // As above, 'undo' any section offset adjustment to give a view of the
466     // original sections layout.
467     ELF::Off offset = section_header->sh_offset;
468     if (section_header->sh_offset >= hole_start) {
469       offset -= hole_size;
470     }
471 
472     if (offset < segment_end) {
473       last_section = section;
474     }
475   }
476   LOG_IF(FATAL, !last_section)
477       << "Cannot identify the last section in the given segment";
478 
479   return last_section;
480 }
481 
482 // Helper for ResizeSection().  Order loadable segments by their offsets.
483 // The crazy linker contains assumptions about loadable segment ordering,
484 // and it is better if we do not break them.
SortOrderSensitiveProgramHeaders(ELF::Phdr * program_headers,size_t count)485 void SortOrderSensitiveProgramHeaders(ELF::Phdr* program_headers,
486                                       size_t count) {
487   std::vector<ELF::Phdr*> orderable;
488 
489   // Collect together orderable program headers.  These are all the LOAD
490   // segments, and any GNU_STACK that may be present (removed on packing,
491   // but replaced on unpacking).
492   for (size_t i = 0; i < count; ++i) {
493     ELF::Phdr* program_header = &program_headers[i];
494 
495     if (program_header->p_type == PT_LOAD ||
496         program_header->p_type == PT_GNU_STACK) {
497       orderable.push_back(program_header);
498     }
499   }
500 
501   // Order these program headers so that any PT_GNU_STACK is last, and
502   // the LOAD segments that precede it appear in offset order.  Uses
503   // insertion sort.
504   for (size_t i = 1; i < orderable.size(); ++i) {
505     for (size_t j = i; j > 0; --j) {
506       ELF::Phdr* first = orderable[j - 1];
507       ELF::Phdr* second = orderable[j];
508 
509       if (!(first->p_type == PT_GNU_STACK ||
510             first->p_offset > second->p_offset)) {
511         break;
512       }
513       std::swap(*first, *second);
514     }
515   }
516 }
517 
518 // Helper for ResizeSection().  The GNU_STACK program header is unused in
519 // Android, so we can repurpose it here.  Before packing, the program header
520 // table contains something like:
521 //
522 //   Type      Offset    VirtAddr   PhysAddr   FileSiz   MemSiz    Flg Align
523 //   LOAD      0x000000  0x00000000 0x00000000 0x1efc818 0x1efc818 R E 0x1000
524 //   LOAD      0x1efd008 0x01efe008 0x01efe008 0x17ec3c  0x1a0324  RW  0x1000
525 //   DYNAMIC   0x205ec50 0x0205fc50 0x0205fc50 0x00108   0x00108   RW  0x4
526 //   GNU_STACK 0x000000  0x00000000 0x00000000 0x00000   0x00000   RW  0
527 //
528 // The hole in the file is in the first of these.  In order to preserve all
529 // load addresses, what we do is to turn the GNU_STACK into a new LOAD entry
530 // that maps segments up to where we created the hole, adjust the first LOAD
531 // entry so that it maps segments after that, adjust any other program
532 // headers whose offset is after the hole start, and finally order the LOAD
533 // segments by offset, to give:
534 //
535 //   Type      Offset    VirtAddr   PhysAddr   FileSiz   MemSiz    Flg Align
536 //   LOAD      0x000000  0x00000000 0x00000000 0x14ea4   0x14ea4   R E 0x1000
537 //   LOAD      0x014ea4  0x00212ea4 0x00212ea4 0x1cea164 0x1cea164 R E 0x1000
538 //   DYNAMIC   0x1e60c50 0x0205fc50 0x0205fc50 0x00108   0x00108   RW  0x4
539 //   LOAD      0x1cff008 0x01efe008 0x01efe008 0x17ec3c  0x1a0324  RW  0x1000
540 //
541 // We work out the split points by finding the .rel.dyn or .rela.dyn section
542 // that contains the hole, and by finding the last section in a given segment.
543 //
544 // To unpack, we reverse the above to leave the file as it was originally.
SplitProgramHeadersForHole(Elf * elf,ELF::Off hole_start,ssize_t hole_size)545 void SplitProgramHeadersForHole(Elf* elf,
546                                 ELF::Off hole_start,
547                                 ssize_t hole_size) {
548   CHECK(hole_size < 0);
549   const ELF::Ehdr* elf_header = ELF::getehdr(elf);
550   CHECK(elf_header);
551 
552   ELF::Phdr* elf_program_header = ELF::getphdr(elf);
553   CHECK(elf_program_header);
554 
555   const size_t program_header_count = elf_header->e_phnum;
556 
557   // Locate the segment that we can overwrite to form the new LOAD entry,
558   // and the segment that we are going to split into two parts.
559   ELF::Phdr* spliced_header =
560       FindUnusedGnuStackSegment(elf_program_header, program_header_count);
561   ELF::Phdr* split_header =
562       FindFirstLoadSegment(elf_program_header, program_header_count);
563 
564   VLOG(1) << "phdr[" << split_header - elf_program_header << "] split";
565   VLOG(1) << "phdr[" << spliced_header - elf_program_header << "] new LOAD";
566 
567   // Find the section that contains the hole.  We split on the section that
568   // follows it.
569   Elf_Scn* holed_section =
570       FindSectionContainingHole(elf, hole_start, hole_size);
571 
572   size_t string_index;
573   elf_getshdrstrndx(elf, &string_index);
574 
575   ELF::Shdr* section_header = ELF::getshdr(holed_section);
576   std::string name = elf_strptr(elf, string_index, section_header->sh_name);
577   VLOG(1) << "section " << name << " split after";
578 
579   // Find the last section in the segment we are splitting.
580   Elf_Scn* last_section =
581       FindLastSectionInSegment(elf, split_header, hole_start, hole_size);
582 
583   section_header = ELF::getshdr(last_section);
584   name = elf_strptr(elf, string_index, section_header->sh_name);
585   VLOG(1) << "section " << name << " split end";
586 
587   // Split on the section following the holed one, and up to (but not
588   // including) the section following the last one in the split segment.
589   Elf_Scn* split_section = elf_nextscn(elf, holed_section);
590   LOG_IF(FATAL, !split_section)
591       << "No section follows the section that contains the hole";
592   Elf_Scn* end_section = elf_nextscn(elf, last_section);
593   LOG_IF(FATAL, !end_section)
594       << "No section follows the last section in the segment being split";
595 
596   // Split the first portion of split_header into spliced_header.
597   const ELF::Shdr* split_section_header = ELF::getshdr(split_section);
598   spliced_header->p_type = split_header->p_type;
599   spliced_header->p_offset = split_header->p_offset;
600   spliced_header->p_vaddr = split_header->p_vaddr;
601   spliced_header->p_paddr = split_header->p_paddr;
602   CHECK(split_header->p_filesz == split_header->p_memsz);
603   spliced_header->p_filesz = split_section_header->sh_offset;
604   spliced_header->p_memsz = split_section_header->sh_offset;
605   spliced_header->p_flags = split_header->p_flags;
606   spliced_header->p_align = split_header->p_align;
607 
608   // Now rewrite split_header to remove the part we spliced from it.
609   const ELF::Shdr* end_section_header = ELF::getshdr(end_section);
610   split_header->p_offset = spliced_header->p_filesz;
611   CHECK(split_header->p_vaddr == split_header->p_paddr);
612   split_header->p_vaddr = split_section_header->sh_addr;
613   split_header->p_paddr = split_section_header->sh_addr;
614   CHECK(split_header->p_filesz == split_header->p_memsz);
615   split_header->p_filesz =
616       end_section_header->sh_offset - spliced_header->p_filesz;
617   split_header->p_memsz =
618       end_section_header->sh_offset - spliced_header->p_filesz;
619 
620   // Adjust the offsets of all program headers that are not one of the pair
621   // we just created by splitting.
622   AdjustProgramHeaderOffsets(elf_program_header,
623                              program_header_count,
624                              spliced_header,
625                              split_header,
626                              hole_start,
627                              hole_size);
628 
629   // Finally, order loadable segments by offset/address.  The crazy linker
630   // contains assumptions about loadable segment ordering.
631   SortOrderSensitiveProgramHeaders(elf_program_header,
632                                    program_header_count);
633 }
634 
635 // Helper for ResizeSection().  Undo the work of SplitProgramHeadersForHole().
CoalesceProgramHeadersForHole(Elf * elf,ELF::Off hole_start,ssize_t hole_size)636 void CoalesceProgramHeadersForHole(Elf* elf,
637                                    ELF::Off hole_start,
638                                    ssize_t hole_size) {
639   CHECK(hole_size > 0);
640   const ELF::Ehdr* elf_header = ELF::getehdr(elf);
641   CHECK(elf_header);
642 
643   ELF::Phdr* elf_program_header = ELF::getphdr(elf);
644   CHECK(elf_program_header);
645 
646   const size_t program_header_count = elf_header->e_phnum;
647 
648   // Locate the segment that we overwrote to form the new LOAD entry, and
649   // the segment that we split into two parts on packing.
650   ELF::Phdr* spliced_header =
651       FindFirstLoadSegment(elf_program_header, program_header_count);
652   ELF::Phdr* split_header =
653       FindOriginalFirstLoadSegment(elf_program_header, program_header_count);
654 
655   VLOG(1) << "phdr[" << spliced_header - elf_program_header << "] stack";
656   VLOG(1) << "phdr[" << split_header - elf_program_header << "] coalesce";
657 
658   // Find the last section in the second segment we are coalescing.
659   Elf_Scn* last_section =
660       FindLastSectionInSegment(elf, split_header, hole_start, hole_size);
661 
662   size_t string_index;
663   elf_getshdrstrndx(elf, &string_index);
664 
665   const ELF::Shdr* section_header = ELF::getshdr(last_section);
666   std::string name = elf_strptr(elf, string_index, section_header->sh_name);
667   VLOG(1) << "section " << name << " coalesced";
668 
669   // Rewrite the coalesced segment into split_header.
670   const ELF::Shdr* last_section_header = ELF::getshdr(last_section);
671   split_header->p_offset = spliced_header->p_offset;
672   CHECK(split_header->p_vaddr == split_header->p_paddr);
673   split_header->p_vaddr = spliced_header->p_vaddr;
674   split_header->p_paddr = spliced_header->p_vaddr;
675   CHECK(split_header->p_filesz == split_header->p_memsz);
676   split_header->p_filesz =
677       last_section_header->sh_offset + last_section_header->sh_size;
678   split_header->p_memsz =
679       last_section_header->sh_offset + last_section_header->sh_size;
680 
681   // Reconstruct the original GNU_STACK segment into spliced_header.
682   spliced_header->p_type = PT_GNU_STACK;
683   spliced_header->p_offset = 0;
684   spliced_header->p_vaddr = 0;
685   spliced_header->p_paddr = 0;
686   spliced_header->p_filesz = 0;
687   spliced_header->p_memsz = 0;
688   spliced_header->p_flags = PF_R | PF_W;
689   spliced_header->p_align = ELF::kGnuStackSegmentAlignment;
690 
691   // Adjust the offsets of all program headers that are not one of the pair
692   // we just coalesced.
693   AdjustProgramHeaderOffsets(elf_program_header,
694                              program_header_count,
695                              spliced_header,
696                              split_header,
697                              hole_start,
698                              hole_size);
699 
700   // Finally, order loadable segments by offset/address.  The crazy linker
701   // contains assumptions about loadable segment ordering.
702   SortOrderSensitiveProgramHeaders(elf_program_header,
703                                    program_header_count);
704 }
705 
706 // Helper for ResizeSection().  Rewrite program headers.
RewriteProgramHeadersForHole(Elf * elf,ELF::Off hole_start,ssize_t hole_size)707 void RewriteProgramHeadersForHole(Elf* elf,
708                                   ELF::Off hole_start,
709                                   ssize_t hole_size) {
710   // If hole_size is negative then we are removing a piece of the file, and
711   // we want to split program headers so that we keep the same addresses
712   // for text and data.  If positive, then we are putting that piece of the
713   // file back in, so we coalesce the previously split program headers.
714   if (hole_size < 0)
715     SplitProgramHeadersForHole(elf, hole_start, hole_size);
716   else if (hole_size > 0)
717     CoalesceProgramHeadersForHole(elf, hole_start, hole_size);
718 }
719 
720 // Helper for ResizeSection().  Locate and return the dynamic section.
GetDynamicSection(Elf * elf)721 Elf_Scn* GetDynamicSection(Elf* elf) {
722   const ELF::Ehdr* elf_header = ELF::getehdr(elf);
723   CHECK(elf_header);
724 
725   const ELF::Phdr* elf_program_header = ELF::getphdr(elf);
726   CHECK(elf_program_header);
727 
728   // Find the program header that describes the dynamic section.
729   const ELF::Phdr* dynamic_program_header = NULL;
730   for (size_t i = 0; i < elf_header->e_phnum; ++i) {
731     const ELF::Phdr* program_header = &elf_program_header[i];
732 
733     if (program_header->p_type == PT_DYNAMIC) {
734       dynamic_program_header = program_header;
735     }
736   }
737   CHECK(dynamic_program_header);
738 
739   // Now find the section with the same offset as this program header.
740   Elf_Scn* dynamic_section = NULL;
741   Elf_Scn* section = NULL;
742   while ((section = elf_nextscn(elf, section)) != NULL) {
743     ELF::Shdr* section_header = ELF::getshdr(section);
744 
745     if (section_header->sh_offset == dynamic_program_header->p_offset) {
746       dynamic_section = section;
747     }
748   }
749   CHECK(dynamic_section != NULL);
750 
751   return dynamic_section;
752 }
753 
754 // Helper for ResizeSection().  Adjust the .dynamic section for the hole.
755 template <typename Rel>
AdjustDynamicSectionForHole(Elf_Scn * dynamic_section,ELF::Off hole_start,ssize_t hole_size)756 void AdjustDynamicSectionForHole(Elf_Scn* dynamic_section,
757                                  ELF::Off hole_start,
758                                  ssize_t hole_size) {
759   Elf_Data* data = GetSectionData(dynamic_section);
760 
761   const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf);
762   std::vector<ELF::Dyn> dynamics(
763       dynamic_base,
764       dynamic_base + data->d_size / sizeof(dynamics[0]));
765 
766   for (size_t i = 0; i < dynamics.size(); ++i) {
767     ELF::Dyn* dynamic = &dynamics[i];
768     const ELF::Sword tag = dynamic->d_tag;
769 
770     // DT_RELSZ or DT_RELASZ indicate the overall size of relocations.
771     // Only one will be present.  Adjust by hole size.
772     if (tag == DT_RELSZ || tag == DT_RELASZ) {
773       dynamic->d_un.d_val += hole_size;
774       VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag
775               << " d_val adjusted to " << dynamic->d_un.d_val;
776     }
777 
778     // DT_RELCOUNT or DT_RELACOUNT hold the count of relative relocations.
779     // Only one will be present.  Packing reduces it to the alignment
780     // padding, if any; unpacking restores it to its former value.  The
781     // crazy linker does not use it, but we update it anyway.
782     if (tag == DT_RELCOUNT || tag == DT_RELACOUNT) {
783       // Cast sizeof to a signed type to avoid the division result being
784       // promoted into an unsigned size_t.
785       const ssize_t sizeof_rel = static_cast<ssize_t>(sizeof(Rel));
786       dynamic->d_un.d_val += hole_size / sizeof_rel;
787       VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag
788               << " d_val adjusted to " << dynamic->d_un.d_val;
789     }
790 
791     // DT_RELENT and DT_RELAENT do not change, but make sure they are what
792     // we expect.  Only one will be present.
793     if (tag == DT_RELENT || tag == DT_RELAENT) {
794       CHECK(dynamic->d_un.d_val == sizeof(Rel));
795     }
796   }
797 
798   void* section_data = &dynamics[0];
799   size_t bytes = dynamics.size() * sizeof(dynamics[0]);
800   RewriteSectionData(data, section_data, bytes);
801 }
802 
803 // Resize a section.  If the new size is larger than the current size, open
804 // up a hole by increasing file offsets that come after the hole.  If smaller
805 // than the current size, remove the hole by decreasing those offsets.
806 template <typename Rel>
ResizeSection(Elf * elf,Elf_Scn * section,size_t new_size)807 void ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size) {
808   ELF::Shdr* section_header = ELF::getshdr(section);
809   if (section_header->sh_size == new_size)
810     return;
811 
812   // Note if we are resizing the real dyn relocations.
813   size_t string_index;
814   elf_getshdrstrndx(elf, &string_index);
815   const std::string section_name =
816       elf_strptr(elf, string_index, section_header->sh_name);
817   const bool is_relocations_resize =
818       (section_name == ".rel.dyn" || section_name == ".rela.dyn");
819 
820   // Require that the section size and the data size are the same.  True
821   // in practice for all sections we resize when packing or unpacking.
822   Elf_Data* data = GetSectionData(section);
823   CHECK(data->d_off == 0 && data->d_size == section_header->sh_size);
824 
825   // Require that the section is not zero-length (that is, has allocated
826   // data that we can validly expand).
827   CHECK(data->d_size && data->d_buf);
828 
829   const ELF::Off hole_start = section_header->sh_offset;
830   const ssize_t hole_size = new_size - data->d_size;
831 
832   VLOG_IF(1, (hole_size > 0)) << "expand section size = " << data->d_size;
833   VLOG_IF(1, (hole_size < 0)) << "shrink section size = " << data->d_size;
834 
835   // Resize the data and the section header.
836   data->d_size += hole_size;
837   section_header->sh_size += hole_size;
838 
839   // Add the hole size to all offsets in the ELF file that are after the
840   // start of the hole.  If the hole size is positive we are expanding the
841   // section to create a new hole; if negative, we are closing up a hole.
842 
843   // Start with the main ELF header.
844   ELF::Ehdr* elf_header = ELF::getehdr(elf);
845   AdjustElfHeaderForHole(elf_header, hole_start, hole_size);
846 
847   // Adjust all section headers.
848   AdjustSectionHeadersForHole(elf, hole_start, hole_size);
849 
850   // If resizing the dynamic relocations, rewrite the program headers to
851   // either split or coalesce segments, and adjust dynamic entries to match.
852   if (is_relocations_resize) {
853     RewriteProgramHeadersForHole(elf, hole_start, hole_size);
854 
855     Elf_Scn* dynamic_section = GetDynamicSection(elf);
856     AdjustDynamicSectionForHole<Rel>(dynamic_section, hole_start, hole_size);
857   }
858 }
859 
860 // Find the first slot in a dynamics array with the given tag.  The array
861 // always ends with a free (unused) element, and which we exclude from the
862 // search.  Returns dynamics->size() if not found.
FindDynamicEntry(ELF::Sword tag,std::vector<ELF::Dyn> * dynamics)863 size_t FindDynamicEntry(ELF::Sword tag,
864                         std::vector<ELF::Dyn>* dynamics) {
865   // Loop until the penultimate entry.  We exclude the end sentinel.
866   for (size_t i = 0; i < dynamics->size() - 1; ++i) {
867     if (dynamics->at(i).d_tag == tag)
868       return i;
869   }
870 
871   // The tag was not found.
872   return dynamics->size();
873 }
874 
875 // Replace the first free (unused) slot in a dynamics vector with the given
876 // value.  The vector always ends with a free (unused) element, so the slot
877 // found cannot be the last one in the vector.
AddDynamicEntry(const ELF::Dyn & dyn,std::vector<ELF::Dyn> * dynamics)878 void AddDynamicEntry(const ELF::Dyn& dyn,
879                      std::vector<ELF::Dyn>* dynamics) {
880   const size_t slot = FindDynamicEntry(DT_NULL, dynamics);
881   if (slot == dynamics->size()) {
882     LOG(FATAL) << "No spare dynamic array slots found "
883                << "(to fix, increase gold's --spare-dynamic-tags value)";
884   }
885 
886   // Replace this entry with the one supplied.
887   dynamics->at(slot) = dyn;
888   VLOG(1) << "dynamic[" << slot << "] overwritten with " << dyn.d_tag;
889 }
890 
891 // Remove the element in the dynamics vector that matches the given tag with
892 // unused slot data.  Shuffle the following elements up, and ensure that the
893 // last is the null sentinel.
RemoveDynamicEntry(ELF::Sword tag,std::vector<ELF::Dyn> * dynamics)894 void RemoveDynamicEntry(ELF::Sword tag,
895                         std::vector<ELF::Dyn>* dynamics) {
896   const size_t slot = FindDynamicEntry(tag, dynamics);
897   CHECK(slot != dynamics->size());
898 
899   // Remove this entry by shuffling up everything that follows.
900   for (size_t i = slot; i < dynamics->size() - 1; ++i) {
901     dynamics->at(i) = dynamics->at(i + 1);
902     VLOG(1) << "dynamic[" << i
903             << "] overwritten with dynamic[" << i + 1 << "]";
904   }
905 
906   // Ensure that the end sentinel is still present.
907   CHECK(dynamics->at(dynamics->size() - 1).d_tag == DT_NULL);
908 }
909 
910 template <typename Rel>
911 void PadRelocations(size_t count, std::vector<Rel>* relocations);
912 
913 template <>
PadRelocations(size_t count,std::vector<ELF::Rel> * relocations)914 void PadRelocations<ELF::Rel>(size_t count,
915                               std::vector<ELF::Rel>* relocations) {
916   ELF::Rel null_relocation;
917   null_relocation.r_offset = 0;
918   null_relocation.r_info = ELF_R_INFO(0, ELF::kNoRelocationCode);
919   std::vector<ELF::Rel> padding(count, null_relocation);
920   relocations->insert(relocations->end(), padding.begin(), padding.end());
921 }
922 
923 template <>
PadRelocations(size_t count,std::vector<ELF::Rela> * relocations)924 void PadRelocations<ELF::Rela>(size_t count,
925                                std::vector<ELF::Rela>* relocations) {
926   ELF::Rela null_relocation;
927   null_relocation.r_offset = 0;
928   null_relocation.r_info = ELF_R_INFO(0, ELF::kNoRelocationCode);
929   null_relocation.r_addend = 0;
930   std::vector<ELF::Rela> padding(count, null_relocation);
931   relocations->insert(relocations->end(), padding.begin(), padding.end());
932 }
933 
934 }  // namespace
935 
936 // Remove relative entries from dynamic relocations and write as packed
937 // data into android packed relocations.
PackRelocations()938 bool ElfFile::PackRelocations() {
939   // Load the ELF file into libelf.
940   if (!Load()) {
941     LOG(ERROR) << "Failed to load as ELF";
942     return false;
943   }
944 
945   // Retrieve the current dynamic relocations section data.
946   Elf_Data* data = GetSectionData(relocations_section_);
947 
948   if (relocations_type_ == REL) {
949     // Convert data to a vector of relocations.
950     const ELF::Rel* relocations_base = reinterpret_cast<ELF::Rel*>(data->d_buf);
951     std::vector<ELF::Rel> relocations(
952         relocations_base,
953         relocations_base + data->d_size / sizeof(relocations[0]));
954 
955     LOG(INFO) << "Relocations   : REL";
956     return PackTypedRelocations<ELF::Rel>(relocations, data);
957   }
958 
959   if (relocations_type_ == RELA) {
960     // Convert data to a vector of relocations with addends.
961     const ELF::Rela* relocations_base =
962         reinterpret_cast<ELF::Rela*>(data->d_buf);
963     std::vector<ELF::Rela> relocations(
964         relocations_base,
965         relocations_base + data->d_size / sizeof(relocations[0]));
966 
967     LOG(INFO) << "Relocations   : RELA";
968     return PackTypedRelocations<ELF::Rela>(relocations, data);
969   }
970 
971   NOTREACHED();
972   return false;
973 }
974 
975 // Helper for PackRelocations().  Rel type is one of ELF::Rel or ELF::Rela.
976 template <typename Rel>
PackTypedRelocations(const std::vector<Rel> & relocations,Elf_Data * data)977 bool ElfFile::PackTypedRelocations(const std::vector<Rel>& relocations,
978                                    Elf_Data* data) {
979   // Filter relocations into those that are relative and others.
980   std::vector<Rel> relative_relocations;
981   std::vector<Rel> other_relocations;
982 
983   for (size_t i = 0; i < relocations.size(); ++i) {
984     const Rel& relocation = relocations[i];
985     if (ELF_R_TYPE(relocation.r_info) == ELF::kRelativeRelocationCode) {
986       CHECK(ELF_R_SYM(relocation.r_info) == 0);
987       relative_relocations.push_back(relocation);
988     } else {
989       other_relocations.push_back(relocation);
990     }
991   }
992   LOG(INFO) << "Relative      : " << relative_relocations.size() << " entries";
993   LOG(INFO) << "Other         : " << other_relocations.size() << " entries";
994   LOG(INFO) << "Total         : " << relocations.size() << " entries";
995 
996   // If no relative relocations then we have nothing packable.  Perhaps
997   // the shared object has already been packed?
998   if (relative_relocations.empty()) {
999     LOG(ERROR) << "No relative relocations found (already packed?)";
1000     return false;
1001   }
1002 
1003   // If not padding fully, apply only enough padding to preserve alignment.
1004   // Otherwise, pad so that we do not shrink the relocations section at all.
1005   if (!is_padding_relocations_) {
1006     // Calculate the size of the hole we will close up when we rewrite
1007     // dynamic relocations.
1008     ELF::Shdr* section_header = ELF::getshdr(relocations_section_);
1009     const ELF::Off hole_start = section_header->sh_offset;
1010     ssize_t hole_size =
1011         relative_relocations.size() * sizeof(relative_relocations[0]);
1012     const ssize_t unaligned_hole_size = hole_size;
1013 
1014     // Adjust the actual hole size to preserve alignment.  We always adjust
1015     // by a whole number of NONE-type relocations.
1016     while (hole_size % kPreserveAlignment)
1017       hole_size -= sizeof(relative_relocations[0]);
1018     LOG(INFO) << "Compaction    : " << hole_size << " bytes";
1019 
1020     // Adjusting for alignment may have removed any packing benefit.
1021     if (hole_size == 0) {
1022       LOG(INFO) << "Too few relative relocations to pack after alignment";
1023       return false;
1024     }
1025 
1026     // Find the padding needed in other_relocations to preserve alignment.
1027     // Ensure that we never completely empty the real relocations section.
1028     size_t padding_bytes = unaligned_hole_size - hole_size;
1029     if (padding_bytes == 0 && other_relocations.size() == 0) {
1030       do {
1031         padding_bytes += sizeof(relative_relocations[0]);
1032       } while (padding_bytes % kPreserveAlignment);
1033     }
1034     CHECK(padding_bytes % sizeof(other_relocations[0]) == 0);
1035     const size_t padding = padding_bytes / sizeof(other_relocations[0]);
1036 
1037     // Padding may have removed any packing benefit.
1038     if (padding >= relative_relocations.size()) {
1039       LOG(INFO) << "Too few relative relocations to pack after padding";
1040       return false;
1041     }
1042 
1043     // Add null relocations to other_relocations to preserve alignment.
1044     PadRelocations<Rel>(padding, &other_relocations);
1045     LOG(INFO) << "Alignment pad : " << padding << " relocations";
1046   } else {
1047     // If padding, add NONE-type relocations to other_relocations to make it
1048     // the same size as the the original relocations we read in.  This makes
1049     // the ResizeSection() below a no-op.
1050     const size_t padding = relocations.size() - other_relocations.size();
1051     PadRelocations<Rel>(padding, &other_relocations);
1052   }
1053 
1054   // Pack relative relocations.
1055   const size_t initial_bytes =
1056       relative_relocations.size() * sizeof(relative_relocations[0]);
1057   LOG(INFO) << "Unpacked relative: " << initial_bytes << " bytes";
1058   std::vector<uint8_t> packed;
1059   RelocationPacker packer;
1060   packer.PackRelativeRelocations(relative_relocations, &packed);
1061   const void* packed_data = &packed[0];
1062   const size_t packed_bytes = packed.size() * sizeof(packed[0]);
1063   LOG(INFO) << "Packed   relative: " << packed_bytes << " bytes";
1064 
1065   // If we have insufficient relative relocations to form a run then
1066   // packing fails.
1067   if (packed.empty()) {
1068     LOG(INFO) << "Too few relative relocations to pack";
1069     return false;
1070   }
1071 
1072   // Run a loopback self-test as a check that packing is lossless.
1073   std::vector<Rel> unpacked;
1074   packer.UnpackRelativeRelocations(packed, &unpacked);
1075   CHECK(unpacked.size() == relative_relocations.size());
1076   CHECK(!memcmp(&unpacked[0],
1077                 &relative_relocations[0],
1078                 unpacked.size() * sizeof(unpacked[0])));
1079 
1080   // Make sure packing saved some space.
1081   if (packed_bytes >= initial_bytes) {
1082     LOG(INFO) << "Packing relative relocations saves no space";
1083     return false;
1084   }
1085 
1086   // Rewrite the current dynamic relocations section to be only the ARM
1087   // non-relative relocations, then shrink it to size.
1088   const void* section_data = &other_relocations[0];
1089   const size_t bytes = other_relocations.size() * sizeof(other_relocations[0]);
1090   ResizeSection<Rel>(elf_, relocations_section_, bytes);
1091   RewriteSectionData(data, section_data, bytes);
1092 
1093   // Rewrite the current packed android relocations section to hold the packed
1094   // relative relocations.
1095   data = GetSectionData(android_relocations_section_);
1096   ResizeSection<Rel>(elf_, android_relocations_section_, packed_bytes);
1097   RewriteSectionData(data, packed_data, packed_bytes);
1098 
1099   // Rewrite .dynamic to include two new tags describing the packed android
1100   // relocations.
1101   data = GetSectionData(dynamic_section_);
1102   const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf);
1103   std::vector<ELF::Dyn> dynamics(
1104       dynamic_base,
1105       dynamic_base + data->d_size / sizeof(dynamics[0]));
1106   // Use two of the spare slots to describe the packed section.
1107   ELF::Shdr* section_header = ELF::getshdr(android_relocations_section_);
1108   {
1109     ELF::Dyn dyn;
1110     dyn.d_tag = DT_ANDROID_REL_OFFSET;
1111     dyn.d_un.d_ptr = section_header->sh_offset;
1112     AddDynamicEntry(dyn, &dynamics);
1113   }
1114   {
1115     ELF::Dyn dyn;
1116     dyn.d_tag = DT_ANDROID_REL_SIZE;
1117     dyn.d_un.d_val = section_header->sh_size;
1118     AddDynamicEntry(dyn, &dynamics);
1119   }
1120   const void* dynamics_data = &dynamics[0];
1121   const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]);
1122   RewriteSectionData(data, dynamics_data, dynamics_bytes);
1123 
1124   Flush();
1125   return true;
1126 }
1127 
1128 // Find packed relative relocations in the packed android relocations
1129 // section, unpack them, and rewrite the dynamic relocations section to
1130 // contain unpacked data.
UnpackRelocations()1131 bool ElfFile::UnpackRelocations() {
1132   // Load the ELF file into libelf.
1133   if (!Load()) {
1134     LOG(ERROR) << "Failed to load as ELF";
1135     return false;
1136   }
1137 
1138   // Retrieve the current packed android relocations section data.
1139   Elf_Data* data = GetSectionData(android_relocations_section_);
1140 
1141   // Convert data to a vector of bytes.
1142   const uint8_t* packed_base = reinterpret_cast<uint8_t*>(data->d_buf);
1143   std::vector<uint8_t> packed(
1144       packed_base,
1145       packed_base + data->d_size / sizeof(packed[0]));
1146 
1147   if (packed.size() > 3 &&
1148       packed[0] == 'A' &&
1149       packed[1] == 'P' &&
1150       packed[2] == 'R' &&
1151       packed[3] == '1') {
1152     // Signature is APR1, unpack relocations.
1153     CHECK(relocations_type_ == REL);
1154     LOG(INFO) << "Relocations   : REL";
1155     return UnpackTypedRelocations<ELF::Rel>(packed, data);
1156   }
1157 
1158   if (packed.size() > 3 &&
1159       packed[0] == 'A' &&
1160       packed[1] == 'P' &&
1161       packed[2] == 'A' &&
1162       packed[3] == '1') {
1163     // Signature is APA1, unpack relocations with addends.
1164     CHECK(relocations_type_ == RELA);
1165     LOG(INFO) << "Relocations   : RELA";
1166     return UnpackTypedRelocations<ELF::Rela>(packed, data);
1167   }
1168 
1169   LOG(ERROR) << "Packed relative relocations not found (not packed?)";
1170   return false;
1171 }
1172 
1173 // Helper for UnpackRelocations().  Rel type is one of ELF::Rel or ELF::Rela.
1174 template <typename Rel>
UnpackTypedRelocations(const std::vector<uint8_t> & packed,Elf_Data * data)1175 bool ElfFile::UnpackTypedRelocations(const std::vector<uint8_t>& packed,
1176                                      Elf_Data* data) {
1177   // Unpack the data to re-materialize the relative relocations.
1178   const size_t packed_bytes = packed.size() * sizeof(packed[0]);
1179   LOG(INFO) << "Packed   relative: " << packed_bytes << " bytes";
1180   std::vector<Rel> relative_relocations;
1181   RelocationPacker packer;
1182   packer.UnpackRelativeRelocations(packed, &relative_relocations);
1183   const size_t unpacked_bytes =
1184       relative_relocations.size() * sizeof(relative_relocations[0]);
1185   LOG(INFO) << "Unpacked relative: " << unpacked_bytes << " bytes";
1186 
1187   // Retrieve the current dynamic relocations section data.
1188   data = GetSectionData(relocations_section_);
1189 
1190   // Interpret data as relocations.
1191   const Rel* relocations_base = reinterpret_cast<Rel*>(data->d_buf);
1192   std::vector<Rel> relocations(
1193       relocations_base,
1194       relocations_base + data->d_size / sizeof(relocations[0]));
1195 
1196   std::vector<Rel> other_relocations;
1197   size_t padding = 0;
1198 
1199   // Filter relocations to locate any that are NONE-type.  These will occur
1200   // if padding was turned on for packing.
1201   for (size_t i = 0; i < relocations.size(); ++i) {
1202     const Rel& relocation = relocations[i];
1203     if (ELF_R_TYPE(relocation.r_info) != ELF::kNoRelocationCode) {
1204       other_relocations.push_back(relocation);
1205     } else {
1206       ++padding;
1207     }
1208   }
1209   LOG(INFO) << "Relative      : " << relative_relocations.size() << " entries";
1210   LOG(INFO) << "Other         : " << other_relocations.size() << " entries";
1211 
1212   // If we found the same number of null relocation entries in the dynamic
1213   // relocations section as we hold as unpacked relative relocations, then
1214   // this is a padded file.
1215   const bool is_padded = padding == relative_relocations.size();
1216 
1217   // Unless padded, pre-apply relative relocations to account for the
1218   // hole, and pre-adjust all relocation offsets accordingly.
1219   if (!is_padded) {
1220     // Pre-calculate the size of the hole we will open up when we rewrite
1221     // dynamic relocations.  We have to adjust relocation addresses to
1222     // account for this.
1223     ELF::Shdr* section_header = ELF::getshdr(relocations_section_);
1224     const ELF::Off hole_start = section_header->sh_offset;
1225     ssize_t hole_size =
1226         relative_relocations.size() * sizeof(relative_relocations[0]);
1227 
1228     // Adjust the hole size for the padding added to preserve alignment.
1229     hole_size -= padding * sizeof(other_relocations[0]);
1230     LOG(INFO) << "Expansion     : " << hole_size << " bytes";
1231   }
1232 
1233   // Rewrite the current dynamic relocations section to be the relative
1234   // relocations followed by other relocations.  This is the usual order in
1235   // which we find them after linking, so this action will normally put the
1236   // entire dynamic relocations section back to its pre-split-and-packed state.
1237   relocations.assign(relative_relocations.begin(), relative_relocations.end());
1238   relocations.insert(relocations.end(),
1239                      other_relocations.begin(), other_relocations.end());
1240   const void* section_data = &relocations[0];
1241   const size_t bytes = relocations.size() * sizeof(relocations[0]);
1242   LOG(INFO) << "Total         : " << relocations.size() << " entries";
1243   ResizeSection<Rel>(elf_, relocations_section_, bytes);
1244   RewriteSectionData(data, section_data, bytes);
1245 
1246   // Nearly empty the current packed android relocations section.  Leaves a
1247   // four-byte stub so that some data remains allocated to the section.
1248   // This is a convenience which allows us to re-pack this file again without
1249   // having to remove the section and then add a new small one with objcopy.
1250   // The way we resize sections relies on there being some data in a section.
1251   data = GetSectionData(android_relocations_section_);
1252   ResizeSection<Rel>(
1253       elf_, android_relocations_section_, sizeof(kStubIdentifier));
1254   RewriteSectionData(data, &kStubIdentifier, sizeof(kStubIdentifier));
1255 
1256   // Rewrite .dynamic to remove two tags describing packed android relocations.
1257   data = GetSectionData(dynamic_section_);
1258   const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf);
1259   std::vector<ELF::Dyn> dynamics(
1260       dynamic_base,
1261       dynamic_base + data->d_size / sizeof(dynamics[0]));
1262   RemoveDynamicEntry(DT_ANDROID_REL_OFFSET, &dynamics);
1263   RemoveDynamicEntry(DT_ANDROID_REL_SIZE, &dynamics);
1264   const void* dynamics_data = &dynamics[0];
1265   const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]);
1266   RewriteSectionData(data, dynamics_data, dynamics_bytes);
1267 
1268   Flush();
1269   return true;
1270 }
1271 
1272 // Flush rewritten shared object file data.
Flush()1273 void ElfFile::Flush() {
1274   // Flag all ELF data held in memory as needing to be written back to the
1275   // file, and tell libelf that we have controlled the file layout.
1276   elf_flagelf(elf_, ELF_C_SET, ELF_F_DIRTY);
1277   elf_flagelf(elf_, ELF_C_SET, ELF_F_LAYOUT);
1278 
1279   // Write ELF data back to disk.
1280   const off_t file_bytes = elf_update(elf_, ELF_C_WRITE);
1281   CHECK(file_bytes > 0);
1282   VLOG(1) << "elf_update returned: " << file_bytes;
1283 
1284   // Clean up libelf, and truncate the output file to the number of bytes
1285   // written by elf_update().
1286   elf_end(elf_);
1287   elf_ = NULL;
1288   const int truncate = ftruncate(fd_, file_bytes);
1289   CHECK(truncate == 0);
1290 }
1291 
1292 }  // namespace relocation_packer
1293