1 /*
   2  * Copyright (c) 2019, 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  *
  23  */
  24 
  25 #if defined(LINUX) || defined(__APPLE__)
  26 #include <unistd.h>
  27 #include <fcntl.h>
  28 #include <string.h>
  29 #include <stdlib.h>
  30 #include <stddef.h>
  31 #ifdef LINUX
  32 #include <elf.h>
  33 #include <link.h>
  34 #include "proc_service.h"
  35 #include "salibelf.h"
  36 #endif
  37 #include "libproc_impl.h"
  38 #include "cds.h"
  39 
  40 #ifdef __APPLE__
  41 #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
  42 #endif
  43 
  44 // Define a segment permission flag allowing read.
  45 #ifdef PF_R
  46 #define MAP_R_FLAG PF_R
  47 #else
  48 #define MAP_R_FLAG 0
  49 #endif
  50 
  51 #ifdef LINUX
  52 // I have no idea why this function is called ps_pread() on macos but ps_pdread on linux.
  53 #define ps_pread ps_pdread
  54 #endif
  55 
  56 // Common code shared between linux/native/libsaproc/ps_core.c and macosx/native/libsaproc/ps_core.c
  57 
  58 //----------------------------------------------------------------------
  59 // ps_prochandle cleanup helper functions
  60 
  61 // close all file descriptors
  62 static void close_files(struct ps_prochandle* ph) {
  63   lib_info* lib = NULL;
  64 
  65   // close core file descriptor
  66   if (ph->core->core_fd >= 0)
  67     close(ph->core->core_fd);
  68 
  69   // close exec file descriptor
  70   if (ph->core->exec_fd >= 0)
  71     close(ph->core->exec_fd);
  72 
  73   // close interp file descriptor
  74   if (ph->core->interp_fd >= 0)
  75     close(ph->core->interp_fd);
  76 
  77   // close class share archive file
  78   if (ph->core->classes_jsa_fd >= 0)
  79     close(ph->core->classes_jsa_fd);
  80 
  81   // close all library file descriptors
  82   lib = ph->libs;
  83   while (lib) {
  84     int fd = lib->fd;
  85     if (fd >= 0 && fd != ph->core->exec_fd) {
  86       close(fd);
  87     }
  88     lib = lib->next;
  89   }
  90 }
  91 
  92 // clean all map_info stuff
  93 static void destroy_map_info(struct ps_prochandle* ph) {
  94   map_info* map = ph->core->maps;
  95   while (map) {
  96     map_info* next = map->next;
  97     free(map);
  98     map = next;
  99   }
 100 
 101   if (ph->core->map_array) {
 102     free(ph->core->map_array);
 103   }
 104 
 105   // Part of the class sharing workaround
 106   map = ph->core->class_share_maps;
 107   while (map) {
 108     map_info* next = map->next;
 109     free(map);
 110     map = next;
 111   }
 112 }
 113 
 114 // ps_prochandle operations
 115 void core_release(struct ps_prochandle* ph) {
 116   if (ph->core) {
 117     close_files(ph);
 118     destroy_map_info(ph);
 119     free(ph->core);
 120   }
 121 }
 122 
 123 static map_info* allocate_init_map(int fd, off_t offset, uintptr_t vaddr, size_t memsz, uint32_t flags) {
 124   map_info* map;
 125   if ( (map = (map_info*) calloc(1, sizeof(map_info))) == NULL) {
 126     print_debug("can't allocate memory for map_info\n");
 127     return NULL;
 128   }
 129 
 130   // initialize map
 131   map->fd     = fd;
 132   map->offset = offset;
 133   map->vaddr  = vaddr;
 134   map->memsz  = memsz;
 135   map->flags  = flags;
 136   return map;
 137 }
 138 
 139 // add map info with given fd, offset, vaddr and memsz
 140 map_info* add_map_info(struct ps_prochandle* ph, int fd, off_t offset,
 141                        uintptr_t vaddr, size_t memsz, uint32_t flags) {
 142   map_info* map;
 143   if ((map = allocate_init_map(fd, offset, vaddr, memsz, flags)) == NULL) {
 144     return NULL;
 145   }
 146 
 147   // add this to map list
 148   map->next  = ph->core->maps;
 149   ph->core->maps   = map;
 150   ph->core->num_maps++;
 151 
 152   return map;
 153 }
 154 
 155 // Part of the class sharing workaround
 156 static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset,
 157                              uintptr_t vaddr, size_t memsz) {
 158   map_info* map;
 159   if ((map = allocate_init_map(ph->core->classes_jsa_fd,
 160                                offset, vaddr, memsz, MAP_R_FLAG)) == NULL) {
 161     return NULL;
 162   }
 163 
 164   map->next = ph->core->class_share_maps;
 165   ph->core->class_share_maps = map;
 166   return map;
 167 }
 168 
 169 // Return the map_info for the given virtual address.  We keep a sorted
 170 // array of pointers in ph->map_array, so we can binary search.
 171 map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr) {
 172   int mid, lo = 0, hi = ph->core->num_maps - 1;
 173   map_info *mp;
 174 
 175   while (hi - lo > 1) {
 176     mid = (lo + hi) / 2;
 177     if (addr >= ph->core->map_array[mid]->vaddr) {
 178       lo = mid;
 179     } else {
 180       hi = mid;
 181     }
 182   }
 183 
 184   if (addr < ph->core->map_array[hi]->vaddr) {
 185     mp = ph->core->map_array[lo];
 186   } else {
 187     mp = ph->core->map_array[hi];
 188   }
 189 
 190   if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
 191     return (mp);
 192   }
 193 
 194 
 195   // Part of the class sharing workaround
 196   // Unfortunately, we have no way of detecting -Xshare state.
 197   // Check out the share maps atlast, if we don't find anywhere.
 198   // This is done this way so to avoid reading share pages
 199   // ahead of other normal maps. For eg. with -Xshare:off we don't
 200   // want to prefer class sharing data to data from core.
 201   mp = ph->core->class_share_maps;
 202   if (mp) {
 203     print_debug("can't locate map_info at 0x%lx, trying class share maps\n", addr);
 204   }
 205   while (mp) {
 206     if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
 207       print_debug("located map_info at 0x%lx from class share maps\n", addr);
 208       return (mp);
 209     }
 210     mp = mp->next;
 211   }
 212 
 213   print_debug("can't locate map_info at 0x%lx\n", addr);
 214   return (NULL);
 215 }
 216 
 217 //---------------------------------------------------------------
 218 // Part of the class sharing workaround:
 219 //
 220 // With class sharing, pages are mapped from classes.jsa file.
 221 // The read-only class sharing pages are mapped as MAP_SHARED,
 222 // PROT_READ pages. These pages are not dumped into core dump.
 223 // With this workaround, these pages are read from classes.jsa.
 224 
 225 static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pvalue) {
 226   jboolean i;
 227   if (ps_pread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) {
 228     *pvalue = i;
 229     return true;
 230   } else {
 231     return false;
 232   }
 233 }
 234 
 235 static bool read_pointer(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* pvalue) {
 236   uintptr_t uip;
 237   if (ps_pread(ph, (psaddr_t) addr, (char *)&uip, sizeof(uip)) == PS_OK) {
 238     *pvalue = uip;
 239     return true;
 240   } else {
 241     return false;
 242   }
 243 }
 244 
 245 // used to read strings from debuggee
 246 bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t size) {
 247   size_t i = 0;
 248   char  c = ' ';
 249 
 250   while (c != '\0') {
 251     if (ps_pread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK) {
 252       return false;
 253     }
 254     if (i < size - 1) {
 255       buf[i] = c;
 256     } else {
 257       // smaller buffer
 258       return false;
 259     }
 260     i++; addr++;
 261   }
 262   buf[i] = '\0';
 263   return true;
 264 }
 265 
 266 #ifdef LINUX
 267 // mangled name of Arguments::SharedArchivePath
 268 #define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
 269 #define USE_SHARED_SPACES_SYM "UseSharedSpaces"
 270 #define SHARED_BASE_ADDRESS_SYM "SharedBaseAddress"
 271 #define LIBJVM_NAME "/libjvm.so"
 272 #endif
 273 
 274 #ifdef __APPLE__
 275 // mangled name of Arguments::SharedArchivePath
 276 #define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
 277 #define USE_SHARED_SPACES_SYM "_UseSharedSpaces"
 278 #define SHARED_BASE_ADDRESS_SYM "_SharedBaseAddress"
 279 #define LIBJVM_NAME "/libjvm.dylib"
 280 #endif
 281 
 282 bool init_classsharing_workaround(struct ps_prochandle* ph) {
 283   lib_info* lib = ph->libs;
 284   while (lib != NULL) {
 285     // we are iterating over shared objects from the core dump. look for
 286     // libjvm.so.
 287     const char *jvm_name = 0;
 288     if ((jvm_name = strstr(lib->name, LIBJVM_NAME)) != 0) {
 289       char classes_jsa[PATH_MAX];
 290       CDSFileMapHeaderBase header;
 291       int fd = -1;
 292       uintptr_t useSharedSpacesAddr = 0;
 293       uintptr_t sharedBaseAddressAddr = 0, sharedBaseAddress = 0;
 294       uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0;
 295       jboolean useSharedSpaces = 0;
 296       int m;
 297       size_t n;
 298 
 299       memset(classes_jsa, 0, sizeof(classes_jsa));
 300       jvm_name = lib->name;
 301       useSharedSpacesAddr = lookup_symbol(ph, jvm_name, USE_SHARED_SPACES_SYM);
 302       if (useSharedSpacesAddr == 0) {
 303         print_debug("can't lookup 'UseSharedSpaces' flag\n");
 304         return false;
 305       }
 306 
 307       // Hotspot vm types are not exported to build this library. So
 308       // using equivalent type jboolean to read the value of
 309       // UseSharedSpaces which is same as hotspot type "bool".
 310       if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) {
 311         print_debug("can't read the value of 'UseSharedSpaces' flag\n");
 312         return false;
 313       }
 314 
 315       if ((int)useSharedSpaces == 0) {
 316         print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n");
 317         return true;
 318       }
 319 
 320       sharedBaseAddressAddr = lookup_symbol(ph, jvm_name, SHARED_BASE_ADDRESS_SYM);
 321       if (sharedBaseAddressAddr == 0) {
 322         print_debug("can't lookup 'SharedBaseAddress' flag\n");
 323         return false;
 324       }
 325 
 326       if (read_pointer(ph, sharedBaseAddressAddr, &sharedBaseAddress) != true) {
 327         print_debug("can't read the value of 'SharedBaseAddress' flag\n");
 328         return false;
 329       }
 330 
 331       sharedArchivePathAddrAddr = lookup_symbol(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM);
 332       if (sharedArchivePathAddrAddr == 0) {
 333         print_debug("can't lookup shared archive path symbol\n");
 334         return false;
 335       }
 336 
 337       if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) {
 338         print_debug("can't read shared archive path pointer\n");
 339         return false;
 340       }
 341 
 342       if (read_string(ph, sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) {
 343         print_debug("can't read shared archive path value\n");
 344         return false;
 345       }
 346 
 347       print_debug("looking for %s\n", classes_jsa);
 348       // open the class sharing archive file
 349       fd = pathmap_open(classes_jsa);
 350       if (fd < 0) {
 351         print_debug("can't open %s!\n", classes_jsa);
 352         ph->core->classes_jsa_fd = -1;
 353         return false;
 354       } else {
 355         print_debug("opened %s\n", classes_jsa);
 356       }
 357 
 358       // read CDSFileMapHeaderBase from the file
 359       memset(&header, 0, sizeof(CDSFileMapHeaderBase));
 360       if ((n = read(fd, &header, sizeof(CDSFileMapHeaderBase)))
 361            != sizeof(CDSFileMapHeaderBase)) {
 362         print_debug("can't read shared archive file map header from %s\n", classes_jsa);
 363         close(fd);
 364         return false;
 365       }
 366 
 367       // check file magic
 368       if (header._magic != CDS_ARCHIVE_MAGIC) {
 369         print_debug("%s has bad shared archive file magic number 0x%x, expecting 0x%x\n",
 370                     classes_jsa, header._magic, CDS_ARCHIVE_MAGIC);
 371         close(fd);
 372         return false;
 373       }
 374 
 375       // check version
 376       if (header._version != CURRENT_CDS_ARCHIVE_VERSION) {
 377         print_debug("%s has wrong shared archive file version %d, expecting %d\n",
 378                      classes_jsa, header._version, CURRENT_CDS_ARCHIVE_VERSION);
 379         close(fd);
 380         return false;
 381       }
 382 
 383       ph->core->classes_jsa_fd = fd;
 384       // add read-only maps from classes.jsa to the list of maps
 385       for (m = 0; m < NUM_CDS_REGIONS; m++) {
 386         if (header._space[m]._read_only &&
 387             !header._space[m]._is_heap_region &&
 388             !header._space[m]._is_bitmap_region) {
 389           // With *some* linux versions, the core file doesn't include read-only mmap'ed
 390           // files regions, so let's add them here. This is harmless if the core file also
 391           // include these regions.
 392           uintptr_t base = sharedBaseAddress + (uintptr_t) header._space[m]._mapping_offset;
 393           size_t size = header._space[m]._used;
 394           // no need to worry about the fractional pages at-the-end.
 395           // possible fractional pages are handled by core_read_data.
 396           add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
 397                                    base, size);
 398           print_debug("added a share archive map [%d] at 0x%lx (size 0x%lx bytes)\n", m, base, size);
 399         }
 400       }
 401       return true;
 402    }
 403    lib = lib->next;
 404   }
 405   return true;
 406 }
 407 
 408 #endif // defined(LINUX) || defined(__APPLE__)