summaryrefslogtreecommitdiff
path: root/src/pal/src
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/src')
-rw-r--r--src/pal/src/CMakeLists.txt108
-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.h106
-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.S259
-rw-r--r--src/pal/src/arch/amd64/debugbreak.S12
-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.S42
-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.cpp64
-rw-r--r--src/pal/src/arch/arm/exceptionhelper.S2
-rw-r--r--src/pal/src/arch/i386/asmconstants.h76
-rw-r--r--src/pal/src/arch/i386/context2.S354
-rw-r--r--src/pal/src/arch/i386/exceptionhelper.S47
-rw-r--r--src/pal/src/config.h.in1
-rw-r--r--src/pal/src/configure.cmake11
-rw-r--r--src/pal/src/cruntime/lstr.cpp210
-rw-r--r--src/pal/src/cruntime/math.cpp367
-rw-r--r--src/pal/src/cruntime/mbstring.cpp54
-rw-r--r--src/pal/src/cruntime/path.cpp482
-rw-r--r--src/pal/src/cruntime/printf.cpp202
-rw-r--r--src/pal/src/cruntime/string.cpp55
-rw-r--r--src/pal/src/cruntime/wchar.cpp211
-rw-r--r--src/pal/src/debug/debug.cpp1087
-rw-r--r--src/pal/src/examples/CMakeLists.txt2
-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.cpp7
-rw-r--r--src/pal/src/exception/machmessage.cpp2
-rw-r--r--src/pal/src/exception/machmessage.h4
-rw-r--r--src/pal/src/exception/seh-unwind.cpp76
-rw-r--r--src/pal/src/exception/seh.cpp8
-rw-r--r--src/pal/src/exception/signal.cpp6
-rw-r--r--src/pal/src/file/find.cpp10
-rw-r--r--src/pal/src/include/pal/context.h24
-rw-r--r--src/pal/src/include/pal/palinternal.h45
-rw-r--r--src/pal/src/init/pal.cpp3
-rw-r--r--src/pal/src/map/virtual.cpp5
-rw-r--r--src/pal/src/misc/sysinfo.cpp2
-rw-r--r--src/pal/src/safecrt/input.inl4
-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.inl39
-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.inl29
-rw-r--r--src/pal/src/synchmgr/synchmanager.cpp2
-rw-r--r--src/pal/src/thread/context.cpp108
-rw-r--r--src/pal/src/thread/process.cpp12
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, &param)
- {
- 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, &param)
- {
- 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)
{