diff options
Diffstat (limited to 'src/pal/src')
-rw-r--r-- | src/pal/src/CMakeLists.txt | 108 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/activationhandlerwrapper.S (renamed from src/pal/src/arch/i386/activationhandlerwrapper.S) | 0 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/asmconstants.h | 106 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/context.S (renamed from src/pal/src/arch/i386/context.S) | 0 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/context2.S | 259 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/debugbreak.S | 12 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/dispatchexceptionwrapper.S (renamed from src/pal/src/arch/i386/dispatchexceptionwrapper.S) | 0 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/exceptionhelper.S | 42 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/optimizedtls.cpp (renamed from src/pal/src/arch/i386/optimizedtls.cpp) | 2 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/processor.cpp | 64 | ||||
-rw-r--r-- | src/pal/src/arch/arm/exceptionhelper.S | 2 | ||||
-rw-r--r-- | src/pal/src/arch/i386/asmconstants.h | 76 | ||||
-rw-r--r-- | src/pal/src/arch/i386/context2.S | 354 | ||||
-rw-r--r-- | src/pal/src/arch/i386/exceptionhelper.S | 47 | ||||
-rw-r--r-- | src/pal/src/config.h.in | 1 | ||||
-rw-r--r-- | src/pal/src/configure.cmake | 11 | ||||
-rw-r--r-- | src/pal/src/cruntime/lstr.cpp | 210 | ||||
-rw-r--r-- | src/pal/src/cruntime/math.cpp | 367 | ||||
-rw-r--r-- | src/pal/src/cruntime/mbstring.cpp | 54 | ||||
-rw-r--r-- | src/pal/src/cruntime/path.cpp | 482 | ||||
-rw-r--r-- | src/pal/src/cruntime/printf.cpp | 202 | ||||
-rw-r--r-- | src/pal/src/cruntime/string.cpp | 55 | ||||
-rw-r--r-- | src/pal/src/cruntime/wchar.cpp | 211 | ||||
-rw-r--r-- | src/pal/src/debug/debug.cpp | 1087 | ||||
-rw-r--r-- | src/pal/src/examples/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/pal/src/examples/example1.cpp (renamed from src/pal/src/examples/example1.c) | 0 | ||||
-rw-r--r-- | src/pal/src/exception/machexception.cpp | 7 | ||||
-rw-r--r-- | src/pal/src/exception/machmessage.cpp | 2 | ||||
-rw-r--r-- | src/pal/src/exception/machmessage.h | 4 | ||||
-rw-r--r-- | src/pal/src/exception/seh-unwind.cpp | 76 | ||||
-rw-r--r-- | src/pal/src/exception/seh.cpp | 8 | ||||
-rw-r--r-- | src/pal/src/exception/signal.cpp | 6 | ||||
-rw-r--r-- | src/pal/src/file/find.cpp | 10 | ||||
-rw-r--r-- | src/pal/src/include/pal/context.h | 24 | ||||
-rw-r--r-- | src/pal/src/include/pal/palinternal.h | 45 | ||||
-rw-r--r-- | src/pal/src/init/pal.cpp | 3 | ||||
-rw-r--r-- | src/pal/src/map/virtual.cpp | 5 | ||||
-rw-r--r-- | src/pal/src/misc/sysinfo.cpp | 2 | ||||
-rw-r--r-- | src/pal/src/safecrt/input.inl | 4 | ||||
-rw-r--r-- | src/pal/src/safecrt/makepath_s.cpp (renamed from src/pal/src/safecrt/makepath_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/mbusafecrt.cpp (renamed from src/pal/src/safecrt/mbusafecrt.c) | 11 | ||||
-rw-r--r-- | src/pal/src/safecrt/memcpy_s.cpp (renamed from src/pal/src/safecrt/memcpy_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/memmove_s.cpp (renamed from src/pal/src/safecrt/memmove_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/output.inl | 39 | ||||
-rw-r--r-- | src/pal/src/safecrt/safecrt_input_s.cpp (renamed from src/pal/src/safecrt/safecrt_input_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/safecrt_output_l.cpp (renamed from src/pal/src/safecrt/safecrt_output_l.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/safecrt_output_s.cpp (renamed from src/pal/src/safecrt/safecrt_output_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/safecrt_winput_s.cpp (renamed from src/pal/src/safecrt/safecrt_winput_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/safecrt_woutput_s.cpp (renamed from src/pal/src/safecrt/safecrt_woutput_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/snprintf.cpp (renamed from src/pal/src/safecrt/snprintf.c) | 2 | ||||
-rw-r--r-- | src/pal/src/safecrt/splitpath_s.cpp (renamed from src/pal/src/safecrt/splitpath_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/sprintf_s.cpp (renamed from src/pal/src/safecrt/sprintf.c) | 12 | ||||
-rw-r--r-- | src/pal/src/safecrt/sscanf_s.cpp (renamed from src/pal/src/safecrt/sscanf.c) | 4 | ||||
-rw-r--r-- | src/pal/src/safecrt/strcat_s.cpp (renamed from src/pal/src/safecrt/strcat_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/strcpy_s.cpp (renamed from src/pal/src/safecrt/strcpy_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/strlen_s.cpp (renamed from src/pal/src/safecrt/strlen_s.c) | 2 | ||||
-rw-r--r-- | src/pal/src/safecrt/strncat_s.cpp (renamed from src/pal/src/safecrt/strncat_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/strncpy_s.cpp (renamed from src/pal/src/safecrt/strncpy_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/strtok_s.cpp (renamed from src/pal/src/safecrt/strtok_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/swprintf.cpp (renamed from src/pal/src/safecrt/swprintf.c) | 2 | ||||
-rw-r--r-- | src/pal/src/safecrt/vsprintf.cpp (renamed from src/pal/src/safecrt/vsprintf.c) | 2 | ||||
-rw-r--r-- | src/pal/src/safecrt/vswprint.cpp (renamed from src/pal/src/safecrt/vswprint.c) | 83 | ||||
-rw-r--r-- | src/pal/src/safecrt/wcscat_s.cpp (renamed from src/pal/src/safecrt/wcscat_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/wcscpy_s.cpp (renamed from src/pal/src/safecrt/wcscpy_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/wcslen_s.cpp (renamed from src/pal/src/safecrt/wcslen_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/wcsncat_s.cpp (renamed from src/pal/src/safecrt/wcsncat_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/wcsncpy_s.cpp (renamed from src/pal/src/safecrt/wcsncpy_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/wcstok_s.cpp (renamed from src/pal/src/safecrt/wcstok_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/wmakepath_s.cpp (renamed from src/pal/src/safecrt/wmakepath_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/wsplitpath_s.cpp (renamed from src/pal/src/safecrt/wsplitpath_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/xtoa_s.cpp (renamed from src/pal/src/safecrt/xtoa_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/xtow_s.cpp (renamed from src/pal/src/safecrt/xtow_s.c) | 0 | ||||
-rw-r--r-- | src/pal/src/safecrt/xtox_s.inl | 29 | ||||
-rw-r--r-- | src/pal/src/synchmgr/synchmanager.cpp | 2 | ||||
-rw-r--r-- | src/pal/src/thread/context.cpp | 108 | ||||
-rw-r--r-- | src/pal/src/thread/process.cpp | 12 |
76 files changed, 1397 insertions, 2861 deletions
diff --git a/src/pal/src/CMakeLists.txt b/src/pal/src/CMakeLists.txt index 7df0aaf360..28ee83a77c 100644 --- a/src/pal/src/CMakeLists.txt +++ b/src/pal/src/CMakeLists.txt @@ -2,13 +2,6 @@ cmake_minimum_required(VERSION 2.8.12.2) include_directories(SYSTEM /usr/local/include) -# set kernel version to detect Alpine -EXEC_PROGRAM(uname ARGS -v OUTPUT_VARIABLE CMAKE_SYSTEM_KERNEL_VERSION) -string(FIND "${CMAKE_SYSTEM_KERNEL_VERSION}" "Alpine" PAL_SYSTEM_ALPINE) -if(PAL_SYSTEM_ALPINE EQUAL -1) - unset(PAL_SYSTEM_ALPINE) -endif() - include(configure.cmake) project(coreclrpal) @@ -39,16 +32,20 @@ elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) set(PAL_CMAKE_PLATFORM_ARCH_ARM64 1) add_definitions(-D_ARM64_) +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL i686) + set(CLR_CMAKE_PLATFORM_ARCH_I386 1) + add_definitions(-D_X86_) else() message(FATAL_ERROR "Only ARM and AMD64 is supported") endif() if(CMAKE_SYSTEM_NAME STREQUAL Darwin) add_definitions(-D_TARGET_MAC64) + add_definitions(-DXSTATE_SUPPORTED) set(PLATFORM_SOURCES - arch/i386/activationhandlerwrapper.S - arch/i386/context.S - arch/i386/dispatchexceptionwrapper.S + arch/amd64/activationhandlerwrapper.S + arch/amd64/context.S + arch/amd64/dispatchexceptionwrapper.S exception/machexception.cpp exception/machmessage.cpp ) @@ -68,8 +65,20 @@ elseif(PAL_CMAKE_PLATFORM_ARCH_ARM) elseif(PAL_CMAKE_PLATFORM_ARCH_ARM64) add_definitions(-DBIT64=1) add_definitions(-D_WIN64=1) +elseif(CLR_CMAKE_PLATFORM_ARCH_I386) + add_definitions(-DBIT32=1) endif() +if(CMAKE_SYSTEM_NAME STREQUAL Linux AND NOT CLR_CMAKE_PLATFORM_ALPINE_LINUX) + # Currently the _xstate is not available on Alpine Linux + add_definitions(-DXSTATE_SUPPORTED) +endif(CMAKE_SYSTEM_NAME STREQUAL Linux AND NOT CLR_CMAKE_PLATFORM_ALPINE_LINUX) + +if(CLR_CMAKE_PLATFORM_ALPINE_LINUX) + # Setting RLIMIT_NOFILE breaks debugging of coreclr on Alpine Linux for some reason + add_definitions(-DDONT_SET_RLIMIT_NOFILE) +endif(CLR_CMAKE_PLATFORM_ALPINE_LINUX) + # turn off capability to remove unused functions (which was enabled in debug build with sanitizers) set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -Wl,--no-gc-sections") @@ -77,10 +86,10 @@ add_compile_options(-fPIC) if(PAL_CMAKE_PLATFORM_ARCH_AMD64) set(ARCH_SOURCES - arch/i386/context2.S - arch/i386/debugbreak.S - arch/i386/exceptionhelper.S - arch/i386/processor.cpp + arch/amd64/context2.S + arch/amd64/debugbreak.S + arch/amd64/exceptionhelper.S + arch/amd64/processor.cpp ) elseif(PAL_CMAKE_PLATFORM_ARCH_ARM) set(ARCH_SOURCES @@ -96,6 +105,13 @@ elseif(PAL_CMAKE_PLATFORM_ARCH_ARM64) arch/arm64/exceptionhelper.S arch/arm64/processor.cpp ) +elseif(CLR_CMAKE_PLATFORM_ARCH_I386) + set(ARCH_SOURCES + arch/i386/context2.S + arch/i386/debugbreak.S + arch/i386/exceptionhelper.S + arch/i386/processor.cpp + ) endif() if(PAL_CMAKE_PLATFORM_ARCH_ARM) @@ -160,37 +176,37 @@ set(SOURCES objmgr/palobjbase.cpp objmgr/shmobject.cpp objmgr/shmobjectmanager.cpp - safecrt/makepath_s.c - safecrt/memcpy_s.c - safecrt/memmove_s.c - safecrt/mbusafecrt.c - safecrt/safecrt_input_s.c - safecrt/safecrt_output_l.c - safecrt/safecrt_output_s.c - safecrt/safecrt_winput_s.c - safecrt/safecrt_woutput_s.c - safecrt/splitpath_s.c - safecrt/sprintf.c - safecrt/sscanf.c - safecrt/strcat_s.c - safecrt/strcpy_s.c - safecrt/strlen_s.c - safecrt/strncat_s.c - safecrt/strncpy_s.c - safecrt/strtok_s.c - safecrt/swprintf.c - safecrt/vsprintf.c - safecrt/vswprint.c - safecrt/wcscat_s.c - safecrt/wcscpy_s.c - safecrt/wcslen_s.c - safecrt/wcsncat_s.c - safecrt/wcsncpy_s.c - safecrt/wcstok_s.c - safecrt/wmakepath_s.c - safecrt/wsplitpath_s.c - safecrt/xtoa_s.c - safecrt/xtow_s.c + safecrt/makepath_s.cpp + safecrt/memcpy_s.cpp + safecrt/memmove_s.cpp + safecrt/mbusafecrt.cpp + safecrt/safecrt_input_s.cpp + safecrt/safecrt_output_l.cpp + safecrt/safecrt_output_s.cpp + safecrt/safecrt_winput_s.cpp + safecrt/safecrt_woutput_s.cpp + safecrt/splitpath_s.cpp + safecrt/sprintf_s.cpp + safecrt/sscanf_s.cpp + safecrt/strcat_s.cpp + safecrt/strcpy_s.cpp + safecrt/strlen_s.cpp + safecrt/strncat_s.cpp + safecrt/strncpy_s.cpp + safecrt/strtok_s.cpp + safecrt/swprintf.cpp + safecrt/vsprintf.cpp + safecrt/vswprint.cpp + safecrt/wcscat_s.cpp + safecrt/wcscpy_s.cpp + safecrt/wcslen_s.cpp + safecrt/wcsncat_s.cpp + safecrt/wcsncpy_s.cpp + safecrt/wcstok_s.cpp + safecrt/wmakepath_s.cpp + safecrt/wsplitpath_s.cpp + safecrt/xtoa_s.cpp + safecrt/xtow_s.cpp sharedmemory/sharedmemory.cpp shmemory/shmemory.cpp sync/cs.cpp @@ -252,7 +268,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL Linux) find_library(UNWIND_ARCH NAMES unwind-x86_64) endif() - if(PAL_SYSTEM_ALPINE) + if(CLR_CMAKE_PLATFORM_ALPINE_LINUX) find_library(INTL intl) endif() diff --git a/src/pal/src/arch/i386/activationhandlerwrapper.S b/src/pal/src/arch/amd64/activationhandlerwrapper.S index 63f718e81f..63f718e81f 100644 --- a/src/pal/src/arch/i386/activationhandlerwrapper.S +++ b/src/pal/src/arch/amd64/activationhandlerwrapper.S diff --git a/src/pal/src/arch/amd64/asmconstants.h b/src/pal/src/arch/amd64/asmconstants.h new file mode 100644 index 0000000000..182c1191e4 --- /dev/null +++ b/src/pal/src/arch/amd64/asmconstants.h @@ -0,0 +1,106 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifdef BIT64 + +#define CONTEXT_AMD64 0x100000 + +#define CONTEXT_CONTROL 1 // SegSs, Rsp, SegCs, Rip, and EFlags +#define CONTEXT_INTEGER 2 // Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, R8-R15 +#define CONTEXT_SEGMENTS 4 // SegDs, SegEs, SegFs, SegGs +#define CONTEXT_FLOATING_POINT 8 +#define CONTEXT_DEBUG_REGISTERS 16 // Dr0-Dr3 and Dr6-Dr7 + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + +#define CONTEXT_XSTATE 64 + +#define CONTEXT_ContextFlags 6*8 +#define CONTEXT_SegCs CONTEXT_ContextFlags+8 +#define CONTEXT_SegDs CONTEXT_SegCs+2 +#define CONTEXT_SegEs CONTEXT_SegDs+2 +#define CONTEXT_SegFs CONTEXT_SegEs+2 +#define CONTEXT_SegGs CONTEXT_SegFs+2 +#define CONTEXT_SegSs CONTEXT_SegGs+2 +#define CONTEXT_EFlags CONTEXT_SegSs+2 +#define CONTEXT_Dr0 CONTEXT_EFlags+4 +#define CONTEXT_Dr1 CONTEXT_Dr0+8 +#define CONTEXT_Dr2 CONTEXT_Dr1+8 +#define CONTEXT_Dr3 CONTEXT_Dr2+8 +#define CONTEXT_Dr6 CONTEXT_Dr3+8 +#define CONTEXT_Dr7 CONTEXT_Dr6+8 +#define CONTEXT_Rax CONTEXT_Dr7+8 +#define CONTEXT_Rcx CONTEXT_Rax+8 +#define CONTEXT_Rdx CONTEXT_Rcx+8 +#define CONTEXT_Rbx CONTEXT_Rdx+8 +#define CONTEXT_Rsp CONTEXT_Rbx+8 +#define CONTEXT_Rbp CONTEXT_Rsp+8 +#define CONTEXT_Rsi CONTEXT_Rbp+8 +#define CONTEXT_Rdi CONTEXT_Rsi+8 +#define CONTEXT_R8 CONTEXT_Rdi+8 +#define CONTEXT_R9 CONTEXT_R8+8 +#define CONTEXT_R10 CONTEXT_R9+8 +#define CONTEXT_R11 CONTEXT_R10+8 +#define CONTEXT_R12 CONTEXT_R11+8 +#define CONTEXT_R13 CONTEXT_R12+8 +#define CONTEXT_R14 CONTEXT_R13+8 +#define CONTEXT_R15 CONTEXT_R14+8 +#define CONTEXT_Rip CONTEXT_R15+8 +#define CONTEXT_FltSave CONTEXT_Rip+8 +#define FLOATING_SAVE_AREA_SIZE 4*8+24*16+96 +#define CONTEXT_Xmm0 CONTEXT_FltSave+10*16 +#define CONTEXT_Xmm1 CONTEXT_Xmm0+16 +#define CONTEXT_Xmm2 CONTEXT_Xmm1+16 +#define CONTEXT_Xmm3 CONTEXT_Xmm2+16 +#define CONTEXT_Xmm4 CONTEXT_Xmm3+16 +#define CONTEXT_Xmm5 CONTEXT_Xmm4+16 +#define CONTEXT_Xmm6 CONTEXT_Xmm5+16 +#define CONTEXT_Xmm7 CONTEXT_Xmm6+16 +#define CONTEXT_Xmm8 CONTEXT_Xmm7+16 +#define CONTEXT_Xmm9 CONTEXT_Xmm8+16 +#define CONTEXT_Xmm10 CONTEXT_Xmm9+16 +#define CONTEXT_Xmm11 CONTEXT_Xmm10+16 +#define CONTEXT_Xmm12 CONTEXT_Xmm11+16 +#define CONTEXT_Xmm13 CONTEXT_Xmm12+16 +#define CONTEXT_Xmm14 CONTEXT_Xmm13+16 +#define CONTEXT_Xmm15 CONTEXT_Xmm14+16 +#define CONTEXT_VectorRegister CONTEXT_FltSave+FLOATING_SAVE_AREA_SIZE +#define CONTEXT_VectorControl CONTEXT_VectorRegister+16*26 +#define CONTEXT_DebugControl CONTEXT_VectorControl+8 +#define CONTEXT_LastBranchToRip CONTEXT_DebugControl+8 +#define CONTEXT_LastBranchFromRip CONTEXT_LastBranchToRip+8 +#define CONTEXT_LastExceptionToRip CONTEXT_LastBranchFromRip+8 +#define CONTEXT_LastExceptionFromRip CONTEXT_LastExceptionToRip+8 +#define CONTEXT_Size CONTEXT_LastExceptionFromRip+8 + +#else // BIT64 + +#define CONTEXT_ContextFlags 0 +#define CONTEXT_FLOATING_POINT 8 +#define CONTEXT_FloatSave 7*4 +#define FLOATING_SAVE_AREA_SIZE 8*4+80 +#define CONTEXT_Edi CONTEXT_FloatSave + FLOATING_SAVE_AREA_SIZE + 4*4 +#define CONTEXT_Esi CONTEXT_Edi+4 +#define CONTEXT_Ebx CONTEXT_Esi+4 +#define CONTEXT_Edx CONTEXT_Ebx+4 +#define CONTEXT_Ecx CONTEXT_Edx+4 +#define CONTEXT_Eax CONTEXT_Ecx+4 +#define CONTEXT_Ebp CONTEXT_Eax+4 +#define CONTEXT_Eip CONTEXT_Ebp+4 +#define CONTEXT_SegCs CONTEXT_Eip+4 +#define CONTEXT_EFlags CONTEXT_SegCs+4 +#define CONTEXT_Esp CONTEXT_EFlags+4 +#define CONTEXT_SegSs CONTEXT_Esp+4 +#define CONTEXT_EXTENDED_REGISTERS 32 +#define CONTEXT_ExtendedRegisters CONTEXT_SegSs+4 +#define CONTEXT_Xmm0 CONTEXT_ExtendedRegisters+160 +#define CONTEXT_Xmm1 CONTEXT_Xmm0+16 +#define CONTEXT_Xmm2 CONTEXT_Xmm1+16 +#define CONTEXT_Xmm3 CONTEXT_Xmm2+16 +#define CONTEXT_Xmm4 CONTEXT_Xmm3+16 +#define CONTEXT_Xmm5 CONTEXT_Xmm4+16 +#define CONTEXT_Xmm6 CONTEXT_Xmm5+16 +#define CONTEXT_Xmm7 CONTEXT_Xmm6+16 + +#endif // BIT64 diff --git a/src/pal/src/arch/i386/context.S b/src/pal/src/arch/amd64/context.S index f8a2dca89c..f8a2dca89c 100644 --- a/src/pal/src/arch/i386/context.S +++ b/src/pal/src/arch/amd64/context.S diff --git a/src/pal/src/arch/amd64/context2.S b/src/pal/src/arch/amd64/context2.S new file mode 100644 index 0000000000..0e93e81a55 --- /dev/null +++ b/src/pal/src/arch/amd64/context2.S @@ -0,0 +1,259 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// Implementation of _CONTEXT_CaptureContext for the Intel x86 platform. +// This function is processor dependent. It is used by exception handling, +// and is always apply to the current thread. +// + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + +#ifdef BIT64 + +#define IRETFRAME_Rip 0 +#define IRETFRAME_SegCs IRETFRAME_Rip+8 +#define IRETFRAME_EFlags IRETFRAME_SegCs+8 +#define IRETFRAME_Rsp IRETFRAME_EFlags+8 +#define IRETFRAME_SegSs IRETFRAME_Rsp+8 +#define IRetFrameLength IRETFRAME_SegSs+8 +#define IRetFrameLengthAligned 16*((IRetFrameLength+8)/16) + +// Incoming: +// RDI: Context* +// +LEAF_ENTRY CONTEXT_CaptureContext, _TEXT + // Save processor flags before calling any of the following 'test' instructions + // because they will modify state of some flags + push_eflags + END_PROLOGUE + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_INTEGER + je LOCAL_LABEL(Done_CONTEXT_INTEGER) + mov [rdi + CONTEXT_Rdi], rdi + mov [rdi + CONTEXT_Rsi], rsi + mov [rdi + CONTEXT_Rbx], rbx + mov [rdi + CONTEXT_Rdx], rdx + mov [rdi + CONTEXT_Rcx], rcx + mov [rdi + CONTEXT_Rax], rax + mov [rdi + CONTEXT_Rbp], rbp + mov [rdi + CONTEXT_R8], r8 + mov [rdi + CONTEXT_R9], r9 + mov [rdi + CONTEXT_R10], r10 + mov [rdi + CONTEXT_R11], r11 + mov [rdi + CONTEXT_R12], r12 + mov [rdi + CONTEXT_R13], r13 + mov [rdi + CONTEXT_R14], r14 + mov [rdi + CONTEXT_R15], r15 +LOCAL_LABEL(Done_CONTEXT_INTEGER): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL + je LOCAL_LABEL(Done_CONTEXT_CONTROL) + + // Return address is @ (RSP + 8) + mov rdx, [rsp + 8] + mov [rdi + CONTEXT_Rip], rdx +.att_syntax + mov %cs, CONTEXT_SegCs(%rdi) +.intel_syntax noprefix + // Get the value of EFlags that was pushed on stack at the beginning of the function + mov rdx, [rsp] + mov [rdi + CONTEXT_EFlags], edx + lea rdx, [rsp + 16] + mov [rdi + CONTEXT_Rsp], rdx +.att_syntax + mov %ss, CONTEXT_SegSs(%rdi) +.intel_syntax noprefix +LOCAL_LABEL(Done_CONTEXT_CONTROL): + + // Need to double check this is producing the right result + // also that FFSXR (fast save/restore) is not turned on + // otherwise it omits the xmm registers. + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + je LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT) + fxsave [rdi + CONTEXT_FltSave] +LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_DEBUG_REGISTERS + je LOCAL_LABEL(Done_CONTEXT_DEBUG_REGISTERS) + mov rdx, dr0 + mov [rdi + CONTEXT_Dr0], rdx + mov rdx, dr1 + mov [rdi + CONTEXT_Dr1], rdx + mov rdx, dr2 + mov [rdi + CONTEXT_Dr2], rdx + mov rdx, dr3 + mov [rdi + CONTEXT_Dr3], rdx + mov rdx, dr6 + mov [rdi + CONTEXT_Dr6], rdx + mov rdx, dr7 + mov [rdi + CONTEXT_Dr7], rdx +LOCAL_LABEL(Done_CONTEXT_DEBUG_REGISTERS): + + free_stack 8 + ret +LEAF_END CONTEXT_CaptureContext, _TEXT + +LEAF_ENTRY RtlCaptureContext, _TEXT + mov DWORD PTR [rdi + CONTEXT_ContextFlags], (CONTEXT_AMD64 | CONTEXT_FULL | CONTEXT_SEGMENTS) + jmp C_FUNC(CONTEXT_CaptureContext) +LEAF_END RtlCaptureContext, _TEXT + +LEAF_ENTRY RtlRestoreContext, _TEXT + push_nonvol_reg rbp + alloc_stack (IRetFrameLengthAligned) + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_DEBUG_REGISTERS + je LOCAL_LABEL(Done_Restore_CONTEXT_DEBUG_REGISTERS) + mov rdx, [rdi + CONTEXT_Dr0] + mov dr0, rdx + mov rdx, [rdi + CONTEXT_Dr1] + mov dr1, rdx + mov rdx, [rdi + CONTEXT_Dr2] + mov dr2, rdx + mov rdx, [rdi + CONTEXT_Dr3] + mov dr3, rdx + mov rdx, [rdi + CONTEXT_Dr6] + mov dr6, rdx + mov rdx, [rdi + CONTEXT_Dr7] + mov dr7, rdx +LOCAL_LABEL(Done_Restore_CONTEXT_DEBUG_REGISTERS): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + je LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT) + fxrstor [rdi + CONTEXT_FltSave] +LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_XSTATE + je LOCAL_LABEL(Done_Restore_CONTEXT_XSTATE) + + // Restore the extended state (for now, this is just the upper halves of YMM registers) + vinsertf128 ymm0, ymm0, xmmword ptr [rdi + (CONTEXT_VectorRegister + 0 * 16)], 1 + vinsertf128 ymm1, ymm1, xmmword ptr [rdi + (CONTEXT_VectorRegister + 1 * 16)], 1 + vinsertf128 ymm2, ymm2, xmmword ptr [rdi + (CONTEXT_VectorRegister + 2 * 16)], 1 + vinsertf128 ymm3, ymm3, xmmword ptr [rdi + (CONTEXT_VectorRegister + 3 * 16)], 1 + vinsertf128 ymm4, ymm4, xmmword ptr [rdi + (CONTEXT_VectorRegister + 4 * 16)], 1 + vinsertf128 ymm5, ymm5, xmmword ptr [rdi + (CONTEXT_VectorRegister + 5 * 16)], 1 + vinsertf128 ymm6, ymm6, xmmword ptr [rdi + (CONTEXT_VectorRegister + 6 * 16)], 1 + vinsertf128 ymm7, ymm7, xmmword ptr [rdi + (CONTEXT_VectorRegister + 7 * 16)], 1 + vinsertf128 ymm8, ymm8, xmmword ptr [rdi + (CONTEXT_VectorRegister + 8 * 16)], 1 + vinsertf128 ymm9, ymm9, xmmword ptr [rdi + (CONTEXT_VectorRegister + 9 * 16)], 1 + vinsertf128 ymm10, ymm10, xmmword ptr [rdi + (CONTEXT_VectorRegister + 10 * 16)], 1 + vinsertf128 ymm11, ymm11, xmmword ptr [rdi + (CONTEXT_VectorRegister + 11 * 16)], 1 + vinsertf128 ymm12, ymm12, xmmword ptr [rdi + (CONTEXT_VectorRegister + 12 * 16)], 1 + vinsertf128 ymm13, ymm13, xmmword ptr [rdi + (CONTEXT_VectorRegister + 13 * 16)], 1 + vinsertf128 ymm14, ymm14, xmmword ptr [rdi + (CONTEXT_VectorRegister + 14 * 16)], 1 + vinsertf128 ymm15, ymm15, xmmword ptr [rdi + (CONTEXT_VectorRegister + 15 * 16)], 1 +LOCAL_LABEL(Done_Restore_CONTEXT_XSTATE): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL + je LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL) + + // The control registers are restored via the iret instruction + // so we build the frame for the iret on the stack. +#ifdef __APPLE__ +.att_syntax + // On OSX, we cannot read SS via the thread_get_context and RtlRestoreContext + // needs to be used on context extracted by thread_get_context. So we + // don't change the SS. + mov %ss, %ax +.intel_syntax noprefix +#else + mov ax, [rdi + CONTEXT_SegSs] +#endif + mov [rsp + IRETFRAME_SegSs], ax + mov rax, [rdi + CONTEXT_Rsp] + mov [rsp + IRETFRAME_Rsp], rax + mov eax, [rdi + CONTEXT_EFlags] + mov [rsp + IRETFRAME_EFlags], eax + mov ax, [rdi + CONTEXT_SegCs] + mov [rsp + IRETFRAME_SegCs], ax + mov rax, [rdi + CONTEXT_Rip] + mov [rsp + IRETFRAME_Rip], rax + +LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL): + // Remember the result of the test for the CONTEXT_CONTROL + push_eflags + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_INTEGER + je LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER) + mov rsi, [rdi + CONTEXT_Rsi] + mov rbx, [rdi + CONTEXT_Rbx] + mov rdx, [rdi + CONTEXT_Rdx] + mov rcx, [rdi + CONTEXT_Rcx] + mov rax, [rdi + CONTEXT_Rax] + mov rbp, [rdi + CONTEXT_Rbp] + mov r8, [rdi + CONTEXT_R8] + mov r9, [rdi + CONTEXT_R9] + mov r10, [rdi + CONTEXT_R10] + mov r11, [rdi + CONTEXT_R11] + mov r12, [rdi + CONTEXT_R12] + mov r13, [rdi + CONTEXT_R13] + mov r14, [rdi + CONTEXT_R14] + mov r15, [rdi + CONTEXT_R15] + mov rdi, [rdi + CONTEXT_Rdi] +LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER): + + // Restore the result of the test for the CONTEXT_CONTROL + pop_eflags + je LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) + // The function was asked to restore the control registers, so + // we perform iretq that restores them all. + // We don't return to the caller in this case. + iretq +LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): + + // The function was not asked to restore the control registers + // so we return back to the caller. + free_stack (IRetFrameLengthAligned) + pop_nonvol_reg rbp + ret +LEAF_END RtlRestoreContext, _TEXT + +#else + + .globl C_FUNC(CONTEXT_CaptureContext) +C_FUNC(CONTEXT_CaptureContext): + push %eax + mov 8(%esp), %eax + mov %edi, CONTEXT_Edi(%eax) + mov %esi, CONTEXT_Esi(%eax) + mov %ebx, CONTEXT_Ebx(%eax) + mov %edx, CONTEXT_Edx(%eax) + mov %ecx, CONTEXT_Ecx(%eax) + pop %ecx + mov %ecx, CONTEXT_Eax(%eax) + mov %ebp, CONTEXT_Ebp(%eax) + mov (%esp), %edx + mov %edx, CONTEXT_Eip(%eax) + push %cs + pop %edx + mov %edx, CONTEXT_SegCs(%eax) + pushf + pop %edx + mov %edx, CONTEXT_EFlags(%eax) + lea 4(%esp), %edx + mov %edx, CONTEXT_Esp(%eax) + push %ss + pop %edx + mov %edx, CONTEXT_SegSs(%eax) + testb $CONTEXT_FLOATING_POINT, CONTEXT_ContextFlags(%eax) + je 0f + fnsave CONTEXT_FloatSave(%eax) + frstor CONTEXT_FloatSave(%eax) +0: + testb $CONTEXT_EXTENDED_REGISTERS, CONTEXT_ContextFlags(%eax) + je 2f + movdqu %xmm0, CONTEXT_Xmm0(%eax) + movdqu %xmm1, CONTEXT_Xmm1(%eax) + movdqu %xmm2, CONTEXT_Xmm2(%eax) + movdqu %xmm3, CONTEXT_Xmm3(%eax) + movdqu %xmm4, CONTEXT_Xmm4(%eax) + movdqu %xmm5, CONTEXT_Xmm5(%eax) + movdqu %xmm6, CONTEXT_Xmm6(%eax) + movdqu %xmm7, CONTEXT_Xmm7(%eax) +2: + ret + +#endif diff --git a/src/pal/src/arch/amd64/debugbreak.S b/src/pal/src/arch/amd64/debugbreak.S new file mode 100644 index 0000000000..3065e4064c --- /dev/null +++ b/src/pal/src/arch/amd64/debugbreak.S @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.intel_syntax noprefix +#include "unixasmmacros.inc" + +LEAF_ENTRY DBG_DebugBreak, _TEXT + int3 + ret +LEAF_END_MARKED DBG_DebugBreak, _TEXT + diff --git a/src/pal/src/arch/i386/dispatchexceptionwrapper.S b/src/pal/src/arch/amd64/dispatchexceptionwrapper.S index ee5ff468d6..ee5ff468d6 100644 --- a/src/pal/src/arch/i386/dispatchexceptionwrapper.S +++ b/src/pal/src/arch/amd64/dispatchexceptionwrapper.S diff --git a/src/pal/src/arch/amd64/exceptionhelper.S b/src/pal/src/arch/amd64/exceptionhelper.S new file mode 100644 index 0000000000..b7b34ace41 --- /dev/null +++ b/src/pal/src/arch/amd64/exceptionhelper.S @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + +////////////////////////////////////////////////////////////////////////// +// +// This function creates a stack frame right below the target frame, restores all callee +// saved registers from the passed in context, sets the RSP to that frame and sets the +// return address to the target frame's RIP. +// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. +// EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); +LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT + // Save the RBP to the stack so that the unwind can work at the instruction after + // loading the RBP from the context, but before loading the RSP from the context. + push_nonvol_reg rbp + mov r12, [rdi + CONTEXT_R12] + mov r13, [rdi + CONTEXT_R13] + mov r14, [rdi + CONTEXT_R14] + mov r15, [rdi + CONTEXT_R15] + mov rbx, [rdi + CONTEXT_Rbx] + mov rbp, [rdi + CONTEXT_Rbp] + mov rsp, [rdi + CONTEXT_Rsp] + // The RSP was set to the target frame's value, so the current function's + // CFA is now right at the RSP. + .cfi_def_cfa_offset 0 + + // Indicate that now that we have moved the RSP to the target address, + // the RBP is no longer saved in the current stack frame. + .cfi_restore rbp + + mov rax, [rdi + CONTEXT_Rip] + + // Store return address to the stack + push_register rax + // The PAL_SEHException pointer + mov rdi, rsi + jmp EXTERNAL_C_FUNC(ThrowExceptionHelper) +LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/src/pal/src/arch/i386/optimizedtls.cpp b/src/pal/src/arch/amd64/optimizedtls.cpp index 910a6eb931..cd89db6b0a 100644 --- a/src/pal/src/arch/i386/optimizedtls.cpp +++ b/src/pal/src/arch/amd64/optimizedtls.cpp @@ -79,7 +79,7 @@ CorUnix::TLSMakeOptimizedGetter( } // Need to preserve %ecx, %edx, and %esi registers as specified in - // GetThreadGeneric(void) in vm/i386/asmhelpers.s + // GetThreadGeneric(void) in vm/amd64/asmhelpers.s p[i++] = 0x51; // push %ecx p[i++] = 0x52; // push %edx p[i++] = 0x89; // mov %esp,%eax // %eax = sp; diff --git a/src/pal/src/arch/amd64/processor.cpp b/src/pal/src/arch/amd64/processor.cpp new file mode 100644 index 0000000000..ac3d448a81 --- /dev/null +++ b/src/pal/src/arch/amd64/processor.cpp @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*++ + + + +Module Name: + + processor.cpp + +Abstract: + + Implementation of processor related functions for the Intel x86/x64 + platforms. These functions are processor dependent. + + + +--*/ + +#include "pal/palinternal.h" + +/*++ +Function: +YieldProcessor + +The YieldProcessor function signals to the processor to give resources +to threads that are waiting for them. This macro is only effective on +processors that support technology allowing multiple threads running +on a single processor, such as Intel's Hyper-Threading technology. + +--*/ +void +PALAPI +YieldProcessor( + VOID) +{ + __asm__ __volatile__ ( + "rep\n" + "nop" + ); +} + +/*++ +Function: +XmmYmmStateSupport + +Check if OS has enabled both XMM and YMM state support + +Return value: +1 if XMM and YMM are enabled, 0 otherwise +--*/ +extern "C" unsigned int XmmYmmStateSupport() +{ + unsigned int eax; + __asm(" xgetbv\n" \ + : "=a"(eax) /*output in eax*/\ + : "c"(0) /*inputs - 0 in ecx*/\ + : "eax", "edx" /* registers that are clobbered*/ + ); + // Check OS has enabled both XMM and YMM state support + return ((eax & 0x06) == 0x06) ? 1 : 0; +} diff --git a/src/pal/src/arch/arm/exceptionhelper.S b/src/pal/src/arch/arm/exceptionhelper.S index ed1c9c3dc2..76cdcba9b4 100644 --- a/src/pal/src/arch/arm/exceptionhelper.S +++ b/src/pal/src/arch/arm/exceptionhelper.S @@ -10,7 +10,7 @@ // EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT - // Ported from src/pal/src/arch/i386/exceptionhelper.S + // Ported from src/pal/src/arch/amd64/exceptionhelper.S push_nonvol_reg {r7} /* FP. x64-RBP */ ldr r4, [r0, #(CONTEXT_R4)] diff --git a/src/pal/src/arch/i386/asmconstants.h b/src/pal/src/arch/i386/asmconstants.h index 182c1191e4..ff763ef16b 100644 --- a/src/pal/src/arch/i386/asmconstants.h +++ b/src/pal/src/arch/i386/asmconstants.h @@ -2,80 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#ifdef BIT64 - -#define CONTEXT_AMD64 0x100000 - -#define CONTEXT_CONTROL 1 // SegSs, Rsp, SegCs, Rip, and EFlags -#define CONTEXT_INTEGER 2 // Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, R8-R15 -#define CONTEXT_SEGMENTS 4 // SegDs, SegEs, SegFs, SegGs -#define CONTEXT_FLOATING_POINT 8 -#define CONTEXT_DEBUG_REGISTERS 16 // Dr0-Dr3 and Dr6-Dr7 - -#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) - -#define CONTEXT_XSTATE 64 - -#define CONTEXT_ContextFlags 6*8 -#define CONTEXT_SegCs CONTEXT_ContextFlags+8 -#define CONTEXT_SegDs CONTEXT_SegCs+2 -#define CONTEXT_SegEs CONTEXT_SegDs+2 -#define CONTEXT_SegFs CONTEXT_SegEs+2 -#define CONTEXT_SegGs CONTEXT_SegFs+2 -#define CONTEXT_SegSs CONTEXT_SegGs+2 -#define CONTEXT_EFlags CONTEXT_SegSs+2 -#define CONTEXT_Dr0 CONTEXT_EFlags+4 -#define CONTEXT_Dr1 CONTEXT_Dr0+8 -#define CONTEXT_Dr2 CONTEXT_Dr1+8 -#define CONTEXT_Dr3 CONTEXT_Dr2+8 -#define CONTEXT_Dr6 CONTEXT_Dr3+8 -#define CONTEXT_Dr7 CONTEXT_Dr6+8 -#define CONTEXT_Rax CONTEXT_Dr7+8 -#define CONTEXT_Rcx CONTEXT_Rax+8 -#define CONTEXT_Rdx CONTEXT_Rcx+8 -#define CONTEXT_Rbx CONTEXT_Rdx+8 -#define CONTEXT_Rsp CONTEXT_Rbx+8 -#define CONTEXT_Rbp CONTEXT_Rsp+8 -#define CONTEXT_Rsi CONTEXT_Rbp+8 -#define CONTEXT_Rdi CONTEXT_Rsi+8 -#define CONTEXT_R8 CONTEXT_Rdi+8 -#define CONTEXT_R9 CONTEXT_R8+8 -#define CONTEXT_R10 CONTEXT_R9+8 -#define CONTEXT_R11 CONTEXT_R10+8 -#define CONTEXT_R12 CONTEXT_R11+8 -#define CONTEXT_R13 CONTEXT_R12+8 -#define CONTEXT_R14 CONTEXT_R13+8 -#define CONTEXT_R15 CONTEXT_R14+8 -#define CONTEXT_Rip CONTEXT_R15+8 -#define CONTEXT_FltSave CONTEXT_Rip+8 -#define FLOATING_SAVE_AREA_SIZE 4*8+24*16+96 -#define CONTEXT_Xmm0 CONTEXT_FltSave+10*16 -#define CONTEXT_Xmm1 CONTEXT_Xmm0+16 -#define CONTEXT_Xmm2 CONTEXT_Xmm1+16 -#define CONTEXT_Xmm3 CONTEXT_Xmm2+16 -#define CONTEXT_Xmm4 CONTEXT_Xmm3+16 -#define CONTEXT_Xmm5 CONTEXT_Xmm4+16 -#define CONTEXT_Xmm6 CONTEXT_Xmm5+16 -#define CONTEXT_Xmm7 CONTEXT_Xmm6+16 -#define CONTEXT_Xmm8 CONTEXT_Xmm7+16 -#define CONTEXT_Xmm9 CONTEXT_Xmm8+16 -#define CONTEXT_Xmm10 CONTEXT_Xmm9+16 -#define CONTEXT_Xmm11 CONTEXT_Xmm10+16 -#define CONTEXT_Xmm12 CONTEXT_Xmm11+16 -#define CONTEXT_Xmm13 CONTEXT_Xmm12+16 -#define CONTEXT_Xmm14 CONTEXT_Xmm13+16 -#define CONTEXT_Xmm15 CONTEXT_Xmm14+16 -#define CONTEXT_VectorRegister CONTEXT_FltSave+FLOATING_SAVE_AREA_SIZE -#define CONTEXT_VectorControl CONTEXT_VectorRegister+16*26 -#define CONTEXT_DebugControl CONTEXT_VectorControl+8 -#define CONTEXT_LastBranchToRip CONTEXT_DebugControl+8 -#define CONTEXT_LastBranchFromRip CONTEXT_LastBranchToRip+8 -#define CONTEXT_LastExceptionToRip CONTEXT_LastBranchFromRip+8 -#define CONTEXT_LastExceptionFromRip CONTEXT_LastExceptionToRip+8 -#define CONTEXT_Size CONTEXT_LastExceptionFromRip+8 - -#else // BIT64 - #define CONTEXT_ContextFlags 0 #define CONTEXT_FLOATING_POINT 8 #define CONTEXT_FloatSave 7*4 @@ -102,5 +28,3 @@ #define CONTEXT_Xmm5 CONTEXT_Xmm4+16 #define CONTEXT_Xmm6 CONTEXT_Xmm5+16 #define CONTEXT_Xmm7 CONTEXT_Xmm6+16 - -#endif // BIT64 diff --git a/src/pal/src/arch/i386/context2.S b/src/pal/src/arch/i386/context2.S index 0e93e81a55..16cbcc855c 100644 --- a/src/pal/src/arch/i386/context2.S +++ b/src/pal/src/arch/i386/context2.S @@ -1,259 +1,151 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// -// Implementation of _CONTEXT_CaptureContext for the Intel x86 platform. -// This function is processor dependent. It is used by exception handling, -// and is always apply to the current thread. -// .intel_syntax noprefix #include "unixasmmacros.inc" #include "asmconstants.h" -#ifdef BIT64 - -#define IRETFRAME_Rip 0 -#define IRETFRAME_SegCs IRETFRAME_Rip+8 -#define IRETFRAME_EFlags IRETFRAME_SegCs+8 -#define IRETFRAME_Rsp IRETFRAME_EFlags+8 -#define IRETFRAME_SegSs IRETFRAME_Rsp+8 -#define IRetFrameLength IRETFRAME_SegSs+8 -#define IRetFrameLengthAligned 16*((IRetFrameLength+8)/16) - -// Incoming: -// RDI: Context* +// +// Implementation of CONTEXT_CaptureContext for the Intel x86 platform. +// +// extern void CONTEXT_CaptureContext(LPCONTEXT lpContext); +// +// This function is processor-dependent. It is used by exception handling, +// and is always apply to the current thread. // LEAF_ENTRY CONTEXT_CaptureContext, _TEXT - // Save processor flags before calling any of the following 'test' instructions - // because they will modify state of some flags - push_eflags - END_PROLOGUE + // Store + push eax + push ebx + + // The stack will contain the following elements on the top of + // the caller's stack + // [ebx] / esp + 00 + // [eax] / esp + 04 + // [ret] / esp + 08 + // [arg0: lpContext] / esp + 12 + + mov eax, [esp + 12] // eax will point to lpContext + + // Capture INTEGER registers + mov ebx, [esp + 4] + mov [eax + CONTEXT_Eax], ebx + mov ebx, [esp] + mov [eax + CONTEXT_Ebx], ebx + mov [eax + CONTEXT_Ecx], ecx + mov [eax + CONTEXT_Edx], edx + mov [eax + CONTEXT_Esi], esi + mov [eax + CONTEXT_Edi], edi + + // Capture CONTROL registers + mov [eax + CONTEXT_Ebp], ebp + lea ebx, [esp + 12] + mov [eax + CONTEXT_Esp], ebx + mov ebx, [esp + 8] + mov [eax + CONTEXT_Eip], ebx + + push cs + xor ebx, ebx + pop bx + mov [eax + CONTEXT_SegCs], ebx + + push ss + xor ebx, ebx + pop bx + mov [eax + CONTEXT_SegSs], ebx - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_INTEGER - je LOCAL_LABEL(Done_CONTEXT_INTEGER) - mov [rdi + CONTEXT_Rdi], rdi - mov [rdi + CONTEXT_Rsi], rsi - mov [rdi + CONTEXT_Rbx], rbx - mov [rdi + CONTEXT_Rdx], rdx - mov [rdi + CONTEXT_Rcx], rcx - mov [rdi + CONTEXT_Rax], rax - mov [rdi + CONTEXT_Rbp], rbp - mov [rdi + CONTEXT_R8], r8 - mov [rdi + CONTEXT_R9], r9 - mov [rdi + CONTEXT_R10], r10 - mov [rdi + CONTEXT_R11], r11 - mov [rdi + CONTEXT_R12], r12 - mov [rdi + CONTEXT_R13], r13 - mov [rdi + CONTEXT_R14], r14 - mov [rdi + CONTEXT_R15], r15 -LOCAL_LABEL(Done_CONTEXT_INTEGER): - - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL - je LOCAL_LABEL(Done_CONTEXT_CONTROL) - - // Return address is @ (RSP + 8) - mov rdx, [rsp + 8] - mov [rdi + CONTEXT_Rip], rdx -.att_syntax - mov %cs, CONTEXT_SegCs(%rdi) -.intel_syntax noprefix - // Get the value of EFlags that was pushed on stack at the beginning of the function - mov rdx, [rsp] - mov [rdi + CONTEXT_EFlags], edx - lea rdx, [rsp + 16] - mov [rdi + CONTEXT_Rsp], rdx -.att_syntax - mov %ss, CONTEXT_SegSs(%rdi) -.intel_syntax noprefix -LOCAL_LABEL(Done_CONTEXT_CONTROL): + pushf + xor ebx, ebx + pop bx + mov [eax + CONTEXT_EFlags], ebx - // Need to double check this is producing the right result - // also that FFSXR (fast save/restore) is not turned on - // otherwise it omits the xmm registers. - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT je LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT) - fxsave [rdi + CONTEXT_FltSave] + // Capture FPU status + fnsave [eax + CONTEXT_FloatSave] + frstor [eax + CONTEXT_FloatSave] LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT): - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_DEBUG_REGISTERS - je LOCAL_LABEL(Done_CONTEXT_DEBUG_REGISTERS) - mov rdx, dr0 - mov [rdi + CONTEXT_Dr0], rdx - mov rdx, dr1 - mov [rdi + CONTEXT_Dr1], rdx - mov rdx, dr2 - mov [rdi + CONTEXT_Dr2], rdx - mov rdx, dr3 - mov [rdi + CONTEXT_Dr3], rdx - mov rdx, dr6 - mov [rdi + CONTEXT_Dr6], rdx - mov rdx, dr7 - mov [rdi + CONTEXT_Dr7], rdx -LOCAL_LABEL(Done_CONTEXT_DEBUG_REGISTERS): - - free_stack 8 - ret + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_EXTENDED_REGISTERS + je LOCAL_LABEL(Done_CONTEXT_EXTENDED_REGISTERS) + movdqu [eax + CONTEXT_Xmm0], xmm0 + movdqu [eax + CONTEXT_Xmm1], xmm1 + movdqu [eax + CONTEXT_Xmm2], xmm2 + movdqu [eax + CONTEXT_Xmm3], xmm3 + movdqu [eax + CONTEXT_Xmm4], xmm4 + movdqu [eax + CONTEXT_Xmm5], xmm5 + movdqu [eax + CONTEXT_Xmm6], xmm6 + movdqu [eax + CONTEXT_Xmm7], xmm7 +LOCAL_LABEL(Done_CONTEXT_EXTENDED_REGISTERS): + + // Restore + pop ebx + pop eax + ret 4 LEAF_END CONTEXT_CaptureContext, _TEXT LEAF_ENTRY RtlCaptureContext, _TEXT - mov DWORD PTR [rdi + CONTEXT_ContextFlags], (CONTEXT_AMD64 | CONTEXT_FULL | CONTEXT_SEGMENTS) + push eax + mov eax, [esp + 8] + mov DWORD PTR [eax + CONTEXT_ContextFlags], (CONTEXT_FLOATING_POINT) + pop eax jmp C_FUNC(CONTEXT_CaptureContext) LEAF_END RtlCaptureContext, _TEXT LEAF_ENTRY RtlRestoreContext, _TEXT - push_nonvol_reg rbp - alloc_stack (IRetFrameLengthAligned) - - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_DEBUG_REGISTERS - je LOCAL_LABEL(Done_Restore_CONTEXT_DEBUG_REGISTERS) - mov rdx, [rdi + CONTEXT_Dr0] - mov dr0, rdx - mov rdx, [rdi + CONTEXT_Dr1] - mov dr1, rdx - mov rdx, [rdi + CONTEXT_Dr2] - mov dr2, rdx - mov rdx, [rdi + CONTEXT_Dr3] - mov dr3, rdx - mov rdx, [rdi + CONTEXT_Dr6] - mov dr6, rdx - mov rdx, [rdi + CONTEXT_Dr7] - mov dr7, rdx -LOCAL_LABEL(Done_Restore_CONTEXT_DEBUG_REGISTERS): + mov eax, [esp + 4] - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT je LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT) - fxrstor [rdi + CONTEXT_FltSave] + frstor [eax + CONTEXT_FloatSave] LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT): - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_XSTATE - je LOCAL_LABEL(Done_Restore_CONTEXT_XSTATE) - - // Restore the extended state (for now, this is just the upper halves of YMM registers) - vinsertf128 ymm0, ymm0, xmmword ptr [rdi + (CONTEXT_VectorRegister + 0 * 16)], 1 - vinsertf128 ymm1, ymm1, xmmword ptr [rdi + (CONTEXT_VectorRegister + 1 * 16)], 1 - vinsertf128 ymm2, ymm2, xmmword ptr [rdi + (CONTEXT_VectorRegister + 2 * 16)], 1 - vinsertf128 ymm3, ymm3, xmmword ptr [rdi + (CONTEXT_VectorRegister + 3 * 16)], 1 - vinsertf128 ymm4, ymm4, xmmword ptr [rdi + (CONTEXT_VectorRegister + 4 * 16)], 1 - vinsertf128 ymm5, ymm5, xmmword ptr [rdi + (CONTEXT_VectorRegister + 5 * 16)], 1 - vinsertf128 ymm6, ymm6, xmmword ptr [rdi + (CONTEXT_VectorRegister + 6 * 16)], 1 - vinsertf128 ymm7, ymm7, xmmword ptr [rdi + (CONTEXT_VectorRegister + 7 * 16)], 1 - vinsertf128 ymm8, ymm8, xmmword ptr [rdi + (CONTEXT_VectorRegister + 8 * 16)], 1 - vinsertf128 ymm9, ymm9, xmmword ptr [rdi + (CONTEXT_VectorRegister + 9 * 16)], 1 - vinsertf128 ymm10, ymm10, xmmword ptr [rdi + (CONTEXT_VectorRegister + 10 * 16)], 1 - vinsertf128 ymm11, ymm11, xmmword ptr [rdi + (CONTEXT_VectorRegister + 11 * 16)], 1 - vinsertf128 ymm12, ymm12, xmmword ptr [rdi + (CONTEXT_VectorRegister + 12 * 16)], 1 - vinsertf128 ymm13, ymm13, xmmword ptr [rdi + (CONTEXT_VectorRegister + 13 * 16)], 1 - vinsertf128 ymm14, ymm14, xmmword ptr [rdi + (CONTEXT_VectorRegister + 14 * 16)], 1 - vinsertf128 ymm15, ymm15, xmmword ptr [rdi + (CONTEXT_VectorRegister + 15 * 16)], 1 -LOCAL_LABEL(Done_Restore_CONTEXT_XSTATE): - - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL - je LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL) - - // The control registers are restored via the iret instruction - // so we build the frame for the iret on the stack. -#ifdef __APPLE__ -.att_syntax - // On OSX, we cannot read SS via the thread_get_context and RtlRestoreContext - // needs to be used on context extracted by thread_get_context. So we - // don't change the SS. - mov %ss, %ax -.intel_syntax noprefix -#else - mov ax, [rdi + CONTEXT_SegSs] -#endif - mov [rsp + IRETFRAME_SegSs], ax - mov rax, [rdi + CONTEXT_Rsp] - mov [rsp + IRETFRAME_Rsp], rax - mov eax, [rdi + CONTEXT_EFlags] - mov [rsp + IRETFRAME_EFlags], eax - mov ax, [rdi + CONTEXT_SegCs] - mov [rsp + IRETFRAME_SegCs], ax - mov rax, [rdi + CONTEXT_Rip] - mov [rsp + IRETFRAME_Rip], rax - -LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL): - // Remember the result of the test for the CONTEXT_CONTROL - push_eflags - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_INTEGER - je LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER) - mov rsi, [rdi + CONTEXT_Rsi] - mov rbx, [rdi + CONTEXT_Rbx] - mov rdx, [rdi + CONTEXT_Rdx] - mov rcx, [rdi + CONTEXT_Rcx] - mov rax, [rdi + CONTEXT_Rax] - mov rbp, [rdi + CONTEXT_Rbp] - mov r8, [rdi + CONTEXT_R8] - mov r9, [rdi + CONTEXT_R9] - mov r10, [rdi + CONTEXT_R10] - mov r11, [rdi + CONTEXT_R11] - mov r12, [rdi + CONTEXT_R12] - mov r13, [rdi + CONTEXT_R13] - mov r14, [rdi + CONTEXT_R14] - mov r15, [rdi + CONTEXT_R15] - mov rdi, [rdi + CONTEXT_Rdi] -LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER): - - // Restore the result of the test for the CONTEXT_CONTROL - pop_eflags - je LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) - // The function was asked to restore the control registers, so - // we perform iretq that restores them all. - // We don't return to the caller in this case. - iretq -LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): - - // The function was not asked to restore the control registers - // so we return back to the caller. - free_stack (IRetFrameLengthAligned) - pop_nonvol_reg rbp - ret + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_EXTENDED_REGISTERS + je LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS) + movdqu xmm0, [eax + CONTEXT_Xmm0] + movdqu xmm1, [eax + CONTEXT_Xmm1] + movdqu xmm2, [eax + CONTEXT_Xmm2] + movdqu xmm3, [eax + CONTEXT_Xmm3] + movdqu xmm4, [eax + CONTEXT_Xmm4] + movdqu xmm5, [eax + CONTEXT_Xmm5] + movdqu xmm6, [eax + CONTEXT_Xmm6] + movdqu xmm7, [eax + CONTEXT_Xmm7] +LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS): + + // Restore CONTROL register(s) + mov ecx, [eax + CONTEXT_Eip] + mov [esp], ecx + + mov ecx, [eax + CONTEXT_Esp] + push ecx + mov ecx, [eax + CONTEXT_Ebp] + push ecx + + pop ebp + pop esp + + // Restore INTEGER register(s) + mov ecx, [eax + CONTEXT_Edi] + push ecx + mov ecx, [eax + CONTEXT_Esi] + push ecx + mov ecx, [eax + CONTEXT_Edx] + push ecx + mov ecx, [eax + CONTEXT_Ecx] + push ecx + mov ecx, [eax + CONTEXT_Ebx] + push ecx + mov ecx, [eax + CONTEXT_Eax] + push ecx + + pop eax + pop ebx + pop ecx + pop edx + pop esi + pop edi + + ret 8 LEAF_END RtlRestoreContext, _TEXT -#else - - .globl C_FUNC(CONTEXT_CaptureContext) -C_FUNC(CONTEXT_CaptureContext): - push %eax - mov 8(%esp), %eax - mov %edi, CONTEXT_Edi(%eax) - mov %esi, CONTEXT_Esi(%eax) - mov %ebx, CONTEXT_Ebx(%eax) - mov %edx, CONTEXT_Edx(%eax) - mov %ecx, CONTEXT_Ecx(%eax) - pop %ecx - mov %ecx, CONTEXT_Eax(%eax) - mov %ebp, CONTEXT_Ebp(%eax) - mov (%esp), %edx - mov %edx, CONTEXT_Eip(%eax) - push %cs - pop %edx - mov %edx, CONTEXT_SegCs(%eax) - pushf - pop %edx - mov %edx, CONTEXT_EFlags(%eax) - lea 4(%esp), %edx - mov %edx, CONTEXT_Esp(%eax) - push %ss - pop %edx - mov %edx, CONTEXT_SegSs(%eax) - testb $CONTEXT_FLOATING_POINT, CONTEXT_ContextFlags(%eax) - je 0f - fnsave CONTEXT_FloatSave(%eax) - frstor CONTEXT_FloatSave(%eax) -0: - testb $CONTEXT_EXTENDED_REGISTERS, CONTEXT_ContextFlags(%eax) - je 2f - movdqu %xmm0, CONTEXT_Xmm0(%eax) - movdqu %xmm1, CONTEXT_Xmm1(%eax) - movdqu %xmm2, CONTEXT_Xmm2(%eax) - movdqu %xmm3, CONTEXT_Xmm3(%eax) - movdqu %xmm4, CONTEXT_Xmm4(%eax) - movdqu %xmm5, CONTEXT_Xmm5(%eax) - movdqu %xmm6, CONTEXT_Xmm6(%eax) - movdqu %xmm7, CONTEXT_Xmm7(%eax) -2: - ret - -#endif diff --git a/src/pal/src/arch/i386/exceptionhelper.S b/src/pal/src/arch/i386/exceptionhelper.S index b7b34ace41..2061be26f8 100644 --- a/src/pal/src/arch/i386/exceptionhelper.S +++ b/src/pal/src/arch/i386/exceptionhelper.S @@ -8,35 +8,36 @@ ////////////////////////////////////////////////////////////////////////// // -// This function creates a stack frame right below the target frame, restores all callee -// saved registers from the passed in context, sets the RSP to that frame and sets the -// return address to the target frame's RIP. -// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. // EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); +// +// This function creates a stack frame right below the target frame, restores all callee +// saved registers from the passed in context, sets the SP to that frame and sets the +// return address to the target frame's IP. +// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. +// +////////////////////////////////////////////////////////////////////////// + LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT - // Save the RBP to the stack so that the unwind can work at the instruction after - // loading the RBP from the context, but before loading the RSP from the context. - push_nonvol_reg rbp - mov r12, [rdi + CONTEXT_R12] - mov r13, [rdi + CONTEXT_R13] - mov r14, [rdi + CONTEXT_R14] - mov r15, [rdi + CONTEXT_R15] - mov rbx, [rdi + CONTEXT_Rbx] - mov rbp, [rdi + CONTEXT_Rbp] - mov rsp, [rdi + CONTEXT_Rsp] - // The RSP was set to the target frame's value, so the current function's - // CFA is now right at the RSP. + push ebp + mov eax, [esp + 12] // ebx: PAL_SEHException * + mov ebx, [esp + 8] // eax: CONTEXT * + + mov ebp, [ebx + CONTEXT_Ebp] + mov esp, [ebx + CONTEXT_Esp] + + // The ESP is re-initialized as the target frame's value, so the current function's + // CFA is now right at the ESP. .cfi_def_cfa_offset 0 - // Indicate that now that we have moved the RSP to the target address, - // the RBP is no longer saved in the current stack frame. - .cfi_restore rbp + // Indicate that now that we have moved the RSP to the target address, + // the EBP is no longer saved in the current stack frame. + .cfi_restore ebp - mov rax, [rdi + CONTEXT_Rip] + // Store PAL_SEHException as the first argument + push eax // Store return address to the stack - push_register rax - // The PAL_SEHException pointer - mov rdi, rsi + mov ebx, [ebx + CONTEXT_Eip] + push ebx jmp EXTERNAL_C_FUNC(ThrowExceptionHelper) LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/src/pal/src/config.h.in b/src/pal/src/config.h.in index 7a53c8cb5d..4d21fb70e4 100644 --- a/src/pal/src/config.h.in +++ b/src/pal/src/config.h.in @@ -43,7 +43,6 @@ #cmakedefine01 HAVE_LOCALTIME_R #cmakedefine01 HAVE_GMTIME_R #cmakedefine01 HAVE_TIMEGM -#cmakedefine01 HAVE__SNWPRINTF #cmakedefine01 HAVE_POLL #cmakedefine01 HAVE_STATVFS #cmakedefine01 HAVE_THREAD_SELF diff --git a/src/pal/src/configure.cmake b/src/pal/src/configure.cmake index cc38bc8541..a53e0db51e 100644 --- a/src/pal/src/configure.cmake +++ b/src/pal/src/configure.cmake @@ -13,7 +13,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL SunOS) set(CMAKE_REQUIRED_INCLUDES /opt/local/include) endif() if(NOT CMAKE_SYSTEM_NAME STREQUAL Darwin AND NOT CMAKE_SYSTEM_NAME STREQUAL FreeBSD AND NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD) - set(CMAKE_REQUIRED_DEFINITIONS "-D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L") + set(CMAKE_REQUIRED_DEFINITIONS "-D_BSD_SOURCE -D_SVID_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L") endif() list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_FILE_OFFSET_BITS=64) @@ -33,7 +33,15 @@ check_include_files(sys/lwp.h HAVE_SYS_LWP_H) check_include_files(lwp.h HAVE_LWP_H) check_include_files(libunwind.h HAVE_LIBUNWIND_H) check_include_files(runetype.h HAVE_RUNETYPE_H) + +if(NOT CMAKE_SYSTEM_NAME STREQUAL FreeBSD AND NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD) + set(CMAKE_REQUIRED_FLAGS "-ldl") +endif() check_include_files(lttng/tracepoint.h HAVE_LTTNG_TRACEPOINT_H) +if(NOT CMAKE_SYSTEM_NAME STREQUAL FreeBSD AND NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD) + unset(CMAKE_REQUIRED_FLAGS) +endif() + check_include_files(uuid/uuid.h HAVE_LIBUUID_H) check_include_files(sys/sysctl.h HAVE_SYS_SYSCTL_H) check_include_files(gnu/lib-names.h HAVE_GNU_LIBNAMES_H) @@ -62,7 +70,6 @@ check_function_exists(sysconf HAVE_SYSCONF) check_function_exists(localtime_r HAVE_LOCALTIME_R) check_function_exists(gmtime_r HAVE_GMTIME_R) check_function_exists(timegm HAVE_TIMEGM) -check_function_exists(_snwprintf HAVE__SNWPRINTF) check_function_exists(poll HAVE_POLL) check_function_exists(statvfs HAVE_STATVFS) check_function_exists(thread_self HAVE_THREAD_SELF) diff --git a/src/pal/src/cruntime/lstr.cpp b/src/pal/src/cruntime/lstr.cpp index 2267d8491b..4502b025aa 100644 --- a/src/pal/src/cruntime/lstr.cpp +++ b/src/pal/src/cruntime/lstr.cpp @@ -24,141 +24,6 @@ Abstract: SET_DEFAULT_DEBUG_CHANNEL(CRT); - -/*++ -Function: - lstrcatW - -The lstrcat function appends one string to another. - -Parameters - -lpString1 [in/out] Pointer to a null-terminated string. The buffer must be large - enough to contain both strings. -lpString2 [in] Pointer to the null-terminated string to be appended to the - string specified in the lpString1 parameter. - -Return Values - -If the function succeeds, the return value is a pointer to the buffer. -If the function fails, the return value is NULL. - ---*/ -LPWSTR -PALAPI -lstrcatW( - IN OUT LPWSTR lpString1, - IN LPCWSTR lpString2) -{ - LPWSTR lpStart = lpString1; - - PERF_ENTRY(lstrcatW); - ENTRY("lstrcatW (lpString1=%p (%S), lpString2=%p (%S))\n", - lpString1?lpString1:W16_NULLSTRING, - lpString1?lpString1:W16_NULLSTRING, lpString2?lpString2:W16_NULLSTRING, lpString2?lpString2:W16_NULLSTRING); - - if (lpString1 == NULL) - { - ERROR("invalid lpString1 argument\n"); - LOGEXIT("lstrcatW returning LPWSTR NULL\n"); - PERF_EXIT(lstrcatW); - return NULL; - } - - if (lpString2 == NULL) - { - ERROR("invalid lpString2 argument\n"); - LOGEXIT("lstrcatW returning LPWSTR NULL\n"); - PERF_EXIT(lstrcatW); - return NULL; - } - - /* find end of source string */ - while (*lpString1) - { - lpString1++; - } - - /* concatenate new string */ - while(*lpString2) - { - *lpString1++ = *lpString2++; - } - - /* add terminating null */ - *lpString1 = '\0'; - - LOGEXIT("lstrcatW returning LPWSTR %p (%S)\n", lpStart, lpStart); - PERF_EXIT(lstrcatW); - return lpStart; -} - - -/*++ -Function: - lstrcpyW - -The lstrcpy function copies a string to a buffer. - -To copy a specified number of characters, use the lstrcpyn function. - -Parameters - -lpString1 [out] Pointer to a buffer to receive the contents of the string pointed - to by the lpString2 parameter. The buffer must be large enough to - contain the string, including the terminating null character. - -lpString2 [in] Pointer to the null-terminated string to be copied. - -Return Values - -If the function succeeds, the return value is a pointer to the buffer. -If the function fails, the return value is NULL. - ---*/ -LPWSTR -PALAPI -lstrcpyW( - OUT LPWSTR lpString1, - IN LPCWSTR lpString2) -{ - LPWSTR lpStart = lpString1; - - PERF_ENTRY(lstrcpyW); - ENTRY("lstrcpyW (lpString1=%p, lpString2=%p (%S))\n", - lpString1?lpString1:W16_NULLSTRING, lpString2?lpString2:W16_NULLSTRING, lpString2?lpString2:W16_NULLSTRING); - - if (lpString1 == NULL) - { - ERROR("invalid lpString1 argument\n"); - LOGEXIT("lstrcpyW returning LPWSTR NULL\n"); - PERF_EXIT(lstrcpyW); - return NULL; - } - - if (lpString2 == NULL) - { - ERROR("invalid lpString2 argument\n"); - LOGEXIT("lstrcpyW returning LPWSTR NULL\n"); - PERF_EXIT(lstrcpyW); - return NULL; - } - - /* copy source string to destination string */ - while(*lpString2) - { - *lpString1++ = *lpString2++; - } - - /* add terminating null */ - *lpString1 = '\0'; - - LOGEXIT("lstrcpyW returning LPWSTR %p (%S)\n", lpStart, lpStart); - PERF_EXIT(lstrcpyW); - return lpStart; -} - - /*++ Function: lstrlenA @@ -239,78 +104,3 @@ lstrlenW( PERF_EXIT(lstrlenW); return nChar; } - - -/*++ -Function: - lstrcpynW - -The lstrcpyn function copies a specified number of characters from a -source string into a buffer. - -Parameters - -lpString1 [out] Pointer to a buffer into which the function copies characters. - The buffer must be large enough to contain the number of TCHARs - specified by iMaxLength, including room for a terminating null character. -lpString2 [in] Pointer to a null-terminated string from which the function copies - characters. -iMaxLength [in] Specifies the number of TCHARs to be copied from the string pointed - to by lpString2 into the buffer pointed to by lpString1, including a - terminating null character. - -Return Values - -If the function succeeds, the return value is a pointer to the buffer. -If the function fails, the return value is NULL. - ---*/ -LPWSTR -PALAPI -lstrcpynW( - OUT LPWSTR lpString1, - IN LPCWSTR lpString2, - IN int iMaxLength) -{ - LPWSTR lpStart = lpString1; - - PERF_ENTRY(lstrcpynW); - ENTRY("lstrcpynW (lpString1=%p, lpString2=%p (%S), iMaxLength=%d)\n", - lpString1?lpString1:W16_NULLSTRING, lpString2?lpString2:W16_NULLSTRING, lpString2?lpString2:W16_NULLSTRING, iMaxLength); - - if (lpString1 == NULL) - { - ERROR("invalid lpString1 argument\n"); - LOGEXIT("lstrcpynW returning LPWSTR NULL\n"); - PERF_EXIT(lstrcpynW); - return NULL; - } - - if (lpString2 == NULL) - { - ERROR("invalid lpString2 argument\n"); - LOGEXIT("lstrcpynW returning LPWSTR NULL\n"); - PERF_EXIT(lstrcpynW); - return NULL; - } - - /* copy source string to destination string */ - while(iMaxLength > 1 && *lpString2) - { - *lpString1++ = *lpString2++; - iMaxLength--; - } - - /* add terminating null */ - if (iMaxLength > 0) - { - *lpString1 = '\0'; - } - - LOGEXIT("lstrcpynW returning LPWSTR %p (%S)\n", lpStart, lpStart); - PERF_EXIT(lstrcpynW); - return lpStart; - -} - - diff --git a/src/pal/src/cruntime/math.cpp b/src/pal/src/cruntime/math.cpp index 7075fd60f9..08f4192998 100644 --- a/src/pal/src/cruntime/math.cpp +++ b/src/pal/src/cruntime/math.cpp @@ -35,6 +35,12 @@ Abstract: #define IS_DBL_NEGZERO(x) (((*((INT64*)((void*)&x))) & I64(0xFFFFFFFFFFFFFFFF)) == I64(0x8000000000000000)) +#define PAL_NAN_FLT sqrtf(-1.0f) +#define PAL_POSINF_FLT -logf(0.0f) +#define PAL_NEGINF_FLT logf(0.0f) + +#define IS_FLT_NEGZERO(x) (((*((INT32*)((void*)&x))) & 0xFFFFFFFF) == 0x80000000) + SET_DEFAULT_DEBUG_CHANNEL(CRT); /*++ @@ -422,3 +428,364 @@ PALIMPORT double __cdecl PAL_pow(double x, double y) PERF_EXIT(pow); return ret; } + +/*++ +Function: + _finitef + +Determines whether given single-precision floating point value is finite. + +Return Value + +_finitef returns a nonzero value (TRUE) if its argument x is not +infinite, that is, if -INF < x < +INF. It returns 0 (FALSE) if the +argument is infinite or a NaN. + +Parameter + +x Single-precision floating-point value + +--*/ +int __cdecl _finitef(float x) +{ + int ret; + PERF_ENTRY(_finitef); + ENTRY("_finitef (x=%f)\n", x); + +#if defined(_IA64_) && defined (_HPUX_) + ret = !isnan(x) && (x != PAL_POSINF_FLT) && (x != PAL_NEGINF_FLT); +#else + ret = isfinite(x); +#endif + + LOGEXIT("_finitef returns int %d\n", ret); + PERF_EXIT(_finitef); + return ret; +} + +/*++ +Function: + _isnanf + +See MSDN doc +--*/ +int __cdecl _isnanf(float x) +{ + int ret; + PERF_ENTRY(_isnanf); + ENTRY("_isnanf (x=%f)\n", x); + + ret = isnan(x); + + LOGEXIT("_isnanf returns int %d\n", ret); + PERF_EXIT(_isnanf); + return ret; +} + +/*++ +Function: + _copysignf + +See MSDN doc +--*/ +float __cdecl _copysignf(float x, float y) +{ + float ret; + PERF_ENTRY(_copysignf); + ENTRY("_copysignf (x=%f, y=%f)\n", x, y); + + ret = copysign(x, y); + + LOGEXIT("_copysignf returns float %f\n", ret); + PERF_EXIT(_copysignf); + return ret; +} + +/*++ +Function: + acosf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_acosf(float x) +{ + float ret; + PERF_ENTRY(acosf); + ENTRY("acosf (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_ACOS + errno = 0; +#endif // HAVE_COMPATIBLE_ACOS + + ret = acosf(x); + +#if !HAVE_COMPATIBLE_ACOS + if (errno == EDOM) + { + ret = PAL_NAN_FLT; // NaN + } +#endif // HAVE_COMPATIBLE_ACOS + + LOGEXIT("acosf returns float %f\n", ret); + PERF_EXIT(acosf); + return ret; +} + +/*++ +Function: + asinf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_asinf(float x) +{ + float ret; + PERF_ENTRY(asinf); + ENTRY("asinf (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_ASIN + errno = 0; +#endif // HAVE_COMPATIBLE_ASIN + + ret = asinf(x); + +#if !HAVE_COMPATIBLE_ASIN + if (errno == EDOM) + { + ret = PAL_NAN_FLT; // NaN + } +#endif // HAVE_COMPATIBLE_ASIN + + LOGEXIT("asinf returns float %f\n", ret); + PERF_EXIT(asinf); + return ret; +} + +/*++ +Function: + atan2f + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_atan2f(float y, float x) +{ + float ret; + PERF_ENTRY(atan2f); + ENTRY("atan2f (y=%f, x=%f)\n", y, x); + +#if !HAVE_COMPATIBLE_ATAN2 + errno = 0; +#endif // !HAVE_COMPATIBLE_ATAN2 + + ret = atan2f(y, x); + +#if !HAVE_COMPATIBLE_ATAN2 + if ((errno == EDOM) && (x == 0.0f) && (y == 0.0f)) + { + const float sign_x = copysign(1.0f, x); + const float sign_y = copysign(1.0f, y); + + if (sign_x > 0) + { + ret = copysign(0.0f, sign_y); + } + else + { + ret = copysign(atan2f(0.0f, -1.0f), sign_y); + } + } +#endif // !HAVE_COMPATIBLE_ATAN2 + + LOGEXIT("atan2f returns float %f\n", ret); + PERF_EXIT(atan2f); + return ret; +} + +/*++ +Function: + expf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_expf(float x) +{ + float ret; + PERF_ENTRY(expf); + ENTRY("expf (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_EXP + if (x == 1.0f) + { + ret = M_E; + } + else + { +#endif // HAVE_COMPATIBLE_EXP + + ret = expf(x); + +#if !HAVE_COMPATIBLE_EXP + } +#endif // HAVE_COMPATIBLE_EXP + + LOGEXIT("expf returns float %f\n", ret); + PERF_EXIT(expf); + return ret; +} + +/*++ +Function: + logf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_logf(float x) +{ + float ret; + PERF_ENTRY(logf); + ENTRY("logf (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_LOG + errno = 0; +#endif // !HAVE_COMPATIBLE_LOG + + ret = logf(x); + +#if !HAVE_COMPATIBLE_LOG + if ((errno == EDOM) && (x < 0)) + { + ret = PAL_NAN_FLT; // NaN + } +#endif // !HAVE_COMPATIBLE_LOG + + LOGEXIT("logf returns float %f\n", ret); + PERF_EXIT(logf); + return ret; +} + +/*++ +Function: + log10f + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_log10f(float x) +{ + float ret; + PERF_ENTRY(log10f); + ENTRY("log10f (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_LOG10 + errno = 0; +#endif // !HAVE_COMPATIBLE_LOG10 + + ret = log10f(x); + +#if !HAVE_COMPATIBLE_LOG10 + if ((errno == EDOM) && (x < 0)) + { + ret = PAL_NAN_FLT; // NaN + } +#endif // !HAVE_COMPATIBLE_LOG10 + + LOGEXIT("log10f returns float %f\n", ret); + PERF_EXIT(log10f); + return ret; +} + +/*++ +Function: + powf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_powf(float x, float y) +{ + float ret; + PERF_ENTRY(powf); + ENTRY("powf (x=%f, y=%f)\n", x, y); + +#if !HAVE_COMPATIBLE_POW + if ((y == PAL_POSINF_FLT) && !isnan(x)) // +Inf + { + if (x == 1.0f) + { + ret = x; + } + else if (x == -1.0f) + { + ret = PAL_NAN_FLT; // NaN + } + else if ((x > -1.0f) && (x < 1.0f)) + { + ret = 0.0f; + } + else + { + ret = PAL_POSINF_FLT; // +Inf + } + } + else if ((y == PAL_NEGINF_FLT) && !isnan(x)) // -Inf + { + if (x == 1.0f) + { + ret = x; + } + else if (x == -1.0f) + { + ret = PAL_NAN_FLT; // NaN + } + else if ((x > -1.0f) && (x < 1.0f)) + { + ret = PAL_POSINF_FLT; // +Inf + } + else + { + ret = 0.0f; + } + } + else if (IS_FLT_NEGZERO(x) && (y == -1.0f)) + { + ret = PAL_NEGINF_FLT; // -Inf + } + else if ((x == 0.0f) && (y < 0.0f)) + { + ret = PAL_POSINF_FLT; // +Inf + } + else +#endif // !HAVE_COMPATIBLE_POW + + if ((y == 0.0f) && isnan(x)) + { + // Windows returns NaN for powf(NaN, 0), but POSIX specifies + // a return value of 1 for that case. We need to return + // the same result as Windows. + ret = PAL_NAN_FLT; + } + else + { + ret = powf(x, y); + } + +#if !HAVE_VALID_NEGATIVE_INF_POW + if ((ret == PAL_POSINF_FLT) && (x < 0) && isfinite(x) && (ceilf(y / 2) != floorf(y / 2))) + { + ret = PAL_NEGINF_FLT; // -Inf + } +#endif // !HAVE_VALID_NEGATIVE_INF_POW + +#if !HAVE_VALID_POSITIVE_INF_POW + /* + * The (ceil(y/2) == floor(y/2)) test is slower, but more robust for platforms where large y + * will return the wrong result for ((long) y % 2 == 0). See PAL_pow(double) above for more details. + */ + if ((ret == PAL_NEGINF_FLT) && (x < 0) && isfinite(x) && (ceilf(y / 2) == floorf(y / 2))) + { + ret = PAL_POSINF_FLT; // +Inf + } +#endif // !HAVE_VALID_POSITIVE_INF_POW + + LOGEXIT("powf returns float %f\n", ret); + PERF_EXIT(powf); + return ret; +} diff --git a/src/pal/src/cruntime/mbstring.cpp b/src/pal/src/cruntime/mbstring.cpp index dd4bcbbdce..ace2aa56c6 100644 --- a/src/pal/src/cruntime/mbstring.cpp +++ b/src/pal/src/cruntime/mbstring.cpp @@ -37,60 +37,6 @@ SET_DEFAULT_DEBUG_CHANNEL(CRT); /*++ Function: - _mbslen - -Determines the number of characters (code points) in a multibyte -character string. - -Parameters - -string Points to a multibyte character string. - -Return Values - -The mbslen subroutine returns the number of multibyte characters in a -multibyte character string. It returns 0 if the string parameter -points to a null character or if a character cannot be formed from the -string pointed to by this parameter. - ---*/ -size_t -__cdecl -_mbslen( - const unsigned char *string) -{ - size_t ret = 0; - CPINFO cpinfo; - PERF_ENTRY(_mbslen); - ENTRY("_mbslen (string=%p (%s))\n", string, string); - - if (string) - { - if (GetCPInfo(CP_ACP, &cpinfo) && cpinfo.MaxCharSize == 1) - { - ret = strlen((const char*)string); - } - else - { - while (*string) - { - if (IsDBCSLeadByteEx(CP_ACP, *string)) - { - ++string; - } - ++string; - ++ret; - } - } - } - - LOGEXIT("_mbslen returning size_t %u\n", ret); - PERF_EXIT(_mbslen); - return ret; -} - -/*++ -Function: _mbsinc Return Value diff --git a/src/pal/src/cruntime/path.cpp b/src/pal/src/cruntime/path.cpp index e5b955ebd9..4925af5b89 100644 --- a/src/pal/src/cruntime/path.cpp +++ b/src/pal/src/cruntime/path.cpp @@ -33,488 +33,6 @@ Revision History: SET_DEFAULT_DEBUG_CHANNEL(CRT); - -/* ON_ERROR. A Helper macro for _?splitpath functions. */ -#define ON_ERROR if ( drive ) \ - {\ - drive[0] = 0;\ - }\ - if(dir)\ - {\ - dir[0] = 0;\ - }\ - if(fname)\ - {\ - fname[0] = 0;\ - }\ - if(ext)\ - {\ - ext[0] = 0;\ - }\ - goto done;\ - -/*++ -Function: - _wsplitpath - -See MSDN doc. - -Notes : - This implementation ignores drive letters as they should not be - present. If the drive argument is non-NULL, it always returns an empty - string. - File names in which the only period is at the beginning (like .bashrc, but - not .bashrc.bak), the file is treated as having no extension - (fname is ".bashrc", ext is "") - ---*/ -void -__cdecl -_wsplitpath( - const wchar_16 *dospath, - wchar_16 *drive, - wchar_16 *dir, - wchar_16 *fname, - wchar_16 *ext) -{ - WCHAR path[_MAX_PATH+1]; - LPCWSTR slash_ptr = NULL; - LPCWSTR period_ptr = NULL; - INT size = 0; - - PERF_ENTRY(_wsplitpath); - ENTRY("_wsplitpath (path=%p (%S), drive=%p, dir=%p, fname=%p, ext=%p)\n", - dospath?dospath:W16_NULLSTRING, - dospath?dospath:W16_NULLSTRING, drive, dir, fname, ext); - - /* Do performance intensive error checking only in debug builds. - - NOTE: This function must fail predictably across all platforms. - Under Windows this function throw an access violation if NULL - was passed in as the value for path. - - */ -#if _DEBUG - if ( !dospath ) - { - ERROR( "path cannot be NULL!\n" ); - } -#endif - - if( lstrlenW( dospath ) >= _MAX_PATH ) - { - ERROR("Path length is > _MAX_PATH (%d)!\n", _MAX_PATH); - ON_ERROR; - } - - - PAL_wcscpy(path, dospath); - FILEDosToUnixPathW(path); - - /* no drive letters in the PAL */ - if( drive != NULL ) - { - drive[0] = 0; - } - - /* find last path separator char */ - slash_ptr = PAL_wcsrchr(path, '/'); - - if( slash_ptr == NULL ) - { - TRACE("No path separator in path\n"); - slash_ptr = path - 1; - } - /* find extension separator, if any */ - period_ptr = PAL_wcsrchr(path, '.'); - - /* make sure we only consider periods after the last path separator */ - if( period_ptr < slash_ptr ) - { - period_ptr = NULL; - } - - /* if the only period in the file is a leading period (denoting a hidden - file), don't treat what follows as an extension */ - if( period_ptr == slash_ptr+1 ) - { - period_ptr = NULL; - } - - if( period_ptr == NULL ) - { - TRACE("No extension in path\n"); - period_ptr = path + lstrlenW(path); - } - - size = slash_ptr - path + 1; - if( dir != NULL ) - { - INT i; - - if( (size + 1 ) > _MAX_DIR ) - { - ERROR("Directory component needs %d characters, _MAX_DIR is %d\n", - size+1, _MAX_DIR); - ON_ERROR; - } - - memcpy(dir, path, size*sizeof(WCHAR)); - dir[size] = 0; - - /* only allow / separators in returned path */ - i = 0; - while( dir[ i ] ) - { - if( dir[ i ] == '\\' ) - { - dir[i]='/'; - } - i++; - } - } - - size = period_ptr-slash_ptr-1; - if( fname != NULL ) - { - if( (size+1) > _MAX_FNAME ) - { - ERROR("Filename component needs %d characters, _MAX_FNAME is %d\n", - size+1, _MAX_FNAME); - ON_ERROR; - } - memcpy(fname, slash_ptr+1, size*sizeof(WCHAR)); - fname[size] = 0; - } - - size = 1 + lstrlenW( period_ptr ); - if( ext != NULL ) - { - if( size > _MAX_EXT ) - { - ERROR("Extension component needs %d characters, _MAX_EXT is %d\n", - size, _MAX_EXT); - ON_ERROR; - } - memcpy(ext, period_ptr, size*sizeof(WCHAR)); - ext[size-1] = 0; - } - - TRACE("Path components are '%S' '%S' '%S'\n", dir, fname, ext); - -done: - - LOGEXIT("_wsplitpath returns.\n"); - PERF_EXIT(_wsplitpath); -} - - -/*++ -Function: - _splitpath - -See description above for _wsplitpath. - ---*/ -void -__cdecl -_splitpath( - const char *path, - char *drive, - char *dir, - char *fname, - char *ext) -{ - WCHAR w_path[_MAX_PATH]; - WCHAR w_dir[_MAX_DIR]; - WCHAR w_fname[_MAX_FNAME]; - WCHAR w_ext[_MAX_EXT]; - - PERF_ENTRY(_splitpath); - ENTRY("_splitpath (path=%p (%s), drive=%p, dir=%p, fname=%p, ext=%p)\n", - path?path:"NULL", - path?path:"NULL", drive, dir, fname, ext); - - /* Do performance intensive error checking only in debug builds. - - NOTE: This function must fail predictably across all platforms. - Under Windows this function throw an access violation if NULL - was passed in as the value for path. - - */ -#if _DEBUG - if ( !path ) - { - ERROR( "path cannot be NULL!\n" ); - } - - if( strlen( path ) >= _MAX_PATH ) - { - ERROR( "Path length is > _MAX_PATH (%d)!\n", _MAX_PATH); - } -#endif - - /* no drive letters in the PAL */ - if(drive) - { - drive[0] = '\0'; - } - - if(0 == MultiByteToWideChar(CP_ACP, 0, path, -1, w_path, _MAX_PATH)) - { - ASSERT("MultiByteToWideChar failed!\n"); - ON_ERROR; - } - - /* Call up to Unicode version; pass NULL for parameters the caller doesn't - care about */ - _wsplitpath(w_path, NULL, dir?w_dir:NULL, - fname?w_fname:NULL, ext?w_ext:NULL); - - /* Convert result back to MultiByte; report conversion errors but don't - stop because of them */ - - if(dir) - { - if(0 == WideCharToMultiByte(CP_ACP, 0, w_dir, -1, dir, _MAX_DIR, - NULL, NULL)) - { - ASSERT("WideCharToMultiByte failed!\n"); - ON_ERROR; - } - } - if(fname) - { - if(0 == WideCharToMultiByte(CP_ACP, 0, w_fname, -1, fname, _MAX_FNAME, - NULL, NULL)) - { - ASSERT("WideCharToMultiByte failed!\n"); - ON_ERROR; - } - } - if(ext) - { - if(0 == WideCharToMultiByte(CP_ACP, 0, w_ext, -1, ext, _MAX_EXT, - NULL, NULL)) - { - ASSERT("WideCharToMultiByte failed!\n"); - ON_ERROR; - } - } - -done: - LOGEXIT("_splitpath returns.\n"); - PERF_EXIT(_splitpath); -} - - - -/*++ -Function: - _makepath - -See MSDN doc. - ---*/ -void -__cdecl -_makepath( - char *path, - const char *drive, - const char *dir, - const char *fname, - const char *ext) -{ - UINT Length = 0; - - PERF_ENTRY(_makepath); - ENTRY( "_makepath (path=%p, drive=%p (%s), dir=%p (%s), fname=%p (%s), ext=%p (%s))\n", - path, drive ? drive:"NULL", drive ? drive:"NULL", dir ? dir:"NULL", dir ? dir:"NULL", fname ? fname:"NULL", fname ? fname:"NULL", - ext ? ext:"NULL", - ext ? ext:"NULL"); - - path[ 0 ] = '\0'; - - /* According to the pal documentation, host operating systems that - don't support drive letters, the "drive" parameter must always be null. */ - if ( drive != NULL && drive[0] != '\0' ) - { - ASSERT( "The drive parameter must always be NULL on systems that don't" - "support drive letters. drive is being ignored!.\n" ); - } - - if ( dir != NULL && dir[ 0 ] != '\0' ) - { - UINT DirLength = strlen( dir ); - Length += DirLength ; - - if ( Length < _MAX_PATH ) - { - strncat( path, dir, DirLength ); - if ( dir[ DirLength - 1 ] != '/' && dir[ DirLength - 1 ] != '\\' ) - { - if ( Length + 1 < _MAX_PATH ) - { - path[ Length ] = '/'; - Length++; - path[ Length ] = '\0'; - } - else - { - goto Max_Path_Error; - } - } - } - else - { - goto Max_Path_Error; - } - } - - if ( fname != NULL && fname[ 0 ] != '\0' ) - { - UINT fNameLength = strlen( fname ); - Length += fNameLength; - - if ( Length < _MAX_PATH ) - { - strncat( path, fname, fNameLength ); - } - else - { - goto Max_Path_Error; - } - } - - if ( ext != NULL && ext[ 0 ] != '\0' ) - { - UINT ExtLength = strlen( ext ); - Length += ExtLength; - - if ( ext[ 0 ] != '.' ) - { - /* Add a '.' */ - if ( Length + 1 < _MAX_PATH ) - { - path[ Length - ExtLength ] = '.'; - Length++; - path[ Length - ExtLength ] = '\0'; - strncat( path, ext, ExtLength ); - } - else - { - goto Max_Path_Error; - } - } - else - { - /* Already has a '.' */ - if ( Length < _MAX_PATH ) - { - strncat( path, ext, ExtLength ); - } - else - { - goto Max_Path_Error; - } - } - } - - FILEDosToUnixPathA( path ); - LOGEXIT( "_makepath returning void.\n" ); - PERF_EXIT(_makepath); - return; - -Max_Path_Error: - - ERROR( "path cannot be greater then _MAX_PATH\n" ); - path[ 0 ] = '\0'; - LOGEXIT( "_makepath returning void \n" ); - PERF_EXIT(_makepath); - return; -} - -/*++ -Function: - _wmakepath - -See MSDN doc. - ---*/ -void -__cdecl -_wmakepath( - wchar_16 *path, - const wchar_16 *drive, - const wchar_16 *dir, - const wchar_16 *fname, - const wchar_16 *ext) -{ - CHAR Dir[ _MAX_DIR ]={0}; - CHAR FileName[ _MAX_FNAME ]={0}; - CHAR Ext[ _MAX_EXT ]={0}; - CHAR Path[ _MAX_PATH ]={0}; - - PERF_ENTRY(_wmakepath); - ENTRY("_wmakepath (path=%p, drive=%p (%S), dir=%p (%S), fname=%p (%S), ext=%p (%S))\n", - path, drive ? drive:W16_NULLSTRING, drive ? drive:W16_NULLSTRING, dir ? dir:W16_NULLSTRING, dir ? dir:W16_NULLSTRING, - fname ? fname:W16_NULLSTRING, - fname ? fname:W16_NULLSTRING, ext ? ext:W16_NULLSTRING, ext ? ext:W16_NULLSTRING); - - /* According to the pal documentation, host operating systems that - don't support drive letters, the "drive" parameter must always be null. */ - if ( drive != NULL && drive[0] != '\0' ) - { - ASSERT( "The drive parameter must always be NULL on systems that don't" - "support drive letters. drive is being ignored!.\n" ); - } - - if ((dir != NULL) && WideCharToMultiByte( CP_ACP, 0, dir, -1, Dir, - _MAX_DIR, NULL, NULL ) == 0 ) - { - ASSERT( "An error occurred while converting dir to multibyte." - "Possible error: Length of dir is greater than _MAX_DIR.\n" ); - goto error; - } - - if ((fname != NULL) && WideCharToMultiByte( CP_ACP, 0, fname, -1, FileName, - _MAX_FNAME, NULL, NULL ) == 0 ) - { - ASSERT( "An error occurred while converting fname to multibyte." - "Possible error: Length of fname is greater than _MAX_FNAME.\n" ); - goto error; - } - - if ((ext != NULL) && WideCharToMultiByte( CP_ACP, 0, ext, -1, Ext, - _MAX_EXT, NULL, NULL ) == 0 ) - { - ASSERT( "An error occurred while converting ext to multibyte." - "Possible error: Length of ext is greater than _MAX_EXT.\n" ); - goto error; - } - - /* Call up to the ANSI _makepath. */ - _makepath_s( Path, sizeof(Path), NULL, Dir, FileName, Ext ); - - if ( MultiByteToWideChar( CP_ACP, 0, Path, -1, path, _MAX_PATH ) == 0 ) - { - ASSERT( "An error occurred while converting the back wide char." - "Possible error: The length of combined path is greater " - "than _MAX_PATH.\n" ); - goto error; - } - - LOGEXIT("_wmakepath returns void\n"); - PERF_EXIT(_wmakepath); - return; - -error: - *path = '\0'; - LOGEXIT("_wmakepath returns void\n"); - PERF_EXIT(_wmakepath); -} - - /*++ Function: _fullpath diff --git a/src/pal/src/cruntime/printf.cpp b/src/pal/src/cruntime/printf.cpp index 2d9d6e4b94..c437b8e39f 100644 --- a/src/pal/src/cruntime/printf.cpp +++ b/src/pal/src/cruntime/printf.cpp @@ -277,124 +277,6 @@ PAL_vprintf( /*++ Function: - wsprintfA - -See MSDN doc. ---*/ -int -PALAPIV -wsprintfA( - OUT LPSTR buffer, - IN LPCSTR format, - ...) -{ - LONG Length; - va_list ap; - - PERF_ENTRY(wsprintfA); - ENTRY("wsprintfA (buffer=%p, format=%p (%s))\n", buffer, format, format); - - va_start(ap, format); - Length = InternalVsnprintf(CorUnix::InternalGetCurrentThread(), buffer, 1024, format, ap); - va_end(ap); - - LOGEXIT("wsprintfA returns int %d\n", Length); - PERF_EXIT(wsprintfA); - return Length; -} - -/*++ -Function: - wsprintfW - -See MSDN doc. ---*/ -int -PALAPIV -wsprintfW( - OUT LPWSTR buffer, - IN LPCWSTR format, - ...) -{ - LONG Length; - va_list ap; - - PERF_ENTRY(wsprintfW); - ENTRY("wsprintfW (buffer=%p, format=%p (%S))\n", buffer, format, format); - - va_start(ap, format); - Length = PAL__wvsnprintf(buffer, 1024, format, ap); - va_end(ap); - - LOGEXIT("wsprintfW returns int %d\n", Length); - PERF_EXIT(wsprintfW); - return Length; -} - - -/*++ -Function: - _snprintf - -See MSDN doc. ---*/ -int -__cdecl -_snprintf( - char *buffer, - size_t count, - const char *format, - ...) -{ - LONG Length; - va_list ap; - - PERF_ENTRY(_snprintf); - ENTRY("_snprintf (buffer=%p, count=%lu, format=%p (%s))\n", - buffer, (unsigned long) count, format, format); - - va_start(ap, format); - Length = InternalVsnprintf(CorUnix::InternalGetCurrentThread(), buffer, count, format, ap); - va_end(ap); - - LOGEXIT("_snprintf returns int %d\n", Length); - PERF_EXIT(_snprintf); - return Length; -} - - -/*++ -Function: - _snwprintf - -See MSDN doc. ---*/ -int -__cdecl -_snwprintf( - wchar_16 *buffer, - size_t count, - const wchar_16 *format, - ...) -{ - LONG Length; - va_list ap; - - PERF_ENTRY(_snwprintf); - ENTRY("_snwprintf (buffer=%p, count=%lu, format=%p (%S))\n", - buffer, (unsigned long) count, format, format); - - va_start(ap, format); - Length = PAL__wvsnprintf(buffer, count, format, ap); - va_end(ap); - - LOGEXIT("_snwprintf returns int %d\n", Length); - PERF_EXIT(_snwprintf); - return Length; -} - -/*++ -Function: fwprintf See MSDN doc. @@ -1483,63 +1365,6 @@ int PAL_wvsscanf(LPCWSTR Buffer, LPCWSTR Format, va_list ap) /*++ Function: - PAL_sscanf - -See MSDN doc. ---*/ -int -__cdecl -PAL_sscanf( - const char *buffer, - const char *format, - ...) -{ - int Length; - va_list ap; - - PERF_ENTRY(sscanf); - ENTRY("PAL_sscanf (buffer=%p (%s), format=%p (%s))\n", buffer, buffer, format, format); - - va_start(ap, format); - Length = PAL_vsscanf(buffer, format, ap); - va_end(ap); - - LOGEXIT("PAL_sscanf returns int %d\n", Length); - PERF_EXIT(sscanf); - return Length; -} - -/*++ -Function: - PAL_sprintf - -See MSDN doc. ---*/ -int -__cdecl -PAL_sprintf( - char *buffer, - const char *format, - ...) -{ - LONG Length; - va_list ap; - - PERF_ENTRY(sprintf); - ENTRY("PAL_sprintf (buffer=%p, format=%p (%s))\n", buffer, format, format); - - va_start(ap, format); - Length = InternalVsnprintf(CorUnix::InternalGetCurrentThread(), buffer, 0x7fffffff, format, ap); - va_end(ap); - - LOGEXIT("PAL_sprintf returns int %d\n", Length); - PERF_EXIT(sprintf); - return Length; -} - - -/*++ -Function: PAL_swprintf See MSDN doc. @@ -1649,33 +1474,6 @@ PAL_vswprintf(wchar_16 *buffer, } -/*++ -Function: - _vsnwprintf - -See MSDN doc. ---*/ -int -__cdecl -_vsnwprintf(wchar_16 *buffer, - size_t count, - const wchar_16 *format, - va_list argptr) -{ - LONG Length; - - PERF_ENTRY(_vsnwprintf); - ENTRY("_vsnwprintf (buffer=%p, count=%lu, format=%p (%S), argptr=%p)\n", - buffer, (unsigned long) count, format, format, argptr); - - Length = PAL__wvsnprintf(buffer, count, format, argptr); - - LOGEXIT("_vsnwprintf returns int %d\n", Length); - PERF_EXIT(_vsnwprintf); - - return Length; -} - #if SSCANF_CANNOT_HANDLE_MISSING_EXPONENT /*++ Function: diff --git a/src/pal/src/cruntime/string.cpp b/src/pal/src/cruntime/string.cpp index 23781d8b39..abe6d136f0 100644 --- a/src/pal/src/cruntime/string.cpp +++ b/src/pal/src/cruntime/string.cpp @@ -151,61 +151,6 @@ _strlwr( return orig; } - -/*++ -Function: - _swab - -Swaps bytes. - -Return Value - -None - -Parameters - -src Data to be copied and swapped -dest Storage location for swapped data -n Number of bytes to be copied and swapped - -Remarks - -The _swab function copies n bytes from src, swaps each pair of -adjacent bytes, and stores the result at dest. The integer n should be -an even number to allow for swapping. _swab is typically used to -prepare binary data for transfer to a machine that uses a different -byte order. - -Example - -char from[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -char to[] = ".........................."; - -printf("Before:\n%s\n%s\n\n", from, to); -_swab(from, to, strlen(from)); -printf("After:\n%s\n%s\n\n", from, to); - -Before: -ABCDEFGHIJKLMNOPQRSTUVWXYZ -.......................... - -After: -ABCDEFGHIJKLMNOPQRSTUVWXYZ -BADCFEHGJILKNMPORQTSVUXWZY - ---*/ -void -__cdecl -_swab(char *src, char *dest, int n) -{ - PERF_ENTRY(_swab); - ENTRY("_swab (src=%p (%s), dest=%p (%s), n=%d)\n", src?src:"NULL", src?src:"NULL", dest?dest:"NULL", dest?dest:"NULL", n); - swab(src, dest, n); - LOGEXIT("_swab returning\n"); - PERF_EXIT(_swab); -} - - /*++ Function: PAL_strtoul diff --git a/src/pal/src/cruntime/wchar.cpp b/src/pal/src/cruntime/wchar.cpp index 2d244a639f..3de065e361 100644 --- a/src/pal/src/cruntime/wchar.cpp +++ b/src/pal/src/cruntime/wchar.cpp @@ -73,146 +73,6 @@ wtolower(wchar_16 c) } -/******************************************************************************* -Function: - Internal_i64tow - -Parameters: - value - - INT64 value to be converted to a string - string - - out buffer to place interger string - radix - - numeric base to convert to - isI64 - - TRUE if value is INT64, FALSE if value is a long - -Note: - - only a radix of ten (and value < 0) will result in a negative - sign in the output buffer -*******************************************************************************/ -LPWSTR Internal_i64tow(INT64 value, LPWSTR string, int radix, BOOL isI64) -{ - int length = 0; - int n; - int r; - UINT64 uval = value; - LPWSTR stringPtr = string; - int start = 0; - int end; - WCHAR tempCh; - - if (radix < 2 || radix > 36) - { - ASSERT( "Invalid radix, radix must be between 2 and 36\n" ); - SetLastError(ERROR_INVALID_PARAMETER); - return string; - } - if (FALSE == isI64) - { - uval = (ULONG) uval; - } - if (10 == radix && value < 0) - { - uval = value * -1; - } - if(0 == uval) - { - ++length; - *stringPtr++ = '0'; - } - else while (uval > 0) - { - ++length; - n = uval / radix; - r = uval - (n * radix); - uval /= radix; - if (r > 9) - { - *stringPtr++ = r + 87; - } - else - { - *stringPtr++ = r + 48; - } - } - if (10 == radix && value < 0) - { - *stringPtr++ = '-'; - ++length; - } - *stringPtr = 0; /* end the string */ - - /* reverse the string */ - end = length - 1; - while (start < end) - { - tempCh = string[start]; - string[start] = string[end]; - string[end] = tempCh; - ++start; - --end; - } - - return string; -} - -/*-- -Function: - _itow - -16-bit wide character version of the ANSI tolower() function. - - --*/ -wchar_16 * -__cdecl -_itow( - int value, - wchar_16 *string, - int radix) -{ - wchar_16 *ret; - - PERF_ENTRY(_itow); - ENTRY("_itow (value=%d, string=%p, radix=%d)\n", - value, string, radix); - - ret = Internal_i64tow(value, string, radix, FALSE); - - LOGEXIT("_itow returns wchar_t* %p\n", ret); - PERF_EXIT(_itow); - - return ret; -} - -/*-- -Function: - _i64tow - -See MSDN doc ---*/ -wchar_16 * - __cdecl -_i64tow( - __int64 value, - wchar_16 *string, - int radix) -{ - wchar_16 *ret; - - PERF_ENTRY(_i64tow); - ENTRY("_i64tow (value=%ld, string=%p, radix=%d)\n", - value, string, radix); - - ret = Internal_i64tow(value, string, radix, TRUE); - - LOGEXIT("_i64tow returns wchar_t* %p\n", ret); - PERF_EXIT(_i64tow); - - return ret; -} - - /*-- Function: _wtoi @@ -1558,77 +1418,6 @@ PAL_wcstod( const wchar_16 * nptr, wchar_16 **endptr ) } /*++ -Function : - - _ui64tow - -See MSDN for more details. ---*/ -wchar_16 * -__cdecl -_ui64tow( unsigned __int64 value , wchar_16 * string , int radix ) -{ - UINT ReversedIndex = 0; - WCHAR ReversedString[ 65 ]; - LPWSTR lpString = string; - UINT Index = 0; - - PERF_ENTRY(_ui64tow); - ENTRY( "_ui64tow( value=%I64d, string=%p (%S), radix=%d )\n", - value, string, string, radix ); - - if ( !string ) - { - ERROR( "string has to be a valid pointer.\n" ); - LOGEXIT( "_ui64tow returning NULL.\n" ); - PERF_EXIT(_ui64tow); - return NULL; - } - if ( radix < 2 || radix > 36 ) - { - ERROR( "radix has to be between 2 and 36.\n" ); - LOGEXIT( "_ui64tow returning NULL.\n" ); - PERF_EXIT(_ui64tow); - return NULL; - } - - if(0 == value) - { - ReversedString[0] = '0'; - Index++; - } - else while ( value ) - { - int temp = value % radix; - value /= radix; - - if ( temp < 10 ) - { - ReversedString[ Index ] = temp + '0'; - Index++; - } - else - { - ReversedString[ Index ] = temp - 10 + 'a'; - Index++; - } - } - - /* Reverse the string. */ - ReversedIndex = Index; - for ( Index = 0; ReversedIndex > 0; ReversedIndex--, Index++ ) - { - string[ Index ] = ReversedString[ ReversedIndex - 1 ]; - } - - string[ Index ] = '\0'; - LOGEXIT( "_ui64tow returning %p (%S).\n", lpString , lpString ); - PERF_EXIT(_ui64tow); - return lpString; -} - - -/*++ Function: iswdigit diff --git a/src/pal/src/debug/debug.cpp b/src/pal/src/debug/debug.cpp index 5461ac6265..2f7d17cabe 100644 --- a/src/pal/src/debug/debug.cpp +++ b/src/pal/src/debug/debug.cpp @@ -92,29 +92,6 @@ static const char PAL_OUTPUTDEBUGSTRING[] = "PAL_OUTPUTDEBUGSTRING"; static const char PAL_RUN_ON_DEBUG_BREAK[] = "PAL_RUN_ON_DEBUG_BREAK"; #endif // ENABLE_RUN_ON_DEBUG_BREAK -/* ------------------- Static function prototypes ----------------------------*/ - -#if !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE -static int -DBGWriteProcMem_Int(DWORD processId, int *addr, int data); -static int -DBGWriteProcMem_IntWithMask(DWORD processId, int *addr, int data, - unsigned int mask); -#endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE - -#if !HAVE_VM_READ && !HAVE_PROCFS_CTL - -static BOOL -DBGAttachProcess(CPalThread *pThread, HANDLE hProcess, DWORD dwProcessId); - -static BOOL -DBGDetachProcess(CPalThread *pThread, HANDLE hProcess, DWORD dwProcessId); - -static int -DBGSetProcessAttached(CPalThread *pThread, HANDLE hProcess, BOOL bAttach); - -#endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL - extern "C" { /*++ @@ -566,457 +543,6 @@ SetThreadContext( return ret; } -#if !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE -/*++ -Function: - DBGWriteProcMem_Int - -Abstract - write one int to a process memory address - -Parameter - processId : process handle - addr : memory address where the int should be written - data : int to be written in addr - -Return - Return 1 if it succeeds, or 0 if it's fails ---*/ -static -int -DBGWriteProcMem_Int(IN DWORD processId, - IN int *addr, - IN int data) -{ - if (PAL_PTRACE( PAL_PT_WRITE_D, processId, addr, data ) == -1) - { - if (errno == EFAULT) - { - ERROR("ptrace(PT_WRITE_D, pid:%d caddr_t:%p data:%x) failed " - "errno:%d (%s)\n", processId, addr, data, errno, strerror(errno)); - SetLastError(ERROR_INVALID_ADDRESS); - } - else - { - ASSERT("ptrace(PT_WRITE_D, pid:%d caddr_t:%p data:%x) failed " - "errno:%d (%s)\n", processId, addr, data, errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - return 0; - } - - return 1; -} - -/*++ -Function: - DBGWriteProcMem_IntWithMask - -Abstract - write one int to a process memory address space using mask - -Parameter - processId : process ID - addr : memory address where the int should be written - data : int to be written in addr - mask : the mask used to write only a parts of data - -Return - Return 1 if it succeeds, or 0 if it's fails ---*/ -static -int -DBGWriteProcMem_IntWithMask(IN DWORD processId, - IN int *addr, - IN int data, - IN unsigned int mask ) -{ - int readInt; - - if (mask != ~0) - { - errno = 0; - if (((readInt = PAL_PTRACE( PAL_PT_READ_D, processId, addr, 0 )) == -1) - && errno) - { - if (errno == EFAULT) - { - ERROR("ptrace(PT_READ_D, pid:%d, caddr_t:%p, 0) failed " - "errno:%d (%s)\n", processId, addr, errno, strerror(errno)); - SetLastError(ERROR_INVALID_ADDRESS); - } - else - { - ASSERT("ptrace(PT_READ_D, pid:%d, caddr_t:%p, 0) failed " - "errno:%d (%s)\n", processId, addr, errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - - return 0; - } - data = (data & mask) | (readInt & ~mask); - } - return DBGWriteProcMem_Int(processId, addr, data); -} -#endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE - -#if !HAVE_VM_READ && !HAVE_PROCFS_CTL - -/*++ -Function: - DBGAttachProcess - -Abstract - - Attach the indicated process to the current process. - - if the indicated process is already attached by the current process, then - increment the number of attachment pending. if ot, attach it to the current - process (with PT_ATTACH). - -Parameter - hProcess : handle to process to attach to - processId : process ID to attach -Return - Return true if it succeeds, or false if it's fails ---*/ -static -BOOL -DBGAttachProcess( - CPalThread *pThread, - HANDLE hProcess, - DWORD processId - ) -{ - int attchmentCount; - int savedErrno; -#if HAVE_PROCFS_CTL - int fd = -1; - char ctlPath[1024]; -#endif // HAVE_PROCFS_CTL - - attchmentCount = - DBGSetProcessAttached(pThread, hProcess, DBG_ATTACH); - - if (attchmentCount == -1) - { - /* Failed to set the process as attached */ - goto EXIT; - } - - if (attchmentCount == 1) - { -#if HAVE_PROCFS_CTL - struct timespec waitTime; - - // FreeBSD has some trouble when a series of attach/detach sequences - // occurs too close together. When this happens, we'll be able to - // attach to the process, but waiting for the process to stop - // (either via writing "wait" to /proc/<pid>/ctl or via waitpid) - // will hang. If we pause for a very short amount of time before - // trying to attach, we don't run into this situation. - waitTime.tv_sec = 0; - waitTime.tv_nsec = 50000000; - nanosleep(&waitTime, NULL); - - sprintf_s(ctlPath, sizeof(ctlPath), "/proc/%d/ctl", processId); - fd = InternalOpen(ctlPath, O_WRONLY); - if (fd == -1) - { - ERROR("Failed to open %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - goto DETACH1; - } - - if (write(fd, CTL_ATTACH, sizeof(CTL_ATTACH)) < (int)sizeof(CTL_ATTACH)) - { - ERROR("Failed to attach to %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - close(fd); - goto DETACH1; - } - - if (write(fd, CTL_WAIT, sizeof(CTL_WAIT)) < (int)sizeof(CTL_WAIT)) - { - ERROR("Failed to wait for %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - goto DETACH2; - } - - close(fd); -#elif HAVE_TTRACE - if (ttrace(TT_PROC_ATTACH, processId, 0, TT_DETACH_ON_EXIT, TT_VERSION, 0) == -1) - { - if (errno != ESRCH) - { - ASSERT("ttrace(TT_PROC_ATTACH, pid:%d) failed errno:%d (%s)\n", - processId, errno, strerror(errno)); - } - goto DETACH1; - } -#else // HAVE_TTRACE - if (PAL_PTRACE( PAL_PT_ATTACH, processId, 0, 0 ) == -1) - { - if (errno != ESRCH) - { - ASSERT("ptrace(PT_ATTACH, pid:%d) failed errno:%d (%s)\n", - processId, errno, strerror(errno)); - } - goto DETACH1; - } - - if (waitpid(processId, NULL, WUNTRACED) == -1) - { - if (errno != ESRCH) - { - ASSERT("waitpid(pid:%d, NULL, WUNTRACED) failed.errno:%d" - " (%s)\n", processId, errno, strerror(errno)); - } - goto DETACH2; - } -#endif // HAVE_PROCFS_CTL - } - - return TRUE; - -#if HAVE_PROCFS_CTL -DETACH2: - if (write(fd, CTL_DETACH, sizeof(CTL_DETACH)) < (int)sizeof(CTL_DETACH)) - { - ASSERT("Failed to detach from %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - } - close(fd); -#elif !HAVE_TTRACE -DETACH2: - if (PAL_PTRACE(PAL_PT_DETACH, processId, 0, 0) == -1) - { - ASSERT("ptrace(PT_DETACH, pid:%d) failed. errno:%d (%s)\n", processId, - errno, strerror(errno)); - } -#endif // HAVE_PROCFS_CTL - -DETACH1: - savedErrno = errno; - DBGSetProcessAttached(pThread, hProcess, DBG_DETACH); - errno = savedErrno; -EXIT: - if (errno == ESRCH || errno == ENOENT || errno == EBADF) - { - ERROR("Invalid process ID:%d\n", processId); - SetLastError(ERROR_INVALID_PARAMETER); - } - else - { - SetLastError(ERROR_INTERNAL_ERROR); - } - return FALSE; -} - -/*++ -Function: - DBGDetachProcess - -Abstract - Detach the indicated process from the current process. - - if the indicated process is already attached by the current process, then - decrement the number of attachment pending and detach it from the current - process (with PT_DETACH) if there's no more attachment left. - -Parameter - hProcess : process handle - processId : process ID - -Return - Return true if it succeeds, or true if it's fails ---*/ -static -BOOL -DBGDetachProcess( - CPalThread *pThread, - HANDLE hProcess, - DWORD processId - ) -{ - int nbAttachLeft; -#if HAVE_PROCFS_CTL - int fd = -1; - char ctlPath[1024]; -#endif // HAVE_PROCFS_CTL - - nbAttachLeft = DBGSetProcessAttached(pThread, hProcess, DBG_DETACH); - - if (nbAttachLeft == -1) - { - /* Failed to set the process as detached */ - return FALSE; - } - - /* check if there's no more attachment left on processId */ - if (nbAttachLeft == 0) - { -#if HAVE_PROCFS_CTL - sprintf(ctlPath, sizeof(ctlPath), "/proc/%d/ctl", processId); - fd = InternalOpen(pThread, ctlPath, O_WRONLY); - if (fd == -1) - { - if (errno == ENOENT) - { - ERROR("Invalid process ID: %d\n", processId); - SetLastError(ERROR_INVALID_PARAMETER); - } - else - { - ERROR("Failed to open %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - return FALSE; - } - - if (write(fd, CTL_DETACH, sizeof(CTL_DETACH)) < (int)sizeof(CTL_DETACH)) - { - ERROR("Failed to detach from %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - close(fd); - return FALSE; - } - close(fd); - -#elif HAVE_TTRACE - if (ttrace(TT_PROC_DETACH, processId, 0, 0, 0, 0) == -1) - { - if (errno == ESRCH) - { - ERROR("Invalid process ID: %d\n", processId); - SetLastError(ERROR_INVALID_PARAMETER); - } - else - { - ASSERT("ttrace(TT_PROC_DETACH, pid:%d) failed. errno:%d (%s)\n", - processId, errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - return FALSE; - } -#else // HAVE_TTRACE - if (PAL_PTRACE(PAL_PT_DETACH, processId, 1, 0) == -1) - { - if (errno == ESRCH) - { - ERROR("Invalid process ID: %d\n", processId); - SetLastError(ERROR_INVALID_PARAMETER); - } - else - { - ASSERT("ptrace(PT_DETACH, pid:%d) failed. errno:%d (%s)\n", - processId, errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - return FALSE; - } -#endif // HAVE_PROCFS_CTL - -#if !HAVE_TTRACE - if (kill(processId, SIGCONT) == -1) - { - ERROR("Failed to continue the detached process:%d errno:%d (%s)\n", - processId, errno, strerror(errno)); - return FALSE; - } -#endif // !HAVE_TTRACE - } - return TRUE; -} - -/*++ -Function: - DBGSetProcessAttached - -Abstract - saves the current process Id in the attached process structure - -Parameter - hProcess : process handle - bAttach : true (false) to set the process as attached (as detached) -Return - returns the number of attachment left on attachedProcId, or -1 if it fails ---*/ -static int -DBGSetProcessAttached( - CPalThread *pThread, - HANDLE hProcess, - BOOL bAttach - ) -{ - PAL_ERROR palError = NO_ERROR; - IPalObject *pobjProcess = NULL; - IDataLock *pDataLock = NULL; - CProcProcessLocalData *pLocalData = NULL; - int ret = -1; - CAllowedObjectTypes aotProcess(otiProcess); - - palError = g_pObjectManager->ReferenceObjectByHandle( - pThread, - hProcess, - &aotProcess, - 0, - &pobjProcess - ); - - if (NO_ERROR != palError) - { - goto DBGSetProcessAttachedExit; - } - - palError = pobjProcess->GetProcessLocalData( - pThread, - WriteLock, - &pDataLock, - reinterpret_cast<void **>(&pLocalData) - ); - - if (NO_ERROR != palError) - { - goto DBGSetProcessAttachedExit; - } - - if (bAttach) - { - pLocalData->lAttachCount += 1; - } - else - { - pLocalData->lAttachCount -= 1; - - if (pLocalData->lAttachCount < 0) - { - ASSERT("pLocalData->lAttachCount < 0 check for extra DBGDetachProcess calls\n"); - palError = ERROR_INTERNAL_ERROR; - goto DBGSetProcessAttachedExit; - } - } - - ret = pLocalData->lAttachCount; - -DBGSetProcessAttachedExit: - - if (NULL != pDataLock) - { - pDataLock->ReleaseLock(pThread, TRUE); - } - - if (NULL != pobjProcess) - { - pobjProcess->ReleaseReference(pThread); - } - - return ret; -} - -#endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL - /*++ Function: PAL_CreateExecWatchpoint @@ -1240,605 +766,64 @@ PAL_DeleteExecWatchpointExit: return dwError; } -// We want to enable hardware exception handling for ReadProcessMemory -// and WriteProcessMemory in all cases since it is acceptable if they -// hit AVs, so redefine HardwareExceptionHolder for these two functions -// (here to the end of the file). -#undef HardwareExceptionHolder -#define HardwareExceptionHolder CatchHardwareExceptionHolder __catchHardwareException; - -/*++ -Function: - ReadProcessMemory - -See MSDN doc. ---*/ -BOOL -PALAPI -ReadProcessMemory( - IN HANDLE hProcess, - IN LPCVOID lpBaseAddress, - IN LPVOID lpBuffer, - IN SIZE_T nSize, - OUT SIZE_T * lpNumberOfBytesRead - ) +__attribute__((noinline)) +__attribute__((optnone)) +void +ProbeMemory(volatile PBYTE pbBuffer, DWORD cbBuffer, bool fWriteAccess) { - CPalThread *pThread; - DWORD processId; - Volatile<BOOL> ret = FALSE; - Volatile<SIZE_T> numberOfBytesRead = 0; -#if HAVE_VM_READ - kern_return_t result; - vm_map_t task; - LONG_PTR bytesToRead; -#elif HAVE_PROCFS_CTL - int fd = -1; - char memPath[64]; - off_t offset; -#elif !HAVE_TTRACE - SIZE_T nbInts; - int* ptrInt; - int* lpTmpBuffer; -#endif -#if !HAVE_PROCFS_CTL && !HAVE_TTRACE - int* lpBaseAddressAligned; - SIZE_T offset; -#endif // !HAVE_PROCFS_CTL && !HAVE_TTRACE - - PERF_ENTRY(ReadProcessMemory); - ENTRY("ReadProcessMemory (hProcess=%p,lpBaseAddress=%p, lpBuffer=%p, " - "nSize=%u, lpNumberOfBytesRead=%p)\n",hProcess,lpBaseAddress, - lpBuffer, (unsigned int)nSize, lpNumberOfBytesRead); - - pThread = InternalGetCurrentThread(); - - if (!(processId = PROCGetProcessIDFromHandle(hProcess))) - { - ERROR("Invalid process handler hProcess:%p.",hProcess); - SetLastError(ERROR_INVALID_HANDLE); - goto EXIT; - } - - // Check if the read request is for the current process. - // We don't need ptrace in that case. - if (GetCurrentProcessId() == processId) + // Need an throw in this function to fool the C++ runtime into handling the + // possible h/w exception below. + if (pbBuffer == NULL) { - TRACE("We are in the same process, so ptrace is not needed\n"); - - struct Param - { - LPCVOID lpBaseAddress; - LPVOID lpBuffer; - SIZE_T nSize; - SIZE_T numberOfBytesRead; - BOOL ret; - } param; - param.lpBaseAddress = lpBaseAddress; - param.lpBuffer = lpBuffer; - param.nSize = nSize; - param.numberOfBytesRead = numberOfBytesRead; - param.ret = ret; - - PAL_TRY(Param *, pParam, ¶m) - { - SIZE_T i; - - // Seg fault in memcpy can't be caught - // so we simulate the memcpy here - - for (i = 0; i<pParam->nSize; i++) - { - *((char*)(pParam->lpBuffer)+i) = *((char*)(pParam->lpBaseAddress)+i); - } - - pParam->numberOfBytesRead = pParam->nSize; - pParam->ret = TRUE; - } - PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - SetLastError(ERROR_ACCESS_DENIED); - } - PAL_ENDTRY - - numberOfBytesRead = param.numberOfBytesRead; - ret = param.ret; - goto EXIT; + throw PAL_SEHException(); } -#if HAVE_VM_READ - result = task_for_pid(mach_task_self(), processId, &task); - if (result != KERN_SUCCESS) + // Simple one byte at a time probing + while (cbBuffer > 0) { - ERROR("No Mach task for pid %d: %d\n", processId, ret.Load()); - SetLastError(ERROR_INVALID_HANDLE); - goto EXIT; - } - // vm_read_overwrite usually requires that the address be page-aligned - // and the size be a multiple of the page size. We can't differentiate - // between the cases in which that's required and those in which it - // isn't, so we do it all the time. - lpBaseAddressAligned = (int*)((SIZE_T) lpBaseAddress & ~VIRTUAL_PAGE_MASK); - offset = ((SIZE_T) lpBaseAddress & VIRTUAL_PAGE_MASK); - char *data; - data = (char*)alloca(VIRTUAL_PAGE_SIZE); - while (nSize > 0) - { - vm_size_t bytesRead; - - bytesToRead = VIRTUAL_PAGE_SIZE - offset; - if (bytesToRead > (LONG_PTR)nSize) - { - bytesToRead = nSize; - } - bytesRead = VIRTUAL_PAGE_SIZE; - result = vm_read_overwrite(task, (vm_address_t) lpBaseAddressAligned, - VIRTUAL_PAGE_SIZE, (vm_address_t) data, &bytesRead); - if (result != KERN_SUCCESS || bytesRead != VIRTUAL_PAGE_SIZE) + volatile BYTE read = *pbBuffer; + if (fWriteAccess) { - ERROR("vm_read_overwrite failed for %d bytes from %p in %d: %d\n", - VIRTUAL_PAGE_SIZE, (char *) lpBaseAddressAligned, task, result); - if (result <= KERN_RETURN_MAX) - { - SetLastError(ERROR_INVALID_ACCESS); - } - else - { - SetLastError(ERROR_INTERNAL_ERROR); - } - goto EXIT; + *pbBuffer = read; } - memcpy((LPSTR)lpBuffer + numberOfBytesRead, data + offset, bytesToRead); - numberOfBytesRead.Store(numberOfBytesRead.Load() + bytesToRead); - lpBaseAddressAligned = (int*)((char*)lpBaseAddressAligned + VIRTUAL_PAGE_SIZE); - nSize -= bytesToRead; - offset = 0; + ++pbBuffer; + --cbBuffer; } - ret = TRUE; -#else // HAVE_VM_READ -#if HAVE_PROCFS_CTL - snprintf(memPath, sizeof(memPath), "/proc/%u/%s", processId, PROCFS_MEM_NAME); - fd = InternalOpen(memPath, O_RDONLY); - if (fd == -1) - { - ERROR("Failed to open %s\n", memPath); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; - } - - // - // off_t may be greater in size than void*, so first cast to - // an unsigned type to ensure that no sign extension takes place - // - - offset = (off_t) (UINT_PTR) lpBaseAddress; - - if (lseek(fd, offset, SEEK_SET) == -1) - { - ERROR("Failed to seek to base address\n"); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; - } - - numberOfBytesRead = read(fd, lpBuffer, nSize); - ret = TRUE; - -#else // HAVE_PROCFS_CTL - // Attach the process before calling ttrace/ptrace otherwise it fails. - if (DBGAttachProcess(pThread, hProcess, processId)) - { -#if HAVE_TTRACE - if (ttrace(TT_PROC_RDDATA, processId, 0, (__uint64_t)lpBaseAddress, (__uint64_t)nSize, (__uint64_t)lpBuffer) == -1) - { - if (errno == EFAULT) - { - ERROR("ttrace(TT_PROC_RDDATA, pid:%d, 0, addr:%p, data:%d, addr2:%d) failed" - " errno=%d (%s)\n", processId, lpBaseAddress, (int)nSize, lpBuffer, - errno, strerror(errno)); - - SetLastError(ERROR_ACCESS_DENIED); - } - else - { - ASSERT("ttrace(TT_PROC_RDDATA, pid:%d, 0, addr:%p, data:%d, addr2:%d) failed" - " errno=%d (%s)\n", processId, lpBaseAddress, (int)nSize, lpBuffer, - errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - - goto CLEANUP1; - } - - numberOfBytesRead = nSize; - ret = TRUE; - -#else // HAVE_TTRACE - - offset = (SIZE_T)lpBaseAddress % sizeof(int); - lpBaseAddressAligned = (int*)((char*)lpBaseAddress - offset); - nbInts = (nSize + offset)/sizeof(int) + - ((nSize + offset)%sizeof(int) ? 1:0); - - /* before transferring any data to lpBuffer we should make sure that all - data is accessible for read. so we need to use a temp buffer for that.*/ - if (!(lpTmpBuffer = (int*)InternalMalloc((nbInts * sizeof(int))))) - { - ERROR("Insufficient memory available !\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto CLEANUP1; - } - - for (ptrInt = lpTmpBuffer; nbInts; ptrInt++, - lpBaseAddressAligned++, nbInts--) - { - errno = 0; - *ptrInt = - PAL_PTRACE(PAL_PT_READ_D, processId, lpBaseAddressAligned, 0); - if (*ptrInt == -1 && errno) - { - if (errno == EFAULT) - { - ERROR("ptrace(PT_READ_D, pid:%d, addr:%p, data:0) failed" - " errno=%d (%s)\n", processId, lpBaseAddressAligned, - errno, strerror(errno)); - - SetLastError(ptrInt == lpTmpBuffer ? ERROR_ACCESS_DENIED : - ERROR_PARTIAL_COPY); - } - else - { - ASSERT("ptrace(PT_READ_D, pid:%d, addr:%p, data:0) failed" - " errno=%d (%s)\n", processId, lpBaseAddressAligned, - errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - - goto CLEANUP2; - } - } - - /* transfer data from temp buffer to lpBuffer */ - memcpy( (char *)lpBuffer, ((char*)lpTmpBuffer) + offset, nSize); - numberOfBytesRead = nSize; - ret = TRUE; -#endif // HAVE_TTRACE - } - else - { - /* Failed to attach processId */ - goto EXIT; - } -#endif // HAVE_PROCFS_CTL - -#if HAVE_PROCFS_CTL -PROCFSCLEANUP: - if (fd != -1) - { - close(fd); - } -#elif !HAVE_TTRACE -CLEANUP2: - if (lpTmpBuffer) - { - free(lpTmpBuffer); - } -#endif // !HAVE_TTRACE - -#if !HAVE_PROCFS_CTL -CLEANUP1: - if (!DBGDetachProcess(pThread, hProcess, processId)) - { - /* Failed to detach processId */ - ret = FALSE; - } -#endif // HAVE_PROCFS_CTL -#endif // HAVE_VM_READ - -EXIT: - if (lpNumberOfBytesRead) - { - *lpNumberOfBytesRead = numberOfBytesRead; - } - LOGEXIT("ReadProcessMemory returns BOOL %d\n", ret.Load()); - PERF_EXIT(ReadProcessMemory); - return ret; } /*++ Function: - WriteProcessMemory + PAL_ProbeMemory -See MSDN doc. +Abstract + +Parameter + pBuffer : address of memory to validate + cbBuffer : size of memory region to validate + fWriteAccess : if true, validate writable access, else just readable. + +Return + true if memory is valid, false if not. --*/ BOOL PALAPI -WriteProcessMemory( - IN HANDLE hProcess, - IN LPVOID lpBaseAddress, - IN LPCVOID lpBuffer, - IN SIZE_T nSize, - OUT SIZE_T * lpNumberOfBytesWritten - ) - +PAL_ProbeMemory( + PVOID pBuffer, + DWORD cbBuffer, + BOOL fWriteAccess) { - CPalThread *pThread; - DWORD processId; - Volatile<BOOL> ret = FALSE; - Volatile<SIZE_T> numberOfBytesWritten = 0; -#if HAVE_VM_READ - kern_return_t result; - vm_map_t task; -#elif HAVE_PROCFS_CTL - int fd = -1; - char memPath[64]; - LONG_PTR bytesWritten; - off_t offset; -#elif !HAVE_TTRACE - SIZE_T FirstIntOffset; - SIZE_T LastIntOffset; - unsigned int FirstIntMask; - unsigned int LastIntMask; - SIZE_T nbInts; - int *lpTmpBuffer = 0, *lpInt; - int* lpBaseAddressAligned; -#endif - - PERF_ENTRY(WriteProcessMemory); - ENTRY("WriteProcessMemory (hProcess=%p,lpBaseAddress=%p, lpBuffer=%p, " - "nSize=%u, lpNumberOfBytesWritten=%p)\n", - hProcess,lpBaseAddress, lpBuffer, (unsigned int)nSize, lpNumberOfBytesWritten); - - pThread = InternalGetCurrentThread(); - - if (!(nSize && (processId = PROCGetProcessIDFromHandle(hProcess)))) - { - ERROR("Invalid nSize:%u number or invalid process handler " - "hProcess:%p\n", (unsigned int)nSize, hProcess); - SetLastError(ERROR_INVALID_PARAMETER); - goto EXIT; - } - - // Check if the write request is for the current process. - // In that case we don't need ptrace. - if (GetCurrentProcessId() == processId) - { - TRACE("We are in the same process so we don't need ptrace\n"); - - struct Param - { - LPVOID lpBaseAddress; - LPCVOID lpBuffer; - SIZE_T nSize; - SIZE_T numberOfBytesWritten; - BOOL ret; - } param; - param.lpBaseAddress = lpBaseAddress; - param.lpBuffer = lpBuffer; - param.nSize = nSize; - param.numberOfBytesWritten = numberOfBytesWritten; - param.ret = ret; - - PAL_TRY(Param *, pParam, ¶m) - { - SIZE_T i; - - // Seg fault in memcpy can't be caught - // so we simulate the memcpy here - - for (i = 0; i<pParam->nSize; i++) - { - *((char*)(pParam->lpBaseAddress)+i) = *((char*)(pParam->lpBuffer)+i); - } - - pParam->numberOfBytesWritten = pParam->nSize; - pParam->ret = TRUE; - } - PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - SetLastError(ERROR_ACCESS_DENIED); - } - PAL_ENDTRY - - numberOfBytesWritten = param.numberOfBytesWritten; - ret = param.ret; - goto EXIT; - } - -#if HAVE_VM_READ - result = task_for_pid(mach_task_self(), processId, &task); - if (result != KERN_SUCCESS) - { - ERROR("No Mach task for pid %d: %d\n", processId, ret.Load()); - SetLastError(ERROR_INVALID_HANDLE); - goto EXIT; - } - result = vm_write(task, (vm_address_t) lpBaseAddress, - (vm_address_t) lpBuffer, nSize); - if (result != KERN_SUCCESS) - { - ERROR("vm_write failed for %d bytes from %p in %d: %d\n", - (int)nSize, lpBaseAddress, task, result); - if (result <= KERN_RETURN_MAX) - { - SetLastError(ERROR_ACCESS_DENIED); - } - else - { - SetLastError(ERROR_INTERNAL_ERROR); - } - goto EXIT; - } - numberOfBytesWritten = nSize; - ret = TRUE; -#else // HAVE_VM_READ -#if HAVE_PROCFS_CTL - snprintf(memPath, sizeof(memPath), "/proc/%u/%s", processId, PROCFS_MEM_NAME); - fd = InternalOpen(memPath, O_WRONLY); - if (fd == -1) + try { - ERROR("Failed to open %s\n", memPath); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; - } - - // - // off_t may be greater in size than void*, so first cast to - // an unsigned type to ensure that no sign extension takes place - // - - offset = (off_t) (UINT_PTR) lpBaseAddress; + // Need to explicit h/w exception holder so to catch them in ProbeMemory + CatchHardwareExceptionHolder __catchHardwareException; - if (lseek(fd, offset, SEEK_SET) == -1) - { - ERROR("Failed to seek to base address\n"); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; + ProbeMemory((PBYTE)pBuffer, cbBuffer, fWriteAccess); } - - bytesWritten = write(fd, lpBuffer, nSize); - if (bytesWritten < 0) - { - ERROR("Failed to write to %s\n", memPath); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; - } - - numberOfBytesWritten = bytesWritten; - ret = TRUE; - -#else // HAVE_PROCFS_CTL - /* Attach the process before calling ptrace otherwise it fails */ - if (DBGAttachProcess(pThread, hProcess, processId)) + catch(...) { -#if HAVE_TTRACE - if (ttrace(TT_PROC_WRDATA, processId, 0, (__uint64_t)lpBaseAddress, (__uint64_t)nSize, (__uint64_t)lpBuffer) == -1) - { - if (errno == EFAULT) - { - ERROR("ttrace(TT_PROC_WRDATA, pid:%d, addr:%p, data:%d, addr2:%d) failed" - " errno=%d (%s)\n", processId, lpBaseAddress, nSize, lpBuffer, - errno, strerror(errno)); - - SetLastError(ERROR_ACCESS_DENIED); - } - else - { - ASSERT("ttrace(TT_PROC_WRDATA, pid:%d, addr:%p, data:%d, addr2:%d) failed" - " errno=%d (%s)\n", processId, lpBaseAddress, nSize, lpBuffer, - errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - - goto CLEANUP1; - } - - numberOfBytesWritten = nSize; - ret = TRUE; - -#else // HAVE_TTRACE - - FirstIntOffset = (SIZE_T)lpBaseAddress % sizeof(int); - FirstIntMask = -1; - FirstIntMask <<= (FirstIntOffset * 8); - - nbInts = (nSize + FirstIntOffset) / sizeof(int) + - (((nSize + FirstIntOffset)%sizeof(int)) ? 1:0); - lpBaseAddressAligned = (int*)((char*)lpBaseAddress - FirstIntOffset); - - if ((lpTmpBuffer = (int*)InternalMalloc((nbInts * sizeof(int)))) == NULL) - { - ERROR("Insufficient memory available !\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto CLEANUP1; - } - - memcpy((char *)lpTmpBuffer + FirstIntOffset, (char *)lpBuffer, nSize); - lpInt = lpTmpBuffer; - - LastIntOffset = (nSize + FirstIntOffset) % sizeof(int); - LastIntMask = -1; - LastIntMask >>= ((sizeof(int) - LastIntOffset) * 8); - - if (nbInts == 1) - { - if (DBGWriteProcMem_IntWithMask(processId, lpBaseAddressAligned, - *lpInt, - LastIntMask & FirstIntMask) - == 0) - { - goto CLEANUP2; - } - numberOfBytesWritten = nSize; - ret = TRUE; - goto CLEANUP2; - } - - if (DBGWriteProcMem_IntWithMask(processId, - lpBaseAddressAligned++, - *lpInt++, FirstIntMask) - == 0) - { - goto CLEANUP2; - } - - while (--nbInts > 1) - { - if (DBGWriteProcMem_Int(processId, lpBaseAddressAligned++, - *lpInt++) == 0) - { - goto CLEANUP2; - } - } - - if (DBGWriteProcMem_IntWithMask(processId, lpBaseAddressAligned, - *lpInt, LastIntMask ) == 0) - { - goto CLEANUP2; - } - - numberOfBytesWritten = nSize; - ret = TRUE; -#endif // HAVE_TTRACE - } - else - { - /* Failed to attach processId */ - goto EXIT; - } -#endif // HAVE_PROCFS_CTL - -#if HAVE_PROCFS_CTL -PROCFSCLEANUP: - if (fd != -1) - { - close(fd); - } -#elif !HAVE_TTRACE -CLEANUP2: - if (lpTmpBuffer) - { - free(lpTmpBuffer); - } -#endif // !HAVE_TTRACE - -#if !HAVE_PROCFS_CTL -CLEANUP1: - if (!DBGDetachProcess(pThread, hProcess, processId)) - { - /* Failed to detach processId */ - ret = FALSE; - } -#endif // !HAVE_PROCFS_CTL -#endif // HAVE_VM_READ - -EXIT: - if (lpNumberOfBytesWritten) - { - *lpNumberOfBytesWritten = numberOfBytesWritten; + return FALSE; } - - LOGEXIT("WriteProcessMemory returns BOOL %d\n", ret.Load()); - PERF_EXIT(WriteProcessMemory); - return ret; + return TRUE; } } // extern "C" diff --git a/src/pal/src/examples/CMakeLists.txt b/src/pal/src/examples/CMakeLists.txt index 2cef914892..3797d89b68 100644 --- a/src/pal/src/examples/CMakeLists.txt +++ b/src/pal/src/examples/CMakeLists.txt @@ -4,7 +4,7 @@ project(palexmpl) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - example1.c + example1.cpp ) add_executable(palexmpl diff --git a/src/pal/src/examples/example1.c b/src/pal/src/examples/example1.cpp index 071f42e4f9..071f42e4f9 100644 --- a/src/pal/src/examples/example1.c +++ b/src/pal/src/examples/example1.cpp diff --git a/src/pal/src/exception/machexception.cpp b/src/pal/src/exception/machexception.cpp index 8b0d7f22a8..5328e1f329 100644 --- a/src/pal/src/exception/machexception.cpp +++ b/src/pal/src/exception/machexception.cpp @@ -1518,6 +1518,7 @@ ActivationHandler(CONTEXT* context) extern "C" void ActivationHandlerWrapper(); extern "C" int ActivationHandlerReturnOffset; +extern "C" unsigned int XmmYmmStateSupport(); /*++ Function : @@ -1581,6 +1582,12 @@ InjectActivationInternal(CPalThread* pThread) // after the activation function returns. CONTEXT *pContext = (CONTEXT *)contextAddress; pContext->ContextFlags = CONTEXT_FULL | CONTEXT_SEGMENTS; +#ifdef XSTATE_SUPPORTED + if (XmmYmmStateSupport() == 1) + { + pContext->ContextFlags |= CONTEXT_XSTATE; + } +#endif MachRet = CONTEXT_GetThreadContextFromPort(threadPort, pContext); _ASSERT_MSG(MachRet == KERN_SUCCESS, "CONTEXT_GetThreadContextFromPort\n"); diff --git a/src/pal/src/exception/machmessage.cpp b/src/pal/src/exception/machmessage.cpp index a6f7e57484..b786960782 100644 --- a/src/pal/src/exception/machmessage.cpp +++ b/src/pal/src/exception/machmessage.cpp @@ -1069,7 +1069,7 @@ thread_act_t MachMessage::GetThreadFromState(thread_state_flavor_t eFlavor, thre NONPAL_RETAIL_ASSERT("Failed to locate thread from state."); } -// Transform a exception handler behavior type into the corresponding Mach message ID for the notification. +// Transform an exception handler behavior type into the corresponding Mach message ID for the notification. mach_msg_id_t MachMessage::MapBehaviorToNotificationType(exception_behavior_t eBehavior) { switch ((uint)eBehavior) diff --git a/src/pal/src/exception/machmessage.h b/src/pal/src/exception/machmessage.h index 244396cd35..abc583f6c4 100644 --- a/src/pal/src/exception/machmessage.h +++ b/src/pal/src/exception/machmessage.h @@ -36,7 +36,7 @@ using namespace CorUnix; if (machret != KERN_SUCCESS) \ { \ char _szError[1024]; \ - sprintf(_szError, "%s: %u: %s", __FUNCTION__, __LINE__, _msg); \ + snprintf(_szError, _countof(_szError), "%s: %u: %s", __FUNCTION__, __LINE__, _msg); \ mach_error(_szError, machret); \ abort(); \ } \ @@ -395,7 +395,7 @@ private: // x86_THREAD_STATE and x86_THREAD_STATE32 state flavors are supported. thread_act_t GetThreadFromState(thread_state_flavor_t eFlavor, thread_state_t pState); - // Transform a exception handler behavior type into the corresponding Mach message ID for the + // Transform an exception handler behavior type into the corresponding Mach message ID for the // notification. mach_msg_id_t MapBehaviorToNotificationType(exception_behavior_t eBehavior); diff --git a/src/pal/src/exception/seh-unwind.cpp b/src/pal/src/exception/seh-unwind.cpp index 24eebbbf94..fa2f109875 100644 --- a/src/pal/src/exception/seh-unwind.cpp +++ b/src/pal/src/exception/seh-unwind.cpp @@ -73,6 +73,14 @@ Abstract: ASSIGN_REG(X26) \ ASSIGN_REG(X27) \ ASSIGN_REG(X28) +#elif defined(_X86_) +#define ASSIGN_UNWIND_REGS \ + ASSIGN_REG(Eip) \ + ASSIGN_REG(Esp) \ + ASSIGN_REG(Ebp) \ + ASSIGN_REG(Ebx) \ + ASSIGN_REG(Esi) \ + ASSIGN_REG(Edi) #else #error unsupported architecture #endif @@ -122,6 +130,13 @@ static void WinContextToUnwindCursor(CONTEXT *winContext, unw_cursor_t *cursor) unw_set_reg(cursor, UNW_X86_64_R13, winContext->R13); unw_set_reg(cursor, UNW_X86_64_R14, winContext->R14); unw_set_reg(cursor, UNW_X86_64_R15, winContext->R15); +#elif defined(_X86_) + unw_set_reg(cursor, UNW_REG_IP, winContext->Eip); + unw_set_reg(cursor, UNW_REG_SP, winContext->Esp); + unw_set_reg(cursor, UNW_X86_EBP, winContext->Ebp); + unw_set_reg(cursor, UNW_X86_EBX, winContext->Ebx); + unw_set_reg(cursor, UNW_X86_ESI, winContext->Esi); + unw_set_reg(cursor, UNW_X86_EDI, winContext->Edi); #endif } #endif @@ -137,6 +152,13 @@ static void UnwindContextToWinContext(unw_cursor_t *cursor, CONTEXT *winContext) unw_get_reg(cursor, UNW_X86_64_R13, (unw_word_t *) &winContext->R13); unw_get_reg(cursor, UNW_X86_64_R14, (unw_word_t *) &winContext->R14); unw_get_reg(cursor, UNW_X86_64_R15, (unw_word_t *) &winContext->R15); +#elif defined(_X86_) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Eip); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Esp); + unw_get_reg(cursor, UNW_X86_EBP, (unw_word_t *) &winContext->Ebp); + unw_get_reg(cursor, UNW_X86_EBX, (unw_word_t *) &winContext->Ebx); + unw_get_reg(cursor, UNW_X86_ESI, (unw_word_t *) &winContext->Esi); + unw_get_reg(cursor, UNW_X86_EDI, (unw_word_t *) &winContext->Edi); #elif defined(_ARM_) unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); @@ -196,6 +218,11 @@ static void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, GetContextPointer(cursor, unwContext, UNW_X86_64_R13, &contextPointers->R13); GetContextPointer(cursor, unwContext, UNW_X86_64_R14, &contextPointers->R14); GetContextPointer(cursor, unwContext, UNW_X86_64_R15, &contextPointers->R15); +#elif defined(_X86_) + GetContextPointer(cursor, unwContext, UNW_X86_EBX, &contextPointers->Ebx); + GetContextPointer(cursor, unwContext, UNW_X86_EBP, &contextPointers->Ebp); + GetContextPointer(cursor, unwContext, UNW_X86_ESI, &contextPointers->Esi); + GetContextPointer(cursor, unwContext, UNW_X86_EDI, &contextPointers->Edi); #elif defined(_ARM_) GetContextPointer(cursor, unwContext, UNW_ARM_R4, &contextPointers->R4); GetContextPointer(cursor, unwContext, UNW_ARM_R5, &contextPointers->R5); @@ -221,15 +248,34 @@ static void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, #endif } +extern int g_common_signal_handler_context_locvar_offset; + BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers) { int st; unw_context_t unwContext; unw_cursor_t cursor; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(_ARM64_) || defined(_ARM_) - DWORD64 curPc; -#endif + DWORD64 curPc = CONTEXTGetPC(context); + +#ifndef __APPLE__ + // Check if the PC is the return address from the SEHProcessException in the common_signal_handler. + // If that's the case, extract its local variable containing the native_context_t of the hardware + // exception and return that. This skips the hardware signal handler trampoline that the libunwind + // cannot cross on some systems. + if ((void*)curPc == g_SEHProcessExceptionReturnAddress) + { + ULONG contextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_EXCEPTION_ACTIVE; + + #if defined(_AMD64_) + contextFlags |= CONTEXT_XSTATE; + #endif + size_t nativeContext = *(size_t*)(CONTEXTGetFP(context) + g_common_signal_handler_context_locvar_offset); + CONTEXTFromNativeContext((const native_context_t *)nativeContext, context, contextFlags); + + return TRUE; + } +#endif if ((context->ContextFlags & CONTEXT_EXCEPTION_ACTIVE) != 0) { @@ -240,7 +286,7 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP // So we compensate it by incrementing the PC before passing it to the unwinder. // Without it, the unwinder would not find unwind info if the hardware exception // happened in the first instruction of a function. - CONTEXTSetPC(context, CONTEXTGetPC(context) + 1); + CONTEXTSetPC(context, curPc + 1); } #if !UNWIND_CONTEXT_IS_UCONTEXT_T @@ -264,18 +310,6 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP WinContextToUnwindCursor(context, &cursor); #endif -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(_ARM64_) || defined(_ARM_) - // FreeBSD, NetBSD and OSX appear to do two different things when unwinding - // 1: If it reaches where it cannot unwind anymore, say a - // managed frame. It wil return 0, but also update the $pc - // 2: If it unwinds all the way to _start it will return - // 0 from the step, but $pc will stay the same. - // The behaviour of libunwind from nongnu.org is to null the PC - // So we bank the original PC here, so we can compare it after - // the step - curPc = CONTEXTGetPC(context); -#endif - st = unw_step(&cursor); if (st < 0) { @@ -303,12 +337,18 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP // Update the passed in windows context to reflect the unwind // UnwindContextToWinContext(&cursor, context); -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(_ARM64_) || defined(_ARM_) + + // FreeBSD, NetBSD, OSX and Alpine appear to do two different things when unwinding + // 1: If it reaches where it cannot unwind anymore, say a + // managed frame. It will return 0, but also update the $pc + // 2: If it unwinds all the way to _start it will return + // 0 from the step, but $pc will stay the same. + // So we detect that here and set the $pc to NULL in that case. + // This is the default behavior of the libunwind on Linux. if (st == 0 && CONTEXTGetPC(context) == curPc) { CONTEXTSetPC(context, 0); } -#endif if (contextPointers != NULL) { diff --git a/src/pal/src/exception/seh.cpp b/src/pal/src/exception/seh.cpp index 38779bf59b..ad09e02884 100644 --- a/src/pal/src/exception/seh.cpp +++ b/src/pal/src/exception/seh.cpp @@ -88,6 +88,10 @@ PHARDWARE_EXCEPTION_SAFETY_CHECK_FUNCTION g_safeExceptionCheckFunction = NULL; PGET_GCMARKER_EXCEPTION_CODE g_getGcMarkerExceptionCode = NULL; +// Return address of the SEHProcessException, which is used to enable walking over +// the signal handler trampoline on some Unixes where the libunwind cannot do that. +void* g_SEHProcessExceptionReturnAddress = NULL; + /* Internal function definitions **********************************************/ /*++ @@ -245,6 +249,8 @@ Return value: BOOL SEHProcessException(PAL_SEHException* exception) { + g_SEHProcessExceptionReturnAddress = __builtin_return_address(0); + CONTEXT* contextRecord = exception->GetContextRecord(); EXCEPTION_RECORD* exceptionRecord = exception->GetExceptionRecord(); @@ -268,7 +274,7 @@ SEHProcessException(PAL_SEHException* exception) { // The exception happened in the page right below the stack limit, // so it is a stack overflow - write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1); + (void)write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1); PROCAbort(); } } diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index c2c217993a..26e2a012c5 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -100,6 +100,10 @@ static bool registered_sigterm_handler = false; struct sigaction g_previous_activation; #endif +// Offset of the local variable containing native context in the common_signal_handler function. +// This offset is relative to the frame pointer. +int g_common_signal_handler_context_locvar_offset = 0; + /* public function definitions ************************************************/ /*++ @@ -582,6 +586,7 @@ Note: the "pointers" parameter should contain a valid exception record pointer, but the ContextRecord pointer will be overwritten. --*/ +__attribute__((noinline)) static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext, int numParams, ...) { sigset_t signal_set; @@ -590,6 +595,7 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext native_context_t *ucontext; ucontext = (native_context_t *)sigcontext; + g_common_signal_handler_context_locvar_offset = (int)((char*)&ucontext - (char*)__builtin_frame_address(0)); AllocateExceptionRecords(&exceptionRecord, &contextRecord); diff --git a/src/pal/src/file/find.cpp b/src/pal/src/file/find.cpp index 18639d3d14..18bf8c4cf1 100644 --- a/src/pal/src/file/find.cpp +++ b/src/pal/src/file/find.cpp @@ -383,7 +383,7 @@ FindNextFileA( // Split the path into a dir and filename. if (_splitpath_s(path, NULL, 0, find_data->dir, _MAX_DIR, find_data->fname, _MAX_PATH, ext, _MAX_EXT) != 0) { - ASSERT("_splitpath failed on %s\n", path); + ASSERT("_splitpath_s failed on %s\n", path); dwLastError = ERROR_INTERNAL_ERROR; goto done; } @@ -716,7 +716,7 @@ Simple helper function to insert backslashes before square brackets to prevent glob from using them as wildcards. note: this functions assumes all backslashes have previously been - converted into forwardslashes by _splitpath. + converted into forwardslashes by _splitpath_s. --*/ static void FILEEscapeSquareBrackets(char *pattern, char *escaped_pattern) { @@ -750,7 +750,7 @@ Function: FILEGlobFromSplitPath Simple wrapper function around glob(3), except that the pattern is accepted -in broken-down form like _splitpath produces. +in broken-down form like _splitpath_s produces. ie. calling splitpath on a pattern then calling this function should produce the same result as just calling glob() on the pattern. @@ -874,12 +874,12 @@ static BOOL FILEDosGlobA( CPalThread *pthrCurrent, _splitpath_s( pattern, NULL, 0, Dir, _MAX_DIR, Filename, _MAX_FNAME+1, Ext, _MAX_EXT); - /* check to see if _splitpath failed */ + /* check to see if _splitpath_s failed */ if ( Filename[0] == 0 ) { if ( Dir[0] == 0 ) { - ERROR("_splitpath failed on path [%s]\n", pattern); + ERROR("_splitpath_s failed on path [%s]\n", pattern); } else { diff --git a/src/pal/src/include/pal/context.h b/src/pal/src/include/pal/context.h index 5e378942fb..6857c130ee 100644 --- a/src/pal/src/include/pal/context.h +++ b/src/pal/src/include/pal/context.h @@ -139,6 +139,8 @@ typedef ucontext_t native_context_t; ///////////////////// // Extended state +#ifdef XSTATE_SUPPORTED + inline _fpx_sw_bytes *FPREG_FpxSwBytes(const ucontext_t *uc) { // Bytes 464..511 in the FXSAVE format are available for software to use for any purpose. In this case, they are used to @@ -185,6 +187,8 @@ inline void *FPREG_Xstate_Ymmh(const ucontext_t *uc) return reinterpret_cast<_xstate *>(FPREG_Fpstate(uc))->ymmh.ymmh_space; } +#endif // XSTATE_SUPPORTED + ///////////////////// #else // BIT64 @@ -450,6 +454,8 @@ inline static DWORD64 CONTEXTGetPC(LPCONTEXT pContext) { #if defined(_AMD64_) return pContext->Rip; +#elif defined(_X86_) + return pContext->Eip; #elif defined(_ARM64_) || defined(_ARM_) return pContext->Pc; #else @@ -461,6 +467,8 @@ inline static void CONTEXTSetPC(LPCONTEXT pContext, DWORD64 pc) { #if defined(_AMD64_) pContext->Rip = pc; +#elif defined(_X86_) + pContext->Eip = pc; #elif defined(_ARM64_) || defined(_ARM_) pContext->Pc = pc; #else @@ -468,6 +476,21 @@ inline static void CONTEXTSetPC(LPCONTEXT pContext, DWORD64 pc) #endif } +inline static DWORD64 CONTEXTGetFP(LPCONTEXT pContext) +{ +#if defined(_AMD64_) + return pContext->Rbp; +#elif defined(_X86_) + return pContext->Ebp; +#elif defined(_ARM_) + return pContext->R7; +#elif defined(_ARM64_) + return pContext->Fp; +#else +#error don't know how to get the frame pointer for this architecture +#endif +} + /*++ Function : CONTEXT_CaptureContext @@ -481,6 +504,7 @@ Parameters : --*/ void +PALAPI CONTEXT_CaptureContext( LPCONTEXT lpContext ); diff --git a/src/pal/src/include/pal/palinternal.h b/src/pal/src/include/pal/palinternal.h index 7348192e6d..f7856be902 100644 --- a/src/pal/src/include/pal/palinternal.h +++ b/src/pal/src/include/pal/palinternal.h @@ -169,7 +169,6 @@ function_name() to call the system's implementation #define memmove DUMMY_memmove #define memchr DUMMY_memchr #define strlen DUMMY_strlen -#define strnlen DUMMY_strnlen #define stricmp DUMMY_stricmp #define strstr DUMMY_strstr #define strcmp DUMMY_strcmp @@ -184,12 +183,6 @@ function_name() to call the system's implementation #define strpbrk DUMMY_strpbrk #define strtod DUMMY_strtod #define strspn DUMMY_strspn -#if HAVE__SNPRINTF -#define _snprintf DUMMY__snprintf -#endif /* HAVE__SNPRINTF */ -#if HAVE__SNWPRINTF -#define _snwprintf DUMMY__snwprintf -#endif /* HAVE__SNWPRINTF */ #define tolower DUMMY_tolower #define toupper DUMMY_toupper #define islower DUMMY_islower @@ -217,9 +210,18 @@ function_name() to call the system's implementation #define sqrt DUMMY_sqrt #define tan DUMMY_tan #define tanh DUMMY_tanh +#define ceilf DUMMY_ceilf +#define cosf DUMMY_cosf +#define coshf DUMMY_coshf #define fabsf DUMMY_fabsf +#define floorf DUMMY_floorf #define fmodf DUMMY_fmodf #define modff DUMMY_modff +#define sinf DUMMY_sinf +#define sinhf DUMMY_sinhf +#define sqrtf DUMMY_sqrtf +#define tanf DUMMY_tanf +#define tanhf DUMMY_tanhf /* RAND_MAX needed to be renamed to avoid duplicate definition when including stdlib.h header files. PAL_RAND_MAX should have the same value as RAND_MAX @@ -349,9 +351,7 @@ function_name() to call the system's implementation #undef atexit #undef div #undef div_t -#if !defined(_DEBUG) #undef memcpy -#endif //!defined(_DEBUG) #undef memcmp #undef memset #undef memmove @@ -460,9 +460,26 @@ function_name() to call the system's implementation #undef sqrt #undef tan #undef tanh +#undef acosf +#undef asinf +#undef atanf +#undef atan2f +#undef ceilf +#undef cosf +#undef coshf +#undef expf #undef fabsf +#undef floorf #undef fmodf +#undef logf +#undef log10f #undef modff +#undef powf +#undef sinf +#undef sinhf +#undef sqrtf +#undef tanf +#undef tanhf #undef rand #undef srand #undef errno @@ -485,13 +502,7 @@ function_name() to call the system's implementation #undef vfwprintf #undef vprintf #undef wprintf -#undef sprintf #undef swprintf -#undef _snprintf -#if HAVE__SNWPRINTF -#undef _snwprintf -#endif /* HAVE__SNWPRINTF */ -#undef sscanf #undef wcstod #undef wcstol #undef wcstoul @@ -502,7 +513,6 @@ function_name() to call the system's implementation #undef wcsncmp #undef wcschr #undef wcsrchr -#undef wsprintf #undef swscanf #undef wcspbrk #undef wcsstr @@ -518,7 +528,6 @@ function_name() to call the system's implementation #undef vsprintf #undef vswprintf #undef _vsnprintf -#undef _vsnwprintf #undef vsnprintf #undef wvsnprintf @@ -689,7 +698,7 @@ inline T* InterlockedCompareExchangePointerT( #include "volatile.h" -const char StackOverflowMessage[] = "Process is terminated due to StackOverflowException.\n"; +const char StackOverflowMessage[] = "Process is terminating due to StackOverflowException.\n"; #endif // __cplusplus diff --git a/src/pal/src/init/pal.cpp b/src/pal/src/init/pal.cpp index a5edb36428..0bda27644e 100644 --- a/src/pal/src/init/pal.cpp +++ b/src/pal/src/init/pal.cpp @@ -992,6 +992,7 @@ Return value: --*/ static BOOL INIT_IncreaseDescriptorLimit(void) { +#ifndef DONT_SET_RLIMIT_NOFILE struct rlimit rlp; int result; @@ -1008,7 +1009,7 @@ static BOOL INIT_IncreaseDescriptorLimit(void) { return FALSE; } - +#endif // !DONT_SET_RLIMIT_NOFILE return TRUE; } diff --git a/src/pal/src/map/virtual.cpp b/src/pal/src/map/virtual.cpp index 4b5209642c..4a55de9891 100644 --- a/src/pal/src/map/virtual.cpp +++ b/src/pal/src/map/virtual.cpp @@ -1096,6 +1096,7 @@ VIRTUALCommitMemory( } StartBoundary = pInformation->startBoundary + runStart * VIRTUAL_PAGE_SIZE; + pRetVal = (void *)StartBoundary; MemSize = runLength * VIRTUAL_PAGE_SIZE; if (allocationType != MEM_COMMIT) @@ -1156,10 +1157,10 @@ error: pRetVal = NULL; goto done; } - pInformation = NULL; - pRetVal = NULL; } + pInformation = NULL; + pRetVal = NULL; done: LogVaOperation( diff --git a/src/pal/src/misc/sysinfo.cpp b/src/pal/src/misc/sysinfo.cpp index 515ccf1cdb..e7589e8583 100644 --- a/src/pal/src/misc/sysinfo.cpp +++ b/src/pal/src/misc/sysinfo.cpp @@ -172,7 +172,7 @@ GetSystemInfo( #ifdef VM_MAXUSER_ADDRESS lpSystemInfo->lpMaximumApplicationAddress = (PVOID) VM_MAXUSER_ADDRESS; #elif defined(__sun__) || defined(_AIX) || defined(__hppa__) || ( defined (_IA64_) && defined (_HPUX_) ) || defined(__linux__) - lpSystemInfo->lpMaximumApplicationAddress = (PVOID) -1; + lpSystemInfo->lpMaximumApplicationAddress = (PVOID) (1ull << 47); #elif defined(USERLIMIT) lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USERLIMIT; #elif defined(_WIN64) diff --git a/src/pal/src/safecrt/input.inl b/src/pal/src/safecrt/input.inl index eaad174ff5..25c4541029 100644 --- a/src/pal/src/safecrt/input.inl +++ b/src/pal/src/safecrt/input.inl @@ -671,7 +671,7 @@ scanit: #endif /* _SECURE_SCANF */ #ifndef _UNICODE if (fl_wchar_arg) { - wctemp = L'?'; + wctemp = W('?'); char temp[2]; temp[0] = (char) ch; #if 0 // we are not supporting multibyte input strings @@ -682,7 +682,7 @@ scanit: #endif /* 0 */ _MBTOWC(&wctemp, temp, MB_CUR_MAX); *(wchar_t UNALIGNED *)pointer = wctemp; - /* just copy L'?' if mbtowc fails, errno is set by mbtowc */ + /* just copy W('?') if mbtowc fails, errno is set by mbtowc */ pointer = (wchar_t *)pointer + 1; #ifdef _SECURE_SCANF --array_width; diff --git a/src/pal/src/safecrt/makepath_s.c b/src/pal/src/safecrt/makepath_s.cpp index 4342685b9c..4342685b9c 100644 --- a/src/pal/src/safecrt/makepath_s.c +++ b/src/pal/src/safecrt/makepath_s.cpp diff --git a/src/pal/src/safecrt/mbusafecrt.c b/src/pal/src/safecrt/mbusafecrt.cpp index ca853d9269..4446f77fd1 100644 --- a/src/pal/src/safecrt/mbusafecrt.c +++ b/src/pal/src/safecrt/mbusafecrt.cpp @@ -147,14 +147,11 @@ int _ungetwc_nolock( wchar_t inChar, miniFILE* inStream ) /*** * _safecrt_cfltcvt - convert a float to an ascii string. -* Uses sprintf - this usage is OK. ****/ /* routine used for floating-point output */ #define FORMATSIZE 30 -#define _snprintf snprintf - // taken from output.inl #define FL_ALTERNATE 0x00080 /* alternate form requested */ @@ -181,7 +178,7 @@ errno_t _safecrt_cfltcvt(double *arg, char *buffer, size_t sizeInBytes, int type format[formatlen] = 0; buffer[sizeInBytes - 1] = 0; - retvalue = _snprintf(buffer, sizeInBytes, format, *arg); + retvalue = snprintf(buffer, sizeInBytes, format, *arg); if (buffer[sizeInBytes - 1] != 0 || retvalue <= 0) { buffer[0] = 0; @@ -199,14 +196,12 @@ void _safecrt_fassign(int flag, void* argument, char* number ) { if ( flag != 0 ) // double { - double dblValue = 0.0; - (void)sscanf( number, "%lf", &dblValue ); + double dblValue = strtod(number, NULL); *( ( double* )argument ) = dblValue; } else // float { - float fltValue = 0.0; - (void)sscanf( number, "%f", &fltValue ); + float fltValue = strtof(number, NULL); *( ( float* )argument ) = fltValue; } } diff --git a/src/pal/src/safecrt/memcpy_s.c b/src/pal/src/safecrt/memcpy_s.cpp index 27aeb79665..27aeb79665 100644 --- a/src/pal/src/safecrt/memcpy_s.c +++ b/src/pal/src/safecrt/memcpy_s.cpp diff --git a/src/pal/src/safecrt/memmove_s.c b/src/pal/src/safecrt/memmove_s.cpp index a0ae5f7ea6..a0ae5f7ea6 100644 --- a/src/pal/src/safecrt/memmove_s.c +++ b/src/pal/src/safecrt/memmove_s.cpp diff --git a/src/pal/src/safecrt/output.inl b/src/pal/src/safecrt/output.inl index ae0692efc5..5b86cf2c96 100644 --- a/src/pal/src/safecrt/output.inl +++ b/src/pal/src/safecrt/output.inl @@ -857,6 +857,12 @@ int __cdecl _output ( flags |= FL_LONG; /* 'l' => long int or wchar_t */ } break; + case _T('L'): + if (*format == _T('p')) + { + flags |= FL_LONG; + } + break; case _T('I'): /* @@ -956,7 +962,11 @@ int __cdecl _output ( #else /* _UNICODE */ if (flags & (FL_LONG|FL_WIDECHAR)) { wchar = (wchar_t) get_int_arg(&argptr); - no_output = 1; + textlen = snprintf(buffer.sz, BUFFERSIZE, "%lc", wchar); + if (textlen == 0) + { + no_output = 1; + } } else { /* format multibyte character */ /* this is an extension of ANSI */ @@ -1172,7 +1182,15 @@ int __cdecl _output ( precision = 2 * sizeof(void *); /* number of hex digits needed */ #if PTR_IS_INT64 - flags |= FL_I64; /* assume we're converting an int64 */ + if (flags & (FL_LONG | FL_SHORT)) + { + /* %lp, %Lp or %hp - these print 8 hex digits*/ + precision = 2 * sizeof(int32_t); + } + else + { + flags |= FL_I64; /* assume we're converting an int64 */ + } #elif !PTR_IS_INT flags |= FL_LONG; /* assume we're converting a long */ #endif /* !PTR_IS_INT */ @@ -1371,7 +1389,22 @@ int __cdecl _output ( /* write text */ #ifndef _UNICODE if (bufferiswide && (textlen > 0)) { - charsout = -1; + const WCHAR *p; + int mbCharCount; + int count; + char mbStr[5]; + + p = text.wz; + count = textlen; + while (count-- > 0) { + mbCharCount = snprintf(mbStr, sizeof(mbStr), "%lc", *p); + if (mbCharCount == 0) { + charsout = -1; + break; + } + WRITE_STRING(mbStr, mbCharCount, &charsout); + p++; + } } else { WRITE_STRING(text.sz, textlen, &charsout); } diff --git a/src/pal/src/safecrt/safecrt_input_s.c b/src/pal/src/safecrt/safecrt_input_s.cpp index 6ba607c669..6ba607c669 100644 --- a/src/pal/src/safecrt/safecrt_input_s.c +++ b/src/pal/src/safecrt/safecrt_input_s.cpp diff --git a/src/pal/src/safecrt/safecrt_output_l.c b/src/pal/src/safecrt/safecrt_output_l.cpp index d6844f4f8b..d6844f4f8b 100644 --- a/src/pal/src/safecrt/safecrt_output_l.c +++ b/src/pal/src/safecrt/safecrt_output_l.cpp diff --git a/src/pal/src/safecrt/safecrt_output_s.c b/src/pal/src/safecrt/safecrt_output_s.cpp index c3e7f91404..c3e7f91404 100644 --- a/src/pal/src/safecrt/safecrt_output_s.c +++ b/src/pal/src/safecrt/safecrt_output_s.cpp diff --git a/src/pal/src/safecrt/safecrt_winput_s.c b/src/pal/src/safecrt/safecrt_winput_s.cpp index 17a621781b..17a621781b 100644 --- a/src/pal/src/safecrt/safecrt_winput_s.c +++ b/src/pal/src/safecrt/safecrt_winput_s.cpp diff --git a/src/pal/src/safecrt/safecrt_woutput_s.c b/src/pal/src/safecrt/safecrt_woutput_s.cpp index 52fe9400d5..52fe9400d5 100644 --- a/src/pal/src/safecrt/safecrt_woutput_s.c +++ b/src/pal/src/safecrt/safecrt_woutput_s.cpp diff --git a/src/pal/src/safecrt/snprintf.c b/src/pal/src/safecrt/snprintf.cpp index c892d1a9b6..dea87167b9 100644 --- a/src/pal/src/safecrt/snprintf.c +++ b/src/pal/src/safecrt/snprintf.cpp @@ -8,7 +8,7 @@ * *Purpose: -* The _snprintf() flavor takes a count argument that is +* The sprintf_s() flavor takes a count argument that is * the max number of bytes that should be written to the * user's buffer. * diff --git a/src/pal/src/safecrt/splitpath_s.c b/src/pal/src/safecrt/splitpath_s.cpp index cb8a364550..cb8a364550 100644 --- a/src/pal/src/safecrt/splitpath_s.c +++ b/src/pal/src/safecrt/splitpath_s.cpp diff --git a/src/pal/src/safecrt/sprintf.c b/src/pal/src/safecrt/sprintf_s.cpp index 5454179f8d..edfb768670 100644 --- a/src/pal/src/safecrt/sprintf.c +++ b/src/pal/src/safecrt/sprintf_s.cpp @@ -3,12 +3,12 @@ // See the LICENSE file in the project root for more information. /*** -*sprintf.c - print formatted to string +*sprintf_s.c - print formatted to string * * *Purpose: -* defines sprintf() and _snprintf() - print formatted data to string +* defines sprintf_s() and _snprintf_s() - print formatted data to string * *******************************************************************************/ @@ -22,9 +22,9 @@ /*** *ifndef _COUNT_ -*int sprintf(string, format, ...) - print formatted data to string +*int sprintf_s(string, format, ...) - print formatted data to string *else -*int _snprintf(string, cnt, format, ...) - print formatted data to string +*int _snprintf_s(string, cnt, format, ...) - print formatted data to string *endif * *Purpose: @@ -40,7 +40,7 @@ * entries are in are in DGROUP and, thus, are near. * *ifdef _COUNT_ -* The _snprintf() flavor takes a count argument that is +* The _snprintf_s() flavor takes a count argument that is * the max number of bytes that should be written to the * user's buffer. *endif @@ -76,7 +76,7 @@ int sprintf_s ( int ret; va_list arglist; va_start(arglist, format); - ret = _vsprintf_s(string, sizeInBytes, format, arglist); + ret = vsprintf_s(string, sizeInBytes, format, arglist); va_end(arglist); return ret; } diff --git a/src/pal/src/safecrt/sscanf.c b/src/pal/src/safecrt/sscanf_s.cpp index 94b5148875..4f548bccc6 100644 --- a/src/pal/src/safecrt/sscanf.c +++ b/src/pal/src/safecrt/sscanf_s.cpp @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. /*** -*sscanf.c - read formatted data from string +*sscanf_s.c - read formatted data from string * * @@ -20,7 +20,7 @@ #include "mbusafecrt_internal.h" typedef int (*INPUTFN)(miniFILE *, const unsigned char*, va_list); -typedef int (*WINPUTFN)(miniFILE *, const unsigned short*, va_list); +typedef int (*WINPUTFN)(miniFILE *, const wchar_t*, va_list); /*** diff --git a/src/pal/src/safecrt/strcat_s.c b/src/pal/src/safecrt/strcat_s.cpp index 4dc2332006..4dc2332006 100644 --- a/src/pal/src/safecrt/strcat_s.c +++ b/src/pal/src/safecrt/strcat_s.cpp diff --git a/src/pal/src/safecrt/strcpy_s.c b/src/pal/src/safecrt/strcpy_s.cpp index 821dbe85f6..821dbe85f6 100644 --- a/src/pal/src/safecrt/strcpy_s.c +++ b/src/pal/src/safecrt/strcpy_s.cpp diff --git a/src/pal/src/safecrt/strlen_s.c b/src/pal/src/safecrt/strlen_s.cpp index 34c1308d5c..3f1e1cf1ae 100644 --- a/src/pal/src/safecrt/strlen_s.c +++ b/src/pal/src/safecrt/strlen_s.cpp @@ -42,7 +42,7 @@ * *******************************************************************************/ -size_t __cdecl strnlen(const char *str, size_t maxsize) +size_t __cdecl PAL_strnlen(const char *str, size_t maxsize) { size_t n; diff --git a/src/pal/src/safecrt/strncat_s.c b/src/pal/src/safecrt/strncat_s.cpp index ef8c6cfc7f..ef8c6cfc7f 100644 --- a/src/pal/src/safecrt/strncat_s.c +++ b/src/pal/src/safecrt/strncat_s.cpp diff --git a/src/pal/src/safecrt/strncpy_s.c b/src/pal/src/safecrt/strncpy_s.cpp index f819ebb6bb..f819ebb6bb 100644 --- a/src/pal/src/safecrt/strncpy_s.c +++ b/src/pal/src/safecrt/strncpy_s.cpp diff --git a/src/pal/src/safecrt/strtok_s.c b/src/pal/src/safecrt/strtok_s.cpp index 6f1c80633f..6f1c80633f 100644 --- a/src/pal/src/safecrt/strtok_s.c +++ b/src/pal/src/safecrt/strtok_s.cpp diff --git a/src/pal/src/safecrt/swprintf.c b/src/pal/src/safecrt/swprintf.cpp index 75004eafe2..2fbfcfaf58 100644 --- a/src/pal/src/safecrt/swprintf.c +++ b/src/pal/src/safecrt/swprintf.cpp @@ -92,7 +92,7 @@ int __cdecl swprintf_s ( va_start(arglist, format); - ret = _vswprintf_s(string, sizeInWords, format, arglist); + ret = vswprintf_s(string, sizeInWords, format, arglist); va_end(arglist); diff --git a/src/pal/src/safecrt/vsprintf.c b/src/pal/src/safecrt/vsprintf.cpp index 4f2bd9fdeb..e1a94d086d 100644 --- a/src/pal/src/safecrt/vsprintf.c +++ b/src/pal/src/safecrt/vsprintf.cpp @@ -119,7 +119,7 @@ int __cdecl _vsnprintf_helper ( return -1; } -int __cdecl _vsprintf_s ( +int __cdecl vsprintf_s ( char *string, size_t sizeInBytes, const char *format, diff --git a/src/pal/src/safecrt/vswprint.c b/src/pal/src/safecrt/vswprint.cpp index 77c79b8752..b9940a693a 100644 --- a/src/pal/src/safecrt/vswprint.c +++ b/src/pal/src/safecrt/vswprint.cpp @@ -6,7 +6,7 @@ *vswprint.c - print formatted data into a string from var arg list * *Purpose: -* defines vswprintf(), _vswprintf_c and _vsnwprintf() - print formatted output to +* defines vswprintf_s() and _vsnwprintf_s() - print formatted output to * a string, get the data from an argument ptr instead of explicit * arguments. * @@ -23,19 +23,10 @@ typedef int (*WOUTPUTFN)(miniFILE *, const wchar_t *, va_list); static int _vswprintf_helper( WOUTPUTFN outfn, wchar_t *string, size_t count, const wchar_t *format, va_list ap ); -static int _vscwprintf_helper (WOUTPUTFN outfn, const wchar_t *format, va_list ap ); /*** -*ifndef _COUNT_ -*int _vswprintf(string, format, ap) - print formatted data to string from arg ptr -*else -*ifndef _SWPRINTFS_ERROR_RETURN_FIX -*int _vsnwprintf(string, cnt, format, ap) - print formatted data to string from arg ptr -*else -*int _vswprintf_c(string, cnt, format, ...) - print formatted data to string -*endif -*endif -* +*int vswprintf_s(string, sizeInWords, format, ap) - print formatted data to string from arg ptr +*int _vsnwprintf_s(string, sizeInWords, cnt, format, ap) - print formatted data to string from arg ptr *Purpose: * Prints formatted data, but to a string and gets data from an argument * pointer. @@ -47,21 +38,10 @@ static int _vscwprintf_helper (WOUTPUTFN outfn, const wchar_t *format, va_list a * the stack so that other routines can assume that _iob[] entries are in * are in DGROUP and, thus, are near. * -*ifdef _COUNT_ -*ifndef _SWPRINTFS_ERROR_RETURN_FIX -* The _vsnwprintf() flavor takes a count argument that is +* The _vsnwprintf_s() flavor takes a count argument that is * the max number of bytes that should be written to the * user's buffer. * We don't expose this function directly in the headers. -*else -* The _vswprintf_c() flavor does the same thing as the _snwprintf -* above, but, it also fixes an issue in the return value in the case -* when there isn't enough space to write the null terminator -* We don't fix this issue in _vsnwprintf because of backward -* compatibility. In new code, however, _vsnwprintf is #defined to -* _vswprintf_c so users get the fix. -* -*endif * * Multi-thread: (1) Since there is no stream, this routine must never try * to get the stream lock (i.e., there is no stream lock either). (2) @@ -70,9 +50,8 @@ static int _vscwprintf_helper (WOUTPUTFN outfn, const wchar_t *format, va_list a * *Entry: * wchar_t *string - place to put destination string -*ifdef _COUNT_ +* size_t sizeInWords - size of the string buffer in wchar_t units * size_t count - max number of bytes to put in buffer -*endif * wchar_t *format - format string, describes format of data * va_list ap - varargs argument pointer * @@ -133,7 +112,7 @@ int __cdecl _vswprintf_helper ( return -1; } -int __cdecl _vswprintf_s ( +int __cdecl vswprintf_s ( wchar_t *string, size_t sizeInWords, const wchar_t *format, @@ -230,53 +209,3 @@ int __cdecl _vsnwprintf_s ( return (retvalue < 0 ? -1 : retvalue); } - -/*** -* _vscwprintf() - counts the number of character needed to print the formatted -* data -* -*Purpose: -* Counts the number of characters in the fotmatted data. -* -*Entry: -* wchar_t *format - format string, describes format of data -* va_list ap - varargs argument pointer -* -*Exit: -* returns number of characters needed to print formatted data. -* -*Exceptions: -* -*******************************************************************************/ - -#ifndef _COUNT_ - -int __cdecl _vscwprintf_helper ( - WOUTPUTFN woutfn, - const wchar_t *format, - va_list ap - ) -{ - miniFILE str; - miniFILE *outfile = &str; - int retval; - - _VALIDATE_RETURN( (format != NULL), EINVAL, -1); - - outfile->_cnt = INT_MAX; //MAXSTR; - outfile->_flag = _IOWRT|_IOSTRG; - outfile->_ptr = outfile->_base = NULL; - - retval = woutfn(outfile, format, ap); - return(retval); -} - -int __cdecl _vscwprintf ( - const wchar_t *format, - va_list ap - ) -{ - return _vscwprintf_helper(_woutput_s, format, ap); -} - -#endif /* _COUNT_ */ diff --git a/src/pal/src/safecrt/wcscat_s.c b/src/pal/src/safecrt/wcscat_s.cpp index 06179888ff..06179888ff 100644 --- a/src/pal/src/safecrt/wcscat_s.c +++ b/src/pal/src/safecrt/wcscat_s.cpp diff --git a/src/pal/src/safecrt/wcscpy_s.c b/src/pal/src/safecrt/wcscpy_s.cpp index 4c60a81489..4c60a81489 100644 --- a/src/pal/src/safecrt/wcscpy_s.c +++ b/src/pal/src/safecrt/wcscpy_s.cpp diff --git a/src/pal/src/safecrt/wcslen_s.c b/src/pal/src/safecrt/wcslen_s.cpp index 4fd5371035..4fd5371035 100644 --- a/src/pal/src/safecrt/wcslen_s.c +++ b/src/pal/src/safecrt/wcslen_s.cpp diff --git a/src/pal/src/safecrt/wcsncat_s.c b/src/pal/src/safecrt/wcsncat_s.cpp index 1ff39d55f3..1ff39d55f3 100644 --- a/src/pal/src/safecrt/wcsncat_s.c +++ b/src/pal/src/safecrt/wcsncat_s.cpp diff --git a/src/pal/src/safecrt/wcsncpy_s.c b/src/pal/src/safecrt/wcsncpy_s.cpp index 7902ded43a..7902ded43a 100644 --- a/src/pal/src/safecrt/wcsncpy_s.c +++ b/src/pal/src/safecrt/wcsncpy_s.cpp diff --git a/src/pal/src/safecrt/wcstok_s.c b/src/pal/src/safecrt/wcstok_s.cpp index c99b30c773..c99b30c773 100644 --- a/src/pal/src/safecrt/wcstok_s.c +++ b/src/pal/src/safecrt/wcstok_s.cpp diff --git a/src/pal/src/safecrt/wmakepath_s.c b/src/pal/src/safecrt/wmakepath_s.cpp index 35ab7d386e..35ab7d386e 100644 --- a/src/pal/src/safecrt/wmakepath_s.c +++ b/src/pal/src/safecrt/wmakepath_s.cpp diff --git a/src/pal/src/safecrt/wsplitpath_s.c b/src/pal/src/safecrt/wsplitpath_s.cpp index c7fb107803..c7fb107803 100644 --- a/src/pal/src/safecrt/wsplitpath_s.c +++ b/src/pal/src/safecrt/wsplitpath_s.cpp diff --git a/src/pal/src/safecrt/xtoa_s.c b/src/pal/src/safecrt/xtoa_s.cpp index 42cc5786d1..42cc5786d1 100644 --- a/src/pal/src/safecrt/xtoa_s.c +++ b/src/pal/src/safecrt/xtoa_s.cpp diff --git a/src/pal/src/safecrt/xtow_s.c b/src/pal/src/safecrt/xtow_s.cpp index 7a02424c85..7a02424c85 100644 --- a/src/pal/src/safecrt/xtow_s.c +++ b/src/pal/src/safecrt/xtow_s.cpp diff --git a/src/pal/src/safecrt/xtox_s.inl b/src/pal/src/safecrt/xtox_s.inl index e07d87adf5..7c8b2f2fd6 100644 --- a/src/pal/src/safecrt/xtox_s.inl +++ b/src/pal/src/safecrt/xtox_s.inl @@ -21,12 +21,9 @@ #define _i64tox_s _i64tow_s #define _ui64tox_s _ui64tow_s #define xtox xtow -#define _itox _itow #define _ltox _ltow #define _ultox _ultow #define x64tox x64tow -#define _i64tox _i64tow -#define _ui64tox _ui64tow #else /* _UNICODE */ #define xtox_s xtoa_s #define _itox_s _itoa_s @@ -36,12 +33,9 @@ #define _i64tox_s _i64toa_s #define _ui64tox_s _ui64toa_s #define xtox xtoa -#define _itox _itoa #define _ltox _ltoa #define _ultox _ultoa #define x64tox x64toa -#define _i64tox _i64toa -#define _ui64tox _ui64toa #endif /* _UNICODE */ /*** @@ -224,19 +218,6 @@ errno_t __cdecl _ultox_s ( /* Actual functions just call conversion helper with neg flag set correctly, and return pointer to buffer. */ -TCHAR * __cdecl _itox ( - int val, - TCHAR *buf, - int radix - ) -{ - if (radix == 10 && val < 0) - xtox((unsigned long)val, buf, radix, 1); - else - xtox((unsigned long)(unsigned int)val, buf, radix, 0); - return buf; -} - TCHAR * __cdecl _ltox ( long val, TCHAR *buf, @@ -425,16 +406,6 @@ errno_t __cdecl _ui64tox_s ( /* Actual functions just call conversion helper with neg flag set correctly, and return pointer to buffer. */ -TCHAR * __cdecl _i64tox ( - __int64 val, - TCHAR *buf, - int radix - ) -{ - x64tox((unsigned __int64)val, buf, radix, (radix == 10 && val < 0)); - return buf; -} - TCHAR * __cdecl _ui64tox ( unsigned __int64 val, TCHAR *buf, diff --git a/src/pal/src/synchmgr/synchmanager.cpp b/src/pal/src/synchmgr/synchmanager.cpp index 473918cb68..3aec140474 100644 --- a/src/pal/src/synchmgr/synchmanager.cpp +++ b/src/pal/src/synchmgr/synchmanager.cpp @@ -1648,7 +1648,7 @@ namespace CorUnix } // Entry point routine for the thread that initiates process termination. - DWORD TerminationRequestHandlingRoutine(LPVOID pArg) + DWORD PALAPI TerminationRequestHandlingRoutine(LPVOID pArg) { // Call the termination request handler if one is registered. if (g_terminationRequestHandler != NULL) diff --git a/src/pal/src/thread/context.cpp b/src/pal/src/thread/context.cpp index f832015710..0449df568b 100644 --- a/src/pal/src/thread/context.cpp +++ b/src/pal/src/thread/context.cpp @@ -33,9 +33,7 @@ SET_DEFAULT_DEBUG_CHANNEL(THREAD); // some headers have code with asserts, so do extern PGET_GCMARKER_EXCEPTION_CODE g_getGcMarkerExceptionCode; -// in context2.S -extern void CONTEXT_CaptureContext(LPCONTEXT lpContext); - +#define CONTEXT_AREA_MASK 0xffff #ifdef _X86_ #define CONTEXT_ALL_FLOATING (CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS) #elif defined(_AMD64_) @@ -288,7 +286,7 @@ CONTEXT_GetThreadContext( } if (lpContext->ContextFlags & - (CONTEXT_CONTROL | CONTEXT_INTEGER)) + (CONTEXT_CONTROL | CONTEXT_INTEGER) & CONTEXT_AREA_MASK) { if (CONTEXT_GetRegisters(dwProcessId, lpContext) == FALSE) { @@ -348,7 +346,7 @@ CONTEXT_SetThreadContext( } if (lpContext->ContextFlags & - (CONTEXT_CONTROL | CONTEXT_INTEGER)) + (CONTEXT_CONTROL | CONTEXT_INTEGER) & CONTEXT_AREA_MASK) { #if HAVE_PT_REGS if (ptrace((__ptrace_request)PT_GETREGS, dwProcessId, (caddr_t)&ptrace_registers, 0) == -1) @@ -371,11 +369,11 @@ CONTEXT_SetThreadContext( ASSERT("Don't know how to set the context of another process on this platform!"); return FALSE; #endif - if (lpContext->ContextFlags & CONTEXT_CONTROL) + if (lpContext->ContextFlags & CONTEXT_CONTROL & CONTEXT_AREA_MASK) { ASSIGN_CONTROL_REGS } - if (lpContext->ContextFlags & CONTEXT_INTEGER) + if (lpContext->ContextFlags & CONTEXT_INTEGER & CONTEXT_AREA_MASK) { ASSIGN_INTEGER_REGS } @@ -467,13 +465,13 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) } // TODO: Enable for all Unix systems -#if defined(_AMD64_) && defined(__linux__) +#if defined(_AMD64_) && defined(XSTATE_SUPPORTED) if ((lpContext->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE) { _ASSERTE(FPREG_HasExtendedState(native)); memcpy_s(FPREG_Xstate_Ymmh(native), sizeof(M128A) * 16, lpContext->VectorRegister, sizeof(M128A) * 16); } -#endif // _AMD64_ +#endif //_AMD64_ && XSTATE_SUPPORTED } /*++ @@ -564,22 +562,24 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex #endif } - // TODO: Enable for all Unix systems -#if defined(_AMD64_) && defined(__linux__) +#ifdef _AMD64_ if ((contextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE) { + // TODO: Enable for all Unix systems +#if XSTATE_SUPPORTED if (FPREG_HasExtendedState(native)) { memcpy_s(lpContext->VectorRegister, sizeof(M128A) * 16, FPREG_Xstate_Ymmh(native), sizeof(M128A) * 16); } else +#endif // XSTATE_SUPPORTED { // Reset the CONTEXT_XSTATE bit(s) so it's clear that the extended state data in // the CONTEXT is not valid. const ULONG xstateFlags = CONTEXT_XSTATE & ~(CONTEXT_CONTROL & CONTEXT_INTEGER); lpContext->ContextFlags &= ~xstateFlags; } - } + } #endif // _AMD64_ } @@ -855,7 +855,7 @@ CONTEXT_GetThreadContextFromPort( mach_msg_type_number_t StateCount; thread_state_flavor_t StateFlavor; - if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)) + if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) & CONTEXT_AREA_MASK) { #ifdef _X86_ x86_thread_state32_t State; @@ -877,7 +877,7 @@ CONTEXT_GetThreadContextFromPort( CONTEXT_GetThreadContextFromThreadState(StateFlavor, (thread_state_t)&State, lpContext); } - if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING) { + if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING & CONTEXT_AREA_MASK) { #ifdef _X86_ x86_float_state32_t State; StateFlavor = x86_FLOAT_STATE32; @@ -898,6 +898,22 @@ CONTEXT_GetThreadContextFromPort( CONTEXT_GetThreadContextFromThreadState(StateFlavor, (thread_state_t)&State, lpContext); } +#if defined(_AMD64_) && defined(XSTATE_SUPPORTED) + if (lpContext->ContextFlags & CONTEXT_XSTATE & CONTEXT_AREA_MASK) { + x86_avx_state64_t State; + StateFlavor = x86_AVX_STATE64; + StateCount = sizeof(State) / sizeof(natural_t); + MachRet = thread_get_state(Port, StateFlavor, (thread_state_t)&State, &StateCount); + if (MachRet != KERN_SUCCESS) + { + ASSERT("thread_get_state(XSTATE) failed: %d\n", MachRet); + goto exit; + } + + CONTEXT_GetThreadContextFromThreadState(StateFlavor, (thread_state_t)&State, lpContext); + } +#endif + exit: return MachRet; } @@ -917,7 +933,7 @@ CONTEXT_GetThreadContextFromThreadState( { #ifdef _X86_ case x86_THREAD_STATE32: - if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)) + if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) & CONTEXT_AREA_MASK) { x86_thread_state32_t *pState = (x86_thread_state32_t *)threadState; @@ -944,7 +960,7 @@ CONTEXT_GetThreadContextFromThreadState( { x86_float_state32_t *pState = (x86_float_state32_t *)threadState; - if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT) + if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT & CONTEXT_AREA_MASK) { lpContext->FloatSave.ControlWord = *(DWORD*)&pState->fpu_fcw; lpContext->FloatSave.StatusWord = *(DWORD*)&pState->fpu_fsw; @@ -963,7 +979,7 @@ CONTEXT_GetThreadContextFromThreadState( memcpy(&lpContext->FloatSave.RegisterArea[i * 10], (&pState->fpu_stmm0)[i].mmst_reg, 10); } - if (lpContext->ContextFlags & CONTEXT_EXTENDED_REGISTERS) + if (lpContext->ContextFlags & CONTEXT_EXTENDED_REGISTERS & CONTEXT_AREA_MASK) { // The only extended register information that Mach will tell us about are the xmm register values. // Both Windows and Mach store the registers in a packed layout (each of the 8 registers is 16 bytes) @@ -975,7 +991,7 @@ CONTEXT_GetThreadContextFromThreadState( #elif defined(_AMD64_) case x86_THREAD_STATE64: - if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)) + if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) & CONTEXT_AREA_MASK) { x86_thread_state64_t *pState = (x86_thread_state64_t *)threadState; @@ -1009,7 +1025,7 @@ CONTEXT_GetThreadContextFromThreadState( break; case x86_FLOAT_STATE64: - if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT) + if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT & CONTEXT_AREA_MASK) { x86_float_state64_t *pState = (x86_float_state64_t *)threadState; @@ -1031,9 +1047,19 @@ CONTEXT_GetThreadContextFromThreadState( memcpy(&lpContext->FltSave.FloatRegisters[i], (&pState->__fpu_stmm0)[i].__mmst_reg, 10); // AMD64's FLOATING_POINT includes the xmm registers. - memcpy(&lpContext->Xmm0, &pState->__fpu_xmm0, 8 * 16); + memcpy(&lpContext->Xmm0, &pState->__fpu_xmm0, 16 * 16); + } + break; + +#ifdef XSTATE_SUPPORTED + case x86_AVX_STATE64: + if (lpContext->ContextFlags & CONTEXT_XSTATE & CONTEXT_AREA_MASK) + { + x86_avx_state64_t *pState = (x86_avx_state64_t *)threadState; + memcpy(&lpContext->VectorRegister, &pState->__fpu_ymmh0, 16 * 16); } break; +#endif #else #error Unexpected architecture. #endif @@ -1120,7 +1146,7 @@ CONTEXT_SetThreadContextOnPort( mach_msg_type_number_t StateCount; thread_state_flavor_t StateFlavor; - if (lpContext->ContextFlags & (CONTEXT_CONTROL|CONTEXT_INTEGER)) + if (lpContext->ContextFlags & (CONTEXT_CONTROL|CONTEXT_INTEGER) & CONTEXT_AREA_MASK) { #ifdef _X86_ x86_thread_state32_t State; @@ -1187,21 +1213,42 @@ CONTEXT_SetThreadContextOnPort( } } - if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING) + if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING & CONTEXT_AREA_MASK) { #ifdef _X86_ x86_float_state32_t State; StateFlavor = x86_FLOAT_STATE32; + StateCount = sizeof(State) / sizeof(natural_t); #elif defined(_AMD64_) +#ifdef XSTATE_SUPPORTED + // We're relying on the fact that the initial portion of + // x86_avx_state64_t is identical to x86_float_state64_t. + // Check a few fields to make sure the assumption is correct. + static_assert_no_msg(sizeof(x86_avx_state64_t) > sizeof(x86_float_state64_t)); + static_assert_no_msg(offsetof(x86_avx_state64_t, __fpu_fcw) == offsetof(x86_float_state64_t, __fpu_fcw)); + static_assert_no_msg(offsetof(x86_avx_state64_t, __fpu_xmm0) == offsetof(x86_float_state64_t, __fpu_xmm0)); + + x86_avx_state64_t State; + if (lpContext->ContextFlags & CONTEXT_XSTATE & CONTEXT_AREA_MASK) + { + StateFlavor = x86_AVX_STATE64; + StateCount = sizeof(State) / sizeof(natural_t); + } + else + { + StateFlavor = x86_FLOAT_STATE64; + StateCount = sizeof(x86_float_state64_t) / sizeof(natural_t); + } +#else x86_float_state64_t State; StateFlavor = x86_FLOAT_STATE64; + StateCount = sizeof(State) / sizeof(natural_t); +#endif #else #error Unexpected architecture. #endif - StateCount = sizeof(State) / sizeof(natural_t); - // If we're setting only one of the floating point or extended registers (of which Mach supports only // the xmm values) then we don't have values for the other set. This is a problem since Mach only // supports setting both groups as a single unit. So in this case we'll need to fetch the current @@ -1222,7 +1269,7 @@ CONTEXT_SetThreadContextOnPort( _ASSERTE(StateCountGet == StateCount); } - if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT) + if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT & CONTEXT_AREA_MASK) { #ifdef _X86_ *(DWORD*)&State.fpu_fcw = lpContext->FloatSave.ControlWord; @@ -1258,14 +1305,14 @@ CONTEXT_SetThreadContextOnPort( for (int i = 0; i < 8; i++) memcpy((&State.__fpu_stmm0)[i].__mmst_reg, &lpContext->FltSave.FloatRegisters[i], 10); - memcpy(&State.__fpu_xmm0, &lpContext->Xmm0, 8 * 16); + memcpy(&State.__fpu_xmm0, &lpContext->Xmm0, 16 * 16); #else #error Unexpected architecture. #endif } #ifdef _X86_ - if (lpContext->ContextFlags & CONTEXT_EXTENDED_REGISTERS) + if (lpContext->ContextFlags & CONTEXT_EXTENDED_REGISTERS & CONTEXT_AREA_MASK) { // The only extended register information that Mach will tell us about are the xmm register // values. Both Windows and Mach store the registers in a packed layout (each of the 8 registers @@ -1274,6 +1321,13 @@ CONTEXT_SetThreadContextOnPort( } #endif // _X86_ +#if defined(_AMD64_) && defined(XSTATE_SUPPORTED) + if (lpContext->ContextFlags & CONTEXT_XSTATE & CONTEXT_AREA_MASK) + { + memcpy(&State.__fpu_ymmh0, lpContext->VectorRegister, 16 * 16); + } +#endif + MachRet = thread_set_state(Port, StateFlavor, (thread_state_t)&State, diff --git a/src/pal/src/thread/process.cpp b/src/pal/src/thread/process.cpp index 315145dc03..a64bfb8ab1 100644 --- a/src/pal/src/thread/process.cpp +++ b/src/pal/src/thread/process.cpp @@ -2049,18 +2049,18 @@ GetProcessIdDisambiguationKey(DWORD processId, UINT64 *disambiguationKey) // According to `man proc`, the second field in the stat file is the filename of the executable, // in parentheses. Tokenizing the stat file using spaces as separators breaks when that name - // has spaces in it, so we start using sscanf after skipping everything up to and including the + // has spaces in it, so we start using sscanf_s after skipping everything up to and including the // last closing paren and the space after it. char *scanStartPosition = strrchr(line, ')') + 2; // All the format specifiers for the fields in the stat file are provided by 'man proc'. - int sscanfRet = sscanf(scanStartPosition, + int sscanfRet = sscanf_s(scanStartPosition, "%*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu %*lu %*ld %*ld %*ld %*ld %*ld %*ld %llu \n", &starttime); if (sscanfRet != 1) { - _ASSERTE(!"Failed to parse stat file contents with sscanf."); + _ASSERTE(!"Failed to parse stat file contents with sscanf_s."); return FALSE; } @@ -2095,7 +2095,7 @@ PAL_GetTransportPipeName(char *name, DWORD id, const char *suffix) // also try to use 0 as the value. _ASSERTE(ret == TRUE || disambiguationKey == 0); - int chars = _snprintf(name, MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH, PipeNameFormat, id, disambiguationKey, suffix); + int chars = snprintf(name, MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH, PipeNameFormat, id, disambiguationKey, suffix); _ASSERTE(chars > 0 && chars < MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH); } @@ -2690,7 +2690,7 @@ CreateProcessModules( char moduleName[PATH_MAX]; int size; - if (sscanf(line, "__TEXT %p-%p [ %dK] %*[-/rwxsp] SM=%*[A-Z] %s\n", &startAddress, &endAddress, &size, moduleName) == 4) + if (sscanf_s(line, "__TEXT %p-%p [ %dK] %*[-/rwxsp] SM=%*[A-Z] %s\n", &startAddress, &endAddress, &size, moduleName, _countof(moduleName)) == 4) { bool dup = false; for (ProcessModules *entry = listHead; entry != NULL; entry = entry->Next) @@ -2768,7 +2768,7 @@ exit: int devHi, devLo, inode; char moduleName[PATH_MAX]; - if (sscanf(line, "%p-%p %*[-rwxsp] %p %x:%x %d %s\n", &startAddress, &endAddress, &offset, &devHi, &devLo, &inode, moduleName) == 7) + if (sscanf_s(line, "%p-%p %*[-rwxsp] %p %x:%x %d %s\n", &startAddress, &endAddress, &offset, &devHi, &devLo, &inode, moduleName, _countof(moduleName)) == 7) { if (inode != 0) { |