1 /*
2 * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
86 }
87
88 // Part of the class sharing workaround
89 map = ph->core->class_share_maps;
90 while (map) {
91 map_info* next = map->next;
92 free(map);
93 map = next;
94 }
95 }
96
97 // ps_prochandle operations
98 static void core_release(struct ps_prochandle* ph) {
99 if (ph->core) {
100 close_files(ph);
101 destroy_map_info(ph);
102 free(ph->core);
103 }
104 }
105
106 static map_info* allocate_init_map(int fd, off_t offset, uintptr_t vaddr, size_t memsz) {
107 map_info* map;
108 if ( (map = (map_info*) calloc(1, sizeof(map_info))) == NULL) {
109 print_debug("can't allocate memory for map_info\n");
110 return NULL;
111 }
112
113 // initialize map
114 map->fd = fd;
115 map->offset = offset;
116 map->vaddr = vaddr;
117 map->memsz = memsz;
118 return map;
119 }
120
121 // add map info with given fd, offset, vaddr and memsz
122 static map_info* add_map_info(struct ps_prochandle* ph, int fd, off_t offset,
123 uintptr_t vaddr, size_t memsz) {
124 map_info* map;
125 if ((map = allocate_init_map(fd, offset, vaddr, memsz)) == NULL) {
126 return NULL;
127 }
128
129 // add this to map list
130 map->next = ph->core->maps;
131 ph->core->maps = map;
132 ph->core->num_maps++;
133
134 return map;
135 }
136
137 // Part of the class sharing workaround
138 static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset,
139 uintptr_t vaddr, size_t memsz) {
140 map_info* map;
141 if ((map = allocate_init_map(ph->core->classes_jsa_fd,
142 offset, vaddr, memsz)) == NULL) {
143 return NULL;
144 }
145
146 map->next = ph->core->class_share_maps;
147 ph->core->class_share_maps = map;
148 return map;
149 }
150
151 // Return the map_info for the given virtual address. We keep a sorted
152 // array of pointers in ph->map_array, so we can binary search.
153 static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr) {
154 int mid, lo = 0, hi = ph->core->num_maps - 1;
155 map_info *mp;
156
157 while (hi - lo > 1) {
158 mid = (lo + hi) / 2;
159 if (addr >= ph->core->map_array[mid]->vaddr) {
160 lo = mid;
161 } else {
162 hi = mid;
656 * entry that has integer regset for that LWP.
657 *
658 * Linux threads are actually 'clone'd processes. To support core analysis
659 * of "multithreaded" process, Linux creates more than one pstatus (called
660 * "prstatus") entry in PT_NOTE. Each prstatus entry has integer regset for one
661 * "thread". Please refer to Linux kernel src file 'fs/binfmt_elf.c', in particular
662 * function "elf_core_dump".
663 */
664
665 for (core_php = phbuf, i = 0; i < core_ehdr->e_phnum; i++) {
666 switch (core_php->p_type) {
667 case PT_NOTE:
668 if (core_handle_note(ph, core_php) != true) {
669 goto err;
670 }
671 break;
672
673 case PT_LOAD: {
674 if (core_php->p_filesz != 0) {
675 if (add_map_info(ph, ph->core->core_fd, core_php->p_offset,
676 core_php->p_vaddr, core_php->p_filesz) == NULL) goto err;
677 }
678 break;
679 }
680 }
681
682 core_php++;
683 }
684
685 free(phbuf);
686 return true;
687 err:
688 free(phbuf);
689 return false;
690 }
691
692 // read segments of a shared object
693 static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* lib_ehdr, uintptr_t lib_base) {
694 int i = 0;
695 ELF_PHDR* phbuf;
696 ELF_PHDR* lib_php = NULL;
697
698 int page_size = sysconf(_SC_PAGE_SIZE);
699
700 if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) {
701 return false;
702 }
703
704 // we want to process only PT_LOAD segments that are not writable.
705 // i.e., text segments. The read/write/exec (data) segments would
706 // have been already added from core file segments.
707 for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) {
708 if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) {
709
710 uintptr_t target_vaddr = lib_php->p_vaddr + lib_base;
711 map_info *existing_map = core_lookup(ph, target_vaddr);
712
713 if (existing_map == NULL){
714 if (add_map_info(ph, lib_fd, lib_php->p_offset,
715 target_vaddr, lib_php->p_memsz) == NULL) {
716 goto err;
717 }
718 } else {
719 // Coredump stores value of p_memsz elf field
720 // rounded up to page boundary.
721
722 if ((existing_map->memsz != page_size) &&
723 (existing_map->fd != lib_fd) &&
724 (ROUNDUP(existing_map->memsz, page_size) != ROUNDUP(lib_php->p_memsz, page_size))) {
725
726 print_debug("address conflict @ 0x%lx (existing map size = %ld, size = %ld, flags = %d)\n",
727 target_vaddr, existing_map->memsz, lib_php->p_memsz, lib_php->p_flags);
728 goto err;
729 }
730
731 /* replace PT_LOAD segment with library segment */
732 print_debug("overwrote with new address mapping (memsz %ld -> %ld)\n",
733 existing_map->memsz, ROUNDUP(lib_php->p_memsz, page_size));
734
735 existing_map->fd = lib_fd;
736 existing_map->offset = lib_php->p_offset;
737 existing_map->memsz = ROUNDUP(lib_php->p_memsz, page_size);
738 }
765 return true;
766 }
767
768 // process segments of a a.out
769 static bool read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehdr) {
770 int i = 0;
771 ELF_PHDR* phbuf = NULL;
772 ELF_PHDR* exec_php = NULL;
773
774 if ((phbuf = read_program_header_table(ph->core->exec_fd, exec_ehdr)) == NULL) {
775 return false;
776 }
777
778 for (exec_php = phbuf, i = 0; i < exec_ehdr->e_phnum; i++) {
779 switch (exec_php->p_type) {
780
781 // add mappings for PT_LOAD segments
782 case PT_LOAD: {
783 // add only non-writable segments of non-zero filesz
784 if (!(exec_php->p_flags & PF_W) && exec_php->p_filesz != 0) {
785 if (add_map_info(ph, ph->core->exec_fd, exec_php->p_offset, exec_php->p_vaddr, exec_php->p_filesz) == NULL) goto err;
786 }
787 break;
788 }
789
790 // read the interpreter and it's segments
791 case PT_INTERP: {
792 char interp_name[BUF_SIZE + 1];
793
794 // BUF_SIZE is PATH_MAX + NAME_MAX + 1.
795 if (exec_php->p_filesz > BUF_SIZE) {
796 goto err;
797 }
798 if (pread(ph->core->exec_fd, interp_name,
799 exec_php->p_filesz, exec_php->p_offset) != exec_php->p_filesz) {
800 print_debug("Unable to read in the ELF interpreter\n");
801 goto err;
802 }
803 interp_name[exec_php->p_filesz] = '\0';
804 print_debug("ELF interpreter %s\n", interp_name);
805 // read interpreter segments as well
|
1 /*
2 * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
86 }
87
88 // Part of the class sharing workaround
89 map = ph->core->class_share_maps;
90 while (map) {
91 map_info* next = map->next;
92 free(map);
93 map = next;
94 }
95 }
96
97 // ps_prochandle operations
98 static void core_release(struct ps_prochandle* ph) {
99 if (ph->core) {
100 close_files(ph);
101 destroy_map_info(ph);
102 free(ph->core);
103 }
104 }
105
106 static map_info* allocate_init_map(int fd, off_t offset, uintptr_t vaddr, size_t memsz, uint32_t flags) {
107 map_info* map;
108 if ( (map = (map_info*) calloc(1, sizeof(map_info))) == NULL) {
109 print_debug("can't allocate memory for map_info\n");
110 return NULL;
111 }
112
113 // initialize map
114 map->fd = fd;
115 map->offset = offset;
116 map->vaddr = vaddr;
117 map->memsz = memsz;
118 map->flags = flags;
119 return map;
120 }
121
122 // add map info with given fd, offset, vaddr and memsz
123 static map_info* add_map_info(struct ps_prochandle* ph, int fd, off_t offset,
124 uintptr_t vaddr, size_t memsz, uint32_t flags) {
125 map_info* map;
126 if ((map = allocate_init_map(fd, offset, vaddr, memsz, flags)) == NULL) {
127 return NULL;
128 }
129
130 // add this to map list
131 map->next = ph->core->maps;
132 ph->core->maps = map;
133 ph->core->num_maps++;
134
135 return map;
136 }
137
138 // Part of the class sharing workaround
139 static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset,
140 uintptr_t vaddr, size_t memsz) {
141 map_info* map;
142 if ((map = allocate_init_map(ph->core->classes_jsa_fd,
143 offset, vaddr, memsz, PF_R)) == NULL) {
144 return NULL;
145 }
146
147 map->next = ph->core->class_share_maps;
148 ph->core->class_share_maps = map;
149 return map;
150 }
151
152 // Return the map_info for the given virtual address. We keep a sorted
153 // array of pointers in ph->map_array, so we can binary search.
154 static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr) {
155 int mid, lo = 0, hi = ph->core->num_maps - 1;
156 map_info *mp;
157
158 while (hi - lo > 1) {
159 mid = (lo + hi) / 2;
160 if (addr >= ph->core->map_array[mid]->vaddr) {
161 lo = mid;
162 } else {
163 hi = mid;
657 * entry that has integer regset for that LWP.
658 *
659 * Linux threads are actually 'clone'd processes. To support core analysis
660 * of "multithreaded" process, Linux creates more than one pstatus (called
661 * "prstatus") entry in PT_NOTE. Each prstatus entry has integer regset for one
662 * "thread". Please refer to Linux kernel src file 'fs/binfmt_elf.c', in particular
663 * function "elf_core_dump".
664 */
665
666 for (core_php = phbuf, i = 0; i < core_ehdr->e_phnum; i++) {
667 switch (core_php->p_type) {
668 case PT_NOTE:
669 if (core_handle_note(ph, core_php) != true) {
670 goto err;
671 }
672 break;
673
674 case PT_LOAD: {
675 if (core_php->p_filesz != 0) {
676 if (add_map_info(ph, ph->core->core_fd, core_php->p_offset,
677 core_php->p_vaddr, core_php->p_filesz, core_php->p_flags) == NULL) goto err;
678 }
679 break;
680 }
681 }
682
683 core_php++;
684 }
685
686 free(phbuf);
687 return true;
688 err:
689 free(phbuf);
690 return false;
691 }
692
693 // read segments of a shared object
694 static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* lib_ehdr, uintptr_t lib_base) {
695 int i = 0;
696 ELF_PHDR* phbuf;
697 ELF_PHDR* lib_php = NULL;
698
699 int page_size = sysconf(_SC_PAGE_SIZE);
700
701 if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) {
702 return false;
703 }
704
705 // we want to process only PT_LOAD segments that are not writable.
706 // i.e., text segments. The read/write/exec (data) segments would
707 // have been already added from core file segments.
708 for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) {
709 if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) {
710
711 uintptr_t target_vaddr = lib_php->p_vaddr + lib_base;
712 map_info *existing_map = core_lookup(ph, target_vaddr);
713
714 if (existing_map == NULL){
715 if (add_map_info(ph, lib_fd, lib_php->p_offset,
716 target_vaddr, lib_php->p_memsz, lib_php->p_flags) == NULL) {
717 goto err;
718 }
719 } else if (lib_php->p_flags != existing_map->flags) {
720 // Access flags for this memory region are different between the library
721 // and coredump. It might be caused by mprotect() call at runtime.
722 // We should respect the coredump.
723 continue;
724 } else {
725 // Read only segments in ELF should not be any different from PT_LOAD segments
726 // in the coredump.
727 // Also the first page of the ELF header might be included
728 // in the coredump (See JDK-7133122).
729 // Thus we need to replace the PT_LOAD segment with the library version.
730 //
731 // Coredump stores value of p_memsz elf field
732 // rounded up to page boundary.
733
734 if ((existing_map->memsz != page_size) &&
735 (existing_map->fd != lib_fd) &&
736 (ROUNDUP(existing_map->memsz, page_size) != ROUNDUP(lib_php->p_memsz, page_size))) {
737
738 print_debug("address conflict @ 0x%lx (existing map size = %ld, size = %ld, flags = %d)\n",
739 target_vaddr, existing_map->memsz, lib_php->p_memsz, lib_php->p_flags);
740 goto err;
741 }
742
743 /* replace PT_LOAD segment with library segment */
744 print_debug("overwrote with new address mapping (memsz %ld -> %ld)\n",
745 existing_map->memsz, ROUNDUP(lib_php->p_memsz, page_size));
746
747 existing_map->fd = lib_fd;
748 existing_map->offset = lib_php->p_offset;
749 existing_map->memsz = ROUNDUP(lib_php->p_memsz, page_size);
750 }
777 return true;
778 }
779
780 // process segments of a a.out
781 static bool read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehdr) {
782 int i = 0;
783 ELF_PHDR* phbuf = NULL;
784 ELF_PHDR* exec_php = NULL;
785
786 if ((phbuf = read_program_header_table(ph->core->exec_fd, exec_ehdr)) == NULL) {
787 return false;
788 }
789
790 for (exec_php = phbuf, i = 0; i < exec_ehdr->e_phnum; i++) {
791 switch (exec_php->p_type) {
792
793 // add mappings for PT_LOAD segments
794 case PT_LOAD: {
795 // add only non-writable segments of non-zero filesz
796 if (!(exec_php->p_flags & PF_W) && exec_php->p_filesz != 0) {
797 if (add_map_info(ph, ph->core->exec_fd, exec_php->p_offset, exec_php->p_vaddr, exec_php->p_filesz, exec_php->p_flags) == NULL) goto err;
798 }
799 break;
800 }
801
802 // read the interpreter and it's segments
803 case PT_INTERP: {
804 char interp_name[BUF_SIZE + 1];
805
806 // BUF_SIZE is PATH_MAX + NAME_MAX + 1.
807 if (exec_php->p_filesz > BUF_SIZE) {
808 goto err;
809 }
810 if (pread(ph->core->exec_fd, interp_name,
811 exec_php->p_filesz, exec_php->p_offset) != exec_php->p_filesz) {
812 print_debug("Unable to read in the ELF interpreter\n");
813 goto err;
814 }
815 interp_name[exec_php->p_filesz] = '\0';
816 print_debug("ELF interpreter %s\n", interp_name);
817 // read interpreter segments as well
|