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:
Mike McLaughlin 2018-10-17 09:36:04 -07:00 коммит произвёл GitHub
Родитель c82d902d1a
Коммит b84277a43f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
41 изменённых файлов: 2532 добавлений и 2867 удалений

Просмотреть файл

@ -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;
}