Sun, 22 Sep 2013 18:49:09 +0400
7133122: SA throws sun.jvm.hotspot.debugger.UnmappedAddressException when it should not
Summary: replace PT_LOAD segment with library segment when necessary
Reviewed-by: dholmes, sla
agent/src/os/linux/ps_core.c | file | annotate | diff | comparison | revisions |
1.1 --- a/agent/src/os/linux/ps_core.c Fri Sep 20 18:19:07 2013 -0700 1.2 +++ b/agent/src/os/linux/ps_core.c Sun Sep 22 18:49:09 2013 +0400 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -698,29 +698,58 @@ 1.11 1.12 // read segments of a shared object 1.13 static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* lib_ehdr, uintptr_t lib_base) { 1.14 - int i = 0; 1.15 - ELF_PHDR* phbuf; 1.16 - ELF_PHDR* lib_php = NULL; 1.17 + int i = 0; 1.18 + ELF_PHDR* phbuf; 1.19 + ELF_PHDR* lib_php = NULL; 1.20 1.21 - if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) 1.22 - return false; 1.23 + int page_size=sysconf(_SC_PAGE_SIZE); 1.24 1.25 - // we want to process only PT_LOAD segments that are not writable. 1.26 - // i.e., text segments. The read/write/exec (data) segments would 1.27 - // have been already added from core file segments. 1.28 - for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) { 1.29 - if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) { 1.30 - if (add_map_info(ph, lib_fd, lib_php->p_offset, lib_php->p_vaddr + lib_base, lib_php->p_filesz) == NULL) 1.31 - goto err; 1.32 + if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) { 1.33 + return false; 1.34 + } 1.35 + 1.36 + // we want to process only PT_LOAD segments that are not writable. 1.37 + // i.e., text segments. The read/write/exec (data) segments would 1.38 + // have been already added from core file segments. 1.39 + for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) { 1.40 + if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) { 1.41 + 1.42 + uintptr_t target_vaddr = lib_php->p_vaddr + lib_base; 1.43 + map_info *existing_map = core_lookup(ph, target_vaddr); 1.44 + 1.45 + if (existing_map == NULL){ 1.46 + if (add_map_info(ph, lib_fd, lib_php->p_offset, 1.47 + target_vaddr, lib_php->p_filesz) == NULL) { 1.48 + goto err; 1.49 + } 1.50 + } else { 1.51 + if ((existing_map->memsz != page_size) && 1.52 + (existing_map->fd != lib_fd) && 1.53 + (existing_map->memsz != lib_php->p_filesz)){ 1.54 + 1.55 + print_debug("address conflict @ 0x%lx (size = %ld, flags = %d\n)", 1.56 + target_vaddr, lib_php->p_filesz, lib_php->p_flags); 1.57 + goto err; 1.58 + } 1.59 + 1.60 + /* replace PT_LOAD segment with library segment */ 1.61 + print_debug("overwrote with new address mapping (memsz %ld -> %ld)\n", 1.62 + existing_map->memsz, lib_php->p_filesz); 1.63 + 1.64 + existing_map->fd = lib_fd; 1.65 + existing_map->offset = lib_php->p_offset; 1.66 + existing_map->memsz = lib_php->p_filesz; 1.67 } 1.68 - lib_php++; 1.69 - } 1.70 + } 1.71 1.72 - free(phbuf); 1.73 - return true; 1.74 + lib_php++; 1.75 + } 1.76 + 1.77 + free(phbuf); 1.78 + return true; 1.79 err: 1.80 - free(phbuf); 1.81 - return false; 1.82 + free(phbuf); 1.83 + return false; 1.84 } 1.85 1.86 // process segments from interpreter (ld.so or ld-linux.so)