Skip to content

Commit

Permalink
Update native code to upstream tag v2.4.0 (#3178)
Browse files Browse the repository at this point in the history
* Use IsShutdownRequested to avoid recursive lock acquisition

Changes from DataDog/dd-trace-dotnet@40d6d6a

* Move EnumNgenModuleMethodsInliningThisMethod call from the background thread

Changes from DataDog/dd-trace-dotnet@3ff5c49

* Add regression tests for running in partial trust environments (only native code changes)

Changes from DataDog/dd-trace-dotnet@9855be8
adjusted to changes from 909fe3e

* Refactorings to avoid merge conflicts with the Live Debugger

Changes from DataDog/dd-trace-dotnet@2d16f74 adjusted by 4d5167f#diff-8bf37bfc95dfd31f530857af76bf993aa717e988084918f54a228d2242ef39d6R171-R173
and dropped enableByRefInstrumentation and enableCallTargetStateByRef (always true)

* Refactor all EnumNgenModuleMethodsInliningThisMethod call sites

Changes from DataDog/dd-trace-dotnet@579d516
  • Loading branch information
Kielek authored Dec 11, 2023
1 parent 2d23c1a commit 5ff9a44
Show file tree
Hide file tree
Showing 15 changed files with 1,185 additions and 984 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ add_library("OpenTelemetry.AutoInstrumentation.Native.static" STATIC
rejit_work_offloader.cpp
environment_variables_util.cpp
method_rewriter.cpp
tracer_tokens.cpp
lib/coreclr/src/pal/prebuilt/idl/corprof_i.cpp
# Source dependencies retrievied via additional commands using git
${OUTPUT_DEPS_DIR}/fmt/libfmt.a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@
<ClInclude Include="startup_hook.h" />
<ClInclude Include="stats.h" />
<ClInclude Include="string.h" />
<ClInclude Include="tracer_tokens.h" />
<ClInclude Include="util.h" />
<ClInclude Include="version.h" />
</ItemGroup>
Expand All @@ -232,6 +233,7 @@
<ClCompile Include="rejit_preprocessor.cpp" />
<ClCompile Include="rejit_work_offloader.cpp" />
<ClCompile Include="string.cpp" />
<ClCompile Include="tracer_tokens.cpp" />
<ClCompile Include="util.cpp" />
</ItemGroup>
<ItemGroup>
Expand Down
962 changes: 184 additions & 778 deletions src/OpenTelemetry.AutoInstrumentation.Native/calltarget_tokens.cpp

Large diffs are not rendered by default.

64 changes: 26 additions & 38 deletions src/OpenTelemetry.AutoInstrumentation.Native/calltarget_tokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
#include "integration.h"
#include "string.h" // NOLINT

#define FASTPATH_COUNT 9

namespace trace
{

Expand All @@ -30,61 +28,63 @@ namespace trace
class CallTargetTokens
{
private:
// The variables 'enable_by_ref_instrumentation' and 'enable_calltarget_state_by_ref' will always be true,
// but instead of removing them and the conditional branches they affect, we will keep the variables to make
// future upstream pulls easier.
ModuleMetadata* module_metadata_ptr = nullptr;
const bool enable_by_ref_instrumentation = true;
const bool enable_calltarget_state_by_ref = true;

// CorLib tokens
mdAssemblyRef corLibAssemblyRef = mdAssemblyRefNil;
mdTypeRef objectTypeRef = mdTypeRefNil;
mdTypeRef exTypeRef = mdTypeRefNil;
mdTypeRef typeRef = mdTypeRefNil;
mdTypeRef runtimeTypeHandleRef = mdTypeRefNil;
mdToken getTypeFromHandleToken = mdTokenNil;
mdTypeRef runtimeMethodHandleRef = mdTypeRefNil;

// CallTarget tokens
mdAssemblyRef profilerAssemblyRef = mdAssemblyRefNil;
mdTypeRef callTargetTypeRef = mdTypeRefNil;
mdTypeRef callTargetStateTypeRef = mdTypeRefNil;
mdTypeRef callTargetReturnVoidTypeRef = mdTypeRefNil;
mdTypeRef callTargetReturnTypeRef = mdTypeRefNil;

mdMemberRef beginArrayMemberRef = mdMemberRefNil;
mdMemberRef beginMethodFastPathRefs[FASTPATH_COUNT];
mdMemberRef endVoidMemberRef = mdMemberRefNil;

mdMemberRef logExceptionRef = mdMemberRefNil;

mdMemberRef callTargetStateTypeGetDefault = mdMemberRefNil;
mdMemberRef callTargetReturnVoidTypeGetDefault = mdMemberRefNil;
mdMemberRef getDefaultMemberRef = mdMemberRefNil;

ModuleMetadata* GetMetadata();
HRESULT EnsureCorLibTokens();
HRESULT EnsureBaseCalltargetTokens();
mdTypeRef GetTargetStateTypeRef();
mdTypeRef GetTargetVoidReturnTypeRef();
mdTypeSpec GetTargetReturnValueTypeRef(FunctionMethodArgument* returnArgument);
mdMemberRef GetCallTargetStateDefaultMemberRef();
mdMemberRef GetCallTargetReturnVoidDefaultMemberRef();
mdMemberRef GetCallTargetReturnValueDefaultMemberRef(mdTypeSpec callTargetReturnTypeSpec);
mdMethodSpec GetCallTargetDefaultValueMethodSpec(FunctionMethodArgument* methodArgument);
mdToken GetCurrentTypeRef(const TypeInfo* currentType, bool& isValueType);
mdMethodSpec GetCallTargetDefaultValueMethodSpec(TypeSignature* methodArgument);

HRESULT ModifyLocalSig(ILRewriter* reWriter, FunctionMethodArgument* methodReturnValue, ULONG* callTargetStateIndex,
HRESULT ModifyLocalSig(ILRewriter* reWriter, TypeSignature* methodReturnValue, ULONG* callTargetStateIndex,
ULONG* exceptionIndex, ULONG* callTargetReturnIndex, ULONG* returnValueIndex,
mdToken* callTargetStateToken, mdToken* exceptionToken, mdToken* callTargetReturnToken);

HRESULT WriteBeginMethodWithArgumentsArray(void* rewriterWrapperPtr, mdTypeRef integrationTypeRef,
const TypeInfo* currentType, ILInstr** instruction);

public:
CallTargetTokens(ModuleMetadata* module_metadata_ptr);
protected:
// The variables 'enable_by_ref_instrumentation' and 'enable_calltarget_state_by_ref' will always be true,
// but instead of removing them and the conditional branches they affect, we will keep the variables to make
// future upstream pulls easier.
const bool enable_by_ref_instrumentation = true;
const bool enable_calltarget_state_by_ref = true;
mdTypeRef callTargetTypeRef = mdTypeRefNil;
mdTypeRef callTargetStateTypeRef = mdTypeRefNil;
mdTypeRef callTargetReturnVoidTypeRef = mdTypeRefNil;
mdTypeRef callTargetReturnTypeRef = mdTypeRefNil;
mdTypeRef exTypeRef = mdTypeRefNil;

ModuleMetadata* GetMetadata();
HRESULT EnsureBaseCalltargetTokens();
mdTypeSpec GetTargetReturnValueTypeRef(TypeSignature* returnArgument);
mdToken GetCurrentTypeRef(const TypeInfo* currentType, bool& isValueType);

virtual const WSTRING& GetCallTargetType() = 0;
virtual const WSTRING& GetCallTargetStateType() = 0;
virtual const WSTRING& GetCallTargetReturnType() = 0;
virtual const WSTRING& GetCallTargetReturnGenericType() = 0;

CallTargetTokens(ModuleMetadata* moduleMetadataPtr);

public:
mdTypeRef GetObjectTypeRef();
mdTypeRef GetExceptionTypeRef();
mdAssemblyRef GetCorLibAssemblyRef();
Expand All @@ -95,18 +95,6 @@ class CallTargetTokens
mdToken* callTargetStateToken, mdToken* exceptionToken,
mdToken* callTargetReturnToken, ILInstr** firstInstruction);

HRESULT WriteBeginMethod(void* rewriterWrapperPtr, mdTypeRef integrationTypeRef, const TypeInfo* currentType,
const std::vector<FunctionMethodArgument>& methodArguments, ILInstr** instruction);

HRESULT WriteEndVoidReturnMemberRef(void* rewriterWrapperPtr, mdTypeRef integrationTypeRef,
const TypeInfo* currentType, ILInstr** instruction);

HRESULT WriteEndReturnMemberRef(void* rewriterWrapperPtr, mdTypeRef integrationTypeRef, const TypeInfo* currentType,
FunctionMethodArgument* returnArgument, ILInstr** instruction);

HRESULT WriteLogException(void* rewriterWrapperPtr, mdTypeRef integrationTypeRef, const TypeInfo* currentType,
ILInstr** instruction);

HRESULT WriteCallTargetReturnGetReturnValue(void* rewriterWrapperPtr, mdTypeSpec callTargetReturnTypeSpec,
ILInstr** instruction);
};
Expand Down
78 changes: 60 additions & 18 deletions src/OpenTelemetry.AutoInstrumentation.Native/clr_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,23 +340,24 @@ HRESULT GetCorLibAssemblyRef(const ComPtr<IMetaDataAssemblyEmit>& assembly_emit,
}
}

// FunctionMethodArgument
int FunctionMethodArgument::GetTypeFlags(unsigned& elementType) const
// TypeSignature
std::tuple<unsigned, int> TypeSignature::GetElementTypeAndFlags() const
{
int flag = 0;
int typeFlags = 0;
unsigned elementType;

PCCOR_SIGNATURE pbCur = &pbBase[offset];

if (*pbCur == ELEMENT_TYPE_VOID)
{
elementType = ELEMENT_TYPE_VOID;
flag |= TypeFlagVoid;
return flag;
typeFlags |= TypeFlagVoid;
}

if (*pbCur == ELEMENT_TYPE_BYREF)
{
pbCur++;
flag |= TypeFlagByRef;
typeFlags |= TypeFlagByRef;
}

elementType = *pbCur;
Expand All @@ -380,22 +381,22 @@ int FunctionMethodArgument::GetTypeFlags(unsigned& elementType) const
case ELEMENT_TYPE_VALUETYPE:
case ELEMENT_TYPE_MVAR:
case ELEMENT_TYPE_VAR:
flag |= TypeFlagBoxedType;
typeFlags |= TypeFlagBoxedType;
break;
case ELEMENT_TYPE_GENERICINST:
pbCur++;
if (*pbCur == ELEMENT_TYPE_VALUETYPE)
{
flag |= TypeFlagBoxedType;
typeFlags |= TypeFlagBoxedType;
}
break;
default:
break;
}
return flag;
return {elementType, typeFlags};
}

mdToken FunctionMethodArgument::GetTypeTok(ComPtr<IMetaDataEmit2>& pEmit, mdAssemblyRef corLibRef) const
mdToken TypeSignature::GetTypeTok(ComPtr<IMetaDataEmit2>& pEmit, mdAssemblyRef corLibRef) const
{
mdToken token = mdTokenNil;
PCCOR_SIGNATURE pbCur = &pbBase[offset];
Expand Down Expand Up @@ -612,13 +613,13 @@ WSTRING GetSigTypeTokName(PCCOR_SIGNATURE& pbCur, const ComPtr<IMetaDataImport2>
return tokenName;
}

WSTRING FunctionMethodArgument::GetTypeTokName(ComPtr<IMetaDataImport2>& pImport) const
WSTRING TypeSignature::GetTypeTokName(ComPtr<IMetaDataImport2>& pImport) const
{
PCCOR_SIGNATURE pbCur = &pbBase[offset];
return GetSigTypeTokName(pbCur, pImport);
}

ULONG FunctionMethodArgument::GetSignature(PCCOR_SIGNATURE& data) const
ULONG TypeSignature::GetSignature(PCCOR_SIGNATURE& data) const
{
data = &pbBase[offset];
return length;
Expand Down Expand Up @@ -839,7 +840,7 @@ bool ParseType(PCCOR_SIGNATURE& pbCur, PCCOR_SIGNATURE pbEnd)

// Param ::= CustomMod* ( TYPEDBYREF | [BYREF] Type )
// CustomMod* TYPEDBYREF we don't support
bool ParseParam(PCCOR_SIGNATURE& pbCur, PCCOR_SIGNATURE pbEnd)
bool ParseParamOrLocal(PCCOR_SIGNATURE& pbCur, PCCOR_SIGNATURE pbEnd)
{
if (*pbCur == ELEMENT_TYPE_CMOD_OPT || *pbCur == ELEMENT_TYPE_CMOD_REQD)
{
Expand Down Expand Up @@ -905,9 +906,9 @@ HRESULT FunctionMethodSignature::TryParse()
const PCCOR_SIGNATURE pbRet = pbCur;

IfFalseRetFAIL(ParseRetType(pbCur, pbEnd));
ret.pbBase = pbBase;
ret.length = (ULONG)(pbCur - pbRet);
ret.offset = (ULONG)(pbCur - pbBase - ret.length);
returnValue.pbBase = pbBase;
returnValue.length = (ULONG)(pbCur - pbRet);
returnValue.offset = (ULONG)(pbCur - pbBase - returnValue.length);

auto fEncounteredSentinal = false;
for (unsigned i = 0; i < param_count; i++)
Expand All @@ -926,9 +927,9 @@ HRESULT FunctionMethodSignature::TryParse()

const PCCOR_SIGNATURE pbParam = pbCur;

IfFalseRetFAIL(ParseParam(pbCur, pbEnd));
IfFalseRetFAIL(ParseParamOrLocal(pbCur, pbEnd));

FunctionMethodArgument argument{};
TypeSignature argument{};
argument.pbBase = pbBase;
argument.length = (ULONG)(pbCur - pbParam);
argument.offset = (ULONG)(pbCur - pbBase - argument.length);
Expand Down Expand Up @@ -984,4 +985,45 @@ bool FindTypeDefByName(const trace::WSTRING instrumentationTargetMeth

return true;
}

// FunctionLocalSignature
HRESULT FunctionLocalSignature::TryParse(PCCOR_SIGNATURE pbBase, unsigned len, std::vector<TypeSignature>& locals)
{
PCCOR_SIGNATURE pbCur = pbBase;
PCCOR_SIGNATURE pbEnd = pbBase + len;

BYTE temp;
unsigned get_locals_count;

const int LocalVarSig = 0x07;

IfFalseRetFAIL(ParseByte(pbCur, pbEnd, &temp));
if (temp != LocalVarSig)
{
// Not a LocalVarSig
return E_FAIL;
}

// Number of locals - 1 to 0xFFFE (65534)
IfFalseRetFAIL(ParseNumber(pbCur, pbEnd, &get_locals_count));

for (unsigned i = 0; i < get_locals_count; i++)
{
if (pbCur >= pbEnd)
return E_FAIL;

const PCCOR_SIGNATURE pbLocal = pbCur;

IfFalseRetFAIL(ParseParamOrLocal(pbCur, pbEnd));

TypeSignature local{};
local.pbBase = pbBase;
local.length = (ULONG)(pbCur - pbLocal);
local.offset = (ULONG)(pbCur - pbBase - local.length);

locals.push_back(local);
}
return S_OK;
}

} // namespace trace
56 changes: 49 additions & 7 deletions src/OpenTelemetry.AutoInstrumentation.Native/clr_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,14 +407,16 @@ enum MethodArgumentTypeFlag
TypeFlagBoxedType = 0x04
};

struct FunctionMethodArgument
// Represents a segment inside a larger signature (Method Signature / Local Var Signature) of
// an Argument, Local or Return Value.
struct TypeSignature
{
ULONG offset;
ULONG length;
PCCOR_SIGNATURE pbBase;
mdToken GetTypeTok(ComPtr<IMetaDataEmit2>& pEmit, mdAssemblyRef corLibRef) const;
WSTRING GetTypeTokName(ComPtr<IMetaDataImport2>& pImport) const;
int GetTypeFlags(unsigned& elementType) const;
std::tuple<unsigned, int> GetElementTypeAndFlags() const;
ULONG GetSignature(PCCOR_SIGNATURE& data) const;
};

Expand All @@ -425,8 +427,8 @@ struct FunctionMethodSignature
unsigned len;
ULONG numberOfTypeArguments = 0;
ULONG numberOfArguments = 0;
FunctionMethodArgument ret{};
std::vector<FunctionMethodArgument> params;
TypeSignature returnValue{};
std::vector<TypeSignature> params;

public:
FunctionMethodSignature() : pbBase(nullptr), len(0)
Expand All @@ -449,11 +451,11 @@ struct FunctionMethodSignature
{
return HexStr(pbBase, len);
}
FunctionMethodArgument GetRet() const
TypeSignature GetReturnValue() const
{
return ret;
return returnValue;
}
std::vector<FunctionMethodArgument> GetMethodArguments() const
const std::vector<TypeSignature>& GetMethodArguments() const
{
return params;
}
Expand All @@ -472,6 +474,46 @@ struct FunctionMethodSignature
}
};

struct FunctionLocalSignature
{
private:
PCCOR_SIGNATURE pbBase;
unsigned len;
ULONG numberOfLocals = 0;
std::vector<TypeSignature> locals;

public:
FunctionLocalSignature() : pbBase(nullptr), len(0) {}
FunctionLocalSignature(PCCOR_SIGNATURE pb, unsigned cbBuffer, std::vector<TypeSignature>&& localsSigs)
: pbBase(pb)
, len(cbBuffer)
, numberOfLocals(static_cast<ULONG>(localsSigs.size()))
, locals(std::move(localsSigs))
{
}
ULONG NumberOfLocals() const
{
return numberOfLocals;
}
WSTRING str() const
{
return HexStr(pbBase, len);
}
const std::vector<TypeSignature>& GetMethodLocals() const
{
return locals;
}
static HRESULT TryParse(PCCOR_SIGNATURE pbBase, unsigned len, std::vector<TypeSignature>& locals);
bool operator==(const FunctionLocalSignature& other) const
{
return memcmp(pbBase, other.pbBase, len);
}
bool IsEmpty() const
{
return len == 0;
}
};

struct FunctionInfo
{
const mdToken id;
Expand Down
Loading

0 comments on commit 5ff9a44

Please sign in to comment.