/*- * Copyright (c) 2004 - 2011 CTPP Team * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the CTPP Team nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * CTPP2VMFileLoader.cpp * * $CTPP$ */ #include "CTPP2VMFileLoader.hpp" #include "CTPP2Util.hpp" #include "CTPP2Exception.hpp" #include "CTPP2VMExecutable.hpp" #include "CTPP2VMInstruction.hpp" #include "CTPP2VMMemoryCore.hpp" #include #include #include #include #include namespace CTPP // C++ Template Engine { // // Convert byte order // static void ConvertExecutable(VMExecutable * oCore) { // Code entry point oCore -> entry_point = Swap32(oCore -> entry_point); // Offset of code segment oCore -> code_offset = Swap32(oCore -> code_offset); // Code segment size oCore -> code_size = Swap32(oCore -> code_size); // Offset of static text segment oCore -> syscalls_offset = Swap32(oCore -> syscalls_offset); // Static text segment size oCore -> syscalls_data_size = Swap32(oCore -> syscalls_data_size); // Offset of static text index segment oCore -> syscalls_index_offset = Swap32(oCore -> syscalls_index_offset); // Static text index segment size oCore -> syscalls_index_size = Swap32(oCore -> syscalls_index_size); // Offset of static data segment oCore -> static_data_offset = Swap32(oCore -> static_data_offset); // Static data segment size oCore -> static_data_data_size = Swap32(oCore -> static_data_data_size); // Offset of static text segment oCore -> static_text_offset = Swap32(oCore -> static_text_offset); // Static text segment size oCore -> static_text_data_size = Swap32(oCore -> static_text_data_size); // Offset of static text index segment oCore -> static_text_index_offset = Swap32(oCore -> static_text_index_offset); // Static text index segment size oCore -> static_text_index_size = Swap32(oCore -> static_text_index_size); // Version 2.2+ // Offset of static data bit index oCore -> static_data_bit_index_offset = Swap32(oCore -> static_data_bit_index_offset); /// Offset of static data bit index oCore -> static_data_bit_index_size = Swap32(oCore -> static_data_bit_index_size); // Platform oCore -> platform = Swap64(oCore -> platform); // Ugly-jolly hack! // ... dereferencing type-punned pointer will break strict-aliasing rules ... UINT_64 iTMP; memcpy(&iTMP, &(oCore -> ieee754double), sizeof(UINT_64)); iTMP = Swap64(iTMP); memcpy(&(oCore -> ieee754double), &iTMP, sizeof(UINT_64)); // Cyclic Redundancy Check oCore -> crc = 0; // Convert data structures // Convert code segment VMInstruction * pInstructions = const_cast(VMExecutable::GetCodeSeg(oCore)); UINT_32 iI = 0; UINT_32 iSteps = oCore -> code_size / sizeof(VMInstruction); for(iI = 0; iI < iSteps; ++iI) { pInstructions -> instruction = Swap32(pInstructions -> instruction); pInstructions -> argument = Swap32(pInstructions -> argument); pInstructions -> reserved = Swap64(pInstructions -> reserved); ++pInstructions; } // Convert syscalls index TextDataIndex * pTextIndex = const_cast(VMExecutable::GetSyscallsIndexSeg(oCore)); iSteps = oCore -> syscalls_index_size / sizeof(TextDataIndex); for(iI = 0; iI < iSteps; ++iI) { pTextIndex -> offset = Swap32(pTextIndex -> offset); pTextIndex -> length = Swap32(pTextIndex -> length); ++pTextIndex; } // Convert static text index pTextIndex = const_cast(VMExecutable::GetStaticTextIndexSeg(oCore)); iSteps = oCore -> static_text_index_size / sizeof(TextDataIndex); for(iI = 0; iI < iSteps; ++iI) { pTextIndex -> offset = Swap32(pTextIndex -> offset); pTextIndex -> length = Swap32(pTextIndex -> length); ++pTextIndex; } // Convert static data StaticDataVar * pStaticDataVar = const_cast(VMExecutable::GetStaticDataSeg(oCore)); iSteps = oCore -> static_data_data_size / sizeof(StaticDataVar); for(iI = 0; iI < iSteps; ++iI) { (*pStaticDataVar).i_data = Swap64((*pStaticDataVar).i_data); ++pStaticDataVar; } } // // Constructor // VMFileLoader::VMFileLoader(CCHAR_P szFileName) { // Get file size struct stat oStat; if (stat(szFileName, &oStat) == -1) { throw CTPPUnixException("stat", errno); } if (oStat.st_size == 0) { throw CTPPLogicError("Cannot get size of file"); } // Load file FILE * F = fopen(szFileName, "rb"); if (F == NULL) { throw CTPPUnixException("fopen", errno); } // Allocate memory oCore = (VMExecutable *)malloc(oStat.st_size); // Read from file if (fread(oCore, oStat.st_size, 1, F) != 1) { fclose(F); throw CTPPUnixException("fread", errno); } // All Done fclose(F); if (oCore -> magic[0] == 'C' && oCore -> magic[1] == 'T' && oCore -> magic[2] == 'P' && oCore -> magic[3] == 'P') { // Check version if (oCore -> version[0] >= 1) { // Platform-dependent data (byte order) if (oCore -> platform == 0x4142434445464748ull) { #ifdef _DEBUG fprintf(stderr, "Big/Little Endian conversion: Nothing to do\n"); #endif // Nothing to do, only check crc UINT_32 iCRC = oCore -> crc; oCore -> crc = 0; // Calculate CRC of file if (iCRC != crc32((UCCHAR_P)oCore, oStat.st_size)) { free(oCore); throw CTPPLogicError("CRC checksum invalid"); } } // Platform-dependent data (byte order) else if (oCore -> platform == 0x4847464544434241ull) { // Need to reconvert data #ifdef _DEBUG fprintf(stderr, "Big/Little Endian conversion: Need to reconvert core\n"); #endif ConvertExecutable(oCore); } else { free(oCore); throw CTPPLogicError("Conversion of middle-end architecture does not supported."); } // Check IEEE 754 format if (oCore -> ieee754double != 15839800103804824402926068484019465486336.0) { free(oCore); throw CTPPLogicError("IEEE 754 format is broken, cannot convert file"); } } pVMMemoryCore = new VMMemoryCore(oCore); } else { free(oCore); throw CTPPLogicError("Not an CTPP bytecode file."); } } // // Get ready-to-run program // const VMMemoryCore * VMFileLoader::GetCore() const { return pVMMemoryCore; } // // A destructor // VMFileLoader::~VMFileLoader() throw() { delete pVMMemoryCore; free(oCore); } } // namespace CTPP // End.