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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <assert.h> 27 #include <string.h> 28 #include <stdlib.h> 29 30 #include "endian.hpp" 31 #include "imageDecompressor.hpp" 32 #include "imageFile.hpp" 33 #include "inttypes.hpp" 34 #include "jni.h" 35 #include "osSupport.hpp" 36 37 // Map the full jimage, only with 64 bit addressing. 38 bool MemoryMapImage = sizeof(void *) == 8; 39 40 #ifdef WIN32 41 const char FileSeparator = '\\'; 42 #else 43 const char FileSeparator = '/'; 44 #endif 45 46 // Image files are an alternate file format for storing classes and resources. The 47 // goal is to supply file access which is faster and smaller than the jar format. 48 // 49 // (More detailed nodes in the header.) 50 // 51 52 // Compute the Perfect Hashing hash code for the supplied UTF-8 string. 53 s4 ImageStrings::hash_code(const char* string, s4 seed) { 54 // Access bytes as unsigned. 55 u1* bytes = (u1*)string; 56 // Compute hash code. 57 for (u1 byte = *bytes++; byte; byte = *bytes++) { 58 seed = (seed * HASH_MULTIPLIER) ^ byte; 59 } 60 // Ensure the result is not signed. 61 return seed & 0x7FFFFFFF; 62 } 63 64 // Match up a string in a perfect hash table. 65 // Returns the index where the name should be. 66 // Result still needs validation for precise match (false positive.) 67 s4 ImageStrings::find(Endian* endian, const char* name, s4* redirect, u4 length) { 68 // If the table is empty, then short cut. 69 if (!redirect || !length) { 70 return NOT_FOUND; 71 } 72 // Compute the basic perfect hash for name. 73 s4 hash_code = ImageStrings::hash_code(name); 74 // Modulo table size. 75 s4 index = hash_code % length; 76 // Get redirect entry. 77 // value == 0 then not found 78 // value < 0 then -1 - value is true index 79 // value > 0 then value is seed for recomputing hash. 80 s4 value = endian->get(redirect[index]); 81 // if recompute is required. 82 if (value > 0 ) { 83 // Entry collision value, need to recompute hash. 84 hash_code = ImageStrings::hash_code(name, value); 85 // Modulo table size. 86 return hash_code % length; 87 } else if (value < 0) { 88 // Compute direct index. 89 return -1 - value; 90 } 91 // No entry found. 92 return NOT_FOUND; 93 } 94 95 // Test to see if UTF-8 string begins with the start UTF-8 string. If so, 96 // return non-NULL address of remaining portion of string. Otherwise, return 97 // NULL. Used to test sections of a path without copying from image string 98 // table. 99 const char* ImageStrings::starts_with(const char* string, const char* start) { 100 char ch1, ch2; 101 // Match up the strings the best we can. 102 while ((ch1 = *string) && (ch2 = *start)) { 103 if (ch1 != ch2) { 104 // Mismatch, return NULL. 105 return NULL; 106 } 107 // Next characters. 108 string++, start++; 109 } 110 // Return remainder of string. 111 return string; 112 } 113 114 // Inflates the attribute stream into individual values stored in the long 115 // array _attributes. This allows an attribute value to be quickly accessed by 116 // direct indexing. Unspecified values default to zero (from constructor.) 117 void ImageLocation::set_data(u1* data) { 118 // Deflate the attribute stream into an array of attributes. 119 u1 byte; 120 // Repeat until end header is found. 121 while ((byte = *data)) { 122 // Extract kind from header byte. 123 u1 kind = attribute_kind(byte); 124 assert(kind < ATTRIBUTE_COUNT && "invalid image location attribute"); 125 // Extract length of data (in bytes). 126 u1 n = attribute_length(byte); 127 // Read value (most significant first.) 128 _attributes[kind] = attribute_value(data + 1, n); 129 // Position to next attribute by skipping attribute header and data bytes. 130 data += n + 1; 131 } 132 } 133 134 // Zero all attribute values. 135 void ImageLocation::clear_data() { 136 // Set defaults to zero. 137 memset(_attributes, 0, sizeof(_attributes)); 138 } 139 140 // ImageModuleData constructor maps out sub-tables for faster access. 141 ImageModuleData::ImageModuleData(const ImageFileReader* image_file, 142 const char* module_data_name) : 143 _image_file(image_file), 144 _endian(image_file->endian()), 145 _strings(image_file->get_strings()) { 146 // Retrieve the resource containing the module data for the image file. 147 ImageLocation location; 148 bool found = image_file->find_location(module_data_name, location); 149 if (found) { 150 u8 data_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); 151 _data = new u1[(size_t)data_size]; 152 _image_file->get_resource(location, _data); 153 // Map out the header. 154 _header = (Header*)_data; 155 // Get the package to module entry count. 156 u4 ptm_count = _header->ptm_count(_endian); 157 // Get the module to package entry count. 158 u4 mtp_count = _header->mtp_count(_endian); 159 // Compute the offset of the package to module perfect hash redirect. 160 u4 ptm_redirect_offset = sizeof(Header); 161 // Compute the offset of the package to module data. 162 u4 ptm_data_offset = ptm_redirect_offset + ptm_count * sizeof(s4); 163 // Compute the offset of the module to package perfect hash redirect. 164 u4 mtp_redirect_offset = ptm_data_offset + ptm_count * sizeof(PTMData); 165 // Compute the offset of the module to package data. 166 u4 mtp_data_offset = mtp_redirect_offset + mtp_count * sizeof(s4); 167 // Compute the offset of the module to package tables. 168 u4 mtp_packages_offset = mtp_data_offset + mtp_count * sizeof(MTPData); 169 // Compute the address of the package to module perfect hash redirect. 170 _ptm_redirect = (s4*)(_data + ptm_redirect_offset); 171 // Compute the address of the package to module data. 172 _ptm_data = (PTMData*)(_data + ptm_data_offset); 173 // Compute the address of the module to package perfect hash redirect. 174 _mtp_redirect = (s4*)(_data + mtp_redirect_offset); 175 // Compute the address of the module to package data. 176 _mtp_data = (MTPData*)(_data + mtp_data_offset); 177 // Compute the address of the module to package tables. 178 _mtp_packages = (s4*)(_data + mtp_packages_offset); 179 } else { 180 // No module data present. 181 _data = NULL; 182 _header = NULL; 183 _ptm_redirect = NULL; 184 _ptm_data = NULL; 185 _mtp_redirect = NULL; 186 _mtp_data = NULL; 187 _mtp_packages = NULL; 188 } 189 } 190 191 // Release module data resource. 192 ImageModuleData::~ImageModuleData() { 193 if (_data) { 194 delete _data; 195 } 196 } 197 198 // Return the name of the module data resource. Ex. "./lib/modules/file.jimage" 199 // yields "file.jdata" 200 void ImageModuleData::module_data_name(char* buffer, const char* image_file_name) { 201 // Locate the last slash in the file name path. 202 const char* slash = strrchr(image_file_name, FileSeparator); 203 // Trim the path to name and extension. 204 const char* name = slash ? slash + 1 : (char *)image_file_name; 205 // Locate the extension period. 206 const char* dot = strrchr(name, '.'); 207 assert(dot && "missing extension on jimage name"); 208 // Trim to only base name. 209 int length = (int)(dot - name); 210 strncpy(buffer, name, length); 211 buffer[length] = '\0'; 212 // Append extension. 213 strcat(buffer, ".jdata"); 214 } 215 216 // Return the module in which a package resides. Returns NULL if not found. 217 const char* ImageModuleData::package_to_module(const char* package_name) { 218 // Test files may contain no module data. 219 if (_data != NULL) { 220 // Search the package to module table. 221 s4 index = ImageStrings::find(_endian, package_name, _ptm_redirect, 222 _header->ptm_count(_endian)); 223 // If entry is found. 224 if (index != ImageStrings::NOT_FOUND) { 225 // Retrieve the package to module entry. 226 PTMData* data = _ptm_data + index; 227 // Verify that it is the correct data. 228 if (strcmp(package_name, get_string(data->name_offset(_endian))) != 0) { 229 return NULL; 230 } 231 // Return the module name. 232 return get_string(data->module_name_offset(_endian)); 233 } 234 } 235 return NULL; 236 } 237 238 // Returns all the package names in a module in a NULL terminated array. 239 // Returns NULL if module not found. 240 const char** ImageModuleData::module_to_packages(const char* module_name) { 241 // Test files may contain no module data. 242 if (_data != NULL) { 243 // Search the module to package table. 244 s4 index = ImageStrings::find(_endian, module_name, _mtp_redirect, 245 _header->mtp_count(_endian)); 246 // If entry is found. 247 if (index != ImageStrings::NOT_FOUND) { 248 // Retrieve the module to package entry. 249 MTPData* data = _mtp_data + index; 250 // Verify that it is the correct data. 251 if (strcmp(module_name, get_string(data->name_offset(_endian))) != 0) { 252 return NULL; 253 } 254 // Construct an array of all the package entries. 255 u4 count = data->package_count(_endian); 256 const char** packages = new const char*[count + 1]; 257 s4 package_offset = data->package_offset(_endian); 258 for (u4 i = 0; i < count; i++) { 259 u4 package_name_offset = mtp_package(package_offset + i); 260 const char* package_name = get_string(package_name_offset); 261 packages[i] = package_name; 262 } 263 packages[count] = NULL; 264 return packages; 265 } 266 } 267 return NULL; 268 } 269 270 // Manage a table of open image files. This table allows multiple access points 271 // to share an open image. 272 ImageFileReaderTable::ImageFileReaderTable() : _count(0), _max(_growth) { 273 _table = new ImageFileReader*[_max]; 274 } 275 276 ImageFileReaderTable::~ImageFileReaderTable() { 277 delete _table; 278 } 279 280 // Add a new image entry to the table. 281 void ImageFileReaderTable::add(ImageFileReader* image) { 282 if (_count == _max) { 283 _max += _growth; 284 _table = static_cast<ImageFileReader**>(realloc(_table, _max * sizeof(ImageFileReader*))); 285 } 286 _table[_count++] = image; 287 } 288 289 // Remove an image entry from the table. 290 void ImageFileReaderTable::remove(ImageFileReader* image) { 291 s4 last = _count - 1; 292 for (s4 i = 0; _count; i++) { 293 if (_table[i] == image) { 294 if (i != last) { 295 _table[i] = _table[last]; 296 _count = last; 297 } 298 break; 299 } 300 } 301 302 if (_count != 0 && _count == _max - _growth) { 303 _max -= _growth; 304 _table = static_cast<ImageFileReader**>(realloc(_table, _max * sizeof(ImageFileReader*))); 305 } 306 } 307 308 // Determine if image entry is in table. 309 bool ImageFileReaderTable::contains(ImageFileReader* image) { 310 for (s4 i = 0; _count; i++) { 311 if (_table[i] == image) { 312 return true; 313 } 314 } 315 return false; 316 } 317 318 // Table to manage multiple opens of an image file. 319 ImageFileReaderTable ImageFileReader::_reader_table; 320 321 SimpleCriticalSection _reader_table_lock; 322 323 // Open an image file, reuse structure if file already open. 324 ImageFileReader* ImageFileReader::open(const char* name, bool big_endian) { 325 { 326 // Lock out _reader_table. 327 SimpleCriticalSectionLock cs(&_reader_table_lock); 328 // Search for an exist image file. 329 for (u4 i = 0; i < _reader_table.count(); i++) { 330 // Retrieve table entry. 331 ImageFileReader* reader = _reader_table.get(i); 332 // If name matches, then reuse (bump up use count.) 333 if (strcmp(reader->name(), name) == 0) { 334 reader->inc_use(); 335 return reader; 336 } 337 } 338 } // Unlock the mutex 339 340 // Need a new image reader. 341 ImageFileReader* reader = new ImageFileReader(name, big_endian); 342 bool opened = reader->open(); 343 // If failed to open. 344 if (!opened) { 345 delete reader; 346 return NULL; 347 } 348 349 // Lock to update 350 SimpleCriticalSectionLock cs(&_reader_table_lock); 351 // Search for an exist image file. 352 for (u4 i = 0; i < _reader_table.count(); i++) { 353 // Retrieve table entry. 354 ImageFileReader* existing_reader = _reader_table.get(i); 355 // If name matches, then reuse (bump up use count.) 356 if (strcmp(existing_reader->name(), name) == 0) { 357 existing_reader->inc_use(); 358 reader->close(); 359 delete reader; 360 return existing_reader; 361 } 362 } 363 // Bump use count and add to table. 364 reader->inc_use(); 365 _reader_table.add(reader); 366 return reader; 367 } 368 369 // Close an image file if the file is not in use elsewhere. 370 void ImageFileReader::close(ImageFileReader *reader) { 371 // Lock out _reader_table. 372 SimpleCriticalSectionLock cs(&_reader_table_lock); 373 // If last use then remove from table and then close. 374 if (reader->dec_use()) { 375 _reader_table.remove(reader); 376 delete reader; 377 } 378 } 379 380 // Return an id for the specifed ImageFileReader. 381 u8 ImageFileReader::readerToID(ImageFileReader *reader) { 382 // ID is just the cloaked reader address. 383 return (u8)reader; 384 } 385 386 // Validate the image id. 387 bool ImageFileReader::idCheck(u8 id) { 388 // Make sure the ID is a managed (_reader_table) reader. 389 SimpleCriticalSectionLock cs(&_reader_table_lock); 390 return _reader_table.contains((ImageFileReader*)id); 391 } 392 393 // Return an id for the specifed ImageFileReader. 394 ImageFileReader* ImageFileReader::idToReader(u8 id) { 395 assert(idCheck(id) && "invalid image id"); 396 return (ImageFileReader*)id; 397 } 398 399 // Constructor intializes to a closed state. 400 ImageFileReader::ImageFileReader(const char* name, bool big_endian) { 401 // Copy the image file name. 402 int len = (int) strlen(name) + 1; 403 _name = new char[len]; 404 strncpy(_name, name, len); 405 // Initialize for a closed file. 406 _fd = -1; 407 _endian = Endian::get_handler(big_endian); 408 _index_data = NULL; 409 } 410 411 // Close image and free up data structures. 412 ImageFileReader::~ImageFileReader() { 413 // Ensure file is closed. 414 close(); 415 // Free up name. 416 if (_name) { 417 delete _name; 418 _name = NULL; 419 } 420 } 421 422 // Open image file for read access. 423 bool ImageFileReader::open() { 424 char buffer[IMAGE_MAX_PATH]; 425 426 // If file exists open for reading. 427 _fd = osSupport::openReadOnly(_name); 428 if (_fd == -1) { 429 return false; 430 } 431 // Retrieve the file size. 432 _file_size = osSupport::size(_name); 433 // Read image file header and verify it has a valid header. 434 size_t header_size = sizeof(ImageHeader); 435 if (_file_size < header_size || 436 !read_at((u1*)&_header, header_size, 0) || 437 _header.magic(_endian) != IMAGE_MAGIC || 438 _header.major_version(_endian) != MAJOR_VERSION || 439 _header.minor_version(_endian) != MINOR_VERSION) { 440 close(); 441 return false; 442 } 443 // Size of image index. 444 _index_size = index_size(); 445 // Make sure file is large enough to contain the index. 446 if (_file_size < _index_size) { 447 return false; 448 } 449 // Determine how much of the image is memory mapped. 450 size_t map_size = (size_t)(MemoryMapImage ? _file_size : _index_size); 451 // Memory map image (minimally the index.) 452 _index_data = (u1*)osSupport::map_memory(_fd, _name, 0, map_size); 453 assert(_index_data && "image file not memory mapped"); 454 // Retrieve length of index perfect hash table. 455 u4 length = table_length(); 456 // Compute offset of the perfect hash table redirect table. 457 u4 redirect_table_offset = (u4)header_size; 458 // Compute offset of index attribute offsets. 459 u4 offsets_table_offset = redirect_table_offset + length * sizeof(s4); 460 // Compute offset of index location attribute data. 461 u4 location_bytes_offset = offsets_table_offset + length * sizeof(u4); 462 // Compute offset of index string table. 463 u4 string_bytes_offset = location_bytes_offset + locations_size(); 464 // Compute address of the perfect hash table redirect table. 465 _redirect_table = (s4*)(_index_data + redirect_table_offset); 466 // Compute address of index attribute offsets. 467 _offsets_table = (u4*)(_index_data + offsets_table_offset); 468 // Compute address of index location attribute data. 469 _location_bytes = _index_data + location_bytes_offset; 470 // Compute address of index string table. 471 _string_bytes = _index_data + string_bytes_offset; 472 473 // Initialize the module data 474 ImageModuleData::module_data_name(buffer, _name); 475 module_data = new ImageModuleData(this, buffer); 476 // Successful open. 477 return true; 478 } 479 480 // Close image file. 481 void ImageFileReader::close() { 482 // Deallocate the index. 483 if (_index_data) { 484 osSupport::unmap_memory((char*)_index_data, _index_size); 485 _index_data = NULL; 486 } 487 // Close file. 488 if (_fd != -1) { 489 osSupport::close(_fd); 490 _fd = -1; 491 } 492 } 493 494 // Read directly from the file. 495 bool ImageFileReader::read_at(u1* data, u8 size, u8 offset) const { 496 return (u8)osSupport::read(_fd, (char*)data, size, offset) == size; 497 } 498 499 // Find the location attributes associated with the path. Returns true if 500 // the location is found, false otherwise. 501 bool ImageFileReader::find_location(const char* path, ImageLocation& location) const { 502 // Locate the entry in the index perfect hash table. 503 s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length()); 504 // If is found. 505 if (index != ImageStrings::NOT_FOUND) { 506 // Get address of first byte of location attribute stream. 507 u1* data = get_location_data(index); 508 // Expand location attributes. 509 location.set_data(data); 510 // Make sure result is not a false positive. 511 return verify_location(location, path); 512 } 513 return false; 514 } 515 516 // Find the location index and size associated with the path. 517 // Returns the location index and size if the location is found, 0 otherwise. 518 u4 ImageFileReader::find_location_index(const char* path, u8 *size) const { 519 // Locate the entry in the index perfect hash table. 520 s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length()); 521 // If found. 522 if (index != ImageStrings::NOT_FOUND) { 523 // Get address of first byte of location attribute stream. 524 u4 offset = get_location_offset(index); 525 u1* data = get_location_offset_data(offset); 526 // Expand location attributes. 527 ImageLocation location(data); 528 // Make sure result is not a false positive. 529 if (verify_location(location, path)) { 530 *size = (jlong)location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); 531 return offset; 532 } 533 } 534 return 0; // not found 535 } 536 537 // Assemble the location path from the string fragments indicated in the location attributes. 538 void ImageFileReader::location_path(ImageLocation& location, char* path, size_t max) const { 539 // Manage the image string table. 540 ImageStrings strings(_string_bytes, _header.strings_size(_endian)); 541 // Position to first character of the path buffer. 542 char* next = path; 543 // Temp for string length. 544 size_t length; 545 // Get module string. 546 const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings); 547 // If module string is not empty string. 548 if (*module != '\0') { 549 // Get length of module name. 550 length = strlen(module); 551 // Make sure there is no buffer overflow. 552 assert(next - path + length + 2 < max && "buffer overflow"); 553 // Append '/module/'. 554 *next++ = '/'; 555 strncpy(next, module, length); next += length; 556 *next++ = '/'; 557 } 558 // Get parent (package) string. 559 const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings); 560 // If parent string is not empty string. 561 if (*parent != '\0') { 562 // Get length of module string. 563 length = strlen(parent); 564 // Make sure there is no buffer overflow. 565 assert(next - path + length + 1 < max && "buffer overflow"); 566 // Append 'patent/' . 567 strncpy(next, parent, length); next += length; 568 *next++ = '/'; 569 } 570 // Get base name string. 571 const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings); 572 // Get length of base name. 573 length = strlen(base); 574 // Make sure there is no buffer overflow. 575 assert(next - path + length < max && "buffer overflow"); 576 // Append base name. 577 strncpy(next, base, length); next += length; 578 // Get extension string. 579 const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings); 580 // If extension string is not empty string. 581 if (*extension != '\0') { 582 // Get length of extension string. 583 length = strlen(extension); 584 // Make sure there is no buffer overflow. 585 assert(next - path + length + 1 < max && "buffer overflow"); 586 // Append '.extension' . 587 *next++ = '.'; 588 strncpy(next, extension, length); next += length; 589 } 590 // Make sure there is no buffer overflow. 591 assert((size_t)(next - path) < max && "buffer overflow"); 592 // Terminate string. 593 *next = '\0'; 594 } 595 596 // Verify that a found location matches the supplied path (without copying.) 597 bool ImageFileReader::verify_location(ImageLocation& location, const char* path) const { 598 // Manage the image string table. 599 ImageStrings strings(_string_bytes, _header.strings_size(_endian)); 600 // Position to first character of the path string. 601 const char* next = path; 602 // Get module name string. 603 const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings); 604 // If module string is not empty. 605 if (*module != '\0') { 606 // Compare '/module/' . 607 if (*next++ != '/') return false; 608 if (!(next = ImageStrings::starts_with(next, module))) return false; 609 if (*next++ != '/') return false; 610 } 611 // Get parent (package) string 612 const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings); 613 // If parent string is not empty string. 614 if (*parent != '\0') { 615 // Compare 'parent/' . 616 if (!(next = ImageStrings::starts_with(next, parent))) return false; 617 if (*next++ != '/') return false; 618 } 619 // Get base name string. 620 const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings); 621 // Compare with basne name. 622 if (!(next = ImageStrings::starts_with(next, base))) return false; 623 // Get extension string. 624 const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings); 625 // If extension is not empty. 626 if (*extension != '\0') { 627 // Compare '.extension' . 628 if (*next++ != '.') return false; 629 if (!(next = ImageStrings::starts_with(next, extension))) return false; 630 } 631 // True only if complete match and no more characters. 632 return *next == '\0'; 633 } 634 635 // Return the resource for the supplied location offset. 636 void ImageFileReader::get_resource(u4 offset, u1* uncompressed_data) const { 637 // Get address of first byte of location attribute stream. 638 u1* data = get_location_offset_data(offset); 639 // Expand location attributes. 640 ImageLocation location(data); 641 // Read the data 642 get_resource(location, uncompressed_data); 643 } 644 645 // Return the resource for the supplied location. 646 void ImageFileReader::get_resource(ImageLocation& location, u1* uncompressed_data) const { 647 // Retrieve the byte offset and size of the resource. 648 u8 offset = location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET); 649 u8 uncompressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); 650 u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED); 651 // If the resource is compressed. 652 if (compressed_size != 0) { 653 u1* compressed_data; 654 // If not memory mapped read in bytes. 655 if (!MemoryMapImage) { 656 // Allocate buffer for compression. 657 compressed_data = new u1[(u4)compressed_size]; 658 // Read bytes from offset beyond the image index. 659 bool is_read = read_at(compressed_data, compressed_size, _index_size + offset); 660 assert(is_read && "error reading from image or short read"); 661 } else { 662 compressed_data = get_data_address() + offset; 663 } 664 // Get image string table. 665 const ImageStrings strings = get_strings(); 666 // Decompress resource. 667 ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, (u4)uncompressed_size, 668 &strings); 669 // If not memory mapped then release temporary buffer. 670 if (!MemoryMapImage) { 671 delete compressed_data; 672 } 673 } else { 674 // Read bytes from offset beyond the image index. 675 bool is_read = read_at(uncompressed_data, uncompressed_size, _index_size + offset); 676 assert(is_read && "error reading from image or short read"); 677 } 678 } 679 680 // Return the ImageModuleData for this image 681 ImageModuleData * ImageFileReader::get_image_module_data() { 682 return module_data; 683 } --- EOF ---