# HG changeset patch # User ccheung # Date 1380945643 25200 # Node ID 2720ab7a0d70eb2a1ecc90a116b710defafffde8 # Parent 4212bfb33d76f9a672ca8744857b5ff03c5ac156# Parent 798522662fcd08211bd64fdde7fe22b54c83ad98 Merge diff -r 798522662fcd -r 2720ab7a0d70 agent/src/os/bsd/ps_core.c --- a/agent/src/os/bsd/ps_core.c Fri Oct 04 13:37:25 2013 -0700 +++ b/agent/src/os/bsd/ps_core.c Fri Oct 04 21:00:43 2013 -0700 @@ -44,6 +44,7 @@ // close all file descriptors static void close_files(struct ps_prochandle* ph) { lib_info* lib = NULL; + // close core file descriptor if (ph->core->core_fd >= 0) close(ph->core->core_fd); @@ -149,8 +150,7 @@ // Return the map_info for the given virtual address. We keep a sorted // array of pointers in ph->map_array, so we can binary search. -static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr) -{ +static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr) { int mid, lo = 0, hi = ph->core->num_maps - 1; map_info *mp; @@ -230,9 +230,9 @@ size_t _used; // for setting space top on read // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with - // the C type matching the C++ bool type on any given platform. For - // Hotspot on BSD we assume the corresponding C type is char but - // licensees on BSD versions may need to adjust the type of these fields. + // the C type matching the C++ bool type on any given platform. + // We assume the corresponding C type is char but licensees + // may need to adjust the type of these fields. char _read_only; // read only space? char _allow_exec; // executable code in space? @@ -286,10 +286,12 @@ #define USE_SHARED_SPACES_SYM "_UseSharedSpaces" // mangled name of Arguments::SharedArchivePath #define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE" +#define LIBJVM_NAME "/libjvm.dylib" #else #define USE_SHARED_SPACES_SYM "UseSharedSpaces" // mangled name of Arguments::SharedArchivePath #define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE" +#define LIBJVM_NAME "/libjvm.so" #endif // __APPLE_ static bool init_classsharing_workaround(struct ps_prochandle* ph) { @@ -300,12 +302,7 @@ // we are iterating over shared objects from the core dump. look for // libjvm.so. const char *jvm_name = 0; -#ifdef __APPLE__ - if ((jvm_name = strstr(lib->name, "/libjvm.dylib")) != 0) -#else - if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0) -#endif // __APPLE__ - { + if ((jvm_name = strstr(lib->name, LIBJVM_NAME)) != 0) { char classes_jsa[PATH_MAX]; struct FileMapHeader header; int fd = -1; @@ -399,8 +396,8 @@ } } return true; - } - lib = lib->next; + } + lib = lib->next; } return true; } @@ -432,8 +429,8 @@ // allocate map_array map_info** array; if ( (array = (map_info**) malloc(sizeof(map_info*) * num_maps)) == NULL) { - print_debug("can't allocate memory for map array\n"); - return false; + print_debug("can't allocate memory for map array\n"); + return false; } // add maps to array @@ -450,7 +447,7 @@ ph->core->map_array = array; // sort the map_info array by base virtual address. qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*), - core_cmp_mapping); + core_cmp_mapping); // print map if (is_debug()) { @@ -458,7 +455,7 @@ print_debug("---- sorted virtual address map ----\n"); for (j = 0; j < ph->core->num_maps; j++) { print_debug("base = 0x%lx\tsize = %d\n", ph->core->map_array[j]->vaddr, - ph->core->map_array[j]->memsz); + ph->core->map_array[j]->memsz); } } @@ -1091,9 +1088,9 @@ notep->n_type, notep->n_descsz); if (notep->n_type == NT_PRSTATUS) { - if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true) { - return false; - } + if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true) { + return false; + } } p = descdata + ROUNDUP(notep->n_descsz, 4); } @@ -1121,7 +1118,7 @@ * contains a set of saved /proc structures), and PT_LOAD (which * represents a memory mapping from the process's address space). * - * Difference b/w Solaris PT_NOTE and BSD PT_NOTE: + * Difference b/w Solaris PT_NOTE and Linux/BSD PT_NOTE: * * In Solaris there are two PT_NOTE segments the first PT_NOTE (if present) * contains /proc structs in the pre-2.6 unstructured /proc format. the last @@ -1167,32 +1164,61 @@ // read segments of a shared object static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* lib_ehdr, uintptr_t lib_base) { - int i = 0; - ELF_PHDR* phbuf; - ELF_PHDR* lib_php = NULL; + int i = 0; + ELF_PHDR* phbuf; + ELF_PHDR* lib_php = NULL; + + int page_size=sysconf(_SC_PAGE_SIZE); - if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) - return false; + if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) { + return false; + } + + // we want to process only PT_LOAD segments that are not writable. + // i.e., text segments. The read/write/exec (data) segments would + // have been already added from core file segments. + for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) { + if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) { + + uintptr_t target_vaddr = lib_php->p_vaddr + lib_base; + map_info *existing_map = core_lookup(ph, target_vaddr); - // we want to process only PT_LOAD segments that are not writable. - // i.e., text segments. The read/write/exec (data) segments would - // have been already added from core file segments. - for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) { - if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) { - if (add_map_info(ph, lib_fd, lib_php->p_offset, lib_php->p_vaddr + lib_base, lib_php->p_filesz) == NULL) - goto err; + if (existing_map == NULL){ + if (add_map_info(ph, lib_fd, lib_php->p_offset, + target_vaddr, lib_php->p_filesz) == NULL) { + goto err; + } + } else { + if ((existing_map->memsz != page_size) && + (existing_map->fd != lib_fd) && + (existing_map->memsz != lib_php->p_filesz)){ + + print_debug("address conflict @ 0x%lx (size = %ld, flags = %d\n)", + target_vaddr, lib_php->p_filesz, lib_php->p_flags); + goto err; + } + + /* replace PT_LOAD segment with library segment */ + print_debug("overwrote with new address mapping (memsz %ld -> %ld)\n", + existing_map->memsz, lib_php->p_filesz); + + existing_map->fd = lib_fd; + existing_map->offset = lib_php->p_offset; + existing_map->memsz = lib_php->p_filesz; } - lib_php++; - } + } + + lib_php++; + } - free(phbuf); - return true; + free(phbuf); + return true; err: - free(phbuf); - return false; + free(phbuf); + return false; } -// process segments from interpreter (ld-elf.so.1) +// process segments from interpreter (ld.so or ld-linux.so or ld-elf.so) static bool read_interp_segments(struct ps_prochandle* ph) { ELF_EHDR interp_ehdr; @@ -1303,32 +1329,34 @@ debug_base = dyn.d_un.d_ptr; // at debug_base we have struct r_debug. This has first link map in r_map field if (ps_pread(ph, (psaddr_t) debug_base + FIRST_LINK_MAP_OFFSET, - &first_link_map_addr, sizeof(uintptr_t)) != PS_OK) { + &first_link_map_addr, sizeof(uintptr_t)) != PS_OK) { print_debug("can't read first link map address\n"); return false; } // read ld_base address from struct r_debug - // XXX: There is no r_ldbase member on BSD - /* +#if 0 // There is no r_ldbase member on BSD if (ps_pread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr, sizeof(uintptr_t)) != PS_OK) { print_debug("can't read ld base address\n"); return false; } ph->core->ld_base_addr = ld_base_addr; - */ +#else ph->core->ld_base_addr = 0; +#endif print_debug("interpreter base address is 0x%lx\n", ld_base_addr); - // now read segments from interp (i.e ld-elf.so.1) - if (read_interp_segments(ph) != true) + // now read segments from interp (i.e ld.so or ld-linux.so or ld-elf.so) + if (read_interp_segments(ph) != true) { return false; + } // after adding interpreter (ld.so) mappings sort again - if (sort_map_array(ph) != true) + if (sort_map_array(ph) != true) { return false; + } print_debug("first link map is at 0x%lx\n", first_link_map_addr); @@ -1380,8 +1408,9 @@ add_lib_info_fd(ph, lib_name, lib_fd, lib_base); // Map info is added for the library (lib_name) so // we need to re-sort it before calling the p_pdread. - if (sort_map_array(ph) != true) + if (sort_map_array(ph) != true) { return false; + } } else { print_debug("can't read ELF header for shared object %s\n", lib_name); close(lib_fd); @@ -1392,7 +1421,7 @@ // read next link_map address if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NEXT_OFFSET, - &link_map_addr, sizeof(uintptr_t)) != PS_OK) { + &link_map_addr, sizeof(uintptr_t)) != PS_OK) { print_debug("can't read next link in link_map\n"); return false; } @@ -1408,7 +1437,7 @@ struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle)); if (ph == NULL) { - print_debug("cant allocate ps_prochandle\n"); + print_debug("can't allocate ps_prochandle\n"); return NULL; } @@ -1444,38 +1473,45 @@ } if (read_elf_header(ph->core->exec_fd, &exec_ehdr) != true || exec_ehdr.e_type != ET_EXEC) { - print_debug("executable file is not a valid ELF ET_EXEC file\n"); - goto err; + print_debug("executable file is not a valid ELF ET_EXEC file\n"); + goto err; } // process core file segments - if (read_core_segments(ph, &core_ehdr) != true) - goto err; + if (read_core_segments(ph, &core_ehdr) != true) { + goto err; + } // process exec file segments - if (read_exec_segments(ph, &exec_ehdr) != true) - goto err; + if (read_exec_segments(ph, &exec_ehdr) != true) { + goto err; + } // exec file is also treated like a shared object for symbol search if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd, - (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL) - goto err; + (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL) { + goto err; + } // allocate and sort maps into map_array, we need to do this // here because read_shared_lib_info needs to read from debuggee // address space - if (sort_map_array(ph) != true) + if (sort_map_array(ph) != true) { goto err; + } - if (read_shared_lib_info(ph) != true) + if (read_shared_lib_info(ph) != true) { goto err; + } // sort again because we have added more mappings from shared objects - if (sort_map_array(ph) != true) + if (sort_map_array(ph) != true) { goto err; + } - if (init_classsharing_workaround(ph) != true) + if (init_classsharing_workaround(ph) != true) { goto err; + } print_debug("Leave Pgrab_core\n"); return ph; diff -r 798522662fcd -r 2720ab7a0d70 agent/src/os/linux/ps_core.c --- a/agent/src/os/linux/ps_core.c Fri Oct 04 13:37:25 2013 -0700 +++ b/agent/src/os/linux/ps_core.c Fri Oct 04 21:00:43 2013 -0700 @@ -41,155 +41,158 @@ // ps_prochandle cleanup helper functions // close all file descriptors -static void close_elf_files(struct ps_prochandle* ph) { - lib_info* lib = NULL; +static void close_files(struct ps_prochandle* ph) { + lib_info* lib = NULL; - // close core file descriptor - if (ph->core->core_fd >= 0) - close(ph->core->core_fd); + // close core file descriptor + if (ph->core->core_fd >= 0) + close(ph->core->core_fd); - // close exec file descriptor - if (ph->core->exec_fd >= 0) - close(ph->core->exec_fd); + // close exec file descriptor + if (ph->core->exec_fd >= 0) + close(ph->core->exec_fd); - // close interp file descriptor - if (ph->core->interp_fd >= 0) - close(ph->core->interp_fd); + // close interp file descriptor + if (ph->core->interp_fd >= 0) + close(ph->core->interp_fd); - // close class share archive file - if (ph->core->classes_jsa_fd >= 0) - close(ph->core->classes_jsa_fd); + // close class share archive file + if (ph->core->classes_jsa_fd >= 0) + close(ph->core->classes_jsa_fd); - // close all library file descriptors - lib = ph->libs; - while (lib) { - int fd = lib->fd; - if (fd >= 0 && fd != ph->core->exec_fd) close(fd); - lib = lib->next; - } + // close all library file descriptors + lib = ph->libs; + while (lib) { + int fd = lib->fd; + if (fd >= 0 && fd != ph->core->exec_fd) { + close(fd); + } + lib = lib->next; + } } // clean all map_info stuff static void destroy_map_info(struct ps_prochandle* ph) { map_info* map = ph->core->maps; while (map) { - map_info* next = map->next; - free(map); - map = next; + map_info* next = map->next; + free(map); + map = next; } if (ph->core->map_array) { - free(ph->core->map_array); + free(ph->core->map_array); } // Part of the class sharing workaround map = ph->core->class_share_maps; while (map) { - map_info* next = map->next; - free(map); - map = next; + map_info* next = map->next; + free(map); + map = next; } } // ps_prochandle operations static void core_release(struct ps_prochandle* ph) { - if (ph->core) { - close_elf_files(ph); - destroy_map_info(ph); - free(ph->core); - } + if (ph->core) { + close_files(ph); + destroy_map_info(ph); + free(ph->core); + } } static map_info* allocate_init_map(int fd, off_t offset, uintptr_t vaddr, size_t memsz) { - map_info* map; - if ( (map = (map_info*) calloc(1, sizeof(map_info))) == NULL) { - print_debug("can't allocate memory for map_info\n"); - return NULL; - } + map_info* map; + if ( (map = (map_info*) calloc(1, sizeof(map_info))) == NULL) { + print_debug("can't allocate memory for map_info\n"); + return NULL; + } - // initialize map - map->fd = fd; - map->offset = offset; - map->vaddr = vaddr; - map->memsz = memsz; - return map; + // initialize map + map->fd = fd; + map->offset = offset; + map->vaddr = vaddr; + map->memsz = memsz; + return map; } // add map info with given fd, offset, vaddr and memsz static map_info* add_map_info(struct ps_prochandle* ph, int fd, off_t offset, uintptr_t vaddr, size_t memsz) { - map_info* map; - if ((map = allocate_init_map(fd, offset, vaddr, memsz)) == NULL) { - return NULL; - } + map_info* map; + if ((map = allocate_init_map(fd, offset, vaddr, memsz)) == NULL) { + return NULL; + } - // add this to map list - map->next = ph->core->maps; - ph->core->maps = map; - ph->core->num_maps++; + // add this to map list + map->next = ph->core->maps; + ph->core->maps = map; + ph->core->num_maps++; - return map; + return map; } // Part of the class sharing workaround -static void add_class_share_map_info(struct ps_prochandle* ph, off_t offset, +static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset, uintptr_t vaddr, size_t memsz) { - map_info* map; - if ((map = allocate_init_map(ph->core->classes_jsa_fd, - offset, vaddr, memsz)) == NULL) { - return; - } + map_info* map; + if ((map = allocate_init_map(ph->core->classes_jsa_fd, + offset, vaddr, memsz)) == NULL) { + return NULL; + } - map->next = ph->core->class_share_maps; - ph->core->class_share_maps = map; + map->next = ph->core->class_share_maps; + ph->core->class_share_maps = map; + return map; } // Return the map_info for the given virtual address. We keep a sorted // array of pointers in ph->map_array, so we can binary search. -static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr) -{ - int mid, lo = 0, hi = ph->core->num_maps - 1; - map_info *mp; +static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr) { + int mid, lo = 0, hi = ph->core->num_maps - 1; + map_info *mp; - while (hi - lo > 1) { - mid = (lo + hi) / 2; - if (addr >= ph->core->map_array[mid]->vaddr) - lo = mid; - else - hi = mid; - } + while (hi - lo > 1) { + mid = (lo + hi) / 2; + if (addr >= ph->core->map_array[mid]->vaddr) { + lo = mid; + } else { + hi = mid; + } + } - if (addr < ph->core->map_array[hi]->vaddr) - mp = ph->core->map_array[lo]; - else - mp = ph->core->map_array[hi]; + if (addr < ph->core->map_array[hi]->vaddr) { + mp = ph->core->map_array[lo]; + } else { + mp = ph->core->map_array[hi]; + } - if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) - return (mp); + if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) { + return (mp); + } - // Part of the class sharing workaround - // Unfortunately, we have no way of detecting -Xshare state. - // Check out the share maps atlast, if we don't find anywhere. - // This is done this way so to avoid reading share pages - // ahead of other normal maps. For eg. with -Xshare:off we don't - // want to prefer class sharing data to data from core. - mp = ph->core->class_share_maps; - if (mp) { - print_debug("can't locate map_info at 0x%lx, trying class share maps\n", - addr); - } - while (mp) { - if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) { - print_debug("located map_info at 0x%lx from class share maps\n", - addr); - return (mp); - } - mp = mp->next; - } + // Part of the class sharing workaround + // Unfortunately, we have no way of detecting -Xshare state. + // Check out the share maps atlast, if we don't find anywhere. + // This is done this way so to avoid reading share pages + // ahead of other normal maps. For eg. with -Xshare:off we don't + // want to prefer class sharing data to data from core. + mp = ph->core->class_share_maps; + if (mp) { + print_debug("can't locate map_info at 0x%lx, trying class share maps\n", addr); + } + while (mp) { + if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) { + print_debug("located map_info at 0x%lx from class share maps\n", addr); + return (mp); + } + mp = mp->next; + } - print_debug("can't locate map_info at 0x%lx\n", addr); - return (NULL); + print_debug("can't locate map_info at 0x%lx\n", addr); + return (NULL); } //--------------------------------------------------------------- @@ -226,9 +229,9 @@ size_t _used; // for setting space top on read // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with - // the C type matching the C++ bool type on any given platform. For - // Hotspot on Linux we assume the corresponding C type is char but - // licensees on Linux versions may need to adjust the type of these fields. + // the C type matching the C++ bool type on any given platform. + // We assume the corresponding C type is char but licensees + // may need to adjust the type of these fields. char _read_only; // read only space? char _allow_exec; // executable code in space? @@ -238,154 +241,159 @@ }; static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pvalue) { - jboolean i; - if (ps_pdread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) { - *pvalue = i; - return true; - } else { - return false; - } + jboolean i; + if (ps_pdread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) { + *pvalue = i; + return true; + } else { + return false; + } } static bool read_pointer(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* pvalue) { - uintptr_t uip; - if (ps_pdread(ph, (psaddr_t) addr, &uip, sizeof(uip)) == PS_OK) { - *pvalue = uip; - return true; - } else { - return false; - } + uintptr_t uip; + if (ps_pdread(ph, (psaddr_t) addr, (char *)&uip, sizeof(uip)) == PS_OK) { + *pvalue = uip; + return true; + } else { + return false; + } } // used to read strings from debuggee static bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t size) { - size_t i = 0; - char c = ' '; + size_t i = 0; + char c = ' '; - while (c != '\0') { - if (ps_pdread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK) - return false; - if (i < size - 1) - buf[i] = c; - else // smaller buffer - return false; - i++; addr++; - } + while (c != '\0') { + if (ps_pdread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK) { + return false; + } + if (i < size - 1) { + buf[i] = c; + } else { + // smaller buffer + return false; + } + i++; addr++; + } - buf[i] = '\0'; - return true; + buf[i] = '\0'; + return true; } #define USE_SHARED_SPACES_SYM "UseSharedSpaces" // mangled name of Arguments::SharedArchivePath #define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE" +#define LIBJVM_NAME "/libjvm.so" static bool init_classsharing_workaround(struct ps_prochandle* ph) { - lib_info* lib = ph->libs; - while (lib != NULL) { - // we are iterating over shared objects from the core dump. look for - // libjvm.so. - const char *jvm_name = 0; - if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0) { - char classes_jsa[PATH_MAX]; - struct FileMapHeader header; - size_t n = 0; - int fd = -1, m = 0; - uintptr_t base = 0, useSharedSpacesAddr = 0; - uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0; - jboolean useSharedSpaces = 0; - map_info* mi = 0; + lib_info* lib = ph->libs; + while (lib != NULL) { + // we are iterating over shared objects from the core dump. look for + // libjvm.so. + const char *jvm_name = 0; + if ((jvm_name = strstr(lib->name, LIBJVM_NAME)) != 0) { + char classes_jsa[PATH_MAX]; + struct FileMapHeader header; + int fd = -1; + int m = 0; + size_t n = 0; + uintptr_t base = 0, useSharedSpacesAddr = 0; + uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0; + jboolean useSharedSpaces = 0; + map_info* mi = 0; - memset(classes_jsa, 0, sizeof(classes_jsa)); - jvm_name = lib->name; - useSharedSpacesAddr = lookup_symbol(ph, jvm_name, USE_SHARED_SPACES_SYM); - if (useSharedSpacesAddr == 0) { - print_debug("can't lookup 'UseSharedSpaces' flag\n"); - return false; - } + memset(classes_jsa, 0, sizeof(classes_jsa)); + jvm_name = lib->name; + useSharedSpacesAddr = lookup_symbol(ph, jvm_name, USE_SHARED_SPACES_SYM); + if (useSharedSpacesAddr == 0) { + print_debug("can't lookup 'UseSharedSpaces' flag\n"); + return false; + } - // Hotspot vm types are not exported to build this library. So - // using equivalent type jboolean to read the value of - // UseSharedSpaces which is same as hotspot type "bool". - if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) { - print_debug("can't read the value of 'UseSharedSpaces' flag\n"); - return false; - } + // Hotspot vm types are not exported to build this library. So + // using equivalent type jboolean to read the value of + // UseSharedSpaces which is same as hotspot type "bool". + if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) { + print_debug("can't read the value of 'UseSharedSpaces' flag\n"); + return false; + } - if ((int)useSharedSpaces == 0) { - print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n"); - return true; - } + if ((int)useSharedSpaces == 0) { + print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n"); + return true; + } - sharedArchivePathAddrAddr = lookup_symbol(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM); - if (sharedArchivePathAddrAddr == 0) { - print_debug("can't lookup shared archive path symbol\n"); - return false; - } + sharedArchivePathAddrAddr = lookup_symbol(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM); + if (sharedArchivePathAddrAddr == 0) { + print_debug("can't lookup shared archive path symbol\n"); + return false; + } - if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) { - print_debug("can't read shared archive path pointer\n"); - return false; - } + if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) { + print_debug("can't read shared archive path pointer\n"); + return false; + } - if (read_string(ph, sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) { - print_debug("can't read shared archive path value\n"); - return false; - } + if (read_string(ph, sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) { + print_debug("can't read shared archive path value\n"); + return false; + } - print_debug("looking for %s\n", classes_jsa); - // open the class sharing archive file - fd = pathmap_open(classes_jsa); - if (fd < 0) { - print_debug("can't open %s!\n", classes_jsa); - ph->core->classes_jsa_fd = -1; - return false; - } else { - print_debug("opened %s\n", classes_jsa); - } + print_debug("looking for %s\n", classes_jsa); + // open the class sharing archive file + fd = pathmap_open(classes_jsa); + if (fd < 0) { + print_debug("can't open %s!\n", classes_jsa); + ph->core->classes_jsa_fd = -1; + return false; + } else { + print_debug("opened %s\n", classes_jsa); + } - // read FileMapHeader from the file - memset(&header, 0, sizeof(struct FileMapHeader)); - if ((n = read(fd, &header, sizeof(struct FileMapHeader))) - != sizeof(struct FileMapHeader)) { - print_debug("can't read shared archive file map header from %s\n", classes_jsa); - close(fd); - return false; - } + // read FileMapHeader from the file + memset(&header, 0, sizeof(struct FileMapHeader)); + if ((n = read(fd, &header, sizeof(struct FileMapHeader))) + != sizeof(struct FileMapHeader)) { + print_debug("can't read shared archive file map header from %s\n", classes_jsa); + close(fd); + return false; + } - // check file magic - if (header._magic != 0xf00baba2) { - print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n", - classes_jsa, header._magic); - close(fd); - return false; - } + // check file magic + if (header._magic != 0xf00baba2) { + print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n", + classes_jsa, header._magic); + close(fd); + return false; + } - // check version - if (header._version != CURRENT_ARCHIVE_VERSION) { - print_debug("%s has wrong shared archive file version %d, expecting %d\n", - classes_jsa, header._version, CURRENT_ARCHIVE_VERSION); - close(fd); - return false; - } + // check version + if (header._version != CURRENT_ARCHIVE_VERSION) { + print_debug("%s has wrong shared archive file version %d, expecting %d\n", + classes_jsa, header._version, CURRENT_ARCHIVE_VERSION); + close(fd); + return false; + } - ph->core->classes_jsa_fd = fd; - // add read-only maps from classes.jsa to the list of maps - for (m = 0; m < NUM_SHARED_MAPS; m++) { - if (header._space[m]._read_only) { - base = (uintptr_t) header._space[m]._base; - // no need to worry about the fractional pages at-the-end. - // possible fractional pages are handled by core_read_data. - add_class_share_map_info(ph, (off_t) header._space[m]._file_offset, - base, (size_t) header._space[m]._used); - print_debug("added a share archive map at 0x%lx\n", base); - } - } - return true; + ph->core->classes_jsa_fd = fd; + // add read-only maps from classes.jsa to the list of maps + for (m = 0; m < NUM_SHARED_MAPS; m++) { + if (header._space[m]._read_only) { + base = (uintptr_t) header._space[m]._base; + // no need to worry about the fractional pages at-the-end. + // possible fractional pages are handled by core_read_data. + add_class_share_map_info(ph, (off_t) header._space[m]._file_offset, + base, (size_t) header._space[m]._used); + print_debug("added a share archive map at 0x%lx\n", base); + } } - lib = lib->next; + return true; } - return true; + lib = lib->next; + } + return true; } @@ -396,54 +404,58 @@ // callback for sorting the array of map_info pointers. static int core_cmp_mapping(const void *lhsp, const void *rhsp) { - const map_info *lhs = *((const map_info **)lhsp); - const map_info *rhs = *((const map_info **)rhsp); + const map_info *lhs = *((const map_info **)lhsp); + const map_info *rhs = *((const map_info **)rhsp); - if (lhs->vaddr == rhs->vaddr) - return (0); + if (lhs->vaddr == rhs->vaddr) { + return (0); + } - return (lhs->vaddr < rhs->vaddr ? -1 : 1); + return (lhs->vaddr < rhs->vaddr ? -1 : 1); } // we sort map_info by starting virtual address so that we can do // binary search to read from an address. static bool sort_map_array(struct ps_prochandle* ph) { - size_t num_maps = ph->core->num_maps; - map_info* map = ph->core->maps; - int i = 0; + size_t num_maps = ph->core->num_maps; + map_info* map = ph->core->maps; + int i = 0; - // allocate map_array - map_info** array; - if ( (array = (map_info**) malloc(sizeof(map_info*) * num_maps)) == NULL) { - print_debug("can't allocate memory for map array\n"); - return false; - } + // allocate map_array + map_info** array; + if ( (array = (map_info**) malloc(sizeof(map_info*) * num_maps)) == NULL) { + print_debug("can't allocate memory for map array\n"); + return false; + } - // add maps to array - while (map) { - array[i] = map; - i++; - map = map->next; - } + // add maps to array + while (map) { + array[i] = map; + i++; + map = map->next; + } - // sort is called twice. If this is second time, clear map array - if (ph->core->map_array) free(ph->core->map_array); - ph->core->map_array = array; - // sort the map_info array by base virtual address. - qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*), - core_cmp_mapping); + // sort is called twice. If this is second time, clear map array + if (ph->core->map_array) { + free(ph->core->map_array); + } + + ph->core->map_array = array; + // sort the map_info array by base virtual address. + qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*), + core_cmp_mapping); - // print map - if (is_debug()) { - int j = 0; - print_debug("---- sorted virtual address map ----\n"); - for (j = 0; j < ph->core->num_maps; j++) { - print_debug("base = 0x%lx\tsize = %zu\n", ph->core->map_array[j]->vaddr, - ph->core->map_array[j]->memsz); - } - } + // print map + if (is_debug()) { + int j = 0; + print_debug("---- sorted virtual address map ----\n"); + for (j = 0; j < ph->core->num_maps; j++) { + print_debug("base = 0x%lx\tsize = %zu\n", ph->core->map_array[j]->vaddr, + ph->core->map_array[j]->memsz); + } + } - return true; + return true; } #ifndef MIN @@ -460,16 +472,18 @@ off_t off; int fd; - if (mp == NULL) + if (mp == NULL) { break; /* No mapping for this address */ + } fd = mp->fd; mapoff = addr - mp->vaddr; len = MIN(resid, mp->memsz - mapoff); off = mp->offset + mapoff; - if ((len = pread(fd, buf, len, off)) <= 0) + if ((len = pread(fd, buf, len, off)) <= 0) { break; + } resid -= len; addr += len; @@ -625,8 +639,9 @@ notep->n_type, notep->n_descsz); if (notep->n_type == NT_PRSTATUS) { - if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true) - return false; + if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true) { + return false; + } } p = descdata + ROUNDUP(notep->n_descsz, 4); } @@ -654,7 +669,7 @@ * contains a set of saved /proc structures), and PT_LOAD (which * represents a memory mapping from the process's address space). * - * Difference b/w Solaris PT_NOTE and Linux PT_NOTE: + * Difference b/w Solaris PT_NOTE and Linux/BSD PT_NOTE: * * In Solaris there are two PT_NOTE segments the first PT_NOTE (if present) * contains /proc structs in the pre-2.6 unstructured /proc format. the last @@ -674,7 +689,9 @@ for (core_php = phbuf, i = 0; i < core_ehdr->e_phnum; i++) { switch (core_php->p_type) { case PT_NOTE: - if (core_handle_note(ph, core_php) != true) goto err; + if (core_handle_note(ph, core_php) != true) { + goto err; + } break; case PT_LOAD: { @@ -832,60 +849,62 @@ // read shared library info from runtime linker's data structures. // This work is done by librtlb_db in Solaris static bool read_shared_lib_info(struct ps_prochandle* ph) { - uintptr_t addr = ph->core->dynamic_addr; - uintptr_t debug_base; - uintptr_t first_link_map_addr; - uintptr_t ld_base_addr; - uintptr_t link_map_addr; - uintptr_t lib_base_diff; - uintptr_t lib_base; - uintptr_t lib_name_addr; - char lib_name[BUF_SIZE]; - ELF_DYN dyn; - ELF_EHDR elf_ehdr; - int lib_fd; + uintptr_t addr = ph->core->dynamic_addr; + uintptr_t debug_base; + uintptr_t first_link_map_addr; + uintptr_t ld_base_addr; + uintptr_t link_map_addr; + uintptr_t lib_base_diff; + uintptr_t lib_base; + uintptr_t lib_name_addr; + char lib_name[BUF_SIZE]; + ELF_DYN dyn; + ELF_EHDR elf_ehdr; + int lib_fd; - // _DYNAMIC has information of the form - // [tag] [data] [tag] [data] ..... - // Both tag and data are pointer sized. - // We look for dynamic info with DT_DEBUG. This has shared object info. - // refer to struct r_debug in link.h + // _DYNAMIC has information of the form + // [tag] [data] [tag] [data] ..... + // Both tag and data are pointer sized. + // We look for dynamic info with DT_DEBUG. This has shared object info. + // refer to struct r_debug in link.h + + dyn.d_tag = DT_NULL; + while (dyn.d_tag != DT_DEBUG) { + if (ps_pdread(ph, (psaddr_t) addr, &dyn, sizeof(ELF_DYN)) != PS_OK) { + print_debug("can't read debug info from _DYNAMIC\n"); + return false; + } + addr += sizeof(ELF_DYN); + } - dyn.d_tag = DT_NULL; - while (dyn.d_tag != DT_DEBUG) { - if (ps_pdread(ph, (psaddr_t) addr, &dyn, sizeof(ELF_DYN)) != PS_OK) { - print_debug("can't read debug info from _DYNAMIC\n"); - return false; - } - addr += sizeof(ELF_DYN); - } - - // we have got Dyn entry with DT_DEBUG - debug_base = dyn.d_un.d_ptr; - // at debug_base we have struct r_debug. This has first link map in r_map field - if (ps_pdread(ph, (psaddr_t) debug_base + FIRST_LINK_MAP_OFFSET, + // we have got Dyn entry with DT_DEBUG + debug_base = dyn.d_un.d_ptr; + // at debug_base we have struct r_debug. This has first link map in r_map field + if (ps_pdread(ph, (psaddr_t) debug_base + FIRST_LINK_MAP_OFFSET, &first_link_map_addr, sizeof(uintptr_t)) != PS_OK) { - print_debug("can't read first link map address\n"); - return false; - } + print_debug("can't read first link map address\n"); + return false; + } - // read ld_base address from struct r_debug - if (ps_pdread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr, + // read ld_base address from struct r_debug + if (ps_pdread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr, sizeof(uintptr_t)) != PS_OK) { - print_debug("can't read ld base address\n"); - return false; - } - ph->core->ld_base_addr = ld_base_addr; + print_debug("can't read ld base address\n"); + return false; + } + ph->core->ld_base_addr = ld_base_addr; + + print_debug("interpreter base address is 0x%lx\n", ld_base_addr); - print_debug("interpreter base address is 0x%lx\n", ld_base_addr); - - // now read segments from interp (i.e ld.so or ld-linux.so) - if (read_interp_segments(ph) != true) + // now read segments from interp (i.e ld.so or ld-linux.so or ld-elf.so) + if (read_interp_segments(ph) != true) { return false; + } - // after adding interpreter (ld.so) mappings sort again - if (sort_map_array(ph) != true) - return false; + // after adding interpreter (ld.so) mappings sort again + if (sort_map_array(ph) != true) { + return false; + } print_debug("first link map is at 0x%lx\n", first_link_map_addr); @@ -950,95 +969,102 @@ } } - // read next link_map address - if (ps_pdread(ph, (psaddr_t) link_map_addr + LINK_MAP_NEXT_OFFSET, - &link_map_addr, sizeof(uintptr_t)) != PS_OK) { - print_debug("can't read next link in link_map\n"); - return false; - } - } + // read next link_map address + if (ps_pdread(ph, (psaddr_t) link_map_addr + LINK_MAP_NEXT_OFFSET, + &link_map_addr, sizeof(uintptr_t)) != PS_OK) { + print_debug("can't read next link in link_map\n"); + return false; + } + } - return true; + return true; } // the one and only one exposed stuff from this file struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) { - ELF_EHDR core_ehdr; - ELF_EHDR exec_ehdr; - ELF_EHDR lib_ehdr; + ELF_EHDR core_ehdr; + ELF_EHDR exec_ehdr; + ELF_EHDR lib_ehdr; - struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle)); - if (ph == NULL) { - print_debug("can't allocate ps_prochandle\n"); - return NULL; - } + struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle)); + if (ph == NULL) { + print_debug("can't allocate ps_prochandle\n"); + return NULL; + } - if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) { - free(ph); - print_debug("can't allocate ps_prochandle\n"); - return NULL; - } + if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) { + free(ph); + print_debug("can't allocate ps_prochandle\n"); + return NULL; + } - // initialize ph - ph->ops = &core_ops; - ph->core->core_fd = -1; - ph->core->exec_fd = -1; - ph->core->interp_fd = -1; + // initialize ph + ph->ops = &core_ops; + ph->core->core_fd = -1; + ph->core->exec_fd = -1; + ph->core->interp_fd = -1; - // open the core file - if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) { - print_debug("can't open core file\n"); - goto err; - } + // open the core file + if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) { + print_debug("can't open core file\n"); + goto err; + } - // read core file ELF header - if (read_elf_header(ph->core->core_fd, &core_ehdr) != true || core_ehdr.e_type != ET_CORE) { - print_debug("core file is not a valid ELF ET_CORE file\n"); - goto err; - } + // read core file ELF header + if (read_elf_header(ph->core->core_fd, &core_ehdr) != true || core_ehdr.e_type != ET_CORE) { + print_debug("core file is not a valid ELF ET_CORE file\n"); + goto err; + } + + if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) { + print_debug("can't open executable file\n"); + goto err; + } - if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) { - print_debug("can't open executable file\n"); - goto err; - } + if (read_elf_header(ph->core->exec_fd, &exec_ehdr) != true || exec_ehdr.e_type != ET_EXEC) { + print_debug("executable file is not a valid ELF ET_EXEC file\n"); + goto err; + } + + // process core file segments + if (read_core_segments(ph, &core_ehdr) != true) { + goto err; + } - if (read_elf_header(ph->core->exec_fd, &exec_ehdr) != true || exec_ehdr.e_type != ET_EXEC) { - print_debug("executable file is not a valid ELF ET_EXEC file\n"); - goto err; - } + // process exec file segments + if (read_exec_segments(ph, &exec_ehdr) != true) { + goto err; + } - // process core file segments - if (read_core_segments(ph, &core_ehdr) != true) - goto err; - - // process exec file segments - if (read_exec_segments(ph, &exec_ehdr) != true) - goto err; + // exec file is also treated like a shared object for symbol search + if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd, + (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL) { + goto err; + } - // exec file is also treated like a shared object for symbol search - if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd, - (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL) - goto err; + // allocate and sort maps into map_array, we need to do this + // here because read_shared_lib_info needs to read from debuggee + // address space + if (sort_map_array(ph) != true) { + goto err; + } - // allocate and sort maps into map_array, we need to do this - // here because read_shared_lib_info needs to read from debuggee - // address space - if (sort_map_array(ph) != true) - goto err; + if (read_shared_lib_info(ph) != true) { + goto err; + } - if (read_shared_lib_info(ph) != true) - goto err; + // sort again because we have added more mappings from shared objects + if (sort_map_array(ph) != true) { + goto err; + } - // sort again because we have added more mappings from shared objects - if (sort_map_array(ph) != true) - goto err; + if (init_classsharing_workaround(ph) != true) { + goto err; + } - if (init_classsharing_workaround(ph) != true) - goto err; - - return ph; + return ph; err: - Prelease(ph); - return NULL; + Prelease(ph); + return NULL; } diff -r 798522662fcd -r 2720ab7a0d70 make/windows/makefiles/fastdebug.make --- a/make/windows/makefiles/fastdebug.make Fri Oct 04 13:37:25 2013 -0700 +++ b/make/windows/makefiles/fastdebug.make Fri Oct 04 21:00:43 2013 -0700 @@ -38,7 +38,7 @@ !include ../local.make !include compile.make -CXX_FLAGS=$(CXX_FLAGS) $(FASTDEBUG_OPT_OPTION) /D "CHECK_UNHANDLED_OOPS" +CXX_FLAGS=$(CXX_FLAGS) $(FASTDEBUG_OPT_OPTION) !include $(WorkSpace)/make/windows/makefiles/vm.make !include local.make diff -r 798522662fcd -r 2720ab7a0d70 src/os/bsd/vm/osThread_bsd.hpp --- a/src/os/bsd/vm/osThread_bsd.hpp Fri Oct 04 13:37:25 2013 -0700 +++ b/src/os/bsd/vm/osThread_bsd.hpp Fri Oct 04 21:00:43 2013 -0700 @@ -42,7 +42,7 @@ #ifdef __APPLE__ typedef thread_t thread_id_t; #else - typedef pthread_t thread_id_t; + typedef pid_t thread_id_t; #endif // _pthread_id is the pthread id, which is used by library calls diff -r 798522662fcd -r 2720ab7a0d70 src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Fri Oct 04 13:37:25 2013 -0700 +++ b/src/os/bsd/vm/os_bsd.cpp Fri Oct 04 21:00:43 2013 -0700 @@ -100,6 +100,7 @@ # include # include # include +# include #if defined(__FreeBSD__) || defined(__NetBSD__) # include @@ -152,6 +153,7 @@ // utility functions static int SR_initialize(); +static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); julong os::available_memory() { return Bsd::available_memory(); @@ -247,7 +249,17 @@ * since it returns a 64 bit value) */ mib[0] = CTL_HW; + +#if defined (HW_MEMSIZE) // Apple mib[1] = HW_MEMSIZE; +#elif defined(HW_PHYSMEM) // Most of BSD + mib[1] = HW_PHYSMEM; +#elif defined(HW_REALMEM) // Old FreeBSD + mib[1] = HW_REALMEM; +#else + #error No ways to get physmem +#endif + len = sizeof(mem_val); if (sysctl(mib, 2, &mem_val, &len, NULL, 0) != -1) { assert(len == sizeof(mem_val), "unexpected data size"); @@ -679,18 +691,12 @@ return NULL; } + osthread->set_thread_id(os::Bsd::gettid()); + #ifdef __APPLE__ - // thread_id is mach thread on macos, which pthreads graciously caches and provides for us - mach_port_t thread_id = ::pthread_mach_thread_np(::pthread_self()); - guarantee(thread_id != 0, "thread id missing from pthreads"); - osthread->set_thread_id(thread_id); - - uint64_t unique_thread_id = locate_unique_thread_id(thread_id); + uint64_t unique_thread_id = locate_unique_thread_id(osthread->thread_id()); guarantee(unique_thread_id != 0, "unique thread id was not found"); osthread->set_unique_thread_id(unique_thread_id); -#else - // thread_id is pthread_id on BSD - osthread->set_thread_id(::pthread_self()); #endif // initialize signal mask for this thread os::Bsd::hotspot_sigmask(thread); @@ -847,18 +853,13 @@ return false; } + osthread->set_thread_id(os::Bsd::gettid()); + // Store pthread info into the OSThread #ifdef __APPLE__ - // thread_id is mach thread on macos, which pthreads graciously caches and provides for us - mach_port_t thread_id = ::pthread_mach_thread_np(::pthread_self()); - guarantee(thread_id != 0, "just checking"); - osthread->set_thread_id(thread_id); - - uint64_t unique_thread_id = locate_unique_thread_id(thread_id); + uint64_t unique_thread_id = locate_unique_thread_id(osthread->thread_id()); guarantee(unique_thread_id != 0, "just checking"); osthread->set_unique_thread_id(unique_thread_id); -#else - osthread->set_thread_id(::pthread_self()); #endif osthread->set_pthread_id(::pthread_self()); @@ -1125,6 +1126,30 @@ return n; } +// Information of current thread in variety of formats +pid_t os::Bsd::gettid() { + int retval = -1; + +#ifdef __APPLE__ //XNU kernel + // despite the fact mach port is actually not a thread id use it + // instead of syscall(SYS_thread_selfid) as it certainly fits to u4 + retval = ::pthread_mach_thread_np(::pthread_self()); + guarantee(retval != 0, "just checking"); + return retval; + +#elif __FreeBSD__ + retval = syscall(SYS_thr_self); +#elif __OpenBSD__ + retval = syscall(SYS_getthrid); +#elif __NetBSD__ + retval = (pid_t) syscall(SYS__lwp_self); +#endif + + if (retval == -1) { + return getpid(); + } +} + intx os::current_thread_id() { #ifdef __APPLE__ return (intx)::pthread_mach_thread_np(::pthread_self()); @@ -1132,6 +1157,7 @@ return (intx)::pthread_self(); #endif } + int os::current_process_id() { // Under the old bsd thread library, bsd gives each thread @@ -1904,7 +1930,7 @@ bool timedwait(unsigned int sec, int nsec); private: jlong currenttime() const; - semaphore_t _semaphore; + os_semaphore_t _semaphore; }; Semaphore::Semaphore() : _semaphore(0) { @@ -1972,7 +1998,7 @@ bool Semaphore::timedwait(unsigned int sec, int nsec) { struct timespec ts; - jlong endtime = unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); + unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); while (1) { int result = sem_timedwait(&_semaphore, &ts); diff -r 798522662fcd -r 2720ab7a0d70 src/os/bsd/vm/os_bsd.hpp --- a/src/os/bsd/vm/os_bsd.hpp Fri Oct 04 13:37:25 2013 -0700 +++ b/src/os/bsd/vm/os_bsd.hpp Fri Oct 04 21:00:43 2013 -0700 @@ -84,6 +84,7 @@ static void hotspot_sigmask(Thread* thread); static bool is_initial_thread(void); + static pid_t gettid(); static int page_size(void) { return _page_size; } static void set_page_size(int val) { _page_size = val; } diff -r 798522662fcd -r 2720ab7a0d70 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Fri Oct 04 13:37:25 2013 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Fri Oct 04 21:00:43 2013 -0700 @@ -1376,8 +1376,15 @@ const char* klass_name = holder->external_name(); int buf_len = (int)strlen(klass_name); - // pushing to the stack trace added one. + // The method id may point to an obsolete method, can't get more stack information Method* method = holder->method_with_idnum(method_id); + if (method == NULL) { + char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); + // This is what the java code prints in this case - added Redefined + sprintf(buf, "\tat %s.null (Redefined)", klass_name); + return buf; + } + char* method_name = method->name()->as_C_string(); buf_len += (int)strlen(method_name); @@ -1773,7 +1780,8 @@ return element; } -oop java_lang_StackTraceElement::create(Handle mirror, int method_id, int version, int bci, TRAPS) { +oop java_lang_StackTraceElement::create(Handle mirror, int method_id, + int version, int bci, TRAPS) { // Allocate java.lang.StackTraceElement instance Klass* k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); @@ -1790,8 +1798,16 @@ oop classname = StringTable::intern((char*) str, CHECK_0); java_lang_StackTraceElement::set_declaringClass(element(), classname); + Method* method = holder->method_with_idnum(method_id); + // Method on stack may be obsolete because it was redefined so cannot be + // found by idnum. + if (method == NULL) { + // leave name and fileName null + java_lang_StackTraceElement::set_lineNumber(element(), -1); + return element(); + } + // Fill in method name - Method* method = holder->method_with_idnum(method_id); oop methodname = StringTable::intern(method->name(), CHECK_0); java_lang_StackTraceElement::set_methodName(element(), methodname); diff -r 798522662fcd -r 2720ab7a0d70 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Fri Oct 04 13:37:25 2013 -0700 +++ b/src/share/vm/oops/instanceKlass.cpp Fri Oct 04 21:00:43 2013 -0700 @@ -456,14 +456,14 @@ return java_lang_Class::signers(java_mirror()); } -volatile oop InstanceKlass::init_lock() const { +oop InstanceKlass::init_lock() const { // return the init lock from the mirror return java_lang_Class::init_lock(java_mirror()); } void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_oop) { EXCEPTION_MARK; - volatile oop init_lock = this_oop->init_lock(); + oop init_lock = this_oop->init_lock(); ObjectLocker ol(init_lock, THREAD); // abort if someone beat us to the initialization @@ -608,7 +608,7 @@ // verification & rewriting { - volatile oop init_lock = this_oop->init_lock(); + oop init_lock = this_oop->init_lock(); ObjectLocker ol(init_lock, THREAD); // rewritten will have been set if loader constraint error found // on an earlier link attempt @@ -731,7 +731,7 @@ // refer to the JVM book page 47 for description of steps // Step 1 { - volatile oop init_lock = this_oop->init_lock(); + oop init_lock = this_oop->init_lock(); ObjectLocker ol(init_lock, THREAD); Thread *self = THREAD; // it's passed the current thread @@ -879,7 +879,7 @@ } void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_oop, ClassState state, TRAPS) { - volatile oop init_lock = this_oop->init_lock(); + oop init_lock = this_oop->init_lock(); ObjectLocker ol(init_lock, THREAD); this_oop->set_init_state(state); ol.notify_all(CHECK); diff -r 798522662fcd -r 2720ab7a0d70 src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Fri Oct 04 13:37:25 2013 -0700 +++ b/src/share/vm/oops/instanceKlass.hpp Fri Oct 04 21:00:43 2013 -0700 @@ -995,7 +995,7 @@ // Must be one per class and it has to be a VM internal object so java code // cannot lock it (like the mirror). // It has to be an object not a Mutex because it's held through java calls. - volatile oop init_lock() const; + oop init_lock() const; private: // Static methods that are used to implement member methods where an exposed this pointer diff -r 798522662fcd -r 2720ab7a0d70 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Fri Oct 04 13:37:25 2013 -0700 +++ b/src/share/vm/prims/jvm.cpp Fri Oct 04 21:00:43 2013 -0700 @@ -3954,248 +3954,6 @@ } -// Serialization -JVM_ENTRY(void, JVM_SetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj, - jlongArray fieldIDs, jcharArray typecodes, jbyteArray data)) - assert(!JDK_Version::is_gte_jdk14x_version(), "should only be used in 1.3.1 and earlier"); - - typeArrayOop tcodes = typeArrayOop(JNIHandles::resolve(typecodes)); - typeArrayOop dbuf = typeArrayOop(JNIHandles::resolve(data)); - typeArrayOop fids = typeArrayOop(JNIHandles::resolve(fieldIDs)); - oop o = JNIHandles::resolve(obj); - - if (o == NULL || fids == NULL || dbuf == NULL || tcodes == NULL) { - THROW(vmSymbols::java_lang_NullPointerException()); - } - - jsize nfids = fids->length(); - if (nfids == 0) return; - - if (tcodes->length() < nfids) { - THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); - } - - jsize off = 0; - /* loop through fields, setting values */ - for (jsize i = 0; i < nfids; i++) { - jfieldID fid = (jfieldID)(intptr_t) fids->long_at(i); - int field_offset; - if (fid != NULL) { - // NULL is a legal value for fid, but retrieving the field offset - // trigger assertion in that case - field_offset = jfieldIDWorkaround::from_instance_jfieldID(o->klass(), fid); - } - - switch (tcodes->char_at(i)) { - case 'Z': - if (fid != NULL) { - jboolean val = (dbuf->byte_at(off) != 0) ? JNI_TRUE : JNI_FALSE; - o->bool_field_put(field_offset, val); - } - off++; - break; - - case 'B': - if (fid != NULL) { - o->byte_field_put(field_offset, dbuf->byte_at(off)); - } - off++; - break; - - case 'C': - if (fid != NULL) { - jchar val = ((dbuf->byte_at(off + 0) & 0xFF) << 8) - + ((dbuf->byte_at(off + 1) & 0xFF) << 0); - o->char_field_put(field_offset, val); - } - off += 2; - break; - - case 'S': - if (fid != NULL) { - jshort val = ((dbuf->byte_at(off + 0) & 0xFF) << 8) - + ((dbuf->byte_at(off + 1) & 0xFF) << 0); - o->short_field_put(field_offset, val); - } - off += 2; - break; - - case 'I': - if (fid != NULL) { - jint ival = ((dbuf->byte_at(off + 0) & 0xFF) << 24) - + ((dbuf->byte_at(off + 1) & 0xFF) << 16) - + ((dbuf->byte_at(off + 2) & 0xFF) << 8) - + ((dbuf->byte_at(off + 3) & 0xFF) << 0); - o->int_field_put(field_offset, ival); - } - off += 4; - break; - - case 'F': - if (fid != NULL) { - jint ival = ((dbuf->byte_at(off + 0) & 0xFF) << 24) - + ((dbuf->byte_at(off + 1) & 0xFF) << 16) - + ((dbuf->byte_at(off + 2) & 0xFF) << 8) - + ((dbuf->byte_at(off + 3) & 0xFF) << 0); - jfloat fval = (*int_bits_to_float_fn)(env, NULL, ival); - o->float_field_put(field_offset, fval); - } - off += 4; - break; - - case 'J': - if (fid != NULL) { - jlong lval = (((jlong) dbuf->byte_at(off + 0) & 0xFF) << 56) - + (((jlong) dbuf->byte_at(off + 1) & 0xFF) << 48) - + (((jlong) dbuf->byte_at(off + 2) & 0xFF) << 40) - + (((jlong) dbuf->byte_at(off + 3) & 0xFF) << 32) - + (((jlong) dbuf->byte_at(off + 4) & 0xFF) << 24) - + (((jlong) dbuf->byte_at(off + 5) & 0xFF) << 16) - + (((jlong) dbuf->byte_at(off + 6) & 0xFF) << 8) - + (((jlong) dbuf->byte_at(off + 7) & 0xFF) << 0); - o->long_field_put(field_offset, lval); - } - off += 8; - break; - - case 'D': - if (fid != NULL) { - jlong lval = (((jlong) dbuf->byte_at(off + 0) & 0xFF) << 56) - + (((jlong) dbuf->byte_at(off + 1) & 0xFF) << 48) - + (((jlong) dbuf->byte_at(off + 2) & 0xFF) << 40) - + (((jlong) dbuf->byte_at(off + 3) & 0xFF) << 32) - + (((jlong) dbuf->byte_at(off + 4) & 0xFF) << 24) - + (((jlong) dbuf->byte_at(off + 5) & 0xFF) << 16) - + (((jlong) dbuf->byte_at(off + 6) & 0xFF) << 8) - + (((jlong) dbuf->byte_at(off + 7) & 0xFF) << 0); - jdouble dval = (*long_bits_to_double_fn)(env, NULL, lval); - o->double_field_put(field_offset, dval); - } - off += 8; - break; - - default: - // Illegal typecode - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "illegal typecode"); - } - } -JVM_END - - -JVM_ENTRY(void, JVM_GetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj, - jlongArray fieldIDs, jcharArray typecodes, jbyteArray data)) - assert(!JDK_Version::is_gte_jdk14x_version(), "should only be used in 1.3.1 and earlier"); - - typeArrayOop tcodes = typeArrayOop(JNIHandles::resolve(typecodes)); - typeArrayOop dbuf = typeArrayOop(JNIHandles::resolve(data)); - typeArrayOop fids = typeArrayOop(JNIHandles::resolve(fieldIDs)); - oop o = JNIHandles::resolve(obj); - - if (o == NULL || fids == NULL || dbuf == NULL || tcodes == NULL) { - THROW(vmSymbols::java_lang_NullPointerException()); - } - - jsize nfids = fids->length(); - if (nfids == 0) return; - - if (tcodes->length() < nfids) { - THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); - } - - /* loop through fields, fetching values */ - jsize off = 0; - for (jsize i = 0; i < nfids; i++) { - jfieldID fid = (jfieldID)(intptr_t) fids->long_at(i); - if (fid == NULL) { - THROW(vmSymbols::java_lang_NullPointerException()); - } - int field_offset = jfieldIDWorkaround::from_instance_jfieldID(o->klass(), fid); - - switch (tcodes->char_at(i)) { - case 'Z': - { - jboolean val = o->bool_field(field_offset); - dbuf->byte_at_put(off++, (val != 0) ? 1 : 0); - } - break; - - case 'B': - dbuf->byte_at_put(off++, o->byte_field(field_offset)); - break; - - case 'C': - { - jchar val = o->char_field(field_offset); - dbuf->byte_at_put(off++, (val >> 8) & 0xFF); - dbuf->byte_at_put(off++, (val >> 0) & 0xFF); - } - break; - - case 'S': - { - jshort val = o->short_field(field_offset); - dbuf->byte_at_put(off++, (val >> 8) & 0xFF); - dbuf->byte_at_put(off++, (val >> 0) & 0xFF); - } - break; - - case 'I': - { - jint val = o->int_field(field_offset); - dbuf->byte_at_put(off++, (val >> 24) & 0xFF); - dbuf->byte_at_put(off++, (val >> 16) & 0xFF); - dbuf->byte_at_put(off++, (val >> 8) & 0xFF); - dbuf->byte_at_put(off++, (val >> 0) & 0xFF); - } - break; - - case 'F': - { - jfloat fval = o->float_field(field_offset); - jint ival = (*float_to_int_bits_fn)(env, NULL, fval); - dbuf->byte_at_put(off++, (ival >> 24) & 0xFF); - dbuf->byte_at_put(off++, (ival >> 16) & 0xFF); - dbuf->byte_at_put(off++, (ival >> 8) & 0xFF); - dbuf->byte_at_put(off++, (ival >> 0) & 0xFF); - } - break; - - case 'J': - { - jlong val = o->long_field(field_offset); - dbuf->byte_at_put(off++, (val >> 56) & 0xFF); - dbuf->byte_at_put(off++, (val >> 48) & 0xFF); - dbuf->byte_at_put(off++, (val >> 40) & 0xFF); - dbuf->byte_at_put(off++, (val >> 32) & 0xFF); - dbuf->byte_at_put(off++, (val >> 24) & 0xFF); - dbuf->byte_at_put(off++, (val >> 16) & 0xFF); - dbuf->byte_at_put(off++, (val >> 8) & 0xFF); - dbuf->byte_at_put(off++, (val >> 0) & 0xFF); - } - break; - - case 'D': - { - jdouble dval = o->double_field(field_offset); - jlong lval = (*double_to_long_bits_fn)(env, NULL, dval); - dbuf->byte_at_put(off++, (lval >> 56) & 0xFF); - dbuf->byte_at_put(off++, (lval >> 48) & 0xFF); - dbuf->byte_at_put(off++, (lval >> 40) & 0xFF); - dbuf->byte_at_put(off++, (lval >> 32) & 0xFF); - dbuf->byte_at_put(off++, (lval >> 24) & 0xFF); - dbuf->byte_at_put(off++, (lval >> 16) & 0xFF); - dbuf->byte_at_put(off++, (lval >> 8) & 0xFF); - dbuf->byte_at_put(off++, (lval >> 0) & 0xFF); - } - break; - - default: - // Illegal typecode - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "illegal typecode"); - } - } -JVM_END - // Shared JNI/JVM entry points ////////////////////////////////////////////////////////////// diff -r 798522662fcd -r 2720ab7a0d70 src/share/vm/prims/jvm_misc.hpp --- a/src/share/vm/prims/jvm_misc.hpp Fri Oct 04 13:37:25 2013 -0700 +++ b/src/share/vm/prims/jvm_misc.hpp Fri Oct 04 21:00:43 2013 -0700 @@ -36,22 +36,6 @@ void trace_class_resolution(Klass* to_class); /* - * Support for Serialization and RMI. Currently used by HotSpot only. - */ - -extern "C" { - -void JNICALL -JVM_SetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj, - jlongArray fieldIDs, jcharArray typecodes, jbyteArray data); - -void JNICALL -JVM_GetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj, - jlongArray fieldIDs, jcharArray typecodes, jbyteArray data); - -} - -/* * Support for -Xcheck:jni */ diff -r 798522662fcd -r 2720ab7a0d70 src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Oct 04 13:37:25 2013 -0700 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Oct 04 21:00:43 2013 -0700 @@ -2931,7 +2931,8 @@ old_method->set_is_obsolete(); obsolete_count++; - // obsolete methods need a unique idnum + // obsolete methods need a unique idnum so they become new entries in + // the jmethodID cache in InstanceKlass u2 num = InstanceKlass::cast(_the_class_oop)->next_method_idnum(); if (num != ConstMethod::UNSET_IDNUM) { old_method->set_method_idnum(num); diff -r 798522662fcd -r 2720ab7a0d70 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Fri Oct 04 13:37:25 2013 -0700 +++ b/src/share/vm/prims/nativeLookup.cpp Fri Oct 04 21:00:43 2013 -0700 @@ -129,10 +129,6 @@ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) static JNINativeMethod lookup_special_native_methods[] = { - // Next two functions only exist for compatibility with 1.3.1 and earlier. - { CC"Java_java_io_ObjectOutputStream_getPrimitiveFieldValues", NULL, FN_PTR(JVM_GetPrimitiveFieldValues) }, // intercept ObjectOutputStream getPrimitiveFieldValues for faster serialization - { CC"Java_java_io_ObjectInputStream_setPrimitiveFieldValues", NULL, FN_PTR(JVM_SetPrimitiveFieldValues) }, // intercept ObjectInputStream setPrimitiveFieldValues for faster serialization - { CC"Java_sun_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterUnsafeMethods) }, { CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) }, { CC"Java_sun_misc_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) }, @@ -140,9 +136,8 @@ }; static address lookup_special_native(char* jni_name) { - int i = !JDK_Version::is_gte_jdk14x_version() ? 0 : 2; // see comment in lookup_special_native_methods int count = sizeof(lookup_special_native_methods) / sizeof(JNINativeMethod); - for (; i < count; i++) { + for (int i = 0; i < count; i++) { // NB: To ignore the jni prefix and jni postfix strstr is used matching. if (strstr(jni_name, lookup_special_native_methods[i].name) != NULL) { return CAST_FROM_FN_PTR(address, lookup_special_native_methods[i].fnPtr); diff -r 798522662fcd -r 2720ab7a0d70 src/share/vm/prims/wbtestmethods/parserTests.cpp --- a/src/share/vm/prims/wbtestmethods/parserTests.cpp Fri Oct 04 13:37:25 2013 -0700 +++ b/src/share/vm/prims/wbtestmethods/parserTests.cpp Fri Oct 04 21:00:43 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,11 +117,12 @@ const char* c_cmdline = java_lang_String::as_utf8_string(JNIHandles::resolve(j_cmdline)); objArrayOop argumentArray = objArrayOop(JNIHandles::resolve_non_null(arguments)); + objArrayHandle argumentArray_ah(THREAD, argumentArray); - int length = argumentArray->length(); + int length = argumentArray_ah->length(); for (int i = 0; i < length; i++) { - oop argument_oop = argumentArray->obj_at(i); + oop argument_oop = argumentArray_ah->obj_at(i); fill_in_parser(&parser, argument_oop); } @@ -130,19 +131,20 @@ Klass* k = SystemDictionary::Object_klass(); objArrayOop returnvalue_array = oopFactory::new_objArray(k, parser.num_arguments() * 2, CHECK_NULL); + objArrayHandle returnvalue_array_ah(THREAD, returnvalue_array); GrowableArray*parsedArgNames = parser.argument_name_array(); for (int i = 0; i < parser.num_arguments(); i++) { oop parsedName = java_lang_String::create_oop_from_str(parsedArgNames->at(i), CHECK_NULL); - returnvalue_array->obj_at_put(i*2, parsedName); + returnvalue_array_ah->obj_at_put(i*2, parsedName); GenDCmdArgument* arg = parser.lookup_dcmd_option(parsedArgNames->at(i), strlen(parsedArgNames->at(i))); char buf[VALUE_MAXLEN]; arg->value_as_str(buf, sizeof(buf)); oop parsedValue = java_lang_String::create_oop_from_str(buf, CHECK_NULL); - returnvalue_array->obj_at_put(i*2+1, parsedValue); + returnvalue_array_ah->obj_at_put(i*2+1, parsedValue); } - return (jobjectArray) JNIHandles::make_local(returnvalue_array); + return (jobjectArray) JNIHandles::make_local(returnvalue_array_ah()); WB_END diff -r 798522662fcd -r 2720ab7a0d70 test/TEST.groups --- a/test/TEST.groups Fri Oct 04 13:37:25 2013 -0700 +++ b/test/TEST.groups Fri Oct 04 21:00:43 2013 -0700 @@ -65,7 +65,6 @@ gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java \ gc/metaspace/TestMetaspacePerfCounters.java \ runtime/6819213/TestBootNativeLibraryPath.java \ - runtime/6878713/Test6878713.sh \ runtime/6925573/SortMethodsTest.java \ runtime/7107135/Test7107135.sh \ runtime/7158988/FieldMonitor.java \