]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/platform-bionic.git/blob - linker/linker_phdr.cpp
Load library using file handle.
[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 (phdr_mmap_ != NULL) {
131     munmap(phdr_mmap_, phdr_size_);
132   }
135 bool ElfReader::Load(const android_dlextinfo* extinfo) {
136   return ReadElfHeader() &&
137          VerifyElfHeader() &&
138          ReadProgramHeader() &&
139          ReserveAddressSpace(extinfo) &&
140          LoadSegments() &&
141          FindPhdr();
144 bool ElfReader::ReadElfHeader() {
145   ssize_t rc = TEMP_FAILURE_RETRY(read(fd_, &header_, sizeof(header_)));
146   if (rc < 0) {
147     DL_ERR("can't read file \"%s\": %s", name_, strerror(errno));
148     return false;
149   }
150   if (rc != sizeof(header_)) {
151     DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_,
152            static_cast<size_t>(rc));
153     return false;
154   }
155   return true;
158 bool ElfReader::VerifyElfHeader() {
159   if (header_.e_ident[EI_MAG0] != ELFMAG0 ||
160       header_.e_ident[EI_MAG1] != ELFMAG1 ||
161       header_.e_ident[EI_MAG2] != ELFMAG2 ||
162       header_.e_ident[EI_MAG3] != ELFMAG3) {
163     DL_ERR("\"%s\" has bad ELF magic", name_);
164     return false;
165   }
167   // Try to give a clear diagnostic for ELF class mismatches, since they're
168   // an easy mistake to make during the 32-bit/64-bit transition period.
169   int elf_class = header_.e_ident[EI_CLASS];
170 #if defined(__LP64__)
171   if (elf_class != ELFCLASS64) {
172     if (elf_class == ELFCLASS32) {
173       DL_ERR("\"%s\" is 32-bit instead of 64-bit", name_);
174     } else {
175       DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class);
176     }
177     return false;
178   }
179 #else
180   if (elf_class != ELFCLASS32) {
181     if (elf_class == ELFCLASS64) {
182       DL_ERR("\"%s\" is 64-bit instead of 32-bit", name_);
183     } else {
184       DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class);
185     }
186     return false;
187   }
188 #endif
190   if (header_.e_ident[EI_DATA] != ELFDATA2LSB) {
191     DL_ERR("\"%s\" not little-endian: %d", name_, header_.e_ident[EI_DATA]);
192     return false;
193   }
195   if (header_.e_type != ET_DYN) {
196     DL_ERR("\"%s\" has unexpected e_type: %d", name_, header_.e_type);
197     return false;
198   }
200   if (header_.e_version != EV_CURRENT) {
201     DL_ERR("\"%s\" has unexpected e_version: %d", name_, header_.e_version);
202     return false;
203   }
205   if (header_.e_machine != ELF_TARG_MACH) {
206     DL_ERR("\"%s\" has unexpected e_machine: %d", name_, header_.e_machine);
207     return false;
208   }
210   return true;
213 // Loads the program header table from an ELF file into a read-only private
214 // anonymous mmap-ed block.
215 bool ElfReader::ReadProgramHeader() {
216   phdr_num_ = header_.e_phnum;
218   // Like the kernel, we only accept program header tables that
219   // are smaller than 64KiB.
220   if (phdr_num_ < 1 || phdr_num_ > 65536/sizeof(ElfW(Phdr))) {
221     DL_ERR("\"%s\" has invalid e_phnum: %zd", name_, phdr_num_);
222     return false;
223   }
225   ElfW(Addr) page_min = PAGE_START(header_.e_phoff);
226   ElfW(Addr) page_max = PAGE_END(header_.e_phoff + (phdr_num_ * sizeof(ElfW(Phdr))));
227   ElfW(Addr) page_offset = PAGE_OFFSET(header_.e_phoff);
229   phdr_size_ = page_max - page_min;
231   void* mmap_result = mmap(NULL, phdr_size_, PROT_READ, MAP_PRIVATE, fd_, page_min);
232   if (mmap_result == MAP_FAILED) {
233     DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
234     return false;
235   }
237   phdr_mmap_ = mmap_result;
238   phdr_table_ = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<char*>(mmap_result) + page_offset);
239   return true;
242 /* Returns the size of the extent of all the possibly non-contiguous
243  * loadable segments in an ELF program header table. This corresponds
244  * to the page-aligned size in bytes that needs to be reserved in the
245  * process' address space. If there are no loadable segments, 0 is
246  * returned.
247  *
248  * If out_min_vaddr or out_max_vaddr are non-NULL, they will be
249  * set to the minimum and maximum addresses of pages to be reserved,
250  * or 0 if there is nothing to load.
251  */
252 size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
253                                 ElfW(Addr)* out_min_vaddr,
254                                 ElfW(Addr)* out_max_vaddr) {
255   ElfW(Addr) min_vaddr = UINTPTR_MAX;
256   ElfW(Addr) max_vaddr = 0;
258   bool found_pt_load = false;
259   for (size_t i = 0; i < phdr_count; ++i) {
260     const ElfW(Phdr)* phdr = &phdr_table[i];
262     if (phdr->p_type != PT_LOAD) {
263       continue;
264     }
265     found_pt_load = true;
267     if (phdr->p_vaddr < min_vaddr) {
268       min_vaddr = phdr->p_vaddr;
269     }
271     if (phdr->p_vaddr + phdr->p_memsz > max_vaddr) {
272       max_vaddr = phdr->p_vaddr + phdr->p_memsz;
273     }
274   }
275   if (!found_pt_load) {
276     min_vaddr = 0;
277   }
279   min_vaddr = PAGE_START(min_vaddr);
280   max_vaddr = PAGE_END(max_vaddr);
282   if (out_min_vaddr != NULL) {
283     *out_min_vaddr = min_vaddr;
284   }
285   if (out_max_vaddr != NULL) {
286     *out_max_vaddr = max_vaddr;
287   }
288   return max_vaddr - min_vaddr;
291 // Reserve a virtual address range big enough to hold all loadable
292 // segments of a program header table. This is done by creating a
293 // private anonymous mmap() with PROT_NONE.
294 bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) {
295   ElfW(Addr) min_vaddr;
296   load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr);
297   if (load_size_ == 0) {
298     DL_ERR("\"%s\" has no loadable segments", name_);
299     return false;
300   }
302   uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
303   void* start;
304   size_t reserved_size = 0;
305   bool reserved_hint = true;
307   if (extinfo != NULL) {
308     if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
309       reserved_size = extinfo->reserved_size;
310       reserved_hint = false;
311     } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) {
312       reserved_size = extinfo->reserved_size;
313     }
314   }
316   if (load_size_ > reserved_size) {
317     if (!reserved_hint) {
318       DL_ERR("reserved address space %zd smaller than %zd bytes needed for \"%s\"",
319              reserved_size - load_size_, load_size_, name_);
320       return false;
321     }
322     int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
323     start = mmap(addr, load_size_, PROT_NONE, mmap_flags, -1, 0);
324     if (start == MAP_FAILED) {
325       DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_);
326       return false;
327     }
328   } else {
329     start = extinfo->reserved_addr;
330   }
332   load_start_ = start;
333   load_bias_ = reinterpret_cast<uint8_t*>(start) - addr;
334   return true;
337 bool ElfReader::LoadSegments() {
338   for (size_t i = 0; i < phdr_num_; ++i) {
339     const ElfW(Phdr)* phdr = &phdr_table_[i];
341     if (phdr->p_type != PT_LOAD) {
342       continue;
343     }
345     // Segment addresses in memory.
346     ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
347     ElfW(Addr) seg_end   = seg_start + phdr->p_memsz;
349     ElfW(Addr) seg_page_start = PAGE_START(seg_start);
350     ElfW(Addr) seg_page_end   = PAGE_END(seg_end);
352     ElfW(Addr) seg_file_end   = seg_start + phdr->p_filesz;
354     // File offsets.
355     ElfW(Addr) file_start = phdr->p_offset;
356     ElfW(Addr) file_end   = file_start + phdr->p_filesz;
358     ElfW(Addr) file_page_start = PAGE_START(file_start);
359     ElfW(Addr) file_length = file_end - file_page_start;
361     if (file_length != 0) {
362       void* seg_addr = mmap(reinterpret_cast<void*>(seg_page_start),
363                             file_length,
364                             PFLAGS_TO_PROT(phdr->p_flags),
365                             MAP_FIXED|MAP_PRIVATE,
366                             fd_,
367                             file_page_start);
368       if (seg_addr == MAP_FAILED) {
369         DL_ERR("couldn't map \"%s\" segment %zd: %s", name_, i, strerror(errno));
370         return false;
371       }
372     }
374     // if the segment is writable, and does not end on a page boundary,
375     // zero-fill it until the page limit.
376     if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) {
377       memset(reinterpret_cast<void*>(seg_file_end), 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end));
378     }
380     seg_file_end = PAGE_END(seg_file_end);
382     // seg_file_end is now the first page address after the file
383     // content. If seg_end is larger, we need to zero anything
384     // between them. This is done by using a private anonymous
385     // map for all extra pages.
386     if (seg_page_end > seg_file_end) {
387       void* zeromap = mmap(reinterpret_cast<void*>(seg_file_end),
388                            seg_page_end - seg_file_end,
389                            PFLAGS_TO_PROT(phdr->p_flags),
390                            MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE,
391                            -1,
392                            0);
393       if (zeromap == MAP_FAILED) {
394         DL_ERR("couldn't zero fill \"%s\" gap: %s", name_, strerror(errno));
395         return false;
396       }
397     }
398   }
399   return true;
402 /* Used internally. Used to set the protection bits of all loaded segments
403  * with optional extra flags (i.e. really PROT_WRITE). Used by
404  * phdr_table_protect_segments and phdr_table_unprotect_segments.
405  */
406 static int _phdr_table_set_load_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count,
407                                      ElfW(Addr) load_bias, int extra_prot_flags) {
408   const ElfW(Phdr)* phdr = phdr_table;
409   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
411   for (; phdr < phdr_limit; phdr++) {
412     if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) {
413       continue;
414     }
416     ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
417     ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
419     int ret = mprotect(reinterpret_cast<void*>(seg_page_start),
420                        seg_page_end - seg_page_start,
421                        PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags);
422     if (ret < 0) {
423       return -1;
424     }
425   }
426   return 0;
429 /* Restore the original protection modes for all loadable segments.
430  * You should only call this after phdr_table_unprotect_segments and
431  * applying all relocations.
432  *
433  * Input:
434  *   phdr_table  -> program header table
435  *   phdr_count  -> number of entries in tables
436  *   load_bias   -> load bias
437  * Return:
438  *   0 on error, -1 on failure (error code in errno).
439  */
440 int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias) {
441   return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, 0);
444 /* Change the protection of all loaded segments in memory to writable.
445  * This is useful before performing relocations. Once completed, you
446  * will have to call phdr_table_protect_segments to restore the original
447  * protection flags on all segments.
448  *
449  * Note that some writable segments can also have their content turned
450  * to read-only by calling phdr_table_protect_gnu_relro. This is no
451  * performed here.
452  *
453  * Input:
454  *   phdr_table  -> program header table
455  *   phdr_count  -> number of entries in tables
456  *   load_bias   -> load bias
457  * Return:
458  *   0 on error, -1 on failure (error code in errno).
459  */
460 int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias) {
461   return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, PROT_WRITE);
464 /* Used internally by phdr_table_protect_gnu_relro and
465  * phdr_table_unprotect_gnu_relro.
466  */
467 static int _phdr_table_set_gnu_relro_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count,
468                                           ElfW(Addr) load_bias, int prot_flags) {
469   const ElfW(Phdr)* phdr = phdr_table;
470   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
472   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
473     if (phdr->p_type != PT_GNU_RELRO) {
474       continue;
475     }
477     // Tricky: what happens when the relro segment does not start
478     // or end at page boundaries? We're going to be over-protective
479     // here and put every page touched by the segment as read-only.
481     // This seems to match Ian Lance Taylor's description of the
482     // feature at http://www.airs.com/blog/archives/189.
484     //    Extract:
485     //       Note that the current dynamic linker code will only work
486     //       correctly if the PT_GNU_RELRO segment starts on a page
487     //       boundary. This is because the dynamic linker rounds the
488     //       p_vaddr field down to the previous page boundary. If
489     //       there is anything on the page which should not be read-only,
490     //       the program is likely to fail at runtime. So in effect the
491     //       linker must only emit a PT_GNU_RELRO segment if it ensures
492     //       that it starts on a page boundary.
493     ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
494     ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
496     int ret = mprotect(reinterpret_cast<void*>(seg_page_start),
497                        seg_page_end - seg_page_start,
498                        prot_flags);
499     if (ret < 0) {
500       return -1;
501     }
502   }
503   return 0;
506 /* Apply GNU relro protection if specified by the program header. This will
507  * turn some of the pages of a writable PT_LOAD segment to read-only, as
508  * specified by one or more PT_GNU_RELRO segments. This must be always
509  * performed after relocations.
510  *
511  * The areas typically covered are .got and .data.rel.ro, these are
512  * read-only from the program's POV, but contain absolute addresses
513  * that need to be relocated before use.
514  *
515  * Input:
516  *   phdr_table  -> program header table
517  *   phdr_count  -> number of entries in tables
518  *   load_bias   -> load bias
519  * Return:
520  *   0 on error, -1 on failure (error code in errno).
521  */
522 int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias) {
523   return _phdr_table_set_gnu_relro_prot(phdr_table, phdr_count, load_bias, PROT_READ);
526 /* Serialize the GNU relro segments to the given file descriptor. This can be
527  * performed after relocations to allow another process to later share the
528  * relocated segment, if it was loaded at the same address.
529  *
530  * Input:
531  *   phdr_table  -> program header table
532  *   phdr_count  -> number of entries in tables
533  *   load_bias   -> load bias
534  *   fd          -> writable file descriptor to use
535  * Return:
536  *   0 on error, -1 on failure (error code in errno).
537  */
538 int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
539                                    int fd) {
540   const ElfW(Phdr)* phdr = phdr_table;
541   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
542   ssize_t file_offset = 0;
544   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
545     if (phdr->p_type != PT_GNU_RELRO) {
546       continue;
547     }
549     ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
550     ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
551     ssize_t size = seg_page_end - seg_page_start;
553     ssize_t written = TEMP_FAILURE_RETRY(write(fd, reinterpret_cast<void*>(seg_page_start), size));
554     if (written != size) {
555       return -1;
556     }
557     void* map = mmap(reinterpret_cast<void*>(seg_page_start), size, PROT_READ,
558                      MAP_PRIVATE|MAP_FIXED, fd, file_offset);
559     if (map == MAP_FAILED) {
560       return -1;
561     }
562     file_offset += size;
563   }
564   return 0;
567 /* Where possible, replace the GNU relro segments with mappings of the given
568  * file descriptor. This can be performed after relocations to allow a file
569  * previously created by phdr_table_serialize_gnu_relro in another process to
570  * replace the dirty relocated pages, saving memory, if it was loaded at the
571  * same address. We have to compare the data before we map over it, since some
572  * parts of the relro segment may not be identical due to other libraries in
573  * the process being loaded at different addresses.
574  *
575  * Input:
576  *   phdr_table  -> program header table
577  *   phdr_count  -> number of entries in tables
578  *   load_bias   -> load bias
579  *   fd          -> readable file descriptor to use
580  * Return:
581  *   0 on error, -1 on failure (error code in errno).
582  */
583 int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
584                              int fd) {
585   // Map the file at a temporary location so we can compare its contents.
586   struct stat file_stat;
587   if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) {
588     return -1;
589   }
590   off_t file_size = file_stat.st_size;
591   void* temp_mapping = NULL;
592   if (file_size > 0) {
593     temp_mapping = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
594     if (temp_mapping == MAP_FAILED) {
595       return -1;
596     }
597   }
598   size_t file_offset = 0;
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;
604   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
605     if (phdr->p_type != PT_GNU_RELRO) {
606       continue;
607     }
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;
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;
617     if (file_size - file_offset < size) {
618       // File is too short to compare to this segment. The contents are likely
619       // different as well (it's probably for a different library version) so
620       // just don't bother checking.
621       break;
622     }
624     while (match_offset < size) {
625       // Skip over dissimilar pages.
626       while (match_offset < size &&
627              memcmp(mem_base + match_offset, file_base + match_offset, PAGE_SIZE) != 0) {
628         match_offset += PAGE_SIZE;
629       }
631       // Count similar pages.
632       size_t mismatch_offset = match_offset;
633       while (mismatch_offset < size &&
634              memcmp(mem_base + mismatch_offset, file_base + mismatch_offset, PAGE_SIZE) == 0) {
635         mismatch_offset += PAGE_SIZE;
636       }
638       // Map over similar pages.
639       if (mismatch_offset > match_offset) {
640         void* map = mmap(mem_base + match_offset, mismatch_offset - match_offset,
641                          PROT_READ, MAP_PRIVATE|MAP_FIXED, fd, match_offset);
642         if (map == MAP_FAILED) {
643           munmap(temp_mapping, file_size);
644           return -1;
645         }
646       }
648       match_offset = mismatch_offset;
649     }
651     // Add to the base file offset in case there are multiple relro segments.
652     file_offset += size;
653   }
654   munmap(temp_mapping, file_size);
655   return 0;
659 #if defined(__arm__)
661 #  ifndef PT_ARM_EXIDX
662 #    define PT_ARM_EXIDX    0x70000001      /* .ARM.exidx segment */
663 #  endif
665 /* Return the address and size of the .ARM.exidx section in memory,
666  * if present.
667  *
668  * Input:
669  *   phdr_table  -> program header table
670  *   phdr_count  -> number of entries in tables
671  *   load_bias   -> load bias
672  * Output:
673  *   arm_exidx       -> address of table in memory (NULL on failure).
674  *   arm_exidx_count -> number of items in table (0 on failure).
675  * Return:
676  *   0 on error, -1 on failure (_no_ error code in errno)
677  */
678 int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count,
679                              ElfW(Addr) load_bias,
680                              ElfW(Addr)** arm_exidx, unsigned* arm_exidx_count) {
681   const ElfW(Phdr)* phdr = phdr_table;
682   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
684   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
685     if (phdr->p_type != PT_ARM_EXIDX) {
686       continue;
687     }
689     *arm_exidx = reinterpret_cast<ElfW(Addr)*>(load_bias + phdr->p_vaddr);
690     *arm_exidx_count = (unsigned)(phdr->p_memsz / 8);
691     return 0;
692   }
693   *arm_exidx = NULL;
694   *arm_exidx_count = 0;
695   return -1;
697 #endif
699 /* Return the address and size of the ELF file's .dynamic section in memory,
700  * or NULL if missing.
701  *
702  * Input:
703  *   phdr_table  -> program header table
704  *   phdr_count  -> number of entries in tables
705  *   load_bias   -> load bias
706  * Output:
707  *   dynamic       -> address of table in memory (NULL on failure).
708  *   dynamic_count -> number of items in table (0 on failure).
709  *   dynamic_flags -> protection flags for section (unset on failure)
710  * Return:
711  *   void
712  */
713 void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count,
714                                     ElfW(Addr) load_bias,
715                                     ElfW(Dyn)** dynamic, size_t* dynamic_count, ElfW(Word)* dynamic_flags) {
716   const ElfW(Phdr)* phdr = phdr_table;
717   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
719   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
720     if (phdr->p_type != PT_DYNAMIC) {
721       continue;
722     }
724     *dynamic = reinterpret_cast<ElfW(Dyn)*>(load_bias + phdr->p_vaddr);
725     if (dynamic_count) {
726       *dynamic_count = (unsigned)(phdr->p_memsz / 8);
727     }
728     if (dynamic_flags) {
729       *dynamic_flags = phdr->p_flags;
730     }
731     return;
732   }
733   *dynamic = NULL;
734   if (dynamic_count) {
735     *dynamic_count = 0;
736   }
739 // Returns the address of the program header table as it appears in the loaded
740 // segments in memory. This is in contrast with 'phdr_table_' which
741 // is temporary and will be released before the library is relocated.
742 bool ElfReader::FindPhdr() {
743   const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
745   // If there is a PT_PHDR, use it directly.
746   for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
747     if (phdr->p_type == PT_PHDR) {
748       return CheckPhdr(load_bias_ + phdr->p_vaddr);
749     }
750   }
752   // Otherwise, check the first loadable segment. If its file offset
753   // is 0, it starts with the ELF header, and we can trivially find the
754   // loaded program header from it.
755   for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
756     if (phdr->p_type == PT_LOAD) {
757       if (phdr->p_offset == 0) {
758         ElfW(Addr)  elf_addr = load_bias_ + phdr->p_vaddr;
759         const ElfW(Ehdr)* ehdr = reinterpret_cast<const ElfW(Ehdr)*>(elf_addr);
760         ElfW(Addr)  offset = ehdr->e_phoff;
761         return CheckPhdr((ElfW(Addr))ehdr + offset);
762       }
763       break;
764     }
765   }
767   DL_ERR("can't find loaded phdr for \"%s\"", name_);
768   return false;
771 // Ensures that our program header is actually within a loadable
772 // segment. This should help catch badly-formed ELF files that
773 // would cause the linker to crash later when trying to access it.
774 bool ElfReader::CheckPhdr(ElfW(Addr) loaded) {
775   const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
776   ElfW(Addr) loaded_end = loaded + (phdr_num_ * sizeof(ElfW(Phdr)));
777   for (ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
778     if (phdr->p_type != PT_LOAD) {
779       continue;
780     }
781     ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
782     ElfW(Addr) seg_end = phdr->p_filesz + seg_start;
783     if (seg_start <= loaded && loaded_end <= seg_end) {
784       loaded_phdr_ = reinterpret_cast<const ElfW(Phdr)*>(loaded);
785       return true;
786     }
787   }
788   DL_ERR("\"%s\" loaded phdr %p not in loadable segment", name_, reinterpret_cast<void*>(loaded));
789   return false;