summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt8
-rw-r--r--src/debug/createdump/crashinfo.cpp522
-rw-r--r--src/debug/createdump/crashinfo.h16
-rw-r--r--src/debug/createdump/createdump.h4
-rw-r--r--src/debug/createdump/dumpwriter.cpp65
-rw-r--r--src/debug/createdump/dumpwriter.h6
-rw-r--r--src/debug/createdump/memoryregion.h71
-rw-r--r--src/debug/createdump/threadinfo.cpp22
-rw-r--r--src/jit/lower.cpp10
-rw-r--r--src/jit/morph.cpp115
-rw-r--r--src/mscorlib/System.Private.CoreLib.csproj1
-rw-r--r--src/mscorlib/shared/System/Char.cs1
-rw-r--r--src/mscorlib/shared/System/Collections/DictionaryEntry.cs5
-rw-r--r--src/mscorlib/shared/System/Collections/Generic/KeyValuePair.cs5
-rw-r--r--src/mscorlib/shared/System/DateTime.cs5
-rw-r--r--src/mscorlib/shared/System/DateTimeOffset.cs9
-rw-r--r--src/mscorlib/shared/System/Globalization/SortVersion.cs1
-rw-r--r--src/mscorlib/shared/System/Reflection/Assembly.cs5
-rw-r--r--src/mscorlib/shared/System/Reflection/Module.cs5
-rw-r--r--src/mscorlib/shared/System/Reflection/ParameterInfo.cs41
-rw-r--r--src/mscorlib/shared/System/StringComparer.cs137
-rw-r--r--src/mscorlib/shared/System/Text/StringBuilder.cs10
-rw-r--r--src/mscorlib/shared/System/ValueTuple.cs9
-rw-r--r--src/mscorlib/shared/System/Version.cs9
-rw-r--r--src/mscorlib/src/System/AggregateException.cs3
-rw-r--r--src/mscorlib/src/System/Array.cs1
-rw-r--r--src/mscorlib/src/System/ArraySegment.cs7
-rw-r--r--src/mscorlib/src/System/Attribute.cs1
-rw-r--r--src/mscorlib/src/System/Boolean.cs1
-rw-r--r--src/mscorlib/src/System/Byte.cs1
-rw-r--r--src/mscorlib/src/System/Collections/Comparer.cs11
-rw-r--r--src/mscorlib/src/System/Collections/Generic/Comparer.cs8
-rw-r--r--src/mscorlib/src/System/Collections/Generic/Dictionary.cs9
-rw-r--r--src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs10
-rw-r--r--src/mscorlib/src/System/Collections/Generic/List.cs7
-rw-r--r--src/mscorlib/src/System/Collections/ListDictionaryInternal.cs7
-rw-r--r--src/mscorlib/src/System/Collections/ObjectModel/Collection.cs3
-rw-r--r--src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs3
-rw-r--r--src/mscorlib/src/System/Decimal.cs4
-rw-r--r--src/mscorlib/src/System/Double.cs1
-rw-r--r--src/mscorlib/src/System/Enum.cs1
-rw-r--r--src/mscorlib/src/System/Exception.cs49
-rw-r--r--src/mscorlib/src/System/Globalization/CompareInfo.Windows.cs1
-rw-r--r--src/mscorlib/src/System/Globalization/CompareInfo.cs29
-rw-r--r--src/mscorlib/src/System/Globalization/CultureInfo.cs47
-rw-r--r--src/mscorlib/src/System/Guid.cs23
-rw-r--r--src/mscorlib/src/System/Int16.cs1
-rw-r--r--src/mscorlib/src/System/Int32.cs1
-rw-r--r--src/mscorlib/src/System/Int64.cs1
-rw-r--r--src/mscorlib/src/System/IntPtr.cs3
-rw-r--r--src/mscorlib/src/System/Nullable.cs5
-rw-r--r--src/mscorlib/src/System/Object.cs1
-rw-r--r--src/mscorlib/src/System/Reflection/Assembly.CoreCLR.cs14
-rw-r--r--src/mscorlib/src/System/Resources/LooselyLinkedResourceReference.cs85
-rw-r--r--src/mscorlib/src/System/SByte.cs1
-rw-r--r--src/mscorlib/src/System/Single.cs1
-rw-r--r--src/mscorlib/src/System/String.cs1
-rw-r--r--src/mscorlib/src/System/TimeSpan.cs2
-rw-r--r--src/mscorlib/src/System/TimeZoneInfo.AdjustmentRule.cs28
-rw-r--r--src/mscorlib/src/System/TimeZoneInfo.TransitionTime.cs24
-rw-r--r--src/mscorlib/src/System/TimeZoneInfo.cs29
-rw-r--r--src/mscorlib/src/System/Tuple.cs80
-rw-r--r--src/mscorlib/src/System/UInt16.cs1
-rw-r--r--src/mscorlib/src/System/UInt32.cs1
-rw-r--r--src/mscorlib/src/System/UInt64.cs1
-rw-r--r--src/mscorlib/src/System/UIntPtr.cs3
-rw-r--r--src/mscorlib/src/System/ValueType.cs1
-rw-r--r--src/mscorlib/src/System/WeakReference.cs9
-rw-r--r--src/mscorlib/src/System/WeakReferenceOfT.cs9
-rw-r--r--src/mscorlib/src/mscorlib.Friends.cs2
-rw-r--r--src/pal/src/exception/seh-unwind.cpp9
-rw-r--r--src/pal/src/exception/signal.cpp36
-rw-r--r--src/pal/src/thread/process.cpp4
-rwxr-xr-xsrc/pal/tools/gen-buildsys-clang.sh2
-rw-r--r--src/scripts/genEventPipe.py2
-rw-r--r--src/vm/gcenv.ee.cpp7
-rw-r--r--src/vm/object.cpp3
77 files changed, 1168 insertions, 508 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b761b6a82d..d8a3abf68d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -53,9 +53,15 @@ else()
)
endif(WIN32)
+if(CLR_CMAKE_WARNINGS_ARE_ERRORS)
+ set(PYTHON_WARNING_FLAGS -Wall -Werror)
+else()
+ set(PYTHON_WARNING_FLAGS -Wall)
+endif(CLR_CMAKE_WARNINGS_ARE_ERRORS)
+
add_custom_command(
COMMENT "Generating Eventing Files"
- COMMAND ${PYTHON} -B -Wall -Werror ${GenEventFilesScript} ${GenEventArgs} --man "${VM_DIR}/ClrEtwAll.man" --exc "${VM_DIR}/ClrEtwAllMeta.lst" --dummy "${GENERATED_INCLUDE_DIR}/etmdummy.h"
+ COMMAND ${PYTHON} -B ${PYTHON_WARNING_FLAGS} ${GenEventFilesScript} ${GenEventArgs} --man "${VM_DIR}/ClrEtwAll.man" --exc "${VM_DIR}/ClrEtwAllMeta.lst" --dummy "${GENERATED_INCLUDE_DIR}/etmdummy.h"
OUTPUT ${ScriptGeneratedEventFiles}
DEPENDS ${GenEventFilesScript} "${VM_DIR}/ClrEtwAll.man" "${VM_DIR}/ClrEtwAllMeta.lst" "${CLR_DIR}/src/scripts/genXplatEventing.py"
)
diff --git a/src/debug/createdump/crashinfo.cpp b/src/debug/createdump/crashinfo.cpp
index b825f4d301..edc31616de 100644
--- a/src/debug/createdump/crashinfo.cpp
+++ b/src/debug/createdump/crashinfo.cpp
@@ -89,6 +89,10 @@ CrashInfo::EnumMemoryRegion(
return S_OK;
}
+//
+// Suspends all the threads and creating a list of them. Should be the first before
+// gather any info about the process.
+//
bool
CrashInfo::EnumerateAndSuspendThreads()
{
@@ -134,6 +138,9 @@ CrashInfo::EnumerateAndSuspendThreads()
return true;
}
+//
+// Gather all the necessary crash dump info.
+//
bool
CrashInfo::GatherCrashInfo(const char* programPath, MINIDUMP_TYPE minidumpType)
{
@@ -168,42 +175,33 @@ CrashInfo::GatherCrashInfo(const char* programPath, MINIDUMP_TYPE minidumpType)
// If full memory dump, include everything regardless of permissions
if (minidumpType & MiniDumpWithFullMemory)
{
- for (const MemoryRegion& region : m_moduleMappings)
- {
- if (ValidRegion(region))
- {
- InsertMemoryRegion(region);
- }
+ for (const MemoryRegion& region : m_moduleMappings)
+ {
+ InsertMemoryBackedRegion(region);
}
for (const MemoryRegion& region : m_otherMappings)
{
- if (ValidRegion(region))
- {
- InsertMemoryRegion(region);
- }
+ InsertMemoryBackedRegion(region);
}
}
- else
+ // Add all the heap (read/write) memory regions (m_otherMappings contains the heaps)
+ else if (minidumpType & MiniDumpWithPrivateReadWriteMemory)
{
- // Add all the heap (read/write) memory regions but not the modules' r/w data segments
- if (minidumpType & MiniDumpWithPrivateReadWriteMemory)
+ for (const MemoryRegion& region : m_otherMappings)
{
- for (const MemoryRegion& region : m_otherMappings)
+ if (region.Permissions() == (PF_R | PF_W))
{
- if (region.Permissions() == (PF_R | PF_W))
- {
- if (ValidRegion(region))
- {
- InsertMemoryRegion(region);
- }
- }
+ InsertMemoryBackedRegion(region);
}
}
- // Gather all the useful memory regions from the DAC
- if (!EnumerateMemoryRegionsWithDAC(programPath, minidumpType))
- {
- return false;
- }
+ }
+ // Gather all the useful memory regions from the DAC
+ if (!EnumerateMemoryRegionsWithDAC(programPath, minidumpType))
+ {
+ return false;
+ }
+ if ((minidumpType & MiniDumpWithFullMemory) == 0)
+ {
// Add the thread's stack and some code memory to core
for (ThreadInfo* thread : m_threads)
{
@@ -217,6 +215,19 @@ CrashInfo::GatherCrashInfo(const char* programPath, MINIDUMP_TYPE minidumpType)
thread->GetThreadCode(&start, &size);
InsertMemoryRegion(start, size);
}
+ // All the regions added so far has been backed by memory. Now add the rest of
+ // mappings so the debuggers like lldb see that an address is code (PF_X) even
+ // if it isn't actually in the core dump.
+ for (const MemoryRegion& region : m_moduleMappings)
+ {
+ assert(!region.IsBackedByMemory());
+ InsertMemoryRegion(region);
+ }
+ for (const MemoryRegion& region : m_otherMappings)
+ {
+ assert(!region.IsBackedByMemory());
+ InsertMemoryRegion(region);
+ }
}
// Join all adjacent memory regions
CombineMemoryRegions();
@@ -235,6 +246,9 @@ CrashInfo::ResumeThreads()
}
}
+//
+// Get the auxv entries to use and add to the core dump
+//
bool
CrashInfo::GetAuxvEntries()
{
@@ -269,6 +283,9 @@ CrashInfo::GetAuxvEntries()
return result;
}
+//
+// Get the module mappings for the core dump NT_FILE notes
+//
bool
CrashInfo::EnumerateModuleMappings()
{
@@ -320,30 +337,38 @@ CrashInfo::EnumerateModuleMappings()
int c = sscanf(line, "%lx-%lx %m[-rwxsp] %lx %*[:0-9a-f] %*d %ms\n", &start, &end, &permissions, &offset, &moduleName);
if (c == 4 || c == 5)
{
- if (linuxGateAddress != nullptr && reinterpret_cast<void*>(start) == linuxGateAddress)
- {
- InsertMemoryRegion(start, end - start);
- free(moduleName);
+ // r = read
+ // w = write
+ // x = execute
+ // s = shared
+ // p = private (copy on write)
+ uint32_t regionFlags = 0;
+ if (strchr(permissions, 'r')) {
+ regionFlags |= PF_R;
}
- else {
- uint32_t permissionFlags = 0;
- if (strchr(permissions, 'r')) {
- permissionFlags |= PF_R;
- }
- if (strchr(permissions, 'w')) {
- permissionFlags |= PF_W;
- }
- if (strchr(permissions, 'x')) {
- permissionFlags |= PF_X;
- }
- MemoryRegion memoryRegion(permissionFlags, start, end, offset, moduleName);
+ if (strchr(permissions, 'w')) {
+ regionFlags |= PF_W;
+ }
+ if (strchr(permissions, 'x')) {
+ regionFlags |= PF_X;
+ }
+ if (strchr(permissions, 's')) {
+ regionFlags |= MEMORY_REGION_FLAG_SHARED;
+ }
+ if (strchr(permissions, 'p')) {
+ regionFlags |= MEMORY_REGION_FLAG_PRIVATE;
+ }
+ MemoryRegion memoryRegion(regionFlags, start, end, offset, moduleName);
- if (moduleName != nullptr && *moduleName == '/') {
- m_moduleMappings.insert(memoryRegion);
- }
- else {
- m_otherMappings.insert(memoryRegion);
- }
+ if (moduleName != nullptr && *moduleName == '/') {
+ m_moduleMappings.insert(memoryRegion);
+ }
+ else {
+ m_otherMappings.insert(memoryRegion);
+ }
+ if (linuxGateAddress != nullptr && reinterpret_cast<void*>(start) == linuxGateAddress)
+ {
+ InsertMemoryBackedRegion(memoryRegion);
}
free(permissions);
}
@@ -354,12 +379,12 @@ CrashInfo::EnumerateModuleMappings()
TRACE("Module mappings:\n");
for (const MemoryRegion& region : m_moduleMappings)
{
- region.Print();
+ region.Trace();
}
TRACE("Other mappings:\n");
for (const MemoryRegion& region : m_otherMappings)
{
- region.Print();
+ region.Trace();
}
}
@@ -369,12 +394,16 @@ CrashInfo::EnumerateModuleMappings()
return true;
}
+//
+// All the shared (native) module info to the core dump
+//
bool
CrashInfo::GetDSOInfo()
{
Phdr* phdrAddr = reinterpret_cast<Phdr*>(m_auxvValues[AT_PHDR]);
int phnum = m_auxvValues[AT_PHNUM];
assert(m_auxvValues[AT_PHENT] == sizeof(Phdr));
+ assert(phnum != PN_XNUM);
if (phnum <= 0 || phdrAddr == nullptr) {
return false;
@@ -387,6 +416,7 @@ CrashInfo::GetDSOInfo()
{
Phdr ph;
if (!ReadMemory(phdrAddr, &ph, sizeof(ph))) {
+ fprintf(stderr, "ReadMemory(%p, %lx) phdr FAILED\n", phdrAddr, sizeof(ph));
return false;
}
TRACE("DSO: phdr %p type %d (%x) vaddr %016lx memsz %016lx offset %016lx\n",
@@ -396,7 +426,7 @@ CrashInfo::GetDSOInfo()
{
dynamicAddr = reinterpret_cast<ElfW(Dyn)*>(ph.p_vaddr);
}
- else if (ph.p_type == PT_GNU_EH_FRAME)
+ else if (ph.p_type == PT_NOTE || ph.p_type == PT_GNU_EH_FRAME)
{
if (ph.p_vaddr != 0 && ph.p_memsz != 0)
{
@@ -414,6 +444,7 @@ CrashInfo::GetDSOInfo()
for (;;) {
ElfW(Dyn) dyn;
if (!ReadMemory(dynamicAddr, &dyn, sizeof(dyn))) {
+ fprintf(stderr, "ReadMemory(%p, %lx) dyn FAILED\n", dynamicAddr, sizeof(dyn));
return false;
}
TRACE("DSO: dyn %p tag %ld (%lx) d_ptr %016lx\n", dynamicAddr, dyn.d_tag, dyn.d_tag, dyn.d_un.d_ptr);
@@ -430,6 +461,7 @@ CrashInfo::GetDSOInfo()
TRACE("DSO: rdebugAddr %p\n", rdebugAddr);
struct r_debug debugEntry;
if (!ReadMemory(rdebugAddr, &debugEntry, sizeof(debugEntry))) {
+ fprintf(stderr, "ReadMemory(%p, %lx) r_debug FAILED\n", rdebugAddr, sizeof(debugEntry));
return false;
}
@@ -438,8 +470,10 @@ CrashInfo::GetDSOInfo()
for (struct link_map* linkMapAddr = debugEntry.r_map; linkMapAddr != nullptr;) {
struct link_map map;
if (!ReadMemory(linkMapAddr, &map, sizeof(map))) {
+ fprintf(stderr, "ReadMemory(%p, %lx) link_map FAILED\n", linkMapAddr, sizeof(map));
return false;
}
+ // Read the module's name and make sure the memory is added to the core dump
int i = 0;
if (map.l_name != nullptr) {
for (; i < PATH_MAX; i++)
@@ -454,18 +488,134 @@ CrashInfo::GetDSOInfo()
}
}
moduleName[i] = '\0';
- TRACE("DSO: link_map entry %p l_ld %p l_addr %lx %s\n", linkMapAddr, map.l_ld, map.l_addr, (char*)moduleName);
+ TRACE("\nDSO: link_map entry %p l_ld %p l_addr (Ehdr) %lx %s\n", linkMapAddr, map.l_ld, map.l_addr, (char*)moduleName);
+
+ // Read the ELF header and info adding it to the core dump
+ if (!GetELFInfo(map.l_addr)) {
+ return false;
+ }
linkMapAddr = map.l_next;
}
return true;
}
+inline bool
+NameCompare(const char* name, const char* sectionName)
+{
+ return strncmp(name, sectionName, strlen(sectionName) + 1) == 0;
+}
+
+//
+// Add all the necessary ELF headers to the core dump
+//
+bool
+CrashInfo::GetELFInfo(uint64_t baseAddress)
+{
+ if (baseAddress == 0) {
+ return true;
+ }
+ Ehdr ehdr;
+ if (!ReadMemory((void*)baseAddress, &ehdr, sizeof(ehdr))) {
+ fprintf(stderr, "ReadMemory(%p, %lx) ehdr FAILED\n", (void*)baseAddress, sizeof(ehdr));
+ return false;
+ }
+ int phnum = ehdr.e_phnum;
+ int shnum = ehdr.e_shnum;
+ assert(phnum != PN_XNUM);
+ assert(shnum != SHN_XINDEX);
+ assert(ehdr.e_shstrndx != SHN_XINDEX);
+ assert(ehdr.e_phentsize == sizeof(Phdr));
+ assert(ehdr.e_shentsize == sizeof(Shdr));
+ assert(ehdr.e_ident[EI_CLASS] == ELFCLASS64);
+ assert(ehdr.e_ident[EI_DATA] == ELFDATA2LSB);
+
+ TRACE("ELF: type %d mach 0x%x ver %d flags 0x%x phnum %d phoff %016lx phentsize 0x%02x shnum %d shoff %016lx shentsize 0x%02x shstrndx %d\n",
+ ehdr.e_type, ehdr.e_machine, ehdr.e_version, ehdr.e_flags, phnum, ehdr.e_phoff, ehdr.e_phentsize, shnum, ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shstrndx);
+
+ if (ehdr.e_phoff != 0 && phnum > 0)
+ {
+ Phdr* phdrAddr = reinterpret_cast<Phdr*>(baseAddress + ehdr.e_phoff);
+
+ // Add the program headers and search for the module's note and unwind info segments
+ for (int i = 0; i < phnum; i++, phdrAddr++)
+ {
+ Phdr ph;
+ if (!ReadMemory(phdrAddr, &ph, sizeof(ph))) {
+ fprintf(stderr, "ReadMemory(%p, %lx) phdr FAILED\n", phdrAddr, sizeof(ph));
+ return false;
+ }
+ TRACE("ELF: phdr %p type %d (%x) vaddr %016lx memsz %016lx paddr %016lx filesz %016lx offset %016lx align %016lx\n",
+ phdrAddr, ph.p_type, ph.p_type, ph.p_vaddr, ph.p_memsz, ph.p_paddr, ph.p_filesz, ph.p_offset, ph.p_align);
+
+ if (ph.p_type == PT_DYNAMIC || ph.p_type == PT_NOTE || ph.p_type == PT_GNU_EH_FRAME)
+ {
+ if (ph.p_vaddr != 0 && ph.p_memsz != 0)
+ {
+ InsertMemoryRegion(baseAddress + ph.p_vaddr, ph.p_memsz);
+ }
+ }
+ }
+ }
+
+ // Skip the "interpreter" module i.e. /lib64/ld-linux-x86-64.so.2 or ld-2.19.so. The in-memory section headers are
+ // not valid. Ignore all failures too because on debug builds of coreclr, the section headers are not in valid memory.
+ if (baseAddress != m_auxvValues[AT_BASE] && ehdr.e_shoff != 0 && shnum > 0 && ehdr.e_shstrndx != SHN_UNDEF)
+ {
+ Shdr* shdrAddr = reinterpret_cast<Shdr*>(baseAddress + ehdr.e_shoff);
+
+ // Get the string table section header
+ Shdr stringTableSectionHeader;
+ if (!ReadMemory(shdrAddr + ehdr.e_shstrndx, &stringTableSectionHeader, sizeof(stringTableSectionHeader))) {
+ TRACE("ELF: %2d shdr %p ReadMemory string table section header FAILED\n", ehdr.e_shstrndx, shdrAddr + ehdr.e_shstrndx);
+ return true;
+ }
+ // Get the string table
+ ArrayHolder<char> stringTable = new char[stringTableSectionHeader.sh_size];
+ if (!ReadMemory((void*)(baseAddress + stringTableSectionHeader.sh_offset), stringTable.GetPtr(), stringTableSectionHeader.sh_size)) {
+ TRACE("ELF: %2d shdr %p ReadMemory string table FAILED\n", ehdr.e_shstrndx, (void*)(baseAddress + stringTableSectionHeader.sh_offset));
+ return true;
+ }
+ // Add the section headers to the core dump
+ for (int sectionIndex = 0; sectionIndex < shnum; sectionIndex++, shdrAddr++)
+ {
+ Shdr sh;
+ if (!ReadMemory(shdrAddr, &sh, sizeof(sh))) {
+ TRACE("ELF: %2d shdr %p ReadMemory FAILED\n", sectionIndex, shdrAddr);
+ return true;
+ }
+ TRACE("ELF: %2d shdr %p type %2d (%x) addr %016lx offset %016lx size %016lx link %08x info %08x name %4d %s\n",
+ sectionIndex, shdrAddr, sh.sh_type, sh.sh_type, sh.sh_addr, sh.sh_offset, sh.sh_size, sh.sh_link, sh.sh_info, sh.sh_name, &stringTable[sh.sh_name]);
+
+ if (sh.sh_name != SHN_UNDEF && sh.sh_offset > 0 && sh.sh_size > 0) {
+ char* name = &stringTable[sh.sh_name];
+
+ // Add the .eh_frame/.eh_frame_hdr unwind info to the core dump
+ if (NameCompare(name, ".eh_frame") ||
+ NameCompare(name, ".eh_frame_hdr") ||
+ NameCompare(name, ".note.gnu.build-id") ||
+ NameCompare(name, ".note.gnu.ABI-tag") ||
+ NameCompare(name, ".gnu_debuglink"))
+ {
+ TRACE("ELF: %s %p size %016lx\n", name, (void*)(baseAddress + sh.sh_offset), sh.sh_size);
+ InsertMemoryRegion(baseAddress + sh.sh_offset, sh.sh_size);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+//
+// Enumerate all the memory regions using the DAC memory region support given a minidump type
+//
bool
CrashInfo::EnumerateMemoryRegionsWithDAC(const char* programPath, MINIDUMP_TYPE minidumpType)
{
PFN_CLRDataCreateInstance pfnCLRDataCreateInstance = nullptr;
- ICLRDataEnumMemoryRegions *clrDataEnumRegions = nullptr;
+ ICLRDataEnumMemoryRegions* clrDataEnumRegions = nullptr;
+ IXCLRDataProcess* clrDataProcess = nullptr;
HMODULE hdac = nullptr;
HRESULT hr = S_OK;
bool result = false;
@@ -475,7 +625,7 @@ CrashInfo::EnumerateMemoryRegionsWithDAC(const char* programPath, MINIDUMP_TYPE
dacPath.append(programPath);
dacPath.append("/");
dacPath.append(MAKEDLLNAME_A("mscordaccore"));
-
+
// Load and initialize the DAC
hdac = LoadLibraryA(dacPath.c_str());
if (hdac == nullptr)
@@ -489,17 +639,30 @@ CrashInfo::EnumerateMemoryRegionsWithDAC(const char* programPath, MINIDUMP_TYPE
fprintf(stderr, "GetProcAddress(CLRDataCreateInstance) FAILED %d\n", GetLastError());
goto exit;
}
- hr = pfnCLRDataCreateInstance(__uuidof(ICLRDataEnumMemoryRegions), m_dataTarget, (void**)&clrDataEnumRegions);
+ if ((minidumpType & MiniDumpWithFullMemory) == 0)
+ {
+ hr = pfnCLRDataCreateInstance(__uuidof(ICLRDataEnumMemoryRegions), m_dataTarget, (void**)&clrDataEnumRegions);
+ if (FAILED(hr))
+ {
+ fprintf(stderr, "CLRDataCreateInstance(ICLRDataEnumMemoryRegions) FAILED %08x\n", hr);
+ goto exit;
+ }
+ // Calls CrashInfo::EnumMemoryRegion for each memory region found by the DAC
+ hr = clrDataEnumRegions->EnumMemoryRegions(this, minidumpType, CLRDATA_ENUM_MEM_DEFAULT);
+ if (FAILED(hr))
+ {
+ fprintf(stderr, "EnumMemoryRegions FAILED %08x\n", hr);
+ goto exit;
+ }
+ }
+ hr = pfnCLRDataCreateInstance(__uuidof(IXCLRDataProcess), m_dataTarget, (void**)&clrDataProcess);
if (FAILED(hr))
{
- fprintf(stderr, "CLRDataCreateInstance(ICLRDataEnumMemoryRegions) FAILED %08x\n", hr);
+ fprintf(stderr, "CLRDataCreateInstance(IXCLRDataProcess) FAILED %08x\n", hr);
goto exit;
}
- // Calls CrashInfo::EnumMemoryRegion for each memory region found by the DAC
- hr = clrDataEnumRegions->EnumMemoryRegions(this, minidumpType, CLRDATA_ENUM_MEM_DEFAULT);
- if (FAILED(hr))
+ if (!EnumerateManagedModules(clrDataProcess))
{
- fprintf(stderr, "EnumMemoryRegions FAILED %08x\n", hr);
goto exit;
}
result = true;
@@ -508,6 +671,10 @@ exit:
{
clrDataEnumRegions->Release();
}
+ if (clrDataProcess != nullptr)
+ {
+ clrDataProcess->Release();
+ }
if (hdac != nullptr)
{
FreeLibrary(hdac);
@@ -516,6 +683,104 @@ exit:
}
//
+// Enumerate all the managed modules and replace the module
+// mapping with the module name found.
+//
+bool
+CrashInfo::EnumerateManagedModules(IXCLRDataProcess* clrDataProcess)
+{
+ IXCLRDataModule* clrDataModule = nullptr;
+ CLRDATA_ENUM enumModules = 0;
+ HRESULT hr = S_OK;
+
+ if (FAILED(hr = clrDataProcess->StartEnumModules(&enumModules))) {
+ fprintf(stderr, "StartEnumModules FAILED %08x\n", hr);
+ return false;
+ }
+ while ((hr = clrDataProcess->EnumModule(&enumModules, &clrDataModule)) == S_OK)
+ {
+ DacpGetModuleData moduleData;
+ if (SUCCEEDED(hr = moduleData.Request(clrDataModule)))
+ {
+ TRACE("MODULE: %016lx dyn %d inmem %d file %d pe %016lx pdb %016lx", moduleData.LoadedPEAddress, moduleData.IsDynamic,
+ moduleData.IsInMemory, moduleData.IsFileLayout, moduleData.PEFile, moduleData.InMemoryPdbAddress);
+
+ if (!moduleData.IsDynamic && moduleData.LoadedPEAddress != 0)
+ {
+ ArrayHolder<WCHAR> wszUnicodeName = new WCHAR[MAX_LONGPATH + 1];
+ if (SUCCEEDED(hr = clrDataModule->GetFileName(MAX_LONGPATH, NULL, wszUnicodeName)))
+ {
+ char* pszName = (char*)malloc(MAX_LONGPATH + 1);
+ if (pszName == nullptr) {
+ fprintf(stderr, "Allocating module name FAILED\n");
+ return false;
+ }
+ sprintf_s(pszName, MAX_LONGPATH, "%S", (WCHAR*)wszUnicodeName);
+ TRACE(" %s\n", pszName);
+
+ // Change the module mapping name
+ ReplaceModuleMapping(moduleData.LoadedPEAddress, pszName);
+ }
+ else {
+ TRACE("\nModule.GetFileName FAILED %08x\n", hr);
+ }
+ }
+ else {
+ TRACE("\n");
+ }
+ }
+ else {
+ TRACE("moduleData.Request FAILED %08x\n", hr);
+ }
+ if (clrDataModule != nullptr) {
+ clrDataModule->Release();
+ }
+ }
+ if (enumModules != 0) {
+ clrDataProcess->EndEnumModules(enumModules);
+ }
+ return true;
+}
+
+//
+// Replace an existing module mapping with one with a different name.
+//
+void
+CrashInfo::ReplaceModuleMapping(CLRDATA_ADDRESS baseAddress, const char* pszName)
+{
+ // Add or change the module mapping for this PE image. The managed assembly images are
+ // already in the module mappings list but in .NET 2.0 they have the name "/dev/zero".
+ MemoryRegion region(PF_R | PF_W | PF_X, baseAddress, baseAddress + PAGE_SIZE, 0, pszName);
+ const auto& found = m_moduleMappings.find(region);
+ if (found == m_moduleMappings.end())
+ {
+ m_moduleMappings.insert(region);
+
+ if (g_diagnostics) {
+ TRACE("MODULE: ADD ");
+ region.Trace();
+ }
+ }
+ else
+ {
+ // Create the new memory region with the managed assembly name.
+ MemoryRegion newRegion(*found, pszName);
+
+ // Remove and cleanup the old one
+ m_moduleMappings.erase(found);
+ const_cast<MemoryRegion&>(*found).Cleanup();
+
+ // Add the new memory region
+ m_moduleMappings.insert(newRegion);
+
+ if (g_diagnostics) {
+ TRACE("MODULE: REPLACE ");
+ newRegion.Trace();
+ }
+ }
+}
+
+//
// ReadMemory from target and add to memory regions list
//
bool
@@ -524,7 +789,6 @@ CrashInfo::ReadMemory(void* address, void* buffer, size_t size)
uint32_t read = 0;
if (FAILED(m_dataTarget->ReadVirtual(reinterpret_cast<CLRDATA_ADDRESS>(address), reinterpret_cast<PBYTE>(buffer), size, &read)))
{
- fprintf(stderr, "ReadMemory(%p, %lx) FAILED\n", address, size);
return false;
}
InsertMemoryRegion(reinterpret_cast<uint64_t>(address), size);
@@ -538,6 +802,8 @@ CrashInfo::ReadMemory(void* address, void* buffer, size_t size)
void
CrashInfo::InsertMemoryRegion(uint64_t address, size_t size)
{
+ assert(size < UINT_MAX);
+
// Round to page boundary
uint64_t start = address & PAGE_MASK;
assert(start > 0);
@@ -546,8 +812,16 @@ CrashInfo::InsertMemoryRegion(uint64_t address, size_t size)
uint64_t end = ((address + size) + (PAGE_SIZE - 1)) & PAGE_MASK;
assert(end > 0);
- MemoryRegion region(start, end);
- InsertMemoryRegion(region);
+ InsertMemoryRegion(MemoryRegion(GetMemoryRegionFlags(start) | MEMORY_REGION_FLAG_MEMORY_BACKED, start, end));
+}
+
+//
+// Adds a memory backed flagged copy of the memory region. The file name is not preserved.
+//
+void
+CrashInfo::InsertMemoryBackedRegion(const MemoryRegion& region)
+{
+ InsertMemoryRegion(MemoryRegion(region, region.Flags() | MEMORY_REGION_FLAG_MEMORY_BACKED));
}
//
@@ -556,52 +830,88 @@ CrashInfo::InsertMemoryRegion(uint64_t address, size_t size)
void
CrashInfo::InsertMemoryRegion(const MemoryRegion& region)
{
- // First check if the full memory region can be added without conflicts
+ // First check if the full memory region can be added without conflicts and is fully valid.
const auto& found = m_memoryRegions.find(region);
if (found == m_memoryRegions.end())
{
- // Add full memory region
- m_memoryRegions.insert(region);
+ // If the region is valid, add the full memory region
+ if (ValidRegion(region)) {
+ m_memoryRegions.insert(region);
+ return;
+ }
}
else
{
- // The memory region is not wholely contained in region found
- if (!found->Contains(region))
- {
- uint64_t start = region.StartAddress();
+ // If the memory region is wholly contained in region found and both have the
+ // same backed by memory state, we're done.
+ if (found->Contains(region) && (found->IsBackedByMemory() == region.IsBackedByMemory())) {
+ return;
+ }
+ }
+ // Either part of the region was invalid, part of it hasn't been added or the backed
+ // by memory state is different.
+ uint64_t start = region.StartAddress();
- // The region overlaps/conflicts with one already in the set so
- // add one page at a time to avoid the overlapping pages.
- uint64_t numberPages = region.Size() >> PAGE_SHIFT;
+ // The region overlaps/conflicts with one already in the set so add one page at a
+ // time to avoid the overlapping pages.
+ uint64_t numberPages = region.Size() >> PAGE_SHIFT;
- for (int p = 0; p < numberPages; p++, start += PAGE_SIZE)
- {
- MemoryRegion memoryRegionPage(start, start + PAGE_SIZE);
+ for (int p = 0; p < numberPages; p++, start += PAGE_SIZE)
+ {
+ MemoryRegion memoryRegionPage(region.Flags(), start, start + PAGE_SIZE);
- const auto& found = m_memoryRegions.find(memoryRegionPage);
- if (found == m_memoryRegions.end())
- {
- m_memoryRegions.insert(memoryRegionPage);
- }
+ const auto& found = m_memoryRegions.find(memoryRegionPage);
+ if (found == m_memoryRegions.end())
+ {
+ // All the single pages added here will be combined in CombineMemoryRegions()
+ if (ValidRegion(memoryRegionPage)) {
+ m_memoryRegions.insert(memoryRegionPage);
}
}
+ else {
+ assert(found->IsBackedByMemory() || !region.IsBackedByMemory());
+ }
}
}
+//
+// Get the memory region flags for a start address
+//
+uint32_t
+CrashInfo::GetMemoryRegionFlags(uint64_t start)
+{
+ const MemoryRegion* region = SearchMemoryRegions(m_moduleMappings, start);
+ if (region != nullptr) {
+ return region->Flags();
+ }
+ region = SearchMemoryRegions(m_otherMappings, start);
+ if (region != nullptr) {
+ return region->Flags();
+ }
+ TRACE("GetMemoryRegionFlags: FAILED\n");
+ return PF_R | PF_W | PF_X;
+}
+
+//
+// Validates a memory region
+//
bool
CrashInfo::ValidRegion(const MemoryRegion& region)
{
- uint64_t start = region.StartAddress();
- uint64_t numberPages = region.Size() >> PAGE_SHIFT;
-
- for (int p = 0; p < numberPages; p++, start += PAGE_SIZE)
+ if (region.IsBackedByMemory())
{
- BYTE buffer[1];
- uint32_t read;
+ uint64_t start = region.StartAddress();
+ uint64_t numberPages = region.Size() >> PAGE_SHIFT;
- if (FAILED(m_dataTarget->ReadVirtual(start, buffer, 1, &read)))
+ for (int p = 0; p < numberPages; p++, start += PAGE_SIZE)
{
- return false;
+ BYTE buffer[1];
+ uint32_t read;
+
+ if (FAILED(m_dataTarget->ReadVirtual(start, buffer, 1, &read)))
+ {
+ return false;
+ }
}
}
return true;
@@ -617,28 +927,34 @@ CrashInfo::CombineMemoryRegions()
std::set<MemoryRegion> memoryRegionsNew;
+ // MEMORY_REGION_FLAG_SHARED and MEMORY_REGION_FLAG_PRIVATE are internal flags that
+ // don't affect the core dump so ignore them when comparing the flags.
+ uint32_t flags = m_memoryRegions.begin()->Flags() & (MEMORY_REGION_FLAG_MEMORY_BACKED | MEMORY_REGION_FLAG_PERMISSIONS_MASK);
uint64_t start = m_memoryRegions.begin()->StartAddress();
uint64_t end = start;
for (const MemoryRegion& region : m_memoryRegions)
{
- if (end == region.StartAddress())
+ // To combine a region it needs to be contiguous, same permissions and memory backed flag.
+ if ((end == region.StartAddress()) &&
+ (flags == (region.Flags() & (MEMORY_REGION_FLAG_MEMORY_BACKED | MEMORY_REGION_FLAG_PERMISSIONS_MASK))))
{
end = region.EndAddress();
}
else
{
- MemoryRegion memoryRegion(start, end);
+ MemoryRegion memoryRegion(flags, start, end);
assert(memoryRegionsNew.find(memoryRegion) == memoryRegionsNew.end());
memoryRegionsNew.insert(memoryRegion);
+ flags = region.Flags() & (MEMORY_REGION_FLAG_MEMORY_BACKED | MEMORY_REGION_FLAG_PERMISSIONS_MASK);
start = region.StartAddress();
end = region.EndAddress();
}
}
assert(start != end);
- MemoryRegion memoryRegion(start, end);
+ MemoryRegion memoryRegion(flags, start, end);
assert(memoryRegionsNew.find(memoryRegion) == memoryRegionsNew.end());
memoryRegionsNew.insert(memoryRegion);
@@ -649,11 +965,31 @@ CrashInfo::CombineMemoryRegions()
TRACE("Memory Regions:\n");
for (const MemoryRegion& region : m_memoryRegions)
{
- region.Print();
+ region.Trace();
+ }
+ }
+}
+
+//
+// Searches for a memory region given an address.
+//
+const MemoryRegion*
+CrashInfo::SearchMemoryRegions(const std::set<MemoryRegion>& regions, uint64_t start)
+{
+ std::set<MemoryRegion>::iterator found = regions.find(MemoryRegion(0, start, start + PAGE_SIZE));
+ for (; found != regions.end(); found++)
+ {
+ if (start >= found->StartAddress() && start < found->EndAddress())
+ {
+ return &*found;
}
}
+ return nullptr;
}
+//
+// Get the process or thread status
+//
bool
CrashInfo::GetStatus(pid_t pid, pid_t* ppid, pid_t* tgid, char** name)
{
diff --git a/src/debug/createdump/crashinfo.h b/src/debug/createdump/crashinfo.h
index 914a88e8dd..43e82691aa 100644
--- a/src/debug/createdump/crashinfo.h
+++ b/src/debug/createdump/crashinfo.h
@@ -38,6 +38,7 @@ public:
bool GatherCrashInfo(const char* programPath, MINIDUMP_TYPE minidumpType);
void ResumeThreads();
static bool GetStatus(pid_t pid, pid_t* ppid, pid_t* tgid, char** name);
+ static const MemoryRegion* SearchMemoryRegions(const std::set<MemoryRegion>& regions, uint64_t start);
const pid_t Pid() const { return m_pid; }
const pid_t Ppid() const { return m_ppid; }
@@ -46,9 +47,9 @@ public:
ICLRDataTarget* DataTarget() const { return m_dataTarget; }
const std::vector<ThreadInfo*> Threads() const { return m_threads; }
- const std::set<MemoryRegion> ModuleMappings() const { return m_moduleMappings; }
- const std::set<MemoryRegion> OtherMappings() const { return m_otherMappings; }
- const std::set<MemoryRegion> MemoryRegions() const { return m_memoryRegions; }
+ const std::set<MemoryRegion> ModuleMappings() const { return m_moduleMappings; }
+ const std::set<MemoryRegion> OtherMappings() const { return m_otherMappings; }
+ const std::set<MemoryRegion> MemoryRegions() const { return m_memoryRegions; }
const std::vector<elf_aux_entry> AuxvEntries() const { return m_auxvEntries; }
const size_t GetAuxvSize() const { return m_auxvEntries.size() * sizeof(elf_aux_entry); }
@@ -58,18 +59,21 @@ public:
STDMETHOD_(ULONG, Release)();
// ICLRDataEnumMemoryRegionsCallback
- virtual HRESULT STDMETHODCALLTYPE EnumMemoryRegion(
- /* [in] */ CLRDATA_ADDRESS address,
- /* [in] */ ULONG32 size);
+ virtual HRESULT STDMETHODCALLTYPE EnumMemoryRegion(/* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 size);
private:
bool GetAuxvEntries();
bool EnumerateModuleMappings();
bool GetDSOInfo();
+ bool GetELFInfo(uint64_t baseAddress);
bool EnumerateMemoryRegionsWithDAC(const char* programPath, MINIDUMP_TYPE minidumpType);
+ bool EnumerateManagedModules(IXCLRDataProcess* clrDataProcess);
+ void ReplaceModuleMapping(CLRDATA_ADDRESS baseAddress, const char* pszName);
bool ReadMemory(void* address, void* buffer, size_t size);
+ void InsertMemoryBackedRegion(const MemoryRegion& region);
void InsertMemoryRegion(uint64_t address, size_t size);
void InsertMemoryRegion(const MemoryRegion& region);
+ uint32_t GetMemoryRegionFlags(uint64_t start);
bool ValidRegion(const MemoryRegion& region);
void CombineMemoryRegions();
};
diff --git a/src/debug/createdump/createdump.h b/src/debug/createdump/createdump.h
index 38c3525f34..6f72f0e955 100644
--- a/src/debug/createdump/createdump.h
+++ b/src/debug/createdump/createdump.h
@@ -33,6 +33,8 @@ extern bool g_diagnostics;
#include <xcordebug.h>
#include <mscoree.h>
#include <dumpcommon.h>
+typedef int T_CONTEXT;
+#include <dacprivate.h>
#include <arrayholder.h>
#include <releaseholder.h>
#include <unistd.h>
@@ -54,4 +56,4 @@ extern bool g_diagnostics;
#include "threadinfo.h"
#include "memoryregion.h"
#include "crashinfo.h"
-#include "dumpwriter.h" \ No newline at end of file
+#include "dumpwriter.h"
diff --git a/src/debug/createdump/dumpwriter.cpp b/src/debug/createdump/dumpwriter.cpp
index 69f0ece8af..06c5b96d01 100644
--- a/src/debug/createdump/dumpwriter.cpp
+++ b/src/debug/createdump/dumpwriter.cpp
@@ -91,14 +91,9 @@ DumpWriter::WriteDump()
ehdr.e_ident[1] = ELFMAG1;
ehdr.e_ident[2] = ELFMAG2;
ehdr.e_ident[3] = ELFMAG3;
- ehdr.e_ident[4] = ELF_CLASS;
-
- // Note: The sex is the current system running minidump-2-core
- // Big or Little endian. This means you have to create
- // the core (minidump-2-core) on the system that matches
- // your intent to debug properly.
- ehdr.e_ident[5] = sex() ? ELFDATA2MSB : ELFDATA2LSB;
- ehdr.e_ident[6] = EV_CURRENT;
+ ehdr.e_ident[EI_CLASS] = ELF_CLASS;
+ ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+ ehdr.e_ident[EI_VERSION] = EV_CURRENT;
ehdr.e_ident[EI_OSABI] = ELFOSABI_LINUX;
ehdr.e_type = ET_CORE;
@@ -180,9 +175,17 @@ DumpWriter::WriteDump()
phdr.p_vaddr = memoryRegion.StartAddress();
phdr.p_memsz = memoryRegion.Size();
- offset += filesz;
- phdr.p_filesz = filesz = memoryRegion.Size();
- phdr.p_offset = offset;
+ if (memoryRegion.IsBackedByMemory())
+ {
+ offset += filesz;
+ phdr.p_filesz = filesz = memoryRegion.Size();
+ phdr.p_offset = offset;
+ }
+ else
+ {
+ phdr.p_filesz = 0;
+ phdr.p_offset = 0;
+ }
if (!WriteData(&phdr, sizeof(phdr))) {
return false;
@@ -230,26 +233,30 @@ DumpWriter::WriteDump()
uint64_t total = 0;
for (const MemoryRegion& memoryRegion : m_crashInfo.MemoryRegions())
{
- uint32_t size = memoryRegion.Size();
- uint64_t address = memoryRegion.StartAddress();
- total += size;
-
- while (size > 0)
+ // Only write the regions that are backed by memory
+ if (memoryRegion.IsBackedByMemory())
{
- uint32_t bytesToRead = std::min(size, (uint32_t)sizeof(m_tempBuffer));
- uint32_t read = 0;
-
- if (FAILED(m_crashInfo.DataTarget()->ReadVirtual(address, m_tempBuffer, bytesToRead, &read))) {
- fprintf(stderr, "ReadVirtual(%016lx, %08x) FAILED\n", address, bytesToRead);
- return false;
- }
-
- if (!WriteData(m_tempBuffer, read)) {
- return false;
+ uint32_t size = memoryRegion.Size();
+ uint64_t address = memoryRegion.StartAddress();
+ total += size;
+
+ while (size > 0)
+ {
+ uint32_t bytesToRead = std::min(size, (uint32_t)sizeof(m_tempBuffer));
+ uint32_t read = 0;
+
+ if (FAILED(m_crashInfo.DataTarget()->ReadVirtual(address, m_tempBuffer, bytesToRead, &read))) {
+ fprintf(stderr, "ReadVirtual(%016lx, %08x) FAILED\n", address, bytesToRead);
+ return false;
+ }
+
+ if (!WriteData(m_tempBuffer, read)) {
+ return false;
+ }
+
+ address += read;
+ size -= read;
}
-
- address += read;
- size -= read;
}
}
diff --git a/src/debug/createdump/dumpwriter.h b/src/debug/createdump/dumpwriter.h
index 0b4f88cbd6..7da0d63ccf 100644
--- a/src/debug/createdump/dumpwriter.h
+++ b/src/debug/createdump/dumpwriter.h
@@ -69,9 +69,3 @@ private:
);
}
};
-
-static inline int sex()
-{
- int probe = 1;
- return !*(char *)&probe;
-}
diff --git a/src/debug/createdump/memoryregion.h b/src/debug/createdump/memoryregion.h
index 1332ab1416..1f6c5f53e6 100644
--- a/src/debug/createdump/memoryregion.h
+++ b/src/debug/createdump/memoryregion.h
@@ -2,20 +2,31 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+enum MEMORY_REGION_FLAGS : uint32_t
+{
+ // PF_X = 0x01, // Execute
+ // PF_W = 0x02, // Write
+ // PF_R = 0x04, // Read
+ MEMORY_REGION_FLAG_PERMISSIONS_MASK = 0x0f,
+ MEMORY_REGION_FLAG_SHARED = 0x10,
+ MEMORY_REGION_FLAG_PRIVATE = 0x20,
+ MEMORY_REGION_FLAG_MEMORY_BACKED = 0x40
+};
+
struct MemoryRegion
{
private:
- uint32_t m_permissions;
+ uint32_t m_flags;
uint64_t m_startAddress;
uint64_t m_endAddress;
uint64_t m_offset;
// The name used for NT_FILE output
- char* m_fileName;
+ const char* m_fileName;
public:
- MemoryRegion(uint64_t start, uint64_t end) :
- m_permissions(PF_R | PF_W | PF_X),
+ MemoryRegion(uint32_t flags, uint64_t start, uint64_t end) :
+ m_flags(flags),
m_startAddress(start),
m_endAddress(end),
m_offset(0),
@@ -25,8 +36,8 @@ public:
assert((end & ~PAGE_MASK) == 0);
}
- MemoryRegion(uint32_t permissions, uint64_t start, uint64_t end, uint64_t offset, char* filename) :
- m_permissions(permissions),
+ MemoryRegion(uint32_t flags, uint64_t start, uint64_t end, uint64_t offset, const char* filename) :
+ m_flags(flags),
m_startAddress(start),
m_endAddress(end),
m_offset(offset),
@@ -36,7 +47,39 @@ public:
assert((end & ~PAGE_MASK) == 0);
}
- const uint32_t Permissions() const { return m_permissions; }
+ // copy with new file name constructor
+ MemoryRegion(const MemoryRegion& region, const char* fileName) :
+ m_flags(region.m_flags),
+ m_startAddress(region.m_startAddress),
+ m_endAddress(region.m_endAddress),
+ m_offset(region.m_offset),
+ m_fileName(fileName)
+ {
+ }
+
+ // copy with new flags constructor. The file name is not copied.
+ MemoryRegion(const MemoryRegion& region, uint32_t flags) :
+ m_flags(flags),
+ m_startAddress(region.m_startAddress),
+ m_endAddress(region.m_endAddress),
+ m_offset(region.m_offset),
+ m_fileName(nullptr)
+ {
+ }
+
+ // copy constructor
+ MemoryRegion(const MemoryRegion& region) :
+ m_flags(region.m_flags),
+ m_startAddress(region.m_startAddress),
+ m_endAddress(region.m_endAddress),
+ m_offset(region.m_offset),
+ m_fileName(region.m_fileName)
+ {
+ }
+
+ const uint32_t Permissions() const { return m_flags & MEMORY_REGION_FLAG_PERMISSIONS_MASK; }
+ const uint32_t Flags() const { return m_flags; }
+ const bool IsBackedByMemory() const { return (m_flags & MEMORY_REGION_FLAG_MEMORY_BACKED) != 0; }
const uint64_t StartAddress() const { return m_startAddress; }
const uint64_t EndAddress() const { return m_endAddress; }
const uint64_t Size() const { return m_endAddress - m_startAddress; }
@@ -48,27 +91,25 @@ public:
return (m_startAddress < rhs.m_startAddress) && (m_endAddress <= rhs.m_startAddress);
}
+ // Returns true if "rhs" is wholly contained in this one
bool Contains(const MemoryRegion& rhs) const
{
return (m_startAddress <= rhs.m_startAddress) && (m_endAddress >= rhs.m_endAddress);
}
+ // Free the file name memory
void Cleanup()
{
if (m_fileName != nullptr)
{
- free(m_fileName);
+ free((void*)m_fileName);
m_fileName = nullptr;
}
}
- void Print() const
+ void Trace() const
{
- if (m_fileName != nullptr) {
- TRACE("%016lx - %016lx (%06ld) %016lx %x %s\n", m_startAddress, m_endAddress, (Size() >> PAGE_SHIFT), m_offset, m_permissions, m_fileName);
- }
- else {
- TRACE("%016lx - %016lx (%06ld) %x\n", m_startAddress, m_endAddress, (Size() >> PAGE_SHIFT), m_permissions);
- }
+ TRACE("%s%016lx - %016lx (%06ld) %016lx %02x %s\n", IsBackedByMemory() ? "*" : " ", m_startAddress, m_endAddress,
+ (Size() >> PAGE_SHIFT), m_offset, m_flags, m_fileName != nullptr ? m_fileName : "");
}
};
diff --git a/src/debug/createdump/threadinfo.cpp b/src/debug/createdump/threadinfo.cpp
index e2c10fc4b7..35a4f0d4cd 100644
--- a/src/debug/createdump/threadinfo.cpp
+++ b/src/debug/createdump/threadinfo.cpp
@@ -145,21 +145,19 @@ ThreadInfo::GetThreadStack(const CrashInfo& crashInfo, uint64_t* startAddress, s
*startAddress = m_gpRegisters.rsp & PAGE_MASK;
*size = 4 * PAGE_SIZE;
- for (const MemoryRegion& mapping : crashInfo.OtherMappings())
- {
- if (*startAddress >= mapping.StartAddress() && *startAddress < mapping.EndAddress())
+ const MemoryRegion* region = CrashInfo::SearchMemoryRegions(crashInfo.OtherMappings(), *startAddress);
+ if (region != nullptr) {
+
+ // Use the mapping found for the size of the thread's stack
+ *size = region->EndAddress() - *startAddress;
+
+ if (g_diagnostics)
{
- // Use the mapping found for the size of the thread's stack
- *size = mapping.EndAddress() - *startAddress;
-
- if (g_diagnostics)
- {
- TRACE("Thread %04x stack found in other mapping (size %08lx): ", m_tid, *size);
- mapping.Print();
- }
- break;
+ TRACE("Thread %04x stack found in other mapping (size %08lx): ", m_tid, *size);
+ region->Trace();
}
}
+
}
void
diff --git a/src/jit/lower.cpp b/src/jit/lower.cpp
index 72dba4ee7e..9cab5eecf2 100644
--- a/src/jit/lower.cpp
+++ b/src/jit/lower.cpp
@@ -1723,14 +1723,14 @@ void Lowering::LowerFastTailCall(GenTreeCall* call)
{
tmpLclNum = comp->lvaGrabTemp(
true DEBUGARG("Fast tail call lowering is creating a new local variable"));
- comp->lvaSortAgain = true;
- tmpType = genActualType(callerArgDsc->lvaArgType());
- comp->lvaTable[tmpLclNum].lvType = tmpType;
- comp->lvaTable[tmpLclNum].lvRefCnt = 1;
+ comp->lvaSortAgain = true;
+ tmpType = genActualType(callerArgDsc->lvaArgType());
+ comp->lvaTable[tmpLclNum].lvType = tmpType;
+ comp->lvaTable[tmpLclNum].lvRefCnt = 1;
+ comp->lvaTable[tmpLclNum].lvDoNotEnregister = comp->lvaTable[lcl->gtLclNum].lvDoNotEnregister;
}
lcl->SetLclNum(tmpLclNum);
- lcl->SetOper(GT_LCL_VAR);
}
}
}
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp
index 6928c3c393..9404469c7f 100644
--- a/src/jit/morph.cpp
+++ b/src/jit/morph.cpp
@@ -7529,6 +7529,39 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa
fgInsertStmtBefore(block, paramAssignmentInsertionPoint, arg0AssignmentStmt);
}
+ // If compInitMem is set, we may need to zero-initialize some locals. Normally it's done in the prolog
+ // but this loop can't include the prolog. Since we don't have liveness information, we insert zero-initialization
+ // for all non-parameter non-temp locals. Liveness phase will remove unnecessary initializations.
+ if (info.compInitMem)
+ {
+ unsigned varNum;
+ LclVarDsc* varDsc;
+ for (varNum = 0, varDsc = lvaTable; varNum < info.compLocalsCount; varNum++, varDsc++)
+ {
+ if (!varDsc->lvIsParam)
+ {
+ assert(!varDsc->lvIsTemp);
+ var_types lclType = varDsc->TypeGet();
+ GenTreePtr lcl = gtNewLclvNode(varNum, lclType);
+ GenTreePtr init = nullptr;
+ if (lclType == TYP_STRUCT)
+ {
+ const bool isVolatile = false;
+ const bool isCopyBlock = false;
+ init = gtNewBlkOpNode(lcl, gtNewIconNode(0), varDsc->lvSize(), isVolatile, isCopyBlock);
+ init = fgMorphInitBlock(init);
+ }
+ else
+ {
+ GenTreePtr zero = gtNewZeroConNode(genActualType(lclType));
+ init = gtNewAssignNode(lcl, zero);
+ }
+ GenTreePtr initStmt = gtNewStmt(init, callILOffset);
+ fgInsertStmtBefore(block, last, initStmt);
+ }
+ }
+ }
+
// Remove the call
fgRemoveStmt(block, last);
@@ -10514,6 +10547,43 @@ GenTree* Compiler::fgMorphForRegisterFP(GenTree* tree)
return tree;
}
+//--------------------------------------------------------------------------------------------------------------
+// fgMorphRecognizeBoxNullable:
+// Recognize this pattern:
+//
+// stmtExpr void (IL 0x000... ???)
+// return int
+// CNS_INT ref null
+// EQ/NE/GT int
+// CALL help ref HELPER.CORINFO_HELP_BOX_NULLABLE
+// CNS_INT(h) long 0x7fed96836c8 class
+// ADDR byref
+// FIELD struct value
+// LCL_VAR ref V00 this
+//
+// which comes from this code:
+//
+// return this.value==null;
+//
+// and transform it into
+//
+// stmtExpr void (IL 0x000... ???)
+// return int
+// CNS_INT ref null
+// EQ/NE/GT int
+// IND bool
+// ADDR byref
+// FIELD struct value
+// LCL_VAR ref V00 this
+//
+// Arguments:
+// compare - Compare tree to optimize.
+//
+// return value:
+// A tree that has a call to CORINFO_HELP_BOX_NULLABLE optimized away if the pattern is found;
+// the original tree otherwise.
+//
+
GenTree* Compiler::fgMorphRecognizeBoxNullable(GenTree* compare)
{
GenTree* op1 = compare->gtOp.gtOp1;
@@ -10521,26 +10591,6 @@ GenTree* Compiler::fgMorphRecognizeBoxNullable(GenTree* compare)
GenTree* opCns;
GenTreeCall* opCall;
- // recognize this pattern:
- //
- // stmtExpr void (IL 0x000... ???)
- // return int
- // const ref null
- // == int
- // call help ref HELPER.CORINFO_HELP_BOX_NULLABLE
- // const(h) long 0x7fed96836c8 class
- // addr byref
- // ld.lclVar struct V00 arg0
- //
- //
- // which comes from this code (reported by customer as being slow) :
- //
- // private static bool IsNull<T>(T arg)
- // {
- // return arg==null;
- // }
- //
-
if (op1->IsCnsIntOrI() && op2->IsHelperCall())
{
opCns = op1;
@@ -10566,8 +10616,17 @@ GenTree* Compiler::fgMorphRecognizeBoxNullable(GenTree* compare)
return compare;
}
- // replace the box with an access of the nullable 'hasValue' field which is at the zero offset
- GenTree* newOp = gtNewOperNode(GT_IND, TYP_BOOL, opCall->gtCall.gtCallArgs->gtOp.gtOp2->gtOp.gtOp1);
+ // Get the nullable struct argument
+ GenTree* arg = opCall->gtCall.gtCallArgs->gtOp.gtOp2->gtOp.gtOp1;
+
+ // Check for cases that are unsafe to optimize and return the unchanged tree
+ if (arg->IsArgPlaceHolderNode() || arg->IsNothingNode() || ((arg->gtFlags & GTF_LATE_ARG) != 0))
+ {
+ return compare;
+ }
+
+ // Replace the box with an access of the nullable 'hasValue' field which is at the zero offset
+ GenTree* newOp = gtNewOperNode(GT_IND, TYP_BOOL, arg);
if (opCall == op1)
{
@@ -11426,7 +11485,17 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac)
}
}
}
- fgMorphRecognizeBoxNullable(tree);
+
+ __fallthrough;
+
+ case GT_GT:
+
+ // Try to optimize away calls to CORINFO_HELP_BOX_NULLABLE for GT_EQ, GT_NE, and unsigned GT_GT.
+ if ((oper != GT_GT) || tree->IsUnsigned())
+ {
+ fgMorphRecognizeBoxNullable(tree);
+ }
+
op1 = tree->gtOp.gtOp1;
op2 = tree->gtGetOp2IfPresent();
diff --git a/src/mscorlib/System.Private.CoreLib.csproj b/src/mscorlib/System.Private.CoreLib.csproj
index 513e002497..18256086d7 100644
--- a/src/mscorlib/System.Private.CoreLib.csproj
+++ b/src/mscorlib/System.Private.CoreLib.csproj
@@ -619,7 +619,6 @@
<Compile Include="$(BclSourcesRoot)\System\Resources\__HResults.cs" />
<Compile Include="$(BclSourcesRoot)\System\Resources\FileBasedResourceGroveler.cs" />
<Compile Include="$(BclSourcesRoot)\System\Resources\IResourceGroveler.cs" />
- <Compile Include="$(BclSourcesRoot)\System\Resources\LooselyLinkedResourceReference.cs" />
<Compile Include="$(BclSourcesRoot)\System\Resources\ManifestBasedResourceGroveler.cs" />
<Compile Include="$(BclSourcesRoot)\System\Resources\ResourceManager.cs" />
<Compile Include="$(BclSourcesRoot)\System\Resources\ResourceReader.cs" />
diff --git a/src/mscorlib/shared/System/Char.cs b/src/mscorlib/shared/System/Char.cs
index 3fad7a4827..72441763e9 100644
--- a/src/mscorlib/shared/System/Char.cs
+++ b/src/mscorlib/shared/System/Char.cs
@@ -21,6 +21,7 @@ namespace System
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct Char : IComparable, IComparable<Char>, IEquatable<Char>, IConvertible
{
//
diff --git a/src/mscorlib/shared/System/Collections/DictionaryEntry.cs b/src/mscorlib/shared/System/Collections/DictionaryEntry.cs
index 290306d006..3c1c0befa3 100644
--- a/src/mscorlib/shared/System/Collections/DictionaryEntry.cs
+++ b/src/mscorlib/shared/System/Collections/DictionaryEntry.cs
@@ -9,10 +9,11 @@ namespace System.Collections
// A DictionaryEntry holds a key and a value from a dictionary.
// It is returned by IDictionaryEnumerator::GetEntry().
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct DictionaryEntry
{
- private Object _key;
- private Object _value;
+ private Object _key; // Do not rename (binary serialization)
+ private Object _value; // Do not rename (binary serialization)
// Constructs a new DictionaryEnumerator by setting the Key
// and Value fields appropriately.
diff --git a/src/mscorlib/shared/System/Collections/Generic/KeyValuePair.cs b/src/mscorlib/shared/System/Collections/Generic/KeyValuePair.cs
index fc51af25f8..aeafecd958 100644
--- a/src/mscorlib/shared/System/Collections/Generic/KeyValuePair.cs
+++ b/src/mscorlib/shared/System/Collections/Generic/KeyValuePair.cs
@@ -46,10 +46,11 @@ namespace System.Collections.Generic
// It is used by the IEnumerable<T> implementation for both IDictionary<TKey, TValue>
// and IReadOnlyDictionary<TKey, TValue>.
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct KeyValuePair<TKey, TValue>
{
- private TKey key; // DO NOT change the field name, it's required for compatibility with desktop .NET as it appears in serialization payload.
- private TValue value; // DO NOT change the field name, it's required for compatibility with desktop .NET as it appears in serialization payload.
+ private TKey key; // Do not rename (binary serialization)
+ private TValue value; // Do not rename (binary serialization)
public KeyValuePair(TKey key, TValue value)
{
diff --git a/src/mscorlib/shared/System/DateTime.cs b/src/mscorlib/shared/System/DateTime.cs
index ddb72da77d..4fd9727fcd 100644
--- a/src/mscorlib/shared/System/DateTime.cs
+++ b/src/mscorlib/shared/System/DateTime.cs
@@ -54,6 +54,7 @@ namespace System
//
[StructLayout(LayoutKind.Auto)]
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public partial struct DateTime : IComparable, IFormattable, IConvertible, IComparable<DateTime>, IEquatable<DateTime>, ISerializable
{
// Number of 100ns ticks per time unit
@@ -125,8 +126,8 @@ namespace System
private const UInt64 KindLocalAmbiguousDst = 0xC000000000000000;
private const Int32 KindShift = 62;
- private const String TicksField = "ticks";
- private const String DateDataField = "_dateData";
+ private const String TicksField = "ticks"; // Do not rename (binary serialization)
+ private const String DateDataField = "dateData"; // Do not rename (binary serialization)
// The data is stored as an unsigned 64-bit integeter
// Bits 01-62: The value of 100-nanosecond ticks where 0 represents 1/1/0001 12:00am, up until the value
diff --git a/src/mscorlib/shared/System/DateTimeOffset.cs b/src/mscorlib/shared/System/DateTimeOffset.cs
index d5ccbd9195..ab35bdb0fe 100644
--- a/src/mscorlib/shared/System/DateTimeOffset.cs
+++ b/src/mscorlib/shared/System/DateTimeOffset.cs
@@ -30,6 +30,7 @@ namespace System
[StructLayout(LayoutKind.Auto)]
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct DateTimeOffset : IComparable, IFormattable, IComparable<DateTimeOffset>, IEquatable<DateTimeOffset>, ISerializable, IDeserializationCallback
{
// Constants
@@ -573,8 +574,8 @@ namespace System
throw new ArgumentNullException(nameof(info));
}
- info.AddValue("DateTime", _dateTime);
- info.AddValue("OffsetMinutes", _offsetMinutes);
+ info.AddValue("DateTime", _dateTime); // Do not rename (binary serialization)
+ info.AddValue("OffsetMinutes", _offsetMinutes); // Do not rename (binary serialization)
}
@@ -585,8 +586,8 @@ namespace System
throw new ArgumentNullException(nameof(info));
}
- _dateTime = (DateTime)info.GetValue("DateTime", typeof(DateTime));
- _offsetMinutes = (Int16)info.GetValue("OffsetMinutes", typeof(Int16));
+ _dateTime = (DateTime)info.GetValue("DateTime", typeof(DateTime)); // Do not rename (binary serialization)
+ _offsetMinutes = (Int16)info.GetValue("OffsetMinutes", typeof(Int16)); // Do not rename (binary serialization)
}
// Returns the hash code for this DateTimeOffset.
diff --git a/src/mscorlib/shared/System/Globalization/SortVersion.cs b/src/mscorlib/shared/System/Globalization/SortVersion.cs
index 94c04d7063..46e9a833ec 100644
--- a/src/mscorlib/shared/System/Globalization/SortVersion.cs
+++ b/src/mscorlib/shared/System/Globalization/SortVersion.cs
@@ -5,6 +5,7 @@
namespace System.Globalization
{
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public sealed class SortVersion : IEquatable<SortVersion>
{
private int m_NlsVersion; // Do not rename (binary serialization)
diff --git a/src/mscorlib/shared/System/Reflection/Assembly.cs b/src/mscorlib/shared/System/Reflection/Assembly.cs
index b965c9f7fb..d35ffc7066 100644
--- a/src/mscorlib/shared/System/Reflection/Assembly.cs
+++ b/src/mscorlib/shared/System/Reflection/Assembly.cs
@@ -125,10 +125,7 @@ namespace System.Reflection
public virtual FileStream[] GetFiles() => GetFiles(getResourceModules: false);
public virtual FileStream[] GetFiles(bool getResourceModules) { throw NotImplemented.ByDesign; }
- public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- throw new PlatformNotSupportedException();
- }
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { throw NotImplemented.ByDesign; }
public override string ToString()
{
diff --git a/src/mscorlib/shared/System/Reflection/Module.cs b/src/mscorlib/shared/System/Reflection/Module.cs
index 7822e9ff10..56f83c40d9 100644
--- a/src/mscorlib/shared/System/Reflection/Module.cs
+++ b/src/mscorlib/shared/System/Reflection/Module.cs
@@ -110,10 +110,7 @@ namespace System.Reflection
public Type ResolveType(int metadataToken) => ResolveType(metadataToken, null, null);
public virtual Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { throw NotImplemented.ByDesign; }
- public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- throw new PlatformNotSupportedException();
- }
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { throw NotImplemented.ByDesign; }
public override bool Equals(object o) => base.Equals(o);
public override int GetHashCode() => base.GetHashCode();
diff --git a/src/mscorlib/shared/System/Reflection/ParameterInfo.cs b/src/mscorlib/shared/System/Reflection/ParameterInfo.cs
index fd130e569b..94bfffaa53 100644
--- a/src/mscorlib/shared/System/Reflection/ParameterInfo.cs
+++ b/src/mscorlib/shared/System/Reflection/ParameterInfo.cs
@@ -54,7 +54,46 @@ namespace System.Reflection
public object GetRealObject(StreamingContext context)
{
- throw new PlatformNotSupportedException();
+ // Once all the serializable fields have come in we can set up the real
+ // instance based on just two of them (MemberImpl and PositionImpl).
+
+ if (MemberImpl == null)
+ throw new SerializationException(SR.Serialization_InsufficientState);
+
+ ParameterInfo[] args = null;
+
+ switch (MemberImpl.MemberType)
+ {
+ case MemberTypes.Constructor:
+ case MemberTypes.Method:
+ if (PositionImpl == -1)
+ {
+ if (MemberImpl.MemberType == MemberTypes.Method)
+ return ((MethodInfo)MemberImpl).ReturnParameter;
+ else
+ throw new SerializationException(SR.Serialization_BadParameterInfo);
+ }
+ else
+ {
+ args = ((MethodBase)MemberImpl).GetParametersNoCopy();
+
+ if (args != null && PositionImpl < args.Length)
+ return args[PositionImpl];
+ else
+ throw new SerializationException(SR.Serialization_BadParameterInfo);
+ }
+
+ case MemberTypes.Property:
+ args = ((PropertyInfo)MemberImpl).GetIndexParameters();
+
+ if (args != null && PositionImpl > -1 && PositionImpl < args.Length)
+ return args[PositionImpl];
+ else
+ throw new SerializationException(SR.Serialization_BadParameterInfo);
+
+ default:
+ throw new SerializationException(SR.Serialization_NoParameterInfo);
+ }
}
public override string ToString() => ParameterType.FormatTypeName() + " " + Name;
diff --git a/src/mscorlib/shared/System/StringComparer.cs b/src/mscorlib/shared/System/StringComparer.cs
index b327e770d5..6990378812 100644
--- a/src/mscorlib/shared/System/StringComparer.cs
+++ b/src/mscorlib/shared/System/StringComparer.cs
@@ -6,15 +6,17 @@ using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Diagnostics.Contracts;
+using System.Runtime.Serialization;
namespace System
{
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract class StringComparer : IComparer, IEqualityComparer, IComparer<string>, IEqualityComparer<string>
{
private static readonly CultureAwareComparer s_invariantCulture = new CultureAwareComparer(CultureInfo.InvariantCulture, false);
private static readonly CultureAwareComparer s_invariantCultureIgnoreCase = new CultureAwareComparer(CultureInfo.InvariantCulture, true);
- private static readonly OrdinalComparer s_ordinal = new OrdinalComparer();
+ private static readonly OrdinalCaseSensitiveComparer s_ordinal = new OrdinalCaseSensitiveComparer();
private static readonly OrdinalIgnoreCaseComparer s_ordinalIgnoreCase = new OrdinalIgnoreCaseComparer();
public static StringComparer InvariantCulture
@@ -170,30 +172,33 @@ namespace System
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class CultureAwareComparer : StringComparer
{
- private readonly CompareInfo _compareInfo;
- private readonly CompareOptions _options;
+ private readonly CompareInfo _compareInfo; // Do not rename (binary serialization)
+ private readonly bool _ignoreCase; // Do not rename (binary serialization)
internal CultureAwareComparer(CultureInfo culture, bool ignoreCase)
{
_compareInfo = culture.CompareInfo;
- _options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+ _ignoreCase = ignoreCase;
}
+ private CompareOptions Options => _ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+
public override int Compare(string x, string y)
{
if (object.ReferenceEquals(x, y)) return 0;
if (x == null) return -1;
if (y == null) return 1;
- return _compareInfo.Compare(x, y, _options);
+ return _compareInfo.Compare(x, y, Options);
}
public override bool Equals(string x, string y)
{
if (object.ReferenceEquals(x, y)) return true;
if (x == null || y == null) return false;
- return _compareInfo.Compare(x, y, _options) == 0;
+ return _compareInfo.Compare(x, y, Options) == 0;
}
public override int GetHashCode(string obj)
@@ -202,7 +207,7 @@ namespace System
{
throw new ArgumentNullException(nameof(obj));
}
- return _compareInfo.GetHashCodeOfString(obj, _options);
+ return _compareInfo.GetHashCodeOfString(obj, Options);
}
// Equals method for the comparer itself.
@@ -211,20 +216,108 @@ namespace System
CultureAwareComparer comparer = obj as CultureAwareComparer;
return
comparer != null &&
- _options == comparer._options &&
+ _ignoreCase == comparer._ignoreCase &&
_compareInfo.Equals(comparer._compareInfo);
}
public override int GetHashCode()
{
int hashCode = _compareInfo.GetHashCode();
- return _options == CompareOptions.None ? hashCode : ~hashCode;
+ return _ignoreCase ? ~hashCode : hashCode;
+ }
+ }
+
+ [Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ internal class OrdinalComparer : StringComparer
+ {
+ private readonly bool _ignoreCase; // Do not rename (binary serialization)
+
+ internal OrdinalComparer(bool ignoreCase)
+ {
+ _ignoreCase = ignoreCase;
+ }
+
+ public override int Compare(string x, string y)
+ {
+ if (ReferenceEquals(x, y))
+ return 0;
+ if (x == null)
+ return -1;
+ if (y == null)
+ return 1;
+
+ if (_ignoreCase)
+ {
+ return string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
+ }
+
+ return string.CompareOrdinal(x, y);
+ }
+
+ public override bool Equals(string x, string y)
+ {
+ if (ReferenceEquals(x, y))
+ return true;
+ if (x == null || y == null)
+ return false;
+
+ if (_ignoreCase)
+ {
+ if (x.Length != y.Length)
+ {
+ return false;
+ }
+ return (string.Compare(x, y, StringComparison.OrdinalIgnoreCase) == 0);
+ }
+ return x.Equals(y);
+ }
+
+ public override int GetHashCode(string obj)
+ {
+ if (obj == null)
+ {
+#if CORECLR
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj);
+#else
+ throw new ArgumentNullException(nameof(obj));
+#endif
+ }
+ Contract.EndContractBlock();
+
+ if (_ignoreCase)
+ {
+ return TextInfo.GetHashCodeOrdinalIgnoreCase(obj);
+ }
+
+ return obj.GetHashCode();
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(object obj)
+ {
+ OrdinalComparer comparer = obj as OrdinalComparer;
+ if (comparer == null)
+ {
+ return false;
+ }
+ return (this._ignoreCase == comparer._ignoreCase);
+ }
+
+ public override int GetHashCode()
+ {
+ int hashCode = nameof(OrdinalComparer).GetHashCode();
+ return _ignoreCase ? (~hashCode) : hashCode;
}
}
[Serializable]
- internal sealed class OrdinalComparer : StringComparer
+ internal sealed class OrdinalCaseSensitiveComparer : OrdinalComparer, ISerializable
{
+ public OrdinalCaseSensitiveComparer() : base(false)
+ {
+ }
+
public override int Compare(string x, string y) => string.CompareOrdinal(x, y);
public override bool Equals(string x, string y) => string.Equals(x, y);
@@ -242,14 +335,20 @@ namespace System
return obj.GetHashCode();
}
- // Equals/GetHashCode methods for the comparer itself.
- public override bool Equals(object obj) => obj is OrdinalComparer;
- public override int GetHashCode() => nameof(OrdinalComparer).GetHashCode();
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.SetType(typeof(OrdinalComparer));
+ info.AddValue("_ignoreCase", false);
+ }
}
- [Serializable]
- internal sealed class OrdinalIgnoreCaseComparer : StringComparer
+ [Serializable]
+ internal sealed class OrdinalIgnoreCaseComparer : OrdinalComparer, ISerializable
{
+ public OrdinalIgnoreCaseComparer() : base(true)
+ {
+ }
+
public override int Compare(string x, string y) => string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
public override bool Equals(string x, string y) => string.Equals(x, y, StringComparison.OrdinalIgnoreCase);
@@ -267,8 +366,10 @@ namespace System
return TextInfo.GetHashCodeOrdinalIgnoreCase(obj);
}
- // Equals/GetHashCode methods for the comparer itself.
- public override bool Equals(object obj) => obj is OrdinalIgnoreCaseComparer;
- public override int GetHashCode() => nameof(OrdinalIgnoreCaseComparer).GetHashCode();
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.SetType(typeof(OrdinalComparer));
+ info.AddValue("_ignoreCase", true);
+ }
}
}
diff --git a/src/mscorlib/shared/System/Text/StringBuilder.cs b/src/mscorlib/shared/System/Text/StringBuilder.cs
index 3a06114bff..1167016cc1 100644
--- a/src/mscorlib/shared/System/Text/StringBuilder.cs
+++ b/src/mscorlib/shared/System/Text/StringBuilder.cs
@@ -35,6 +35,7 @@ namespace System.Text
// Console.WriteLine(sb2);
//
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public sealed partial class StringBuilder : ISerializable
{
// A StringBuilder is internally represented as a linked list of blocks each of which holds
@@ -58,10 +59,11 @@ namespace System.Text
//
//
internal const int DefaultCapacity = 16;
- private const String CapacityField = "Capacity";
- private const String MaxCapacityField = "m_MaxCapacity";
- private const String StringValueField = "m_StringValue";
- private const String ThreadIDField = "m_currentThread";
+ private const String CapacityField = "Capacity"; // Do not rename (binary serialization)
+ private const String MaxCapacityField = "m_MaxCapacity"; // Do not rename (binary serialization)
+ private const String StringValueField = "m_StringValue"; // Do not rename (binary serialization)
+ private const String ThreadIDField = "m_currentThread"; // Do not rename (binary serialization)
+
// We want to keep chunk arrays out of large object heap (< 85K bytes ~ 40K chars) to be sure.
// Making the maximum chunk size big means less allocation code called, but also more waste
// in unused characters and slower inserts / replaces (since you do need to slide characters over
diff --git a/src/mscorlib/shared/System/ValueTuple.cs b/src/mscorlib/shared/System/ValueTuple.cs
index e0cd02e914..3464f2781c 100644
--- a/src/mscorlib/shared/System/ValueTuple.cs
+++ b/src/mscorlib/shared/System/ValueTuple.cs
@@ -29,6 +29,7 @@ namespace System
/// - their members (such as Item1, Item2, etc) are fields rather than properties.
/// </summary>
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple
: IEquatable<ValueTuple>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple>, IValueTupleInternal, ITuple
{
@@ -298,6 +299,7 @@ namespace System
/// <summary>Represents a 1-tuple, or singleton, as a value type.</summary>
/// <typeparam name="T1">The type of the tuple's only component.</typeparam>
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1>
: IEquatable<ValueTuple<T1>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1>>, IValueTupleInternal, ITuple
{
@@ -464,6 +466,7 @@ namespace System
/// <typeparam name="T2">The type of the tuple's second component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2>
: IEquatable<ValueTuple<T1, T2>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2>>, IValueTupleInternal, ITuple
{
@@ -674,6 +677,7 @@ namespace System
/// <typeparam name="T3">The type of the tuple's third component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3>
: IEquatable<ValueTuple<T1, T2, T3>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3>>, IValueTupleInternal, ITuple
{
@@ -882,6 +886,7 @@ namespace System
/// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4>
: IEquatable<ValueTuple<T1, T2, T3, T4>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4>>, IValueTupleInternal, ITuple
{
@@ -1109,6 +1114,7 @@ namespace System
/// <typeparam name="T5">The type of the tuple's fifth component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4, T5>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5>>, IValueTupleInternal, ITuple
{
@@ -1355,6 +1361,7 @@ namespace System
/// <typeparam name="T6">The type of the tuple's sixth component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4, T5, T6>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6>>, IValueTupleInternal, ITuple
{
@@ -1620,6 +1627,7 @@ namespace System
/// <typeparam name="T7">The type of the tuple's seventh component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4, T5, T6, T7>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6, T7>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6, T7>>, IValueTupleInternal, ITuple
{
@@ -1904,6 +1912,7 @@ namespace System
/// <typeparam name="TRest">The type of the tuple's eighth component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, IValueTupleInternal, ITuple
where TRest : struct
diff --git a/src/mscorlib/shared/System/Version.cs b/src/mscorlib/shared/System/Version.cs
index 54b2052ddb..a2140ab137 100644
--- a/src/mscorlib/shared/System/Version.cs
+++ b/src/mscorlib/shared/System/Version.cs
@@ -16,14 +16,15 @@ namespace System
// specified component.
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public sealed class Version : ICloneable, IComparable
, IComparable<Version>, IEquatable<Version>
{
// AssemblyName depends on the order staying the same
- private readonly int _Major;
- private readonly int _Minor;
- private readonly int _Build = -1;
- private readonly int _Revision = -1;
+ private readonly int _Major; // Do not rename (binary serialization)
+ private readonly int _Minor; // Do not rename (binary serialization)
+ private readonly int _Build = -1; // Do not rename (binary serialization)
+ private readonly int _Revision = -1; // Do not rename (binary serialization)
public Version(int major, int minor, int build, int revision)
{
diff --git a/src/mscorlib/src/System/AggregateException.cs b/src/mscorlib/src/System/AggregateException.cs
index 22bc323215..0b840972ef 100644
--- a/src/mscorlib/src/System/AggregateException.cs
+++ b/src/mscorlib/src/System/AggregateException.cs
@@ -30,9 +30,10 @@ namespace System
/// </remarks>
[Serializable]
[DebuggerDisplay("Count = {InnerExceptionCount}")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class AggregateException : Exception
{
- private ReadOnlyCollection<Exception> m_innerExceptions; // Complete set of exceptions.
+ private ReadOnlyCollection<Exception> m_innerExceptions; // Complete set of exceptions. Do not rename (binary serialization)
/// <summary>
/// Initializes a new instance of the <see cref="AggregateException"/> class.
diff --git a/src/mscorlib/src/System/Array.cs b/src/mscorlib/src/System/Array.cs
index fcfeb94675..62a4ecf16e 100644
--- a/src/mscorlib/src/System/Array.cs
+++ b/src/mscorlib/src/System/Array.cs
@@ -26,6 +26,7 @@ namespace System
// Note that we make a T[] (single-dimensional w/ zero as the lower bound) implement both
// IList<U> and IReadOnlyList<U>, where T : U dynamically. See the SZArrayHelper class for details.
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract class Array : ICloneable, IList, IStructuralComparable, IStructuralEquatable
{
// This ctor exists solely to prevent C# from generating a protected .ctor that violates the surface area. I really want this to be a
diff --git a/src/mscorlib/src/System/ArraySegment.cs b/src/mscorlib/src/System/ArraySegment.cs
index 664352708d..7546c5bd56 100644
--- a/src/mscorlib/src/System/ArraySegment.cs
+++ b/src/mscorlib/src/System/ArraySegment.cs
@@ -26,15 +26,16 @@ namespace System
// three fields from an ArraySegment may not see the same ArraySegment from one call to another
// (ie, users could assign a new value to the old location).
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ArraySegment<T> : IList<T>, IReadOnlyList<T>
{
// Do not replace the array allocation with Array.Empty. We don't want to have the overhead of
// instantiating another generic type in addition to ArraySegment<T> for new type parameters.
public static ArraySegment<T> Empty { get; } = new ArraySegment<T>(new T[0]);
- private readonly T[] _array;
- private readonly int _offset;
- private readonly int _count;
+ private readonly T[] _array; // Do not rename (binary serialization)
+ private readonly int _offset; // Do not rename (binary serialization)
+ private readonly int _count; // Do not rename (binary serialization)
public ArraySegment(T[] array)
{
diff --git a/src/mscorlib/src/System/Attribute.cs b/src/mscorlib/src/System/Attribute.cs
index baa9a71638..23fd9aaaaf 100644
--- a/src/mscorlib/src/System/Attribute.cs
+++ b/src/mscorlib/src/System/Attribute.cs
@@ -17,6 +17,7 @@ namespace System
{
[Serializable]
[AttributeUsageAttribute(AttributeTargets.All, Inherited = true, AllowMultiple = false)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract class Attribute
{
#region Private Statics
diff --git a/src/mscorlib/src/System/Boolean.cs b/src/mscorlib/src/System/Boolean.cs
index 59cab74456..a1f5064964 100644
--- a/src/mscorlib/src/System/Boolean.cs
+++ b/src/mscorlib/src/System/Boolean.cs
@@ -21,6 +21,7 @@ namespace System
// The Boolean class provides the
// object representation of the boolean primitive type.
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct Boolean : IComparable, IConvertible, IComparable<Boolean>, IEquatable<Boolean>
{
//
diff --git a/src/mscorlib/src/System/Byte.cs b/src/mscorlib/src/System/Byte.cs
index da3b790ac6..fafdcbb535 100644
--- a/src/mscorlib/src/System/Byte.cs
+++ b/src/mscorlib/src/System/Byte.cs
@@ -25,6 +25,7 @@ namespace System
//
[Serializable]
[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct Byte : IComparable, IFormattable, IConvertible
, IComparable<Byte>, IEquatable<Byte>
{
diff --git a/src/mscorlib/src/System/Collections/Comparer.cs b/src/mscorlib/src/System/Collections/Comparer.cs
index 76e19e77f1..00259e6bdb 100644
--- a/src/mscorlib/src/System/Collections/Comparer.cs
+++ b/src/mscorlib/src/System/Collections/Comparer.cs
@@ -13,21 +13,17 @@
**
===========================================================*/
-using System;
using System.Globalization;
-using System.Runtime.Serialization;
using System.Diagnostics.Contracts;
namespace System.Collections
{
- internal sealed class Comparer : IComparer, ISerializable
+ internal sealed class Comparer : IComparer
{
private CompareInfo m_compareInfo;
public static readonly Comparer Default = new Comparer(CultureInfo.CurrentCulture);
public static readonly Comparer DefaultInvariant = new Comparer(CultureInfo.InvariantCulture);
- private const String CompareInfoName = "CompareInfo";
-
private Comparer()
{
m_compareInfo = null;
@@ -73,10 +69,5 @@ namespace System.Collections
throw new ArgumentException(SR.Argument_ImplementIComparable);
}
-
- public void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- throw new PlatformNotSupportedException();
- }
}
}
diff --git a/src/mscorlib/src/System/Collections/Generic/Comparer.cs b/src/mscorlib/src/System/Collections/Generic/Comparer.cs
index e163faa80f..47c241500d 100644
--- a/src/mscorlib/src/System/Collections/Generic/Comparer.cs
+++ b/src/mscorlib/src/System/Collections/Generic/Comparer.cs
@@ -18,6 +18,7 @@ namespace System.Collections.Generic
{
[Serializable]
[TypeDependencyAttribute("System.Collections.Generic.ObjectComparer`1")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract class Comparer<T> : IComparer, IComparer<T>
{
// To minimize generic instantiation overhead of creating the comparer per type, we keep the generic portion of the code as small
@@ -52,6 +53,7 @@ namespace System.Collections.Generic
// means another generic instantiation, which can be costly esp.
// for value types.
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class GenericComparer<T> : Comparer<T> where T : IComparable<T>
{
public override int Compare(T x, T y)
@@ -74,6 +76,7 @@ namespace System.Collections.Generic
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class NullableComparer<T> : Comparer<T?> where T : struct, IComparable<T>
{
public override int Compare(T? x, T? y)
@@ -96,6 +99,7 @@ namespace System.Collections.Generic
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class ObjectComparer<T> : Comparer<T>
{
public override int Compare(T x, T y)
@@ -132,6 +136,7 @@ namespace System.Collections.Generic
// since we want to serialize as ObjectComparer for
// back-compat reasons (see below).
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class Int32EnumComparer<T> : Comparer<T>, ISerializable where T : struct
{
public Int32EnumComparer()
@@ -167,6 +172,7 @@ namespace System.Collections.Generic
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class UInt32EnumComparer<T> : Comparer<T>, ISerializable where T : struct
{
public UInt32EnumComparer()
@@ -198,6 +204,7 @@ namespace System.Collections.Generic
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class Int64EnumComparer<T> : Comparer<T>, ISerializable where T : struct
{
public Int64EnumComparer()
@@ -226,6 +233,7 @@ namespace System.Collections.Generic
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class UInt64EnumComparer<T> : Comparer<T>, ISerializable where T : struct
{
public UInt64EnumComparer()
diff --git a/src/mscorlib/src/System/Collections/Generic/Dictionary.cs b/src/mscorlib/src/System/Collections/Generic/Dictionary.cs
index cd33428ca1..50724017dd 100644
--- a/src/mscorlib/src/System/Collections/Generic/Dictionary.cs
+++ b/src/mscorlib/src/System/Collections/Generic/Dictionary.cs
@@ -52,6 +52,7 @@ namespace System.Collections.Generic
[DebuggerTypeProxy(typeof(Mscorlib_DictionaryDebugView<,>))]
[DebuggerDisplay("Count = {Count}")]
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue>, ISerializable, IDeserializationCallback
{
private struct Entry
@@ -74,10 +75,10 @@ namespace System.Collections.Generic
private Object _syncRoot;
// constants for serialization
- private const String VersionName = "Version";
- private const String HashSizeName = "HashSize"; // Must save buckets.Length
- private const String KeyValuePairsName = "KeyValuePairs";
- private const String ComparerName = "Comparer";
+ private const String VersionName = "Version"; // Do not rename (binary serialization)
+ private const String HashSizeName = "HashSize"; // Do not rename (binary serialization). Must save buckets.Length
+ private const String KeyValuePairsName = "KeyValuePairs"; // Do not rename (binary serialization)
+ private const String ComparerName = "Comparer"; // Do not rename (binary serialization)
public Dictionary() : this(0, null) { }
diff --git a/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs b/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs
index d6b213c9d7..760c9d10b2 100644
--- a/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs
+++ b/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs
@@ -17,6 +17,7 @@ namespace System.Collections.Generic
{
[Serializable]
[TypeDependencyAttribute("System.Collections.Generic.ObjectEqualityComparer`1")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract class EqualityComparer<T> : IEqualityComparer, IEqualityComparer<T>
{
// To minimize generic instantiation overhead of creating the comparer per type, we keep the generic portion of the code as small
@@ -69,6 +70,7 @@ namespace System.Collections.Generic
// The methods in this class look identical to the inherited methods, but the calls
// to Equal bind to IEquatable<T>.Equals(T) instead of Object.Equals(Object)
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal class GenericEqualityComparer<T> : EqualityComparer<T> where T : IEquatable<T>
{
[Pure]
@@ -137,6 +139,7 @@ namespace System.Collections.Generic
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class NullableEqualityComparer<T> : EqualityComparer<T?> where T : struct, IEquatable<T>
{
[Pure]
@@ -203,6 +206,7 @@ namespace System.Collections.Generic
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class ObjectEqualityComparer<T> : EqualityComparer<T>
{
[Pure]
@@ -275,6 +279,7 @@ namespace System.Collections.Generic
// keep the perofrmance not affected till we hit collision threshold and then we switch to the comparer which is using
// randomized string hashing GenericEqualityComparer<string>
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal class NonRandomizedStringEqualityComparer : GenericEqualityComparer<string>
{
private static IEqualityComparer<string> s_nonRandomizedComparer;
@@ -302,6 +307,7 @@ namespace System.Collections.Generic
// Performance of IndexOf on byte array is very important for some scenarios.
// We will call the C runtime function memchr, which is optimized.
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class ByteEqualityComparer : EqualityComparer<byte>
{
[Pure]
@@ -353,6 +359,7 @@ namespace System.Collections.Generic
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal class EnumEqualityComparer<T> : EqualityComparer<T>, ISerializable where T : struct
{
[Pure]
@@ -416,6 +423,7 @@ namespace System.Collections.Generic
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class SByteEnumEqualityComparer<T> : EnumEqualityComparer<T> where T : struct
{
public SByteEnumEqualityComparer() { }
@@ -432,6 +440,7 @@ namespace System.Collections.Generic
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class ShortEnumEqualityComparer<T> : EnumEqualityComparer<T>, ISerializable where T : struct
{
public ShortEnumEqualityComparer() { }
@@ -448,6 +457,7 @@ namespace System.Collections.Generic
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class LongEnumEqualityComparer<T> : EqualityComparer<T>, ISerializable where T : struct
{
[Pure]
diff --git a/src/mscorlib/src/System/Collections/Generic/List.cs b/src/mscorlib/src/System/Collections/Generic/List.cs
index 94e794cfd2..2031ddc6ed 100644
--- a/src/mscorlib/src/System/Collections/Generic/List.cs
+++ b/src/mscorlib/src/System/Collections/Generic/List.cs
@@ -30,14 +30,15 @@ namespace System.Collections.Generic
[DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
[DebuggerDisplay("Count = {Count}")]
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>
{
private const int _defaultCapacity = 4;
- private T[] _items;
+ private T[] _items; // Do not rename (binary serialization)
[ContractPublicPropertyName("Count")]
- private int _size;
- private int _version;
+ private int _size; // Do not rename (binary serialization)
+ private int _version; // Do not rename (binary serialization)
[NonSerialized]
private Object _syncRoot;
diff --git a/src/mscorlib/src/System/Collections/ListDictionaryInternal.cs b/src/mscorlib/src/System/Collections/ListDictionaryInternal.cs
index 3f92038d4f..17eb89a2b2 100644
--- a/src/mscorlib/src/System/Collections/ListDictionaryInternal.cs
+++ b/src/mscorlib/src/System/Collections/ListDictionaryInternal.cs
@@ -20,11 +20,12 @@ namespace System.Collections
/// will be smaller and faster than a Hashtable if the number of elements is 10 or less.
/// This should not be used if performance is important for large numbers of elements.
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal class ListDictionaryInternal : IDictionary
{
- private DictionaryNode head;
- private int version;
- private int count;
+ private DictionaryNode head; // Do not rename (binary serialization)
+ private int version; // Do not rename (binary serialization)
+ private int count; // Do not rename (binary serialization)
[NonSerialized]
private Object _syncRoot;
diff --git a/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs b/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs
index d9801dfaaf..8e5de70e72 100644
--- a/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs
+++ b/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs
@@ -15,9 +15,10 @@ namespace System.Collections.ObjectModel
[Serializable]
[DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
[DebuggerDisplay("Count = {Count}")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Collection<T> : IList<T>, IList, IReadOnlyList<T>
{
- private IList<T> items;
+ private IList<T> items; // Do not rename (binary serialization)
[NonSerialized]
private Object _syncRoot;
diff --git a/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs b/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs
index b484879c27..03c7d45e16 100644
--- a/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs
+++ b/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs
@@ -15,9 +15,10 @@ namespace System.Collections.ObjectModel
[Serializable]
[DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
[DebuggerDisplay("Count = {Count}")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class ReadOnlyCollection<T> : IList<T>, IList, IReadOnlyList<T>
{
- private IList<T> list;
+ private IList<T> list; // Do not rename (binary serialization)
[NonSerialized]
private Object _syncRoot;
diff --git a/src/mscorlib/src/System/Decimal.cs b/src/mscorlib/src/System/Decimal.cs
index ce59a99334..b120a368da 100644
--- a/src/mscorlib/src/System/Decimal.cs
+++ b/src/mscorlib/src/System/Decimal.cs
@@ -59,6 +59,7 @@ namespace System
[StructLayout(LayoutKind.Sequential)]
[Serializable]
[System.Runtime.Versioning.NonVersionable] // This only applies to field layout
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct Decimal : IFormattable, IComparable, IConvertible, IComparable<Decimal>, IEquatable<Decimal>, IDeserializationCallback
{
// Sign mask for the flags field. A value of zero in this bit indicates a
@@ -132,7 +133,8 @@ namespace System
// positive and 1 meaning negative.
//
// NOTE: Do not change the order in which these fields are declared. The
- // native methods in this class rely on this particular order.
+ // native methods in this class rely on this particular order.
+ // Do not rename (binary serialization).
private int flags;
private int hi;
private int lo;
diff --git a/src/mscorlib/src/System/Double.cs b/src/mscorlib/src/System/Double.cs
index 30fa1a58b3..b64bb72ed2 100644
--- a/src/mscorlib/src/System/Double.cs
+++ b/src/mscorlib/src/System/Double.cs
@@ -23,6 +23,7 @@ namespace System
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct Double : IComparable, IFormattable, IConvertible
, IComparable<Double>, IEquatable<Double>
{
diff --git a/src/mscorlib/src/System/Enum.cs b/src/mscorlib/src/System/Enum.cs
index 489f36739c..25a4ff34d3 100644
--- a/src/mscorlib/src/System/Enum.cs
+++ b/src/mscorlib/src/System/Enum.cs
@@ -15,6 +15,7 @@ using System.Diagnostics.Contracts;
namespace System
{
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
{
#region Private Constants
diff --git a/src/mscorlib/src/System/Exception.cs b/src/mscorlib/src/System/Exception.cs
index 8d01b4c461..725adac4a9 100644
--- a/src/mscorlib/src/System/Exception.cs
+++ b/src/mscorlib/src/System/Exception.cs
@@ -28,6 +28,7 @@ namespace System
using System.Diagnostics.Contracts;
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Exception : ISerializable
{
private void Init()
@@ -75,17 +76,17 @@ namespace System
throw new ArgumentNullException(nameof(info));
Contract.EndContractBlock();
- _className = info.GetString("ClassName");
- _message = info.GetString("Message");
- _data = (IDictionary)(info.GetValueNoThrow("Data", typeof(IDictionary)));
- _innerException = (Exception)(info.GetValue("InnerException", typeof(Exception)));
- _helpURL = info.GetString("HelpURL");
- _stackTraceString = info.GetString("StackTraceString");
- _remoteStackTraceString = info.GetString("RemoteStackTraceString");
- _remoteStackIndex = info.GetInt32("RemoteStackIndex");
-
- HResult = info.GetInt32("HResult");
- _source = info.GetString("Source");
+ _className = info.GetString("ClassName"); // Do not rename (binary serialization)
+ _message = info.GetString("Message"); // Do not rename (binary serialization)
+ _data = (IDictionary)(info.GetValueNoThrow("Data", typeof(IDictionary))); // Do not rename (binary serialization)
+ _innerException = (Exception)(info.GetValue("InnerException", typeof(Exception))); // Do not rename (binary serialization)
+ _helpURL = info.GetString("HelpURL"); // Do not rename (binary serialization)
+ _stackTraceString = info.GetString("StackTraceString"); // Do not rename (binary serialization)
+ _remoteStackTraceString = info.GetString("RemoteStackTraceString"); // Do not rename (binary serialization)
+ _remoteStackIndex = info.GetInt32("RemoteStackIndex"); // Do not rename (binary serialization)
+
+ HResult = info.GetInt32("HResult"); // Do not rename (binary serialization)
+ _source = info.GetString("Source"); // Do not rename (binary serialization)
// Get the WatsonBuckets that were serialized - this is particularly
// done to support exceptions going across AD transitions.
@@ -93,7 +94,7 @@ namespace System
// We use the no throw version since we could be deserializing a pre-V4
// exception object that may not have this entry. In such a case, we would
// get null.
- _watsonBuckets = (Object)info.GetValueNoThrow("WatsonBuckets", typeof(byte[]));
+ _watsonBuckets = (Object)info.GetValueNoThrow("WatsonBuckets", typeof(byte[])); // Do not rename (binary serialization)
if (_className == null || HResult == 0)
@@ -459,20 +460,20 @@ namespace System
_source = Source; // Set the Source information correctly before serialization
}
- info.AddValue("ClassName", GetClassName(), typeof(String));
- info.AddValue("Message", _message, typeof(String));
- info.AddValue("Data", _data, typeof(IDictionary));
- info.AddValue("InnerException", _innerException, typeof(Exception));
- info.AddValue("HelpURL", _helpURL, typeof(String));
- info.AddValue("StackTraceString", tempStackTraceString, typeof(String));
- info.AddValue("RemoteStackTraceString", _remoteStackTraceString, typeof(String));
- info.AddValue("RemoteStackIndex", _remoteStackIndex, typeof(Int32));
- info.AddValue("ExceptionMethod", null, typeof(String));
- info.AddValue("HResult", HResult);
- info.AddValue("Source", _source, typeof(String));
+ info.AddValue("ClassName", GetClassName(), typeof(String)); // Do not rename (binary serialization)
+ info.AddValue("Message", _message, typeof(String)); // Do not rename (binary serialization)
+ info.AddValue("Data", _data, typeof(IDictionary)); // Do not rename (binary serialization)
+ info.AddValue("InnerException", _innerException, typeof(Exception)); // Do not rename (binary serialization)
+ info.AddValue("HelpURL", _helpURL, typeof(String)); // Do not rename (binary serialization)
+ info.AddValue("StackTraceString", tempStackTraceString, typeof(String)); // Do not rename (binary serialization)
+ info.AddValue("RemoteStackTraceString", _remoteStackTraceString, typeof(String)); // Do not rename (binary serialization)
+ info.AddValue("RemoteStackIndex", _remoteStackIndex, typeof(Int32)); // Do not rename (binary serialization)
+ info.AddValue("ExceptionMethod", null, typeof(String)); // Do not rename (binary serialization)
+ info.AddValue("HResult", HResult); // Do not rename (binary serialization)
+ info.AddValue("Source", _source, typeof(String)); // Do not rename (binary serialization)
// Serialize the Watson bucket details as well
- info.AddValue("WatsonBuckets", _watsonBuckets, typeof(byte[]));
+ info.AddValue("WatsonBuckets", _watsonBuckets, typeof(byte[])); // Do not rename (binary serialization)
}
// This method will clear the _stackTrace of the exception object upon deserialization
diff --git a/src/mscorlib/src/System/Globalization/CompareInfo.Windows.cs b/src/mscorlib/src/System/Globalization/CompareInfo.Windows.cs
index eb4dc5613e..0df5463a2f 100644
--- a/src/mscorlib/src/System/Globalization/CompareInfo.Windows.cs
+++ b/src/mscorlib/src/System/Globalization/CompareInfo.Windows.cs
@@ -469,6 +469,7 @@ namespace System.Globalization
Debug.Assert(!_invariantMode);
Interop.Kernel32.NlsVersionInfoEx nlsVersion = new Interop.Kernel32.NlsVersionInfoEx();
+ nlsVersion.dwNLSVersionInfoSize = Marshal.SizeOf(typeof(Interop.Kernel32.NlsVersionInfoEx));
Interop.Kernel32.GetNLSVersionEx(Interop.Kernel32.COMPARE_STRING, _sortName, &nlsVersion);
return new SortVersion(
nlsVersion.dwNLSVersion,
diff --git a/src/mscorlib/src/System/Globalization/CompareInfo.cs b/src/mscorlib/src/System/Globalization/CompareInfo.cs
index 593e86415d..bfdbdc546b 100644
--- a/src/mscorlib/src/System/Globalization/CompareInfo.cs
+++ b/src/mscorlib/src/System/Globalization/CompareInfo.cs
@@ -34,6 +34,7 @@ namespace System.Globalization
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public partial class CompareInfo : IDeserializationCallback
{
// Mask used to check if IndexOf()/LastIndexOf()/IsPrefix()/IsPostfix() has the right flags.
@@ -69,11 +70,13 @@ namespace System.Globalization
private string _sortName; // The name that defines our behavior.
[OptionalField(VersionAdded = 3)]
- private SortVersion m_sortVersion; // Do not rename (binary serialization)
+ private SortVersion m_SortVersion; // Do not rename (binary serialization)
// _invariantMode is defined for the perf reason as accessing the instance field is faster than access the static property GlobalizationMode.Invariant
[NonSerialized]
private readonly bool _invariantMode = GlobalizationMode.Invariant;
+
+ private int culture; // Do not rename (binary serialization). The fields sole purpose is to support Desktop serialization.
internal CompareInfo(CultureInfo culture)
{
@@ -233,14 +236,26 @@ namespace System.Globalization
private void OnDeserialized()
{
- if (m_name != null)
+ // If we didn't have a name, use the LCID
+ if (m_name == null)
+ {
+ // From whidbey, didn't have a name
+ CultureInfo ci = CultureInfo.GetCultureInfo(this.culture);
+ m_name = ci._name;
+ }
+ else
{
InitSort(CultureInfo.GetCultureInfo(m_name));
}
}
[OnSerializing]
- private void OnSerializing(StreamingContext ctx) { }
+ private void OnSerializing(StreamingContext ctx)
+ {
+ // This is merely for serialization compatibility with Whidbey/Orcas, it can go away when we don't want that compat any more.
+ culture = CultureInfo.GetCultureInfo(this.Name).LCID; // This is the lcid of the constructing culture (still have to dereference to get target sort)
+ Contract.Assert(m_name != null, "CompareInfo.OnSerializing - expected m_name to be set already");
+ }
///////////////////////////----- Name -----/////////////////////////////////
//
@@ -1208,11 +1223,11 @@ namespace System.Globalization
{
get
{
- if (m_sortVersion == null)
+ if (m_SortVersion == null)
{
if (_invariantMode)
{
- m_sortVersion = new SortVersion(0, CultureInfo.LOCALE_INVARIANT, new Guid(0, 0, 0, 0, 0, 0, 0,
+ m_SortVersion = new SortVersion(0, CultureInfo.LOCALE_INVARIANT, new Guid(0, 0, 0, 0, 0, 0, 0,
(byte) (CultureInfo.LOCALE_INVARIANT >> 24),
(byte) ((CultureInfo.LOCALE_INVARIANT & 0x00FF0000) >> 16),
(byte) ((CultureInfo.LOCALE_INVARIANT & 0x0000FF00) >> 8),
@@ -1220,11 +1235,11 @@ namespace System.Globalization
}
else
{
- m_sortVersion = GetSortVersion();
+ m_SortVersion = GetSortVersion();
}
}
- return m_sortVersion;
+ return m_SortVersion;
}
}
diff --git a/src/mscorlib/src/System/Globalization/CultureInfo.cs b/src/mscorlib/src/System/Globalization/CultureInfo.cs
index 16e2d291a1..ee64bc52e2 100644
--- a/src/mscorlib/src/System/Globalization/CultureInfo.cs
+++ b/src/mscorlib/src/System/Globalization/CultureInfo.cs
@@ -206,6 +206,26 @@ namespace System.Globalization
InitializeFromName(name, useUserOverride);
}
+ private CultureInfo(CultureData cultureData)
+ {
+ Debug.Assert(cultureData != null);
+ _cultureData = cultureData;
+ _name = cultureData.CultureName;
+ _isInherited = false;
+ }
+
+ private static CultureInfo CreateCultureInfoNoThrow(string name, bool useUserOverride)
+ {
+ Debug.Assert(name != null);
+ CultureData cultureData = CultureData.GetCultureData(name, useUserOverride);
+ if (cultureData == null)
+ {
+ return null;
+ }
+
+ return new CultureInfo(cultureData);
+ }
+
public CultureInfo(int culture) : this(culture, true)
{
}
@@ -533,25 +553,22 @@ namespace System.Globalization
{
if (null == _parent)
{
- try
- {
- string parentName = _cultureData.SPARENT;
+ string parentName = _cultureData.SPARENT;
- if (String.IsNullOrEmpty(parentName))
+ if (String.IsNullOrEmpty(parentName))
+ {
+ _parent = InvariantCulture;
+ }
+ else
+ {
+ _parent = CreateCultureInfoNoThrow(parentName, _cultureData.UseUserOverride);
+ if (_parent == null)
{
+ // For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant
+ // We can't allow ourselves to fail. In case of custom cultures the parent of the
+ // current custom culture isn't installed.
_parent = InvariantCulture;
}
- else
- {
- _parent = new CultureInfo(parentName, _cultureData.UseUserOverride);
- }
- }
- catch (ArgumentException)
- {
- // For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant
- // We can't allow ourselves to fail. In case of custom cultures the parent of the
- // current custom culture isn't installed.
- _parent = InvariantCulture;
}
}
return _parent;
diff --git a/src/mscorlib/src/System/Guid.cs b/src/mscorlib/src/System/Guid.cs
index f64211d5d0..e3b3a6f944 100644
--- a/src/mscorlib/src/System/Guid.cs
+++ b/src/mscorlib/src/System/Guid.cs
@@ -18,6 +18,7 @@ namespace System
[StructLayout(LayoutKind.Sequential)]
[Serializable]
[System.Runtime.Versioning.NonVersionable] // This only applies to field layout
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct Guid : IFormattable, IComparable
, IComparable<Guid>, IEquatable<Guid>
{
@@ -25,17 +26,17 @@ namespace System
////////////////////////////////////////////////////////////////////////////////
// Member variables
////////////////////////////////////////////////////////////////////////////////
- private int _a;
- private short _b;
- private short _c;
- private byte _d;
- private byte _e;
- private byte _f;
- private byte _g;
- private byte _h;
- private byte _i;
- private byte _j;
- private byte _k;
+ private int _a; // Do not rename (binary serialization)
+ private short _b; // Do not rename (binary serialization)
+ private short _c; // Do not rename (binary serialization)
+ private byte _d; // Do not rename (binary serialization)
+ private byte _e; // Do not rename (binary serialization)
+ private byte _f; // Do not rename (binary serialization)
+ private byte _g; // Do not rename (binary serialization)
+ private byte _h; // Do not rename (binary serialization)
+ private byte _i; // Do not rename (binary serialization)
+ private byte _j; // Do not rename (binary serialization)
+ private byte _k; // Do not rename (binary serialization)
diff --git a/src/mscorlib/src/System/Int16.cs b/src/mscorlib/src/System/Int16.cs
index aced05df6d..82e5dd5a38 100644
--- a/src/mscorlib/src/System/Int16.cs
+++ b/src/mscorlib/src/System/Int16.cs
@@ -22,6 +22,7 @@ namespace System
{
[Serializable]
[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct Int16 : IComparable, IFormattable, IConvertible
, IComparable<Int16>, IEquatable<Int16>
{
diff --git a/src/mscorlib/src/System/Int32.cs b/src/mscorlib/src/System/Int32.cs
index afee0e42d7..503552117d 100644
--- a/src/mscorlib/src/System/Int32.cs
+++ b/src/mscorlib/src/System/Int32.cs
@@ -22,6 +22,7 @@ namespace System
{
[Serializable]
[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct Int32 : IComparable, IFormattable, IConvertible
, IComparable<Int32>, IEquatable<Int32>
{
diff --git a/src/mscorlib/src/System/Int64.cs b/src/mscorlib/src/System/Int64.cs
index 619bf7e5d7..015387233c 100644
--- a/src/mscorlib/src/System/Int64.cs
+++ b/src/mscorlib/src/System/Int64.cs
@@ -21,6 +21,7 @@ namespace System
{
[Serializable]
[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct Int64 : IComparable, IFormattable, IConvertible
, IComparable<Int64>, IEquatable<Int64>
{
diff --git a/src/mscorlib/src/System/IntPtr.cs b/src/mscorlib/src/System/IntPtr.cs
index 55c86e3795..e3439801ff 100644
--- a/src/mscorlib/src/System/IntPtr.cs
+++ b/src/mscorlib/src/System/IntPtr.cs
@@ -23,9 +23,10 @@ namespace System
using System.Diagnostics.Contracts;
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct IntPtr : IEquatable<IntPtr>, ISerializable
{
- unsafe private void* _value; // The compiler treats void* closest to uint hence explicit casts are required to preserve int behavior
+ unsafe private void* _value; // The compiler treats void* closest to uint hence explicit casts are required to preserve int behavior. Do not rename (binary serialization)
public static readonly IntPtr Zero;
diff --git a/src/mscorlib/src/System/Nullable.cs b/src/mscorlib/src/System/Nullable.cs
index 31a62ecea8..a2c7c350c9 100644
--- a/src/mscorlib/src/System/Nullable.cs
+++ b/src/mscorlib/src/System/Nullable.cs
@@ -23,10 +23,11 @@ namespace System
//
[Serializable]
[System.Runtime.Versioning.NonVersionable] // This only applies to field layout
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct Nullable<T> where T : struct
{
- private bool hasValue;
- internal T value;
+ private bool hasValue; // Do not rename (binary serialization)
+ internal T value; // Do not rename (binary serialization)
[System.Runtime.Versioning.NonVersionable]
public Nullable(T value)
diff --git a/src/mscorlib/src/System/Object.cs b/src/mscorlib/src/System/Object.cs
index a476557911..8df1caa9e5 100644
--- a/src/mscorlib/src/System/Object.cs
+++ b/src/mscorlib/src/System/Object.cs
@@ -34,6 +34,7 @@ namespace System
[Serializable]
[ClassInterface(ClassInterfaceType.AutoDual)]
[System.Runtime.InteropServices.ComVisible(true)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Object
{
// Creates a new instance of an Object.
diff --git a/src/mscorlib/src/System/Reflection/Assembly.CoreCLR.cs b/src/mscorlib/src/System/Reflection/Assembly.CoreCLR.cs
index 9d34b48177..49a55181d4 100644
--- a/src/mscorlib/src/System/Reflection/Assembly.CoreCLR.cs
+++ b/src/mscorlib/src/System/Reflection/Assembly.CoreCLR.cs
@@ -52,7 +52,19 @@ namespace System.Reflection
string requestedAssemblyPath = Path.Combine(Path.GetDirectoryName(requestorPath), requestedAssemblyName.Name+".dll");
// Load the dependency via LoadFrom so that it goes through the same path of being in the LoadFrom list.
- return Assembly.LoadFrom(requestedAssemblyPath);
+ Assembly resolvedAssembly = null;
+
+ try
+ {
+ resolvedAssembly = Assembly.LoadFrom(requestedAssemblyPath);
+ }
+ catch(FileNotFoundException)
+ {
+ // Catch FileNotFoundException when attempting to resolve assemblies via this handler to account for missing assemblies.
+ resolvedAssembly = null;
+ }
+
+ return resolvedAssembly;
}
public static Assembly LoadFrom(String assemblyFile)
diff --git a/src/mscorlib/src/System/Resources/LooselyLinkedResourceReference.cs b/src/mscorlib/src/System/Resources/LooselyLinkedResourceReference.cs
deleted file mode 100644
index 3179df09b7..0000000000
--- a/src/mscorlib/src/System/Resources/LooselyLinkedResourceReference.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-/*============================================================
-**
-**
-**
-**
-**
-** Purpose: Provides a localizable way of retrieving a file
-** that is linked into your assembly and/or satellite assembly
-** while also leaving the file on disk for unmanaged tools.
-**
-**
-===========================================================*/
-
-// Removing LooselyLinkedResourceReference from Whidbey. We don't
-// yet have any strong customer need for it yet.
-#if LOOSELY_LINKED_RESOURCE_REFERENCE
-
-namespace System.Resources {
- using System.Reflection;
- using System.Diagnostics.Contracts;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Globalization;
-
- [Serializable]
-
- public struct LooselyLinkedResourceReference {
- private String _manifestResourceName;
- private String _typeName;
-
- public LooselyLinkedResourceReference(String looselyLinkedResourceName, String typeName)
- {
- if (looselyLinkedResourceName == null)
- throw new ArgumentNullException(nameof(looselyLinkedResourceName));
- if (typeName == null)
- throw new ArgumentNullException(nameof(typeName));
- if (looselyLinkedResourceName.Length == 0)
- throw new ArgumentException(SR.Argument_EmptyName, nameof(looselyLinkedResourceName));
- if (typeName.Length == 0)
- throw new ArgumentException(SR.Argument_EmptyName, nameof(typeName));
- Contract.EndContractBlock();
-
- _manifestResourceName = looselyLinkedResourceName;
- _typeName = typeName;
- }
-
- public String LooselyLinkedResourceName {
- get { return _manifestResourceName; }
- }
-
- public String TypeName {
- get { return _typeName; }
- }
-
- public Object Resolve(Assembly assembly)
- {
- if (assembly == null)
- throw new ArgumentNullException(nameof(assembly));
- Contract.EndContractBlock();
-
- Stream data = assembly.GetManifestResourceStream(_manifestResourceName);
- if (data == null)
- throw new MissingManifestResourceException(SR.Format(SR.MissingManifestResource_LooselyLinked, _manifestResourceName, assembly.FullName));
-
- Type type = Type.GetType(_typeName, true);
-
- Object obj = Activator.CreateInstance(type, new Object[] { data });
- return obj;
- }
-
- // For good debugging with tools like ResView
- public override String ToString()
- {
- // This is for debugging only. Since we use the property names,
- // this does not need to be localized.
- return "LooselyLinkedResourceName = \""+ _manifestResourceName +"\", TypeName = \"" + _typeName + "\"";
- }
- }
-}
-
-#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
diff --git a/src/mscorlib/src/System/SByte.cs b/src/mscorlib/src/System/SByte.cs
index 9e550936fe..8a0ab3e129 100644
--- a/src/mscorlib/src/System/SByte.cs
+++ b/src/mscorlib/src/System/SByte.cs
@@ -21,6 +21,7 @@ namespace System
// A place holder class for signed bytes.
[Serializable]
[CLSCompliant(false), System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct SByte : IComparable, IFormattable, IConvertible
, IComparable<SByte>, IEquatable<SByte>
{
diff --git a/src/mscorlib/src/System/Single.cs b/src/mscorlib/src/System/Single.cs
index 24e6839be6..c94e673c26 100644
--- a/src/mscorlib/src/System/Single.cs
+++ b/src/mscorlib/src/System/Single.cs
@@ -22,6 +22,7 @@ namespace System
{
[Serializable]
[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct Single : IComparable, IFormattable, IConvertible
, IComparable<Single>, IEquatable<Single>
{
diff --git a/src/mscorlib/src/System/String.cs b/src/mscorlib/src/System/String.cs
index 0a17c1ee24..c2b7466d92 100644
--- a/src/mscorlib/src/System/String.cs
+++ b/src/mscorlib/src/System/String.cs
@@ -40,6 +40,7 @@ namespace System
// (indices) are zero-based.
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public sealed partial class String : IComparable, ICloneable, IConvertible, IEnumerable
, IComparable<String>, IEnumerable<char>, IEquatable<String>
{
diff --git a/src/mscorlib/src/System/TimeSpan.cs b/src/mscorlib/src/System/TimeSpan.cs
index 9166656d0f..ca60bcb16f 100644
--- a/src/mscorlib/src/System/TimeSpan.cs
+++ b/src/mscorlib/src/System/TimeSpan.cs
@@ -68,7 +68,7 @@ namespace System
// internal so that DateTime doesn't have to call an extra get
// method for some arithmetic operations.
- internal long _ticks;
+ internal long _ticks; // Do not rename (binary serialization)
//public TimeSpan() {
// _ticks = 0;
diff --git a/src/mscorlib/src/System/TimeZoneInfo.AdjustmentRule.cs b/src/mscorlib/src/System/TimeZoneInfo.AdjustmentRule.cs
index c0c27eeab7..79fe8db815 100644
--- a/src/mscorlib/src/System/TimeZoneInfo.AdjustmentRule.cs
+++ b/src/mscorlib/src/System/TimeZoneInfo.AdjustmentRule.cs
@@ -212,13 +212,13 @@ namespace System
}
Contract.EndContractBlock();
- info.AddValue("DateStart", _dateStart);
- info.AddValue("DateEnd", _dateEnd);
- info.AddValue("DaylightDelta", _daylightDelta);
- info.AddValue("DaylightTransitionStart", _daylightTransitionStart);
- info.AddValue("DaylightTransitionEnd", _daylightTransitionEnd);
- info.AddValue("BaseUtcOffsetDelta", _baseUtcOffsetDelta);
- info.AddValue("NoDaylightTransitions", _noDaylightTransitions);
+ info.AddValue("DateStart", _dateStart); // Do not rename (binary serialization)
+ info.AddValue("DateEnd", _dateEnd); // Do not rename (binary serialization)
+ info.AddValue("DaylightDelta", _daylightDelta); // Do not rename (binary serialization)
+ info.AddValue("DaylightTransitionStart", _daylightTransitionStart); // Do not rename (binary serialization)
+ info.AddValue("DaylightTransitionEnd", _daylightTransitionEnd); // Do not rename (binary serialization)
+ info.AddValue("BaseUtcOffsetDelta", _baseUtcOffsetDelta); // Do not rename (binary serialization)
+ info.AddValue("NoDaylightTransitions", _noDaylightTransitions); // Do not rename (binary serialization)
}
private AdjustmentRule(SerializationInfo info, StreamingContext context)
@@ -228,19 +228,19 @@ namespace System
throw new ArgumentNullException(nameof(info));
}
- _dateStart = (DateTime)info.GetValue("DateStart", typeof(DateTime));
- _dateEnd = (DateTime)info.GetValue("DateEnd", typeof(DateTime));
- _daylightDelta = (TimeSpan)info.GetValue("DaylightDelta", typeof(TimeSpan));
- _daylightTransitionStart = (TransitionTime)info.GetValue("DaylightTransitionStart", typeof(TransitionTime));
- _daylightTransitionEnd = (TransitionTime)info.GetValue("DaylightTransitionEnd", typeof(TransitionTime));
+ _dateStart = (DateTime)info.GetValue("DateStart", typeof(DateTime)); // Do not rename (binary serialization)
+ _dateEnd = (DateTime)info.GetValue("DateEnd", typeof(DateTime)); // Do not rename (binary serialization)
+ _daylightDelta = (TimeSpan)info.GetValue("DaylightDelta", typeof(TimeSpan)); // Do not rename (binary serialization)
+ _daylightTransitionStart = (TransitionTime)info.GetValue("DaylightTransitionStart", typeof(TransitionTime)); // Do not rename (binary serialization)
+ _daylightTransitionEnd = (TransitionTime)info.GetValue("DaylightTransitionEnd", typeof(TransitionTime)); // Do not rename (binary serialization)
- object o = info.GetValueNoThrow("BaseUtcOffsetDelta", typeof(TimeSpan));
+ object o = info.GetValueNoThrow("BaseUtcOffsetDelta", typeof(TimeSpan)); // Do not rename (binary serialization)
if (o != null)
{
_baseUtcOffsetDelta = (TimeSpan)o;
}
- o = info.GetValueNoThrow("NoDaylightTransitions", typeof(bool));
+ o = info.GetValueNoThrow("NoDaylightTransitions", typeof(bool)); // Do not rename (binary serialization)
if (o != null)
{
_noDaylightTransitions = (bool)o;
diff --git a/src/mscorlib/src/System/TimeZoneInfo.TransitionTime.cs b/src/mscorlib/src/System/TimeZoneInfo.TransitionTime.cs
index 1e1d9d328b..0fe3dab0b6 100644
--- a/src/mscorlib/src/System/TimeZoneInfo.TransitionTime.cs
+++ b/src/mscorlib/src/System/TimeZoneInfo.TransitionTime.cs
@@ -132,12 +132,12 @@ namespace System
}
Contract.EndContractBlock();
- info.AddValue("TimeOfDay", _timeOfDay);
- info.AddValue("Month", _month);
- info.AddValue("Week", _week);
- info.AddValue("Day", _day);
- info.AddValue("DayOfWeek", _dayOfWeek);
- info.AddValue("IsFixedDateRule", _isFixedDateRule);
+ info.AddValue("TimeOfDay", _timeOfDay); // Do not rename (binary serialization)
+ info.AddValue("Month", _month); // Do not rename (binary serialization)
+ info.AddValue("Week", _week); // Do not rename (binary serialization)
+ info.AddValue("Day", _day); // Do not rename (binary serialization)
+ info.AddValue("DayOfWeek", _dayOfWeek); // Do not rename (binary serialization)
+ info.AddValue("IsFixedDateRule", _isFixedDateRule); // Do not rename (binary serialization)
}
private TransitionTime(SerializationInfo info, StreamingContext context)
@@ -147,12 +147,12 @@ namespace System
throw new ArgumentNullException(nameof(info));
}
- _timeOfDay = (DateTime)info.GetValue("TimeOfDay", typeof(DateTime));
- _month = (byte)info.GetValue("Month", typeof(byte));
- _week = (byte)info.GetValue("Week", typeof(byte));
- _day = (byte)info.GetValue("Day", typeof(byte));
- _dayOfWeek = (DayOfWeek)info.GetValue("DayOfWeek", typeof(DayOfWeek));
- _isFixedDateRule = (bool)info.GetValue("IsFixedDateRule", typeof(bool));
+ _timeOfDay = (DateTime)info.GetValue("TimeOfDay", typeof(DateTime)); // Do not rename (binary serialization)
+ _month = (byte)info.GetValue("Month", typeof(byte)); // Do not rename (binary serialization)
+ _week = (byte)info.GetValue("Week", typeof(byte)); // Do not rename (binary serialization)
+ _day = (byte)info.GetValue("Day", typeof(byte)); // Do not rename (binary serialization)
+ _dayOfWeek = (DayOfWeek)info.GetValue("DayOfWeek", typeof(DayOfWeek)); // Do not rename (binary serialization)
+ _isFixedDateRule = (bool)info.GetValue("IsFixedDateRule", typeof(bool)); // Do not rename (binary serialization)
}
}
}
diff --git a/src/mscorlib/src/System/TimeZoneInfo.cs b/src/mscorlib/src/System/TimeZoneInfo.cs
index 8ed7e229c0..a492275a71 100644
--- a/src/mscorlib/src/System/TimeZoneInfo.cs
+++ b/src/mscorlib/src/System/TimeZoneInfo.cs
@@ -29,6 +29,7 @@ namespace System
};
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
public sealed partial class TimeZoneInfo : IEquatable<TimeZoneInfo>, ISerializable, IDeserializationCallback
{
private enum TimeZoneInfoResult
@@ -1040,13 +1041,13 @@ namespace System
}
Contract.EndContractBlock();
- info.AddValue("Id", _id);
- info.AddValue("DisplayName", _displayName);
- info.AddValue("StandardName", _standardDisplayName);
- info.AddValue("DaylightName", _daylightDisplayName);
- info.AddValue("BaseUtcOffset", _baseUtcOffset);
- info.AddValue("AdjustmentRules", _adjustmentRules);
- info.AddValue("SupportsDaylightSavingTime", _supportsDaylightSavingTime);
+ info.AddValue("Id", _id); // Do not rename (binary serialization)
+ info.AddValue("DisplayName", _displayName); // Do not rename (binary serialization)
+ info.AddValue("StandardName", _standardDisplayName); // Do not rename (binary serialization)
+ info.AddValue("DaylightName", _daylightDisplayName); // Do not rename (binary serialization)
+ info.AddValue("BaseUtcOffset", _baseUtcOffset); // Do not rename (binary serialization)
+ info.AddValue("AdjustmentRules", _adjustmentRules); // Do not rename (binary serialization)
+ info.AddValue("SupportsDaylightSavingTime", _supportsDaylightSavingTime); // Do not rename (binary serialization)
}
private TimeZoneInfo(SerializationInfo info, StreamingContext context)
@@ -1056,13 +1057,13 @@ namespace System
throw new ArgumentNullException(nameof(info));
}
- _id = (string)info.GetValue("Id", typeof(string));
- _displayName = (string)info.GetValue("DisplayName", typeof(string));
- _standardDisplayName = (string)info.GetValue("StandardName", typeof(string));
- _daylightDisplayName = (string)info.GetValue("DaylightName", typeof(string));
- _baseUtcOffset = (TimeSpan)info.GetValue("BaseUtcOffset", typeof(TimeSpan));
- _adjustmentRules = (AdjustmentRule[])info.GetValue("AdjustmentRules", typeof(AdjustmentRule[]));
- _supportsDaylightSavingTime = (bool)info.GetValue("SupportsDaylightSavingTime", typeof(bool));
+ _id = (string)info.GetValue("Id", typeof(string)); // Do not rename (binary serialization)
+ _displayName = (string)info.GetValue("DisplayName", typeof(string)); // Do not rename (binary serialization)
+ _standardDisplayName = (string)info.GetValue("StandardName", typeof(string)); // Do not rename (binary serialization)
+ _daylightDisplayName = (string)info.GetValue("DaylightName", typeof(string)); // Do not rename (binary serialization)
+ _baseUtcOffset = (TimeSpan)info.GetValue("BaseUtcOffset", typeof(TimeSpan)); // Do not rename (binary serialization)
+ _adjustmentRules = (AdjustmentRule[])info.GetValue("AdjustmentRules", typeof(AdjustmentRule[])); // Do not rename (binary serialization)
+ _supportsDaylightSavingTime = (bool)info.GetValue("SupportsDaylightSavingTime", typeof(bool)); // Do not rename (binary serialization)
}
private AdjustmentRule GetAdjustmentRuleForTime(DateTime dateTime, out int? ruleIndex)
diff --git a/src/mscorlib/src/System/Tuple.cs b/src/mscorlib/src/System/Tuple.cs
index a118df02bd..6a8758278c 100644
--- a/src/mscorlib/src/System/Tuple.cs
+++ b/src/mscorlib/src/System/Tuple.cs
@@ -105,9 +105,10 @@ namespace System
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Tuple<T1> : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple
{
- private readonly T1 m_Item1;
+ private readonly T1 m_Item1; // Do not rename (binary serialization)
public T1 Item1 { get { return m_Item1; } }
@@ -204,10 +205,11 @@ namespace System
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Tuple<T1, T2> : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple
{
- private readonly T1 m_Item1;
- private readonly T2 m_Item2;
+ private readonly T1 m_Item1; // Do not rename (binary serialization)
+ private readonly T2 m_Item2; // Do not rename (binary serialization)
public T1 Item1 { get { return m_Item1; } }
public T2 Item2 { get { return m_Item2; } }
@@ -318,11 +320,12 @@ namespace System
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Tuple<T1, T2, T3> : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple
{
- private readonly T1 m_Item1;
- private readonly T2 m_Item2;
- private readonly T3 m_Item3;
+ private readonly T1 m_Item1; // Do not rename (binary serialization)
+ private readonly T2 m_Item2; // Do not rename (binary serialization)
+ private readonly T3 m_Item3; // Do not rename (binary serialization)
public T1 Item1 { get { return m_Item1; } }
public T2 Item2 { get { return m_Item2; } }
@@ -443,12 +446,13 @@ namespace System
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Tuple<T1, T2, T3, T4> : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple
{
- private readonly T1 m_Item1;
- private readonly T2 m_Item2;
- private readonly T3 m_Item3;
- private readonly T4 m_Item4;
+ private readonly T1 m_Item1; // Do not rename (binary serialization)
+ private readonly T2 m_Item2; // Do not rename (binary serialization)
+ private readonly T3 m_Item3; // Do not rename (binary serialization)
+ private readonly T4 m_Item4; // Do not rename (binary serialization)
public T1 Item1 { get { return m_Item1; } }
public T2 Item2 { get { return m_Item2; } }
@@ -579,13 +583,14 @@ namespace System
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Tuple<T1, T2, T3, T4, T5> : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple
{
- private readonly T1 m_Item1;
- private readonly T2 m_Item2;
- private readonly T3 m_Item3;
- private readonly T4 m_Item4;
- private readonly T5 m_Item5;
+ private readonly T1 m_Item1; // Do not rename (binary serialization)
+ private readonly T2 m_Item2; // Do not rename (binary serialization)
+ private readonly T3 m_Item3; // Do not rename (binary serialization)
+ private readonly T4 m_Item4; // Do not rename (binary serialization)
+ private readonly T5 m_Item5; // Do not rename (binary serialization)
public T1 Item1 { get { return m_Item1; } }
public T2 Item2 { get { return m_Item2; } }
@@ -726,14 +731,15 @@ namespace System
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Tuple<T1, T2, T3, T4, T5, T6> : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple
{
- private readonly T1 m_Item1;
- private readonly T2 m_Item2;
- private readonly T3 m_Item3;
- private readonly T4 m_Item4;
- private readonly T5 m_Item5;
- private readonly T6 m_Item6;
+ private readonly T1 m_Item1; // Do not rename (binary serialization)
+ private readonly T2 m_Item2; // Do not rename (binary serialization)
+ private readonly T3 m_Item3; // Do not rename (binary serialization)
+ private readonly T4 m_Item4; // Do not rename (binary serialization)
+ private readonly T5 m_Item5; // Do not rename (binary serialization)
+ private readonly T6 m_Item6; // Do not rename (binary serialization)
public T1 Item1 { get { return m_Item1; } }
public T2 Item2 { get { return m_Item2; } }
@@ -884,15 +890,16 @@ namespace System
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Tuple<T1, T2, T3, T4, T5, T6, T7> : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple
{
- private readonly T1 m_Item1;
- private readonly T2 m_Item2;
- private readonly T3 m_Item3;
- private readonly T4 m_Item4;
- private readonly T5 m_Item5;
- private readonly T6 m_Item6;
- private readonly T7 m_Item7;
+ private readonly T1 m_Item1; // Do not rename (binary serialization)
+ private readonly T2 m_Item2; // Do not rename (binary serialization)
+ private readonly T3 m_Item3; // Do not rename (binary serialization)
+ private readonly T4 m_Item4; // Do not rename (binary serialization)
+ private readonly T5 m_Item5; // Do not rename (binary serialization)
+ private readonly T6 m_Item6; // Do not rename (binary serialization)
+ private readonly T7 m_Item7; // Do not rename (binary serialization)
public T1 Item1 { get { return m_Item1; } }
public T2 Item2 { get { return m_Item2; } }
@@ -1053,16 +1060,17 @@ namespace System
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple
{
- private readonly T1 m_Item1;
- private readonly T2 m_Item2;
- private readonly T3 m_Item3;
- private readonly T4 m_Item4;
- private readonly T5 m_Item5;
- private readonly T6 m_Item6;
- private readonly T7 m_Item7;
- private readonly TRest m_Rest;
+ private readonly T1 m_Item1; // Do not rename (binary serialization)
+ private readonly T2 m_Item2; // Do not rename (binary serialization)
+ private readonly T3 m_Item3; // Do not rename (binary serialization)
+ private readonly T4 m_Item4; // Do not rename (binary serialization)
+ private readonly T5 m_Item5; // Do not rename (binary serialization)
+ private readonly T6 m_Item6; // Do not rename (binary serialization)
+ private readonly T7 m_Item7; // Do not rename (binary serialization)
+ private readonly TRest m_Rest; // Do not rename (binary serialization)
public T1 Item1 { get { return m_Item1; } }
public T2 Item2 { get { return m_Item2; } }
diff --git a/src/mscorlib/src/System/UInt16.cs b/src/mscorlib/src/System/UInt16.cs
index c7be2e9a1f..746ed7ba49 100644
--- a/src/mscorlib/src/System/UInt16.cs
+++ b/src/mscorlib/src/System/UInt16.cs
@@ -21,6 +21,7 @@ namespace System
// Wrapper for unsigned 16 bit integers.
[Serializable]
[CLSCompliant(false), System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct UInt16 : IComparable, IFormattable, IConvertible
, IComparable<UInt16>, IEquatable<UInt16>
{
diff --git a/src/mscorlib/src/System/UInt32.cs b/src/mscorlib/src/System/UInt32.cs
index 2731047e06..f696816b98 100644
--- a/src/mscorlib/src/System/UInt32.cs
+++ b/src/mscorlib/src/System/UInt32.cs
@@ -23,6 +23,7 @@ namespace System
// * Wrapper for unsigned 32 bit integers.
[Serializable]
[CLSCompliant(false), System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct UInt32 : IComparable, IFormattable, IConvertible
, IComparable<UInt32>, IEquatable<UInt32>
{
diff --git a/src/mscorlib/src/System/UInt64.cs b/src/mscorlib/src/System/UInt64.cs
index a54bb69ba4..03cdcc5f40 100644
--- a/src/mscorlib/src/System/UInt64.cs
+++ b/src/mscorlib/src/System/UInt64.cs
@@ -21,6 +21,7 @@ namespace System
// Wrapper for unsigned 64 bit integers.
[Serializable]
[CLSCompliant(false), System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct UInt64 : IComparable, IFormattable, IConvertible
, IComparable<UInt64>, IEquatable<UInt64>
{
diff --git a/src/mscorlib/src/System/UIntPtr.cs b/src/mscorlib/src/System/UIntPtr.cs
index 08e494297b..1bed651e6f 100644
--- a/src/mscorlib/src/System/UIntPtr.cs
+++ b/src/mscorlib/src/System/UIntPtr.cs
@@ -21,9 +21,10 @@ namespace System
[Serializable]
[CLSCompliant(false)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct UIntPtr : IEquatable<UIntPtr>, ISerializable
{
- unsafe private void* _value;
+ unsafe private void* _value; // Do not rename (binary serialization)
public static readonly UIntPtr Zero;
diff --git a/src/mscorlib/src/System/ValueType.cs b/src/mscorlib/src/System/ValueType.cs
index 0cd08bd26f..e5b5528314 100644
--- a/src/mscorlib/src/System/ValueType.cs
+++ b/src/mscorlib/src/System/ValueType.cs
@@ -19,6 +19,7 @@ using System.Runtime.Versioning;
namespace System
{
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract class ValueType
{
public override bool Equals(Object obj)
diff --git a/src/mscorlib/src/System/WeakReference.cs b/src/mscorlib/src/System/WeakReference.cs
index 60878b8e1c..a6a30c1978 100644
--- a/src/mscorlib/src/System/WeakReference.cs
+++ b/src/mscorlib/src/System/WeakReference.cs
@@ -20,6 +20,7 @@ using System.Diagnostics.Contracts;
namespace System
{
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class WeakReference : ISerializable
{
// If you fix bugs here, please fix them in WeakReference<T> at the same time.
@@ -57,8 +58,8 @@ namespace System
}
Contract.EndContractBlock();
- Object target = info.GetValue("TrackedObject", typeof(Object));
- bool trackResurrection = info.GetBoolean("TrackResurrection");
+ Object target = info.GetValue("TrackedObject", typeof(Object)); // Do not rename (binary serialization)
+ bool trackResurrection = info.GetBoolean("TrackResurrection"); // Do not rename (binary serialization)
Create(target, trackResurrection);
}
@@ -108,8 +109,8 @@ namespace System
throw new ArgumentNullException(nameof(info));
}
Contract.EndContractBlock();
- info.AddValue("TrackedObject", Target, typeof(Object));
- info.AddValue("TrackResurrection", IsTrackResurrection());
+ info.AddValue("TrackedObject", Target, typeof(Object)); // Do not rename (binary serialization)
+ info.AddValue("TrackResurrection", IsTrackResurrection()); // Do not rename (binary serialization)
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
diff --git a/src/mscorlib/src/System/WeakReferenceOfT.cs b/src/mscorlib/src/System/WeakReferenceOfT.cs
index fbb6f09098..7347683e2f 100644
--- a/src/mscorlib/src/System/WeakReferenceOfT.cs
+++ b/src/mscorlib/src/System/WeakReferenceOfT.cs
@@ -20,6 +20,7 @@ using System.Diagnostics.Contracts;
namespace System
{
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
// This class is sealed to mitigate security issues caused by Object::MemberwiseClone.
public sealed class WeakReference<T> : ISerializable
where T : class
@@ -52,8 +53,8 @@ namespace System
}
Contract.EndContractBlock();
- T target = (T)info.GetValue("TrackedObject", typeof(T));
- bool trackResurrection = info.GetBoolean("TrackResurrection");
+ T target = (T)info.GetValue("TrackedObject", typeof(T)); // Do not rename (binary serialization)
+ bool trackResurrection = info.GetBoolean("TrackResurrection"); // Do not rename (binary serialization)
Create(target, trackResurrection);
}
@@ -105,8 +106,8 @@ namespace System
}
Contract.EndContractBlock();
- info.AddValue("TrackedObject", this.Target, typeof(T));
- info.AddValue("TrackResurrection", IsTrackResurrection());
+ info.AddValue("TrackedObject", this.Target, typeof(T)); // Do not rename (binary serialization)
+ info.AddValue("TrackResurrection", IsTrackResurrection()); // Do not rename (binary serialization)
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
diff --git a/src/mscorlib/src/mscorlib.Friends.cs b/src/mscorlib/src/mscorlib.Friends.cs
index b02b4829d9..709ec21191 100644
--- a/src/mscorlib/src/mscorlib.Friends.cs
+++ b/src/mscorlib/src/mscorlib.Friends.cs
@@ -13,3 +13,5 @@ using System.Runtime.CompilerServices;
// Depends on WindowsRuntimeImportAttribute
[assembly: InternalsVisibleTo("System.Runtime.WindowsRuntime.UI.Xaml, PublicKey=00000000000000000400000000000000", AllInternalsVisible = false)]
+// Cross framework serialization needs access to internals
+[assembly: InternalsVisibleTo("mscorlib, PublicKey=00000000000000000400000000000000", AllInternalsVisible=false)]
diff --git a/src/pal/src/exception/seh-unwind.cpp b/src/pal/src/exception/seh-unwind.cpp
index ba43c2e725..7746bbbbf5 100644
--- a/src/pal/src/exception/seh-unwind.cpp
+++ b/src/pal/src/exception/seh-unwind.cpp
@@ -266,13 +266,8 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP
// cannot cross on some systems.
if ((void*)curPc == g_SEHProcessExceptionReturnAddress)
{
- ULONG contextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_EXCEPTION_ACTIVE;
-
- #if defined(_AMD64_)
- contextFlags |= CONTEXT_XSTATE;
- #endif
- size_t nativeContext = *(size_t*)(CONTEXTGetFP(context) + g_common_signal_handler_context_locvar_offset);
- CONTEXTFromNativeContext((const native_context_t *)nativeContext, context, contextFlags);
+ CONTEXT* signalContext = (CONTEXT*)(CONTEXTGetFP(context) + g_common_signal_handler_context_locvar_offset);
+ memcpy_s(context, sizeof(CONTEXT), signalContext, sizeof(CONTEXT));
return TRUE;
}
diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp
index 57ae62ea21..10eecf7b02 100644
--- a/src/pal/src/exception/signal.cpp
+++ b/src/pal/src/exception/signal.cpp
@@ -411,7 +411,27 @@ extern "C" void signal_handler_worker(int code, siginfo_t *siginfo, void *contex
// TODO: First variable parameter says whether a read (0) or write (non-0) caused the
// fault. We must disassemble the instruction at record.ExceptionAddress
// to correctly fill in this value.
+
+ // Unmask the activation signal now that we are running on the original stack of the thread
+ sigset_t signal_set;
+ sigemptyset(&signal_set);
+ sigaddset(&signal_set, INJECT_ACTIVATION_SIGNAL);
+
+ int sigmaskRet = pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL);
+ if (sigmaskRet != 0)
+ {
+ ASSERT("pthread_sigmask failed; error number is %d\n", sigmaskRet);
+ }
+
returnPoint->returnFromHandler = common_signal_handler(code, siginfo, context, 2, (size_t)0, (size_t)siginfo->si_addr);
+
+ // We are going to return to the alternate stack, so block the activation signal again
+ sigmaskRet = pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
+ if (sigmaskRet != 0)
+ {
+ ASSERT("pthread_sigmask failed; error number is %d\n", sigmaskRet);
+ }
+
RtlRestoreContext(&returnPoint->context, NULL);
}
@@ -761,12 +781,13 @@ __attribute__((noinline))
static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext, int numParams, ...)
{
sigset_t signal_set;
+ CONTEXT signalContextRecord;
CONTEXT *contextRecord;
EXCEPTION_RECORD *exceptionRecord;
native_context_t *ucontext;
ucontext = (native_context_t *)sigcontext;
- g_common_signal_handler_context_locvar_offset = (int)((char*)&ucontext - (char*)__builtin_frame_address(0));
+ g_common_signal_handler_context_locvar_offset = (int)((char*)&signalContextRecord - (char*)__builtin_frame_address(0));
AllocateExceptionRecords(&exceptionRecord, &contextRecord);
@@ -809,6 +830,9 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext
}
contextRecord->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE;
+
+ memcpy_s(&signalContextRecord, sizeof(CONTEXT), contextRecord, sizeof(CONTEXT));
+
// The exception object takes ownership of the exceptionRecord and contextRecord
PAL_SEHException exception(exceptionRecord, contextRecord);
@@ -852,6 +876,16 @@ void handle_signal(int signal_id, SIGFUNC sigfunc, struct sigaction *previousAct
#endif /* HAVE_SIGINFO_T */
sigemptyset(&newAction.sa_mask);
+#ifdef INJECT_ACTIVATION_SIGNAL
+ if ((additionalFlags & SA_ONSTACK) != 0)
+ {
+ // A handler that runs on a separate stack should not be interrupted by the activation signal
+ // until it switches back to the regular stack, since that signal's handler would run on the
+ // limited separate stack and likely run into a stack overflow.
+ sigaddset(&newAction.sa_mask, INJECT_ACTIVATION_SIGNAL);
+ }
+#endif
+
if (-1 == sigaction(signal_id, &newAction, previousAction))
{
ASSERT("handle_signal: sigaction() call failed with error code %d (%s)\n",
diff --git a/src/pal/src/thread/process.cpp b/src/pal/src/thread/process.cpp
index 6db9bf6f51..e22d268cf6 100644
--- a/src/pal/src/thread/process.cpp
+++ b/src/pal/src/thread/process.cpp
@@ -2951,6 +2951,10 @@ PROCAbortInitialize()
{
*argv++ = "--triage";
}
+ else if (strcmp(envvar, "4") == 0)
+ {
+ *argv++ = "--full";
+ }
}
envvar = getenv("COMPlus_CreateDumpDiagnostics");
diff --git a/src/pal/tools/gen-buildsys-clang.sh b/src/pal/tools/gen-buildsys-clang.sh
index 944187786f..132be93c7d 100755
--- a/src/pal/tools/gen-buildsys-clang.sh
+++ b/src/pal/tools/gen-buildsys-clang.sh
@@ -173,8 +173,8 @@ cmake \
"-DCMAKE_NM=$llvm_nm" \
"-DCMAKE_OBJDUMP=$llvm_objdump" \
"-DCMAKE_BUILD_TYPE=$buildtype" \
- "-DCMAKE_ENABLE_CODE_COVERAGE=$code_coverage" \
"-DCMAKE_EXPORT_COMPILE_COMMANDS=1 " \
+ "-DCLR_CMAKE_ENABLE_CODE_COVERAGE=$code_coverage" \
"-DCLR_CMAKE_BUILD_TESTS=$build_tests" \
$cmake_extra_defines \
$__UnprocessedCMakeArgs \
diff --git a/src/scripts/genEventPipe.py b/src/scripts/genEventPipe.py
index a00511d95d..4c802acaf3 100644
--- a/src/scripts/genEventPipe.py
+++ b/src/scripts/genEventPipe.py
@@ -262,6 +262,8 @@ def generateEventPipeCmakeFile(etwmanifest, eventpipe_directory):
topCmake.write(' "eventpipehelpers.cpp"\n')
topCmake.write(""" )
+ add_dependencies(eventpipe GeneratedEventingFiles)
+
# Install the static eventpipe library
install(TARGETS eventpipe DESTINATION lib)
""")
diff --git a/src/vm/gcenv.ee.cpp b/src/vm/gcenv.ee.cpp
index 63c4ffea10..c38419807f 100644
--- a/src/vm/gcenv.ee.cpp
+++ b/src/vm/gcenv.ee.cpp
@@ -1325,10 +1325,13 @@ void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args)
VolatileStore(&g_highest_address, args->highest_address);
::StompWriteBarrierResize(true, false);
- // g_ephemeral_low/high aren't needed for the write barrier stomp, but they
- // are needed in other places.
+ // StompWriteBarrierResize does not necessarily bash g_ephemeral_low
+ // usages, so we must do so here. This is particularly true on x86,
+ // where StompWriteBarrierResize will not bash g_ephemeral_low when
+ // called with the parameters (true, false), as it is above.
g_ephemeral_low = args->ephemeral_low;
g_ephemeral_high = args->ephemeral_high;
+ ::StompWriteBarrierEphemeral(true);
return;
case WriteBarrierOp::SwitchToWriteWatch:
#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
diff --git a/src/vm/object.cpp b/src/vm/object.cpp
index 3e3f6d120a..4c08f0254e 100644
--- a/src/vm/object.cpp
+++ b/src/vm/object.cpp
@@ -2954,8 +2954,9 @@ void __fastcall ZeroMemoryInGCHeap(void* mem, size_t size)
*memBytes++ = 0;
// now write pointer sized pieces
+ // volatile ensures that this doesn't get optimized back into a memset call (see #12207)
size_t nPtrs = (endBytes - memBytes) / sizeof(PTR_PTR_VOID);
- PTR_PTR_VOID memPtr = (PTR_PTR_VOID) memBytes;
+ volatile PTR_PTR_VOID memPtr = (PTR_PTR_VOID) memBytes;
for (size_t i = 0; i < nPtrs; i++)
*memPtr++ = 0;