changeset 5128:ff798ea71518

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
author vkempik
date Tue, 10 Dec 2013 14:17:19 +0400
parents 2f8624935bd2
children 032149b2891f
files agent/src/os/linux/ps_core.c
diffstat 1 files changed, 29 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/agent/src/os/linux/ps_core.c	Mon Dec 09 17:10:50 2013 +0100
+++ b/agent/src/os/linux/ps_core.c	Tue Dec 10 14:17:19 2013 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -704,6 +704,8 @@
    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;
 
@@ -712,8 +714,32 @@
    // 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;
+         uintptr_t target_vaddr = lib_php->p_vaddr + lib_base;
+         map_info *existing_map = core_lookup(ph, target_vaddr);
+
+         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++;
    }