Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
277 changes: 0 additions & 277 deletions src/coreclr/debug/dbgutil/dbgutil.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
//*****************************************************************************
// dbgutil.cpp
//

//
//*****************************************************************************

//
// Various common helpers for PE resource reading used by multiple debug components.
//

#include <dbgutil.h>
#include "corerror.h"
Expand Down Expand Up @@ -136,275 +128,6 @@ HRESULT GetMachineAndResourceSectionRVA(ICorDebugDataTarget* pDataTarget,
return GetMachineAndDirectoryAddress(pDataTarget, moduleBaseAddress, IMAGE_DIRECTORY_ENTRY_RESOURCE, pwImageFileMachine, pdwResourceSectionRVA);
}

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 successful 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 successful 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)u16_strlen(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;
}

#endif // HOST_WINDOWS

// A small wrapper that reads from the data target and throws on error
Expand Down
4 changes: 1 addition & 3 deletions src/coreclr/debug/di/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ set(CORDBDI_SOURCES
rsthread.cpp
rstype.cpp
shared.cpp
symbolinfo.cpp
valuehome.cpp
)

Expand All @@ -40,8 +39,7 @@ set(CORDBDI_HEADERS
nativepipeline.h
rsenumerator.hpp
rspriv.h
rspriv.inl
symbolinfo.h)
rspriv.inl)


if(CLR_CMAKE_HOST_WIN32)
Expand Down
Loading
Loading