JDK-4969341 : AMD64: Hotspot crashes with Suse 2.4.21 beta kernel
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 5.0
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic,linux_redhat_3.0
  • CPU: x86
  • Submitted: 2003-12-16
  • Updated: 2012-10-08
  • Resolved: 2004-01-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.2_05 05Fixed
Related Reports
Duplicate :  
Duplicate :  
Description
From Juergen Kreileder of Blackdown.

I've found the problem that caused crashes with SuSE's 2.4.21 AMD64
kernel:

,----[ Excerpt from linux-2.6.0-test10/Documentation/x86_64/boot-options.txt ]
| Non Executable Mappings
| 
|   noexec=on|off
| 
|   on      Enable
|   off     Disable
|   noforce (default) Don't enable by default for heap/stack/data,
|           but allow PROT_EXEC to be effective
| 
|   noexec32=opt{,opt}
| 
|   Control the no exec default for 32bit processes.
|   Requires noexec=on or noexec=noforce to be effective.
| 
|   Valid options:
|      all,on    Heap,stack,data is non executable.
|      off       (default) Heap,stack,data is executable
|      stack     Stack is non executable, heap/data is.
|      force     Don't imply PROT_EXEC for PROT_READ
|      compat    (default) Imply PROT_EXEC for PROT_READ
`----

2.4.21 doesn't have that documentation bit but it has the code for
this feature.  The 'noforce' setting seems to be a bit broken, on my
UP system (512) most code still worked, on my SMP machine (1024M) I
got crashes immediately when starting java.

The problematic code piece an AMD64 were the signature handlers:
allocated out of the heap but not marked executable.

Somebody apparently thought of this problem before and had already
added a call to os::unguard_memory().  But he missed the fact that the
Linux implementation (mprotect(2)) expects a page size aligned address.

Here's a fix for AMD64 (blatantly stolen from the IA64 version):

--- interpreterRT_amd64.cpp	25 Nov 2003 15:57:50 -0000	1.1.1.2
+++ interpreterRT_amd64.cpp	15 Dec 2003 07:03:32 -0000
@@ -276,9 +276,16 @@
   : public AllStatic 
 {
  public:
-  enum { size = 1024 }; // the size of the temporary code buffer
+  enum { size = 1 * K }; // the size of the temporary code buffer
+  enum { blob_size = 1 * K }; // the size of a handler code blob
 
  private:
+  // the current buffer blob containing the generated handlers
+  static BufferBlob* _handler_blob;
+
+  // next available address within _handler_blob;
+  static address _handler;
+
   // the fingerprint collection
   static GrowableArray<uint64_t>* _fingerprints;
 
@@ -288,15 +295,43 @@
   // the temporary code buffer
   static u_char _buffer[SignatureHandlerLibrary::size];
 
+  static address set_handler_blob()
+  {
+    BufferBlob* handler_blob = BufferBlob::create(blob_size,
+                                                  "native signature handlers");
+    if (handler_blob == NULL) {
+      fatal1("CodeCache: no room for %s", "native signature handlers");
+    }
+    address handler = handler_blob->instructions_begin();
+    _handler_blob = handler_blob;
+    _handler = handler;
+    return handler;
+  }
+
   static void initialize() 
   {
     if (_fingerprints != NULL) {
       return;
     }
+    (void) set_handler_blob();
     _fingerprints = new(ResourceObj::C_HEAP)GrowableArray<uint64_t>(32, true);
-    _handlers     = new(ResourceObj::C_HEAP)GrowableArray<address >(32, true);
+    _handlers = new(ResourceObj::C_HEAP)GrowableArray<address >(32, true);
   }
 
+  static address set_handler(CodeBuffer* buffer)
+  {
+    address handler = _handler;
+    int size = buffer->code_size();
+    if (handler + size > _handler_blob->instructions_end()) {
+      // get a new handler blob
+      handler = set_handler_blob();
+    }
+    memcpy(handler, buffer->code_begin(), size);
+    ICache::invalidate_range(handler, size);
+    _handler = handler + size;
+    return handler;
+   }
+
  public:
   static void add(methodHandle method) 
   {
@@ -315,16 +350,17 @@
         // create handler if necessary
         if (index < 0) {
           ResourceMark rm;
-          CodeBuffer* buffer = new CodeBuffer(_buffer, 
-                                              SignatureHandlerLibrary::size);
+          ptrdiff_t align_offset = (address)
+            round_to((intptr_t) _buffer, CodeEntryAlignment) -
+            (address)_buffer;
+          CodeBuffer* buffer = new CodeBuffer((address)
+                                              (_buffer + align_offset),
+                                              SignatureHandlerLibrary::size -
+                                              align_offset);
           InterpreterRuntime::SignatureHandlerGenerator(method, buffer).generate(fingerprint);
-          // copy into C-heap allocated memory location
-          address handler = (address)NEW_C_HEAP_ARRAY(u_char, buffer->code_size());
-          memcpy(handler, buffer->code_begin(), buffer->code_size());
-          ICache::invalidate_range(handler, buffer->code_size());
+          // copy into code heap
+          address handler = set_handler(buffer);
           // debugging suppport
           if (PrintSignatureHandlers) {
             tty->cr();
@@ -188,9 +226,11 @@
 };
 
 
+BufferBlob* SignatureHandlerLibrary::_handler_blob = NULL;
+address SignatureHandlerLibrary::_handler = NULL;
 GrowableArray<uint64_t>* SignatureHandlerLibrary::_fingerprints = NULL;
 GrowableArray<address >* SignatureHandlerLibrary::_handlers     = NULL;
-uint64_t SignatureHandlerLibrary::_buffer[SignatureHandlerLibrary::size/sizeof(uint64_t)+1];  // the temporary code buffer
+uchar SignatureHandlerLibrary::_buffer[SignatureHandlerLibrary::size];  // the temporary code buffer
 
 
 IRT_ENTRY(void, InterpreterRuntime::prepare_native_call(JavaThread* thread, methodOop method))

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.4.2_05 generic tiger-beta2 FIXED IN: 1.4.2_05 tiger-beta2 INTEGRATED IN: 1.4.2_05 tiger-b35 tiger-beta2 VERIFIED IN: tiger-beta2
14-06-2004

PUBLIC COMMENTS verified tiger beta2 b43 ###@###.### 2004-03-23
23-03-2004

EVALUATION Bug will cause an instant vm crash on OS's that require execute permission on memory containing native signature handler code. See the Description for the suggested fix, which is to steal the ia64 code. ###@###.### 2003-12-16
16-12-2003