This commit is contained in:
Mukul Sabharwal 2021-02-24 22:29:41 -08:00
Родитель b088b8375a
Коммит 2ddd9be429
24 изменённых файлов: 5910 добавлений и 5346 удалений

Просмотреть файл

@ -1,4 +1,5 @@
cmake_minimum_required (VERSION 3.10)
project(bperf)
cmake_minimum_required (VERSION 3.10)
include_directories(coreclr_headers/src/pal/prebuilt/inc)
include_directories(coreclr_headers/src/inc)
if(UNIX)

Просмотреть файл

@ -709,11 +709,19 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeRundown, W("EventPipeRundown"), 1, "E
RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeCircularMB, W("EventPipeCircularMB"), 1024, "The EventPipe circular buffer size in megabytes.")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeProcNumbers, W("EventPipeProcNumbers"), 0, "Enable/disable capturing processor numbers in EventPipe event headers")
//
// Generational Aware Analysis
//
RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisGen, W("GCGenAnalysisGen"), 0, "The generation to trigger generational aware analysis")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisBytes, W("GCGenAnalysisBytes"), 0, "The number of bytes to trigger generational aware analysis")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisIndex, W("GCGenAnalysisIndex"), 0, "The gc index to trigger generational aware analysis")
RETAIL_CONFIG_STRING_INFO(INTERNAL_GCGenAnalysisCmd, W("GCGenAnalysisCmd"), "An optional filter to match with the command line used to spawn the process")
//
// Diagnostics Server
// Diagnostics Ports
//
RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_DOTNET_DiagnosticsMonitorAddress, W("DOTNET_DiagnosticsMonitorAddress"), "NamedPipe path without '\\\\.\\pipe\\' on Windows; Full path of Unix Domain Socket on Linux/Unix. Used for Diagnostics Monitoring Agents.", CLRConfig::DontPrependCOMPlus_);
RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_DOTNET_DiagnosticsMonitorPauseOnStart, W("DOTNET_DiagnosticsMonitorPauseOnStart"), 1, "If DOTNET_DiagnosticsMonitorAddress is set, this will cause the runtime to pause during startup. Resume using the Diagnostics IPC ResumeStartup command.", CLRConfig::DontPrependCOMPlus_);
RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_DOTNET_DefaultDiagnosticPortSuspend, W("DOTNET_DefaultDiagnosticPortSuspend"), 0, "This sets the deafult diagnostic port to suspend causing the runtime to pause during startup before major subsystems are started. Resume using the Diagnostics IPC ResumeStartup command on the default diagnostic port.", CLRConfig::DontPrependCOMPlus_);
RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_DOTNET_DiagnosticPorts, W("DOTNET_DiagnosticPorts"), "A semicolon delimited list of additional Diagnostic Ports, where a Diagnostic Port is a NamedPipe path without '\\\\.\\pipe\\' on Windows or the full path of Unix Domain Socket on Linux/Unix followed by optional tags, e.g., '<path>,connect,nosuspend;<path>'", CLRConfig::DontPrependCOMPlus_);
//
// LTTng

Просмотреть файл

@ -159,6 +159,7 @@ interface ICorDebugReferenceValue;
interface ICorDebugHeapValue;
interface ICorDebugHeapValue2;
interface ICorDebugHeapValue3;
interface ICorDebugHeapValue4;
interface ICorDebugHandleValue;
interface ICorDebugObjectValue;
interface ICorDebugStringValue;
@ -1603,13 +1604,15 @@ typedef enum CorDebugCreateProcessFlags
/* ICorDebugHeapValue::CreateHandle takes a handle flavor.
* A strong handle will keep an object alive while a weak track resurrection
* will not.
* - A strong handle will keep an object alive while allowing GC relocation
* - A weak handle will not keep an object alive
* - A pinned handle will keep an object alive and disallow GC relocation
*/
typedef enum CorDebugHandleType
{
HANDLE_STRONG = 1,
HANDLE_WEAK_TRACK_RESURRECTION = 2
HANDLE_WEAK_TRACK_RESURRECTION = 2,
HANDLE_PINNED = 3
} CorDebugHandleType;
#pragma warning(push)
@ -3304,6 +3307,9 @@ interface ICorDebugProcess10 : IUnknown
// Enable or disable the GC notification events. The GC notification events are turned off by default
// They will be delivered through ICorDebugManagedCallback4
//
// This interface is deprecated. The EnableGCNotificationEvents(true) occasionally deadlocked debug sessions
// in .NET Core 5.0 and later. Please use the IID_ICorDebugHeapValue4 to pin an object and prevent its relocation
//
// Parameters
// fEnable - true to enable the events, false to disable
//
@ -6472,6 +6478,27 @@ interface ICorDebugHeapValue3 : IUnknown
HRESULT GetMonitorEventWaitList([out] ICorDebugThreadEnum **ppThreadEnum);
};
/*
* ICorDebugHeapValue4
*/
[
object,
local,
uuid(B35DD495-A555-463B-9BE9-C55338486BB8),
pointer_default(unique)
]
interface ICorDebugHeapValue4 : IUnknown
{
/*
* Creates a handle of the given type for this heap value.
*
*/
HRESULT CreatePinnedHandle([out] ICorDebugHandleValue ** ppHandle);
};
/*
* ICorDebugObjectValue is a subclass of ICorDebugValue which applies to
* values which contain an object.

Просмотреть файл

@ -115,6 +115,8 @@ struct AutoExpVisibleValue
template <typename TYPE>
class HolderBase
{
friend class ClrDataAccess;
protected:
TYPE m_value;
@ -227,6 +229,7 @@ template
>
class BaseHolder : protected BASE
{
friend class ClrDataAccess;
protected:
BOOL m_acquired; // Have we acquired the resource?
@ -695,6 +698,7 @@ FORCEINLINE void SafeArrayDoNothing(SAFEARRAY* p)
template <typename TYPE, void (*ACQUIREF)(TYPE), void (*RELEASEF)(TYPE)>
class FunctionBase : protected HolderBase<TYPE>
{
friend class ClrDataAccess;
protected:
FORCEINLINE FunctionBase(TYPE value)

Просмотреть файл

@ -424,3 +424,17 @@ interface ISOSDacInterface9 : IUnknown
{
HRESULT GetBreakingChangeVersion(int* pVersion);
}
[
object,
local,
uuid(90B8FCC3-7251-4B0A-AE3D-5C13A67EC9AA)
]
interface ISOSDacInterface10 : IUnknown
{
HRESULT GetObjectComWrappersData(CLRDATA_ADDRESS objAddr, CLRDATA_ADDRESS *rcw, unsigned int count, CLRDATA_ADDRESS *mowList, unsigned int *pNeeded);
HRESULT IsComWrappersCCW(CLRDATA_ADDRESS ccw, BOOL *isComWrappersCCW);
HRESULT GetComWrappersCCWData(CLRDATA_ADDRESS ccw, CLRDATA_ADDRESS *managedObject, int *refCount);
HRESULT IsComWrappersRCW(CLRDATA_ADDRESS rcw, BOOL *isComWrappersRCW);
HRESULT GetComWrappersRCWData(CLRDATA_ADDRESS rcw, CLRDATA_ADDRESS *identity);
}

Просмотреть файл

@ -139,7 +139,7 @@ typedef enum tagEFaultRepRetVal
#ifdef __cplusplus
#ifndef __PLACEMENT_NEW_INLINE
#define __PLACEMENT_NEW_INLINE
inline void *__cdecl operator new(long unsigned int, void *_P)
inline void *__cdecl operator new(size_t, void *_P)
{
return (_P);
}

Просмотреть файл

@ -6,13 +6,11 @@
/* File created by MIDL compiler version 8.01.0622 */
/* at Mon Jan 18 19:14:07 2038
*/
/* Compiler settings for runtime/src/coreclr/src/inc/cordebug.idl:
Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622
/* Compiler settings for cordebug.idl:
Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622
protocol : dce , ms_ext, c_ext, robust
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
DECLSPEC_UUID(), MIDL_INTERFACE()
*/
@ -23,7 +21,7 @@
#ifdef __cplusplus
extern "C"{
#endif
#endif
#include <rpc.h>
@ -367,6 +365,9 @@ MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapValue2,0xE3AC4D6C,0x9CB7,0x43e6,0x96,0xCC
MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapValue3,0xA69ACAD8,0x2374,0x46e9,0x9F,0xF8,0xB1,0xF1,0x41,0x20,0xD2,0x96);
MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapValue4,0xB35DD495,0xA555,0x463B,0x9B,0xE9,0xC5,0x53,0x38,0x48,0x6B,0xB8);
MIDL_DEFINE_GUID(IID, IID_ICorDebugObjectValue,0x18AD3D6E,0xB7D2,0x11d2,0xBD,0x04,0x00,0x00,0xF8,0x08,0x49,0xBD);
@ -479,3 +480,6 @@ MIDL_DEFINE_GUID(CLSID, CLSID_EmbeddedCLRCorDebug,0x211f1254,0xbc7e,0x4af5,0xb9,
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -56,7 +56,7 @@ typedef IID CLSID;
#endif // CLSID_DEFINED
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
EXTERN_C const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
#endif // !_MIDL_USE_GUIDDEF_

Просмотреть файл

@ -105,6 +105,10 @@ MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface8,0xc12f35a9,0xe55c,0x4520,0xa8,0x94,0
MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface9,0x4eca42d8,0x7e7b,0x4c8a,0xa1,0x16,0x7b,0xfb,0xf6,0x92,0x92,0x67);
MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface10,0x90B8FCC3,0x7251,0x4B0A,0xAE,0x3D,0x5C,0x13,0xA6,0x7E,0xC9,0xAA);
#undef MIDL_DEFINE_GUID
#ifdef __cplusplus

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -129,6 +129,20 @@ typedef interface ISOSDacInterface8 ISOSDacInterface8;
#endif /* __ISOSDacInterface8_FWD_DEFINED__ */
#ifndef __ISOSDacInterface9_FWD_DEFINED__
#define __ISOSDacInterface9_FWD_DEFINED__
typedef interface ISOSDacInterface9 ISOSDacInterface9;
#endif /* __ISOSDacInterface9_FWD_DEFINED__ */
#ifndef __ISOSDacInterface10_FWD_DEFINED__
#define __ISOSDacInterface10_FWD_DEFINED__
typedef interface ISOSDacInterface10 ISOSDacInterface10;
#endif /* __ISOSDacInterface10_FWD_DEFINED__ */
/* header files for imported files */
#include "unknwn.h"
#include "xclrdata.h"
@ -2745,6 +2759,144 @@ EXTERN_C const IID IID_ISOSDacInterface9;
#endif /* __ISOSDacInterface9_INTERFACE_DEFINED__ */
#ifndef __ISOSDacInterface10_INTERFACE_DEFINED__
#define __ISOSDacInterface10_INTERFACE_DEFINED__
/* interface ISOSDacInterface10 */
/* [uuid][local][object] */
EXTERN_C const IID IID_ISOSDacInterface10;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("90B8FCC3-7251-4B0A-AE3D-5C13A67EC9AA")
ISOSDacInterface10 : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetObjectComWrappersData(
CLRDATA_ADDRESS objAddr,
CLRDATA_ADDRESS *rcw,
unsigned int count,
CLRDATA_ADDRESS *mowList,
unsigned int *pNeeded) = 0;
virtual HRESULT STDMETHODCALLTYPE IsComWrappersCCW(
CLRDATA_ADDRESS ccw,
BOOL *isComWrappersCCW) = 0;
virtual HRESULT STDMETHODCALLTYPE GetComWrappersCCWData(
CLRDATA_ADDRESS ccw,
CLRDATA_ADDRESS *managedObject,
int *refCount) = 0;
virtual HRESULT STDMETHODCALLTYPE IsComWrappersRCW(
CLRDATA_ADDRESS rcw,
BOOL *isComWrappersRCW) = 0;
virtual HRESULT STDMETHODCALLTYPE GetComWrappersRCWData(
CLRDATA_ADDRESS rcw,
CLRDATA_ADDRESS *identity) = 0;
};
#else /* C style interface */
typedef struct ISOSDacInterface10Vtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISOSDacInterface10 * This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISOSDacInterface10 * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISOSDacInterface10 * This);
HRESULT ( STDMETHODCALLTYPE *GetObjectComWrappersData )(
ISOSDacInterface10 * This,
CLRDATA_ADDRESS objAddr,
CLRDATA_ADDRESS *rcw,
unsigned int count,
CLRDATA_ADDRESS *mowList,
unsigned int *pNeeded);
HRESULT ( STDMETHODCALLTYPE *IsComWrappersCCW )(
ISOSDacInterface10 * This,
CLRDATA_ADDRESS ccw,
BOOL *isComWrappersCCW);
HRESULT ( STDMETHODCALLTYPE *GetComWrappersCCWData )(
ISOSDacInterface10 * This,
CLRDATA_ADDRESS ccw,
CLRDATA_ADDRESS *managedObject,
int *refCount);
HRESULT ( STDMETHODCALLTYPE *IsComWrappersRCW )(
ISOSDacInterface10 * This,
CLRDATA_ADDRESS rcw,
BOOL *isComWrappersRCW);
HRESULT ( STDMETHODCALLTYPE *GetComWrappersRCWData )(
ISOSDacInterface10 * This,
CLRDATA_ADDRESS rcw,
CLRDATA_ADDRESS *identity);
END_INTERFACE
} ISOSDacInterface10Vtbl;
interface ISOSDacInterface10
{
CONST_VTBL struct ISOSDacInterface10Vtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ISOSDacInterface10_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ISOSDacInterface10_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ISOSDacInterface10_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ISOSDacInterface10_GetObjectComWrappersData(This,objAddr,rcw,count,mowList,pNeeded) \
( (This)->lpVtbl -> GetObjectComWrappersData(This,objAddr,rcw,count,mowList,pNeeded) )
#define ISOSDacInterface10_IsComWrappersCCW(This,ccw,isComWrappersCCW) \
( (This)->lpVtbl -> IsComWrappersCCW(This,ccw,isComWrappersCCW) )
#define ISOSDacInterface10_GetComWrappersCCWData(This,ccw,managedObject,refCount) \
( (This)->lpVtbl -> GetComWrappersCCWData(This,ccw,managedObject,refCount) )
#define ISOSDacInterface10_IsComWrappersRCW(This,rcw,isComWrappersRCW) \
( (This)->lpVtbl -> IsComWrappersRCW(This,rcw,isComWrappersRCW) )
#define ISOSDacInterface10_GetComWrappersRCWData(This,rcw,identity) \
( (This)->lpVtbl -> GetComWrappersRCWData(This,rcw,identity) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ISOSDacInterface10_INTERFACE_DEFINED__ */
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */

Просмотреть файл

@ -24,6 +24,7 @@
#cmakedefine01 HAVE_PTHREAD_NP_H
#cmakedefine01 HAVE_AUXV_HWCAP_H
#cmakedefine01 HAVE_SYS_PTRACE_H
#cmakedefine01 HAVE_GETAUXVAL
#cmakedefine01 HAVE_KQUEUE
#cmakedefine01 HAVE_PTHREAD_SUSPEND

Просмотреть файл

@ -47,6 +47,7 @@ check_include_files(numa.h HAVE_NUMA_H)
check_include_files(pthread_np.h HAVE_PTHREAD_NP_H)
check_include_files("sys/auxv.h;asm/hwcap.h" HAVE_AUXV_HWCAP_H)
check_include_files("sys/ptrace.h" HAVE_SYS_PTRACE_H)
check_symbol_exists(getauxval sys/auxv.h HAVE_GETAUXVAL)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_DL_LIBS})
@ -1048,8 +1049,6 @@ if(NOT CLR_CMAKE_USE_SYSTEM_LIBUNWIND)
list(INSERT CMAKE_REQUIRED_INCLUDES 0 ${CMAKE_CURRENT_SOURCE_DIR}/libunwind/include ${CMAKE_CURRENT_BINARY_DIR}/libunwind/include)
endif()
set(CMAKE_REQUIRED_FLAGS "-c -Werror=implicit-function-declaration")
check_c_source_compiles("
#include <libunwind.h>
#include <ucontext.h>
@ -1061,29 +1060,9 @@ int main(int argc, char **argv)
return 0;
}" UNWIND_CONTEXT_IS_UCONTEXT_T)
check_c_source_compiles("
#include <libunwind.h>
check_symbol_exists(unw_get_save_loc libunwind.h HAVE_UNW_GET_SAVE_LOC)
check_symbol_exists(unw_get_accessors libunwind.h HAVE_UNW_GET_ACCESSORS)
int main(int argc, char **argv) {
unw_cursor_t cursor;
unw_save_loc_t saveLoc;
int reg = UNW_REG_IP;
unw_get_save_loc(&cursor, reg, &saveLoc);
return 0;
}" HAVE_UNW_GET_SAVE_LOC)
check_c_source_compiles("
#include <libunwind.h>
int main(int argc, char **argv) {
unw_addr_space_t as;
unw_get_accessors(as);
return 0;
}" HAVE_UNW_GET_ACCESSORS)
set(CMAKE_REQUIRED_FLAGS)
if(NOT CLR_CMAKE_USE_SYSTEM_LIBUNWIND)
list(REMOVE_AT CMAKE_REQUIRED_INCLUDES 0 1)
endif()

Просмотреть файл

@ -55,6 +55,7 @@ add_library(eventprovider
add_library(coreclrtraceptprovider
SHARED
${TRACEPOINT_PROVIDER_SOURCES}
${VERSION_FILE_PATH}
)
add_dependencies(eventprovider generated_eventing_headers)

Просмотреть файл

@ -1698,7 +1698,10 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pip, int nee
ehFrameHdrLen = ph.p_memsz;
break;
#ifdef PT_ARM_EXIDX
#if defined(TARGET_ARM)
#ifndef PT_ARM_EXIDX
#define PT_ARM_EXIDX 0x70000001 /* See llvm ELF.h */
#endif /* !PT_ARM_EXIDX */
case PT_ARM_EXIDX:
exidxFrameHdrAddr = loadbias + ph.p_vaddr;
exidxFrameHdrLen = ph.p_memsz;

Просмотреть файл

@ -67,7 +67,7 @@ DWORD SPINLOCKTryAcquire (LONG * lock);
// Named mutex
// Temporarily disabling usage of pthread process-shared mutexes on ARM/ARM64 due to functional issues that cannot easily be
// detected with code due to hangs. See https://github.com/dotnet/coreclr/issues/5456.
// detected with code due to hangs. See https://github.com/dotnet/runtime/issues/6014.
#if HAVE_FULLY_FEATURED_PTHREAD_MUTEXES && HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES && !(defined(HOST_ARM) || defined(HOST_ARM64) || defined(__FreeBSD__))
#define NAMED_MUTEX_USE_PTHREAD_MUTEX 1
#else

Просмотреть файл

@ -91,6 +91,15 @@ int CacheLineSize;
#endif
#endif
#if defined(__FreeBSD__)
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#endif
#if HAVE_GETAUXVAL
#include <sys/auxv.h>
#endif
#include <algorithm>
using namespace CorUnix;
@ -125,7 +134,7 @@ static DWORD g_initializeDLLFlags = PAL_INITIALIZE_DLL;
static int Initialize(int argc, const char *const argv[], DWORD flags);
static BOOL INIT_IncreaseDescriptorLimit(void);
static LPWSTR INIT_FormatCommandLine (int argc, const char * const *argv);
static LPWSTR INIT_ConvertEXEPath(LPCSTR exe_name);
static LPWSTR INIT_GetCurrentEXEPath();
static BOOL INIT_SharedFilesPath(void);
#ifdef _DEBUG
@ -560,7 +569,7 @@ Initialize(
}
/* find out the application's full path */
exe_path = INIT_ConvertEXEPath(argv[0]);
exe_path = INIT_GetCurrentEXEPath();
if (NULL == exe_path)
{
ERROR("Unable to find exe path\n");
@ -1265,45 +1274,160 @@ static LPWSTR INIT_FormatCommandLine (int argc, const char * const *argv)
return retval;
}
#if defined(__linux__)
#define symlinkEntrypointExecutable "/proc/self/exe"
#elif !defined(__APPLE__)
#define symlinkEntrypointExecutable "/proc/curproc/exe"
#endif
bool GetAbsolutePath(const char* path, PathCharString& absolutePath)
{
bool result = false;
char realPath[PATH_MAX];
if (realpath(path, realPath) != nullptr && realPath[0] != '\0')
{
absolutePath.Set(realPath, strlen(realPath));
// realpath should return canonicalized path without the trailing slash
_ASSERTE(absolutePath[absolutePath.GetCount() - 1] != '/');
result = true;
}
return result;
}
bool GetEntrypointExecutableAbsolutePath(PathCharString& entrypointExecutable)
{
bool result = false;
entrypointExecutable.Clear();
// Get path to the executable for the current process using
// platform specific means.
#if defined(__APPLE__)
// On Mac, we ask the OS for the absolute path to the entrypoint executable
uint32_t lenActualPath = 0;
if (_NSGetExecutablePath(nullptr, &lenActualPath) == -1)
{
// OSX has placed the actual path length in lenActualPath,
// so re-attempt the operation
PathCharString resizedPath;
char *pResizedPath = resizedPath.OpenStringBuffer(lenActualPath);
if (_NSGetExecutablePath(pResizedPath, &lenActualPath) == 0)
{
resizedPath.CloseBuffer(lenActualPath - 1);
entrypointExecutable.Set(resizedPath);
result = true;
}
}
#elif defined (__FreeBSD__)
static const int name[] =
{
CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1
};
char path[PATH_MAX];
size_t len;
len = sizeof(path);
if (sysctl(name, 4, path, &len, nullptr, 0) == 0)
{
entrypointExecutable.Set(path, len);
result = true;
}
else
{
// ENOMEM
result = false;
}
#elif defined(__NetBSD__) && defined(KERN_PROC_PATHNAME)
static const int name[] =
{
CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME,
};
char path[MAXPATHLEN];
size_t len;
len = sizeof(path);
if (sysctl(name, __arraycount(name), path, &len, NULL, 0) != -1)
{
entrypointExecutable.Set(path, len);
result = true;
}
else
{
result = false;
}
#elif defined(__sun)
const char *path;
if ((path = getexecname()) == NULL)
{
result = false;
}
else if (*path != '/')
{
char *cwd;
if ((cwd = getcwd(NULL, PATH_MAX)) == NULL)
{
result = false;
}
else
{
entrypointExecutable.Set(cwd, strlen(cwd));
entrypointExecutable.Append('/');
entrypointExecutable.Append(path, strlen(path));
result = true;
free(cwd);
}
}
else
{
entrypointExecutable.Set(path, strlen(path));
result = true;
}
#else
#if HAVE_GETAUXVAL && defined(AT_EXECFN)
const char *execfn = (const char *)getauxval(AT_EXECFN);
if (execfn)
{
entrypointExecutable.Set(execfn, strlen(execfn));
result = true;
}
else
#endif
// On other OSs, return the symlink that will be resolved by GetAbsolutePath
// to fetch the entrypoint EXE absolute path, inclusive of filename.
result = GetAbsolutePath(symlinkEntrypointExecutable, entrypointExecutable);
#endif
return result;
}
/*++
Function:
INIT_ConvertEXEPath
INIT_GetCurrentEXEPath
Abstract:
Check whether the executable path is valid, and convert its type (LPCSTR -> LPWSTR)
Parameters:
LPCSTR exe_name : full path of the current executable
Get the current exe path
Return:
pointer to buffer containing the full path. This buffer must be released
by the caller using free()
Notes :
this function assumes that "exe_name" is in Unix style (no \)
--*/
static LPWSTR INIT_ConvertEXEPath(LPCSTR exe_path)
static LPWSTR INIT_GetCurrentEXEPath()
{
PathCharString real_path;
LPWSTR return_value;
INT return_size;
struct stat theStats;
if (!strchr(exe_path, '/'))
if (!GetEntrypointExecutableAbsolutePath(real_path))
{
ERROR( "The exe path is not fully specified\n" );
return NULL;
}
if (-1 == stat(exe_path, &theStats))
{
ERROR( "The file does not exist\n" );
return NULL;
}
if (!CorUnix::RealPathHelper(exe_path, real_path))
{
ERROR("realpath() failed!\n");
ERROR( "Cannot get current exe path\n" );
return NULL;
}

Просмотреть файл

@ -14,6 +14,7 @@ Abstract:
#include "pal/dbgmsg.h"
SET_DEFAULT_DEBUG_CHANNEL(MISC);
#include "pal/palinternal.h"
#include <limits>
#include <limits.h>
#include <sys/resource.h>
#include "pal/virtual.h"
@ -53,8 +54,8 @@ public:
static void Initialize()
{
s_cgroup_version = FindCGroupVersion();
s_memory_cgroup_path = FindCGroupPath(&IsCGroup1MemorySubsystem);
s_cpu_cgroup_path = FindCGroupPath(&IsCGroup1CpuSubsystem);
s_memory_cgroup_path = FindCGroupPath(s_cgroup_version == 1 ? &IsCGroup1MemorySubsystem : nullptr);
s_cpu_cgroup_path = FindCGroupPath(s_cgroup_version == 1 ? &IsCGroup1CpuSubsystem : nullptr);
}
static void Cleanup()
@ -245,33 +246,37 @@ private:
if (strncmp(filesystemType, "cgroup", 6) == 0)
{
char* context = nullptr;
char* strTok = strtok_s(options, ",", &context);
while (strTok != nullptr)
bool isSubsystemMatch = is_subsystem == nullptr;
if (!isSubsystemMatch)
{
if (is_subsystem(strTok))
char* context = nullptr;
char* strTok = strtok_s(options, ",", &context);
while (!isSubsystemMatch && strTok != nullptr)
{
mountpath = (char*)PAL_malloc(lineLen+1);
if (mountpath == nullptr)
goto done;
mountroot = (char*)PAL_malloc(lineLen+1);
if (mountroot == nullptr)
goto done;
sscanfRet = sscanf_s(line,
"%*s %*s %*s %s %s ",
mountroot, lineLen+1,
mountpath, lineLen+1);
if (sscanfRet != 2)
_ASSERTE(!"Failed to parse mount info file contents with sscanf_s.");
// assign the output arguments and clear the locals so we don't free them.
*pmountpath = mountpath;
*pmountroot = mountroot;
mountpath = mountroot = nullptr;
goto done;
isSubsystemMatch = is_subsystem(strTok);
strTok = strtok_s(nullptr, ",", &context);
}
strTok = strtok_s(nullptr, ",", &context);
}
if (isSubsystemMatch)
{
mountpath = (char*)PAL_malloc(lineLen+1);
if (mountpath == nullptr)
goto done;
mountroot = (char*)PAL_malloc(lineLen+1);
if (mountroot == nullptr)
goto done;
sscanfRet = sscanf_s(line,
"%*s %*s %*s %s %s ",
mountroot, lineLen+1,
mountpath, lineLen+1);
if (sscanfRet != 2)
_ASSERTE(!"Failed to parse mount info file contents with sscanf_s.");
// assign the output arguments and clear the locals so we don't free them.
*pmountpath = mountpath;
*pmountroot = mountroot;
mountpath = mountroot = nullptr;
}
}
}
@ -343,7 +348,7 @@ private:
// See https://www.kernel.org/doc/Documentation/cgroup-v2.txt
// Look for a "0::/some/path"
int sscanfRet = sscanf_s(line,
"0::%s", lineLen+1,
"0::%s",
cgroup_path, lineLen+1);
if (sscanfRet == 1)
{

Просмотреть файл

@ -13,6 +13,135 @@ SET_DEFAULT_DEBUG_CHANNEL(MISC);
#include <asm/hwcap.h>
#endif
#if defined(HOST_ARM64) && defined(__linux__)
struct CpuCapability
{
const char* name;
unsigned long hwCapFlag;
};
static const CpuCapability CpuCapabilities[] = {
//{ "fp", HWCAP_FP },
#ifdef HWCAP_ASIMD
{ "asimd", HWCAP_ASIMD },
#endif
//{ "evtstrm", HWCAP_EVTSTRM },
#ifdef HWCAP_AES
{ "aes", HWCAP_AES },
#endif
//{ "pmull", HWCAP_PMULL },
#ifdef HWCAP_SHA1
{ "sha1", HWCAP_SHA1 },
#endif
#ifdef HWCAP_SHA2
{ "sha2", HWCAP_SHA2 },
#endif
#ifdef HWCAP_CRC32
{ "crc32", HWCAP_CRC32 },
#endif
#ifdef HWCAP_ATOMICS
{ "atomics", HWCAP_ATOMICS },
#endif
//{ "fphp", HWCAP_FPHP },
//{ "asimdhp", HWCAP_ASIMDHP },
//{ "cpuid", HWCAP_CPUID },
#ifdef HWCAP_ASIMDRDM
{ "asimdrdm", HWCAP_ASIMDRDM },
#endif
//{ "jscvt", HWCAP_JSCVT },
//{ "fcma", HWCAP_FCMA },
//{ "lrcpc", HWCAP_LRCPC },
//{ "dcpop", HWCAP_DCPOP },
//{ "sha3", HWCAP_SHA3 },
//{ "sm3", HWCAP_SM3 },
//{ "sm4", HWCAP_SM4 },
#ifdef HWCAP_ASIMDDP
{ "asimddp", HWCAP_ASIMDDP },
#endif
//{ "sha512", HWCAP_SHA512 },
//{ "sve", HWCAP_SVE },
//{ "asimdfhm", HWCAP_ASIMDFHM },
//{ "dit", HWCAP_DIT },
//{ "uscat", HWCAP_USCAT },
//{ "ilrcpc", HWCAP_ILRCPC },
//{ "flagm", HWCAP_FLAGM },
//{ "ssbs", HWCAP_SSBS },
//{ "sb", HWCAP_SB },
//{ "paca", HWCAP_PACA },
//{ "pacg", HWCAP_PACG },
// Ensure the array is never empty
{ "", 0 }
};
// Returns the HWCAP_* flag corresponding to the given capability name.
// If the capability name is not recognized or unused at present, zero is returned.
static unsigned long LookupCpuCapabilityFlag(const char* start, size_t length)
{
for (int i = 0; i < _countof(CpuCapabilities); i++)
{
const char* capabilityName = CpuCapabilities[i].name;
if ((length == strlen(capabilityName)) && (memcmp(start, capabilityName, length) == 0))
{
return CpuCapabilities[i].hwCapFlag;
}
}
return 0;
}
// Reads the first Features entry from /proc/cpuinfo (assuming other entries are essentially
// identical) and translates it into a set of HWCAP_* flags.
static unsigned long GetCpuCapabilityFlagsFromCpuInfo()
{
unsigned long capabilityFlags = 0;
FILE* cpuInfoFile = fopen("/proc/cpuinfo", "r");
if (cpuInfoFile != NULL)
{
char* line = nullptr;
size_t lineLen = 0;
while (getline(&line, &lineLen, cpuInfoFile) != -1)
{
char* p = line;
while (isspace(*p)) p++;
if (memcmp(p, "Features", 8) != 0)
continue;
// Skip "Features" and look for ':'
p += 8;
while (isspace(*p)) p++;
if (*p != ':')
continue;
// Skip ':' and parse the list
p++;
while (true)
{
while (isspace(*p)) p++;
if (*p == 0)
break;
char* start = p++;
while ((*p != 0) && !isspace(*p)) p++;
capabilityFlags |= LookupCpuCapabilityFlag(start, p - start);
}
break;
}
free(line);
fclose(cpuInfoFile);
}
return capabilityFlags;
}
#endif // defined(HOST_ARM64) && defined(__linux__)
PALIMPORT
VOID
PALAPI
@ -26,6 +155,13 @@ PAL_GetJitCpuCapabilityFlags(CORJIT_FLAGS *flags)
#if HAVE_AUXV_HWCAP_H
unsigned long hwCap = getauxval(AT_HWCAP);
#if defined(__linux__)
// getauxval(AT_HWCAP) returns zero on WSL1 (https://github.com/microsoft/WSL/issues/3682),
// fall back to reading capabilities from /proc/cpuinfo.
if (hwCap == 0)
hwCap = GetCpuCapabilityFlagsFromCpuInfo();
#endif
// HWCAP_* flags are introduced by ARM into the Linux kernel as new extensions are published.
// For a given kernel, some of these flags may not be present yet.
// Use ifdef for each to allow for compilation with any vintage kernel.

Просмотреть файл

@ -565,9 +565,14 @@ PAL_GetLogicalProcessorCacheSizeFromOS()
cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL4_CACHE_SIZE));
#endif
#if defined(HOST_ARM64)
if(cacheSize == 0)
#if defined(TARGET_LINUX) && !defined(HOST_ARM)
if (cacheSize == 0)
{
//
// Fallback to retrieve cachesize via /sys/.. if sysconf was not available
// for the platform. Currently musl and arm64 should be only cases to use
// this method to determine cache size.
//
size_t size;
if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index0/size", &size))
@ -581,8 +586,10 @@ PAL_GetLogicalProcessorCacheSizeFromOS()
if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index4/size", &size))
cacheSize = std::max(cacheSize, size);
}
#endif
if(cacheSize == 0)
#if defined(HOST_ARM64)
if (cacheSize == 0)
{
// It is currently expected to be missing cache size info
//

Просмотреть файл

@ -80,6 +80,7 @@ SET_DEFAULT_DEBUG_CHANNEL(PROCESS); // some headers have code with asserts, so d
#endif
#ifdef __APPLE__
#include <libproc.h>
#include <sys/sysctl.h>
#include <sys/posix_sem.h>
#endif
@ -3005,65 +3006,63 @@ CreateProcessModules(
// NOTE: the module path can have spaces in the name
// __TEXT 0000000196220000-00000001965b4000 [ 3664K 2340K 0K 0K] r-x/rwx SM=COW /Volumes/Builds/builds/devmain/rawproduct/debug/build/out/Applications/Microsoft Excel.app/Contents/SharedSupport/PowerQuery/libcoreclr.dylib
char *line = NULL;
size_t lineLen = 0;
// NOTE: Sometimes vmmap hides full paths to some process modules (.dylibs in non-system folders), causing debugger not to work.
// __TEXT 000000010d8bd000-000000010ddce000 [ 5188K 5188K 0K 0K] r-x/rwx SM=COW /Users/USER/*/libcoreclr.dylib
// So now we get modules information by iterating over regions using proc_pidinfo(). See dotnet/runtime#42888.
int count = 0;
ssize_t read;
char vmmapCommand[100];
int chars = snprintf(vmmapCommand, sizeof(vmmapCommand), "/usr/bin/vmmap -interleaved %d -wide", dwProcessId);
_ASSERTE(chars > 0 && chars <= sizeof(vmmapCommand));
FILE *vmmapFile = popen(vmmapCommand, "r");
if (vmmapFile == NULL)
uint64_t addr = 0;
while (true)
{
goto exit;
}
// Reading maps file line by line
while ((read = getline(&line, &lineLen, vmmapFile)) != -1)
{
void *startAddress, *endAddress;
char moduleName[PATH_MAX];
if (sscanf_s(line, "__TEXT %p-%p [ %*[0-9K ]] %*[-/rwxsp] SM=%*[A-Z] %[^\n]", &startAddress, &endAddress, moduleName, _countof(moduleName)) == 3)
struct proc_regionwithpathinfo rwpi;
int sz = proc_pidinfo(dwProcessId, PROC_PIDREGIONPATHINFO, addr, &rwpi, sizeof rwpi);
if (sz != sizeof rwpi)
{
bool dup = false;
for (ProcessModules *entry = listHead; entry != NULL; entry = entry->Next)
{
if (strcmp(moduleName, entry->Name) == 0)
{
dup = true;
break;
}
}
if (sz == 0 && errno == EINVAL)
break; // ok
if (!dup)
DestroyProcessModules(listHead);
listHead = NULL;
count = 0;
break; // unknown error
}
const char *moduleName = rwpi.prp_vip.vip_path;
bool dup = false;
for (ProcessModules *entry = listHead; entry != NULL; entry = entry->Next)
{
if (strcmp(moduleName, entry->Name) == 0)
{
int cbModuleName = strlen(moduleName) + 1;
ProcessModules *entry = (ProcessModules *)InternalMalloc(sizeof(ProcessModules) + cbModuleName);
if (entry == NULL)
{
DestroyProcessModules(listHead);
listHead = NULL;
count = 0;
break;
}
strcpy_s(entry->Name, cbModuleName, moduleName);
entry->BaseAddress = startAddress;
entry->Next = listHead;
listHead = entry;
count++;
dup = true;
break;
}
}
if (!dup)
{
int cbModuleName = strlen(moduleName) + 1;
ProcessModules *entry = (ProcessModules *)InternalMalloc(sizeof(ProcessModules) + cbModuleName);
if (entry == NULL)
{
DestroyProcessModules(listHead);
listHead = NULL;
count = 0;
break; // no memory
}
memcpy_s(entry->Name, cbModuleName, moduleName, cbModuleName);
entry->BaseAddress = (void *)rwpi.prp_prinfo.pri_address;
entry->Next = listHead;
listHead = entry;
count++;
}
addr = rwpi.prp_prinfo.pri_address + rwpi.prp_prinfo.pri_size;
}
*lpCount = count;
free(line); // We didn't allocate line, but as per contract of getline we should free it
pclose(vmmapFile);
exit:
#elif HAVE_PROCFS_MAPS
// Here we read /proc/<pid>/maps file in order to parse it and figure out what it says

Просмотреть файл

@ -48,4 +48,4 @@ This test case should be run manually. Requires user input.
filemapping_memmgt\MapViewOfFile\test1
=======================================
Refer this github issue https://github.com/dotnet/coreclr/issues/5176
Refer this github issue https://github.com/dotnet/runtime/issues/5924

Просмотреть файл

@ -841,7 +841,7 @@ DWORD AbandonTests_Child_AbruptExit(void *arg = nullptr)
// This child process acquires the mutex lock, creates another child process (to ensure that file locks are not inherited), and
// abandons the mutex abruptly. The second child process detects the abandonment and abandons the mutex again for the parent to
// detect. Issue: https://github.com/dotnet/coreclr/issues/21455
// detect. Issue: https://github.com/dotnet/runtime/issues/11636
DWORD AbandonTests_Child_FileLocksNotInherited_Parent_AbruptExit(void *arg = nullptr)
{
const char *testName = "AbandonTests";

Просмотреть файл

@ -1 +1,7 @@
${NM:-nm} -P -t x $1 | awk -F ' ' '/g_dacTable/ { print "#define DAC_TABLE_RVA 0x" substr("0000000000000000" $3, length($3) + 1); exit }' > $2
if [ "$1" = "--dynamic" ]; then
__DynamicSymbolsOption="-D"
shift
else
__DynamicSymbolsOption=""
fi
${NM:-nm} $__DynamicSymbolsOption -P -t x $1 | awk -F ' ' '/g_dacTable/ { print "#define DAC_TABLE_RVA 0x" substr("0000000000000000" $3, length($3) + 1); exit }' > $2