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) {
127 }
129 ElfReader::~ElfReader() {
130 if (phdr_mmap_ != NULL) {
131 munmap(phdr_mmap_, phdr_size_);
132 }
133 }
135 bool ElfReader::Load(const android_dlextinfo* extinfo) {
136 return ReadElfHeader() &&
137 VerifyElfHeader() &&
138 ReadProgramHeader() &&
139 ReserveAddressSpace(extinfo) &&
140 LoadSegments() &&
141 FindPhdr();
142 }
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;
156 }
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;
211 }
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;
240 }
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;
289 }
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;
335 }
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;
400 }
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;
427 }
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);
442 }
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);
462 }
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;
504 }
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);
524 }
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;
565 }
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;
656 }
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;
696 }
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 }
737 }
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;
769 }
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;
790 }