diff --git a/src/coreclr/ilasm/asmparse.h b/src/coreclr/ilasm/asmparse.h index 6909d92e3d9426..44c5a106dc75fd 100644 --- a/src/coreclr/ilasm/asmparse.h +++ b/src/coreclr/ilasm/asmparse.h @@ -7,6 +7,8 @@ #define asmparse_h #include // for FILE +#include +#include #include "assembler.h" // for ErrorReporter Labels //class Assembler; @@ -95,9 +97,8 @@ class MappedFileStream : public ReadStream { public: MappedFileStream(_In_ __nullterminated WCHAR* wFileName) : m_fileNameUtf8(NULL) - , m_hFile(INVALID_HANDLE_VALUE) + , m_File(nullptr) , m_FileSize(0) - , m_hMapFile(NULL) { m_pStart = open(wFileName); m_pCurr = m_pStart; @@ -112,20 +113,8 @@ class MappedFileStream : public ReadStream { } ~MappedFileStream() { - if (m_hFile != INVALID_HANDLE_VALUE) - { - if (m_pStart) - UnmapViewOfFile((void*)m_pStart); - if (m_hMapFile) - CloseHandle(m_hMapFile); - CloseHandle(m_hFile); - - m_pStart = NULL; - m_hMapFile = NULL; - m_hFile = INVALID_HANDLE_VALUE; - m_FileSize = 0; - } - + if (m_File) + delete m_File; if (m_fileNameUtf8 != NULL) delete [] m_fileNameUtf8; } @@ -171,37 +160,26 @@ class MappedFileStream : public ReadStream { } private: - char* map_file() - { - DWORD dwFileSizeLow; - - dwFileSizeLow = GetFileSize( m_hFile, NULL); - if (dwFileSizeLow == INVALID_FILE_SIZE) - return NULL; - m_FileSize = dwFileSizeLow; - - // No difference between A and W in this case: last param (LPCTSTR) is NULL - m_hMapFile = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL); - if (m_hMapFile == NULL) - return NULL; - - return (char*)(HMODULE) MapViewOfFile(m_hMapFile, FILE_MAP_READ, 0, 0, 0); - } char* open(const WCHAR* moduleName) { _ASSERTE(moduleName); if (!moduleName) return NULL; - m_hFile = WszCreateFile(moduleName, GENERIC_READ, FILE_SHARE_READ, - 0, OPEN_EXISTING, 0, 0); - return (m_hFile == INVALID_HANDLE_VALUE) ? NULL : map_file(); + m_File = CreateMappedFile(moduleName); + if (m_File->Size() > UINT_MAX) + { + delete m_File; + m_File = nullptr; + } + + m_FileSize = (DWORD)m_File->Size(); + return (char*)m_File->Address(); } char* m_fileNameUtf8; // FileName (for error reporting) - HANDLE m_hFile; // File we are reading from + MemoryMappedFile* m_File; // File we are reading from DWORD m_FileSize; - HANDLE m_hMapFile; char* m_pStart; char* m_pEnd; char* m_pCurr; diff --git a/src/coreclr/ildasm/ceeload.cpp b/src/coreclr/ildasm/ceeload.cpp index df7666d6522bea..ffaf67586e1e40 100644 --- a/src/coreclr/ildasm/ceeload.cpp +++ b/src/coreclr/ildasm/ceeload.cpp @@ -17,9 +17,8 @@ /*************************************************************************************/ PELoader::PELoader() { - m_hFile = NULL; + m_File = nullptr; m_hMod = NULL; - m_hMapFile = NULL; m_pNT64 = NULL; m_bIsPE32 = FALSE; m_FileSize = m_FileSizeAligned = 0; @@ -30,91 +29,31 @@ PELoader::~PELoader() m_hMod = NULL; m_pNT64 = NULL; - // If we have an hFile then we opened this file ourselves! - // If we do not then this file was loaded by the OS and the OS will - // close it for us. - if (m_hFile) - this->close(); } /*************************************************************************************/ /*************************************************************************************/ void PELoader::close() { - - // _ASSERTE(m_hFile != NULL); - if (m_hFile) - { - if (m_hMod) - UnmapViewOfFile((void*)m_hMod); - if (m_hMapFile) - CloseHandle(m_hMapFile); - CloseHandle(m_hFile); - - m_hMod = NULL; - m_hMapFile = NULL; - m_hFile = NULL; - m_FileSize = m_FileSizeAligned = 0; - } -} - - -BOOL PELoader::open(LPCSTR moduleName) -{ - HMODULE newhMod = NULL; - DWORD dwFileSizeLow; - - _ASSERTE(moduleName); - if (!moduleName) - return FALSE; - - - m_hFile = CreateFileA(moduleName, GENERIC_READ, FILE_SHARE_READ, - 0, OPEN_EXISTING, 0, 0); - if (m_hFile == INVALID_HANDLE_VALUE) - return FALSE; - - dwFileSizeLow = GetFileSize( m_hFile, NULL); - if (dwFileSizeLow == INVALID_FILE_SIZE) - return FALSE; - m_FileSize = dwFileSizeLow; - - m_hMapFile = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL); - if (m_hMapFile == NULL) - return FALSE; - - newhMod = (HMODULE) MapViewOfFile(m_hMapFile, FILE_MAP_READ, 0, 0, 0); - if (newhMod == NULL) - return FALSE; - return open(newhMod); + delete m_File; + m_File = nullptr; } BOOL PELoader::open(const WCHAR* moduleName) { HMODULE newhMod = NULL; - DWORD dwFileSizeLow; _ASSERTE(moduleName); if (!moduleName) return FALSE; - m_hFile = WszCreateFile(moduleName, GENERIC_READ, FILE_SHARE_READ, - 0, OPEN_EXISTING, 0, 0); - if (m_hFile == INVALID_HANDLE_VALUE) + m_File = CreateMappedFile(moduleName); + if (m_File == nullptr) return FALSE; - dwFileSizeLow = GetFileSize( m_hFile, NULL); - if (dwFileSizeLow == INVALID_FILE_SIZE) - return FALSE; - m_FileSize = dwFileSizeLow; + m_FileSize = m_File->Size(); - m_hMapFile = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL); - if (m_hMapFile == NULL) - return FALSE; - - newhMod = (HMODULE) MapViewOfFile(m_hMapFile, FILE_MAP_READ, 0, 0, 0); - if (newhMod == NULL) - return FALSE; + newhMod = (HMODULE)m_File->Address(); return open(newhMod); } diff --git a/src/coreclr/ildasm/ceeload.h b/src/coreclr/ildasm/ceeload.h index f1c8ec7248b9bb..7d77366ff65e76 100644 --- a/src/coreclr/ildasm/ceeload.h +++ b/src/coreclr/ildasm/ceeload.h @@ -35,8 +35,7 @@ class PELoader { protected: HMODULE m_hMod; - HANDLE m_hFile; - HANDLE m_hMapFile; + MemoryMappedFile* m_File; BOOL m_bIsPE32; size_t m_FileSize; size_t m_FileSizeAligned; @@ -54,7 +53,6 @@ class PELoader { PELoader(); ~PELoader(); - BOOL open(const char* moduleNameIn); BOOL open(const WCHAR* moduleNameIn); BOOL open(HMODULE hMod); BOOL getCOMHeader(IMAGE_COR20_HEADER **ppCorHeader); @@ -69,7 +67,7 @@ class PELoader { inline DWORD Signature() { return m_pNT32->Signature; }; inline BYTE* base() { return (BYTE*) m_hMod; }; inline HMODULE getHModule() { return m_hMod; }; - inline HANDLE getHFile() { return m_hFile; } ; + inline size_t getFileSize() { return m_FileSize; }; }; #endif // CEELoad_H diff --git a/src/coreclr/ildasm/dasm.cpp b/src/coreclr/ildasm/dasm.cpp index 6ec7af2495d712..0adf37c1f9ae31 100644 --- a/src/coreclr/ildasm/dasm.cpp +++ b/src/coreclr/ildasm/dasm.cpp @@ -5837,7 +5837,7 @@ void DumpStatistics(IMAGE_COR20_HEADER *CORHeader, void* GUICookie) TableSeenReset(); metaSize = 0; - sprintf_s(szString,SZSTRING_SIZE,"// File size : %d", fileSize = SafeGetFileSize(g_pPELoader->getHFile(), NULL)); + sprintf_s(szString,SZSTRING_SIZE,"// File size : %d", fileSize = (int)g_pPELoader->getFileSize()); printLine(GUICookie,szStr); if (g_pPELoader->IsPE32()) diff --git a/src/coreclr/ildasm/ildasmpch.h b/src/coreclr/ildasm/ildasmpch.h index af7295f12a21aa..4e751e998997a2 100644 --- a/src/coreclr/ildasm/ildasmpch.h +++ b/src/coreclr/ildasm/ildasmpch.h @@ -14,6 +14,7 @@ #include #include #include "dn-stdio.h" +#include "dn-memmap.h" using std::min; using std::max; diff --git a/src/coreclr/inc/longfilepathwrappers.h b/src/coreclr/inc/longfilepathwrappers.h index ca028bf6d625a1..585c2c3b53dcba 100644 --- a/src/coreclr/inc/longfilepathwrappers.h +++ b/src/coreclr/inc/longfilepathwrappers.h @@ -5,6 +5,8 @@ #define _WIN_PATH_APIS_WRAPPER_ class SString; +#include + #ifdef HOST_WINDOWS HMODULE @@ -27,6 +29,8 @@ CreateFileWrapper( int u16_fopen_wrapper(FILE** stream, const WCHAR* filename, const WCHAR* mode); +MemoryMappedFile* CreateMappedFileWrapper(const WCHAR* filename); + BOOL CopyFileExWrapper( _In_ LPCWSTR lpExistingFileName, diff --git a/src/coreclr/inc/stresslog.h b/src/coreclr/inc/stresslog.h index f93a2cde304a7a..d11c349771ff35 100644 --- a/src/coreclr/inc/stresslog.h +++ b/src/coreclr/inc/stresslog.h @@ -237,13 +237,9 @@ class StressLog { static const size_t MAX_MODULES = 5; ModuleDesc modules[MAX_MODULES]; // descriptor of the modules images -#if defined(HOST_64BIT) +#if defined(HOST_64BIT) && HOST_WINDOWS #define MEMORY_MAPPED_STRESSLOG -#ifdef HOST_WINDOWS #define MEMORY_MAPPED_STRESSLOG_BASE_ADDRESS (void*)0x400000000000 -#else -#define MEMORY_MAPPED_STRESSLOG_BASE_ADDRESS nullptr -#endif #endif #ifdef MEMORY_MAPPED_STRESSLOG diff --git a/src/coreclr/inc/winwrap.h b/src/coreclr/inc/winwrap.h index 2e8946aa50205f..b6ee5743cc0662 100644 --- a/src/coreclr/inc/winwrap.h +++ b/src/coreclr/inc/winwrap.h @@ -43,10 +43,12 @@ #define WszLoadLibrary LoadLibraryExWrapper #define WszCreateFile CreateFileWrapper #define fopen_lp u16_fopen_wrapper +#define CreateMappedFile CreateMappedFileWrapper #else // HOST_WINDOWS #define WszLoadLibrary LoadLibraryExW #define WszCreateFile CreateFileW #define fopen_lp u16_fopen_s +#define CreateMappedFile MemoryMappedFile::Open #endif // HOST_WINDOWS //APIS which have a buffer as an out parameter diff --git a/src/coreclr/md/enc/stgio.cpp b/src/coreclr/md/enc/stgio.cpp index aeba5e59f47359..bb2bc4a11944b0 100644 --- a/src/coreclr/md/enc/stgio.cpp +++ b/src/coreclr/md/enc/stgio.cpp @@ -39,6 +39,13 @@ #include "posterror.h" #include "pedecoder.h" #include "pedecoder.inl" +#ifdef TARGET_UNIX +#include +#include +#include +#include +#include "dn-stdio.h" +#endif //********** Types. *********************************************************** #define SMALL_ALLOC_MAP_SIZE (64 * 1024) // 64 kb is the minimum size of virtual @@ -90,9 +97,14 @@ void StgIO::CtorInit() m_bRewrite = false; m_bFreeMem = false; m_pIStream = 0; +#ifdef TARGET_WINDOWS m_hFile = INVALID_HANDLE_VALUE; m_hModule = NULL; m_hMapping = 0; +#else + m_fd = -1; + m_mmap = false; +#endif m_pBaseData = 0; m_pData = 0; m_cbData = 0; @@ -196,14 +208,24 @@ HRESULT StgIO::Open( // Return code. //@future: This could chose to open the file in write through // mode, which would provide better Duribility (from ACID props), // but would be much slower. - + // Create the new file, overwriting only if caller allows it. +#ifdef TARGET_WINDOWS if ((m_hFile = WszCreateFile(szName, GENERIC_READ | GENERIC_WRITE, 0, 0, (fFlags & DBPROP_TMODEF_FAILIFTHERE) ? CREATE_NEW : CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) { return (MapFileError(GetLastError())); } +#else + MAKE_UTF8PTR_FROMWIDE_NOTHROW(u8Name, szName); + if ((m_fd = open(u8Name, + (fFlags & DBPROP_TMODEF_FAILIFTHERE) ? O_TRUNC : O_EXCL, + O_RDWR)) == -1) + { + return HRESULTFromErrno(); + } +#endif // Data will come from the file. m_iType = STGIO_HFILE; @@ -212,9 +234,13 @@ HRESULT StgIO::Open( // Return code. // memory view, it has to be opened already, so no file open. else if ((fFlags & DBPROP_TMODEF_WRITE) == 0) { +#ifdef TARGET_WINDOWS // We have not opened the file nor loaded it as module _ASSERTE(m_hFile == INVALID_HANDLE_VALUE); _ASSERTE(m_hModule == NULL); +#else + _ASSERTE(m_fd == -1); +#endif // Open the file for read. Sharing is determined by caller, it can // allow other readers or be exclusive. @@ -266,6 +292,7 @@ HRESULT StgIO::Open( // Return code. #endif //!DACCESS_COMPILE && !TARGET_UNIX } +#ifdef TARGET_WINDOWS if (m_hModule == NULL) { // We didn't get the loaded module (we either didn't want to or it failed) HandleHolder hFile(WszCreateFile(szName, @@ -291,6 +318,27 @@ HRESULT StgIO::Open( // Return code. m_iType = STGIO_HFILE; } + #else + MAKE_UTF8PTR_FROMWIDE_NOTHROW(u8Name, szName); + int fd = open(u8Name, O_RDONLY); + if (fd == -1) + return HRESULTFromErrno(); + + // Get size of file. + struct stat st; + if (fstat(fd, &st) != 0 || st.st_size == 0 || st.st_size >= UINT32_MAX) + { + // Can't read anything from an empty file. + close(fd); + return (PostError(CLDB_E_NO_DATA)); + } + + m_cbData = (ULONG)st.st_size; + + // Data will come from the file. + m_fd = fd; + m_iType = STGIO_HFILE; + #endif } ErrExit: @@ -356,6 +404,7 @@ void StgIO::Close() // Intentional fall through to file case, if we kept handle open. FALLTHROUGH; +#if TARGET_WINDOWS case STGIO_HFILE: { // Free the file handle. @@ -373,6 +422,15 @@ void StgIO::Close() m_hModule = NULL; break; } +#else + case STGIO_HFILE: + { + // Free the file handle. + if (m_fd != -1) + close(m_fd); + } + break; +#endif // Free the stream pointer. case STGIO_STREAM: @@ -471,7 +529,11 @@ HRESULT StgIO::Read( // Return code. case STGIO_HFILE: case STGIO_HMODULE: { +#ifdef TARGET_WINDOWS _ASSERTE((m_hFile != INVALID_HANDLE_VALUE) || (m_hModule != NULL)); +#else + _ASSERTE(m_fd != -1); +#endif // Backing store does its own paging. if (IsBackingStore() || IsMemoryMapped()) @@ -488,8 +550,12 @@ HRESULT StgIO::Read( // Return code. // If there is no backing store, this is just a read operation. else { +#ifdef TARGET_WINDOWS _ASSERTE((m_iType == STGIO_HFILE) && (m_hFile != INVALID_HANDLE_VALUE)); _ASSERTE(m_hModule == NULL); +#else + _ASSERTE((m_iType == STGIO_HFILE) && (m_fd != -1)); +#endif ULONG cbTemp = 0; if (!pcbRead) @@ -622,6 +688,7 @@ HRESULT StgIO::Seek( // New offset. { case STGIO_HFILE: { +#ifdef TARGET_WINDOWS // Use the file system's move. _ASSERTE(m_hFile != INVALID_HANDLE_VALUE); cbRtn = ::SetFilePointer(m_hFile, lVal, 0, fMoveType); @@ -636,6 +703,17 @@ HRESULT StgIO::Seek( // New offset. } m_cbOffset = cbRtn; } +#else + _ASSERTE(m_fd != -1); + int64_t offRtn = (int64_t)lseek(m_fd, lVal, + fMoveType == FILE_BEGIN ? SEEK_SET : + (fMoveType == FILE_CURRENT ? SEEK_CUR : SEEK_END)); + if (offRtn < 0 || offRtn > UINT32_MAX) + { + IfFailGo(STG_E_INVALIDFUNCTION); + } + m_cbOffset = (ULONG)offRtn; +#endif } break; @@ -784,6 +862,7 @@ HRESULT StgIO::MapFileToMem( // Return code. // If it is for exclusive, then we need to keep the handle open so the // file is locked, preventing other readers. Also leave it open if // in read/write mode so we can truncate and rewrite. +#ifdef TARGET_WINDOWS if (m_hFile == INVALID_HANDLE_VALUE || ((m_fFlags & DBPROP_TMODEF_EXCLUSIVE) == 0 && (m_fFlags & DBPROP_TMODEF_WRITE) == 0)) { @@ -793,6 +872,17 @@ HRESULT StgIO::MapFileToMem( // Return code. VERIFY(CloseHandle(m_hFile)); m_hFile = INVALID_HANDLE_VALUE; } +#else + if (m_fd == -1 || + ((m_fFlags & DBPROP_TMODEF_EXCLUSIVE) == 0 && (m_fFlags & DBPROP_TMODEF_WRITE) == 0)) + { + // If there was a handle open, then free it. + if (m_fd != -1) + { + VERIFY(close(m_fd) == 0); + m_fd = -1; + } +#endif // Free the stream pointer. else if (m_pIStream != 0) @@ -814,13 +904,16 @@ HRESULT StgIO::MapFileToMem( // Return code. else { // Now we will map, so better have it right. +#ifdef TARGET_WINDOWS _ASSERTE(m_hFile != INVALID_HANDLE_VALUE || m_iType == STGIO_STREAM); _ASSERTE(m_rgPageMap == 0); +#endif // For read mode, use a memory mapped file since the size will never // change for the life of the handle. if ((m_fFlags & DBPROP_TMODEF_WRITE) == 0 && m_iType != STGIO_STREAM) { +#ifdef TARGET_WINDOWS // Create a mapping object for the file. _ASSERTE(m_hMapping == 0); @@ -858,6 +951,16 @@ HRESULT StgIO::MapFileToMem( // Return code. m_pBaseData = m_pData = NULL; goto ErrExit; } +#else + _ASSERTE(!m_mmap); + if ((m_pBaseData = m_pData = mmap(nullptr, m_cbData, PROT_READ, 0, m_fd, 0)) == MAP_FAILED) + { + hr = HRESULTFromErrno(); + m_pBaseData = m_pData = NULL; + goto ErrExit; + } + m_mmap = true; +#endif } // In write mode, we need the hybrid combination of being able to back up // the data in memory via cache, but then later rewrite the contents and @@ -898,9 +1001,11 @@ HRESULT StgIO::MapFileToMem( // Return code. // Check for errors and clean up. if (FAILED(hr)) { +#ifdef TARGET_WINDOWS if (m_hMapping) CloseHandle(m_hMapping); m_hMapping = 0; +#endif m_pBaseData = m_pData = 0; m_cbData = 0; } @@ -924,6 +1029,7 @@ HRESULT StgIO::ReleaseMappingObject() // Return code. return S_OK; } +#ifdef TARGET_WINDOWS // Must have an allocated handle. _ASSERTE(m_hMapping != 0); @@ -941,6 +1047,17 @@ HRESULT StgIO::ReleaseMappingObject() // Return code. VERIFY(CloseHandle(m_hMapping)); m_hMapping = 0; } +#else + _ASSERTE(m_mmap); + + if (m_pData) + { + VERIFY(munmap(m_pData, m_cbData) == 0); + m_pData = nullptr; + } + + m_mmap = false; +#endif return S_OK; } @@ -1118,6 +1235,7 @@ HRESULT StgIO::FlushFileBuffers() { _ASSERTE(!IsReadOnly()); +#ifdef TARGET_WINDOWS if (m_hFile != INVALID_HANDLE_VALUE) { if (::FlushFileBuffers(m_hFile)) @@ -1125,6 +1243,15 @@ HRESULT StgIO::FlushFileBuffers() else return (MapFileError(GetLastError())); } +#else + if (m_fd != -1) + { + if (fsync(m_fd) == 0) + return (S_OK); + else + return HRESULTFromErrno(); + } +#endif return (S_OK); } @@ -1179,12 +1306,18 @@ HRESULT StgIO::WriteToDisk( // Return code. case STGIO_HFILE: case STGIO_HFILEMEM: { +#ifdef TARGET_WINDOWS // Use the file system's move. _ASSERTE(m_hFile != INVALID_HANDLE_VALUE); // Do the write to disk. if (!::WriteFile(m_hFile, pbBuff, cbWrite, pcbWritten, 0)) hr = MapFileError(GetLastError()); +#else + _ASSERTE(m_fd != -1); + if ((cbWritten = write(m_fd, pbBuff, cbWrite)) != cbWrite) + hr = HRESULTFromErrno(); +#endif } break; @@ -1233,9 +1366,15 @@ HRESULT StgIO::ReadFromDisk( // Return code. // Read only from file to avoid recursive logic. if (m_iType == STGIO_HFILE || m_iType == STGIO_HFILEMEM) { +#ifdef TARGET_WINDOWS if (::ReadFile(m_hFile, pbBuff, cbBuff, pcbRead, 0)) return (S_OK); return (MapFileError(GetLastError())); +#else + if ((cbRead = read(m_fd, pbBuff, cbBuff)) >= 0) + return (S_OK); + return HRESULTFromErrno(); +#endif } // Read directly from stream. else @@ -1254,11 +1393,20 @@ void StgIO::FreePageMap() if (m_bFreeMem && m_pBaseData) FreeMemory(m_pBaseData); // For mmf, close handles and free resources. +#ifdef TARGET_WINDOWS else if (m_hMapping && m_pBaseData) { VERIFY(UnmapViewOfFile(m_pBaseData)); VERIFY(CloseHandle(m_hMapping)); + m_hMapping = 0; } +#else + else if (m_mmap && m_pBaseData) + { + VERIFY(munmap(m_pBaseData, m_cbData) == 0); + m_mmap = false; + } +#endif // For our own system, free memory. else if (m_rgPageMap && m_pBaseData) { @@ -1271,7 +1419,6 @@ void StgIO::FreePageMap() } m_pBaseData = 0; - m_hMapping = 0; m_cbData = 0; } diff --git a/src/coreclr/md/inc/stgio.h b/src/coreclr/md/inc/stgio.h index d46c9119a7db49..b1cb821a62993f 100644 --- a/src/coreclr/md/inc/stgio.h +++ b/src/coreclr/md/inc/stgio.h @@ -240,7 +240,11 @@ class StgIO int IsBackingStore() { return (m_rgPageMap != 0); } int IsMemoryMapped() +#ifdef TARGET_WINDOWS { return ((m_hMapping != NULL) || (m_hModule != NULL)); } +#else + { return m_mmap; } +#endif void CtorInit(); HRESULT WriteToDisk(const void *pbBuff, ULONG cbWrite, ULONG *pcbWritten); @@ -258,9 +262,14 @@ class StgIO // Handles. IStream * m_pIStream; // For save to stream instead of file. +#ifdef TARGET_WINDOWS HANDLE m_hFile; // The actual file with contents. HANDLE m_hMapping; // Mapping handle. HMODULE m_hModule; // If we load with LoadLibrary, this is the module (otherwise NULL). +#else + int m_fd; + bool m_mmap; +#endif void * m_pBaseData; // Base address for memory mapped file. void * m_pData; // For memory mapped file read. ULONG m_cbData; // Size of in memory data. diff --git a/src/coreclr/minipal/Unix/CMakeLists.txt b/src/coreclr/minipal/Unix/CMakeLists.txt index 7e1c1a4e9698b9..17de0e621e6f07 100644 --- a/src/coreclr/minipal/Unix/CMakeLists.txt +++ b/src/coreclr/minipal/Unix/CMakeLists.txt @@ -2,6 +2,7 @@ set(SOURCES doublemapping.cpp dn-u16.cpp dn-stdio.cpp + dn-memmap.cpp ) add_library(coreclrminipal_objects diff --git a/src/coreclr/minipal/Unix/dn-memmap.cpp b/src/coreclr/minipal/Unix/dn-memmap.cpp new file mode 100644 index 00000000000000..9e120751188edd --- /dev/null +++ b/src/coreclr/minipal/Unix/dn-memmap.cpp @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +typedef char16_t WCHAR; + +#include +#include +#include +#include +#include +#include +#include +#include + +MemoryMappedFile* MemoryMappedFile::Open(const WCHAR* path) +{ + size_t pathLen = u16_strlen(path); + size_t pathU8Len = minipal_get_length_utf16_to_utf8((CHAR16_T*)path, pathLen, 0); + char* pathU8 = new char[pathU8Len + 1]; + size_t ret = minipal_convert_utf16_to_utf8((CHAR16_T*)path, pathLen, pathU8, pathU8Len, 0); + pathU8[ret] = '\0'; + + void* address = nullptr; + MemoryMappedFile* result = nullptr; + + int fd = open(pathU8, O_RDONLY); + delete[] pathU8; + + if (fd == -1) + goto Fail; + + struct stat st; + if (fstat(fd, &st) != 0) + goto Fail; + +#ifdef TARGET_32BIT + if (st.st_size > INT32_MAX) + goto Fail; +#endif + + address = mmap(nullptr, (size_t)st.st_size, PROT_READ, 0, fd, 0); + if (address == MAP_FAILED) + goto Fail; + + close(fd); + result = new MemoryMappedFile(); + result->m_address = address; + result->m_size = (size_t)st.st_size; + return result; + +Fail: + if (fd != -1) + close(fd); + return nullptr; +} + +MemoryMappedFile::~MemoryMappedFile() +{ + if (m_address != nullptr) + munmap(m_address, m_size); +} diff --git a/src/coreclr/minipal/Windows/CMakeLists.txt b/src/coreclr/minipal/Windows/CMakeLists.txt index ac0af0399d72b4..0440b8bd084079 100644 --- a/src/coreclr/minipal/Windows/CMakeLists.txt +++ b/src/coreclr/minipal/Windows/CMakeLists.txt @@ -2,6 +2,7 @@ set(SOURCES doublemapping.cpp dn-u16.cpp dn-stdio.cpp + dn-memmap.cpp ) add_library(coreclrminipal STATIC diff --git a/src/coreclr/minipal/Windows/dn-memmap.cpp b/src/coreclr/minipal/Windows/dn-memmap.cpp new file mode 100644 index 00000000000000..2ba1214c7a37d8 --- /dev/null +++ b/src/coreclr/minipal/Windows/dn-memmap.cpp @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include +#include + +MemoryMappedFile* MemoryMappedFile::Open(const WCHAR* path) +{ + MemoryMappedFile* result = new MemoryMappedFile(); + + result->m_hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (result->m_hFile == NULL) + goto Fail; + + LARGE_INTEGER size; + if (!GetFileSizeEx(result->m_hFile, &size)) + goto Fail; + + if (size.QuadPart > SIZE_MAX) + goto Fail; + + result->m_size = (size_t)size.QuadPart; + + result->m_hFileMapping = CreateFileMappingW(result->m_hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (result->m_hFileMapping == NULL) + goto Fail; + + result->m_address = MapViewOfFile(result->m_hFileMapping, FILE_MAP_READ, 0, 0, 0); + if (result->m_address == nullptr) + goto Fail; + + return result; + +Fail: + delete result; + return nullptr; +} + +MemoryMappedFile::~MemoryMappedFile() +{ + if (m_address != nullptr) + UnmapViewOfFile(m_address); + if (m_hFileMapping != NULL) + CloseHandle(m_hFileMapping); + if (m_hFile != NULL) + CloseHandle(m_hFile); +} diff --git a/src/coreclr/minipal/dn-memmap.h b/src/coreclr/minipal/dn-memmap.h new file mode 100644 index 00000000000000..3eb9da53929ee9 --- /dev/null +++ b/src/coreclr/minipal/dn-memmap.h @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// + +#ifndef DN_MEMMAP_H +#define DN_MEMMAP_H + +#include + +class MemoryMappedFile +{ + size_t m_size; + void* m_address; + +#ifdef TARGET_WINDOWS + HANDLE m_hFile; + HANDLE m_hFileMapping; +#endif + + MemoryMappedFile() + : m_size(0) + , m_address(nullptr) + #ifdef TARGET_WINDOWS + , m_hFile(NULL) + , m_hFileMapping(NULL) + #endif + { + } + +public: + static MemoryMappedFile* Open(const WCHAR* path); + ~MemoryMappedFile(); + + MemoryMappedFile(const MemoryMappedFile&) = delete; + MemoryMappedFile& operator=(const MemoryMappedFile&) = delete; + + void* Address() { return m_address; } + size_t Size() { return m_size; } +}; + +#endif // DN_MEMMAP_H diff --git a/src/coreclr/tools/metainfo/mdobj.cpp b/src/coreclr/tools/metainfo/mdobj.cpp index 8d9d604280213b..2d541a0d132a85 100644 --- a/src/coreclr/tools/metainfo/mdobj.cpp +++ b/src/coreclr/tools/metainfo/mdobj.cpp @@ -5,6 +5,7 @@ #include #include #include "mdinfo.h" +#include #ifndef STRING_BUFFER_LEN #define STRING_BUFFER_LEN 4096 @@ -55,44 +56,6 @@ static HRESULT FindObjMetaData(PVOID pImage, PVOID *ppMetaData, long *pcbMetaDat return (S_OK); } - -// This function returns the address to the MapView of file and file size. -void GetMapViewOfFile(_In_ WCHAR *szFile, PBYTE *ppbMap, DWORD *pdwFileSize) -{ - HANDLE hMapFile; - DWORD dwHighSize; - - HANDLE hFile = WszCreateFile(szFile, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, - NULL); - if (hFile == INVALID_HANDLE_VALUE) - MDInfo::Error("CreateFileA failed!"); - - *pdwFileSize = GetFileSize(hFile, &dwHighSize); - - if ((*pdwFileSize == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) - { - CloseHandle(hFile); - MDInfo::Error("GetFileSize failed!"); - } - _ASSERTE(dwHighSize == 0); - - hMapFile = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - CloseHandle(hFile); - if (!hMapFile) - MDInfo::Error("CreateFileMappingW failed!"); - - *ppbMap = (PBYTE) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); - CloseHandle(hMapFile); - - if (!*ppbMap) - MDInfo::Error("MapViewOfFile failed!"); -} // void GetMapViewOfFile() - // This function skips a member given the pointer to the member header // and returns a pointer to the next header. PBYTE SkipMember(PBYTE pbMapAddress) @@ -177,7 +140,15 @@ void DisplayArchive(_In_z_ WCHAR* szFile, ULONG DumpFilter, _In_opt_z_ WCHAR* sz HRESULT hr; char szString[1024]; - GetMapViewOfFile(szFile, &pbMapAddress, &dwFileSize); + MemoryMappedFile* f = CreateMappedFile(szFile); + if (f == nullptr || f->Size() >= UINT32_MAX) + { + MDInfo::Error("MapViewOfFile failed!"); + return; + } + + pbMapAddress = (PBYTE)f->Address(); + dwFileSize = (DWORD)f->Size(); pbStartAddress = pbMapAddress; // Verify and skip archive signature. @@ -241,7 +212,7 @@ void DisplayArchive(_In_z_ WCHAR* szFile, ULONG DumpFilter, _In_opt_z_ WCHAR* sz pbMapAddress = SkipMember(pbMapAddress); } - UnmapViewOfFile(pbStartAddress); + delete f; } // void DisplayArchive() // DisplayFile() function diff --git a/src/coreclr/utilcode/longfilepathwrappers.cpp b/src/coreclr/utilcode/longfilepathwrappers.cpp index a0586a0b3ec97b..052400b3928059 100644 --- a/src/coreclr/utilcode/longfilepathwrappers.cpp +++ b/src/coreclr/utilcode/longfilepathwrappers.cpp @@ -343,6 +343,32 @@ CreateFileWrapper( return ret; } +MemoryMappedFile* CreateMappedFileWrapper(const WCHAR* filename) +{ + CONTRACTL + { + NOTHROW; + } + CONTRACTL_END; + + EX_TRY + { + LongPathString path(LongPathString::Literal, filename); + + if (SUCCEEDED(LongFile::NormalizePath(path))) + { + return MemoryMappedFile::Open(path.GetUnicode()); + } + } + EX_CATCH + { + return nullptr; + } + EX_END_CATCH + + return nullptr; +} + int u16_fopen_wrapper(FILE** stream, const WCHAR* filename, const WCHAR* mode) { CONTRACTL