src/share/vm/memory/guardedMemory.hpp

Tue, 24 Feb 2015 15:04:52 -0500

author
dlong
date
Tue, 24 Feb 2015 15:04:52 -0500
changeset 7598
ddce0b7cee93
parent 7032
fa62fb12cdca
child 7627
d68158e12cea
permissions
-rw-r--r--

8072383: resolve conflicts between open and closed ports
Summary: refactor close to remove references to closed ports
Reviewed-by: kvn, simonis, sgehwolf, dholmes

     1 /*
     2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #ifndef SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
    26 #define SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
    28 #include "memory/allocation.hpp"
    29 #include "utilities/globalDefinitions.hpp"
    31 /**
    32  * Guarded memory for detecting buffer overrun.
    33  *
    34  * Allows allocations to be wrapped with padded bytes of a known byte pattern,
    35  * that is a "guard". Guard patterns may be verified to detect buffer overruns.
    36  *
    37  * Primarily used by "debug malloc" and "checked JNI".
    38  *
    39  * Memory layout:
    40  *
    41  * |Offset             | Content              | Description    |
    42  * |------------------------------------------------------------
    43  * |base_addr          | 0xABABABABABABABAB   | Head guard     |
    44  * |+16                | <size_t:user_size>   | User data size |
    45  * |+sizeof(uintptr_t) | <tag>                | Tag word       |
    46  * |+sizeof(void*)     | 0xF1 <user_data> (   | User data      |
    47  * |+user_size         | 0xABABABABABABABAB   | Tail guard     |
    48  * -------------------------------------------------------------
    49  *
    50  * Where:
    51  *  - guard padding uses "badResourceValue" (0xAB)
    52  *  - tag word is general purpose
    53  *  - user data
    54  *    -- initially padded with "uninitBlockPad" (0xF1),
    55  *    -- to "freeBlockPad" (0xBA), when freed
    56  *
    57  * Usage:
    58  *
    59  * * Allocations: one may wrap allocations with guard memory:
    60  * <code>
    61  *   Thing* alloc_thing() {
    62  *     void* mem = user_alloc_fn(GuardedMemory::get_total_size(sizeof(thing)));
    63  *     GuardedMemory guarded(mem, sizeof(thing));
    64  *     return (Thing*) guarded.get_user_ptr();
    65  *   }
    66  * </code>
    67  * * Verify: memory guards are still in tact
    68  * <code>
    69  *   bool verify_thing(Thing* thing) {
    70  *     GuardedMemory guarded((void*)thing);
    71  *     return guarded.verify_guards();
    72  *   }
    73  * </code>
    74  * * Free: one may mark bytes as freed (further debugging support)
    75  * <code>
    76  *   void free_thing(Thing* thing) {
    77  *    GuardedMemory guarded((void*)thing);
    78  *    assert(guarded.verify_guards(), "Corrupt thing");
    79  *    user_free_fn(guards.release_for_freeing();
    80  *   }
    81  * </code>
    82  */
    83 class GuardedMemory : StackObj { // Wrapper on stack
    85   // Private inner classes for memory layout...
    87 protected:
    89   /**
    90    * Guard class for header and trailer known pattern to test for overwrites.
    91    */
    92   class Guard { // Class for raw memory (no vtbl allowed)
    93     friend class GuardedMemory;
    94    protected:
    95     enum {
    96       GUARD_SIZE = 16
    97     };
    99     u_char _guard[GUARD_SIZE];
   101    public:
   103     void build() {
   104       u_char* c = _guard; // Possibly unaligned if tail guard
   105       u_char* end = c + GUARD_SIZE;
   106       while (c < end) {
   107         *c = badResourceValue;
   108         c++;
   109       }
   110     }
   112     bool verify() const {
   113       u_char* c = (u_char*) _guard;
   114       u_char* end = c + GUARD_SIZE;
   115       while (c < end) {
   116         if (*c != badResourceValue) {
   117           return false;
   118         }
   119         c++;
   120       }
   121       return true;
   122     }
   124   }; // GuardedMemory::Guard
   126   /**
   127    * Header guard and size
   128    */
   129   class GuardHeader : Guard {
   130     friend class GuardedMemory;
   131    protected:
   132     // Take care in modifying fields here, will effect alignment
   133     // e.g. x86 ABI 16 byte stack alignment
   134     union {
   135       uintptr_t __unused_full_word1;
   136       size_t _user_size;
   137     };
   138     void* _tag;
   139    public:
   140     void set_user_size(const size_t usz) { _user_size = usz; }
   141     size_t get_user_size() const { return _user_size; }
   143     void set_tag(const void* tag) { _tag = (void*) tag; }
   144     void* get_tag() const { return _tag; }
   146   }; // GuardedMemory::GuardHeader
   148   // Guarded Memory...
   150  protected:
   151   u_char* _base_addr;
   153  public:
   155   /**
   156    * Create new guarded memory.
   157    *
   158    * Wraps, starting at the given "base_ptr" with guards. Use "get_user_ptr()"
   159    * to return a pointer suitable for user data.
   160    *
   161    * @param base_ptr  allocation wishing to be wrapped, must be at least "GuardedMemory::get_total_size()" bytes.
   162    * @param user_size the size of the user data to be wrapped.
   163    * @param tag       optional general purpose tag.
   164    */
   165   GuardedMemory(void* base_ptr, const size_t user_size, const void* tag = NULL) {
   166     wrap_with_guards(base_ptr, user_size, tag);
   167   }
   169   /**
   170    * Wrap existing guarded memory.
   171    *
   172    * To use this constructor, one must have created guarded memory with
   173    * "GuardedMemory(void*, size_t, void*)" (or indirectly via helper, e.g. "wrap_copy()").
   174    *
   175    * @param user_p  existing wrapped memory.
   176    */
   177   GuardedMemory(void* userp) {
   178     u_char* user_ptr = (u_char*) userp;
   179     assert((uintptr_t)user_ptr > (sizeof(GuardHeader) + 0x1000), "Invalid pointer");
   180     _base_addr = (user_ptr - sizeof(GuardHeader));
   181   }
   183   /**
   184    * Create new guarded memory.
   185    *
   186    * Wraps, starting at the given "base_ptr" with guards. Allows reuse of stack allocated helper.
   187    *
   188    * @param base_ptr  allocation wishing to be wrapped, must be at least "GuardedMemory::get_total_size()" bytes.
   189    * @param user_size the size of the user data to be wrapped.
   190    * @param tag       optional general purpose tag.
   191    *
   192    * @return user data pointer (inner pointer to supplied "base_ptr").
   193    */
   194   void* wrap_with_guards(void* base_ptr, size_t user_size, const void* tag = NULL) {
   195     assert(base_ptr != NULL, "Attempt to wrap NULL with memory guard");
   196     _base_addr = (u_char*)base_ptr;
   197     get_head_guard()->build();
   198     get_head_guard()->set_user_size(user_size);
   199     get_tail_guard()->build();
   200     set_tag(tag);
   201     set_user_bytes(uninitBlockPad);
   202     assert(verify_guards(), "Expected valid memory guards");
   203     return get_user_ptr();
   204   }
   206   /**
   207    * Verify head and tail guards.
   208    *
   209    * @return true if guards are intact, false would indicate a buffer overrun.
   210    */
   211   bool verify_guards() const {
   212     if (_base_addr != NULL) {
   213       return (get_head_guard()->verify() && get_tail_guard()->verify());
   214     }
   215     return false;
   216   }
   218   /**
   219    * Set the general purpose tag.
   220    *
   221    * @param tag general purpose tag.
   222    */
   223   void set_tag(const void* tag) { get_head_guard()->set_tag(tag); }
   225   /**
   226    * Return the general purpose tag.
   227    *
   228    * @return the general purpose tag, defaults to NULL.
   229    */
   230   void* get_tag() const { return get_head_guard()->get_tag(); }
   232   /**
   233    * Return the size of the user data.
   234    *
   235    * @return the size of the user data.
   236    */
   237   size_t get_user_size() const {
   238     assert(_base_addr, "Not wrapping any memory");
   239     return get_head_guard()->get_user_size();
   240   }
   242   /**
   243    * Return the user data pointer.
   244    *
   245    * @return the user data pointer.
   246    */
   247   u_char* get_user_ptr() const {
   248     assert(_base_addr, "Not wrapping any memory");
   249     return _base_addr + sizeof(GuardHeader);
   250   }
   252   /**
   253    * Release the wrapped pointer for resource freeing.
   254    *
   255    * Pads the user data with "freeBlockPad", and dis-associates the helper.
   256    *
   257    * @return the original base pointer used to wrap the data.
   258    */
   259   void* release_for_freeing() {
   260     set_user_bytes(freeBlockPad);
   261     return release();
   262   }
   264   /**
   265    * Dis-associate the help from the original base address.
   266    *
   267    * @return the original base pointer used to wrap the data.
   268    */
   269   void* release() {
   270     void* p = (void*) _base_addr;
   271     _base_addr = NULL;
   272     return p;
   273   }
   275   virtual void print_on(outputStream* st) const;
   277  protected:
   278   GuardHeader*  get_head_guard() const { return (GuardHeader*) _base_addr; }
   279   Guard*        get_tail_guard() const { return (Guard*) (get_user_ptr() + get_user_size()); };
   280   void set_user_bytes(u_char ch) {
   281     memset(get_user_ptr(), ch, get_user_size());
   282   }
   284 public:
   285   /**
   286    * Return the total size required for wrapping the given user size.
   287    *
   288    * @return the total size required for wrapping the given user size.
   289    */
   290   static size_t get_total_size(size_t user_size) {
   291     size_t total_size = sizeof(GuardHeader) + user_size + sizeof(Guard);
   292     assert(total_size > user_size, "Unexpected wrap-around");
   293     return total_size;
   294   }
   296   // Helper functions...
   298   /**
   299    * Wrap a copy of size "len" of "ptr".
   300    *
   301    * @param ptr the memory to be copied
   302    * @param len the length of the copy
   303    * @param tag optional general purpose tag (see GuardedMemory::get_tag())
   304    *
   305    * @return guarded wrapped memory pointer to the user area, or NULL if OOM.
   306    */
   307   static void* wrap_copy(const void* p, const size_t len, const void* tag = NULL);
   309   /**
   310    * Free wrapped copy.
   311    *
   312    * Frees memory copied with "wrap_copy()".
   313    *
   314    * @param p memory returned by "wrap_copy()".
   315    *
   316    * @return true if guards were verified as intact. false indicates a buffer overrun.
   317    */
   318   static bool free_copy(void* p);
   320   // Testing...
   321 #ifndef PRODUCT
   322   static void test_guarded_memory(void);
   323 #endif
   324 }; // GuardedMemory
   326 #endif // SHARE_VM_MEMORY_GUARDED_MEMORY_HPP

mercurial