diff options
author | David Mason <davmason@microsoft.com> | 2019-06-17 07:04:19 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-17 07:04:19 -0700 |
commit | 3b624b202a37d16aeab5d747e6143af1b38e4ca3 (patch) | |
tree | c7ffa7845a65c52710ec2bb43e2451e19fcb9426 /src/vm | |
parent | bfe4001c030ceadff6db116d84788118666f8600 (diff) | |
download | coreclr-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.S | 21 | ||||
-rw-r--r-- | src/vm/amd64/profiler.cpp | 119 | ||||
-rw-r--r-- | src/vm/proftoeeinterfaceimpl.h | 7 |
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 |