1 /*
   2  * Copyright (c) 2015, 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  */
  24 
  25 #include "runtime/thread.inline.hpp"
  26 #include "precompiled.hpp"
  27 #include "classfile/imageDecompressor.hpp"
  28 #include "runtime/thread.hpp"
  29 #include "utilities/bytes.hpp"
  30 
  31 /*
  32  * Allocate in C Heap not in resource area, otherwise JVM crashes.
  33  * This array life time is the VM life time. Array is never freed and
  34  * is not expected to contain more than few references.
  35  */
  36 GrowableArray<ImageDecompressor*>* ImageDecompressor::_decompressors =
  37   new(ResourceObj::C_HEAP, mtInternal) GrowableArray<ImageDecompressor*>(2, true);
  38 
  39 static Symbol* createSymbol(const char* str) {
  40   Thread* THREAD = Thread::current();
  41   Symbol* sym = SymbolTable::lookup(str, (int) strlen(str), THREAD);
  42   if (HAS_PENDING_EXCEPTION) {
  43     warning("can't create symbol\n");
  44     CLEAR_PENDING_EXCEPTION;
  45     return NULL;
  46   }
  47   return sym;
  48 }
  49 
  50 /*
  51  * Initialize the array of decompressors.
  52  */
  53 bool image_decompressor_init() {
  54   Symbol* zipSymbol = createSymbol("zip");
  55   if (zipSymbol == NULL) {
  56     return false;
  57   }
  58   ImageDecompressor::add_decompressor(new ZipDecompressor(zipSymbol));
  59 
  60   return true;
  61 }
  62 
  63 /*
  64  * Decompression entry point. Called from ImageFileReader::get_resource.
  65  */
  66 void ImageDecompressor::decompress_resource(u1* compressed, u1* uncompressed,
  67         u4 uncompressed_size, const ImageStrings* strings, bool is_C_heap) {
  68   bool has_header = false;
  69   u1* decompressed_resource = compressed;
  70   u1* compressed_resource = compressed;
  71 
  72   // Resource could have been transformed by a stack of decompressors.
  73   // Iterate and decompress resources until there is no more header.
  74   do {
  75     ResourceHeader _header;
  76     memcpy(&_header, compressed_resource, sizeof (ResourceHeader));
  77     has_header = _header._magic == ResourceHeader::resource_header_magic;
  78     if (has_header) {
  79       // decompressed_resource array contains the result of decompression
  80       // when a resource content is terminal, it means that it is an actual resource,
  81       // not an intermediate not fully uncompressed content. In this case
  82       // the resource is allocated as an mtClass, otherwise as an mtOther
  83       decompressed_resource = is_C_heap && _header._is_terminal ?
  84               NEW_C_HEAP_ARRAY(u1, _header._uncompressed_size, mtClass) :
  85               NEW_C_HEAP_ARRAY(u1, _header._uncompressed_size, mtOther);
  86       // Retrieve the decompressor name
  87       const char* decompressor_name = strings->get(_header._decompressor_name_offset);
  88       if (decompressor_name == NULL) warning("image decompressor not found\n");
  89       guarantee(decompressor_name, "image decompressor not found");
  90       // Retrieve the decompressor instance
  91       ImageDecompressor* decompressor = get_decompressor(decompressor_name);
  92       if (decompressor == NULL) {
  93         warning("image decompressor %s not found\n", decompressor_name);
  94       }
  95       guarantee(decompressor, "image decompressor not found");
  96       u1* compressed_resource_base = compressed_resource;
  97       compressed_resource += ResourceHeader::resource_header_length;
  98       // Ask the decompressor to decompress the compressed content
  99       decompressor->decompress_resource(compressed_resource, decompressed_resource,
 100         &_header, strings);
 101       if (compressed_resource_base != compressed) {
 102         FREE_C_HEAP_ARRAY(char, compressed_resource_base);
 103       }
 104       compressed_resource = decompressed_resource;
 105     }
 106   } while (has_header);
 107   memcpy(uncompressed, decompressed_resource, uncompressed_size);
 108 }
 109 
 110 // Zip decompressor
 111 
 112 void ZipDecompressor::decompress_resource(u1* data, u1* uncompressed,
 113         ResourceHeader* header, const ImageStrings* strings) {
 114   char* msg = NULL;
 115   jboolean res = ClassLoader::decompress(data, header->_size, uncompressed,
 116           header->_uncompressed_size, &msg);
 117   if (!res) warning("decompression failed due to %s\n", msg);
 118   guarantee(res, "decompression failed");
 119 }
 120 
 121 // END Zip Decompressor