зеркало из https://github.com/dotnet/diagnostics.git
Merge changes from coreclr repo. (#78)
* Merge changes from coreclr repo. Misc PAL and inc file changes. Remove context statics support from SOS. Add support for collectible types to SOS. Upgrade to Arcade version 1.0.0-beta.18516.5
This commit is contained in:
Родитель
c82d902d1a
Коммит
b84277a43f
|
@ -3,6 +3,6 @@
|
|||
"dotnet": "2.1.401"
|
||||
},
|
||||
"msbuild-sdks": {
|
||||
"Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.18501.3"
|
||||
"Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.18516.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,426 +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.
|
||||
//*****************************************************************************
|
||||
// dbgutil.cpp
|
||||
//
|
||||
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//
|
||||
// Various common helpers for PE resource reading used by multiple debug components.
|
||||
//
|
||||
|
||||
#include <dbgutil.h>
|
||||
#include "corerror.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Returns the RVA of the resource section for the module specified by the given data target and module base.
|
||||
// Returns failure if the module doesn't have a resource section.
|
||||
//
|
||||
// Arguments
|
||||
// pDataTarget - dataTarget for the process we are inspecting
|
||||
// moduleBaseAddress - base address of a module we should inspect
|
||||
// pwImageFileMachine - updated with the Machine from the IMAGE_FILE_HEADER
|
||||
// pdwResourceSectionRVA - updated with the resultant RVA on success
|
||||
HRESULT GetMachineAndResourceSectionRVA(ICorDebugDataTarget* pDataTarget,
|
||||
ULONG64 moduleBaseAddress,
|
||||
WORD* pwImageFileMachine,
|
||||
DWORD* pdwResourceSectionRVA)
|
||||
{
|
||||
// Fun code ahead... below is a hand written PE decoder with some of the file offsets hardcoded.
|
||||
// It supports no more than what we absolutely have to to get to the resources we need. Any of the
|
||||
// magic numbers used below can be determined by using the public documentation on the web.
|
||||
//
|
||||
// Yes utilcode has a PE decoder, no it does not support reading its data through a datatarget
|
||||
// It was easier to inspect the small portion that I needed than to shove an abstraction layer under
|
||||
// our utilcode and then make sure everything still worked.
|
||||
|
||||
// SECURITY WARNING: all data provided by the data target should be considered untrusted.
|
||||
// Do not allow malicious data to cause large reads, memory allocations, buffer overflow,
|
||||
// or any other undesirable behavior.
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
// at offset 3c in the image is a 4 byte file pointer that indicates where the PE signature is
|
||||
IMAGE_DOS_HEADER dosHeader;
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress, (BYTE*)&dosHeader, sizeof(dosHeader));
|
||||
|
||||
// verify there is a 4 byte PE signature there
|
||||
DWORD peSigFilePointer = 0;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
peSigFilePointer = dosHeader.e_lfanew;
|
||||
DWORD peSig = 0;
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peSigFilePointer, (BYTE*)&peSig, 4);
|
||||
if (SUCCEEDED(hr) && peSig != IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
hr = E_FAIL; // PE signature not present
|
||||
}
|
||||
}
|
||||
|
||||
// after the signature is a 20 byte image file header
|
||||
// we need to parse this to figure out the target architecture
|
||||
IMAGE_FILE_HEADER imageFileHeader;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peSigFilePointer + 4, (BYTE*)&imageFileHeader, IMAGE_SIZEOF_FILE_HEADER);
|
||||
}
|
||||
|
||||
|
||||
|
||||
WORD optHeaderMagic = 0;
|
||||
DWORD peOptImageHeaderFilePointer = 0;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if(pwImageFileMachine != NULL)
|
||||
{
|
||||
*pwImageFileMachine = imageFileHeader.Machine;
|
||||
}
|
||||
|
||||
// 4 bytes after the signature is the 20 byte image file header
|
||||
// 24 bytes after the signature is the image-only header
|
||||
// at the beginning of the image-only header is a 2 byte magic number indicating its format
|
||||
peOptImageHeaderFilePointer = peSigFilePointer + IMAGE_SIZEOF_FILE_HEADER + sizeof(DWORD);
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peOptImageHeaderFilePointer, (BYTE*)&optHeaderMagic, 2);
|
||||
}
|
||||
|
||||
// Either 112 or 128 bytes after the beginning of the image-only header is an 8 byte resource table
|
||||
// depending on whether the image is PE32 or PE32+
|
||||
DWORD resourceSectionRVA = 0;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (optHeaderMagic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) // PE32
|
||||
{
|
||||
IMAGE_OPTIONAL_HEADER32 header32;
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peOptImageHeaderFilePointer,
|
||||
(BYTE*)&header32, sizeof(header32));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
resourceSectionRVA = header32.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
|
||||
}
|
||||
}
|
||||
else if (optHeaderMagic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) //PE32+
|
||||
{
|
||||
IMAGE_OPTIONAL_HEADER64 header64;
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peOptImageHeaderFilePointer,
|
||||
(BYTE*)&header64, sizeof(header64));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
resourceSectionRVA = header64.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_FAIL; // Invalid PE
|
||||
}
|
||||
}
|
||||
|
||||
*pdwResourceSectionRVA = resourceSectionRVA;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GetResourceRvaFromResourceSectionRva(ICorDebugDataTarget* pDataTarget,
|
||||
ULONG64 moduleBaseAddress,
|
||||
DWORD resourceSectionRva,
|
||||
DWORD type,
|
||||
DWORD name,
|
||||
DWORD language,
|
||||
DWORD* pResourceRva,
|
||||
DWORD* pResourceSize)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
DWORD nameTableRva = 0;
|
||||
DWORD langTableRva = 0;
|
||||
DWORD resourceDataEntryRva = 0;
|
||||
*pResourceRva = 0;
|
||||
*pResourceSize = 0;
|
||||
|
||||
// The resource section begins with a resource directory that indexes all the resources by type.
|
||||
// Each entry it points to is another resource directory that indexes all the same type
|
||||
// resources by name. And each entry in that table points to another resource directory that indexes
|
||||
// all the same type/name resources by language. Entries in the final table give the RVA of the actual
|
||||
// resource.
|
||||
// Note all RVAs in this section are relative to the beginning of the resource section,
|
||||
// not the beginning of the image.
|
||||
|
||||
hr = GetNextLevelResourceEntryRVA(pDataTarget, type, moduleBaseAddress, resourceSectionRva, &nameTableRva);
|
||||
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
nameTableRva += resourceSectionRva;
|
||||
hr = GetNextLevelResourceEntryRVA(pDataTarget, name, moduleBaseAddress, nameTableRva, &langTableRva);
|
||||
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
langTableRva += resourceSectionRva;
|
||||
hr = GetNextLevelResourceEntryRVA(pDataTarget, language, moduleBaseAddress, langTableRva, &resourceDataEntryRva);
|
||||
}
|
||||
|
||||
// The resource data entry has the first 4 bytes indicating the RVA of the resource
|
||||
// The next 4 bytes indicate the size of the resource
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
resourceDataEntryRva += resourceSectionRva;
|
||||
IMAGE_RESOURCE_DATA_ENTRY dataEntry;
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDataEntryRva,
|
||||
(BYTE*)&dataEntry, sizeof(dataEntry));
|
||||
*pResourceRva = dataEntry.OffsetToData;
|
||||
*pResourceSize = dataEntry.Size;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT GetResourceRvaFromResourceSectionRvaByName(ICorDebugDataTarget* pDataTarget,
|
||||
ULONG64 moduleBaseAddress,
|
||||
DWORD resourceSectionRva,
|
||||
DWORD type,
|
||||
LPCWSTR pwszName,
|
||||
DWORD language,
|
||||
DWORD* pResourceRva,
|
||||
DWORD* pResourceSize)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
DWORD nameTableRva = 0;
|
||||
DWORD langTableRva = 0;
|
||||
DWORD resourceDataEntryRva = 0;
|
||||
*pResourceRva = 0;
|
||||
*pResourceSize = 0;
|
||||
|
||||
// The resource section begins with a resource directory that indexes all the resources by type.
|
||||
// Each entry it points to is another resource directory that indexes all the same type
|
||||
// resources by name. And each entry in that table points to another resource directory that indexes
|
||||
// all the same type/name resources by language. Entries in the final table give the RVA of the actual
|
||||
// resource.
|
||||
// Note all RVAs in this section are relative to the beginning of the resource section,
|
||||
// not the beginning of the image.
|
||||
hr = GetNextLevelResourceEntryRVA(pDataTarget, type, moduleBaseAddress, resourceSectionRva, &nameTableRva);
|
||||
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
nameTableRva += resourceSectionRva;
|
||||
hr = GetNextLevelResourceEntryRVAByName(pDataTarget, pwszName, moduleBaseAddress, nameTableRva, resourceSectionRva, &langTableRva);
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
langTableRva += resourceSectionRva;
|
||||
hr = GetNextLevelResourceEntryRVA(pDataTarget, language, moduleBaseAddress, langTableRva, &resourceDataEntryRva);
|
||||
}
|
||||
|
||||
// The resource data entry has the first 4 bytes indicating the RVA of the resource
|
||||
// The next 4 bytes indicate the size of the resource
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
resourceDataEntryRva += resourceSectionRva;
|
||||
IMAGE_RESOURCE_DATA_ENTRY dataEntry;
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDataEntryRva,
|
||||
(BYTE*)&dataEntry, sizeof(dataEntry));
|
||||
*pResourceRva = dataEntry.OffsetToData;
|
||||
*pResourceSize = dataEntry.Size;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Traverses down one level in the PE resource tree structure
|
||||
//
|
||||
// Arguments:
|
||||
// pDataTarget - the data target for inspecting this process
|
||||
// id - the id of the next node in the resource tree you want
|
||||
// moduleBaseAddress - the base address of the module being inspected
|
||||
// resourceDirectoryRVA - the base address of the beginning of the resource directory for this
|
||||
// level of the tree
|
||||
// pNextLevelRVA - out - The RVA for the next level tree directory or the RVA of the resource entry
|
||||
//
|
||||
// Returns:
|
||||
// S_OK if succesful or an appropriate failing HRESULT
|
||||
HRESULT GetNextLevelResourceEntryRVA(ICorDebugDataTarget* pDataTarget,
|
||||
DWORD id,
|
||||
ULONG64 moduleBaseAddress,
|
||||
DWORD resourceDirectoryRVA,
|
||||
DWORD* pNextLevelRVA)
|
||||
{
|
||||
*pNextLevelRVA = 0;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
// A resource directory which consists of
|
||||
// a header followed by a number of entries. In the header at offset 12 is
|
||||
// the number entries identified by name, followed by the number of entries
|
||||
// identified by ID at offset 14. Both are 2 bytes.
|
||||
// This method only supports locating entries by ID, not by name
|
||||
IMAGE_RESOURCE_DIRECTORY resourceDirectory;
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDirectoryRVA, (BYTE*)&resourceDirectory, sizeof(resourceDirectory));
|
||||
|
||||
|
||||
|
||||
// The ith resource directory entry is at offset 16 + 8i from the beginning of the resource
|
||||
// directory table
|
||||
WORD numNameEntries;
|
||||
WORD numIDEntries;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
numNameEntries = resourceDirectory.NumberOfNamedEntries;
|
||||
numIDEntries = resourceDirectory.NumberOfIdEntries;
|
||||
|
||||
for (WORD i = numNameEntries; i < numNameEntries + numIDEntries; i++)
|
||||
{
|
||||
IMAGE_RESOURCE_DIRECTORY_ENTRY entry;
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDirectoryRVA + sizeof(resourceDirectory) + sizeof(entry)*i,
|
||||
(BYTE*)&entry, sizeof(entry));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (entry.Id == id)
|
||||
{
|
||||
*pNextLevelRVA = entry.OffsetToDirectory;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find the entry
|
||||
if (SUCCEEDED(hr) && *pNextLevelRVA == 0)
|
||||
{
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
return hr; // resource not found
|
||||
}
|
||||
|
||||
// Traverses down one level in the PE resource tree structure
|
||||
//
|
||||
// Arguments:
|
||||
// pDataTarget - the data target for inspecting this process
|
||||
// name - the name of the next node in the resource tree you want
|
||||
// moduleBaseAddress - the base address of the module being inspected
|
||||
// resourceDirectoryRVA - the base address of the beginning of the resource directory for this
|
||||
// level of the tree
|
||||
// resourceSectionRVA - the rva of the beginning of the resource section of the PE file
|
||||
// pNextLevelRVA - out - The RVA for the next level tree directory or the RVA of the resource entry
|
||||
//
|
||||
// Returns:
|
||||
// S_OK if succesful or an appropriate failing HRESULT
|
||||
HRESULT GetNextLevelResourceEntryRVAByName(ICorDebugDataTarget* pDataTarget,
|
||||
LPCWSTR pwzName,
|
||||
ULONG64 moduleBaseAddress,
|
||||
DWORD resourceDirectoryRva,
|
||||
DWORD resourceSectionRva,
|
||||
DWORD* pNextLevelRva)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
DWORD nameLength = (DWORD)wcslen(pwzName);
|
||||
WCHAR entryName[50];
|
||||
assert(nameLength < 50); // this implementation won't support matching a name longer
|
||||
// than 50 characters. We only look up the hard coded name
|
||||
// of the debug resource in clr.dll though, so it shouldn't be
|
||||
// an issue. Increase this count if we ever want to look up
|
||||
// larger names
|
||||
if (nameLength >= 50)
|
||||
{
|
||||
hr = E_FAIL; // invalid name length
|
||||
}
|
||||
|
||||
// A resource directory which consists of
|
||||
// a header followed by a number of entries. In the header at offset 12 is
|
||||
// the number entries identified by name, followed by the number of entries
|
||||
// identified by ID at offset 14. Both are 2 bytes.
|
||||
// This method only supports locating entries by ID, not by name
|
||||
IMAGE_RESOURCE_DIRECTORY resourceDirectory = { 0 };
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDirectoryRva, (BYTE*)&resourceDirectory, sizeof(resourceDirectory));
|
||||
}
|
||||
|
||||
// The ith resource directory entry is at offset 16 + 8i from the beginning of the resource
|
||||
// directory table
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
WORD numNameEntries = resourceDirectory.NumberOfNamedEntries;
|
||||
for (WORD i = 0; i < numNameEntries; i++)
|
||||
{
|
||||
IMAGE_RESOURCE_DIRECTORY_ENTRY entry;
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDirectoryRva + sizeof(resourceDirectory) + sizeof(entry)*i,
|
||||
(BYTE*)&entry, sizeof(entry));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// the NameRVAOrID field points to a UTF16 string with a 2 byte length in front of it
|
||||
// read the 2 byte length first. The doc of course doesn't mention this, but the RVA is
|
||||
// relative to the base of the resource section and needs the leading bit stripped.
|
||||
WORD entryNameLength = 0;
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceSectionRva +
|
||||
entry.NameOffset, (BYTE*)&entryNameLength, sizeof(entryNameLength));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (entryNameLength != nameLength)
|
||||
{
|
||||
continue; // names aren't the same length, not a match
|
||||
}
|
||||
|
||||
// read the rest of the string data and check for a match
|
||||
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceSectionRva +
|
||||
entry.NameOffset + 2, (BYTE*)entryName, entryNameLength*sizeof(WCHAR));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (memcmp(entryName, pwzName, entryNameLength*sizeof(WCHAR)) == 0)
|
||||
{
|
||||
*pNextLevelRva = entry.OffsetToDirectory;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr) && *pNextLevelRva == 0)
|
||||
{
|
||||
hr = E_FAIL; // resource not found
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// A small wrapper that reads from the data target and throws on error
|
||||
HRESULT ReadFromDataTarget(ICorDebugDataTarget* pDataTarget,
|
||||
ULONG64 addr,
|
||||
BYTE* pBuffer,
|
||||
ULONG32 bytesToRead)
|
||||
{
|
||||
//PRECONDITION(CheckPointer(pDataTarget));
|
||||
//PRECONDITION(CheckPointer(pBuffer));
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
ULONG32 bytesReadTotal = 0;
|
||||
ULONG32 bytesRead = 0;
|
||||
do
|
||||
{
|
||||
if (FAILED(pDataTarget->ReadVirtual((CORDB_ADDRESS)(addr + bytesReadTotal),
|
||||
pBuffer,
|
||||
bytesToRead - bytesReadTotal,
|
||||
&bytesRead)))
|
||||
{
|
||||
hr = CORDBG_E_READVIRTUAL_FAILURE;
|
||||
break;
|
||||
}
|
||||
bytesReadTotal += bytesRead;
|
||||
} while (bytesRead != 0 && (bytesReadTotal < bytesToRead));
|
||||
|
||||
// If we can't read all the expected memory, then fail
|
||||
if (SUCCEEDED(hr) && (bytesReadTotal != bytesToRead))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
|
@ -868,8 +868,7 @@ DWORD GetNumComponents(TADDR obj)
|
|||
return Value;
|
||||
}
|
||||
|
||||
BOOL GetSizeEfficient(DWORD_PTR dwAddrCurrObj,
|
||||
DWORD_PTR dwAddrMethTable, BOOL bLarge, size_t& s, BOOL& bContainsPointers)
|
||||
static MethodTableInfo* GetMethodTableInfo(DWORD_PTR dwAddrMethTable)
|
||||
{
|
||||
// Remove lower bits in case we are in mark phase
|
||||
dwAddrMethTable = dwAddrMethTable & ~3;
|
||||
|
@ -880,12 +879,34 @@ BOOL GetSizeEfficient(DWORD_PTR dwAddrCurrObj,
|
|||
// from the target
|
||||
DacpMethodTableData dmtd;
|
||||
// see code:ClrDataAccess::RequestMethodTableData for details
|
||||
if (dmtd.Request(g_sos,dwAddrMethTable) != S_OK)
|
||||
return FALSE;
|
||||
if (dmtd.Request(g_sos, dwAddrMethTable) != S_OK)
|
||||
return NULL;
|
||||
|
||||
|
||||
info->BaseSize = dmtd.BaseSize;
|
||||
info->ComponentSize = dmtd.ComponentSize;
|
||||
info->bContainsPointers = dmtd.bContainsPointers;
|
||||
|
||||
// The following request doesn't work on older runtimes. For those, the
|
||||
// objects would just look like non-collectible, which is acceptable.
|
||||
DacpMethodTableCollectibleData dmtcd;
|
||||
if (SUCCEEDED(dmtcd.Request(g_sos, dwAddrMethTable)))
|
||||
{
|
||||
info->bCollectible = dmtcd.bCollectible;
|
||||
info->LoaderAllocatorObjectHandle = TO_TADDR(dmtcd.LoaderAllocatorObjectHandle);
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
BOOL GetSizeEfficient(DWORD_PTR dwAddrCurrObj,
|
||||
DWORD_PTR dwAddrMethTable, BOOL bLarge, size_t& s, BOOL& bContainsPointers)
|
||||
{
|
||||
MethodTableInfo* info = GetMethodTableInfo(dwAddrMethTable);
|
||||
if (info == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bContainsPointers = info->bContainsPointers;
|
||||
|
@ -911,6 +932,20 @@ BOOL GetSizeEfficient(DWORD_PTR dwAddrCurrObj,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL GetCollectibleDataEfficient(DWORD_PTR dwAddrMethTable, BOOL& bCollectible, TADDR& loaderAllocatorObjectHandle)
|
||||
{
|
||||
MethodTableInfo* info = GetMethodTableInfo(dwAddrMethTable);
|
||||
if (info == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bCollectible = info->bCollectible;
|
||||
loaderAllocatorObjectHandle = info->LoaderAllocatorObjectHandle;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// This function expects stat to be valid, and ready to get statistics.
|
||||
void GatherOneHeapFinalization(DacpGcHeapDetails& heapDetails, HeapStat *stat, BOOL bAllReady, BOOL bShort)
|
||||
{
|
||||
|
|
|
@ -1009,7 +1009,7 @@ GCRootImpl::RootNode *GCRootImpl::GetGCRefs(RootNode *path, RootNode *node)
|
|||
|
||||
// Only calculate the size if we need it.
|
||||
size_t objSize = 0;
|
||||
if (mSize || node->MTInfo->ContainsPointers)
|
||||
if (mSize || node->MTInfo->ContainsPointers || node->MTInfo->Collectible)
|
||||
{
|
||||
objSize = GetSizeOfObject(obj, node->MTInfo);
|
||||
|
||||
|
@ -1027,7 +1027,7 @@ GCRootImpl::RootNode *GCRootImpl::GetGCRefs(RootNode *path, RootNode *node)
|
|||
}
|
||||
|
||||
// Early out: If the object doesn't contain any pointers, return.
|
||||
if (!node->MTInfo->ContainsPointers)
|
||||
if (!node->MTInfo->ContainsPointers && !node->MTInfo->Collectible)
|
||||
return NULL;
|
||||
|
||||
// Make sure we have the object's data in the cache.
|
||||
|
@ -1139,6 +1139,15 @@ GCRootImpl::MTInfo *GCRootImpl::GetMTInfo(TADDR mt)
|
|||
curr->ComponentSize = (size_t)dmtd.ComponentSize;
|
||||
curr->ContainsPointers = dmtd.bContainsPointers ? true : false;
|
||||
|
||||
// The following request doesn't work on older runtimes. For those, the
|
||||
// objects would just look like non-collectible, which is acceptable.
|
||||
DacpMethodTableCollectibleData dmtcd;
|
||||
if (SUCCEEDED(dmtcd.Request(g_sos, mt)))
|
||||
{
|
||||
curr->Collectible = dmtcd.bCollectible ? true : false;
|
||||
curr->LoaderAllocatorObjectHandle = TO_TADDR(dmtcd.LoaderAllocatorObjectHandle);
|
||||
}
|
||||
|
||||
// If this method table contains pointers, fill out and cache the GCDesc.
|
||||
if (curr->ContainsPointers)
|
||||
{
|
||||
|
@ -1963,6 +1972,22 @@ void HeapTraverser::PrintObjectHead(size_t objAddr,size_t typeID,size_t Size)
|
|||
}
|
||||
}
|
||||
|
||||
void HeapTraverser::PrintLoaderAllocator(size_t memberValue)
|
||||
{
|
||||
if (m_format == FORMAT_XML)
|
||||
{
|
||||
fprintf(m_file,
|
||||
" <loaderallocator address=\"0x%p\"/>\n",
|
||||
(PBYTE)memberValue);
|
||||
}
|
||||
else if (m_format == FORMAT_CLRPROFILER)
|
||||
{
|
||||
fprintf(m_file,
|
||||
" 0x%p",
|
||||
(PBYTE)memberValue);
|
||||
}
|
||||
}
|
||||
|
||||
void HeapTraverser::PrintObjectMember(size_t memberValue, bool dependentHandle)
|
||||
{
|
||||
if (m_format==FORMAT_XML)
|
||||
|
@ -2163,43 +2188,55 @@ void HeapTraverser::PrintRefs(size_t obj, size_t methodTable, size_t size)
|
|||
MethodTableInfo* info = g_special_mtCache.Lookup((DWORD_PTR)methodTable);
|
||||
_ASSERTE(info->IsInitialized()); // This is the second pass, so we should be initialized
|
||||
|
||||
if (!info->bContainsPointers)
|
||||
if (!info->bContainsPointers && !info->bCollectible)
|
||||
return;
|
||||
|
||||
// Fetch the GCInfo from the other process
|
||||
CGCDesc *map = info->GCInfo;
|
||||
if (map == NULL)
|
||||
if (info->bContainsPointers)
|
||||
{
|
||||
INT_PTR nEntries;
|
||||
move_xp (nEntries, dwAddr-sizeof(PVOID));
|
||||
bool arrayOfVC = false;
|
||||
if (nEntries<0)
|
||||
// Fetch the GCInfo from the other process
|
||||
CGCDesc *map = info->GCInfo;
|
||||
if (map == NULL)
|
||||
{
|
||||
arrayOfVC = true;
|
||||
nEntries = -nEntries;
|
||||
}
|
||||
INT_PTR nEntries;
|
||||
move_xp (nEntries, dwAddr-sizeof(PVOID));
|
||||
bool arrayOfVC = false;
|
||||
if (nEntries<0)
|
||||
{
|
||||
arrayOfVC = true;
|
||||
nEntries = -nEntries;
|
||||
}
|
||||
|
||||
size_t nSlots = 1+nEntries*sizeof(CGCDescSeries)/sizeof(DWORD_PTR);
|
||||
info->GCInfoBuffer = new DWORD_PTR[nSlots];
|
||||
if (info->GCInfoBuffer == NULL)
|
||||
{
|
||||
ReportOOM();
|
||||
return;
|
||||
}
|
||||
size_t nSlots = 1+nEntries*sizeof(CGCDescSeries)/sizeof(DWORD_PTR);
|
||||
info->GCInfoBuffer = new DWORD_PTR[nSlots];
|
||||
if (info->GCInfoBuffer == NULL)
|
||||
{
|
||||
ReportOOM();
|
||||
return;
|
||||
}
|
||||
|
||||
if (FAILED(rvCache->Read(TO_CDADDR(dwAddr - nSlots*sizeof(DWORD_PTR)),
|
||||
info->GCInfoBuffer, (ULONG) (nSlots*sizeof(DWORD_PTR)), NULL)))
|
||||
return;
|
||||
if (FAILED(rvCache->Read(TO_CDADDR(dwAddr - nSlots*sizeof(DWORD_PTR)),
|
||||
info->GCInfoBuffer, (ULONG) (nSlots*sizeof(DWORD_PTR)), NULL)))
|
||||
return;
|
||||
|
||||
map = info->GCInfo = (CGCDesc*)(info->GCInfoBuffer+nSlots);
|
||||
info->ArrayOfVC = arrayOfVC;
|
||||
map = info->GCInfo = (CGCDesc*)(info->GCInfoBuffer+nSlots);
|
||||
info->ArrayOfVC = arrayOfVC;
|
||||
}
|
||||
}
|
||||
|
||||
mCache.EnsureRangeInCache((TADDR)obj, (unsigned int)size);
|
||||
for (sos::RefIterator itr(obj, info->GCInfo, info->ArrayOfVC, &mCache); itr; ++itr)
|
||||
{
|
||||
if (*itr && (!m_verify || sos::IsObject(*itr)))
|
||||
PrintObjectMember(*itr, false);
|
||||
{
|
||||
if (itr.IsLoaderAllocator())
|
||||
{
|
||||
PrintLoaderAllocator(*itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintObjectMember(*itr, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<TADDR, std::list<TADDR>>::iterator itr = mDependentHandleMap.find((TADDR)obj);
|
||||
|
@ -2212,7 +2249,6 @@ void HeapTraverser::PrintRefs(size_t obj, size_t methodTable, size_t size)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void sos::ObjectIterator::BuildError(char *out, size_t count, const char *format, ...) const
|
||||
{
|
||||
if (out == NULL || count == 0)
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
// ==--==
|
||||
#include "strike.h"
|
||||
#include "util.h"
|
||||
//#include "genericstackprobe.h"
|
||||
|
||||
/**********************************************************************\
|
||||
* Routine Description: *
|
||||
|
|
|
@ -180,6 +180,15 @@ namespace sos
|
|||
info->BaseSize = mMTData->BaseSize;
|
||||
info->ComponentSize = mMTData->ComponentSize;
|
||||
info->bContainsPointers = mMTData->bContainsPointers;
|
||||
|
||||
// The following request doesn't work on older runtimes. For those, the
|
||||
// objects would just look like non-collectible, which is acceptable.
|
||||
DacpMethodTableCollectibleData mtcd;
|
||||
if (SUCCEEDED(mtcd.Request(g_sos, GetMT())))
|
||||
{
|
||||
info->bCollectible = mtcd.bCollectible;
|
||||
info->LoaderAllocatorObjectHandle = TO_TADDR(mtcd.LoaderAllocatorObjectHandle);
|
||||
}
|
||||
}
|
||||
|
||||
if (mSize == (size_t)~0)
|
||||
|
@ -380,14 +389,14 @@ namespace sos
|
|||
|
||||
|
||||
RefIterator::RefIterator(TADDR obj, LinearReadCache *cache)
|
||||
: mCache(cache), mGCDesc(0), mArrayOfVC(false), mDone(false), mBuffer(0), mCurrSeries(0),
|
||||
: mCache(cache), mGCDesc(0), mArrayOfVC(false), mDone(false), mBuffer(0), mCurrSeries(0), mLoaderAllocatorObjectHandle(0),
|
||||
i(0), mCount(0), mCurr(0), mStop(0), mObject(obj), mObjSize(0)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
RefIterator::RefIterator(TADDR obj, CGCDesc *desc, bool arrayOfVC, LinearReadCache *cache)
|
||||
: mCache(cache), mGCDesc(desc), mArrayOfVC(arrayOfVC), mDone(false), mBuffer(0), mCurrSeries(0),
|
||||
: mCache(cache), mGCDesc(desc), mArrayOfVC(arrayOfVC), mDone(false), mBuffer(0), mCurrSeries(0), mLoaderAllocatorObjectHandle(0),
|
||||
i(0), mCount(0), mCurr(0), mStop(0), mObject(obj), mObjSize(0)
|
||||
{
|
||||
Init();
|
||||
|
@ -403,6 +412,13 @@ namespace sos
|
|||
{
|
||||
if (mDone)
|
||||
Throw<Exception>("Attempt to move past the end of the iterator.");
|
||||
|
||||
if (mCurr == mLoaderAllocatorObjectHandle)
|
||||
{
|
||||
// The mLoaderAllocatorObjectHandle is always the last reference returned
|
||||
mDone = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (!mArrayOfVC)
|
||||
{
|
||||
|
@ -440,6 +456,14 @@ namespace sos
|
|||
mDone = true;
|
||||
}
|
||||
|
||||
if (mDone && mLoaderAllocatorObjectHandle != NULL)
|
||||
{
|
||||
// The iteration over all regular object references is done, but there is one more
|
||||
// reference for collectible types - the LoaderAllocator for GC
|
||||
mCurr = mLoaderAllocatorObjectHandle;
|
||||
mDone = false;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -457,68 +481,90 @@ namespace sos
|
|||
{
|
||||
TADDR mt = ReadPointer(mObject);
|
||||
BOOL bContainsPointers = FALSE;
|
||||
|
||||
BOOL bCollectible = FALSE;
|
||||
TADDR loaderAllocatorObjectHandle;
|
||||
|
||||
if (!GetSizeEfficient(mObject, mt, FALSE, mObjSize, bContainsPointers))
|
||||
Throw<DataRead>("Failed to get size of object.");
|
||||
|
||||
if (!bContainsPointers)
|
||||
|
||||
if (!GetCollectibleDataEfficient(mt, bCollectible, loaderAllocatorObjectHandle))
|
||||
Throw<DataRead>("Failed to get collectible info of object.");
|
||||
|
||||
if (!bContainsPointers && !bCollectible)
|
||||
{
|
||||
mDone = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mGCDesc)
|
||||
|
||||
if (bContainsPointers)
|
||||
{
|
||||
int entries = 0;
|
||||
|
||||
if (FAILED(MOVE(entries, mt - sizeof(TADDR))))
|
||||
if (!mGCDesc)
|
||||
{
|
||||
Throw<DataRead>("Failed to request number of entries.");
|
||||
int entries = 0;
|
||||
|
||||
if (FAILED(MOVE(entries, mt-sizeof(TADDR))))
|
||||
Throw<DataRead>("Failed to request number of entries.");
|
||||
|
||||
// array of vc?
|
||||
if (entries < 0)
|
||||
{
|
||||
entries = -entries;
|
||||
mArrayOfVC = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mArrayOfVC = false;
|
||||
}
|
||||
|
||||
size_t slots = 1 + entries * sizeof(CGCDescSeries)/sizeof(TADDR);
|
||||
|
||||
ArrayHolder<TADDR> buffer = new TADDR[slots];
|
||||
|
||||
ULONG fetched = 0;
|
||||
CLRDATA_ADDRESS address = TO_CDADDR(mt - slots*sizeof(TADDR));
|
||||
if (FAILED(g_ExtData->ReadVirtual(address, buffer, (ULONG)(slots*sizeof(TADDR)), &fetched)))
|
||||
Throw<DataRead>("Failed to request GCDesc.");
|
||||
|
||||
mBuffer = buffer.Detach();
|
||||
mGCDesc = (CGCDesc*)(mBuffer + slots);
|
||||
}
|
||||
|
||||
// array of vc?
|
||||
if (entries < 0)
|
||||
|
||||
mCurrSeries = mGCDesc->GetHighestSeries();
|
||||
|
||||
if (!mArrayOfVC)
|
||||
{
|
||||
entries = -entries;
|
||||
mArrayOfVC = true;
|
||||
mCurr = mObject + mCurrSeries->GetSeriesOffset();
|
||||
mStop = mCurr + mCurrSeries->GetSeriesSize() + mObjSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
mArrayOfVC = false;
|
||||
i = 0;
|
||||
mCurr = mObject + mCurrSeries->startoffset;
|
||||
mStop = mCurr + mCurrSeries->val_serie[i].nptrs * sizeof(TADDR);
|
||||
mCount = (int)mGCDesc->GetNumSeries();
|
||||
}
|
||||
|
||||
size_t slots = 1 + entries * sizeof(CGCDescSeries)/sizeof(TADDR);
|
||||
|
||||
ArrayHolder<TADDR> buffer = new TADDR[slots];
|
||||
|
||||
ULONG fetched = 0;
|
||||
CLRDATA_ADDRESS address = TO_CDADDR(mt - slots*sizeof(TADDR));
|
||||
if (FAILED(g_ExtData->ReadVirtual(address, buffer, (ULONG)(slots*sizeof(TADDR)), &fetched)))
|
||||
Throw<DataRead>("Failed to request GCDesc.");
|
||||
|
||||
mBuffer = buffer.Detach();
|
||||
mGCDesc = (CGCDesc*)(mBuffer + slots);
|
||||
}
|
||||
|
||||
mCurrSeries = mGCDesc->GetHighestSeries();
|
||||
|
||||
if (!mArrayOfVC)
|
||||
{
|
||||
mCurr = mObject + mCurrSeries->GetSeriesOffset();
|
||||
mStop = mCurr + mCurrSeries->GetSeriesSize() + mObjSize;
|
||||
|
||||
if (mCurr == mStop)
|
||||
operator++();
|
||||
else if (mCurr >= mObject + mObjSize - plug_skew)
|
||||
mDone = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
mCurr = mObject + mCurrSeries->startoffset;
|
||||
mStop = mCurr + mCurrSeries->val_serie[i].nptrs * sizeof(TADDR);
|
||||
mCount = (int)mGCDesc->GetNumSeries();
|
||||
mDone = true;
|
||||
}
|
||||
|
||||
if (bCollectible)
|
||||
{
|
||||
mLoaderAllocatorObjectHandle = loaderAllocatorObjectHandle;
|
||||
if (mDone)
|
||||
{
|
||||
// There are no object references, but there is still a reference for
|
||||
// collectible types - the LoaderAllocator for GC
|
||||
mCurr = mLoaderAllocatorObjectHandle;
|
||||
mDone = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mCurr == mStop)
|
||||
operator++();
|
||||
else if (mCurr >= mObject + mObjSize - plug_skew)
|
||||
mDone = true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -475,6 +475,11 @@ namespace sos
|
|||
{
|
||||
return (void*)!mDone;
|
||||
}
|
||||
|
||||
bool IsLoaderAllocator() const
|
||||
{
|
||||
return mLoaderAllocatorObjectHandle == mCurr;
|
||||
}
|
||||
|
||||
private:
|
||||
void Init();
|
||||
|
@ -501,6 +506,8 @@ namespace sos
|
|||
TADDR *mBuffer;
|
||||
CGCDescSeries *mCurrSeries;
|
||||
|
||||
TADDR mLoaderAllocatorObjectHandle;
|
||||
|
||||
int i, mCount;
|
||||
|
||||
TADDR mCurr, mStop, mObject;
|
||||
|
|
|
@ -1248,14 +1248,6 @@ DECLARE_API(DumpClass)
|
|||
ExtOut("NumThreadStaticFields: %x\n", vMethodTableFields.wNumThreadStaticFields);
|
||||
}
|
||||
|
||||
|
||||
if (vMethodTableFields.wContextStaticsSize)
|
||||
{
|
||||
ExtOut("ContextStaticOffset: %x\n", vMethodTableFields.wContextStaticOffset);
|
||||
ExtOut("ContextStaticsSize: %x\n", vMethodTableFields.wContextStaticsSize);
|
||||
}
|
||||
|
||||
|
||||
if (vMethodTableFields.wNumInstanceFields + vMethodTableFields.wNumStaticFields > 0)
|
||||
{
|
||||
DisplayFields(methodTable, &mtdata, &vMethodTableFields, NULL, TRUE, FALSE);
|
||||
|
@ -1328,6 +1320,9 @@ DECLARE_API(DumpMT)
|
|||
return Status;
|
||||
}
|
||||
|
||||
DacpMethodTableCollectibleData vMethTableCollectible;
|
||||
vMethTableCollectible.Request(g_sos, TO_CDADDR(dwStartAddr));
|
||||
|
||||
table.WriteRow("EEClass:", EEClassPtr(vMethTable.Class));
|
||||
|
||||
table.WriteRow("Module:", ModulePtr(vMethTable.Module));
|
||||
|
@ -1340,6 +1335,15 @@ DECLARE_API(DumpMT)
|
|||
table.WriteRow("mdToken:", Pointer(vMethTable.cl));
|
||||
table.WriteRow("File:", fileName[0] ? fileName : W("Unknown Module"));
|
||||
|
||||
if (vMethTableCollectible.LoaderAllocatorObjectHandle != NULL)
|
||||
{
|
||||
TADDR loaderAllocator;
|
||||
if (SUCCEEDED(MOVE(loaderAllocator, vMethTableCollectible.LoaderAllocatorObjectHandle)))
|
||||
{
|
||||
table.WriteRow("LoaderAllocator:", ObjectPtr(loaderAllocator));
|
||||
}
|
||||
}
|
||||
|
||||
table.WriteRow("BaseSize:", PrefixHex(vMethTable.BaseSize));
|
||||
table.WriteRow("ComponentSize:", PrefixHex(vMethTable.ComponentSize));
|
||||
table.WriteRow("Slots in VTable:", Decimal(vMethTable.wNumMethods));
|
||||
|
|
|
@ -1142,61 +1142,6 @@ void DisplayThreadStatic (DacpModuleData* pModule, DacpMethodTableData* pMT, Dac
|
|||
ExtOut(" <<\n");
|
||||
}
|
||||
|
||||
void DisplayContextStatic (DacpFieldDescData *pFD, size_t offset, BOOL fIsShared)
|
||||
{
|
||||
ExtOut("\nDisplay of context static variables is not implemented yet\n");
|
||||
/*
|
||||
int numDomain;
|
||||
DWORD_PTR *domainList = NULL;
|
||||
GetDomainList (domainList, numDomain);
|
||||
ToDestroy des0 ((void**)&domainList);
|
||||
AppDomain vAppDomain;
|
||||
Context vContext;
|
||||
|
||||
ExtOut(" >> Domain:Value");
|
||||
for (int i = 0; i < numDomain; i ++)
|
||||
{
|
||||
DWORD_PTR dwAddr = domainList[i];
|
||||
if (dwAddr == 0) {
|
||||
continue;
|
||||
}
|
||||
vAppDomain.Fill (dwAddr);
|
||||
if (vAppDomain.m_pDefaultContext == 0)
|
||||
continue;
|
||||
dwAddr = (DWORD_PTR)vAppDomain.m_pDefaultContext;
|
||||
vContext.Fill (dwAddr);
|
||||
|
||||
if (fIsShared)
|
||||
dwAddr = (DWORD_PTR)vContext.m_pSharedStaticData;
|
||||
else
|
||||
dwAddr = (DWORD_PTR)vContext.m_pUnsharedStaticData;
|
||||
if (dwAddr == 0)
|
||||
continue;
|
||||
dwAddr += offsetof(STATIC_DATA, dataPtr);
|
||||
dwAddr += offset;
|
||||
if (safemove (dwAddr, dwAddr) == 0)
|
||||
continue;
|
||||
if (dwAddr == 0)
|
||||
// We have not initialized this yet.
|
||||
continue;
|
||||
|
||||
dwAddr += pFD->dwOffset;
|
||||
if (pFD->Type == ELEMENT_TYPE_CLASS
|
||||
|| pFD->Type == ELEMENT_TYPE_VALUETYPE)
|
||||
{
|
||||
if (safemove (dwAddr, dwAddr) == 0)
|
||||
continue;
|
||||
}
|
||||
if (dwAddr == 0)
|
||||
// We have not initialized this yet.
|
||||
continue;
|
||||
ExtOut(" %p:", (ULONG64)domainList[i]);
|
||||
DisplayDataMember (pFD, dwAddr, FALSE);
|
||||
}
|
||||
ExtOut(" <<\n");
|
||||
*/
|
||||
}
|
||||
|
||||
const char * ElementTypeName(unsigned type)
|
||||
{
|
||||
switch (type) {
|
||||
|
@ -1347,7 +1292,7 @@ void DisplayFields(CLRDATA_ADDRESS cdaMT, DacpMethodTableData *pMTD, DacpMethodT
|
|||
dwAddr = vFieldDesc.NextField;
|
||||
|
||||
DWORD offset = vFieldDesc.dwOffset;
|
||||
if(!((vFieldDesc.bIsThreadLocal || vFieldDesc.bIsContextLocal || fIsShared) && vFieldDesc.bIsStatic))
|
||||
if(!((vFieldDesc.bIsThreadLocal || fIsShared) && vFieldDesc.bIsStatic))
|
||||
{
|
||||
if (!bValueClass)
|
||||
{
|
||||
|
@ -1386,7 +1331,7 @@ void DisplayFields(CLRDATA_ADDRESS cdaMT, DacpMethodTableData *pMTD, DacpMethodT
|
|||
|
||||
ExtOut("%2s ", (IsElementValueType(vFieldDesc.Type)) ? "1" : "0");
|
||||
|
||||
if (vFieldDesc.bIsStatic && (vFieldDesc.bIsThreadLocal || vFieldDesc.bIsContextLocal))
|
||||
if (vFieldDesc.bIsStatic && vFieldDesc.bIsThreadLocal)
|
||||
{
|
||||
numStaticFields ++;
|
||||
if (fIsShared)
|
||||
|
@ -1411,12 +1356,6 @@ void DisplayFields(CLRDATA_ADDRESS cdaMT, DacpMethodTableData *pMTD, DacpMethodT
|
|||
DisplayThreadStatic(&vModule, pMTD, &vFieldDesc, fIsShared);
|
||||
}
|
||||
}
|
||||
else if (vFieldDesc.bIsContextLocal)
|
||||
{
|
||||
DisplayContextStatic(&vFieldDesc,
|
||||
pMTFD->wContextStaticOffset,
|
||||
fIsShared);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1557,6 +1496,10 @@ int GetObjFieldOffset(CLRDATA_ADDRESS cdaObj, CLRDATA_ADDRESS cdaMT, __in_z LPCW
|
|||
NameForToken_s (TokenFromRid(vFieldDesc.mb, mdtFieldDef), pImport, g_mdName, mdNameLen, false);
|
||||
if (_wcscmp (wszFieldName, g_mdName) == 0)
|
||||
{
|
||||
if (pDacpFieldDescData != NULL)
|
||||
{
|
||||
*pDacpFieldDescData = vFieldDesc;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
numInstanceFields ++;
|
||||
|
|
|
@ -1660,9 +1660,11 @@ struct MethodTableInfo
|
|||
DWORD BaseSize; // Caching BaseSize and ComponentSize for a MethodTable
|
||||
DWORD ComponentSize; // here has HUGE perf benefits in heap traversals.
|
||||
BOOL bContainsPointers;
|
||||
BOOL bCollectible;
|
||||
DWORD_PTR* GCInfoBuffer; // Start of memory of GC info
|
||||
CGCDesc* GCInfo; // Just past GC info (which is how it is stored)
|
||||
bool ArrayOfVC;
|
||||
TADDR LoaderAllocatorObjectHandle;
|
||||
};
|
||||
|
||||
class MethodTableCache
|
||||
|
@ -1680,9 +1682,11 @@ protected:
|
|||
info.BaseSize = 0;
|
||||
info.ComponentSize = 0;
|
||||
info.bContainsPointers = false;
|
||||
info.bCollectible = false;
|
||||
info.GCInfo = NULL;
|
||||
info.ArrayOfVC = false;
|
||||
info.GCInfoBuffer = NULL;
|
||||
info.LoaderAllocatorObjectHandle = NULL;
|
||||
}
|
||||
};
|
||||
Node *head;
|
||||
|
@ -1948,6 +1952,8 @@ size_t NextOSPageAddress (size_t addr);
|
|||
BOOL GetSizeEfficient(DWORD_PTR dwAddrCurrObj,
|
||||
DWORD_PTR dwAddrMethTable, BOOL bLarge, size_t& s, BOOL& bContainsPointers);
|
||||
|
||||
BOOL GetCollectibleDataEfficient(DWORD_PTR dwAddrMethTable, BOOL& bCollectible, TADDR& loaderAllocatorObjectHandle);
|
||||
|
||||
// ObjSize now uses the methodtable cache for its work too.
|
||||
size_t ObjectSize (DWORD_PTR obj, BOOL fIsLargeObject=FALSE);
|
||||
size_t ObjectSize(DWORD_PTR obj, DWORD_PTR mt, BOOL fIsValueClass, BOOL fIsLargeObject=FALSE);
|
||||
|
@ -2824,6 +2830,7 @@ private:
|
|||
|
||||
void PrintObjectHead(size_t objAddr,size_t typeID,size_t Size);
|
||||
void PrintObjectMember(size_t memberValue, bool dependentHandle);
|
||||
void PrintLoaderAllocator(size_t memberValue);
|
||||
void PrintObjectTail();
|
||||
|
||||
void PrintRootHead();
|
||||
|
@ -2855,8 +2862,10 @@ private:
|
|||
TADDR *Buffer;
|
||||
CGCDesc *GCDesc;
|
||||
|
||||
TADDR LoaderAllocatorObjectHandle;
|
||||
bool ArrayOfVC;
|
||||
bool ContainsPointers;
|
||||
bool Collectible;
|
||||
size_t BaseSize;
|
||||
size_t ComponentSize;
|
||||
|
||||
|
@ -2873,7 +2882,7 @@ private:
|
|||
|
||||
MTInfo()
|
||||
: MethodTable(0), TypeName(0), Buffer(0), GCDesc(0),
|
||||
ArrayOfVC(false), ContainsPointers(false), BaseSize(0), ComponentSize(0)
|
||||
ArrayOfVC(false), ContainsPointers(false), Collectible(false), BaseSize(0), ComponentSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,6 @@ cpp_quote("EXTERN_GUID(IID_ITypeNameFactory, 0xB81FF171, 0x20F3, 0x11d2, 0x8d, 0
|
|||
#pragma midl_echo("DEPRECATED_CLR_STDAPI CorBindToRuntime(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv);")
|
||||
#pragma midl_echo("DEPRECATED_CLR_STDAPI CorBindToCurrentRuntime(LPCWSTR pwszFileName, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv);")
|
||||
#pragma midl_echo("DEPRECATED_CLR_STDAPI ClrCreateManagedInstance(LPCWSTR pTypeName, REFIID riid, void **ppObject);")
|
||||
#pragma midl_echo("DECLARE_DEPRECATED void STDMETHODCALLTYPE CorMarkThreadInThreadPool();")
|
||||
#pragma midl_echo("DEPRECATED_CLR_STDAPI RunDll32ShimW(HWND hwnd, HINSTANCE hinst, LPCWSTR lpszCmdLine, int nCmdShow);")
|
||||
#pragma midl_echo("DEPRECATED_CLR_STDAPI LoadLibraryShim(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll);")
|
||||
#pragma midl_echo("DEPRECATED_CLR_STDAPI CallFunctionShim(LPCWSTR szDllName, LPCSTR szFunctionName, LPVOID lpvArgument1, LPVOID lpvArgument2, LPCWSTR szVersion, LPVOID pvReserved);")
|
||||
|
|
|
@ -146,6 +146,14 @@ public:
|
|||
return (*this);
|
||||
}
|
||||
|
||||
basic_string<T>& operator+=(value_type _Ch)
|
||||
{
|
||||
size_type oldsize = size(); // doesn't include null terminator
|
||||
m_string[oldsize] = _Ch; // Replace the null terminator with the new symbol.
|
||||
m_string.push_back(T()); // Return the replaced terminator again.
|
||||
return (*this);
|
||||
}
|
||||
|
||||
~basic_string()
|
||||
{
|
||||
// vector destructor does all the work
|
||||
|
@ -157,6 +165,11 @@ public:
|
|||
return m_string.size() - 1; // Don't report the null terminator.
|
||||
}
|
||||
|
||||
size_t length() const
|
||||
{
|
||||
return size();
|
||||
}
|
||||
|
||||
T& operator[](size_t iIndex)
|
||||
{
|
||||
assert(iIndex < size() + 1); // allow looking at the null terminator
|
||||
|
|
|
@ -91,6 +91,16 @@ interface ICLRPrivBinder : IUnknown
|
|||
[in] LPVOID pvAssemblySpec,
|
||||
[out] HRESULT * pResult,
|
||||
[out] ICLRPrivAssembly ** ppAssembly);
|
||||
|
||||
/**********************************************************************************
|
||||
** GetLoaderAllocator
|
||||
** Get LoaderAllocator for binders that contain it. For other binders, return
|
||||
** E_FAIL
|
||||
**
|
||||
** pLoaderAllocator - when successful, constains the returned LoaderAllocator
|
||||
**********************************************************************************/
|
||||
HRESULT GetLoaderAllocator(
|
||||
[out, retval] LPVOID * pLoaderAllocator);
|
||||
};
|
||||
|
||||
enum CLR_PRIV_BINDER_FLAGS
|
||||
|
|
|
@ -3701,6 +3701,38 @@ interface ICorDebugRegisterSet : IUnknown
|
|||
REGISTER_ARM_R11,
|
||||
REGISTER_ARM_R12,
|
||||
REGISTER_ARM_LR,
|
||||
REGISTER_ARM_D0,
|
||||
REGISTER_ARM_D1,
|
||||
REGISTER_ARM_D2,
|
||||
REGISTER_ARM_D3,
|
||||
REGISTER_ARM_D4,
|
||||
REGISTER_ARM_D5,
|
||||
REGISTER_ARM_D6,
|
||||
REGISTER_ARM_D7,
|
||||
REGISTER_ARM_D8,
|
||||
REGISTER_ARM_D9,
|
||||
REGISTER_ARM_D10,
|
||||
REGISTER_ARM_D11,
|
||||
REGISTER_ARM_D12,
|
||||
REGISTER_ARM_D13,
|
||||
REGISTER_ARM_D14,
|
||||
REGISTER_ARM_D15,
|
||||
REGISTER_ARM_D16,
|
||||
REGISTER_ARM_D17,
|
||||
REGISTER_ARM_D18,
|
||||
REGISTER_ARM_D19,
|
||||
REGISTER_ARM_D20,
|
||||
REGISTER_ARM_D21,
|
||||
REGISTER_ARM_D22,
|
||||
REGISTER_ARM_D23,
|
||||
REGISTER_ARM_D24,
|
||||
REGISTER_ARM_D25,
|
||||
REGISTER_ARM_D26,
|
||||
REGISTER_ARM_D27,
|
||||
REGISTER_ARM_D28,
|
||||
REGISTER_ARM_D29,
|
||||
REGISTER_ARM_D30,
|
||||
REGISTER_ARM_D31,
|
||||
|
||||
// ARM64 registers
|
||||
|
||||
|
|
|
@ -198,8 +198,8 @@ typedef enum ReplacesCorHdrNumericDefines
|
|||
// The most important of these is the MetaData tables. The easiest way of looking at meta-data is using
|
||||
// the IlDasm.exe tool.
|
||||
//
|
||||
// MetaData holds most of the information in the IL image. THe exceptions are resource blobs and the IL
|
||||
// instructions streams for individual methods. Intstead the Meta-data for a method holds an RVA to a
|
||||
// MetaData holds most of the information in the IL image. The exceptions are resource blobs and the IL
|
||||
// instructions streams for individual methods. Instead the Meta-data for a method holds an RVA to a
|
||||
// code:IMAGE_COR_ILMETHOD which holds all the IL stream (and exception handling information).
|
||||
//
|
||||
// Precompiled (NGEN) images use the same IMAGE_COR20_HEADER but also use the ManagedNativeHeader field to
|
||||
|
@ -644,6 +644,7 @@ typedef enum CorMethodImpl
|
|||
miNoInlining = 0x0008, // Method may not be inlined.
|
||||
miAggressiveInlining = 0x0100, // Method should be inlined if possible.
|
||||
miNoOptimization = 0x0040, // Method may not be optimized.
|
||||
miAggressiveOptimization = 0x0200, // Method may contain hot code and should be aggressively optimized.
|
||||
|
||||
// These are the flags that are allowed in MethodImplAttribute's Value
|
||||
// property. This should include everything above except the code impl
|
||||
|
@ -651,7 +652,7 @@ typedef enum CorMethodImpl
|
|||
miUserMask = miManagedMask | miForwardRef | miPreserveSig |
|
||||
miInternalCall | miSynchronized |
|
||||
miNoInlining | miAggressiveInlining |
|
||||
miNoOptimization,
|
||||
miNoOptimization | miAggressiveOptimization,
|
||||
|
||||
miMaxMethodImplVal = 0xffff, // Range check value
|
||||
} CorMethodImpl;
|
||||
|
@ -674,6 +675,7 @@ typedef enum CorMethodImpl
|
|||
#define IsMiNoInlining(x) ((x) & miNoInlining)
|
||||
#define IsMiAggressiveInlining(x) ((x) & miAggressiveInlining)
|
||||
#define IsMiNoOptimization(x) ((x) & miNoOptimization)
|
||||
#define IsMiAggressiveOptimization(x) (((x) & (miAggressiveOptimization | miNoOptimization)) == miAggressiveOptimization)
|
||||
|
||||
// PinvokeMap attr bits, used by DefinePinvokeMap.
|
||||
typedef enum CorPinvokeMap
|
||||
|
|
|
@ -125,6 +125,8 @@ import "wtypes.idl";
|
|||
import "unknwn.idl";
|
||||
#endif
|
||||
|
||||
#define STDMETHODCALLTYPE
|
||||
|
||||
typedef UINT_PTR ProcessID;
|
||||
typedef UINT_PTR AssemblyID;
|
||||
typedef UINT_PTR AppDomainID;
|
||||
|
@ -303,13 +305,13 @@ typedef struct _COR_PRF_METHOD
|
|||
* bits cleared for COR_PRF_ENABLE_FRAME_INFO, COR_PRF_ENABLE_FUNCTION_RETVAL
|
||||
* and COR_PRF_ENABLE_FUNCTION_ARGS.
|
||||
*/
|
||||
typedef void __stdcall FunctionEnter(
|
||||
typedef void STDMETHODCALLTYPE FunctionEnter(
|
||||
FunctionID funcID);
|
||||
|
||||
typedef void __stdcall FunctionLeave(
|
||||
typedef void STDMETHODCALLTYPE FunctionLeave(
|
||||
FunctionID funcID);
|
||||
|
||||
typedef void __stdcall FunctionTailcall(
|
||||
typedef void STDMETHODCALLTYPE FunctionTailcall(
|
||||
FunctionID funcID);
|
||||
|
||||
/*
|
||||
|
@ -320,19 +322,19 @@ typedef void __stdcall FunctionTailcall(
|
|||
* functionality, use the FunctionEnter3/Leave3/Tailcall3 callbacks.
|
||||
*/
|
||||
|
||||
typedef void __stdcall FunctionEnter2(
|
||||
typedef void STDMETHODCALLTYPE FunctionEnter2(
|
||||
FunctionID funcId,
|
||||
UINT_PTR clientData,
|
||||
COR_PRF_FRAME_INFO func,
|
||||
COR_PRF_FUNCTION_ARGUMENT_INFO *argumentInfo);
|
||||
|
||||
typedef void __stdcall FunctionLeave2(
|
||||
typedef void STDMETHODCALLTYPE FunctionLeave2(
|
||||
FunctionID funcId,
|
||||
UINT_PTR clientData,
|
||||
COR_PRF_FRAME_INFO func,
|
||||
COR_PRF_FUNCTION_ARGUMENT_RANGE *retvalRange);
|
||||
|
||||
typedef void __stdcall FunctionTailcall2(
|
||||
typedef void STDMETHODCALLTYPE FunctionTailcall2(
|
||||
FunctionID funcId,
|
||||
UINT_PTR clientData,
|
||||
COR_PRF_FRAME_INFO func);
|
||||
|
@ -348,13 +350,13 @@ typedef void __stdcall FunctionTailcall2(
|
|||
* true FunctionID of the function.
|
||||
*/
|
||||
|
||||
typedef void __stdcall FunctionEnter3(
|
||||
typedef void STDMETHODCALLTYPE FunctionEnter3(
|
||||
FunctionIDOrClientID functionIDOrClientID);
|
||||
|
||||
typedef void __stdcall FunctionLeave3(
|
||||
typedef void STDMETHODCALLTYPE FunctionLeave3(
|
||||
FunctionIDOrClientID functionIDOrClientID);
|
||||
|
||||
typedef void __stdcall FunctionTailcall3(
|
||||
typedef void STDMETHODCALLTYPE FunctionTailcall3(
|
||||
FunctionIDOrClientID functionIDOrClientID);
|
||||
|
||||
/*
|
||||
|
@ -371,15 +373,15 @@ typedef void __stdcall FunctionTailcall3(
|
|||
* It is only valid during the callback to which it is passed.
|
||||
*/
|
||||
|
||||
typedef void __stdcall FunctionEnter3WithInfo(
|
||||
typedef void STDMETHODCALLTYPE FunctionEnter3WithInfo(
|
||||
FunctionIDOrClientID functionIDOrClientID,
|
||||
COR_PRF_ELT_INFO eltInfo);
|
||||
|
||||
typedef void __stdcall FunctionLeave3WithInfo(
|
||||
typedef void STDMETHODCALLTYPE FunctionLeave3WithInfo(
|
||||
FunctionIDOrClientID functionIDOrClientID,
|
||||
COR_PRF_ELT_INFO eltInfo);
|
||||
|
||||
typedef void __stdcall FunctionTailcall3WithInfo(
|
||||
typedef void STDMETHODCALLTYPE FunctionTailcall3WithInfo(
|
||||
FunctionIDOrClientID functionIDOrClientID,
|
||||
COR_PRF_ELT_INFO eltInfo);
|
||||
|
||||
|
@ -587,7 +589,8 @@ typedef enum
|
|||
COR_PRF_MONITOR_SUSPENDS |
|
||||
COR_PRF_MONITOR_CLASS_LOADS |
|
||||
COR_PRF_MONITOR_EXCEPTIONS |
|
||||
COR_PRF_MONITOR_JIT_COMPILATION,
|
||||
COR_PRF_MONITOR_JIT_COMPILATION |
|
||||
COR_PRF_ENABLE_REJIT,
|
||||
|
||||
// MONITOR_IMMUTABLE represents all flags that may only be set during initialization.
|
||||
// Trying to change any of these flags elsewhere will result in a
|
||||
|
@ -596,7 +599,6 @@ typedef enum
|
|||
COR_PRF_MONITOR_REMOTING |
|
||||
COR_PRF_MONITOR_REMOTING_COOKIE |
|
||||
COR_PRF_MONITOR_REMOTING_ASYNC |
|
||||
COR_PRF_ENABLE_REJIT |
|
||||
COR_PRF_ENABLE_INPROC_DEBUGGING |
|
||||
COR_PRF_ENABLE_JIT_MAPS |
|
||||
COR_PRF_DISABLE_OPTIMIZATIONS |
|
||||
|
@ -3983,3 +3985,25 @@ interface ICorProfilerAssemblyReferenceProvider : IUnknown
|
|||
// assembly specified in the wszAssemblyPath argument of the GetAssemblyReferences callback.
|
||||
HRESULT AddAssemblyReference(const COR_PRF_ASSEMBLY_REFERENCE_INFO * pAssemblyRefInfo);
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** ICLRProfiling **
|
||||
** Activated using mscoree!CLRCreateInstance. Export AttachProfiler API to profilers **
|
||||
***************************************************************************************/
|
||||
[
|
||||
uuid(B349ABE3-B56F-4689-BFCD-76BF39D888EA),
|
||||
version(1.0),
|
||||
helpstring("CoreCLR profiling interface for profiler attach"),
|
||||
local
|
||||
]
|
||||
interface ICLRProfiling : IUnknown
|
||||
{
|
||||
HRESULT AttachProfiler(
|
||||
[in] DWORD dwProfileeProcessID,
|
||||
[in] DWORD dwMillisecondsMax, // optional
|
||||
[in] const CLSID * pClsidProfiler,
|
||||
[in] LPCWSTR wszProfilerPath, // optional
|
||||
[in, size_is(cbClientData)] void * pvClientData, // optional
|
||||
[in] UINT cbClientData); // optional
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#define CROSSBITNESS_COMPILE
|
||||
#endif
|
||||
|
||||
#if defined(_X86_) && defined(_TARGET_ARM_) // Host X86 managing ARM related code
|
||||
#if !defined(_ARM_) && defined(_TARGET_ARM_) // Non-ARM Host managing ARM related code
|
||||
|
||||
#ifndef CROSS_COMPILE
|
||||
#define CROSS_COMPILE
|
||||
|
@ -93,6 +93,7 @@ typedef struct DECLSPEC_ALIGN(8) _T_CONTEXT {
|
|||
//
|
||||
|
||||
#ifndef FEATURE_PAL
|
||||
#ifdef _X86_
|
||||
typedef struct _RUNTIME_FUNCTION {
|
||||
DWORD BeginAddress;
|
||||
DWORD UnwindData;
|
||||
|
@ -119,6 +120,7 @@ typedef struct _UNWIND_HISTORY_TABLE {
|
|||
DWORD HighAddress;
|
||||
UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE];
|
||||
} UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE;
|
||||
#endif // _X86_
|
||||
#endif // !FEATURE_PAL
|
||||
|
||||
|
||||
|
@ -175,8 +177,15 @@ typedef struct _T_DISPATCHER_CONTEXT {
|
|||
PUCHAR NonVolatileRegisters;
|
||||
} T_DISPATCHER_CONTEXT, *PT_DISPATCHER_CONTEXT;
|
||||
|
||||
#if defined(FEATURE_PAL) || defined(_X86_)
|
||||
#define T_RUNTIME_FUNCTION RUNTIME_FUNCTION
|
||||
#define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION
|
||||
#else
|
||||
typedef struct _T_RUNTIME_FUNCTION {
|
||||
DWORD BeginAddress;
|
||||
DWORD UnwindData;
|
||||
} T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION;
|
||||
#endif
|
||||
|
||||
#elif defined(_AMD64_) && defined(_TARGET_ARM64_) // Host amd64 managing ARM64 related code
|
||||
|
||||
|
@ -347,7 +356,7 @@ typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS {
|
|||
|
||||
} T_KNONVOLATILE_CONTEXT_POINTERS, *PT_KNONVOLATILE_CONTEXT_POINTERS;
|
||||
|
||||
#else // !(defined(_X86_) && defined(_TARGET_ARM_)) && !(defined(_AMD64_) && defined(_TARGET_ARM64_))
|
||||
#else
|
||||
|
||||
#define T_CONTEXT CONTEXT
|
||||
#define PT_CONTEXT PCONTEXT
|
||||
|
|
|
@ -177,6 +177,25 @@ struct MSLAYOUT DacpMethodTableFieldData : ZeroInit<DacpMethodTableFieldData>
|
|||
}
|
||||
};
|
||||
|
||||
struct MSLAYOUT DacpMethodTableCollectibleData : ZeroInit<DacpMethodTableCollectibleData>
|
||||
{
|
||||
CLRDATA_ADDRESS LoaderAllocatorObjectHandle;
|
||||
BOOL bCollectible;
|
||||
|
||||
HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
|
||||
{
|
||||
HRESULT hr;
|
||||
ISOSDacInterface6 *pSOS6 = NULL;
|
||||
if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface6), (void**)&pSOS6)))
|
||||
{
|
||||
hr = pSOS6->GetMethodTableCollectibleData(addr, this);
|
||||
pSOS6->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
};
|
||||
|
||||
struct MSLAYOUT DacpMethodTableTransparencyData : ZeroInit<DacpMethodTableTransparencyData>
|
||||
{
|
||||
BOOL bHasCriticalTransparentInfo;
|
||||
|
@ -1043,5 +1062,6 @@ static_assert(sizeof(DacpGetModuleAddress) == 0x8, "Dacp structs cannot be modif
|
|||
static_assert(sizeof(DacpFrameData) == 0x8, "Dacp structs cannot be modified due to backwards compatibility.");
|
||||
static_assert(sizeof(DacpJitCodeHeapInfo) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
|
||||
static_assert(sizeof(DacpExceptionObjectData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility.");
|
||||
static_assert(sizeof(DacpMethodTableCollectibleData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility.");
|
||||
|
||||
#endif // _DACPRIVATE_H_
|
||||
|
|
|
@ -331,9 +331,6 @@ inline const char *ReturnKindToString(ReturnKind returnKind)
|
|||
|
||||
// we use offsetof to get the offset of a field
|
||||
#include <stddef.h> // offsetof
|
||||
#ifndef offsetof
|
||||
#define offsetof(s,m) ((size_t)&(((s *)0)->m))
|
||||
#endif
|
||||
|
||||
enum infoHdrAdjustConstants {
|
||||
// Constants
|
||||
|
|
|
@ -1295,50 +1295,6 @@ private:
|
|||
};
|
||||
#endif // !FEATURE_PAL
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Wrapper to suppress auto-destructor (UNDER CONSTRUCTION)
|
||||
// Usage:
|
||||
//
|
||||
// BEGIN_MANUAL_HOLDER(NewArrayHolder<Foo>, foo);
|
||||
// ... use foo via ->
|
||||
// END_MANUAL_HOLDER(foo);
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <typename TYPE, SIZE_T SIZE = sizeof(TYPE)>
|
||||
class NoAuto__DONTUSEDIRECTLY
|
||||
{
|
||||
private:
|
||||
BYTE hiddeninstance[SIZE];
|
||||
|
||||
public:
|
||||
// Unfortunately, you can only use the default constructor
|
||||
NoAuto__DONTUSEDIRECTLY()
|
||||
{
|
||||
new (hiddeninstance) TYPE ();
|
||||
}
|
||||
|
||||
operator TYPE& () { return *(TYPE *)hiddeninstance; }
|
||||
TYPE& operator->() { return *(TYPE *)hiddeninstance; }
|
||||
TYPE& operator*() { return *(TYPE *)hiddeninstance; }
|
||||
|
||||
void Destructor() { (*(TYPE*)hiddeninstance)->TYPE::~TYPE(); }
|
||||
};
|
||||
|
||||
#define BEGIN_MANUAL_HOLDER(_TYPE, _NAME) \
|
||||
{ \
|
||||
NoAuto__DONTUSEDIRECTLY<_TYPE> _NAME; \
|
||||
__try \
|
||||
{
|
||||
|
||||
#define END_MANUAL_HOLDER(_NAME) \
|
||||
} \
|
||||
__finally \
|
||||
{ \
|
||||
_NAME.Destructor(); \
|
||||
} \
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// External data access does not want certain holder implementations
|
||||
|
|
|
@ -87,9 +87,6 @@ cpp_quote("EXTERN_GUID(CLSID_CLRDebuggingLegacy, 0xDF8395B5, 0xA4BA, 0x450b, 0xA
|
|||
// CLSID CLRProfiling interface : uuid{BD097ED8-733E-43fe-8ED7-A95FF9A8448C}
|
||||
cpp_quote("EXTERN_GUID(CLSID_CLRProfiling, 0xbd097ed8, 0x733e, 0x43fe, 0x8e, 0xd7, 0xa9, 0x5f, 0xf9, 0xa8, 0x44, 0x8c);")
|
||||
|
||||
// IID ICLRProfiling interface : uuid{B349ABE3-B56F-4689-BFCD-76BF39D888EA}
|
||||
cpp_quote("EXTERN_GUID(IID_ICLRProfiling, 0xb349abe3, 0xb56f, 0x4689, 0xbf, 0xcd, 0x76, 0xbf, 0x39, 0xd8, 0x88, 0xea);")
|
||||
|
||||
// IID ICLRDebuggingLibraryProvider interface : uuid{3151C08D-4D09-4f9b-8838-2880BF18FE51}
|
||||
cpp_quote("EXTERN_GUID(IID_ICLRDebuggingLibraryProvider, 0x3151c08d, 0x4d09, 0x4f9b, 0x88, 0x38, 0x28, 0x80, 0xbf, 0x18, 0xfe, 0x51);")
|
||||
|
||||
|
@ -333,27 +330,6 @@ interface ICLRMetaHostPolicy : IUnknown
|
|||
[out, iid_is(riid), retval] LPVOID *ppRuntime);
|
||||
} // interface ICLRMetaHostPolicy
|
||||
|
||||
/***************************************************************************************
|
||||
** ICLRProfiling **
|
||||
** Activated using mscoree!CLRCreateInstance. Export AttachProfiler API to profilers **
|
||||
***************************************************************************************/
|
||||
[
|
||||
uuid(B349ABE3-B56F-4689-BFCD-76BF39D888EA),
|
||||
version(1.0),
|
||||
helpstring("CLR profiling interface for MetaHost interface"),
|
||||
local
|
||||
]
|
||||
interface ICLRProfiling : IUnknown
|
||||
{
|
||||
HRESULT AttachProfiler(
|
||||
[in] DWORD dwProfileeProcessID,
|
||||
[in] DWORD dwMillisecondsMax, // optional
|
||||
[in] const CLSID * pClsidProfiler,
|
||||
[in] LPCWSTR wszProfilerPath, // optional
|
||||
[in, size_is(cbClientData)] void * pvClientData, // optional
|
||||
[in] UINT cbClientData); // optional
|
||||
}
|
||||
|
||||
/*************************************************************************************
|
||||
** This structure defines the version of a CLR for debugging purposes. **
|
||||
** The wStructVersion field allows for future revisions to this structure to be **
|
||||
|
@ -1099,7 +1075,6 @@ library CLRMetaHost
|
|||
{
|
||||
interface ICLRMetaHost;
|
||||
interface ICLRMetaHostPolicy;
|
||||
interface ICLRProfiling;
|
||||
interface ICLRDebuggingLibraryProvider;
|
||||
interface ICLRDebugging;
|
||||
interface ICLRRuntimeInfo;
|
||||
|
@ -1130,7 +1105,6 @@ library CLRMetaHost
|
|||
|
||||
// Scenario: Profiler attach for v4
|
||||
// ICLRMetaHost::EnumerateLoadedRuntimes
|
||||
// ICLRRuntimeInfo::GetInterface(CLSID_CLRProfiling, IID_ICLRProfiling)
|
||||
|
||||
// Scenario: An installer needs to modify configuration of supported runtimes
|
||||
// 1. ICLRMetaHost::EnumerateInstalledRuntimes
|
||||
|
|
|
@ -141,31 +141,17 @@
|
|||
#define IMAGE_IMPORT_DESC_FIELD(img, f) ((img).f)
|
||||
#endif
|
||||
|
||||
//Remove these "unanonymous" unions from newer builds for now. Confirm that they were never needed when we
|
||||
//bring back Rotor.
|
||||
#define IMAGE_RDE_ID(img) ((img)->Id)
|
||||
#ifndef IMAGE_RDE_ID
|
||||
#define IMAGE_RDE_ID(img) ((img)->Id)
|
||||
#endif
|
||||
|
||||
#define IMAGE_RDE_NAME(img) ((img)->Name)
|
||||
#ifndef IMAGE_RDE_NAME
|
||||
#define IMAGE_RDE_NAME(img) ((img)->Name)
|
||||
#endif
|
||||
|
||||
#define IMAGE_RDE_OFFSET(img) ((img)->OffsetToData)
|
||||
#ifndef IMAGE_RDE_OFFSET
|
||||
#define IMAGE_RDE_OFFSET(img) ((img)->OffsetToData)
|
||||
#endif
|
||||
|
||||
#ifndef IMAGE_RDE_NAME_FIELD
|
||||
#define IMAGE_RDE_NAME_FIELD(img, f) ((img)->f)
|
||||
#endif
|
||||
|
||||
#define IMAGE_RDE_OFFSET_FIELD(img, f) ((img)->f)
|
||||
#ifndef IMAGE_RDE_OFFSET_FIELD
|
||||
#define IMAGE_RDE_OFFSET_FIELD(img, f) ((img)->f)
|
||||
#endif
|
||||
|
||||
#ifndef IMAGE_FE64_FIELD
|
||||
#define IMAGE_FE64_FIELD(img, f) ((img).f)
|
||||
|
@ -185,7 +171,7 @@
|
|||
// integer constants. 64-bit integer constants should be wrapped in the
|
||||
// declarations listed here.
|
||||
//
|
||||
// Each of the #defines here is wrapped to avoid conflicts with rotor_pal.h.
|
||||
// Each of the #defines here is wrapped to avoid conflicts with pal.h.
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#elif defined(_WIN64)
|
||||
#elif defined(_TARGET_64BIT_)
|
||||
|
||||
#if defined(_TARGET_ARM64_)
|
||||
typedef struct _Arm64VolatileContextPointer
|
||||
|
@ -250,7 +250,7 @@ struct REGDISPLAY : public REGDISPLAY_BASE {
|
|||
ArmVolatileContextPointer volatileCurrContextPointers;
|
||||
|
||||
DWORD * pPC; // processor neutral name
|
||||
|
||||
#ifndef CROSSGEN_COMPILE
|
||||
REGDISPLAY()
|
||||
{
|
||||
// Initialize regdisplay
|
||||
|
@ -259,6 +259,10 @@ struct REGDISPLAY : public REGDISPLAY_BASE {
|
|||
// Setup the pointer to ControlPC field
|
||||
pPC = &ControlPC;
|
||||
}
|
||||
#else
|
||||
private:
|
||||
REGDISPLAY();
|
||||
#endif
|
||||
};
|
||||
|
||||
// This function tells us if the given stack pointer is in one of the frames of the functions called by the given frame
|
||||
|
@ -278,7 +282,7 @@ inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) {
|
|||
#error "RegDisplay functions are not implemented on this platform."
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64) || defined(_TARGET_ARM_) || (defined(_TARGET_X86_) && defined(WIN64EXCEPTIONS))
|
||||
#if defined(_TARGET_64BIT_) || defined(_TARGET_ARM_) || (defined(_TARGET_X86_) && defined(WIN64EXCEPTIONS))
|
||||
// This needs to be implemented for platforms that have funclets.
|
||||
inline LPVOID GetRegdisplayReturnValue(REGDISPLAY *display)
|
||||
{
|
||||
|
@ -289,7 +293,7 @@ inline LPVOID GetRegdisplayReturnValue(REGDISPLAY *display)
|
|||
#elif defined(_TARGET_ARM64_)
|
||||
return (LPVOID)display->pCurrentContext->X0;
|
||||
#elif defined(_TARGET_ARM_)
|
||||
return (LPVOID)display->pCurrentContext->R0;
|
||||
return (LPVOID)((TADDR)display->pCurrentContext->R0);
|
||||
#elif defined(_TARGET_X86_)
|
||||
return (LPVOID)display->pCurrentContext->Eax;
|
||||
#else
|
||||
|
@ -302,24 +306,24 @@ inline void SyncRegDisplayToCurrentContext(REGDISPLAY* pRD)
|
|||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
|
||||
#if defined(_WIN64)
|
||||
#if defined(_TARGET_64BIT_)
|
||||
pRD->SP = (INT_PTR)GetSP(pRD->pCurrentContext);
|
||||
pRD->ControlPC = INT_PTR(GetIP(pRD->pCurrentContext));
|
||||
#elif defined(_TARGET_ARM_) // _WIN64
|
||||
#elif defined(_TARGET_ARM_)
|
||||
pRD->SP = (DWORD)GetSP(pRD->pCurrentContext);
|
||||
pRD->ControlPC = (DWORD)GetIP(pRD->pCurrentContext);
|
||||
#elif defined(_TARGET_X86_) // _TARGET_ARM_
|
||||
#elif defined(_TARGET_X86_)
|
||||
pRD->SP = (DWORD)GetSP(pRD->pCurrentContext);
|
||||
pRD->ControlPC = (DWORD)GetIP(pRD->pCurrentContext);
|
||||
#else // _TARGET_X86_
|
||||
PORTABILITY_ASSERT("SyncRegDisplayToCurrentContext");
|
||||
#endif // _TARGET_ARM_ || _TARGET_X86_
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_REGDISPLAY
|
||||
CheckRegDisplaySP(pRD);
|
||||
#endif // DEBUG_REGDISPLAY
|
||||
}
|
||||
#endif // _WIN64 || _TARGET_ARM_ || (_TARGET_X86_ && WIN64EXCEPTIONS)
|
||||
#endif // _TARGET_64BIT_ || _TARGET_ARM_ || (_TARGET_X86_ && WIN64EXCEPTIONS)
|
||||
|
||||
typedef REGDISPLAY *PREGDISPLAY;
|
||||
|
||||
|
@ -406,9 +410,20 @@ inline void FillRegDisplay(const PREGDISPLAY pRD, PT_CONTEXT pctx, PT_CONTEXT pC
|
|||
FillContextPointers(&pRD->ctxPtrsOne, pctx);
|
||||
|
||||
#if defined(_TARGET_ARM_)
|
||||
// Fill volatile context pointers. They can be used by GC in the case of the leaf frame
|
||||
pRD->volatileCurrContextPointers.R0 = &pctx->R0;
|
||||
pRD->volatileCurrContextPointers.R1 = &pctx->R1;
|
||||
pRD->volatileCurrContextPointers.R2 = &pctx->R2;
|
||||
pRD->volatileCurrContextPointers.R3 = &pctx->R3;
|
||||
pRD->volatileCurrContextPointers.R12 = &pctx->R12;
|
||||
|
||||
pRD->ctxPtrsOne.Lr = &pctx->Lr;
|
||||
pRD->pPC = &pRD->pCurrentContext->Pc;
|
||||
#endif // _TARGET_ARM_
|
||||
#elif defined(_TARGET_ARM64_) // _TARGET_ARM_
|
||||
// Fill volatile context pointers. They can be used by GC in the case of the leaf frame
|
||||
for (int i=0; i < 18; i++)
|
||||
pRD->volatileCurrContextPointers.X[i] = &pctx->X[i];
|
||||
#endif // _TARGET_ARM64_
|
||||
|
||||
#ifdef DEBUG_REGDISPLAY
|
||||
pRD->_pThread = NULL;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define _ASSERTE_SAFEMATH _ASSERTE
|
||||
#else
|
||||
// Otherwise (eg. we're being used from a tool like SOS) there isn't much
|
||||
// we can rely on that is both available everywhere and rotor-safe. In
|
||||
// we can rely on that is available everywhere. In
|
||||
// several other tools we just take the recourse of disabling asserts,
|
||||
// we'll do the same here.
|
||||
// Ideally we'd have a collection of common utilities available evererywhere.
|
||||
|
@ -855,18 +855,4 @@ typedef ClrSafeInt<UINT16> S_UINT16;
|
|||
typedef ClrSafeInt<UINT64> S_UINT64;
|
||||
typedef ClrSafeInt<SIZE_T> S_SIZE_T;
|
||||
|
||||
// Note: we can get bogus /Wp64 compiler warnings when S_SIZE_T is used.
|
||||
// This is due to VSWhidbey 138322 which the C++ folks have said they can't
|
||||
// currently fix. We can work around the problem by using this macro to force
|
||||
// a no-op cast on 32-bit MSVC platforms. It's not yet clear why we need to
|
||||
// use this in some places (specifically, rotor lkgvc builds) and not others.
|
||||
// We also make the error less likely by using a #define instead of a
|
||||
// typedef for S_UINT32 above since that means we're less likely to instantiate
|
||||
// ClrSafeInt<UINT32> AND ClrSafeInt<SIZE_T> in the same compliation unit.
|
||||
#if defined(_TARGET_X86_) && defined( _MSC_VER )
|
||||
#define S_SIZE_T_WP64BUG(v) S_SIZE_T( static_cast<UINT32>( v ) )
|
||||
#else
|
||||
#define S_SIZE_T_WP64BUG(v) S_SIZE_T( v )
|
||||
#endif
|
||||
|
||||
#endif // SAFEMATH_H_
|
||||
|
|
|
@ -367,3 +367,13 @@ interface ISOSDacInterface5 : IUnknown
|
|||
{
|
||||
HRESULT GetTieredVersions(CLRDATA_ADDRESS methodDesc, int rejitId, struct DacpTieredVersionData *nativeCodeAddrs, int cNativeCodeAddrs, int *pcNativeCodeAddrs);
|
||||
};
|
||||
|
||||
[
|
||||
object,
|
||||
local,
|
||||
uuid(11206399-4B66-4EDB-98EA-85654E59AD45)
|
||||
]
|
||||
interface ISOSDacInterface6 : IUnknown
|
||||
{
|
||||
HRESULT GetMethodTableFieldData(CLRDATA_ADDRESS mt, struct DacpMethodTableFieldData *data);
|
||||
};
|
||||
|
|
|
@ -145,16 +145,6 @@
|
|||
|
||||
#endif // _DEBUG
|
||||
|
||||
|
||||
|
||||
#if defined(PROFILING_SUPPORTED)
|
||||
// On desktop CLR builds, the profiling API uses the event log for end-user-friendly
|
||||
// diagnostic messages. CoreCLR on Windows ouputs debug strings for diagnostic messages.
|
||||
// Rotor builds have no access to event log message resources, though, so they simply
|
||||
// display popup dialogs for now.
|
||||
#define FEATURE_PROFAPI_EVENT_LOGGING
|
||||
#endif // defined(PROFILING_SUPPORTED)
|
||||
|
||||
// MUST NEVER CHECK IN WITH THIS ENABLED.
|
||||
// This is just for convenience in doing performance investigations in a checked-out enlistment.
|
||||
// #define FEATURE_ENABLE_NO_RANGE_CHECKS
|
||||
|
|
|
@ -474,32 +474,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Warning: workaround
|
||||
//
|
||||
// At the bottom of this file, we are going to #define the "volatile" keyword such that it is illegal
|
||||
// to use it. Unfortunately, VC++ uses the volatile keyword in stddef.h, in the definition of "offsetof".
|
||||
// GCC does not use volatile in its definition.
|
||||
//
|
||||
// To get around this, we include stddef.h here (even if we're on GCC, for consistency). We then need
|
||||
// to redefine offsetof such that it does not use volatile, if we're building with VC++.
|
||||
//
|
||||
#include <stddef.h>
|
||||
#ifdef _MSC_VER
|
||||
#undef offsetof
|
||||
#ifdef _WIN64
|
||||
#define offsetof(s,m) (size_t)( (ptrdiff_t)&reinterpret_cast<const char&>((((s *)0)->m)) )
|
||||
#else
|
||||
#define offsetof(s,m) (size_t)&reinterpret_cast<const char&>((((s *)0)->m))
|
||||
#endif //_WIN64
|
||||
|
||||
// These also use volatile, so we'll include them here.
|
||||
//#include <intrin.h>
|
||||
//#include <memory>
|
||||
|
||||
#endif //_MSC_VER
|
||||
|
||||
//
|
||||
// From here on out, we ban the use of the "volatile" keyword. If you found this while trying to define
|
||||
// a volatile variable, go to the top of this file and start reading.
|
||||
|
|
|
@ -91,6 +91,10 @@ MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface4,0x74B9D34C,0xA612,0x4B07,0x93,0xDD,0
|
|||
|
||||
MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface5,0x127d6abe,0x6c86,0x4e48,0x8e,0x7b,0x22,0x07,0x81,0xc5,0x81,0x01);
|
||||
|
||||
|
||||
MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface6,0x11206399,0x4b66,0x4edb,0x98,0xea,0x85,0x65,0x4e,0x59,0xad,0x45);
|
||||
|
||||
|
||||
#undef MIDL_DEFINE_GUID
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -171,7 +171,9 @@ EXTERN_C const IID IID_ICLRPrivBinder;
|
|||
/* [in] */ LPVOID pvAssemblySpec,
|
||||
/* [out] */ HRESULT *pResult,
|
||||
/* [out] */ ICLRPrivAssembly **ppAssembly) = 0;
|
||||
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetLoaderAllocator(
|
||||
/* [retval][out] */ LPVOID* pLoaderAllocator) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -219,6 +221,10 @@ EXTERN_C const IID IID_ICLRPrivBinder;
|
|||
/* [out] */ HRESULT *pResult,
|
||||
/* [out] */ ICLRPrivAssembly **ppAssembly);
|
||||
|
||||
HRESULT(STDMETHODCALLTYPE *GetLoaderAllocator)(
|
||||
ICLRPrivBinder * This,
|
||||
/* [retval][out] */ LPVOID *pLoaderAllocator) = 0;
|
||||
|
||||
END_INTERFACE
|
||||
} ICLRPrivBinderVtbl;
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -59,13 +59,6 @@ typedef interface ICLRMetaHostPolicy ICLRMetaHostPolicy;
|
|||
#endif /* __ICLRMetaHostPolicy_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ICLRProfiling_FWD_DEFINED__
|
||||
#define __ICLRProfiling_FWD_DEFINED__
|
||||
typedef interface ICLRProfiling ICLRProfiling;
|
||||
|
||||
#endif /* __ICLRProfiling_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ICLRDebuggingLibraryProvider_FWD_DEFINED__
|
||||
#define __ICLRDebuggingLibraryProvider_FWD_DEFINED__
|
||||
typedef interface ICLRDebuggingLibraryProvider ICLRDebuggingLibraryProvider;
|
||||
|
@ -129,13 +122,6 @@ typedef interface ICLRMetaHostPolicy ICLRMetaHostPolicy;
|
|||
#endif /* __ICLRMetaHostPolicy_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ICLRProfiling_FWD_DEFINED__
|
||||
#define __ICLRProfiling_FWD_DEFINED__
|
||||
typedef interface ICLRProfiling ICLRProfiling;
|
||||
|
||||
#endif /* __ICLRProfiling_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ICLRDebuggingLibraryProvider_FWD_DEFINED__
|
||||
#define __ICLRDebuggingLibraryProvider_FWD_DEFINED__
|
||||
typedef interface ICLRDebuggingLibraryProvider ICLRDebuggingLibraryProvider;
|
||||
|
@ -194,7 +180,6 @@ EXTERN_GUID(IID_ICLRStrongName2, 0xC22ED5C5, 0x4B59, 0x4975, 0x90, 0xEB, 0x85, 0
|
|||
EXTERN_GUID(IID_ICLRStrongName3, 0x22c7089b, 0xbbd3, 0x414a, 0xb6, 0x98, 0x21, 0x0f, 0x26, 0x3f, 0x1f, 0xed);
|
||||
EXTERN_GUID(CLSID_CLRDebuggingLegacy, 0xDF8395B5, 0xA4BA, 0x450b, 0xA7, 0x7C, 0xA9, 0xA4, 0x77, 0x62, 0xC5, 0x20);
|
||||
EXTERN_GUID(CLSID_CLRProfiling, 0xbd097ed8, 0x733e, 0x43fe, 0x8e, 0xd7, 0xa9, 0x5f, 0xf9, 0xa8, 0x44, 0x8c);
|
||||
EXTERN_GUID(IID_ICLRProfiling, 0xb349abe3, 0xb56f, 0x4689, 0xbf, 0xcd, 0x76, 0xbf, 0x39, 0xd8, 0x88, 0xea);
|
||||
EXTERN_GUID(IID_ICLRDebuggingLibraryProvider, 0x3151c08d, 0x4d09, 0x4f9b, 0x88, 0x38, 0x28, 0x80, 0xbf, 0x18, 0xfe, 0x51);
|
||||
EXTERN_GUID(IID_ICLRDebuggingLibraryProvider2, 0xE04E2FF1, 0xDCFD, 0x45D5, 0xBC, 0xD1, 0x16, 0xFF, 0xF2, 0xFA, 0xF7, 0xBA);
|
||||
typedef HRESULT ( __stdcall *CLRCreateInstanceFnPtr )(
|
||||
|
@ -507,96 +492,6 @@ EXTERN_C const IID IID_ICLRMetaHostPolicy;
|
|||
#endif /* __ICLRMetaHostPolicy_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ICLRProfiling_INTERFACE_DEFINED__
|
||||
#define __ICLRProfiling_INTERFACE_DEFINED__
|
||||
|
||||
/* interface ICLRProfiling */
|
||||
/* [object][local][helpstring][version][uuid] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_ICLRProfiling;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("B349ABE3-B56F-4689-BFCD-76BF39D888EA")
|
||||
ICLRProfiling : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE AttachProfiler(
|
||||
/* [in] */ DWORD dwProfileeProcessID,
|
||||
/* [in] */ DWORD dwMillisecondsMax,
|
||||
/* [in] */ const CLSID *pClsidProfiler,
|
||||
/* [in] */ LPCWSTR wszProfilerPath,
|
||||
/* [size_is][in] */ void *pvClientData,
|
||||
/* [in] */ UINT cbClientData) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct ICLRProfilingVtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
ICLRProfiling * This,
|
||||
/* [in] */ REFIID riid,
|
||||
/* [annotation][iid_is][out] */
|
||||
_COM_Outptr_ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
ICLRProfiling * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
ICLRProfiling * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *AttachProfiler )(
|
||||
ICLRProfiling * This,
|
||||
/* [in] */ DWORD dwProfileeProcessID,
|
||||
/* [in] */ DWORD dwMillisecondsMax,
|
||||
/* [in] */ const CLSID *pClsidProfiler,
|
||||
/* [in] */ LPCWSTR wszProfilerPath,
|
||||
/* [size_is][in] */ void *pvClientData,
|
||||
/* [in] */ UINT cbClientData);
|
||||
|
||||
END_INTERFACE
|
||||
} ICLRProfilingVtbl;
|
||||
|
||||
interface ICLRProfiling
|
||||
{
|
||||
CONST_VTBL struct ICLRProfilingVtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define ICLRProfiling_QueryInterface(This,riid,ppvObject) \
|
||||
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
|
||||
|
||||
#define ICLRProfiling_AddRef(This) \
|
||||
( (This)->lpVtbl -> AddRef(This) )
|
||||
|
||||
#define ICLRProfiling_Release(This) \
|
||||
( (This)->lpVtbl -> Release(This) )
|
||||
|
||||
|
||||
#define ICLRProfiling_AttachProfiler(This,dwProfileeProcessID,dwMillisecondsMax,pClsidProfiler,wszProfilerPath,pvClientData,cbClientData) \
|
||||
( (This)->lpVtbl -> AttachProfiler(This,dwProfileeProcessID,dwMillisecondsMax,pClsidProfiler,wszProfilerPath,pvClientData,cbClientData) )
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __ICLRProfiling_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_metahost_0000_0003 */
|
||||
/* [local] */
|
||||
|
||||
|
|
|
@ -263,7 +263,6 @@ DEPRECATED_CLR_STDAPI CorBindToRuntimeByCfg(IStream* pCfgStream, DWORD reserved,
|
|||
DEPRECATED_CLR_STDAPI CorBindToRuntime(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv);
|
||||
DEPRECATED_CLR_STDAPI CorBindToCurrentRuntime(LPCWSTR pwszFileName, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv);
|
||||
DEPRECATED_CLR_STDAPI ClrCreateManagedInstance(LPCWSTR pTypeName, REFIID riid, void **ppObject);
|
||||
DECLARE_DEPRECATED void STDMETHODCALLTYPE CorMarkThreadInThreadPool();
|
||||
DEPRECATED_CLR_STDAPI RunDll32ShimW(HWND hwnd, HINSTANCE hinst, LPCWSTR lpszCmdLine, int nCmdShow);
|
||||
DEPRECATED_CLR_STDAPI LoadLibraryShim(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll);
|
||||
DEPRECATED_CLR_STDAPI CallFunctionShim(LPCWSTR szDllName, LPCSTR szFunctionName, LPVOID lpvArgument1, LPVOID lpvArgument2, LPCWSTR szVersion, LPVOID pvReserved);
|
||||
|
|
|
@ -2272,6 +2272,86 @@ EXTERN_C const IID IID_ISOSDacInterface5;
|
|||
|
||||
#endif /* __ISOSDacInterface5_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ISOSDacInterface6_INTERFACE_DEFINED__
|
||||
#define __ISOSDacInterface6_INTERFACE_DEFINED__
|
||||
|
||||
/* interface ISOSDacInterface6 */
|
||||
/* [uuid][local][object] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_ISOSDacInterface6;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("11206399-4B66-4EDB-98EA-85654E59AD45")
|
||||
ISOSDacInterface6 : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE GetMethodTableCollectibleData(
|
||||
CLRDATA_ADDRESS mt,
|
||||
struct DacpMethodTableCollectibleData *data) = 0;
|
||||
};
|
||||
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct ISOSDacInterface6Vtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT(STDMETHODCALLTYPE *QueryInterface)(
|
||||
ISOSDacInterface5 * This,
|
||||
/* [in] */ REFIID riid,
|
||||
/* [annotation][iid_is][out] */
|
||||
_COM_Outptr_ void **ppvObject);
|
||||
|
||||
ULONG(STDMETHODCALLTYPE *AddRef)(
|
||||
ISOSDacInterface5 * This);
|
||||
|
||||
ULONG(STDMETHODCALLTYPE *Release)(
|
||||
ISOSDacInterface5 * This);
|
||||
|
||||
HRESULT(STDMETHODCALLTYPE *GetMethodTableCollectibleData)(
|
||||
CLRDATA_ADDRESS mt,
|
||||
struct DacpMethodTableCollectibleData *data);
|
||||
|
||||
END_INTERFACE
|
||||
} ISOSDacInterface6Vtbl;
|
||||
|
||||
interface ISOSDacInterface6
|
||||
{
|
||||
CONST_VTBL struct ISOSDacInterface6Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define ISOSDacInterface6_QueryInterface(This,riid,ppvObject) \
|
||||
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
|
||||
|
||||
#define ISOSDacInterface6_AddRef(This) \
|
||||
( (This)->lpVtbl -> AddRef(This) )
|
||||
|
||||
#define ISOSDacInterface6_Release(This) \
|
||||
( (This)->lpVtbl -> Release(This) )
|
||||
|
||||
|
||||
#define ISOSDacInterface6_GetMethodTableCollectibleData(This,mt,data) \
|
||||
( (This)->lpVtbl -> GetMethodTableCollectibleData(This,mt,data) )
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __ISOSDacInterface6_INTERFACE_DEFINED__ */
|
||||
|
||||
/* Additional Prototypes for ALL interfaces */
|
||||
|
||||
/* end of Additional Prototypes */
|
||||
|
|
|
@ -687,7 +687,7 @@ CorUnix::InternalCreateFile(
|
|||
|
||||
/* make file descriptor close-on-exec; inheritable handles will get
|
||||
"uncloseonexeced" in CreateProcess if they are actually being inherited*/
|
||||
if(-1 == fcntl(filed,F_SETFD,1))
|
||||
if(-1 == fcntl(filed,F_SETFD, FD_CLOEXEC))
|
||||
{
|
||||
ASSERT("can't set close-on-exec flag; fcntl() failed. errno is %d "
|
||||
"(%s)\n", errno, strerror(errno));
|
||||
|
@ -1433,7 +1433,7 @@ Function:
|
|||
GetFileAttributesA
|
||||
|
||||
Note:
|
||||
Checking for directory and read-only file, according to Rotor spec.
|
||||
Checking for directory and read-only file.
|
||||
|
||||
Caveats:
|
||||
There are some important things to note about this implementation, which
|
||||
|
|
|
@ -857,7 +857,7 @@ finding no matches but without any error occurring) or FALSE if any error
|
|||
occurs. It calls SetLastError() if it returns FALSE.
|
||||
|
||||
Sorting doesn't seem to be consistent on all Windows platform, and it's
|
||||
not required for Rotor to have the same sorting algorithm than Windows 2000.
|
||||
not required for CoreCLR to have the same sorting algorithm as Windows 2000.
|
||||
This implementation will give slightly different result for the sort list
|
||||
than Windows 2000.
|
||||
|
||||
|
|
|
@ -321,32 +321,20 @@ bool DBG_ShouldCheckStackAlignment();
|
|||
BOOL __bHeader = bHeader;\
|
||||
DBG_PRINTF2
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define DBG_PRINTF2(args...)\
|
||||
DBG_printf_gcc(__chanid,__levid,__bHeader,__FUNCTION__,__FILE__,\
|
||||
__LINE__,args);\
|
||||
}\
|
||||
}
|
||||
#else /* __GNUC__ */
|
||||
#define DBG_PRINTF2(...)\
|
||||
DBG_printf_c99(__chanid,__levid,__bHeader,__FILE__,__LINE__,__VA_ARGS__);\
|
||||
DBG_printf(__chanid,__levid,__bHeader,__FUNCTION__,__FILE__,__LINE__,__VA_ARGS__);\
|
||||
}\
|
||||
}
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#endif /* _ENABLE_DEBUG_MESSAGES_ */
|
||||
|
||||
/* Use GNU C-specific features if available : __FUNCTION__ pseudo-macro,
|
||||
variable-argument macros */
|
||||
#ifdef __GNUC__
|
||||
|
||||
/* define NOTRACE as nothing; this will absorb the variable-argument list used
|
||||
in tracing macros */
|
||||
#define NOTRACE(args...)
|
||||
#define NOTRACE(...)
|
||||
|
||||
#if defined(__cplusplus) && defined(FEATURE_PAL_SXS)
|
||||
#define __ASSERT_ENTER() \
|
||||
/* DBG_printf_gcc() and DebugBreak() need a PAL thread */ \
|
||||
/* DBG_printf_c99() and DebugBreak() need a PAL thread */ \
|
||||
PAL_EnterHolder __holder(PALIsThreadDataInitialized() && \
|
||||
(CorUnix::InternalGetCurrentThread() == NULL || \
|
||||
!CorUnix::InternalGetCurrentThread()->IsInPal()));
|
||||
|
@ -356,49 +344,6 @@ bool DBG_ShouldCheckStackAlignment();
|
|||
|
||||
#if !defined(_DEBUG)
|
||||
|
||||
#define ASSERT(args...)
|
||||
#define _ASSERT(expr)
|
||||
#define _ASSERTE(expr)
|
||||
#define _ASSERT_MSG(args...)
|
||||
|
||||
#else /* defined(_DEBUG) */
|
||||
|
||||
#define ASSERT(args...) \
|
||||
{ \
|
||||
__ASSERT_ENTER(); \
|
||||
if (output_file && dbg_master_switch) \
|
||||
{ \
|
||||
DBG_printf_gcc(defdbgchan,DLI_ASSERT,TRUE,__FUNCTION__,__FILE__,__LINE__,args); \
|
||||
} \
|
||||
if (g_Dbg_asserts_enabled) \
|
||||
{ \
|
||||
DebugBreak(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _ASSERT(expr) do { if (!(expr)) { ASSERT(""); } } while(0)
|
||||
#define _ASSERTE(expr) do { if (!(expr)) { ASSERT("Expression: " #expr "\n"); } } while(0)
|
||||
#define _ASSERT_MSG(expr, args...) \
|
||||
do { \
|
||||
if (!(expr)) \
|
||||
{ \
|
||||
ASSERT("Expression: " #expr ", Description: " args); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* defined(_DEBUG) */
|
||||
|
||||
#else /* __GNUC__ */
|
||||
/* Not GNU C : C99 [the latest version of the ISO C Standard] specifies
|
||||
a different syntax for variable-argument macros, so try using that*/
|
||||
#if defined __STDC_VERSION__ && __STDC_VERSION__ >=199901L
|
||||
|
||||
/* define NOTRACE as nothing; this will absorb the variable-argument list used
|
||||
in tracing macros */
|
||||
#define NOTRACE(...)
|
||||
|
||||
#if !defined(_DEBUG)
|
||||
|
||||
#define ASSERT(...)
|
||||
#define _ASSERT(expr)
|
||||
#define _ASSERTE(expr)
|
||||
|
@ -411,11 +356,10 @@ bool DBG_ShouldCheckStackAlignment();
|
|||
__ASSERT_ENTER(); \
|
||||
if (output_file && dbg_master_switch) \
|
||||
{ \
|
||||
DBG_printf_c99(defdbgchan,DLI_ASSERT,TRUE,__FILE__,__LINE__,__VA_ARGS__); \
|
||||
DBG_printf(defdbgchan,DLI_ASSERT,TRUE,__FUNCTION__,__FILE__,__LINE__,__VA_ARGS__); \
|
||||
} \
|
||||
if(g_Dbg_asserts_enabled) \
|
||||
{ \
|
||||
PAL_Leave(); \
|
||||
DebugBreak(); \
|
||||
} \
|
||||
}
|
||||
|
@ -432,17 +376,6 @@ bool DBG_ShouldCheckStackAlignment();
|
|||
|
||||
#endif /* !_DEBUG */
|
||||
|
||||
#else /* __STDC_VERSION__ */
|
||||
/* Not GNU C, not C99 :
|
||||
possible work around for the lack of variable-argument macros:
|
||||
by using 2 function calls; must wrap the whole thing in a critical
|
||||
section to avoid interleaved output from multiple threads */
|
||||
|
||||
#error The compiler is missing support for variable-argument macros.
|
||||
|
||||
#endif /* __STDC_VERSION__*/
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
/* Function declarations */
|
||||
|
||||
/*++
|
||||
|
@ -495,42 +428,7 @@ BOOL DBG_preprintf(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
|||
|
||||
/*++
|
||||
Function :
|
||||
DBG_printf_gcc
|
||||
|
||||
Internal function for debug channels; don't use.
|
||||
This function outputs a complete debug message, including the function name.
|
||||
|
||||
Parameters :
|
||||
DBG_CHANNEL_ID channel : debug channel to use
|
||||
DBG_LEVEL_ID level : debug message level
|
||||
BOOL bHeader : whether or not to output message header (thread id, etc)
|
||||
LPSTR function : current function
|
||||
LPSTR file : current file
|
||||
INT line : line number
|
||||
LPSTR format, ... : standard printf parameter list.
|
||||
|
||||
Return Value :
|
||||
always 1.
|
||||
|
||||
Notes :
|
||||
This version is for gnu compilers that support variable-argument macros
|
||||
and the __FUNCTION__ pseudo-macro.
|
||||
|
||||
--*/
|
||||
#if __GNUC__ && CHECK_TRACE_SPECIFIERS
|
||||
/* if requested, use an __attribute__ feature to ask gcc to check that format
|
||||
specifiers match their parameters */
|
||||
int DBG_printf_gcc(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
||||
LPCSTR function, LPCSTR file, INT line, LPCSTR format, ...)
|
||||
__attribute__ ((format (printf,7, 8)));
|
||||
#else
|
||||
int DBG_printf_gcc(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
||||
LPCSTR function, LPCSTR file, INT line, LPCSTR format, ...);
|
||||
#endif
|
||||
|
||||
/*++
|
||||
Function :
|
||||
DBG_printf_c99
|
||||
DBG_printf
|
||||
|
||||
Internal function for debug channels; don't use.
|
||||
This function outputs a complete debug message, without function name.
|
||||
|
@ -539,21 +437,30 @@ Parameters :
|
|||
DBG_CHANNEL_ID channel : debug channel to use
|
||||
DBG_LEVEL_ID level : debug message level
|
||||
BOOL bHeader : whether or not to output message header (thread id, etc)
|
||||
LPSTR file : current file
|
||||
LPCSTR function : current function
|
||||
LPCSTR file : current file
|
||||
INT line : line number
|
||||
LPSTR format, ... : standard printf parameter list.
|
||||
LPCSTR format, ... : standard printf parameter list.
|
||||
|
||||
Return Value :
|
||||
always 1.
|
||||
|
||||
Notes :
|
||||
This version is for compilers that support the C99 flavor of
|
||||
variable-argument macros but not the gnu flavor, and do not support the
|
||||
__FUNCTION__ pseudo-macro.
|
||||
This function requires that the compiler support the C99 flavor of
|
||||
variable-argument macros, and that they support the __FUNCTION__
|
||||
pseudo-macro.
|
||||
|
||||
--*/
|
||||
int DBG_printf_c99(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
||||
LPSTR file, INT line, LPSTR format, ...);
|
||||
#if __GNUC__ && CHECK_TRACE_SPECIFIERS
|
||||
/* if requested, use an __attribute__ feature to ask gcc to check that format
|
||||
specifiers match their parameters */
|
||||
int DBG_printf(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
||||
LPCSTR function, LPCSTR file, INT line, LPCSTR format, ...)
|
||||
__attribute__ ((format (printf,7, 8)));
|
||||
#else
|
||||
int DBG_printf(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
||||
LPCSTR function, LPCSTR file, INT line, LPCSTR format, ...);
|
||||
#endif
|
||||
|
||||
/*++
|
||||
Function :
|
||||
|
|
|
@ -12,9 +12,9 @@ Module Name:
|
|||
|
||||
Abstract:
|
||||
|
||||
Rotor Platform Adaptation Layer (PAL) header file used by source
|
||||
Platform Adaptation Layer (PAL) header file used by source
|
||||
file part of the PAL implementation. This is a wrapper over
|
||||
unix/inc/pal.h. It allows avoiding name collisions when including
|
||||
pal/inc/pal.h. It allows avoiding name collisions when including
|
||||
system header files, and it allows redirecting calls to 'standard' functions
|
||||
to their PAL counterpart
|
||||
|
||||
|
|
|
@ -40,11 +40,11 @@ SET_DEFAULT_DEBUG_CHANNEL(LOADER);
|
|||
Internal wrapper for dladder used only to get module name
|
||||
|
||||
Parameters:
|
||||
None
|
||||
LPVOID ProcAddress: a pointer to a function in a shared library
|
||||
|
||||
Return value:
|
||||
Pointer to string with the fullpath to the librotor_pal.so being
|
||||
used.
|
||||
Pointer to string with the fullpath to the shared library containing
|
||||
ProcAddress.
|
||||
|
||||
NULL if error occurred.
|
||||
|
||||
|
|
|
@ -314,7 +314,7 @@ Notes :
|
|||
"pseudo code pages", like CP_ACP, aren't considered 'valid' in this context.
|
||||
CP_UTF7 and CP_UTF8, however, *are* considered valid code pages, even though
|
||||
MSDN fails to mention them in the IsValidCodePage entry.
|
||||
Note : CP_UTF7 support isn't required for Rotor
|
||||
Note : CP_UTF7 support isn't required for SOS
|
||||
--*/
|
||||
BOOL
|
||||
PALAPI
|
||||
|
|
|
@ -23,6 +23,7 @@ SET_DEFAULT_DEBUG_CHANNEL(MISC);
|
|||
#define PROC_CGROUP_FILENAME "/proc/self/cgroup"
|
||||
#define PROC_STATM_FILENAME "/proc/self/statm"
|
||||
#define MEM_LIMIT_FILENAME "/memory.limit_in_bytes"
|
||||
#define MEM_USAGE_FILENAME "/memory.usage_in_bytes"
|
||||
#define CFS_QUOTA_FILENAME "/cpu.cfs_quota_us"
|
||||
#define CFS_PERIOD_FILENAME "/cpu.cfs_period_us"
|
||||
class CGroup
|
||||
|
@ -63,6 +64,27 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
bool GetPhysicalMemoryUsage(size_t *val)
|
||||
{
|
||||
char *mem_usage_filename = nullptr;
|
||||
bool result = false;
|
||||
|
||||
if (m_memory_cgroup_path == nullptr)
|
||||
return result;
|
||||
|
||||
size_t len = strlen(m_memory_cgroup_path);
|
||||
len += strlen(MEM_USAGE_FILENAME);
|
||||
mem_usage_filename = (char*)malloc(len+1);
|
||||
if (mem_usage_filename == nullptr)
|
||||
return result;
|
||||
|
||||
strcpy(mem_usage_filename, m_memory_cgroup_path);
|
||||
strcat(mem_usage_filename, MEM_USAGE_FILENAME);
|
||||
result = ReadMemoryValueFromFile(mem_usage_filename, val);
|
||||
free(mem_usage_filename);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GetCpuLimit(UINT *val)
|
||||
{
|
||||
long long quota;
|
||||
|
@ -384,15 +406,20 @@ PAL_GetRestrictedPhysicalMemoryLimit()
|
|||
|
||||
BOOL
|
||||
PALAPI
|
||||
PAL_GetWorkingSetSize(size_t* val)
|
||||
PAL_GetPhysicalMemoryUsed(size_t* val)
|
||||
{
|
||||
BOOL result = false;
|
||||
size_t linelen;
|
||||
char* line = nullptr;
|
||||
CGroup cgroup;
|
||||
|
||||
if (val == nullptr)
|
||||
return FALSE;
|
||||
|
||||
if (cgroup.GetPhysicalMemoryUsage(val))
|
||||
return TRUE;
|
||||
|
||||
// process resident set size.
|
||||
FILE* file = fopen(PROC_STATM_FILENAME, "r");
|
||||
if (file != nullptr && getline(&line, &linelen, file) != -1)
|
||||
{
|
||||
|
|
|
@ -442,10 +442,9 @@ static const void *DBG_get_module_id()
|
|||
#define MODULE_FORMAT
|
||||
#endif // FEATURE_PAL_SXS
|
||||
|
||||
|
||||
/*++
|
||||
Function :
|
||||
DBG_printf_gcc
|
||||
DBG_printf
|
||||
|
||||
Internal function for debug channels; don't use.
|
||||
This function outputs a complete debug message, including the function name.
|
||||
|
@ -454,21 +453,22 @@ Parameters :
|
|||
DBG_CHANNEL_ID channel : debug channel to use
|
||||
DBG_LEVEL_ID level : debug message level
|
||||
BOOL bHeader : whether or not to output message header (thread id, etc)
|
||||
LPSTR function : current function
|
||||
LPSTR file : current file
|
||||
LPCSTR function : current function
|
||||
LPCSTR file : current file
|
||||
INT line : line number
|
||||
LPSTR format, ... : standard printf parameter list.
|
||||
LPCSTR format, ... : standard printf parameter list.
|
||||
|
||||
Return Value :
|
||||
always 1.
|
||||
|
||||
Notes :
|
||||
This version is for gnu compilers that support variable-argument macros
|
||||
and the __FUNCTION__ pseudo-macro.
|
||||
This version is for compilers that support the C99 flavor of
|
||||
variable-argument macros but not the gnu flavor, and do not support the
|
||||
__FUNCTION__ pseudo-macro.
|
||||
|
||||
--*/
|
||||
int DBG_printf_gcc(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
||||
LPCSTR function, LPCSTR file, INT line, LPCSTR format, ...)
|
||||
int DBG_printf(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
||||
LPCSTR function, LPCSTR file, INT line, LPCSTR format, ...)
|
||||
{
|
||||
CHAR *buffer = (CHAR*)alloca(DBG_BUFFER_SIZE);
|
||||
CHAR indent[MAX_NESTING+1];
|
||||
|
@ -477,7 +477,6 @@ int DBG_printf_gcc(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
|||
va_list args;
|
||||
void *thread_id;
|
||||
int old_errno = 0;
|
||||
CPalThread *pthrCurrent = InternalGetCurrentThread();
|
||||
|
||||
old_errno = errno;
|
||||
|
||||
|
@ -495,7 +494,7 @@ int DBG_printf_gcc(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
|||
/* also print file name for ASSERTs, to match Win32 behavior */
|
||||
if( DLI_ENTRY == level || DLI_ASSERT == level || DLI_EXIT == level)
|
||||
{
|
||||
output_size=snprintf(buffer, DBG_BUFFER_SIZE,
|
||||
output_size=snprintf(buffer, DBG_BUFFER_SIZE,
|
||||
"{%p" MODULE_FORMAT "} %-5s [%-7s] at %s.%d: ",
|
||||
thread_id, MODULE_ID
|
||||
dbg_level_names[level], dbg_channel_names[channel], file, line);
|
||||
|
@ -507,10 +506,10 @@ int DBG_printf_gcc(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
|||
thread_id, MODULE_ID
|
||||
dbg_level_names[level], dbg_channel_names[channel], function, line);
|
||||
}
|
||||
|
||||
|
||||
if(output_size + 1 > DBG_BUFFER_SIZE)
|
||||
{
|
||||
fprintf(stderr, "ERROR : buffer overflow in DBG_printf_gcc");
|
||||
fprintf(stderr, "ERROR : buffer overflow in DBG_printf");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -530,21 +529,21 @@ int DBG_printf_gcc(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
|||
|
||||
if( output_size > DBG_BUFFER_SIZE )
|
||||
{
|
||||
fprintf(stderr, "ERROR : buffer overflow in DBG_printf_gcc");
|
||||
fprintf(stderr, "ERROR : buffer overflow in DBG_printf");
|
||||
}
|
||||
|
||||
/* Use a Critical section before calling printf code to
|
||||
avoid holding a libc lock while another thread is calling
|
||||
SuspendThread on this one. */
|
||||
|
||||
InternalEnterCriticalSection(pthrCurrent, &fprintf_crit_section);
|
||||
InternalEnterCriticalSection(NULL, &fprintf_crit_section);
|
||||
fprintf( output_file, "%s%s", indent, buffer );
|
||||
InternalLeaveCriticalSection(pthrCurrent, &fprintf_crit_section);
|
||||
InternalLeaveCriticalSection(NULL, &fprintf_crit_section);
|
||||
|
||||
/* flush the output to file */
|
||||
if ( fflush(output_file) != 0 )
|
||||
{
|
||||
fprintf(stderr, "ERROR : fflush() failed errno:%d (%s)\n",
|
||||
fprintf(stderr, "ERROR : fflush() failed errno:%d (%s)\n",
|
||||
errno, strerror(errno));
|
||||
}
|
||||
|
||||
|
@ -554,111 +553,7 @@ int DBG_printf_gcc(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
|||
|
||||
if ( old_errno != errno )
|
||||
{
|
||||
fprintf( stderr,"ERROR: errno changed by DBG_printf_gcc\n" );
|
||||
errno = old_errno;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*++
|
||||
Function :
|
||||
DBG_printf_c99
|
||||
|
||||
Internal function for debug channels; don't use.
|
||||
This function outputs a complete debug message, without function name.
|
||||
|
||||
Parameters :
|
||||
DBG_CHANNEL_ID channel : debug channel to use
|
||||
DBG_LEVEL_ID level : debug message level
|
||||
BOOL bHeader : whether or not to output message header (thread id, etc)
|
||||
LPSTR file : current file
|
||||
INT line : line number
|
||||
LPSTR format, ... : standard printf parameter list.
|
||||
|
||||
Return Value :
|
||||
always 1.
|
||||
|
||||
Notes :
|
||||
This version is for compilers that support the C99 flavor of
|
||||
variable-argument macros but not the gnu flavor, and do not support the
|
||||
__FUNCTION__ pseudo-macro.
|
||||
|
||||
--*/
|
||||
int DBG_printf_c99(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
|
||||
LPSTR file, INT line, LPSTR format, ...)
|
||||
{
|
||||
CHAR *buffer = (CHAR*)alloca(DBG_BUFFER_SIZE);
|
||||
CHAR indent[MAX_NESTING+1];
|
||||
LPSTR buffer_ptr;
|
||||
INT output_size;
|
||||
va_list args;
|
||||
static INT call_count=0;
|
||||
void *thread_id;
|
||||
int old_errno = 0;
|
||||
CPalThread *pthrCurrent = InternalGetCurrentThread();
|
||||
|
||||
old_errno = errno;
|
||||
|
||||
if(!DBG_get_indent(level, format, indent))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
thread_id= (void *)THREADSilentGetCurrentThreadId();
|
||||
|
||||
if(bHeader)
|
||||
{
|
||||
output_size=snprintf(buffer, DBG_BUFFER_SIZE,
|
||||
"{%p" MODULE_FORMAT "} %-5s [%-7s] at %s.%d: ", thread_id, MODULE_ID
|
||||
dbg_level_names[level], dbg_channel_names[channel],
|
||||
file, line);
|
||||
|
||||
if(output_size + 1 > DBG_BUFFER_SIZE)
|
||||
{
|
||||
fprintf(stderr, "ERROR : buffer overflow in DBG_printf_gcc");
|
||||
return 1;
|
||||
}
|
||||
|
||||
buffer_ptr=buffer+output_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
output_size = 0;
|
||||
buffer_ptr = buffer;
|
||||
}
|
||||
|
||||
va_start(args, format);
|
||||
output_size+=_vsnprintf_s(buffer_ptr, DBG_BUFFER_SIZE-output_size, _TRUNCATE,
|
||||
format, args);
|
||||
va_end(args);
|
||||
|
||||
if(output_size>DBG_BUFFER_SIZE)
|
||||
fprintf(stderr, "ERROR : buffer overflow in DBG_printf_c99");
|
||||
|
||||
/* Use a Critical section before calling printf code to
|
||||
avoid holding a libc lock while another thread is calling
|
||||
SuspendThread on this one. */
|
||||
|
||||
InternalEnterCriticalSection(pthrCurrent, &fprintf_crit_section);
|
||||
fprintf( output_file, "%s", buffer );
|
||||
InternalLeaveCriticalSection(pthrCurrent, &fprintf_crit_section);
|
||||
|
||||
/* flush the output to file every once in a while */
|
||||
call_count++;
|
||||
if(call_count>5)
|
||||
{
|
||||
call_count=0;
|
||||
if ( fflush(output_file) != 0 )
|
||||
{
|
||||
fprintf(stderr, "ERROR : fflush() failed errno:%d (%s)\n",
|
||||
errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
if ( old_errno != errno )
|
||||
{
|
||||
fprintf( stderr, "ERROR: DBG_printf_c99 changed the errno.\n" );
|
||||
fprintf( stderr,"ERROR: errno changed by DBG_printf\n" );
|
||||
errno = old_errno;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче