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
7 changes: 4 additions & 3 deletions docs/design/datacontracts/AuxiliarySymbols.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Contract AuxiliarySymbols

This contract provides name resolution for helper functions whose executing code
resides at dynamically-determined addresses.
This contract provides name resolution for helper functions. It may include other functions in the future but at minimum it has functions:
* whose executing code resides at dynamically-determined addresses or
* that are native helpers used to implement new.

## APIs of contract

Expand All @@ -20,7 +21,7 @@ bool TryGetAuxiliarySymbolName(TargetPointer ip, out string symbolName);
| Data Descriptor | Field | Type | Meaning |
| --- | --- | --- | --- |
| `AuxiliarySymbolInfo` | *(type size)* | `uint32` | Size in bytes of each entry in the auxiliary symbol array |
| `AuxiliarySymbolInfo` | `Address` | `CodePointer` | Code pointer to the dynamically-located helper function |
| `AuxiliarySymbolInfo` | `Address` | `CodePointer` | Code pointer to the helper function |
| `AuxiliarySymbolInfo` | `Name` | `pointer` | Pointer to a null-terminated char string with the helper name |

### Global variables used
Expand Down
2 changes: 1 addition & 1 deletion docs/design/datacontracts/data-descriptor-meanings.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"AsyncMethodData.Signature": "The async variant's signature (see `Signature`)",
"AsyncMethodData.Size": "Size of the async method data, added when HasAsyncMethodData flag is set",
"AsyncResumeInfo.DiagnosticIP": "Native IP into the resumed method used for diagnostics (may be null)",
"AuxiliarySymbolInfo.Address": "Code pointer to the dynamically-located helper function",
"AuxiliarySymbolInfo.Address": "Code pointer to the helper function",
"AuxiliarySymbolInfo.Name": "Pointer to a null-terminated char string with the helper name",
"AuxiliarySymbolInfo.Size": "Size in bytes of each entry in the auxiliary symbol array",
"Bucket.Keys": "Array of keys of `HashMapSlotsPerBucket` length",
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/jitinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,7 @@ struct VMAUXILIARYSYMBOLDEF
PTR_CSTR name;
};

#define MAX_AUXILIARY_SYMBOLS 7
#define MAX_AUXILIARY_SYMBOLS 17

#if defined(DACCESS_COMPILE)

Expand Down
32 changes: 32 additions & 0 deletions src/coreclr/vm/jitinterfacegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@
#include "ecall.h"
#include "writebarriermanager.h"

static void SetJitHelperAuxiliarySymbol(CorInfoHelpFunc ftnNum, const char* name)
{
LIMITED_METHOD_CONTRACT;

VMHELPDEF const& helperDef = hlpFuncTable[ftnNum];
PCODE pfnHelper = helperDef.pfnHelper;
DynamicCorInfoHelpFunc dynamicFtnNum;
if (helperDef.IsDynamicHelper(&dynamicFtnNum))
{
pfnHelper = hlpDynamicFuncTable[dynamicFtnNum].pfnHelper;
}

if (pfnHelper != (PCODE)NULL)
{
SetAuxiliarySymbol((void*)pfnHelper, name);
}
}

void InitJITAllocationHelpers()
{
STANDARD_VM_CONTRACT;
Expand Down Expand Up @@ -57,4 +75,18 @@ void InitJITAllocationHelpers()
#endif
}
}

// Debugger depends on new helper names starting with CORINFO_HELP_NEW
#define SET_NEW_HELPER_AUXILIARY_SYMBOL(code) SetJitHelperAuxiliarySymbol(code, #code);
Comment thread
rcj1 marked this conversation as resolved.
SET_NEW_HELPER_AUXILIARY_SYMBOL(CORINFO_HELP_NEWFAST)
SET_NEW_HELPER_AUXILIARY_SYMBOL(CORINFO_HELP_NEWFAST_MAYBEFROZEN)
SET_NEW_HELPER_AUXILIARY_SYMBOL(CORINFO_HELP_NEWSFAST)
SET_NEW_HELPER_AUXILIARY_SYMBOL(CORINFO_HELP_NEWSFAST_ALIGN8)
SET_NEW_HELPER_AUXILIARY_SYMBOL(CORINFO_HELP_NEWSFAST_ALIGN8_VC)
SET_NEW_HELPER_AUXILIARY_SYMBOL(CORINFO_HELP_NEWARR_1_DIRECT)
SET_NEW_HELPER_AUXILIARY_SYMBOL(CORINFO_HELP_NEWARR_1_MAYBEFROZEN)
SET_NEW_HELPER_AUXILIARY_SYMBOL(CORINFO_HELP_NEWARR_1_PTR)
SET_NEW_HELPER_AUXILIARY_SYMBOL(CORINFO_HELP_NEWARR_1_VC)
SET_NEW_HELPER_AUXILIARY_SYMBOL(CORINFO_HELP_NEWARR_1_ALIGN8)
#undef SET_NEW_HELPER_AUXILIARY_SYMBOL
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using Microsoft.Diagnostics.DataContractReader.Contracts;
using Microsoft.Diagnostics.DataContractReader.TestInfrastructure;
using Xunit;

namespace Microsoft.Diagnostics.DataContractReader.DumpTests;

public class AuxiliarySymbolsDumpTests : DumpTestBase
{
protected override string DebuggeeName => "BasicThreads";
protected override string DumpType => "full";

[ConditionalTheory]
[MemberData(nameof(TestConfigurations))]
[SkipOnVersion("net10.0", "Allocation helpers are not included in the .NET 10 auxiliary symbol table")]
public void JitHelpersAreReachableByAddress(TestConfiguration config)
{
InitializeDumpTest(config);

HashSet<string> expectedHelpers =
[
"CORINFO_HELP_NEWFAST",
"CORINFO_HELP_NEWFAST_MAYBEFROZEN",
"CORINFO_HELP_NEWSFAST",
"CORINFO_HELP_NEWSFAST_ALIGN8",
"CORINFO_HELP_NEWSFAST_ALIGN8_VC",
"CORINFO_HELP_NEWARR_1_DIRECT",
"CORINFO_HELP_NEWARR_1_MAYBEFROZEN",
"CORINFO_HELP_NEWARR_1_PTR",
"CORINFO_HELP_NEWARR_1_VC",
"CORINFO_HELP_NEWARR_1_ALIGN8",
];
Dictionary<TargetCodePointer, string> helpersByAddress = [];

TargetPointer table = Target.ReadGlobalPointer(Constants.Globals.AuxiliarySymbols);
uint count = Target.Read<uint>(Target.ReadGlobalPointer(Constants.Globals.AuxiliarySymbolCount));
Target.TypeInfo typeInfo = Target.GetTypeInfo(DataType.AuxiliarySymbolInfo);
uint entrySize = typeInfo.Size!.Value;
int addressOffset = typeInfo.Fields["Address"].Offset;
int nameOffset = typeInfo.Fields["Name"].Offset;

for (uint i = 0; i < count; i++)
{
TargetPointer entry = table + ((ulong)i * entrySize);
TargetPointer namePointer = Target.ReadPointer(entry + (ulong)nameOffset);
string name = Target.ReadUtf8String(namePointer);
if (expectedHelpers.Remove(name))
{
TargetCodePointer address = Target.ReadCodePointer(entry + (ulong)addressOffset);
Assert.NotEqual(TargetCodePointer.Null, address);
helpersByAddress.TryAdd(address, name);
}
}

Assert.Empty(expectedHelpers);
foreach ((TargetCodePointer address, string expectedName) in helpersByAddress)
{
Assert.True(Target.Contracts.AuxiliarySymbols.TryGetAuxiliarySymbolName(address.AsTargetPointer, out string? name));
Assert.Equal(expectedName, name);
}
}
}
Loading