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