1 /* |
1 /* |
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
696 return false; |
696 return false; |
697 } |
697 } |
698 |
698 |
699 // read segments of a shared object |
699 // read segments of a shared object |
700 static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* lib_ehdr, uintptr_t lib_base) { |
700 static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* lib_ehdr, uintptr_t lib_base) { |
701 int i = 0; |
701 int i = 0; |
702 ELF_PHDR* phbuf; |
702 ELF_PHDR* phbuf; |
703 ELF_PHDR* lib_php = NULL; |
703 ELF_PHDR* lib_php = NULL; |
704 |
704 |
705 if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) |
705 int page_size=sysconf(_SC_PAGE_SIZE); |
706 return false; |
706 |
707 |
707 if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) { |
708 // we want to process only PT_LOAD segments that are not writable. |
708 return false; |
709 // i.e., text segments. The read/write/exec (data) segments would |
709 } |
710 // have been already added from core file segments. |
710 |
711 for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) { |
711 // we want to process only PT_LOAD segments that are not writable. |
712 if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) { |
712 // i.e., text segments. The read/write/exec (data) segments would |
713 if (add_map_info(ph, lib_fd, lib_php->p_offset, lib_php->p_vaddr + lib_base, lib_php->p_filesz) == NULL) |
713 // have been already added from core file segments. |
714 goto err; |
714 for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) { |
715 } |
715 if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) { |
716 lib_php++; |
716 |
717 } |
717 uintptr_t target_vaddr = lib_php->p_vaddr + lib_base; |
718 |
718 map_info *existing_map = core_lookup(ph, target_vaddr); |
719 free(phbuf); |
719 |
720 return true; |
720 if (existing_map == NULL){ |
|
721 if (add_map_info(ph, lib_fd, lib_php->p_offset, |
|
722 target_vaddr, lib_php->p_filesz) == NULL) { |
|
723 goto err; |
|
724 } |
|
725 } else { |
|
726 if ((existing_map->memsz != page_size) && |
|
727 (existing_map->fd != lib_fd) && |
|
728 (existing_map->memsz != lib_php->p_filesz)){ |
|
729 |
|
730 print_debug("address conflict @ 0x%lx (size = %ld, flags = %d\n)", |
|
731 target_vaddr, lib_php->p_filesz, lib_php->p_flags); |
|
732 goto err; |
|
733 } |
|
734 |
|
735 /* replace PT_LOAD segment with library segment */ |
|
736 print_debug("overwrote with new address mapping (memsz %ld -> %ld)\n", |
|
737 existing_map->memsz, lib_php->p_filesz); |
|
738 |
|
739 existing_map->fd = lib_fd; |
|
740 existing_map->offset = lib_php->p_offset; |
|
741 existing_map->memsz = lib_php->p_filesz; |
|
742 } |
|
743 } |
|
744 |
|
745 lib_php++; |
|
746 } |
|
747 |
|
748 free(phbuf); |
|
749 return true; |
721 err: |
750 err: |
722 free(phbuf); |
751 free(phbuf); |
723 return false; |
752 return false; |
724 } |
753 } |
725 |
754 |
726 // process segments from interpreter (ld.so or ld-linux.so) |
755 // process segments from interpreter (ld.so or ld-linux.so) |
727 static bool read_interp_segments(struct ps_prochandle* ph) { |
756 static bool read_interp_segments(struct ps_prochandle* ph) { |
728 ELF_EHDR interp_ehdr; |
757 ELF_EHDR interp_ehdr; |