< prev index next >

src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c

Print this page


   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


< prev index next >