summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorDavid Mason <davmason@microsoft.com>2019-06-17 07:04:19 -0700
committerGitHub <noreply@github.com>2019-06-17 07:04:19 -0700
commit3b624b202a37d16aeab5d747e6143af1b38e4ca3 (patch)
treec7ffa7845a65c52710ec2bb43e2451e19fcb9426 /src/vm
parentbfe4001c030ceadff6db116d84788118666f8600 (diff)
downloadcoreclr-3b624b202a37d16aeab5d747e6143af1b38e4ca3.tar.gz
coreclr-3b624b202a37d16aeab5d747e6143af1b38e4ca3.tar.bz2
coreclr-3b624b202a37d16aeab5d747e6143af1b38e4ca3.zip
Fix GetFunctionEnter3Info on linux (#25147)
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/amd64/asmhelpers.S21
-rw-r--r--src/vm/amd64/profiler.cpp119
-rw-r--r--src/vm/proftoeeinterfaceimpl.h7
3 files changed, 135 insertions, 12 deletions
diff --git a/src/vm/amd64/asmhelpers.S b/src/vm/amd64/asmhelpers.S
index 78b5185eed..0df6114d79 100644
--- a/src/vm/amd64/asmhelpers.S
+++ b/src/vm/amd64/asmhelpers.S
@@ -35,9 +35,12 @@
// UINT64 r8;
// UINT64 r9;
// UINT32 flags;
+// UINT64 buffer[PROFILE_PLATFORM_SPECIFIC_DATA_BUFFER_SIZE];
// } PROFILE_PLATFORM_SPECIFIC_DATA, *PPROFILE_PLATFORM_SPECIFIC_DATA;
-//
-.equ SIZEOF_PROFILE_PLATFORM_SPECIFIC_DATA, 0x8*22 + 0x8 // includes fudge to make FP_SPILL right
+
+// Buffer to copy structs sequentially
+.equ SIZEOF_PROFILE_STRUCT_BUFFER, 0x8*16
+.equ SIZEOF_PROFILE_PLATFORM_SPECIFIC_DATA, 0x8*22 + 0x8 + SIZEOF_PROFILE_STRUCT_BUFFER // includes fudge to make FP_SPILL right
.equ SIZEOF_FP_ARG_SPILL, 0x10*2
.equ SIZEOF_STACK_FRAME, SIZEOF_PROFILE_PLATFORM_SPECIFIC_DATA + SIZEOF_FP_ARG_SPILL
@@ -101,14 +104,14 @@ NESTED_ENTRY ProfileEnterNaked, _TEXT, NoHandler
movsd real8 ptr [rsp + 0x60], xmm5 // -- struct flt5 field
movsd real8 ptr [rsp + 0x68], xmm6 // -- struct flt6 field
movsd real8 ptr [rsp + 0x70], xmm7 // -- struct flt7 field
- mov [rsp + 0x78], rdi // -- struct rdi field
- mov [rsp + 0x80], rsi // -- struct rsi field
- mov [rsp + 0x88], rdx // -- struct rdx field
- mov [rsp + 0x90], rcx // -- struct rcx field
- mov [rsp + 0x98], r8 // -- struct r8 field
- mov [rsp + 0xa0], r9 // -- struct r9 field
+ mov [rsp + 0x78], rdi // -- struct rdi field
+ mov [rsp + 0x80], rsi // -- struct rsi field
+ mov [rsp + 0x88], rdx // -- struct rdx field
+ mov [rsp + 0x90], rcx // -- struct rcx field
+ mov [rsp + 0x98], r8 // -- struct r8 field
+ mov [rsp + 0xa0], r9 // -- struct r9 field
mov r10, 0x1 // PROFILE_ENTER
- mov [rsp + 0xa8], r10d // -- struct flags field
+ mov [rsp + 0xa8], r10d // -- struct flags field
// get aligned stack ptr (rsp + FRAME_SIZE) & (-16)
lea rax, [rsp + 0xb8]
diff --git a/src/vm/amd64/profiler.cpp b/src/vm/amd64/profiler.cpp
index 7dc1780c67..29b4d93898 100644
--- a/src/vm/amd64/profiler.cpp
+++ b/src/vm/amd64/profiler.cpp
@@ -14,6 +14,7 @@
#ifdef PROFILING_SUPPORTED
#include "proftoeeinterfaceimpl.h"
+#include "argdestination.h"
MethodDesc *FunctionIdToMethodDesc(FunctionID functionID);
@@ -23,6 +24,8 @@ MethodDesc *FunctionIdToMethodDesc(FunctionID functionID);
#define PROFILE_LEAVE 0x2
#define PROFILE_TAILCALL 0x4
+#define PROFILE_PLATFORM_SPECIFIC_DATA_BUFFER_SIZE 16
+
typedef struct _PROFILE_PLATFORM_SPECIFIC_DATA
{
FunctionID functionId;
@@ -49,6 +52,10 @@ typedef struct _PROFILE_PLATFORM_SPECIFIC_DATA
UINT64 r9;
#endif
UINT32 flags;
+#if defined(UNIX_AMD64_ABI)
+ // A buffer to copy structs in to so they are sequential for GetFunctionEnter3Info.
+ UINT64 buffer[PROFILE_PLATFORM_SPECIFIC_DATA_BUFFER_SIZE];
+#endif
} PROFILE_PLATFORM_SPECIFIC_DATA, *PPROFILE_PLATFORM_SPECIFIC_DATA;
@@ -118,6 +125,9 @@ ProfileArgIterator::ProfileArgIterator(MetaSig * pSig, void * platformSpecificHa
m_handle = platformSpecificHandle;
PROFILE_PLATFORM_SPECIFIC_DATA* pData = (PROFILE_PLATFORM_SPECIFIC_DATA*)m_handle;
+#ifdef UNIX_AMD64_ABI
+ m_bufferPos = 0;
+#endif // UNIX_AMD64_ABI
// unwind a frame and get the Rsp for the profiled method to make sure it matches
// what the JIT gave us
@@ -204,6 +214,84 @@ ProfileArgIterator::~ProfileArgIterator()
m_handle = NULL;
}
+#ifdef UNIX_AMD64_ABI
+LPVOID ProfileArgIterator::CopyStructFromRegisters()
+{
+ STATIC_CONTRACT_NOTHROW;
+ STATIC_CONTRACT_GC_NOTRIGGER;
+ STATIC_CONTRACT_FORBID_FAULT;
+ STATIC_CONTRACT_MODE_COOPERATIVE;
+
+
+ PROFILE_PLATFORM_SPECIFIC_DATA* pData = (PROFILE_PLATFORM_SPECIFIC_DATA*)m_handle;
+ ArgLocDesc *argLocDesc = m_argIterator.GetArgLocDescForStructInRegs();
+
+ LPVOID dest = (LPVOID)&pData->buffer[m_bufferPos];
+ BYTE* genRegSrc = (BYTE*)&pData->rdi + argLocDesc->m_idxGenReg * 8;
+ BYTE* floatRegSrc = (BYTE*)&pData->flt0 + argLocDesc->m_idxFloatReg * 8;
+
+ TypeHandle th;
+ m_argIterator.GetArgType(&th);
+ int fieldBytes = th.AsMethodTable()->GetNumInstanceFieldBytes();
+ INDEBUG(int remainingBytes = fieldBytes;)
+
+ EEClass* eeClass = argLocDesc->m_eeClass;
+ _ASSERTE(eeClass != NULL);
+
+ for (int i = 0; i < eeClass->GetNumberEightBytes(); i++)
+ {
+ int eightByteSize = eeClass->GetEightByteSize(i);
+ SystemVClassificationType eightByteClassification = eeClass->GetEightByteClassification(i);
+
+ _ASSERTE(remainingBytes >= eightByteSize);
+
+ if (eightByteClassification == SystemVClassificationTypeSSE)
+ {
+ if (eightByteSize == 8)
+ {
+ *(UINT64*)dest = *(UINT64*)floatRegSrc ;
+ }
+ else
+ {
+ _ASSERTE(eightByteSize == 4);
+ *(UINT32*)dest = *(UINT32*)floatRegSrc;
+ }
+ floatRegSrc += 8;
+ }
+ else
+ {
+ if (eightByteSize == 8)
+ {
+ _ASSERTE((eightByteClassification == SystemVClassificationTypeInteger) ||
+ (eightByteClassification == SystemVClassificationTypeIntegerReference) ||
+ (eightByteClassification == SystemVClassificationTypeIntegerByRef));
+
+ _ASSERTE(IS_ALIGNED((SIZE_T)genRegSrc, 8));
+ *(UINT64*)dest = *(UINT64*)genRegSrc;
+ }
+ else
+ {
+ _ASSERTE(eightByteClassification == SystemVClassificationTypeInteger);
+ memcpyNoGCRefs(dest, genRegSrc, eightByteSize);
+ }
+
+ genRegSrc += eightByteSize;
+ }
+
+ dest = (BYTE*)dest + eightByteSize;
+ INDEBUG(remainingBytes -= eightByteSize;)
+ }
+
+ _ASSERTE(remainingBytes == 0);
+ LPVOID destOrig = (LPVOID)&pData->buffer[m_bufferPos];
+ //Increase bufferPos by ceiling(fieldBytes/8)
+ m_bufferPos += (fieldBytes + 7) / 8;
+ _ASSERTE(m_bufferPos <= PROFILE_PLATFORM_SPECIFIC_DATA_BUFFER_SIZE);
+
+ return destOrig;
+}
+#endif // UNIX_AMD64_ABI
+
/*
* ProfileArgIterator::GetNextArgAddr
*
@@ -248,12 +336,36 @@ LPVOID ProfileArgIterator::GetNextArgAddr()
}
// if we're here we have an enregistered argument
+ CorElementType argType = m_argIterator.GetArgType();
+#if defined(UNIX_AMD64_ABI)
+ if (argOffset == TransitionBlock::StructInRegsOffset)
+ {
+ LPVOID argPtr = CopyStructFromRegisters();
+ return argPtr;
+ }
+ else
+ {
+ ArgLocDesc argLocDesc;
+ m_argIterator.GetArgLoc(argOffset, &argLocDesc);
+
+ if (argLocDesc.m_cFloatReg > 0)
+ {
+ return (LPBYTE)&pData->flt0 + (argLocDesc.m_idxFloatReg * 8);
+ }
+ else
+ {
+ // Stack arguments and float registers are already dealt with,
+ // so it better be a general purpose register
+ _ASSERTE(argLocDesc.m_cGenReg > 0);
+ return (LPBYTE)&pData->rdi + (argLocDesc.m_idxGenReg * 8);
+ }
+ }
+#else // UNIX_AMD64_ABI
unsigned int regStructOfs = (argOffset - TransitionBlock::GetOffsetOfArgumentRegisters());
_ASSERTE(regStructOfs < ARGUMENTREGISTERS_SIZE);
- CorElementType t = m_argIterator.GetArgType();
_ASSERTE(IS_ALIGNED(regStructOfs, sizeof(SLOT)));
- if (t == ELEMENT_TYPE_R4 || t == ELEMENT_TYPE_R8)
+ if (argType == ELEMENT_TYPE_R4 || argType == ELEMENT_TYPE_R8)
{
return (LPBYTE)&pData->flt0 + regStructOfs;
}
@@ -267,7 +379,8 @@ LPVOID ProfileArgIterator::GetNextArgAddr()
return pArg;
}
-
+#endif // UNIX_AMD64_ABI
+
return NULL;
}
diff --git a/src/vm/proftoeeinterfaceimpl.h b/src/vm/proftoeeinterfaceimpl.h
index 016b1f714b..335b4f7179 100644
--- a/src/vm/proftoeeinterfaceimpl.h
+++ b/src/vm/proftoeeinterfaceimpl.h
@@ -57,6 +57,9 @@ class ProfileArgIterator
private:
void *m_handle;
ArgIterator m_argIterator;
+#ifdef UNIX_AMD64_ABI
+ UINT64 m_bufferPos;
+#endif // UNIX_AMD64_ABI
public:
ProfileArgIterator(MetaSig * pMetaSig, void* platformSpecificHandle);
@@ -71,6 +74,10 @@ public:
LIMITED_METHOD_CONTRACT;
return m_argIterator.NumFixedArgs();
}
+
+#ifdef UNIX_AMD64_ABI
+ LPVOID CopyStructFromRegisters();
+#endif // UNIX_AMD64_ABI
//
// After initialization, this method is called repeatedly until it