]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/platform-bionic.git/blob - linker/linker_phdr.cpp
Merge "Reserve space for the future in statvfs(64)"
[android-sdk/platform-bionic.git] / linker / linker_phdr.cpp
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  */
29 #include "linker_phdr.h"
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>
38 #include "linker.h"
39 #include "linker_debug.h"
41 /**
42   TECHNICAL NOTE ON ELF LOADING.
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.
48   Each loadable segment has the following important properties:
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)
56   We will ignore the p_paddr and p_align fields of ElfW(Phdr) for now.
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:
61   - the virtual address ranges should not overlap.
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.
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.
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.
74   For example, consider the following list:
76     [ offset:0,      filesz:0x4000, memsz:0x4000, vaddr:0x30000 ],
77     [ offset:0x4000, filesz:0x2000, memsz:0x8000, vaddr:0x40000 ],
79   This corresponds to two segments that cover these virtual address ranges:
81        0x30000...0x34000
82        0x40000...0x48000
84   If the loader decides to load the first segment at address 0xa0000000
85   then the segments' load address ranges will be:
87        0xa0030000...0xa0034000
88        0xa0040000...0xa0048000
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.
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:
98        load_bias = phdr0_load_address - PAGE_START(phdr0->p_vaddr)
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).
103   And that the phdr0_load_address must start at a page boundary, with
104   the segment's real content starting at:
106        phdr0_load_address + PAGE_OFFSET(phdr0->p_vaddr)
108   Note that ELF requires the following condition to make the mmap()-ing work:
110       PAGE_OFFSET(phdr0->p_vaddr) == PAGE_OFFSET(phdr0->p_offset)
112   The load_bias must be added to any p_vaddr value read from the ELF file to
113   determine the corresponding memory address.
115  **/
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))
122 ElfReader::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) {
129 ElfReader::~ElfReader() {
130   if (fd_ != -1) {
131     close(fd_);
132   }
133   if (phdr_mmap_ != NULL) {
134     munmap(phdr_mmap_, phdr_size_);
135   }
138 bool ElfReader::Load(const android_dlextinfo* extinfo) {
139   return ReadElfHeader() &&
140          VerifyElfHeader() &&
141          ReadProgramHeader() &&
142          ReserveAddressSpace(extinfo) &&
143          LoadSegments() &&
144          FindPhdr();
147 bool 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;
161 bool 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   }
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
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   }
198   if (header_.e_type != ET_DYN) {
199     DL_ERR("\"%s\" has unexpected e_type: %d", name_, header_.e_type);
200     return false;
201   }
203   if (header_.e_version != EV_CURRENT) {
204     DL_ERR("\"%s\" has unexpected e_version: %d", name_, header_.e_version);
205     return false;
206   }
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   }
213   return true;
216 // Loads the program header table from an ELF file into a read-only private
217 // anonymous mmap-ed block.
218 bool ElfReader::ReadProgramHeader() {
219   phdr_num_ = header_.e_phnum;
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   }
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);
232   phdr_size_ = page_max - page_min;
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   }
240   phdr_mmap_ = mmap_result;
241   phdr_table_ = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<char*>(mmap_result) + page_offset);
242   return true;
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  */
255 size_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;
261   bool found_pt_load = false;
262   for (size_t i = 0; i < phdr_count; ++i) {
263     const ElfW(Phdr)* phdr = &phdr_table[i];
265     if (phdr->p_type != PT_LOAD) {
266       continue;
267     }
268     found_pt_load = true;
270     if (phdr->p_vaddr < min_vaddr) {
271       min_vaddr = phdr->p_vaddr;
272     }
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   }
282   min_vaddr = PAGE_START(min_vaddr);
283   max_vaddr = PAGE_END(max_vaddr);
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;
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.
297 bool 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   }
305   uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
306   void* start;
307   size_t reserved_size = 0;
308   bool reserved_hint = true;
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   }
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   }
335   load_start_ = start;
336   load_bias_ = reinterpret_cast<uint8_t*>(start) - addr;
337   return true;
340 bool ElfReader::LoadSegments() {
341   for (size_t i = 0; i < phdr_num_; ++i) {
342     const ElfW(Phdr)* phdr = &phdr_table_[i];
344     if (phdr->p_type != PT_LOAD) {
345       continue;
346     }
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;
352     ElfW(Addr) seg_page_start = PAGE_START(seg_start);
353     ElfW(Addr) seg_page_end   = PAGE_END(seg_end);
355     ElfW(Addr) seg_file_end   = seg_start + phdr->p_filesz;
357     // File offsets.
358     ElfW(Addr) file_start = phdr->p_offset;
359     ElfW(Addr) file_end   = file_start + phdr->p_filesz;
361     ElfW(Addr) file_page_start = PAGE_START(file_start);
362     ElfW(Addr) file_length = file_end - file_page_start;
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     }
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     }
383     seg_file_end = PAGE_END(seg_file_end);
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;
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  */
409 static 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;
414   for (; phdr < phdr_limit; phdr++) {
415     if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) {
416       continue;
417     }
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;
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;
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  */
443 int 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);
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  */
463 int 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);
467 /* Used internally by phdr_table_protect_gnu_relro and
468  * phdr_table_unprotect_gnu_relro.
469  */
470 static 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;
475   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
476     if (phdr->p_type != PT_GNU_RELRO) {
477       continue;
478     }
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.
484     // This seems to match Ian Lance Taylor's description of the
485     // feature at http://www.airs.com/blog/archives/189.
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;
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;
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  */
525 int 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);
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  */
541 int 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;
547   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
548     if (phdr->p_type != PT_GNU_RELRO) {
549       continue;
550     }
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;
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;
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  */
586 int 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 = NULL;
595   if (file_size > 0) {
596     temp_mapping = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
597     if (temp_mapping == MAP_FAILED) {
598       return -1;
599     }
600   }
601   size_t file_offset = 0;
603   // Iterate over the relro segments and compare/remap the pages.
604   const ElfW(Phdr)* phdr = phdr_table;
605   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
607   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
608     if (phdr->p_type != PT_GNU_RELRO) {
609       continue;
610     }
612     ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
613     ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
615     char* file_base = static_cast<char*>(temp_mapping) + file_offset;
616     char* mem_base = reinterpret_cast<char*>(seg_page_start);
617     size_t match_offset = 0;
618     size_t size = seg_page_end - seg_page_start;
620     if (file_size - file_offset < size) {
621       // File is too short to compare to this segment. The contents are likely
622       // different as well (it's probably for a different library version) so
623       // just don't bother checking.
624       break;
625     }
627     while (match_offset < size) {
628       // Skip over dissimilar pages.
629       while (match_offset < size &&
630              memcmp(mem_base + match_offset, file_base + match_offset, PAGE_SIZE) != 0) {
631         match_offset += PAGE_SIZE;
632       }
634       // Count similar pages.
635       size_t mismatch_offset = match_offset;
636       while (mismatch_offset < size &&
637              memcmp(mem_base + mismatch_offset, file_base + mismatch_offset, PAGE_SIZE) == 0) {
638         mismatch_offset += PAGE_SIZE;
639       }
641       // Map over similar pages.
642       if (mismatch_offset > match_offset) {
643         void* map = mmap(mem_base + match_offset, mismatch_offset - match_offset,
644                          PROT_READ, MAP_PRIVATE|MAP_FIXED, fd, match_offset);
645         if (map == MAP_FAILED) {
646           munmap(temp_mapping, file_size);
647           return -1;
648         }
649       }
651       match_offset = mismatch_offset;
652     }
654     // Add to the base file offset in case there are multiple relro segments.
655     file_offset += size;
656   }
657   munmap(temp_mapping, file_size);
658   return 0;
662 #if defined(__arm__)
664 #  ifndef PT_ARM_EXIDX
665 #    define PT_ARM_EXIDX    0x70000001      /* .ARM.exidx segment */
666 #  endif
668 /* Return the address and size of the .ARM.exidx section in memory,
669  * if present.
670  *
671  * Input:
672  *   phdr_table  -> program header table
673  *   phdr_count  -> number of entries in tables
674  *   load_bias   -> load bias
675  * Output:
676  *   arm_exidx       -> address of table in memory (NULL on failure).
677  *   arm_exidx_count -> number of items in table (0 on failure).
678  * Return:
679  *   0 on error, -1 on failure (_no_ error code in errno)
680  */
681 int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count,
682                              ElfW(Addr) load_bias,
683                              ElfW(Addr)** arm_exidx, unsigned* arm_exidx_count) {
684   const ElfW(Phdr)* phdr = phdr_table;
685   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
687   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
688     if (phdr->p_type != PT_ARM_EXIDX) {
689       continue;
690     }
692     *arm_exidx = reinterpret_cast<ElfW(Addr)*>(load_bias + phdr->p_vaddr);
693     *arm_exidx_count = (unsigned)(phdr->p_memsz / 8);
694     return 0;
695   }
696   *arm_exidx = NULL;
697   *arm_exidx_count = 0;
698   return -1;
700 #endif
702 /* Return the address and size of the ELF file's .dynamic section in memory,
703  * or NULL if missing.
704  *
705  * Input:
706  *   phdr_table  -> program header table
707  *   phdr_count  -> number of entries in tables
708  *   load_bias   -> load bias
709  * Output:
710  *   dynamic       -> address of table in memory (NULL on failure).
711  *   dynamic_count -> number of items in table (0 on failure).
712  *   dynamic_flags -> protection flags for section (unset on failure)
713  * Return:
714  *   void
715  */
716 void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count,
717                                     ElfW(Addr) load_bias,
718                                     ElfW(Dyn)** dynamic, size_t* dynamic_count, ElfW(Word)* dynamic_flags) {
719   const ElfW(Phdr)* phdr = phdr_table;
720   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
722   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
723     if (phdr->p_type != PT_DYNAMIC) {
724       continue;
725     }
727     *dynamic = reinterpret_cast<ElfW(Dyn)*>(load_bias + phdr->p_vaddr);
728     if (dynamic_count) {
729       *dynamic_count = (unsigned)(phdr->p_memsz / 8);
730     }
731     if (dynamic_flags) {
732       *dynamic_flags = phdr->p_flags;
733     }
734     return;
735   }
736   *dynamic = NULL;
737   if (dynamic_count) {
738     *dynamic_count = 0;
739   }
742 // Returns the address of the program header table as it appears in the loaded
743 // segments in memory. This is in contrast with 'phdr_table_' which
744 // is temporary and will be released before the library is relocated.
745 bool ElfReader::FindPhdr() {
746   const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
748   // If there is a PT_PHDR, use it directly.
749   for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
750     if (phdr->p_type == PT_PHDR) {
751       return CheckPhdr(load_bias_ + phdr->p_vaddr);
752     }
753   }
755   // Otherwise, check the first loadable segment. If its file offset
756   // is 0, it starts with the ELF header, and we can trivially find the
757   // loaded program header from it.
758   for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
759     if (phdr->p_type == PT_LOAD) {
760       if (phdr->p_offset == 0) {
761         ElfW(Addr)  elf_addr = load_bias_ + phdr->p_vaddr;
762         const ElfW(Ehdr)* ehdr = reinterpret_cast<const ElfW(Ehdr)*>(elf_addr);
763         ElfW(Addr)  offset = ehdr->e_phoff;
764         return CheckPhdr((ElfW(Addr))ehdr + offset);
765       }
766       break;
767     }
768   }
770   DL_ERR("can't find loaded phdr for \"%s\"", name_);
771   return false;
774 // Ensures that our program header is actually within a loadable
775 // segment. This should help catch badly-formed ELF files that
776 // would cause the linker to crash later when trying to access it.
777 bool ElfReader::CheckPhdr(ElfW(Addr) loaded) {
778   const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
779   ElfW(Addr) loaded_end = loaded + (phdr_num_ * sizeof(ElfW(Phdr)));
780   for (ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
781     if (phdr->p_type != PT_LOAD) {
782       continue;
783     }
784     ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
785     ElfW(Addr) seg_end = phdr->p_filesz + seg_start;
786     if (seg_start <= loaded && loaded_end <= seg_end) {
787       loaded_phdr_ = reinterpret_cast<const ElfW(Phdr)*>(loaded);
788       return true;
789     }
790   }
791   DL_ERR("\"%s\" loaded phdr %p not in loadable segment", name_, reinterpret_cast<void*>(loaded));
792   return false;