changeset 23520:86ab5bae08bd

7189721: nightly tests failed on JDI attaching Summary: If for some reason elf section with section names is not loaded to cache it attempts to read data using NULL section pointer. Reviewed-by: sspitsyn, sla, kevinw
author dsamersoff
date Mon, 31 Mar 2014 08:23:02 -0700
parents 9a78876cefeb
children d6b7406c492e
files hotspot/agent/src/os/linux/symtab.c
diffstat 1 files changed, 15 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/hotspot/agent/src/os/linux/symtab.c	Sun Mar 30 03:29:48 2014 -0700
+++ b/hotspot/agent/src/os/linux/symtab.c	Mon Mar 31 08:23:02 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, 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
@@ -162,28 +162,27 @@
 static struct elf_section *find_section_by_name(char *name,
                                                 int fd,
                                                 ELF_EHDR *ehdr,
-                                                ELF_SHDR *shbuf,
                                                 struct elf_section *scn_cache)
 {
-  ELF_SHDR* cursct = NULL;
   char *strtab;
   int cnt;
+  int strtab_size;
 
+  // Section cache have to already contain data for e_shstrndx section.
+  // If it's not true - elf file is broken, so just bail out
   if (scn_cache[ehdr->e_shstrndx].c_data == NULL) {
-    if ((scn_cache[ehdr->e_shstrndx].c_data
-         = read_section_data(fd, ehdr, cursct)) == NULL) {
-      return NULL;
-    }
+    return NULL;
   }
 
   strtab = scn_cache[ehdr->e_shstrndx].c_data;
+  strtab_size = scn_cache[ehdr->e_shstrndx].c_shdr->sh_size;
 
-  for (cursct = shbuf, cnt = 0;
-       cnt < ehdr->e_shnum;
-       cnt++, cursct++) {
-    if (strcmp(cursct->sh_name + strtab, name) == 0) {
-      scn_cache[cnt].c_data = read_section_data(fd, ehdr, cursct);
-      return &scn_cache[cnt];
+  for (cnt = 0; cnt < ehdr->e_shnum; ++cnt) {
+    if (scn_cache[cnt].c_shdr->sh_name < strtab_size) {
+      if (strcmp(scn_cache[cnt].c_shdr->sh_name + strtab, name) == 0) {
+        scn_cache[cnt].c_data = read_section_data(fd, ehdr, scn_cache[cnt].c_shdr);
+        return &scn_cache[cnt];
+      }
     }
   }
 
@@ -195,12 +194,11 @@
 static int open_file_from_debug_link(const char *name,
                                      int fd,
                                      ELF_EHDR *ehdr,
-                                     ELF_SHDR *shbuf,
                                      struct elf_section *scn_cache)
 {
   int debug_fd;
   struct elf_section *debug_link = find_section_by_name(".gnu_debuglink", fd, ehdr,
-                                                        shbuf, scn_cache);
+                                                         scn_cache);
   if (debug_link == NULL)
     return -1;
   char *debug_filename = debug_link->c_data;
@@ -221,7 +219,6 @@
 
   /* Look in the same directory as the object.  */
   strcpy(last_slash+1, debug_filename);
-
   debug_fd = open_debug_file(debug_pathname, crc);
   if (debug_fd >= 0) {
     free(debug_pathname);
@@ -261,10 +258,9 @@
 static struct symtab *build_symtab_from_debug_link(const char *name,
                                      int fd,
                                      ELF_EHDR *ehdr,
-                                     ELF_SHDR *shbuf,
                                      struct elf_section *scn_cache)
 {
-  fd = open_file_from_debug_link(name, fd, ehdr, shbuf, scn_cache);
+  fd = open_file_from_debug_link(name, fd, ehdr, scn_cache);
 
   if (fd >= 0) {
     struct symtab *symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false);
@@ -463,7 +459,7 @@
 
     // Then, if that doesn't work, the debug link
     if (symtab == NULL) {
-      symtab = build_symtab_from_debug_link(filename, fd, &ehdr, shbuf,
+      symtab = build_symtab_from_debug_link(filename, fd, &ehdr,
                                             scn_cache);
     }