linker_phdr.cpp revision 183ad9df536ab04ef35a397a1f4724e4e401d11f
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *  * Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *  * Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in
12 *    the documentation and/or other materials provided with the
13 *    distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include "linker_phdr.h"
30
31#include <errno.h>
32#include <machine/exec.h>
33#include <sys/mman.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <unistd.h>
37
38#include "linker.h"
39#include "linker_debug.h"
40
41/**
42  TECHNICAL NOTE ON ELF LOADING.
43
44  An ELF file's program header table contains one or more PT_LOAD
45  segments, which corresponds to portions of the file that need to
46  be mapped into the process' address space.
47
48  Each loadable segment has the following important properties:
49
50    p_offset  -> segment file offset
51    p_filesz  -> segment file size
52    p_memsz   -> segment memory size (always >= p_filesz)
53    p_vaddr   -> segment's virtual address
54    p_flags   -> segment flags (e.g. readable, writable, executable)
55
56  We will ignore the p_paddr and p_align fields of ElfW(Phdr) for now.
57
58  The loadable segments can be seen as a list of [p_vaddr ... p_vaddr+p_memsz)
59  ranges of virtual addresses. A few rules apply:
60
61  - the virtual address ranges should not overlap.
62
63  - if a segment's p_filesz is smaller than its p_memsz, the extra bytes
64    between them should always be initialized to 0.
65
66  - ranges do not necessarily start or end at page boundaries. Two distinct
67    segments can have their start and end on the same page. In this case, the
68    page inherits the mapping flags of the latter segment.
69
70  Finally, the real load addrs of each segment is not p_vaddr. Instead the
71  loader decides where to load the first segment, then will load all others
72  relative to the first one to respect the initial range layout.
73
74  For example, consider the following list:
75
76    [ offset:0,      filesz:0x4000, memsz:0x4000, vaddr:0x30000 ],
77    [ offset:0x4000, filesz:0x2000, memsz:0x8000, vaddr:0x40000 ],
78
79  This corresponds to two segments that cover these virtual address ranges:
80
81       0x30000...0x34000
82       0x40000...0x48000
83
84  If the loader decides to load the first segment at address 0xa0000000
85  then the segments' load address ranges will be:
86
87       0xa0030000...0xa0034000
88       0xa0040000...0xa0048000
89
90  In other words, all segments must be loaded at an address that has the same
91  constant offset from their p_vaddr value. This offset is computed as the
92  difference between the first segment's load address, and its p_vaddr value.
93
94  However, in practice, segments do _not_ start at page boundaries. Since we
95  can only memory-map at page boundaries, this means that the bias is
96  computed as:
97
98       load_bias = phdr0_load_address - PAGE_START(phdr0->p_vaddr)
99
100  (NOTE: The value must be used as a 32-bit unsigned integer, to deal with
101          possible wrap around UINT32_MAX for possible large p_vaddr values).
102
103  And that the phdr0_load_address must start at a page boundary, with
104  the segment's real content starting at:
105
106       phdr0_load_address + PAGE_OFFSET(phdr0->p_vaddr)
107
108  Note that ELF requires the following condition to make the mmap()-ing work:
109
110      PAGE_OFFSET(phdr0->p_vaddr) == PAGE_OFFSET(phdr0->p_offset)
111
112  The load_bias must be added to any p_vaddr value read from the ELF file to
113  determine the corresponding memory address.
114
115 **/
116
117#define MAYBE_MAP_FLAG(x, from, to)  (((x) & (from)) ? (to) : 0)
118#define PFLAGS_TO_PROT(x)            (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \
119                                      MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
120                                      MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
121
122ElfReader::ElfReader(const char* name, int fd)
123    : name_(name), fd_(fd),
124      phdr_num_(0), phdr_mmap_(NULL), phdr_table_(NULL), phdr_size_(0),
125      load_start_(NULL), load_size_(0), load_bias_(0),
126      loaded_phdr_(NULL) {
127}
128
129ElfReader::~ElfReader() {
130  if (fd_ != -1) {
131    close(fd_);
132  }
133  if (phdr_mmap_ != NULL) {
134    munmap(phdr_mmap_, phdr_size_);
135  }
136}
137
138bool ElfReader::Load(const android_dlextinfo* extinfo) {
139  return ReadElfHeader() &&
140         VerifyElfHeader() &&
141         ReadProgramHeader() &&
142         ReserveAddressSpace(extinfo) &&
143         LoadSegments() &&
144         FindPhdr();
145}
146
147bool ElfReader::ReadElfHeader() {
148  ssize_t rc = TEMP_FAILURE_RETRY(read(fd_, &header_, sizeof(header_)));
149  if (rc < 0) {
150    DL_ERR("can't read file \"%s\": %s", name_, strerror(errno));
151    return false;
152  }
153  if (rc != sizeof(header_)) {
154    DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_,
155           static_cast<size_t>(rc));
156    return false;
157  }
158  return true;
159}
160
161bool ElfReader::VerifyElfHeader() {
162  if (header_.e_ident[EI_MAG0] != ELFMAG0 ||
163      header_.e_ident[EI_MAG1] != ELFMAG1 ||
164      header_.e_ident[EI_MAG2] != ELFMAG2 ||
165      header_.e_ident[EI_MAG3] != ELFMAG3) {
166    DL_ERR("\"%s\" has bad ELF magic", name_);
167    return false;
168  }
169
170  // Try to give a clear diagnostic for ELF class mismatches, since they're
171  // an easy mistake to make during the 32-bit/64-bit transition period.
172  int elf_class = header_.e_ident[EI_CLASS];
173#if defined(__LP64__)
174  if (elf_class != ELFCLASS64) {
175    if (elf_class == ELFCLASS32) {
176      DL_ERR("\"%s\" is 32-bit instead of 64-bit", name_);
177    } else {
178      DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class);
179    }
180    return false;
181  }
182#else
183  if (elf_class != ELFCLASS32) {
184    if (elf_class == ELFCLASS64) {
185      DL_ERR("\"%s\" is 64-bit instead of 32-bit", name_);
186    } else {
187      DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class);
188    }
189    return false;
190  }
191#endif
192
193  if (header_.e_ident[EI_DATA] != ELFDATA2LSB) {
194    DL_ERR("\"%s\" not little-endian: %d", name_, header_.e_ident[EI_DATA]);
195    return false;
196  }
197
198  if (header_.e_type != ET_DYN) {
199    DL_ERR("\"%s\" has unexpected e_type: %d", name_, header_.e_type);
200    return false;
201  }
202
203  if (header_.e_version != EV_CURRENT) {
204    DL_ERR("\"%s\" has unexpected e_version: %d", name_, header_.e_version);
205    return false;
206  }
207
208  if (header_.e_machine != ELF_TARG_MACH) {
209    DL_ERR("\"%s\" has unexpected e_machine: %d", name_, header_.e_machine);
210    return false;
211  }
212
213  return true;
214}
215
216// Loads the program header table from an ELF file into a read-only private
217// anonymous mmap-ed block.
218bool ElfReader::ReadProgramHeader() {
219  phdr_num_ = header_.e_phnum;
220
221  // Like the kernel, we only accept program header tables that
222  // are smaller than 64KiB.
223  if (phdr_num_ < 1 || phdr_num_ > 65536/sizeof(ElfW(Phdr))) {
224    DL_ERR("\"%s\" has invalid e_phnum: %zd", name_, phdr_num_);
225    return false;
226  }
227
228  ElfW(Addr) page_min = PAGE_START(header_.e_phoff);
229  ElfW(Addr) page_max = PAGE_END(header_.e_phoff + (phdr_num_ * sizeof(ElfW(Phdr))));
230  ElfW(Addr) page_offset = PAGE_OFFSET(header_.e_phoff);
231
232  phdr_size_ = page_max - page_min;
233
234  void* mmap_result = mmap(NULL, phdr_size_, PROT_READ, MAP_PRIVATE, fd_, page_min);
235  if (mmap_result == MAP_FAILED) {
236    DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
237    return false;
238  }
239
240  phdr_mmap_ = mmap_result;
241  phdr_table_ = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<char*>(mmap_result) + page_offset);
242  return true;
243}
244
245/* Returns the size of the extent of all the possibly non-contiguous
246 * loadable segments in an ELF program header table. This corresponds
247 * to the page-aligned size in bytes that needs to be reserved in the
248 * process' address space. If there are no loadable segments, 0 is
249 * returned.
250 *
251 * If out_min_vaddr or out_max_vaddr are non-NULL, they will be
252 * set to the minimum and maximum addresses of pages to be reserved,
253 * or 0 if there is nothing to load.
254 */
255size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
256                                ElfW(Addr)* out_min_vaddr,
257                                ElfW(Addr)* out_max_vaddr) {
258  ElfW(Addr) min_vaddr = UINTPTR_MAX;
259  ElfW(Addr) max_vaddr = 0;
260
261  bool found_pt_load = false;
262  for (size_t i = 0; i < phdr_count; ++i) {
263    const ElfW(Phdr)* phdr = &phdr_table[i];
264
265    if (phdr->p_type != PT_LOAD) {
266      continue;
267    }
268    found_pt_load = true;
269
270    if (phdr->p_vaddr < min_vaddr) {
271      min_vaddr = phdr->p_vaddr;
272    }
273
274    if (phdr->p_vaddr + phdr->p_memsz > max_vaddr) {
275      max_vaddr = phdr->p_vaddr + phdr->p_memsz;
276    }
277  }
278  if (!found_pt_load) {
279    min_vaddr = 0;
280  }
281
282  min_vaddr = PAGE_START(min_vaddr);
283  max_vaddr = PAGE_END(max_vaddr);
284
285  if (out_min_vaddr != NULL) {
286    *out_min_vaddr = min_vaddr;
287  }
288  if (out_max_vaddr != NULL) {
289    *out_max_vaddr = max_vaddr;
290  }
291  return max_vaddr - min_vaddr;
292}
293
294// Reserve a virtual address range big enough to hold all loadable
295// segments of a program header table. This is done by creating a
296// private anonymous mmap() with PROT_NONE.
297bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) {
298  ElfW(Addr) min_vaddr;
299  load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr);
300  if (load_size_ == 0) {
301    DL_ERR("\"%s\" has no loadable segments", name_);
302    return false;
303  }
304
305  uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
306  void* start;
307  size_t reserved_size = 0;
308  bool reserved_hint = true;
309
310  if (extinfo != NULL) {
311    if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
312      reserved_size = extinfo->reserved_size;
313      reserved_hint = false;
314    } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) {
315      reserved_size = extinfo->reserved_size;
316    }
317  }
318
319  if (load_size_ > reserved_size) {
320    if (!reserved_hint) {
321      DL_ERR("reserved address space %zd smaller than %zd bytes needed for \"%s\"",
322             reserved_size - load_size_, load_size_, name_);
323      return false;
324    }
325    int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
326    start = mmap(addr, load_size_, PROT_NONE, mmap_flags, -1, 0);
327    if (start == MAP_FAILED) {
328      DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_);
329      return false;
330    }
331  } else {
332    start = extinfo->reserved_addr;
333  }
334
335  load_start_ = start;
336  load_bias_ = reinterpret_cast<uint8_t*>(start) - addr;
337  return true;
338}
339
340bool ElfReader::LoadSegments() {
341  for (size_t i = 0; i < phdr_num_; ++i) {
342    const ElfW(Phdr)* phdr = &phdr_table_[i];
343
344    if (phdr->p_type != PT_LOAD) {
345      continue;
346    }
347
348    // Segment addresses in memory.
349    ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
350    ElfW(Addr) seg_end   = seg_start + phdr->p_memsz;
351
352    ElfW(Addr) seg_page_start = PAGE_START(seg_start);
353    ElfW(Addr) seg_page_end   = PAGE_END(seg_end);
354
355    ElfW(Addr) seg_file_end   = seg_start + phdr->p_filesz;
356
357    // File offsets.
358    ElfW(Addr) file_start = phdr->p_offset;
359    ElfW(Addr) file_end   = file_start + phdr->p_filesz;
360
361    ElfW(Addr) file_page_start = PAGE_START(file_start);
362    ElfW(Addr) file_length = file_end - file_page_start;
363
364    if (file_length != 0) {
365      void* seg_addr = mmap(reinterpret_cast<void*>(seg_page_start),
366                            file_length,
367                            PFLAGS_TO_PROT(phdr->p_flags),
368                            MAP_FIXED|MAP_PRIVATE,
369                            fd_,
370                            file_page_start);
371      if (seg_addr == MAP_FAILED) {
372        DL_ERR("couldn't map \"%s\" segment %zd: %s", name_, i, strerror(errno));
373        return false;
374      }
375    }
376
377    // if the segment is writable, and does not end on a page boundary,
378    // zero-fill it until the page limit.
379    if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) {
380      memset(reinterpret_cast<void*>(seg_file_end), 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end));
381    }
382
383    seg_file_end = PAGE_END(seg_file_end);
384
385    // seg_file_end is now the first page address after the file
386    // content. If seg_end is larger, we need to zero anything
387    // between them. This is done by using a private anonymous
388    // map for all extra pages.
389    if (seg_page_end > seg_file_end) {
390      void* zeromap = mmap(reinterpret_cast<void*>(seg_file_end),
391                           seg_page_end - seg_file_end,
392                           PFLAGS_TO_PROT(phdr->p_flags),
393                           MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE,
394                           -1,
395                           0);
396      if (zeromap == MAP_FAILED) {
397        DL_ERR("couldn't zero fill \"%s\" gap: %s", name_, strerror(errno));
398        return false;
399      }
400    }
401  }
402  return true;
403}
404
405/* Used internally. Used to set the protection bits of all loaded segments
406 * with optional extra flags (i.e. really PROT_WRITE). Used by
407 * phdr_table_protect_segments and phdr_table_unprotect_segments.
408 */
409static int _phdr_table_set_load_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count,
410                                     ElfW(Addr) load_bias, int extra_prot_flags) {
411  const ElfW(Phdr)* phdr = phdr_table;
412  const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
413
414  for (; phdr < phdr_limit; phdr++) {
415    if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) {
416      continue;
417    }
418
419    ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
420    ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
421
422    int ret = mprotect(reinterpret_cast<void*>(seg_page_start),
423                       seg_page_end - seg_page_start,
424                       PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags);
425    if (ret < 0) {
426      return -1;
427    }
428  }
429  return 0;
430}
431
432/* Restore the original protection modes for all loadable segments.
433 * You should only call this after phdr_table_unprotect_segments and
434 * applying all relocations.
435 *
436 * Input:
437 *   phdr_table  -> program header table
438 *   phdr_count  -> number of entries in tables
439 *   load_bias   -> load bias
440 * Return:
441 *   0 on error, -1 on failure (error code in errno).
442 */
443int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias) {
444  return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, 0);
445}
446
447/* Change the protection of all loaded segments in memory to writable.
448 * This is useful before performing relocations. Once completed, you
449 * will have to call phdr_table_protect_segments to restore the original
450 * protection flags on all segments.
451 *
452 * Note that some writable segments can also have their content turned
453 * to read-only by calling phdr_table_protect_gnu_relro. This is no
454 * performed here.
455 *
456 * Input:
457 *   phdr_table  -> program header table
458 *   phdr_count  -> number of entries in tables
459 *   load_bias   -> load bias
460 * Return:
461 *   0 on error, -1 on failure (error code in errno).
462 */
463int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias) {
464  return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, PROT_WRITE);
465}
466
467/* Used internally by phdr_table_protect_gnu_relro and
468 * phdr_table_unprotect_gnu_relro.
469 */
470static int _phdr_table_set_gnu_relro_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count,
471                                          ElfW(Addr) load_bias, int prot_flags) {
472  const ElfW(Phdr)* phdr = phdr_table;
473  const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
474
475  for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
476    if (phdr->p_type != PT_GNU_RELRO) {
477      continue;
478    }
479
480    // Tricky: what happens when the relro segment does not start
481    // or end at page boundaries? We're going to be over-protective
482    // here and put every page touched by the segment as read-only.
483
484    // This seems to match Ian Lance Taylor's description of the
485    // feature at http://www.airs.com/blog/archives/189.
486
487    //    Extract:
488    //       Note that the current dynamic linker code will only work
489    //       correctly if the PT_GNU_RELRO segment starts on a page
490    //       boundary. This is because the dynamic linker rounds the
491    //       p_vaddr field down to the previous page boundary. If
492    //       there is anything on the page which should not be read-only,
493    //       the program is likely to fail at runtime. So in effect the
494    //       linker must only emit a PT_GNU_RELRO segment if it ensures
495    //       that it starts on a page boundary.
496    ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
497    ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
498
499    int ret = mprotect(reinterpret_cast<void*>(seg_page_start),
500                       seg_page_end - seg_page_start,
501                       prot_flags);
502    if (ret < 0) {
503      return -1;
504    }
505  }
506  return 0;
507}
508
509/* Apply GNU relro protection if specified by the program header. This will
510 * turn some of the pages of a writable PT_LOAD segment to read-only, as
511 * specified by one or more PT_GNU_RELRO segments. This must be always
512 * performed after relocations.
513 *
514 * The areas typically covered are .got and .data.rel.ro, these are
515 * read-only from the program's POV, but contain absolute addresses
516 * that need to be relocated before use.
517 *
518 * Input:
519 *   phdr_table  -> program header table
520 *   phdr_count  -> number of entries in tables
521 *   load_bias   -> load bias
522 * Return:
523 *   0 on error, -1 on failure (error code in errno).
524 */
525int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias) {
526  return _phdr_table_set_gnu_relro_prot(phdr_table, phdr_count, load_bias, PROT_READ);
527}
528
529/* Serialize the GNU relro segments to the given file descriptor. This can be
530 * performed after relocations to allow another process to later share the
531 * relocated segment, if it was loaded at the same address.
532 *
533 * Input:
534 *   phdr_table  -> program header table
535 *   phdr_count  -> number of entries in tables
536 *   load_bias   -> load bias
537 *   fd          -> writable file descriptor to use
538 * Return:
539 *   0 on error, -1 on failure (error code in errno).
540 */
541int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
542                                   int fd) {
543  const ElfW(Phdr)* phdr = phdr_table;
544  const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
545  ssize_t file_offset = 0;
546
547  for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
548    if (phdr->p_type != PT_GNU_RELRO) {
549      continue;
550    }
551
552    ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
553    ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
554    ssize_t size = seg_page_end - seg_page_start;
555
556    ssize_t written = TEMP_FAILURE_RETRY(write(fd, reinterpret_cast<void*>(seg_page_start), size));
557    if (written != size) {
558      return -1;
559    }
560    void* map = mmap(reinterpret_cast<void*>(seg_page_start), size, PROT_READ,
561                     MAP_PRIVATE|MAP_FIXED, fd, file_offset);
562    if (map == MAP_FAILED) {
563      return -1;
564    }
565    file_offset += size;
566  }
567  return 0;
568}
569
570/* Where possible, replace the GNU relro segments with mappings of the given
571 * file descriptor. This can be performed after relocations to allow a file
572 * previously created by phdr_table_serialize_gnu_relro in another process to
573 * replace the dirty relocated pages, saving memory, if it was loaded at the
574 * same address. We have to compare the data before we map over it, since some
575 * parts of the relro segment may not be identical due to other libraries in
576 * the process being loaded at different addresses.
577 *
578 * Input:
579 *   phdr_table  -> program header table
580 *   phdr_count  -> number of entries in tables
581 *   load_bias   -> load bias
582 *   fd          -> readable file descriptor to use
583 * Return:
584 *   0 on error, -1 on failure (error code in errno).
585 */
586int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
587                             int fd) {
588  // Map the file at a temporary location so we can compare its contents.
589  struct stat file_stat;
590  if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) {
591    return -1;
592  }
593  off_t file_size = file_stat.st_size;
594  void* temp_mapping = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
595  if (temp_mapping == MAP_FAILED) {
596    return -1;
597  }
598  size_t file_offset = 0;
599
600  // Iterate over the relro segments and compare/remap the pages.
601  const ElfW(Phdr)* phdr = phdr_table;
602  const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
603
604  for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
605    if (phdr->p_type != PT_GNU_RELRO) {
606      continue;
607    }
608
609    ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
610    ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
611
612    char* file_base = static_cast<char*>(temp_mapping) + file_offset;
613    char* mem_base = reinterpret_cast<char*>(seg_page_start);
614    size_t match_offset = 0;
615    size_t size = seg_page_end - seg_page_start;
616
617    while (match_offset < size) {
618      // Skip over dissimilar pages.
619      while (match_offset < size &&
620             memcmp(mem_base + match_offset, file_base + match_offset, PAGE_SIZE) != 0) {
621        match_offset += PAGE_SIZE;
622      }
623
624      // Count similar pages.
625      size_t mismatch_offset = match_offset;
626      while (mismatch_offset < size &&
627             memcmp(mem_base + mismatch_offset, file_base + mismatch_offset, PAGE_SIZE) == 0) {
628        mismatch_offset += PAGE_SIZE;
629      }
630
631      // Map over similar pages.
632      if (mismatch_offset > match_offset) {
633        void* map = mmap(mem_base + match_offset, mismatch_offset - match_offset,
634                         PROT_READ, MAP_PRIVATE|MAP_FIXED, fd, match_offset);
635        if (map == MAP_FAILED) {
636          munmap(temp_mapping, file_size);
637          return -1;
638        }
639      }
640
641      match_offset = mismatch_offset;
642    }
643
644    // Add to the base file offset in case there are multiple relro segments.
645    file_offset += size;
646  }
647  munmap(temp_mapping, file_size);
648  return 0;
649}
650
651
652#if defined(__arm__)
653
654#  ifndef PT_ARM_EXIDX
655#    define PT_ARM_EXIDX    0x70000001      /* .ARM.exidx segment */
656#  endif
657
658/* Return the address and size of the .ARM.exidx section in memory,
659 * if present.
660 *
661 * Input:
662 *   phdr_table  -> program header table
663 *   phdr_count  -> number of entries in tables
664 *   load_bias   -> load bias
665 * Output:
666 *   arm_exidx       -> address of table in memory (NULL on failure).
667 *   arm_exidx_count -> number of items in table (0 on failure).
668 * Return:
669 *   0 on error, -1 on failure (_no_ error code in errno)
670 */
671int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count,
672                             ElfW(Addr) load_bias,
673                             ElfW(Addr)** arm_exidx, unsigned* arm_exidx_count) {
674  const ElfW(Phdr)* phdr = phdr_table;
675  const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
676
677  for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
678    if (phdr->p_type != PT_ARM_EXIDX) {
679      continue;
680    }
681
682    *arm_exidx = reinterpret_cast<ElfW(Addr)*>(load_bias + phdr->p_vaddr);
683    *arm_exidx_count = (unsigned)(phdr->p_memsz / 8);
684    return 0;
685  }
686  *arm_exidx = NULL;
687  *arm_exidx_count = 0;
688  return -1;
689}
690#endif
691
692/* Return the address and size of the ELF file's .dynamic section in memory,
693 * or NULL if missing.
694 *
695 * Input:
696 *   phdr_table  -> program header table
697 *   phdr_count  -> number of entries in tables
698 *   load_bias   -> load bias
699 * Output:
700 *   dynamic       -> address of table in memory (NULL on failure).
701 *   dynamic_count -> number of items in table (0 on failure).
702 *   dynamic_flags -> protection flags for section (unset on failure)
703 * Return:
704 *   void
705 */
706void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count,
707                                    ElfW(Addr) load_bias,
708                                    ElfW(Dyn)** dynamic, size_t* dynamic_count, ElfW(Word)* dynamic_flags) {
709  const ElfW(Phdr)* phdr = phdr_table;
710  const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
711
712  for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
713    if (phdr->p_type != PT_DYNAMIC) {
714      continue;
715    }
716
717    *dynamic = reinterpret_cast<ElfW(Dyn)*>(load_bias + phdr->p_vaddr);
718    if (dynamic_count) {
719      *dynamic_count = (unsigned)(phdr->p_memsz / 8);
720    }
721    if (dynamic_flags) {
722      *dynamic_flags = phdr->p_flags;
723    }
724    return;
725  }
726  *dynamic = NULL;
727  if (dynamic_count) {
728    *dynamic_count = 0;
729  }
730}
731
732// Returns the address of the program header table as it appears in the loaded
733// segments in memory. This is in contrast with 'phdr_table_' which
734// is temporary and will be released before the library is relocated.
735bool ElfReader::FindPhdr() {
736  const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
737
738  // If there is a PT_PHDR, use it directly.
739  for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
740    if (phdr->p_type == PT_PHDR) {
741      return CheckPhdr(load_bias_ + phdr->p_vaddr);
742    }
743  }
744
745  // Otherwise, check the first loadable segment. If its file offset
746  // is 0, it starts with the ELF header, and we can trivially find the
747  // loaded program header from it.
748  for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
749    if (phdr->p_type == PT_LOAD) {
750      if (phdr->p_offset == 0) {
751        ElfW(Addr)  elf_addr = load_bias_ + phdr->p_vaddr;
752        const ElfW(Ehdr)* ehdr = reinterpret_cast<const ElfW(Ehdr)*>(elf_addr);
753        ElfW(Addr)  offset = ehdr->e_phoff;
754        return CheckPhdr((ElfW(Addr))ehdr + offset);
755      }
756      break;
757    }
758  }
759
760  DL_ERR("can't find loaded phdr for \"%s\"", name_);
761  return false;
762}
763
764// Ensures that our program header is actually within a loadable
765// segment. This should help catch badly-formed ELF files that
766// would cause the linker to crash later when trying to access it.
767bool ElfReader::CheckPhdr(ElfW(Addr) loaded) {
768  const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
769  ElfW(Addr) loaded_end = loaded + (phdr_num_ * sizeof(ElfW(Phdr)));
770  for (ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
771    if (phdr->p_type != PT_LOAD) {
772      continue;
773    }
774    ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
775    ElfW(Addr) seg_end = phdr->p_filesz + seg_start;
776    if (seg_start <= loaded && loaded_end <= seg_end) {
777      loaded_phdr_ = reinterpret_cast<const ElfW(Phdr)*>(loaded);
778      return true;
779    }
780  }
781  DL_ERR("\"%s\" loaded phdr %p not in loadable segment", name_, reinterpret_cast<void*>(loaded));
782  return false;
783}
784