src/hotspot/share/utilities/elfStringTable.cpp
changeset 48975 2c35fd3c5789
parent 47765 b7c7428eaab9
child 51334 cc2c79d22508
--- a/src/hotspot/share/utilities/elfStringTable.cpp	Wed Feb 14 16:42:00 2018 +0100
+++ b/src/hotspot/share/utilities/elfStringTable.cpp	Wed Feb 14 17:20:59 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -33,58 +33,44 @@
 
 // We will try to load whole string table into memory if we can.
 // Otherwise, fallback to more expensive file operation.
-ElfStringTable::ElfStringTable(FILE* file, Elf_Shdr shdr, int index) {
-  assert(file, "null file handle");
-  m_table = NULL;
-  m_index = index;
-  m_next = NULL;
-  m_file = file;
-  m_status = NullDecoder::no_error;
-
-  // try to load the string table
-  long cur_offset = ftell(file);
-  m_table = (char*)os::malloc(sizeof(char) * shdr.sh_size, mtInternal);
-  if (m_table != NULL) {
-    // if there is an error, mark the error
-    if (fseek(file, shdr.sh_offset, SEEK_SET) ||
-      fread((void*)m_table, shdr.sh_size, 1, file) != 1 ||
-      fseek(file, cur_offset, SEEK_SET)) {
-      m_status = NullDecoder::file_invalid;
-      os::free((void*)m_table);
-      m_table = NULL;
-    }
-  } else {
-    memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr));
-  }
+ElfStringTable::ElfStringTable(FILE* const file, Elf_Shdr& shdr, int index) :
+  _section(file, shdr), _index(index), _fd(file), _next(NULL) {
+  _status = _section.status();
 }
 
 ElfStringTable::~ElfStringTable() {
-  if (m_table != NULL) {
-    os::free((void*)m_table);
-  }
-
-  if (m_next != NULL) {
-    delete m_next;
+  if (_next != NULL) {
+    delete _next;
   }
 }
 
-bool ElfStringTable::string_at(int pos, char* buf, int buflen) {
-  if (NullDecoder::is_error(m_status)) {
+bool ElfStringTable::string_at(size_t pos, char* buf, int buflen) {
+  if (NullDecoder::is_error(get_status())) {
+    return false;
+  }
+
+  assert(buflen > 0, "no buffer");
+  if (pos >= _section.section_header()->sh_size) {
     return false;
   }
-  if (m_table != NULL) {
-    jio_snprintf(buf, buflen, "%s", (const char*)(m_table + pos));
+
+  const char* data = (const char*)_section.section_data();
+  if (data != NULL) {
+    jio_snprintf(buf, buflen, "%s", data + pos);
     return true;
-  } else {
-    long cur_pos = ftell(m_file);
-    if (cur_pos == -1 ||
-      fseek(m_file, m_shdr.sh_offset + pos, SEEK_SET) ||
-      fread(buf, 1, buflen, m_file) <= 0 ||
-      fseek(m_file, cur_pos, SEEK_SET)) {
-      m_status = NullDecoder::file_invalid;
+  } else {  // no cache data, read from file instead
+    const Elf_Shdr* const shdr = _section.section_header();
+    MarkedFileReader mfd(_fd);
+    if (mfd.has_mark() &&
+      mfd.set_position(shdr->sh_offset + pos) &&
+      mfd.read((void*)buf, size_t(buflen))) {
+      buf[buflen - 1] = '\0';
+      return true;
+    } else {
+      // put it in error state to avoid retry
+      _status = NullDecoder::file_invalid;
       return false;
     }
-    return true;
   }
 }